view usr/src/cmd/lp/cmd/lpsched/disp1.c @ 13:f60a82e85167 default tip

Revert NEC's changes to fix krb5 build
author Andrew Stormont <andyjstormont@gmail.com>
date Fri, 02 Mar 2012 22:25:26 +0000
parents 1a15d5aaf794
children
line wrap: on
line source

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved  	*/

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include "dispatch.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>

static char	*reqpath(char *, char **);
static int	mv_file(RSTATUS *, char *);


RSTATUS			*NewRequest;

/**
 ** s_alloc_files()
 **/

void s_alloc_files ( char * m, MESG * md )	/* funcdef */
{
    char			*file_prefix;
    ushort			count;
    mode_t			old_msk;


    /*
     * Bugid 4140311
     * Set umask to 0 before creating files.
     */
    old_msk = umask((mode_t) 0);

    getmessage (m, S_ALLOC_FILES, &count);
    syslog(LOG_DEBUG, "s_alloc_files(%d)", count);

    if ((file_prefix = _alloc_files(count, (char *)0, md->uid, md->gid))) {
	mputm (md, R_ALLOC_FILES, MOK, file_prefix);
	add_flt_act(md, FLT_FILES, file_prefix, count);
    }
    else if (errno == EEXIST)
	mputm (md, R_ALLOC_FILES, MERRDEST, "");
    else
	mputm (md, R_ALLOC_FILES, MNOMEM, "");

    (void) umask(old_msk);

    return;
}

/**
 ** s_print_request()
 **/

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, 0600);
	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
	     * 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, 0600);
			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);
    return;
}

/**
 ** s_start_change_request()
 **/

void s_start_change_request (char *m, MESG *md)
{
    char		*req_id;
    char		*req_file	= "";
    short		status;
    RSTATUS		*rp;
    char		*path;
    
    (void) getmessage(m, S_START_CHANGE_REQUEST, &req_id);
    syslog(LOG_DEBUG, "s_start_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_DONE)
	status = M2LATE;
    else if (!md->admin && md->uid != rp->secure->uid)
	status = MNOPERM;
    else if (rp->request->outcome & RS_CHANGING)
	status = MNOOPEN;
    else if (rp->request->outcome & RS_NOTIFYING)
	status = MBUSY;
    else {
	status = MOK;

	if (
	    rp->request->outcome & RS_FILTERING
	 && !(rp->request->outcome & RS_STOPPED)
	)
	{
	    rp->request->outcome |= (RS_REFILTER|RS_STOPPED);
	    terminate (rp->exec);
	}

	if (
	    rp->request->outcome & RS_PRINTING
	 && !(rp->request->outcome & RS_STOPPED)
	)
	{
	    rp->request->outcome |= RS_STOPPED;
	    terminate (rp->printer->exec);
	}

	rp->request->outcome |= RS_CHANGING;	
    
	/*
	 * Change the ownership of the request file to be "md->uid".
	 * Either this is identical to "rp->secure->uid", or it is
	 * "Lp_Uid" or it is root. The idea is that the
	 * person at the other end needs access, and that may not
	 * be who queued the request.
	 */
	path = makepath(Lp_Tmp, rp->req_file, (char *)0);
	(void) Chown(path, md->uid, rp->secure->gid);
	Free (path);

	add_flt_act(md, FLT_CHANGE, rp);
	req_file = rp->req_file;

    }
    mputm(md, R_START_CHANGE_REQUEST, status, req_file);
    return;
}

/**
 ** s_end_change_request()
 **/

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;
    
    (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, 0600);
	Free (path);

	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);
    return;
}

/**
 ** _cancel()
 **	user may be (host!user)
 **/

