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