Home | History | Annotate | Download | only in lpsched
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     27 /*	  All Rights Reserved  	*/
     28 
     29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     30 
     31 #include "dispatch.h"
     32 #include <sys/types.h>
     33 #include <sys/stat.h>
     34 #include <syslog.h>
     35 
     36 static char	*reqpath(char *, char **);
     37 static int	mv_file(RSTATUS *, char *);
     38 
     39 
     40 RSTATUS			*NewRequest;
     41 
     42 /**
     43  ** s_alloc_files()
     44  **/
     45 
     46 void s_alloc_files ( char * m, MESG * md )	/* funcdef */
     47 {
     48     char			*file_prefix;
     49     ushort			count;
     50     mode_t			old_msk;
     51 
     52 
     53     /*
     54      * Bugid 4140311
     55      * Set umask to 0 before creating files.
     56      */
     57     old_msk = umask((mode_t) 0);
     58 
     59     getmessage (m, S_ALLOC_FILES, &count);
     60     syslog(LOG_DEBUG, "s_alloc_files(%d)", count);
     61 
     62     if ((file_prefix = _alloc_files(count, (char *)0, md->uid, md->gid))) {
     63 	mputm (md, R_ALLOC_FILES, MOK, file_prefix);
     64 	add_flt_act(md, FLT_FILES, file_prefix, count);
     65     }
     66     else if (errno == EEXIST)
     67 	mputm (md, R_ALLOC_FILES, MERRDEST, "");
     68     else
     69 	mputm (md, R_ALLOC_FILES, MNOMEM, "");
     70 
     71     (void) umask(old_msk);
     72 
     73     return;
     74 }
     75 
     76 /**
     77  ** s_print_request()
     78  **/
     79 
     80 void s_print_request ( char * m, MESG * md )
     81 {
     82     extern char			*Local_System;
     83     char			*file;
     84     char			*idno;
     85     char			*path;
     86     char			*req_file;
     87     char			*req_id	= 0;
     88     RSTATUS			*rp;
     89     REQUEST			*r;
     90     SECURE			*s;
     91     struct passwd		*pw;
     92     short			err;
     93     short			status;
     94     off_t			size;
     95     uid_t			org_uid;
     96     gid_t			org_gid;
     97 #ifdef LP_USE_PAPI_ATTR
     98     struct stat			tmpBuf;
     99     char 			tmpName[BUFSIZ];
    100 #endif
    101 
    102 
    103     (void) getmessage (m, S_PRINT_REQUEST, &file);
    104     syslog(LOG_DEBUG, "s_print_request(%s)", (file ? file : "NULL"));
    105 
    106     /*
    107      * "NewRequest" points to a request that's not yet in the
    108      * request list but is to be considered with the rest of the
    109      * requests (e.g. calculating # of requests awaiting a form).
    110      */
    111     if ((rp = NewRequest = new_rstatus(NULL, NULL)) == NULL)
    112 	status = MNOMEM;
    113 
    114     else
    115     {
    116 	req_file = reqpath(file, &idno);
    117 	path = makepath(Lp_Tmp, req_file, (char *)0);
    118 	(void) chownmod(path, Lp_Uid, Lp_Gid, 0600);
    119 	Free (path);
    120 
    121 	if (!(r = Getrequest(req_file)))
    122 	    status = MNOOPEN;
    123 
    124 	else
    125 	{
    126 	    rp->req_file = Strdup(req_file);
    127 
    128 	    freerequest(rp->request);
    129 	    rp->request = r;
    130 
    131 	    rp->request->outcome = 0;
    132 	    rp->secure->uid = md->uid;
    133 	    rp->secure->gid = md->gid;
    134 	    if (md->slabel != NULL)
    135 		    rp->secure->slabel = Strdup(md->slabel);
    136 
    137 	    pw = getpwuid(md->uid);
    138 	    endpwent();
    139 	    if (pw && pw->pw_name && *pw->pw_name)
    140 		rp->secure->user = Strdup(pw->pw_name);
    141 	    else {
    142 		rp->secure->user = Strdup(BIGGEST_NUMBER_S);
    143 		(void) sprintf (rp->secure->user, "%u", md->uid);
    144 	    }
    145 
    146 	    if ((rp->request->actions & ACT_SPECIAL) == ACT_HOLD)
    147 	        rp->request->outcome |= RS_HELD;
    148 	    if ((rp->request->actions & ACT_SPECIAL) == ACT_RESUME)
    149 	        rp->request->outcome &= ~RS_HELD;
    150 	    if((rp->request->actions & ACT_SPECIAL) == ACT_IMMEDIATE) {
    151 	        if (!md->admin) {
    152 	    		status = MNOPERM;
    153 	    		goto Return;
    154 	        }
    155 	        rp->request->outcome |= RS_IMMEDIATE;
    156 	    }
    157 
    158 	    size = chfiles(rp->request->file_list, Lp_Uid, Lp_Gid);
    159 
    160 	    if (size < 0) {
    161 	    /* at this point, chfiles() may have failed because the
    162 	     * the file may live on an NFS mounted filesystem, under
    163 	     * a directory of mode 700. such a directory isn't
    164 	     * accessible even by root, according to the NFS protocol
    165 	     * (i.e. the Stat() in chfiles() failed). this most commonly
    166 	     * happens via the automounter, and rlogin.
    167 	     *
    168 	     * thus we change our euid/egid to that of the user, and
    169 	     * try again. if *this* fails, then the file must really
    170 	     * be inaccessible.
    171 	     */
    172 	        org_uid = geteuid();
    173 	        org_gid = getegid();
    174 
    175 	        if (setegid(md->gid) != 0) {
    176 	    	    status = MUNKNOWN;
    177 	    	    goto Return;
    178 	        }
    179 
    180 	        if (seteuid(md->uid) != 0) {
    181 	    	    setgid(org_gid);
    182 	    	    status = MUNKNOWN;
    183 	    	    goto Return;
    184 	        }
    185 
    186 	        size = chfiles(rp->request->file_list, Lp_Uid, Lp_Gid);
    187 
    188 	        if (seteuid(org_uid) != 0) { /* should never happen */
    189 	    		note("s_print_request(): ");
    190 	    		note("seteuid back to uid=%d failed!!\n", org_uid);
    191 	    		size = -1;
    192 	        }
    193 
    194 	        if (setegid(org_gid) != 0) { /* should never happen */
    195 	    		note("s_print_request(): ");
    196 	    		note("setegid back to uid=%d failed!!\n", org_uid);
    197 	    		size = -1;
    198 	        }
    199 
    200 	        if (size < 0) {
    201 	    	    	status = MUNKNOWN;
    202 	    	    	goto Return;
    203 	        }
    204 	    }
    205 	    if (!(rp->request->outcome & RS_HELD) && size == 0) {
    206 	        	status = MNOPERM;
    207 	        	goto Return;
    208 	    }
    209 	    rp->secure->size = size;
    210 
    211 	    (void) time(&rp->secure->date);
    212 	    rp->secure->req_id = NULL;
    213 
    214 	   if (!rp->request->title) {
    215 		if (strlen(*rp->request->file_list) < (size_t)24)
    216 			rp->request->title = Strdup(*rp->request->file_list);
    217 		else {
    218 			char *r;
    219 
    220 			if (r = strrchr(*rp->request->file_list, '/'))
    221 				r++;
    222 			else
    223 				r = *rp->request->file_list ;
    224 
    225 			rp->request->title = malloc(25);
    226 			sprintf(rp->request->title, "%-.24s", r);
    227 		}
    228 	   }
    229 
    230 	    if((err = validate_request(rp, &req_id, 0)) != MOK)
    231 		status = err;
    232 	    else {
    233 		/*
    234 		 * "req_id" will be supplied if this is from a
    235 		 * remote system.
    236 		 */
    237 		if (rp->secure->req_id == NULL)
    238 		{
    239 		    req_id = makestr(req_id, "-", idno, (char *)0);
    240 		    rp->secure->req_id = req_id;
    241 		} else
    242 		    req_id = rp->secure->req_id;
    243 
    244 #ifdef LP_USE_PAPI_ATTR
    245 		/*
    246 		 * Check if the PAPI job attribute file exists, if it does
    247 		 * change the permissions and ownership of the file. This file
    248 		 * is created when print jobs are submitted via the PAPI
    249 		 * interface, the file pathname of this file is passed to
    250 		 * the slow-filters and printer interface script as an
    251 		 * environment variable when they are executed
    252 		 */
    253 		snprintf(tmpName, sizeof (tmpName),
    254 			"%s-%s", idno, LP_PAPIATTRNAME);
    255 		path = makepath(Lp_Temp, tmpName, (char *)0);
    256 
    257 		if (stat(path, &tmpBuf) == 0)
    258 		{
    259 			syslog(LOG_DEBUG,
    260 				"s_print_request: attribute file ='%s'", path);
    261 
    262 			/*
    263 			 * IPP job attribute file exists for this job so
    264 			 * change permissions and ownership of the file
    265 			 */
    266 			(void) chownmod(path, Lp_Uid, Lp_Gid, 0600);
    267 			Free(path);
    268 		}
    269 		else
    270 		{
    271 			syslog(LOG_DEBUG, "s_print_request: no attribute file");
    272 		}
    273 #endif
    274 
    275 		/* fix for bugid 1103890. use Putsecure instead. */
    276 		if (
    277 		    Putsecure(req_file, rp->secure) == -1
    278 		 || putrequest(req_file, rp->request) == -1
    279 		)
    280 		    status = MNOMEM;
    281 		else
    282 		{
    283 		    status = MOK;
    284 
    285 		    insertr(rp);
    286 		    NewRequest = 0;
    287 
    288 		    if (rp->slow)
    289 			schedule (EV_SLOWF, rp);
    290 		    else
    291 			schedule (EV_INTERF, rp->printer);
    292 
    293 		    del_flt_act(md, FLT_FILES);
    294 		}
    295 	    }
    296 	}
    297     }
    298 
    299 Return:
    300     NewRequest = 0;
    301     Free(req_file);
    302     Free(idno);
    303     if (status != MOK && rp) {
    304 	rmfiles(rp, 0);
    305 	free_rstatus(rp);
    306     }
    307     mputm(md, R_PRINT_REQUEST, status, NB(req_id), chkprinter_result);
    308     return;
    309 }
    310 
    311 /**
    312  ** s_start_change_request()
    313  **/
    314 
    315 void s_start_change_request (char *m, MESG *md)
    316 {
    317     char		*req_id;
    318     char		*req_file	= "";
    319     short		status;
    320     RSTATUS		*rp;
    321     char		*path;
    322 
    323     (void) getmessage(m, S_START_CHANGE_REQUEST, &req_id);
    324     syslog(LOG_DEBUG, "s_start_change_request(%s)",
    325 	   (req_id ? req_id : "NULL"));
    326 
    327 
    328     if (!(rp = request_by_id(req_id)))
    329 	status = MUNKNOWN;
    330     else if ((md->admin == 0) && (is_system_labeled()) &&
    331 	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
    332 	    (!STREQU(md->slabel, rp->secure->slabel)))
    333 	status = MUNKNOWN;
    334     else if (rp->request->outcome & RS_DONE)
    335 	status = M2LATE;
    336     else if (!md->admin && md->uid != rp->secure->uid)
    337 	status = MNOPERM;
    338     else if (rp->request->outcome & RS_CHANGING)
    339 	status = MNOOPEN;
    340     else if (rp->request->outcome & RS_NOTIFYING)
    341 	status = MBUSY;
    342     else {
    343 	status = MOK;
    344 
    345 	if (
    346 	    rp->request->outcome & RS_FILTERING
    347 	 && !(rp->request->outcome & RS_STOPPED)
    348 	)
    349 	{
    350 	    rp->request->outcome |= (RS_REFILTER|RS_STOPPED);
    351 	    terminate (rp->exec);
    352 	}
    353 
    354 	if (
    355 	    rp->request->outcome & RS_PRINTING
    356 	 && !(rp->request->outcome & RS_STOPPED)
    357 	)
    358 	{
    359 	    rp->request->outcome |= RS_STOPPED;
    360 	    terminate (rp->printer->exec);
    361 	}
    362 
    363 	rp->request->outcome |= RS_CHANGING;
    364 
    365 	/*
    366 	 * Change the ownership of the request file to be "md->uid".
    367 	 * Either this is identical to "rp->secure->uid", or it is
    368 	 * "Lp_Uid" or it is root. The idea is that the
    369 	 * person at the other end needs access, and that may not
    370 	 * be who queued the request.
    371 	 */
    372 	path = makepath(Lp_Tmp, rp->req_file, (char *)0);
    373 	(void) Chown(path, md->uid, rp->secure->gid);
    374 	Free (path);
    375 
    376 	add_flt_act(md, FLT_CHANGE, rp);
    377 	req_file = rp->req_file;
    378 
    379     }
    380     mputm(md, R_START_CHANGE_REQUEST, status, req_file);
    381     return;
    382 }
    383 
    384 /**
    385  ** s_end_change_request()
    386  **/
    387 
    388 void s_end_change_request(char *m, MESG *md)
    389 {
    390     char		*req_id;
    391     RSTATUS		*rp;
    392     off_t		size;
    393     off_t		osize;
    394     short		err;
    395     short		status;
    396     REQUEST		*r		= 0;
    397     REQUEST		oldr;
    398     int			call_schedule	= 0;
    399     int			move_ok		= 0;
    400     char		*path;
    401 
    402     (void) getmessage(m, S_END_CHANGE_REQUEST, &req_id);
    403     syslog(LOG_DEBUG, "s_end_change_request(%s)", (req_id ? req_id : "NULL"));
    404 
    405     if (!(rp = request_by_id(req_id)))
    406 	status = MUNKNOWN;
    407     else if ((md->admin == 0) && (is_system_labeled()) &&
    408 	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
    409 	    (!STREQU(md->slabel, rp->secure->slabel)))
    410 	status = MUNKNOWN;
    411     else if (!(rp->request->outcome & RS_CHANGING))
    412 	status = MNOSTART;
    413     else {
    414 	path = makepath(Lp_Tmp, rp->req_file, (char *)0);
    415 	(void) chownmod(path, Lp_Uid, Lp_Gid, 0600);
    416 	Free (path);
    417 
    418 	rp->request->outcome &= ~(RS_CHANGING);
    419 	del_flt_act(md, FLT_CHANGE);
    420 	/*
    421 	 * The RS_CHANGING bit may have been the only thing preventing
    422 	 * this request from filtering or printing, so regardless of what
    423 	 * happens below, we must check to see if the request can proceed.
    424 	 */
    425 	call_schedule = 1;
    426 
    427 	if (!(r = Getrequest(rp->req_file)))
    428 	    status = MNOOPEN;
    429 	else {
    430 	    oldr = *(rp->request);
    431 	    *(rp->request) = *r;
    432 
    433 	    move_ok = STREQU(oldr.destination, r->destination);
    434 
    435 	    /*
    436 	     * Preserve the current request status!
    437 	     */
    438 	    rp->request->outcome = oldr.outcome;
    439 
    440 	    /*
    441 	     * Here's an example of the dangers one meets when public
    442 	     * flags are used for private purposes. ".actions" (indeed,
    443 	     * anything in the REQUEST structure) is set by the person
    444 	     * changing the job. However, lpsched uses ".actions" as
    445 	     * place to indicate that a job came from a remote system
    446 	     * and we must send back job completion--this is a strictly
    447 	     * private flag that we must preserve.
    448 	     */
    449 	    rp->request->actions |= (oldr.actions & ACT_NOTIFY);
    450 
    451 	    if ((rp->request->actions & ACT_SPECIAL) == ACT_HOLD) {
    452 		rp->request->outcome |= RS_HELD;
    453 		/*
    454 		 * To be here means either the user owns the request
    455 		 * or he or she is the administrator. Since we don't
    456 		 * want to set the RS_ADMINHELD flag if the user is
    457 		 * the administrator, the following compare will work.
    458 		 */
    459 		if (md->uid != rp->secure->uid)
    460 		    rp->request->outcome |= RS_ADMINHELD;
    461 	    }
    462 
    463 	    if ((rp->request->actions & ACT_SPECIAL) == ACT_RESUME) {
    464 		if ((rp->request->outcome & RS_ADMINHELD) && !md->admin) {
    465 		    status = MNOPERM;
    466 		    goto Return;
    467 		}
    468 		rp->request->outcome &= ~(RS_ADMINHELD|RS_HELD);
    469 	    }
    470 
    471 	    if((rp->request->actions & ACT_SPECIAL) == ACT_IMMEDIATE) {
    472 		if (!md->admin)
    473 		{
    474 		    status = MNOPERM;
    475 		    goto Return;
    476 		}
    477 		rp->request->outcome |= RS_IMMEDIATE;
    478 	    }
    479 
    480 	    size = chfiles(rp->request->file_list, Lp_Uid, Lp_Gid);
    481 	    if (size < 0) {
    482 		status = MUNKNOWN;
    483 		goto Return;
    484 	    }
    485 	    if (!(rp->request->outcome & RS_HELD) && size == 0) {
    486 		status = MNOPERM;
    487 		goto Return;
    488 	    }
    489 
    490 	    osize = rp->secure->size;
    491 	    rp->secure->size = size;
    492 
    493 	    if (move_ok == 0) {
    494 		char *dest = strdup(r->destination);
    495 		if ((status = mv_file(rp, dest)) == MOK)
    496 			rp->secure->size = osize;
    497 		free(dest);
    498 	    } else if ((err = validate_request(rp, (char **)0, move_ok))\
    499 	    != MOK) {
    500 		status = err;
    501 		rp->secure->size = osize;
    502 	    } else {
    503 		status = MOK;
    504 
    505 		if ((rp->request->outcome & RS_IMMEDIATE) ||
    506 		    (rp->request->priority != oldr.priority)) {
    507 		    remover(rp);
    508 		    insertr(rp);
    509 		}
    510 
    511 		freerequest(&oldr);
    512 		(void) putrequest(rp->req_file, rp->request);
    513 		/* fix for bugid 1103890. use Putsecure instead.       */
    514 		(void) Putsecure(rp->req_file, rp->secure);
    515 	    }
    516 	}
    517     }
    518 
    519 Return:
    520     if (status != MOK && rp) {
    521 	if (r) {
    522 	    freerequest(r);
    523 	    *(rp->request) = oldr;
    524 	}
    525 	if (status != MNOSTART)
    526 	    (void) putrequest(rp->req_file, rp->request);
    527     }
    528 
    529     if (call_schedule)
    530 	maybe_schedule(rp);
    531 
    532     mputm(md, R_END_CHANGE_REQUEST, status, chkprinter_result);
    533     return;
    534 }
    535 
    536 /**
    537  ** _cancel()
    538  **	user may be (host!user)
    539  **/
    540 
    541 static char *
    542 _cancel(MESG *md, char *dest, char *user, char *req_id)
    543 {
    544     static RSTATUS	*rp;
    545     static char		*s_dest;
    546     static char		*s_user;
    547     static char		*s_req_id;
    548     static int		current;
    549     RSTATUS		*crp;
    550     char		*creq_id;
    551 
    552     syslog(LOG_DEBUG, "_cancel(%s, %s, %s)", (dest ? dest : "NULL"),
    553 	   (user ? user : "NULL"), (req_id ? req_id : "NULL"));
    554 
    555     if (dest || user || req_id) {
    556 	s_dest = dest;
    557         if (STREQU(user, "!"))
    558 		s_user = strdup("all!all");
    559 	else
    560 		s_user = user;
    561 	s_req_id = req_id;
    562 	rp = Request_List;
    563 	current = 0;
    564 	if (STREQU(s_req_id, CURRENT_REQ)) {
    565 	    current = 1;
    566 	    s_req_id = NULL;
    567 	}
    568     }
    569 
    570     while (rp != NULL) {
    571 	crp = rp;
    572 	rp = rp->next;
    573 
    574 	if (*s_dest && !STREQU(s_dest, crp->request->destination))
    575 	    continue;
    576 
    577 	if (current && !(crp->request->outcome & RS_PRINTING))
    578 	    continue;
    579 
    580 	if (s_req_id && *s_req_id && !STREQU(s_req_id, crp->secure->req_id))
    581 	    continue;
    582 
    583 	if (*s_user && !bangequ(s_user, crp->secure->user))
    584 	    continue;
    585 
    586 	if (!md->admin && md->uid != crp->secure->uid) {
    587 	    errno = MNOPERM;
    588 	    return(Strdup(crp->secure->req_id));
    589 	}
    590 
    591 	/*
    592 	 * For Trusted Extensions, we need to check the sensitivity label of the
    593 	 * connection and job before we try to cancel it.
    594 	 */
    595 	if ((md->admin == 0) && (is_system_labeled()) &&
    596 	    (md->slabel != NULL) && (crp->secure->slabel != NULL) &&
    597 	    (!STREQU(md->slabel, crp->secure->slabel)))
    598 	    continue;
    599 
    600 	crp->reason = MOK;
    601 	creq_id = Strdup(crp->secure->req_id);
    602 
    603 	syslog(LOG_DEBUG, "cancel reqid (%s) uid: %d, secureuid: %d",
    604 		creq_id, md->uid, crp->secure->uid);
    605 
    606 	if (cancel(crp, (md->uid != crp->secure->uid)))
    607 	    errno = MOK;
    608 	else
    609 	    errno = M2LATE;
    610 	return(creq_id);
    611     }
    612 
    613     errno = MUNKNOWN;
    614     return(NULL);
    615 }
    616 
    617 /**
    618  ** s_cancel_request()
    619  **/
    620 
    621 void s_cancel_request(char *m, MESG *md)
    622 {
    623 	char	*req_id, *rid;
    624 	short	status;
    625 
    626 	(void) getmessage(m, S_CANCEL_REQUEST, &req_id);
    627 	syslog(LOG_DEBUG, "s_cancel_request(%s)", (req_id ? req_id : "NULL"));
    628 
    629 	if ((rid = _cancel(md, "", "", req_id)) != NULL)
    630 		Free(rid);
    631 	status = (short)errno;
    632 
    633 	mputm(md, R_CANCEL_REQUEST, status);
    634 }
    635 
    636 /**
    637  ** s_cancel()
    638  **/
    639 
    640 void s_cancel(char *m, MESG *md)
    641 {
    642     char	*req_id;
    643     char	*user;
    644     char	*destination;
    645     char	*rid;
    646     char	*nrid;
    647     int		nerrno;
    648     int		oerrno;
    649 
    650     (void) getmessage(m, S_CANCEL, &destination, &user, &req_id);
    651     syslog(LOG_DEBUG, "s_cancel(%s, %s, %s)",
    652 	   (destination ? destination : "NULL"), (user ? user : "NULL"),
    653 	   (req_id ? req_id : "NULL"));
    654 
    655     if (STREQU(destination, NAME_ALL))
    656 	destination = "";
    657     if (STREQU(req_id, NAME_ALL))
    658 	req_id = "";
    659 
    660     if (rid = _cancel(md, destination, user, req_id)) {
    661 	oerrno = errno;
    662 
    663 	while ((nrid = _cancel(md, NULL, NULL, NULL)) != NULL) {
    664 	    nerrno = errno;
    665 	    mputm(md, R_CANCEL, MOKMORE, oerrno, rid);
    666 	    Free(rid);
    667 	    rid = nrid;
    668 	    oerrno = nerrno;
    669 	}
    670 	mputm(md, R_CANCEL, MOK, oerrno, rid);
    671 	Free(rid);
    672 	return;
    673     }
    674 
    675     mputm(md, R_CANCEL, MOK, MUNKNOWN, "");
    676 }
    677 
    678 /*
    679  * s_inquire_request_rank()
    680  */
    681 
    682 void s_inquire_request_rank(char *m, MESG *md)
    683 {
    684 	char		*form;
    685 	char		*dest;
    686 	char		*pwheel;
    687 	char		*user;
    688 	char		*req_id;
    689 	RSTATUS		*rp;
    690 	RSTATUS		*found = NULL;
    691 	int		found_rank = 0;
    692 	short		prop;
    693 	char		files[BUFSIZ];
    694 	int 		i;
    695 
    696 	(void) getmessage(m, S_INQUIRE_REQUEST_RANK, &prop, &form, &dest,
    697 		&req_id, &user, &pwheel);
    698 	syslog(LOG_DEBUG, "s_inquire_request_rank(%d, %s, %s, %s, %s, %s)",
    699 	   prop, (form ? form : "NULL"), (dest ? dest : "NULL"),
    700 	   (req_id ? req_id : "NULL"), (user ? user : "NULL"),
    701 	   (pwheel ? pwheel : "NULL"));
    702 
    703 	for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
    704 		PStatus[i]->nrequests = 0;
    705 
    706 	for (rp = Request_List; rp != NULL; rp = rp->next) {
    707 		if (rp->printer && !(rp->request->outcome & RS_DONE))
    708 			rp->printer->nrequests++;
    709 
    710 		if (*form && !SAME(form, rp->request->form))
    711 			continue;
    712 
    713 		if (*dest && !STREQU(dest, rp->request->destination)) {
    714 			if (!rp->printer)
    715 				continue;
    716 			if (!STREQU(dest, rp->printer->printer->name))
    717 				continue;
    718 		}
    719 
    720 		if (*req_id && !STREQU(req_id, rp->secure->req_id))
    721 			continue;
    722 
    723 		if (*user && !bangequ(user, rp->secure->user))
    724 			continue;
    725 
    726 		if (*pwheel && !SAME(pwheel, rp->pwheel_name))
    727 			continue;
    728 		/*
    729 		 * For Trusted Extensions, we need to check the sensitivity
    730 		 * label of the connection and job before we return it to the
    731 		 * client.
    732 		 */
    733 		if ((md->admin <= 0) && (is_system_labeled()) &&
    734 		    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
    735 		    (!STREQU(md->slabel, rp->secure->slabel)))
    736 			continue;
    737 
    738 		if (found) {
    739 			GetRequestFiles(found->request, files, sizeof(files));
    740 			mputm(md, R_INQUIRE_REQUEST_RANK,
    741 				MOKMORE,
    742 				found->secure->req_id,
    743 				found->request->user,
    744 					/* bgolden 091996, bug 1257405 */
    745 				found->secure->slabel,
    746 				found->secure->size,
    747 				found->secure->date,
    748 				found->request->outcome,
    749 				found->printer->printer->name,
    750 				(found->form? found->form->form->name : ""),
    751 				NB(found->pwheel_name),
    752 				found_rank,
    753 				files
    754 			);
    755 		}
    756 		found = rp;
    757 		found_rank = found->printer->nrequests;
    758 	}
    759 
    760 	if (found) {
    761 		GetRequestFiles(found->request, files, sizeof(files));
    762 		mputm(md, R_INQUIRE_REQUEST_RANK,
    763 			MOK,
    764 			found->secure->req_id,
    765 			found->request->user, /* bgolden 091996, bug 1257405 */
    766 			found->secure->slabel,
    767 			found->secure->size,
    768 			found->secure->date,
    769 			found->request->outcome,
    770 			found->printer->printer->name,
    771 			(found->form? found->form->form->name : ""),
    772 			NB(found->pwheel_name),
    773 			found_rank,
    774 			files
    775 		);
    776 	} else
    777 		mputm(md, R_INQUIRE_REQUEST_RANK, MNOINFO, "", "", "", 0L, 0L,
    778 			0, "", "", "", 0, "");
    779 }
    780 
    781 static int
    782 mv_file(RSTATUS *rp, char *dest)
    783 {
    784 	int	stat;
    785 	char	*olddest;
    786 	EXEC	*oldexec;
    787 	SECURE * securep;
    788 	RSTATUS * prs;
    789 	char * reqno;
    790 
    791 	oldexec = rp->printer->exec;
    792 	olddest = rp->request->destination;
    793 	rp->request->destination = Strdup(dest);
    794 	if ((stat = validate_request(rp, (char **)0, 1)) == MOK) {
    795 		Free(olddest);
    796 
    797 		if (rp->request->outcome & RS_FILTERED) {
    798 			int cnt = 0;
    799 			char *reqno;
    800 			char **listp;
    801 			char tmp_nam[MAXPATHLEN];
    802 
    803 			reqno = getreqno(rp->secure->req_id);
    804 			for (listp = rp->request->file_list; *listp; listp++) {
    805 				cnt++;
    806 				snprintf(tmp_nam, sizeof (tmp_nam),
    807 					"%s/F%s-%d", Lp_Temp, reqno, cnt);
    808 				unlink(tmp_nam);
    809 
    810 			}
    811 			rp->request->outcome &= ~RS_FILTERED;
    812 		}
    813 
    814 		/* update /var/spool/lp/tmp/<host>/nnn-0 */
    815 		if (putrequest(rp->req_file, rp->request) < 0) {
    816 			note("putrequest failed\n");
    817 			return (MNOMEM);
    818 		}
    819 
    820 		/* update /var/spool/lp/requests/<host>/nnn-0 */
    821 		if ((securep = Getsecure(rp->req_file))) {
    822 			reqno = strdup(getreqno(securep->req_id));
    823 			(void) free(securep->req_id);
    824 			if ((securep->req_id = calloc(strlen(dest) + 1 +
    825 				strlen(reqno) +1, sizeof (char))) == NULL)
    826 				return (MNOMEM);
    827 			(void) sprintf(securep->req_id, "%s-%s", dest, reqno);
    828 			/* remove the old request file; save new one */
    829 			(void) rmsecure(rp->secure->req_id);
    830 			if (Putsecure(rp->req_file, securep) < 0) {
    831 				/* Putsecure includes note/errmessage */
    832 				return (MNOMEM);
    833 			}
    834 		} else {
    835 			note("Getsecure failed\n");
    836 			return (MNOMEM);
    837 		}
    838 
    839 		/* update internal jobs list: Request_list */
    840 		if (prs = request_by_id(rp->secure->req_id)) {
    841 			free(prs->secure->req_id);
    842 			prs->secure->req_id = strdup(securep->req_id);
    843 
    844 			/*
    845 			 * We calloc'd securep->reqid earlier, now we free it
    846 			 * here because we no longer call 'freesecure' from
    847 			 * Putsecure() if we use a static structure
    848 			 */
    849 
    850 			free(securep->req_id);
    851 		} else {
    852 			note("request_by_id failed\n");
    853 			return (MUNKNOWN);
    854 		}
    855 
    856 		/*
    857 		 * If the request was being filtered or was printing,
    858 		 * it would have been stopped in "validate_request()",
    859 		 * but only if it has to be refiltered. Thus, the
    860 		 * filtering has been stopped if it has to be stopped,
    861 		 * but the printing may still be going.
    862 		 */
    863 		if (rp->request->outcome & RS_PRINTING &&
    864 		    !(rp->request->outcome & RS_STOPPED)) {
    865 			rp->request->outcome |= RS_STOPPED;
    866 			terminate (oldexec);
    867 	        }
    868 
    869 		maybe_schedule(rp);
    870 		return (MOK);
    871 	}
    872 
    873 	Free(rp->request->destination);
    874 	rp->request->destination = olddest;
    875 	return (stat);
    876 }
    877 
    878 /*
    879  * s_move_request()
    880  */
    881 
    882 void s_move_request(char *m, MESG *md)
    883 {
    884 	RSTATUS	*rp;
    885 	short	err;
    886 	char	*req_id;
    887 	char	*dest;
    888 
    889 	(void) getmessage(m, S_MOVE_REQUEST, &req_id, &dest);
    890 	syslog(LOG_DEBUG, "s_move_request(%s, %s)", (req_id ? req_id : "NULL"),
    891 	       (dest ? dest : "NULL"));
    892 
    893 
    894 	if (!(search_pstatus(dest)) && !(search_cstatus(dest))) {
    895 		mputm(md, R_MOVE_REQUEST, MNODEST, 0L);
    896 		return;
    897 	}
    898 
    899 	if ((rp = request_by_id(req_id))) {
    900 		if (STREQU(rp->request->destination, dest)) {
    901 			mputm(md, R_MOVE_REQUEST, MOK, 0L);
    902 			return;
    903 		}
    904 		if (rp->request->outcome & (RS_DONE|RS_NOTIFYING)) {
    905 			mputm(md, R_MOVE_REQUEST, M2LATE, 0L);
    906 			return;
    907 		}
    908 		if (rp->request->outcome & RS_CHANGING)	{
    909 			mputm(md, R_MOVE_REQUEST, MBUSY, 0L);
    910 			return;
    911 		}
    912 		if ((err = mv_file(rp, dest)) == MOK) {
    913 			mputm(md, R_MOVE_REQUEST, MOK, 0L);
    914 			return;
    915 		}
    916 		mputm(md, R_MOVE_REQUEST, err, chkprinter_result);
    917 		return;
    918 	}
    919 	mputm(md, R_MOVE_REQUEST, MUNKNOWN, 0L);
    920 }
    921 
    922 /**
    923  ** s_move_dest()
    924  **/
    925 
    926 void s_move_dest(char *m, MESG *md)
    927 {
    928     char		*dest;
    929     char		*fromdest;
    930     RSTATUS		*rp;
    931     char		*found = (char *)0;
    932     short		num_ok = 0;
    933 
    934     (void) getmessage(m, S_MOVE_DEST, &fromdest, &dest);
    935     syslog(LOG_DEBUG, "s_move_dest(%s, %s)", (fromdest ? fromdest : "NULL"),
    936 	   (dest ? dest : "NULL"));
    937 
    938     if (!search_pstatus(fromdest) && !search_cstatus(fromdest))
    939     {
    940 	mputm(md, R_MOVE_DEST, MNODEST, fromdest, 0);
    941 	return;
    942     }
    943 
    944     if (!(search_pstatus(dest)) && !(search_cstatus(dest)))
    945     {
    946 	mputm(md, R_MOVE_DEST, MNODEST, dest, 0);
    947 	return;
    948     }
    949 
    950     if (STREQU(dest, fromdest))
    951     {
    952 	mputm(md, R_MOVE_DEST, MOK, "", 0);
    953 	return;
    954     }
    955 
    956     for (rp = Request_List; rp != NULL; rp = rp->next) {
    957 	if ((STREQU(rp->request->destination, fromdest)) &&
    958 	    (!(rp->request->outcome & (RS_DONE|RS_CHANGING|RS_NOTIFYING)))) {
    959 	    if (mv_file(rp, dest) == MOK) {
    960 		num_ok++;
    961 		continue;
    962 	    }
    963 	}
    964 
    965 	if (found)
    966 	    mputm(md, R_MOVE_DEST, MMORERR, found, 0);
    967 
    968 	found = rp->secure->req_id;
    969     }
    970 
    971     if (found)
    972 	mputm(md, R_MOVE_DEST, MERRDEST, found, num_ok);
    973     else
    974 	mputm(md, R_MOVE_DEST, MOK, "", num_ok);
    975 }
    976 
    977 /**
    978  ** reqpath
    979  **/
    980 
    981 static char *
    982 reqpath(char *file, char **idnumber)
    983 {
    984     char	*path;
    985     char	*cp;
    986     char	*cp2;
    987 
    988     /*
    989     **	/var/spool/lp/tmp/machine/123-0
    990     **	/var/spool/lp/temp/123-0
    991     **	/usr/spool/lp/temp/123-0
    992     **	/usr/spool/lp/tmp/machine/123-0
    993     **	123-0
    994     **	machine/123-0
    995     **
    996     **	/var/spool/lp/tmp/machine/123-0 + 123
    997     */
    998     if (*file == '/')
    999     {
   1000 	/*CONSTCOND*/
   1001 	if (STRNEQU(file, Lp_Spooldir, strlen(Lp_Spooldir)))
   1002 	    cp = file + strlen(Lp_Spooldir) + 1;
   1003 	else
   1004 	    if(STRNEQU(file, "/usr/spool/lp", 13))
   1005 		cp = file + strlen("/usr/spool/lp") + 1;
   1006 	    else
   1007 	    {
   1008 		*idnumber = NULL;
   1009 		return(NULL);
   1010 	    }
   1011 
   1012 	if (STRNEQU(cp, "temp", 4))
   1013 	{
   1014 	    cp += 5;
   1015 	    path = makepath(Local_System, cp, NULL);
   1016 	}
   1017 	else
   1018 	    path = Strdup(cp);