xref: /illumos-gate/usr/src/cmd/lp/cmd/lpsched/disp1.c (revision 3db86aab)
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 2006 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, NULL)))
63     {
64 	mputm (md, R_ALLOC_FILES, MOK, file_prefix);
65 	add_flt_act(md, FLT_FILES, file_prefix, count);
66     }
67     else if (errno == EEXIST)
68 	mputm (md, R_ALLOC_FILES, MERRDEST, "");
69     else
70 	mputm (md, R_ALLOC_FILES, MNOMEM, "");
71 
72     (void) umask(old_msk);
73 
74     return;
75 }
76 
77 /**
78  ** s_print_request()
79  **/
80 
81 void s_print_request ( char * m, MESG * md )
82 {
83     extern char			*Local_System;
84     char			*file;
85     char			*idno;
86     char			*path;
87     char			*req_file;
88     char			*req_id	= 0;
89     RSTATUS			*rp;
90     REQUEST			*r;
91     SECURE			*s;
92     struct passwd		*pw;
93     short			err;
94     short			status;
95     off_t			size;
96     uid_t			org_uid;
97     gid_t			org_gid;
98 #ifdef LP_USE_PAPI_ATTR
99     struct stat			tmpBuf;
100     char 			tmpName[BUFSIZ];
101 #endif
102 
103 
104     (void) getmessage (m, S_PRINT_REQUEST, &file);
105     syslog(LOG_DEBUG, "s_print_request(%s)", (file ? file : "NULL"));
106 
107     /*
108      * "NewRequest" points to a request that's not yet in the
109      * request list but is to be considered with the rest of the
110      * requests (e.g. calculating # of requests awaiting a form).
111      */
112     if ((rp = NewRequest = allocr()) == NULL)
113 	status = MNOMEM;
114 
115     else
116     {
117 	req_file = reqpath(file, &idno);
118 	path = makepath(Lp_Tmp, req_file, (char *)0);
119 	(void) chownmod(path, Lp_Uid, Lp_Gid, 0600);
120 	Free (path);
121 
122 	if (!(r = Getrequest(req_file)))
123 	    status = MNOOPEN;
124 
125 	else
126 	{
127 	    *(rp->request) = *r;
128 	    rp->req_file = Strdup(req_file);
129 
130 	    /*
131 	    **	Test for the presence of a secure file.
132 	    **	If found skip sanity checks.
133 	    **  The secure file will only exist if the request
134 	    **  originated on a different system.  Since the
135 	    **  request has not been validated on this side yet
136 	    **  we remove the secure file until it is.
137 	    **
138 	    */
139 	    if ((s = Getsecure(req_file)))
140 	    {
141 		(void)  rmsecure (req_file);
142 		rp->request->outcome = 0;
143 		*(rp->secure) = *s;
144 		rp->secure->req_id = Strdup(s->req_id);
145 		rp->secure->user = Strdup(s->user);
146 		rp->secure->system = Strdup(s->system);
147 		if (md->slabel != NULL)
148 			rp->secure->slabel = Strdup(md->slabel);
149 		freesecure(s);
150 		/*
151 		**  There are some anomallies associated w/
152 		**  '-1', '-2', etc. files received from other systems
153 		**  so even though the uid and gid will be 'lp'
154 		**  the mode may be incorrect.  'chfiles()' will
155 		**  fix this for us.
156 		*/
157 		(void)	chfiles (rp->request->file_list, Lp_Uid, Lp_Gid);
158 	    }
159 	    else
160 	    {
161 		rp->request->outcome = 0;
162 		rp->secure->uid = md->uid;
163 		rp->secure->gid = md->gid;
164 		if (md->slabel != NULL)
165 			rp->secure->slabel = Strdup(md->slabel);
166 
167 		pw = getpwuid(md->uid);
168 		endpwent();
169 		if (pw && pw->pw_name && *pw->pw_name)
170 		    rp->secure->user = Strdup(pw->pw_name);
171 		else
172 		{
173 		    rp->secure->user = Strdup(BIGGEST_NUMBER_S);
174 		    (void) sprintf (rp->secure->user, "%ld", md->uid);
175 		}
176 
177 		if ((rp->request->actions & ACT_SPECIAL) == ACT_HOLD)
178 		    rp->request->outcome |= RS_HELD;
179 		if ((rp->request->actions & ACT_SPECIAL) == ACT_RESUME)
180 		    rp->request->outcome &= ~RS_HELD;
181 		if((rp->request->actions & ACT_SPECIAL) == ACT_IMMEDIATE)
182 		{
183 		    if (!md->admin)
184 		    {
185 			status = MNOPERM;
186 			goto Return;
187 		    }
188 		    rp->request->outcome |= RS_IMMEDIATE;
189 		}
190 
191 		size = chfiles(rp->request->file_list, Lp_Uid, Lp_Gid);
192 
193 		if (size < 0)
194 		{
195 
196 		/* at this point, chfiles() may have failed because the
197 		 * the file may live on an NFS mounted filesystem, under
198 		 * a directory of mode 700. such a directory isn't
199 		 * accessible even by root, according to the NFS protocol
200 		 * (i.e. the Stat() in chfiles() failed). this most commonly
201 		 * happens via the automounter, and rlogin.
202 		 *
203 		 * thus we change our euid/egid to that of the user, and
204 		 * try again. if *this* fails, then the file must really
205 		 * be inaccessible.
206 		 */
207 		    org_uid = geteuid();
208 		    org_gid = getegid();
209 
210 		    if (setegid(md->gid) != 0) {
211 			    status = MUNKNOWN;
212 			    goto Return;
213 		    }
214 
215 		    if (seteuid(md->uid) != 0) {
216 			    setgid(org_gid);
217 			    status = MUNKNOWN;
218 			    goto Return;
219 		    }
220 
221 		    size = chfiles(rp->request->file_list, Lp_Uid, Lp_Gid);
222 
223 		    if (seteuid(org_uid) != 0) {
224 			/* should never happen */
225 			note("s_print_request(): ");
226 			note("seteuid back to uid=%d failed!!\n", org_uid);
227 			size = -1;
228 		    }
229 
230 		    if (setegid(org_gid) != 0) {
231 			/* should never happen */
232 			note("s_print_request(): ");
233 			note("setegid back to uid=%d failed!!\n", org_uid);
234 			size = -1;
235 		    }
236 
237 		    if (size < 0) {
238 			    status = MUNKNOWN;
239 			    goto Return;
240 		    }
241 		}
242 		if (!(rp->request->outcome & RS_HELD) && size == 0)
243 		{
244 		    status = MNOPERM;
245 		    goto Return;
246 		}
247 		rp->secure->size = size;
248 
249 		(void) time(&rp->secure->date);
250 		rp->secure->req_id = NULL;
251 		rp->secure->system = Strdup(Local_System);
252 	    }
253 
254 	   if (!rp->request->title) {
255 		if (strlen(*rp->request->file_list) < (size_t)24)
256 			rp->request->title = Strdup(*rp->request->file_list);
257 		else {
258 			char *r;
259 
260 			if (r = strrchr(*rp->request->file_list, '/'))
261 				r++;
262 			else
263 				r = *rp->request->file_list ;
264 
265 			rp->request->title = malloc(25);
266 			sprintf(rp->request->title, "%-.24s", r);
267 		}
268 	   }
269 
270 	    if((err = validate_request(rp, &req_id, 0)) != MOK)
271 		status = err;
272 	    else {
273 		/*
274 		 * "req_id" will be supplied if this is from a
275 		 * remote system.
276 		 */
277 		if (rp->secure->req_id == NULL)
278 		{
279 		    req_id = makestr(req_id, "-", idno, (char *)0);
280 		    rp->secure->req_id = req_id;
281 		} else
282 		    req_id = rp->secure->req_id;
283 
284 #ifdef LP_USE_PAPI_ATTR
285 		/*
286 		 * Check if the PAPI job attribute file exists, if it does
287 		 * change the permissions and ownership of the file. This file
288 		 * is created when print jobs are submitted via the PAPI
289 		 * interface, the file pathname of this file is passed to
290 		 * the slow-filters and printer interface script as an
291 		 * environment variable when they are executed
292 		 */
293 		snprintf(tmpName, sizeof (tmpName),
294 			"%s-%s", idno, LP_PAPIATTRNAME);
295 		path = makepath(SPOOLDIR, "temp", tmpName, (char *)0);
296 
297 		if (stat(path, &tmpBuf) == 0)
298 		{
299 			syslog(LOG_DEBUG,
300 				"s_print_request: attribute file ='%s'", path);
301 
302 			/*
303 			 * IPP job attribute file exists for this job so
304 			 * change permissions and ownership of the file
305 			 */
306 			(void) chownmod(path, Lp_Uid, Lp_Gid, 0600);
307 			Free(path);
308 		}
309 		else
310 		{
311 			syslog(LOG_DEBUG, "s_print_request: no attribute file");
312 		}
313 #endif
314 
315 		/* fix for bugid 1103890. use Putsecure instead. */
316 		if (
317 		    Putsecure(req_file, rp->secure) == -1
318 		 || putrequest(req_file, rp->request) == -1
319 		)
320 		    status = MNOMEM;
321 
322 		else
323 		{
324 		    status = MOK;
325 
326 		    insertr(rp);
327 		    NewRequest = 0;
328 
329 		    if (rp->slow)
330 			schedule (EV_SLOWF, rp);
331 		    else
332 			schedule (EV_INTERF, rp->printer);
333 
334 		    del_flt_act(md, FLT_FILES);
335 		}
336 	    }
337 	}
338     }
339 
340 Return:
341     NewRequest = 0;
342     Free(req_file);
343     Free(idno);
344     if (status != MOK && rp) {
345 	rmfiles(rp, 0);
346 	freerstatus(rp);
347     }
348     mputm(md, R_PRINT_REQUEST, status, NB(req_id), chkprinter_result);
349     return;
350 }
351 
352 /**
353  ** s_start_change_request()
354  **/
355 
356 void s_start_change_request (char *m, MESG *md)
357 {
358     char		*req_id;
359     char		*req_file	= "";
360     short		status;
361     RSTATUS		*rp;
362     char		*path;
363 
364     (void) getmessage(m, S_START_CHANGE_REQUEST, &req_id);
365     syslog(LOG_DEBUG, "s_start_change_request(%s)",
366 	   (req_id ? req_id : "NULL"));
367 
368 
369     if (!(rp = request_by_id(req_id)))
370 	status = MUNKNOWN;
371     else if ((md->admin == 0) && (is_system_labeled()) &&
372 	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
373 	    (!STREQU(md->slabel, rp->secure->slabel)))
374 	status = MUNKNOWN;
375     else if (rp->request->outcome & RS_DONE)
376 	status = M2LATE;
377     else if (!md->admin && md->uid != rp->secure->uid)
378 	status = MNOPERM;
379     else if (rp->request->outcome & RS_CHANGING)
380 	status = MNOOPEN;
381     else if (rp->request->outcome & RS_NOTIFYING)
382 	status = MBUSY;
383     else {
384 	status = MOK;
385 
386 	if (
387 	    rp->request->outcome & RS_FILTERING
388 	 && !(rp->request->outcome & RS_STOPPED)
389 	)
390 	{
391 	    rp->request->outcome |= (RS_REFILTER|RS_STOPPED);
392 	    terminate (rp->exec);
393 	}
394 
395 	if (
396 	    rp->request->outcome & RS_PRINTING
397 	 && !(rp->request->outcome & RS_STOPPED)
398 	)
399 	{
400 	    rp->request->outcome |= RS_STOPPED;
401 	    terminate (rp->printer->exec);
402 	}
403 
404 	rp->request->outcome |= RS_CHANGING;
405 
406 	/*
407 	 * Change the ownership of the request file to be "md->uid".
408 	 * Either this is identical to "rp->secure->uid", or it is
409 	 * "Lp_Uid" or it is root. The idea is that the
410 	 * person at the other end needs access, and that may not
411 	 * be who queued the request.
412 	 */
413 	path = makepath(Lp_Tmp, rp->req_file, (char *)0);
414 	(void) Chown(path, md->uid, rp->secure->gid);
415 	Free (path);
416 
417 	add_flt_act(md, FLT_CHANGE, rp);
418 	req_file = rp->req_file;
419 
420     }
421     mputm(md, R_START_CHANGE_REQUEST, status, req_file);
422     return;
423 }
424 
425 /**
426  ** s_end_change_request()
427  **/
428 
429 void s_end_change_request(char *m, MESG *md)
430 {
431     char		*req_id;
432     RSTATUS		*rp;
433     off_t		size;
434     off_t		osize;
435     short		err;
436     short		status;
437     REQUEST		*r		= 0;
438     REQUEST		oldr;
439     int			call_schedule	= 0;
440     int			move_ok		= 0;
441     char		*path;
442 
443     (void) getmessage(m, S_END_CHANGE_REQUEST, &req_id);
444     syslog(LOG_DEBUG, "s_end_change_request(%s)", (req_id ? req_id : "NULL"));
445 
446     if (!(rp = request_by_id(req_id)))
447 	status = MUNKNOWN;
448     else if ((md->admin == 0) && (is_system_labeled()) &&
449 	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
450 	    (!STREQU(md->slabel, rp->secure->slabel)))
451 	status = MUNKNOWN;
452     else if (!(rp->request->outcome & RS_CHANGING))
453 	status = MNOSTART;
454     else {
455 	path = makepath(Lp_Tmp, rp->req_file, (char *)0);
456 	(void) chownmod(path, Lp_Uid, Lp_Gid, 0600);
457 	Free (path);
458 
459 	rp->request->outcome &= ~(RS_CHANGING);
460 	del_flt_act(md, FLT_CHANGE);
461 	/*
462 	 * The RS_CHANGING bit may have been the only thing preventing
463 	 * this request from filtering or printing, so regardless of what
464 	 * happens below, we must check to see if the request can proceed.
465 	 */
466 	call_schedule = 1;
467 
468 	if (!(r = Getrequest(rp->req_file)))
469 	    status = MNOOPEN;
470 	else {
471 	    oldr = *(rp->request);
472 	    *(rp->request) = *r;
473 
474 	    move_ok = STREQU(oldr.destination, r->destination);
475 
476 	    /*
477 	     * Preserve the current request status!
478 	     */
479 	    rp->request->outcome = oldr.outcome;
480 
481 	    /*
482 	     * Here's an example of the dangers one meets when public
483 	     * flags are used for private purposes. ".actions" (indeed,
484 	     * anything in the REQUEST structure) is set by the person
485 	     * changing the job. However, lpsched uses ".actions" as
486 	     * place to indicate that a job came from a remote system
487 	     * and we must send back job completion--this is a strictly
488 	     * private flag that we must preserve.
489 	     */
490 	    rp->request->actions |= (oldr.actions & ACT_NOTIFY);
491 
492 	    if ((rp->request->actions & ACT_SPECIAL) == ACT_HOLD) {
493 		rp->request->outcome |= RS_HELD;
494 		/*
495 		 * To be here means either the user owns the request
496 		 * or he or she is the administrator. Since we don't
497 		 * want to set the RS_ADMINHELD flag if the user is
498 		 * the administrator, the following compare will work.
499 		 */
500 		if (md->uid != rp->secure->uid)
501 		    rp->request->outcome |= RS_ADMINHELD;
502 	    }
503 
504 	    if ((rp->request->actions & ACT_SPECIAL) == ACT_RESUME) {
505 		if ((rp->request->outcome & RS_ADMINHELD) && !md->admin) {
506 		    status = MNOPERM;
507 		    goto Return;
508 		}
509 		rp->request->outcome &= ~(RS_ADMINHELD|RS_HELD);
510 	    }
511 
512 	    if((rp->request->actions & ACT_SPECIAL) == ACT_IMMEDIATE) {
513 		if (!md->admin)
514 		{
515 		    status = MNOPERM;
516 		    goto Return;
517 		}
518 		rp->request->outcome |= RS_IMMEDIATE;
519 	    }
520 
521 	    size = chfiles(rp->request->file_list, Lp_Uid, Lp_Gid);
522 	    if (size < 0) {
523 		status = MUNKNOWN;
524 		goto Return;
525 	    }
526 	    if (!(rp->request->outcome & RS_HELD) && size == 0) {
527 		status = MNOPERM;
528 		goto Return;
529 	    }
530 
531 	    osize = rp->secure->size;
532 	    rp->secure->size = size;
533 
534 	    if (move_ok == 0) {
535 		char *dest = strdup(r->destination);
536 		if ((status = mv_file(rp, dest)) == MOK)
537 			rp->secure->size = osize;
538 		free(dest);
539 	    } else if ((err = validate_request(rp, (char **)0, move_ok))\
540 	    != MOK) {
541 		status = err;
542 		rp->secure->size = osize;
543 	    } else {
544 		status = MOK;
545 
546 		if ((rp->request->outcome & RS_IMMEDIATE) ||
547 		    (rp->request->priority != oldr.priority)) {
548 		    remover(rp);
549 		    insertr(rp);
550 		}
551 
552 		freerequest(&oldr);
553 		(void) putrequest(rp->req_file, rp->request);
554 		/* fix for bugid 1103890. use Putsecure instead.       */
555 		(void) Putsecure(rp->req_file, rp->secure);
556 	    }
557 	}
558     }
559 
560 Return:
561     if (status != MOK && rp) {
562 	if (r) {
563 	    freerequest(r);
564 	    *(rp->request) = oldr;
565 	}
566 	if (status != MNOSTART)
567 	    (void) putrequest(rp->req_file, rp->request);
568     }
569 
570     if (call_schedule)
571 	maybe_schedule(rp);
572 
573     mputm(md, R_END_CHANGE_REQUEST, status, chkprinter_result);
574     return;
575 }
576 
577 /**
578  ** _cancel()
579  **	user may be (host!user)
580  **/
581 
582 static char *
583 _cancel(MESG *md, char *dest, char *user, char *req_id)
584 {
585     static RSTATUS	*rp;
586     static char		*s_dest;
587     static char		*s_user;
588     static char		*s_req_id;
589     static int		current;
590     RSTATUS		*crp;
591     char		*creq_id;
592 
593     syslog(LOG_DEBUG, "_cancel(%s, %s, %s)", (dest ? dest : "NULL"),
594 	   (user ? user : "NULL"), (req_id ? req_id : "NULL"));
595 
596     if (dest || user || req_id) {
597 	s_dest = dest;
598         if (STREQU(user, "!"))
599 		s_user = strdup("all!all");
600 	else
601 		s_user = user;
602 	s_req_id = req_id;
603 	rp = Request_List;
604 	current = 0;
605 	if (STREQU(s_req_id, CURRENT_REQ)) {
606 	    current = 1;
607 	    s_req_id = NULL;
608 	}
609     }
610 
611     while (rp != NULL) {
612 	crp = rp;
613 	rp = rp->next;
614 
615 	if (*s_dest && !STREQU(s_dest, crp->request->destination))
616 	    continue;
617 
618 	if (current && !(crp->request->outcome & RS_PRINTING))
619 	    continue;
620 
621 	if (s_req_id && *s_req_id && !STREQU(s_req_id, crp->secure->req_id))
622 	    continue;
623 
624 	if (*s_user && !bangequ(s_user, crp->secure->user))
625 	    continue;
626 
627 	if (!md->admin && md->uid != crp->secure->uid) {
628 	    errno = MNOPERM;
629 	    return(Strdup(crp->secure->req_id));
630 	}
631 
632 	/*
633 	 * For Trusted Extensions, we need to check the sensitivity label of the
634 	 * connection and job before we try to cancel it.
635 	 */
636 	if ((md->admin == 0) && (is_system_labeled()) &&
637 	    (md->slabel != NULL) && (crp->secure->slabel != NULL) &&
638 	    (!STREQU(md->slabel, crp->secure->slabel)))
639 	    continue;
640 
641 	crp->reason = MOK;
642 	creq_id = Strdup(crp->secure->req_id);
643 
644 	syslog(LOG_DEBUG, "cancel reqid (%s) uid: %d, secureuid: %d\n",
645 		creq_id, md->uid, crp->secure->uid);
646 
647 	if (cancel(crp, (md->uid != crp->secure->uid)))
648 	    errno = MOK;
649 	else
650 	    errno = M2LATE;
651 	return(creq_id);
652     }
653 
654     errno = MUNKNOWN;
655     return(NULL);
656 }
657 
658 /**
659  ** s_cancel_request()
660  **/
661 
662 void s_cancel_request(char *m, MESG *md)
663 {
664 	char	*req_id, *rid;
665 	short	status;
666 
667 	(void) getmessage(m, S_CANCEL_REQUEST, &req_id);
668 	syslog(LOG_DEBUG, "s_cancel_request(%s)", (req_id ? req_id : "NULL"));
669 
670 	if ((rid = _cancel(md, "", "", req_id)) != NULL)
671 		Free(rid);
672 	status = (short)errno;
673 
674 	mputm(md, R_CANCEL_REQUEST, status);
675 }
676 
677 /**
678  ** s_cancel()
679  **/
680 
681 void s_cancel(char *m, MESG *md)
682 {
683     char	*req_id;
684     char	*user;
685     char	*destination;
686     char	*rid;
687     char	*nrid;
688     int		nerrno;
689     int		oerrno;
690 
691     (void) getmessage(m, S_CANCEL, &destination, &user, &req_id);
692     syslog(LOG_DEBUG, "s_cancel(%s, %s, %s)",
693 	   (destination ? destination : "NULL"), (user ? user : "NULL"),
694 	   (req_id ? req_id : "NULL"));
695 
696     if (STREQU(destination, NAME_ALL))
697 	destination = "";
698     if (STREQU(req_id, NAME_ALL))
699 	req_id = "";
700 
701     if (rid = _cancel(md, destination, user, req_id)) {
702 	oerrno = errno;
703 
704 	while ((nrid = _cancel(md, NULL, NULL, NULL)) != NULL) {
705 	    nerrno = errno;
706 	    mputm(md, R_CANCEL, MOKMORE, oerrno, rid);
707 	    Free(rid);
708 	    rid = nrid;
709 	    oerrno = nerrno;
710 	}
711 	mputm(md, R_CANCEL, MOK, oerrno, rid);
712 	Free(rid);
713 	return;
714     }
715 
716     mputm(md, R_CANCEL, MOK, MUNKNOWN, "");
717 }
718 
719 /**
720  ** s_inquire_request()
721  **/
722 
723 void s_inquire_request(char *m, MESG *md)
724 {
725     char	*form;
726     char	*dest;
727     char	*pwheel;
728     char	*user;
729     char	*req_id;
730     RSTATUS	*rp;
731     RSTATUS	*found;
732     char files[BUFSIZ];
733 
734     found = (RSTATUS *)0;
735 
736     (void) getmessage(m, S_INQUIRE_REQUEST,&form,&dest,&req_id,&user,&pwheel);
737     syslog(LOG_DEBUG, "s_inquire_request(%s, %s, %s, %s, %s)",
738 	   (form ? form : "NULL"), (dest ? dest : "NULL"),
739 	   (req_id ? req_id : "NULL"), (user ? user : "NULL"),
740 	   (pwheel ? pwheel : "NULL"));
741 
742     for(rp = Request_List; rp != NULL; rp = rp->next) {
743 	if (*form && !SAME(form, rp->request->form))
744 	    continue;
745 
746 	if (*dest && !STREQU(dest, rp->request->destination)) {
747 	    if (!rp->printer)
748 		continue;
749 	    if (!STREQU(dest, rp->printer->printer->name))
750 		continue;
751 	}
752 	if (*req_id && !STREQU(req_id, rp->secure->req_id))
753 	    continue;
754 
755 	if (*user && !bangequ(user, rp->secure->user))
756 	    continue;
757 
758 	if (*pwheel && !SAME(pwheel, rp->pwheel_name))
759 	    continue;
760 
761 	/*
762 	 * For Trusted Extensions, we need to check the sensitivity label of the
763 	 * connection and job before we return it to the client.
764 	 */
765 	if ((md->admin <= 0) && (is_system_labeled()) &&
766 	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
767 	    (!STREQU(md->slabel, rp->secure->slabel)))
768 	    continue;
769 
770 	if (found) {
771 	    GetRequestFiles(found->request, files, sizeof(files));
772 	    mputm(md, R_INQUIRE_REQUEST,
773 		 MOKMORE,
774 		 found->secure->req_id,
775 		 found->request->user, /* bgolden 091996, bug 1257405 */
776 		 found->secure->slabel,
777 		 found->secure->size,
778 		 found->secure->date,
779 		 found->request->outcome,
780 		 found->printer->printer->name,
781 		 (found->form? found->form->form->name : ""),
782 		 NB(found->pwheel_name),
783 		 files
784 	    );
785 	}
786 	found = rp;
787     }
788 
789     if (found) {
790 	GetRequestFiles(found->request, files, sizeof(files));
791 	mputm(md, R_INQUIRE_REQUEST,
792 	     MOK,
793 	     found->secure->req_id,
794 	     found->request->user, /* bgolden 091996, bug 1257405 */
795 	     found->secure->slabel,
796 	     found->secure->size,
797 	     found->secure->date,
798 	     found->request->outcome,
799 	     found->printer->printer->name,
800 	     (found->form? found->form->form->name : ""),
801 	     (NB(found->pwheel_name)),
802 	     files
803 	);
804     } else
805 	mputm(md, R_INQUIRE_REQUEST, MNOINFO, "", "", "", 0L, 0L, 0, "", "", "",
806 	      "");
807 
808     return;
809 }
810 
811 
812 /*
813  * s_inquire_request_rank()
814  */
815 
816 void s_inquire_request_rank(char *m, MESG *md)
817 {
818 	char		*form;
819 	char		*dest;
820 	char		*pwheel;
821 	char		*user;
822 	char		*req_id;
823 	RSTATUS		*rp;
824 	RSTATUS		*found = NULL;
825 	PSTATUS		*pps;
826 	int		found_rank = 0;
827 	short		prop;
828 	char		files[BUFSIZ];
829 
830 	(void) getmessage(m, S_INQUIRE_REQUEST_RANK, &prop, &form, &dest,
831 		&req_id, &user, &pwheel);
832 	syslog(LOG_DEBUG, "s_inquire_request_rank(%d, %s, %s, %s, %s, %s)",
833 	   prop, (form ? form : "NULL"), (dest ? dest : "NULL"),
834 	   (req_id ? req_id : "NULL"), (user ? user : "NULL"),
835 	   (pwheel ? pwheel : "NULL"));
836 
837 	for (pps = walk_ptable(1); pps; pps = walk_ptable(0))
838 		pps->nrequests = 0;
839 
840 	for (rp = Request_List; rp != NULL; rp = rp->next) {
841 		if (rp->printer && !(rp->request->outcome & RS_DONE))
842 			rp->printer->nrequests++;
843 
844 		if (*form && !SAME(form, rp->request->form))
845 			continue;
846 
847 		if (*dest && !STREQU(dest, rp->request->destination)) {
848 			if (!rp->printer)
849 				continue;
850 			if (!STREQU(dest, rp->printer->printer->name))
851 				continue;
852 		}
853 
854 		if (*req_id && !STREQU(req_id, rp->secure->req_id))
855 			continue;
856 
857 		if (*user && !bangequ(user, rp->secure->user))
858 			continue;
859 
860 		if (*pwheel && !SAME(pwheel, rp->pwheel_name))
861 			continue;
862 		/*
863 		 * For Trusted Extensions, we need to check the sensitivity
864 		 * label of the connection and job before we return it to the
865 		 * client.
866 		 */
867 		if ((md->admin <= 0) && (is_system_labeled()) &&
868 		    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
869 		    (!STREQU(md->slabel, rp->secure->slabel)))
870 			continue;
871 
872 		if (found) {
873 			GetRequestFiles(found->request, files, sizeof(files));
874 			mputm(md, R_INQUIRE_REQUEST_RANK,
875 				MOKMORE,
876 				found->secure->req_id,
877 				found->request->user,
878 					/* bgolden 091996, bug 1257405 */
879 				found->secure->slabel,
880 				found->secure->size,
881 				found->secure->date,
882 				found->request->outcome,
883 				found->printer->printer->name,
884 				(found->form? found->form->form->name : ""),
885 				NB(found->pwheel_name),
886 				((found->status & RSS_RANK) ?
887 				    found->rank : found_rank),
888 				files
889 			);
890 		}
891 		found = rp;
892 		found_rank = found->printer->nrequests;
893 	}
894 
895 	if (found) {
896 		GetRequestFiles(found->request, files, sizeof(files));
897 		mputm(md, R_INQUIRE_REQUEST_RANK,
898 			MOK,
899 			found->secure->req_id,
900 			found->request->user, /* bgolden 091996, bug 1257405 */
901 			found->secure->slabel,
902 			found->secure->size,
903 			found->secure->date,
904 			found->request->outcome,
905 			found->printer->printer->name,
906 			(found->form? found->form->form->name : ""),
907 			NB(found->pwheel_name),
908 			((found->status & RSS_RANK) ? found->rank : found_rank),
909 			files
910 		);
911 	} else
912 		mputm(md, R_INQUIRE_REQUEST_RANK, MNOINFO, "", "", "", 0L, 0L,
913 			0, "", "", "", 0, "");
914 }
915 
916 static int
917 mv_file(RSTATUS *rp, char *dest)
918 {
919 	int	stat;
920 	char	*olddest;
921 	EXEC	*oldexec;
922 	SECURE * securep;
923 	RSTATUS * prs;
924 	char * reqno;
925 
926 	oldexec = rp->printer->exec;
927 	olddest = rp->request->destination;
928 	rp->request->destination = Strdup(dest);
929 	if ((stat = validate_request(rp, (char **)0, 1)) == MOK) {
930 		Free(olddest);
931 
932 		if (rp->request->outcome & RS_FILTERED) {
933 			int cnt = 0;
934 			char *reqno;
935 			char **listp;
936 			char tmp_nam[MAXPATHLEN];
937 
938 			reqno = getreqno(rp->secure->req_id);
939 			for (listp = rp->request->file_list; *listp; listp++) {
940 				cnt++;
941 				snprintf(tmp_nam, sizeof (tmp_nam),
942 					"%s/%s/F%s-%d", Lp_Tmp,
943 					rp->secure->system, reqno, cnt);
944 				unlink(tmp_nam);
945 
946 			}
947 			rp->request->outcome &= ~RS_FILTERED;
948 		}
949 
950 		/* update /var/spool/lp/tmp/<host>/nnn-0 */
951 		if (putrequest(rp->req_file, rp->request) < 0) {
952 			note("putrequest failed\n");
953 			return (MNOMEM);
954 		}
955 
956 		/* update /var/spool/lp/requests/<host>/nnn-0 */
957 		if ((securep = Getsecure(rp->req_file))) {
958 			reqno = strdup(getreqno(securep->req_id));
959 			(void) free(securep->req_id);
960 			if ((securep->req_id = calloc(strlen(dest) + 1 +
961 				strlen(reqno) +1, sizeof (char))) == NULL)
962 				return (MNOMEM);
963 			(void) sprintf(securep->req_id, "%s-%s", dest, reqno);
964 			/* remove the old request file; save new one */
965 			(void) rmsecure(rp->secure->req_id);
966 			if (Putsecure(rp->req_file, securep) < 0) {
967 				/* Putsecure includes note/errmessage */
968 				return (MNOMEM);
969 			}
970 		} else {
971 			note("Getsecure failed\n");
972 			return (MNOMEM);
973 		}
974 
975 		/* update internal jobs list: Request_list */
976 		if (prs = request_by_id(rp->secure->req_id)) {
977 			free(prs->secure->req_id);
978 			prs->secure->req_id = strdup(securep->req_id);
979 
980 			/*
981 			 * We calloc'd securep->reqid earlier, now we free it
982 			 * here because we no longer call 'freesecure' from
983 			 * Putsecure() if we use a static structure
984 			 */
985 
986 			free(securep->req_id);
987 		} else {
988 			note("request_by_id failed\n");
989 			return (MUNKNOWN);
990 		}
991 
992 		/*
993 		 * If the request was being filtered or was printing,
994 		 * it would have been stopped in "validate_request()",
995 		 * but only if it has to be refiltered. Thus, the
996 		 * filtering has been stopped if it has to be stopped,
997 		 * but the printing may still be going.
998 		 */
999 		if (rp->request->outcome & RS_PRINTING &&
1000 		    !(rp->request->outcome & RS_STOPPED)) {
1001 			rp->request->outcome |= RS_STOPPED;
1002 			terminate (oldexec);
1003 	        }
1004 
1005 		maybe_schedule(rp);
1006 		return (MOK);
1007 	}
1008 
1009 	Free(rp->request->destination);
1010 	rp->request->destination = olddest;
1011 	return (stat);
1012 }
1013 
1014 /*
1015  * s_move_request()
1016  */
1017 
1018 void s_move_request(char *m, MESG *md)
1019 {
1020 	RSTATUS	*rp;
1021 	short	err;
1022 	char	*req_id;
1023 	char	*dest;
1024 
1025 	(void) getmessage(m, S_MOVE_REQUEST, &req_id, &dest);
1026 	syslog(LOG_DEBUG, "s_move_request(%s, %s)", (req_id ? req_id : "NULL"),
1027 	       (dest ? dest : "NULL"));
1028 
1029 
1030 	if (!(search_ptable(dest)) && !(search_ctable(dest))) {
1031 		mputm(md, R_MOVE_REQUEST, MNODEST, 0L);
1032 		return;
1033 	}
1034 
1035 	if ((rp = request_by_id(req_id))) {
1036 		if (STREQU(rp->request->destination, dest)) {
1037 			mputm(md, R_MOVE_REQUEST, MOK, 0L);
1038 			return;
1039 		}
1040 		if (rp->request->outcome & (RS_DONE|RS_NOTIFYING)) {
1041 			mputm(md, R_MOVE_REQUEST, M2LATE, 0L);
1042 			return;
1043 		}
1044 		if (rp->request->outcome & RS_CHANGING)	{
1045 			mputm(md, R_MOVE_REQUEST, MBUSY, 0L);
1046 			return;
1047 		}
1048 		if ((err = mv_file(rp, dest)) == MOK) {
1049 			mputm(md, R_MOVE_REQUEST, MOK, 0L);
1050 			return;
1051 		}
1052 		mputm(md, R_MOVE_REQUEST, err, chkprinter_result);
1053 		return;
1054 	}
1055 	mputm(md, R_MOVE_REQUEST, MUNKNOWN, 0L);
1056 }
1057 
1058 /**
1059  ** s_move_dest()
1060  **/
1061 
1062 void s_move_dest(char *m, MESG *md)
1063 {
1064     char		*dest;
1065     char		*fromdest;
1066     RSTATUS		*rp;
1067     char		*found = (char *)0;
1068     short		num_ok = 0;
1069 
1070     (void) getmessage(m, S_MOVE_DEST, &fromdest, &dest);
1071     syslog(LOG_DEBUG, "s_move_dest(%s, %s)", (fromdest ? fromdest : "NULL"),
1072 	   (dest ? dest : "NULL"));
1073 
1074     if (!search_ptable(fromdest) && !search_ctable(fromdest))
1075     {
1076 	mputm(md, R_MOVE_DEST, MNODEST, fromdest, 0);
1077 	return;
1078     }
1079 
1080     if (!(search_ptable(dest)) && !(search_ctable(dest)))
1081     {
1082 	mputm(md, R_MOVE_DEST, MNODEST, dest, 0);
1083 	return;
1084     }
1085 
1086     if (STREQU(dest, fromdest))
1087     {
1088 	mputm(md, R_MOVE_DEST, MOK, "", 0);
1089 	return;
1090     }
1091 
1092     BEGIN_WALK_BY_DEST_LOOP (rp, fromdest)
1093 	if (!(rp->request->outcome &
1094 	    (RS_DONE|RS_CHANGING|RS_NOTIFYING))) {
1095 	    if (mv_file(rp, dest) == MOK) {
1096 		num_ok++;
1097 		continue;
1098 	    }
1099 	}
1100 
1101 	if (found)
1102 	    mputm(md, R_MOVE_DEST, MMORERR, found, 0);
1103 
1104 	found = rp->secure->req_id;
1105     END_WALK_LOOP
1106 
1107     if (found)
1108 	mputm(md, R_MOVE_DEST, MERRDEST, found, num_ok);
1109     else
1110 	mputm(md, R_MOVE_DEST, MOK, "", num_ok);
1111 }
1112 
1113 /**
1114  ** reqpath
1115  **/
1116 
1117 static char *
1118 reqpath(char *file, char **idnumber)
1119 {
1120     char	*path;
1121     char	*cp;
1122     char	*cp2;
1123 
1124     /*
1125     **	/var/spool/lp/tmp/machine/123-0
1126     **	/var/spool/lp/temp/123-0
1127     **	/usr/spool/lp/temp/123-0
1128     **	/usr/spool/lp/tmp/machine/123-0
1129     **	123-0
1130     **	machine/123-0
1131     **
1132     **	/var/spool/lp/tmp/machine/123-0 + 123
1133     */
1134     if (*file == '/')
1135     {
1136 	/*CONSTCOND*/
1137 	if (STRNEQU(file, Lp_Spooldir, strlen(Lp_Spooldir)))
1138 	    cp = file + strlen(Lp_Spooldir) + 1;
1139 	else
1140 	    if(STRNEQU(file, "/usr/spool/lp", 13))
1141 		cp = file + strlen("/usr/spool/lp") + 1;
1142 	    else
1143 	    {
1144 		*idnumber = NULL;
1145 		return(NULL);
1146 	    }
1147 
1148 	if (STRNEQU(cp, "temp", 4))
1149 	{
1150 	    cp += 5;
1151 	    path = makepath(Local_System, cp, NULL);
1152 	}
1153 	else
1154 	    path = Strdup(cp);
1155     }
1156     else
1157     {
1158 	if (strchr(file, '/'))
1159 	    path = makepath(file, NULL);
1160 	else
1161 	    path = makepath(Local_System, file, NULL);
1162     }
1163 
1164     cp = strrchr(path, '/');
1165     cp++;
1166     if ((cp2 = strrchr(cp, '-')) == NULL)
1167 	*idnumber = Strdup(cp);
1168     else
1169     {
1170 	*cp2 = '\0';
1171 	*idnumber = Strdup(cp);
1172 	*cp2 = '-';
1173     }
1174 
1175     return(path);
1176 }
1177 
1178 /*
1179  * The client is sending a peer connection to retreive label information
1180  * from.  This is used in the event that the client is an intermediary for
1181  * the actual requestor in a Trusted environment.
1182  */
1183 void s_pass_peer_connection(char *m, MESG *md)
1184 {
1185 	short	status = MTRANSMITERR;
1186 	char	*dest;
1187 	struct strrecvfd recv_fd;
1188 
1189 	(void) getmessage(m, S_PASS_PEER_CONNECTION);
1190 	syslog(LOG_DEBUG, "s_pass_peer_connection()");
1191 
1192 	memset(&recv_fd, NULL, sizeof (recv_fd));
1193 	if (ioctl(md->readfd, I_RECVFD, &recv_fd) == 0) {
1194 		int fd = recv_fd.fd;
1195 
1196 		if (get_peer_label(fd, &md->slabel) == 0) {
1197 			if (md->admin == 1)
1198 				md->admin = -1; /* turn off query privilege */
1199 			status = MOK;
1200 		}
1201 
1202 		close(fd);
1203 	}
1204 
1205 	mputm(md, R_PASS_PEER_CONNECTION, status);
1206 }
1207