-- UnixSysCallsMXCode.mesa
DIRECTORY Atom, PFS, Rope, Scheme, SchemeSys, UnixSpawn, UnixSysCalls, UnixTypes;
UnixSysCallsMXCode: CEDAR PROGRAM
IMPORTS Atom, PFS, Scheme, SchemeSys, UnixSpawn, UnixSysCalls
= BEGIN OPEN Scheme;
SymbolFromRope: PROC [rope: Rope.ROPE] RETURNS [Symbol] ~ {RETURN[Atom.MakeAtom[rope]]};
RopeFromSymbol: PROC [Symbol] RETURNS [Rope.ROPE] ~ Atom.GetPName;
UnixSysCallsPrim: PROC [SELF: Primitive, ARG1,ARG2,ARG3: Any, REST: ProperList] RETURNS [result: Any ← unspecified] = {
INNER: PROC = {
POP: PROC RETURNS [a: Any ← undefined] = {
IF REST#NIL THEN {a ← REST.car; REST ← NARROW[REST.cdr]}};
DATA: Pair ~ NARROW[SELF.data];
env: Environment ~ NARROW[DATA.cdr];
SELECT NAT[NARROW[DATA.car, REF INT]↑] FROM
5 => {
pid: Any ← ARG1;
signal: Any ← ARG2;
res: UnixTypes.SysCallResult = UnixSysCalls.KillPG[KCheck[pid], VAL[KCheck[signal]]];
result ← IF res=success THEN true ELSE false;
};
4 => {
pid: Any ← ARG1;
signal: Any ← ARG2;
res: UnixTypes.SysCallResult = UnixSysCalls.Kill[KCheck[pid], VAL[KCheck[signal]]];
result ← IF res=success THEN true ELSE false;
};
3 => {
pid: Any ← ARG1;
result ← MakeFixnum[UnixSysCalls.GetPGrp[KCheck[pid]]];
};
2 => {
result ← MakeFixnum[UnixSysCalls.GetPPID[]];
};
1 => {
result ← MakeFixnum[UnixSysCalls.GetPID[]];
};
0 => {
cmdString: Any ← ARG1;
stdin: Any ← ARG2;
stdout: Any ← ARG3;
stderr: Any ← POP[];
stdin ← DeScheme[stdin, TRUE];
stdout ← DeScheme[stdout, FALSE];
stderr ← DeScheme[stderr, FALSE];
result ← DeCedar[UnixSpawn.Spawn[command: RopeFromString[TheString[cmdString]], stdin: stdin, stdout: stdout, stderr: stderr, wd: PFS.RopeFromPath[PFS.GetWDir[]], exec: TRUE, tty: FALSE, debug: FALSE].details];
};
ENDCASE => ERROR
}; INNER[!
UnixSpawn.Error => {
Complain[code, msg];
};
];
};
UnixSysCallsInit: PROC [env: Environment] = {
DefinePrimitive[name: "unix-killpg", nArgs: 2, proc: UnixSysCallsPrim, doc: "(pid signal) kill (signal) a unix process group", env: env, optional: 0, dotted: FALSE, data: Cons[MakeFixnum[5], env]];
DefinePrimitive[name: "unix-kill", nArgs: 2, proc: UnixSysCallsPrim, doc: "(pid signal) kill (signal) a unix process", env: env, optional: 0, dotted: FALSE, data: Cons[MakeFixnum[4], env]];
DefinePrimitive[name: "unix-getpgrp", nArgs: 1, proc: UnixSysCallsPrim, doc: "(pid) get unix process group", env: env, optional: 0, dotted: FALSE, data: Cons[MakeFixnum[3], env]];
DefinePrimitive[name: "unix-getppid", nArgs: 0, proc: UnixSysCallsPrim, doc: "() get unix parent process id", env: env, optional: 0, dotted: FALSE, data: Cons[MakeFixnum[2], env]];
DefinePrimitive[name: "unix-getpid", nArgs: 0, proc: UnixSysCallsPrim, doc: "() get unix process id", env: env, optional: 0, dotted: FALSE, data: Cons[MakeFixnum[1], env]];
DefinePrimitive[name: "unix-spawn", nArgs: 4, proc: UnixSysCallsPrim, doc: "(cmd-string [ stdin ] [ stdout ] [ stderr ]) fork a (Unix) process to run cmd, attaching its standard input, output and error file descriptors to the files named by stdin, stdout, stderr", env: env, optional: 3, dotted: FALSE, data: Cons[MakeFixnum[0], env]];
};
ROPE: TYPE ~ Rope.ROPE;
devNull: ROPE = "/dev/null";
DeScheme: PROC [ref: REF, inP: BOOL] RETURNS [REF] = {
SELECT ref FROM
undefined, true => ref ← SchemeSys.GetPort[undefined, inP];
false => ref ← devNull;
ENDCASE => {
WITH ref SELECT FROM
string: Scheme.String => ref ← RopeFromString[string];
ENDCASE => NULL;
};
RETURN [ref]
};
DeCedar: PROC [a: REF] RETURNS [REF] = {
WITH a SELECT FROM
lora: LIST OF REF => RETURN [Cons[lora.first, DeCedar[lora.rest]]];
rope: ROPE => RETURN [StringFromRope[rope]];
ENDCASE => RETURN [a];
};
RegisterInit[UnixSysCallsInit];
END.