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; 5030995Sbostic register char *cp; 5112113Sralph struct queue **queue; 5212113Sralph struct stat statb; 5312113Sralph FILE *fp; 5430995Sbostic 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; 9330995Sbostic } 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 */ 10430995Sbostic if (strcmp(name, hp->h_name)) { 10530995Sbostic *LP = '\0'; 10630995Sbostic ++sendtorem; 10730995Sbostic } 10825467Stef } 10925467Stef localcheck_done: 11025467Stef 11125467Stef /* 11230995Sbostic * 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 14030995Sbostic if (nitems) { 14130995Sbostic fp = fopen(LO, "r"); 14230995Sbostic if (fp == NULL) 14313441Sralph warn(); 14413441Sralph else { 14530995Sbostic register char *cp; 14630995Sbostic 14730995Sbostic /* get daemon pid */ 14813441Sralph cp = current; 14913441Sralph while ((*cp = getc(fp)) != EOF && *cp != '\n') 15013441Sralph cp++; 15113441Sralph *cp = '\0'; 15230995Sbostic i = atoi(current); 15330995Sbostic if (i <= 0 || kill(i, 0) < 0) 15430995Sbostic warn(); 15530995Sbostic else { 15630995Sbostic /* read current file name */ 15730995Sbostic cp = current; 15830995Sbostic while ((*cp = getc(fp)) != EOF && *cp != '\n') 15930995Sbostic cp++; 16030995Sbostic *cp = '\0'; 16130995Sbostic /* 16230995Sbostic * Print the status file. 16330995Sbostic */ 16430995Sbostic if (sendtorem) 16530995Sbostic printf("%s: ", host); 16630995Sbostic fd = open(ST, O_RDONLY); 16730995Sbostic if (fd >= 0) { 16830995Sbostic (void) flock(fd, LOCK_SH); 16930995Sbostic while ((i = read(fd, line, sizeof(line))) > 0) 17030995Sbostic (void) fwrite(line, 1, i, stdout); 17130995Sbostic (void) close(fd); /* unlocks as well */ 17230995Sbostic } else 17330995Sbostic putchar('\n'); 17430995Sbostic } 17530995Sbostic (void) fclose(fp); 17613441Sralph } 17730995Sbostic /* 17830995Sbostic * Now, examine the control files and print out the jobs to 17930995Sbostic * be done for each user. 18030995Sbostic */ 18130995Sbostic if (!lflag) 18230995Sbostic header(); 18330995Sbostic for (i = 0; i < nitems; i++) { 18430995Sbostic q = queue[i]; 18530995Sbostic inform(q->q_name); 18630995Sbostic free(q); 18730995Sbostic } 18830995Sbostic free(queue); 18912113Sralph } 190*31678Skarels if (!sendtorem) { 191*31678Skarels if (nitems == 0) 192*31678Skarels puts("no entries"); 19330995Sbostic return; 19430995Sbostic } 19530995Sbostic 19612113Sralph /* 19730995Sbostic * Print foreign queue 19830995Sbostic * Note that a file in transit may show up in either queue. 19912113Sralph */ 20030995Sbostic if (nitems) 20130995Sbostic putchar('\n'); 20230995Sbostic (void) sprintf(line, "%c%s", format + '\3', RP); 20330995Sbostic cp = line; 20430995Sbostic for (i = 0; i < requests; i++) { 20530995Sbostic cp += strlen(cp); 20630995Sbostic (void) sprintf(cp, " %d", requ[i]); 20712113Sralph } 20830995Sbostic for (i = 0; i < users; i++) { 20930995Sbostic cp += strlen(cp); 21030995Sbostic *cp++ = ' '; 21130995Sbostic (void) strcpy(cp, user[i]); 21230995Sbostic } 21330995Sbostic strcat(line, "\n"); 21430995Sbostic fd = getport(RM); 21530995Sbostic if (fd < 0) { 21630995Sbostic if (from != host) 21730995Sbostic printf("%s: ", host); 21830995Sbostic printf("connection to %s is down\n", RM); 21930995Sbostic } 22030995Sbostic else { 22130995Sbostic i = strlen(line); 22230995Sbostic if (write(fd, line, i) != i) 22330995Sbostic fatal("Lost connection"); 22430995Sbostic while ((i = read(fd, line, sizeof(line))) > 0) 22530995Sbostic (void) fwrite(line, 1, i, stdout); 22630995Sbostic (void) close(fd); 22730995Sbostic } 22812113Sralph } 22912113Sralph 23012113Sralph /* 23113441Sralph * Print a warning message if there is no daemon present. 23213441Sralph */ 23313441Sralph warn() 23413441Sralph { 23513441Sralph if (sendtorem) 23613441Sralph printf("\n%s: ", host); 23730995Sbostic puts("Warning: no daemon present"); 23813441Sralph current[0] = '\0'; 23913441Sralph } 24013441Sralph 24113441Sralph /* 24212113Sralph * Print the header for the short listing format 24312113Sralph */ 24412113Sralph header() 24512113Sralph { 24612113Sralph printf(head0); 24712113Sralph col = strlen(head0)+1; 24812113Sralph blankfill(SIZCOL); 24912113Sralph printf(head1); 25012113Sralph } 25112113Sralph 25212113Sralph inform(cf) 25312113Sralph char *cf; 25412113Sralph { 25512113Sralph register int j, k; 25612113Sralph register char *cp; 25712113Sralph FILE *cfp; 25812113Sralph 25912113Sralph /* 26012113Sralph * There's a chance the control file has gone away 26112113Sralph * in the meantime; if this is the case just keep going 26212113Sralph */ 26312113Sralph if ((cfp = fopen(cf, "r")) == NULL) 26412113Sralph return; 26512113Sralph 26612113Sralph if (rank < 0) 26712113Sralph rank = 0; 26812113Sralph if (sendtorem || garbage || strcmp(cf, current)) 26912113Sralph rank++; 27012113Sralph j = 0; 27112113Sralph while (getline(cfp)) { 27212113Sralph switch (line[0]) { 27312113Sralph case 'P': /* Was this file specified in the user's list? */ 27412113Sralph if (!inlist(line+1, cf)) { 27512113Sralph fclose(cfp); 27612113Sralph return; 27712113Sralph } 27812113Sralph if (lflag) { 27912113Sralph printf("\n%s: ", line+1); 28012113Sralph col = strlen(line+1) + 2; 28112113Sralph prank(rank); 28212113Sralph blankfill(JOBCOL); 28312113Sralph printf(" [job %s]\n", cf+3); 28412113Sralph } else { 28512113Sralph col = 0; 28612113Sralph prank(rank); 28712113Sralph blankfill(OWNCOL); 28812113Sralph printf("%-10s %-3d ", line+1, atoi(cf+3)); 28912113Sralph col += 16; 29012113Sralph first = 1; 29112113Sralph } 29212113Sralph continue; 29312113Sralph default: /* some format specifer and file name? */ 29412113Sralph if (line[0] < 'a' || line[0] > 'z') 29512113Sralph continue; 29612113Sralph if (j == 0 || strcmp(file, line+1) != 0) 29730995Sbostic (void) strcpy(file, line+1); 29812113Sralph j++; 29912113Sralph continue; 30012113Sralph case 'N': 30112113Sralph show(line+1, file, j); 30212113Sralph file[0] = '\0'; 30312113Sralph j = 0; 30412113Sralph } 30512113Sralph } 30612113Sralph fclose(cfp); 30712113Sralph if (!lflag) { 30812113Sralph blankfill(SIZCOL); 30912113Sralph printf("%D bytes\n", totsize); 31012113Sralph totsize = 0; 31112113Sralph } 31212113Sralph } 31312113Sralph 31412113Sralph inlist(name, file) 31512113Sralph char *name, *file; 31612113Sralph { 31712113Sralph register int *r, n; 31812113Sralph register char **u, *cp; 31912113Sralph 32012113Sralph if (users == 0 && requests == 0) 32112113Sralph return(1); 32212113Sralph /* 32312113Sralph * Check to see if it's in the user list 32412113Sralph */ 32512113Sralph for (u = user; u < &user[users]; u++) 32612113Sralph if (!strcmp(*u, name)) 32712113Sralph return(1); 32812113Sralph /* 32912113Sralph * Check the request list 33012113Sralph */ 33112113Sralph for (n = 0, cp = file+3; isdigit(*cp); ) 33212113Sralph n = n * 10 + (*cp++ - '0'); 33312113Sralph for (r = requ; r < &requ[requests]; r++) 33412113Sralph if (*r == n && !strcmp(cp, from)) 33512113Sralph return(1); 33612113Sralph return(0); 33712113Sralph } 33812113Sralph 33912113Sralph show(nfile, file, copies) 34012113Sralph register char *nfile, *file; 34112113Sralph { 34212113Sralph if (strcmp(nfile, " ") == 0) 34312113Sralph nfile = "(standard input)"; 34412113Sralph if (lflag) 34512113Sralph ldump(nfile, file, copies); 34612113Sralph else 34712113Sralph dump(nfile, file, copies); 34812113Sralph } 34912113Sralph 35012113Sralph /* 35112113Sralph * Fill the line with blanks to the specified column 35212113Sralph */ 35312113Sralph blankfill(n) 35412113Sralph register int n; 35512113Sralph { 35612113Sralph while (col++ < n) 35712113Sralph putchar(' '); 35812113Sralph } 35912113Sralph 36012113Sralph /* 36112113Sralph * Give the abbreviated dump of the file names 36212113Sralph */ 36312113Sralph dump(nfile, file, copies) 36412113Sralph char *nfile, *file; 36512113Sralph { 36612113Sralph register short n, fill; 36712113Sralph struct stat lbuf; 36812113Sralph 36912113Sralph /* 37012113Sralph * Print as many files as will fit 37112113Sralph * (leaving room for the total size) 37212113Sralph */ 37312113Sralph fill = first ? 0 : 2; /* fill space for ``, '' */ 37412113Sralph if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 37512113Sralph if (col < SIZCOL) { 37612113Sralph printf(" ..."), col += 4; 37712113Sralph blankfill(SIZCOL); 37812113Sralph } 37912113Sralph } else { 38012113Sralph if (first) 38112113Sralph first = 0; 38212113Sralph else 38312113Sralph printf(", "); 38412113Sralph printf("%s", nfile); 38512113Sralph col += n+fill; 38612113Sralph } 38712113Sralph if (*file && !stat(file, &lbuf)) 38812113Sralph totsize += copies * lbuf.st_size; 38912113Sralph } 39012113Sralph 39112113Sralph /* 39212113Sralph * Print the long info about the file 39312113Sralph */ 39412113Sralph ldump(nfile, file, copies) 39512113Sralph char *nfile, *file; 39612113Sralph { 39712113Sralph struct stat lbuf; 39812113Sralph 39912113Sralph putchar('\t'); 40012113Sralph if (copies > 1) 40112113Sralph printf("%-2d copies of %-19s", copies, nfile); 40212113Sralph else 40312113Sralph printf("%-32s", nfile); 40412113Sralph if (*file && !stat(file, &lbuf)) 40512113Sralph printf(" %D bytes", lbuf.st_size); 40612113Sralph else 40712113Sralph printf(" ??? bytes"); 40812113Sralph putchar('\n'); 40912113Sralph } 41012113Sralph 41112113Sralph /* 41212113Sralph * Print the job's rank in the queue, 41312113Sralph * update col for screen management 41412113Sralph */ 41512113Sralph prank(n) 41612113Sralph { 41712113Sralph char line[100]; 41812113Sralph static char *r[] = { 41912113Sralph "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 42012113Sralph }; 42112113Sralph 42212113Sralph if (n == 0) { 42312113Sralph printf("active"); 42412113Sralph col += 6; 42512113Sralph return; 42612113Sralph } 42712113Sralph if ((n/10) == 1) 42812113Sralph (void) sprintf(line, "%dth", n); 42912113Sralph else 43012113Sralph (void) sprintf(line, "%d%s", n, r[n%10]); 43112113Sralph col += strlen(line); 43212113Sralph printf("%s", line); 43312113Sralph } 434