static char *
_cancel(MESG *md, char *dest, char *user, char *req_id)
{
    static RSTATUS	*rp;
    static char		*s_dest;
    static char		*s_user;
    static char		*s_req_id;
    static int		current;
    RSTATUS		*crp;
    char		*creq_id;

    syslog(LOG_DEBUG, "_cancel(%s, %s, %s)", (dest ? dest : "NULL"),
	   (user ? user : "NULL"), (req_id ? req_id : "NULL"));

    if (dest || user || req_id) {
	s_dest = dest;
        if (STREQU(user, "!"))
		s_user = strdup("all!all");
	else
		s_user = user;
	s_req_id = req_id;
	rp = Request_List;
	current = 0;
	if (STREQU(s_req_id, CURRENT_REQ)) {
	    current = 1;
	    s_req_id = NULL;
	}
    }

    while (rp != NULL) {
	crp = rp;
	rp = rp->next;
	
	if (*s_dest && !STREQU(s_dest, crp->request->destination))
	    continue;

	if (current && !(crp->request->outcome & RS_PRINTING))
	    continue;

	if (s_req_id && *s_req_id && !STREQU(s_req_id, crp->secure->req_id))
	    continue;

	if (*s_user && !bangequ(s_user, crp->secure->user))
	    continue;

	if (!md->admin && md->uid != crp->secure->uid) {
	    errno = MNOPERM;
	    return(Strdup(crp->secure->req_id));
	}

	/*
	 * For Trusted Extensions, we need to check the sensitivity label of the
	 * connection and job before we try to cancel it.
	 */
	if ((md->admin == 0) && (is_system_labeled()) &&
	    (md->slabel != NULL) && (crp->secure->slabel != NULL) &&
	    (!STREQU(md->slabel, crp->secure->slabel)))
	    continue;

	crp->reason = MOK;
	creq_id = Strdup(crp->secure->req_id);

	syslog(LOG_DEBUG, "cancel reqid (%s) uid: %d, secureuid: %d",
		creq_id, md->uid, crp->secure->uid);

	if (cancel(crp, (md->uid != crp->secure->uid)))
	    errno = MOK;
	else
	    errno = M2LATE;
	return(creq_id);
    }

    errno = MUNKNOWN;
    return(NULL);
}

/**
 ** s_cancel_request()
 **/

void s_cancel_request(char *m, MESG *md)
{
	char	*req_id, *rid;
	short	status;

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

	if ((rid = _cancel(md, "", "", req_id)) != NULL)
		Free(rid);
	status = (short)errno;
	
	mputm(md, R_CANCEL_REQUEST, status);
}

/**
 ** s_cancel()
 **/

void s_cancel(char *m, MESG *md)
{
    char	*req_id;
    char	*user;
    char	*destination;
    char	*rid;
    char	*nrid;
    int		nerrno;
    int		oerrno;

    (void) getmessage(m, S_CANCEL, &destination, &user, &req_id);
    syslog(LOG_DEBUG, "s_cancel(%s, %s, %s)",
	   (destination ? destination : "NULL"), (user ? user : "NULL"),
	   (req_id ? req_id : "NULL"));

    if (STREQU(destination, NAME_ALL))
	destination = "";
    if (STREQU(req_id, NAME_ALL))
	req_id = "";

    if (rid = _cancel(md, destination, user, req_id)) {
	oerrno = errno;

	while ((nrid = _cancel(md, NULL, NULL, NULL)) != NULL) {
	    nerrno = errno;
	    mputm(md, R_CANCEL, MOKMORE, oerrno, rid);
	    Free(rid);
	    rid = nrid;
	    oerrno = nerrno;
	}
	mputm(md, R_CANCEL, MOK, oerrno, rid);
	Free(rid);
	return;
    }

    mputm(md, R_CANCEL, MOK, MUNKNOWN, "");
}

/*
 * s_inquire_request_rank()
 */

