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