Home | History | Annotate | Download | only in lpsched
      1      0   stevel /*
      2      0   stevel  * CDDL HEADER START
      3      0   stevel  *
      4      0   stevel  * The contents of this file are subject to the terms of the
      5   1676      jpk  * Common Development and Distribution License (the "License").
      6   1676      jpk  * You may not use this file except in compliance with the License.
      7      0   stevel  *
      8      0   stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0   stevel  * or http://www.opensolaris.org/os/licensing.
     10      0   stevel  * See the License for the specific language governing permissions
     11      0   stevel  * and limitations under the License.
     12      0   stevel  *
     13      0   stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0   stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0   stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0   stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0   stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0   stevel  *
     19      0   stevel  * CDDL HEADER END
     20      0   stevel  */
     21   3125   jacobs 
     22      0   stevel /*
     23  10460    Sonam  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24      0   stevel  * Use is subject to license terms.
     25      0   stevel  */
     26    320  ceastha 
     27    320  ceastha /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28    320  ceastha /*	  All Rights Reserved  	*/
     29      0   stevel 
     30   1676      jpk #include <pwd.h>
     31   1676      jpk #include <zone.h>
     32   1676      jpk #if defined PS_FAULTED
     33   1676      jpk #undef  PS_FAULTED
     34   1676      jpk #endif /* PS_FAULTED */
     35      0   stevel #include <dial.h>
     36      0   stevel 
     37      0   stevel #include <stdlib.h>
     38      0   stevel #include "limits.h"
     39      0   stevel #include "stdarg.h"
     40      0   stevel #include "wait.h"
     41      0   stevel #include "dial.h"
     42      0   stevel #include "lpsched.h"
     43      0   stevel #include <syslog.h>
     44   1676      jpk #include "tsol/label.h"
     45      0   stevel 
     46      0   stevel #define Done(EC,ERRNO)	done(((EC) << 8),ERRNO)
     47      0   stevel 
     48      0   stevel #define	STRLCAT(dst, src, size) \
     49      0   stevel 	if (strlcat((dst), (src), (size)) >= (size)) { \
     50      0   stevel 		errno = EINVAL; \
     51      0   stevel 		return (-1); \
     52      0   stevel 	}
     53      0   stevel 
     54      0   stevel static MESG *		ChildMd;
     55      0   stevel 
     56      0   stevel static int		ChildPid;
     57      0   stevel static int		WaitedChildPid;
     58      0   stevel static int		do_undial;
     59      0   stevel 
     60      0   stevel static char		argbuf[ARG_MAX];
     61      0   stevel 
     62      0   stevel static long		key;
     63      0   stevel 
     64      0   stevel static void		sigtrap ( int );
     65      0   stevel static void		done ( int , int );
     66      0   stevel static void		cool_heels ( void );
     67      0   stevel static void		addenv (char ***envp, char * , char * );
     68      0   stevel static void		trap_fault_signals ( void );
     69      0   stevel static void		ignore_fault_signals ( void );
     70      0   stevel static void		child_mallocfail ( void );
     71      0   stevel static void		Fork2 ( void );
     72      0   stevel 
     73      0   stevel static int		Fork1 ( EXEC * );
     74      0   stevel 
     75      0   stevel static void
     76      0   stevel relock(void)
     77      0   stevel {
     78      0   stevel 	struct flock		l;
     79      0   stevel 
     80      0   stevel 	l.l_type = F_WRLCK;
     81      0   stevel 	l.l_whence = 1;
     82      0   stevel 	l.l_start = 0;
     83      0   stevel 	l.l_len = 0;
     84      0   stevel 	(void)Fcntl (lock_fd, F_SETLK, &l);
     85      0   stevel 	return;
     86      0   stevel }
     87      0   stevel 
     88      0   stevel static char *_exec_name(int type)
     89      0   stevel {
     90      0   stevel 	static char *_names[] = {
     91      0   stevel 	"", "EX_INTERF", "EX_SLOWF", "EX_ALERT", "EX_FALERT", "EX_PALERT",
     92      0   stevel 	"EX_NOTIFY", "EX_FAULT_MESSAGE", "EX_FORM_MESSAGE", NULL };
     93      0   stevel 
     94      0   stevel 	if ((type < 0) || (type > EX_FORM_MESSAGE))
     95      0   stevel 		return ("BAD_EXEC_TYPE");
     96      0   stevel 	else
     97      0   stevel 		return (_names[type]);
     98      0   stevel }
     99      0   stevel 
    100      0   stevel /*
    101      0   stevel  * This function replaces characters in a string that might be used
    102      0   stevel  * to exploit a security hole.  Replace command seperators (`, &, ;, |, ^),
    103      0   stevel  * output redirection (>, |), variable expansion ($), and character
    104      0   stevel  * escape (\).
    105      0   stevel  *
    106      0   stevel  * Bugid 4141687
    107      0   stevel  * Add ( ) < * ? [
    108      0   stevel  * Bugid 4139071
    109      0   stevel  * Remove \
    110      0   stevel  */
    111      0   stevel void clean_string(char *ptr)
    112      0   stevel {
    113      0   stevel 	char *cp;
    114      0   stevel 	wchar_t wc;
    115      0   stevel 	size_t len;
    116      0   stevel 
    117      0   stevel 	for (cp = ptr; *cp != NULL; ) {
    118      0   stevel 		if ((len = mbtowc(&wc, cp, MB_CUR_MAX)) == -1) {
    119      0   stevel 			cp++;
    120      0   stevel 			continue;
    121      0   stevel 		}
    122      0   stevel 
    123      0   stevel 		if (len == 1 &&
    124      0   stevel 		    ((wc == L'`') || (wc == L'&') || (wc == L';') ||
    125      0   stevel 		    (wc == L'|') || (wc == L'>') || (wc == L'^') ||
    126      0   stevel 		    (wc == L'$') || (wc == L'(') || (wc == L')') ||
    127      0   stevel 		    (wc == L'<') || (wc == L'*') || (wc == L'?') ||
    128      0   stevel 		    (wc == L'[')))
    129      0   stevel 			*cp = '_';
    130      0   stevel 		cp += len;
    131      0   stevel 	}
    132      0   stevel }
    133      0   stevel 
    134      0   stevel enum trust {TRUSTED, UNTRUSTED};
    135   3204   jacobs 
    136   3204   jacobs static char *arg_string(enum trust type, char *fmt, ...) __PRINTFLIKE(2);
    137   3204   jacobs 
    138   3204   jacobs /* PRINTFLIKE2 */
    139      0   stevel static char *
    140      0   stevel arg_string(enum trust type, char *fmt, ...)
    141      0   stevel {
    142      0   stevel 	char buf[BUFSIZ];
    143      0   stevel 	va_list	args;
    144      0   stevel 
    145      0   stevel 	va_start(args, fmt);
    146      0   stevel 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
    147      0   stevel 	va_end(args);
    148      0   stevel 
    149      0   stevel 	/*
    150      0   stevel 	 * If the string contains data from an untrusted origin (user supplied),
    151      0   stevel 	 * clean it up in case one of our progeny is a shell script and isn't
    152      0   stevel 	 * careful about checking its input.
    153      0   stevel 	 */
    154      0   stevel 	if (type == UNTRUSTED)
    155      0   stevel 		clean_string(buf);
    156      0   stevel 
    157      0   stevel 	return (strdup(buf));
    158      0   stevel }
    159      0   stevel 
    160      0   stevel /* stolen from libc/gen/port/gen/execvp.c */
    161      0   stevel static const char *
    162      0   stevel execat(const char *s1, const char *s2, char *si)
    163      0   stevel {
    164      0   stevel         char    *s;
    165      0   stevel         int cnt = PATH_MAX + 1; /* number of characters in s2 */
    166      0   stevel 
    167      0   stevel         s = si;
    168      0   stevel         while (*s1 && *s1 != ':') {
    169      0   stevel                 if (cnt > 0) {
    170      0   stevel                         *s++ = *s1++;
    171      0   stevel                         cnt--;
    172      0   stevel                 } else
    173      0   stevel                         s1++;
    174      0   stevel         }
    175      0   stevel         if (si != s && cnt > 0) {
    176      0   stevel                 *s++ = '/';
    177      0   stevel                 cnt--;
    178      0   stevel         }
    179      0   stevel         while (*s2 && cnt > 0) {
    180      0   stevel                 *s++ = *s2++;
    181      0   stevel                 cnt--;
    182      0   stevel         }
    183      0   stevel         *s = '\0';
    184      0   stevel         return (*s1 ? ++s1: 0);
    185      0   stevel }
    186      0   stevel 
    187      0   stevel /*
    188      0   stevel  * Similiar to execvp(), execpt you can supply an environment and we always
    189      0   stevel  * use /bin/sh for shell scripts.  The PATH searched is the PATH in the
    190      0   stevel  * current environment, not the environment in the argument list.
    191      0   stevel  * This was pretty much stolen from libc/gen/port/execvp.c
    192      0   stevel  */
    193      0   stevel static int
    194      0   stevel execvpe(char *name, char *const argv[], char *const envp[])
    195      0   stevel {
    196      0   stevel 	char *path;
    197      0   stevel 	char fname[PATH_MAX+2];
    198      0   stevel 	char *newargs[256];
    199      0   stevel 	int i;
    200      0   stevel 	const char *cp;
    201      0   stevel 	unsigned etxtbsy = 1;
    202      0   stevel         int eacces = 0;
    203      0   stevel 
    204      0   stevel 	if (*name == '\0') {
    205      0   stevel 		errno = ENOENT;
    206      0   stevel 		return (-1);
    207      0   stevel 	}
    208      0   stevel 
    209      0   stevel 	if ((path = getenv("PATH")) == NULL)
    210      0   stevel 		path = "/usr/bin:/bin";
    211      0   stevel 
    212      0   stevel         cp = strchr(name, '/')? (const char *)"": path;
    213      0   stevel 
    214      0   stevel         do {
    215      0   stevel                 cp = execat(cp, name, fname);
    216      0   stevel         retry:
    217      0   stevel                 /*
    218      0   stevel                  * 4025035 and 4038378
    219      0   stevel                  * if a filename begins with a "-" prepend "./" so that
    220      0   stevel                  * the shell can't interpret it as an option
    221      0   stevel                  */
    222      0   stevel                 if (*fname == '-') {
    223      0   stevel                         size_t size = strlen(fname) + 1;
    224      0   stevel                         if ((size + 2) > sizeof (fname)) {
    225      0   stevel                                 errno = E2BIG;
    226      0   stevel                                 return (-1);
    227      0   stevel                         }
    228      0   stevel                         (void) memmove(fname + 2, fname, size);
    229      0   stevel                         fname[0] = '.';
    230      0   stevel                         fname[1] = '/';
    231      0   stevel                 }
    232      0   stevel                 (void) execve(fname, argv, envp);
    233      0   stevel                 switch (errno) {
    234      0   stevel                 case ENOEXEC:
    235      0   stevel                         newargs[0] = "sh";
    236      0   stevel                         newargs[1] = fname;
    237      0   stevel                         for (i = 1; (newargs[i + 1] = argv[i]) != NULL; ++i) {
    238      0   stevel                                 if (i >= 254) {
    239      0   stevel                                         errno = E2BIG;
    240      0   stevel                                         return (-1);
    241      0   stevel                                 }
    242      0   stevel                         }
    243      0   stevel                         (void) execve("/bin/sh", newargs, envp);
    244      0   stevel                         return (-1);
    245      0   stevel                 case ETXTBSY:
    246      0   stevel                         if (++etxtbsy > 5)
    247      0   stevel                                 return (-1);
    248      0   stevel                         (void) sleep(etxtbsy);
    249      0   stevel                         goto retry;
    250      0   stevel                 case EACCES:
    251      0   stevel                         ++eacces;
    252      0   stevel                         break;
    253      0   stevel                 case ENOMEM:
    254      0   stevel                 case E2BIG:
    255      0   stevel                 case EFAULT:
    256      0   stevel                         return (-1);
    257      0   stevel                 }
    258      0   stevel         } while (cp);
    259      0   stevel         if (eacces)
    260      0   stevel                 errno = EACCES;
    261      0   stevel         return (-1);
    262      0   stevel }
    263      0   stevel 
    264      0   stevel static char time_buf[50];
    265   1676      jpk 
    266      0   stevel /**
    267      0   stevel  ** exec() - FORK AND EXEC CHILD PROCESS
    268      0   stevel  **/
    269      0   stevel 
    270      0   stevel /*VARARGS1*/
    271      0   stevel int
    272      0   stevel exec(int type, ...)
    273      0   stevel {
    274      0   stevel 	va_list			args;
    275      0   stevel 
    276      0   stevel 	int			i;
    277      0   stevel 	int			procuid;
    278      0   stevel 	int			procgid;
    279      0   stevel 	int			ret;
    280      0   stevel 	int			fr_flg;
    281      0   stevel 
    282      0   stevel 	char			*cp;
    283      0   stevel 	char			*infile;
    284      0   stevel 	char			*outfile;
    285      0   stevel 	char			*errfile;
    286      0   stevel 	char			*sep;
    287      0   stevel 
    288      0   stevel 	char			**listp;
    289      0   stevel 	char			**file_list;
    290      0   stevel 	char			*printerName;
    291      0   stevel 	char			*printerNameToShow;
    292      0   stevel 	static char		nameBuf[100];
    293      0   stevel 	char			*clean_title;
    294      0   stevel 
    295      0   stevel 	PSTATUS			*printer;
    296      0   stevel 
    297      0   stevel 	RSTATUS			*request;
    298      0   stevel 
    299      0   stevel 	FSTATUS			*form;
    300      0   stevel 
    301      0   stevel 	EXEC			*ep;
    302      0   stevel 
    303      0   stevel 	PWSTATUS		*pwheel;
    304      0   stevel 	time_t			now;
    305      0   stevel 	struct passwd		*pwp;
    306      0   stevel #ifdef LP_USE_PAPI_ATTR
    307      0   stevel 	struct stat		tmpBuf;
    308      0   stevel 	char 			tmpName[BUFSIZ];
    309      0   stevel 	char			*path = NULL;
    310      0   stevel #endif
    311      0   stevel 	char *av[ARG_MAX];
    312      0   stevel 	char **envp = NULL;
    313      0   stevel 	int ac = 0;
    314   1676      jpk 	char	*mail_zonename = NULL;
    315   1676      jpk 	char	*slabel = NULL;
    316  10460    Sonam 	int	setid = 1;
    317  10460    Sonam 	char	*ridno = NULL;
    318      0   stevel 
    319      0   stevel 	syslog(LOG_DEBUG, "exec(%s)", _exec_name(type));
    320      0   stevel 
    321      0   stevel 	memset(av, 0, sizeof (*av));
    322      0   stevel 
    323      0   stevel 	va_start (args, type);
    324      0   stevel 
    325      0   stevel 	switch (type) {
    326      0   stevel 
    327      0   stevel 	case EX_INTERF:
    328      0   stevel 		printer = va_arg(args, PSTATUS *);
    329      0   stevel 		request = printer->request;
    330      0   stevel 		ep = printer->exec;
    331      0   stevel 		break;
    332      0   stevel 
    333      0   stevel 	case EX_FAULT_MESSAGE:
    334      0   stevel 		printer = va_arg(args, PSTATUS *);
    335      0   stevel 		request = va_arg(args, RSTATUS *);
    336      0   stevel 		if (! ( printer->status & (PS_FORM_FAULT | PS_SHOW_FAULT))) {
    337      0   stevel 			return(0);
    338      0   stevel 		}
    339      0   stevel 		ep = printer->fault_exec;
    340      0   stevel 		printerName = (printer->printer && printer->printer->name
    341      0   stevel 				  ? printer->printer->name : "??");
    342      0   stevel 			snprintf(nameBuf, sizeof (nameBuf),
    343      0   stevel 				"%s (on %s)\n", printerName, Local_System);
    344      0   stevel 
    345      0   stevel 		printerNameToShow = nameBuf;
    346      0   stevel 
    347      0   stevel 		(void) time(&now);
    348      0   stevel 		(void) strftime(time_buf, sizeof (time_buf),
    349      0   stevel 			NULL, localtime(&now));
    350      0   stevel 		break;
    351      0   stevel 
    352      0   stevel 	case EX_SLOWF:
    353      0   stevel 		request = va_arg(args, RSTATUS *);
    354      0   stevel 		ep = request->exec;
    355      0   stevel 		break;
    356      0   stevel 
    357      0   stevel 	case EX_NOTIFY:
    358      0   stevel 		request = va_arg(args, RSTATUS *);
    359      0   stevel 		if (request->request->actions & ACT_NOTIFY) {
    360      0   stevel 			errno = EINVAL;
    361      0   stevel 			return (-1);
    362      0   stevel 		}
    363      0   stevel 		ep = request->exec;
    364      0   stevel 		break;
    365      0   stevel 
    366      0   stevel 	case EX_ALERT:
    367      0   stevel 		printer = va_arg(args, PSTATUS *);
    368      0   stevel 		if (!(printer->printer->fault_alert.shcmd)) {
    369      0   stevel 			errno = EINVAL;
    370      0   stevel 			return(-1);
    371      0   stevel 		}
    372      0   stevel 		ep = printer->alert->exec;
    373      0   stevel 		break;
    374      0   stevel 
    375      0   stevel 	case EX_PALERT:
    376      0   stevel 		pwheel = va_arg(args, PWSTATUS *);
    377      0   stevel 		ep = pwheel->alert->exec;
    378      0   stevel 		break;
    379      0   stevel 
    380      0   stevel 	case EX_FORM_MESSAGE:
    381      0   stevel 		(void) time(&now);
    382      0   stevel 		(void) strftime(time_buf, sizeof (time_buf),
    383      0   stevel 			NULL, localtime(&now));
    384      0   stevel 
    385      0   stevel 		/*FALLTHRU*/
    386      0   stevel 	case EX_FALERT:
    387      0   stevel 		form = va_arg(args, FSTATUS *);
    388      0   stevel 		ep = form->alert->exec;
    389      0   stevel 		break;
    390      0   stevel 
    391      0   stevel 	default:
    392      0   stevel 		errno = EINVAL;
    393      0   stevel 		return(-1);
    394      0   stevel 
    395      0   stevel 	}
    396      0   stevel 	va_end (args);
    397      0   stevel 
    398      0   stevel 	if (!ep || (ep->pid > 0)) {
    399      0   stevel 		errno = EBUSY;
    400      0   stevel 		return(-1);
    401      0   stevel 	}
    402      0   stevel 
    403      0   stevel 	ep->flags = 0;
    404      0   stevel 
    405      0   stevel 	key = ep->key = getkey();
    406      0   stevel 
    407      0   stevel 	switch ((ep->pid = Fork1(ep))) {
    408      0   stevel 
    409      0   stevel 	case -1:
    410      0   stevel 		relock ();
    411      0   stevel 		return(-1);
    412      0   stevel 
    413      0   stevel 	case 0:
    414      0   stevel 		/*
    415      0   stevel 		 * We want to be able to tell our parent how we died.
    416      0   stevel 		 */
    417      0   stevel 		lp_alloc_fail_handler = child_mallocfail;
    418      0   stevel 		break;
    419      0   stevel 
    420      0   stevel 	default:
    421      0   stevel 		switch(type) {
    422      0   stevel 
    423      0   stevel 		case EX_INTERF:
    424      0   stevel 			request->request->outcome |= RS_PRINTING;
    425      0   stevel 			break;
    426      0   stevel 
    427      0   stevel 		case EX_NOTIFY:
    428      0   stevel 			request->request->outcome |= RS_NOTIFYING;
    429      0   stevel 			break;
    430      0   stevel 
    431      0   stevel 		case EX_SLOWF:
    432      0   stevel 			request->request->outcome |= RS_FILTERING;
    433      0   stevel 			request->request->outcome &= ~RS_REFILTER;
    434      0   stevel 			break;
    435      0   stevel 
    436      0   stevel 		}
    437      0   stevel 		return(0);
    438      0   stevel 
    439      0   stevel 	}
    440      0   stevel 
    441      0   stevel 	for (i = 0; i < NSIG; i++)
    442      0   stevel 		(void)signal (i, SIG_DFL);
    443      0   stevel 	(void)signal (SIGALRM, SIG_IGN);
    444      0   stevel 	(void)signal (SIGTERM, sigtrap);
    445   3125   jacobs 
    446   3125   jacobs 	closelog();
    447      0   stevel 	for (i = 0; i < OpenMax; i++)
    448      0   stevel 		if (i != ChildMd->writefd)
    449      0   stevel 			Close (i);
    450   3125   jacobs 	openlog("lpsched", LOG_PID|LOG_NDELAY|LOG_NOWAIT, LOG_LPR);
    451   3125   jacobs 
    452      0   stevel 	setpgrp();
    453      0   stevel 
    454      0   stevel 	/* Set a default path */
    455      0   stevel 	addenv (&envp, "PATH", "/usr/lib/lp/bin:/usr/bin:/bin:/usr/sbin:/sbin");
    456      0   stevel 	/* copy locale related variables */
    457      0   stevel 	addenv (&envp, "TZ", getenv("TZ"));
    458      0   stevel 	addenv (&envp, "LANG", getenv("LANG"));
    459      0   stevel 	addenv (&envp, "LC_ALL", getenv("LC_ALL"));
    460      0   stevel 	addenv (&envp, "LC_COLLATE", getenv("LC_COLLATE"));
    461      0   stevel 	addenv (&envp, "LC_CTYPE", getenv("LC_CTYPE"));
    462      0   stevel 	addenv (&envp, "LC_MESSAGES", getenv("LC_MESSAGES"));
    463      0   stevel 	addenv (&envp, "LC_MONETARY", getenv("LC_MONETARY"));
    464      0   stevel 	addenv (&envp, "LC_NUMERIC", getenv("LC_NUMERIC"));
    465      0   stevel 	addenv (&envp, "LC_TIME", getenv("LC_TIME"));
    466      0   stevel 
    467      0   stevel 	sprintf ((cp = BIGGEST_NUMBER_S), "%ld", key);
    468      0   stevel 	addenv (&envp, "SPOOLER_KEY", cp);
    469      0   stevel 
    470      0   stevel #if	defined(DEBUG)
    471      0   stevel 	addenv (&envp, "LPDEBUG", (debug? "1" : "0"));
    472      0   stevel #endif
    473      0   stevel 
    474      0   stevel 	/*
    475      0   stevel 	 * Open the standard input, standard output, and standard error.
    476      0   stevel 	 */
    477      0   stevel 	switch (type) {
    478      0   stevel 
    479      0   stevel 	case EX_SLOWF:
    480      0   stevel 	case EX_INTERF:
    481      0   stevel 		/*
    482      0   stevel 		 * stdin:  /dev/null
    483      0   stevel 		 * stdout: /dev/null (EX_SLOWF), printer port (EX_INTERF)
    484      0   stevel 		 * stderr: req#
    485      0   stevel 		 */
    486      0   stevel 		infile = 0;
    487      0   stevel 		outfile = 0;
    488      0   stevel 		errfile = makereqerr(request);
    489      0   stevel 		break;
    490      0   stevel 
    491      0   stevel 	case EX_NOTIFY:
    492      0   stevel 		/*
    493      0   stevel 		 * stdin:  req#
    494      0   stevel 		 * stdout: /dev/null
    495      0   stevel 		 * stderr: /dev/null
    496      0   stevel 		 */
    497      0   stevel 		infile = makereqerr(request);
    498      0   stevel 		outfile = 0;
    499      0   stevel 		errfile = 0;
    500      0   stevel 
    501      0   stevel 		break;
    502      0   stevel 
    503      0   stevel 	case EX_ALERT:
    504      0   stevel 	case EX_FALERT:
    505      0   stevel 	case EX_PALERT:
    506      0   stevel 	case EX_FAULT_MESSAGE:
    507      0   stevel 	case EX_FORM_MESSAGE:
    508      0   stevel 		/*
    509      0   stevel 		 * stdin:  /dev/null
    510      0   stevel 		 * stdout: /dev/null
    511      0   stevel 		 * stderr: /dev/null
    512      0   stevel 		 */
    513      0   stevel 		infile = 0;
    514      0   stevel 		outfile = 0;
    515      0   stevel 		errfile = 0;
    516      0   stevel 		break;
    517      0   stevel 
    518      0   stevel 	}
    519      0   stevel 
    520      0   stevel 	if (infile) {
    521      0   stevel 		if (Open(infile, O_RDONLY) == -1)
    522      0   stevel 			Done (EXEC_EXIT_NOPEN, errno);
    523      0   stevel 	} else {
    524      0   stevel 		if (Open("/dev/null", O_RDONLY) == -1)
    525      0   stevel 			Done (EXEC_EXIT_NOPEN, errno);
    526      0   stevel 	}
    527      0   stevel 
    528      0   stevel 	if (outfile) {
    529      0   stevel 		if (Open(outfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1)
    530      0   stevel 			Done (EXEC_EXIT_NOPEN, errno);
    531      0   stevel 	} else {
    532      0   stevel 		/*
    533      0   stevel 		 * If EX_INTERF, this is still needed to cause the
    534      0   stevel 		 * standard error channel to be #2.
    535      0   stevel 		 */
    536      0   stevel 		if (Open("/dev/null", O_WRONLY) == -1)
    537      0   stevel 			Done (EXEC_EXIT_NOPEN, errno);
    538      0   stevel 	}
    539      0   stevel 
    540      0   stevel 	if (errfile) {
    541      0   stevel 		if (Open(errfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1)
    542      0   stevel 			Done (EXEC_EXIT_NOPEN, errno);
    543      0   stevel 	} else {
    544      0   stevel 		if (Open("/dev/null", O_WRONLY) == -1)
    545      0   stevel 			Done (EXEC_EXIT_NOPEN, errno);
    546      0   stevel 	}
    547      0   stevel 
    548      0   stevel 	switch (type) {
    549      0   stevel 
    550      0   stevel 	case EX_INTERF:
    551      0   stevel 		/*
    552      0   stevel 		 * Opening a ``port'' can be dangerous to our health:
    553      0   stevel 		 *
    554      0   stevel 		 *	- Hangups can occur if the line is dropped.
    555      0   stevel 		 *	- The printer may send an interrupt.
    556      0   stevel 		 *	- A FIFO may be closed, generating SIGPIPE.
    557      0   stevel 		 *
    558      0   stevel 		 * We catch these so we can complain nicely.
    559      0   stevel 		 */
    560      0   stevel 		trap_fault_signals ();
    561      0   stevel 
    562      0   stevel 		(void)Close (1);
    563      0   stevel 
    564   3125   jacobs 		if (strchr (request->request->user, '@'))
    565      0   stevel 		{
    566      0   stevel 			procuid = Lp_Uid;
    567      0   stevel 			procgid = Lp_Gid;
    568      0   stevel 		}
    569      0   stevel 		else
    570      0   stevel 		{
    571      0   stevel 			procuid = request->secure->uid;
    572      0   stevel 			procgid = request->secure->gid;
    573      0   stevel 		}
    574      0   stevel 		if (printer->printer->dial_info)
    575      0   stevel 		{
    576      0   stevel 			ret = open_dialup(request->printer_type,
    577      0   stevel 				printer->printer);
    578      0   stevel 			if (ret == 0)
    579      0   stevel 				do_undial = 1;
    580      0   stevel 		}
    581      0   stevel 		else
    582      0   stevel 		{
    583      0   stevel 			ret = open_direct(request->printer_type,
    584      0   stevel 				printer->printer);
    585      0   stevel 			do_undial = 0;
    586      0   stevel 			/* this is a URI */
    587      0   stevel 			if (is_printer_uri(printer->printer->device) == 0)
    588      0   stevel 				addenv(&envp, "DEVICE_URI",
    589      0   stevel 					 printer->printer->device);
    590      0   stevel 		}
    591      0   stevel 				addenv(&envp, "DEVICE_URI",
    592      0   stevel 					 printer->printer->device);
    593      0   stevel 		if (ret != 0)
    594      0   stevel 			Done (ret, errno);
    595      0   stevel 
    596      0   stevel 		if (!(request->request->outcome & RS_FILTERED))
    597      0   stevel 			file_list = request->request->file_list;
    598      0   stevel 
    599      0   stevel 		else {
    600      0   stevel 			register int		count	= 0;
    601      0   stevel 			register char *		num	= BIGGEST_REQID_S;
    602      0   stevel 			register char *		prefix;
    603      0   stevel 
    604      0   stevel 			prefix = makestr(
    605   3125   jacobs 				Lp_Temp,
    606      0   stevel 				"/F",
    607      0   stevel 				getreqno(request->secure->req_id),
    608      0   stevel 				"-",
    609      0   stevel 				(char *)0
    610      0   stevel 			);
    611      0   stevel 
    612      0   stevel 			file_list = (char **)Malloc(
    613      0   stevel 				(lenlist(request->request->file_list) + 1)
    614      0   stevel 			      * sizeof(char *)
    615      0   stevel 			);
    616      0   stevel 
    617      0   stevel 			for (
    618      0   stevel 				listp = request->request->file_list;
    619      0   stevel 				*listp;
    620      0   stevel 				listp++
    621      0   stevel 			) {
    622      0   stevel 				sprintf (num, "%d", count + 1);
    623      0   stevel 				file_list[count] = makestr(
    624      0   stevel 					prefix,
    625      0   stevel 					num,
    626      0   stevel 					(char *)0
    627      0   stevel 				);
    628      0   stevel 				count++;
    629      0   stevel 			}
    630      0   stevel 			file_list[count] = 0;
    631      0   stevel 		}
    632      0   stevel 
    633      0   stevel #ifdef LP_USE_PAPI_ATTR
    634      0   stevel 		/*
    635      0   stevel 		 * Check if the PAPI job attribute file exists, if it does
    636      0   stevel 		 * pass the file's pathname to the printer interface script
    637      0   stevel 		 * in an environment variable. This file is created when
    638      0   stevel 		 * print jobs are submitted via the PAPI interface.
    639      0   stevel 		 */
    640      0   stevel 		snprintf(tmpName, sizeof (tmpName), "%s-%s",
    641      0   stevel 			getreqno(request->secure->req_id), LP_PAPIATTRNAME);
    642   3125   jacobs 		path = makepath(Lp_Temp, tmpName, (char *)0);
    643      0   stevel 		if ((path != NULL) && (stat(path, &tmpBuf) == 0))
    644      0   stevel 		{
    645      0   stevel 			/*
    646      0   stevel 			 * IPP job attribute file exists for this job so
    647      0   stevel 			 * set the environment variable
    648      0   stevel 			 */
    649      0   stevel 			addenv(&envp, "ATTRPATH", path);
    650      0   stevel 		}
    651      0   stevel 		Free(path);
    652      0   stevel 
    653      0   stevel 		/*
    654      0   stevel 		 * now set environment variable for the printer's PostScript
    655      0   stevel 		 * Printer Description (PPD) file, this is used by the filter
    656      0   stevel 		 * when forming the print data for this printer.
    657      0   stevel 		 */
    658      0   stevel 		if ((request->printer != NULL) &&
    659      0   stevel 		    (request->printer->printer != NULL) &&
    660      0   stevel 		    (request->printer->printer->name != NULL))
    661      0   stevel 		{
    662      0   stevel 			snprintf(tmpName, sizeof (tmpName), "%s.ppd",
    663      0   stevel 				request->printer->printer->name);
    664      0   stevel 			path = makepath(ETCDIR, "ppd", tmpName, (char *)0);
    665      0   stevel 			if ((path != NULL) && (stat(path, &tmpBuf) == 0))
    666      0   stevel 			{
    667      0   stevel 				addenv(&envp, "PPD", path);
    668      0   stevel 			}
    669      0   stevel 			Free(path);
    670      0   stevel 		}
    671      0   stevel #endif
    672      0   stevel 
    673      0   stevel 		if (request->printer_type)
    674      0   stevel 			addenv(&envp, "TERM", request->printer_type);
    675      0   stevel 
    676      0   stevel 		if (!(printer->printer->daisy)) {
    677      0   stevel 			register char *	chset = 0;
    678      0   stevel 			register char *	csp;
    679      0   stevel 
    680      0   stevel 			if (
    681      0   stevel 				request->form
    682      0   stevel 			     && request->form->form->chset
    683      0   stevel 			     && request->form->form->mandatory
    684      0   stevel 			     && !STREQU(NAME_ANY, request->form->form->chset)
    685      0   stevel 			)
    686      0   stevel 				chset = request->form->form->chset;
    687      0   stevel 
    688      0   stevel 			else if (
    689      0   stevel 				request->request->charset
    690      0   stevel 			     && !STREQU(NAME_ANY, request->request->charset)
    691      0   stevel 			)
    692      0   stevel 				chset = request->request->charset;
    693      0   stevel 
    694      0   stevel 			if (chset) {
    695      0   stevel 				csp = search_cslist(
    696      0   stevel 					chset,
    697      0   stevel 					printer->printer->char_sets
    698      0   stevel 				);
    699      0   stevel 
    700      0   stevel 				/*
    701      0   stevel 				 * The "strtok()" below wrecks the string
    702      0   stevel 				 * for future use, but this is a child
    703      0   stevel 				 * process where it won't be needed again.
    704      0   stevel 				 */
    705      0   stevel 				addenv (&envp, "CHARSET",
    706      0   stevel 					(csp? strtok(csp, "=") : chset)
    707      0   stevel 				);
    708      0   stevel 			}
    709      0   stevel 		}
    710      0   stevel 
    711      0   stevel 		if (request->fast)
    712      0   stevel 			addenv(&envp, "FILTER", request->fast);
    713      0   stevel 
    714      0   stevel 		/*
    715   1676      jpk 		 * Add the sensitivity label to the environment for
    716   1676      jpk 		 * banner page and header/footer processing
    717   1676      jpk 		 */
    718   1676      jpk 
    719   1676      jpk 		if (is_system_labeled() && request->secure->slabel != NULL)
    720   1676      jpk 			addenv(&envp, "SLABEL", request->secure->slabel);
    721   1676      jpk 
    722   1676      jpk 		/*
    723      0   stevel 		 * Add the system name to the user name (ala system!user)
    724      0   stevel 		 * unless it is already there. RFS users may have trouble
    725      0   stevel 		 * here, sorry!
    726      0   stevel 		 */
    727      0   stevel 		cp = strchr(request->secure->user, '@');
    728      0   stevel 
    729      0   stevel 		allTraysWithForm(printer, request->form);
    730      0   stevel 
    731      0   stevel 		/*
    732      0   stevel 		 * Fix for 4137389
    733      0   stevel 		 * Remove double quotes from title string.
    734      0   stevel 		 */
    735      0   stevel 		fr_flg = 1;
    736      0   stevel 		clean_title = strdup(NB(request->request->title));
    737      0   stevel 		if (clean_title == NULL) {
    738      0   stevel 			/*
    739      0   stevel 			 * strdup failed. We're probably hosed
    740      0   stevel 			 * but try setting clean_title
    741      0   stevel 			 * to original title and continuing.
    742      0   stevel 			 */
    743      0   stevel 			clean_title = NB(request->request->title);
    744      0   stevel 			fr_flg = 0;
    745      0   stevel 		} else if (strcmp(clean_title, "") != 0) {
    746      0   stevel 			char *ct_p;
    747      0   stevel 
    748      0   stevel 			for (ct_p = clean_title; *ct_p != NULL; ct_p++) {
    749      0   stevel 				if (*ct_p == '"')
    750      0   stevel 					*ct_p = ' ';
    751      0   stevel 			}
    752      0   stevel 		}
    753      0   stevel 
    754      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_A_Interfaces,
    755      0   stevel 					printer->printer->name);
    756  10460    Sonam 		/*
    757  10460    Sonam 		 * Read the options field of the request
    758  10460    Sonam 		 * In case of remote lpd request
    759  10460    Sonam 		 * the options field will have
    760  10460    Sonam 		 * job-id-requested. This is the
    761  10460    Sonam 		 * id sent by the client
    762  10460    Sonam 		 */
    763  10460    Sonam 		if (request->request->options != NULL) {
    764  10460    Sonam 			char *options = NULL, *temp = NULL;
    765  10460    Sonam 			options = temp = strdup(request->request->options);
    766  10460    Sonam 
    767  10460    Sonam 			/*
    768  10460    Sonam 			 * Search for job-id-requested in
    769  10460    Sonam 			 * options string
    770  10460    Sonam 			 */
    771  10460    Sonam 			options = strstr(options, "job-id-requested");
    772  10460    Sonam 			if (options != NULL) {
    773  10460    Sonam 				/*
    774  10460    Sonam 				 * Extract the ridno from the string
    775  10460    Sonam 				 * job-id-requested=xxx
    776  10460    Sonam 				 * In this case ridno = xxx
    777  10460    Sonam 				 */
    778  10460    Sonam 				if (STRNEQU(options, "job-id-requested=", 17)) {
    779  10460    Sonam 					ridno = strdup(options + 17);
    780  10460    Sonam 					if (ridno != NULL)
    781  10460    Sonam 						/*
    782  10460    Sonam 						 * Read job-id-requested
    783  10460    Sonam 						 * successfully
    784  10460    Sonam 						 */
    785  10460    Sonam 						setid = 0;
    786  10460    Sonam 					else
    787  10460    Sonam 						/*
    788  10460    Sonam 						 * could not read
    789  10460    Sonam 						 * ridno from the string
    790  10460    Sonam 						 * job-id-requested=xxx
    791  10460    Sonam 						 */
    792  10460    Sonam 						setid = 1;
    793  10460    Sonam 				} else
    794  10460    Sonam 					/*
    795  10460    Sonam 					 * could not read
    796  10460    Sonam 					 * ridno from the string
    797  10460    Sonam 					 * job-id-requested=xxx
    798  10460    Sonam 					 */
    799  10460    Sonam 					setid = 1;
    800  10460    Sonam 			} else
    801  10460    Sonam 				/*
    802  10460    Sonam 				 * No job-id-requested in
    803  10460    Sonam 				 * request options
    804  10460    Sonam 				 */
    805  10460    Sonam 				setid = 1;
    806  10460    Sonam 
    807  10460    Sonam 			if (temp != NULL)
    808  10460    Sonam 				free(temp);
    809  10460    Sonam 
    810  10460    Sonam 		} else
    811  10460    Sonam 			/*
    812  10460    Sonam 			 * options field in request structure
    813  10460    Sonam 			 * not set
    814  10460    Sonam 			 */
    815  10460    Sonam 			setid = 1;
    816  10460    Sonam 
    817  10460    Sonam 
    818  10460    Sonam 		/*
    819  10460    Sonam 		 * setid = 1 means the job-id-requested attribute
    820  10460    Sonam 		 * is not set so read the request->secure->req_id
    821  10460    Sonam 		 */
    822  10460    Sonam 		if (setid)
    823  10460    Sonam 			av[ac++] = arg_string(TRUSTED, "%s",
    824  10460    Sonam 			    request->secure->req_id);
    825  10460    Sonam 		else {
    826  10460    Sonam 			/*
    827  10460    Sonam 			 * From request->secure->req_id extract the
    828  10460    Sonam 			 * printer-name.
    829  10460    Sonam 			 * request->secure->req_id = <printer-name>-<req_id>
    830  10460    Sonam 			 * The final req-id will be
    831  10460    Sonam 			 * <printer-name>-<ridno>
    832  10460    Sonam 			 */
    833  10460    Sonam 			char *r1 = NULL, *r2 = NULL, *tmp = NULL;
    834  10460    Sonam 			r1 = r2 = tmp = strdup(request->secure->req_id);
    835  10460    Sonam 			r2 = strrchr(r1, '-');
    836  10460    Sonam 			if (r2 != NULL) {
    837  10460    Sonam 				char *r3 = NULL;
    838  10460    Sonam 				int lr1 = strlen(r1);
    839  10460    Sonam 				int lr2 = strlen(r2);
    840  10460    Sonam 				r1[lr1 - lr2 + 1] = '\0';
    841  10460    Sonam 
    842  10460    Sonam 				/*
    843  10460    Sonam 				 * Now r1 = <printer-name>-
    844  10460    Sonam 				 */
    845  10460    Sonam 				lr1 = strlen(r1);
    846  10460    Sonam 				lr2 = strlen(ridno);
    847  10460    Sonam 
    848  10460    Sonam 				r3 = (char *)malloc(lr1+lr2+1);
    849  10460    Sonam 				if (r3 != NULL) {
    850  10460    Sonam 					strcpy(r3, r1);
    851  10460    Sonam 					strcat(r3, ridno);
    852  10460    Sonam 					/*
    853  10460    Sonam 					 * Here r3 = <printer-name>-<ridno>
    854  10460    Sonam 					 */
    855  10460    Sonam 					av[ac++] = arg_string(TRUSTED,
    856  10460    Sonam 					    "%s", r3);
    857  10460    Sonam 					free(r3);
    858  10460    Sonam 				} else
    859  10460    Sonam 					av[ac++] = arg_string(TRUSTED, "%s",
    860  10460    Sonam 					    request->secure->req_id);
    861  10460    Sonam 
    862  10460    Sonam 			} else
    863  10460    Sonam 				av[ac++] = arg_string(TRUSTED, "%s",
    864  10460    Sonam 				    request->secure->req_id);
    865  10460    Sonam 
    866  10460    Sonam 			if (tmp != NULL)
    867  10460    Sonam 				free(tmp);
    868  10460    Sonam 
    869  10460    Sonam 			if (ridno != NULL)
    870  10460    Sonam 				free(ridno);
    871  10460    Sonam 		}
    872  10460    Sonam 
    873   3125   jacobs 		av[ac++] = arg_string(UNTRUSTED, "%s", request->request->user);
    874      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s", clean_title);
    875      0   stevel 		av[ac++] = arg_string(TRUSTED, "%d", request->copies);
    876      0   stevel 
    877      0   stevel 		if (fr_flg)
    878      0   stevel 			free (clean_title);
    879      0   stevel 
    880      0   stevel 		sep = "";
    881      0   stevel 
    882      0   stevel 		/*
    883      0   stevel 		 * Do the administrator defined key=value pair options
    884      0   stevel 		 */
    885      0   stevel 
    886      0   stevel 		argbuf[0] = '\0';
    887      0   stevel 
    888      0   stevel 		if (printer->printer->options) {
    889      0   stevel 			char **tmp = printer->printer->options;
    890      0   stevel 			while(*tmp != NULL) {
    891      0   stevel 				STRLCAT(argbuf, sep, sizeof (argbuf));
    892      0   stevel 				sep = " ";
    893      0   stevel 				STRLCAT(argbuf, *tmp++, sizeof (argbuf));
    894      0   stevel 			}
    895      0   stevel 		}
    896      0   stevel 
    897      0   stevel 		/*
    898      0   stevel 		 * Do the administrator defined ``stty'' stuff before
    899      0   stevel 		 * the user's -o options, to allow the user to override.
    900      0   stevel 		 */
    901      0   stevel 		if (printer->printer->stty) {
    902      0   stevel 			STRLCAT (argbuf, sep, sizeof (argbuf));
    903      0   stevel 			sep = " ";
    904      0   stevel 			STRLCAT (argbuf, "stty='", sizeof (argbuf));
    905      0   stevel 			STRLCAT (argbuf, printer->printer->stty,
    906      0   stevel 			    sizeof (argbuf));
    907      0   stevel 			STRLCAT (argbuf, "'", sizeof (argbuf));
    908      0   stevel 		}
    909      0   stevel 
    910      0   stevel 		/*
    911      0   stevel 		 * Do all of the user's options except the cpi/lpi/etc.
    912      0   stevel 		 * stuff, which is done separately.
    913      0   stevel 		 */
    914      0   stevel 		if (request->request->options) {
    915      0   stevel 			listp = dashos(request->request->options);
    916      0   stevel 			while (*listp) {
    917      0   stevel 				if (
    918      0   stevel 					!STRNEQU(*listp, "cpi=", 4)
    919      0   stevel 				     && !STRNEQU(*listp, "lpi=", 4)
    920      0   stevel 				     && !STRNEQU(*listp, "width=", 6)
    921      0   stevel 				     && !STRNEQU(*listp, "length=", 7)
    922      0   stevel 				) {
    923      0   stevel 					STRLCAT (argbuf, sep, sizeof (argbuf));
    924      0   stevel 					sep = " ";
    925      0   stevel 					STRLCAT (argbuf, *listp,
    926      0   stevel 					    sizeof (argbuf));
    927      0   stevel 				}
    928      0   stevel 				listp++;
    929      0   stevel 			}
    930      0   stevel 		}
    931      0   stevel 
    932      0   stevel 		/*
    933      0   stevel 		 * The "pickfilter()" routine (from "validate()")
    934      0   stevel 		 * stored the cpi/lpi/etc. stuff that should be
    935      0   stevel 		 * used for this request. It chose form over user,
    936      0   stevel 		 * and user over printer.
    937      0   stevel 		 */
    938      0   stevel 		if (request->cpi) {
    939      0   stevel 			STRLCAT (argbuf, sep, sizeof (argbuf));
    940      0   stevel 			sep = " ";
    941      0   stevel 			STRLCAT (argbuf, "cpi=", sizeof (argbuf));
    942      0   stevel 			STRLCAT (argbuf, request->cpi, sizeof (argbuf));
    943      0   stevel 		}
    944      0   stevel 		if (request->lpi) {
    945      0   stevel 			STRLCAT (argbuf, sep, sizeof (argbuf));
    946      0   stevel 			sep = " ";
    947      0   stevel 			STRLCAT (argbuf, "lpi=", sizeof (argbuf));
    948      0   stevel 			STRLCAT (argbuf, request->lpi, sizeof (argbuf));
    949      0   stevel 		}
    950      0   stevel 		if (request->pwid) {
    951      0   stevel 			STRLCAT (argbuf, sep, sizeof (argbuf));
    952      0   stevel 			sep = " ";
    953      0   stevel 			STRLCAT (argbuf, "width=", sizeof (argbuf));
    954      0   stevel 			STRLCAT (argbuf, request->pwid, sizeof (argbuf));
    955      0   stevel 		}
    956      0   stevel 		if (request->plen) {
    957      0   stevel 			STRLCAT (argbuf, sep, sizeof (argbuf));
    958      0   stevel 			sep = " ";
    959      0   stevel 			STRLCAT (argbuf, "length=", sizeof (argbuf));
    960      0   stevel 			STRLCAT (argbuf, request->plen, sizeof (argbuf));
    961      0   stevel 		}
    962      0   stevel 
    963      0   stevel 		/*
    964      0   stevel 		 * Do the ``raw'' bit last, to ensure it gets
    965      0   stevel 		 * done. If the user doesn't want this, then he or
    966      0   stevel 		 * she can do the correct thing using -o stty=
    967      0   stevel 		 * and leaving out the -r option.
    968      0   stevel 		 */
    969      0   stevel 		if (request->request->actions & ACT_RAW) {
    970      0   stevel 			STRLCAT (argbuf, sep, sizeof (argbuf));
    971      0   stevel 			sep = " ";
    972      0   stevel 			STRLCAT (argbuf, "stty=-opost", sizeof (argbuf));
    973      0   stevel 		}
    974      0   stevel 
    975      0   stevel 
    976      0   stevel 		/* the "options" */
    977      0   stevel 		av[ac++] = arg_string(UNTRUSTED, "%s", argbuf);
    978      0   stevel 
    979      0   stevel 		for (listp = file_list; *listp; listp++)
    980      0   stevel 			av[ac++] = arg_string(TRUSTED, "%s", *listp);
    981      0   stevel 
    982      0   stevel 		(void)chfiles (file_list, procuid, procgid);
    983      0   stevel 
    984      0   stevel 		break;
    985      0   stevel 
    986      0   stevel 
    987      0   stevel 	case EX_SLOWF:
    988      0   stevel 		if (request->slow)
    989      0   stevel 			addenv(&envp, "FILTER", request->slow);
    990      0   stevel 
    991   3125   jacobs 		if (strchr (request->request->user, '@'))
    992      0   stevel 		{
    993      0   stevel 			procuid = Lp_Uid;
    994      0   stevel 			procgid = Lp_Gid;
    995      0   stevel 		}
    996      0   stevel 		else
    997      0   stevel 		{
    998      0   stevel 			procuid = request->secure->uid;
    999      0   stevel 			procgid = request->secure->gid;
   1000      0   stevel 		}
   1001      0   stevel 		cp = _alloc_files(
   1002      0   stevel 			lenlist(request->request->file_list),
   1003      0   stevel 			getreqno(request->secure->req_id),
   1004   3125   jacobs 			procuid, procgid);
   1005      0   stevel 
   1006      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s", Lp_Slow_Filter);
   1007   3204   jacobs 		av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_Temp, cp);
   1008      0   stevel 		for (listp = request->request->file_list; *listp; listp++)
   1009      0   stevel 			av[ac++] = arg_string(TRUSTED, "%s", *listp);
   1010      0   stevel 
   1011      0   stevel 		(void)chfiles (request->request->file_list, procuid, procgid);
   1012      0   stevel 
   1013      0   stevel #ifdef LP_USE_PAPI_ATTR
   1014      0   stevel 		/*
   1015      0   stevel 		 * Check if the PAPI job attribute file exists, if it does
   1016      0   stevel 		 * pass the file's pathname to the slow-filters in an
   1017      0   stevel 		 * environment variable. Note: this file is created when
   1018      0   stevel 		 * print jobs are submitted via the PAPI interface.
   1019      0   stevel 		 */
   1020      0   stevel 		snprintf(tmpName, sizeof (tmpName), "%s-%s",
   1021      0   stevel 			getreqno(request->secure->req_id), LP_PAPIATTRNAME);
   1022   3125   jacobs 		path = makepath(Lp_Temp, tmpName, (char *)0);
   1023      0   stevel 		if ((path != NULL) && (stat(path, &tmpBuf) == 0))
   1024      0   stevel 		{
   1025      0   stevel 			/*
   1026      0   stevel 			 * IPP job attribute file exists for this job so
   1027      0   stevel 			 * set the environment variable
   1028      0   stevel 			 */
   1029      0   stevel 			addenv(&envp, "ATTRPATH", path);
   1030      0   stevel 		}
   1031      0   stevel 		Free(path);
   1032      0   stevel 
   1033      0   stevel 
   1034      0   stevel 		/*
   1035      0   stevel 		 * now set environment variable for the printer's PostScript
   1036      0   stevel 		 * Printer Description (PPD) file, this is used by the filter
   1037      0   stevel 		 * when forming the print data for this printer.
   1038      0   stevel 		 */
   1039      0   stevel 		if ((request->printer != NULL) &&
   1040      0   stevel 		    (request->printer->printer != NULL) &&
   1041      0   stevel 		    (request->printer->printer->name != NULL))
   1042      0   stevel 		{
   1043      0   stevel 			snprintf(tmpName, sizeof (tmpName), "%s.ppd",
   1044      0   stevel 				request->printer->printer->name);
   1045      0   stevel 			path = makepath(ETCDIR, "ppd", tmpName, (char *)0);
   1046      0   stevel 			if ((path != NULL) && (stat(path, &tmpBuf) == 0))
   1047      0   stevel 			{
   1048      0   stevel 				addenv(&envp, "PPD", path);
   1049      0   stevel 			}
   1050      0   stevel 			Free(path);
   1051      0   stevel 		}
   1052      0   stevel #endif
   1053      0   stevel 		break;
   1054      0   stevel 
   1055      0   stevel 	case EX_ALERT:
   1056      0   stevel 		procuid = Lp_Uid;
   1057      0   stevel 		procgid = Lp_Gid;
   1058      0   stevel 		(void)Chown (printer->alert->msgfile, procuid, procgid);
   1059      0   stevel 
   1060      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers,
   1061      0   stevel 				printer->printer->name, ALERTSHFILE);
   1062      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);
   1063      0   stevel 
   1064      0   stevel 		break;
   1065      0   stevel 
   1066      0   stevel 	case EX_PALERT:
   1067      0   stevel 		procuid = Lp_Uid;
   1068      0   stevel 		procgid = Lp_Gid;
   1069      0   stevel 		(void)Chown (pwheel->alert->msgfile, procuid, procgid);
   1070      0   stevel 
   1071      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_PrintWheels,
   1072      0   stevel 				pwheel->pwheel->name, ALERTSHFILE);
   1073      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);
   1074      0   stevel 
   1075      0   stevel 		break;
   1076      0   stevel 
   1077      0   stevel 	case EX_FALERT:
   1078      0   stevel 		procuid = Lp_Uid;
   1079      0   stevel 		procgid = Lp_Gid;
   1080      0   stevel 		(void)Chown (form->alert->msgfile, procuid, procgid);
   1081      0   stevel 
   1082      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms,
   1083      0   stevel 				form->form->name, ALERTSHFILE);
   1084      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);
   1085      0   stevel 
   1086      0   stevel 		break;
   1087      0   stevel 
   1088      0   stevel 	case EX_FORM_MESSAGE:
   1089      0   stevel 		procuid = Lp_Uid;
   1090      0   stevel 		procgid = Lp_Gid;
   1091      0   stevel 
   1092      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s/form", Lp_A_Faults);
   1093      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s", form->form->name);
   1094      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s", time_buf);
   1095      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms,
   1096      0   stevel 				form->form->name, FORMMESSAGEFILE);
   1097      0   stevel 
   1098      0   stevel 		break;
   1099      0   stevel 
   1100      0   stevel 	case EX_FAULT_MESSAGE:
   1101      0   stevel 		procuid = Lp_Uid;
   1102      0   stevel 		procgid = Lp_Gid;
   1103      0   stevel 
   1104      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s/printer", Lp_A_Faults);
   1105      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s", printerNameToShow);
   1106      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s", time_buf);
   1107      0   stevel 		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers,
   1108      0   stevel 				printerName, FAULTMESSAGEFILE);
   1109      0   stevel 
   1110      0   stevel 		break;
   1111      0   stevel 
   1112      0   stevel 	case EX_NOTIFY:
   1113      0   stevel 		if (request->request->alert) {
   1114   3125   jacobs 			if (strchr(request->request->user, '@')) {
   1115      0   stevel 				procuid = Lp_Uid;
   1116      0   stevel 				procgid = Lp_Gid;
   1117      0   stevel 			} else {
   1118      0   stevel 				procuid = request->secure->uid;
   1119      0   stevel 				procgid = request->secure->gid;
   1120      0   stevel 			}
   1121      0   stevel 			av[ac++] = arg_string(TRUSTED, "%s",
   1122      0   stevel 					request->request->alert);
   1123      0   stevel 		} else {
   1124   3125   jacobs 			char *user = strdup(request->request->user);
   1125      0   stevel 			clean_string(user);
   1126   1676      jpk 			slabel = request->secure->slabel;
   1127      0   stevel 
   1128   3125   jacobs 			if (request->request->actions & ACT_WRITE) {
   1129      0   stevel 				av[ac++] = arg_string(TRUSTED, "%s", BINWRITE);
   1130      0   stevel 				snprintf(argbuf, sizeof (argbuf),
   1131      0   stevel 					"%s %s || %s %s",
   1132      0   stevel 					BINWRITE, user,
   1133      0   stevel 					BINMAIL, user
   1134      0   stevel 				);
   1135      0   stevel 				av[ac++] = arg_string(TRUSTED, "/bin/sh");
   1136      0   stevel 				av[ac++] = arg_string(TRUSTED, "-c");
   1137      0   stevel 				av[ac++] = arg_string(TRUSTED, "%s", argbuf);
   1138   1676      jpk 			} else if ((getzoneid() == GLOBAL_ZONEID) &&
   1139   1676      jpk 				   is_system_labeled() && (slabel != NULL)) {
   1140   1676      jpk 				/*
   1141   1676      jpk 				 * If in the global zone and the system is
   1142   1676      jpk 				 * labeled, mail is handled via a local
   1143   1676      jpk 				 * labeled zone that is the same label as
   1144   1676      jpk 				 * the request.
   1145   1676      jpk 				 */
   1146   1676      jpk 				if ((mail_zonename =
   1147   1676      jpk 				    get_labeled_zonename(slabel)) ==
   1148   1676      jpk 				    (char *)-1) {
   1149   1676      jpk 					/*
   1150   1676      jpk 					 * Cannot find labeled zone, just
   1151   1676      jpk 					 * return 0.
   1152   1676      jpk 					 */
   1153   1676      jpk 					return(0);
   1154   1676      jpk 				}
   1155   1676      jpk 			}
   1156   1676      jpk 			if (mail_zonename == NULL) {
   1157   1676      jpk 				procuid = Lp_Uid;
   1158   1676      jpk 				procgid = Lp_Gid;
   1159      0   stevel 				av[ac++] = arg_string(TRUSTED, "%s", BINMAIL);
   1160      0   stevel 				av[ac++] = arg_string(UNTRUSTED, "%s", user);
   1161   1676      jpk 			} else {
   1162   1676      jpk 				procuid = getuid();
   1163   1676      jpk 				procgid = getgid();
   1164   1676      jpk 				av[ac++] = arg_string(TRUSTED, "%s",
   1165   1676      jpk 				    "/usr/sbin/zlogin");
   1166   1676      jpk 				av[ac++] = arg_string(TRUSTED, "%s",
   1167   1676      jpk 				    mail_zonename);
   1168   1676      jpk 				av[ac++] = arg_string(TRUSTED, "%s",
   1169   1676      jpk 				    BINMAIL);
   1170   1676      jpk 				av[ac++] = arg_string(UNTRUSTED, "%s",
   1171   1676      jpk 				    user);
   1172   1676      jpk 				Free(mail_zonename);
   1173      0   stevel 			}
   1174      0   stevel 
   1175      0   stevel 			free(user);
   1176      0   stevel 		}
   1177      0   stevel 		break;
   1178      0   stevel 	}
   1179      0   stevel 
   1180      0   stevel 	av[ac++] = NULL;
   1181      0   stevel 
   1182      0   stevel 	Fork2 ();
   1183      0   stevel 	/* only the child returns */
   1184      0   stevel 
   1185      0   stevel 	/*
   1186      0   stevel 	 * Correctly set up the supplemental group list
   1187      0   stevel 	 * for proper file access (before execl the interface program)
   1188      0   stevel 	 */
   1189      0   stevel 
   1190      0   stevel 	pwp = getpwuid(procuid);
   1191      0   stevel 	if (pwp == NULL) {
   1192      0   stevel 		note("getpwuid(%d) call failed\n", procuid);
   1193      0   stevel 	} else if (initgroups(pwp->pw_name, procgid) < 0) {
   1194      0   stevel 		note("initgroups() call failed %d\n", errno);
   1195      0   stevel 	}
   1196      0   stevel 
   1197      0   stevel 	setgid (procgid);
   1198      0   stevel 	setuid (procuid);
   1199      0   stevel 
   1200      0   stevel 	/*
   1201      0   stevel 	 * The shell doesn't allow the "trap" builtin to set a trap
   1202      0   stevel 	 * for a signal ignored when the shell is started. Thus, don't
   1203      0   stevel 	 * turn off signals in the last child!
   1204      0   stevel 	 */
   1205      0   stevel 
   1206   3125   jacobs #ifdef DEBUG
   1207      0   stevel 	for (i = 0; av[i] != NULL; i++)
   1208   3125   jacobs 		note("exec(%s): av[%d] = %s", _exec_name(type), i, av[i]);
   1209   1676      jpk 	for (i = 0; envp[i] != NULL; i++)
   1210   3125   jacobs 		note("exec(%s): envp[%d] = %s", _exec_name(type), i, envp[i]);
   1211   3125   jacobs #endif
   1212      0   stevel 
   1213      0   stevel 	execvpe(av[0], av, envp);
   1214      0   stevel 	Done (EXEC_EXIT_NEXEC, errno);
   1215      0   stevel 	/*NOTREACHED*/
   1216    320  ceastha 	return (0);
   1217      0   stevel }
   1218      0   stevel 
   1219      0   stevel /**
   1220      0   stevel  ** addenv() - ADD A VARIABLE TO THE ENVIRONMENT
   1221      0   stevel  **/
   1222      0   stevel 
   1223      0   stevel static void
   1224      0   stevel addenv(char ***envp, char *name, char *value)
   1225      0   stevel {
   1226      0   stevel 	register char *		cp;
   1227      0   stevel 
   1228      0   stevel 	if ((name == NULL) || (value == NULL))
   1229      0   stevel 		return;
   1230      0   stevel 
   1231      0   stevel 	if ((cp = makestr(name, "=", value, (char *)0)))
   1232      0   stevel 		addlist(envp, cp);
   1233      0   stevel 	return;
   1234      0   stevel }
   1235      0   stevel 
   1236      0   stevel /**
   1237      0   stevel  ** Fork1() - FORK FIRST CHILD, SET UP CONNECTION TO IT
   1238      0   stevel  **/
   1239      0   stevel 
   1240      0   stevel static int
   1241      0   stevel Fork1(EXEC *ep)
   1242      0   stevel {
   1243      0   stevel 	int			pid;
   1244      0   stevel 	int			fds[2];
   1245      0   stevel 
   1246      0   stevel 	if (pipe(fds) == -1) {
   1247      0   stevel 		note("Failed to create pipe for child process (%s).\n", PERROR);
   1248      0   stevel 		errno = EAGAIN ;
   1249      0   stevel 		return(-1);
   1250      0   stevel 	}
   1251      0   stevel 
   1252      0   stevel 	ep->md = mconnect((char *)0, fds[0], fds[1]);
   1253      0   stevel 
   1254      0   stevel 	switch (pid = fork()) {
   1255      0   stevel 
   1256      0   stevel 	case -1:
   1257      0   stevel 		mdisconnect(ep->md);
   1258      0   stevel 		close(fds[0]);
   1259      0   stevel 		close(fds[1]);
   1260      0   stevel 		ep->md = 0;
   1261      0   stevel 		return (-1);
   1262      0   stevel 
   1263      0   stevel 	case 0:
   1264      0   stevel 		ChildMd = mconnect(NULL, fds[1], fds[1]);
   1265      0   stevel 		return (0);
   1266      0   stevel 
   1267      0   stevel 	default:
   1268      0   stevel 		mlistenadd(ep->md, POLLIN);
   1269      0   stevel 		return (pid);
   1270      0   stevel 	}
   1271      0   stevel }
   1272      0   stevel 
   1273      0   stevel /**
   1274      0   stevel  ** Fork2() - FORK SECOND CHILD AND WAIT FOR IT
   1275      0   stevel  **/
   1276      0   stevel 
   1277      0   stevel static void
   1278      0   stevel Fork2(void)
   1279      0   stevel {
   1280      0   stevel 	switch ((ChildPid = fork())) {
   1281      0   stevel 
   1282      0   stevel 	case -1:
   1283      0   stevel 		Done (EXEC_EXIT_NFORK, errno);
   1284      0   stevel 		/*NOTREACHED*/
   1285      0   stevel 
   1286      0   stevel 	case 0:
   1287      0   stevel 		return;
   1288      0   stevel 
   1289      0   stevel 	default:
   1290      0   stevel 		/*
   1291      0   stevel 		 * Delay calling "ignore_fault_signals()" as long
   1292      0   stevel 		 * as possible, to give the child a chance to exec
   1293      0   stevel 		 * the interface program and turn on traps.
   1294      0   stevel 		 */
   1295      0   stevel 
   1296      0   stevel 		cool_heels ();
   1297      0   stevel 		/*NOTREACHED*/
   1298      0   stevel 
   1299      0   stevel 	}
   1300      0   stevel }
   1301      0   stevel 
   1302      0   stevel 
   1303      0   stevel /**
   1304      0   stevel  ** cool_heels() - WAIT FOR CHILD TO "DIE"
   1305      0   stevel  **/
   1306      0   stevel 
   1307      0   stevel static void
   1308      0   stevel cool_heels(void)
   1309      0   stevel {
   1310      0   stevel 	int			status;
   1311      0   stevel 
   1312      0   stevel 	/*
   1313      0   stevel 	 * At this point our only job is to wait for the child process.
   1314      0   stevel 	 * If we hang out for a bit longer, that's okay.
   1315      0   stevel 	 * By delaying before turning off the fault signals,
   1316      0   stevel 	 * we increase the chance that the child process has completed
   1317      0   stevel 	 * its exec and has turned on the fault traps. Nonetheless,
   1318      0   stevel 	 * we can't guarantee a zero chance of missing a fault.
   1319      0   stevel 	 * (We don't want to keep trapping the signals because the
   1320      0   stevel 	 * interface program is likely to have a better way to handle
   1321      0   stevel 	 * them; this process provides only rudimentary handling.)
   1322      0   stevel 	 *
   1323      0   stevel 	 * Note that on a very busy system, or with a very fast interface
   1324      0   stevel 	 * program, the tables could be turned: Our sleep below (coupled
   1325      0   stevel 	 * with a delay in the kernel scheduling us) may cause us to
   1326      0   stevel 	 * detect the fault instead of the interface program.
   1327      0   stevel 	 *
   1328      0   stevel 	 * What we need is a way to synchronize with the child process.
   1329      0   stevel 	 */
   1330      0   stevel 	sleep (1);
   1331      0   stevel 	ignore_fault_signals ();
   1332      0   stevel 
   1333      0   stevel 	WaitedChildPid = 0;
   1334      0   stevel 	while ((WaitedChildPid = wait(&status)) != ChildPid)
   1335      0   stevel 		;
   1336      0   stevel 
   1337      0   stevel 	if (
   1338      0   stevel 		EXITED(status) > EXEC_EXIT_USER
   1339      0   stevel 	     && EXITED(status) != EXEC_EXIT_FAULT
   1340      0   stevel 	)
   1341      0   stevel 		Done (EXEC_EXIT_EXIT, EXITED(status));
   1342      0   stevel 
   1343      0   stevel 	done (status, 0);	/* Don't use Done() */
   1344      0   stevel 	/*NOTREACHED*/
   1345      0   stevel }
   1346      0   stevel 
   1347      0   stevel 
   1348      0   stevel /**
   1349      0   stevel  ** trap_fault_signals() - TRAP SIGNALS THAT CAN OCCUR ON PRINTER FAULT
   1350      0   stevel  ** ignore_fault_signals() - IGNORE SAME
   1351      0   stevel  **/
   1352      0   stevel 
   1353      0   stevel static void
   1354      0   stevel trap_fault_signals(void)
   1355      0   stevel {
   1356      0   stevel 	signal (SIGHUP, sigtrap);
   1357      0   stevel 	signal (SIGINT, sigtrap);
   1358      0   stevel 	signal (SIGQUIT, sigtrap);
   1359      0   stevel 	signal (SIGPIPE, sigtrap);
   1360      0   stevel 	return;
   1361      0   stevel }
   1362      0   stevel 
   1363      0   stevel static void
   1364      0   stevel ignore_fault_signals(void)
   1365      0   stevel {
   1366      0   stevel 	signal (SIGHUP, SIG_IGN);
   1367      0   stevel 	signal (SIGINT, SIG_IGN);
   1368      0   stevel 	signal (SIGQUIT, SIG_IGN);
   1369      0   stevel 	signal (SIGPIPE, SIG_IGN);
   1370      0   stevel 	return;
   1371      0   stevel }
   1372      0   stevel 
   1373      0   stevel /**
   1374      0   stevel  ** sigtrap() - TRAP VARIOUS SIGNALS
   1375      0   stevel  **/
   1376      0   stevel 
   1377      0   stevel static void
   1378      0   stevel sigtrap(int sig)
   1379      0   stevel {
   1380      0   stevel 	signal (sig, SIG_IGN);
   1381      0   stevel 	switch (sig) {
   1382      0   stevel 
   1383      0   stevel 	case SIGHUP:
   1384      0   stevel 		Done (EXEC_EXIT_HUP, 0);
   1385      0   stevel 		/*NOTREACHED*/
   1386      0   stevel 
   1387      0   stevel 	case SIGQUIT:
   1388      0   stevel 	case SIGINT:
   1389      0   stevel 		Done (EXEC_EXIT_INTR, 0);
   1390      0   stevel 		/*NOTREACHED*/
   1391      0   stevel 
   1392      0   stevel 	case SIGPIPE:
   1393      0   stevel 		Done (EXEC_EXIT_PIPE, 0);
   1394      0   stevel 		/*NOTREACHED*/
   1395      0   stevel 
   1396      0   stevel 	case SIGTERM:
   1397      0   stevel 		/*
   1398      0   stevel 		 * If we were killed with SIGTERM, it should have been
   1399      0   stevel 		 * via the Spooler who should have killed the entire
   1400      0   stevel 		 * process group. We have to wait for the children,
   1401      0   stevel 		 * since we're their parent, but WE MAY HAVE WAITED
   1402      0   stevel 		 * FOR THEM ALREADY (in cool_heels()).
   1403      0   stevel 		 */
   1404      0   stevel 		if (ChildPid != WaitedChildPid) {
   1405      0   stevel 			register int		cpid;
   1406      0   stevel 
   1407      0   stevel 			while (
   1408      0   stevel 				(cpid = wait((int *)0)) != ChildPid
   1409      0   stevel 			     && (cpid != -1 || errno != ECHILD)
   1410      0   stevel 			)
   1411      0   stevel 				;
   1412      0   stevel 		}
   1413      0   stevel 
   1414      0   stevel 		/*
   1415      0   stevel 		 * We can't rely on getting SIGTERM back in the wait()
   1416      0   stevel 		 * above, because, for instance, some shells trap SIGTERM
   1417      0   stevel 		 * and exit instead. Thus we force it.
   1418      0   stevel 		 */
   1419      0   stevel 		done (SIGTERM, 0);	/* Don't use Done() */
   1420      0   stevel 		/*NOTREACHED*/
   1421      0   stevel 	}
   1422      0   stevel }
   1423      0   stevel 
   1424      0   stevel /**
   1425      0   stevel  ** done() - TELL SPOOLER THIS CHILD IS DONE
   1426      0   stevel  **/
   1427      0   stevel 
   1428      0   stevel static void
   1429      0   stevel done(int status, int err)
   1430      0   stevel {
   1431      0   stevel 	if (do_undial)
   1432      0   stevel 		undial (1);
   1433      0   stevel 
   1434   3125   jacobs 	mputm (ChildMd, S_CHILD_DONE, key, status, err);
   1435      0   stevel 	mdisconnect (ChildMd);
   1436      0   stevel 
   1437      0   stevel 	exit (0);
   1438      0   stevel 	/*NOTREACHED*/
   1439      0   stevel }
   1440      0   stevel 
   1441      0   stevel /**
   1442      0   stevel  ** child_mallocfail()
   1443      0   stevel  **/
   1444      0   stevel 
   1445      0   stevel static void
   1446      0   stevel child_mallocfail(void)
   1447      0   stevel {
   1448      0   stevel 	Done (EXEC_EXIT_NOMEM, ENOMEM);
   1449      0   stevel }
   1450