This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / usr.sbin / lpr / common_source / displayq.c
CommitLineData
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
35static 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 */
52extern char *user[]; /* users to process */
53extern int users; /* # of users in user array */
54extern int requ[]; /* job number of spool entries */
55extern int requests; /* # of spool requests */
56
57int lflag; /* long output option */
58char current[40]; /* current file being printed */
59int garbage; /* # of garbage cf files */
60int rank; /* order to be printed (-1=none, 0=active) */
61long totsize; /* total print job size in bytes */
62int first; /* first file in ``files'' column? */
63int col; /* column on screen */
64char file[132]; /* print file name */
65
66char *head0 = "Rank Owner Job Files";
67char *head1 = "Total Size\n";
68
69/*
70 * Display the current state of the queue. Format = 1 if long format.
71 */
72displayq(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 */
225warn()
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 */
236header()
237{
238 printf(head0);
239 col = strlen(head0)+1;
240 blankfill(SIZCOL);
241 printf(head1);
242}
243
244inform(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
306inlist(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
331show(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 */
345blankfill(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 */
355dump(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 */
386ldump(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 */
407prank(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}