3 IMPORT SYSTEM
, DswProcs
, HostLang
, unistd
:= PosixCunistd
, stdlib
:= PosixCstdlib
,
4 signal
:= PosixCsignal
, sys_wait
:= PosixCsys_wait
, macro
:= PosixCmacro
,
5 errno
:= PosixCerrno
, sys_stat
:= PosixCsys_stat
;
8 Directory
= POINTER TO RECORD (DswProcs
.Directory
) END;
10 String
= POINTER TO ARRAY OF SHORTCHAR
;
11 SString
= POINTER TO ARRAY OF String
;
13 Process
= POINTER TO RECORD (DswProcs
.Process
)
19 PROCEDURE ToHost (IN s
: ARRAY OF CHAR): String
;
20 VAR ss
: String
; res
: INTEGER;
22 NEW(ss
, LEN(s$
) * 3 + 1);
23 ASSERT(ss
# NIL, 100);
24 HostLang
.StringToHost(s
, ss
, HostLang
.pep383x
, res
);
29 PROCEDURE IsRegular (mode
: sys_stat
.mode_t
): BOOLEAN;
31 RETURN BITS(mode
) * BITS(sys_stat
.S_IFMT
) = BITS(sys_stat
.S_IFREG
)
34 PROCEDURE (d
: Directory
) New
* (): Process
;
37 NEW(p
); p
.argv
:= NIL; p
.pid
:= -1; p
.code
:= 0;
41 PROCEDURE (d
: Directory
) GetPath (IN name
: ARRAY OF CHAR): DswProcs
.String
;
44 v
: POINTER [untagged
] TO ARRAY [untagged
] OF SHORTCHAR
;
45 s
, e
, ret
: POINTER TO ARRAY OF CHAR;
48 i
, j
, k
, len
, res
: INTEGER;
49 buf
: sys_stat
.struct_stat
;
52 v
:= stdlib
.getenv("PATH");
54 NEW(s
, LEN(v$
) * 3 + 1);
55 HostLang
.HostToString(v$
, s
, HostLang
.pep383x
, res
);
58 NEW(e
, LEN(s$
) + len
+ 2);
61 j
:= -1; found
:= FALSE
;
62 REPEAT ch
:= s
[i
]; INC(i
); INC(j
); e
[j
] := ch
UNTIL (ch
= ":") OR (ch
= 0X
);
70 cres
:= macro
.stat(w
, buf
);
71 found
:= (cres
= 0) & IsRegular(buf
.st_mode
) & (unistd
.access(w
, unistd
.X_OK
) = 0)
73 UNTIL found
OR (ch
= 0X
);
74 IF ~found
THEN e
:= NIL END
79 PROCEDURE (p
: Process
) Program
* (IN exe
: ARRAY OF CHAR);
82 ASSERT(p
.pid
= -1, 20);
83 NEW(argv
, 1); argv
[0] := ToHost(exe
);
87 PROCEDURE (p
: Process
) PutParam
* (IN par
: ARRAY OF CHAR);
88 VAR i
: INTEGER; argv
: SString
;
90 ASSERT(p
.pid
= -1, 20);
91 ASSERT(p
.argv
# NIL, 21);
92 NEW(argv
, LEN(p
.argv
) + 1);
93 FOR i
:= 0 TO LEN(p
.argv
) - 1 DO
96 argv
[i
] := ToHost(par
);
100 PROCEDURE (p
: Process
) Execute
* (OUT ok
: BOOLEAN);
102 UString
= POINTER [untagged
] TO ARRAY [untagged
] OF SHORTCHAR
;
103 SUString
= POINTER TO ARRAY OF UString
;
105 i
: INTEGER; pid
: unistd
.pid_t
; res
: unistd
.int
; argv
: SUString
; s
: String
;
107 ASSERT(p
.pid
= -1, 20);
108 ASSERT(p
.argv
# NIL, 21);
109 NEW(argv
, LEN(p
.argv
) + 2);
110 FOR i
:= 0 TO LEN(p
.argv
) - 1 DO
112 argv
[i
] := SYSTEM
.VAL(UString
, SYSTEM
.ADR(s
[0]))
115 pid
:= unistd
.fork();
117 res
:= unistd
.execv(argv
[0], argv
);
118 unistd
._exit(127); (* system() and most utils exit with 126/127 *)
123 p
.argv
:= NIL; (* or save it for debugging and reuse? *)
129 PROCEDURE (p
: Process
) Terminate
* (OUT ok
: BOOLEAN);
130 VAR res
, e
: signal
.int
;
132 ASSERT(p
.pid
> 0, 20);
133 res
:= signal
.kill(p
.pid
, signal
.SIGTERM
);
134 IF res
= 0 THEN p
.Wait
; ok
:= TRUE
138 | errno
.EINVAL
: HALT(100) (* wat *)
139 | errno
.EPERM
: ok
:= FALSE (* process can not be killed *)
140 | errno
.ESRCH
: p
.code
:= 0; p
.pid
:= -1; ok
:= TRUE (* process already killed *)
142 ELSE HALT(101) (* wat *)
146 PROCEDURE (p
: Process
) IsTerminated
* (): BOOLEAN;
147 VAR pid
: unistd
.pid_t
; e
: unistd
.int
;
150 ASSERT(p
.pid
> 0, 100); (* wat *)
151 pid
:= sys_wait
.waitpid(p
.pid
, p
.code
, sys_wait
.WNOHANG
);
152 IF pid
= 0 THEN (* process still executes *)
153 ELSIF pid
= p
.pid
THEN p
.pid
:= -1 (* process returns code *)
157 | errno
.ECHILD
: p
.code
:= 0; p
.pid
:= -1 (* process was killed externally *)
158 | errno
.EINVAL
: HALT(101) (* wat *)
159 | errno
.EINTR
: (* assume that process still executes *)
161 ELSE HALT(102) (* wat *)
167 PROCEDURE (p
: Process
) Wait
*;
168 VAR pid
: unistd
.pid_t
; e
: unistd
.int
;
170 ASSERT(p
.pid
> 0, 20);
172 pid
:= sys_wait
.waitpid(p
.pid
, p
.code
, 0);
173 IF pid
= p
.pid
THEN p
.pid
:= -1 (* was terminated *)
177 | errno
.ECHILD
: p
.code
:= 0; p
.pid
:= -1 (* process was killed externally *)
178 | errno
.EINVAL
: HALT(100) (* wat *)
179 | errno
.EINTR
: (* continue wait for process termination *)
181 ELSE HALT(101) (* wat *)
186 PROCEDURE (p
: Process
) Result (): INTEGER;
188 IF p
.pid
# -1 THEN p
.Wait
END;
189 (* RETURN SYSTEM.CONV(INTEGER, sys_wait.WEXITSTATUS(p.code)) *) (* !!! *)
190 RETURN SYSTEM
.VAL(INTEGER, p
.code
) DIV 256 MOD 128
196 NEW(d
); DswProcs
.SetDir(d
)