Calling Linux Commands from Delphi

One of the great features of Linux is that you can do just about anything from the command line. If we’re able to gain access to command line instructions from our Delphi applications, this will give us a very powerful API for the system. In this video I’m going to show you how to access the Linux command line from your Delphi applications.

*note* In this video I am assuming you are already configured to deploy an application to Linux and understand how to launch it from the Linux command line. If this is not the case, see my earlier posts covering these subjects: 

Best Viewed Full Screen:

Here is the source code for the ‘myls’ application featured in the video…

program myls;
{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  Posix.Base,
  Posix.Fcntl;

type
  TStreamHandle = pointer;

///  <summary>
///    Man Page: http://man7.org/linux/man-pages/man3/popen.3.html
///  </summary>
function popen(const command: MarshaledAString; const _type: MarshaledAString): TStreamHandle; cdecl; external libc name _PU + 'popen';

///  <summary>
///    Man Page: http://man7.org/linux/man-pages/man3/pclose.3p.html
///  </summary>
function pclose(filehandle: TStreamHandle): int32; cdecl; external libc name _PU + 'pclose';

///  <summary>
///    Man Page: http://man7.org/linux/man-pages/man3/fgets.3p.html
///  </summary>
function fgets(buffer: pointer; size: int32; Stream: TStreamHAndle): pointer; cdecl; external libc name _PU + 'fgets';

///  <summary>
///    Utility function to return a buffer of ASCII-Z data as a string.
///  </summary>
function BufferToString( Buffer: pointer; MaxSize: uint32 ): string;
var
  cursor: ^uint8;
  EndOfBuffer: nativeuint;
begin
  Result := '';
  if not assigned(Buffer) then begin
    exit;
  end;
  cursor := Buffer;
  EndOfBuffer := NativeUint(cursor) + MaxSize;
  while (NativeUint(cursor)<EndOfBuffer) and (cursor^<>0) do begin
    Result := Result + chr(cursor^);
    cursor := pointer( succ(NativeUInt(cursor)) );
  end;
end;

var
  Handle: TStreamHandle;
  Data: array[0..511] of uint8;

begin
  try
    Handle := popen('/bin/ls -lart','r');
    try
      while fgets(@data[0],Sizeof(Data),Handle)<>nil do begin
        Write(BufferToString(@Data[0],sizeof(Data)));
      end;
    finally
      pclose(Handle);
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

 

Facebooktwittergoogle_plusredditpinterestlinkedintumblrmail

1 Response

  1. andrew.sovtsov@embarcadero.com says:

    Hi Craig,
    Nice post and very useful one!
    In practice your BufferToString function works incorrectly with non-ascii symbols (e.g. UTF8)

Leave a Reply