122427Sdist /*
261840Sbostic * Copyright (c) 1983, 1993
361840Sbostic * The Regents of the University of California. All rights reserved.
434203Sbostic *
556243Selan * %sccs.include.redist.c%
622427Sdist */
722427Sdist
813952Ssam #ifndef lint
9*69060Stef static char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 04/28/95";
1034203Sbostic #endif /* not lint */
1113952Ssam
1255470Sbostic #include <sys/param.h>
1355470Sbostic #include <sys/stat.h>
14*69060Stef #include <sys/file.h>
1512113Sralph
1655470Sbostic #include <signal.h>
1755470Sbostic #include <fcntl.h>
1855470Sbostic #include <dirent.h>
1955470Sbostic #include <unistd.h>
2055470Sbostic #include <stdio.h>
2155470Sbostic #include <stdlib.h>
2255470Sbostic #include <string.h>
2355470Sbostic #include <ctype.h>
2412113Sralph #include "lp.h"
2555470Sbostic #include "lp.local.h"
2637968Sbostic #include "pathnames.h"
2712113Sralph
2855470Sbostic /*
2955470Sbostic * Routines to display the state of the queue.
3055470Sbostic */
3113170Sralph #define JOBCOL 40 /* column for job # in -l format */
3213170Sralph #define OWNCOL 7 /* start of Owner column in normal */
3313170Sralph #define SIZCOL 62 /* start of Size column in normal */
3412113Sralph
3512113Sralph /*
3612113Sralph * Stuff for handling job specifications
3712113Sralph */
3812113Sralph extern int requ[]; /* job number of spool entries */
3912113Sralph extern int requests; /* # of spool requests */
4056120Selan extern char *user[]; /* users to process */
4156120Selan extern int users; /* # of users in user array */
4212113Sralph
4356120Selan static int col; /* column on screen */
4456120Selan static char current[40]; /* current file being printed */
4556120Selan static char file[132]; /* print file name */
4656120Selan static int first; /* first file in ``files'' column? */
4756120Selan static int garbage; /* # of garbage cf files */
4856120Selan static int lflag; /* long output option */
4956120Selan static int rank; /* order to be printed (-1=none, 0=active) */
5056120Selan static long totsize; /* total print job size in bytes */
5112113Sralph
5256120Selan static char *head0 = "Rank Owner Job Files";
5356120Selan static char *head1 = "Total Size\n";
5412113Sralph
5512113Sralph /*
5612113Sralph * Display the current state of the queue. Format = 1 if long format.
5712113Sralph */
5855470Sbostic void
displayq(format)5912113Sralph displayq(format)
6012113Sralph int format;
6112113Sralph {
6212113Sralph register struct queue *q;
6312113Sralph register int i, nitems, fd;
6430995Sbostic register char *cp;
6512113Sralph struct queue **queue;
6612113Sralph struct stat statb;
6712113Sralph FILE *fp;
6812113Sralph
6912113Sralph lflag = format;
7012113Sralph totsize = 0;
7112113Sralph rank = -1;
7256120Selan if ((i = cgetent(&bp, printcapdb, printer)) == -2)
7356120Selan fatal("can't open printer description file");
7456120Selan else if (i == -1)
7512113Sralph fatal("unknown printer");
7656120Selan else if (i == -3)
7756120Selan fatal("potential reference loop detected in printcap file");
7856120Selan if (cgetstr(bp, "lp", &LP) < 0)
7937968Sbostic LP = _PATH_DEFDEVLP;
8056120Selan if (cgetstr(bp, "rp", &RP) < 0)
8112434Sralph RP = DEFLP;
8256120Selan if (cgetstr(bp, "sd", &SD) < 0)
8337968Sbostic SD = _PATH_DEFSPOOL;
8456120Selan if (cgetstr(bp,"lo", &LO) < 0)
8512113Sralph LO = DEFLOCK;
8656120Selan if (cgetstr(bp, "st", &ST) < 0)
8712113Sralph ST = DEFSTAT;
8856120Selan cgetstr(bp, "rm", &RM);
8938736Stef if (cp = checkremote())
9038736Stef printf("Warning: %s\n", cp);
9112113Sralph
9212113Sralph /*
9330995Sbostic * Print out local queue
9412113Sralph * Find all the control files in the spooling directory
9512113Sralph */
9612113Sralph if (chdir(SD) < 0)
9712113Sralph fatal("cannot chdir to spooling directory");
9812113Sralph if ((nitems = getq(&queue)) < 0)
9912113Sralph fatal("cannot examine spooling area\n");
10016205Sralph if (stat(LO, &statb) >= 0) {
10116205Sralph if (statb.st_mode & 0100) {
10269009Stef if (remote)
10316205Sralph printf("%s: ", host);
10416205Sralph printf("Warning: %s is down: ", printer);
10516205Sralph fd = open(ST, O_RDONLY);
10616205Sralph if (fd >= 0) {
10716205Sralph (void) flock(fd, LOCK_SH);
10816205Sralph while ((i = read(fd, line, sizeof(line))) > 0)
10916205Sralph (void) fwrite(line, 1, i, stdout);
11016205Sralph (void) close(fd); /* unlocks as well */
11116205Sralph } else
11216205Sralph putchar('\n');
11316205Sralph }
11416205Sralph if (statb.st_mode & 010) {
11569009Stef if (remote)
11616205Sralph printf("%s: ", host);
11716205Sralph printf("Warning: %s queue is turned off\n", printer);
11816205Sralph }
11912740Sralph }
12012113Sralph
12130995Sbostic if (nitems) {
12230995Sbostic fp = fopen(LO, "r");
12330995Sbostic if (fp == NULL)
12413441Sralph warn();
12513441Sralph else {
12630995Sbostic /* get daemon pid */
12713441Sralph cp = current;
12868971Stef while ((i = getc(fp)) != EOF && i != '\n')
12968971Stef *cp++ = i;
13013441Sralph *cp = '\0';
13130995Sbostic i = atoi(current);
13230995Sbostic if (i <= 0 || kill(i, 0) < 0)
13330995Sbostic warn();
13430995Sbostic else {
13530995Sbostic /* read current file name */
13630995Sbostic cp = current;
13768971Stef while ((i = getc(fp)) != EOF && i != '\n')
13868971Stef *cp++ = i;
13930995Sbostic *cp = '\0';
14030995Sbostic /*
14130995Sbostic * Print the status file.
14230995Sbostic */
14369009Stef if (remote)
14430995Sbostic printf("%s: ", host);
14530995Sbostic fd = open(ST, O_RDONLY);
14630995Sbostic if (fd >= 0) {
14730995Sbostic (void) flock(fd, LOCK_SH);
14830995Sbostic while ((i = read(fd, line, sizeof(line))) > 0)
14930995Sbostic (void) fwrite(line, 1, i, stdout);
15030995Sbostic (void) close(fd); /* unlocks as well */
15130995Sbostic } else
15230995Sbostic putchar('\n');
15330995Sbostic }
15430995Sbostic (void) fclose(fp);
15513441Sralph }
15630995Sbostic /*
15730995Sbostic * Now, examine the control files and print out the jobs to
15830995Sbostic * be done for each user.
15930995Sbostic */
16030995Sbostic if (!lflag)
16130995Sbostic header();
16230995Sbostic for (i = 0; i < nitems; i++) {
16330995Sbostic q = queue[i];
16430995Sbostic inform(q->q_name);
16530995Sbostic free(q);
16630995Sbostic }
16730995Sbostic free(queue);
16812113Sralph }
16969009Stef if (!remote) {
17031678Skarels if (nitems == 0)
17131678Skarels puts("no entries");
17230995Sbostic return;
17330995Sbostic }
17430995Sbostic
17512113Sralph /*
17630995Sbostic * Print foreign queue
17730995Sbostic * Note that a file in transit may show up in either queue.
17812113Sralph */
17930995Sbostic if (nitems)
18030995Sbostic putchar('\n');
18130995Sbostic (void) sprintf(line, "%c%s", format + '\3', RP);
18230995Sbostic cp = line;
18330995Sbostic for (i = 0; i < requests; i++) {
18430995Sbostic cp += strlen(cp);
18530995Sbostic (void) sprintf(cp, " %d", requ[i]);
18612113Sralph }
18730995Sbostic for (i = 0; i < users; i++) {
18830995Sbostic cp += strlen(cp);
18930995Sbostic *cp++ = ' ';
19030995Sbostic (void) strcpy(cp, user[i]);
19130995Sbostic }
19230995Sbostic strcat(line, "\n");
19369009Stef fd = getport(RM, 0);
19430995Sbostic if (fd < 0) {
19530995Sbostic if (from != host)
19630995Sbostic printf("%s: ", host);
19730995Sbostic printf("connection to %s is down\n", RM);
19830995Sbostic }
19930995Sbostic else {
20030995Sbostic i = strlen(line);
20130995Sbostic if (write(fd, line, i) != i)
20230995Sbostic fatal("Lost connection");
20330995Sbostic while ((i = read(fd, line, sizeof(line))) > 0)
20430995Sbostic (void) fwrite(line, 1, i, stdout);
20530995Sbostic (void) close(fd);
20630995Sbostic }
20712113Sralph }
20812113Sralph
20912113Sralph /*
21013441Sralph * Print a warning message if there is no daemon present.
21113441Sralph */
21255470Sbostic void
warn()21313441Sralph warn()
21413441Sralph {
21569009Stef if (remote)
21613441Sralph printf("\n%s: ", host);
21730995Sbostic puts("Warning: no daemon present");
21813441Sralph current[0] = '\0';
21913441Sralph }
22013441Sralph
22113441Sralph /*
22212113Sralph * Print the header for the short listing format
22312113Sralph */
22455470Sbostic void
header()22512113Sralph header()
22612113Sralph {
22712113Sralph printf(head0);
22812113Sralph col = strlen(head0)+1;
22912113Sralph blankfill(SIZCOL);
23012113Sralph printf(head1);
23112113Sralph }
23212113Sralph
23355470Sbostic void
inform(cf)23412113Sralph inform(cf)
23512113Sralph char *cf;
23612113Sralph {
23755470Sbostic register int j;
23812113Sralph FILE *cfp;
23912113Sralph
24012113Sralph /*
24112113Sralph * There's a chance the control file has gone away
24212113Sralph * in the meantime; if this is the case just keep going
24312113Sralph */
24412113Sralph if ((cfp = fopen(cf, "r")) == NULL)
24512113Sralph return;
24612113Sralph
24712113Sralph if (rank < 0)
24812113Sralph rank = 0;
24969009Stef if (remote || garbage || strcmp(cf, current))
25012113Sralph rank++;
25112113Sralph j = 0;
25212113Sralph while (getline(cfp)) {
25312113Sralph switch (line[0]) {
25412113Sralph case 'P': /* Was this file specified in the user's list? */
25512113Sralph if (!inlist(line+1, cf)) {
25612113Sralph fclose(cfp);
25712113Sralph return;
25812113Sralph }
25912113Sralph if (lflag) {
26012113Sralph printf("\n%s: ", line+1);
26112113Sralph col = strlen(line+1) + 2;
26212113Sralph prank(rank);
26312113Sralph blankfill(JOBCOL);
26412113Sralph printf(" [job %s]\n", cf+3);
26512113Sralph } else {
26612113Sralph col = 0;
26712113Sralph prank(rank);
26812113Sralph blankfill(OWNCOL);
26912113Sralph printf("%-10s %-3d ", line+1, atoi(cf+3));
27012113Sralph col += 16;
27112113Sralph first = 1;
27212113Sralph }
27312113Sralph continue;
27412113Sralph default: /* some format specifer and file name? */
27512113Sralph if (line[0] < 'a' || line[0] > 'z')
27612113Sralph continue;
27712113Sralph if (j == 0 || strcmp(file, line+1) != 0)
27830995Sbostic (void) strcpy(file, line+1);
27912113Sralph j++;
28012113Sralph continue;
28112113Sralph case 'N':
28212113Sralph show(line+1, file, j);
28312113Sralph file[0] = '\0';
28412113Sralph j = 0;
28512113Sralph }
28612113Sralph }
28712113Sralph fclose(cfp);
28812113Sralph if (!lflag) {
28912113Sralph blankfill(SIZCOL);
29034587Sbostic printf("%ld bytes\n", totsize);
29112113Sralph totsize = 0;
29212113Sralph }
29312113Sralph }
29412113Sralph
29555470Sbostic int
inlist(name,file)29612113Sralph inlist(name, file)
29712113Sralph char *name, *file;
29812113Sralph {
29912113Sralph register int *r, n;
30012113Sralph register char **u, *cp;
30112113Sralph
30212113Sralph if (users == 0 && requests == 0)
30312113Sralph return(1);
30412113Sralph /*
30512113Sralph * Check to see if it's in the user list
30612113Sralph */
30712113Sralph for (u = user; u < &user[users]; u++)
30812113Sralph if (!strcmp(*u, name))
30912113Sralph return(1);
31012113Sralph /*
31112113Sralph * Check the request list
31212113Sralph */
31312113Sralph for (n = 0, cp = file+3; isdigit(*cp); )
31412113Sralph n = n * 10 + (*cp++ - '0');
31512113Sralph for (r = requ; r < &requ[requests]; r++)
31612113Sralph if (*r == n && !strcmp(cp, from))
31712113Sralph return(1);
31812113Sralph return(0);
31912113Sralph }
32012113Sralph
32155470Sbostic void
show(nfile,file,copies)32212113Sralph show(nfile, file, copies)
32312113Sralph register char *nfile, *file;
32455470Sbostic int copies;
32512113Sralph {
32612113Sralph if (strcmp(nfile, " ") == 0)
32712113Sralph nfile = "(standard input)";
32812113Sralph if (lflag)
32912113Sralph ldump(nfile, file, copies);
33012113Sralph else
33112113Sralph dump(nfile, file, copies);
33212113Sralph }
33312113Sralph
33412113Sralph /*
33512113Sralph * Fill the line with blanks to the specified column
33612113Sralph */
33755470Sbostic void
blankfill(n)33812113Sralph blankfill(n)
33912113Sralph register int n;
34012113Sralph {
34112113Sralph while (col++ < n)
34212113Sralph putchar(' ');
34312113Sralph }
34412113Sralph
34512113Sralph /*
34612113Sralph * Give the abbreviated dump of the file names
34712113Sralph */
34855470Sbostic void
dump(nfile,file,copies)34912113Sralph dump(nfile, file, copies)
35012113Sralph char *nfile, *file;
35155470Sbostic int copies;
35212113Sralph {
35312113Sralph register short n, fill;
35412113Sralph struct stat lbuf;
35512113Sralph
35612113Sralph /*
35712113Sralph * Print as many files as will fit
35812113Sralph * (leaving room for the total size)
35912113Sralph */
36012113Sralph fill = first ? 0 : 2; /* fill space for ``, '' */
36112113Sralph if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) {
36212113Sralph if (col < SIZCOL) {
36312113Sralph printf(" ..."), col += 4;
36412113Sralph blankfill(SIZCOL);
36512113Sralph }
36612113Sralph } else {
36712113Sralph if (first)
36812113Sralph first = 0;
36912113Sralph else
37012113Sralph printf(", ");
37112113Sralph printf("%s", nfile);
37212113Sralph col += n+fill;
37312113Sralph }
37412113Sralph if (*file && !stat(file, &lbuf))
37512113Sralph totsize += copies * lbuf.st_size;
37612113Sralph }
37712113Sralph
37812113Sralph /*
37912113Sralph * Print the long info about the file
38012113Sralph */
38155470Sbostic void
ldump(nfile,file,copies)38212113Sralph ldump(nfile, file, copies)
38312113Sralph char *nfile, *file;
38455470Sbostic int copies;
38512113Sralph {
38612113Sralph struct stat lbuf;
38712113Sralph
38812113Sralph putchar('\t');
38912113Sralph if (copies > 1)
39012113Sralph printf("%-2d copies of %-19s", copies, nfile);
39112113Sralph else
39212113Sralph printf("%-32s", nfile);
39312113Sralph if (*file && !stat(file, &lbuf))
39468971Stef printf(" %ld bytes", (long)lbuf.st_size);
39512113Sralph else
39612113Sralph printf(" ??? bytes");
39712113Sralph putchar('\n');
39812113Sralph }
39912113Sralph
40012113Sralph /*
40112113Sralph * Print the job's rank in the queue,
40212113Sralph * update col for screen management
40312113Sralph */
40455470Sbostic void
prank(n)40512113Sralph prank(n)
40655470Sbostic int n;
40712113Sralph {
40855470Sbostic char rline[100];
40912113Sralph static char *r[] = {
41012113Sralph "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
41112113Sralph };
41212113Sralph
41312113Sralph if (n == 0) {
41412113Sralph printf("active");
41512113Sralph col += 6;
41612113Sralph return;
41712113Sralph }
41838491Sbostic if ((n/10)%10 == 1)
41955470Sbostic (void)snprintf(rline, sizeof(rline), "%dth", n);
42012113Sralph else
42155470Sbostic (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]);
42255470Sbostic col += strlen(rline);
42355470Sbostic printf("%s", rline);
42412113Sralph }
425