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