示例#1
0
void
s_end_change_request(char *m, MESG *md)
{
	char		*req_id;
	RSTATUS		*rp;
	off_t		size;
	off_t		osize;
	short		err;
	short		status;
	REQUEST		*r = 0;
	REQUEST		oldr;
	int		call_schedule = 0;
	int		move_ok	= 0;
	char		*path;
	char		tmpName[BUFSIZ];
	struct stat	tmpBuf;

	(void) getmessage(m, S_END_CHANGE_REQUEST, &req_id);
	syslog(LOG_DEBUG, "s_end_change_request(%s)",
	    (req_id ? req_id : "NULL"));

	if (!(rp = request_by_id(req_id)))
		status = MUNKNOWN;
	else if ((md->admin == 0) && (is_system_labeled()) &&
	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
	    (!STREQU(md->slabel, rp->secure->slabel)))
		status = MUNKNOWN;
	else if (!(rp->request->outcome & RS_CHANGING))
		status = MNOSTART;
	else {
		path = makepath(Lp_Tmp, rp->req_file, (char *)0);
		(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
		Free(path);

#ifdef LP_USE_PAPI_ATTR

		/*
		 * Check if the PAPI job attribute file exists,
		 * if it does change the permission and the ownership
		 * of the file to be "Lp_Uid".
		 */

		snprintf(tmpName, sizeof (tmpName),
		    "%s-%s", strtok(strdup(rp->req_file), "-"),
		    LP_PAPIATTRNAME);

		path = makepath(Lp_Tmp, tmpName, (char *)0);

		if (stat(path, &tmpBuf) == 0) {
			syslog(LOG_DEBUG,
			    "s_end_change_request: attribute file ='%s'",
			    path);

			/*
			 * IPP job attribute file exists for this job so
			 * change permissions and ownership of the file
			 */
			(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
			Free(path);
		}
		else
		{
			syslog(LOG_DEBUG,
			    "s_end_change_request: no attribute file");
		}
#endif
		rp->request->outcome &= ~(RS_CHANGING);
		del_flt_act(md, FLT_CHANGE);
		/*
		 * The RS_CHANGING bit may have been the only thing
		 * preventing this request from filtering or printing,
		 * so regardless of what happens below,
		 * we must check to see if the request can proceed.
		 */
		call_schedule = 1;

		if (!(r = Getrequest(rp->req_file)))
			status = MNOOPEN;
		else {
			oldr = *(rp->request);
			*(rp->request) = *r;

			move_ok =
			    STREQU(oldr.destination, r->destination);

			/*
			 * Preserve the current request status!
			 */
			rp->request->outcome = oldr.outcome;

			/*
			 * Here's an example of the dangers one meets
			 * when public flags are used for private
			 * purposes. ".actions" (indeed, anything in the
			 * REQUEST structure) is set by the person
			 * changing the job. However, lpsched uses
			 * ".actions" as place to indicate that a job
			 * came from a remote system and we must send
			 * back job completion--this is a strictly
			 * private flag that we must preserve.
			 */
			rp->request->actions |=
			    (oldr.actions & ACT_NOTIFY);

			if ((rp->request->actions & ACT_SPECIAL) ==
			    ACT_HOLD) {
				rp->request->outcome |= RS_HELD;
				/*
				 * To be here means either the user owns
				 * the request or he or she is the
				 * administrator. Since we don't want to
				 * set the RS_ADMINHELD flag if the user
				 * is the administrator, the following
				 * compare will work.
				 */
				if (md->uid != rp->secure->uid)
					rp->request->outcome |=
					    RS_ADMINHELD;
			}

			if ((rp->request->actions & ACT_SPECIAL) ==
			    ACT_RESUME) {
				if ((rp->request->outcome & RS_ADMINHELD) &&
				    !md->admin) {
					status = MNOPERM;
					goto Return;
				}
				rp->request->outcome &=
				    ~(RS_ADMINHELD|RS_HELD);
			}

			if ((rp->request->actions & ACT_SPECIAL)
			    == ACT_IMMEDIATE) {
				if (!md->admin) {
					status = MNOPERM;
					goto Return;
				}
				rp->request->outcome |= RS_IMMEDIATE;
			}

			size = chfiles(rp->request->file_list, Lp_Uid,
			    Lp_Gid);
			if (size < 0) {
				status = MUNKNOWN;
				goto Return;
			}
			if (!(rp->request->outcome & RS_HELD) &&
			    size == 0) {
				status = MNOPERM;
				goto Return;
			}

			osize = rp->secure->size;
			rp->secure->size = size;

			if (move_ok == 0) {
				char *dest = strdup(r->destination);
				if ((status = mv_file(rp, dest)) == MOK)
					rp->secure->size = osize;
				free(dest);
			} else if ((err = validate_request(rp, (char **)0,
			    move_ok)) != MOK) {
				status = err;
				rp->secure->size = osize;
			} else {
				status = MOK;

				if ((rp->request->outcome & RS_IMMEDIATE) ||
				    (rp->request->priority != oldr.priority)) {
					remover(rp);
					insertr(rp);
				}

				freerequest(&oldr);
				(void) putrequest(rp->req_file, rp->request);
				/*
				 * fix for bugid 1103890.
				 * use Putsecure instead.
				 */
				(void) Putsecure(rp->req_file, rp->secure);
			}
		}
	}

Return:
	if (status != MOK && rp) {
		if (r) {
			freerequest(r);
			*(rp->request) = oldr;
		}
		if (status != MNOSTART)
			(void) putrequest(rp->req_file, rp->request);
	}

	if (call_schedule)
		maybe_schedule(rp);

	mputm(md, R_END_CHANGE_REQUEST, status, chkprinter_result);
}
示例#2
0
void
s_print_request(char *m, MESG *md)
{
	extern char		*Local_System;
	char			*file;
	char			*idno;
	char			*path;
	char			*req_file;
	char			*req_id	= 0;
	RSTATUS			*rp;
	REQUEST			*r;
	SECURE			*s;
	struct passwd		*pw;
	short			err;
	short			status;
	off_t			size;
	uid_t			org_uid;
	gid_t			org_gid;
#ifdef LP_USE_PAPI_ATTR
	struct stat		tmpBuf;
	char 			tmpName[BUFSIZ];
#endif


	(void) getmessage(m, S_PRINT_REQUEST, &file);
	syslog(LOG_DEBUG, "s_print_request(%s)", (file ? file : "NULL"));

	/*
	 * "NewRequest" points to a request that's not yet in the
	 * request list but is to be considered with the rest of the
	 * requests (e.g. calculating # of requests awaiting a form).
	 */
	if ((rp = NewRequest = new_rstatus(NULL, NULL)) == NULL)
		status = MNOMEM;

	else
	{
		req_file = reqpath(file, &idno);
		path = makepath(Lp_Tmp, req_file, (char *)0);
		(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
		Free(path);

		if (!(r = Getrequest(req_file)))
			status = MNOOPEN;

		else
		{
			rp->req_file = Strdup(req_file);

			freerequest(rp->request);
			rp->request = r;

			rp->request->outcome = 0;
			rp->secure->uid = md->uid;
			rp->secure->gid = md->gid;
			if (md->slabel != NULL)
				rp->secure->slabel = Strdup(md->slabel);

			pw = getpwuid(md->uid);
			endpwent();
			if (pw && pw->pw_name && *pw->pw_name)
				rp->secure->user = Strdup(pw->pw_name);
			else {
				rp->secure->user = Strdup(BIGGEST_NUMBER_S);
				(void) sprintf(rp->secure->user, "%u",
				    md->uid);
			}

			if ((rp->request->actions & ACT_SPECIAL) == ACT_HOLD)
				rp->request->outcome |= RS_HELD;
			if ((rp->request->actions & ACT_SPECIAL) == ACT_RESUME)
				rp->request->outcome &= ~RS_HELD;
			if ((rp->request->actions & ACT_SPECIAL) ==
			    ACT_IMMEDIATE) {
				if (!md->admin) {
					status = MNOPERM;
					goto Return;
				}
				rp->request->outcome |= RS_IMMEDIATE;
			}

			size = chfiles(rp->request->file_list, Lp_Uid, Lp_Gid);

			if (size < 0) {
				/*
				 * at this point, chfiles() may have
				 * failed because the file may live on
				 * an NFS mounted filesystem, under
				 * a directory of mode 700. such a
				 * directory isn't accessible even by
				 * root, according to the NFS protocol
				 * (i.e. the Stat() in chfiles() failed).
				 * this most commonly happens via the
				 * automounter, and rlogin. thus we
				 * change our euid/egid to that of the
				 * user, and try again. if *this* fails,
				 * then the file must really be
				 * inaccessible.
				 */
				org_uid = geteuid();
				org_gid = getegid();

				if (setegid(md->gid) != 0) {
					status = MUNKNOWN;
					goto Return;
				}

				if (seteuid(md->uid) != 0) {
					setgid(org_gid);
					status = MUNKNOWN;
					goto Return;
				}

				size = chfiles(rp->request->file_list,
				    Lp_Uid, Lp_Gid);

				if (seteuid(org_uid) != 0) {
					/* should never happen */
					note("s_print_request(): ");
					note("seteuid back to uid=%d "
					    "failed!!\n", org_uid);
					size = -1;
				}

				if (setegid(org_gid) != 0) {
					/* should never happen */
					note("s_print_request(): ");
					note("setegid back to uid=%d "
					    "failed!!\n", org_uid);
					size = -1;
				}

				if (size < 0) {
					status = MUNKNOWN;
					goto Return;
				}
			}
			if (!(rp->request->outcome & RS_HELD) && size == 0) {
				status = MNOPERM;
				goto Return;
			}
			rp->secure->size = size;

			(void) time(&rp->secure->date);
			rp->secure->req_id = NULL;

			if (!rp->request->title) {
				if (strlen(*rp->request->file_list) <
				    (size_t)24)
					rp->request->title =
					    Strdup(*rp->request->file_list);
				else {
					char *r;
					if (r = strrchr(
					    *rp->request->file_list, '/'))
						r++;
					else
						r = *rp->request->file_list;

					rp->request->title = malloc(25);
					sprintf(rp->request->title,
					    "%-.24s", r);
				}
			}

			if ((err = validate_request(rp, &req_id, 0)) != MOK)
				status = err;
			else {
				/*
				 * "req_id" will be supplied if this is from a
				 * remote system.
				 */
				if (rp->secure->req_id == NULL) {
					req_id = makestr(req_id, "-",
					    idno, (char *)0);
					rp->secure->req_id = req_id;
				} else
					req_id = rp->secure->req_id;

#ifdef LP_USE_PAPI_ATTR
				/*
				 * Check if the PAPI job attribute file
				 * exists, if it does change the
				 * permissions and ownership of the file.
				 * This file is created when print jobs
				 * are submitted via the PAPI interface,
				 * the file pathname of this file is
				 * passed to the slow-filters and printer
				 * interface script as an environment
				 * variable when they are executed
				 */
				snprintf(tmpName, sizeof (tmpName),
				    "%s-%s", idno, LP_PAPIATTRNAME);
				path = makepath(Lp_Temp, tmpName, (char *)0);

				if (stat(path, &tmpBuf) == 0) {
					syslog(LOG_DEBUG,
					    "s_print_request: "\
					    "attribute file ='%s'", path);

					/*
					 * IPP job attribute file exists
					 * for this job so change
					 * permissions and ownership of
					 * the file
					 */
					(void) chownmod(path, Lp_Uid,
					    Lp_Gid, 0644);
					Free(path);
				}
				else
				{
					syslog(LOG_DEBUG,
					    "s_print_request: "\
					    "no attribute file");
				}
#endif

				/*
				 * fix for bugid 1103890.
				 * use Putsecure instead.
				 */
				if ((Putsecure(req_file, rp->secure) == -1) ||
				    (putrequest(req_file, rp->request) == -1))
					status = MNOMEM;
				else
				{
					status = MOK;

					insertr(rp);
					NewRequest = 0;

					if (rp->slow)
						schedule(EV_SLOWF, rp);
					else
						schedule(EV_INTERF,
						    rp->printer);

					del_flt_act(md, FLT_FILES);
				}
			}
		}
	}

Return:
	NewRequest = 0;
	Free(req_file);
	Free(idno);
	if (status != MOK && rp) {
		rmfiles(rp, 0);
		free_rstatus(rp);
	}
	mputm(md, R_PRINT_REQUEST, status, NB(req_id), chkprinter_result);
}
示例#3
0
文件: exec.c 项目: alhazred/onarm
/*VARARGS1*/
int
exec(int type, ...)
{
	va_list			args;

	int			i;
	int			procuid;
	int			procgid;
	int			ret;
	int			fr_flg;

	char			*cp;
	char			*infile;
	char			*outfile;
	char			*errfile;
	char			*sep;

	char			**listp;
	char			**file_list;
	char			*printerName;
	char			*printerNameToShow;
	static char		nameBuf[100];
	char			*clean_title;

	PSTATUS			*printer;

	RSTATUS			*request;

	FSTATUS			*form;

	EXEC			*ep;

	PWSTATUS		*pwheel;
	time_t			now;
	struct passwd		*pwp;
#ifdef LP_USE_PAPI_ATTR
	struct stat		tmpBuf;
	char 			tmpName[BUFSIZ];
	char			*path = NULL;
#endif
	char *av[ARG_MAX];
	char **envp = NULL;
	int ac = 0;
	char	*mail_zonename = NULL;
	char	*slabel = NULL;

	syslog(LOG_DEBUG, "exec(%s)", _exec_name(type));

	memset(av, 0, sizeof (*av));

	va_start (args, type);

	switch (type) {

	case EX_INTERF:
		printer = va_arg(args, PSTATUS *);
		request = printer->request;
		ep = printer->exec;
		break;
		
	case EX_FAULT_MESSAGE:
		printer = va_arg(args, PSTATUS *);
		request = va_arg(args, RSTATUS *);
		if (! ( printer->status & (PS_FORM_FAULT | PS_SHOW_FAULT))) {
			return(0);
		}
		ep = printer->fault_exec;
		printerName = (printer->printer && printer->printer->name 
				  ? printer->printer->name : "??");
			snprintf(nameBuf, sizeof (nameBuf),
				"%s (on %s)\n", printerName, Local_System);

		printerNameToShow = nameBuf;

		(void) time(&now);
		(void) strftime(time_buf, sizeof (time_buf),
			NULL, localtime(&now));
		break;

	case EX_SLOWF:
		request = va_arg(args, RSTATUS *);
		ep = request->exec;
		break;

	case EX_NOTIFY:
		request = va_arg(args, RSTATUS *);
		if (request->request->actions & ACT_NOTIFY) {
			errno = EINVAL;
			return (-1);
		}
		ep = request->exec;
		break;

	case EX_ALERT:
		printer = va_arg(args, PSTATUS *);
		if (!(printer->printer->fault_alert.shcmd)) {
			errno = EINVAL;
			return(-1);
		}
		ep = printer->alert->exec;
		break;

	case EX_PALERT:
		pwheel = va_arg(args, PWSTATUS *);
		ep = pwheel->alert->exec;
		break;

	case EX_FORM_MESSAGE:
		(void) time(&now);
		(void) strftime(time_buf, sizeof (time_buf),
			NULL, localtime(&now));

		/*FALLTHRU*/
	case EX_FALERT:
		form = va_arg(args, FSTATUS *);
		ep = form->alert->exec;
		break;

	default:
		errno = EINVAL;
		return(-1);

	}
	va_end (args);

	if (!ep || (ep->pid > 0)) {
		errno = EBUSY;
		return(-1);
	}

	ep->flags = 0;

	key = ep->key = getkey();

	switch ((ep->pid = Fork1(ep))) {

	case -1:
		relock ();
		return(-1);

	case 0:
		/*
		 * We want to be able to tell our parent how we died.
		 */
		lp_alloc_fail_handler = child_mallocfail;
		break;

	default:
		switch(type) {

		case EX_INTERF:
			request->request->outcome |= RS_PRINTING;
			break;

		case EX_NOTIFY:
			request->request->outcome |= RS_NOTIFYING;
			break;

		case EX_SLOWF:
			request->request->outcome |= RS_FILTERING;
			request->request->outcome &= ~RS_REFILTER;
			break;

		}
		return(0);

	}

	for (i = 0; i < NSIG; i++)
		(void)signal (i, SIG_DFL);
	(void)signal (SIGALRM, SIG_IGN);
	(void)signal (SIGTERM, sigtrap);

	closelog();
	for (i = 0; i < OpenMax; i++)
		if (i != ChildMd->writefd)
			Close (i);
	openlog("lpsched", LOG_PID|LOG_NDELAY|LOG_NOWAIT, LOG_LPR);

	setpgrp();

	/* Set a default path */
	addenv (&envp, "PATH", "/usr/lib/lp/bin:/usr/bin:/bin:/usr/sbin:/sbin");
	/* copy locale related variables */
	addenv (&envp, "TZ", getenv("TZ"));
	addenv (&envp, "LANG", getenv("LANG"));
	addenv (&envp, "LC_ALL", getenv("LC_ALL"));
	addenv (&envp, "LC_COLLATE", getenv("LC_COLLATE"));
	addenv (&envp, "LC_CTYPE", getenv("LC_CTYPE"));
	addenv (&envp, "LC_MESSAGES", getenv("LC_MESSAGES"));
	addenv (&envp, "LC_MONETARY", getenv("LC_MONETARY"));
	addenv (&envp, "LC_NUMERIC", getenv("LC_NUMERIC"));
	addenv (&envp, "LC_TIME", getenv("LC_TIME"));

	sprintf ((cp = BIGGEST_NUMBER_S), "%ld", key);
	addenv (&envp, "SPOOLER_KEY", cp);

#if	defined(DEBUG)
	addenv (&envp, "LPDEBUG", (debug? "1" : "0"));
#endif

	/*
	 * Open the standard input, standard output, and standard error.
	 */
	switch (type) {
		
	case EX_SLOWF:
	case EX_INTERF:
		/*
		 * stdin:  /dev/null
		 * stdout: /dev/null (EX_SLOWF), printer port (EX_INTERF)
		 * stderr: req#
		 */
		infile = 0;
		outfile = 0;
		errfile = makereqerr(request);
		break;

	case EX_NOTIFY:
		/*
		 * stdin:  req#
		 * stdout: /dev/null
		 * stderr: /dev/null
		 */
		infile = makereqerr(request);
		outfile = 0;
		errfile = 0;

		break;

	case EX_ALERT:
	case EX_FALERT:
	case EX_PALERT:
	case EX_FAULT_MESSAGE:
	case EX_FORM_MESSAGE:
		/*
		 * stdin:  /dev/null
		 * stdout: /dev/null
		 * stderr: /dev/null
		 */
		infile = 0;
		outfile = 0;
		errfile = 0;
		break;

	}

	if (infile) {
		if (Open(infile, O_RDONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	} else {
		if (Open("/dev/null", O_RDONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	}

	if (outfile) {
		if (Open(outfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	} else {
		/*
		 * If EX_INTERF, this is still needed to cause the
		 * standard error channel to be #2.
		 */
		if (Open("/dev/null", O_WRONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	}

	if (errfile) {
		if (Open(errfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	} else {
		if (Open("/dev/null", O_WRONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	}

	switch (type) {

	case EX_INTERF:
		/*
		 * Opening a ``port'' can be dangerous to our health:
		 *
		 *	- Hangups can occur if the line is dropped.
		 *	- The printer may send an interrupt.
		 *	- A FIFO may be closed, generating SIGPIPE.
		 *
		 * We catch these so we can complain nicely.
		 */
		trap_fault_signals ();

		(void)Close (1);

		if (strchr (request->request->user, '@'))
		{
			procuid = Lp_Uid;
			procgid = Lp_Gid;
		}
		else
		{
			procuid = request->secure->uid;
			procgid = request->secure->gid;
		}
		if (printer->printer->dial_info)
		{
			ret = open_dialup(request->printer_type,
				printer->printer);
			if (ret == 0)
				do_undial = 1;
		}
		else
		{
			ret = open_direct(request->printer_type,
				printer->printer);
			do_undial = 0;
			/* this is a URI */
			if (is_printer_uri(printer->printer->device) == 0)
				addenv(&envp, "DEVICE_URI",
					 printer->printer->device);
		}
				addenv(&envp, "DEVICE_URI",
					 printer->printer->device);
		if (ret != 0)
			Done (ret, errno);
			
		if (!(request->request->outcome & RS_FILTERED))
			file_list = request->request->file_list;

		else {
			register int		count	= 0;
			register char *		num	= BIGGEST_REQID_S;
			register char *		prefix;

			prefix = makestr(
				Lp_Temp,
				"/F",
				getreqno(request->secure->req_id),
				"-",
				(char *)0
			);

			file_list = (char **)Malloc(
				(lenlist(request->request->file_list) + 1)
			      * sizeof(char *)
			);

			for (
				listp = request->request->file_list;
				*listp;
				listp++
			) {
				sprintf (num, "%d", count + 1);
				file_list[count] = makestr(
					prefix,
					num,
					(char *)0
				);
				count++;
			}
			file_list[count] = 0;
		}

#ifdef LP_USE_PAPI_ATTR
		/*
		 * Check if the PAPI job attribute file exists, if it does
		 * pass the file's pathname to the printer interface script
		 * in an environment variable. This file is created when
		 * print jobs are submitted via the PAPI interface.
		 */
		snprintf(tmpName, sizeof (tmpName), "%s-%s",
			getreqno(request->secure->req_id), LP_PAPIATTRNAME);
		path = makepath(Lp_Temp, tmpName, (char *)0);
		if ((path != NULL) && (stat(path, &tmpBuf) == 0))
		{
			/*
			 * IPP job attribute file exists for this job so
			 * set the environment variable
			 */
			addenv(&envp, "ATTRPATH", path);
		}
		Free(path);

		/*
		 * now set environment variable for the printer's PostScript
		 * Printer Description (PPD) file, this is used by the filter
		 * when forming the print data for this printer.
		 */
		if ((request->printer != NULL) &&
		    (request->printer->printer != NULL) &&
		    (request->printer->printer->name != NULL))
		{
			snprintf(tmpName, sizeof (tmpName), "%s.ppd",
				request->printer->printer->name);
			path = makepath(ETCDIR, "ppd", tmpName, (char *)0);
			if ((path != NULL) && (stat(path, &tmpBuf) == 0))
			{
				addenv(&envp, "PPD", path);
			}
			Free(path);
		}
#endif

		if (request->printer_type)
			addenv(&envp, "TERM", request->printer_type);

		if (!(printer->printer->daisy)) {
			register char *	chset = 0;
			register char *	csp;

			if (
				request->form
			     && request->form->form->chset
			     && request->form->form->mandatory
			     && !STREQU(NAME_ANY, request->form->form->chset)
			)
				chset = request->form->form->chset;

			else if (
				request->request->charset
			     && !STREQU(NAME_ANY, request->request->charset)
			)
				chset = request->request->charset;

			if (chset) {
				csp = search_cslist(
					chset,
					printer->printer->char_sets
				);

				/*
				 * The "strtok()" below wrecks the string
				 * for future use, but this is a child
				 * process where it won't be needed again.
				 */
				addenv (&envp, "CHARSET",
					(csp? strtok(csp, "=") : chset)
				);
			}
		}

		if (request->fast)
			addenv(&envp, "FILTER", request->fast);

		/*
		 * Add the sensitivity label to the environment for
		 * banner page and header/footer processing
		 */

		if (is_system_labeled() && request->secure->slabel != NULL)
			addenv(&envp, "SLABEL", request->secure->slabel);

		/*
		 * Add the system name to the user name (ala system!user)
		 * unless it is already there. RFS users may have trouble
		 * here, sorry!
		 */
		cp = strchr(request->secure->user, '@');

		allTraysWithForm(printer, request->form); 

		/*
		 * Fix for 4137389
		 * Remove double quotes from title string.
		 */
		fr_flg = 1;
		clean_title = strdup(NB(request->request->title));
		if (clean_title == NULL) {
			/*
			 * strdup failed. We're probably hosed
			 * but try setting clean_title
			 * to original title and continuing.
			 */
			clean_title = NB(request->request->title);
			fr_flg = 0;
		} else if (strcmp(clean_title, "") != 0) {
			char *ct_p;

			for (ct_p = clean_title; *ct_p != NULL; ct_p++) {
				if (*ct_p == '"')
					*ct_p = ' ';
			}
		}

		av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_A_Interfaces,
					printer->printer->name);
		av[ac++] = arg_string(TRUSTED, "%s", request->secure->req_id);
		av[ac++] = arg_string(UNTRUSTED, "%s", request->request->user);
		av[ac++] = arg_string(TRUSTED, "%s", clean_title);
		av[ac++] = arg_string(TRUSTED, "%d", request->copies);

		if (fr_flg)
			free (clean_title);

		sep = "";

		/*
		 * Do the administrator defined key=value pair options
		 */

		argbuf[0] = '\0';
				
		if (printer->printer->options) {
			char **tmp = printer->printer->options;
			while(*tmp != NULL) {
				STRLCAT(argbuf, sep, sizeof (argbuf));
				sep = " ";
				STRLCAT(argbuf, *tmp++, sizeof (argbuf));
			}
		}

		/*
		 * Do the administrator defined ``stty'' stuff before
		 * the user's -o options, to allow the user to override.
		 */
		if (printer->printer->stty) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "stty='", sizeof (argbuf));
			STRLCAT (argbuf, printer->printer->stty,
			    sizeof (argbuf));
			STRLCAT (argbuf, "'", sizeof (argbuf));
		}

		/*
		 * Do all of the user's options except the cpi/lpi/etc.
		 * stuff, which is done separately.
		 */
		if (request->request->options) {
			listp = dashos(request->request->options);
			while (*listp) {
				if (
					!STRNEQU(*listp, "cpi=", 4)
				     && !STRNEQU(*listp, "lpi=", 4)
				     && !STRNEQU(*listp, "width=", 6)
				     && !STRNEQU(*listp, "length=", 7)
				) {
					STRLCAT (argbuf, sep, sizeof (argbuf));
					sep = " ";
					STRLCAT (argbuf, *listp,
					    sizeof (argbuf));
				}
				listp++;
			}
		}

		/*
		 * The "pickfilter()" routine (from "validate()")
		 * stored the cpi/lpi/etc. stuff that should be
		 * used for this request. It chose form over user,
		 * and user over printer.
		 */
		if (request->cpi) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "cpi=", sizeof (argbuf));
			STRLCAT (argbuf, request->cpi, sizeof (argbuf));
		}
		if (request->lpi) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "lpi=", sizeof (argbuf));
			STRLCAT (argbuf, request->lpi, sizeof (argbuf));
		}
		if (request->pwid) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "width=", sizeof (argbuf));
			STRLCAT (argbuf, request->pwid, sizeof (argbuf));
		}
		if (request->plen) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "length=", sizeof (argbuf));
			STRLCAT (argbuf, request->plen, sizeof (argbuf));
		}

		/*
		 * Do the ``raw'' bit last, to ensure it gets
		 * done. If the user doesn't want this, then he or
		 * she can do the correct thing using -o stty=
		 * and leaving out the -r option.
		 */
		if (request->request->actions & ACT_RAW) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "stty=-opost", sizeof (argbuf));
		}


		/* the "options" */
		av[ac++] = arg_string(UNTRUSTED, "%s", argbuf);

		for (listp = file_list; *listp; listp++)
			av[ac++] = arg_string(TRUSTED, "%s", *listp);

		(void)chfiles (file_list, procuid, procgid);

		break;


	case EX_SLOWF:
		if (request->slow)
			addenv(&envp, "FILTER", request->slow);

		if (strchr (request->request->user, '@'))
		{
			procuid = Lp_Uid;
			procgid = Lp_Gid;
		}
		else
		{
			procuid = request->secure->uid;
			procgid = request->secure->gid;
		}
		cp = _alloc_files(
			lenlist(request->request->file_list),
			getreqno(request->secure->req_id),
			procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s", Lp_Slow_Filter);
		av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_Temp, cp);
		for (listp = request->request->file_list; *listp; listp++)
			av[ac++] = arg_string(TRUSTED, "%s", *listp);

		(void)chfiles (request->request->file_list, procuid, procgid);

#ifdef LP_USE_PAPI_ATTR
		/*
		 * Check if the PAPI job attribute file exists, if it does
		 * pass the file's pathname to the slow-filters in an
		 * environment variable. Note: this file is created when
		 * print jobs are submitted via the PAPI interface.
		 */
		snprintf(tmpName, sizeof (tmpName), "%s-%s",
			getreqno(request->secure->req_id), LP_PAPIATTRNAME);
		path = makepath(Lp_Temp, tmpName, (char *)0);
		if ((path != NULL) && (stat(path, &tmpBuf) == 0))
		{
			/*
			 * IPP job attribute file exists for this job so
			 * set the environment variable
			 */
			addenv(&envp, "ATTRPATH", path);
		}
		Free(path);


		/*
		 * now set environment variable for the printer's PostScript
		 * Printer Description (PPD) file, this is used by the filter
		 * when forming the print data for this printer.
		 */
		if ((request->printer != NULL) &&
		    (request->printer->printer != NULL) &&
		    (request->printer->printer->name != NULL))
		{
			snprintf(tmpName, sizeof (tmpName), "%s.ppd",
				request->printer->printer->name);
			path = makepath(ETCDIR, "ppd", tmpName, (char *)0);
			if ((path != NULL) && (stat(path, &tmpBuf) == 0))
			{
				addenv(&envp, "PPD", path);
			}
			Free(path);
		}
#endif
		break;

	case EX_ALERT:
		procuid = Lp_Uid;
		procgid = Lp_Gid;
		(void)Chown (printer->alert->msgfile, procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers,
				printer->printer->name, ALERTSHFILE);
		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);

		break;

	case EX_PALERT:
		procuid = Lp_Uid;
		procgid = Lp_Gid;
		(void)Chown (pwheel->alert->msgfile, procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_PrintWheels,
				pwheel->pwheel->name, ALERTSHFILE);
		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);

		break;

	case EX_FALERT:
		procuid = Lp_Uid;
		procgid = Lp_Gid;
		(void)Chown (form->alert->msgfile, procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms,
				form->form->name, ALERTSHFILE);
		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);

		break;

	case EX_FORM_MESSAGE:
		procuid = Lp_Uid;
		procgid = Lp_Gid;

		av[ac++] = arg_string(TRUSTED, "%s/form", Lp_A_Faults);
		av[ac++] = arg_string(TRUSTED, "%s", form->form->name);
		av[ac++] = arg_string(TRUSTED, "%s", time_buf);
		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms,
				form->form->name, FORMMESSAGEFILE);

		break;

	case EX_FAULT_MESSAGE:
		procuid = Lp_Uid;
		procgid = Lp_Gid;

		av[ac++] = arg_string(TRUSTED, "%s/printer", Lp_A_Faults);
		av[ac++] = arg_string(TRUSTED, "%s", printerNameToShow);
		av[ac++] = arg_string(TRUSTED, "%s", time_buf);
		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers,
				printerName, FAULTMESSAGEFILE);

		break;

	case EX_NOTIFY:
		if (request->request->alert) {
			if (strchr(request->request->user, '@')) {
				procuid = Lp_Uid;
				procgid = Lp_Gid;
			} else {
				procuid = request->secure->uid;
				procgid = request->secure->gid;
			}
			av[ac++] = arg_string(TRUSTED, "%s",
					request->request->alert);
		} else {
			char *user = strdup(request->request->user);
			clean_string(user);
			slabel = request->secure->slabel;

			if (request->request->actions & ACT_WRITE) {
				av[ac++] = arg_string(TRUSTED, "%s", BINWRITE);
				snprintf(argbuf, sizeof (argbuf),
					"%s %s || %s %s",
					BINWRITE, user,
					BINMAIL, user
				);
				av[ac++] = arg_string(TRUSTED, "/bin/sh");
				av[ac++] = arg_string(TRUSTED, "-c");
				av[ac++] = arg_string(TRUSTED, "%s", argbuf);
			} else if ((getzoneid() == GLOBAL_ZONEID) &&
				   is_system_labeled() && (slabel != NULL)) {
				/*
				 * If in the global zone and the system is
				 * labeled, mail is handled via a local
				 * labeled zone that is the same label as
				 * the request.
				 */
				if ((mail_zonename =
				    get_labeled_zonename(slabel)) ==
				    (char *)-1) {
					/*
					 * Cannot find labeled zone, just
					 * return 0.
					 */
					return(0);
				}
			}
			if (mail_zonename == NULL) {
				procuid = Lp_Uid;
				procgid = Lp_Gid;
				av[ac++] = arg_string(TRUSTED, "%s", BINMAIL);
				av[ac++] = arg_string(UNTRUSTED, "%s", user);
			} else {
				procuid = getuid();
				procgid = getgid();
				av[ac++] = arg_string(TRUSTED, "%s",
				    "/usr/sbin/zlogin");
				av[ac++] = arg_string(TRUSTED, "%s",
				    mail_zonename);
				av[ac++] = arg_string(TRUSTED, "%s",
				    BINMAIL);
				av[ac++] = arg_string(UNTRUSTED, "%s",
				    user);
				Free(mail_zonename);
			}

			free(user);
		}
		break;
	}

	av[ac++] = NULL;

	Fork2 ();
	/* only the child returns */

	/*
	 * Correctly set up the supplemental group list
	 * for proper file access (before execl the interface program)
	 */

	pwp = getpwuid(procuid);
	if (pwp == NULL) {
		note("getpwuid(%d) call failed\n", procuid);
	} else if (initgroups(pwp->pw_name, procgid) < 0) {
		note("initgroups() call failed %d\n", errno);
	}
	
	setgid (procgid);
	setuid (procuid);

	/*
	 * The shell doesn't allow the "trap" builtin to set a trap
	 * for a signal ignored when the shell is started. Thus, don't
	 * turn off signals in the last child!
	 */

#ifdef DEBUG
	for (i = 0; av[i] != NULL; i++)
		note("exec(%s): av[%d] = %s", _exec_name(type), i, av[i]);
	for (i = 0; envp[i] != NULL; i++)
		note("exec(%s): envp[%d] = %s", _exec_name(type), i, envp[i]);
#endif

	execvpe(av[0], av, envp);
	Done (EXEC_EXIT_NEXEC, errno);
	/*NOTREACHED*/
	return (0);
}