displayq.c revision 31020
1156230Smux/* 2156230Smux * Copyright (c) 1983, 1993 3156230Smux * The Regents of the University of California. All rights reserved. 4156230Smux * 5156230Smux * Redistribution and use in source and binary forms, with or without 6156230Smux * modification, are permitted provided that the following conditions 7156230Smux * are met: 8156230Smux * 1. Redistributions of source code must retain the above copyright 9156230Smux * notice, this list of conditions and the following disclaimer. 10156230Smux * 2. Redistributions in binary form must reproduce the above copyright 11156230Smux * notice, this list of conditions and the following disclaimer in the 12156230Smux * documentation and/or other materials provided with the distribution. 13156230Smux * 3. All advertising materials mentioning features or use of this software 14156230Smux * must display the following acknowledgement: 15156230Smux * This product includes software developed by the University of 16156230Smux * California, Berkeley and its contributors. 17156230Smux * 4. Neither the name of the University nor the names of its contributors 18156230Smux * may be used to endorse or promote products derived from this software 19156230Smux * without specific prior written permission. 20156230Smux * 21156230Smux * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22156230Smux * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23156230Smux * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24156230Smux * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25156230Smux * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26156230Smux * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27156230Smux * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28156230Smux * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29156230Smux * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30156230Smux * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31156230Smux * SUCH DAMAGE. 32156230Smux */ 33186781Slulf 34156230Smux#ifndef lint 35156230Smuxstatic char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95"; 36156230Smux#endif /* not lint */ 37156230Smux 38156230Smux#include <sys/param.h> 39156230Smux#include <sys/stat.h> 40156230Smux#include <sys/file.h> 41156230Smux 42156230Smux#include <signal.h> 43156230Smux#include <fcntl.h> 44156230Smux#include <dirent.h> 45156230Smux#include <unistd.h> 46156230Smux#include <stdio.h> 47156230Smux#include <stdlib.h> 48156230Smux#include <string.h> 49156230Smux#include <ctype.h> 50156230Smux#include "lp.h" 51186781Slulf#include "lp.local.h" 52156230Smux#include "pathnames.h" 53156230Smux 54156230Smux/* 55156230Smux * Routines to display the state of the queue. 56156230Smux */ 57156230Smux#define JOBCOL 40 /* column for job # in -l format */ 58156230Smux#define OWNCOL 7 /* start of Owner column in normal */ 59156701Smux#define SIZCOL 62 /* start of Size column in normal */ 60156230Smux 61186781Slulf/* 62186781Slulf * Stuff for handling job specifications 63156230Smux */ 64156230Smuxextern uid_t uid, euid; 65156230Smux 66156230Smuxstatic int col; /* column on screen */ 67156701Smuxstatic char current[40]; /* current file being printed */ 68186781Slulfstatic char file[132]; /* print file name */ 69156230Smuxstatic int first; /* first file in ``files'' column? */ 70156230Smuxstatic int garbage; /* # of garbage cf files */ 71156230Smuxstatic int lflag; /* long output option */ 72156230Smuxstatic int rank; /* order to be printed (-1=none, 0=active) */ 73156230Smuxstatic long totsize; /* total print job size in bytes */ 74156230Smux 75156230Smuxstatic char *head0 = "Rank Owner Job Files"; 76156230Smuxstatic char *head1 = "Total Size\n"; 77186781Slulf 78156230Smuxstatic void alarmhandler __P((int)); 79156230Smuxstatic void warn __P((void)); 80156230Smux 81156230Smux/* 82156230Smux * Display the current state of the queue. Format = 1 if long format. 83156230Smux */ 84156230Smuxvoid 85156701Smuxdisplayq(format) 86156230Smux int format; 87156230Smux{ 88156230Smux register struct queue *q; 89186781Slulf register int i, nitems, fd, ret; 90156230Smux register char *cp; 91156230Smux struct queue **queue; 92156230Smux struct stat statb; 93156230Smux FILE *fp; 94156230Smux void (*savealrm)(int); 95156230Smux 96156701Smux lflag = format; 97156701Smux totsize = 0; 98156230Smux rank = -1; 99186781Slulf if ((i = cgetent(&bp, printcapdb, printer)) == -2) 100186781Slulf fatal("can't open printer description file"); 101186781Slulf else if (i == -1) 102156230Smux fatal("unknown printer"); 103156230Smux else if (i == -3) 104186781Slulf fatal("potential reference loop detected in printcap file"); 105186781Slulf if (cgetstr(bp, "lp", &LP) < 0) 106156701Smux LP = _PATH_DEFDEVLP; 107156230Smux if (cgetstr(bp, "rp", &RP) < 0) 108186781Slulf RP = DEFLP; 109186781Slulf if (cgetstr(bp, "sd", &SD) < 0) 110156230Smux SD = _PATH_DEFSPOOL; 111156230Smux if (cgetstr(bp,"lo", &LO) < 0) 112156230Smux LO = DEFLOCK; 113156230Smux if (cgetstr(bp, "st", &ST) < 0) 114186781Slulf ST = DEFSTAT; 115186781Slulf if (cgetnum(bp, "ct", &CT) < 0) 116186781Slulf CT = DEFTIMEOUT; 117186781Slulf if (cgetstr(bp, "rm", &RM) < 0) 118186781Slulf RM = NULL; 119186781Slulf if ((cp = checkremote())) 120156230Smux printf("Warning: %s\n", cp); 121156230Smux 122156230Smux /* 123156230Smux * Print out local queue 124156230Smux * Find all the control files in the spooling directory 125156230Smux */ 126156230Smux seteuid(euid); 127156230Smux if (chdir(SD) < 0) 128156230Smux fatal("cannot chdir to spooling directory"); 129156230Smux seteuid(uid); 130156230Smux if ((nitems = getq(&queue)) < 0) 131156230Smux fatal("cannot examine spooling area\n"); 132156230Smux seteuid(euid); 133156230Smux ret = stat(LO, &statb); 134186781Slulf seteuid(uid); 135156230Smux if (ret >= 0) { 136156230Smux if (statb.st_mode & 0100) { 137156230Smux if (remote) 138156230Smux printf("%s: ", host); 139186781Slulf printf("Warning: %s is down: ", printer); 140186781Slulf seteuid(euid); 141186781Slulf fd = open(ST, O_RDONLY); 142186781Slulf seteuid(uid); 143186781Slulf if (fd >= 0) { 144186781Slulf (void) flock(fd, LOCK_SH); 145186781Slulf while ((i = read(fd, line, sizeof(line))) > 0) 146186781Slulf (void) fwrite(line, 1, i, stdout); 147186781Slulf (void) close(fd); /* unlocks as well */ 148186781Slulf } else 149186781Slulf putchar('\n'); 150186781Slulf } 151186781Slulf if (statb.st_mode & 010) { 152186781Slulf if (remote) 153186781Slulf printf("%s: ", host); 154186781Slulf printf("Warning: %s queue is turned off\n", printer); 155156230Smux } 156156230Smux } 157156230Smux 158156230Smux if (nitems) { 159156230Smux seteuid(euid); 160156230Smux fp = fopen(LO, "r"); 161156230Smux seteuid(uid); 162156230Smux if (fp == NULL) 163156230Smux warn(); 164156230Smux else { 165156230Smux /* get daemon pid */ 166156230Smux cp = current; 167156230Smux while ((i = getc(fp)) != EOF && i != '\n') 168156230Smux *cp++ = i; 169156230Smux *cp = '\0'; 170156230Smux i = atoi(current); 171156230Smux if (i <= 0) { 172156230Smux ret = -1; 173156701Smux } else { 174156701Smux seteuid(euid); 175156701Smux ret = kill(i, 0); 176156701Smux seteuid(uid); 177186781Slulf } 178186781Slulf if (ret < 0) { 179186781Slulf warn(); 180186781Slulf } else { 181156230Smux /* read current file name */ 182156230Smux cp = current; 183156230Smux while ((i = getc(fp)) != EOF && i != '\n') 184156230Smux *cp++ = i; 185156230Smux *cp = '\0'; 186156230Smux /* 187156230Smux * Print the status file. 188156230Smux */ 189156230Smux if (remote) 190156230Smux printf("%s: ", host); 191156230Smux seteuid(euid); 192156230Smux fd = open(ST, O_RDONLY); 193156230Smux seteuid(uid); 194156230Smux if (fd >= 0) { 195156230Smux (void) flock(fd, LOCK_SH); 196156230Smux while ((i = read(fd, line, sizeof(line))) > 0) 197156230Smux (void) fwrite(line, 1, i, stdout); 198156230Smux (void) close(fd); /* unlocks as well */ 199156230Smux } else 200156230Smux putchar('\n'); 201156230Smux } 202156230Smux (void) fclose(fp); 203156230Smux } 204156230Smux /* 205156230Smux * Now, examine the control files and print out the jobs to 206156230Smux * be done for each user. 207156230Smux */ 208156230Smux if (!lflag) 209156230Smux header(); 210156230Smux for (i = 0; i < nitems; i++) { 211156230Smux q = queue[i]; 212156230Smux inform(q->q_name); 213156230Smux free(q); 214156230Smux } 215156230Smux free(queue); 216156230Smux } 217156230Smux if (!remote) { 218156230Smux if (nitems == 0) 219156230Smux puts("no entries"); 220156230Smux return; 221156230Smux } 222156230Smux 223156230Smux /* 224156230Smux * Print foreign queue 225156230Smux * Note that a file in transit may show up in either queue. 226156230Smux */ 227156230Smux if (nitems) 228156230Smux putchar('\n'); 229156230Smux (void) snprintf(line, sizeof(line), "%c%s", format + '\3', RP); 230156230Smux cp = line; 231156230Smux for (i = 0; i < requests && cp-line+10 < sizeof(line) - 1; i++) { 232156230Smux cp += strlen(cp); 233156230Smux (void) sprintf(cp, " %d", requ[i]); 234156230Smux } 235156701Smux for (i = 0; i < users && cp - line + 1 + strlen(user[i]) < 236156230Smux sizeof(line) - 1; i++) { 237156230Smux cp += strlen(cp); 238156230Smux *cp++ = ' '; 239156230Smux (void) strcpy(cp, user[i]); 240156230Smux } 241225979Sadrian strcat(line, "\n"); 242156230Smux savealrm = signal(SIGALRM, alarmhandler); 243156230Smux alarm(CT); 244156230Smux fd = getport(RM, 0); 245156230Smux alarm(0); 246156230Smux (void)signal(SIGALRM, savealrm); 247156230Smux if (fd < 0) { 248156230Smux if (from != host) 249156230Smux printf("%s: ", host); 250156230Smux printf("connection to %s is down\n", RM); 251156230Smux } 252156230Smux else { 253156230Smux i = strlen(line); 254156230Smux if (write(fd, line, i) != i) 255156230Smux fatal("Lost connection"); 256156230Smux while ((i = read(fd, line, sizeof(line))) > 0) 257156230Smux (void) fwrite(line, 1, i, stdout); 258156230Smux (void) close(fd); 259156230Smux } 260156230Smux} 261156230Smux 262156230Smux/* 263156230Smux * Print a warning message if there is no daemon present. 264156230Smux */ 265156230Smuxstatic void 266156701Smuxwarn() 267156701Smux{ 268156701Smux if (remote) 269156701Smux printf("%s: ", host); 270156701Smux puts("Warning: no daemon present"); 271156230Smux current[0] = '\0'; 272156230Smux} 273156230Smux 274156230Smux/* 275156230Smux * Print the header for the short listing format 276156230Smux */ 277156230Smuxvoid 278156230Smuxheader() 279156230Smux{ 280156230Smux printf(head0); 281156230Smux col = strlen(head0)+1; 282156230Smux blankfill(SIZCOL); 283156230Smux printf(head1); 284156230Smux} 285156230Smux 286156230Smuxvoid 287156230Smuxinform(cf) 288156230Smux char *cf; 289156230Smux{ 290156230Smux register int j; 291156230Smux FILE *cfp; 292156230Smux 293156230Smux /* 294156230Smux * There's a chance the control file has gone away 295156230Smux * in the meantime; if this is the case just keep going 296156230Smux */ 297156230Smux seteuid(euid); 298156230Smux if ((cfp = fopen(cf, "r")) == NULL) 299156230Smux return; 300156230Smux seteuid(uid); 301156230Smux 302156230Smux if (rank < 0) 303156230Smux rank = 0; 304156230Smux if (remote || garbage || strcmp(cf, current)) 305156230Smux rank++; 306156230Smux j = 0; 307156230Smux while (getline(cfp)) { 308156230Smux switch (line[0]) { 309156230Smux case 'P': /* Was this file specified in the user's list? */ 310156230Smux if (!inlist(line+1, cf)) { 311156230Smux fclose(cfp); 312156230Smux return; 313156230Smux } 314156230Smux if (lflag) { 315156230Smux printf("\n%s: ", line+1); 316156230Smux col = strlen(line+1) + 2; 317156230Smux prank(rank); 318156701Smux blankfill(JOBCOL); 319156230Smux printf(" [job %s]\n", cf+3); 320156230Smux } else { 321156230Smux col = 0; 322156230Smux prank(rank); 323156230Smux blankfill(OWNCOL); 324156230Smux printf("%-10s %-3d ", line+1, atoi(cf+3)); 325156230Smux col += 16; 326156230Smux first = 1; 327156230Smux } 328156230Smux continue; 329156230Smux default: /* some format specifer and file name? */ 330156230Smux if (line[0] < 'a' || line[0] > 'z') 331156230Smux continue; 332156230Smux if (j == 0 || strcmp(file, line+1) != 0) { 333156230Smux (void) strncpy(file, line+1, sizeof(file) - 1); 334156230Smux file[sizeof(file) - 1] = '\0'; 335156230Smux } 336156230Smux j++; 337156230Smux continue; 338156230Smux case 'N': 339156230Smux show(line+1, file, j); 340156230Smux file[0] = '\0'; 341156230Smux j = 0; 342156230Smux } 343156230Smux } 344156230Smux fclose(cfp); 345156230Smux if (!lflag) { 346156230Smux blankfill(SIZCOL); 347156230Smux printf("%ld bytes\n", totsize); 348156230Smux totsize = 0; 349156230Smux } 350186781Slulf} 351156230Smux 352156230Smuxint 353186781Slulfinlist(name, file) 354156230Smux char *name, *file; 355186781Slulf{ 356186781Slulf register int *r, n; 357156230Smux register char **u, *cp; 358156230Smux 359156230Smux if (users == 0 && requests == 0) 360156230Smux return(1); 361156230Smux /* 362156230Smux * Check to see if it's in the user list 363156230Smux */ 364156230Smux for (u = user; u < &user[users]; u++) 365156230Smux if (!strcmp(*u, name)) 366156230Smux return(1); 367156230Smux /* 368156230Smux * Check the request list 369156230Smux */ 370156230Smux for (n = 0, cp = file+3; isdigit(*cp); ) 371156230Smux n = n * 10 + (*cp++ - '0'); 372156230Smux for (r = requ; r < &requ[requests]; r++) 373156230Smux if (*r == n && !strcmp(cp, from)) 374156230Smux return(1); 375156230Smux return(0); 376156230Smux} 377156230Smux 378156230Smuxvoid 379156230Smuxshow(nfile, file, copies) 380156230Smux register char *nfile, *file; 381156230Smux int copies; 382156230Smux{ 383156230Smux if (strcmp(nfile, " ") == 0) 384156230Smux nfile = "(standard input)"; 385156230Smux if (lflag) 386156230Smux ldump(nfile, file, copies); 387156230Smux else 388156230Smux dump(nfile, file, copies); 389156230Smux} 390186781Slulf 391156230Smux/* 392156230Smux * Fill the line with blanks to the specified column 393156230Smux */ 394156230Smuxvoid 395156230Smuxblankfill(n) 396156230Smux register int n; 397156230Smux{ 398156230Smux while (col++ < n) 399156230Smux putchar(' '); 400156230Smux} 401156230Smux 402156230Smux/* 403156230Smux * Give the abbreviated dump of the file names 404156230Smux */ 405156230Smuxvoid 406156230Smuxdump(nfile, file, copies) 407156230Smux char *nfile, *file; 408186781Slulf int copies; 409156230Smux{ 410156230Smux register short n, fill; 411156230Smux struct stat lbuf; 412156230Smux 413156230Smux /* 414156701Smux * Print as many files as will fit 415156701Smux * (leaving room for the total size) 416156701Smux */ 417156701Smux fill = first ? 0 : 2; /* fill space for ``, '' */ 418156701Smux if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 419156230Smux if (col < SIZCOL) { 420156230Smux printf(" ..."), col += 4; 421156230Smux blankfill(SIZCOL); 422156230Smux } 423156230Smux } else { 424156230Smux if (first) 425156230Smux first = 0; 426156230Smux else 427156230Smux printf(", "); 428156230Smux printf("%s", nfile); 429156230Smux col += n+fill; 430156230Smux } 431156230Smux seteuid(euid); 432156230Smux if (*file && !stat(file, &lbuf)) 433156230Smux totsize += copies * lbuf.st_size; 434156230Smux seteuid(uid); 435156230Smux} 436156230Smux 437156230Smux/* 438156230Smux * Print the long info about the file 439156230Smux */ 440156230Smuxvoid 441156230Smuxldump(nfile, file, copies) 442156230Smux char *nfile, *file; 443156230Smux int copies; 444156230Smux{ 445156230Smux struct stat lbuf; 446156230Smux 447156230Smux putchar('\t'); 448156230Smux if (copies > 1) 449156230Smux printf("%-2d copies of %-19s", copies, nfile); 450156230Smux else 451156230Smux printf("%-32s", nfile); 452156230Smux if (*file && !stat(file, &lbuf)) 453156230Smux printf(" %qd bytes", lbuf.st_size); 454156230Smux else 455156230Smux printf(" ??? bytes"); 456156230Smux putchar('\n'); 457156230Smux} 458156230Smux 459156230Smux/* 460156230Smux * Print the job's rank in the queue, 461156230Smux * update col for screen management 462186781Slulf */ 463156230Smuxvoid 464156230Smuxprank(n) 465156230Smux int n; 466156230Smux{ 467156701Smux char rline[100]; 468156230Smux static char *r[] = { 469156230Smux "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 470156230Smux }; 471156230Smux 472156230Smux if (n == 0) { 473156230Smux printf("active"); 474156230Smux col += 6; 475156230Smux return; 476156230Smux } 477156230Smux if ((n/10)%10 == 1) 478156230Smux (void)snprintf(rline, sizeof(rline), "%dth", n); 479156230Smux else 480156230Smux (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]); 481186781Slulf col += strlen(rline); 482156230Smux printf("%s", rline); 483156230Smux} 484156701Smux 485156701Smuxvoid 486156701Smuxalarmhandler(signo) 487156230Smux int signo; 488156230Smux{ 489156230Smux /* ignored */ 490156230Smux} 491156230Smux