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