DEADSOFTWARE

DswHostProcs: hack-fix for cpfront
[cpc.git] / src / posix / generic / Dsw / Mod / HostProcs.cp
1 MODULE DswHostProcs;
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;
7 TYPE
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)
14 argv: SString;
15 pid: unistd.pid_t;
16 code: unistd.int;
17 END;
19 PROCEDURE ToHost (IN s: ARRAY OF CHAR): String;
20 VAR ss: String; res: INTEGER;
21 BEGIN
22 NEW(ss, LEN(s$) * 3 + 1);
23 ASSERT(ss # NIL, 100);
24 HostLang.StringToHost(s, ss, HostLang.pep383x, res);
25 ASSERT(res = 0, 101);
26 RETURN ss
27 END ToHost;
29 PROCEDURE IsRegular (mode: sys_stat.mode_t): BOOLEAN;
30 BEGIN
31 RETURN BITS(mode) * BITS(sys_stat.S_IFMT) = BITS(sys_stat.S_IFREG)
32 END IsRegular;
34 PROCEDURE (d: Directory) New* (): Process;
35 VAR p: Process;
36 BEGIN
37 NEW(p); p.argv := NIL; p.pid := -1; p.code := 0;
38 RETURN p
39 END New;
41 PROCEDURE (d: Directory) GetPath (IN name: ARRAY OF CHAR): DswProcs.String;
42 VAR
43 ch: CHAR;
44 v: POINTER [untagged] TO ARRAY [untagged] OF SHORTCHAR;
45 s, e, ret: POINTER TO ARRAY OF CHAR;
46 w: String;
47 cres: sys_stat.int;
48 i, j, k, len, res: INTEGER;
49 buf: sys_stat.struct_stat;
50 found: BOOLEAN;
51 BEGIN
52 v := stdlib.getenv("PATH");
53 IF v # NIL THEN
54 NEW(s, LEN(v$) * 3 + 1);
55 HostLang.HostToString(v$, s, HostLang.pep383x, res);
56 ASSERT(res = 0, 100);
57 len := LEN(name$);
58 NEW(e, LEN(s$) + len + 2);
59 i := 0;
60 REPEAT
61 j := -1; found := FALSE;
62 REPEAT ch := s[i]; INC(i); INC(j); e[j] := ch UNTIL (ch = ":") OR (ch = 0X);
63 IF e[0] = "/" THEN
64 e[j] := "/"; INC(j);
65 FOR k := 0 TO len DO
66 e[j + k] := name[k]
67 END;
68 e[j + k] := 0X;
69 w := ToHost(e);
70 cres := macro.stat(w, buf);
71 found := (cres = 0) & IsRegular(buf.st_mode) & (unistd.access(w, unistd.X_OK) = 0)
72 END
73 UNTIL found OR (ch = 0X);
74 IF ~found THEN e := NIL END
75 END;
76 RETURN e
77 END GetPath;
79 PROCEDURE (p: Process) Program* (IN exe: ARRAY OF CHAR);
80 VAR argv: SString;
81 BEGIN
82 ASSERT(p.pid = -1, 20);
83 NEW(argv, 1); argv[0] := ToHost(exe);
84 p.argv := argv
85 END Program;
87 PROCEDURE (p: Process) PutParam* (IN par: ARRAY OF CHAR);
88 VAR i: INTEGER; argv: SString;
89 BEGIN
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
94 argv[i] := p.argv[i]
95 END;
96 argv[i] := ToHost(par);
97 p.argv := argv
98 END PutParam;
100 PROCEDURE (p: Process) Execute* (OUT ok: BOOLEAN);
101 TYPE
102 UString = POINTER [untagged] TO ARRAY [untagged] OF SHORTCHAR;
103 SUString = POINTER [untagged] TO ARRAY [untagged] OF UString;
104 VAR
105 i, j, adr: INTEGER; pid: unistd.pid_t; res: unistd.int; argv: SUString;
106 BEGIN
107 ASSERT(p.pid = -1, 20);
108 ASSERT(p.argv # NIL, 21);
109 argv := SYSTEM.VAL(SUString, stdlib.malloc((LEN(p.argv) + 1)) * SIZE(UString));
110 FOR i := 0 TO LEN(p.argv) - 1 DO
111 argv[i] := SYSTEM.VAL(UString, SYSTEM.ADR(p.argv[i, 0]))
112 END;
113 argv[i] := NIL;
114 pid := unistd.fork();
115 IF pid = 0 THEN
116 res := unistd.execv(argv[0], argv);
117 unistd._exit(127); (* system() and most utils exit with 126/127 *)
118 ok := FALSE
119 ELSIF pid = -1 THEN
120 ok := FALSE
121 ELSE
122 p.argv := NIL; (* or save it for debugging and reuse? *)
123 p.pid := pid;
124 ok := TRUE
125 END;
126 stdlib.free(SYSTEM.ADR(argv[0]))
127 END Execute;
129 PROCEDURE (p: Process) Terminate* (OUT ok: BOOLEAN);
130 VAR res, e: signal.int;
131 BEGIN
132 ASSERT(p.pid > 0, 20);
133 res := signal.kill(p.pid, signal.SIGTERM);
134 IF res = 0 THEN p.Wait; ok := TRUE
135 ELSIF res = -1 THEN
136 e := macro.errno();
137 CASE e OF
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 *)
141 END
142 ELSE HALT(101) (* wat *)
143 END
144 END Terminate;
146 PROCEDURE (p: Process) IsTerminated* (): BOOLEAN;
147 VAR pid: unistd.pid_t; e: unistd.int;
148 BEGIN
149 IF p.pid # -1 THEN
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 *)
154 ELSIF pid = -1 THEN
155 e := macro.errno();
156 CASE e OF
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 *)
160 END
161 ELSE HALT(102) (* wat *)
162 END
163 END;
164 RETURN p.pid = -1
165 END IsTerminated;
167 PROCEDURE (p: Process) Wait*;
168 VAR pid: unistd.pid_t; e: unistd.int;
169 BEGIN
170 ASSERT(p.pid > 0, 20);
171 REPEAT
172 pid := sys_wait.waitpid(p.pid, p.code, 0);
173 IF pid = p.pid THEN p.pid := -1 (* was terminated *)
174 ELSIF pid = -1 THEN
175 e := macro.errno();
176 CASE e OF
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 *)
180 END
181 ELSE HALT(101) (* wat *)
182 END
183 UNTIL p.pid = -1
184 END Wait;
186 PROCEDURE (p: Process) Result (): INTEGER;
187 BEGIN
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
191 END Result;
193 PROCEDURE Init;
194 VAR d: Directory;
195 BEGIN
196 NEW(d); DswProcs.SetDir(d)
197 END Init;
199 BEGIN
200 Init
201 END DswHostProcs.