displayq.c revision 22466
1/* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35static char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95"; 36#endif /* not lint */ 37 38#include <sys/param.h> 39#include <sys/stat.h> 40#include <sys/file.h> 41 42#include <signal.h> 43#include <fcntl.h> 44#include <dirent.h> 45#include <unistd.h> 46#include <stdio.h> 47#include <stdlib.h> 48#include <string.h> 49#include <ctype.h> 50#include "lp.h" 51#include "lp.local.h" 52#include "pathnames.h" 53 54/* 55 * Routines to display the state of the queue. 56 */ 57#define JOBCOL 40 /* column for job # in -l format */ 58#define OWNCOL 7 /* start of Owner column in normal */ 59#define SIZCOL 62 /* start of Size column in normal */ 60 61/* 62 * Stuff for handling job specifications 63 */ 64static int col; /* column on screen */ 65static char current[40]; /* current file being printed */ 66static char file[132]; /* print file name */ 67static int first; /* first file in ``files'' column? */ 68static int garbage; /* # of garbage cf files */ 69static int lflag; /* long output option */ 70static int rank; /* order to be printed (-1=none, 0=active) */ 71static long totsize; /* total print job size in bytes */ 72 73static char *head0 = "Rank Owner Job Files"; 74static char *head1 = "Total Size\n"; 75 76/* 77 * Display the current state of the queue. Format = 1 if long format. 78 */ 79void 80displayq(format) 81 int format; 82{ 83 register struct queue *q; 84 register int i, nitems, fd; 85 register char *cp; 86 struct queue **queue; 87 struct stat statb; 88 FILE *fp; 89 90 lflag = format; 91 totsize = 0; 92 rank = -1; 93 if ((i = cgetent(&bp, printcapdb, printer)) == -2) 94 fatal("can't open printer description file"); 95 else if (i == -1) 96 fatal("unknown printer"); 97 else if (i == -3) 98 fatal("potential reference loop detected in printcap file"); 99 if (cgetstr(bp, "lp", &LP) < 0) 100 LP = _PATH_DEFDEVLP; 101 if (cgetstr(bp, "rp", &RP) < 0) 102 RP = DEFLP; 103 if (cgetstr(bp, "sd", &SD) < 0) 104 SD = _PATH_DEFSPOOL; 105 if (cgetstr(bp,"lo", &LO) < 0) 106 LO = DEFLOCK; 107 if (cgetstr(bp, "st", &ST) < 0) 108 ST = DEFSTAT; 109 cgetstr(bp, "rm", &RM); 110 if (cp = checkremote()) 111 printf("Warning: %s\n", cp); 112 113 /* 114 * Print out local queue 115 * Find all the control files in the spooling directory 116 */ 117 if (chdir(SD) < 0) 118 fatal("cannot chdir to spooling directory"); 119 if ((nitems = getq(&queue)) < 0) 120 fatal("cannot examine spooling area\n"); 121 if (stat(LO, &statb) >= 0) { 122 if (statb.st_mode & 0100) { 123 if (remote) 124 printf("%s: ", host); 125 printf("Warning: %s is down: ", printer); 126 fd = open(ST, O_RDONLY); 127 if (fd >= 0) { 128 (void) flock(fd, LOCK_SH); 129 while ((i = read(fd, line, sizeof(line))) > 0) 130 (void) fwrite(line, 1, i, stdout); 131 (void) close(fd); /* unlocks as well */ 132 } else 133 putchar('\n'); 134 } 135 if (statb.st_mode & 010) { 136 if (remote) 137 printf("%s: ", host); 138 printf("Warning: %s queue is turned off\n", printer); 139 } 140 } 141 142 if (nitems) { 143 fp = fopen(LO, "r"); 144 if (fp == NULL) 145 warn(); 146 else { 147 /* get daemon pid */ 148 cp = current; 149 while ((i = getc(fp)) != EOF && i != '\n') 150 *cp++ = i; 151 *cp = '\0'; 152 i = atoi(current); 153 if (i <= 0 || kill(i, 0) < 0) 154 warn(); 155 else { 156 /* read current file name */ 157 cp = current; 158 while ((i = getc(fp)) != EOF && i != '\n') 159 *cp++ = i; 160 *cp = '\0'; 161 /* 162 * Print the status file. 163 */ 164 if (remote) 165 printf("%s: ", host); 166 fd = open(ST, O_RDONLY); 167 if (fd >= 0) { 168 (void) flock(fd, LOCK_SH); 169 while ((i = read(fd, line, sizeof(line))) > 0) 170 (void) fwrite(line, 1, i, stdout); 171 (void) close(fd); /* unlocks as well */ 172 } else 173 putchar('\n'); 174 } 175 (void) fclose(fp); 176 } 177 /* 178 * Now, examine the control files and print out the jobs to 179 * be done for each user. 180 */ 181 if (!lflag) 182 header(); 183 for (i = 0; i < nitems; i++) { 184 q = queue[i]; 185 inform(q->q_name); 186 free(q); 187 } 188 free(queue); 189 } 190 if (!remote) { 191 if (nitems == 0) 192 puts("no entries"); 193 return; 194 } 195 196 /* 197 * Print foreign queue 198 * Note that a file in transit may show up in either queue. 199 */ 200 if (nitems) 201 putchar('\n'); 202 (void) snprintf(line, sizeof(line), "%c%s", format + '\3', RP); 203 cp = line; 204 for (i = 0; i < requests && cp-line+10 < sizeof(line); i++) { 205 cp += strlen(cp); 206 (void) sprintf(cp, " %d", requ[i]); 207 } 208 for (i = 0; i < users && cp - line + 1 + strlen(user[i]) < 209 sizeof(line); i++) { 210 cp += strlen(cp); 211 *cp++ = ' '; 212 (void) strcpy(cp, user[i]); 213 } 214 strcat(line, "\n"); 215 fd = getport(RM, 0); 216 if (fd < 0) { 217 if (from != host) 218 printf("%s: ", host); 219 printf("connection to %s is down\n", RM); 220 } 221 else { 222 i = strlen(line); 223 if (write(fd, line, i) != i) 224 fatal("Lost connection"); 225 while ((i = read(fd, line, sizeof(line))) > 0) 226 (void) fwrite(line, 1, i, stdout); 227 (void) close(fd); 228 } 229} 230 231/* 232 * Print a warning message if there is no daemon present. 233 */ 234void 235warn() 236{ 237 if (remote) 238 printf("\n%s: ", host); 239 puts("Warning: no daemon present"); 240 current[0] = '\0'; 241} 242 243/* 244 * Print the header for the short listing format 245 */ 246void 247header() 248{ 249 printf(head0); 250 col = strlen(head0)+1; 251 blankfill(SIZCOL); 252 printf(head1); 253} 254 255void 256inform(cf) 257 char *cf; 258{ 259 register int j; 260 FILE *cfp; 261 262 /* 263 * There's a chance the control file has gone away 264 * in the meantime; if this is the case just keep going 265 */ 266 if ((cfp = fopen(cf, "r")) == NULL) 267 return; 268 269 if (rank < 0) 270 rank = 0; 271 if (remote || garbage || strcmp(cf, current)) 272 rank++; 273 j = 0; 274 while (getline(cfp)) { 275 switch (line[0]) { 276 case 'P': /* Was this file specified in the user's list? */ 277 if (!inlist(line+1, cf)) { 278 fclose(cfp); 279 return; 280 } 281 if (lflag) { 282 printf("\n%s: ", line+1); 283 col = strlen(line+1) + 2; 284 prank(rank); 285 blankfill(JOBCOL); 286 printf(" [job %s]\n", cf+3); 287 } else { 288 col = 0; 289 prank(rank); 290 blankfill(OWNCOL); 291 printf("%-10s %-3d ", line+1, atoi(cf+3)); 292 col += 16; 293 first = 1; 294 } 295 continue; 296 default: /* some format specifer and file name? */ 297 if (line[0] < 'a' || line[0] > 'z') 298 continue; 299 if (j == 0 || strcmp(file, line+1) != 0) { 300 (void) strncpy(file, line+1, sizeof(file) - 1); 301 file[sizeof(file) - 1] = '\0'; 302 } 303 j++; 304 continue; 305 case 'N': 306 show(line+1, file, j); 307 file[0] = '\0'; 308 j = 0; 309 } 310 } 311 fclose(cfp); 312 if (!lflag) { 313 blankfill(SIZCOL); 314 printf("%ld bytes\n", totsize); 315 totsize = 0; 316 } 317} 318 319int 320inlist(name, file) 321 char *name, *file; 322{ 323 register int *r, n; 324 register char **u, *cp; 325 326 if (users == 0 && requests == 0) 327 return(1); 328 /* 329 * Check to see if it's in the user list 330 */ 331 for (u = user; u < &user[users]; u++) 332 if (!strcmp(*u, name)) 333 return(1); 334 /* 335 * Check the request list 336 */ 337 for (n = 0, cp = file+3; isdigit(*cp); ) 338 n = n * 10 + (*cp++ - '0'); 339 for (r = requ; r < &requ[requests]; r++) 340 if (*r == n && !strcmp(cp, from)) 341 return(1); 342 return(0); 343} 344 345void 346show(nfile, file, copies) 347 register char *nfile, *file; 348 int copies; 349{ 350 if (strcmp(nfile, " ") == 0) 351 nfile = "(standard input)"; 352 if (lflag) 353 ldump(nfile, file, copies); 354 else 355 dump(nfile, file, copies); 356} 357 358/* 359 * Fill the line with blanks to the specified column 360 */ 361void 362blankfill(n) 363 register int n; 364{ 365 while (col++ < n) 366 putchar(' '); 367} 368 369/* 370 * Give the abbreviated dump of the file names 371 */ 372void 373dump(nfile, file, copies) 374 char *nfile, *file; 375 int copies; 376{ 377 register short n, fill; 378 struct stat lbuf; 379 380 /* 381 * Print as many files as will fit 382 * (leaving room for the total size) 383 */ 384 fill = first ? 0 : 2; /* fill space for ``, '' */ 385 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 386 if (col < SIZCOL) { 387 printf(" ..."), col += 4; 388 blankfill(SIZCOL); 389 } 390 } else { 391 if (first) 392 first = 0; 393 else 394 printf(", "); 395 printf("%s", nfile); 396 col += n+fill; 397 } 398 if (*file && !stat(file, &lbuf)) 399 totsize += copies * lbuf.st_size; 400} 401 402/* 403 * Print the long info about the file 404 */ 405void 406ldump(nfile, file, copies) 407 char *nfile, *file; 408 int copies; 409{ 410 struct stat lbuf; 411 412 putchar('\t'); 413 if (copies > 1) 414 printf("%-2d copies of %-19s", copies, nfile); 415 else 416 printf("%-32s", nfile); 417 if (*file && !stat(file, &lbuf)) 418 printf(" %qd bytes", lbuf.st_size); 419 else 420 printf(" ??? bytes"); 421 putchar('\n'); 422} 423 424/* 425 * Print the job's rank in the queue, 426 * update col for screen management 427 */ 428void 429prank(n) 430 int n; 431{ 432 char rline[100]; 433 static char *r[] = { 434 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 435 }; 436 437 if (n == 0) { 438 printf("active"); 439 col += 6; 440 return; 441 } 442 if ((n/10)%10 == 1) 443 (void)snprintf(rline, sizeof(rline), "%dth", n); 444 else 445 (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]); 446 col += strlen(rline); 447 printf("%s", rline); 448} 449