78 lines · 2.8 KB · Text
RawDownload
= command: command interface     include "sh.m";    cmd := load Command path;     PATH: con "/dis/sh.dis";    init: fn(ctxt: ref Draw->Context, args: list of string); Command  defines the module interface for programs started bythe Inferno shells sh(1) and mash(1), and the window  managerwm(1).  Applications to be run as commands must adhere to it,and any application wishing to start another command may  useit. Every  command  must have an init function with the signatureshown above.  Note that Limbo rules allow a module to  exposea  larger  interface  for  use by other applications (see forinstance sh(2)); provided it includes the form of init  shownabove, the module can also be invoked as a command. Ctxt  provides  the graphics context for a windowing applica‐tion, which typically passes it to wmlib(2) (eg, to titlebar)or  directly to tk(2).  It is nil for commands started by theshells. The arguments to the command are passed as a simple  list  ofstrings, args.  By convention, the name of the command or thename of its .dis file heads the list. PATH names the file containing sh(1), (on small systems, thismight  actually  name an instance of tiny(1)) but usually thepath name of another command will be given to the Limbo  loadoperator:        include "sh.m";       ...        cmd := load Command "/dis/date.dis";       cmd->init(nil, "date" :: nil); In  practice  more care must be taken when invoking programs.In the example above, the current process executes  the  bodyof  cmd->init and if that executes exit, raises an exception,or otherwise modifies the state of the process, the caller isaffected.  The following is more prudent:        child(file: string, args: list of string, pidc: chan of int)       {             pidc <-= sys->pctl(Sys->NEWFD|Sys->FORKNS|Sys->NEWPGRP,                   list of {0, 1, 2});             cmd := load Command file;             if(cmd == nil){                   sys->print("can't load %s: %r\n", file);                   exit;             }             cmd->init(nil, args);       }       parent()       {             pidc := chan of int;             spawn child(disfile, args, pidc);             pid := <-pidc;             ...       } A  new  child  process runs the command only after using sys-pctl to insulate the caller  from  untoward  changes  to  itsenvironment.   Note  the idiomatic use of a channel to returnthe child's process ID to  its  parent,  which  can  then  ifdesired  use the wait file of prog(3) to watch over the childand wait for its demise.  or use the ctl file of  prog(3)  todispose  of it.  Furthermore, any state shared between parentand child can safely be accessed by the child before it sendsthe ID because the parent is blocked on the receive. == see ALSOmash(1), sh(1), wm(1), sh(2), sys-pctl(2)