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