00001 00002 // Last modified on Thu Nov 10 09:19:30 PST 1994 by levin 00003 /* 00004 00005 This file implements the portion of the Vesta EXEC primitive that 00006 is invoked directly from the evaluator/interpreter. 00007 00008 */ 00009 00010 /* 00011 00012 TYPE 00013 StdTreatment = TEXT, 00014 /* "ignore" => send to /dev/null 00015 "report" => report to user 00016 "reportError" => report to user, 00017 "value" => include {stdxxx = <value>} in return, where 00018 xxx is either "out" or "err" 00019 */ 00020 ExecResult = { 00021 code: INT, // exit status: 00022 // 256 > code >= 0 => tool reported this result 00023 // -256 < code < 0 => tool got -code as a signal 00024 // code <= -256 => 00025 // tool reported -code as a result, but 00026 // also produced output for which the 00027 // specified treatment was "reportError" 00028 // if x is (-code) DIV 256 then 00029 // x == 1 => output on stdout 00030 // x == 2 => output on stderr, 00031 // x == 3 => output on both 00032 // code >= 256 or code < -1023 => undefined 00033 // 00034 wd: BINDING, // files created in the working directory 00035 root: BINDING, // files created elsewhere in the file system 00036 stdout: TEXT, // defined iff stdoutTreatment == "value" 00037 stderr: TEXT // defined iff stderrTreatment == "value" 00038 } 00039 00040 EXEC( 00041 platform: TEXT, // on which command is to execute 00042 command: LIST[TEXT], // HEAD is tool name, TAIL is arguments 00043 stdin: TEXT := "", 00044 stdoutTreatment: StdTreatment := "report", 00045 stderrTreatment: StdTreatment := "reportError", 00046 ENV: BINDING // for expected fields, see below 00047 ): ExecResult 00048 00049 */ 00050 00051 00052 00053 ValC 00054 prim_exec( 00055 ValC platform, // TEXT 00056 ValC command, // LIST[TEXT], 00057 ValC stdin, // TEXT 00058 ValC stdoutTr, // TEXT (StdTreatment) 00059 ValC stderrTr, // TEXT (StdTreatment) 00060 ValC env // BINDING 00061 ) 00062 { 00063 String pf 00064 String host 00065 // convert platform to ordinary text string 00066 if (!choose_host(pf, &host)) { 00067 // can't find a suitable host platform; complain 00068 } 00069 if (host == NIL) { 00070 // tool will execute locally 00071 // establish stdin, stdout, stderr: 00072 // stdin: if non-NIL, copy to file and open as filedescriptor 00073 // stdout: ignore => /dev/null, report => pipe to stdout 00074 // reportError => ??? (tee) 00075 // value => open derived file, pass descriptor, remember 00076 // shortId 00077 // set up environment variables from env$ENVVARS 00078 // create mount points for file system root and wd 00079 // create combined command line for tooldriver, including: 00080 // chroot info (mount points) 00081 // user id (to switch back from superuser) 00082 // original command line 00083 // fork 00084 // in child, perform chroot and mounts, switch user id, sigvec, exec 00085 // in parent, wait for child 00086 // when child exits, compute error code (perhaps done by child?) 00087 // if treatments are "value", create VV's from shortIds 00088 // talk to mount points to get result bindings for wd and fs 00089 // put together result value from pieces 00090 } else { 00091 // tool will execute remotely 00092 // establish stdin, stdout, stderr: 00093 // stdin: if non-NIL, copy to file (if necessary) and 00094 // pass file name to tooldriver on command line 00095 // stdout and stderr: 00096 // ignore => tell tooldriver to set to /dev/null, 00097 // report => create socket, pass to tooldriver on command line 00098 // reportError => as for "report", but pass flag to tooldriver 00099 // value => open derived file, pass name to tooldriver, remember 00100 // shortId locally 00101 // look at env$ENVVARS and create text rep for tooldriver 00102 // create mount points for file system root and wd 00103 // do nfs_mount 00104 // call remote tooldriver on "host". This is pseudo RPC: 00105 // start with rsh /vesta/components/tooldriver (platform specific) 00106 // alternative: tooldriver is a daemon that listens on a well-known 00107 // socket and forks a unique child instance for each request. 00108 // pass socket name for argument stream 00109 // push "marshalled" data down socket: 00110 // stdin, stdout, stderr setup info from above 00111 // mount point names and server info 00112 // user id (to switch back from superuser) 00113 // environment vars (text rep) 00114 // tool command line 00115 // need threads for stdout/stderr sockets (alertable wait?) 00116 // main thread waits on completion info from tooldriver 00117 // tooldriver does: 00118 // if stdin is needed, opens the file name passed and sets file desc. 00119 // sets file descriptors for stdout and stderr by creating sockets 00120 // and connecting to those passed as parameters. If error flag 00121 // is set, must create a thread and a pty, passing the pty as 00122 // the file descriptor and having the thread copy data from pty 00123 // to socket, setting flag on firs time. 00124 // create mount points and nfs mount for root and wd 00125 // chroot 00126 // switch user id 00127 // set up sigvec 00128 // exec tool, using command 00129 // in parent, wait for child 00130 // when child exits, compute error code (perhaps done by child?) 00131 // if treatments are "value", create VV's from shortIds 00132 // talk to mount points to get result bindings for wd and fs 00133 // put together result value from pieces 00134 } 00135 00136