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