displayq.c revision 28621
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1983, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 3. All advertising materials mentioning features or use of this software 141541Srgrimes * must display the following acknowledgement: 151541Srgrimes * This product includes software developed by the University of 161541Srgrimes * California, Berkeley and its contributors. 171541Srgrimes * 4. Neither the name of the University nor the names of its contributors 181541Srgrimes * may be used to endorse or promote products derived from this software 191541Srgrimes * without specific prior written permission. 201541Srgrimes * 211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311541Srgrimes * SUCH DAMAGE. 321541Srgrimes */ 331541Srgrimes 3450477Speter#ifndef lint 351541Srgrimesstatic char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95"; 361541Srgrimes#endif /* not lint */ 3732350Seivind 3814328Speter#include <sys/param.h> 3914328Speter#include <sys/stat.h> 401541Srgrimes#include <sys/file.h> 411541Srgrimes 4229024Sbde#include <signal.h> 431541Srgrimes#include <fcntl.h> 441541Srgrimes#include <dirent.h> 451541Srgrimes#include <unistd.h> 4646161Sluoqi#include <stdio.h> 471541Srgrimes#include <stdlib.h> 481541Srgrimes#include <string.h> 491541Srgrimes#include <ctype.h> 501541Srgrimes#include "lp.h" 511541Srgrimes#include "lp.local.h" 527090Sbde#include "pathnames.h" 531541Srgrimes 541541Srgrimes/* 551541Srgrimes * Routines to display the state of the queue. 569759Sbde */ 5712820Sphk#define JOBCOL 40 /* column for job # in -l format */ 589759Sbde#define OWNCOL 7 /* start of Owner column in normal */ 599759Sbde#define SIZCOL 62 /* start of Size column in normal */ 6012820Sphk 611541Srgrimes/* 6212820Sphk * Stuff for handling job specifications 6312820Sphk */ 6412820Sphkextern uid_t uid, euid; 6512820Sphk 6612820Sphkstatic int col; /* column on screen */ 671541Srgrimesstatic char current[40]; /* current file being printed */ 681541Srgrimesstatic char file[132]; /* print file name */ 691541Srgrimesstatic int first; /* first file in ``files'' column? */ 701541Srgrimesstatic int garbage; /* # of garbage cf files */ 711541Srgrimesstatic int lflag; /* long output option */ 721541Srgrimesstatic int rank; /* order to be printed (-1=none, 0=active) */ 731541Srgrimesstatic long totsize; /* total print job size in bytes */ 741541Srgrimes 751541Srgrimesstatic char *head0 = "Rank Owner Job Files"; 761541Srgrimesstatic char *head1 = "Total Size\n"; 771541Srgrimes 781541Srgrimesstatic void alarmhandler __P((int)); 791541Srgrimesstatic void warn __P((void)); 801541Srgrimes 811541Srgrimes/* 821541Srgrimes * Display the current state of the queue. Format = 1 if long format. 831541Srgrimes */ 841541Srgrimesvoid 851541Srgrimesdisplayq(format) 861541Srgrimes int format; 871541Srgrimes{ 881541Srgrimes register struct queue *q; 891541Srgrimes register int i, nitems, fd, ret; 901541Srgrimes register char *cp; 911541Srgrimes struct queue **queue; 921541Srgrimes struct stat statb; 935099Swollman FILE *fp; 941541Srgrimes void (*savealrm)(int); 951541Srgrimes 965104Swollman lflag = format; 975104Swollman totsize = 0; 985104Swollman rank = -1; 995104Swollman if ((i = cgetent(&bp, printcapdb, printer)) == -2) 1005104Swollman fatal("can't open printer description file"); 1015104Swollman else if (i == -1) 1025104Swollman fatal("unknown printer"); 1035104Swollman else if (i == -3) 1045104Swollman fatal("potential reference loop detected in printcap file"); 1055104Swollman if (cgetstr(bp, "lp", &LP) < 0) 10653541Sshin LP = _PATH_DEFDEVLP; 10753541Sshin if (cgetstr(bp, "rp", &RP) < 0) 10853541Sshin RP = DEFLP; 10953541Sshin if (cgetstr(bp, "sd", &SD) < 0) 11053541Sshin SD = _PATH_DEFSPOOL; 11153541Sshin if (cgetstr(bp,"lo", &LO) < 0) 11253541Sshin LO = DEFLOCK; 11353541Sshin if (cgetstr(bp, "st", &ST) < 0) 11453541Sshin ST = DEFSTAT; 11553541Sshin cgetstr(bp, "rm", &RM); 11618206Sjulian if ((cp = checkremote())) 11718206Sjulian printf("Warning: %s\n", cp); 11818206Sjulian 11918206Sjulian /* 1201541Srgrimes * Print out local queue 1215099Swollman * Find all the control files in the spooling directory 1221541Srgrimes */ 1231541Srgrimes seteuid(euid); 1245099Swollman if (chdir(SD) < 0) 1251541Srgrimes fatal("cannot chdir to spooling directory"); 1261541Srgrimes seteuid(uid); 1271541Srgrimes if ((nitems = getq(&queue)) < 0) 1281541Srgrimes fatal("cannot examine spooling area\n"); 1291541Srgrimes seteuid(euid); 1301541Srgrimes ret = stat(LO, &statb); 1315099Swollman seteuid(uid); 1321541Srgrimes if (ret >= 0) { 1331541Srgrimes if (statb.st_mode & 0100) { 13453541Sshin if (remote) 13518206Sjulian printf("%s: ", host); 13618206Sjulian printf("Warning: %s is down: ", printer); 1371541Srgrimes seteuid(euid); 1381541Srgrimes fd = open(ST, O_RDONLY); 13918206Sjulian seteuid(uid); 14018206Sjulian if (fd >= 0) { 14118206Sjulian (void) flock(fd, LOCK_SH); 14218206Sjulian while ((i = read(fd, line, sizeof(line))) > 0) 1431541Srgrimes (void) fwrite(line, 1, i, stdout); 1445099Swollman (void) close(fd); /* unlocks as well */ 1455099Swollman } else 14618206Sjulian putchar('\n'); 14718206Sjulian } 14818206Sjulian if (statb.st_mode & 010) { 14918206Sjulian if (remote) 15018206Sjulian printf("%s: ", host); 1511541Srgrimes printf("Warning: %s queue is turned off\n", printer); 1521541Srgrimes } 1531541Srgrimes } 15418206Sjulian 15518206Sjulian if (nitems) { 15618206Sjulian seteuid(euid); 15718206Sjulian fp = fopen(LO, "r"); 1581541Srgrimes seteuid(uid); 1591541Srgrimes if (fp == NULL) 1601541Srgrimes warn(); 1611541Srgrimes else { 1621541Srgrimes /* get daemon pid */ 16318206Sjulian cp = current; 16453541Sshin while ((i = getc(fp)) != EOF && i != '\n') 16518206Sjulian *cp++ = i; 16618206Sjulian *cp = '\0'; 1671541Srgrimes i = atoi(current); 1681541Srgrimes if (i <= 0) { 1691541Srgrimes ret = -1; 1701541Srgrimes } else { 1711541Srgrimes seteuid(euid); 1721541Srgrimes ret = kill(i, 0); 17318206Sjulian seteuid(uid); 17418206Sjulian } 17518206Sjulian if (ret < 0) { 17618206Sjulian warn(); 17718206Sjulian } else { 1781541Srgrimes /* read current file name */ 1791541Srgrimes cp = current; 18018206Sjulian while ((i = getc(fp)) != EOF && i != '\n') 18118206Sjulian *cp++ = i; 18218206Sjulian *cp = '\0'; 18318206Sjulian /* 18418206Sjulian * Print the status file. 1851541Srgrimes */ 1861541Srgrimes if (remote) 1871541Srgrimes printf("%s: ", host); 1881541Srgrimes seteuid(euid); 1891541Srgrimes fd = open(ST, O_RDONLY); 1901541Srgrimes seteuid(uid); 1911541Srgrimes if (fd >= 0) { 1921541Srgrimes (void) flock(fd, LOCK_SH); 1931541Srgrimes while ((i = read(fd, line, sizeof(line))) > 0) 19423392Sjulian (void) fwrite(line, 1, i, stdout); 19523392Sjulian (void) close(fd); /* unlocks as well */ 19623392Sjulian } else 19723392Sjulian putchar('\n'); 1981541Srgrimes } 1991541Srgrimes (void) fclose(fp); 2001541Srgrimes } 2011541Srgrimes /* 20223392Sjulian * Now, examine the control files and print out the jobs to 20323392Sjulian * be done for each user. 20423392Sjulian */ 2058876Srgrimes if (!lflag) 2064073Swollman header(); 2071541Srgrimes for (i = 0; i < nitems; i++) { 2081541Srgrimes q = queue[i]; 2097279Swollman inform(q->q_name); 2101541Srgrimes free(q); 21123392Sjulian } 21223392Sjulian free(queue); 21323392Sjulian } 21423392Sjulian if (!remote) { 21523392Sjulian if (nitems == 0) 2161541Srgrimes puts("no entries"); 2174073Swollman return; 2184073Swollman } 2194073Swollman 22023392Sjulian /* 22123392Sjulian * Print foreign queue 22223392Sjulian * Note that a file in transit may show up in either queue. 22323392Sjulian */ 22423392Sjulian if (nitems) 22523392Sjulian putchar('\n'); 2261541Srgrimes (void) snprintf(line, sizeof(line), "%c%s", format + '\3', RP); 2271541Srgrimes cp = line; 2281541Srgrimes for (i = 0; i < requests && cp-line+10 < sizeof(line) - 1; i++) { 22953541Sshin cp += strlen(cp); 23023392Sjulian (void) sprintf(cp, " %d", requ[i]); 23123392Sjulian } 23223392Sjulian for (i = 0; i < users && cp - line + 1 + strlen(user[i]) < 2331541Srgrimes sizeof(line) - 1; i++) { 23423392Sjulian cp += strlen(cp); 23523392Sjulian *cp++ = ' '; 2361541Srgrimes (void) strcpy(cp, user[i]); 2373311Sphk } 2381541Srgrimes strcat(line, "\n"); 2391541Srgrimes savealrm = signal(SIGALRM, alarmhandler); 24023392Sjulian alarm(10); 24123392Sjulian fd = getport(RM, 0); 24253541Sshin (void)signal(SIGALRM, savealrm); 24323392Sjulian if (fd < 0) { 24423392Sjulian if (from != host) 24523392Sjulian printf("%s: ", host); 24623392Sjulian printf("connection to %s is down\n", RM); 24723392Sjulian } 2487224Swollman else { 2497224Swollman i = strlen(line); 2507224Swollman if (write(fd, line, i) != i) 25123392Sjulian fatal("Lost connection"); 25223392Sjulian while ((i = read(fd, line, sizeof(line))) > 0) 25323392Sjulian (void) fwrite(line, 1, i, stdout); 25423392Sjulian (void) close(fd); 25523392Sjulian } 25623392Sjulian} 2571541Srgrimes 25823392Sjulian/* 25923392Sjulian * Print a warning message if there is no daemon present. 26023392Sjulian */ 26123392Sjulianstatic void 2621541Srgrimeswarn() 2631541Srgrimes{ 2641541Srgrimes if (remote) 2651541Srgrimes printf("\n%s: ", host); 2661541Srgrimes puts("Warning: no daemon present"); 2671541Srgrimes current[0] = '\0'; 2681541Srgrimes} 2691541Srgrimes 2701541Srgrimes/* 2711541Srgrimes * Print the header for the short listing format 2721541Srgrimes */ 2731541Srgrimesvoid 2741541Srgrimesheader() 2751541Srgrimes{ 2761541Srgrimes printf(head0); 2771541Srgrimes col = strlen(head0)+1; 2781541Srgrimes blankfill(SIZCOL); 2791541Srgrimes printf(head1); 2801541Srgrimes} 2811541Srgrimes 2821541Srgrimesvoid 2831541Srgrimesinform(cf) 2841541Srgrimes char *cf; 2851541Srgrimes{ 2861541Srgrimes register int j; 2871549Srgrimes FILE *cfp; 2881541Srgrimes 2891541Srgrimes /* 2901541Srgrimes * There's a chance the control file has gone away 2911541Srgrimes * in the meantime; if this is the case just keep going 2921541Srgrimes */ 2931541Srgrimes seteuid(euid); 2941541Srgrimes if ((cfp = fopen(cf, "r")) == NULL) 2951541Srgrimes return; 2961541Srgrimes seteuid(uid); 2971541Srgrimes 2981541Srgrimes if (rank < 0) 2991541Srgrimes rank = 0; 3001541Srgrimes if (remote || garbage || strcmp(cf, current)) 3011541Srgrimes rank++; 3021541Srgrimes j = 0; 3031541Srgrimes while (getline(cfp)) { 3045099Swollman switch (line[0]) { 3051541Srgrimes case 'P': /* Was this file specified in the user's list? */ 3061541Srgrimes if (!inlist(line+1, cf)) { 3071541Srgrimes fclose(cfp); 3081541Srgrimes return; 3091541Srgrimes } 3101541Srgrimes if (lflag) { 3111541Srgrimes printf("\n%s: ", line+1); 3121541Srgrimes col = strlen(line+1) + 2; 3131541Srgrimes prank(rank); 3141541Srgrimes blankfill(JOBCOL); 3151541Srgrimes printf(" [job %s]\n", cf+3); 3161541Srgrimes } else { 3171541Srgrimes col = 0; 3181541Srgrimes prank(rank); 3191541Srgrimes blankfill(OWNCOL); 3201541Srgrimes printf("%-10s %-3d ", line+1, atoi(cf+3)); 3211541Srgrimes col += 16; 3221541Srgrimes first = 1; 3231541Srgrimes } 3241541Srgrimes continue; 3251541Srgrimes default: /* some format specifer and file name? */ 3261541Srgrimes if (line[0] < 'a' || line[0] > 'z') 3271541Srgrimes continue; 3281541Srgrimes if (j == 0 || strcmp(file, line+1) != 0) { 3298876Srgrimes (void) strncpy(file, line+1, sizeof(file) - 1); 3301541Srgrimes file[sizeof(file) - 1] = '\0'; 3311541Srgrimes } 3321541Srgrimes j++; 3331541Srgrimes continue; 3341541Srgrimes case 'N': 3351541Srgrimes show(line+1, file, j); 3361541Srgrimes file[0] = '\0'; 3371541Srgrimes j = 0; 3381541Srgrimes } 3391541Srgrimes } 3401541Srgrimes fclose(cfp); 3411541Srgrimes if (!lflag) { 3421541Srgrimes blankfill(SIZCOL); 3431541Srgrimes printf("%ld bytes\n", totsize); 3441541Srgrimes totsize = 0; 3451541Srgrimes } 3461541Srgrimes} 3471541Srgrimes 3481541Srgrimesint 3491541Srgrimesinlist(name, file) 3501541Srgrimes char *name, *file; 35123392Sjulian{ 35223392Sjulian register int *r, n; 35323392Sjulian register char **u, *cp; 3541541Srgrimes 3551541Srgrimes if (users == 0 && requests == 0) 3561541Srgrimes return(1); 3571541Srgrimes /* 3581541Srgrimes * Check to see if it's in the user list 3591541Srgrimes */ 3601541Srgrimes for (u = user; u < &user[users]; u++) 3611541Srgrimes if (!strcmp(*u, name)) 3621541Srgrimes return(1); 3631541Srgrimes /* 3641541Srgrimes * Check the request list 3651541Srgrimes */ 3661541Srgrimes for (n = 0, cp = file+3; isdigit(*cp); ) 3671541Srgrimes n = n * 10 + (*cp++ - '0'); 3681541Srgrimes for (r = requ; r < &requ[requests]; r++) 3691541Srgrimes if (*r == n && !strcmp(cp, from)) 3701541Srgrimes return(1); 3711541Srgrimes return(0); 3721541Srgrimes} 3731541Srgrimes 3741541Srgrimesvoid 3751541Srgrimesshow(nfile, file, copies) 3761541Srgrimes register char *nfile, *file; 3771541Srgrimes int copies; 3781541Srgrimes{ 3791541Srgrimes if (strcmp(nfile, " ") == 0) 3801541Srgrimes nfile = "(standard input)"; 3811541Srgrimes if (lflag) 3821541Srgrimes ldump(nfile, file, copies); 3831541Srgrimes else 3841541Srgrimes dump(nfile, file, copies); 3851541Srgrimes} 3861541Srgrimes 3873311Sphk/* 3882531Swollman * Fill the line with blanks to the specified column 38912578Sbde */ 39012578Sbdevoid 39112578Sbdeblankfill(n) 3922544Sse register int n; 39312578Sbde{ 3943311Sphk while (col++ < n) 3953311Sphk putchar(' '); 3963311Sphk} 3971541Srgrimes 3981541Srgrimes/* 3991541Srgrimes * Give the abbreviated dump of the file names 4001541Srgrimes */ 4011541Srgrimesvoid 4021541Srgrimesdump(nfile, file, copies) 4031541Srgrimes char *nfile, *file; 4041541Srgrimes int copies; 4051541Srgrimes{ 4061541Srgrimes register short n, fill; 4071541Srgrimes struct stat lbuf; 4081541Srgrimes 4091541Srgrimes /* 4101541Srgrimes * Print as many files as will fit 4111541Srgrimes * (leaving room for the total size) 4121541Srgrimes */ 4131541Srgrimes fill = first ? 0 : 2; /* fill space for ``, '' */ 4143514Swollman if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 4151541Srgrimes if (col < SIZCOL) { 4163514Swollman printf(" ..."), col += 4; 4171541Srgrimes blankfill(SIZCOL); 4181541Srgrimes } 4191541Srgrimes } else { 4201541Srgrimes if (first) 4211541Srgrimes first = 0; 4221541Srgrimes else 4231541Srgrimes printf(", "); 4241541Srgrimes printf("%s", nfile); 4251541Srgrimes col += n+fill; 4261541Srgrimes } 4271541Srgrimes seteuid(euid); 4281541Srgrimes if (*file && !stat(file, &lbuf)) 4291541Srgrimes totsize += copies * lbuf.st_size; 4305099Swollman seteuid(uid); 4311541Srgrimes} 4321541Srgrimes 4331541Srgrimes/* 4341541Srgrimes * Print the long info about the file 4351541Srgrimes */ 4361541Srgrimesvoid 4371541Srgrimesldump(nfile, file, copies) 4381541Srgrimes char *nfile, *file; 4391541Srgrimes int copies; 4401541Srgrimes{ 4411541Srgrimes struct stat lbuf; 4421541Srgrimes 4431541Srgrimes putchar('\t'); 4441541Srgrimes if (copies > 1) 4451541Srgrimes printf("%-2d copies of %-19s", copies, nfile); 4461541Srgrimes else 4471541Srgrimes printf("%-32s", nfile); 44829506Sbde if (*file && !stat(file, &lbuf)) 44929506Sbde printf(" %qd bytes", lbuf.st_size); 4505791Swollman else 4518070Swollman printf(" ??? bytes"); 4528070Swollman putchar('\n'); 4538070Swollman} 4548070Swollman 4558070Swollman/* 45618206Sjulian * Print the job's rank in the queue, 45718206Sjulian * update col for screen management 45818206Sjulian */ 45918206Sjulianvoid 4601541Srgrimesprank(n) 4611541Srgrimes int n; 4621541Srgrimes{ 4631541Srgrimes char rline[100]; 4641541Srgrimes static char *r[] = { 4651541Srgrimes "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 4661541Srgrimes }; 4671541Srgrimes 4681541Srgrimes if (n == 0) { 4691541Srgrimes printf("active"); 4701541Srgrimes col += 6; 4711541Srgrimes return; 4721541Srgrimes } 4731541Srgrimes if ((n/10)%10 == 1) 47418206Sjulian (void)snprintf(rline, sizeof(rline), "%dth", n); 47518206Sjulian else 47618206Sjulian (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]); 4771541Srgrimes col += strlen(rline); 4781541Srgrimes printf("%s", rline); 47918206Sjulian} 48018206Sjulian 48118206Sjulianvoid 48218206Sjulianalarmhandler(signo) 4831541Srgrimes int signo; 4841541Srgrimes{ 4851541Srgrimes /* ignored */ 4861541Srgrimes} 48718206Sjulian