void s_inquire_request_rank(char *m, MESG *md)
{
	char		*form;
	char		*dest;
	char		*pwheel;
	char		*user;
	char		*req_id;
	RSTATUS		*rp;
	RSTATUS		*found = NULL;
	int		found_rank = 0;
	short		prop;
	char		files[BUFSIZ];
	int 		i;

	(void) getmessage(m, S_INQUIRE_REQUEST_RANK, &prop, &form, &dest,
		&req_id, &user, &pwheel);
	syslog(LOG_DEBUG, "s_inquire_request_rank(%d, %s, %s, %s, %s, %s)",
	   prop, (form ? form : "NULL"), (dest ? dest : "NULL"),
	   (req_id ? req_id : "NULL"), (user ? user : "NULL"),
	   (pwheel ? pwheel : "NULL"));

	for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
		PStatus[i]->nrequests = 0;

	for (rp = Request_List; rp != NULL; rp = rp->next) {
		if (rp->printer && !(rp->request->outcome & RS_DONE))
			rp->printer->nrequests++;

		if (*form && !SAME(form, rp->request->form))
			continue;

		if (*dest && !STREQU(dest, rp->request->destination)) {
			if (!rp->printer)
				continue;
			if (!STREQU(dest, rp->printer->printer->name))
				continue;
		}
	
		if (*req_id && !STREQU(req_id, rp->secure->req_id))
			continue;

		if (*user && !bangequ(user, rp->secure->user))
			continue;

		if (*pwheel && !SAME(pwheel, rp->pwheel_name))
			continue;
		/*
		 * For Trusted Extensions, we need to check the sensitivity
		 * label of the connection and job before we return it to the
		 * client.
		 */
		if ((md->admin <= 0) && (is_system_labeled()) &&
		    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
		    (!STREQU(md->slabel, rp->secure->slabel)))
			continue;

		if (found) {
			GetRequestFiles(found->request, files, sizeof(files));
			mputm(md, R_INQUIRE_REQUEST_RANK,
				MOKMORE,
				found->secure->req_id,
				found->request->user,
					/* bgolden 091996, bug 1257405 */
				found->secure->slabel,
				found->secure->size,
				found->secure->date,
				found->request->outcome,
				found->printer->printer->name,
				(found->form? found->form->form->name : ""),
				NB(found->pwheel_name),
				found_rank,
				files
			);
		}
		found = rp;
		found_rank = found->printer->nrequests;
	}

	if (found) {
		GetRequestFiles(found->request, files, sizeof(files));
		mputm(md, R_INQUIRE_REQUEST_RANK,
			MOK,
			found->secure->req_id,
			found->request->user, /* bgolden 091996, bug 1257405 */
			found->secure->slabel,
			found->secure->size,
			found->secure->date,
			found->request->outcome,
			found->printer->printer->name,
			(found->form? found->form->form->name : ""),
			NB(found->pwheel_name),
			found_rank,
			files
		);
	} else
		mputm(md, R_INQUIRE_REQUEST_RANK, MNOINFO, "", "", "", 0L, 0L,
			0, "", "", "", 0, "");
}

