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