displayq.c revision 35998
11556Srgrimes/* 21556Srgrimes * Copyright (c) 1983, 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * Redistribution and use in source and binary forms, with or without 61556Srgrimes * modification, are permitted provided that the following conditions 71556Srgrimes * are met: 81556Srgrimes * 1. Redistributions of source code must retain the above copyright 91556Srgrimes * notice, this list of conditions and the following disclaimer. 101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111556Srgrimes * notice, this list of conditions and the following disclaimer in the 121556Srgrimes * documentation and/or other materials provided with the distribution. 131556Srgrimes * 3. All advertising materials mentioning features or use of this software 141556Srgrimes * must display the following acknowledgement: 151556Srgrimes * This product includes software developed by the University of 161556Srgrimes * California, Berkeley and its contributors. 171556Srgrimes * 4. Neither the name of the University nor the names of its contributors 181556Srgrimes * may be used to endorse or promote products derived from this software 191556Srgrimes * without specific prior written permission. 201556Srgrimes * 211556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311556Srgrimes * SUCH DAMAGE. 321556Srgrimes */ 331556Srgrimes 341556Srgrimes#ifndef lint 353044Sdg/* 3620425Sstevestatic char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95"; 371556Srgrimes*/ 381556Srgrimesstatic const char rcsid[] = 391556Srgrimes "$Id: displayq.c,v 1.13 1997/12/02 20:45:19 wollman Exp $"; 4020425Ssteve#endif /* not lint */ 411556Srgrimes 421556Srgrimes#include <sys/param.h> 4317987Speter#include <sys/stat.h> 4417987Speter 451556Srgrimes#include <ctype.h> 461556Srgrimes#include <dirent.h> 471556Srgrimes#include <errno.h> 481556Srgrimes#include <fcntl.h> 491556Srgrimes#include <signal.h> 501556Srgrimes#include <stdio.h> 511556Srgrimes#include <stdlib.h> 521556Srgrimes#include <string.h> 531556Srgrimes#define psignal foil_gcc_psignal 541556Srgrimes#define sys_siglist foil_gcc_siglist 551556Srgrimes#include <unistd.h> 561556Srgrimes#undef psignal 571556Srgrimes#undef sys_siglist 581556Srgrimes 5917987Speter#include "lp.h" 6017987Speter#include "lp.local.h" 611556Srgrimes#include "pathnames.h" 6217987Speter 631556Srgrimes/* 641556Srgrimes * Routines to display the state of the queue. 651556Srgrimes */ 661556Srgrimes#define JOBCOL 40 /* column for job # in -l format */ 671556Srgrimes#define OWNCOL 7 /* start of Owner column in normal */ 681556Srgrimes#define SIZCOL 62 /* start of Size column in normal */ 691556Srgrimes 701556Srgrimes/* 7117987Speter * Stuff for handling job specifications 721556Srgrimes */ 731556Srgrimesextern uid_t uid, euid; 741556Srgrimes 751556Srgrimesstatic int col; /* column on screen */ 761556Srgrimesstatic char current[40]; /* current file being printed */ 771556Srgrimesstatic char file[132]; /* print file name */ 781556Srgrimesstatic int first; /* first file in ``files'' column? */ 791556Srgrimesstatic int garbage; /* # of garbage cf files */ 801556Srgrimesstatic int lflag; /* long output option */ 811556Srgrimesstatic int rank; /* order to be printed (-1=none, 0=active) */ 821556Srgrimesstatic long totsize; /* total print job size in bytes */ 831556Srgrimes 841556Srgrimesstatic char *head0 = "Rank Owner Job Files"; 851556Srgrimesstatic char *head1 = "Total Size\n"; 861556Srgrimes 871556Srgrimesstatic void alarmhandler __P((int)); 881556Srgrimesstatic void warn __P((const struct printer *pp)); 891556Srgrimes 901556Srgrimes/* 911556Srgrimes * Display the current state of the queue. Format = 1 if long format. 921556Srgrimes */ 931556Srgrimesvoid 941556Srgrimesdisplayq(pp, format) 951556Srgrimes struct printer *pp; 961556Srgrimes int format; 971556Srgrimes{ 9818018Speter register struct queue *q; 9918018Speter register int i, nitems, fd, ret; 1001556Srgrimes register char *cp; 1011556Srgrimes struct queue **queue; 1021556Srgrimes struct stat statb; 1031556Srgrimes FILE *fp; 1041556Srgrimes void (*savealrm)(int); 1051556Srgrimes 1061556Srgrimes lflag = format; 1071556Srgrimes totsize = 0; 1081556Srgrimes rank = -1; 1091556Srgrimes 1101556Srgrimes if ((cp = checkremote(pp))) { 1111556Srgrimes printf("Warning: %s\n", cp); 1121556Srgrimes free(cp); 11317987Speter } 1141556Srgrimes 1151556Srgrimes /* 11617987Speter * Print out local queue 1171556Srgrimes * Find all the control files in the spooling directory 11817987Speter */ 1191556Srgrimes seteuid(euid); 1201556Srgrimes if (chdir(pp->spool_dir) < 0) 1211556Srgrimes fatal(pp, "cannot chdir to spooling directory: %s", 1221556Srgrimes strerror(errno)); 12320425Ssteve seteuid(uid); 1241556Srgrimes if ((nitems = getq(pp, &queue)) < 0) 12517987Speter fatal(pp, "cannot examine spooling area\n"); 1261556Srgrimes seteuid(euid); 1271556Srgrimes ret = stat(pp->lock_file, &statb); 1281556Srgrimes seteuid(uid); 1291556Srgrimes if (ret >= 0) { 1301556Srgrimes if (statb.st_mode & LFM_PRINT_DIS) { 1311556Srgrimes if (pp->remote) 13220425Ssteve printf("%s: ", host); 13317987Speter printf("Warning: %s is down: ", pp->printer); 13417987Speter seteuid(euid); 1351556Srgrimes fd = open(pp->status_file, O_RDONLY|O_SHLOCK); 1361556Srgrimes seteuid(uid); 1371556Srgrimes if (fd >= 0) { 1381556Srgrimes while ((i = read(fd, line, sizeof(line))) > 0) 1391556Srgrimes (void) fwrite(line, 1, i, stdout); 1401556Srgrimes (void) close(fd); /* unlocks as well */ 1411556Srgrimes } else 1421556Srgrimes putchar('\n'); 1431556Srgrimes } 1441556Srgrimes if (statb.st_mode & LFM_QUEUE_DIS) { 1451556Srgrimes if (pp->remote) 1461556Srgrimes printf("%s: ", host); 1471556Srgrimes printf("Warning: %s queue is turned off\n", 1481556Srgrimes pp->printer); 1491556Srgrimes } 1501556Srgrimes } 1511556Srgrimes 1521556Srgrimes if (nitems) { 1531556Srgrimes seteuid(euid); 15420425Ssteve fp = fopen(pp->lock_file, "r"); 15517987Speter seteuid(uid); 15617987Speter if (fp == NULL) 1571556Srgrimes warn(pp); 15817987Speter else { 1591556Srgrimes /* get daemon pid */ 1601556Srgrimes cp = current; 1611556Srgrimes while ((i = getc(fp)) != EOF && i != '\n') 1621556Srgrimes *cp++ = i; 16317987Speter *cp = '\0'; 1641556Srgrimes i = atoi(current); 16517987Speter if (i <= 0) { 16617987Speter ret = -1; 16717987Speter } else { 16817987Speter seteuid(euid); 16917987Speter ret = kill(i, 0); 17017987Speter seteuid(uid); 17117987Speter } 17217987Speter if (ret < 0) { 17317987Speter warn(pp); 17417987Speter } else { 17517987Speter /* read current file name */ 17617987Speter cp = current; 17717987Speter while ((i = getc(fp)) != EOF && i != '\n') 17817987Speter *cp++ = i; 17917987Speter *cp = '\0'; 18017987Speter /* 18117987Speter * Print the status file. 18217987Speter */ 18317987Speter if (pp->remote) 18417987Speter printf("%s: ", host); 18517987Speter seteuid(euid); 18617987Speter fd = open(pp->status_file, O_RDONLY|O_SHLOCK); 18717987Speter seteuid(uid); 18817987Speter if (fd >= 0) { 18917987Speter while ((i = read(fd, line, 19017987Speter sizeof(line))) > 0) 19113882Sjoerg fwrite(line, 1, i, stdout); 19217987Speter close(fd); /* unlocks as well */ 19317987Speter } else 19417987Speter putchar('\n'); 1951556Srgrimes } 19617987Speter (void) fclose(fp); 19717987Speter } 19817987Speter /* 19917987Speter * Now, examine the control files and print out the jobs to 20017987Speter * be done for each user. 20117987Speter */ 20217987Speter if (!lflag) 2031556Srgrimes header(); 2041556Srgrimes for (i = 0; i < nitems; i++) { 2051556Srgrimes q = queue[i]; 2061556Srgrimes inform(pp, q->q_name); 2071556Srgrimes free(q); 2081556Srgrimes } 2091556Srgrimes free(queue); 2101556Srgrimes } 2111556Srgrimes if (!pp->remote) { 2121556Srgrimes if (nitems == 0) 2131556Srgrimes puts("no entries"); 2141556Srgrimes return; 2151556Srgrimes } 2161556Srgrimes 2171556Srgrimes /* 2181556Srgrimes * Print foreign queue 2191556Srgrimes * Note that a file in transit may show up in either queue. 2201556Srgrimes */ 2211556Srgrimes if (nitems) 2221556Srgrimes putchar('\n'); 2231556Srgrimes (void) snprintf(line, sizeof(line), "%c%s", format ? '\4' : '\3', 2241556Srgrimes pp->remote_queue); 2251556Srgrimes cp = line; 2261556Srgrimes for (i = 0; i < requests && cp-line+10 < sizeof(line) - 1; i++) { 2271556Srgrimes cp += strlen(cp); 2281556Srgrimes (void) sprintf(cp, " %d", requ[i]); 2291556Srgrimes } 2301556Srgrimes for (i = 0; i < users && cp - line + 1 + strlen(user[i]) < 2311556Srgrimes sizeof(line) - 1; i++) { 2321556Srgrimes cp += strlen(cp); 2331556Srgrimes *cp++ = ' '; 2341556Srgrimes (void) strcpy(cp, user[i]); 2351556Srgrimes } 2361556Srgrimes strcat(line, "\n"); 2371556Srgrimes savealrm = signal(SIGALRM, alarmhandler); 2381556Srgrimes alarm(pp->conn_timeout); 2391556Srgrimes fd = getport(pp, pp->remote_host, 0); 2401556Srgrimes alarm(0); 2411556Srgrimes (void)signal(SIGALRM, savealrm); 2421556Srgrimes if (fd < 0) { 2431556Srgrimes if (from != host) 2441556Srgrimes printf("%s: ", host); 2451556Srgrimes printf("connection to %s is down\n", pp->remote_host); 2461556Srgrimes } 2471556Srgrimes else { 2481556Srgrimes i = strlen(line); 2491556Srgrimes if (write(fd, line, i) != i) 2501556Srgrimes fatal(pp, "Lost connection"); 2511556Srgrimes while ((i = read(fd, line, sizeof(line))) > 0) 25220425Ssteve (void) fwrite(line, 1, i, stdout); 2531556Srgrimes (void) close(fd); 2541556Srgrimes } 2551556Srgrimes} 2561556Srgrimes 2571556Srgrimes/* 2581556Srgrimes * Print a warning message if there is no daemon present. 2591556Srgrimes */ 2601556Srgrimesstatic void 2611556Srgrimeswarn(pp) 2621556Srgrimes const struct printer *pp; 2631556Srgrimes{ 2641556Srgrimes if (pp->remote) 2651556Srgrimes printf("%s: ", host); 2661556Srgrimes puts("Warning: no daemon present"); 2671556Srgrimes current[0] = '\0'; 2681556Srgrimes} 2691556Srgrimes 2701556Srgrimes/* 2711556Srgrimes * Print the header for the short listing format 2721556Srgrimes */ 2731556Srgrimesvoid 2741556Srgrimesheader() 2751556Srgrimes{ 2761556Srgrimes printf(head0); 2771556Srgrimes col = strlen(head0)+1; 2781556Srgrimes blankfill(SIZCOL); 2791556Srgrimes printf(head1); 2801556Srgrimes} 2811556Srgrimes 2821556Srgrimesvoid 2831556Srgrimesinform(pp, cf) 2841556Srgrimes const struct printer *pp; 28520425Ssteve char *cf; 2861556Srgrimes{ 2871556Srgrimes register int j; 28817987Speter FILE *cfp; 28917987Speter 2901556Srgrimes /* 29120425Ssteve * There's a chance the control file has gone away 2921556Srgrimes * in the meantime; if this is the case just keep going 2931556Srgrimes */ 2941556Srgrimes seteuid(euid); 2951556Srgrimes if ((cfp = fopen(cf, "r")) == NULL) 2961556Srgrimes return; 2971556Srgrimes seteuid(uid); 2981556Srgrimes 2991556Srgrimes if (rank < 0) 30020425Ssteve rank = 0; 30120425Ssteve if (pp->remote || garbage || strcmp(cf, current)) 30220425Ssteve rank++; 30320425Ssteve j = 0; 30420425Ssteve while (getline(cfp)) { 30520425Ssteve switch (line[0]) { 3061556Srgrimes case 'P': /* Was this file specified in the user's list? */ 3071556Srgrimes if (!inlist(line+1, cf)) { 3081556Srgrimes fclose(cfp); 3091556Srgrimes return; 3101556Srgrimes } 3111556Srgrimes if (lflag) { 3121556Srgrimes printf("\n%s: ", line+1); 3131556Srgrimes col = strlen(line+1) + 2; 3141556Srgrimes prank(rank); 3151556Srgrimes blankfill(JOBCOL); 3161556Srgrimes printf(" [job %s]\n", cf+3); 3171556Srgrimes } else { 3181556Srgrimes col = 0; 3191556Srgrimes prank(rank); 3201556Srgrimes blankfill(OWNCOL); 3211556Srgrimes printf("%-10s %-3d ", line+1, atoi(cf+3)); 3221556Srgrimes col += 16; 3231556Srgrimes first = 1; 3241556Srgrimes } 3251556Srgrimes continue; 3261556Srgrimes default: /* some format specifer and file name? */ 3271556Srgrimes if (line[0] < 'a' || line[0] > 'z') 3281556Srgrimes continue; 3291556Srgrimes if (j == 0 || strcmp(file, line+1) != 0) { 3301556Srgrimes (void) strncpy(file, line+1, sizeof(file) - 1); 3311556Srgrimes file[sizeof(file) - 1] = '\0'; 3321556Srgrimes } 3331556Srgrimes j++; 3341556Srgrimes continue; 3351556Srgrimes case 'N': 3361556Srgrimes show(line+1, file, j); 3371556Srgrimes file[0] = '\0'; 3381556Srgrimes j = 0; 3391556Srgrimes } 3401556Srgrimes } 3411556Srgrimes fclose(cfp); 3421556Srgrimes if (!lflag) { 3431556Srgrimes blankfill(SIZCOL); 3441556Srgrimes printf("%ld bytes\n", totsize); 3451556Srgrimes totsize = 0; 3461556Srgrimes } 3471556Srgrimes} 3481556Srgrimes 3491556Srgrimesint 3501556Srgrimesinlist(name, file) 3511556Srgrimes char *name, *file; 3521556Srgrimes{ 3531556Srgrimes register int *r, n; 3541556Srgrimes register char **u, *cp; 3551556Srgrimes 3561556Srgrimes if (users == 0 && requests == 0) 3571556Srgrimes return(1); 3581556Srgrimes /* 3591556Srgrimes * Check to see if it's in the user list 3601556Srgrimes */ 3611556Srgrimes for (u = user; u < &user[users]; u++) 3621556Srgrimes if (!strcmp(*u, name)) 3631556Srgrimes return(1); 3641556Srgrimes /* 3651556Srgrimes * Check the request list 3661556Srgrimes */ 3671556Srgrimes for (n = 0, cp = file+3; isdigit(*cp); ) 3681556Srgrimes n = n * 10 + (*cp++ - '0'); 3691556Srgrimes for (r = requ; r < &requ[requests]; r++) 3701556Srgrimes if (*r == n && !strcmp(cp, from)) 3711556Srgrimes return(1); 3721556Srgrimes return(0); 3731556Srgrimes} 3741556Srgrimes 3751556Srgrimesvoid 3761556Srgrimesshow(nfile, file, copies) 3771556Srgrimes register char *nfile, *file; 3781556Srgrimes int copies; 3791556Srgrimes{ 3801556Srgrimes if (strcmp(nfile, " ") == 0) 3811556Srgrimes nfile = "(standard input)"; 3821556Srgrimes if (lflag) 3831556Srgrimes ldump(nfile, file, copies); 3841556Srgrimes else 3851556Srgrimes dump(nfile, file, copies); 3861556Srgrimes} 3871556Srgrimes 3881556Srgrimes/* 3891556Srgrimes * Fill the line with blanks to the specified column 3901556Srgrimes */ 3911556Srgrimesvoid 3921556Srgrimesblankfill(n) 3931556Srgrimes register int n; 3941556Srgrimes{ 3951556Srgrimes while (col++ < n) 3961556Srgrimes putchar(' '); 3971556Srgrimes} 3981556Srgrimes 3991556Srgrimes/* 4001556Srgrimes * Give the abbreviated dump of the file names 4011556Srgrimes */ 4021556Srgrimesvoid 4031556Srgrimesdump(nfile, file, copies) 4041556Srgrimes char *nfile, *file; 4051556Srgrimes int copies; 4061556Srgrimes{ 4071556Srgrimes register short n, fill; 4081556Srgrimes struct stat lbuf; 4091556Srgrimes 4101556Srgrimes /* 4111556Srgrimes * Print as many files as will fit 4121556Srgrimes * (leaving room for the total size) 4131556Srgrimes */ 41418018Speter fill = first ? 0 : 2; /* fill space for ``, '' */ 4152760Ssef if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 4162760Ssef if (col < SIZCOL) { 4171556Srgrimes printf(" ..."), col += 4; 4181556Srgrimes blankfill(SIZCOL); 4191556Srgrimes } 4201556Srgrimes } else { 4211556Srgrimes if (first) 4221556Srgrimes first = 0; 4231556Srgrimes else 4241556Srgrimes printf(", "); 4252760Ssef printf("%s", nfile); 4261556Srgrimes col += n+fill; 4271556Srgrimes } 4282760Ssef seteuid(euid); 4291556Srgrimes if (*file && !stat(file, &lbuf)) 4301556Srgrimes totsize += copies * lbuf.st_size; 4311556Srgrimes seteuid(uid); 43218018Speter} 4331556Srgrimes 4342760Ssef/* 4352760Ssef * Print the long info about the file 4362760Ssef */ 4372760Ssefvoid 43818018Speterldump(nfile, file, copies) 4392760Ssef char *nfile, *file; 4402760Ssef int copies; 4412760Ssef{ 4421556Srgrimes struct stat lbuf; 4432760Ssef 44418018Speter putchar('\t'); 4451556Srgrimes if (copies > 1) 4461556Srgrimes printf("%-2d copies of %-19s", copies, nfile); 4471556Srgrimes else 4481556Srgrimes printf("%-32s", nfile); 4491556Srgrimes if (*file && !stat(file, &lbuf)) 4501556Srgrimes printf(" %qd bytes", (long long) lbuf.st_size); 4511556Srgrimes else 4521556Srgrimes printf(" ??? bytes"); 4531556Srgrimes putchar('\n'); 4541556Srgrimes} 4551556Srgrimes 4561556Srgrimes/* 4571556Srgrimes * Print the job's rank in the queue, 4581556Srgrimes * update col for screen management 4591556Srgrimes */ 4601556Srgrimesvoid 4611556Srgrimesprank(n) 4621556Srgrimes int n; 4631556Srgrimes{ 46417987Speter char rline[100]; 46517987Speter static char *r[] = { 46617987Speter "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 46717987Speter }; 46817987Speter 46917987Speter if (n == 0) { 47017987Speter printf("active"); 47120425Ssteve col += 6; 47220425Ssteve return; 4731556Srgrimes } 47410399Sjoerg if ((n/10)%10 == 1) 4751556Srgrimes (void)snprintf(rline, sizeof(rline), "%dth", n); 47617987Speter else 4771556Srgrimes (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]); 47820425Ssteve col += strlen(rline); 47920425Ssteve printf("%s", rline); 4801556Srgrimes} 4811556Srgrimes 4821556Srgrimesvoid 4831556Srgrimesalarmhandler(signo) 4841556Srgrimes int signo; 4851556Srgrimes{ 4861556Srgrimes /* ignored */ 4871556Srgrimes} 4881556Srgrimes