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