(* Return true if the parameter is blank, representing an anonymous pipe
normally set up by the shell.
*)
function isPipe(const name: string): boolean;
begin
result := name = ''
end { isPipe } ;
(* Return true if the parameter represents a regular file.
*)
function isFile(const name: string): boolean;
var
s: stat;
begin
if name = '' then
exit(false);
if fpStat(name, s{%H-}) <> 0 then
exit(false);
(* The low 9 bits of the mode are the usual permissions, the next 3 bits are *)
(* the sticky, setgid and setuid bits, leaving 4 bits to define the type of *)
(* object i.e. ordinary file, directory and so on. There might be additional *)
(* filesystem-specific attribute bits stored elsewhere, e.g. in an extension *)
(* to the inode structure. *)
// Does this need special handling for symlinks, or are they followed?
result := ((s.st_mode and S_IFMT) = S_IFREG) or ((s.st_mode and S_IFMT) = S_IFCHR)
end { isFile } ;
(* Return true if the parameter represents a FIFO (named pipe).
*)
function isFifo(const name: string): boolean;
var
s: stat;
begin
if name = '' then
exit(false);
if fpStat(name, s{%H-}) <> 0 then
exit(false);
(* The low 9 bits of the mode are the usual permissions, the next 3 bits are *)
(* the sticky, setgid and setuid bits, leaving 4 bits to define the type of *)
(* object i.e. ordinary file, directory and so on. There might be additional *)
(* filesystem-specific attribute bits stored elsewhere, e.g. in an extension *)
(* to the inode structure. *)
// Does this need special handling for symlinks, or are they followed?
result := (s.st_mode and S_IFMT) = S_IFIFO
end { isFifo } ;
(* Return true if the parameter represents a unix domain socket.
*)
function isUDSocket(const name: string): boolean;
var
s: stat;
begin
if name = '' then
exit(false);
if fpStat(name, s{%H-}) <> 0 then
exit(false);
(* The low 9 bits of the mode are the usual permissions, the next 3 bits are *)
(* the sticky, setgid and setuid bits, leaving 4 bits to define the type of *)
(* object i.e. ordinary file, directory and so on. There might be additional *)
(* filesystem-specific attribute bits stored elsewhere, e.g. in an extension *)
(* to the inode structure. *)
// Does this need special handling for symlinks, or are they followed?
result := (s.st_mode and S_IFMT) = S_IFSOCK
end { isUDSocket } ;
(* Reopen something that isn't a unix-domain socket.
*)
procedure reopenFile(var t: Text; const n: string; alreadyClosed: boolean= false);
begin
if not alreadyClosed then
CloseFile(t);
AssignFile(t, n);
Rewrite(t)
end { reopenFile } ;
(* This is a reimplementation of the standard Connect() since it doesn't
support a unix-domain address and truncates it if told to cast it to an
inet domain address structure.
Test using e.g. $ nc -lkU ~/dsocket noting the -k to prevent the listener
terminating when the writer (this program) closes the connection.
*)
Function Connect(Sock:longint;const addr: TUnixSockAddr;var SockIn,SockOut:text):Boolean;
Function DoConnect(Sock:longint;const addr: TUnixSockAddr): Boolean;
var
res: longint;
begin
repeat
res:=fpconnect(Sock,@Addr,SizeOF(TUnixSockAddr)); (* NOTA BENE *)
until (res<>-1) or (SocketError <> EsockEINTR);
DoConnect:= res = 0;
end;
begin
Connect:=DoConnect(Sock,addr);
If Connect then
Sock2Text(Sock,SockIn,SockOut);
end { Connect } ;
var
reopenedInput: Text; (* Dummy since only output is used *)
(* Reopen a unix-domain socket. This needs special implementation of Connect()
as above.
*)
procedure reopenUDSocket(var t: Text; const n: string; alreadyClosed: boolean= false);
var
skt: TSocket;
ipcAddr: TUnixSockAddr;
begin
if not alreadyClosed then
CloseFile(t);
skt:= fpSocket(PF_UNIX, SOCK_STREAM, 0);
if skt < 0 then begin
if not quiet then
WriteLn(erroutput, 'Cannot create unix-domain socket handle');
Halt(9)
end;
FillChar(ipcAddr{%H-}, SizeOf(ipcAddr), 0);
ipcAddr.family:= AF_UNIX;
StrPCopy(ipcAddr.path, n);
if not Connect(skt, ipcAddr, reopenedInput, t) then begin
if not quiet then begin
Write(erroutput, 'Cannot open unix-domain socket "' + n + '" ');
if not FileExists(n) then
WriteLn(erroutput, '(does not exist)')
else
WriteLn(erroutput, '(check listener is running)');
Halt(9)
end
end;
{$push }{$I- }
Reset(reopenedInput);
{$pop }
Rewrite(t)
end { reopenUDSocket } ;