1*13147Ssam /* displayq.c 4.6 83/06/15 */ 212113Sralph /* 312113Sralph * Routines to display the state of the queue. 412113Sralph */ 512113Sralph 612113Sralph #include "lp.h" 712113Sralph 812878Sralph #define JOBCOL 40 /* column for job # in -l format */ 912878Sralph #define OWNCOL 7 /* start of Owner column in normal */ 1012878Sralph #define SIZCOL 62 /* start of Size column in normal */ 1112113Sralph 1212113Sralph /* 1312113Sralph * Stuff for handling job specifications 1412113Sralph */ 1512113Sralph extern char *user[]; /* users to process */ 1612113Sralph extern int users; /* # of users in user array */ 1712113Sralph extern int requ[]; /* job number of spool entries */ 1812113Sralph extern int requests; /* # of spool requests */ 1912113Sralph 2012878Sralph static int lflag; /* long output option */ 2112878Sralph static char current[40]; /* current file being printed */ 2212878Sralph static int garbage; /* # of garbage cf files */ 2312878Sralph static int rank; /* order to be printed (-1=none, 0=active) */ 2412878Sralph static long totsize; /* total print job size in bytes */ 2512878Sralph static int first; /* first file in ``files'' column? */ 2612878Sralph static int col; /* column on screen */ 2712878Sralph static int sendtorem; /* are we sending to a remote? */ 2812878Sralph static char file[132]; /* print file name */ 2912113Sralph 3012878Sralph static char *head0 = "Rank Owner Job Files"; 3112878Sralph static char *head1 = "Total Size\n"; 3212113Sralph 3312113Sralph /* 3412113Sralph * Display the current state of the queue. Format = 1 if long format. 3512113Sralph */ 3612113Sralph displayq(format) 3712113Sralph int format; 3812113Sralph { 3912113Sralph register struct queue *q; 4012113Sralph register int i, nitems, fd; 4112113Sralph struct queue **queue; 4212113Sralph struct stat statb; 4312113Sralph FILE *fp; 4412113Sralph 4512113Sralph lflag = format; 4612113Sralph totsize = 0; 4712113Sralph rank = -1; 4812113Sralph 4912113Sralph if ((i = pgetent(line, printer)) < 0) 5012113Sralph fatal("cannot open printer description file"); 5112113Sralph else if (i == 0) 5212113Sralph fatal("unknown printer"); 5312113Sralph if ((LP = pgetstr("lp", &bp)) == NULL) 5412113Sralph LP = DEFDEVLP; 5512113Sralph if ((RP = pgetstr("rp", &bp)) == NULL) 5612434Sralph RP = DEFLP; 5712113Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 5812113Sralph SD = DEFSPOOL; 5912113Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 6012113Sralph LO = DEFLOCK; 6112113Sralph if ((ST = pgetstr("st", &bp)) == NULL) 6212113Sralph ST = DEFSTAT; 6312113Sralph RM = pgetstr("rm", &bp); 6412113Sralph 6512113Sralph /* 6612113Sralph * If there is no local printer, then print the queue on 6712113Sralph * the remote machine and then what's in the queue here. 6812113Sralph * Note that a file in transit may not show up in either queue. 6912113Sralph */ 7012113Sralph if (*LP == '\0') { 7112113Sralph register char *cp; 7212113Sralph char c; 7312113Sralph 7412113Sralph sendtorem++; 7512113Sralph (void) sprintf(line, "%c%s", format + '\3', RP); 7612113Sralph cp = line; 7712113Sralph for (i = 0; i < requests; i++) { 7812113Sralph cp += strlen(cp); 7912113Sralph (void) sprintf(cp, " %d", requ[i]); 8012113Sralph } 8112113Sralph for (i = 0; i < users; i++) { 8212113Sralph cp += strlen(cp); 8312113Sralph *cp++ = ' '; 8412113Sralph strcpy(cp, user[i]); 8512113Sralph } 8612113Sralph strcat(line, "\n"); 8712531Sralph fd = getport(RM); 8812113Sralph if (fd < 0) { 8912113Sralph if (from != host) 9012113Sralph printf("%s: ", host); 9112113Sralph printf("connection to %s is down\n", RM); 9212113Sralph } else { 9312113Sralph i = strlen(line); 9412113Sralph if (write(fd, line, i) != i) 9512113Sralph fatal("Lost connection"); 9612113Sralph while ((i = read(fd, line, sizeof(line))) > 0) 9712113Sralph (void) fwrite(line, 1, i, stdout); 9812113Sralph (void) close(fd); 9912113Sralph } 10012113Sralph } 10112113Sralph /* 10212113Sralph * Find all the control files in the spooling directory 10312113Sralph */ 10412113Sralph if (chdir(SD) < 0) 10512113Sralph fatal("cannot chdir to spooling directory"); 10612113Sralph if ((nitems = getq(&queue)) < 0) 10712113Sralph fatal("cannot examine spooling area\n"); 10812740Sralph if (stat(LO, &statb) >= 0 && (statb.st_mode & 010)) { 10912113Sralph if (sendtorem) 11012113Sralph printf("\n%s: ", host); 11112740Sralph printf("Warning: %s queue is turned off\n", printer); 11212740Sralph } 11312740Sralph if (nitems == 0) { 11412740Sralph if (!sendtorem) 11512740Sralph printf("no entries\n"); 11612113Sralph return(0); 11712113Sralph } 11812113Sralph fp = fopen(LO, "r"); 119*13147Ssam if (fp == NULL || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { 12012113Sralph if (fp != NULL) 12112113Sralph fclose(fp); 12212113Sralph garbage = nitems; 12312740Sralph if (sendtorem) 12412740Sralph printf("\n%s: ", host); 12512434Sralph if (stat(LO, &statb) >= 0 && (statb.st_mode & 0100)) 12612434Sralph printf("Warning: %s is down\n", printer); 12712113Sralph else 12812434Sralph printf("Warning: no daemon present\n"); 12912113Sralph } else { 13012113Sralph register char *cp = current; 13112113Sralph 13212113Sralph /* skip daemon pid */ 13312113Sralph while ((*cp = getc(fp)) != EOF && *cp != '\n'); 13412113Sralph /* read current file name */ 13512113Sralph while ((*cp = getc(fp)) != EOF && *cp != '\n') 13612113Sralph cp++; 13712113Sralph *cp = '\0'; 13812113Sralph fclose(fp); 13912434Sralph /* 14012434Sralph * Print the status file to show what the daemon is doing. 14112434Sralph */ 14212434Sralph if (sendtorem) 14312434Sralph printf("\n%s: ", host); 144*13147Ssam fd = open(ST, O_RDONLY); 145*13147Ssam if (fd >= 0) { 146*13147Ssam (void) flock(fd, LOCK_SH); 14712434Sralph while ((i = read(fd, line, sizeof(line))) > 0) 14812434Sralph (void) fwrite(line, 1, i, stdout); 14912434Sralph (void) close(fd); 15012434Sralph } else 15112434Sralph putchar('\n'); 15212113Sralph } 15312113Sralph /* 15412113Sralph * Now, examine the control files and print out the jobs to 15512113Sralph * be done for each user. 15612113Sralph */ 15712113Sralph if (!lflag) 15812113Sralph header(); 15912113Sralph for (i = 0; i < nitems; i++) { 16012113Sralph q = queue[i]; 16112113Sralph inform(q->q_name); 16212113Sralph free(q); 16312113Sralph } 16412113Sralph free(queue); 16512113Sralph return(nitems-garbage); 16612113Sralph } 16712113Sralph 16812113Sralph /* 16912113Sralph * Print the header for the short listing format 17012113Sralph */ 17112878Sralph static 17212113Sralph header() 17312113Sralph { 17412113Sralph printf(head0); 17512113Sralph col = strlen(head0)+1; 17612113Sralph blankfill(SIZCOL); 17712113Sralph printf(head1); 17812113Sralph } 17912113Sralph 18012878Sralph static 18112113Sralph inform(cf) 18212113Sralph char *cf; 18312113Sralph { 18412113Sralph register int j, k; 18512113Sralph register char *cp; 18612113Sralph FILE *cfp; 18712113Sralph 18812113Sralph /* 18912113Sralph * There's a chance the control file has gone away 19012113Sralph * in the meantime; if this is the case just keep going 19112113Sralph */ 19212113Sralph if ((cfp = fopen(cf, "r")) == NULL) 19312113Sralph return; 19412113Sralph 19512113Sralph if (rank < 0) 19612113Sralph rank = 0; 19712113Sralph if (sendtorem || garbage || strcmp(cf, current)) 19812113Sralph rank++; 19912113Sralph j = 0; 20012113Sralph while (getline(cfp)) { 20112113Sralph switch (line[0]) { 20212113Sralph case 'P': /* Was this file specified in the user's list? */ 20312113Sralph if (!inlist(line+1, cf)) { 20412113Sralph fclose(cfp); 20512113Sralph return; 20612113Sralph } 20712113Sralph if (lflag) { 20812113Sralph printf("\n%s: ", line+1); 20912113Sralph col = strlen(line+1) + 2; 21012113Sralph prank(rank); 21112113Sralph blankfill(JOBCOL); 21212113Sralph printf(" [job %s]\n", cf+3); 21312113Sralph } else { 21412113Sralph col = 0; 21512113Sralph prank(rank); 21612113Sralph blankfill(OWNCOL); 21712113Sralph printf("%-10s %-3d ", line+1, atoi(cf+3)); 21812113Sralph col += 16; 21912113Sralph first = 1; 22012113Sralph } 22112113Sralph continue; 22212113Sralph default: /* some format specifer and file name? */ 22312113Sralph if (line[0] < 'a' || line[0] > 'z') 22412113Sralph continue; 22512113Sralph if (j == 0 || strcmp(file, line+1) != 0) 22612113Sralph strcpy(file, line+1); 22712113Sralph j++; 22812113Sralph continue; 22912113Sralph case 'N': 23012113Sralph show(line+1, file, j); 23112113Sralph file[0] = '\0'; 23212113Sralph j = 0; 23312113Sralph } 23412113Sralph } 23512113Sralph fclose(cfp); 23612113Sralph if (!lflag) { 23712113Sralph blankfill(SIZCOL); 23812113Sralph printf("%D bytes\n", totsize); 23912113Sralph totsize = 0; 24012113Sralph } 24112113Sralph } 24212113Sralph 24312878Sralph static 24412113Sralph inlist(name, file) 24512113Sralph char *name, *file; 24612113Sralph { 24712113Sralph register int *r, n; 24812113Sralph register char **u, *cp; 24912113Sralph 25012113Sralph if (users == 0 && requests == 0) 25112113Sralph return(1); 25212113Sralph /* 25312113Sralph * Check to see if it's in the user list 25412113Sralph */ 25512113Sralph for (u = user; u < &user[users]; u++) 25612113Sralph if (!strcmp(*u, name)) 25712113Sralph return(1); 25812113Sralph /* 25912113Sralph * Check the request list 26012113Sralph */ 26112113Sralph for (n = 0, cp = file+3; isdigit(*cp); ) 26212113Sralph n = n * 10 + (*cp++ - '0'); 26312113Sralph for (r = requ; r < &requ[requests]; r++) 26412113Sralph if (*r == n && !strcmp(cp, from)) 26512113Sralph return(1); 26612113Sralph return(0); 26712113Sralph } 26812113Sralph 26912878Sralph static 27012113Sralph show(nfile, file, copies) 27112113Sralph register char *nfile, *file; 27212113Sralph { 27312113Sralph if (strcmp(nfile, " ") == 0) 27412113Sralph nfile = "(standard input)"; 27512113Sralph if (lflag) 27612113Sralph ldump(nfile, file, copies); 27712113Sralph else 27812113Sralph dump(nfile, file, copies); 27912113Sralph } 28012113Sralph 28112113Sralph /* 28212113Sralph * Fill the line with blanks to the specified column 28312113Sralph */ 28412878Sralph static 28512113Sralph blankfill(n) 28612113Sralph register int n; 28712113Sralph { 28812113Sralph while (col++ < n) 28912113Sralph putchar(' '); 29012113Sralph } 29112113Sralph 29212113Sralph /* 29312113Sralph * Give the abbreviated dump of the file names 29412113Sralph */ 29512878Sralph static 29612113Sralph dump(nfile, file, copies) 29712113Sralph char *nfile, *file; 29812113Sralph { 29912113Sralph register short n, fill; 30012113Sralph struct stat lbuf; 30112113Sralph 30212113Sralph /* 30312113Sralph * Print as many files as will fit 30412113Sralph * (leaving room for the total size) 30512113Sralph */ 30612113Sralph fill = first ? 0 : 2; /* fill space for ``, '' */ 30712113Sralph if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 30812113Sralph if (col < SIZCOL) { 30912113Sralph printf(" ..."), col += 4; 31012113Sralph blankfill(SIZCOL); 31112113Sralph } 31212113Sralph } else { 31312113Sralph if (first) 31412113Sralph first = 0; 31512113Sralph else 31612113Sralph printf(", "); 31712113Sralph printf("%s", nfile); 31812113Sralph col += n+fill; 31912113Sralph } 32012113Sralph if (*file && !stat(file, &lbuf)) 32112113Sralph totsize += copies * lbuf.st_size; 32212113Sralph } 32312113Sralph 32412113Sralph /* 32512113Sralph * Print the long info about the file 32612113Sralph */ 32712878Sralph static 32812113Sralph ldump(nfile, file, copies) 32912113Sralph char *nfile, *file; 33012113Sralph { 33112113Sralph struct stat lbuf; 33212113Sralph 33312113Sralph putchar('\t'); 33412113Sralph if (copies > 1) 33512113Sralph printf("%-2d copies of %-19s", copies, nfile); 33612113Sralph else 33712113Sralph printf("%-32s", nfile); 33812113Sralph if (*file && !stat(file, &lbuf)) 33912113Sralph printf(" %D bytes", lbuf.st_size); 34012113Sralph else 34112113Sralph printf(" ??? bytes"); 34212113Sralph putchar('\n'); 34312113Sralph } 34412113Sralph 34512113Sralph /* 34612113Sralph * Print the job's rank in the queue, 34712113Sralph * update col for screen management 34812113Sralph */ 34912878Sralph static 35012113Sralph prank(n) 35112113Sralph { 35212113Sralph char line[100]; 35312113Sralph static char *r[] = { 35412113Sralph "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 35512113Sralph }; 35612113Sralph 35712113Sralph if (n == 0) { 35812113Sralph printf("active"); 35912113Sralph col += 6; 36012113Sralph return; 36112113Sralph } 36212113Sralph if ((n/10) == 1) 36312113Sralph (void) sprintf(line, "%dth", n); 36412113Sralph else 36512113Sralph (void) sprintf(line, "%d%s", n, r[n%10]); 36612113Sralph col += strlen(line); 36712113Sralph printf("%s", line); 36812113Sralph } 369