displayq.c revision 1.1.1.3 1 /*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 static char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95";
36 #endif /* not lint */
37
38 #include <sys/param.h>
39 #include <sys/stat.h>
40 #include <sys/file.h>
41
42 #include <signal.h>
43 #include <fcntl.h>
44 #include <dirent.h>
45 #include <unistd.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <ctype.h>
50 #include "lp.h"
51 #include "lp.local.h"
52 #include "pathnames.h"
53
54 /*
55 * Routines to display the state of the queue.
56 */
57 #define JOBCOL 40 /* column for job # in -l format */
58 #define OWNCOL 7 /* start of Owner column in normal */
59 #define SIZCOL 62 /* start of Size column in normal */
60
61 /*
62 * Stuff for handling job specifications
63 */
64 extern int requ[]; /* job number of spool entries */
65 extern int requests; /* # of spool requests */
66 extern char *user[]; /* users to process */
67 extern int users; /* # of users in user array */
68
69 static int col; /* column on screen */
70 static char current[40]; /* current file being printed */
71 static char file[132]; /* print file name */
72 static int first; /* first file in ``files'' column? */
73 static int garbage; /* # of garbage cf files */
74 static int lflag; /* long output option */
75 static int rank; /* order to be printed (-1=none, 0=active) */
76 static long totsize; /* total print job size in bytes */
77
78 static char *head0 = "Rank Owner Job Files";
79 static char *head1 = "Total Size\n";
80
81 /*
82 * Display the current state of the queue. Format = 1 if long format.
83 */
84 void
85 displayq(format)
86 int format;
87 {
88 register struct queue *q;
89 register int i, nitems, fd;
90 register char *cp;
91 struct queue **queue;
92 struct stat statb;
93 FILE *fp;
94
95 lflag = format;
96 totsize = 0;
97 rank = -1;
98 if ((i = cgetent(&bp, printcapdb, printer)) == -2)
99 fatal("can't open printer description file");
100 else if (i == -1)
101 fatal("unknown printer");
102 else if (i == -3)
103 fatal("potential reference loop detected in printcap file");
104 if (cgetstr(bp, "lp", &LP) < 0)
105 LP = _PATH_DEFDEVLP;
106 if (cgetstr(bp, "rp", &RP) < 0)
107 RP = DEFLP;
108 if (cgetstr(bp, "sd", &SD) < 0)
109 SD = _PATH_DEFSPOOL;
110 if (cgetstr(bp,"lo", &LO) < 0)
111 LO = DEFLOCK;
112 if (cgetstr(bp, "st", &ST) < 0)
113 ST = DEFSTAT;
114 cgetstr(bp, "rm", &RM);
115 if (cp = checkremote())
116 printf("Warning: %s\n", cp);
117
118 /*
119 * Print out local queue
120 * Find all the control files in the spooling directory
121 */
122 if (chdir(SD) < 0)
123 fatal("cannot chdir to spooling directory");
124 if ((nitems = getq(&queue)) < 0)
125 fatal("cannot examine spooling area\n");
126 if (stat(LO, &statb) >= 0) {
127 if (statb.st_mode & 0100) {
128 if (remote)
129 printf("%s: ", host);
130 printf("Warning: %s is down: ", printer);
131 fd = open(ST, O_RDONLY);
132 if (fd >= 0) {
133 (void) flock(fd, LOCK_SH);
134 while ((i = read(fd, line, sizeof(line))) > 0)
135 (void) fwrite(line, 1, i, stdout);
136 (void) close(fd); /* unlocks as well */
137 } else
138 putchar('\n');
139 }
140 if (statb.st_mode & 010) {
141 if (remote)
142 printf("%s: ", host);
143 printf("Warning: %s queue is turned off\n", printer);
144 }
145 }
146
147 if (nitems) {
148 fp = fopen(LO, "r");
149 if (fp == NULL)
150 warn();
151 else {
152 /* get daemon pid */
153 cp = current;
154 while ((i = getc(fp)) != EOF && i != '\n')
155 *cp++ = i;
156 *cp = '\0';
157 i = atoi(current);
158 if (i <= 0 || kill(i, 0) < 0)
159 warn();
160 else {
161 /* read current file name */
162 cp = current;
163 while ((i = getc(fp)) != EOF && i != '\n')
164 *cp++ = i;
165 *cp = '\0';
166 /*
167 * Print the status file.
168 */
169 if (remote)
170 printf("%s: ", host);
171 fd = open(ST, O_RDONLY);
172 if (fd >= 0) {
173 (void) flock(fd, LOCK_SH);
174 while ((i = read(fd, line, sizeof(line))) > 0)
175 (void) fwrite(line, 1, i, stdout);
176 (void) close(fd); /* unlocks as well */
177 } else
178 putchar('\n');
179 }
180 (void) fclose(fp);
181 }
182 /*
183 * Now, examine the control files and print out the jobs to
184 * be done for each user.
185 */
186 if (!lflag)
187 header();
188 for (i = 0; i < nitems; i++) {
189 q = queue[i];
190 inform(q->q_name);
191 free(q);
192 }
193 free(queue);
194 }
195 if (!remote) {
196 if (nitems == 0)
197 puts("no entries");
198 return;
199 }
200
201 /*
202 * Print foreign queue
203 * Note that a file in transit may show up in either queue.
204 */
205 if (nitems)
206 putchar('\n');
207 (void) sprintf(line, "%c%s", format + '\3', RP);
208 cp = line;
209 for (i = 0; i < requests; i++) {
210 cp += strlen(cp);
211 (void) sprintf(cp, " %d", requ[i]);
212 }
213 for (i = 0; i < users; i++) {
214 cp += strlen(cp);
215 *cp++ = ' ';
216 (void) strcpy(cp, user[i]);
217 }
218 strcat(line, "\n");
219 fd = getport(RM, 0);
220 if (fd < 0) {
221 if (from != host)
222 printf("%s: ", host);
223 printf("connection to %s is down\n", RM);
224 }
225 else {
226 i = strlen(line);
227 if (write(fd, line, i) != i)
228 fatal("Lost connection");
229 while ((i = read(fd, line, sizeof(line))) > 0)
230 (void) fwrite(line, 1, i, stdout);
231 (void) close(fd);
232 }
233 }
234
235 /*
236 * Print a warning message if there is no daemon present.
237 */
238 void
239 warn()
240 {
241 if (remote)
242 printf("\n%s: ", host);
243 puts("Warning: no daemon present");
244 current[0] = '\0';
245 }
246
247 /*
248 * Print the header for the short listing format
249 */
250 void
251 header()
252 {
253 printf(head0);
254 col = strlen(head0)+1;
255 blankfill(SIZCOL);
256 printf(head1);
257 }
258
259 void
260 inform(cf)
261 char *cf;
262 {
263 register int j;
264 FILE *cfp;
265
266 /*
267 * There's a chance the control file has gone away
268 * in the meantime; if this is the case just keep going
269 */
270 if ((cfp = fopen(cf, "r")) == NULL)
271 return;
272
273 if (rank < 0)
274 rank = 0;
275 if (remote || garbage || strcmp(cf, current))
276 rank++;
277 j = 0;
278 while (getline(cfp)) {
279 switch (line[0]) {
280 case 'P': /* Was this file specified in the user's list? */
281 if (!inlist(line+1, cf)) {
282 fclose(cfp);
283 return;
284 }
285 if (lflag) {
286 printf("\n%s: ", line+1);
287 col = strlen(line+1) + 2;
288 prank(rank);
289 blankfill(JOBCOL);
290 printf(" [job %s]\n", cf+3);
291 } else {
292 col = 0;
293 prank(rank);
294 blankfill(OWNCOL);
295 printf("%-10s %-3d ", line+1, atoi(cf+3));
296 col += 16;
297 first = 1;
298 }
299 continue;
300 default: /* some format specifer and file name? */
301 if (line[0] < 'a' || line[0] > 'z')
302 continue;
303 if (j == 0 || strcmp(file, line+1) != 0)
304 (void) strcpy(file, line+1);
305 j++;
306 continue;
307 case 'N':
308 show(line+1, file, j);
309 file[0] = '\0';
310 j = 0;
311 }
312 }
313 fclose(cfp);
314 if (!lflag) {
315 blankfill(SIZCOL);
316 printf("%ld bytes\n", totsize);
317 totsize = 0;
318 }
319 }
320
321 int
322 inlist(name, file)
323 char *name, *file;
324 {
325 register int *r, n;
326 register char **u, *cp;
327
328 if (users == 0 && requests == 0)
329 return(1);
330 /*
331 * Check to see if it's in the user list
332 */
333 for (u = user; u < &user[users]; u++)
334 if (!strcmp(*u, name))
335 return(1);
336 /*
337 * Check the request list
338 */
339 for (n = 0, cp = file+3; isdigit(*cp); )
340 n = n * 10 + (*cp++ - '0');
341 for (r = requ; r < &requ[requests]; r++)
342 if (*r == n && !strcmp(cp, from))
343 return(1);
344 return(0);
345 }
346
347 void
348 show(nfile, file, copies)
349 register char *nfile, *file;
350 int copies;
351 {
352 if (strcmp(nfile, " ") == 0)
353 nfile = "(standard input)";
354 if (lflag)
355 ldump(nfile, file, copies);
356 else
357 dump(nfile, file, copies);
358 }
359
360 /*
361 * Fill the line with blanks to the specified column
362 */
363 void
364 blankfill(n)
365 register int n;
366 {
367 while (col++ < n)
368 putchar(' ');
369 }
370
371 /*
372 * Give the abbreviated dump of the file names
373 */
374 void
375 dump(nfile, file, copies)
376 char *nfile, *file;
377 int copies;
378 {
379 register short n, fill;
380 struct stat lbuf;
381
382 /*
383 * Print as many files as will fit
384 * (leaving room for the total size)
385 */
386 fill = first ? 0 : 2; /* fill space for ``, '' */
387 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) {
388 if (col < SIZCOL) {
389 printf(" ..."), col += 4;
390 blankfill(SIZCOL);
391 }
392 } else {
393 if (first)
394 first = 0;
395 else
396 printf(", ");
397 printf("%s", nfile);
398 col += n+fill;
399 }
400 if (*file && !stat(file, &lbuf))
401 totsize += copies * lbuf.st_size;
402 }
403
404 /*
405 * Print the long info about the file
406 */
407 void
408 ldump(nfile, file, copies)
409 char *nfile, *file;
410 int copies;
411 {
412 struct stat lbuf;
413
414 putchar('\t');
415 if (copies > 1)
416 printf("%-2d copies of %-19s", copies, nfile);
417 else
418 printf("%-32s", nfile);
419 if (*file && !stat(file, &lbuf))
420 printf(" %ld bytes", (long)lbuf.st_size);
421 else
422 printf(" ??? bytes");
423 putchar('\n');
424 }
425
426 /*
427 * Print the job's rank in the queue,
428 * update col for screen management
429 */
430 void
431 prank(n)
432 int n;
433 {
434 char rline[100];
435 static char *r[] = {
436 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
437 };
438
439 if (n == 0) {
440 printf("active");
441 col += 6;
442 return;
443 }
444 if ((n/10)%10 == 1)
445 (void)snprintf(rline, sizeof(rline), "%dth", n);
446 else
447 (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]);
448 col += strlen(rline);
449 printf("%s", rline);
450 }
451