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 */ 213125Sjacobs 220Sstevel@tonic-gate /* 2310460SSonam.Gupta@Sun.COM * Copyright 2009 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 301676Sjpk #include <pwd.h> 311676Sjpk #include <zone.h> 321676Sjpk #if defined PS_FAULTED 331676Sjpk #undef PS_FAULTED 341676Sjpk #endif /* PS_FAULTED */ 350Sstevel@tonic-gate #include <dial.h> 360Sstevel@tonic-gate 370Sstevel@tonic-gate #include <stdlib.h> 380Sstevel@tonic-gate #include "limits.h" 390Sstevel@tonic-gate #include "stdarg.h" 400Sstevel@tonic-gate #include "wait.h" 410Sstevel@tonic-gate #include "dial.h" 420Sstevel@tonic-gate #include "lpsched.h" 430Sstevel@tonic-gate #include <syslog.h> 441676Sjpk #include "tsol/label.h" 450Sstevel@tonic-gate 460Sstevel@tonic-gate #define Done(EC,ERRNO) done(((EC) << 8),ERRNO) 470Sstevel@tonic-gate 480Sstevel@tonic-gate #define STRLCAT(dst, src, size) \ 490Sstevel@tonic-gate if (strlcat((dst), (src), (size)) >= (size)) { \ 500Sstevel@tonic-gate errno = EINVAL; \ 510Sstevel@tonic-gate return (-1); \ 520Sstevel@tonic-gate } 530Sstevel@tonic-gate 540Sstevel@tonic-gate static MESG * ChildMd; 550Sstevel@tonic-gate 560Sstevel@tonic-gate static int ChildPid; 570Sstevel@tonic-gate static int WaitedChildPid; 580Sstevel@tonic-gate static int do_undial; 590Sstevel@tonic-gate 600Sstevel@tonic-gate static char argbuf[ARG_MAX]; 610Sstevel@tonic-gate 620Sstevel@tonic-gate static long key; 630Sstevel@tonic-gate 640Sstevel@tonic-gate static void sigtrap ( int ); 650Sstevel@tonic-gate static void done ( int , int ); 660Sstevel@tonic-gate static void cool_heels ( void ); 670Sstevel@tonic-gate static void addenv (char ***envp, char * , char * ); 680Sstevel@tonic-gate static void trap_fault_signals ( void ); 690Sstevel@tonic-gate static void ignore_fault_signals ( void ); 700Sstevel@tonic-gate static void child_mallocfail ( void ); 710Sstevel@tonic-gate static void Fork2 ( void ); 720Sstevel@tonic-gate 730Sstevel@tonic-gate static int Fork1 ( EXEC * ); 740Sstevel@tonic-gate 750Sstevel@tonic-gate static void 760Sstevel@tonic-gate relock(void) 770Sstevel@tonic-gate { 780Sstevel@tonic-gate struct flock l; 790Sstevel@tonic-gate 800Sstevel@tonic-gate l.l_type = F_WRLCK; 810Sstevel@tonic-gate l.l_whence = 1; 820Sstevel@tonic-gate l.l_start = 0; 830Sstevel@tonic-gate l.l_len = 0; 840Sstevel@tonic-gate (void)Fcntl (lock_fd, F_SETLK, &l); 850Sstevel@tonic-gate return; 860Sstevel@tonic-gate } 870Sstevel@tonic-gate 880Sstevel@tonic-gate static char *_exec_name(int type) 890Sstevel@tonic-gate { 900Sstevel@tonic-gate static char *_names[] = { 910Sstevel@tonic-gate "", "EX_INTERF", "EX_SLOWF", "EX_ALERT", "EX_FALERT", "EX_PALERT", 920Sstevel@tonic-gate "EX_NOTIFY", "EX_FAULT_MESSAGE", "EX_FORM_MESSAGE", NULL }; 930Sstevel@tonic-gate 940Sstevel@tonic-gate if ((type < 0) || (type > EX_FORM_MESSAGE)) 950Sstevel@tonic-gate return ("BAD_EXEC_TYPE"); 960Sstevel@tonic-gate else 970Sstevel@tonic-gate return (_names[type]); 980Sstevel@tonic-gate } 990Sstevel@tonic-gate 1000Sstevel@tonic-gate /* 1010Sstevel@tonic-gate * This function replaces characters in a string that might be used 1020Sstevel@tonic-gate * to exploit a security hole. Replace command seperators (`, &, ;, |, ^), 1030Sstevel@tonic-gate * output redirection (>, |), variable expansion ($), and character 1040Sstevel@tonic-gate * escape (\). 1050Sstevel@tonic-gate * 1060Sstevel@tonic-gate * Bugid 4141687 1070Sstevel@tonic-gate * Add ( ) < * ? [ 1080Sstevel@tonic-gate * Bugid 4139071 1090Sstevel@tonic-gate * Remove \ 1100Sstevel@tonic-gate */ 1110Sstevel@tonic-gate void clean_string(char *ptr) 1120Sstevel@tonic-gate { 1130Sstevel@tonic-gate char *cp; 1140Sstevel@tonic-gate wchar_t wc; 1150Sstevel@tonic-gate size_t len; 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate for (cp = ptr; *cp != NULL; ) { 1180Sstevel@tonic-gate if ((len = mbtowc(&wc, cp, MB_CUR_MAX)) == -1) { 1190Sstevel@tonic-gate cp++; 1200Sstevel@tonic-gate continue; 1210Sstevel@tonic-gate } 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate if (len == 1 && 1240Sstevel@tonic-gate ((wc == L'`') || (wc == L'&') || (wc == L';') || 1250Sstevel@tonic-gate (wc == L'|') || (wc == L'>') || (wc == L'^') || 1260Sstevel@tonic-gate (wc == L'$') || (wc == L'(') || (wc == L')') || 1270Sstevel@tonic-gate (wc == L'<') || (wc == L'*') || (wc == L'?') || 1280Sstevel@tonic-gate (wc == L'['))) 1290Sstevel@tonic-gate *cp = '_'; 1300Sstevel@tonic-gate cp += len; 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate enum trust {TRUSTED, UNTRUSTED}; 1353204Sjacobs 1363204Sjacobs static char *arg_string(enum trust type, char *fmt, ...) __PRINTFLIKE(2); 1373204Sjacobs 1383204Sjacobs /* PRINTFLIKE2 */ 1390Sstevel@tonic-gate static char * 1400Sstevel@tonic-gate arg_string(enum trust type, char *fmt, ...) 1410Sstevel@tonic-gate { 1420Sstevel@tonic-gate char buf[BUFSIZ]; 1430Sstevel@tonic-gate va_list args; 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate va_start(args, fmt); 1460Sstevel@tonic-gate (void) vsnprintf(buf, sizeof(buf), fmt, args); 1470Sstevel@tonic-gate va_end(args); 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate /* 1500Sstevel@tonic-gate * If the string contains data from an untrusted origin (user supplied), 1510Sstevel@tonic-gate * clean it up in case one of our progeny is a shell script and isn't 1520Sstevel@tonic-gate * careful about checking its input. 1530Sstevel@tonic-gate */ 1540Sstevel@tonic-gate if (type == UNTRUSTED) 1550Sstevel@tonic-gate clean_string(buf); 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate return (strdup(buf)); 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate /* stolen from libc/gen/port/gen/execvp.c */ 1610Sstevel@tonic-gate static const char * 1620Sstevel@tonic-gate execat(const char *s1, const char *s2, char *si) 1630Sstevel@tonic-gate { 1640Sstevel@tonic-gate char *s; 1650Sstevel@tonic-gate int cnt = PATH_MAX + 1; /* number of characters in s2 */ 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate s = si; 1680Sstevel@tonic-gate while (*s1 && *s1 != ':') { 1690Sstevel@tonic-gate if (cnt > 0) { 1700Sstevel@tonic-gate *s++ = *s1++; 1710Sstevel@tonic-gate cnt--; 1720Sstevel@tonic-gate } else 1730Sstevel@tonic-gate s1++; 1740Sstevel@tonic-gate } 1750Sstevel@tonic-gate if (si != s && cnt > 0) { 1760Sstevel@tonic-gate *s++ = '/'; 1770Sstevel@tonic-gate cnt--; 1780Sstevel@tonic-gate } 1790Sstevel@tonic-gate while (*s2 && cnt > 0) { 1800Sstevel@tonic-gate *s++ = *s2++; 1810Sstevel@tonic-gate cnt--; 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate *s = '\0'; 1840Sstevel@tonic-gate return (*s1 ? ++s1: 0); 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate /* 1880Sstevel@tonic-gate * Similiar to execvp(), execpt you can supply an environment and we always 1890Sstevel@tonic-gate * use /bin/sh for shell scripts. The PATH searched is the PATH in the 1900Sstevel@tonic-gate * current environment, not the environment in the argument list. 1910Sstevel@tonic-gate * This was pretty much stolen from libc/gen/port/execvp.c 1920Sstevel@tonic-gate */ 1930Sstevel@tonic-gate static int 1940Sstevel@tonic-gate execvpe(char *name, char *const argv[], char *const envp[]) 1950Sstevel@tonic-gate { 1960Sstevel@tonic-gate char *path; 1970Sstevel@tonic-gate char fname[PATH_MAX+2]; 1980Sstevel@tonic-gate char *newargs[256]; 1990Sstevel@tonic-gate int i; 2000Sstevel@tonic-gate const char *cp; 2010Sstevel@tonic-gate unsigned etxtbsy = 1; 2020Sstevel@tonic-gate int eacces = 0; 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate if (*name == '\0') { 2050Sstevel@tonic-gate errno = ENOENT; 2060Sstevel@tonic-gate return (-1); 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate if ((path = getenv("PATH")) == NULL) 2100Sstevel@tonic-gate path = "/usr/bin:/bin"; 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate cp = strchr(name, '/')? (const char *)"": path; 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate do { 2150Sstevel@tonic-gate cp = execat(cp, name, fname); 2160Sstevel@tonic-gate retry: 2170Sstevel@tonic-gate /* 2180Sstevel@tonic-gate * 4025035 and 4038378 2190Sstevel@tonic-gate * if a filename begins with a "-" prepend "./" so that 2200Sstevel@tonic-gate * the shell can't interpret it as an option 2210Sstevel@tonic-gate */ 2220Sstevel@tonic-gate if (*fname == '-') { 2230Sstevel@tonic-gate size_t size = strlen(fname) + 1; 2240Sstevel@tonic-gate if ((size + 2) > sizeof (fname)) { 2250Sstevel@tonic-gate errno = E2BIG; 2260Sstevel@tonic-gate return (-1); 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate (void) memmove(fname + 2, fname, size); 2290Sstevel@tonic-gate fname[0] = '.'; 2300Sstevel@tonic-gate fname[1] = '/'; 2310Sstevel@tonic-gate } 2320Sstevel@tonic-gate (void) execve(fname, argv, envp); 2330Sstevel@tonic-gate switch (errno) { 2340Sstevel@tonic-gate case ENOEXEC: 2350Sstevel@tonic-gate newargs[0] = "sh"; 2360Sstevel@tonic-gate newargs[1] = fname; 2370Sstevel@tonic-gate for (i = 1; (newargs[i + 1] = argv[i]) != NULL; ++i) { 2380Sstevel@tonic-gate if (i >= 254) { 2390Sstevel@tonic-gate errno = E2BIG; 2400Sstevel@tonic-gate return (-1); 2410Sstevel@tonic-gate } 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate (void) execve("/bin/sh", newargs, envp); 2440Sstevel@tonic-gate return (-1); 2450Sstevel@tonic-gate case ETXTBSY: 2460Sstevel@tonic-gate if (++etxtbsy > 5) 2470Sstevel@tonic-gate return (-1); 2480Sstevel@tonic-gate (void) sleep(etxtbsy); 2490Sstevel@tonic-gate goto retry; 2500Sstevel@tonic-gate case EACCES: 2510Sstevel@tonic-gate ++eacces; 2520Sstevel@tonic-gate break; 2530Sstevel@tonic-gate case ENOMEM: 2540Sstevel@tonic-gate case E2BIG: 2550Sstevel@tonic-gate case EFAULT: 2560Sstevel@tonic-gate return (-1); 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate } while (cp); 2590Sstevel@tonic-gate if (eacces) 2600Sstevel@tonic-gate errno = EACCES; 2610Sstevel@tonic-gate return (-1); 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate static char time_buf[50]; 2651676Sjpk 2660Sstevel@tonic-gate /** 2670Sstevel@tonic-gate ** exec() - FORK AND EXEC CHILD PROCESS 2680Sstevel@tonic-gate **/ 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate /*VARARGS1*/ 2710Sstevel@tonic-gate int 2720Sstevel@tonic-gate exec(int type, ...) 2730Sstevel@tonic-gate { 2740Sstevel@tonic-gate va_list args; 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate int i; 2770Sstevel@tonic-gate int procuid; 2780Sstevel@tonic-gate int procgid; 2790Sstevel@tonic-gate int ret; 2800Sstevel@tonic-gate int fr_flg; 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate char *cp; 2830Sstevel@tonic-gate char *infile; 2840Sstevel@tonic-gate char *outfile; 2850Sstevel@tonic-gate char *errfile; 2860Sstevel@tonic-gate char *sep; 2870Sstevel@tonic-gate 2880Sstevel@tonic-gate char **listp; 2890Sstevel@tonic-gate char **file_list; 2900Sstevel@tonic-gate char *printerName; 2910Sstevel@tonic-gate char *printerNameToShow; 2920Sstevel@tonic-gate static char nameBuf[100]; 2930Sstevel@tonic-gate char *clean_title; 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate PSTATUS *printer; 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate RSTATUS *request; 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate FSTATUS *form; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate EXEC *ep; 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate PWSTATUS *pwheel; 3040Sstevel@tonic-gate time_t now; 3050Sstevel@tonic-gate struct passwd *pwp; 3060Sstevel@tonic-gate #ifdef LP_USE_PAPI_ATTR 3070Sstevel@tonic-gate struct stat tmpBuf; 3080Sstevel@tonic-gate char tmpName[BUFSIZ]; 3090Sstevel@tonic-gate char *path = NULL; 3100Sstevel@tonic-gate #endif 3110Sstevel@tonic-gate char *av[ARG_MAX]; 3120Sstevel@tonic-gate char **envp = NULL; 3130Sstevel@tonic-gate int ac = 0; 3141676Sjpk char *mail_zonename = NULL; 3151676Sjpk char *slabel = NULL; 31610460SSonam.Gupta@Sun.COM int setid = 1; 31710460SSonam.Gupta@Sun.COM char *ridno = NULL; 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate syslog(LOG_DEBUG, "exec(%s)", _exec_name(type)); 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate memset(av, 0, sizeof (*av)); 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate va_start (args, type); 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate switch (type) { 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate case EX_INTERF: 3280Sstevel@tonic-gate printer = va_arg(args, PSTATUS *); 3290Sstevel@tonic-gate request = printer->request; 3300Sstevel@tonic-gate ep = printer->exec; 3310Sstevel@tonic-gate break; 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate case EX_FAULT_MESSAGE: 3340Sstevel@tonic-gate printer = va_arg(args, PSTATUS *); 3350Sstevel@tonic-gate request = va_arg(args, RSTATUS *); 3360Sstevel@tonic-gate if (! ( printer->status & (PS_FORM_FAULT | PS_SHOW_FAULT))) { 3370Sstevel@tonic-gate return(0); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate ep = printer->fault_exec; 3400Sstevel@tonic-gate printerName = (printer->printer && printer->printer->name 3410Sstevel@tonic-gate ? printer->printer->name : "??"); 3420Sstevel@tonic-gate snprintf(nameBuf, sizeof (nameBuf), 3430Sstevel@tonic-gate "%s (on %s)\n", printerName, Local_System); 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate printerNameToShow = nameBuf; 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate (void) time(&now); 3480Sstevel@tonic-gate (void) strftime(time_buf, sizeof (time_buf), 3490Sstevel@tonic-gate NULL, localtime(&now)); 3500Sstevel@tonic-gate break; 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate case EX_SLOWF: 3530Sstevel@tonic-gate request = va_arg(args, RSTATUS *); 3540Sstevel@tonic-gate ep = request->exec; 3550Sstevel@tonic-gate break; 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate case EX_NOTIFY: 3580Sstevel@tonic-gate request = va_arg(args, RSTATUS *); 3590Sstevel@tonic-gate if (request->request->actions & ACT_NOTIFY) { 3600Sstevel@tonic-gate errno = EINVAL; 3610Sstevel@tonic-gate return (-1); 3620Sstevel@tonic-gate } 3630Sstevel@tonic-gate ep = request->exec; 3640Sstevel@tonic-gate break; 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate case EX_ALERT: 3670Sstevel@tonic-gate printer = va_arg(args, PSTATUS *); 3680Sstevel@tonic-gate if (!(printer->printer->fault_alert.shcmd)) { 3690Sstevel@tonic-gate errno = EINVAL; 3700Sstevel@tonic-gate return(-1); 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate ep = printer->alert->exec; 3730Sstevel@tonic-gate break; 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate case EX_PALERT: 3760Sstevel@tonic-gate pwheel = va_arg(args, PWSTATUS *); 3770Sstevel@tonic-gate ep = pwheel->alert->exec; 3780Sstevel@tonic-gate break; 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate case EX_FORM_MESSAGE: 3810Sstevel@tonic-gate (void) time(&now); 3820Sstevel@tonic-gate (void) strftime(time_buf, sizeof (time_buf), 3830Sstevel@tonic-gate NULL, localtime(&now)); 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate /*FALLTHRU*/ 3860Sstevel@tonic-gate case EX_FALERT: 3870Sstevel@tonic-gate form = va_arg(args, FSTATUS *); 3880Sstevel@tonic-gate ep = form->alert->exec; 3890Sstevel@tonic-gate break; 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate default: 3920Sstevel@tonic-gate errno = EINVAL; 3930Sstevel@tonic-gate return(-1); 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate va_end (args); 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate if (!ep || (ep->pid > 0)) { 3990Sstevel@tonic-gate errno = EBUSY; 4000Sstevel@tonic-gate return(-1); 4010Sstevel@tonic-gate } 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate ep->flags = 0; 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate key = ep->key = getkey(); 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate switch ((ep->pid = Fork1(ep))) { 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate case -1: 4100Sstevel@tonic-gate relock (); 4110Sstevel@tonic-gate return(-1); 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate case 0: 4140Sstevel@tonic-gate /* 4150Sstevel@tonic-gate * We want to be able to tell our parent how we died. 4160Sstevel@tonic-gate */ 4170Sstevel@tonic-gate lp_alloc_fail_handler = child_mallocfail; 4180Sstevel@tonic-gate break; 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate default: 4210Sstevel@tonic-gate switch(type) { 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate case EX_INTERF: 4240Sstevel@tonic-gate request->request->outcome |= RS_PRINTING; 4250Sstevel@tonic-gate break; 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate case EX_NOTIFY: 4280Sstevel@tonic-gate request->request->outcome |= RS_NOTIFYING; 4290Sstevel@tonic-gate break; 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate case EX_SLOWF: 4320Sstevel@tonic-gate request->request->outcome |= RS_FILTERING; 4330Sstevel@tonic-gate request->request->outcome &= ~RS_REFILTER; 4340Sstevel@tonic-gate break; 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate } 4370Sstevel@tonic-gate return(0); 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate for (i = 0; i < NSIG; i++) 4420Sstevel@tonic-gate (void)signal (i, SIG_DFL); 4430Sstevel@tonic-gate (void)signal (SIGALRM, SIG_IGN); 4440Sstevel@tonic-gate (void)signal (SIGTERM, sigtrap); 4453125Sjacobs 4463125Sjacobs closelog(); 4470Sstevel@tonic-gate for (i = 0; i < OpenMax; i++) 4480Sstevel@tonic-gate if (i != ChildMd->writefd) 4490Sstevel@tonic-gate Close (i); 4503125Sjacobs openlog("lpsched", LOG_PID|LOG_NDELAY|LOG_NOWAIT, LOG_LPR); 4513125Sjacobs 4520Sstevel@tonic-gate setpgrp(); 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate /* Set a default path */ 4550Sstevel@tonic-gate addenv (&envp, "PATH", "/usr/lib/lp/bin:/usr/bin:/bin:/usr/sbin:/sbin"); 4560Sstevel@tonic-gate /* copy locale related variables */ 4570Sstevel@tonic-gate addenv (&envp, "TZ", getenv("TZ")); 4580Sstevel@tonic-gate addenv (&envp, "LANG", getenv("LANG")); 4590Sstevel@tonic-gate addenv (&envp, "LC_ALL", getenv("LC_ALL")); 4600Sstevel@tonic-gate addenv (&envp, "LC_COLLATE", getenv("LC_COLLATE")); 4610Sstevel@tonic-gate addenv (&envp, "LC_CTYPE", getenv("LC_CTYPE")); 4620Sstevel@tonic-gate addenv (&envp, "LC_MESSAGES", getenv("LC_MESSAGES")); 4630Sstevel@tonic-gate addenv (&envp, "LC_MONETARY", getenv("LC_MONETARY")); 4640Sstevel@tonic-gate addenv (&envp, "LC_NUMERIC", getenv("LC_NUMERIC")); 4650Sstevel@tonic-gate addenv (&envp, "LC_TIME", getenv("LC_TIME")); 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate sprintf ((cp = BIGGEST_NUMBER_S), "%ld", key); 4680Sstevel@tonic-gate addenv (&envp, "SPOOLER_KEY", cp); 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate #if defined(DEBUG) 4710Sstevel@tonic-gate addenv (&envp, "LPDEBUG", (debug? "1" : "0")); 4720Sstevel@tonic-gate #endif 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate /* 4750Sstevel@tonic-gate * Open the standard input, standard output, and standard error. 4760Sstevel@tonic-gate */ 4770Sstevel@tonic-gate switch (type) { 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate case EX_SLOWF: 4800Sstevel@tonic-gate case EX_INTERF: 4810Sstevel@tonic-gate /* 4820Sstevel@tonic-gate * stdin: /dev/null 4830Sstevel@tonic-gate * stdout: /dev/null (EX_SLOWF), printer port (EX_INTERF) 4840Sstevel@tonic-gate * stderr: req# 4850Sstevel@tonic-gate */ 4860Sstevel@tonic-gate infile = 0; 4870Sstevel@tonic-gate outfile = 0; 4880Sstevel@tonic-gate errfile = makereqerr(request); 4890Sstevel@tonic-gate break; 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate case EX_NOTIFY: 4920Sstevel@tonic-gate /* 4930Sstevel@tonic-gate * stdin: req# 4940Sstevel@tonic-gate * stdout: /dev/null 4950Sstevel@tonic-gate * stderr: /dev/null 4960Sstevel@tonic-gate */ 4970Sstevel@tonic-gate infile = makereqerr(request); 4980Sstevel@tonic-gate outfile = 0; 4990Sstevel@tonic-gate errfile = 0; 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate break; 5020Sstevel@tonic-gate 5030Sstevel@tonic-gate case EX_ALERT: 5040Sstevel@tonic-gate case EX_FALERT: 5050Sstevel@tonic-gate case EX_PALERT: 5060Sstevel@tonic-gate case EX_FAULT_MESSAGE: 5070Sstevel@tonic-gate case EX_FORM_MESSAGE: 5080Sstevel@tonic-gate /* 5090Sstevel@tonic-gate * stdin: /dev/null 5100Sstevel@tonic-gate * stdout: /dev/null 5110Sstevel@tonic-gate * stderr: /dev/null 5120Sstevel@tonic-gate */ 5130Sstevel@tonic-gate infile = 0; 5140Sstevel@tonic-gate outfile = 0; 5150Sstevel@tonic-gate errfile = 0; 5160Sstevel@tonic-gate break; 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate } 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate if (infile) { 5210Sstevel@tonic-gate if (Open(infile, O_RDONLY) == -1) 5220Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5230Sstevel@tonic-gate } else { 5240Sstevel@tonic-gate if (Open("/dev/null", O_RDONLY) == -1) 5250Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate if (outfile) { 5290Sstevel@tonic-gate if (Open(outfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1) 5300Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5310Sstevel@tonic-gate } else { 5320Sstevel@tonic-gate /* 5330Sstevel@tonic-gate * If EX_INTERF, this is still needed to cause the 5340Sstevel@tonic-gate * standard error channel to be #2. 5350Sstevel@tonic-gate */ 5360Sstevel@tonic-gate if (Open("/dev/null", O_WRONLY) == -1) 5370Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5380Sstevel@tonic-gate } 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate if (errfile) { 5410Sstevel@tonic-gate if (Open(errfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1) 5420Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5430Sstevel@tonic-gate } else { 5440Sstevel@tonic-gate if (Open("/dev/null", O_WRONLY) == -1) 5450Sstevel@tonic-gate Done (EXEC_EXIT_NOPEN, errno); 5460Sstevel@tonic-gate } 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate switch (type) { 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate case EX_INTERF: 5510Sstevel@tonic-gate /* 5520Sstevel@tonic-gate * Opening a ``port'' can be dangerous to our health: 5530Sstevel@tonic-gate * 5540Sstevel@tonic-gate * - Hangups can occur if the line is dropped. 5550Sstevel@tonic-gate * - The printer may send an interrupt. 5560Sstevel@tonic-gate * - A FIFO may be closed, generating SIGPIPE. 5570Sstevel@tonic-gate * 5580Sstevel@tonic-gate * We catch these so we can complain nicely. 5590Sstevel@tonic-gate */ 5600Sstevel@tonic-gate trap_fault_signals (); 5610Sstevel@tonic-gate 5620Sstevel@tonic-gate (void)Close (1); 5630Sstevel@tonic-gate 564*11378SSonam.Gupta@Sun.COM procuid = request->secure->uid; 565*11378SSonam.Gupta@Sun.COM procgid = request->secure->gid; 566*11378SSonam.Gupta@Sun.COM 5670Sstevel@tonic-gate if (printer->printer->dial_info) 5680Sstevel@tonic-gate { 5690Sstevel@tonic-gate ret = open_dialup(request->printer_type, 5700Sstevel@tonic-gate printer->printer); 5710Sstevel@tonic-gate if (ret == 0) 5720Sstevel@tonic-gate do_undial = 1; 5730Sstevel@tonic-gate } 5740Sstevel@tonic-gate else 5750Sstevel@tonic-gate { 5760Sstevel@tonic-gate ret = open_direct(request->printer_type, 5770Sstevel@tonic-gate printer->printer); 5780Sstevel@tonic-gate do_undial = 0; 5790Sstevel@tonic-gate /* this is a URI */ 5800Sstevel@tonic-gate if (is_printer_uri(printer->printer->device) == 0) 5810Sstevel@tonic-gate addenv(&envp, "DEVICE_URI", 5820Sstevel@tonic-gate printer->printer->device); 5830Sstevel@tonic-gate } 5840Sstevel@tonic-gate addenv(&envp, "DEVICE_URI", 5850Sstevel@tonic-gate printer->printer->device); 5860Sstevel@tonic-gate if (ret != 0) 5870Sstevel@tonic-gate Done (ret, errno); 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate if (!(request->request->outcome & RS_FILTERED)) 5900Sstevel@tonic-gate file_list = request->request->file_list; 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate else { 5930Sstevel@tonic-gate register int count = 0; 5940Sstevel@tonic-gate register char * num = BIGGEST_REQID_S; 5950Sstevel@tonic-gate register char * prefix; 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate prefix = makestr( 5983125Sjacobs Lp_Temp, 5990Sstevel@tonic-gate "/F", 6000Sstevel@tonic-gate getreqno(request->secure->req_id), 6010Sstevel@tonic-gate "-", 6020Sstevel@tonic-gate (char *)0 6030Sstevel@tonic-gate ); 6040Sstevel@tonic-gate 6050Sstevel@tonic-gate file_list = (char **)Malloc( 6060Sstevel@tonic-gate (lenlist(request->request->file_list) + 1) 6070Sstevel@tonic-gate * sizeof(char *) 6080Sstevel@tonic-gate ); 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate for ( 6110Sstevel@tonic-gate listp = request->request->file_list; 6120Sstevel@tonic-gate *listp; 6130Sstevel@tonic-gate listp++ 6140Sstevel@tonic-gate ) { 6150Sstevel@tonic-gate sprintf (num, "%d", count + 1); 6160Sstevel@tonic-gate file_list[count] = makestr( 6170Sstevel@tonic-gate prefix, 6180Sstevel@tonic-gate num, 6190Sstevel@tonic-gate (char *)0 6200Sstevel@tonic-gate ); 6210Sstevel@tonic-gate count++; 6220Sstevel@tonic-gate } 6230Sstevel@tonic-gate file_list[count] = 0; 6240Sstevel@tonic-gate } 6250Sstevel@tonic-gate 6260Sstevel@tonic-gate #ifdef LP_USE_PAPI_ATTR 6270Sstevel@tonic-gate /* 6280Sstevel@tonic-gate * Check if the PAPI job attribute file exists, if it does 6290Sstevel@tonic-gate * pass the file's pathname to the printer interface script 6300Sstevel@tonic-gate * in an environment variable. This file is created when 6310Sstevel@tonic-gate * print jobs are submitted via the PAPI interface. 6320Sstevel@tonic-gate */ 6330Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s-%s", 6340Sstevel@tonic-gate getreqno(request->secure->req_id), LP_PAPIATTRNAME); 6353125Sjacobs path = makepath(Lp_Temp, tmpName, (char *)0); 6360Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 6370Sstevel@tonic-gate { 6380Sstevel@tonic-gate /* 6390Sstevel@tonic-gate * IPP job attribute file exists for this job so 6400Sstevel@tonic-gate * set the environment variable 6410Sstevel@tonic-gate */ 6420Sstevel@tonic-gate addenv(&envp, "ATTRPATH", path); 6430Sstevel@tonic-gate } 6440Sstevel@tonic-gate Free(path); 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate /* 6470Sstevel@tonic-gate * now set environment variable for the printer's PostScript 6480Sstevel@tonic-gate * Printer Description (PPD) file, this is used by the filter 6490Sstevel@tonic-gate * when forming the print data for this printer. 6500Sstevel@tonic-gate */ 6510Sstevel@tonic-gate if ((request->printer != NULL) && 6520Sstevel@tonic-gate (request->printer->printer != NULL) && 6530Sstevel@tonic-gate (request->printer->printer->name != NULL)) 6540Sstevel@tonic-gate { 6550Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s.ppd", 6560Sstevel@tonic-gate request->printer->printer->name); 6570Sstevel@tonic-gate path = makepath(ETCDIR, "ppd", tmpName, (char *)0); 6580Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 6590Sstevel@tonic-gate { 6600Sstevel@tonic-gate addenv(&envp, "PPD", path); 6610Sstevel@tonic-gate } 6620Sstevel@tonic-gate Free(path); 6630Sstevel@tonic-gate } 6640Sstevel@tonic-gate #endif 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate if (request->printer_type) 6670Sstevel@tonic-gate addenv(&envp, "TERM", request->printer_type); 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate if (!(printer->printer->daisy)) { 6700Sstevel@tonic-gate register char * chset = 0; 6710Sstevel@tonic-gate register char * csp; 6720Sstevel@tonic-gate 6730Sstevel@tonic-gate if ( 6740Sstevel@tonic-gate request->form 6750Sstevel@tonic-gate && request->form->form->chset 6760Sstevel@tonic-gate && request->form->form->mandatory 6770Sstevel@tonic-gate && !STREQU(NAME_ANY, request->form->form->chset) 6780Sstevel@tonic-gate ) 6790Sstevel@tonic-gate chset = request->form->form->chset; 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate else if ( 6820Sstevel@tonic-gate request->request->charset 6830Sstevel@tonic-gate && !STREQU(NAME_ANY, request->request->charset) 6840Sstevel@tonic-gate ) 6850Sstevel@tonic-gate chset = request->request->charset; 6860Sstevel@tonic-gate 6870Sstevel@tonic-gate if (chset) { 6880Sstevel@tonic-gate csp = search_cslist( 6890Sstevel@tonic-gate chset, 6900Sstevel@tonic-gate printer->printer->char_sets 6910Sstevel@tonic-gate ); 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate /* 6940Sstevel@tonic-gate * The "strtok()" below wrecks the string 6950Sstevel@tonic-gate * for future use, but this is a child 6960Sstevel@tonic-gate * process where it won't be needed again. 6970Sstevel@tonic-gate */ 6980Sstevel@tonic-gate addenv (&envp, "CHARSET", 6990Sstevel@tonic-gate (csp? strtok(csp, "=") : chset) 7000Sstevel@tonic-gate ); 7010Sstevel@tonic-gate } 7020Sstevel@tonic-gate } 7030Sstevel@tonic-gate 7040Sstevel@tonic-gate if (request->fast) 7050Sstevel@tonic-gate addenv(&envp, "FILTER", request->fast); 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate /* 7081676Sjpk * Add the sensitivity label to the environment for 7091676Sjpk * banner page and header/footer processing 7101676Sjpk */ 7111676Sjpk 7121676Sjpk if (is_system_labeled() && request->secure->slabel != NULL) 7131676Sjpk addenv(&envp, "SLABEL", request->secure->slabel); 7141676Sjpk 7151676Sjpk /* 7160Sstevel@tonic-gate * Add the system name to the user name (ala system!user) 7170Sstevel@tonic-gate * unless it is already there. RFS users may have trouble 7180Sstevel@tonic-gate * here, sorry! 7190Sstevel@tonic-gate */ 7200Sstevel@tonic-gate cp = strchr(request->secure->user, '@'); 7210Sstevel@tonic-gate 7220Sstevel@tonic-gate allTraysWithForm(printer, request->form); 7230Sstevel@tonic-gate 7240Sstevel@tonic-gate /* 7250Sstevel@tonic-gate * Fix for 4137389 7260Sstevel@tonic-gate * Remove double quotes from title string. 7270Sstevel@tonic-gate */ 7280Sstevel@tonic-gate fr_flg = 1; 7290Sstevel@tonic-gate clean_title = strdup(NB(request->request->title)); 7300Sstevel@tonic-gate if (clean_title == NULL) { 7310Sstevel@tonic-gate /* 7320Sstevel@tonic-gate * strdup failed. We're probably hosed 7330Sstevel@tonic-gate * but try setting clean_title 7340Sstevel@tonic-gate * to original title and continuing. 7350Sstevel@tonic-gate */ 7360Sstevel@tonic-gate clean_title = NB(request->request->title); 7370Sstevel@tonic-gate fr_flg = 0; 7380Sstevel@tonic-gate } else if (strcmp(clean_title, "") != 0) { 7390Sstevel@tonic-gate char *ct_p; 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate for (ct_p = clean_title; *ct_p != NULL; ct_p++) { 7420Sstevel@tonic-gate if (*ct_p == '"') 7430Sstevel@tonic-gate *ct_p = ' '; 7440Sstevel@tonic-gate } 7450Sstevel@tonic-gate } 7460Sstevel@tonic-gate 7470Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_A_Interfaces, 7480Sstevel@tonic-gate printer->printer->name); 74910460SSonam.Gupta@Sun.COM /* 75010460SSonam.Gupta@Sun.COM * Read the options field of the request 75110460SSonam.Gupta@Sun.COM * In case of remote lpd request 75210460SSonam.Gupta@Sun.COM * the options field will have 75310460SSonam.Gupta@Sun.COM * job-id-requested. This is the 75410460SSonam.Gupta@Sun.COM * id sent by the client 75510460SSonam.Gupta@Sun.COM */ 75610460SSonam.Gupta@Sun.COM if (request->request->options != NULL) { 75710460SSonam.Gupta@Sun.COM char *options = NULL, *temp = NULL; 75810460SSonam.Gupta@Sun.COM options = temp = strdup(request->request->options); 75910460SSonam.Gupta@Sun.COM 76010460SSonam.Gupta@Sun.COM /* 76110460SSonam.Gupta@Sun.COM * Search for job-id-requested in 76210460SSonam.Gupta@Sun.COM * options string 76310460SSonam.Gupta@Sun.COM */ 76410460SSonam.Gupta@Sun.COM options = strstr(options, "job-id-requested"); 76510460SSonam.Gupta@Sun.COM if (options != NULL) { 76610460SSonam.Gupta@Sun.COM /* 76710460SSonam.Gupta@Sun.COM * Extract the ridno from the string 76810460SSonam.Gupta@Sun.COM * job-id-requested=xxx 76910460SSonam.Gupta@Sun.COM * In this case ridno = xxx 77010460SSonam.Gupta@Sun.COM */ 77110460SSonam.Gupta@Sun.COM if (STRNEQU(options, "job-id-requested=", 17)) { 77210460SSonam.Gupta@Sun.COM ridno = strdup(options + 17); 77310460SSonam.Gupta@Sun.COM if (ridno != NULL) 77410460SSonam.Gupta@Sun.COM /* 77510460SSonam.Gupta@Sun.COM * Read job-id-requested 77610460SSonam.Gupta@Sun.COM * successfully 77710460SSonam.Gupta@Sun.COM */ 77810460SSonam.Gupta@Sun.COM setid = 0; 77910460SSonam.Gupta@Sun.COM else 78010460SSonam.Gupta@Sun.COM /* 78110460SSonam.Gupta@Sun.COM * could not read 78210460SSonam.Gupta@Sun.COM * ridno from the string 78310460SSonam.Gupta@Sun.COM * job-id-requested=xxx 78410460SSonam.Gupta@Sun.COM */ 78510460SSonam.Gupta@Sun.COM setid = 1; 78610460SSonam.Gupta@Sun.COM } else 78710460SSonam.Gupta@Sun.COM /* 78810460SSonam.Gupta@Sun.COM * could not read 78910460SSonam.Gupta@Sun.COM * ridno from the string 79010460SSonam.Gupta@Sun.COM * job-id-requested=xxx 79110460SSonam.Gupta@Sun.COM */ 79210460SSonam.Gupta@Sun.COM setid = 1; 79310460SSonam.Gupta@Sun.COM } else 79410460SSonam.Gupta@Sun.COM /* 79510460SSonam.Gupta@Sun.COM * No job-id-requested in 79610460SSonam.Gupta@Sun.COM * request options 79710460SSonam.Gupta@Sun.COM */ 79810460SSonam.Gupta@Sun.COM setid = 1; 79910460SSonam.Gupta@Sun.COM 80010460SSonam.Gupta@Sun.COM if (temp != NULL) 80110460SSonam.Gupta@Sun.COM free(temp); 80210460SSonam.Gupta@Sun.COM 80310460SSonam.Gupta@Sun.COM } else 80410460SSonam.Gupta@Sun.COM /* 80510460SSonam.Gupta@Sun.COM * options field in request structure 80610460SSonam.Gupta@Sun.COM * not set 80710460SSonam.Gupta@Sun.COM */ 80810460SSonam.Gupta@Sun.COM setid = 1; 80910460SSonam.Gupta@Sun.COM 81010460SSonam.Gupta@Sun.COM 81110460SSonam.Gupta@Sun.COM /* 81210460SSonam.Gupta@Sun.COM * setid = 1 means the job-id-requested attribute 81310460SSonam.Gupta@Sun.COM * is not set so read the request->secure->req_id 81410460SSonam.Gupta@Sun.COM */ 81510460SSonam.Gupta@Sun.COM if (setid) 81610460SSonam.Gupta@Sun.COM av[ac++] = arg_string(TRUSTED, "%s", 81710460SSonam.Gupta@Sun.COM request->secure->req_id); 81810460SSonam.Gupta@Sun.COM else { 81910460SSonam.Gupta@Sun.COM /* 82010460SSonam.Gupta@Sun.COM * From request->secure->req_id extract the 82110460SSonam.Gupta@Sun.COM * printer-name. 82210460SSonam.Gupta@Sun.COM * request->secure->req_id = <printer-name>-<req_id> 82310460SSonam.Gupta@Sun.COM * The final req-id will be 82410460SSonam.Gupta@Sun.COM * <printer-name>-<ridno> 82510460SSonam.Gupta@Sun.COM */ 82610460SSonam.Gupta@Sun.COM char *r1 = NULL, *r2 = NULL, *tmp = NULL; 82710460SSonam.Gupta@Sun.COM r1 = r2 = tmp = strdup(request->secure->req_id); 82810460SSonam.Gupta@Sun.COM r2 = strrchr(r1, '-'); 82910460SSonam.Gupta@Sun.COM if (r2 != NULL) { 83010460SSonam.Gupta@Sun.COM char *r3 = NULL; 83110460SSonam.Gupta@Sun.COM int lr1 = strlen(r1); 83210460SSonam.Gupta@Sun.COM int lr2 = strlen(r2); 83310460SSonam.Gupta@Sun.COM r1[lr1 - lr2 + 1] = '\0'; 83410460SSonam.Gupta@Sun.COM 83510460SSonam.Gupta@Sun.COM /* 83610460SSonam.Gupta@Sun.COM * Now r1 = <printer-name>- 83710460SSonam.Gupta@Sun.COM */ 83810460SSonam.Gupta@Sun.COM lr1 = strlen(r1); 83910460SSonam.Gupta@Sun.COM lr2 = strlen(ridno); 84010460SSonam.Gupta@Sun.COM 84110460SSonam.Gupta@Sun.COM r3 = (char *)malloc(lr1+lr2+1); 84210460SSonam.Gupta@Sun.COM if (r3 != NULL) { 84310460SSonam.Gupta@Sun.COM strcpy(r3, r1); 84410460SSonam.Gupta@Sun.COM strcat(r3, ridno); 84510460SSonam.Gupta@Sun.COM /* 84610460SSonam.Gupta@Sun.COM * Here r3 = <printer-name>-<ridno> 84710460SSonam.Gupta@Sun.COM */ 84810460SSonam.Gupta@Sun.COM av[ac++] = arg_string(TRUSTED, 84910460SSonam.Gupta@Sun.COM "%s", r3); 85010460SSonam.Gupta@Sun.COM free(r3); 85110460SSonam.Gupta@Sun.COM } else 85210460SSonam.Gupta@Sun.COM av[ac++] = arg_string(TRUSTED, "%s", 85310460SSonam.Gupta@Sun.COM request->secure->req_id); 85410460SSonam.Gupta@Sun.COM 85510460SSonam.Gupta@Sun.COM } else 85610460SSonam.Gupta@Sun.COM av[ac++] = arg_string(TRUSTED, "%s", 85710460SSonam.Gupta@Sun.COM request->secure->req_id); 85810460SSonam.Gupta@Sun.COM 85910460SSonam.Gupta@Sun.COM if (tmp != NULL) 86010460SSonam.Gupta@Sun.COM free(tmp); 86110460SSonam.Gupta@Sun.COM 86210460SSonam.Gupta@Sun.COM if (ridno != NULL) 86310460SSonam.Gupta@Sun.COM free(ridno); 86410460SSonam.Gupta@Sun.COM } 86510460SSonam.Gupta@Sun.COM 8663125Sjacobs av[ac++] = arg_string(UNTRUSTED, "%s", request->request->user); 8670Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", clean_title); 8680Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%d", request->copies); 8690Sstevel@tonic-gate 8700Sstevel@tonic-gate if (fr_flg) 8710Sstevel@tonic-gate free (clean_title); 8720Sstevel@tonic-gate 8730Sstevel@tonic-gate sep = ""; 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate /* 8760Sstevel@tonic-gate * Do the administrator defined key=value pair options 8770Sstevel@tonic-gate */ 8780Sstevel@tonic-gate 8790Sstevel@tonic-gate argbuf[0] = '\0'; 8800Sstevel@tonic-gate 8810Sstevel@tonic-gate if (printer->printer->options) { 8820Sstevel@tonic-gate char **tmp = printer->printer->options; 8830Sstevel@tonic-gate while(*tmp != NULL) { 8840Sstevel@tonic-gate STRLCAT(argbuf, sep, sizeof (argbuf)); 8850Sstevel@tonic-gate sep = " "; 8860Sstevel@tonic-gate STRLCAT(argbuf, *tmp++, sizeof (argbuf)); 8870Sstevel@tonic-gate } 8880Sstevel@tonic-gate } 8890Sstevel@tonic-gate 8900Sstevel@tonic-gate /* 8910Sstevel@tonic-gate * Do the administrator defined ``stty'' stuff before 8920Sstevel@tonic-gate * the user's -o options, to allow the user to override. 8930Sstevel@tonic-gate */ 8940Sstevel@tonic-gate if (printer->printer->stty) { 8950Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 8960Sstevel@tonic-gate sep = " "; 8970Sstevel@tonic-gate STRLCAT (argbuf, "stty='", sizeof (argbuf)); 8980Sstevel@tonic-gate STRLCAT (argbuf, printer->printer->stty, 8990Sstevel@tonic-gate sizeof (argbuf)); 9000Sstevel@tonic-gate STRLCAT (argbuf, "'", sizeof (argbuf)); 9010Sstevel@tonic-gate } 9020Sstevel@tonic-gate 9030Sstevel@tonic-gate /* 9040Sstevel@tonic-gate * Do all of the user's options except the cpi/lpi/etc. 9050Sstevel@tonic-gate * stuff, which is done separately. 9060Sstevel@tonic-gate */ 9070Sstevel@tonic-gate if (request->request->options) { 9080Sstevel@tonic-gate listp = dashos(request->request->options); 9090Sstevel@tonic-gate while (*listp) { 9100Sstevel@tonic-gate if ( 9110Sstevel@tonic-gate !STRNEQU(*listp, "cpi=", 4) 9120Sstevel@tonic-gate && !STRNEQU(*listp, "lpi=", 4) 9130Sstevel@tonic-gate && !STRNEQU(*listp, "width=", 6) 9140Sstevel@tonic-gate && !STRNEQU(*listp, "length=", 7) 9150Sstevel@tonic-gate ) { 9160Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9170Sstevel@tonic-gate sep = " "; 9180Sstevel@tonic-gate STRLCAT (argbuf, *listp, 9190Sstevel@tonic-gate sizeof (argbuf)); 9200Sstevel@tonic-gate } 9210Sstevel@tonic-gate listp++; 9220Sstevel@tonic-gate } 9230Sstevel@tonic-gate } 9240Sstevel@tonic-gate 9250Sstevel@tonic-gate /* 9260Sstevel@tonic-gate * The "pickfilter()" routine (from "validate()") 9270Sstevel@tonic-gate * stored the cpi/lpi/etc. stuff that should be 9280Sstevel@tonic-gate * used for this request. It chose form over user, 9290Sstevel@tonic-gate * and user over printer. 9300Sstevel@tonic-gate */ 9310Sstevel@tonic-gate if (request->cpi) { 9320Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9330Sstevel@tonic-gate sep = " "; 9340Sstevel@tonic-gate STRLCAT (argbuf, "cpi=", sizeof (argbuf)); 9350Sstevel@tonic-gate STRLCAT (argbuf, request->cpi, sizeof (argbuf)); 9360Sstevel@tonic-gate } 9370Sstevel@tonic-gate if (request->lpi) { 9380Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9390Sstevel@tonic-gate sep = " "; 9400Sstevel@tonic-gate STRLCAT (argbuf, "lpi=", sizeof (argbuf)); 9410Sstevel@tonic-gate STRLCAT (argbuf, request->lpi, sizeof (argbuf)); 9420Sstevel@tonic-gate } 9430Sstevel@tonic-gate if (request->pwid) { 9440Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9450Sstevel@tonic-gate sep = " "; 9460Sstevel@tonic-gate STRLCAT (argbuf, "width=", sizeof (argbuf)); 9470Sstevel@tonic-gate STRLCAT (argbuf, request->pwid, sizeof (argbuf)); 9480Sstevel@tonic-gate } 9490Sstevel@tonic-gate if (request->plen) { 9500Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9510Sstevel@tonic-gate sep = " "; 9520Sstevel@tonic-gate STRLCAT (argbuf, "length=", sizeof (argbuf)); 9530Sstevel@tonic-gate STRLCAT (argbuf, request->plen, sizeof (argbuf)); 9540Sstevel@tonic-gate } 9550Sstevel@tonic-gate 9560Sstevel@tonic-gate /* 9570Sstevel@tonic-gate * Do the ``raw'' bit last, to ensure it gets 9580Sstevel@tonic-gate * done. If the user doesn't want this, then he or 9590Sstevel@tonic-gate * she can do the correct thing using -o stty= 9600Sstevel@tonic-gate * and leaving out the -r option. 9610Sstevel@tonic-gate */ 9620Sstevel@tonic-gate if (request->request->actions & ACT_RAW) { 9630Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9640Sstevel@tonic-gate sep = " "; 9650Sstevel@tonic-gate STRLCAT (argbuf, "stty=-opost", sizeof (argbuf)); 9660Sstevel@tonic-gate } 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate 9690Sstevel@tonic-gate /* the "options" */ 9700Sstevel@tonic-gate av[ac++] = arg_string(UNTRUSTED, "%s", argbuf); 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate for (listp = file_list; *listp; listp++) 9730Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", *listp); 9740Sstevel@tonic-gate 9750Sstevel@tonic-gate (void)chfiles (file_list, procuid, procgid); 9760Sstevel@tonic-gate 9770Sstevel@tonic-gate break; 9780Sstevel@tonic-gate 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate case EX_SLOWF: 9810Sstevel@tonic-gate if (request->slow) 9820Sstevel@tonic-gate addenv(&envp, "FILTER", request->slow); 9830Sstevel@tonic-gate 984*11378SSonam.Gupta@Sun.COM procuid = request->secure->uid; 985*11378SSonam.Gupta@Sun.COM procgid = request->secure->gid; 986*11378SSonam.Gupta@Sun.COM 9870Sstevel@tonic-gate cp = _alloc_files( 9880Sstevel@tonic-gate lenlist(request->request->file_list), 9890Sstevel@tonic-gate getreqno(request->secure->req_id), 9903125Sjacobs procuid, procgid); 9910Sstevel@tonic-gate 9920Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", Lp_Slow_Filter); 9933204Sjacobs av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_Temp, cp); 9940Sstevel@tonic-gate for (listp = request->request->file_list; *listp; listp++) 9950Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", *listp); 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate (void)chfiles (request->request->file_list, procuid, procgid); 9980Sstevel@tonic-gate 9990Sstevel@tonic-gate #ifdef LP_USE_PAPI_ATTR 10000Sstevel@tonic-gate /* 10010Sstevel@tonic-gate * Check if the PAPI job attribute file exists, if it does 10020Sstevel@tonic-gate * pass the file's pathname to the slow-filters in an 10030Sstevel@tonic-gate * environment variable. Note: this file is created when 10040Sstevel@tonic-gate * print jobs are submitted via the PAPI interface. 10050Sstevel@tonic-gate */ 10060Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s-%s", 10070Sstevel@tonic-gate getreqno(request->secure->req_id), LP_PAPIATTRNAME); 10083125Sjacobs path = makepath(Lp_Temp, tmpName, (char *)0); 10090Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 10100Sstevel@tonic-gate { 10110Sstevel@tonic-gate /* 10120Sstevel@tonic-gate * IPP job attribute file exists for this job so 10130Sstevel@tonic-gate * set the environment variable 10140Sstevel@tonic-gate */ 10150Sstevel@tonic-gate addenv(&envp, "ATTRPATH", path); 10160Sstevel@tonic-gate } 10170Sstevel@tonic-gate Free(path); 10180Sstevel@tonic-gate 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate /* 10210Sstevel@tonic-gate * now set environment variable for the printer's PostScript 10220Sstevel@tonic-gate * Printer Description (PPD) file, this is used by the filter 10230Sstevel@tonic-gate * when forming the print data for this printer. 10240Sstevel@tonic-gate */ 10250Sstevel@tonic-gate if ((request->printer != NULL) && 10260Sstevel@tonic-gate (request->printer->printer != NULL) && 10270Sstevel@tonic-gate (request->printer->printer->name != NULL)) 10280Sstevel@tonic-gate { 10290Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s.ppd", 10300Sstevel@tonic-gate request->printer->printer->name); 10310Sstevel@tonic-gate path = makepath(ETCDIR, "ppd", tmpName, (char *)0); 10320Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 10330Sstevel@tonic-gate { 10340Sstevel@tonic-gate addenv(&envp, "PPD", path); 10350Sstevel@tonic-gate } 10360Sstevel@tonic-gate Free(path); 10370Sstevel@tonic-gate } 10380Sstevel@tonic-gate #endif 10390Sstevel@tonic-gate break; 10400Sstevel@tonic-gate 10410Sstevel@tonic-gate case EX_ALERT: 10420Sstevel@tonic-gate procuid = Lp_Uid; 10430Sstevel@tonic-gate procgid = Lp_Gid; 10440Sstevel@tonic-gate (void)Chown (printer->alert->msgfile, procuid, procgid); 10450Sstevel@tonic-gate 10460Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers, 10470Sstevel@tonic-gate printer->printer->name, ALERTSHFILE); 10480Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); 10490Sstevel@tonic-gate 10500Sstevel@tonic-gate break; 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate case EX_PALERT: 10530Sstevel@tonic-gate procuid = Lp_Uid; 10540Sstevel@tonic-gate procgid = Lp_Gid; 10550Sstevel@tonic-gate (void)Chown (pwheel->alert->msgfile, procuid, procgid); 10560Sstevel@tonic-gate 10570Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_PrintWheels, 10580Sstevel@tonic-gate pwheel->pwheel->name, ALERTSHFILE); 10590Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); 10600Sstevel@tonic-gate 10610Sstevel@tonic-gate break; 10620Sstevel@tonic-gate 10630Sstevel@tonic-gate case EX_FALERT: 10640Sstevel@tonic-gate procuid = Lp_Uid; 10650Sstevel@tonic-gate procgid = Lp_Gid; 10660Sstevel@tonic-gate (void)Chown (form->alert->msgfile, procuid, procgid); 10670Sstevel@tonic-gate 10680Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms, 10690Sstevel@tonic-gate form->form->name, ALERTSHFILE); 10700Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); 10710Sstevel@tonic-gate 10720Sstevel@tonic-gate break; 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate case EX_FORM_MESSAGE: 10750Sstevel@tonic-gate procuid = Lp_Uid; 10760Sstevel@tonic-gate procgid = Lp_Gid; 10770Sstevel@tonic-gate 10780Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/form", Lp_A_Faults); 10790Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", form->form->name); 10800Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", time_buf); 10810Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms, 10820Sstevel@tonic-gate form->form->name, FORMMESSAGEFILE); 10830Sstevel@tonic-gate 10840Sstevel@tonic-gate break; 10850Sstevel@tonic-gate 10860Sstevel@tonic-gate case EX_FAULT_MESSAGE: 10870Sstevel@tonic-gate procuid = Lp_Uid; 10880Sstevel@tonic-gate procgid = Lp_Gid; 10890Sstevel@tonic-gate 10900Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/printer", Lp_A_Faults); 10910Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printerNameToShow); 10920Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", time_buf); 10930Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers, 10940Sstevel@tonic-gate printerName, FAULTMESSAGEFILE); 10950Sstevel@tonic-gate 10960Sstevel@tonic-gate break; 10970Sstevel@tonic-gate 10980Sstevel@tonic-gate case EX_NOTIFY: 10990Sstevel@tonic-gate if (request->request->alert) { 1100*11378SSonam.Gupta@Sun.COM procuid = request->secure->uid; 1101*11378SSonam.Gupta@Sun.COM procgid = request->secure->gid; 1102*11378SSonam.Gupta@Sun.COM 11030Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", 11040Sstevel@tonic-gate request->request->alert); 11050Sstevel@tonic-gate } else { 11063125Sjacobs char *user = strdup(request->request->user); 11070Sstevel@tonic-gate clean_string(user); 11081676Sjpk slabel = request->secure->slabel; 11090Sstevel@tonic-gate 11103125Sjacobs if (request->request->actions & ACT_WRITE) { 11110Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", BINWRITE); 11120Sstevel@tonic-gate snprintf(argbuf, sizeof (argbuf), 11130Sstevel@tonic-gate "%s %s || %s %s", 11140Sstevel@tonic-gate BINWRITE, user, 11150Sstevel@tonic-gate BINMAIL, user 11160Sstevel@tonic-gate ); 11170Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "/bin/sh"); 11180Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "-c"); 11190Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", argbuf); 11201676Sjpk } else if ((getzoneid() == GLOBAL_ZONEID) && 11211676Sjpk is_system_labeled() && (slabel != NULL)) { 11221676Sjpk /* 11231676Sjpk * If in the global zone and the system is 11241676Sjpk * labeled, mail is handled via a local 11251676Sjpk * labeled zone that is the same label as 11261676Sjpk * the request. 11271676Sjpk */ 11281676Sjpk if ((mail_zonename = 11291676Sjpk get_labeled_zonename(slabel)) == 11301676Sjpk (char *)-1) { 11311676Sjpk /* 11321676Sjpk * Cannot find labeled zone, just 11331676Sjpk * return 0. 11341676Sjpk */ 11351676Sjpk return(0); 11361676Sjpk } 11371676Sjpk } 11381676Sjpk if (mail_zonename == NULL) { 11391676Sjpk procuid = Lp_Uid; 11401676Sjpk procgid = Lp_Gid; 11410Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", BINMAIL); 11420Sstevel@tonic-gate av[ac++] = arg_string(UNTRUSTED, "%s", user); 11431676Sjpk } else { 11441676Sjpk procuid = getuid(); 11451676Sjpk procgid = getgid(); 11461676Sjpk av[ac++] = arg_string(TRUSTED, "%s", 11471676Sjpk "/usr/sbin/zlogin"); 11481676Sjpk av[ac++] = arg_string(TRUSTED, "%s", 11491676Sjpk mail_zonename); 11501676Sjpk av[ac++] = arg_string(TRUSTED, "%s", 11511676Sjpk BINMAIL); 11521676Sjpk av[ac++] = arg_string(UNTRUSTED, "%s", 11531676Sjpk user); 11541676Sjpk Free(mail_zonename); 11550Sstevel@tonic-gate } 11560Sstevel@tonic-gate 11570Sstevel@tonic-gate free(user); 11580Sstevel@tonic-gate } 11590Sstevel@tonic-gate break; 11600Sstevel@tonic-gate } 11610Sstevel@tonic-gate 11620Sstevel@tonic-gate av[ac++] = NULL; 11630Sstevel@tonic-gate 11640Sstevel@tonic-gate Fork2 (); 11650Sstevel@tonic-gate /* only the child returns */ 11660Sstevel@tonic-gate 11670Sstevel@tonic-gate /* 11680Sstevel@tonic-gate * Correctly set up the supplemental group list 11690Sstevel@tonic-gate * for proper file access (before execl the interface program) 11700Sstevel@tonic-gate */ 11710Sstevel@tonic-gate 11720Sstevel@tonic-gate pwp = getpwuid(procuid); 11730Sstevel@tonic-gate if (pwp == NULL) { 11740Sstevel@tonic-gate note("getpwuid(%d) call failed\n", procuid); 11750Sstevel@tonic-gate } else if (initgroups(pwp->pw_name, procgid) < 0) { 11760Sstevel@tonic-gate note("initgroups() call failed %d\n", errno); 11770Sstevel@tonic-gate } 11780Sstevel@tonic-gate 11790Sstevel@tonic-gate setgid (procgid); 11800Sstevel@tonic-gate setuid (procuid); 11810Sstevel@tonic-gate 11820Sstevel@tonic-gate /* 11830Sstevel@tonic-gate * The shell doesn't allow the "trap" builtin to set a trap 11840Sstevel@tonic-gate * for a signal ignored when the shell is started. Thus, don't 11850Sstevel@tonic-gate * turn off signals in the last child! 11860Sstevel@tonic-gate */ 11870Sstevel@tonic-gate 11883125Sjacobs #ifdef DEBUG 11890Sstevel@tonic-gate for (i = 0; av[i] != NULL; i++) 11903125Sjacobs note("exec(%s): av[%d] = %s", _exec_name(type), i, av[i]); 11911676Sjpk for (i = 0; envp[i] != NULL; i++) 11923125Sjacobs note("exec(%s): envp[%d] = %s", _exec_name(type), i, envp[i]); 11933125Sjacobs #endif 11940Sstevel@tonic-gate 11950Sstevel@tonic-gate execvpe(av[0], av, envp); 11960Sstevel@tonic-gate Done (EXEC_EXIT_NEXEC, errno); 11970Sstevel@tonic-gate /*NOTREACHED*/ 1198320Sceastha return (0); 11990Sstevel@tonic-gate } 12000Sstevel@tonic-gate 12010Sstevel@tonic-gate /** 12020Sstevel@tonic-gate ** addenv() - ADD A VARIABLE TO THE ENVIRONMENT 12030Sstevel@tonic-gate **/ 12040Sstevel@tonic-gate 12050Sstevel@tonic-gate static void 12060Sstevel@tonic-gate addenv(char ***envp, char *name, char *value) 12070Sstevel@tonic-gate { 12080Sstevel@tonic-gate register char * cp; 12090Sstevel@tonic-gate 12100Sstevel@tonic-gate if ((name == NULL) || (value == NULL)) 12110Sstevel@tonic-gate return; 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate if ((cp = makestr(name, "=", value, (char *)0))) 12140Sstevel@tonic-gate addlist(envp, cp); 12150Sstevel@tonic-gate return; 12160Sstevel@tonic-gate } 12170Sstevel@tonic-gate 12180Sstevel@tonic-gate /** 12190Sstevel@tonic-gate ** Fork1() - FORK FIRST CHILD, SET UP CONNECTION TO IT 12200Sstevel@tonic-gate **/ 12210Sstevel@tonic-gate 12220Sstevel@tonic-gate static int 12230Sstevel@tonic-gate Fork1(EXEC *ep) 12240Sstevel@tonic-gate { 12250Sstevel@tonic-gate int pid; 12260Sstevel@tonic-gate int fds[2]; 12270Sstevel@tonic-gate 12280Sstevel@tonic-gate if (pipe(fds) == -1) { 12290Sstevel@tonic-gate note("Failed to create pipe for child process (%s).\n", PERROR); 12300Sstevel@tonic-gate errno = EAGAIN ; 12310Sstevel@tonic-gate return(-1); 12320Sstevel@tonic-gate } 12330Sstevel@tonic-gate 12340Sstevel@tonic-gate ep->md = mconnect((char *)0, fds[0], fds[1]); 12350Sstevel@tonic-gate 12360Sstevel@tonic-gate switch (pid = fork()) { 12370Sstevel@tonic-gate 12380Sstevel@tonic-gate case -1: 12390Sstevel@tonic-gate mdisconnect(ep->md); 12400Sstevel@tonic-gate close(fds[0]); 12410Sstevel@tonic-gate close(fds[1]); 12420Sstevel@tonic-gate ep->md = 0; 12430Sstevel@tonic-gate return (-1); 12440Sstevel@tonic-gate 12450Sstevel@tonic-gate case 0: 12460Sstevel@tonic-gate ChildMd = mconnect(NULL, fds[1], fds[1]); 12470Sstevel@tonic-gate return (0); 12480Sstevel@tonic-gate 12490Sstevel@tonic-gate default: 12500Sstevel@tonic-gate mlistenadd(ep->md, POLLIN); 12510Sstevel@tonic-gate return (pid); 12520Sstevel@tonic-gate } 12530Sstevel@tonic-gate } 12540Sstevel@tonic-gate 12550Sstevel@tonic-gate /** 12560Sstevel@tonic-gate ** Fork2() - FORK SECOND CHILD AND WAIT FOR IT 12570Sstevel@tonic-gate **/ 12580Sstevel@tonic-gate 12590Sstevel@tonic-gate static void 12600Sstevel@tonic-gate Fork2(void) 12610Sstevel@tonic-gate { 12620Sstevel@tonic-gate switch ((ChildPid = fork())) { 12630Sstevel@tonic-gate 12640Sstevel@tonic-gate case -1: 12650Sstevel@tonic-gate Done (EXEC_EXIT_NFORK, errno); 12660Sstevel@tonic-gate /*NOTREACHED*/ 12670Sstevel@tonic-gate 12680Sstevel@tonic-gate case 0: 12690Sstevel@tonic-gate return; 12700Sstevel@tonic-gate 12710Sstevel@tonic-gate default: 12720Sstevel@tonic-gate /* 12730Sstevel@tonic-gate * Delay calling "ignore_fault_signals()" as long 12740Sstevel@tonic-gate * as possible, to give the child a chance to exec 12750Sstevel@tonic-gate * the interface program and turn on traps. 12760Sstevel@tonic-gate */ 12770Sstevel@tonic-gate 12780Sstevel@tonic-gate cool_heels (); 12790Sstevel@tonic-gate /*NOTREACHED*/ 12800Sstevel@tonic-gate 12810Sstevel@tonic-gate } 12820Sstevel@tonic-gate } 12830Sstevel@tonic-gate 12840Sstevel@tonic-gate 12850Sstevel@tonic-gate /** 12860Sstevel@tonic-gate ** cool_heels() - WAIT FOR CHILD TO "DIE" 12870Sstevel@tonic-gate **/ 12880Sstevel@tonic-gate 12890Sstevel@tonic-gate static void 12900Sstevel@tonic-gate cool_heels(void) 12910Sstevel@tonic-gate { 12920Sstevel@tonic-gate int status; 12930Sstevel@tonic-gate 12940Sstevel@tonic-gate /* 12950Sstevel@tonic-gate * At this point our only job is to wait for the child process. 12960Sstevel@tonic-gate * If we hang out for a bit longer, that's okay. 12970Sstevel@tonic-gate * By delaying before turning off the fault signals, 12980Sstevel@tonic-gate * we increase the chance that the child process has completed 12990Sstevel@tonic-gate * its exec and has turned on the fault traps. Nonetheless, 13000Sstevel@tonic-gate * we can't guarantee a zero chance of missing a fault. 13010Sstevel@tonic-gate * (We don't want to keep trapping the signals because the 13020Sstevel@tonic-gate * interface program is likely to have a better way to handle 13030Sstevel@tonic-gate * them; this process provides only rudimentary handling.) 13040Sstevel@tonic-gate * 13050Sstevel@tonic-gate * Note that on a very busy system, or with a very fast interface 13060Sstevel@tonic-gate * program, the tables could be turned: Our sleep below (coupled 13070Sstevel@tonic-gate * with a delay in the kernel scheduling us) may cause us to 13080Sstevel@tonic-gate * detect the fault instead of the interface program. 13090Sstevel@tonic-gate * 13100Sstevel@tonic-gate * What we need is a way to synchronize with the child process. 13110Sstevel@tonic-gate */ 13120Sstevel@tonic-gate sleep (1); 13130Sstevel@tonic-gate ignore_fault_signals (); 13140Sstevel@tonic-gate 13150Sstevel@tonic-gate WaitedChildPid = 0; 13160Sstevel@tonic-gate while ((WaitedChildPid = wait(&status)) != ChildPid) 13170Sstevel@tonic-gate ; 13180Sstevel@tonic-gate 13190Sstevel@tonic-gate if ( 13200Sstevel@tonic-gate EXITED(status) > EXEC_EXIT_USER 13210Sstevel@tonic-gate && EXITED(status) != EXEC_EXIT_FAULT 13220Sstevel@tonic-gate ) 13230Sstevel@tonic-gate Done (EXEC_EXIT_EXIT, EXITED(status)); 13240Sstevel@tonic-gate 13250Sstevel@tonic-gate done (status, 0); /* Don't use Done() */ 13260Sstevel@tonic-gate /*NOTREACHED*/ 13270Sstevel@tonic-gate } 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate 13300Sstevel@tonic-gate /** 13310Sstevel@tonic-gate ** trap_fault_signals() - TRAP SIGNALS THAT CAN OCCUR ON PRINTER FAULT 13320Sstevel@tonic-gate ** ignore_fault_signals() - IGNORE SAME 13330Sstevel@tonic-gate **/ 13340Sstevel@tonic-gate 13350Sstevel@tonic-gate static void 13360Sstevel@tonic-gate trap_fault_signals(void) 13370Sstevel@tonic-gate { 13380Sstevel@tonic-gate signal (SIGHUP, sigtrap); 13390Sstevel@tonic-gate signal (SIGINT, sigtrap); 13400Sstevel@tonic-gate signal (SIGQUIT, sigtrap); 13410Sstevel@tonic-gate signal (SIGPIPE, sigtrap); 13420Sstevel@tonic-gate return; 13430Sstevel@tonic-gate } 13440Sstevel@tonic-gate 13450Sstevel@tonic-gate static void 13460Sstevel@tonic-gate ignore_fault_signals(void) 13470Sstevel@tonic-gate { 13480Sstevel@tonic-gate signal (SIGHUP, SIG_IGN); 13490Sstevel@tonic-gate signal (SIGINT, SIG_IGN); 13500Sstevel@tonic-gate signal (SIGQUIT, SIG_IGN); 13510Sstevel@tonic-gate signal (SIGPIPE, SIG_IGN); 13520Sstevel@tonic-gate return; 13530Sstevel@tonic-gate } 13540Sstevel@tonic-gate 13550Sstevel@tonic-gate /** 13560Sstevel@tonic-gate ** sigtrap() - TRAP VARIOUS SIGNALS 13570Sstevel@tonic-gate **/ 13580Sstevel@tonic-gate 13590Sstevel@tonic-gate static void 13600Sstevel@tonic-gate sigtrap(int sig) 13610Sstevel@tonic-gate { 13620Sstevel@tonic-gate signal (sig, SIG_IGN); 13630Sstevel@tonic-gate switch (sig) { 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate case SIGHUP: 13660Sstevel@tonic-gate Done (EXEC_EXIT_HUP, 0); 13670Sstevel@tonic-gate /*NOTREACHED*/ 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate case SIGQUIT: 13700Sstevel@tonic-gate case SIGINT: 13710Sstevel@tonic-gate Done (EXEC_EXIT_INTR, 0); 13720Sstevel@tonic-gate /*NOTREACHED*/ 13730Sstevel@tonic-gate 13740Sstevel@tonic-gate case SIGPIPE: 13750Sstevel@tonic-gate Done (EXEC_EXIT_PIPE, 0); 13760Sstevel@tonic-gate /*NOTREACHED*/ 13770Sstevel@tonic-gate 13780Sstevel@tonic-gate case SIGTERM: 13790Sstevel@tonic-gate /* 13800Sstevel@tonic-gate * If we were killed with SIGTERM, it should have been 13810Sstevel@tonic-gate * via the Spooler who should have killed the entire 13820Sstevel@tonic-gate * process group. We have to wait for the children, 13830Sstevel@tonic-gate * since we're their parent, but WE MAY HAVE WAITED 13840Sstevel@tonic-gate * FOR THEM ALREADY (in cool_heels()). 13850Sstevel@tonic-gate */ 13860Sstevel@tonic-gate if (ChildPid != WaitedChildPid) { 13870Sstevel@tonic-gate register int cpid; 13880Sstevel@tonic-gate 13890Sstevel@tonic-gate while ( 13900Sstevel@tonic-gate (cpid = wait((int *)0)) != ChildPid 13910Sstevel@tonic-gate && (cpid != -1 || errno != ECHILD) 13920Sstevel@tonic-gate ) 13930Sstevel@tonic-gate ; 13940Sstevel@tonic-gate } 13950Sstevel@tonic-gate 13960Sstevel@tonic-gate /* 13970Sstevel@tonic-gate * We can't rely on getting SIGTERM back in the wait() 13980Sstevel@tonic-gate * above, because, for instance, some shells trap SIGTERM 13990Sstevel@tonic-gate * and exit instead. Thus we force it. 14000Sstevel@tonic-gate */ 14010Sstevel@tonic-gate done (SIGTERM, 0); /* Don't use Done() */ 14020Sstevel@tonic-gate /*NOTREACHED*/ 14030Sstevel@tonic-gate } 14040Sstevel@tonic-gate } 14050Sstevel@tonic-gate 14060Sstevel@tonic-gate /** 14070Sstevel@tonic-gate ** done() - TELL SPOOLER THIS CHILD IS DONE 14080Sstevel@tonic-gate **/ 14090Sstevel@tonic-gate 14100Sstevel@tonic-gate static void 14110Sstevel@tonic-gate done(int status, int err) 14120Sstevel@tonic-gate { 14130Sstevel@tonic-gate if (do_undial) 14140Sstevel@tonic-gate undial (1); 14150Sstevel@tonic-gate 14163125Sjacobs mputm (ChildMd, S_CHILD_DONE, key, status, err); 14170Sstevel@tonic-gate mdisconnect (ChildMd); 14180Sstevel@tonic-gate 14190Sstevel@tonic-gate exit (0); 14200Sstevel@tonic-gate /*NOTREACHED*/ 14210Sstevel@tonic-gate } 14220Sstevel@tonic-gate 14230Sstevel@tonic-gate /** 14240Sstevel@tonic-gate ** child_mallocfail() 14250Sstevel@tonic-gate **/ 14260Sstevel@tonic-gate 14270Sstevel@tonic-gate static void 14280Sstevel@tonic-gate child_mallocfail(void) 14290Sstevel@tonic-gate { 14300Sstevel@tonic-gate Done (EXEC_EXIT_NOMEM, ENOMEM); 14310Sstevel@tonic-gate } 1432