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 /* 23*10460SSonam.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; 316*10460SSonam.Gupta@Sun.COM int setid = 1; 317*10460SSonam.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 5643125Sjacobs if (strchr (request->request->user, '@')) 5650Sstevel@tonic-gate { 5660Sstevel@tonic-gate procuid = Lp_Uid; 5670Sstevel@tonic-gate procgid = Lp_Gid; 5680Sstevel@tonic-gate } 5690Sstevel@tonic-gate else 5700Sstevel@tonic-gate { 5710Sstevel@tonic-gate procuid = request->secure->uid; 5720Sstevel@tonic-gate procgid = request->secure->gid; 5730Sstevel@tonic-gate } 5740Sstevel@tonic-gate if (printer->printer->dial_info) 5750Sstevel@tonic-gate { 5760Sstevel@tonic-gate ret = open_dialup(request->printer_type, 5770Sstevel@tonic-gate printer->printer); 5780Sstevel@tonic-gate if (ret == 0) 5790Sstevel@tonic-gate do_undial = 1; 5800Sstevel@tonic-gate } 5810Sstevel@tonic-gate else 5820Sstevel@tonic-gate { 5830Sstevel@tonic-gate ret = open_direct(request->printer_type, 5840Sstevel@tonic-gate printer->printer); 5850Sstevel@tonic-gate do_undial = 0; 5860Sstevel@tonic-gate /* this is a URI */ 5870Sstevel@tonic-gate if (is_printer_uri(printer->printer->device) == 0) 5880Sstevel@tonic-gate addenv(&envp, "DEVICE_URI", 5890Sstevel@tonic-gate printer->printer->device); 5900Sstevel@tonic-gate } 5910Sstevel@tonic-gate addenv(&envp, "DEVICE_URI", 5920Sstevel@tonic-gate printer->printer->device); 5930Sstevel@tonic-gate if (ret != 0) 5940Sstevel@tonic-gate Done (ret, errno); 5950Sstevel@tonic-gate 5960Sstevel@tonic-gate if (!(request->request->outcome & RS_FILTERED)) 5970Sstevel@tonic-gate file_list = request->request->file_list; 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate else { 6000Sstevel@tonic-gate register int count = 0; 6010Sstevel@tonic-gate register char * num = BIGGEST_REQID_S; 6020Sstevel@tonic-gate register char * prefix; 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate prefix = makestr( 6053125Sjacobs Lp_Temp, 6060Sstevel@tonic-gate "/F", 6070Sstevel@tonic-gate getreqno(request->secure->req_id), 6080Sstevel@tonic-gate "-", 6090Sstevel@tonic-gate (char *)0 6100Sstevel@tonic-gate ); 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate file_list = (char **)Malloc( 6130Sstevel@tonic-gate (lenlist(request->request->file_list) + 1) 6140Sstevel@tonic-gate * sizeof(char *) 6150Sstevel@tonic-gate ); 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate for ( 6180Sstevel@tonic-gate listp = request->request->file_list; 6190Sstevel@tonic-gate *listp; 6200Sstevel@tonic-gate listp++ 6210Sstevel@tonic-gate ) { 6220Sstevel@tonic-gate sprintf (num, "%d", count + 1); 6230Sstevel@tonic-gate file_list[count] = makestr( 6240Sstevel@tonic-gate prefix, 6250Sstevel@tonic-gate num, 6260Sstevel@tonic-gate (char *)0 6270Sstevel@tonic-gate ); 6280Sstevel@tonic-gate count++; 6290Sstevel@tonic-gate } 6300Sstevel@tonic-gate file_list[count] = 0; 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate #ifdef LP_USE_PAPI_ATTR 6340Sstevel@tonic-gate /* 6350Sstevel@tonic-gate * Check if the PAPI job attribute file exists, if it does 6360Sstevel@tonic-gate * pass the file's pathname to the printer interface script 6370Sstevel@tonic-gate * in an environment variable. This file is created when 6380Sstevel@tonic-gate * print jobs are submitted via the PAPI interface. 6390Sstevel@tonic-gate */ 6400Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s-%s", 6410Sstevel@tonic-gate getreqno(request->secure->req_id), LP_PAPIATTRNAME); 6423125Sjacobs path = makepath(Lp_Temp, tmpName, (char *)0); 6430Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 6440Sstevel@tonic-gate { 6450Sstevel@tonic-gate /* 6460Sstevel@tonic-gate * IPP job attribute file exists for this job so 6470Sstevel@tonic-gate * set the environment variable 6480Sstevel@tonic-gate */ 6490Sstevel@tonic-gate addenv(&envp, "ATTRPATH", path); 6500Sstevel@tonic-gate } 6510Sstevel@tonic-gate Free(path); 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate /* 6540Sstevel@tonic-gate * now set environment variable for the printer's PostScript 6550Sstevel@tonic-gate * Printer Description (PPD) file, this is used by the filter 6560Sstevel@tonic-gate * when forming the print data for this printer. 6570Sstevel@tonic-gate */ 6580Sstevel@tonic-gate if ((request->printer != NULL) && 6590Sstevel@tonic-gate (request->printer->printer != NULL) && 6600Sstevel@tonic-gate (request->printer->printer->name != NULL)) 6610Sstevel@tonic-gate { 6620Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s.ppd", 6630Sstevel@tonic-gate request->printer->printer->name); 6640Sstevel@tonic-gate path = makepath(ETCDIR, "ppd", tmpName, (char *)0); 6650Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 6660Sstevel@tonic-gate { 6670Sstevel@tonic-gate addenv(&envp, "PPD", path); 6680Sstevel@tonic-gate } 6690Sstevel@tonic-gate Free(path); 6700Sstevel@tonic-gate } 6710Sstevel@tonic-gate #endif 6720Sstevel@tonic-gate 6730Sstevel@tonic-gate if (request->printer_type) 6740Sstevel@tonic-gate addenv(&envp, "TERM", request->printer_type); 6750Sstevel@tonic-gate 6760Sstevel@tonic-gate if (!(printer->printer->daisy)) { 6770Sstevel@tonic-gate register char * chset = 0; 6780Sstevel@tonic-gate register char * csp; 6790Sstevel@tonic-gate 6800Sstevel@tonic-gate if ( 6810Sstevel@tonic-gate request->form 6820Sstevel@tonic-gate && request->form->form->chset 6830Sstevel@tonic-gate && request->form->form->mandatory 6840Sstevel@tonic-gate && !STREQU(NAME_ANY, request->form->form->chset) 6850Sstevel@tonic-gate ) 6860Sstevel@tonic-gate chset = request->form->form->chset; 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate else if ( 6890Sstevel@tonic-gate request->request->charset 6900Sstevel@tonic-gate && !STREQU(NAME_ANY, request->request->charset) 6910Sstevel@tonic-gate ) 6920Sstevel@tonic-gate chset = request->request->charset; 6930Sstevel@tonic-gate 6940Sstevel@tonic-gate if (chset) { 6950Sstevel@tonic-gate csp = search_cslist( 6960Sstevel@tonic-gate chset, 6970Sstevel@tonic-gate printer->printer->char_sets 6980Sstevel@tonic-gate ); 6990Sstevel@tonic-gate 7000Sstevel@tonic-gate /* 7010Sstevel@tonic-gate * The "strtok()" below wrecks the string 7020Sstevel@tonic-gate * for future use, but this is a child 7030Sstevel@tonic-gate * process where it won't be needed again. 7040Sstevel@tonic-gate */ 7050Sstevel@tonic-gate addenv (&envp, "CHARSET", 7060Sstevel@tonic-gate (csp? strtok(csp, "=") : chset) 7070Sstevel@tonic-gate ); 7080Sstevel@tonic-gate } 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate if (request->fast) 7120Sstevel@tonic-gate addenv(&envp, "FILTER", request->fast); 7130Sstevel@tonic-gate 7140Sstevel@tonic-gate /* 7151676Sjpk * Add the sensitivity label to the environment for 7161676Sjpk * banner page and header/footer processing 7171676Sjpk */ 7181676Sjpk 7191676Sjpk if (is_system_labeled() && request->secure->slabel != NULL) 7201676Sjpk addenv(&envp, "SLABEL", request->secure->slabel); 7211676Sjpk 7221676Sjpk /* 7230Sstevel@tonic-gate * Add the system name to the user name (ala system!user) 7240Sstevel@tonic-gate * unless it is already there. RFS users may have trouble 7250Sstevel@tonic-gate * here, sorry! 7260Sstevel@tonic-gate */ 7270Sstevel@tonic-gate cp = strchr(request->secure->user, '@'); 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate allTraysWithForm(printer, request->form); 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate /* 7320Sstevel@tonic-gate * Fix for 4137389 7330Sstevel@tonic-gate * Remove double quotes from title string. 7340Sstevel@tonic-gate */ 7350Sstevel@tonic-gate fr_flg = 1; 7360Sstevel@tonic-gate clean_title = strdup(NB(request->request->title)); 7370Sstevel@tonic-gate if (clean_title == NULL) { 7380Sstevel@tonic-gate /* 7390Sstevel@tonic-gate * strdup failed. We're probably hosed 7400Sstevel@tonic-gate * but try setting clean_title 7410Sstevel@tonic-gate * to original title and continuing. 7420Sstevel@tonic-gate */ 7430Sstevel@tonic-gate clean_title = NB(request->request->title); 7440Sstevel@tonic-gate fr_flg = 0; 7450Sstevel@tonic-gate } else if (strcmp(clean_title, "") != 0) { 7460Sstevel@tonic-gate char *ct_p; 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate for (ct_p = clean_title; *ct_p != NULL; ct_p++) { 7490Sstevel@tonic-gate if (*ct_p == '"') 7500Sstevel@tonic-gate *ct_p = ' '; 7510Sstevel@tonic-gate } 7520Sstevel@tonic-gate } 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_A_Interfaces, 7550Sstevel@tonic-gate printer->printer->name); 756*10460SSonam.Gupta@Sun.COM /* 757*10460SSonam.Gupta@Sun.COM * Read the options field of the request 758*10460SSonam.Gupta@Sun.COM * In case of remote lpd request 759*10460SSonam.Gupta@Sun.COM * the options field will have 760*10460SSonam.Gupta@Sun.COM * job-id-requested. This is the 761*10460SSonam.Gupta@Sun.COM * id sent by the client 762*10460SSonam.Gupta@Sun.COM */ 763*10460SSonam.Gupta@Sun.COM if (request->request->options != NULL) { 764*10460SSonam.Gupta@Sun.COM char *options = NULL, *temp = NULL; 765*10460SSonam.Gupta@Sun.COM options = temp = strdup(request->request->options); 766*10460SSonam.Gupta@Sun.COM 767*10460SSonam.Gupta@Sun.COM /* 768*10460SSonam.Gupta@Sun.COM * Search for job-id-requested in 769*10460SSonam.Gupta@Sun.COM * options string 770*10460SSonam.Gupta@Sun.COM */ 771*10460SSonam.Gupta@Sun.COM options = strstr(options, "job-id-requested"); 772*10460SSonam.Gupta@Sun.COM if (options != NULL) { 773*10460SSonam.Gupta@Sun.COM /* 774*10460SSonam.Gupta@Sun.COM * Extract the ridno from the string 775*10460SSonam.Gupta@Sun.COM * job-id-requested=xxx 776*10460SSonam.Gupta@Sun.COM * In this case ridno = xxx 777*10460SSonam.Gupta@Sun.COM */ 778*10460SSonam.Gupta@Sun.COM if (STRNEQU(options, "job-id-requested=", 17)) { 779*10460SSonam.Gupta@Sun.COM ridno = strdup(options + 17); 780*10460SSonam.Gupta@Sun.COM if (ridno != NULL) 781*10460SSonam.Gupta@Sun.COM /* 782*10460SSonam.Gupta@Sun.COM * Read job-id-requested 783*10460SSonam.Gupta@Sun.COM * successfully 784*10460SSonam.Gupta@Sun.COM */ 785*10460SSonam.Gupta@Sun.COM setid = 0; 786*10460SSonam.Gupta@Sun.COM else 787*10460SSonam.Gupta@Sun.COM /* 788*10460SSonam.Gupta@Sun.COM * could not read 789*10460SSonam.Gupta@Sun.COM * ridno from the string 790*10460SSonam.Gupta@Sun.COM * job-id-requested=xxx 791*10460SSonam.Gupta@Sun.COM */ 792*10460SSonam.Gupta@Sun.COM setid = 1; 793*10460SSonam.Gupta@Sun.COM } else 794*10460SSonam.Gupta@Sun.COM /* 795*10460SSonam.Gupta@Sun.COM * could not read 796*10460SSonam.Gupta@Sun.COM * ridno from the string 797*10460SSonam.Gupta@Sun.COM * job-id-requested=xxx 798*10460SSonam.Gupta@Sun.COM */ 799*10460SSonam.Gupta@Sun.COM setid = 1; 800*10460SSonam.Gupta@Sun.COM } else 801*10460SSonam.Gupta@Sun.COM /* 802*10460SSonam.Gupta@Sun.COM * No job-id-requested in 803*10460SSonam.Gupta@Sun.COM * request options 804*10460SSonam.Gupta@Sun.COM */ 805*10460SSonam.Gupta@Sun.COM setid = 1; 806*10460SSonam.Gupta@Sun.COM 807*10460SSonam.Gupta@Sun.COM if (temp != NULL) 808*10460SSonam.Gupta@Sun.COM free(temp); 809*10460SSonam.Gupta@Sun.COM 810*10460SSonam.Gupta@Sun.COM } else 811*10460SSonam.Gupta@Sun.COM /* 812*10460SSonam.Gupta@Sun.COM * options field in request structure 813*10460SSonam.Gupta@Sun.COM * not set 814*10460SSonam.Gupta@Sun.COM */ 815*10460SSonam.Gupta@Sun.COM setid = 1; 816*10460SSonam.Gupta@Sun.COM 817*10460SSonam.Gupta@Sun.COM 818*10460SSonam.Gupta@Sun.COM /* 819*10460SSonam.Gupta@Sun.COM * setid = 1 means the job-id-requested attribute 820*10460SSonam.Gupta@Sun.COM * is not set so read the request->secure->req_id 821*10460SSonam.Gupta@Sun.COM */ 822*10460SSonam.Gupta@Sun.COM if (setid) 823*10460SSonam.Gupta@Sun.COM av[ac++] = arg_string(TRUSTED, "%s", 824*10460SSonam.Gupta@Sun.COM request->secure->req_id); 825*10460SSonam.Gupta@Sun.COM else { 826*10460SSonam.Gupta@Sun.COM /* 827*10460SSonam.Gupta@Sun.COM * From request->secure->req_id extract the 828*10460SSonam.Gupta@Sun.COM * printer-name. 829*10460SSonam.Gupta@Sun.COM * request->secure->req_id = <printer-name>-<req_id> 830*10460SSonam.Gupta@Sun.COM * The final req-id will be 831*10460SSonam.Gupta@Sun.COM * <printer-name>-<ridno> 832*10460SSonam.Gupta@Sun.COM */ 833*10460SSonam.Gupta@Sun.COM char *r1 = NULL, *r2 = NULL, *tmp = NULL; 834*10460SSonam.Gupta@Sun.COM r1 = r2 = tmp = strdup(request->secure->req_id); 835*10460SSonam.Gupta@Sun.COM r2 = strrchr(r1, '-'); 836*10460SSonam.Gupta@Sun.COM if (r2 != NULL) { 837*10460SSonam.Gupta@Sun.COM char *r3 = NULL; 838*10460SSonam.Gupta@Sun.COM int lr1 = strlen(r1); 839*10460SSonam.Gupta@Sun.COM int lr2 = strlen(r2); 840*10460SSonam.Gupta@Sun.COM r1[lr1 - lr2 + 1] = '\0'; 841*10460SSonam.Gupta@Sun.COM 842*10460SSonam.Gupta@Sun.COM /* 843*10460SSonam.Gupta@Sun.COM * Now r1 = <printer-name>- 844*10460SSonam.Gupta@Sun.COM */ 845*10460SSonam.Gupta@Sun.COM lr1 = strlen(r1); 846*10460SSonam.Gupta@Sun.COM lr2 = strlen(ridno); 847*10460SSonam.Gupta@Sun.COM 848*10460SSonam.Gupta@Sun.COM r3 = (char *)malloc(lr1+lr2+1); 849*10460SSonam.Gupta@Sun.COM if (r3 != NULL) { 850*10460SSonam.Gupta@Sun.COM strcpy(r3, r1); 851*10460SSonam.Gupta@Sun.COM strcat(r3, ridno); 852*10460SSonam.Gupta@Sun.COM /* 853*10460SSonam.Gupta@Sun.COM * Here r3 = <printer-name>-<ridno> 854*10460SSonam.Gupta@Sun.COM */ 855*10460SSonam.Gupta@Sun.COM av[ac++] = arg_string(TRUSTED, 856*10460SSonam.Gupta@Sun.COM "%s", r3); 857*10460SSonam.Gupta@Sun.COM free(r3); 858*10460SSonam.Gupta@Sun.COM } else 859*10460SSonam.Gupta@Sun.COM av[ac++] = arg_string(TRUSTED, "%s", 860*10460SSonam.Gupta@Sun.COM request->secure->req_id); 861*10460SSonam.Gupta@Sun.COM 862*10460SSonam.Gupta@Sun.COM } else 863*10460SSonam.Gupta@Sun.COM av[ac++] = arg_string(TRUSTED, "%s", 864*10460SSonam.Gupta@Sun.COM request->secure->req_id); 865*10460SSonam.Gupta@Sun.COM 866*10460SSonam.Gupta@Sun.COM if (tmp != NULL) 867*10460SSonam.Gupta@Sun.COM free(tmp); 868*10460SSonam.Gupta@Sun.COM 869*10460SSonam.Gupta@Sun.COM if (ridno != NULL) 870*10460SSonam.Gupta@Sun.COM free(ridno); 871*10460SSonam.Gupta@Sun.COM } 872*10460SSonam.Gupta@Sun.COM 8733125Sjacobs av[ac++] = arg_string(UNTRUSTED, "%s", request->request->user); 8740Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", clean_title); 8750Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%d", request->copies); 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate if (fr_flg) 8780Sstevel@tonic-gate free (clean_title); 8790Sstevel@tonic-gate 8800Sstevel@tonic-gate sep = ""; 8810Sstevel@tonic-gate 8820Sstevel@tonic-gate /* 8830Sstevel@tonic-gate * Do the administrator defined key=value pair options 8840Sstevel@tonic-gate */ 8850Sstevel@tonic-gate 8860Sstevel@tonic-gate argbuf[0] = '\0'; 8870Sstevel@tonic-gate 8880Sstevel@tonic-gate if (printer->printer->options) { 8890Sstevel@tonic-gate char **tmp = printer->printer->options; 8900Sstevel@tonic-gate while(*tmp != NULL) { 8910Sstevel@tonic-gate STRLCAT(argbuf, sep, sizeof (argbuf)); 8920Sstevel@tonic-gate sep = " "; 8930Sstevel@tonic-gate STRLCAT(argbuf, *tmp++, sizeof (argbuf)); 8940Sstevel@tonic-gate } 8950Sstevel@tonic-gate } 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate /* 8980Sstevel@tonic-gate * Do the administrator defined ``stty'' stuff before 8990Sstevel@tonic-gate * the user's -o options, to allow the user to override. 9000Sstevel@tonic-gate */ 9010Sstevel@tonic-gate if (printer->printer->stty) { 9020Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9030Sstevel@tonic-gate sep = " "; 9040Sstevel@tonic-gate STRLCAT (argbuf, "stty='", sizeof (argbuf)); 9050Sstevel@tonic-gate STRLCAT (argbuf, printer->printer->stty, 9060Sstevel@tonic-gate sizeof (argbuf)); 9070Sstevel@tonic-gate STRLCAT (argbuf, "'", sizeof (argbuf)); 9080Sstevel@tonic-gate } 9090Sstevel@tonic-gate 9100Sstevel@tonic-gate /* 9110Sstevel@tonic-gate * Do all of the user's options except the cpi/lpi/etc. 9120Sstevel@tonic-gate * stuff, which is done separately. 9130Sstevel@tonic-gate */ 9140Sstevel@tonic-gate if (request->request->options) { 9150Sstevel@tonic-gate listp = dashos(request->request->options); 9160Sstevel@tonic-gate while (*listp) { 9170Sstevel@tonic-gate if ( 9180Sstevel@tonic-gate !STRNEQU(*listp, "cpi=", 4) 9190Sstevel@tonic-gate && !STRNEQU(*listp, "lpi=", 4) 9200Sstevel@tonic-gate && !STRNEQU(*listp, "width=", 6) 9210Sstevel@tonic-gate && !STRNEQU(*listp, "length=", 7) 9220Sstevel@tonic-gate ) { 9230Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9240Sstevel@tonic-gate sep = " "; 9250Sstevel@tonic-gate STRLCAT (argbuf, *listp, 9260Sstevel@tonic-gate sizeof (argbuf)); 9270Sstevel@tonic-gate } 9280Sstevel@tonic-gate listp++; 9290Sstevel@tonic-gate } 9300Sstevel@tonic-gate } 9310Sstevel@tonic-gate 9320Sstevel@tonic-gate /* 9330Sstevel@tonic-gate * The "pickfilter()" routine (from "validate()") 9340Sstevel@tonic-gate * stored the cpi/lpi/etc. stuff that should be 9350Sstevel@tonic-gate * used for this request. It chose form over user, 9360Sstevel@tonic-gate * and user over printer. 9370Sstevel@tonic-gate */ 9380Sstevel@tonic-gate if (request->cpi) { 9390Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9400Sstevel@tonic-gate sep = " "; 9410Sstevel@tonic-gate STRLCAT (argbuf, "cpi=", sizeof (argbuf)); 9420Sstevel@tonic-gate STRLCAT (argbuf, request->cpi, sizeof (argbuf)); 9430Sstevel@tonic-gate } 9440Sstevel@tonic-gate if (request->lpi) { 9450Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9460Sstevel@tonic-gate sep = " "; 9470Sstevel@tonic-gate STRLCAT (argbuf, "lpi=", sizeof (argbuf)); 9480Sstevel@tonic-gate STRLCAT (argbuf, request->lpi, sizeof (argbuf)); 9490Sstevel@tonic-gate } 9500Sstevel@tonic-gate if (request->pwid) { 9510Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9520Sstevel@tonic-gate sep = " "; 9530Sstevel@tonic-gate STRLCAT (argbuf, "width=", sizeof (argbuf)); 9540Sstevel@tonic-gate STRLCAT (argbuf, request->pwid, sizeof (argbuf)); 9550Sstevel@tonic-gate } 9560Sstevel@tonic-gate if (request->plen) { 9570Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9580Sstevel@tonic-gate sep = " "; 9590Sstevel@tonic-gate STRLCAT (argbuf, "length=", sizeof (argbuf)); 9600Sstevel@tonic-gate STRLCAT (argbuf, request->plen, sizeof (argbuf)); 9610Sstevel@tonic-gate } 9620Sstevel@tonic-gate 9630Sstevel@tonic-gate /* 9640Sstevel@tonic-gate * Do the ``raw'' bit last, to ensure it gets 9650Sstevel@tonic-gate * done. If the user doesn't want this, then he or 9660Sstevel@tonic-gate * she can do the correct thing using -o stty= 9670Sstevel@tonic-gate * and leaving out the -r option. 9680Sstevel@tonic-gate */ 9690Sstevel@tonic-gate if (request->request->actions & ACT_RAW) { 9700Sstevel@tonic-gate STRLCAT (argbuf, sep, sizeof (argbuf)); 9710Sstevel@tonic-gate sep = " "; 9720Sstevel@tonic-gate STRLCAT (argbuf, "stty=-opost", sizeof (argbuf)); 9730Sstevel@tonic-gate } 9740Sstevel@tonic-gate 9750Sstevel@tonic-gate 9760Sstevel@tonic-gate /* the "options" */ 9770Sstevel@tonic-gate av[ac++] = arg_string(UNTRUSTED, "%s", argbuf); 9780Sstevel@tonic-gate 9790Sstevel@tonic-gate for (listp = file_list; *listp; listp++) 9800Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", *listp); 9810Sstevel@tonic-gate 9820Sstevel@tonic-gate (void)chfiles (file_list, procuid, procgid); 9830Sstevel@tonic-gate 9840Sstevel@tonic-gate break; 9850Sstevel@tonic-gate 9860Sstevel@tonic-gate 9870Sstevel@tonic-gate case EX_SLOWF: 9880Sstevel@tonic-gate if (request->slow) 9890Sstevel@tonic-gate addenv(&envp, "FILTER", request->slow); 9900Sstevel@tonic-gate 9913125Sjacobs if (strchr (request->request->user, '@')) 9920Sstevel@tonic-gate { 9930Sstevel@tonic-gate procuid = Lp_Uid; 9940Sstevel@tonic-gate procgid = Lp_Gid; 9950Sstevel@tonic-gate } 9960Sstevel@tonic-gate else 9970Sstevel@tonic-gate { 9980Sstevel@tonic-gate procuid = request->secure->uid; 9990Sstevel@tonic-gate procgid = request->secure->gid; 10000Sstevel@tonic-gate } 10010Sstevel@tonic-gate cp = _alloc_files( 10020Sstevel@tonic-gate lenlist(request->request->file_list), 10030Sstevel@tonic-gate getreqno(request->secure->req_id), 10043125Sjacobs procuid, procgid); 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", Lp_Slow_Filter); 10073204Sjacobs av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_Temp, cp); 10080Sstevel@tonic-gate for (listp = request->request->file_list; *listp; listp++) 10090Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", *listp); 10100Sstevel@tonic-gate 10110Sstevel@tonic-gate (void)chfiles (request->request->file_list, procuid, procgid); 10120Sstevel@tonic-gate 10130Sstevel@tonic-gate #ifdef LP_USE_PAPI_ATTR 10140Sstevel@tonic-gate /* 10150Sstevel@tonic-gate * Check if the PAPI job attribute file exists, if it does 10160Sstevel@tonic-gate * pass the file's pathname to the slow-filters in an 10170Sstevel@tonic-gate * environment variable. Note: this file is created when 10180Sstevel@tonic-gate * print jobs are submitted via the PAPI interface. 10190Sstevel@tonic-gate */ 10200Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s-%s", 10210Sstevel@tonic-gate getreqno(request->secure->req_id), LP_PAPIATTRNAME); 10223125Sjacobs path = makepath(Lp_Temp, tmpName, (char *)0); 10230Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 10240Sstevel@tonic-gate { 10250Sstevel@tonic-gate /* 10260Sstevel@tonic-gate * IPP job attribute file exists for this job so 10270Sstevel@tonic-gate * set the environment variable 10280Sstevel@tonic-gate */ 10290Sstevel@tonic-gate addenv(&envp, "ATTRPATH", path); 10300Sstevel@tonic-gate } 10310Sstevel@tonic-gate Free(path); 10320Sstevel@tonic-gate 10330Sstevel@tonic-gate 10340Sstevel@tonic-gate /* 10350Sstevel@tonic-gate * now set environment variable for the printer's PostScript 10360Sstevel@tonic-gate * Printer Description (PPD) file, this is used by the filter 10370Sstevel@tonic-gate * when forming the print data for this printer. 10380Sstevel@tonic-gate */ 10390Sstevel@tonic-gate if ((request->printer != NULL) && 10400Sstevel@tonic-gate (request->printer->printer != NULL) && 10410Sstevel@tonic-gate (request->printer->printer->name != NULL)) 10420Sstevel@tonic-gate { 10430Sstevel@tonic-gate snprintf(tmpName, sizeof (tmpName), "%s.ppd", 10440Sstevel@tonic-gate request->printer->printer->name); 10450Sstevel@tonic-gate path = makepath(ETCDIR, "ppd", tmpName, (char *)0); 10460Sstevel@tonic-gate if ((path != NULL) && (stat(path, &tmpBuf) == 0)) 10470Sstevel@tonic-gate { 10480Sstevel@tonic-gate addenv(&envp, "PPD", path); 10490Sstevel@tonic-gate } 10500Sstevel@tonic-gate Free(path); 10510Sstevel@tonic-gate } 10520Sstevel@tonic-gate #endif 10530Sstevel@tonic-gate break; 10540Sstevel@tonic-gate 10550Sstevel@tonic-gate case EX_ALERT: 10560Sstevel@tonic-gate procuid = Lp_Uid; 10570Sstevel@tonic-gate procgid = Lp_Gid; 10580Sstevel@tonic-gate (void)Chown (printer->alert->msgfile, procuid, procgid); 10590Sstevel@tonic-gate 10600Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers, 10610Sstevel@tonic-gate printer->printer->name, ALERTSHFILE); 10620Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); 10630Sstevel@tonic-gate 10640Sstevel@tonic-gate break; 10650Sstevel@tonic-gate 10660Sstevel@tonic-gate case EX_PALERT: 10670Sstevel@tonic-gate procuid = Lp_Uid; 10680Sstevel@tonic-gate procgid = Lp_Gid; 10690Sstevel@tonic-gate (void)Chown (pwheel->alert->msgfile, procuid, procgid); 10700Sstevel@tonic-gate 10710Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_PrintWheels, 10720Sstevel@tonic-gate pwheel->pwheel->name, ALERTSHFILE); 10730Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); 10740Sstevel@tonic-gate 10750Sstevel@tonic-gate break; 10760Sstevel@tonic-gate 10770Sstevel@tonic-gate case EX_FALERT: 10780Sstevel@tonic-gate procuid = Lp_Uid; 10790Sstevel@tonic-gate procgid = Lp_Gid; 10800Sstevel@tonic-gate (void)Chown (form->alert->msgfile, procuid, procgid); 10810Sstevel@tonic-gate 10820Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms, 10830Sstevel@tonic-gate form->form->name, ALERTSHFILE); 10840Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); 10850Sstevel@tonic-gate 10860Sstevel@tonic-gate break; 10870Sstevel@tonic-gate 10880Sstevel@tonic-gate case EX_FORM_MESSAGE: 10890Sstevel@tonic-gate procuid = Lp_Uid; 10900Sstevel@tonic-gate procgid = Lp_Gid; 10910Sstevel@tonic-gate 10920Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/form", Lp_A_Faults); 10930Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", form->form->name); 10940Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", time_buf); 10950Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms, 10960Sstevel@tonic-gate form->form->name, FORMMESSAGEFILE); 10970Sstevel@tonic-gate 10980Sstevel@tonic-gate break; 10990Sstevel@tonic-gate 11000Sstevel@tonic-gate case EX_FAULT_MESSAGE: 11010Sstevel@tonic-gate procuid = Lp_Uid; 11020Sstevel@tonic-gate procgid = Lp_Gid; 11030Sstevel@tonic-gate 11040Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/printer", Lp_A_Faults); 11050Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", printerNameToShow); 11060Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", time_buf); 11070Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers, 11080Sstevel@tonic-gate printerName, FAULTMESSAGEFILE); 11090Sstevel@tonic-gate 11100Sstevel@tonic-gate break; 11110Sstevel@tonic-gate 11120Sstevel@tonic-gate case EX_NOTIFY: 11130Sstevel@tonic-gate if (request->request->alert) { 11143125Sjacobs if (strchr(request->request->user, '@')) { 11150Sstevel@tonic-gate procuid = Lp_Uid; 11160Sstevel@tonic-gate procgid = Lp_Gid; 11170Sstevel@tonic-gate } else { 11180Sstevel@tonic-gate procuid = request->secure->uid; 11190Sstevel@tonic-gate procgid = request->secure->gid; 11200Sstevel@tonic-gate } 11210Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", 11220Sstevel@tonic-gate request->request->alert); 11230Sstevel@tonic-gate } else { 11243125Sjacobs char *user = strdup(request->request->user); 11250Sstevel@tonic-gate clean_string(user); 11261676Sjpk slabel = request->secure->slabel; 11270Sstevel@tonic-gate 11283125Sjacobs if (request->request->actions & ACT_WRITE) { 11290Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", BINWRITE); 11300Sstevel@tonic-gate snprintf(argbuf, sizeof (argbuf), 11310Sstevel@tonic-gate "%s %s || %s %s", 11320Sstevel@tonic-gate BINWRITE, user, 11330Sstevel@tonic-gate BINMAIL, user 11340Sstevel@tonic-gate ); 11350Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "/bin/sh"); 11360Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "-c"); 11370Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", argbuf); 11381676Sjpk } else if ((getzoneid() == GLOBAL_ZONEID) && 11391676Sjpk is_system_labeled() && (slabel != NULL)) { 11401676Sjpk /* 11411676Sjpk * If in the global zone and the system is 11421676Sjpk * labeled, mail is handled via a local 11431676Sjpk * labeled zone that is the same label as 11441676Sjpk * the request. 11451676Sjpk */ 11461676Sjpk if ((mail_zonename = 11471676Sjpk get_labeled_zonename(slabel)) == 11481676Sjpk (char *)-1) { 11491676Sjpk /* 11501676Sjpk * Cannot find labeled zone, just 11511676Sjpk * return 0. 11521676Sjpk */ 11531676Sjpk return(0); 11541676Sjpk } 11551676Sjpk } 11561676Sjpk if (mail_zonename == NULL) { 11571676Sjpk procuid = Lp_Uid; 11581676Sjpk procgid = Lp_Gid; 11590Sstevel@tonic-gate av[ac++] = arg_string(TRUSTED, "%s", BINMAIL); 11600Sstevel@tonic-gate av[ac++] = arg_string(UNTRUSTED, "%s", user); 11611676Sjpk } else { 11621676Sjpk procuid = getuid(); 11631676Sjpk procgid = getgid(); 11641676Sjpk av[ac++] = arg_string(TRUSTED, "%s", 11651676Sjpk "/usr/sbin/zlogin"); 11661676Sjpk av[ac++] = arg_string(TRUSTED, "%s", 11671676Sjpk mail_zonename); 11681676Sjpk av[ac++] = arg_string(TRUSTED, "%s", 11691676Sjpk BINMAIL); 11701676Sjpk av[ac++] = arg_string(UNTRUSTED, "%s", 11711676Sjpk user); 11721676Sjpk Free(mail_zonename); 11730Sstevel@tonic-gate } 11740Sstevel@tonic-gate 11750Sstevel@tonic-gate free(user); 11760Sstevel@tonic-gate } 11770Sstevel@tonic-gate break; 11780Sstevel@tonic-gate } 11790Sstevel@tonic-gate 11800Sstevel@tonic-gate av[ac++] = NULL; 11810Sstevel@tonic-gate 11820Sstevel@tonic-gate Fork2 (); 11830Sstevel@tonic-gate /* only the child returns */ 11840Sstevel@tonic-gate 11850Sstevel@tonic-gate /* 11860Sstevel@tonic-gate * Correctly set up the supplemental group list 11870Sstevel@tonic-gate * for proper file access (before execl the interface program) 11880Sstevel@tonic-gate */ 11890Sstevel@tonic-gate 11900Sstevel@tonic-gate pwp = getpwuid(procuid); 11910Sstevel@tonic-gate if (pwp == NULL) { 11920Sstevel@tonic-gate note("getpwuid(%d) call failed\n", procuid); 11930Sstevel@tonic-gate } else if (initgroups(pwp->pw_name, procgid) < 0) { 11940Sstevel@tonic-gate note("initgroups() call failed %d\n", errno); 11950Sstevel@tonic-gate } 11960Sstevel@tonic-gate 11970Sstevel@tonic-gate setgid (procgid); 11980Sstevel@tonic-gate setuid (procuid); 11990Sstevel@tonic-gate 12000Sstevel@tonic-gate /* 12010Sstevel@tonic-gate * The shell doesn't allow the "trap" builtin to set a trap 12020Sstevel@tonic-gate * for a signal ignored when the shell is started. Thus, don't 12030Sstevel@tonic-gate * turn off signals in the last child! 12040Sstevel@tonic-gate */ 12050Sstevel@tonic-gate 12063125Sjacobs #ifdef DEBUG 12070Sstevel@tonic-gate for (i = 0; av[i] != NULL; i++) 12083125Sjacobs note("exec(%s): av[%d] = %s", _exec_name(type), i, av[i]); 12091676Sjpk for (i = 0; envp[i] != NULL; i++) 12103125Sjacobs note("exec(%s): envp[%d] = %s", _exec_name(type), i, envp[i]); 12113125Sjacobs #endif 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate execvpe(av[0], av, envp); 12140Sstevel@tonic-gate Done (EXEC_EXIT_NEXEC, errno); 12150Sstevel@tonic-gate /*NOTREACHED*/ 1216320Sceastha return (0); 12170Sstevel@tonic-gate } 12180Sstevel@tonic-gate 12190Sstevel@tonic-gate /** 12200Sstevel@tonic-gate ** addenv() - ADD A VARIABLE TO THE ENVIRONMENT 12210Sstevel@tonic-gate **/ 12220Sstevel@tonic-gate 12230Sstevel@tonic-gate static void 12240Sstevel@tonic-gate addenv(char ***envp, char *name, char *value) 12250Sstevel@tonic-gate { 12260Sstevel@tonic-gate register char * cp; 12270Sstevel@tonic-gate 12280Sstevel@tonic-gate if ((name == NULL) || (value == NULL)) 12290Sstevel@tonic-gate return; 12300Sstevel@tonic-gate 12310Sstevel@tonic-gate if ((cp = makestr(name, "=", value, (char *)0))) 12320Sstevel@tonic-gate addlist(envp, cp); 12330Sstevel@tonic-gate return; 12340Sstevel@tonic-gate } 12350Sstevel@tonic-gate 12360Sstevel@tonic-gate /** 12370Sstevel@tonic-gate ** Fork1() - FORK FIRST CHILD, SET UP CONNECTION TO IT 12380Sstevel@tonic-gate **/ 12390Sstevel@tonic-gate 12400Sstevel@tonic-gate static int 12410Sstevel@tonic-gate Fork1(EXEC *ep) 12420Sstevel@tonic-gate { 12430Sstevel@tonic-gate int pid; 12440Sstevel@tonic-gate int fds[2]; 12450Sstevel@tonic-gate 12460Sstevel@tonic-gate if (pipe(fds) == -1) { 12470Sstevel@tonic-gate note("Failed to create pipe for child process (%s).\n", PERROR); 12480Sstevel@tonic-gate errno = EAGAIN ; 12490Sstevel@tonic-gate return(-1); 12500Sstevel@tonic-gate } 12510Sstevel@tonic-gate 12520Sstevel@tonic-gate ep->md = mconnect((char *)0, fds[0], fds[1]); 12530Sstevel@tonic-gate 12540Sstevel@tonic-gate switch (pid = fork()) { 12550Sstevel@tonic-gate 12560Sstevel@tonic-gate case -1: 12570Sstevel@tonic-gate mdisconnect(ep->md); 12580Sstevel@tonic-gate close(fds[0]); 12590Sstevel@tonic-gate close(fds[1]); 12600Sstevel@tonic-gate ep->md = 0; 12610Sstevel@tonic-gate return (-1); 12620Sstevel@tonic-gate 12630Sstevel@tonic-gate case 0: 12640Sstevel@tonic-gate ChildMd = mconnect(NULL, fds[1], fds[1]); 12650Sstevel@tonic-gate return (0); 12660Sstevel@tonic-gate 12670Sstevel@tonic-gate default: 12680Sstevel@tonic-gate mlistenadd(ep->md, POLLIN); 12690Sstevel@tonic-gate return (pid); 12700Sstevel@tonic-gate } 12710Sstevel@tonic-gate } 12720Sstevel@tonic-gate 12730Sstevel@tonic-gate /** 12740Sstevel@tonic-gate ** Fork2() - FORK SECOND CHILD AND WAIT FOR IT 12750Sstevel@tonic-gate **/ 12760Sstevel@tonic-gate 12770Sstevel@tonic-gate static void 12780Sstevel@tonic-gate Fork2(void) 12790Sstevel@tonic-gate { 12800Sstevel@tonic-gate switch ((ChildPid = fork())) { 12810Sstevel@tonic-gate 12820Sstevel@tonic-gate case -1: 12830Sstevel@tonic-gate Done (EXEC_EXIT_NFORK, errno); 12840Sstevel@tonic-gate /*NOTREACHED*/ 12850Sstevel@tonic-gate 12860Sstevel@tonic-gate case 0: 12870Sstevel@tonic-gate return; 12880Sstevel@tonic-gate 12890Sstevel@tonic-gate default: 12900Sstevel@tonic-gate /* 12910Sstevel@tonic-gate * Delay calling "ignore_fault_signals()" as long 12920Sstevel@tonic-gate * as possible, to give the child a chance to exec 12930Sstevel@tonic-gate * the interface program and turn on traps. 12940Sstevel@tonic-gate */ 12950Sstevel@tonic-gate 12960Sstevel@tonic-gate cool_heels (); 12970Sstevel@tonic-gate /*NOTREACHED*/ 12980Sstevel@tonic-gate 12990Sstevel@tonic-gate } 13000Sstevel@tonic-gate } 13010Sstevel@tonic-gate 13020Sstevel@tonic-gate 13030Sstevel@tonic-gate /** 13040Sstevel@tonic-gate ** cool_heels() - WAIT FOR CHILD TO "DIE" 13050Sstevel@tonic-gate **/ 13060Sstevel@tonic-gate 13070Sstevel@tonic-gate static void 13080Sstevel@tonic-gate cool_heels(void) 13090Sstevel@tonic-gate { 13100Sstevel@tonic-gate int status; 13110Sstevel@tonic-gate 13120Sstevel@tonic-gate /* 13130Sstevel@tonic-gate * At this point our only job is to wait for the child process. 13140Sstevel@tonic-gate * If we hang out for a bit longer, that's okay. 13150Sstevel@tonic-gate * By delaying before turning off the fault signals, 13160Sstevel@tonic-gate * we increase the chance that the child process has completed 13170Sstevel@tonic-gate * its exec and has turned on the fault traps. Nonetheless, 13180Sstevel@tonic-gate * we can't guarantee a zero chance of missing a fault. 13190Sstevel@tonic-gate * (We don't want to keep trapping the signals because the 13200Sstevel@tonic-gate * interface program is likely to have a better way to handle 13210Sstevel@tonic-gate * them; this process provides only rudimentary handling.) 13220Sstevel@tonic-gate * 13230Sstevel@tonic-gate * Note that on a very busy system, or with a very fast interface 13240Sstevel@tonic-gate * program, the tables could be turned: Our sleep below (coupled 13250Sstevel@tonic-gate * with a delay in the kernel scheduling us) may cause us to 13260Sstevel@tonic-gate * detect the fault instead of the interface program. 13270Sstevel@tonic-gate * 13280Sstevel@tonic-gate * What we need is a way to synchronize with the child process. 13290Sstevel@tonic-gate */ 13300Sstevel@tonic-gate sleep (1); 13310Sstevel@tonic-gate ignore_fault_signals (); 13320Sstevel@tonic-gate 13330Sstevel@tonic-gate WaitedChildPid = 0; 13340Sstevel@tonic-gate while ((WaitedChildPid = wait(&status)) != ChildPid) 13350Sstevel@tonic-gate ; 13360Sstevel@tonic-gate 13370Sstevel@tonic-gate if ( 13380Sstevel@tonic-gate EXITED(status) > EXEC_EXIT_USER 13390Sstevel@tonic-gate && EXITED(status) != EXEC_EXIT_FAULT 13400Sstevel@tonic-gate ) 13410Sstevel@tonic-gate Done (EXEC_EXIT_EXIT, EXITED(status)); 13420Sstevel@tonic-gate 13430Sstevel@tonic-gate done (status, 0); /* Don't use Done() */ 13440Sstevel@tonic-gate /*NOTREACHED*/ 13450Sstevel@tonic-gate } 13460Sstevel@tonic-gate 13470Sstevel@tonic-gate 13480Sstevel@tonic-gate /** 13490Sstevel@tonic-gate ** trap_fault_signals() - TRAP SIGNALS THAT CAN OCCUR ON PRINTER FAULT 13500Sstevel@tonic-gate ** ignore_fault_signals() - IGNORE SAME 13510Sstevel@tonic-gate **/ 13520Sstevel@tonic-gate 13530Sstevel@tonic-gate static void 13540Sstevel@tonic-gate trap_fault_signals(void) 13550Sstevel@tonic-gate { 13560Sstevel@tonic-gate signal (SIGHUP, sigtrap); 13570Sstevel@tonic-gate signal (SIGINT, sigtrap); 13580Sstevel@tonic-gate signal (SIGQUIT, sigtrap); 13590Sstevel@tonic-gate signal (SIGPIPE, sigtrap); 13600Sstevel@tonic-gate return; 13610Sstevel@tonic-gate } 13620Sstevel@tonic-gate 13630Sstevel@tonic-gate static void 13640Sstevel@tonic-gate ignore_fault_signals(void) 13650Sstevel@tonic-gate { 13660Sstevel@tonic-gate signal (SIGHUP, SIG_IGN); 13670Sstevel@tonic-gate signal (SIGINT, SIG_IGN); 13680Sstevel@tonic-gate signal (SIGQUIT, SIG_IGN); 13690Sstevel@tonic-gate signal (SIGPIPE, SIG_IGN); 13700Sstevel@tonic-gate return; 13710Sstevel@tonic-gate } 13720Sstevel@tonic-gate 13730Sstevel@tonic-gate /** 13740Sstevel@tonic-gate ** sigtrap() - TRAP VARIOUS SIGNALS 13750Sstevel@tonic-gate **/ 13760Sstevel@tonic-gate 13770Sstevel@tonic-gate static void 13780Sstevel@tonic-gate sigtrap(int sig) 13790Sstevel@tonic-gate { 13800Sstevel@tonic-gate signal (sig, SIG_IGN); 13810Sstevel@tonic-gate switch (sig) { 13820Sstevel@tonic-gate 13830Sstevel@tonic-gate case SIGHUP: 13840Sstevel@tonic-gate Done (EXEC_EXIT_HUP, 0); 13850Sstevel@tonic-gate /*NOTREACHED*/ 13860Sstevel@tonic-gate 13870Sstevel@tonic-gate case SIGQUIT: 13880Sstevel@tonic-gate case SIGINT: 13890Sstevel@tonic-gate Done (EXEC_EXIT_INTR, 0); 13900Sstevel@tonic-gate /*NOTREACHED*/ 13910Sstevel@tonic-gate 13920Sstevel@tonic-gate case SIGPIPE: 13930Sstevel@tonic-gate Done (EXEC_EXIT_PIPE, 0); 13940Sstevel@tonic-gate /*NOTREACHED*/ 13950Sstevel@tonic-gate 13960Sstevel@tonic-gate case SIGTERM: 13970Sstevel@tonic-gate /* 13980Sstevel@tonic-gate * If we were killed with SIGTERM, it should have been 13990Sstevel@tonic-gate * via the Spooler who should have killed the entire 14000Sstevel@tonic-gate * process group. We have to wait for the children, 14010Sstevel@tonic-gate * since we're their parent, but WE MAY HAVE WAITED 14020Sstevel@tonic-gate * FOR THEM ALREADY (in cool_heels()). 14030Sstevel@tonic-gate */ 14040Sstevel@tonic-gate if (ChildPid != WaitedChildPid) { 14050Sstevel@tonic-gate register int cpid; 14060Sstevel@tonic-gate 14070Sstevel@tonic-gate while ( 14080Sstevel@tonic-gate (cpid = wait((int *)0)) != ChildPid 14090Sstevel@tonic-gate && (cpid != -1 || errno != ECHILD) 14100Sstevel@tonic-gate ) 14110Sstevel@tonic-gate ; 14120Sstevel@tonic-gate } 14130Sstevel@tonic-gate 14140Sstevel@tonic-gate /* 14150Sstevel@tonic-gate * We can't rely on getting SIGTERM back in the wait() 14160Sstevel@tonic-gate * above, because, for instance, some shells trap SIGTERM 14170Sstevel@tonic-gate * and exit instead. Thus we force it. 14180Sstevel@tonic-gate */ 14190Sstevel@tonic-gate done (SIGTERM, 0); /* Don't use Done() */ 14200Sstevel@tonic-gate /*NOTREACHED*/ 14210Sstevel@tonic-gate } 14220Sstevel@tonic-gate } 14230Sstevel@tonic-gate 14240Sstevel@tonic-gate /** 14250Sstevel@tonic-gate ** done() - TELL SPOOLER THIS CHILD IS DONE 14260Sstevel@tonic-gate **/ 14270Sstevel@tonic-gate 14280Sstevel@tonic-gate static void 14290Sstevel@tonic-gate done(int status, int err) 14300Sstevel@tonic-gate { 14310Sstevel@tonic-gate if (do_undial) 14320Sstevel@tonic-gate undial (1); 14330Sstevel@tonic-gate 14343125Sjacobs mputm (ChildMd, S_CHILD_DONE, key, status, err); 14350Sstevel@tonic-gate mdisconnect (ChildMd); 14360Sstevel@tonic-gate 14370Sstevel@tonic-gate exit (0); 14380Sstevel@tonic-gate /*NOTREACHED*/ 14390Sstevel@tonic-gate } 14400Sstevel@tonic-gate 14410Sstevel@tonic-gate /** 14420Sstevel@tonic-gate ** child_mallocfail() 14430Sstevel@tonic-gate **/ 14440Sstevel@tonic-gate 14450Sstevel@tonic-gate static void 14460Sstevel@tonic-gate child_mallocfail(void) 14470Sstevel@tonic-gate { 14480Sstevel@tonic-gate Done (EXEC_EXIT_NOMEM, ENOMEM); 14490Sstevel@tonic-gate } 1450