10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51676Sjpk * Common Development and Distribution License (the "License"). 61676Sjpk * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 21*3125Sjacobs 220Sstevel@tonic-gate /* 231676Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 27320Sceastha /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28320Sceastha /* All Rights Reserved */ 29320Sceastha 300Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 310Sstevel@tonic-gate 321676Sjpk #include <pwd.h> 331676Sjpk #include <zone.h> 341676Sjpk #if defined PS_FAULTED 351676Sjpk #undef PS_FAULTED 361676Sjpk #endif /* PS_FAULTED */ 370Sstevel@tonic-gate #include <dial.h> 380Sstevel@tonic-gate 390Sstevel@tonic-gate #include <stdlib.h> 400Sstevel@tonic-gate #include "limits.h" 410Sstevel@tonic-gate #include "stdarg.h" 420Sstevel@tonic-gate #include "wait.h" 430Sstevel@tonic-gate #include "dial.h" 440Sstevel@tonic-gate #include "lpsched.h" 450Sstevel@tonic-gate #include <syslog.h> 461676Sjpk #include "tsol/label.h" 470Sstevel@tonic-gate 480Sstevel@tonic-gate #define Done(EC,ERRNO) done(((EC) << 8),ERRNO) 490Sstevel@tonic-gate 500Sstevel@tonic-gate #define STRLCAT(dst, src, size) \ 510Sstevel@tonic-gate if (strlcat((dst), (src), (size)) >= (size)) { \ 520Sstevel@tonic-gate errno = EINVAL; \ 530Sstevel@tonic-gate return (-1); \ 540Sstevel@tonic-gate } 550Sstevel@tonic-gate 560Sstevel@tonic-gate static MESG * ChildMd; 570Sstevel@tonic-gate 580Sstevel@tonic-gate static int ChildPid; 590Sstevel@tonic-gate static int WaitedChildPid; 600Sstevel@tonic-gate static int do_undial; 610Sstevel@tonic-gate 620Sstevel@tonic-gate static char argbuf[ARG_MAX]; 630Sstevel@tonic-gate 640Sstevel@tonic-gate static long key; 650Sstevel@tonic-gate 660Sstevel@tonic-gate static void sigtrap ( int ); 670Sstevel@tonic-gate static void done ( int , int ); 680Sstevel@tonic-gate static void cool_heels ( void ); 690Sstevel@tonic-gate static void addenv (char ***envp, char * , char * ); 700Sstevel@tonic-gate static void trap_fault_signals ( void ); 710Sstevel@tonic-gate static void ignore_fault_signals ( void ); 720Sstevel@tonic-gate static void child_mallocfail ( void ); 730Sstevel@tonic-gate static void Fork2 ( void ); 740Sstevel@tonic-gate 750Sstevel@tonic-gate static int Fork1 ( EXEC * ); 760Sstevel@tonic-gate 770Sstevel@tonic-gate static void 780Sstevel@tonic-gate relock(void) 790Sstevel@tonic-gate { 800Sstevel@tonic-gate struct flock l; 810Sstevel@tonic-gate 820Sstevel@tonic-gate l.l_type = F_WRLCK; 830Sstevel@tonic-gate l.l_whence = 1; 840Sstevel@tonic-gate l.l_start = 0; 850Sstevel@tonic-gate l.l_len = 0; 860Sstevel@tonic-gate (void)Fcntl (lock_fd, F_SETLK, &l); 870Sstevel@tonic-gate return; 880Sstevel@tonic-gate } 890Sstevel@tonic-gate 900Sstevel@tonic-gate static char *_exec_name(int type) 910Sstevel@tonic-gate { 920Sstevel@tonic-gate static char *_names[] = { 930Sstevel@tonic-gate "", "EX_INTERF", "EX_SLOWF", "EX_ALERT", "EX_FALERT", "EX_PALERT", 940Sstevel@tonic-gate "EX_NOTIFY", "EX_FAULT_MESSAGE", "EX_FORM_MESSAGE", NULL }; 950Sstevel@tonic-gate 960Sstevel@tonic-gate if ((type < 0) || (type > EX_FORM_MESSAGE)) 970Sstevel@tonic-gate return ("BAD_EXEC_TYPE"); 980Sstevel@tonic-gate else 990Sstevel@tonic-gate return (_names[type]); 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate /* 1030Sstevel@tonic-gate * This function replaces characters in a string that might be used 1040Sstevel@tonic-gate * to exploit a security hole. Replace command seperators (`, &, ;, |, ^), 1050Sstevel@tonic-gate * output redirection (>, |), variable expansion ($), and character 1060Sstevel@tonic-gate * escape (\). 1070Sstevel@tonic-gate * 1080Sstevel@tonic-gate * Bugid 4141687 1090Sstevel@tonic-gate * Add ( ) < * ? [ 1100Sstevel@tonic-gate * Bugid 4139071 1110Sstevel@tonic-gate * Remove \ 1120Sstevel@tonic-gate */ 1130Sstevel@tonic-gate void clean_string(char *ptr) 1140Sstevel@tonic-gate { 1150Sstevel@tonic-gate char *cp; 1160Sstevel@tonic-gate wchar_t wc; 1170Sstevel@tonic-gate size_t len; 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate for (cp = ptr; *cp != NULL; ) { 1200Sstevel@tonic-gate if ((len = mbtowc(&wc, cp, MB_CUR_MAX)) == -1) { 1210Sstevel@tonic-gate cp++; 1220Sstevel@tonic-gate continue; 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate if (len == 1 && 1260Sstevel@tonic-gate ((wc == L'`') || (wc == L'&') || (wc == L';') || 1270Sstevel@tonic-gate (wc == L'|') || (wc == L'>') || (wc == L'^') || 1280Sstevel@tonic-gate (wc == L'$') || (wc == L'(') || (wc == L')') || 1290Sstevel@tonic-gate (wc == L'<') || (wc == L'*') || (wc == L'?') || 1300Sstevel@tonic-gate (wc == L'['))) 1310Sstevel@tonic-gate *cp = '_'; 1320Sstevel@tonic-gate cp += len; 1330Sstevel@tonic-gate } 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate enum trust {TRUSTED, UNTRUSTED}; 1370Sstevel@tonic-gate static char * 1380Sstevel@tonic-gate arg_string(enum trust type, char *fmt, ...) 1390Sstevel@tonic-gate { 1400Sstevel@tonic-gate char buf[BUFSIZ]; 1410Sstevel@tonic-gate va_list args; 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate va_start(args, fmt); 1440Sstevel@tonic-gate (void) vsnprintf(buf, sizeof(buf), fmt, args); 1450Sstevel@tonic-gate va_end(args); 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate /* 1480Sstevel@tonic-gate * If the string contains data from an untrusted origin (user supplied), 1490Sstevel@tonic-gate * clean it up in case one of our progeny is a shell script and isn't 1500Sstevel@tonic-gate * careful about checking its input. 1510Sstevel@tonic-gate */ 1520Sstevel@tonic-gate if (type == UNTRUSTED) 1530Sstevel@tonic-gate clean_string(buf); 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate return (strdup(buf)); 1560Sstevel@tonic-gate } 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate /* stolen from libc/gen/port/gen/execvp.c */ 1590Sstevel@tonic-gate static const char * 1600Sstevel@tonic-gate execat(const char *s1, const char *s2, char *si) 1610Sstevel@tonic-gate { 1620Sstevel@tonic-gate char *s; 1630Sstevel@tonic-gate int cnt = PATH_MAX + 1; /* number of characters in s2 */ 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate s = si; 1660Sstevel@tonic-gate while (*s1 && *s1 != ':') { 1670Sstevel@tonic-gate if (cnt > 0) { 1680Sstevel@tonic-gate *s++ = *s1++; 1690Sstevel@tonic-gate cnt--; 1700Sstevel@tonic-gate } else 1710Sstevel@tonic-gate s1++; 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate if (si != s && cnt > 0) { 1740Sstevel@tonic-gate *s++ = '/'; 1750Sstevel@tonic-gate cnt--; 1760Sstevel@tonic-gate } 1770Sstevel@tonic-gate while (*s2 && cnt > 0) { 1780Sstevel@tonic-gate *s++ = *s2++; 1790Sstevel@tonic-gate cnt--; 1800Sstevel@tonic-gate } 1810Sstevel@tonic-gate *s = '\0'; 1820Sstevel@tonic-gate return (*s1 ? ++s1: 0); 1830Sstevel@tonic-gate } 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate /* 1860Sstevel@tonic-gate * Similiar to execvp(), execpt you can supply an environment and we always 1870Sstevel@tonic-gate * use /bin/sh for shell scripts. The PATH searched is the PATH in the 1880Sstevel@tonic-gate * current environment, not the environment in the argument list. 1890Sstevel@tonic-gate * This was pretty much stolen from libc/gen/port/execvp.c 1900Sstevel@tonic-gate */ 1910Sstevel@tonic-gate static int 1920Sstevel@tonic-gate execvpe(char *name, char *const argv[], char *const envp[]) 1930Sstevel@tonic-gate { 1940Sstevel@tonic-gate char *path; 1950Sstevel@tonic-gate char fname[PATH_MAX+2]; 1960Sstevel@tonic-gate char *newargs[256]; 1970Sstevel@tonic-gate int i; 1980Sstevel@tonic-gate const char *cp; 1990Sstevel@tonic-gate unsigned etxtbsy = 1; 2000Sstevel@tonic-gate int eacces = 0; 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate if (*name == '\0') { 2030Sstevel@tonic-gate errno = ENOENT; 2040Sstevel@tonic-gate return (-1); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate if ((path = getenv("PATH")) == NULL) 2080Sstevel@tonic-gate path = "/usr/bin:/bin"; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate cp = strchr(name, '/')? (const char *)"": path; 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate do { 2130Sstevel@tonic-gate cp = execat(cp, name, fname); 2140Sstevel@tonic-gate retry: 2150Sstevel@tonic-gate /* 2160Sstevel@tonic-gate * 4025035 and 4038378 2170Sstevel@tonic-gate * if a filename begins with a "-" prepend "./" so that 2180Sstevel@tonic-gate * the shell can't interpret it as an option 2190Sstevel@tonic-gate */ 2200Sstevel@tonic-gate if (*fname == '-') { 2210Sstevel@tonic-gate size_t size = strlen(fname) + 1; 2220Sstevel@tonic-gate if ((size + 2) > sizeof (fname)) { 2230Sstevel@tonic-gate errno = E2BIG; 2240Sstevel@tonic-gate return (-1); 2250Sstevel@tonic-gate } 2260Sstevel@tonic-gate (void) memmove(fname + 2, fname, size); 2270Sstevel@tonic-gate fname[0] = '.'; 2280Sstevel@tonic-gate fname[1] = '/'; 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate (void) execve(fname, argv, envp); 2310Sstevel@tonic-gate switch (errno) { 2320Sstevel@tonic-gate case ENOEXEC: 2330Sstevel@tonic-gate newargs[0] = "sh"; 2340Sstevel@tonic-gate newargs[1] = fname; 2350Sstevel@tonic-gate for (i = 1; (newargs[i + 1] = argv[i]) != NULL; ++i) { 2360Sstevel@tonic-gate if (i >= 254) { 2370Sstevel@tonic-gate errno = E2BIG; 2380Sstevel@tonic-gate return (-1); 2390Sstevel@tonic-gate } 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate (void) execve("/bin/sh", newargs, envp); 2420Sstevel@tonic-gate return (-1); 2430Sstevel@tonic-gate case ETXTBSY: 2440Sstevel@tonic-gate if (++etxtbsy > 5) 2450Sstevel@tonic-gate return (-1); 2460Sstevel@tonic-gate (void) sleep(etxtbsy); 2470Sstevel@tonic-gate goto retry; 2480Sstevel@tonic-gate case EACCES: 2490Sstevel@tonic-gate ++eacces; 2500Sstevel@tonic-gate break; 2510Sstevel@tonic-gate case ENOMEM: 2520Sstevel@tonic-gate case E2BIG: 2530Sstevel@tonic-gate case EFAULT: 2540Sstevel@tonic-gate return (-1); 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate } while (cp); 2570Sstevel@tonic-gate if (eacces) 2580Sstevel@tonic-gate errno = EACCES; 2590Sstevel@tonic-gate return (-1); 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate static char time_buf[50]; 2631676Sjpk 2640Sstevel@tonic-gate /** 2650Sstevel@tonic-gate ** exec() - FORK AND EXEC CHILD PROCESS 2660Sstevel@tonic-gate **/ 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate /*VARARGS1*/ 2690Sstevel@tonic-gate int 2700Sstevel@tonic-gate exec(int type, ...) 2710Sstevel@tonic-gate { 2720Sstevel@tonic-gate va_list args; 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate int i; 2750Sstevel@tonic-gate int procuid; 2760Sstevel@tonic-gate int procgid; 2770Sstevel@tonic-gate int ret; 2780Sstevel@tonic-gate int fr_flg; 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate char *cp; 2810Sstevel@tonic-gate char *infile; 2820Sstevel@tonic-gate char *outfile; 2830Sstevel@tonic-gate char *errfile; 2840Sstevel@tonic-gate char *sep; 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate char **listp; 2870Sstevel@tonic-gate char **file_list; 2880Sstevel@tonic-gate char *printerName; 2890Sstevel@tonic-gate char *printerNameToShow; 2900Sstevel@tonic-gate static char nameBuf[100]; 2910Sstevel@tonic-gate char *clean_title; 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate PSTATUS *printer; 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate RSTATUS *request; 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate FSTATUS *form; 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate EXEC *ep; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate PWSTATUS *pwheel; 3020Sstevel@tonic-gate time_t now; 3030Sstevel@tonic-gate struct passwd *pwp; 3040Sstevel@tonic-gate #ifdef LP_USE_PAPI_ATTR 3050Sstevel@tonic-gate struct stat tmpBuf; 3060Sstevel@tonic-gate char tmpName[BUFSIZ]; 3070Sstevel@tonic-gate char *path = NULL; 3080Sstevel@tonic-gate #endif 3090Sstevel@tonic-gate char *av[ARG_MAX]; 3100Sstevel@tonic-gate char **envp = NULL; 3110Sstevel@tonic-gate int ac = 0; 3121676Sjpk char *mail_zonename = NULL; 3131676Sjpk char *slabel = NULL; 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate syslog(LOG_DEBUG, "exec(%s)", _exec_name(type)); 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate memset(av, 0, sizeof (*av)); 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate va_start (args, type); 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate switch (type) { 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate case EX_INTERF: 3240Sstevel@tonic-gate printer = va_arg(args, PSTATUS *); 3250Sstevel@tonic-gate request = printer->request; 3260Sstevel@tonic-gate ep = printer->exec; 3270Sstevel@tonic-gate break; 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate case EX_FAULT_MESSAGE: 3300Sstevel@tonic-gate printer = va_arg(args, PSTATUS *); 3310Sstevel@tonic-gate request = va_arg(args, RSTATUS *); 3320Sstevel@tonic-gate if (! ( printer->status & (PS_FORM_FAULT | PS_SHOW_FAULT))) { 3330Sstevel@tonic-gate return(0); 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate ep = printer->fault_exec; 3360Sstevel@tonic-gate printerName = (printer->printer && printer->printer->name 3370Sstevel@tonic-gate ? printer->printer->name : "??"); 3380Sstevel@tonic-gate snprintf(nameBuf, sizeof (nameBuf), 3390Sstevel@tonic-gate "%s (on %s)\n", printerName, Local_System); 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate printerNameToShow = nameBuf; 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate (void) time(&now); 3440Sstevel@tonic-gate (void) strftime(time_buf, sizeof (time_buf), 3450Sstevel@tonic-gate NULL, localtime(&now)); 3460Sstevel@tonic-gate break; 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate case EX_SLOWF: 3490Sstevel@tonic-gate request = va_arg(args, RSTATUS *); 3500Sstevel@tonic-gate ep = request->exec; 3510Sstevel@tonic-gate break; 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate case EX_NOTIFY: 3540Sstevel@tonic-gate request = va_arg(args, RSTATUS *); 3550Sstevel@tonic-gate if (request->request->actions & ACT_NOTIFY) { 3560Sstevel@tonic-gate errno = EINVAL; 3570Sstevel@tonic-gate return (-1); 3580Sstevel@tonic-gate } 3590Sstevel@tonic-gate ep = request->exec; 3600Sstevel@tonic-gate break; 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate case EX_ALERT: 3630Sstevel@tonic-gate printer = va_arg(args, PSTATUS *); 3640Sstevel@tonic-gate if (!(printer->printer->fault_alert.shcmd)) { 3650Sstevel@tonic-gate errno = EINVAL; 3660Sstevel@tonic-gate return(-1); 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate ep = printer->alert->exec; 3690Sstevel@tonic-gate break; 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate case EX_PALERT: 3720Sstevel@tonic-gate pwheel = va_arg(args, PWSTATUS *); 3730Sstevel@tonic-gate ep = pwheel->alert->exec; 3740Sstevel@tonic-gate break; 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate case EX_FORM_MESSAGE: 3770Sstevel@tonic-gate (void) time(&now); 3780Sstevel@tonic-gate (void) strftime(time_buf, sizeof (time_buf), 3790Sstevel@tonic-gate NULL, localtime(&now)); 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate /*FALLTHRU*/ 3820Sstevel@tonic-gate case EX_FALERT: 3830Sstevel@tonic-gate form = va_arg(args, FSTATUS *); 3840Sstevel@tonic-gate ep = form->alert->exec; 3850Sstevel@tonic-gate break; 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate default: 3880Sstevel@tonic-gate errno = EINVAL; 3890Sstevel@tonic-gate return(-1); 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate va_end (args); 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate if (!ep || (ep->pid > 0)) { 3950Sstevel@tonic-gate errno = EBUSY; 3960Sstevel@tonic-gate return(-1); 3970Sstevel@tonic-gate } 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate ep->flags = 0; 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate key = ep->key = getkey(); 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate switch ((ep->pid = Fork1(ep))) { 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate case -1: 4060Sstevel@tonic-gate relock (); 4070Sstevel@tonic-gate return(-1); 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate case 0: 4100Sstevel@tonic-gate /* 4110Sstevel@tonic-gate * We want to be able to tell our parent how we died. 4120Sstevel@tonic-gate */ 4130Sstevel@tonic-gate lp_alloc_fail_handler = child_mallocfail; 4140Sstevel@tonic-gate break; 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate default: 4170Sstevel@tonic-gate switch(type) { 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate case EX_INTERF: 4200Sstevel@tonic-gate request->request->outcome |= RS_PRINTING; 4210Sstevel@tonic-gate break; 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate case EX_NOTIFY: 4240Sstevel@tonic-gate request->request->outcome |= RS_NOTIFYING; 4250Sstevel@tonic-gate break; 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate case EX_SLOWF: 4280Sstevel@tonic-gate request->request->outcome |= RS_FILTERING; 4290Sstevel@tonic-gate request->request->outcome &= ~RS_REFILTER; 4300Sstevel@tonic-gate break; 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate } 4330Sstevel@tonic-gate return(0); 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate } 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate for (i = 0; i < NSIG; i++) 4380Sstevel@tonic-gate (void)signal (i, SIG_DFL); 4390Sstevel@tonic-gate (void)signal (SIGALRM, SIG_IGN); 4400Sstevel@tonic-gate (void)signal (SIGTERM, sigtrap); 441*3125Sjacobs 442*3125Sjacobs closelog(); 4430Sstevel@tonic-gate for (i = 0; i < OpenMax; i++) 4440Sstevel@tonic-gate if (i != ChildMd->writefd) 4450Sstevel@tonic-gate Close (i); 446*3125Sjacobs openlog("lpsched", LOG_PID|LOG_NDELAY|LOG_NOWAIT, LOG_LPR); 447*3125Sjacobs 4480Sstevel@tonic-gate setpgrp(); 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate /* Set a default path */ 4510Sstevel@tonic-gate addenv (&envp, "PATH", "/usr/lib/lp/bin:/usr/bin:/bin:/usr/sbin:/sbin"); 4520Sstevel@tonic-gate /* copy locale related variables */ 4530Sstevel@tonic-gate addenv (&envp, "TZ", getenv("TZ")); 4540Sstevel@tonic-gate addenv (&envp, "LANG", getenv("LANG")); 4550Sstevel@tonic-gate addenv (&envp, "LC_ALL", getenv("LC_ALL")); 4560Sstevel@tonic-gate addenv (&envp, "LC_COLLATE", getenv("LC_COLLATE")); 4570Sstevel@tonic-gate addenv (&envp, "LC_CTYPE", getenv("LC_CTYPE")); 4580Sstevel@tonic-gate addenv (&envp, "LC_MESSAGES", getenv("LC_MESSAGES")); 4590Sstevel@tonic-gate addenv (&envp, "LC_MONETARY", getenv("LC_MONETARY")); 4600Sstevel@tonic-gate addenv (&envp, "LC_NUMERIC", getenv("LC_NUMERIC")); 4610Sstevel@tonic-gate addenv (&envp, "LC_TIME", getenv("LC_TIME")); 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate sprintf ((cp = BIGGEST_NUMBER_S), "%ld", key); 4640Sstevel@tonic-gate addenv (&envp, "SPOOLER_KEY", cp); 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate #if defined(DEBUG) 4670Sstevel@tonic-gate addenv (&envp, "LPDEBUG", (debug? "1" : "0")); 4680Sstevel@tonic-gate #endif 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate /* 4710Sstevel@tonic-gate * Open the standard input, standard output, and standard error. 4720Sstevel@tonic-gate */ 4730Sstevel@tonic-gate switch (type) { 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate case EX_SLOWF: 4760Sstevel@tonic-gate case EX_INTERF: 4770Sstevel@tonic-gate /* 4780Sstevel@tonic-gate * stdin: /dev/null 4790Sstevel@tonic-gate * stdout: /dev/null (EX_SLOWF), printer port (EX_INTERF) 4800Sstevel@tonic-gate * stderr: req# 4810Sstevel@tonic-gate */ 4820Sstevel@tonic-gate infile = 0; 4830Sstevel@tonic-gate outfile = 0; 4840Sstevel@tonic-gate errfile = makereqerr(request); 4850Sstevel@tonic-gate break; 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate case EX_NOTIFY: 4880Sstevel@tonic-gate /* 4890Sstevel@tonic-gate * stdin: req# 4900Sstevel@tonic-gate * stdout: /dev/null 4910Sstevel@tonic-gate * stderr: /dev/null 4920Sstevel@tonic-gate */ 4930Sstevel@tonic-gate infile = makereqerr(request); 4940Sstevel@tonic-gate outfile = 0; 4950Sstevel@tonic-gate errfile = 0; 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate break; 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate case EX_ALERT: 5000Sstevel@tonic-gate case EX_FALERT: 5010Sstevel@tonic-gate case EX_PALERT: 5020Sstevel@tonic-gate case EX_FAULT_MESSAGE: 5030Sstevel@tonic-gate case EX_FORM_MESSAGE: 5040Sstevel@tonic-gate /* 5050Sstevel@tonic-gate * stdin: /dev/null 5060Sstevel@tonic-gate * stdout: /dev/null 5070Sstevel@tonic-gate * stderr: /dev/null 5080Sstevel@tonic-gate */ 5090Sstevel@tonic-gate infile = 0; 5100Sstevel@tonic-gate outfile = 0; 5110Sstevel@tonic-gate errfile = 0; 5120Sstevel@tonic-gate break; 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate } 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate if (infile) { 5170Sstevel@tonic-gate if (Open(infile, O_RDONLY) == -1) 5180Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5190Sstevel@tonic-gate } else { 5200Sstevel@tonic-gate if (Open("/dev/null", O_RDONLY) == -1) 5210Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5220Sstevel@tonic-gate } 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate if (outfile) { 5250Sstevel@tonic-gate if (Open(outfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1) 5260Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5270Sstevel@tonic-gate } else { 5280Sstevel@tonic-gate /* 5290Sstevel@tonic-gate * If EX_INTERF, this is still needed to cause the 5300Sstevel@tonic-gate * standard error channel to be #2. 5310Sstevel@tonic-gate */ 5320Sstevel@tonic-gate if (Open("/dev/null", O_WRONLY) == -1) 5330Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate if (errfile) { 5370Sstevel@tonic-gate if (Open(errfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1) 5380Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5390Sstevel@tonic-gate } else { 5400Sstevel@tonic-gate if (Open("/dev/null", O_WRONLY) == -1) 5410Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5420Sstevel@tonic-gate } 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate switch (type) { 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate case EX_INTERF: 5470Sstevel@tonic-gate /* 5480Sstevel@tonic-gate * Opening a ``port'' can be dangerous to our health: 5490Sstevel@tonic-gate * 5500Sstevel@tonic-gate * - Hangups can occur if the line is dropped. 5510Sstevel@tonic-gate * - The printer may send an interrupt. 5520Sstevel@tonic-gate * - A FIFO may be closed, generating SIGPIPE. 5530Sstevel@tonic-gate * 5540Sstevel@tonic-gate * We catch these so we can complain nicely. 5550Sstevel@tonic-gate */ 5560Sstevel@tonic-gate trap_fault_signals (); 5570Sstevel@tonic-gate 5580Sstevel@tonic-gate (void)Close (1); 5590Sstevel@tonic-gate 560*3125Sjacobs if (strchr (request->request->user, '@')) 5610Sstevel@tonic-gate { 5620Sstevel@tonic-gate procuid = Lp_Uid; 5630Sstevel@tonic-gate procgid = Lp_Gid; 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate else 5660Sstevel@tonic-gate { 5670Sstevel@tonic-gate procuid = request->secure->uid; 5680Sstevel@tonic-gate procgid = request->secure->gid; 5690Sstevel@tonic-gate } 5700Sstevel@tonic-gate if (printer->printer->dial_info) 5710Sstevel@tonic-gate { 5720Sstevel@tonic-gate ret = open_dialup(request->printer_type, 5730Sstevel@tonic-gate printer->printer); 5740Sstevel@tonic-gate if (ret == 0) 5750Sstevel@tonic-gate do_undial = 1; 5760Sstevel@tonic-gate } 5770Sstevel@tonic-gate else 5780Sstevel@tonic-gate { 5790Sstevel@tonic-gate ret = open_direct(request->printer_type, 5800Sstevel@tonic-gate printer->printer); 5810Sstevel@tonic-gate do_undial = 0; 5820Sstevel@tonic-gate /* this is a URI */ 5830Sstevel@tonic-gate if (is_printer_uri(printer->printer->device) == 0) 5840Sstevel@tonic-gate addenv(&envp, "DEVICE_URI", 5850Sstevel@tonic-gate printer->printer->device); 5860Sstevel@tonic-gate } 5870Sstevel@tonic-gate addenv(&envp, "DEVICE_URI", 5880Sstevel@tonic-gate printer->printer->device); 5890Sstevel@tonic-gate if (ret != 0) 5900Sstevel@tonic-gate Done (ret, errno); 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate if (!(request->request->outcome & RS_FILTERED)) 5930Sstevel@tonic-gate file_list = request->request->file_list; 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate else { 5960Sstevel@tonic-gate register int count = 0; 5970Sstevel@tonic-gate register char * num = BIGGEST_REQID_S; 5980Sstevel@tonic-gate register char * prefix; 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate prefix = makestr( 601*3125Sjacobs Lp_Temp, 6020Sstevel@tonic-gate "/F", 6030Sstevel@tonic-gate getreqno(request->secure->req_id), 6040Sstevel@tonic-gate "-", 6050Sstevel@tonic-gate (char *)0 6060Sstevel@tonic-gate ); 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate file_list = (char **)Malloc( 6090Sstevel@tonic-gate (lenlist(request->request->file_list) + 1) 6100Sstevel@tonic-gate * sizeof(char *) 6110Sstevel@tonic-gate ); 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate for ( 6140Sstevel@tonic-gate listp = request->request->file_list; 6150Sstevel@tonic-gate *listp; 6160Sstevel@tonic-gate listp++ 6170Sstevel@tonic-gate ) { 6180Sstevel@tonic-gate sprintf (num, "%d", count + 1); 6190Sstevel@tonic-gate file_list[count] = makestr( 6200Sstevel@tonic-gate prefix, 6210Sstevel@tonic-gate num, 6220Sstevel@tonic-gate (char *)0 6230Sstevel@tonic-gate ); 6240Sstevel@tonic-gate count++; 6250Sstevel@tonic-gate } 6260Sstevel@tonic-gate file_list[count] = 0; 6270Sstevel@tonic-gate } 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate #ifdef LP_USE_PAPI_ATTR 6300Sstevel@tonic-gate /* 6310Sstevel@tonic-gate * Check if the PAPI job attribute file exists, if it does 6320Sstevel@tonic-gate * pass the file's pathname to the printer interface script 6330Sstevel@tonic-gate * in an environment variable. This file is created when 6340Sstevel@tonic-gate * print jobs are submitted via the PAPI interface. 6350Sstevel@tonic-gate */ 6360Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s-%s", 6370Sstevel@tonic-gate getreqno(request->secure->req_id), LP_PAPIATTRNAME); 638*3125Sjacobs path = makepath(Lp_Temp, tmpName, (char *)0); 6390Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 6400Sstevel@tonic-gate { 6410Sstevel@tonic-gate /* 6420Sstevel@tonic-gate * IPP job attribute file exists for this job so 6430Sstevel@tonic-gate * set the environment variable 6440Sstevel@tonic-gate */ 6450Sstevel@tonic-gate addenv(&envp, "ATTRPATH", path); 6460Sstevel@tonic-gate } 6470Sstevel@tonic-gate Free(path); 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate /* 6500Sstevel@tonic-gate * now set environment variable for the printer's PostScript 6510Sstevel@tonic-gate * Printer Description (PPD) file, this is used by the filter 6520Sstevel@tonic-gate * when forming the print data for this printer. 6530Sstevel@tonic-gate */ 6540Sstevel@tonic-gate if ((request->printer != NULL) && 6550Sstevel@tonic-gate (request->printer->printer != NULL) && 6560Sstevel@tonic-gate (request->printer->printer->name != NULL)) 6570Sstevel@tonic-gate { 6580Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s.ppd", 6590Sstevel@tonic-gate request->printer->printer->name); 6600Sstevel@tonic-gate path = makepath(ETCDIR, "ppd", tmpName, (char *)0); 6610Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 6620Sstevel@tonic-gate { 6630Sstevel@tonic-gate addenv(&envp, "PPD", path); 6640Sstevel@tonic-gate } 6650Sstevel@tonic-gate Free(path); 6660Sstevel@tonic-gate } 6670Sstevel@tonic-gate #endif 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate if (request->printer_type) 6700Sstevel@tonic-gate addenv(&envp, "TERM", request->printer_type); 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate if (!(printer->printer->daisy)) { 6730Sstevel@tonic-gate register char * chset = 0; 6740Sstevel@tonic-gate register char * csp; 6750Sstevel@tonic-gate 6760Sstevel@tonic-gate if ( 6770Sstevel@tonic-gate request->form 6780Sstevel@tonic-gate && request->form->form->chset 6790Sstevel@tonic-gate && request->form->form->mandatory 6800Sstevel@tonic-gate && !STREQU(NAME_ANY, request->form->form->chset) 6810Sstevel@tonic-gate ) 6820Sstevel@tonic-gate chset = request->form->form->chset; 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate else if ( 6850Sstevel@tonic-gate request->request->charset 6860Sstevel@tonic-gate && !STREQU(NAME_ANY, request->request->charset) 6870Sstevel@tonic-gate ) 6880Sstevel@tonic-gate chset = request->request->charset; 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate if (chset) { 6910Sstevel@tonic-gate csp = search_cslist( 6920Sstevel@tonic-gate chset, 6930Sstevel@tonic-gate printer->printer->char_sets 6940Sstevel@tonic-gate ); 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate /* 6970Sstevel@tonic-gate * The "strtok()" below wrecks the string 6980Sstevel@tonic-gate * for future use, but this is a child 6990Sstevel@tonic-gate * process where it won't be needed again. 7000Sstevel@tonic-gate */ 7010Sstevel@tonic-gate addenv (&envp, "CHARSET", 7020Sstevel@tonic-gate (csp? strtok(csp, "=") : chset) 7030Sstevel@tonic-gate ); 7040Sstevel@tonic-gate } 7050Sstevel@tonic-gate } 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate if (request->fast) 7080Sstevel@tonic-gate addenv(&envp, "FILTER", request->fast); 7090Sstevel@tonic-gate 7100Sstevel@tonic-gate /* 7111676Sjpk * Add the sensitivity label to the environment for 7121676Sjpk * banner page and header/footer processing 7131676Sjpk */ 7141676Sjpk 7151676Sjpk if (is_system_labeled() && request->secure->slabel != NULL) 7161676Sjpk addenv(&envp, "SLABEL", request->secure->slabel); 7171676Sjpk 7181676Sjpk /* 7190Sstevel@tonic-gate * Add the system name to the user name (ala system!user) 7200Sstevel@tonic-gate * unless it is already there. RFS users may have trouble 7210Sstevel@tonic-gate * here, sorry! 7220Sstevel@tonic-gate */ 7230Sstevel@tonic-gate cp = strchr(request->secure->user, '@'); 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate allTraysWithForm(printer, request->form); 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate /* 7280Sstevel@tonic-gate * Fix for 4137389 7290Sstevel@tonic-gate * Remove double quotes from title string. 7300Sstevel@tonic-gate */ 7310Sstevel@tonic-gate fr_flg = 1; 7320Sstevel@tonic-gate clean_title = strdup(NB(request->request->title)); 7330Sstevel@tonic-gate if (clean_title == NULL) { 7340Sstevel@tonic-gate /* 7350Sstevel@tonic-gate * strdup failed. We're probably hosed 7360Sstevel@tonic-gate * but try setting clean_title 7370Sstevel@tonic-gate * to original title and continuing. 7380Sstevel@tonic-gate */ 7390Sstevel@tonic-gate clean_title = NB(request->request->title); 7400Sstevel@tonic-gate fr_flg = 0; 7410Sstevel@tonic-gate } else if (strcmp(clean_title, "") != 0) { 7420Sstevel@tonic-gate char *ct_p; 7430Sstevel@tonic-gate 7440Sstevel@tonic-gate for (ct_p = clean_title; *ct_p != NULL; ct_p++) { 7450Sstevel@tonic-gate if (*ct_p == '"') 7460Sstevel@tonic-gate *ct_p = ' '; 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate } 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_A_Interfaces, 7510Sstevel@tonic-gate printer->printer->name); 7520Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", request->secure->req_id); 753*3125Sjacobs av[ac++] = arg_string(UNTRUSTED, "%s", request->request->user); 7540Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", clean_title); 7550Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%d", request->copies); 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate if (fr_flg) 7580Sstevel@tonic-gate free (clean_title); 7590Sstevel@tonic-gate 7600Sstevel@tonic-gate sep = ""; 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate /* 7630Sstevel@tonic-gate * Do the administrator defined key=value pair options 7640Sstevel@tonic-gate */ 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate argbuf[0] = '\0'; 7670Sstevel@tonic-gate 7680Sstevel@tonic-gate if (printer->printer->options) { 7690Sstevel@tonic-gate char **tmp = printer->printer->options; 7700Sstevel@tonic-gate while(*tmp != NULL) { 7710Sstevel@tonic-gate STRLCAT(argbuf, sep, sizeof (argbuf)); 7720Sstevel@tonic-gate sep = " "; 7730Sstevel@tonic-gate STRLCAT(argbuf, *tmp++, sizeof (argbuf)); 7740Sstevel@tonic-gate } 7750Sstevel@tonic-gate } 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate /* 7780Sstevel@tonic-gate * Do the administrator defined ``stty'' stuff before 7790Sstevel@tonic-gate * the user's -o options, to allow the user to override. 7800Sstevel@tonic-gate */ 7810Sstevel@tonic-gate if (printer->printer->stty) { 7820Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 7830Sstevel@tonic-gate sep = " "; 7840Sstevel@tonic-gate STRLCAT (argbuf, "stty='", sizeof (argbuf)); 7850Sstevel@tonic-gate STRLCAT (argbuf, printer->printer->stty, 7860Sstevel@tonic-gate sizeof (argbuf)); 7870Sstevel@tonic-gate STRLCAT (argbuf, "'", sizeof (argbuf)); 7880Sstevel@tonic-gate } 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate /* 7910Sstevel@tonic-gate * Do all of the user's options except the cpi/lpi/etc. 7920Sstevel@tonic-gate * stuff, which is done separately. 7930Sstevel@tonic-gate */ 7940Sstevel@tonic-gate if (request->request->options) { 7950Sstevel@tonic-gate listp = dashos(request->request->options); 7960Sstevel@tonic-gate while (*listp) { 7970Sstevel@tonic-gate if ( 7980Sstevel@tonic-gate !STRNEQU(*listp, "cpi=", 4) 7990Sstevel@tonic-gate && !STRNEQU(*listp, "lpi=", 4) 8000Sstevel@tonic-gate && !STRNEQU(*listp, "width=", 6) 8010Sstevel@tonic-gate && !STRNEQU(*listp, "length=", 7) 8020Sstevel@tonic-gate ) { 8030Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 8040Sstevel@tonic-gate sep = " "; 8050Sstevel@tonic-gate STRLCAT (argbuf, *listp, 8060Sstevel@tonic-gate sizeof (argbuf)); 8070Sstevel@tonic-gate } 8080Sstevel@tonic-gate listp++; 8090Sstevel@tonic-gate } 8100Sstevel@tonic-gate } 8110Sstevel@tonic-gate 8120Sstevel@tonic-gate /* 8130Sstevel@tonic-gate * The "pickfilter()" routine (from "validate()") 8140Sstevel@tonic-gate * stored the cpi/lpi/etc. stuff that should be 8150Sstevel@tonic-gate * used for this request. It chose form over user, 8160Sstevel@tonic-gate * and user over printer. 8170Sstevel@tonic-gate */ 8180Sstevel@tonic-gate if (request->cpi) { 8190Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 8200Sstevel@tonic-gate sep = " "; 8210Sstevel@tonic-gate STRLCAT (argbuf, "cpi=", sizeof (argbuf)); 8220Sstevel@tonic-gate STRLCAT (argbuf, request->cpi, sizeof (argbuf)); 8230Sstevel@tonic-gate } 8240Sstevel@tonic-gate if (request->lpi) { 8250Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 8260Sstevel@tonic-gate sep = " "; 8270Sstevel@tonic-gate STRLCAT (argbuf, "lpi=", sizeof (argbuf)); 8280Sstevel@tonic-gate STRLCAT (argbuf, request->lpi, sizeof (argbuf)); 8290Sstevel@tonic-gate } 8300Sstevel@tonic-gate if (request->pwid) { 8310Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 8320Sstevel@tonic-gate sep = " "; 8330Sstevel@tonic-gate STRLCAT (argbuf, "width=", sizeof (argbuf)); 8340Sstevel@tonic-gate STRLCAT (argbuf, request->pwid, sizeof (argbuf)); 8350Sstevel@tonic-gate } 8360Sstevel@tonic-gate if (request->plen) { 8370Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 8380Sstevel@tonic-gate sep = " "; 8390Sstevel@tonic-gate STRLCAT (argbuf, "length=", sizeof (argbuf)); 8400Sstevel@tonic-gate STRLCAT (argbuf, request->plen, sizeof (argbuf)); 8410Sstevel@tonic-gate } 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate /* 8440Sstevel@tonic-gate * Do the ``raw'' bit last, to ensure it gets 8450Sstevel@tonic-gate * done. If the user doesn't want this, then he or 8460Sstevel@tonic-gate * she can do the correct thing using -o stty= 8470Sstevel@tonic-gate * and leaving out the -r option. 8480Sstevel@tonic-gate */ 8490Sstevel@tonic-gate if (request->request->actions & ACT_RAW) { 8500Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 8510Sstevel@tonic-gate sep = " "; 8520Sstevel@tonic-gate STRLCAT (argbuf, "stty=-opost", sizeof (argbuf)); 8530Sstevel@tonic-gate } 8540Sstevel@tonic-gate 8550Sstevel@tonic-gate 8560Sstevel@tonic-gate /* the "options" */ 8570Sstevel@tonic-gate av[ac++] = arg_string(UNTRUSTED, "%s", argbuf); 8580Sstevel@tonic-gate 8590Sstevel@tonic-gate for (listp = file_list; *listp; listp++) 8600Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", *listp); 8610Sstevel@tonic-gate 8620Sstevel@tonic-gate (void)chfiles (file_list, procuid, procgid); 8630Sstevel@tonic-gate 8640Sstevel@tonic-gate break; 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate 8670Sstevel@tonic-gate case EX_SLOWF: 8680Sstevel@tonic-gate if (request->slow) 8690Sstevel@tonic-gate addenv(&envp, "FILTER", request->slow); 8700Sstevel@tonic-gate 871*3125Sjacobs if (strchr (request->request->user, '@')) 8720Sstevel@tonic-gate { 8730Sstevel@tonic-gate procuid = Lp_Uid; 8740Sstevel@tonic-gate procgid = Lp_Gid; 8750Sstevel@tonic-gate } 8760Sstevel@tonic-gate else 8770Sstevel@tonic-gate { 8780Sstevel@tonic-gate procuid = request->secure->uid; 8790Sstevel@tonic-gate procgid = request->secure->gid; 8800Sstevel@tonic-gate } 8810Sstevel@tonic-gate cp = _alloc_files( 8820Sstevel@tonic-gate lenlist(request->request->file_list), 8830Sstevel@tonic-gate getreqno(request->secure->req_id), 884*3125Sjacobs procuid, procgid); 8850Sstevel@tonic-gate 8860Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", Lp_Slow_Filter); 887*3125Sjacobs av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_Temp, cp); 8880Sstevel@tonic-gate for (listp = request->request->file_list; *listp; listp++) 8890Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", *listp); 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate (void)chfiles (request->request->file_list, procuid, procgid); 8920Sstevel@tonic-gate 8930Sstevel@tonic-gate #ifdef LP_USE_PAPI_ATTR 8940Sstevel@tonic-gate /* 8950Sstevel@tonic-gate * Check if the PAPI job attribute file exists, if it does 8960Sstevel@tonic-gate * pass the file's pathname to the slow-filters in an 8970Sstevel@tonic-gate * environment variable. Note: this file is created when 8980Sstevel@tonic-gate * print jobs are submitted via the PAPI interface. 8990Sstevel@tonic-gate */ 9000Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s-%s", 9010Sstevel@tonic-gate getreqno(request->secure->req_id), LP_PAPIATTRNAME); 902*3125Sjacobs path = makepath(Lp_Temp, tmpName, (char *)0); 9030Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 9040Sstevel@tonic-gate { 9050Sstevel@tonic-gate /* 9060Sstevel@tonic-gate * IPP job attribute file exists for this job so 9070Sstevel@tonic-gate * set the environment variable 9080Sstevel@tonic-gate */ 9090Sstevel@tonic-gate addenv(&envp, "ATTRPATH", path); 9100Sstevel@tonic-gate } 9110Sstevel@tonic-gate Free(path); 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate /* 9150Sstevel@tonic-gate * now set environment variable for the printer's PostScript 9160Sstevel@tonic-gate * Printer Description (PPD) file, this is used by the filter 9170Sstevel@tonic-gate * when forming the print data for this printer. 9180Sstevel@tonic-gate */ 9190Sstevel@tonic-gate if ((request->printer != NULL) && 9200Sstevel@tonic-gate (request->printer->printer != NULL) && 9210Sstevel@tonic-gate (request->printer->printer->name != NULL)) 9220Sstevel@tonic-gate { 9230Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s.ppd", 9240Sstevel@tonic-gate request->printer->printer->name); 9250Sstevel@tonic-gate path = makepath(ETCDIR, "ppd", tmpName, (char *)0); 9260Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 9270Sstevel@tonic-gate { 9280Sstevel@tonic-gate addenv(&envp, "PPD", path); 9290Sstevel@tonic-gate } 9300Sstevel@tonic-gate Free(path); 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate #endif 9330Sstevel@tonic-gate break; 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate case EX_ALERT: 9360Sstevel@tonic-gate procuid = Lp_Uid; 9370Sstevel@tonic-gate procgid = Lp_Gid; 9380Sstevel@tonic-gate (void)Chown (printer->alert->msgfile, procuid, procgid); 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers, 9410Sstevel@tonic-gate printer->printer->name, ALERTSHFILE); 9420Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); 9430Sstevel@tonic-gate 9440Sstevel@tonic-gate break; 9450Sstevel@tonic-gate 9460Sstevel@tonic-gate case EX_PALERT: 9470Sstevel@tonic-gate procuid = Lp_Uid; 9480Sstevel@tonic-gate procgid = Lp_Gid; 9490Sstevel@tonic-gate (void)Chown (pwheel->alert->msgfile, procuid, procgid); 9500Sstevel@tonic-gate 9510Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_PrintWheels, 9520Sstevel@tonic-gate pwheel->pwheel->name, ALERTSHFILE); 9530Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); 9540Sstevel@tonic-gate 9550Sstevel@tonic-gate break; 9560Sstevel@tonic-gate 9570Sstevel@tonic-gate case EX_FALERT: 9580Sstevel@tonic-gate procuid = Lp_Uid; 9590Sstevel@tonic-gate procgid = Lp_Gid; 9600Sstevel@tonic-gate (void)Chown (form->alert->msgfile, procuid, procgid); 9610Sstevel@tonic-gate 9620Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms, 9630Sstevel@tonic-gate form->form->name, ALERTSHFILE); 9640Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); 9650Sstevel@tonic-gate 9660Sstevel@tonic-gate break; 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate case EX_FORM_MESSAGE: 9690Sstevel@tonic-gate procuid = Lp_Uid; 9700Sstevel@tonic-gate procgid = Lp_Gid; 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/form", Lp_A_Faults); 9730Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", form->form->name); 9740Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", time_buf); 9750Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms, 9760Sstevel@tonic-gate form->form->name, FORMMESSAGEFILE); 9770Sstevel@tonic-gate 9780Sstevel@tonic-gate break; 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate case EX_FAULT_MESSAGE: 9810Sstevel@tonic-gate procuid = Lp_Uid; 9820Sstevel@tonic-gate procgid = Lp_Gid; 9830Sstevel@tonic-gate 9840Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/printer", Lp_A_Faults); 9850Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printerNameToShow); 9860Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", time_buf); 9870Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers, 9880Sstevel@tonic-gate printerName, FAULTMESSAGEFILE); 9890Sstevel@tonic-gate 9900Sstevel@tonic-gate break; 9910Sstevel@tonic-gate 9920Sstevel@tonic-gate case EX_NOTIFY: 9930Sstevel@tonic-gate if (request->request->alert) { 994*3125Sjacobs if (strchr(request->request->user, '@')) { 9950Sstevel@tonic-gate procuid = Lp_Uid; 9960Sstevel@tonic-gate procgid = Lp_Gid; 9970Sstevel@tonic-gate } else { 9980Sstevel@tonic-gate procuid = request->secure->uid; 9990Sstevel@tonic-gate procgid = request->secure->gid; 10000Sstevel@tonic-gate } 10010Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", 10020Sstevel@tonic-gate request->request->alert); 10030Sstevel@tonic-gate } else { 1004*3125Sjacobs char *user = strdup(request->request->user); 10050Sstevel@tonic-gate clean_string(user); 10061676Sjpk slabel = request->secure->slabel; 10070Sstevel@tonic-gate 1008*3125Sjacobs if (request->request->actions & ACT_WRITE) { 10090Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", BINWRITE); 10100Sstevel@tonic-gate snprintf(argbuf, sizeof (argbuf), 10110Sstevel@tonic-gate "%s %s || %s %s", 10120Sstevel@tonic-gate BINWRITE, user, 10130Sstevel@tonic-gate BINMAIL, user 10140Sstevel@tonic-gate ); 10150Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "/bin/sh"); 10160Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "-c"); 10170Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", argbuf); 10181676Sjpk } else if ((getzoneid() == GLOBAL_ZONEID) && 10191676Sjpk is_system_labeled() && (slabel != NULL)) { 10201676Sjpk /* 10211676Sjpk * If in the global zone and the system is 10221676Sjpk * labeled, mail is handled via a local 10231676Sjpk * labeled zone that is the same label as 10241676Sjpk * the request. 10251676Sjpk */ 10261676Sjpk if ((mail_zonename = 10271676Sjpk get_labeled_zonename(slabel)) == 10281676Sjpk (char *)-1) { 10291676Sjpk /* 10301676Sjpk * Cannot find labeled zone, just 10311676Sjpk * return 0. 10321676Sjpk */ 10331676Sjpk return(0); 10341676Sjpk } 10351676Sjpk } 10361676Sjpk if (mail_zonename == NULL) { 10371676Sjpk procuid = Lp_Uid; 10381676Sjpk procgid = Lp_Gid; 10390Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", BINMAIL); 10400Sstevel@tonic-gate av[ac++] = arg_string(UNTRUSTED, "%s", user); 10411676Sjpk } else { 10421676Sjpk procuid = getuid(); 10431676Sjpk procgid = getgid(); 10441676Sjpk av[ac++] = arg_string(TRUSTED, "%s", 10451676Sjpk "/usr/sbin/zlogin"); 10461676Sjpk av[ac++] = arg_string(TRUSTED, "%s", 10471676Sjpk mail_zonename); 10481676Sjpk av[ac++] = arg_string(TRUSTED, "%s", 10491676Sjpk BINMAIL); 10501676Sjpk av[ac++] = arg_string(UNTRUSTED, "%s", 10511676Sjpk user); 10521676Sjpk Free(mail_zonename); 10530Sstevel@tonic-gate } 10540Sstevel@tonic-gate 10550Sstevel@tonic-gate free(user); 10560Sstevel@tonic-gate } 10570Sstevel@tonic-gate break; 10580Sstevel@tonic-gate } 10590Sstevel@tonic-gate 10600Sstevel@tonic-gate av[ac++] = NULL; 10610Sstevel@tonic-gate 10620Sstevel@tonic-gate Fork2 (); 10630Sstevel@tonic-gate /* only the child returns */ 10640Sstevel@tonic-gate 10650Sstevel@tonic-gate /* 10660Sstevel@tonic-gate * Correctly set up the supplemental group list 10670Sstevel@tonic-gate * for proper file access (before execl the interface program) 10680Sstevel@tonic-gate */ 10690Sstevel@tonic-gate 10700Sstevel@tonic-gate pwp = getpwuid(procuid); 10710Sstevel@tonic-gate if (pwp == NULL) { 10720Sstevel@tonic-gate note("getpwuid(%d) call failed\n", procuid); 10730Sstevel@tonic-gate } else if (initgroups(pwp->pw_name, procgid) < 0) { 10740Sstevel@tonic-gate note("initgroups() call failed %d\n", errno); 10750Sstevel@tonic-gate } 10760Sstevel@tonic-gate 10770Sstevel@tonic-gate setgid (procgid); 10780Sstevel@tonic-gate setuid (procuid); 10790Sstevel@tonic-gate 10800Sstevel@tonic-gate /* 10810Sstevel@tonic-gate * The shell doesn't allow the "trap" builtin to set a trap 10820Sstevel@tonic-gate * for a signal ignored when the shell is started. Thus, don't 10830Sstevel@tonic-gate * turn off signals in the last child! 10840Sstevel@tonic-gate */ 10850Sstevel@tonic-gate 1086*3125Sjacobs #ifdef DEBUG 10870Sstevel@tonic-gate for (i = 0; av[i] != NULL; i++) 1088*3125Sjacobs note("exec(%s): av[%d] = %s", _exec_name(type), i, av[i]); 10891676Sjpk for (i = 0; envp[i] != NULL; i++) 1090*3125Sjacobs note("exec(%s): envp[%d] = %s", _exec_name(type), i, envp[i]); 1091*3125Sjacobs #endif 10920Sstevel@tonic-gate 10930Sstevel@tonic-gate execvpe(av[0], av, envp); 10940Sstevel@tonic-gate Done (EXEC_EXIT_NEXEC, errno); 10950Sstevel@tonic-gate /*NOTREACHED*/ 1096320Sceastha return (0); 10970Sstevel@tonic-gate } 10980Sstevel@tonic-gate 10990Sstevel@tonic-gate /** 11000Sstevel@tonic-gate ** addenv() - ADD A VARIABLE TO THE ENVIRONMENT 11010Sstevel@tonic-gate **/ 11020Sstevel@tonic-gate 11030Sstevel@tonic-gate static void 11040Sstevel@tonic-gate addenv(char ***envp, char *name, char *value) 11050Sstevel@tonic-gate { 11060Sstevel@tonic-gate register char * cp; 11070Sstevel@tonic-gate 11080Sstevel@tonic-gate if ((name == NULL) || (value == NULL)) 11090Sstevel@tonic-gate return; 11100Sstevel@tonic-gate 11110Sstevel@tonic-gate if ((cp = makestr(name, "=", value, (char *)0))) 11120Sstevel@tonic-gate addlist(envp, cp); 11130Sstevel@tonic-gate return; 11140Sstevel@tonic-gate } 11150Sstevel@tonic-gate 11160Sstevel@tonic-gate /** 11170Sstevel@tonic-gate ** Fork1() - FORK FIRST CHILD, SET UP CONNECTION TO IT 11180Sstevel@tonic-gate **/ 11190Sstevel@tonic-gate 11200Sstevel@tonic-gate static int 11210Sstevel@tonic-gate Fork1(EXEC *ep) 11220Sstevel@tonic-gate { 11230Sstevel@tonic-gate int pid; 11240Sstevel@tonic-gate int fds[2]; 11250Sstevel@tonic-gate 11260Sstevel@tonic-gate if (pipe(fds) == -1) { 11270Sstevel@tonic-gate note("Failed to create pipe for child process (%s).\n", PERROR); 11280Sstevel@tonic-gate errno = EAGAIN ; 11290Sstevel@tonic-gate return(-1); 11300Sstevel@tonic-gate } 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate ep->md = mconnect((char *)0, fds[0], fds[1]); 11330Sstevel@tonic-gate 11340Sstevel@tonic-gate switch (pid = fork()) { 11350Sstevel@tonic-gate 11360Sstevel@tonic-gate case -1: 11370Sstevel@tonic-gate mdisconnect(ep->md); 11380Sstevel@tonic-gate close(fds[0]); 11390Sstevel@tonic-gate close(fds[1]); 11400Sstevel@tonic-gate ep->md = 0; 11410Sstevel@tonic-gate return (-1); 11420Sstevel@tonic-gate 11430Sstevel@tonic-gate case 0: 11440Sstevel@tonic-gate ChildMd = mconnect(NULL, fds[1], fds[1]); 11450Sstevel@tonic-gate return (0); 11460Sstevel@tonic-gate 11470Sstevel@tonic-gate default: 11480Sstevel@tonic-gate mlistenadd(ep->md, POLLIN); 11490Sstevel@tonic-gate return (pid); 11500Sstevel@tonic-gate } 11510Sstevel@tonic-gate } 11520Sstevel@tonic-gate 11530Sstevel@tonic-gate /** 11540Sstevel@tonic-gate ** Fork2() - FORK SECOND CHILD AND WAIT FOR IT 11550Sstevel@tonic-gate **/ 11560Sstevel@tonic-gate 11570Sstevel@tonic-gate static void 11580Sstevel@tonic-gate Fork2(void) 11590Sstevel@tonic-gate { 11600Sstevel@tonic-gate switch ((ChildPid = fork())) { 11610Sstevel@tonic-gate 11620Sstevel@tonic-gate case -1: 11630Sstevel@tonic-gate Done (EXEC_EXIT_NFORK, errno); 11640Sstevel@tonic-gate /*NOTREACHED*/ 11650Sstevel@tonic-gate 11660Sstevel@tonic-gate case 0: 11670Sstevel@tonic-gate return; 11680Sstevel@tonic-gate 11690Sstevel@tonic-gate default: 11700Sstevel@tonic-gate /* 11710Sstevel@tonic-gate * Delay calling "ignore_fault_signals()" as long 11720Sstevel@tonic-gate * as possible, to give the child a chance to exec 11730Sstevel@tonic-gate * the interface program and turn on traps. 11740Sstevel@tonic-gate */ 11750Sstevel@tonic-gate 11760Sstevel@tonic-gate cool_heels (); 11770Sstevel@tonic-gate /*NOTREACHED*/ 11780Sstevel@tonic-gate 11790Sstevel@tonic-gate } 11800Sstevel@tonic-gate } 11810Sstevel@tonic-gate 11820Sstevel@tonic-gate 11830Sstevel@tonic-gate /** 11840Sstevel@tonic-gate ** cool_heels() - WAIT FOR CHILD TO "DIE" 11850Sstevel@tonic-gate **/ 11860Sstevel@tonic-gate 11870Sstevel@tonic-gate static void 11880Sstevel@tonic-gate cool_heels(void) 11890Sstevel@tonic-gate { 11900Sstevel@tonic-gate int status; 11910Sstevel@tonic-gate 11920Sstevel@tonic-gate /* 11930Sstevel@tonic-gate * At this point our only job is to wait for the child process. 11940Sstevel@tonic-gate * If we hang out for a bit longer, that's okay. 11950Sstevel@tonic-gate * By delaying before turning off the fault signals, 11960Sstevel@tonic-gate * we increase the chance that the child process has completed 11970Sstevel@tonic-gate * its exec and has turned on the fault traps. Nonetheless, 11980Sstevel@tonic-gate * we can't guarantee a zero chance of missing a fault. 11990Sstevel@tonic-gate * (We don't want to keep trapping the signals because the 12000Sstevel@tonic-gate * interface program is likely to have a better way to handle 12010Sstevel@tonic-gate * them; this process provides only rudimentary handling.) 12020Sstevel@tonic-gate * 12030Sstevel@tonic-gate * Note that on a very busy system, or with a very fast interface 12040Sstevel@tonic-gate * program, the tables could be turned: Our sleep below (coupled 12050Sstevel@tonic-gate * with a delay in the kernel scheduling us) may cause us to 12060Sstevel@tonic-gate * detect the fault instead of the interface program. 12070Sstevel@tonic-gate * 12080Sstevel@tonic-gate * What we need is a way to synchronize with the child process. 12090Sstevel@tonic-gate */ 12100Sstevel@tonic-gate sleep (1); 12110Sstevel@tonic-gate ignore_fault_signals (); 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate WaitedChildPid = 0; 12140Sstevel@tonic-gate while ((WaitedChildPid = wait(&status)) != ChildPid) 12150Sstevel@tonic-gate ; 12160Sstevel@tonic-gate 12170Sstevel@tonic-gate if ( 12180Sstevel@tonic-gate EXITED(status) > EXEC_EXIT_USER 12190Sstevel@tonic-gate && EXITED(status) != EXEC_EXIT_FAULT 12200Sstevel@tonic-gate ) 12210Sstevel@tonic-gate Done (EXEC_EXIT_EXIT, EXITED(status)); 12220Sstevel@tonic-gate 12230Sstevel@tonic-gate done (status, 0); /* Don't use Done() */ 12240Sstevel@tonic-gate /*NOTREACHED*/ 12250Sstevel@tonic-gate } 12260Sstevel@tonic-gate 12270Sstevel@tonic-gate 12280Sstevel@tonic-gate /** 12290Sstevel@tonic-gate ** trap_fault_signals() - TRAP SIGNALS THAT CAN OCCUR ON PRINTER FAULT 12300Sstevel@tonic-gate ** ignore_fault_signals() - IGNORE SAME 12310Sstevel@tonic-gate **/ 12320Sstevel@tonic-gate 12330Sstevel@tonic-gate static void 12340Sstevel@tonic-gate trap_fault_signals(void) 12350Sstevel@tonic-gate { 12360Sstevel@tonic-gate signal (SIGHUP, sigtrap); 12370Sstevel@tonic-gate signal (SIGINT, sigtrap); 12380Sstevel@tonic-gate signal (SIGQUIT, sigtrap); 12390Sstevel@tonic-gate signal (SIGPIPE, sigtrap); 12400Sstevel@tonic-gate return; 12410Sstevel@tonic-gate } 12420Sstevel@tonic-gate 12430Sstevel@tonic-gate static void 12440Sstevel@tonic-gate ignore_fault_signals(void) 12450Sstevel@tonic-gate { 12460Sstevel@tonic-gate signal (SIGHUP, SIG_IGN); 12470Sstevel@tonic-gate signal (SIGINT, SIG_IGN); 12480Sstevel@tonic-gate signal (SIGQUIT, SIG_IGN); 12490Sstevel@tonic-gate signal (SIGPIPE, SIG_IGN); 12500Sstevel@tonic-gate return; 12510Sstevel@tonic-gate } 12520Sstevel@tonic-gate 12530Sstevel@tonic-gate /** 12540Sstevel@tonic-gate ** sigtrap() - TRAP VARIOUS SIGNALS 12550Sstevel@tonic-gate **/ 12560Sstevel@tonic-gate 12570Sstevel@tonic-gate static void 12580Sstevel@tonic-gate sigtrap(int sig) 12590Sstevel@tonic-gate { 12600Sstevel@tonic-gate signal (sig, SIG_IGN); 12610Sstevel@tonic-gate switch (sig) { 12620Sstevel@tonic-gate 12630Sstevel@tonic-gate case SIGHUP: 12640Sstevel@tonic-gate Done (EXEC_EXIT_HUP, 0); 12650Sstevel@tonic-gate /*NOTREACHED*/ 12660Sstevel@tonic-gate 12670Sstevel@tonic-gate case SIGQUIT: 12680Sstevel@tonic-gate case SIGINT: 12690Sstevel@tonic-gate Done (EXEC_EXIT_INTR, 0); 12700Sstevel@tonic-gate /*NOTREACHED*/ 12710Sstevel@tonic-gate 12720Sstevel@tonic-gate case SIGPIPE: 12730Sstevel@tonic-gate Done (EXEC_EXIT_PIPE, 0); 12740Sstevel@tonic-gate /*NOTREACHED*/ 12750Sstevel@tonic-gate 12760Sstevel@tonic-gate case SIGTERM: 12770Sstevel@tonic-gate /* 12780Sstevel@tonic-gate * If we were killed with SIGTERM, it should have been 12790Sstevel@tonic-gate * via the Spooler who should have killed the entire 12800Sstevel@tonic-gate * process group. We have to wait for the children, 12810Sstevel@tonic-gate * since we're their parent, but WE MAY HAVE WAITED 12820Sstevel@tonic-gate * FOR THEM ALREADY (in cool_heels()). 12830Sstevel@tonic-gate */ 12840Sstevel@tonic-gate if (ChildPid != WaitedChildPid) { 12850Sstevel@tonic-gate register int cpid; 12860Sstevel@tonic-gate 12870Sstevel@tonic-gate while ( 12880Sstevel@tonic-gate (cpid = wait((int *)0)) != ChildPid 12890Sstevel@tonic-gate && (cpid != -1 || errno != ECHILD) 12900Sstevel@tonic-gate ) 12910Sstevel@tonic-gate ; 12920Sstevel@tonic-gate } 12930Sstevel@tonic-gate 12940Sstevel@tonic-gate /* 12950Sstevel@tonic-gate * We can't rely on getting SIGTERM back in the wait() 12960Sstevel@tonic-gate * above, because, for instance, some shells trap SIGTERM 12970Sstevel@tonic-gate * and exit instead. Thus we force it. 12980Sstevel@tonic-gate */ 12990Sstevel@tonic-gate done (SIGTERM, 0); /* Don't use Done() */ 13000Sstevel@tonic-gate /*NOTREACHED*/ 13010Sstevel@tonic-gate } 13020Sstevel@tonic-gate } 13030Sstevel@tonic-gate 13040Sstevel@tonic-gate /** 13050Sstevel@tonic-gate ** done() - TELL SPOOLER THIS CHILD IS DONE 13060Sstevel@tonic-gate **/ 13070Sstevel@tonic-gate 13080Sstevel@tonic-gate static void 13090Sstevel@tonic-gate done(int status, int err) 13100Sstevel@tonic-gate { 13110Sstevel@tonic-gate if (do_undial) 13120Sstevel@tonic-gate undial (1); 13130Sstevel@tonic-gate 1314*3125Sjacobs mputm (ChildMd, S_CHILD_DONE, key, status, err); 13150Sstevel@tonic-gate mdisconnect (ChildMd); 13160Sstevel@tonic-gate 13170Sstevel@tonic-gate exit (0); 13180Sstevel@tonic-gate /*NOTREACHED*/ 13190Sstevel@tonic-gate } 13200Sstevel@tonic-gate 13210Sstevel@tonic-gate /** 13220Sstevel@tonic-gate ** child_mallocfail() 13230Sstevel@tonic-gate **/ 13240Sstevel@tonic-gate 13250Sstevel@tonic-gate static void 13260Sstevel@tonic-gate child_mallocfail(void) 13270Sstevel@tonic-gate { 13280Sstevel@tonic-gate Done (EXEC_EXIT_NOMEM, ENOMEM); 13290Sstevel@tonic-gate } 1330