#include <pwd.h>
#include <zone.h>
#include <dial.h>
#include <stdlib.h>
#include "limits.h"
#include "stdarg.h"
#include "wait.h"
#include "dial.h"
#include "lpsched.h"
#include <syslog.h>
#include "tsol/label.h"
#define Done(EC,ERRNO) done(((EC) << 8),ERRNO)
#define STRLCAT(dst, src, size) \
if (strlcat((dst), (src), (size)) >= (size)) { \
errno = EINVAL; \
return (-1); \
}
static MESG * ChildMd;
static int ChildPid;
static int WaitedChildPid;
static int do_undial;
static char argbuf[ARG_MAX];
static long key;
static void sigtrap ( int );
static void done ( int , int );
static void cool_heels ( void );
static void addenv (char ***envp, char * , char * );
static void trap_fault_signals ( void );
static void ignore_fault_signals ( void );
static void child_mallocfail ( void );
static void Fork2 ( void );
static int Fork1 ( EXEC * );
static void
relock(void)
{
struct flock l;
l.l_type = F_WRLCK;
l.l_whence = 1;
l.l_start = 0;
l.l_len = 0;
(void)Fcntl (lock_fd, F_SETLK, &l);
return;
}
static char *_exec_name(int type)
{
static char *_names[] = {
"", "EX_INTERF", "EX_SLOWF", "EX_ALERT", "EX_FALERT", "EX_PALERT",
"EX_NOTIFY", "EX_FAULT_MESSAGE", "EX_FORM_MESSAGE", NULL };
if ((type < 0) || (type > EX_FORM_MESSAGE))
return ("BAD_EXEC_TYPE");
else
return (_names[type]);
}
void clean_string(char *ptr)
{
char *cp;
wchar_t wc;
size_t len;
for (cp = ptr; *cp != '\0'; ) {
if ((len = mbtowc(&wc, cp, MB_CUR_MAX)) == -1) {
cp++;
continue;
}
if (len == 1 &&
((wc == L'`') || (wc == L'&') || (wc == L';') ||
(wc == L'|') || (wc == L'>') || (wc == L'^') ||
(wc == L'$') || (wc == L'(') || (wc == L')') ||
(wc == L'<') || (wc == L'*') || (wc == L'?') ||
(wc == L'[')))
*cp = '_';
cp += len;
}
}
enum trust {TRUSTED, UNTRUSTED};
static char *arg_string(enum trust type, char *fmt, ...) __PRINTFLIKE(2);
static char *
arg_string(enum trust type, char *fmt, ...)
{
char buf[BUFSIZ];
va_list args;
va_start(args, fmt);
(void) vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if (type == UNTRUSTED)
clean_string(buf);
return (strdup(buf));
}
static char time_buf[50];
int
exec(int type, ...)
{
va_list args;
int i;
int procuid;
int procgid;
int ret;
int fr_flg;
char *cp;
char *infile;
char *outfile;
char *errfile;
char *sep;
char **listp;
char **file_list;
char *printerName;
char *printerNameToShow;
static char nameBuf[100];
char keyBuf[sizeof (BIGGEST_NUMBER_S)];
char *clean_title;
PSTATUS *printer;
RSTATUS *request;
FSTATUS *form;
EXEC *ep;
PWSTATUS *pwheel;
time_t now;
struct passwd *pwp;
#ifdef LP_USE_PAPI_ATTR
struct stat tmpBuf;
char tmpName[BUFSIZ];
char *path = NULL;
#endif
char *av[ARG_MAX];
char **envp = NULL;
int ac = 0;
char *mail_zonename = NULL;
char *slabel = NULL;
int setid = 1;
char *ridno = NULL, *tmprid = NULL;
syslog(LOG_DEBUG, "exec(%s)", _exec_name(type));
memset(av, 0, sizeof (*av));
va_start (args, type);
switch (type) {
case EX_INTERF:
printer = va_arg(args, PSTATUS *);
request = printer->request;
ep = printer->exec;
break;
case EX_FAULT_MESSAGE:
printer = va_arg(args, PSTATUS *);
request = va_arg(args, RSTATUS *);
if (! ( printer->status & (PS_FORM_FAULT | PS_SHOW_FAULT))) {
return(0);
}
ep = printer->fault_exec;
printerName = (printer->printer && printer->printer->name
? printer->printer->name : "??");
snprintf(nameBuf, sizeof (nameBuf),
"%s (on %s)\n", printerName, Local_System);
printerNameToShow = nameBuf;
(void) time(&now);
(void) strftime(time_buf, sizeof (time_buf),
NULL, localtime(&now));
break;
case EX_SLOWF:
request = va_arg(args, RSTATUS *);
ep = request->exec;
break;
case EX_NOTIFY:
request = va_arg(args, RSTATUS *);
if (request->request->actions & ACT_NOTIFY) {
errno = EINVAL;
return (-1);
}
ep = request->exec;
break;
case EX_ALERT:
printer = va_arg(args, PSTATUS *);
if (!(printer->printer->fault_alert.shcmd)) {
errno = EINVAL;
return(-1);
}
ep = printer->alert->exec;
break;
case EX_PALERT:
pwheel = va_arg(args, PWSTATUS *);
ep = pwheel->alert->exec;
break;
case EX_FORM_MESSAGE:
(void) time(&now);
(void) strftime(time_buf, sizeof (time_buf),
NULL, localtime(&now));
case EX_FALERT:
form = va_arg(args, FSTATUS *);
ep = form->alert->exec;
break;
default:
errno = EINVAL;
return(-1);
}
va_end (args);
if (!ep || (ep->pid > 0)) {
errno = EBUSY;
return(-1);
}
ep->flags = 0;
key = ep->key = getkey();
switch ((ep->pid = Fork1(ep))) {
case -1:
relock ();
return(-1);
case 0:
lp_alloc_fail_handler = child_mallocfail;
break;
default:
switch(type) {
case EX_INTERF:
request->request->outcome |= RS_PRINTING;
break;
case EX_NOTIFY:
request->request->outcome |= RS_NOTIFYING;
break;
case EX_SLOWF:
request->request->outcome |= RS_FILTERING;
request->request->outcome &= ~RS_REFILTER;
break;
}
return(0);
}
for (i = 0; i < NSIG; i++)
(void)signal (i, SIG_DFL);
(void)signal (SIGALRM, SIG_IGN);
(void)signal (SIGTERM, sigtrap);
closelog();
for (i = 0; i < OpenMax; i++)
if (i != ChildMd->writefd)
Close (i);
openlog("lpsched", LOG_PID|LOG_NDELAY|LOG_NOWAIT, LOG_LPR);
setpgrp();
addenv (&envp, "PATH", "/usr/lib/lp/bin:/usr/bin:/bin:/usr/sbin:/sbin");
addenv (&envp, "TZ", getenv("TZ"));
addenv (&envp, "LANG", getenv("LANG"));
addenv (&envp, "LC_ALL", getenv("LC_ALL"));
addenv (&envp, "LC_COLLATE", getenv("LC_COLLATE"));
addenv (&envp, "LC_CTYPE", getenv("LC_CTYPE"));
addenv (&envp, "LC_MESSAGES", getenv("LC_MESSAGES"));
addenv (&envp, "LC_MONETARY", getenv("LC_MONETARY"));
addenv (&envp, "LC_NUMERIC", getenv("LC_NUMERIC"));
addenv (&envp, "LC_TIME", getenv("LC_TIME"));
sprintf (keyBuf, "%ld", key);
addenv (&envp, "SPOOLER_KEY", keyBuf);
#if defined(DEBUG)
addenv (&envp, "LPDEBUG", (debug? "1" : "0"));
#endif
switch (type) {
case EX_SLOWF:
case EX_INTERF:
infile = 0;
outfile = 0;
errfile = makereqerr(request);
break;
case EX_NOTIFY:
infile = makereqerr(request);
outfile = 0;
errfile = 0;
break;
case EX_ALERT:
case EX_FALERT:
case EX_PALERT:
case EX_FAULT_MESSAGE:
case EX_FORM_MESSAGE:
infile = 0;
outfile = 0;
errfile = 0;
break;
}
if (infile) {
if (Open(infile, O_RDONLY) == -1)
Done (EXEC_EXIT_NOPEN, errno);
} else {
if (Open("/dev/null", O_RDONLY) == -1)
Done (EXEC_EXIT_NOPEN, errno);
}
if (outfile) {
if (Open(outfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1)
Done (EXEC_EXIT_NOPEN, errno);
} else {
if (Open("/dev/null", O_WRONLY) == -1)
Done (EXEC_EXIT_NOPEN, errno);
}
if (errfile) {
if (Open(errfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1)
Done (EXEC_EXIT_NOPEN, errno);
} else {
if (Open("/dev/null", O_WRONLY) == -1)
Done (EXEC_EXIT_NOPEN, errno);
}
switch (type) {
case EX_INTERF:
trap_fault_signals ();
(void)Close (1);
procuid = request->secure->uid;
procgid = request->secure->gid;
if (printer->printer->dial_info)
{
ret = open_dialup(request->printer_type,
printer->printer);
if (ret == 0)
do_undial = 1;
}
else
{
ret = open_direct(request->printer_type,
printer->printer);
do_undial = 0;
if (is_printer_uri(printer->printer->device) == 0)
addenv(&envp, "DEVICE_URI",
printer->printer->device);
}
addenv(&envp, "DEVICE_URI",
printer->printer->device);
if (ret != 0)
Done (ret, errno);
if (!(request->request->outcome & RS_FILTERED))
file_list = request->request->file_list;
else {
register int count = 0;
char num[sizeof (BIGGEST_REQID_S)];
register char * prefix;
prefix = makestr(
Lp_Temp,
"/F",
getreqno(request->secure->req_id),
"-",
(char *)0
);
file_list = (char **)Malloc(
(lenlist(request->request->file_list) + 1)
* sizeof(char *)
);
for (
listp = request->request->file_list;
*listp;
listp++
) {
sprintf (num, "%d", count + 1);
file_list[count] = makestr(
prefix,
num,
(char *)0
);
count++;
}
file_list[count] = 0;
}
#ifdef LP_USE_PAPI_ATTR
snprintf(tmpName, sizeof (tmpName), "%s-%s",
getreqno(request->secure->req_id), LP_PAPIATTRNAME);
path = makepath(Lp_Temp, tmpName, (char *)0);
if ((path != NULL) && (stat(path, &tmpBuf) == 0))
{
addenv(&envp, "ATTRPATH", path);
}
Free(path);
if ((request->printer != NULL) &&
(request->printer->printer != NULL) &&
(request->printer->printer->name != NULL))
{
snprintf(tmpName, sizeof (tmpName), "%s.ppd",
request->printer->printer->name);
path = makepath(ETCDIR, "ppd", tmpName, (char *)0);
if ((path != NULL) && (stat(path, &tmpBuf) == 0))
{
addenv(&envp, "PPD", path);
}
Free(path);
}
#endif
if (request->printer_type)
addenv(&envp, "TERM", request->printer_type);
if (!(printer->printer->daisy)) {
register char * chset = 0;
register char * csp;
if (
request->form
&& request->form->form->chset
&& request->form->form->mandatory
&& !STREQU(NAME_ANY, request->form->form->chset)
)
chset = request->form->form->chset;
else if (
request->request->charset
&& !STREQU(NAME_ANY, request->request->charset)
)
chset = request->request->charset;
if (chset) {
csp = search_cslist(
chset,
printer->printer->char_sets
);
addenv (&envp, "CHARSET",
(csp? strtok(csp, "=") : chset)
);
}
}
if (request->fast)
addenv(&envp, "FILTER", request->fast);
if (is_system_labeled() && request->secure->slabel != NULL)
addenv(&envp, "SLABEL", request->secure->slabel);
cp = strchr(request->secure->user, '@');
allTraysWithForm(printer, request->form);
fr_flg = 1;
clean_title = strdup(NB(request->request->title));
if (clean_title == NULL) {
clean_title = NB(request->request->title);
fr_flg = 0;
} else if (strcmp(clean_title, "") != 0) {
char *ct_p;
for (ct_p = clean_title; *ct_p != '\0'; ct_p++) {
if (*ct_p == '"')
*ct_p = ' ';
}
}
av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_A_Interfaces,
printer->printer->name);
if (request->request->options != NULL) {
char *options = NULL, *temp = NULL;
options = temp = strdup(request->request->options);
options = strstr(options, "job-id-requested");
if (options != NULL) {
if (STRNEQU(options, "job-id-requested=", 17)) {
ridno = strdup(options + 17);
tmprid = strstr(ridno, " ");
if (ridno != NULL) {
tmprid = strstr(ridno, " ");
if (tmprid != NULL)
*tmprid = '\0';
setid = 0;
} else
setid = 1;
} else
setid = 1;
} else
setid = 1;
if (temp != NULL)
free(temp);
} else
setid = 1;
if (setid)
av[ac++] = arg_string(TRUSTED, "%s",
request->secure->req_id);
else {
char *r1 = NULL, *r2 = NULL, *tmp = NULL;
r1 = r2 = tmp = strdup(request->secure->req_id);
r2 = strrchr(r1, '-');
if (r2 != NULL) {
char *r3 = NULL;
int lr1 = strlen(r1);
int lr2 = strlen(r2);
r1[lr1 - lr2 + 1] = '\0';
lr1 = strlen(r1);
lr2 = strlen(ridno);
r3 = (char *)malloc(lr1+lr2+1);
if (r3 != NULL) {
strcpy(r3, r1);
strcat(r3, ridno);
av[ac++] = arg_string(TRUSTED,
"%s", r3);
free(r3);
} else
av[ac++] = arg_string(TRUSTED, "%s",
request->secure->req_id);
} else
av[ac++] = arg_string(TRUSTED, "%s",
request->secure->req_id);
if (tmp != NULL)
free(tmp);
if (ridno != NULL)
free(ridno);
}
av[ac++] = arg_string(UNTRUSTED, "%s", request->request->user);
av[ac++] = arg_string(TRUSTED, "%s", clean_title);
av[ac++] = arg_string(TRUSTED, "%d", request->copies);
if (fr_flg)
free (clean_title);
sep = "";
argbuf[0] = '\0';
if (printer->printer->options) {
char **tmp = printer->printer->options;
while(*tmp != NULL) {
STRLCAT(argbuf, sep, sizeof (argbuf));
sep = " ";
STRLCAT(argbuf, *tmp++, sizeof (argbuf));
}
}
if (printer->printer->stty) {
STRLCAT (argbuf, sep, sizeof (argbuf));
sep = " ";
STRLCAT (argbuf, "stty='", sizeof (argbuf));
STRLCAT (argbuf, printer->printer->stty,
sizeof (argbuf));
STRLCAT (argbuf, "'", sizeof (argbuf));
}
if (request->request->options) {
listp = dashos(request->request->options);
while (*listp) {
if (
!STRNEQU(*listp, "cpi=", 4)
&& !STRNEQU(*listp, "lpi=", 4)
&& !STRNEQU(*listp, "width=", 6)
&& !STRNEQU(*listp, "length=", 7)
) {
STRLCAT (argbuf, sep, sizeof (argbuf));
sep = " ";
STRLCAT (argbuf, *listp,
sizeof (argbuf));
}
listp++;
}
}
if (request->cpi) {
STRLCAT (argbuf, sep, sizeof (argbuf));
sep = " ";
STRLCAT (argbuf, "cpi=", sizeof (argbuf));
STRLCAT (argbuf, request->cpi, sizeof (argbuf));
}
if (request->lpi) {
STRLCAT (argbuf, sep, sizeof (argbuf));
sep = " ";
STRLCAT (argbuf, "lpi=", sizeof (argbuf));
STRLCAT (argbuf, request->lpi, sizeof (argbuf));
}
if (request->pwid) {
STRLCAT (argbuf, sep, sizeof (argbuf));
sep = " ";
STRLCAT (argbuf, "width=", sizeof (argbuf));
STRLCAT (argbuf, request->pwid, sizeof (argbuf));
}
if (request->plen) {
STRLCAT (argbuf, sep, sizeof (argbuf));
sep = " ";
STRLCAT (argbuf, "length=", sizeof (argbuf));
STRLCAT (argbuf, request->plen, sizeof (argbuf));
}
if (request->request->actions & ACT_RAW) {
STRLCAT (argbuf, sep, sizeof (argbuf));
sep = " ";
STRLCAT (argbuf, "stty=-opost", sizeof (argbuf));
}
av[ac++] = arg_string(UNTRUSTED, "%s", argbuf);
for (listp = file_list; *listp; listp++)
av[ac++] = arg_string(TRUSTED, "%s", *listp);
(void)chfiles (file_list, procuid, procgid);
break;
case EX_SLOWF:
if (request->slow)
addenv(&envp, "FILTER", request->slow);
procuid = request->secure->uid;
procgid = request->secure->gid;
cp = _alloc_files(
lenlist(request->request->file_list),
getreqno(request->secure->req_id),
procuid, procgid);
av[ac++] = arg_string(TRUSTED, "%s", Lp_Slow_Filter);
av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_Temp, cp);
for (listp = request->request->file_list; *listp; listp++)
av[ac++] = arg_string(TRUSTED, "%s", *listp);
(void)chfiles (request->request->file_list, procuid, procgid);
#ifdef LP_USE_PAPI_ATTR
snprintf(tmpName, sizeof (tmpName), "%s-%s",
getreqno(request->secure->req_id), LP_PAPIATTRNAME);
path = makepath(Lp_Temp, tmpName, (char *)0);
if ((path != NULL) && (stat(path, &tmpBuf) == 0))
{
addenv(&envp, "ATTRPATH", path);
}
Free(path);
if ((request->printer != NULL) &&
(request->printer->printer != NULL) &&
(request->printer->printer->name != NULL))
{
snprintf(tmpName, sizeof (tmpName), "%s.ppd",
request->printer->printer->name);
path = makepath(ETCDIR, "ppd", tmpName, (char *)0);
if ((path != NULL) && (stat(path, &tmpBuf) == 0))
{
addenv(&envp, "PPD", path);
}
Free(path);
}
#endif
break;
case EX_ALERT:
procuid = Lp_Uid;
procgid = Lp_Gid;
(void)Chown (printer->alert->msgfile, procuid, procgid);
av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers,
printer->printer->name, ALERTSHFILE);
av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);
break;
case EX_PALERT:
procuid = Lp_Uid;
procgid = Lp_Gid;
(void)Chown (pwheel->alert->msgfile, procuid, procgid);
av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_PrintWheels,
pwheel->pwheel->name, ALERTSHFILE);
av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);
break;
case EX_FALERT:
procuid = Lp_Uid;
procgid = Lp_Gid;
(void)Chown (form->alert->msgfile, procuid, procgid);
av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms,
form->form->name, ALERTSHFILE);
av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);
break;
case EX_FORM_MESSAGE:
procuid = Lp_Uid;
procgid = Lp_Gid;
av[ac++] = arg_string(TRUSTED, "%s/form", Lp_A_Faults);
av[ac++] = arg_string(TRUSTED, "%s", form->form->name);
av[ac++] = arg_string(TRUSTED, "%s", time_buf);
av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms,
form->form->name, FORMMESSAGEFILE);
break;
case EX_FAULT_MESSAGE:
procuid = Lp_Uid;
procgid = Lp_Gid;
av[ac++] = arg_string(TRUSTED, "%s/printer", Lp_A_Faults);
av[ac++] = arg_string(TRUSTED, "%s", printerNameToShow);
av[ac++] = arg_string(TRUSTED, "%s", time_buf);
av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers,
printerName, FAULTMESSAGEFILE);
break;
case EX_NOTIFY:
if (request->request->alert) {
procuid = request->secure->uid;
procgid = request->secure->gid;
av[ac++] = arg_string(TRUSTED, "%s",
request->request->alert);
} else {
char *user = strdup(request->request->user);
clean_string(user);
slabel = request->secure->slabel;
if (request->request->actions & ACT_WRITE) {
av[ac++] = arg_string(TRUSTED, "%s", BINWRITE);
snprintf(argbuf, sizeof (argbuf),
"%s %s || %s %s",
BINWRITE, user,
BINMAIL, user
);
av[ac++] = arg_string(TRUSTED, "/bin/sh");
av[ac++] = arg_string(TRUSTED, "-c");
av[ac++] = arg_string(TRUSTED, "%s", argbuf);
} else if ((getzoneid() == GLOBAL_ZONEID) &&
is_system_labeled() && (slabel != NULL)) {
if ((mail_zonename =
get_labeled_zonename(slabel)) ==
(char *)-1) {
return(0);
}
}
if (mail_zonename == NULL) {
procuid = Lp_Uid;
procgid = Lp_Gid;
av[ac++] = arg_string(TRUSTED, "%s", BINMAIL);
av[ac++] = arg_string(UNTRUSTED, "%s", user);
} else {
procuid = getuid();
procgid = getgid();
av[ac++] = arg_string(TRUSTED, "%s",
"/usr/sbin/zlogin");
av[ac++] = arg_string(TRUSTED, "%s",
mail_zonename);
av[ac++] = arg_string(TRUSTED, "%s",
BINMAIL);
av[ac++] = arg_string(UNTRUSTED, "%s",
user);
Free(mail_zonename);
}
free(user);
}
break;
}
av[ac++] = NULL;
Fork2 ();
pwp = getpwuid(procuid);
if (pwp == NULL) {
note("getpwuid(%d) call failed\n", procuid);
} else if (initgroups(pwp->pw_name, procgid) < 0) {
note("initgroups() call failed %d\n", errno);
}
setgid (procgid);
setuid (procuid);
#ifdef DEBUG
for (i = 0; av[i] != NULL; i++)
note("exec(%s): av[%d] = %s", _exec_name(type), i, av[i]);
for (i = 0; envp[i] != NULL; i++)
note("exec(%s): envp[%d] = %s", _exec_name(type), i, envp[i]);
#endif
execvpe(av[0], av, envp);
Done (EXEC_EXIT_NEXEC, errno);
return (0);
}
static void
addenv(char ***envp, char *name, char *value)
{
register char * cp;
if ((name == NULL) || (value == NULL))
return;
if ((cp = makestr(name, "=", value, (char *)0)))
addlist(envp, cp);
return;
}
static int
Fork1(EXEC *ep)
{
int pid;
int fds[2];
if (pipe(fds) == -1) {
note("Failed to create pipe for child process (%s).\n", PERROR);
errno = EAGAIN ;
return(-1);
}
ep->md = mconnect((char *)0, fds[0], fds[1]);
switch (pid = fork()) {
case -1:
mdisconnect(ep->md);
close(fds[0]);
close(fds[1]);
ep->md = 0;
return (-1);
case 0:
ChildMd = mconnect(NULL, fds[1], fds[1]);
return (0);
default:
mlistenadd(ep->md, POLLIN);
return (pid);
}
}
static void
Fork2(void)
{
switch ((ChildPid = fork())) {
case -1:
Done (EXEC_EXIT_NFORK, errno);
case 0:
return;
default:
cool_heels ();
}
}
static void
cool_heels(void)
{
int status;
sleep (1);
ignore_fault_signals ();
WaitedChildPid = 0;
while ((WaitedChildPid = wait(&status)) != ChildPid)
;
if (
EXITED(status) > EXEC_EXIT_USER
&& EXITED(status) != EXEC_EXIT_FAULT
)
Done (EXEC_EXIT_EXIT, EXITED(status));
done (status, 0);
}
static void
trap_fault_signals(void)
{
signal (SIGHUP, sigtrap);
signal (SIGINT, sigtrap);
signal (SIGQUIT, sigtrap);
signal (SIGPIPE, sigtrap);
return;
}
static void
ignore_fault_signals(void)
{
signal (SIGHUP, SIG_IGN);
signal (SIGINT, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
signal (SIGPIPE, SIG_IGN);
return;
}
static void
sigtrap(int sig)
{
signal (sig, SIG_IGN);
switch (sig) {
case SIGHUP:
Done (EXEC_EXIT_HUP, 0);
case SIGQUIT:
case SIGINT:
Done (EXEC_EXIT_INTR, 0);
case SIGPIPE:
Done (EXEC_EXIT_PIPE, 0);
case SIGTERM:
if (ChildPid != WaitedChildPid) {
register int cpid;
while (
(cpid = wait((int *)0)) != ChildPid
&& (cpid != -1 || errno != ECHILD)
)
;
}
done (SIGTERM, 0);
}
}
static void
done(int status, int err)
{
if (do_undial)
undial (1);
mputm (ChildMd, S_CHILD_DONE, key, status, err);
mdisconnect (ChildMd);
exit (0);
}
static void
child_mallocfail(void)
{
Done (EXEC_EXIT_NOMEM, ENOMEM);
}