DEADSOFTWARE

add utility cpmake
[cpc.git] / src / posix / generic / Dsw / Mod / HostProcs.cp
1 MODULE DswHostProcs;
3 IMPORT SYSTEM, Log, DswProcs, HostLang, unistd := PosixCunistd, stdlib := PosixCstdlib,
4 signal := PosixCsignal, sys_wait := PosixCsys_wait, macro := PosixCmacro,
5 errno := PosixCerrno;
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 (d: Directory) New* (): Process;
20 VAR p: Process;
21 BEGIN
22 NEW(p); p.argv := NIL; p.pid := -1; p.code := 0;
23 RETURN p
24 END New;
26 PROCEDURE ToHost (IN s: ARRAY OF CHAR): String;
27 VAR ss: String; res: INTEGER;
28 BEGIN
29 NEW(ss, LEN(s$) * 3 + 1);
30 ASSERT(ss # NIL, 100);
31 HostLang.StringToHost(s, ss, HostLang.pep383x, res);
32 ASSERT(res = 0, 101);
33 RETURN ss
34 END ToHost;
36 PROCEDURE (p: Process) Program* (IN exe: ARRAY OF CHAR);
37 VAR argv: SString;
38 BEGIN
39 ASSERT(p.pid = -1, 20);
40 NEW(argv, 1); argv[0] := ToHost(exe);
41 p.argv := argv
42 END Program;
44 PROCEDURE (p: Process) PutParam* (IN par: ARRAY OF CHAR);
45 VAR i: INTEGER; argv: SString;
46 BEGIN
47 ASSERT(p.pid = -1, 20);
48 ASSERT(p.argv # NIL, 21);
49 NEW(argv, LEN(p.argv) + 1);
50 FOR i := 0 TO LEN(p.argv) - 1 DO
51 argv[i] := p.argv[i]
52 END;
53 argv[i] := ToHost(par);
54 p.argv := argv
55 END PutParam;
57 PROCEDURE (p: Process) Execute* (OUT ok: BOOLEAN);
58 TYPE
59 UString = POINTER [untagged] TO ARRAY [untagged] OF SHORTCHAR;
60 SUString = POINTER TO ARRAY OF UString;
61 VAR
62 i, j: INTEGER; pid: unistd.pid_t; res: unistd.int; argv: SUString;
63 BEGIN
64 ASSERT(p.pid = -1, 20);
65 ASSERT(p.argv # NIL, 21);
66 NEW(argv, LEN(p.argv) + 1);
67 FOR i := 0 TO LEN(p.argv) - 1 DO
68 argv[i] := SYSTEM.VAL(UString, SYSTEM.ADR(p.argv[i, 0]))
69 END;
70 pid := unistd.fork();
71 IF pid = 0 THEN
72 res := unistd.execv(argv[0], argv);
73 unistd._exit(127); (* system() and most utils exit with 126/127 *)
74 ok := FALSE
75 ELSIF pid = -1 THEN
76 ok := FALSE
77 ELSE
78 p.argv := NIL; (* or save it for debugging and reuse? *)
79 p.pid := pid;
80 ok := TRUE
81 END
82 END Execute;
84 PROCEDURE (p: Process) Terminate* (OUT ok: BOOLEAN);
85 VAR res, e: signal.int;
86 BEGIN
87 ASSERT(p.pid > 0, 20);
88 res := signal.kill(p.pid, signal.SIGTERM);
89 IF res = 0 THEN p.Wait; ok := TRUE
90 ELSIF res = -1 THEN
91 e := macro.errno();
92 CASE e OF
93 | errno.EINVAL: HALT(100) (* wat *)
94 | errno.EPERM: ok := FALSE (* process can not be killed *)
95 | errno.ESRCH: p.code := 0; p.pid := -1; ok := TRUE (* process already killed *)
96 END
97 ELSE HALT(101) (* wat *)
98 END
99 END Terminate;
101 PROCEDURE (p: Process) IsTerminated* (): BOOLEAN;
102 VAR pid: unistd.pid_t; e: unistd.int;
103 BEGIN
104 IF p.pid # -1 THEN
105 ASSERT(p.pid > 0, 100); (* wat *)
106 pid := sys_wait.waitpid(p.pid, p.code, sys_wait.WNOHANG);
107 IF pid = 0 THEN (* process still executes *)
108 ELSIF pid = p.pid THEN p.pid := -1 (* process returns code *)
109 ELSIF pid = -1 THEN
110 e := macro.errno();
111 CASE e OF
112 | errno.ECHILD: p.code := 0; p.pid := -1 (* process was killed externally *)
113 | errno.EINVAL: HALT(101) (* wat *)
114 | errno.EINTR: (* assume that process still executes *)
115 END
116 ELSE HALT(102) (* wat *)
117 END
118 END;
119 RETURN p.pid = -1
120 END IsTerminated;
122 PROCEDURE (p: Process) Wait*;
123 VAR pid: unistd.pid_t; e: unistd.int;
124 BEGIN
125 ASSERT(p.pid > 0, 20);
126 REPEAT
127 pid := sys_wait.waitpid(p.pid, p.code, 0);
128 IF pid = p.pid THEN p.pid := -1 (* was terminated *)
129 ELSIF pid = -1 THEN
130 e := macro.errno();
131 CASE e OF
132 | errno.ECHILD: p.code := 0; p.pid := -1 (* process was killed externally *)
133 | errno.EINVAL: HALT(100) (* wat *)
134 | errno.EINTR: (* continue wait for process termination *)
135 END
136 ELSE HALT(101) (* wat *)
137 END
138 UNTIL p.pid = -1
139 END Wait;
141 PROCEDURE (p: Process) Result (): INTEGER;
142 BEGIN
143 IF p.pid # -1 THEN p.Wait END;
144 (* RETURN SYSTEM.CONV(INTEGER, sys_wait.WEXITSTATUS(p.code)) *) (* !!! *)
145 RETURN SYSTEM.VAL(INTEGER, p.code) DIV 256 MOD 128
146 END Result;
148 PROCEDURE Init;
149 VAR d: Directory;
150 BEGIN
151 NEW(d); DswProcs.SetDir(d)
152 END Init;
154 BEGIN
155 Init
156 END DswHostProcs.