source: trunk/athena/bin/lpr/displayq.c @ 10496

Revision 10496, 11.7 KB checked in by ghudson, 27 years ago (diff)
From mhpower via mwhitson: prevent buffer overflows.
Line 
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.  The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8static char sccsid[] = "@(#)displayq.c  5.1 (Berkeley) 6/6/85";
9#endif not lint
10
11/*
12 * Routines to display the state of the queue.
13 */
14
15#include "lp.h"
16#if defined(POSIX) && !defined(ultrix)
17#include "posix.h"   /* for flock() */
18#endif
19#define JOBCOL  40              /* column for job # in -l format */
20#define OWNCOL  7               /* start of Owner column in normal */
21#define SIZCOL  62              /* start of Size column in normal */
22
23/*
24 * Stuff for handling job specifications
25 */
26extern char     *user[];        /* users to process */
27extern int      users;          /* # of users in user array */
28extern int      requ[];         /* job number of spool entries */
29extern int      requests;       /* # of spool requests */
30
31int     lflag;          /* long output option */
32char    current[40];    /* current file being printed */
33int     garbage;        /* # of garbage cf files */
34int     rank;           /* order to be printed (-1=none, 0=active) */
35long    totsize;        /* total print job size in bytes */
36int     first;          /* first file in ``files'' column? */
37int     col;            /* column on screen */
38int     sendtorem;      /* are we sending to a remote? */
39char    file[132];      /* print file name */
40
41char    *head0 = "Rank   Owner      Job  Files";
42char    *head1 = "Total Size\n";
43char    restart_succeed[] =
44        "%s daemon %d does not exist; restarting a new one....";
45char    restart_fail[] =
46        "%s daemon %d does not exist; could not start a new daemon!";
47
48/*
49 * Display the current state of the queue. Format = 1 if long format.
50 */
51displayq(format)
52        int format;
53{
54        register struct queue_ *q;
55        register int i, nitems, fd;
56        struct queue_ **queue;
57        struct stat statb;
58        int rem_fils;
59        char *tmpptr;
60        FILE *fp;
61#ifdef KERBEROS
62        short KA;
63#endif
64#if defined(PQUOTA) && defined(KERBEROS)
65        int pagecost;
66#endif
67        lflag = format;
68        totsize = 0;
69        rank = -1;
70        rem_fils = 0;
71
72#ifdef HESIOD
73        if ((i = pgetent(line, printer)) <= 0) {
74                if (pralias(alibuf, printer))
75                        printer = alibuf;
76                if ((i = hpgetent(line, printer)) < 1)
77                        fatal("unknown printer");
78        }
79#else
80        if ((i = pgetent(line, printer)) < 0) {
81                fatal("cannot open printer description file");
82        } else if (i == 0)
83                fatal("unknown printer");
84#endif HESIOD
85        if ((LP = pgetstr("lp", &bp)) == NULL)
86                LP = DEFDEVLP;
87        if ((RP = pgetstr("rp", &bp)) == NULL)
88                RP = DEFLP;
89        if ((SD = pgetstr("sd", &bp)) == NULL)
90                SD = DEFSPOOL;
91        if ((LO = pgetstr("lo", &bp)) == NULL)
92                LO = DEFLOCK;
93        if ((ST = pgetstr("st", &bp)) == NULL)
94                ST = DEFSTAT;
95        RM = pgetstr("rm", &bp);
96#ifdef KERBEROS
97        KA = pgetnum("ka");
98#endif
99#ifdef PQUOTA
100        RQ = pgetstr("rq", &bp);
101#endif PQUOTA
102#if defined(PQUOTA) && defined(KERBEROS)
103        pagecost = pgetnum("pc");
104#endif
105        /*
106         * Figure out whether the local machine is the same as the remote
107         * machine entry (if it exists).  If not, then ignore the local
108         * queue information.
109         */
110
111         if (RM != (char *) NULL) {
112
113                char name[MAXHOSTNAMELEN + 1];
114                struct hostent *hp;
115
116                        /* get the name of the local host */
117                gethostname (name, sizeof(name) - 1);
118                name[sizeof(name)-1] = '\0';
119                        /* get the network standard name of the local host */
120                hp = gethostbyname (name);
121                if (hp == (struct hostent *) NULL) {
122                    printf ("unable to get hostname for local machine %s\n",
123                                name);
124                }
125                else {
126                  strncpy (name, hp->h_name, sizeof(name));
127                  name[sizeof(name) - 1] = '\0';
128                  /* get the network standard name of RM */
129                  hp = gethostbyname (RM);
130                  if (hp == (struct hostent *) NULL) {
131                    printf ("unable to get hostname for remote machine %s\n",
132                            RM);
133                  }
134                  /* if printer is not on local machine, ignore LP */
135                  else if (strcasecmp (name, hp->h_name) != 0)
136                      LP = "";
137                }
138        }
139
140        /*
141         * If there is no local printer, then print the queue on
142         * the remote machine and then what's in the queue here.
143         * Note that a file in transit may not show up in either queue.
144         */
145        if (*LP == '\0') {
146                register char *cp;
147
148                sendtorem++;
149                (void) sprintf(line, "%c%s", format + '\3', RP);
150                cp = line;
151                for (i = 0; i < requests; i++) {
152                        cp += strlen(cp);
153                        (void) sprintf(cp, " %d", requ[i]);
154                }
155                for (i = 0; i < users; i++) {
156                        cp += strlen(cp);
157                        *cp++ = ' ';
158                        strcpy(cp, user[i]);
159                }
160                strcat(line, "\n");
161                fd = getport(RM);
162                if (fd < 0) {
163                        if (from != host)
164                                printf("%s: ", host);
165                        printf("unable to connect to %s (for %s)\n", RM, RP);
166                } else {
167                        printf("%s...  ", RM); fflush(stdout);
168                        i = strlen(line);
169                        if (write(fd, line, i) != i)
170                                fatal("Lost connection");
171                        rem_fils = -1;
172                        while ((i = read(fd, line, sizeof(line))) > 0) {
173                                (void) fwrite(line, 1, i, stdout);
174                                for (tmpptr = line;
175                                     tmpptr = strchr(tmpptr,'\n'); ) {
176                                        rem_fils++;
177                                        tmpptr++;
178                                }
179                        }
180                        (void) close(fd);
181                }
182        }
183        /*
184         * Allow lpq -l info about printing
185         */
186        else if (lflag) {
187#ifdef KERBEROS
188            if(KA > 0) {
189                printf("\nKerberos authenticated");
190#ifndef PQUOTA
191                putchar('\n');
192#endif PQUOTA   
193            }   
194#endif KERBEROS
195
196#ifdef PQUOTA
197            if((RQ != (char *) NULL)) {
198                printf("\nQuota server: %s\n", RQ);
199            }
200#ifdef KERBEROS
201            else putchar('\n');
202#endif KERBEROS
203#if defined(PQUOTA) && defined(KERBEROS)
204            if (pagecost > 0) printf("Page cost: %d cents\n", pagecost);
205#endif
206#endif
207        }
208        /*
209         * Find all the control files in the spooling directory
210         */
211        if (chdir(SD) < 0) {
212                char msgbuf[(2 * BUFSIZ) + 255];
213
214                if (RM) return(rem_fils);
215                sprintf(msgbuf,
216                        "Cannot chdir to spooling directory %s for %s",
217                        SD, printer);
218                fatal(msgbuf);
219                }
220        if ((nitems = getq_(&queue)) < 0) {
221                char msgbuf[(2 * BUFSIZ) + 255];
222                sprintf(
223                        msgbuf,
224                        "Cannot examine spooling area %s for %s",
225                        SD, printer);
226                fatal (msgbuf);
227                }
228        if (stat(LO, &statb) >= 0) {
229                if ((statb.st_mode & 0110) && sendtorem)
230                        printf("\n");
231                if (statb.st_mode & 0100) {
232                        if (sendtorem)
233                                printf("%s: ", host);
234                        printf("Warning: %s is down: ", printer);
235                        fd = open(ST, O_RDWR);
236                        if (fd >= 0) {
237                                char tmp[1024];
238                                (void) flock(fd, LOCK_SH);
239                                while ((i = read(fd, line, sizeof(line))) > 0){
240                                     strncpy(tmp, printer, sizeof(tmp));
241                                     tmp[sizeof(tmp) - 1] = '\0';
242                                     if (strncmp(line, strcat(tmp," is ready and printing"), 24) != 0)
243                                        (void) fwrite(line, 1, i, stdout);
244                                     else
245                                        putchar('\n');
246                                 }
247                                (void) close(fd);       /* unlocks as well */
248                        } else
249                                putchar('\n');
250                }
251                if (statb.st_mode & 010) {
252                        if (sendtorem)
253                                printf("%s: ", host);
254                        printf("Warning: %s queue is turned off\n", printer);
255                }
256        }
257        if (nitems == 0) {
258                if (!sendtorem)
259                        printf("no entries in %s\n", printer);
260                return(rem_fils);
261        }
262        fp = fopen(LO, "r");
263        if (fp == NULL) {
264                char msgbuf[(2 * BUFSIZ) + 255];
265                sprintf(msgbuf, "Unable to lock file %s/%s for %s",
266                        SD, LO, printer);
267                warn(msgbuf);
268                }
269        else {
270                register char *cp;
271                int icp;
272
273                /* get daemon pid */
274                cp = current;
275                icp = 0;
276                while ((*cp = getc(fp)) != EOF && *cp != '\n') {
277                        if (icp == sizeof(current) - 1) break;
278                        cp++;
279                        icp++;
280                }
281                *cp = '\0';
282                i = atoi(current);
283                if (i <= 0 || kill(i, 0) < 0) {
284                        char    msg[256];
285
286                        if (startdaemon(printer))
287                                sprintf(msg, restart_succeed, printer, i);
288                        else
289                                sprintf(msg, restart_fail, printer, i);
290                        warn(msg);
291                }
292                else {
293                        /* read current file name */
294                        cp = current;
295                        icp = 0;
296                        while ((*cp = getc(fp)) != EOF && *cp != '\n') {
297                                if (icp == sizeof(current) - 1) break;
298                                cp++;
299                                icp++;
300                        }
301                        *cp = '\0';
302                        /*
303                         * Print the status file.
304                         */
305                        if (sendtorem)
306                                printf("\n%s: ", host);
307                        fd = open(ST, O_RDWR);
308                        if (fd >= 0) {
309                                (void) flock(fd, LOCK_SH);
310                                while ((i = read(fd, line, sizeof(line))) > 0)
311                                        (void) fwrite(line, 1, i, stdout);
312                                (void) close(fd);       /* unlocks as well */
313                        } else
314                                putchar('\n');
315                }
316                (void) fclose(fp);
317        }
318        /*
319         * Now, examine the control files and print out the jobs to
320         * be done for each user.
321         */
322        if (!lflag)
323                header();
324
325        for (i = 0; i < nitems; i++) {
326                q = queue[i];
327                inform(q->q_name);
328                free(q);
329        }
330        free(queue);
331        return(nitems-garbage+rem_fils);
332}
333
334/*
335 * Print a warning message if there is no daemon present.
336 */
337warn(msgbuf)
338     char *msgbuf;
339{
340        if (sendtorem)
341                printf("\n%s: ", host);
342        printf("Warning: no daemon present\n[%s]\n", msgbuf);
343        current[0] = '\0';
344}
345
346/*
347 * Print the header for the short listing format
348 */
349header()
350{
351        printf(head0);
352        col = strlen(head0)+1;
353        blankfill(SIZCOL);
354        printf(head1);
355}
356
357inform(cf)
358        char *cf;
359{
360        register int j;
361        FILE *cfp;
362        char jobnum[4];
363
364        /*
365         * There's a chance the control file has gone away
366         * in the meantime; if this is the case just keep going
367         */
368        if ((cfp = fopen(cf, "r")) == NULL)
369                return;
370
371        if (rank < 0)
372                rank = 0;
373        if (sendtorem || garbage || strcmp(cf, current))
374                rank++;
375        j = 0;
376        strncpy(jobnum,cf+3,3);
377        jobnum[3] = '\0';
378        while (getline(cfp)) {
379                switch (line[0]) {
380                case 'P': /* Was this file specified in the user's list? */
381                        if (!inlist(line+1, cf)) {
382                                fclose(cfp);
383                                return;
384                        }
385                        if (lflag) {
386                                printf("\n%s: ", line+1);
387                                col = strlen(line+1) + 2;
388                                prank(rank);
389                                blankfill(JOBCOL);
390                                printf(" [job %s@%s]\n", jobnum, cf+6);
391                        } else {
392                                col = 0;
393                                prank(rank);
394                                blankfill(OWNCOL);
395                                printf("%-10s %-3d  ", line+1, atoi(jobnum));
396                                col += 16;
397                                first = 1;
398                        }
399                        continue;
400                default: /* some format specifer and file name? */
401                        if (line[0] < 'a' || line[0] > 'z')
402                                continue;
403                        if (j == 0 || strcmp(file, line+1) != 0) {
404                                strncpy(file, line+1, sizeof(file));
405                                file[sizeof(file) - 1] = '\0';
406                        }
407                        j++;
408                        continue;
409                case 'N':
410                        show(line+1, file, j);
411                        file[0] = '\0';
412                        j = 0;
413                }
414        }
415        fclose(cfp);
416        if (!lflag) {
417                blankfill(SIZCOL);
418                printf("%ld bytes\n", totsize);
419                totsize = 0;
420        }
421}
422
423inlist(name, file)
424        char *name, *file;
425{
426        register int *r, n;
427        register char **u, *cp;
428
429        if (users == 0 && requests == 0)
430                return(1);
431        /*
432         * Check to see if it's in the user list
433         */
434        for (u = user; u < &user[users]; u++)
435                if (!strcmp(*u, name))
436                        return(1);
437        /*
438         * Check the request list
439         */
440        for (n = 0, cp = file+3; isdigit(*cp); )
441                n = n * 10 + (*cp++ - '0');
442        for (r = requ; r < &requ[requests]; r++)
443                if (*r == n && !strcmp(cp, from))
444                        return(1);
445        return(0);
446}
447
448show(nfile, file, copies)
449        register char *nfile, *file;
450{
451        if (strcmp(nfile, " ") == 0)
452                nfile = "(standard input)";
453        if (lflag)
454                ldump(nfile, file, copies);
455        else
456                dump(nfile, file, copies);
457}
458
459/*
460 * Fill the line with blanks to the specified column
461 */
462blankfill(n)
463        register int n;
464{
465        while (col++ < n)
466                putchar(' ');
467}
468
469/*
470 * Give the abbreviated dump of the file names
471 */
472dump(nfile, file, copies)
473        char *nfile, *file;
474{
475        register short n, fill;
476        struct stat lbuf;
477
478        /*
479         * Print as many files as will fit
480         *  (leaving room for the total size)
481         */
482         fill = first ? 0 : 2;  /* fill space for ``, '' */
483         if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) {
484                if (col < SIZCOL) {
485                        printf(" ..."), col += 4;
486                        blankfill(SIZCOL);
487                }
488        } else {
489                if (first)
490                        first = 0;
491                else
492                        printf(", ");
493                printf("%s", nfile);
494                col += n+fill;
495        }
496        if (*file && !stat(file, &lbuf))
497                totsize += copies * lbuf.st_size;
498}
499
500/*
501 * Print the long info about the file
502 */
503ldump(nfile, file, copies)
504        char *nfile, *file;
505{
506        struct stat lbuf;
507
508        putchar('\t');
509        if (copies > 1)
510                printf("%d copies of %-19s%s", copies, nfile,
511                       copies<10?" ":"");
512        else
513                printf("%-32s", nfile);
514        if (*file && !stat(file, &lbuf))
515                printf(" %ld bytes", lbuf.st_size);
516        else
517                printf(" ??? bytes");
518        putchar('\n');
519}
520
521/*
522 * Print the job's rank in the queue,
523 *   update col for screen management
524 */
525prank(n)
526{
527        char line[100];
528        static char *r[] = {
529                "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
530        };
531
532        if (n == 0) {
533                printf("active");
534                col += 6;
535                return;
536        }
537        if ((n/10) == 1)
538                (void) sprintf(line, "%dth", n);
539        else
540                (void) sprintf(line, "%d%s", n, r[n%10]);
541        col += strlen(line);
542        printf("%s", line);
543}
Note: See TracBrowser for help on using the repository browser.