displayq.c revision 31020
1156230Smux/*
2156230Smux * Copyright (c) 1983, 1993
3156230Smux *	The Regents of the University of California.  All rights reserved.
4156230Smux *
5156230Smux * Redistribution and use in source and binary forms, with or without
6156230Smux * modification, are permitted provided that the following conditions
7156230Smux * are met:
8156230Smux * 1. Redistributions of source code must retain the above copyright
9156230Smux *    notice, this list of conditions and the following disclaimer.
10156230Smux * 2. Redistributions in binary form must reproduce the above copyright
11156230Smux *    notice, this list of conditions and the following disclaimer in the
12156230Smux *    documentation and/or other materials provided with the distribution.
13156230Smux * 3. All advertising materials mentioning features or use of this software
14156230Smux *    must display the following acknowledgement:
15156230Smux *	This product includes software developed by the University of
16156230Smux *	California, Berkeley and its contributors.
17156230Smux * 4. Neither the name of the University nor the names of its contributors
18156230Smux *    may be used to endorse or promote products derived from this software
19156230Smux *    without specific prior written permission.
20156230Smux *
21156230Smux * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22156230Smux * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23156230Smux * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24156230Smux * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25156230Smux * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26156230Smux * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27156230Smux * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28156230Smux * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29156230Smux * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30156230Smux * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31156230Smux * SUCH DAMAGE.
32156230Smux */
33186781Slulf
34156230Smux#ifndef lint
35156230Smuxstatic char sccsid[] = "@(#)displayq.c	8.4 (Berkeley) 4/28/95";
36156230Smux#endif /* not lint */
37156230Smux
38156230Smux#include <sys/param.h>
39156230Smux#include <sys/stat.h>
40156230Smux#include <sys/file.h>
41156230Smux
42156230Smux#include <signal.h>
43156230Smux#include <fcntl.h>
44156230Smux#include <dirent.h>
45156230Smux#include <unistd.h>
46156230Smux#include <stdio.h>
47156230Smux#include <stdlib.h>
48156230Smux#include <string.h>
49156230Smux#include <ctype.h>
50156230Smux#include "lp.h"
51186781Slulf#include "lp.local.h"
52156230Smux#include "pathnames.h"
53156230Smux
54156230Smux/*
55156230Smux * Routines to display the state of the queue.
56156230Smux */
57156230Smux#define JOBCOL	40		/* column for job # in -l format */
58156230Smux#define OWNCOL	7		/* start of Owner column in normal */
59156701Smux#define SIZCOL	62		/* start of Size column in normal */
60156230Smux
61186781Slulf/*
62186781Slulf * Stuff for handling job specifications
63156230Smux */
64156230Smuxextern uid_t	uid, euid;
65156230Smux
66156230Smuxstatic int	col;		/* column on screen */
67156701Smuxstatic char	current[40];	/* current file being printed */
68186781Slulfstatic char	file[132];	/* print file name */
69156230Smuxstatic int	first;		/* first file in ``files'' column? */
70156230Smuxstatic int	garbage;	/* # of garbage cf files */
71156230Smuxstatic int	lflag;		/* long output option */
72156230Smuxstatic int	rank;		/* order to be printed (-1=none, 0=active) */
73156230Smuxstatic long	totsize;	/* total print job size in bytes */
74156230Smux
75156230Smuxstatic char	*head0 = "Rank   Owner      Job  Files";
76156230Smuxstatic char	*head1 = "Total Size\n";
77186781Slulf
78156230Smuxstatic void	alarmhandler __P((int));
79156230Smuxstatic void	warn __P((void));
80156230Smux
81156230Smux/*
82156230Smux * Display the current state of the queue. Format = 1 if long format.
83156230Smux */
84156230Smuxvoid
85156701Smuxdisplayq(format)
86156230Smux	int format;
87156230Smux{
88156230Smux	register struct queue *q;
89186781Slulf	register int i, nitems, fd, ret;
90156230Smux	register char	*cp;
91156230Smux	struct queue **queue;
92156230Smux	struct stat statb;
93156230Smux	FILE *fp;
94156230Smux	void (*savealrm)(int);
95156230Smux
96156701Smux	lflag = format;
97156701Smux	totsize = 0;
98156230Smux	rank = -1;
99186781Slulf	if ((i = cgetent(&bp, printcapdb, printer)) == -2)
100186781Slulf		fatal("can't open printer description file");
101186781Slulf	else if (i == -1)
102156230Smux		fatal("unknown printer");
103156230Smux	else if (i == -3)
104186781Slulf		fatal("potential reference loop detected in printcap file");
105186781Slulf	if (cgetstr(bp, "lp", &LP) < 0)
106156701Smux		LP = _PATH_DEFDEVLP;
107156230Smux	if (cgetstr(bp, "rp", &RP) < 0)
108186781Slulf		RP = DEFLP;
109186781Slulf	if (cgetstr(bp, "sd", &SD) < 0)
110156230Smux		SD = _PATH_DEFSPOOL;
111156230Smux	if (cgetstr(bp,"lo", &LO) < 0)
112156230Smux		LO = DEFLOCK;
113156230Smux	if (cgetstr(bp, "st", &ST) < 0)
114186781Slulf		ST = DEFSTAT;
115186781Slulf	if (cgetnum(bp, "ct", &CT) < 0)
116186781Slulf		CT = DEFTIMEOUT;
117186781Slulf	if (cgetstr(bp, "rm", &RM) < 0)
118186781Slulf		RM = NULL;
119186781Slulf	if ((cp = checkremote()))
120156230Smux		printf("Warning: %s\n", cp);
121156230Smux
122156230Smux	/*
123156230Smux	 * Print out local queue
124156230Smux	 * Find all the control files in the spooling directory
125156230Smux	 */
126156230Smux	seteuid(euid);
127156230Smux	if (chdir(SD) < 0)
128156230Smux		fatal("cannot chdir to spooling directory");
129156230Smux	seteuid(uid);
130156230Smux	if ((nitems = getq(&queue)) < 0)
131156230Smux		fatal("cannot examine spooling area\n");
132156230Smux	seteuid(euid);
133156230Smux	ret = stat(LO, &statb);
134186781Slulf	seteuid(uid);
135156230Smux	if (ret >= 0) {
136156230Smux		if (statb.st_mode & 0100) {
137156230Smux			if (remote)
138156230Smux				printf("%s: ", host);
139186781Slulf			printf("Warning: %s is down: ", printer);
140186781Slulf			seteuid(euid);
141186781Slulf			fd = open(ST, O_RDONLY);
142186781Slulf			seteuid(uid);
143186781Slulf			if (fd >= 0) {
144186781Slulf				(void) flock(fd, LOCK_SH);
145186781Slulf				while ((i = read(fd, line, sizeof(line))) > 0)
146186781Slulf					(void) fwrite(line, 1, i, stdout);
147186781Slulf				(void) close(fd);	/* unlocks as well */
148186781Slulf			} else
149186781Slulf				putchar('\n');
150186781Slulf		}
151186781Slulf		if (statb.st_mode & 010) {
152186781Slulf			if (remote)
153186781Slulf				printf("%s: ", host);
154186781Slulf			printf("Warning: %s queue is turned off\n", printer);
155156230Smux		}
156156230Smux	}
157156230Smux
158156230Smux	if (nitems) {
159156230Smux		seteuid(euid);
160156230Smux		fp = fopen(LO, "r");
161156230Smux		seteuid(uid);
162156230Smux		if (fp == NULL)
163156230Smux			warn();
164156230Smux		else {
165156230Smux			/* get daemon pid */
166156230Smux			cp = current;
167156230Smux			while ((i = getc(fp)) != EOF && i != '\n')
168156230Smux				*cp++ = i;
169156230Smux			*cp = '\0';
170156230Smux			i = atoi(current);
171156230Smux			if (i <= 0) {
172156230Smux				ret = -1;
173156701Smux			} else {
174156701Smux				seteuid(euid);
175156701Smux				ret = kill(i, 0);
176156701Smux				seteuid(uid);
177186781Slulf			}
178186781Slulf			if (ret < 0) {
179186781Slulf				warn();
180186781Slulf			} else {
181156230Smux				/* read current file name */
182156230Smux				cp = current;
183156230Smux				while ((i = getc(fp)) != EOF && i != '\n')
184156230Smux					*cp++ = i;
185156230Smux				*cp = '\0';
186156230Smux				/*
187156230Smux				 * Print the status file.
188156230Smux				 */
189156230Smux				if (remote)
190156230Smux					printf("%s: ", host);
191156230Smux				seteuid(euid);
192156230Smux				fd = open(ST, O_RDONLY);
193156230Smux				seteuid(uid);
194156230Smux				if (fd >= 0) {
195156230Smux					(void) flock(fd, LOCK_SH);
196156230Smux					while ((i = read(fd, line, sizeof(line))) > 0)
197156230Smux						(void) fwrite(line, 1, i, stdout);
198156230Smux					(void) close(fd);	/* unlocks as well */
199156230Smux				} else
200156230Smux					putchar('\n');
201156230Smux			}
202156230Smux			(void) fclose(fp);
203156230Smux		}
204156230Smux		/*
205156230Smux		 * Now, examine the control files and print out the jobs to
206156230Smux		 * be done for each user.
207156230Smux		 */
208156230Smux		if (!lflag)
209156230Smux			header();
210156230Smux		for (i = 0; i < nitems; i++) {
211156230Smux			q = queue[i];
212156230Smux			inform(q->q_name);
213156230Smux			free(q);
214156230Smux		}
215156230Smux		free(queue);
216156230Smux	}
217156230Smux	if (!remote) {
218156230Smux		if (nitems == 0)
219156230Smux			puts("no entries");
220156230Smux		return;
221156230Smux	}
222156230Smux
223156230Smux	/*
224156230Smux	 * Print foreign queue
225156230Smux	 * Note that a file in transit may show up in either queue.
226156230Smux	 */
227156230Smux	if (nitems)
228156230Smux		putchar('\n');
229156230Smux	(void) snprintf(line, sizeof(line), "%c%s", format + '\3', RP);
230156230Smux	cp = line;
231156230Smux	for (i = 0; i < requests && cp-line+10 < sizeof(line) - 1; i++) {
232156230Smux		cp += strlen(cp);
233156230Smux		(void) sprintf(cp, " %d", requ[i]);
234156230Smux	}
235156701Smux	for (i = 0; i < users && cp - line + 1 + strlen(user[i]) <
236156230Smux		sizeof(line) - 1; i++) {
237156230Smux		cp += strlen(cp);
238156230Smux		*cp++ = ' ';
239156230Smux		(void) strcpy(cp, user[i]);
240156230Smux	}
241225979Sadrian	strcat(line, "\n");
242156230Smux	savealrm = signal(SIGALRM, alarmhandler);
243156230Smux	alarm(CT);
244156230Smux	fd = getport(RM, 0);
245156230Smux	alarm(0);
246156230Smux	(void)signal(SIGALRM, savealrm);
247156230Smux	if (fd < 0) {
248156230Smux		if (from != host)
249156230Smux			printf("%s: ", host);
250156230Smux		printf("connection to %s is down\n", RM);
251156230Smux	}
252156230Smux	else {
253156230Smux		i = strlen(line);
254156230Smux		if (write(fd, line, i) != i)
255156230Smux			fatal("Lost connection");
256156230Smux		while ((i = read(fd, line, sizeof(line))) > 0)
257156230Smux			(void) fwrite(line, 1, i, stdout);
258156230Smux		(void) close(fd);
259156230Smux	}
260156230Smux}
261156230Smux
262156230Smux/*
263156230Smux * Print a warning message if there is no daemon present.
264156230Smux */
265156230Smuxstatic void
266156701Smuxwarn()
267156701Smux{
268156701Smux	if (remote)
269156701Smux		printf("%s: ", host);
270156701Smux	puts("Warning: no daemon present");
271156230Smux	current[0] = '\0';
272156230Smux}
273156230Smux
274156230Smux/*
275156230Smux * Print the header for the short listing format
276156230Smux */
277156230Smuxvoid
278156230Smuxheader()
279156230Smux{
280156230Smux	printf(head0);
281156230Smux	col = strlen(head0)+1;
282156230Smux	blankfill(SIZCOL);
283156230Smux	printf(head1);
284156230Smux}
285156230Smux
286156230Smuxvoid
287156230Smuxinform(cf)
288156230Smux	char *cf;
289156230Smux{
290156230Smux	register int j;
291156230Smux	FILE *cfp;
292156230Smux
293156230Smux	/*
294156230Smux	 * There's a chance the control file has gone away
295156230Smux	 * in the meantime; if this is the case just keep going
296156230Smux	 */
297156230Smux	seteuid(euid);
298156230Smux	if ((cfp = fopen(cf, "r")) == NULL)
299156230Smux		return;
300156230Smux	seteuid(uid);
301156230Smux
302156230Smux	if (rank < 0)
303156230Smux		rank = 0;
304156230Smux	if (remote || garbage || strcmp(cf, current))
305156230Smux		rank++;
306156230Smux	j = 0;
307156230Smux	while (getline(cfp)) {
308156230Smux		switch (line[0]) {
309156230Smux		case 'P': /* Was this file specified in the user's list? */
310156230Smux			if (!inlist(line+1, cf)) {
311156230Smux				fclose(cfp);
312156230Smux				return;
313156230Smux			}
314156230Smux			if (lflag) {
315156230Smux				printf("\n%s: ", line+1);
316156230Smux				col = strlen(line+1) + 2;
317156230Smux				prank(rank);
318156701Smux				blankfill(JOBCOL);
319156230Smux				printf(" [job %s]\n", cf+3);
320156230Smux			} else {
321156230Smux				col = 0;
322156230Smux				prank(rank);
323156230Smux				blankfill(OWNCOL);
324156230Smux				printf("%-10s %-3d  ", line+1, atoi(cf+3));
325156230Smux				col += 16;
326156230Smux				first = 1;
327156230Smux			}
328156230Smux			continue;
329156230Smux		default: /* some format specifer and file name? */
330156230Smux			if (line[0] < 'a' || line[0] > 'z')
331156230Smux				continue;
332156230Smux			if (j == 0 || strcmp(file, line+1) != 0) {
333156230Smux				(void) strncpy(file, line+1, sizeof(file) - 1);
334156230Smux				file[sizeof(file) - 1] = '\0';
335156230Smux			}
336156230Smux			j++;
337156230Smux			continue;
338156230Smux		case 'N':
339156230Smux			show(line+1, file, j);
340156230Smux			file[0] = '\0';
341156230Smux			j = 0;
342156230Smux		}
343156230Smux	}
344156230Smux	fclose(cfp);
345156230Smux	if (!lflag) {
346156230Smux		blankfill(SIZCOL);
347156230Smux		printf("%ld bytes\n", totsize);
348156230Smux		totsize = 0;
349156230Smux	}
350186781Slulf}
351156230Smux
352156230Smuxint
353186781Slulfinlist(name, file)
354156230Smux	char *name, *file;
355186781Slulf{
356186781Slulf	register int *r, n;
357156230Smux	register char **u, *cp;
358156230Smux
359156230Smux	if (users == 0 && requests == 0)
360156230Smux		return(1);
361156230Smux	/*
362156230Smux	 * Check to see if it's in the user list
363156230Smux	 */
364156230Smux	for (u = user; u < &user[users]; u++)
365156230Smux		if (!strcmp(*u, name))
366156230Smux			return(1);
367156230Smux	/*
368156230Smux	 * Check the request list
369156230Smux	 */
370156230Smux	for (n = 0, cp = file+3; isdigit(*cp); )
371156230Smux		n = n * 10 + (*cp++ - '0');
372156230Smux	for (r = requ; r < &requ[requests]; r++)
373156230Smux		if (*r == n && !strcmp(cp, from))
374156230Smux			return(1);
375156230Smux	return(0);
376156230Smux}
377156230Smux
378156230Smuxvoid
379156230Smuxshow(nfile, file, copies)
380156230Smux	register char *nfile, *file;
381156230Smux	int copies;
382156230Smux{
383156230Smux	if (strcmp(nfile, " ") == 0)
384156230Smux		nfile = "(standard input)";
385156230Smux	if (lflag)
386156230Smux		ldump(nfile, file, copies);
387156230Smux	else
388156230Smux		dump(nfile, file, copies);
389156230Smux}
390186781Slulf
391156230Smux/*
392156230Smux * Fill the line with blanks to the specified column
393156230Smux */
394156230Smuxvoid
395156230Smuxblankfill(n)
396156230Smux	register int n;
397156230Smux{
398156230Smux	while (col++ < n)
399156230Smux		putchar(' ');
400156230Smux}
401156230Smux
402156230Smux/*
403156230Smux * Give the abbreviated dump of the file names
404156230Smux */
405156230Smuxvoid
406156230Smuxdump(nfile, file, copies)
407156230Smux	char *nfile, *file;
408186781Slulf	int copies;
409156230Smux{
410156230Smux	register short n, fill;
411156230Smux	struct stat lbuf;
412156230Smux
413156230Smux	/*
414156701Smux	 * Print as many files as will fit
415156701Smux	 *  (leaving room for the total size)
416156701Smux	 */
417156701Smux	 fill = first ? 0 : 2;	/* fill space for ``, '' */
418156701Smux	 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) {
419156230Smux		if (col < SIZCOL) {
420156230Smux			printf(" ..."), col += 4;
421156230Smux			blankfill(SIZCOL);
422156230Smux		}
423156230Smux	} else {
424156230Smux		if (first)
425156230Smux			first = 0;
426156230Smux		else
427156230Smux			printf(", ");
428156230Smux		printf("%s", nfile);
429156230Smux		col += n+fill;
430156230Smux	}
431156230Smux	seteuid(euid);
432156230Smux	if (*file && !stat(file, &lbuf))
433156230Smux		totsize += copies * lbuf.st_size;
434156230Smux	seteuid(uid);
435156230Smux}
436156230Smux
437156230Smux/*
438156230Smux * Print the long info about the file
439156230Smux */
440156230Smuxvoid
441156230Smuxldump(nfile, file, copies)
442156230Smux	char *nfile, *file;
443156230Smux	int copies;
444156230Smux{
445156230Smux	struct stat lbuf;
446156230Smux
447156230Smux	putchar('\t');
448156230Smux	if (copies > 1)
449156230Smux		printf("%-2d copies of %-19s", copies, nfile);
450156230Smux	else
451156230Smux		printf("%-32s", nfile);
452156230Smux	if (*file && !stat(file, &lbuf))
453156230Smux		printf(" %qd bytes", lbuf.st_size);
454156230Smux	else
455156230Smux		printf(" ??? bytes");
456156230Smux	putchar('\n');
457156230Smux}
458156230Smux
459156230Smux/*
460156230Smux * Print the job's rank in the queue,
461156230Smux *   update col for screen management
462186781Slulf */
463156230Smuxvoid
464156230Smuxprank(n)
465156230Smux	int n;
466156230Smux{
467156701Smux	char rline[100];
468156230Smux	static char *r[] = {
469156230Smux		"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
470156230Smux	};
471156230Smux
472156230Smux	if (n == 0) {
473156230Smux		printf("active");
474156230Smux		col += 6;
475156230Smux		return;
476156230Smux	}
477156230Smux	if ((n/10)%10 == 1)
478156230Smux		(void)snprintf(rline, sizeof(rline), "%dth", n);
479156230Smux	else
480156230Smux		(void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]);
481186781Slulf	col += strlen(rline);
482156230Smux	printf("%s", rline);
483156230Smux}
484156701Smux
485156701Smuxvoid
486156701Smuxalarmhandler(signo)
487156230Smux	int signo;
488156230Smux{
489156230Smux	/* ignored */
490156230Smux}
491156230Smux