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 8*25467Stef 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; 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 /* 75*25467Stef * Figure out whether the local machine is the same as the remote 76*25467Stef * machine entry (if it exists). If not, then ignore the local 77*25467Stef * queue information. 78*25467Stef */ 79*25467Stef if (RM != (char *) NULL) { 80*25467Stef char name[256]; 81*25467Stef struct hostent *hp; 82*25467Stef 83*25467Stef /* get the standard network name of the local host */ 84*25467Stef gethostname(name, sizeof(name)); 85*25467Stef name[sizeof(name)-1] = '\0'; 86*25467Stef hp = gethostbyname(name); 87*25467Stef if (hp == (struct hostent *) NULL) { 88*25467Stef printf("unable to get network name for local machine %s\n", 89*25467Stef name); 90*25467Stef goto localcheck_done; 91*25467Stef } else strcpy(name, hp->h_name); 92*25467Stef 93*25467Stef /* get the network standard name of RM */ 94*25467Stef hp = gethostbyname(RM); 95*25467Stef if (hp == (struct hostent *) NULL) { 96*25467Stef printf("unable to get hostname for remote machine %s\n", 97*25467Stef RM); 98*25467Stef goto localcheck_done; 99*25467Stef } 100*25467Stef 101*25467Stef /* if printer is not on local machine, ignore LP */ 102*25467Stef if (strcmp(name, hp->h_name) != 0) *LP = '\0'; 103*25467Stef } 104*25467Stef localcheck_done: 105*25467Stef 106*25467Stef /* 10712113Sralph * If there is no local printer, then print the queue on 10812113Sralph * the remote machine and then what's in the queue here. 10912113Sralph * Note that a file in transit may not show up in either queue. 11012113Sralph */ 11112113Sralph if (*LP == '\0') { 11212113Sralph register char *cp; 11312113Sralph char c; 11412113Sralph 11512113Sralph sendtorem++; 11612113Sralph (void) sprintf(line, "%c%s", format + '\3', RP); 11712113Sralph cp = line; 11812113Sralph for (i = 0; i < requests; i++) { 11912113Sralph cp += strlen(cp); 12012113Sralph (void) sprintf(cp, " %d", requ[i]); 12112113Sralph } 12212113Sralph for (i = 0; i < users; i++) { 12312113Sralph cp += strlen(cp); 12412113Sralph *cp++ = ' '; 12512113Sralph strcpy(cp, user[i]); 12612113Sralph } 12712113Sralph strcat(line, "\n"); 12812531Sralph fd = getport(RM); 12912113Sralph if (fd < 0) { 13012113Sralph if (from != host) 13112113Sralph printf("%s: ", host); 13212113Sralph printf("connection to %s is down\n", RM); 13312113Sralph } else { 13412113Sralph i = strlen(line); 13512113Sralph if (write(fd, line, i) != i) 13612113Sralph fatal("Lost connection"); 13712113Sralph while ((i = read(fd, line, sizeof(line))) > 0) 13812113Sralph (void) fwrite(line, 1, i, stdout); 13912113Sralph (void) close(fd); 14012113Sralph } 14112113Sralph } 14212113Sralph /* 14312113Sralph * Find all the control files in the spooling directory 14412113Sralph */ 14512113Sralph if (chdir(SD) < 0) 14612113Sralph fatal("cannot chdir to spooling directory"); 14712113Sralph if ((nitems = getq(&queue)) < 0) 14812113Sralph fatal("cannot examine spooling area\n"); 14916205Sralph if (stat(LO, &statb) >= 0) { 15016205Sralph if ((statb.st_mode & 0110) && sendtorem) 15116205Sralph printf("\n"); 15216205Sralph if (statb.st_mode & 0100) { 15316205Sralph if (sendtorem) 15416205Sralph printf("%s: ", host); 15516205Sralph printf("Warning: %s is down: ", printer); 15616205Sralph fd = open(ST, O_RDONLY); 15716205Sralph if (fd >= 0) { 15816205Sralph (void) flock(fd, LOCK_SH); 15916205Sralph while ((i = read(fd, line, sizeof(line))) > 0) 16016205Sralph (void) fwrite(line, 1, i, stdout); 16116205Sralph (void) close(fd); /* unlocks as well */ 16216205Sralph } else 16316205Sralph putchar('\n'); 16416205Sralph } 16516205Sralph if (statb.st_mode & 010) { 16616205Sralph if (sendtorem) 16716205Sralph printf("%s: ", host); 16816205Sralph printf("Warning: %s queue is turned off\n", printer); 16916205Sralph } 17012740Sralph } 17112740Sralph if (nitems == 0) { 17212740Sralph if (!sendtorem) 17312740Sralph printf("no entries\n"); 17412113Sralph return(0); 17512113Sralph } 17612113Sralph fp = fopen(LO, "r"); 17713441Sralph if (fp == NULL) 17813441Sralph warn(); 17913441Sralph else { 18013441Sralph register char *cp; 18112113Sralph 18213441Sralph /* get daemon pid */ 18313441Sralph cp = current; 18412113Sralph while ((*cp = getc(fp)) != EOF && *cp != '\n') 18512113Sralph cp++; 18612113Sralph *cp = '\0'; 18713441Sralph i = atoi(current); 18815908Sralph if (i <= 0 || kill(i, 0) < 0) 18913441Sralph warn(); 19013441Sralph else { 19113441Sralph /* read current file name */ 19213441Sralph cp = current; 19313441Sralph while ((*cp = getc(fp)) != EOF && *cp != '\n') 19413441Sralph cp++; 19513441Sralph *cp = '\0'; 19613441Sralph /* 19713441Sralph * Print the status file. 19813441Sralph */ 19913441Sralph if (sendtorem) 20013441Sralph printf("\n%s: ", host); 20113441Sralph fd = open(ST, O_RDONLY); 20213441Sralph if (fd >= 0) { 20313441Sralph (void) flock(fd, LOCK_SH); 20413441Sralph while ((i = read(fd, line, sizeof(line))) > 0) 20513441Sralph (void) fwrite(line, 1, i, stdout); 20613441Sralph (void) close(fd); /* unlocks as well */ 20713441Sralph } else 20813441Sralph putchar('\n'); 20913441Sralph } 21013441Sralph (void) fclose(fp); 21112113Sralph } 21212113Sralph /* 21312113Sralph * Now, examine the control files and print out the jobs to 21412113Sralph * be done for each user. 21512113Sralph */ 21612113Sralph if (!lflag) 21712113Sralph header(); 21812113Sralph for (i = 0; i < nitems; i++) { 21912113Sralph q = queue[i]; 22012113Sralph inform(q->q_name); 22112113Sralph free(q); 22212113Sralph } 22312113Sralph free(queue); 22412113Sralph return(nitems-garbage); 22512113Sralph } 22612113Sralph 22712113Sralph /* 22813441Sralph * Print a warning message if there is no daemon present. 22913441Sralph */ 23013441Sralph warn() 23113441Sralph { 23213441Sralph if (sendtorem) 23313441Sralph printf("\n%s: ", host); 23416205Sralph printf("Warning: no daemon present\n"); 23513441Sralph current[0] = '\0'; 23613441Sralph } 23713441Sralph 23813441Sralph /* 23912113Sralph * Print the header for the short listing format 24012113Sralph */ 24112113Sralph header() 24212113Sralph { 24312113Sralph printf(head0); 24412113Sralph col = strlen(head0)+1; 24512113Sralph blankfill(SIZCOL); 24612113Sralph printf(head1); 24712113Sralph } 24812113Sralph 24912113Sralph inform(cf) 25012113Sralph char *cf; 25112113Sralph { 25212113Sralph register int j, k; 25312113Sralph register char *cp; 25412113Sralph FILE *cfp; 25512113Sralph 25612113Sralph /* 25712113Sralph * There's a chance the control file has gone away 25812113Sralph * in the meantime; if this is the case just keep going 25912113Sralph */ 26012113Sralph if ((cfp = fopen(cf, "r")) == NULL) 26112113Sralph return; 26212113Sralph 26312113Sralph if (rank < 0) 26412113Sralph rank = 0; 26512113Sralph if (sendtorem || garbage || strcmp(cf, current)) 26612113Sralph rank++; 26712113Sralph j = 0; 26812113Sralph while (getline(cfp)) { 26912113Sralph switch (line[0]) { 27012113Sralph case 'P': /* Was this file specified in the user's list? */ 27112113Sralph if (!inlist(line+1, cf)) { 27212113Sralph fclose(cfp); 27312113Sralph return; 27412113Sralph } 27512113Sralph if (lflag) { 27612113Sralph printf("\n%s: ", line+1); 27712113Sralph col = strlen(line+1) + 2; 27812113Sralph prank(rank); 27912113Sralph blankfill(JOBCOL); 28012113Sralph printf(" [job %s]\n", cf+3); 28112113Sralph } else { 28212113Sralph col = 0; 28312113Sralph prank(rank); 28412113Sralph blankfill(OWNCOL); 28512113Sralph printf("%-10s %-3d ", line+1, atoi(cf+3)); 28612113Sralph col += 16; 28712113Sralph first = 1; 28812113Sralph } 28912113Sralph continue; 29012113Sralph default: /* some format specifer and file name? */ 29112113Sralph if (line[0] < 'a' || line[0] > 'z') 29212113Sralph continue; 29312113Sralph if (j == 0 || strcmp(file, line+1) != 0) 29412113Sralph strcpy(file, line+1); 29512113Sralph j++; 29612113Sralph continue; 29712113Sralph case 'N': 29812113Sralph show(line+1, file, j); 29912113Sralph file[0] = '\0'; 30012113Sralph j = 0; 30112113Sralph } 30212113Sralph } 30312113Sralph fclose(cfp); 30412113Sralph if (!lflag) { 30512113Sralph blankfill(SIZCOL); 30612113Sralph printf("%D bytes\n", totsize); 30712113Sralph totsize = 0; 30812113Sralph } 30912113Sralph } 31012113Sralph 31112113Sralph inlist(name, file) 31212113Sralph char *name, *file; 31312113Sralph { 31412113Sralph register int *r, n; 31512113Sralph register char **u, *cp; 31612113Sralph 31712113Sralph if (users == 0 && requests == 0) 31812113Sralph return(1); 31912113Sralph /* 32012113Sralph * Check to see if it's in the user list 32112113Sralph */ 32212113Sralph for (u = user; u < &user[users]; u++) 32312113Sralph if (!strcmp(*u, name)) 32412113Sralph return(1); 32512113Sralph /* 32612113Sralph * Check the request list 32712113Sralph */ 32812113Sralph for (n = 0, cp = file+3; isdigit(*cp); ) 32912113Sralph n = n * 10 + (*cp++ - '0'); 33012113Sralph for (r = requ; r < &requ[requests]; r++) 33112113Sralph if (*r == n && !strcmp(cp, from)) 33212113Sralph return(1); 33312113Sralph return(0); 33412113Sralph } 33512113Sralph 33612113Sralph show(nfile, file, copies) 33712113Sralph register char *nfile, *file; 33812113Sralph { 33912113Sralph if (strcmp(nfile, " ") == 0) 34012113Sralph nfile = "(standard input)"; 34112113Sralph if (lflag) 34212113Sralph ldump(nfile, file, copies); 34312113Sralph else 34412113Sralph dump(nfile, file, copies); 34512113Sralph } 34612113Sralph 34712113Sralph /* 34812113Sralph * Fill the line with blanks to the specified column 34912113Sralph */ 35012113Sralph blankfill(n) 35112113Sralph register int n; 35212113Sralph { 35312113Sralph while (col++ < n) 35412113Sralph putchar(' '); 35512113Sralph } 35612113Sralph 35712113Sralph /* 35812113Sralph * Give the abbreviated dump of the file names 35912113Sralph */ 36012113Sralph dump(nfile, file, copies) 36112113Sralph char *nfile, *file; 36212113Sralph { 36312113Sralph register short n, fill; 36412113Sralph struct stat lbuf; 36512113Sralph 36612113Sralph /* 36712113Sralph * Print as many files as will fit 36812113Sralph * (leaving room for the total size) 36912113Sralph */ 37012113Sralph fill = first ? 0 : 2; /* fill space for ``, '' */ 37112113Sralph if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 37212113Sralph if (col < SIZCOL) { 37312113Sralph printf(" ..."), col += 4; 37412113Sralph blankfill(SIZCOL); 37512113Sralph } 37612113Sralph } else { 37712113Sralph if (first) 37812113Sralph first = 0; 37912113Sralph else 38012113Sralph printf(", "); 38112113Sralph printf("%s", nfile); 38212113Sralph col += n+fill; 38312113Sralph } 38412113Sralph if (*file && !stat(file, &lbuf)) 38512113Sralph totsize += copies * lbuf.st_size; 38612113Sralph } 38712113Sralph 38812113Sralph /* 38912113Sralph * Print the long info about the file 39012113Sralph */ 39112113Sralph ldump(nfile, file, copies) 39212113Sralph char *nfile, *file; 39312113Sralph { 39412113Sralph struct stat lbuf; 39512113Sralph 39612113Sralph putchar('\t'); 39712113Sralph if (copies > 1) 39812113Sralph printf("%-2d copies of %-19s", copies, nfile); 39912113Sralph else 40012113Sralph printf("%-32s", nfile); 40112113Sralph if (*file && !stat(file, &lbuf)) 40212113Sralph printf(" %D bytes", lbuf.st_size); 40312113Sralph else 40412113Sralph printf(" ??? bytes"); 40512113Sralph putchar('\n'); 40612113Sralph } 40712113Sralph 40812113Sralph /* 40912113Sralph * Print the job's rank in the queue, 41012113Sralph * update col for screen management 41112113Sralph */ 41212113Sralph prank(n) 41312113Sralph { 41412113Sralph char line[100]; 41512113Sralph static char *r[] = { 41612113Sralph "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 41712113Sralph }; 41812113Sralph 41912113Sralph if (n == 0) { 42012113Sralph printf("active"); 42112113Sralph col += 6; 42212113Sralph return; 42312113Sralph } 42412113Sralph if ((n/10) == 1) 42512113Sralph (void) sprintf(line, "%dth", n); 42612113Sralph else 42712113Sralph (void) sprintf(line, "%d%s", n, r[n%10]); 42812113Sralph col += strlen(line); 42912113Sralph printf("%s", line); 43012113Sralph } 431