home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula
/
nebula.bin
/
SourceCode
/
libcs
/
run.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-11
|
7KB
|
236 lines
/*
* Copyright (c) 1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND CARNEGIE MELLON UNIVERSITY
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT
* SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Users of this software agree to return to Carnegie Mellon any
* improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
* Export of this software is permitted only after complying with the
* regulations of the U.S. Deptartment of Commerce relating to the
* Export of Technical Data.
*/
/* run[c], run[c]v, run[c]p, run[c]vp -- exec process and wait for it to exit
*
* Usage:
* i = run (file, arg1, arg2, ..., argn, 0);
* i = runv (file, arglist);
* i = runp (file, arg1, arg2, ..., argn, 0);
* i = runvp (file, arglist);
* i = runc (func, file, arg1, arg2, ..., argn, 0);
* i = runcv (func, file, arglist);
* i = runcp (func, file, arg1, arg2, ..., argn, 0);
* i = runcvp (func, file, arglist);
*
* Run, runv, runp, runvp and runc, runcv, runcp, runcvp have argument lists
* exactly like the corresponding routines, execl, execv, execlp, execvp. The
* run routines perform a fork, then:
* IN THE NEW PROCESS, an execl[p] or execv[p] is performed with the specified
* arguments (after first invoking the supplied function in the runc* cases).
* The process returns with a -1 code if the exec was not successful.
* IN THE PARENT PROCESS, the signals SIGQUIT and SIGINT are disabled,
* the process waits until the newly forked process exits, the
* signals are restored to their original status, and the return
* status of the process is analyzed.
* All run routines return: -1 if the exec failed or if the child was
* terminated abnormally; otherwise, the exit code of the child is
* returned.
*
**********************************************************************
* HISTORY
* $Log: run.c,v $
* Revision 1.4 90/12/11 17:58:10 mja
* Add copyright/disclaimer for distribution.
*
* Revision 1.3 90/02/01 16:13:57 mja
* Define new runc(), runcv(), runcp() amd runcvp() entry points;
* remove most lint.
* [90/02/01 15:22:40 mja]
*
* Revision 1.2 89/08/03 14:36:46 mja
* Update run() and runp() to use <varargs.h>.
* [89/04/19 mja]
*
* 23-Sep-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Merged old runv and runvp modules.
*
* 22-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Added check and kill if child process was stopped.
*
* 30-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University
* Adapted for 4.2 BSD UNIX: Conforms to new signals and wait.
*
* 15-July-82 Mike Accetta (mja) and Neal Friedman (naf)
* at Carnegie-Mellon University
* Added a return(-1) if vfork fails. This should only happen
* if there are no more processes available.
*
* 28-Jan-80 Steven Shafer (sas) at Carnegie-Mellon University
* Added setuid and setgid for system programs' use.
*
* 21-Jan-80 Steven Shafer (sas) at Carnegie-Mellon University
* Changed fork to vfork.
*
* 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University
* Created for VAX. The proper way to fork-and-execute a system
* program is now by "runvp" or "runp", with the program name
* (rather than an absolute pathname) as the first argument;
* that way, the "PATH" variable in the environment does the right
* thing. Too bad execvp and execlp (hence runvp and runp) don't
* accept a pathlist as an explicit argument.
*
**********************************************************************
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <stdio.h>
#include <signal.h>
#include <varargs.h>
extern uid_t getuid();
extern gid_t getgid();
int run (name,va_alist)
char *name;
va_dcl
{
int val;
va_list ap;
va_start(ap);
val = runv (name,ap);
va_end(ap);
return(val);
}
int runv (name,argv)
char *name,**argv;
{
return (dorun ((int (*)())0, name, argv, 0));
}
int runp (name,va_alist)
char *name;
va_dcl
{
int val;
va_list ap;
va_start(ap);
val = runvp (name,ap);
va_end(ap);
return (val);
}
int runvp (name,argv)
char *name,**argv;
{
return (dorun ((int (*)())0, name, argv, 1));
}
int runc (func,name,va_alist)
int (*func)();
char *name;
va_dcl
{
int val;
va_list ap;
va_start(ap);
val = runcv (func, name, ap);
va_end(ap);
return(val);
}
int runcv (func,name,argv)
int (*func)();
char *name,**argv;
{
return (dorun (func, name, argv, 0));
}
int runcp (func,name,va_alist)
int (*func)();
char *name;
va_dcl
{
int val;
va_list ap;
va_start(ap);
val = runcvp (func, name, ap);
va_end(ap);
return (val);
}
int runcvp (func,name,argv)
int (*func)();
char *name,**argv;
{
return (dorun (func, name, argv, 1));
}
static
int dorun (func,name,argv,usepath)
int (*func)();
char *name,**argv;
int usepath;
{
int wpid;
register int pid;
struct sigvec ignoresig,intsig,quitsig;
union wait status;
int execvp(), execv();
int (*execrtn)() = usepath ? execvp : execv;
if ((pid = vfork()) == -1)
return(-1); /* no more process's, so exit with error */
if (pid == 0) { /* child process */
if (func)
(*func)();
(void) setgid (getgid());
(void) setuid (getuid());
(*execrtn) (name,argv);
fprintf (stderr,"run: can't exec %s\n",name);
_exit (0377);
}
ignoresig.sv_handler = SIG_IGN; /* ignore INT and QUIT signals */
ignoresig.sv_mask = 0;
ignoresig.sv_onstack = 0;
(void) sigvec (SIGINT,&ignoresig,&intsig);
(void) sigvec (SIGQUIT,&ignoresig,&quitsig);
do {
wpid = wait3 (&status.w_status, WUNTRACED, (struct rusage *)0);
if (WIFSTOPPED (status)) {
(void) kill (0,SIGTSTP);
wpid = 0;
}
} while (wpid != pid && wpid != -1);
(void) sigvec (SIGINT,&intsig,(struct sigvec *)0); /* restore signals */
(void) sigvec (SIGQUIT,&quitsig,(struct sigvec *)0);
if (WIFSIGNALED (status) || status.w_retcode == 0377)
return (-1);
return (status.w_retcode);
}