home *** CD-ROM | disk | FTP | other *** search
/ Nebula / nebula.bin / SourceCode / libcs / run.c < prev    next >
C/C++ Source or Header  |  1990-12-11  |  7KB  |  236 lines

  1. /*
  2.  * Copyright (c) 1990 Carnegie Mellon University
  3.  * All Rights Reserved.
  4.  * 
  5.  * Permission to use, copy, modify and distribute this software and its
  6.  * documentation is hereby granted, provided that both the copyright
  7.  * notice and this permission notice appear in all copies of the
  8.  * software, derivative works or modified versions, and any portions
  9.  * thereof, and that both notices appear in supporting documentation.
  10.  *
  11.  * THE SOFTWARE IS PROVIDED "AS IS" AND CARNEGIE MELLON UNIVERSITY
  12.  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  13.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT
  14.  * SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL, DIRECT,
  15.  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  16.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  17.  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  18.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  *
  20.  * Users of this software agree to return to Carnegie Mellon any
  21.  * improvements or extensions that they make and grant Carnegie the
  22.  * rights to redistribute these changes.
  23.  *
  24.  * Export of this software is permitted only after complying with the
  25.  * regulations of the U.S. Deptartment of Commerce relating to the
  26.  * Export of Technical Data.
  27.  */
  28. /*  run[c], run[c]v, run[c]p, run[c]vp -- exec process and wait for it to exit
  29.  *
  30.  *  Usage:
  31.  *    i = run (file, arg1, arg2, ..., argn, 0);
  32.  *    i = runv (file, arglist);
  33.  *    i = runp (file, arg1, arg2, ..., argn, 0);
  34.  *    i = runvp (file, arglist);
  35.  *    i = runc (func, file, arg1, arg2, ..., argn, 0);
  36.  *    i = runcv (func, file, arglist);
  37.  *    i = runcp (func, file, arg1, arg2, ..., argn, 0);
  38.  *    i = runcvp (func, file, arglist);
  39.  *
  40.  *  Run, runv, runp, runvp and runc, runcv, runcp, runcvp have argument lists
  41.  *  exactly like the corresponding routines, execl, execv, execlp, execvp.  The
  42.  *  run routines perform a fork, then:
  43.  *  IN THE NEW PROCESS, an execl[p] or execv[p] is performed with the specified
  44.  *  arguments (after first invoking the supplied function in the runc* cases).
  45.  *  The process returns with a -1 code if the exec was not successful.
  46.  *  IN THE PARENT PROCESS, the signals SIGQUIT and SIGINT are disabled,
  47.  *  the process waits until the newly forked process exits, the
  48.  *  signals are restored to their original status, and the return
  49.  *  status of the process is analyzed.
  50.  *  All run routines return:  -1 if the exec failed or if the child was
  51.  *  terminated abnormally; otherwise, the exit code of the child is
  52.  *  returned.
  53.  *
  54.  **********************************************************************
  55.  * HISTORY
  56.  * $Log:    run.c,v $
  57.  * Revision 1.4  90/12/11  17:58:10  mja
  58.  *     Add copyright/disclaimer for distribution.
  59.  * 
  60.  * Revision 1.3  90/02/01  16:13:57  mja
  61.  *     Define new runc(), runcv(), runcp() amd runcvp() entry points;
  62.  *     remove most lint.
  63.  *     [90/02/01  15:22:40  mja]
  64.  * 
  65.  * Revision 1.2  89/08/03  14:36:46  mja
  66.  *     Update run() and runp() to use <varargs.h>.
  67.  *     [89/04/19            mja]
  68.  * 
  69.  * 23-Sep-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  70.  *    Merged old runv and runvp modules.
  71.  *
  72.  * 22-Nov-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  73.  *    Added check and kill if child process was stopped.
  74.  *
  75.  * 30-Apr-85  Steven Shafer (sas) at Carnegie-Mellon University
  76.  *    Adapted for 4.2 BSD UNIX:  Conforms to new signals and wait.
  77.  *
  78.  * 15-July-82 Mike Accetta (mja) and Neal Friedman (naf)
  79.  *                  at Carnegie-Mellon University
  80.  *    Added a return(-1) if vfork fails.  This should only happen
  81.  *    if there are no more processes available.
  82.  *
  83.  * 28-Jan-80  Steven Shafer (sas) at Carnegie-Mellon University
  84.  *    Added setuid and setgid for system programs' use.
  85.  *
  86.  * 21-Jan-80  Steven Shafer (sas) at Carnegie-Mellon University
  87.  *    Changed fork to vfork.
  88.  *
  89.  * 20-Nov-79  Steven Shafer (sas) at Carnegie-Mellon University
  90.  *    Created for VAX.  The proper way to fork-and-execute a system
  91.  *    program is now by "runvp" or "runp", with the program name
  92.  *    (rather than an absolute pathname) as the first argument;
  93.  *    that way, the "PATH" variable in the environment does the right
  94.  *    thing.  Too bad execvp and execlp (hence runvp and runp) don't
  95.  *    accept a pathlist as an explicit argument.
  96.  *
  97.  **********************************************************************
  98.  */
  99.  
  100. #include <sys/types.h>
  101. #include <sys/wait.h>
  102. #include <sys/resource.h>
  103. #include <stdio.h>
  104. #include <signal.h>
  105. #include <varargs.h>
  106.  
  107. extern uid_t getuid();
  108. extern gid_t getgid();
  109.  
  110. int run (name,va_alist)
  111. char *name;
  112. va_dcl
  113. {
  114.     int val;
  115.     va_list ap;
  116.  
  117.     va_start(ap);
  118.     val = runv (name,ap);
  119.     va_end(ap);
  120.     return(val);
  121. }
  122.  
  123. int runv (name,argv)
  124. char *name,**argv;
  125. {
  126.     return (dorun ((int (*)())0, name, argv, 0));
  127. }
  128.  
  129. int runp (name,va_alist)
  130. char *name;
  131. va_dcl
  132. {
  133.     int val;
  134.     va_list ap;
  135.  
  136.     va_start(ap);
  137.     val = runvp (name,ap);
  138.     va_end(ap);
  139.     return (val);
  140. }
  141.  
  142. int runvp (name,argv)
  143. char *name,**argv;
  144. {
  145.     return (dorun ((int (*)())0, name, argv, 1));
  146. }
  147.  
  148. int runc (func,name,va_alist)
  149. int (*func)();
  150. char *name;
  151. va_dcl
  152. {
  153.     int val;
  154.     va_list ap;
  155.  
  156.     va_start(ap);
  157.     val = runcv (func, name, ap);
  158.     va_end(ap);
  159.     return(val);
  160. }
  161.  
  162. int runcv (func,name,argv)
  163. int (*func)();
  164. char *name,**argv;
  165. {
  166.     return (dorun (func, name, argv, 0));
  167. }
  168.  
  169. int runcp (func,name,va_alist)
  170. int (*func)();
  171. char *name;
  172. va_dcl
  173. {
  174.     int val;
  175.     va_list ap;
  176.  
  177.     va_start(ap);
  178.     val = runcvp (func, name, ap);
  179.     va_end(ap);
  180.     return (val);
  181. }
  182.  
  183. int runcvp (func,name,argv)
  184. int (*func)();
  185. char *name,**argv;
  186. {
  187.     return (dorun (func, name, argv, 1));
  188. }
  189.  
  190. static
  191. int dorun (func,name,argv,usepath)
  192. int (*func)();
  193. char *name,**argv;
  194. int usepath;
  195. {
  196.     int wpid;
  197.     register int pid;
  198.     struct sigvec ignoresig,intsig,quitsig;
  199.     union wait status;
  200.     int execvp(), execv();
  201.     int (*execrtn)() = usepath ? execvp : execv;
  202.  
  203.     if ((pid = vfork()) == -1)
  204.         return(-1);    /* no more process's, so exit with error */
  205.  
  206.     if (pid == 0) {            /* child process */
  207.         if (func)
  208.             (*func)();
  209.         (void) setgid (getgid());
  210.         (void) setuid (getuid());
  211.         (*execrtn) (name,argv);
  212.         fprintf (stderr,"run: can't exec %s\n",name);
  213.         _exit (0377);
  214.     }
  215.  
  216.     ignoresig.sv_handler = SIG_IGN;    /* ignore INT and QUIT signals */
  217.     ignoresig.sv_mask = 0;
  218.     ignoresig.sv_onstack = 0;
  219.     (void) sigvec (SIGINT,&ignoresig,&intsig);
  220.     (void) sigvec (SIGQUIT,&ignoresig,&quitsig);
  221.     do {
  222.         wpid = wait3 (&status.w_status, WUNTRACED, (struct rusage *)0);
  223.         if (WIFSTOPPED (status)) {
  224.             (void) kill (0,SIGTSTP);
  225.             wpid = 0;
  226.         }
  227.     } while (wpid != pid && wpid != -1);
  228.     (void) sigvec (SIGINT,&intsig,(struct sigvec *)0); /* restore signals */
  229.     (void) sigvec (SIGQUIT,&quitsig,(struct sigvec *)0);
  230.  
  231.     if (WIFSIGNALED (status) || status.w_retcode == 0377)
  232.         return (-1);
  233.  
  234.     return (status.w_retcode);
  235. }
  236.