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*68971Stef static char sccsid[] = "@(#)displayq.c 8.2 (Berkeley) 04/27/95"; 1034203Sbostic #endif /* not lint */ 1113952Ssam 1255470Sbostic #include <sys/param.h> 1355470Sbostic #include <sys/stat.h> 1412113Sralph 1555470Sbostic #include <signal.h> 1655470Sbostic #include <fcntl.h> 1755470Sbostic #include <dirent.h> 1855470Sbostic #include <unistd.h> 1955470Sbostic #include <stdio.h> 2055470Sbostic #include <stdlib.h> 2155470Sbostic #include <string.h> 2255470Sbostic #include <ctype.h> 2312113Sralph #include "lp.h" 2455470Sbostic #include "lp.local.h" 2537968Sbostic #include "pathnames.h" 2612113Sralph 2755470Sbostic /* 2855470Sbostic * Routines to display the state of the queue. 2955470Sbostic */ 3013170Sralph #define JOBCOL 40 /* column for job # in -l format */ 3113170Sralph #define OWNCOL 7 /* start of Owner column in normal */ 3213170Sralph #define SIZCOL 62 /* start of Size column in normal */ 3312113Sralph 3412113Sralph /* 3512113Sralph * Stuff for handling job specifications 3612113Sralph */ 3712113Sralph extern int requ[]; /* job number of spool entries */ 3812113Sralph extern int requests; /* # of spool requests */ 3956120Selan extern char *user[]; /* users to process */ 4056120Selan extern int users; /* # of users in user array */ 4112113Sralph 4256120Selan static int col; /* column on screen */ 4356120Selan static char current[40]; /* current file being printed */ 4456120Selan static char file[132]; /* print file name */ 4556120Selan static int first; /* first file in ``files'' column? */ 4656120Selan static int garbage; /* # of garbage cf files */ 4756120Selan static int lflag; /* long output option */ 4856120Selan static int rank; /* order to be printed (-1=none, 0=active) */ 4956120Selan static long totsize; /* total print job size in bytes */ 5012113Sralph 5156120Selan static char *head0 = "Rank Owner Job Files"; 5256120Selan static char *head1 = "Total Size\n"; 5312113Sralph 5412113Sralph /* 5512113Sralph * Display the current state of the queue. Format = 1 if long format. 5612113Sralph */ 5755470Sbostic void 5812113Sralph displayq(format) 5912113Sralph int format; 6012113Sralph { 6112113Sralph register struct queue *q; 6212113Sralph register int i, nitems, fd; 6330995Sbostic register char *cp; 6412113Sralph struct queue **queue; 6512113Sralph struct stat statb; 6612113Sralph FILE *fp; 6712113Sralph 6812113Sralph lflag = format; 6912113Sralph totsize = 0; 7012113Sralph rank = -1; 7156120Selan if ((i = cgetent(&bp, printcapdb, printer)) == -2) 7256120Selan fatal("can't open printer description file"); 7356120Selan else if (i == -1) 7412113Sralph fatal("unknown printer"); 7556120Selan else if (i == -3) 7656120Selan fatal("potential reference loop detected in printcap file"); 7756120Selan if (cgetstr(bp, "lp", &LP) < 0) 7837968Sbostic LP = _PATH_DEFDEVLP; 7956120Selan if (cgetstr(bp, "rp", &RP) < 0) 8012434Sralph RP = DEFLP; 8156120Selan if (cgetstr(bp, "sd", &SD) < 0) 8237968Sbostic SD = _PATH_DEFSPOOL; 8356120Selan if (cgetstr(bp,"lo", &LO) < 0) 8412113Sralph LO = DEFLOCK; 8556120Selan if (cgetstr(bp, "st", &ST) < 0) 8612113Sralph ST = DEFSTAT; 8756120Selan cgetstr(bp, "rm", &RM); 8838736Stef if (cp = checkremote()) 8938736Stef printf("Warning: %s\n", cp); 9012113Sralph 9112113Sralph /* 9230995Sbostic * Print out local queue 9312113Sralph * Find all the control files in the spooling directory 9412113Sralph */ 9512113Sralph if (chdir(SD) < 0) 9612113Sralph fatal("cannot chdir to spooling directory"); 9712113Sralph if ((nitems = getq(&queue)) < 0) 9812113Sralph fatal("cannot examine spooling area\n"); 9916205Sralph if (stat(LO, &statb) >= 0) { 10016205Sralph if (statb.st_mode & 0100) { 10116205Sralph if (sendtorem) 10216205Sralph printf("%s: ", host); 10316205Sralph printf("Warning: %s is down: ", printer); 10416205Sralph fd = open(ST, O_RDONLY); 10516205Sralph if (fd >= 0) { 10616205Sralph (void) flock(fd, LOCK_SH); 10716205Sralph while ((i = read(fd, line, sizeof(line))) > 0) 10816205Sralph (void) fwrite(line, 1, i, stdout); 10916205Sralph (void) close(fd); /* unlocks as well */ 11016205Sralph } else 11116205Sralph putchar('\n'); 11216205Sralph } 11316205Sralph if (statb.st_mode & 010) { 11416205Sralph if (sendtorem) 11516205Sralph printf("%s: ", host); 11616205Sralph printf("Warning: %s queue is turned off\n", printer); 11716205Sralph } 11812740Sralph } 11912113Sralph 12030995Sbostic if (nitems) { 12130995Sbostic fp = fopen(LO, "r"); 12230995Sbostic if (fp == NULL) 12313441Sralph warn(); 12413441Sralph else { 12530995Sbostic /* get daemon pid */ 12613441Sralph cp = current; 127*68971Stef while ((i = getc(fp)) != EOF && i != '\n') 128*68971Stef *cp++ = i; 12913441Sralph *cp = '\0'; 13030995Sbostic i = atoi(current); 13130995Sbostic if (i <= 0 || kill(i, 0) < 0) 13230995Sbostic warn(); 13330995Sbostic else { 13430995Sbostic /* read current file name */ 13530995Sbostic cp = current; 136*68971Stef while ((i = getc(fp)) != EOF && i != '\n') 137*68971Stef *cp++ = i; 13830995Sbostic *cp = '\0'; 13930995Sbostic /* 14030995Sbostic * Print the status file. 14130995Sbostic */ 14230995Sbostic if (sendtorem) 14330995Sbostic printf("%s: ", host); 14430995Sbostic fd = open(ST, O_RDONLY); 14530995Sbostic if (fd >= 0) { 14630995Sbostic (void) flock(fd, LOCK_SH); 14730995Sbostic while ((i = read(fd, line, sizeof(line))) > 0) 14830995Sbostic (void) fwrite(line, 1, i, stdout); 14930995Sbostic (void) close(fd); /* unlocks as well */ 15030995Sbostic } else 15130995Sbostic putchar('\n'); 15230995Sbostic } 15330995Sbostic (void) fclose(fp); 15413441Sralph } 15530995Sbostic /* 15630995Sbostic * Now, examine the control files and print out the jobs to 15730995Sbostic * be done for each user. 15830995Sbostic */ 15930995Sbostic if (!lflag) 16030995Sbostic header(); 16130995Sbostic for (i = 0; i < nitems; i++) { 16230995Sbostic q = queue[i]; 16330995Sbostic inform(q->q_name); 16430995Sbostic free(q); 16530995Sbostic } 16630995Sbostic free(queue); 16712113Sralph } 16831678Skarels if (!sendtorem) { 16931678Skarels if (nitems == 0) 17031678Skarels puts("no entries"); 17130995Sbostic return; 17230995Sbostic } 17330995Sbostic 17412113Sralph /* 17530995Sbostic * Print foreign queue 17630995Sbostic * Note that a file in transit may show up in either queue. 17712113Sralph */ 17830995Sbostic if (nitems) 17930995Sbostic putchar('\n'); 18030995Sbostic (void) sprintf(line, "%c%s", format + '\3', RP); 18130995Sbostic cp = line; 18230995Sbostic for (i = 0; i < requests; i++) { 18330995Sbostic cp += strlen(cp); 18430995Sbostic (void) sprintf(cp, " %d", requ[i]); 18512113Sralph } 18630995Sbostic for (i = 0; i < users; i++) { 18730995Sbostic cp += strlen(cp); 18830995Sbostic *cp++ = ' '; 18930995Sbostic (void) strcpy(cp, user[i]); 19030995Sbostic } 19130995Sbostic strcat(line, "\n"); 19230995Sbostic fd = getport(RM); 19330995Sbostic if (fd < 0) { 19430995Sbostic if (from != host) 19530995Sbostic printf("%s: ", host); 19630995Sbostic printf("connection to %s is down\n", RM); 19730995Sbostic } 19830995Sbostic else { 19930995Sbostic i = strlen(line); 20030995Sbostic if (write(fd, line, i) != i) 20130995Sbostic fatal("Lost connection"); 20230995Sbostic while ((i = read(fd, line, sizeof(line))) > 0) 20330995Sbostic (void) fwrite(line, 1, i, stdout); 20430995Sbostic (void) close(fd); 20530995Sbostic } 20612113Sralph } 20712113Sralph 20812113Sralph /* 20913441Sralph * Print a warning message if there is no daemon present. 21013441Sralph */ 21155470Sbostic void 21213441Sralph warn() 21313441Sralph { 21413441Sralph if (sendtorem) 21513441Sralph printf("\n%s: ", host); 21630995Sbostic puts("Warning: no daemon present"); 21713441Sralph current[0] = '\0'; 21813441Sralph } 21913441Sralph 22013441Sralph /* 22112113Sralph * Print the header for the short listing format 22212113Sralph */ 22355470Sbostic void 22412113Sralph header() 22512113Sralph { 22612113Sralph printf(head0); 22712113Sralph col = strlen(head0)+1; 22812113Sralph blankfill(SIZCOL); 22912113Sralph printf(head1); 23012113Sralph } 23112113Sralph 23255470Sbostic void 23312113Sralph inform(cf) 23412113Sralph char *cf; 23512113Sralph { 23655470Sbostic register int j; 23712113Sralph FILE *cfp; 23812113Sralph 23912113Sralph /* 24012113Sralph * There's a chance the control file has gone away 24112113Sralph * in the meantime; if this is the case just keep going 24212113Sralph */ 24312113Sralph if ((cfp = fopen(cf, "r")) == NULL) 24412113Sralph return; 24512113Sralph 24612113Sralph if (rank < 0) 24712113Sralph rank = 0; 24812113Sralph if (sendtorem || garbage || strcmp(cf, current)) 24912113Sralph rank++; 25012113Sralph j = 0; 25112113Sralph while (getline(cfp)) { 25212113Sralph switch (line[0]) { 25312113Sralph case 'P': /* Was this file specified in the user's list? */ 25412113Sralph if (!inlist(line+1, cf)) { 25512113Sralph fclose(cfp); 25612113Sralph return; 25712113Sralph } 25812113Sralph if (lflag) { 25912113Sralph printf("\n%s: ", line+1); 26012113Sralph col = strlen(line+1) + 2; 26112113Sralph prank(rank); 26212113Sralph blankfill(JOBCOL); 26312113Sralph printf(" [job %s]\n", cf+3); 26412113Sralph } else { 26512113Sralph col = 0; 26612113Sralph prank(rank); 26712113Sralph blankfill(OWNCOL); 26812113Sralph printf("%-10s %-3d ", line+1, atoi(cf+3)); 26912113Sralph col += 16; 27012113Sralph first = 1; 27112113Sralph } 27212113Sralph continue; 27312113Sralph default: /* some format specifer and file name? */ 27412113Sralph if (line[0] < 'a' || line[0] > 'z') 27512113Sralph continue; 27612113Sralph if (j == 0 || strcmp(file, line+1) != 0) 27730995Sbostic (void) strcpy(file, line+1); 27812113Sralph j++; 27912113Sralph continue; 28012113Sralph case 'N': 28112113Sralph show(line+1, file, j); 28212113Sralph file[0] = '\0'; 28312113Sralph j = 0; 28412113Sralph } 28512113Sralph } 28612113Sralph fclose(cfp); 28712113Sralph if (!lflag) { 28812113Sralph blankfill(SIZCOL); 28934587Sbostic printf("%ld bytes\n", totsize); 29012113Sralph totsize = 0; 29112113Sralph } 29212113Sralph } 29312113Sralph 29455470Sbostic int 29512113Sralph inlist(name, file) 29612113Sralph char *name, *file; 29712113Sralph { 29812113Sralph register int *r, n; 29912113Sralph register char **u, *cp; 30012113Sralph 30112113Sralph if (users == 0 && requests == 0) 30212113Sralph return(1); 30312113Sralph /* 30412113Sralph * Check to see if it's in the user list 30512113Sralph */ 30612113Sralph for (u = user; u < &user[users]; u++) 30712113Sralph if (!strcmp(*u, name)) 30812113Sralph return(1); 30912113Sralph /* 31012113Sralph * Check the request list 31112113Sralph */ 31212113Sralph for (n = 0, cp = file+3; isdigit(*cp); ) 31312113Sralph n = n * 10 + (*cp++ - '0'); 31412113Sralph for (r = requ; r < &requ[requests]; r++) 31512113Sralph if (*r == n && !strcmp(cp, from)) 31612113Sralph return(1); 31712113Sralph return(0); 31812113Sralph } 31912113Sralph 32055470Sbostic void 32112113Sralph show(nfile, file, copies) 32212113Sralph register char *nfile, *file; 32355470Sbostic int copies; 32412113Sralph { 32512113Sralph if (strcmp(nfile, " ") == 0) 32612113Sralph nfile = "(standard input)"; 32712113Sralph if (lflag) 32812113Sralph ldump(nfile, file, copies); 32912113Sralph else 33012113Sralph dump(nfile, file, copies); 33112113Sralph } 33212113Sralph 33312113Sralph /* 33412113Sralph * Fill the line with blanks to the specified column 33512113Sralph */ 33655470Sbostic void 33712113Sralph blankfill(n) 33812113Sralph register int n; 33912113Sralph { 34012113Sralph while (col++ < n) 34112113Sralph putchar(' '); 34212113Sralph } 34312113Sralph 34412113Sralph /* 34512113Sralph * Give the abbreviated dump of the file names 34612113Sralph */ 34755470Sbostic void 34812113Sralph dump(nfile, file, copies) 34912113Sralph char *nfile, *file; 35055470Sbostic int copies; 35112113Sralph { 35212113Sralph register short n, fill; 35312113Sralph struct stat lbuf; 35412113Sralph 35512113Sralph /* 35612113Sralph * Print as many files as will fit 35712113Sralph * (leaving room for the total size) 35812113Sralph */ 35912113Sralph fill = first ? 0 : 2; /* fill space for ``, '' */ 36012113Sralph if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 36112113Sralph if (col < SIZCOL) { 36212113Sralph printf(" ..."), col += 4; 36312113Sralph blankfill(SIZCOL); 36412113Sralph } 36512113Sralph } else { 36612113Sralph if (first) 36712113Sralph first = 0; 36812113Sralph else 36912113Sralph printf(", "); 37012113Sralph printf("%s", nfile); 37112113Sralph col += n+fill; 37212113Sralph } 37312113Sralph if (*file && !stat(file, &lbuf)) 37412113Sralph totsize += copies * lbuf.st_size; 37512113Sralph } 37612113Sralph 37712113Sralph /* 37812113Sralph * Print the long info about the file 37912113Sralph */ 38055470Sbostic void 38112113Sralph ldump(nfile, file, copies) 38212113Sralph char *nfile, *file; 38355470Sbostic int copies; 38412113Sralph { 38512113Sralph struct stat lbuf; 38612113Sralph 38712113Sralph putchar('\t'); 38812113Sralph if (copies > 1) 38912113Sralph printf("%-2d copies of %-19s", copies, nfile); 39012113Sralph else 39112113Sralph printf("%-32s", nfile); 39212113Sralph if (*file && !stat(file, &lbuf)) 393*68971Stef printf(" %ld bytes", (long)lbuf.st_size); 39412113Sralph else 39512113Sralph printf(" ??? bytes"); 39612113Sralph putchar('\n'); 39712113Sralph } 39812113Sralph 39912113Sralph /* 40012113Sralph * Print the job's rank in the queue, 40112113Sralph * update col for screen management 40212113Sralph */ 40355470Sbostic void 40412113Sralph prank(n) 40555470Sbostic int n; 40612113Sralph { 40755470Sbostic char rline[100]; 40812113Sralph static char *r[] = { 40912113Sralph "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 41012113Sralph }; 41112113Sralph 41212113Sralph if (n == 0) { 41312113Sralph printf("active"); 41412113Sralph col += 6; 41512113Sralph return; 41612113Sralph } 41738491Sbostic if ((n/10)%10 == 1) 41855470Sbostic (void)snprintf(rline, sizeof(rline), "%dth", n); 41912113Sralph else 42055470Sbostic (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]); 42155470Sbostic col += strlen(rline); 42255470Sbostic printf("%s", rline); 42312113Sralph } 424