122427Sdist /* 222427Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 5*56120Selan * Redistribution and use in source and binary forms, with or without 6*56120Selan * modification, are permitted provided that the following conditions 7*56120Selan * are met: 8*56120Selan * 1. Redistributions of source code must retain the above copyright 9*56120Selan * notice, this list of conditions and the following disclaimer. 10*56120Selan * 2. Redistributions in binary form must reproduce the above copyright 11*56120Selan * notice, this list of conditions and the following disclaimer in the 12*56120Selan * documentation and/or other materials provided with the distribution. 13*56120Selan * 3. All advertising materials mentioning features or use of this software 14*56120Selan * must display the following acknowledgement: 15*56120Selan * This product includes software developed by the University of 16*56120Selan * California, Berkeley and its contributors. 17*56120Selan * 4. Neither the name of the University nor the names of its contributors 18*56120Selan * may be used to endorse or promote products derived from this software 19*56120Selan * without specific prior written permission. 20*56120Selan * 21*56120Selan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22*56120Selan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23*56120Selan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24*56120Selan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25*56120Selan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26*56120Selan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27*56120Selan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28*56120Selan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29*56120Selan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30*56120Selan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*56120Selan * SUCH DAMAGE. 3222427Sdist */ 3322427Sdist 3413952Ssam #ifndef lint 35*56120Selan static char sccsid[] = "@(#)displayq.c 5.16 (Berkeley) 8/31/92"; 3634203Sbostic #endif /* not lint */ 3713952Ssam 3855470Sbostic #include <sys/param.h> 3955470Sbostic #include <sys/stat.h> 4012113Sralph 4155470Sbostic #include <signal.h> 4255470Sbostic #include <fcntl.h> 4355470Sbostic #include <dirent.h> 4455470Sbostic #include <unistd.h> 4555470Sbostic #include <stdio.h> 4655470Sbostic #include <stdlib.h> 4755470Sbostic #include <string.h> 4855470Sbostic #include <ctype.h> 4912113Sralph #include "lp.h" 5055470Sbostic #include "lp.local.h" 5137968Sbostic #include "pathnames.h" 5212113Sralph 5355470Sbostic /* 5455470Sbostic * Routines to display the state of the queue. 5555470Sbostic */ 5613170Sralph #define JOBCOL 40 /* column for job # in -l format */ 5713170Sralph #define OWNCOL 7 /* start of Owner column in normal */ 5813170Sralph #define SIZCOL 62 /* start of Size column in normal */ 5912113Sralph 6012113Sralph /* 6112113Sralph * Stuff for handling job specifications 6212113Sralph */ 6312113Sralph extern int requ[]; /* job number of spool entries */ 6412113Sralph extern int requests; /* # of spool requests */ 65*56120Selan extern char *user[]; /* users to process */ 66*56120Selan extern int users; /* # of users in user array */ 6712113Sralph 68*56120Selan static int col; /* column on screen */ 69*56120Selan static char current[40]; /* current file being printed */ 70*56120Selan static char file[132]; /* print file name */ 71*56120Selan static int first; /* first file in ``files'' column? */ 72*56120Selan static int garbage; /* # of garbage cf files */ 73*56120Selan static int lflag; /* long output option */ 74*56120Selan static int rank; /* order to be printed (-1=none, 0=active) */ 75*56120Selan static long totsize; /* total print job size in bytes */ 7612113Sralph 77*56120Selan static char *head0 = "Rank Owner Job Files"; 78*56120Selan static char *head1 = "Total Size\n"; 7912113Sralph 8012113Sralph /* 8112113Sralph * Display the current state of the queue. Format = 1 if long format. 8212113Sralph */ 8355470Sbostic void 8412113Sralph displayq(format) 8512113Sralph int format; 8612113Sralph { 8712113Sralph register struct queue *q; 8812113Sralph register int i, nitems, fd; 8930995Sbostic register char *cp; 9012113Sralph struct queue **queue; 9112113Sralph struct stat statb; 9212113Sralph FILE *fp; 9312113Sralph 9412113Sralph lflag = format; 9512113Sralph totsize = 0; 9612113Sralph rank = -1; 97*56120Selan if ((i = cgetent(&bp, printcapdb, printer)) == -2) 98*56120Selan fatal("can't open printer description file"); 99*56120Selan else if (i == -1) 10012113Sralph fatal("unknown printer"); 101*56120Selan else if (i == -3) 102*56120Selan fatal("potential reference loop detected in printcap file"); 103*56120Selan if (cgetstr(bp, "lp", &LP) < 0) 10437968Sbostic LP = _PATH_DEFDEVLP; 105*56120Selan if (cgetstr(bp, "rp", &RP) < 0) 10612434Sralph RP = DEFLP; 107*56120Selan if (cgetstr(bp, "sd", &SD) < 0) 10837968Sbostic SD = _PATH_DEFSPOOL; 109*56120Selan if (cgetstr(bp,"lo", &LO) < 0) 11012113Sralph LO = DEFLOCK; 111*56120Selan if (cgetstr(bp, "st", &ST) < 0) 11212113Sralph ST = DEFSTAT; 113*56120Selan cgetstr(bp, "rm", &RM); 11438736Stef if (cp = checkremote()) 11538736Stef printf("Warning: %s\n", cp); 11612113Sralph 11712113Sralph /* 11830995Sbostic * Print out local queue 11912113Sralph * Find all the control files in the spooling directory 12012113Sralph */ 12112113Sralph if (chdir(SD) < 0) 12212113Sralph fatal("cannot chdir to spooling directory"); 12312113Sralph if ((nitems = getq(&queue)) < 0) 12412113Sralph fatal("cannot examine spooling area\n"); 12516205Sralph if (stat(LO, &statb) >= 0) { 12616205Sralph if (statb.st_mode & 0100) { 12716205Sralph if (sendtorem) 12816205Sralph printf("%s: ", host); 12916205Sralph printf("Warning: %s is down: ", printer); 13016205Sralph fd = open(ST, O_RDONLY); 13116205Sralph if (fd >= 0) { 13216205Sralph (void) flock(fd, LOCK_SH); 13316205Sralph while ((i = read(fd, line, sizeof(line))) > 0) 13416205Sralph (void) fwrite(line, 1, i, stdout); 13516205Sralph (void) close(fd); /* unlocks as well */ 13616205Sralph } else 13716205Sralph putchar('\n'); 13816205Sralph } 13916205Sralph if (statb.st_mode & 010) { 14016205Sralph if (sendtorem) 14116205Sralph printf("%s: ", host); 14216205Sralph printf("Warning: %s queue is turned off\n", printer); 14316205Sralph } 14412740Sralph } 14512113Sralph 14630995Sbostic if (nitems) { 14730995Sbostic fp = fopen(LO, "r"); 14830995Sbostic if (fp == NULL) 14913441Sralph warn(); 15013441Sralph else { 15130995Sbostic /* get daemon pid */ 15213441Sralph cp = current; 15313441Sralph while ((*cp = getc(fp)) != EOF && *cp != '\n') 15413441Sralph cp++; 15513441Sralph *cp = '\0'; 15630995Sbostic i = atoi(current); 15730995Sbostic if (i <= 0 || kill(i, 0) < 0) 15830995Sbostic warn(); 15930995Sbostic else { 16030995Sbostic /* read current file name */ 16130995Sbostic cp = current; 16230995Sbostic while ((*cp = getc(fp)) != EOF && *cp != '\n') 16330995Sbostic cp++; 16430995Sbostic *cp = '\0'; 16530995Sbostic /* 16630995Sbostic * Print the status file. 16730995Sbostic */ 16830995Sbostic if (sendtorem) 16930995Sbostic printf("%s: ", host); 17030995Sbostic fd = open(ST, O_RDONLY); 17130995Sbostic if (fd >= 0) { 17230995Sbostic (void) flock(fd, LOCK_SH); 17330995Sbostic while ((i = read(fd, line, sizeof(line))) > 0) 17430995Sbostic (void) fwrite(line, 1, i, stdout); 17530995Sbostic (void) close(fd); /* unlocks as well */ 17630995Sbostic } else 17730995Sbostic putchar('\n'); 17830995Sbostic } 17930995Sbostic (void) fclose(fp); 18013441Sralph } 18130995Sbostic /* 18230995Sbostic * Now, examine the control files and print out the jobs to 18330995Sbostic * be done for each user. 18430995Sbostic */ 18530995Sbostic if (!lflag) 18630995Sbostic header(); 18730995Sbostic for (i = 0; i < nitems; i++) { 18830995Sbostic q = queue[i]; 18930995Sbostic inform(q->q_name); 19030995Sbostic free(q); 19130995Sbostic } 19230995Sbostic free(queue); 19312113Sralph } 19431678Skarels if (!sendtorem) { 19531678Skarels if (nitems == 0) 19631678Skarels puts("no entries"); 19730995Sbostic return; 19830995Sbostic } 19930995Sbostic 20012113Sralph /* 20130995Sbostic * Print foreign queue 20230995Sbostic * Note that a file in transit may show up in either queue. 20312113Sralph */ 20430995Sbostic if (nitems) 20530995Sbostic putchar('\n'); 20630995Sbostic (void) sprintf(line, "%c%s", format + '\3', RP); 20730995Sbostic cp = line; 20830995Sbostic for (i = 0; i < requests; i++) { 20930995Sbostic cp += strlen(cp); 21030995Sbostic (void) sprintf(cp, " %d", requ[i]); 21112113Sralph } 21230995Sbostic for (i = 0; i < users; i++) { 21330995Sbostic cp += strlen(cp); 21430995Sbostic *cp++ = ' '; 21530995Sbostic (void) strcpy(cp, user[i]); 21630995Sbostic } 21730995Sbostic strcat(line, "\n"); 21830995Sbostic fd = getport(RM); 21930995Sbostic if (fd < 0) { 22030995Sbostic if (from != host) 22130995Sbostic printf("%s: ", host); 22230995Sbostic printf("connection to %s is down\n", RM); 22330995Sbostic } 22430995Sbostic else { 22530995Sbostic i = strlen(line); 22630995Sbostic if (write(fd, line, i) != i) 22730995Sbostic fatal("Lost connection"); 22830995Sbostic while ((i = read(fd, line, sizeof(line))) > 0) 22930995Sbostic (void) fwrite(line, 1, i, stdout); 23030995Sbostic (void) close(fd); 23130995Sbostic } 23212113Sralph } 23312113Sralph 23412113Sralph /* 23513441Sralph * Print a warning message if there is no daemon present. 23613441Sralph */ 23755470Sbostic void 23813441Sralph warn() 23913441Sralph { 24013441Sralph if (sendtorem) 24113441Sralph printf("\n%s: ", host); 24230995Sbostic puts("Warning: no daemon present"); 24313441Sralph current[0] = '\0'; 24413441Sralph } 24513441Sralph 24613441Sralph /* 24712113Sralph * Print the header for the short listing format 24812113Sralph */ 24955470Sbostic void 25012113Sralph header() 25112113Sralph { 25212113Sralph printf(head0); 25312113Sralph col = strlen(head0)+1; 25412113Sralph blankfill(SIZCOL); 25512113Sralph printf(head1); 25612113Sralph } 25712113Sralph 25855470Sbostic void 25912113Sralph inform(cf) 26012113Sralph char *cf; 26112113Sralph { 26255470Sbostic register int j; 26312113Sralph FILE *cfp; 26412113Sralph 26512113Sralph /* 26612113Sralph * There's a chance the control file has gone away 26712113Sralph * in the meantime; if this is the case just keep going 26812113Sralph */ 26912113Sralph if ((cfp = fopen(cf, "r")) == NULL) 27012113Sralph return; 27112113Sralph 27212113Sralph if (rank < 0) 27312113Sralph rank = 0; 27412113Sralph if (sendtorem || garbage || strcmp(cf, current)) 27512113Sralph rank++; 27612113Sralph j = 0; 27712113Sralph while (getline(cfp)) { 27812113Sralph switch (line[0]) { 27912113Sralph case 'P': /* Was this file specified in the user's list? */ 28012113Sralph if (!inlist(line+1, cf)) { 28112113Sralph fclose(cfp); 28212113Sralph return; 28312113Sralph } 28412113Sralph if (lflag) { 28512113Sralph printf("\n%s: ", line+1); 28612113Sralph col = strlen(line+1) + 2; 28712113Sralph prank(rank); 28812113Sralph blankfill(JOBCOL); 28912113Sralph printf(" [job %s]\n", cf+3); 29012113Sralph } else { 29112113Sralph col = 0; 29212113Sralph prank(rank); 29312113Sralph blankfill(OWNCOL); 29412113Sralph printf("%-10s %-3d ", line+1, atoi(cf+3)); 29512113Sralph col += 16; 29612113Sralph first = 1; 29712113Sralph } 29812113Sralph continue; 29912113Sralph default: /* some format specifer and file name? */ 30012113Sralph if (line[0] < 'a' || line[0] > 'z') 30112113Sralph continue; 30212113Sralph if (j == 0 || strcmp(file, line+1) != 0) 30330995Sbostic (void) strcpy(file, line+1); 30412113Sralph j++; 30512113Sralph continue; 30612113Sralph case 'N': 30712113Sralph show(line+1, file, j); 30812113Sralph file[0] = '\0'; 30912113Sralph j = 0; 31012113Sralph } 31112113Sralph } 31212113Sralph fclose(cfp); 31312113Sralph if (!lflag) { 31412113Sralph blankfill(SIZCOL); 31534587Sbostic printf("%ld bytes\n", totsize); 31612113Sralph totsize = 0; 31712113Sralph } 31812113Sralph } 31912113Sralph 32055470Sbostic int 32112113Sralph inlist(name, file) 32212113Sralph char *name, *file; 32312113Sralph { 32412113Sralph register int *r, n; 32512113Sralph register char **u, *cp; 32612113Sralph 32712113Sralph if (users == 0 && requests == 0) 32812113Sralph return(1); 32912113Sralph /* 33012113Sralph * Check to see if it's in the user list 33112113Sralph */ 33212113Sralph for (u = user; u < &user[users]; u++) 33312113Sralph if (!strcmp(*u, name)) 33412113Sralph return(1); 33512113Sralph /* 33612113Sralph * Check the request list 33712113Sralph */ 33812113Sralph for (n = 0, cp = file+3; isdigit(*cp); ) 33912113Sralph n = n * 10 + (*cp++ - '0'); 34012113Sralph for (r = requ; r < &requ[requests]; r++) 34112113Sralph if (*r == n && !strcmp(cp, from)) 34212113Sralph return(1); 34312113Sralph return(0); 34412113Sralph } 34512113Sralph 34655470Sbostic void 34712113Sralph show(nfile, file, copies) 34812113Sralph register char *nfile, *file; 34955470Sbostic int copies; 35012113Sralph { 35112113Sralph if (strcmp(nfile, " ") == 0) 35212113Sralph nfile = "(standard input)"; 35312113Sralph if (lflag) 35412113Sralph ldump(nfile, file, copies); 35512113Sralph else 35612113Sralph dump(nfile, file, copies); 35712113Sralph } 35812113Sralph 35912113Sralph /* 36012113Sralph * Fill the line with blanks to the specified column 36112113Sralph */ 36255470Sbostic void 36312113Sralph blankfill(n) 36412113Sralph register int n; 36512113Sralph { 36612113Sralph while (col++ < n) 36712113Sralph putchar(' '); 36812113Sralph } 36912113Sralph 37012113Sralph /* 37112113Sralph * Give the abbreviated dump of the file names 37212113Sralph */ 37355470Sbostic void 37412113Sralph dump(nfile, file, copies) 37512113Sralph char *nfile, *file; 37655470Sbostic int copies; 37712113Sralph { 37812113Sralph register short n, fill; 37912113Sralph struct stat lbuf; 38012113Sralph 38112113Sralph /* 38212113Sralph * Print as many files as will fit 38312113Sralph * (leaving room for the total size) 38412113Sralph */ 38512113Sralph fill = first ? 0 : 2; /* fill space for ``, '' */ 38612113Sralph if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 38712113Sralph if (col < SIZCOL) { 38812113Sralph printf(" ..."), col += 4; 38912113Sralph blankfill(SIZCOL); 39012113Sralph } 39112113Sralph } else { 39212113Sralph if (first) 39312113Sralph first = 0; 39412113Sralph else 39512113Sralph printf(", "); 39612113Sralph printf("%s", nfile); 39712113Sralph col += n+fill; 39812113Sralph } 39912113Sralph if (*file && !stat(file, &lbuf)) 40012113Sralph totsize += copies * lbuf.st_size; 40112113Sralph } 40212113Sralph 40312113Sralph /* 40412113Sralph * Print the long info about the file 40512113Sralph */ 40655470Sbostic void 40712113Sralph ldump(nfile, file, copies) 40812113Sralph char *nfile, *file; 40955470Sbostic int copies; 41012113Sralph { 41112113Sralph struct stat lbuf; 41212113Sralph 41312113Sralph putchar('\t'); 41412113Sralph if (copies > 1) 41512113Sralph printf("%-2d copies of %-19s", copies, nfile); 41612113Sralph else 41712113Sralph printf("%-32s", nfile); 41812113Sralph if (*file && !stat(file, &lbuf)) 41955470Sbostic printf(" %qd bytes", lbuf.st_size); 42012113Sralph else 42112113Sralph printf(" ??? bytes"); 42212113Sralph putchar('\n'); 42312113Sralph } 42412113Sralph 42512113Sralph /* 42612113Sralph * Print the job's rank in the queue, 42712113Sralph * update col for screen management 42812113Sralph */ 42955470Sbostic void 43012113Sralph prank(n) 43155470Sbostic int n; 43212113Sralph { 43355470Sbostic char rline[100]; 43412113Sralph static char *r[] = { 43512113Sralph "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 43612113Sralph }; 43712113Sralph 43812113Sralph if (n == 0) { 43912113Sralph printf("active"); 44012113Sralph col += 6; 44112113Sralph return; 44212113Sralph } 44338491Sbostic if ((n/10)%10 == 1) 44455470Sbostic (void)snprintf(rline, sizeof(rline), "%dth", n); 44512113Sralph else 44655470Sbostic (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]); 44755470Sbostic col += strlen(rline); 44855470Sbostic printf("%s", rline); 44912113Sralph } 450