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