-- 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.