122427Sdist /* 222427Sdist * Copyright (c) 1983 Regents of the University of California. 322427Sdist * All rights reserved. The Berkeley software License Agreement 422427Sdist * specifies the terms and conditions for redistribution. 522427Sdist */ 622427Sdist 713952Ssam #ifndef lint 825467Stef static char sccsid[] = "@(#)displayq.c 5.1 (Berkeley) 6/6/85"; 922427Sdist #endif not lint 1013952Ssam 1112113Sralph /* 1212113Sralph * Routines to display the state of the queue. 1312113Sralph */ 1412113Sralph 1512113Sralph #include "lp.h" 1612113Sralph 1713170Sralph #define JOBCOL 40 /* column for job # in -l format */ 1813170Sralph #define OWNCOL 7 /* start of Owner column in normal */ 1913170Sralph #define SIZCOL 62 /* start of Size column in normal */ 2012113Sralph 2112113Sralph /* 2212113Sralph * Stuff for handling job specifications 2312113Sralph */ 2412113Sralph extern char *user[]; /* users to process */ 2512113Sralph extern int users; /* # of users in user array */ 2612113Sralph extern int requ[]; /* job number of spool entries */ 2712113Sralph extern int requests; /* # of spool requests */ 2812113Sralph 2916758Sralph int lflag; /* long output option */ 3016758Sralph char current[40]; /* current file being printed */ 3116758Sralph int garbage; /* # of garbage cf files */ 3216758Sralph int rank; /* order to be printed (-1=none, 0=active) */ 3316758Sralph long totsize; /* total print job size in bytes */ 3416758Sralph int first; /* first file in ``files'' column? */ 3516758Sralph int col; /* column on screen */ 3616758Sralph int sendtorem; /* are we sending to a remote? */ 3716758Sralph char file[132]; /* print file name */ 3812113Sralph 3916758Sralph char *head0 = "Rank Owner Job Files"; 4016758Sralph char *head1 = "Total Size\n"; 4112113Sralph 4212113Sralph /* 4312113Sralph * Display the current state of the queue. Format = 1 if long format. 4412113Sralph */ 4512113Sralph displayq(format) 4612113Sralph int format; 4712113Sralph { 4812113Sralph register struct queue *q; 4912113Sralph register int i, nitems, fd; 50*30995Sbostic register char *cp; 5112113Sralph struct queue **queue; 5212113Sralph struct stat statb; 5312113Sralph FILE *fp; 54*30995Sbostic char c; 5512113Sralph 5612113Sralph lflag = format; 5712113Sralph totsize = 0; 5812113Sralph rank = -1; 5912113Sralph 6012113Sralph if ((i = pgetent(line, printer)) < 0) 6112113Sralph fatal("cannot open printer description file"); 6212113Sralph else if (i == 0) 6312113Sralph fatal("unknown printer"); 6412113Sralph if ((LP = pgetstr("lp", &bp)) == NULL) 6512113Sralph LP = DEFDEVLP; 6612113Sralph if ((RP = pgetstr("rp", &bp)) == NULL) 6712434Sralph RP = DEFLP; 6812113Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 6912113Sralph SD = DEFSPOOL; 7012113Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 7112113Sralph LO = DEFLOCK; 7212113Sralph if ((ST = pgetstr("st", &bp)) == NULL) 7312113Sralph ST = DEFSTAT; 7412113Sralph RM = pgetstr("rm", &bp); 7512113Sralph 7612113Sralph /* 7725467Stef * Figure out whether the local machine is the same as the remote 7825467Stef * machine entry (if it exists). If not, then ignore the local 7925467Stef * queue information. 8025467Stef */ 8125467Stef if (RM != (char *) NULL) { 8225467Stef char name[256]; 8325467Stef struct hostent *hp; 8425467Stef 8525467Stef /* get the standard network name of the local host */ 8625467Stef gethostname(name, sizeof(name)); 8725467Stef name[sizeof(name)-1] = '\0'; 8825467Stef hp = gethostbyname(name); 8925467Stef if (hp == (struct hostent *) NULL) { 9025467Stef printf("unable to get network name for local machine %s\n", 9125467Stef name); 9225467Stef goto localcheck_done; 93*30995Sbostic } else (void) strcpy(name, hp->h_name); 9425467Stef 9525467Stef /* get the network standard name of RM */ 9625467Stef hp = gethostbyname(RM); 9725467Stef if (hp == (struct hostent *) NULL) { 9825467Stef printf("unable to get hostname for remote machine %s\n", 9925467Stef RM); 10025467Stef goto localcheck_done; 10125467Stef } 10225467Stef 10325467Stef /* if printer is not on local machine, ignore LP */ 104*30995Sbostic if (strcmp(name, hp->h_name)) { 105*30995Sbostic *LP = '\0'; 106*30995Sbostic ++sendtorem; 107*30995Sbostic } 10825467Stef } 10925467Stef localcheck_done: 11025467Stef 11125467Stef /* 112*30995Sbostic * Print out local queue 11312113Sralph * Find all the control files in the spooling directory 11412113Sralph */ 11512113Sralph if (chdir(SD) < 0) 11612113Sralph fatal("cannot chdir to spooling directory"); 11712113Sralph if ((nitems = getq(&queue)) < 0) 11812113Sralph fatal("cannot examine spooling area\n"); 11916205Sralph if (stat(LO, &statb) >= 0) { 12016205Sralph if (statb.st_mode & 0100) { 12116205Sralph if (sendtorem) 12216205Sralph printf("%s: ", host); 12316205Sralph printf("Warning: %s is down: ", printer); 12416205Sralph fd = open(ST, O_RDONLY); 12516205Sralph if (fd >= 0) { 12616205Sralph (void) flock(fd, LOCK_SH); 12716205Sralph while ((i = read(fd, line, sizeof(line))) > 0) 12816205Sralph (void) fwrite(line, 1, i, stdout); 12916205Sralph (void) close(fd); /* unlocks as well */ 13016205Sralph } else 13116205Sralph putchar('\n'); 13216205Sralph } 13316205Sralph if (statb.st_mode & 010) { 13416205Sralph if (sendtorem) 13516205Sralph printf("%s: ", host); 13616205Sralph printf("Warning: %s queue is turned off\n", printer); 13716205Sralph } 13812740Sralph } 13912113Sralph 140*30995Sbostic if (nitems) { 141*30995Sbostic fp = fopen(LO, "r"); 142*30995Sbostic if (fp == NULL) 14313441Sralph warn(); 14413441Sralph else { 145*30995Sbostic register char *cp; 146*30995Sbostic 147*30995Sbostic /* get daemon pid */ 14813441Sralph cp = current; 14913441Sralph while ((*cp = getc(fp)) != EOF && *cp != '\n') 15013441Sralph cp++; 15113441Sralph *cp = '\0'; 152*30995Sbostic i = atoi(current); 153*30995Sbostic if (i <= 0 || kill(i, 0) < 0) 154*30995Sbostic warn(); 155*30995Sbostic else { 156*30995Sbostic /* read current file name */ 157*30995Sbostic cp = current; 158*30995Sbostic while ((*cp = getc(fp)) != EOF && *cp != '\n') 159*30995Sbostic cp++; 160*30995Sbostic *cp = '\0'; 161*30995Sbostic /* 162*30995Sbostic * Print the status file. 163*30995Sbostic */ 164*30995Sbostic if (sendtorem) 165*30995Sbostic printf("%s: ", host); 166*30995Sbostic fd = open(ST, O_RDONLY); 167*30995Sbostic if (fd >= 0) { 168*30995Sbostic (void) flock(fd, LOCK_SH); 169*30995Sbostic while ((i = read(fd, line, sizeof(line))) > 0) 170*30995Sbostic (void) fwrite(line, 1, i, stdout); 171*30995Sbostic (void) close(fd); /* unlocks as well */ 172*30995Sbostic } else 173*30995Sbostic putchar('\n'); 174*30995Sbostic } 175*30995Sbostic (void) fclose(fp); 17613441Sralph } 177*30995Sbostic /* 178*30995Sbostic * Now, examine the control files and print out the jobs to 179*30995Sbostic * be done for each user. 180*30995Sbostic */ 181*30995Sbostic if (!lflag) 182*30995Sbostic header(); 183*30995Sbostic for (i = 0; i < nitems; i++) { 184*30995Sbostic q = queue[i]; 185*30995Sbostic inform(q->q_name); 186*30995Sbostic free(q); 187*30995Sbostic } 188*30995Sbostic free(queue); 18912113Sralph } 190*30995Sbostic else if (!sendtorem) { 191*30995Sbostic puts("no entries"); 192*30995Sbostic return; 193*30995Sbostic } 194*30995Sbostic 19512113Sralph /* 196*30995Sbostic * Print foreign queue 197*30995Sbostic * Note that a file in transit may show up in either queue. 19812113Sralph */ 199*30995Sbostic if (nitems) 200*30995Sbostic putchar('\n'); 201*30995Sbostic (void) sprintf(line, "%c%s", format + '\3', RP); 202*30995Sbostic cp = line; 203*30995Sbostic for (i = 0; i < requests; i++) { 204*30995Sbostic cp += strlen(cp); 205*30995Sbostic (void) sprintf(cp, " %d", requ[i]); 20612113Sralph } 207*30995Sbostic for (i = 0; i < users; i++) { 208*30995Sbostic cp += strlen(cp); 209*30995Sbostic *cp++ = ' '; 210*30995Sbostic (void) strcpy(cp, user[i]); 211*30995Sbostic } 212*30995Sbostic strcat(line, "\n"); 213*30995Sbostic fd = getport(RM); 214*30995Sbostic if (fd < 0) { 215*30995Sbostic if (from != host) 216*30995Sbostic printf("%s: ", host); 217*30995Sbostic printf("connection to %s is down\n", RM); 218*30995Sbostic } 219*30995Sbostic else { 220*30995Sbostic i = strlen(line); 221*30995Sbostic if (write(fd, line, i) != i) 222*30995Sbostic fatal("Lost connection"); 223*30995Sbostic while ((i = read(fd, line, sizeof(line))) > 0) 224*30995Sbostic (void) fwrite(line, 1, i, stdout); 225*30995Sbostic (void) close(fd); 226*30995Sbostic } 22712113Sralph } 22812113Sralph 22912113Sralph /* 23013441Sralph * Print a warning message if there is no daemon present. 23113441Sralph */ 23213441Sralph warn() 23313441Sralph { 23413441Sralph if (sendtorem) 23513441Sralph printf("\n%s: ", host); 236*30995Sbostic puts("Warning: no daemon present"); 23713441Sralph current[0] = '\0'; 23813441Sralph } 23913441Sralph 24013441Sralph /* 24112113Sralph * Print the header for the short listing format 24212113Sralph */ 24312113Sralph header() 24412113Sralph { 24512113Sralph printf(head0); 24612113Sralph col = strlen(head0)+1; 24712113Sralph blankfill(SIZCOL); 24812113Sralph printf(head1); 24912113Sralph } 25012113Sralph 25112113Sralph inform(cf) 25212113Sralph char *cf; 25312113Sralph { 25412113Sralph register int j, k; 25512113Sralph register char *cp; 25612113Sralph FILE *cfp; 25712113Sralph 25812113Sralph /* 25912113Sralph * There's a chance the control file has gone away 26012113Sralph * in the meantime; if this is the case just keep going 26112113Sralph */ 26212113Sralph if ((cfp = fopen(cf, "r")) == NULL) 26312113Sralph return; 26412113Sralph 26512113Sralph if (rank < 0) 26612113Sralph rank = 0; 26712113Sralph if (sendtorem || garbage || strcmp(cf, current)) 26812113Sralph rank++; 26912113Sralph j = 0; 27012113Sralph while (getline(cfp)) { 27112113Sralph switch (line[0]) { 27212113Sralph case 'P': /* Was this file specified in the user's list? */ 27312113Sralph if (!inlist(line+1, cf)) { 27412113Sralph fclose(cfp); 27512113Sralph return; 27612113Sralph } 27712113Sralph if (lflag) { 27812113Sralph printf("\n%s: ", line+1); 27912113Sralph col = strlen(line+1) + 2; 28012113Sralph prank(rank); 28112113Sralph blankfill(JOBCOL); 28212113Sralph printf(" [job %s]\n", cf+3); 28312113Sralph } else { 28412113Sralph col = 0; 28512113Sralph prank(rank); 28612113Sralph blankfill(OWNCOL); 28712113Sralph printf("%-10s %-3d ", line+1, atoi(cf+3)); 28812113Sralph col += 16; 28912113Sralph first = 1; 29012113Sralph } 29112113Sralph continue; 29212113Sralph default: /* some format specifer and file name? */ 29312113Sralph if (line[0] < 'a' || line[0] > 'z') 29412113Sralph continue; 29512113Sralph if (j == 0 || strcmp(file, line+1) != 0) 296*30995Sbostic (void) strcpy(file, line+1); 29712113Sralph j++; 29812113Sralph continue; 29912113Sralph case 'N': 30012113Sralph show(line+1, file, j); 30112113Sralph file[0] = '\0'; 30212113Sralph j = 0; 30312113Sralph } 30412113Sralph } 30512113Sralph fclose(cfp); 30612113Sralph if (!lflag) { 30712113Sralph blankfill(SIZCOL); 30812113Sralph printf("%D bytes\n", totsize); 30912113Sralph totsize = 0; 31012113Sralph } 31112113Sralph } 31212113Sralph 31312113Sralph inlist(name, file) 31412113Sralph char *name, *file; 31512113Sralph { 31612113Sralph register int *r, n; 31712113Sralph register char **u, *cp; 31812113Sralph 31912113Sralph if (users == 0 && requests == 0) 32012113Sralph return(1); 32112113Sralph /* 32212113Sralph * Check to see if it's in the user list 32312113Sralph */ 32412113Sralph for (u = user; u < &user[users]; u++) 32512113Sralph if (!strcmp(*u, name)) 32612113Sralph return(1); 32712113Sralph /* 32812113Sralph * Check the request list 32912113Sralph */ 33012113Sralph for (n = 0, cp = file+3; isdigit(*cp); ) 33112113Sralph n = n * 10 + (*cp++ - '0'); 33212113Sralph for (r = requ; r < &requ[requests]; r++) 33312113Sralph if (*r == n && !strcmp(cp, from)) 33412113Sralph return(1); 33512113Sralph return(0); 33612113Sralph } 33712113Sralph 33812113Sralph show(nfile, file, copies) 33912113Sralph register char *nfile, *file; 34012113Sralph { 34112113Sralph if (strcmp(nfile, " ") == 0) 34212113Sralph nfile = "(standard input)"; 34312113Sralph if (lflag) 34412113Sralph ldump(nfile, file, copies); 34512113Sralph else 34612113Sralph dump(nfile, file, copies); 34712113Sralph } 34812113Sralph 34912113Sralph /* 35012113Sralph * Fill the line with blanks to the specified column 35112113Sralph */ 35212113Sralph blankfill(n) 35312113Sralph register int n; 35412113Sralph { 35512113Sralph while (col++ < n) 35612113Sralph putchar(' '); 35712113Sralph } 35812113Sralph 35912113Sralph /* 36012113Sralph * Give the abbreviated dump of the file names 36112113Sralph */ 36212113Sralph dump(nfile, file, copies) 36312113Sralph char *nfile, *file; 36412113Sralph { 36512113Sralph register short n, fill; 36612113Sralph struct stat lbuf; 36712113Sralph 36812113Sralph /* 36912113Sralph * Print as many files as will fit 37012113Sralph * (leaving room for the total size) 37112113Sralph */ 37212113Sralph fill = first ? 0 : 2; /* fill space for ``, '' */ 37312113Sralph if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 37412113Sralph if (col < SIZCOL) { 37512113Sralph printf(" ..."), col += 4; 37612113Sralph blankfill(SIZCOL); 37712113Sralph } 37812113Sralph } else { 37912113Sralph if (first) 38012113Sralph first = 0; 38112113Sralph else 38212113Sralph printf(", "); 38312113Sralph printf("%s", nfile); 38412113Sralph col += n+fill; 38512113Sralph } 38612113Sralph if (*file && !stat(file, &lbuf)) 38712113Sralph totsize += copies * lbuf.st_size; 38812113Sralph } 38912113Sralph 39012113Sralph /* 39112113Sralph * Print the long info about the file 39212113Sralph */ 39312113Sralph ldump(nfile, file, copies) 39412113Sralph char *nfile, *file; 39512113Sralph { 39612113Sralph struct stat lbuf; 39712113Sralph 39812113Sralph putchar('\t'); 39912113Sralph if (copies > 1) 40012113Sralph printf("%-2d copies of %-19s", copies, nfile); 40112113Sralph else 40212113Sralph printf("%-32s", nfile); 40312113Sralph if (*file && !stat(file, &lbuf)) 40412113Sralph printf(" %D bytes", lbuf.st_size); 40512113Sralph else 40612113Sralph printf(" ??? bytes"); 40712113Sralph putchar('\n'); 40812113Sralph } 40912113Sralph 41012113Sralph /* 41112113Sralph * Print the job's rank in the queue, 41212113Sralph * update col for screen management 41312113Sralph */ 41412113Sralph prank(n) 41512113Sralph { 41612113Sralph char line[100]; 41712113Sralph static char *r[] = { 41812113Sralph "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 41912113Sralph }; 42012113Sralph 42112113Sralph if (n == 0) { 42212113Sralph printf("active"); 42312113Sralph col += 6; 42412113Sralph return; 42512113Sralph } 42612113Sralph if ((n/10) == 1) 42712113Sralph (void) sprintf(line, "%dth", n); 42812113Sralph else 42912113Sralph (void) sprintf(line, "%d%s", n, r[n%10]); 43012113Sralph col += strlen(line); 43112113Sralph printf("%s", line); 43212113Sralph } 433