1*22427Sdist /* 2*22427Sdist * Copyright (c) 1983 Regents of the University of California. 3*22427Sdist * All rights reserved. The Berkeley software License Agreement 4*22427Sdist * specifies the terms and conditions for redistribution. 5*22427Sdist */ 6*22427Sdist 713952Ssam #ifndef lint 8*22427Sdist static char sccsid[] = "@(#)displayq.c 5.1 (Berkeley) 06/06/85"; 9*22427Sdist #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; 5012113Sralph struct queue **queue; 5112113Sralph struct stat statb; 5212113Sralph FILE *fp; 5312113Sralph 5412113Sralph lflag = format; 5512113Sralph totsize = 0; 5612113Sralph rank = -1; 5712113Sralph 5812113Sralph if ((i = pgetent(line, printer)) < 0) 5912113Sralph fatal("cannot open printer description file"); 6012113Sralph else if (i == 0) 6112113Sralph fatal("unknown printer"); 6212113Sralph if ((LP = pgetstr("lp", &bp)) == NULL) 6312113Sralph LP = DEFDEVLP; 6412113Sralph if ((RP = pgetstr("rp", &bp)) == NULL) 6512434Sralph RP = DEFLP; 6612113Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 6712113Sralph SD = DEFSPOOL; 6812113Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 6912113Sralph LO = DEFLOCK; 7012113Sralph if ((ST = pgetstr("st", &bp)) == NULL) 7112113Sralph ST = DEFSTAT; 7212113Sralph RM = pgetstr("rm", &bp); 7312113Sralph 7412113Sralph /* 7512113Sralph * If there is no local printer, then print the queue on 7612113Sralph * the remote machine and then what's in the queue here. 7712113Sralph * Note that a file in transit may not show up in either queue. 7812113Sralph */ 7912113Sralph if (*LP == '\0') { 8012113Sralph register char *cp; 8112113Sralph char c; 8212113Sralph 8312113Sralph sendtorem++; 8412113Sralph (void) sprintf(line, "%c%s", format + '\3', RP); 8512113Sralph cp = line; 8612113Sralph for (i = 0; i < requests; i++) { 8712113Sralph cp += strlen(cp); 8812113Sralph (void) sprintf(cp, " %d", requ[i]); 8912113Sralph } 9012113Sralph for (i = 0; i < users; i++) { 9112113Sralph cp += strlen(cp); 9212113Sralph *cp++ = ' '; 9312113Sralph strcpy(cp, user[i]); 9412113Sralph } 9512113Sralph strcat(line, "\n"); 9612531Sralph fd = getport(RM); 9712113Sralph if (fd < 0) { 9812113Sralph if (from != host) 9912113Sralph printf("%s: ", host); 10012113Sralph printf("connection to %s is down\n", RM); 10112113Sralph } else { 10212113Sralph i = strlen(line); 10312113Sralph if (write(fd, line, i) != i) 10412113Sralph fatal("Lost connection"); 10512113Sralph while ((i = read(fd, line, sizeof(line))) > 0) 10612113Sralph (void) fwrite(line, 1, i, stdout); 10712113Sralph (void) close(fd); 10812113Sralph } 10912113Sralph } 11012113Sralph /* 11112113Sralph * Find all the control files in the spooling directory 11212113Sralph */ 11312113Sralph if (chdir(SD) < 0) 11412113Sralph fatal("cannot chdir to spooling directory"); 11512113Sralph if ((nitems = getq(&queue)) < 0) 11612113Sralph fatal("cannot examine spooling area\n"); 11716205Sralph if (stat(LO, &statb) >= 0) { 11816205Sralph if ((statb.st_mode & 0110) && sendtorem) 11916205Sralph printf("\n"); 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 } 13912740Sralph if (nitems == 0) { 14012740Sralph if (!sendtorem) 14112740Sralph printf("no entries\n"); 14212113Sralph return(0); 14312113Sralph } 14412113Sralph fp = fopen(LO, "r"); 14513441Sralph if (fp == NULL) 14613441Sralph warn(); 14713441Sralph else { 14813441Sralph register char *cp; 14912113Sralph 15013441Sralph /* get daemon pid */ 15113441Sralph cp = current; 15212113Sralph while ((*cp = getc(fp)) != EOF && *cp != '\n') 15312113Sralph cp++; 15412113Sralph *cp = '\0'; 15513441Sralph i = atoi(current); 15615908Sralph if (i <= 0 || kill(i, 0) < 0) 15713441Sralph warn(); 15813441Sralph else { 15913441Sralph /* read current file name */ 16013441Sralph cp = current; 16113441Sralph while ((*cp = getc(fp)) != EOF && *cp != '\n') 16213441Sralph cp++; 16313441Sralph *cp = '\0'; 16413441Sralph /* 16513441Sralph * Print the status file. 16613441Sralph */ 16713441Sralph if (sendtorem) 16813441Sralph printf("\n%s: ", host); 16913441Sralph fd = open(ST, O_RDONLY); 17013441Sralph if (fd >= 0) { 17113441Sralph (void) flock(fd, LOCK_SH); 17213441Sralph while ((i = read(fd, line, sizeof(line))) > 0) 17313441Sralph (void) fwrite(line, 1, i, stdout); 17413441Sralph (void) close(fd); /* unlocks as well */ 17513441Sralph } else 17613441Sralph putchar('\n'); 17713441Sralph } 17813441Sralph (void) fclose(fp); 17912113Sralph } 18012113Sralph /* 18112113Sralph * Now, examine the control files and print out the jobs to 18212113Sralph * be done for each user. 18312113Sralph */ 18412113Sralph if (!lflag) 18512113Sralph header(); 18612113Sralph for (i = 0; i < nitems; i++) { 18712113Sralph q = queue[i]; 18812113Sralph inform(q->q_name); 18912113Sralph free(q); 19012113Sralph } 19112113Sralph free(queue); 19212113Sralph return(nitems-garbage); 19312113Sralph } 19412113Sralph 19512113Sralph /* 19613441Sralph * Print a warning message if there is no daemon present. 19713441Sralph */ 19813441Sralph warn() 19913441Sralph { 20013441Sralph if (sendtorem) 20113441Sralph printf("\n%s: ", host); 20216205Sralph printf("Warning: no daemon present\n"); 20313441Sralph current[0] = '\0'; 20413441Sralph } 20513441Sralph 20613441Sralph /* 20712113Sralph * Print the header for the short listing format 20812113Sralph */ 20912113Sralph header() 21012113Sralph { 21112113Sralph printf(head0); 21212113Sralph col = strlen(head0)+1; 21312113Sralph blankfill(SIZCOL); 21412113Sralph printf(head1); 21512113Sralph } 21612113Sralph 21712113Sralph inform(cf) 21812113Sralph char *cf; 21912113Sralph { 22012113Sralph register int j, k; 22112113Sralph register char *cp; 22212113Sralph FILE *cfp; 22312113Sralph 22412113Sralph /* 22512113Sralph * There's a chance the control file has gone away 22612113Sralph * in the meantime; if this is the case just keep going 22712113Sralph */ 22812113Sralph if ((cfp = fopen(cf, "r")) == NULL) 22912113Sralph return; 23012113Sralph 23112113Sralph if (rank < 0) 23212113Sralph rank = 0; 23312113Sralph if (sendtorem || garbage || strcmp(cf, current)) 23412113Sralph rank++; 23512113Sralph j = 0; 23612113Sralph while (getline(cfp)) { 23712113Sralph switch (line[0]) { 23812113Sralph case 'P': /* Was this file specified in the user's list? */ 23912113Sralph if (!inlist(line+1, cf)) { 24012113Sralph fclose(cfp); 24112113Sralph return; 24212113Sralph } 24312113Sralph if (lflag) { 24412113Sralph printf("\n%s: ", line+1); 24512113Sralph col = strlen(line+1) + 2; 24612113Sralph prank(rank); 24712113Sralph blankfill(JOBCOL); 24812113Sralph printf(" [job %s]\n", cf+3); 24912113Sralph } else { 25012113Sralph col = 0; 25112113Sralph prank(rank); 25212113Sralph blankfill(OWNCOL); 25312113Sralph printf("%-10s %-3d ", line+1, atoi(cf+3)); 25412113Sralph col += 16; 25512113Sralph first = 1; 25612113Sralph } 25712113Sralph continue; 25812113Sralph default: /* some format specifer and file name? */ 25912113Sralph if (line[0] < 'a' || line[0] > 'z') 26012113Sralph continue; 26112113Sralph if (j == 0 || strcmp(file, line+1) != 0) 26212113Sralph strcpy(file, line+1); 26312113Sralph j++; 26412113Sralph continue; 26512113Sralph case 'N': 26612113Sralph show(line+1, file, j); 26712113Sralph file[0] = '\0'; 26812113Sralph j = 0; 26912113Sralph } 27012113Sralph } 27112113Sralph fclose(cfp); 27212113Sralph if (!lflag) { 27312113Sralph blankfill(SIZCOL); 27412113Sralph printf("%D bytes\n", totsize); 27512113Sralph totsize = 0; 27612113Sralph } 27712113Sralph } 27812113Sralph 27912113Sralph inlist(name, file) 28012113Sralph char *name, *file; 28112113Sralph { 28212113Sralph register int *r, n; 28312113Sralph register char **u, *cp; 28412113Sralph 28512113Sralph if (users == 0 && requests == 0) 28612113Sralph return(1); 28712113Sralph /* 28812113Sralph * Check to see if it's in the user list 28912113Sralph */ 29012113Sralph for (u = user; u < &user[users]; u++) 29112113Sralph if (!strcmp(*u, name)) 29212113Sralph return(1); 29312113Sralph /* 29412113Sralph * Check the request list 29512113Sralph */ 29612113Sralph for (n = 0, cp = file+3; isdigit(*cp); ) 29712113Sralph n = n * 10 + (*cp++ - '0'); 29812113Sralph for (r = requ; r < &requ[requests]; r++) 29912113Sralph if (*r == n && !strcmp(cp, from)) 30012113Sralph return(1); 30112113Sralph return(0); 30212113Sralph } 30312113Sralph 30412113Sralph show(nfile, file, copies) 30512113Sralph register char *nfile, *file; 30612113Sralph { 30712113Sralph if (strcmp(nfile, " ") == 0) 30812113Sralph nfile = "(standard input)"; 30912113Sralph if (lflag) 31012113Sralph ldump(nfile, file, copies); 31112113Sralph else 31212113Sralph dump(nfile, file, copies); 31312113Sralph } 31412113Sralph 31512113Sralph /* 31612113Sralph * Fill the line with blanks to the specified column 31712113Sralph */ 31812113Sralph blankfill(n) 31912113Sralph register int n; 32012113Sralph { 32112113Sralph while (col++ < n) 32212113Sralph putchar(' '); 32312113Sralph } 32412113Sralph 32512113Sralph /* 32612113Sralph * Give the abbreviated dump of the file names 32712113Sralph */ 32812113Sralph dump(nfile, file, copies) 32912113Sralph char *nfile, *file; 33012113Sralph { 33112113Sralph register short n, fill; 33212113Sralph struct stat lbuf; 33312113Sralph 33412113Sralph /* 33512113Sralph * Print as many files as will fit 33612113Sralph * (leaving room for the total size) 33712113Sralph */ 33812113Sralph fill = first ? 0 : 2; /* fill space for ``, '' */ 33912113Sralph if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 34012113Sralph if (col < SIZCOL) { 34112113Sralph printf(" ..."), col += 4; 34212113Sralph blankfill(SIZCOL); 34312113Sralph } 34412113Sralph } else { 34512113Sralph if (first) 34612113Sralph first = 0; 34712113Sralph else 34812113Sralph printf(", "); 34912113Sralph printf("%s", nfile); 35012113Sralph col += n+fill; 35112113Sralph } 35212113Sralph if (*file && !stat(file, &lbuf)) 35312113Sralph totsize += copies * lbuf.st_size; 35412113Sralph } 35512113Sralph 35612113Sralph /* 35712113Sralph * Print the long info about the file 35812113Sralph */ 35912113Sralph ldump(nfile, file, copies) 36012113Sralph char *nfile, *file; 36112113Sralph { 36212113Sralph struct stat lbuf; 36312113Sralph 36412113Sralph putchar('\t'); 36512113Sralph if (copies > 1) 36612113Sralph printf("%-2d copies of %-19s", copies, nfile); 36712113Sralph else 36812113Sralph printf("%-32s", nfile); 36912113Sralph if (*file && !stat(file, &lbuf)) 37012113Sralph printf(" %D bytes", lbuf.st_size); 37112113Sralph else 37212113Sralph printf(" ??? bytes"); 37312113Sralph putchar('\n'); 37412113Sralph } 37512113Sralph 37612113Sralph /* 37712113Sralph * Print the job's rank in the queue, 37812113Sralph * update col for screen management 37912113Sralph */ 38012113Sralph prank(n) 38112113Sralph { 38212113Sralph char line[100]; 38312113Sralph static char *r[] = { 38412113Sralph "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 38512113Sralph }; 38612113Sralph 38712113Sralph if (n == 0) { 38812113Sralph printf("active"); 38912113Sralph col += 6; 39012113Sralph return; 39112113Sralph } 39212113Sralph if ((n/10) == 1) 39312113Sralph (void) sprintf(line, "%dth", n); 39412113Sralph else 39512113Sralph (void) sprintf(line, "%d%s", n, r[n%10]); 39612113Sralph col += strlen(line); 39712113Sralph printf("%s", line); 39812113Sralph } 399