Linux System

Devices

The Path Constants

Program: PathConst

In Libc you can find constants pointing at many of the paths in the system.

For instance:

_PATH_MAN: Points at the path to the man files



Devices

Run an ls -l on the files in dev. Notice that they begin with unusual letters for their permissions. b means it is a block device, whiel c means it is a character mode device.

Symbolic Links and Hard Links

Finding out about the Environment

  rusage = packed record
    { Total amount of user time used.  }
    ru_utime: timeval;
    { Total amount of system time used.  }
    ru_stime: timeval;
    { Maximum resident set size (in kilobytes).  }
    ru_maxrss: Integer;
    { Amount of sharing of text segment memory
      with other processes (kilobyte-seconds).  }
    ru_ixrss: Integer;
    { Amount of data segment memory used (kilobyte-seconds).  }
    ru_idrss: Integer;
    { Amount of stack memory used (kilobyte-seconds).  }
    ru_isrss: Integer;
    { Number of soft page faults (i.e. those serviced by reclaiming
      a page from the list of pages awaiting reallocation.  }
    ru_minflt: Integer;
    { Number of hard page faults (i.e. those that required I/O).  }
    ru_majflt: Integer;
    { Number of times a process was swapped out of physical memory.  }
    ru_nswap: Integer;
    { Number of input operations via the file system.  Note: This
      and `ru_oublock' do not include operations with the cache.  }
    ru_inblock: Integer;
    { Number of output operations via the file system.  }
    ru_oublock: Integer;
    { Number of IPC messages sent.  }
    ru_msgsnd: Integer;
    { Number of IPC messages received.  }
    ru_msgrcv: Integer;
    { Number of signals delivered.  }
    ru_nsignals: Integer;
    { Number of voluntary context switches, i.e. because the process
      gave up the process before it had to (usually to wait for some
      resource to be available).  }
    ru_nvcsw: Integer;
    { Number of involuntary context switches, i.e. a higher priority process
      became runnable or the current process used up its time slice.  }
    ru_nivcsw: Integer;
  end;
  {$EXTERNALSYM rusage}
  TRUsage = rusage;
  PRUsage = ^TRUsage;
RLIMIT_CPU CPU time in seconds
RLIMIT_FSIZE Maximum filesize
RLIMIT_DATA max data size
RLIMIT_STACK max stack size
RLIMIT_CORE max core file size
RLIMIT_RSS max resident set size
RLIMIT_NPROC max number of processes
RLIMIT_NOFILE max number of open files
RLIMIT_MEMLOCK max locked-in-memory address space
RLIMIT_AS address space (virtual memory) limit

From the ExploreInfo program

procedure TForm1.SysInfoBtnClick(Sender: TObject);
var
  usage: rusage;
  limit: rlimit;
  S: string;
  Priority: Integer;
begin
  ListBox1.Items.Clear;
  getrusage(RUSAGE_SELF, usage);
  S := Format('User time used = %d.%d, System time used = %d.%d',
    [usage.ru_utime.tv_sec, usage.ru_utime.tv_usec,
     usage.ru_stime.tv_sec, usage.ru_stime.tv_usec]);
  ListBox1.Items.Add(S);
  // (__which: Integer; __who: id_t): Integer; cdecl;
  priority := getpriority(PRIO_PROCESS, getpid());
  S := Format('Current Priority: %d', [priority]);
  ListBox1.Items.Add(S);
  getrlimit(RLIMIT_FSIZE, limit);
  S := Format('Current File Size Limit: soft = %d hard = %d',
    [limit.rlim_cur, limit.rlim_max]);
  ListBox1.Items.Add(S);

  getrlimit(RLIMIT_CORE, limit);
  S := Format('Current Core Dump Size Limit: soft = %d hard = %d',
    [limit.rlim_cur, limit.rlim_max]);
  ListBox1.Items.Add(S);

  getrlimit(RLIMIT_NOFILE, limit);
  S := Format('Current Limit On Number of Open Files: soft = %d hard = %d',
    [limit.rlim_cur, limit.rlim_max]);
  ListBox1.Items.Add(S);

  getrlimit(RLIMIT_STACK, limit);
  S := Format('Current Stack Size Limit: soft = %d hard = %d',
    [limit.rlim_cur, limit.rlim_max]);
  ListBox1.Items.Add(S);

  getrlimit(RLIMIT_AS, limit);
  S := Format('Current Address Space Limit (stack and data): soft = %d hard = %d',
    [limit.rlim_cur, limit.rlim_max]);
  ListBox1.Items.Add(S);

  getrlimit(RLIMIT_CPU, limit);
  S := Format('Current CPU Time Limit: soft = %d hard = %d',
    [limit.rlim_cur, limit.rlim_max]);
  ListBox1.Items.Add(S);
  
  S := Format('Max size for a file name: %d', [FILENAME_MAX]);
  ListBox1.Items.Add(S);
  S := Format('The number of bits in a char value: %d' +
              ' Max size for a char value: %d ' +
              ' Min size for a char value: %d',
              [SysConf(_SC_CHAR_BIT),
               SysConf(_SC_CHAR_MAX),
               SysConf(_SC_CHAR_MIN)]);
  ListBox1.Items.Add(S);

  S := Format('The number of bits in a long value: %d',
              [SysConf(_SC_LONG_BIT)]);
  ListBox1.Items.Add(S);

  S := Format('Max size for a int value: %d ' +
              ' Min size for a int value: %d',
              [SysConf(_SC_INT_MAX), SysConf(_SC_INT_MIN)]);

  ListBox1.Items.Add(S);              

end;

Loading a Library

procedure TForm1.Button1Click(Sender: TObject);
type
  TFunc = function (c: Integer): Integer; cdecl;
var
  lib: Pointer;
  MyFunc: TFunc;
begin
//  dlopen(Filename: PChar; Flag: Integer): Pointer;
  try
    lib := dlopen('libc.so.6', RTLD_NOW );
    if lib <> nil then begin
     // dlsym = GetProcAddress
      MyFunc := dlsym(lib,'isupper');
      if @MyFunc <> nil then begin
        if MyFunc(Ord('A')) <> 0 then
          ListBox1.Items.Add('Yes')
        else
          ListBox1.Items.Add('No');
      end;
    end;
  finally
    dlclose(lib);
  end;
end;

Pipes

Pipe a Small Amount of Data Between Programs

program simplePipe;

{ Simple use of pipes to send data to another program
  Based on a program by Neil Mathew and Richard Stones }

uses
  Libc;
  
{$APPTYPE CONSOLE}

var
  buffer: PChar;
  fp: PIOFile;
begin
  getmem(buffer, 250);
  strcpy(buffer, 'Sam is going crazy!');
  // od writes data in a particular format. Try -x for hex, or -o for octal
  fp := popen('od -c' , 'w');
  fwrite(buffer, sizeof(char), length(buffer), fp);
  pclose(fp);
end.

Piping Lots of Data

program processInfo;
 
{
 Example of reading lots of data from a pipe

 This program calls popen to open another process and pipe the data
 from it back to our program.

 Based on a C program by Neil Mathew and Richard Stones

 Copyright (c) 2000 by Charlie Calvert
}


uses
  Libc;

 {$APPTYPE CONSOLE}
const
  BUFSIZE = 1024;
var
  fp: PIOFile;
  Buffer: PChar;
  CharsRead: Integer;
begin
  GetMem(Buffer, BUFSIZE);
  { Create a new stream connected to a pipe. Run the ps command in the pipe }
  fp := popen('ps -ax', 'r');
  if (fp <> nil) then begin
    CharsRead := fread(Buffer, sizeof(char), BUFSIZE, fp);
    while CharsRead > 0 do begin
      Write(Buffer);
      CharsRead := fread(Buffer, sizeof(char), BUFSIZE, fp);
    end;
  end;
  pclose(fp);
  FreeMem(Buffer, BUFSIZE);
end.

Count the Words in a File

program wordCount;


uses
  SysUtils, Libc;

const
  BUFSIZE = 1024;

var
  fp: PIOFile;
  Buffer: PChar;
  CharsRead: Integer;
  CountCommand: string;
begin { wordCount }
  if ParamCount < 1 then begin
    WriteLn('Pass in a text file and I will count the words in it');
    Exit;
  end;
  CountCommand := SysUtils.Format('cat %s | wc --words', [ParamStr(1)]);
  GetMem(Buffer, BUFSIZE);
  fp := popen(PChar(CountCommand), 'r');
  if (fp <> nil) then begin
    CharsRead := fread(Buffer, sizeof(char), BUFSIZE, fp);
    while CharsRead > 0 do begin
      Write(Buffer);
      CharsRead := fread(Buffer, sizeof(char), BUFSIZE, fp);
    end;
  end;
  pclose(fp);
  FreeMem(Buffer, BUFSIZE);
end. 

Using Uname To Query the System

program simpleReceive;
 
// read information from a pipe
// Based on a program by Neil Mathew and Richard Stones

uses
  Libc;

{$APPTYPE CONSOLE}

const
  BUFSIZE = 1024;
var
  fp: PIOFile;
  Buffer: PChar;
  CharsRead: Integer;
begin
  getmem(Buffer, BUFSIZE);
  // uname prints information about the operating system, -a is the all option
  fp := popen('uname -a', 'r');
  if (fp <> nil) then begin
    CharsRead := fread(Buffer, sizeof(char), BUFSIZE, fp);
    if CharsRead > 0 then
      WriteLn('OS is: ', Buffer);
  end;
  freemem(Buffer, BUFSIZE);
end.

Take Control of the Pipes

program myFilePipe;

uses
  Libc;

const
  BUFSIZE = 1024;
var
  BytesSent: Integer;
  FilePipes: array[0..1] of Integer;
  TempStr: PChar;
  Buffer: PChar;

begin { myFilePipe }
  GetMem(Buffer, BUFSIZE);
  GetMem(TempStr, BUFSIZE);
  strcpy(TempStr, '123');
  if pipe(@FilePipes) = 0 then begin
    BytesSent := Libc.__write(FilePipes[1], TempStr, Length(TempStr));
    WriteLn('Wrote ', BytesSent);
    BytesSent := Libc.__read(FilePipes[0], Buffer, BUFSIZE);
    WriteLn('Read ', BytesSent, ' bytes with value: ', Buffer);
  end;
  FreeMem(Buffer, BUFSIZE);
  Freemem(TempStr, BUFSIZE);
end.