static int
mv_file(RSTATUS *rp, char *dest)
{
	int	stat;
	char	*olddest;
	EXEC	*oldexec;
	SECURE * securep;
	RSTATUS * prs;
	char * reqno;

	oldexec = rp->printer->exec;
	olddest = rp->request->destination;
	rp->request->destination = Strdup(dest);
	if ((stat = validate_request(rp, (char **)0, 1)) == MOK) {
		Free(olddest);

		if (rp->request->outcome & RS_FILTERED) {
			int cnt = 0;
			char *reqno;
			char **listp;
			char tmp_nam[MAXPATHLEN];

			reqno = getreqno(rp->secure->req_id);
			for (listp = rp->request->file_list; *listp; listp++) {
				cnt++;
				snprintf(tmp_nam, sizeof (tmp_nam),
					"%s/F%s-%d", Lp_Temp, reqno, cnt);
				unlink(tmp_nam);

			}
			rp->request->outcome &= ~RS_FILTERED;
		}

		/* update /var/spool/lp/tmp/<host>/nnn-0 */
		if (putrequest(rp->req_file, rp->request) < 0) {
			note("putrequest failed\n");
			return (MNOMEM);
		}

		/* update /var/spool/lp/requests/<host>/nnn-0 */
		if ((securep = Getsecure(rp->req_file))) {
			reqno = strdup(getreqno(securep->req_id));
			(void) free(securep->req_id);
			if ((securep->req_id = calloc(strlen(dest) + 1 +
				strlen(reqno) +1, sizeof (char))) == NULL)
				return (MNOMEM);
			(void) sprintf(securep->req_id, "%s-%s", dest, reqno);
			/* remove the old request file; save new one */
			(void) rmsecure(rp->secure->req_id);
			if (Putsecure(rp->req_file, securep) < 0) {
				/* Putsecure includes note/errmessage */
				return (MNOMEM);
			}
		} else {
			note("Getsecure failed\n");
			return (MNOMEM);
		}

		/* update internal jobs list: Request_list */
		if (prs = request_by_id(rp->secure->req_id)) {
			free(prs->secure->req_id);
			prs->secure->req_id = strdup(securep->req_id);

			/*
			 * We calloc'd securep->reqid earlier, now we free it
			 * here because we no longer call 'freesecure' from
			 * Putsecure() if we use a static structure
			 */

			free(securep->req_id);
		} else {
			note("request_by_id failed\n");
			return (MUNKNOWN);
		}

		/*
		 * If the request was being filtered or was printing,
		 * it would have been stopped in "validate_request()",
		 * but only if it has to be refiltered. Thus, the
		 * filtering has been stopped if it has to be stopped,
		 * but the printing may still be going.
		 */
		if (rp->request->outcome & RS_PRINTING &&
		    !(rp->request->outcome & RS_STOPPED)) {
			rp->request->outcome |= RS_STOPPED;
			terminate (oldexec);
	        }

		maybe_schedule(rp);
		return (MOK);
	}

	Free(rp->request->destination);
	rp->request->destination = olddest;
	return (stat);
}

/*
 * s_move_request()
 */

void s_move_request(char *m, MESG *md)
{
	RSTATUS	*rp;
	short	err;
	char	*req_id;
	char	*dest;

	(void) getmessage(m, S_MOVE_REQUEST, &req_id, &dest);
	syslog(LOG_DEBUG, "s_move_request(%s, %s)", (req_id ? req_id : "NULL"),
	       (dest ? dest : "NULL"));


	if (!(search_pstatus(dest)) && !(search_cstatus(dest))) {
		mputm(md, R_MOVE_REQUEST, MNODEST, 0L);
		return;
	}

	if ((rp = request_by_id(req_id))) {
		if (STREQU(rp->request->destination, dest)) {
			mputm(md, R_MOVE_REQUEST, MOK, 0L);
			return;
		}
		if (rp->request->outcome & (RS_DONE|RS_NOTIFYING)) {
			mputm(md, R_MOVE_REQUEST, M2LATE, 0L);
			return;
		}
		if (rp->request->outcome & RS_CHANGING)	{
			mputm(md, R_MOVE_REQUEST, MBUSY, 0L);
			return;
		}
		if ((err = mv_file(rp, dest)) == MOK) {
			mputm(md, R_MOVE_REQUEST, MOK, 0L);
			return;
		}
		mputm(md, R_MOVE_REQUEST, err, chkprinter_result);
		return;
	}
	mputm(md, R_MOVE_REQUEST, MUNKNOWN, 0L);
}

/**
 ** s_move_dest()
 **/

