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