113952Ssam #ifndef lint 2*15908Sralph static char sccsid[] = "@(#)displayq.c 4.10 (Berkeley) 01/30/84"; 313952Ssam #endif 413952Ssam 512113Sralph /* 612113Sralph * Routines to display the state of the queue. 712113Sralph */ 812113Sralph 912113Sralph #include "lp.h" 1012113Sralph 1113170Sralph #define JOBCOL 40 /* column for job # in -l format */ 1213170Sralph #define OWNCOL 7 /* start of Owner column in normal */ 1313170Sralph #define SIZCOL 62 /* start of Size column in normal */ 1412113Sralph 1512113Sralph /* 1612113Sralph * Stuff for handling job specifications 1712113Sralph */ 1812113Sralph extern char *user[]; /* users to process */ 1912113Sralph extern int users; /* # of users in user array */ 2012113Sralph extern int requ[]; /* job number of spool entries */ 2112113Sralph extern int requests; /* # of spool requests */ 2212113Sralph 2312878Sralph static int lflag; /* long output option */ 2412878Sralph static char current[40]; /* current file being printed */ 2512878Sralph static int garbage; /* # of garbage cf files */ 2612878Sralph static int rank; /* order to be printed (-1=none, 0=active) */ 2712878Sralph static long totsize; /* total print job size in bytes */ 2812878Sralph static int first; /* first file in ``files'' column? */ 2912878Sralph static int col; /* column on screen */ 3012878Sralph static int sendtorem; /* are we sending to a remote? */ 3112878Sralph static char file[132]; /* print file name */ 3212113Sralph 3312878Sralph static char *head0 = "Rank Owner Job Files"; 3412878Sralph static char *head1 = "Total Size\n"; 3512113Sralph 3612113Sralph /* 3712113Sralph * Display the current state of the queue. Format = 1 if long format. 3812113Sralph */ 3912113Sralph displayq(format) 4012113Sralph int format; 4112113Sralph { 4212113Sralph register struct queue *q; 4312113Sralph register int i, nitems, fd; 4412113Sralph struct queue **queue; 4512113Sralph struct stat statb; 4612113Sralph FILE *fp; 4712113Sralph 4812113Sralph lflag = format; 4912113Sralph totsize = 0; 5012113Sralph rank = -1; 5112113Sralph 5212113Sralph if ((i = pgetent(line, printer)) < 0) 5312113Sralph fatal("cannot open printer description file"); 5412113Sralph else if (i == 0) 5512113Sralph fatal("unknown printer"); 5612113Sralph if ((LP = pgetstr("lp", &bp)) == NULL) 5712113Sralph LP = DEFDEVLP; 5812113Sralph if ((RP = pgetstr("rp", &bp)) == NULL) 5912434Sralph RP = DEFLP; 6012113Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 6112113Sralph SD = DEFSPOOL; 6212113Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 6312113Sralph LO = DEFLOCK; 6412113Sralph if ((ST = pgetstr("st", &bp)) == NULL) 6512113Sralph ST = DEFSTAT; 6612113Sralph RM = pgetstr("rm", &bp); 6712113Sralph 6812113Sralph /* 6912113Sralph * If there is no local printer, then print the queue on 7012113Sralph * the remote machine and then what's in the queue here. 7112113Sralph * Note that a file in transit may not show up in either queue. 7212113Sralph */ 7312113Sralph if (*LP == '\0') { 7412113Sralph register char *cp; 7512113Sralph char c; 7612113Sralph 7712113Sralph sendtorem++; 7812113Sralph (void) sprintf(line, "%c%s", format + '\3', RP); 7912113Sralph cp = line; 8012113Sralph for (i = 0; i < requests; i++) { 8112113Sralph cp += strlen(cp); 8212113Sralph (void) sprintf(cp, " %d", requ[i]); 8312113Sralph } 8412113Sralph for (i = 0; i < users; i++) { 8512113Sralph cp += strlen(cp); 8612113Sralph *cp++ = ' '; 8712113Sralph strcpy(cp, user[i]); 8812113Sralph } 8912113Sralph strcat(line, "\n"); 9012531Sralph fd = getport(RM); 9112113Sralph if (fd < 0) { 9212113Sralph if (from != host) 9312113Sralph printf("%s: ", host); 9412113Sralph printf("connection to %s is down\n", RM); 9512113Sralph } else { 9612113Sralph i = strlen(line); 9712113Sralph if (write(fd, line, i) != i) 9812113Sralph fatal("Lost connection"); 9912113Sralph while ((i = read(fd, line, sizeof(line))) > 0) 10012113Sralph (void) fwrite(line, 1, i, stdout); 10112113Sralph (void) close(fd); 10212113Sralph } 10312113Sralph } 10412113Sralph /* 10512113Sralph * Find all the control files in the spooling directory 10612113Sralph */ 10712113Sralph if (chdir(SD) < 0) 10812113Sralph fatal("cannot chdir to spooling directory"); 10912113Sralph if ((nitems = getq(&queue)) < 0) 11012113Sralph fatal("cannot examine spooling area\n"); 11112740Sralph if (stat(LO, &statb) >= 0 && (statb.st_mode & 010)) { 11212113Sralph if (sendtorem) 11312113Sralph printf("\n%s: ", host); 11412740Sralph printf("Warning: %s queue is turned off\n", printer); 11512740Sralph } 11612740Sralph if (nitems == 0) { 11712740Sralph if (!sendtorem) 11812740Sralph printf("no entries\n"); 11912113Sralph return(0); 12012113Sralph } 12112113Sralph fp = fopen(LO, "r"); 12213441Sralph if (fp == NULL) 12313441Sralph warn(); 12413441Sralph else { 12513441Sralph register char *cp; 12612113Sralph 12713441Sralph /* get daemon pid */ 12813441Sralph cp = current; 12912113Sralph while ((*cp = getc(fp)) != EOF && *cp != '\n') 13012113Sralph cp++; 13112113Sralph *cp = '\0'; 13213441Sralph i = atoi(current); 133*15908Sralph if (i <= 0 || kill(i, 0) < 0) 13413441Sralph warn(); 13513441Sralph else { 13613441Sralph /* read current file name */ 13713441Sralph cp = current; 13813441Sralph while ((*cp = getc(fp)) != EOF && *cp != '\n') 13913441Sralph cp++; 14013441Sralph *cp = '\0'; 14113441Sralph /* 14213441Sralph * Print the status file. 14313441Sralph */ 14413441Sralph if (sendtorem) 14513441Sralph printf("\n%s: ", host); 14613441Sralph fd = open(ST, O_RDONLY); 14713441Sralph if (fd >= 0) { 14813441Sralph (void) flock(fd, LOCK_SH); 14913441Sralph while ((i = read(fd, line, sizeof(line))) > 0) 15013441Sralph (void) fwrite(line, 1, i, stdout); 15113441Sralph (void) close(fd); /* unlocks as well */ 15213441Sralph } else 15313441Sralph putchar('\n'); 15413441Sralph } 15513441Sralph (void) fclose(fp); 15612113Sralph } 15712113Sralph /* 15812113Sralph * Now, examine the control files and print out the jobs to 15912113Sralph * be done for each user. 16012113Sralph */ 16112113Sralph if (!lflag) 16212113Sralph header(); 16312113Sralph for (i = 0; i < nitems; i++) { 16412113Sralph q = queue[i]; 16512113Sralph inform(q->q_name); 16612113Sralph free(q); 16712113Sralph } 16812113Sralph free(queue); 16912113Sralph return(nitems-garbage); 17012113Sralph } 17112113Sralph 17212113Sralph /* 17313441Sralph * Print a warning message if there is no daemon present. 17413441Sralph */ 17513441Sralph warn() 17613441Sralph { 17713441Sralph struct stat statb; 178*15908Sralph int i, fd; 17913441Sralph 18013441Sralph if (sendtorem) 18113441Sralph printf("\n%s: ", host); 182*15908Sralph if (stat(LO, &statb) >= 0 && (statb.st_mode & 0100)) { 183*15908Sralph printf("Warning: %s is down: ", printer); 184*15908Sralph fd = open(ST, O_RDONLY); 185*15908Sralph if (fd >= 0) { 186*15908Sralph (void) flock(fd, LOCK_SH); 187*15908Sralph while ((i = read(fd, line, sizeof(line))) > 0) 188*15908Sralph (void) fwrite(line, 1, i, stdout); 189*15908Sralph (void) close(fd); /* unlocks as well */ 190*15908Sralph } else 191*15908Sralph putchar('\n'); 192*15908Sralph } else 19313441Sralph printf("Warning: no daemon present\n"); 19413441Sralph current[0] = '\0'; 19513441Sralph } 19613441Sralph 19713441Sralph /* 19812113Sralph * Print the header for the short listing format 19912113Sralph */ 20012878Sralph static 20112113Sralph header() 20212113Sralph { 20312113Sralph printf(head0); 20412113Sralph col = strlen(head0)+1; 20512113Sralph blankfill(SIZCOL); 20612113Sralph printf(head1); 20712113Sralph } 20812113Sralph 20912878Sralph static 21012113Sralph inform(cf) 21112113Sralph char *cf; 21212113Sralph { 21312113Sralph register int j, k; 21412113Sralph register char *cp; 21512113Sralph FILE *cfp; 21612113Sralph 21712113Sralph /* 21812113Sralph * There's a chance the control file has gone away 21912113Sralph * in the meantime; if this is the case just keep going 22012113Sralph */ 22112113Sralph if ((cfp = fopen(cf, "r")) == NULL) 22212113Sralph return; 22312113Sralph 22412113Sralph if (rank < 0) 22512113Sralph rank = 0; 22612113Sralph if (sendtorem || garbage || strcmp(cf, current)) 22712113Sralph rank++; 22812113Sralph j = 0; 22912113Sralph while (getline(cfp)) { 23012113Sralph switch (line[0]) { 23112113Sralph case 'P': /* Was this file specified in the user's list? */ 23212113Sralph if (!inlist(line+1, cf)) { 23312113Sralph fclose(cfp); 23412113Sralph return; 23512113Sralph } 23612113Sralph if (lflag) { 23712113Sralph printf("\n%s: ", line+1); 23812113Sralph col = strlen(line+1) + 2; 23912113Sralph prank(rank); 24012113Sralph blankfill(JOBCOL); 24112113Sralph printf(" [job %s]\n", cf+3); 24212113Sralph } else { 24312113Sralph col = 0; 24412113Sralph prank(rank); 24512113Sralph blankfill(OWNCOL); 24612113Sralph printf("%-10s %-3d ", line+1, atoi(cf+3)); 24712113Sralph col += 16; 24812113Sralph first = 1; 24912113Sralph } 25012113Sralph continue; 25112113Sralph default: /* some format specifer and file name? */ 25212113Sralph if (line[0] < 'a' || line[0] > 'z') 25312113Sralph continue; 25412113Sralph if (j == 0 || strcmp(file, line+1) != 0) 25512113Sralph strcpy(file, line+1); 25612113Sralph j++; 25712113Sralph continue; 25812113Sralph case 'N': 25912113Sralph show(line+1, file, j); 26012113Sralph file[0] = '\0'; 26112113Sralph j = 0; 26212113Sralph } 26312113Sralph } 26412113Sralph fclose(cfp); 26512113Sralph if (!lflag) { 26612113Sralph blankfill(SIZCOL); 26712113Sralph printf("%D bytes\n", totsize); 26812113Sralph totsize = 0; 26912113Sralph } 27012113Sralph } 27112113Sralph 27212878Sralph static 27312113Sralph inlist(name, file) 27412113Sralph char *name, *file; 27512113Sralph { 27612113Sralph register int *r, n; 27712113Sralph register char **u, *cp; 27812113Sralph 27912113Sralph if (users == 0 && requests == 0) 28012113Sralph return(1); 28112113Sralph /* 28212113Sralph * Check to see if it's in the user list 28312113Sralph */ 28412113Sralph for (u = user; u < &user[users]; u++) 28512113Sralph if (!strcmp(*u, name)) 28612113Sralph return(1); 28712113Sralph /* 28812113Sralph * Check the request list 28912113Sralph */ 29012113Sralph for (n = 0, cp = file+3; isdigit(*cp); ) 29112113Sralph n = n * 10 + (*cp++ - '0'); 29212113Sralph for (r = requ; r < &requ[requests]; r++) 29312113Sralph if (*r == n && !strcmp(cp, from)) 29412113Sralph return(1); 29512113Sralph return(0); 29612113Sralph } 29712113Sralph 29812878Sralph static 29912113Sralph show(nfile, file, copies) 30012113Sralph register char *nfile, *file; 30112113Sralph { 30212113Sralph if (strcmp(nfile, " ") == 0) 30312113Sralph nfile = "(standard input)"; 30412113Sralph if (lflag) 30512113Sralph ldump(nfile, file, copies); 30612113Sralph else 30712113Sralph dump(nfile, file, copies); 30812113Sralph } 30912113Sralph 31012113Sralph /* 31112113Sralph * Fill the line with blanks to the specified column 31212113Sralph */ 31312878Sralph static 31412113Sralph blankfill(n) 31512113Sralph register int n; 31612113Sralph { 31712113Sralph while (col++ < n) 31812113Sralph putchar(' '); 31912113Sralph } 32012113Sralph 32112113Sralph /* 32212113Sralph * Give the abbreviated dump of the file names 32312113Sralph */ 32412878Sralph static 32512113Sralph dump(nfile, file, copies) 32612113Sralph char *nfile, *file; 32712113Sralph { 32812113Sralph register short n, fill; 32912113Sralph struct stat lbuf; 33012113Sralph 33112113Sralph /* 33212113Sralph * Print as many files as will fit 33312113Sralph * (leaving room for the total size) 33412113Sralph */ 33512113Sralph fill = first ? 0 : 2; /* fill space for ``, '' */ 33612113Sralph if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 33712113Sralph if (col < SIZCOL) { 33812113Sralph printf(" ..."), col += 4; 33912113Sralph blankfill(SIZCOL); 34012113Sralph } 34112113Sralph } else { 34212113Sralph if (first) 34312113Sralph first = 0; 34412113Sralph else 34512113Sralph printf(", "); 34612113Sralph printf("%s", nfile); 34712113Sralph col += n+fill; 34812113Sralph } 34912113Sralph if (*file && !stat(file, &lbuf)) 35012113Sralph totsize += copies * lbuf.st_size; 35112113Sralph } 35212113Sralph 35312113Sralph /* 35412113Sralph * Print the long info about the file 35512113Sralph */ 35612878Sralph static 35712113Sralph ldump(nfile, file, copies) 35812113Sralph char *nfile, *file; 35912113Sralph { 36012113Sralph struct stat lbuf; 36112113Sralph 36212113Sralph putchar('\t'); 36312113Sralph if (copies > 1) 36412113Sralph printf("%-2d copies of %-19s", copies, nfile); 36512113Sralph else 36612113Sralph printf("%-32s", nfile); 36712113Sralph if (*file && !stat(file, &lbuf)) 36812113Sralph printf(" %D bytes", lbuf.st_size); 36912113Sralph else 37012113Sralph printf(" ??? bytes"); 37112113Sralph putchar('\n'); 37212113Sralph } 37312113Sralph 37412113Sralph /* 37512113Sralph * Print the job's rank in the queue, 37612113Sralph * update col for screen management 37712113Sralph */ 37812878Sralph static 37912113Sralph prank(n) 38012113Sralph { 38112113Sralph char line[100]; 38212113Sralph static char *r[] = { 38312113Sralph "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 38412113Sralph }; 38512113Sralph 38612113Sralph if (n == 0) { 38712113Sralph printf("active"); 38812113Sralph col += 6; 38912113Sralph return; 39012113Sralph } 39112113Sralph if ((n/10) == 1) 39212113Sralph (void) sprintf(line, "%dth", n); 39312113Sralph else 39412113Sralph (void) sprintf(line, "%d%s", n, r[n%10]); 39512113Sralph col += strlen(line); 39612113Sralph printf("%s", line); 39712113Sralph } 398