1*12113Sralph /*	displayq.c	4.1	83/04/29	*/
2*12113Sralph /*
3*12113Sralph  * Routines to display the state of the queue.
4*12113Sralph  */
5*12113Sralph 
6*12113Sralph #include "lp.h"
7*12113Sralph 
8*12113Sralph #define	JOBCOL		40	/* column for job # in -l format */
9*12113Sralph #define OWNCOL		7	/* start of Owner column in normal */
10*12113Sralph 
11*12113Sralph /*
12*12113Sralph  * Stuff for handling job specifications
13*12113Sralph  */
14*12113Sralph extern char	*user[];	/* users to process */
15*12113Sralph extern int	users;		/* # of users in user array */
16*12113Sralph extern int	requ[];		/* job number of spool entries */
17*12113Sralph extern int	requests;	/* # of spool requests */
18*12113Sralph 
19*12113Sralph int	lflag;			/* long output option */
20*12113Sralph char	current[40];		/* current file being printed */
21*12113Sralph int	garbage;		/* # of garbage cf files */
22*12113Sralph int	rank;			/* order to be printed (-1=none, 0=active) */
23*12113Sralph long	totsize;		/* total print job size in bytes */
24*12113Sralph int	first;			/* first file in ``files'' column? */
25*12113Sralph int	col;			/* column on screen */
26*12113Sralph int	SIZCOL = 62;		/* start of Size column in normal */
27*12113Sralph int	sendtorem;		/* are we sending to a remote? */
28*12113Sralph char	file[132];		/* print file name */
29*12113Sralph 
30*12113Sralph char	*head0 = "Rank   Owner      Job  Files";
31*12113Sralph char	*head1 = "Total Size\n";
32*12113Sralph 
33*12113Sralph /*
34*12113Sralph  * Display the current state of the queue. Format = 1 if long format.
35*12113Sralph  */
36*12113Sralph displayq(format)
37*12113Sralph 	int format;
38*12113Sralph {
39*12113Sralph 	register struct queue *q;
40*12113Sralph 	register int i, nitems, fd;
41*12113Sralph 	struct queue **queue;
42*12113Sralph 	struct stat statb;
43*12113Sralph 	FILE *fp;
44*12113Sralph 
45*12113Sralph 	name = "displayq";
46*12113Sralph 	lflag = format;
47*12113Sralph 	totsize = 0;
48*12113Sralph 	rank = -1;
49*12113Sralph 
50*12113Sralph 	if ((i = pgetent(line, printer)) < 0)
51*12113Sralph 		fatal("cannot open printer description file");
52*12113Sralph 	else if (i == 0)
53*12113Sralph 		fatal("unknown printer");
54*12113Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
55*12113Sralph 		LP = DEFDEVLP;
56*12113Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
57*12113Sralph 		RP = printer;
58*12113Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
59*12113Sralph 		SD = DEFSPOOL;
60*12113Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
61*12113Sralph 		LO = DEFLOCK;
62*12113Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
63*12113Sralph 		ST = DEFSTAT;
64*12113Sralph 	RM = pgetstr("rm", &bp);
65*12113Sralph 
66*12113Sralph 	/*
67*12113Sralph 	 * If there is no local printer, then print the queue on
68*12113Sralph 	 * the remote machine and then what's in the queue here.
69*12113Sralph 	 * Note that a file in transit may not show up in either queue.
70*12113Sralph 	 */
71*12113Sralph 	if (*LP == '\0') {
72*12113Sralph 		register char *cp;
73*12113Sralph 		char c;
74*12113Sralph 
75*12113Sralph 		sendtorem++;
76*12113Sralph 		(void) sprintf(line, "%c%s", format + '\3', RP);
77*12113Sralph 		cp = line;
78*12113Sralph 		for (i = 0; i < requests; i++) {
79*12113Sralph 			cp += strlen(cp);
80*12113Sralph 			(void) sprintf(cp, " %d", requ[i]);
81*12113Sralph 		}
82*12113Sralph 		for (i = 0; i < users; i++) {
83*12113Sralph 			cp += strlen(cp);
84*12113Sralph 			*cp++ = ' ';
85*12113Sralph 			strcpy(cp, user[i]);
86*12113Sralph 		}
87*12113Sralph 		strcat(line, "\n");
88*12113Sralph 		fd = getport();
89*12113Sralph 		if (fd < 0) {
90*12113Sralph 			if (from != host)
91*12113Sralph 				printf("%s: ", host);
92*12113Sralph 			printf("connection to %s is down\n", RM);
93*12113Sralph 		} else {
94*12113Sralph 			i = strlen(line);
95*12113Sralph 			if (write(fd, line, i) != i)
96*12113Sralph 				fatal("Lost connection");
97*12113Sralph 			while ((i = read(fd, line, sizeof(line))) > 0)
98*12113Sralph 				(void) fwrite(line, 1, i, stdout);
99*12113Sralph 			(void) close(fd);
100*12113Sralph 		}
101*12113Sralph 	}
102*12113Sralph 	/*
103*12113Sralph 	 * Find all the control files in the spooling directory
104*12113Sralph 	 */
105*12113Sralph 	if (chdir(SD) < 0)
106*12113Sralph 		fatal("cannot chdir to spooling directory");
107*12113Sralph 	if ((nitems = getq(&queue)) < 0)
108*12113Sralph 		fatal("cannot examine spooling area\n");
109*12113Sralph 	if (nitems == 0) {
110*12113Sralph 		if (sendtorem)
111*12113Sralph 			printf("\n%s: ", host);
112*12113Sralph 		printf("no entries\n");
113*12113Sralph 		return(0);
114*12113Sralph 	}
115*12113Sralph 	fp = fopen(LO, "r");
116*12113Sralph 	if (fp == NULL || flock(fileno(fp), FSHLOCK|FNBLOCK) == 0) {
117*12113Sralph 		if (fp != NULL)
118*12113Sralph 			fclose(fp);
119*12113Sralph 		garbage = nitems;
120*12113Sralph 		if (*LP && stat(LP, &statb) >= 0 && (statb.st_mode & 0777) == 0)
121*12113Sralph 			status("Warning: %s is down", printer);
122*12113Sralph 		else
123*12113Sralph 			status("Warning: no daemon present");
124*12113Sralph 	} else {
125*12113Sralph 		register char *cp = current;
126*12113Sralph 
127*12113Sralph 		/* skip daemon pid */
128*12113Sralph 		while ((*cp = getc(fp)) != EOF && *cp != '\n');
129*12113Sralph 		/* read current file name */
130*12113Sralph 		while ((*cp = getc(fp)) != EOF && *cp != '\n')
131*12113Sralph 			cp++;
132*12113Sralph 		*cp = '\0';
133*12113Sralph 		fclose(fp);
134*12113Sralph 	}
135*12113Sralph 	/*
136*12113Sralph 	 * Now, examine the control files and print out the jobs to
137*12113Sralph 	 * be done for each user.
138*12113Sralph 	 */
139*12113Sralph 	if (sendtorem)
140*12113Sralph 		printf("\n%s: ", host);
141*12113Sralph 	if ((fd = open(ST, FRDONLY|FSHLOCK)) >= 0) {
142*12113Sralph 		while ((i = read(fd, line, sizeof(line))) > 0)
143*12113Sralph 			(void) fwrite(line, 1, i, stdout);
144*12113Sralph 		(void) close(fd);
145*12113Sralph 	} else
146*12113Sralph 		putchar('\n');
147*12113Sralph 	if (!lflag)
148*12113Sralph 		header();
149*12113Sralph 	for (i = 0; i < nitems; i++) {
150*12113Sralph 		q = queue[i];
151*12113Sralph 		inform(q->q_name);
152*12113Sralph 		free(q);
153*12113Sralph 	}
154*12113Sralph 	free(queue);
155*12113Sralph 	return(nitems-garbage);
156*12113Sralph }
157*12113Sralph 
158*12113Sralph /*
159*12113Sralph  * Print the header for the short listing format
160*12113Sralph  */
161*12113Sralph header()
162*12113Sralph {
163*12113Sralph 	printf(head0);
164*12113Sralph 	col = strlen(head0)+1;
165*12113Sralph 	blankfill(SIZCOL);
166*12113Sralph 	printf(head1);
167*12113Sralph }
168*12113Sralph 
169*12113Sralph inform(cf)
170*12113Sralph 	char *cf;
171*12113Sralph {
172*12113Sralph 	register int j, k;
173*12113Sralph 	register char *cp;
174*12113Sralph 	FILE *cfp;
175*12113Sralph 
176*12113Sralph 	/*
177*12113Sralph 	 * There's a chance the control file has gone away
178*12113Sralph 	 * in the meantime; if this is the case just keep going
179*12113Sralph 	 */
180*12113Sralph 	if ((cfp = fopen(cf, "r")) == NULL)
181*12113Sralph 		return;
182*12113Sralph 
183*12113Sralph 	if (rank < 0)
184*12113Sralph 		rank = 0;
185*12113Sralph 	if (sendtorem || garbage || strcmp(cf, current))
186*12113Sralph 		rank++;
187*12113Sralph 	j = 0;
188*12113Sralph 	while (getline(cfp)) {
189*12113Sralph 		switch (line[0]) {
190*12113Sralph 		case 'P': /* Was this file specified in the user's list? */
191*12113Sralph 			if (!inlist(line+1, cf)) {
192*12113Sralph 				fclose(cfp);
193*12113Sralph 				return;
194*12113Sralph 			}
195*12113Sralph 			if (lflag) {
196*12113Sralph 				printf("\n%s: ", line+1);
197*12113Sralph 				col = strlen(line+1) + 2;
198*12113Sralph 				prank(rank);
199*12113Sralph 				blankfill(JOBCOL);
200*12113Sralph 				printf(" [job %s]\n", cf+3);
201*12113Sralph 			} else {
202*12113Sralph 				col = 0;
203*12113Sralph 				prank(rank);
204*12113Sralph 				blankfill(OWNCOL);
205*12113Sralph 				printf("%-10s %-3d  ", line+1, atoi(cf+3));
206*12113Sralph 				col += 16;
207*12113Sralph 				first = 1;
208*12113Sralph 			}
209*12113Sralph 			continue;
210*12113Sralph 		default: /* some format specifer and file name? */
211*12113Sralph 			if (line[0] < 'a' || line[0] > 'z')
212*12113Sralph 				continue;
213*12113Sralph 			if (j == 0 || strcmp(file, line+1) != 0)
214*12113Sralph 				strcpy(file, line+1);
215*12113Sralph 			j++;
216*12113Sralph 			continue;
217*12113Sralph 		case 'N':
218*12113Sralph 			show(line+1, file, j);
219*12113Sralph 			file[0] = '\0';
220*12113Sralph 			j = 0;
221*12113Sralph 		}
222*12113Sralph 	}
223*12113Sralph 	fclose(cfp);
224*12113Sralph 	if (!lflag) {
225*12113Sralph 		blankfill(SIZCOL);
226*12113Sralph 		printf("%D bytes\n", totsize);
227*12113Sralph 		totsize = 0;
228*12113Sralph 	}
229*12113Sralph }
230*12113Sralph 
231*12113Sralph inlist(name, file)
232*12113Sralph 	char *name, *file;
233*12113Sralph {
234*12113Sralph 	register int *r, n;
235*12113Sralph 	register char **u, *cp;
236*12113Sralph 
237*12113Sralph 	if (users == 0 && requests == 0)
238*12113Sralph 		return(1);
239*12113Sralph 	/*
240*12113Sralph 	 * Check to see if it's in the user list
241*12113Sralph 	 */
242*12113Sralph 	for (u = user; u < &user[users]; u++)
243*12113Sralph 		if (!strcmp(*u, name))
244*12113Sralph 			return(1);
245*12113Sralph 	/*
246*12113Sralph 	 * Check the request list
247*12113Sralph 	 */
248*12113Sralph 	for (n = 0, cp = file+3; isdigit(*cp); )
249*12113Sralph 		n = n * 10 + (*cp++ - '0');
250*12113Sralph 	for (r = requ; r < &requ[requests]; r++)
251*12113Sralph 		if (*r == n && !strcmp(cp, from))
252*12113Sralph 			return(1);
253*12113Sralph 	return(0);
254*12113Sralph }
255*12113Sralph 
256*12113Sralph show(nfile, file, copies)
257*12113Sralph 	register char *nfile, *file;
258*12113Sralph {
259*12113Sralph 	if (strcmp(nfile, " ") == 0)
260*12113Sralph 		nfile = "(standard input)";
261*12113Sralph 	if (lflag)
262*12113Sralph 		ldump(nfile, file, copies);
263*12113Sralph 	else
264*12113Sralph 		dump(nfile, file, copies);
265*12113Sralph }
266*12113Sralph 
267*12113Sralph /*
268*12113Sralph  * Fill the line with blanks to the specified column
269*12113Sralph  */
270*12113Sralph blankfill(n)
271*12113Sralph 	register int n;
272*12113Sralph {
273*12113Sralph 	while (col++ < n)
274*12113Sralph 		putchar(' ');
275*12113Sralph }
276*12113Sralph 
277*12113Sralph /*
278*12113Sralph  * Give the abbreviated dump of the file names
279*12113Sralph  */
280*12113Sralph dump(nfile, file, copies)
281*12113Sralph 	char *nfile, *file;
282*12113Sralph {
283*12113Sralph 	register short n, fill;
284*12113Sralph 	struct stat lbuf;
285*12113Sralph 
286*12113Sralph 	/*
287*12113Sralph 	 * Print as many files as will fit
288*12113Sralph 	 *  (leaving room for the total size)
289*12113Sralph 	 */
290*12113Sralph 	 fill = first ? 0 : 2;	/* fill space for ``, '' */
291*12113Sralph 	 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) {
292*12113Sralph 		if (col < SIZCOL) {
293*12113Sralph 			printf(" ..."), col += 4;
294*12113Sralph 			blankfill(SIZCOL);
295*12113Sralph 		}
296*12113Sralph 	} else {
297*12113Sralph 		if (first)
298*12113Sralph 			first = 0;
299*12113Sralph 		else
300*12113Sralph 			printf(", ");
301*12113Sralph 		printf("%s", nfile);
302*12113Sralph 		col += n+fill;
303*12113Sralph 	}
304*12113Sralph 	if (*file && !stat(file, &lbuf))
305*12113Sralph 		totsize += copies * lbuf.st_size;
306*12113Sralph }
307*12113Sralph 
308*12113Sralph /*
309*12113Sralph  * Print the long info about the file
310*12113Sralph  */
311*12113Sralph ldump(nfile, file, copies)
312*12113Sralph 	char *nfile, *file;
313*12113Sralph {
314*12113Sralph 	struct stat lbuf;
315*12113Sralph 
316*12113Sralph 	putchar('\t');
317*12113Sralph 	if (copies > 1)
318*12113Sralph 		printf("%-2d copies of %-19s", copies, nfile);
319*12113Sralph 	else
320*12113Sralph 		printf("%-32s", nfile);
321*12113Sralph 	if (*file && !stat(file, &lbuf))
322*12113Sralph 		printf(" %D bytes", lbuf.st_size);
323*12113Sralph 	else
324*12113Sralph 		printf(" ??? bytes");
325*12113Sralph 	putchar('\n');
326*12113Sralph }
327*12113Sralph 
328*12113Sralph /*
329*12113Sralph  * Print the job's rank in the queue,
330*12113Sralph  *   update col for screen management
331*12113Sralph  */
332*12113Sralph prank(n)
333*12113Sralph {
334*12113Sralph 	char line[100];
335*12113Sralph 	static char *r[] = {
336*12113Sralph 		"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
337*12113Sralph 	};
338*12113Sralph 
339*12113Sralph 	if (n == 0) {
340*12113Sralph 		printf("active");
341*12113Sralph 		col += 6;
342*12113Sralph 		return;
343*12113Sralph 	}
344*12113Sralph 	if ((n/10) == 1)
345*12113Sralph 		(void) sprintf(line, "%dth", n);
346*12113Sralph 	else
347*12113Sralph 		(void) sprintf(line, "%d%s", n, r[n%10]);
348*12113Sralph 	col += strlen(line);
349*12113Sralph 	printf("%s", line);
350*12113Sralph }
351