void s_move_dest(char *m, MESG *md)
{
    char		*dest;
    char		*fromdest;
    RSTATUS		*rp;
    char		*found = (char *)0;
    short		num_ok = 0;

    (void) getmessage(m, S_MOVE_DEST, &fromdest, &dest);
    syslog(LOG_DEBUG, "s_move_dest(%s, %s)", (fromdest ? fromdest : "NULL"),
	   (dest ? dest : "NULL"));

    if (!search_pstatus(fromdest) && !search_cstatus(fromdest))
    {
	mputm(md, R_MOVE_DEST, MNODEST, fromdest, 0);
	return;
    }

    if (!(search_pstatus(dest)) && !(search_cstatus(dest)))
    {
	mputm(md, R_MOVE_DEST, MNODEST, dest, 0);
	return;
    }

    if (STREQU(dest, fromdest))
    {
	mputm(md, R_MOVE_DEST, MOK, "", 0);
	return;
    }

    for (rp = Request_List; rp != NULL; rp = rp->next) {
	if ((STREQU(rp->request->destination, fromdest)) &&
	    (!(rp->request->outcome & (RS_DONE|RS_CHANGING|RS_NOTIFYING)))) {
	    if (mv_file(rp, dest) == MOK) {
		num_ok++;
		continue;
	    }
	}

	if (found)
	    mputm(md, R_MOVE_DEST, MMORERR, found, 0);

	found = rp->secure->req_id;
    }

    if (found)
	mputm(md, R_MOVE_DEST, MERRDEST, found, num_ok);
    else
	mputm(md, R_MOVE_DEST, MOK, "", num_ok);
}

/**
 ** reqpath
 **/

static char *
reqpath(char *file, char **idnumber)
{
    char	*path;
    char	*cp;
    char	*cp2;
    
    /*
    **	/var/spool/lp/tmp/machine/123-0
    **	/var/spool/lp/temp/123-0
    **	/usr/spool/lp/temp/123-0
    **	/usr/spool/lp/tmp/machine/123-0
    **	123-0
    **	machine/123-0
    **
    **	/var/spool/lp/tmp/machine/123-0 + 123
    */
    if (*file == '/')
    {
	/*CONSTCOND*/
	if (STRNEQU(file, Lp_Spooldir, strlen(Lp_Spooldir)))
	    cp = file + strlen(Lp_Spooldir) + 1;
	else
	    if(STRNEQU(file, "/usr/spool/lp", 13))
		cp = file + strlen("/usr/spool/lp") + 1;
	    else
	    {
		*idnumber = NULL;
		return(NULL);
	    }

	if (STRNEQU(cp, "temp", 4))
	{
	    cp += 5;
	    path = makepath(Local_System, cp, NULL);
	}
	else
	    path = Strdup(cp);
    }
    else
    {
	if (strchr(file, '/'))
	    path = makepath(file, NULL);
	else
	    path = makepath(Local_System, file, NULL);
    }

    cp = strrchr(path, '/');
    cp++;
    if ((cp2 = strrchr(cp, '-')) == NULL)
	*idnumber = Strdup(cp);
    else
    {
	*cp2 = '\0';
	*idnumber = Strdup(cp);
	*cp2 = '-';
    }

    return(path);
}

/*
 * The client is sending a peer connection to retrieve label information
 * from.  This is used in the event that the client is an intermediary for
 * the actual requestor in a Trusted environment.
 */
void s_pass_peer_connection(char *m, MESG *md)
{
	short	status = MTRANSMITERR;
	char	*dest;
	struct strrecvfd recv_fd;

	(void) getmessage(m, S_PASS_PEER_CONNECTION);
	syslog(LOG_DEBUG, "s_pass_peer_connection()");

	memset(&recv_fd, NULL, sizeof (recv_fd));
	if (ioctl(md->readfd, I_RECVFD, &recv_fd) == 0) {
		int fd = recv_fd.fd;

		if (get_peer_label(fd, &md->slabel) == 0) {
			if (md->admin == 1)
				md->admin = -1; /* turn off query privilege */
			status = MOK;
		}

		close(fd);
	}

	mputm(md, R_PASS_PEER_CONNECTION, status);
}