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