displayq.c revision 1.9
1/* $OpenBSD: displayq.c,v 1.9 1998/02/27 11:33:41 deraadt 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 char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95"; 39#else 40static char rcsid[] = "$OpenBSD: displayq.c,v 1.9 1998/02/27 11:33:41 deraadt 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[40]; /* current file being printed */ 79static char file[132]; /* 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 register struct queue *q; 97 register int i, nitems, fd, ret, len; 98 register char *cp; 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 while ((i = getc(fp)) != EOF && i != '\n') 172 *cp++ = i; 173 *cp = '\0'; 174 i = atoi(current); 175 if (i <= 0) { 176 ret = -1; 177 } else { 178 seteuid(euid); 179 ret = kill(i, 0); 180 seteuid(uid); 181 } 182 if (ret < 0) { 183 warn(); 184 } else { 185 /* read current file name */ 186 cp = current; 187 while ((i = getc(fp)) != EOF && i != '\n') 188 *cp++ = i; 189 *cp = '\0'; 190 /* 191 * Print the status file. 192 */ 193 if (remote) 194 printf("%s: ", host); 195 seteuid(euid); 196 fd = open(ST, O_RDONLY); 197 seteuid(uid); 198 if (fd >= 0) { 199 (void) flock(fd, LOCK_SH); 200 while ((i = read(fd, line, sizeof(line))) > 0) 201 (void) fwrite(line, 1, i, stdout); 202 (void) close(fd); /* unlocks as well */ 203 } else 204 putchar('\n'); 205 } 206 (void) fclose(fp); 207 } 208 /* 209 * Now, examine the control files and print out the jobs to 210 * be done for each user. 211 */ 212 if (!lflag) 213 header(); 214 for (i = 0; i < nitems; i++) { 215 q = queue[i]; 216 inform(q->q_name); 217 free(q); 218 } 219 free(queue); 220 } 221 if (!remote) { 222 if (nitems == 0) 223 puts("no entries"); 224 return; 225 } 226 227 /* 228 * Print foreign queue 229 * Note that a file in transit may show up in either queue. 230 */ 231 if (nitems) 232 putchar('\n'); 233 (void) snprintf(line, sizeof line, "%c%s", format + '\3', RP); 234 cp = line; 235 cp += strlen(cp); 236 for (i = 0; i < requests && cp-line < sizeof(line) - 1; i++) { 237 len = line + sizeof line - cp; 238 if (snprintf(cp, len, " %d", requ[i]) > len) { 239 cp += strlen(cp); 240 break; 241 } 242 cp += strlen(cp); 243 } 244 for (i = 0; i < users && cp-line < sizeof(line) - 1; i++) { 245 len = line + sizeof line - cp; 246 if (snprintf(cp, len, " %s", user[i]) > len) { 247 cp += strlen(cp); 248 break; 249 } 250 } 251 if (cp-line < sizeof(line) - 1) { 252 strcat(line, "\n"); 253 } else { 254 line[sizeof line-2] = '\n'; 255 } 256 fd = getport(RM, 0); 257 if (fd < 0) { 258 if (from != host) 259 printf("%s: ", host); 260 printf("connection to %s is down\n", RM); 261 } 262 else { 263 i = strlen(line); 264 if (write(fd, line, i) != i) 265 fatal("Lost connection"); 266 while ((i = read(fd, line, sizeof(line))) > 0) 267 (void) fwrite(line, 1, i, stdout); 268 (void) close(fd); 269 } 270} 271 272/* 273 * Print a warning message if there is no daemon present. 274 */ 275void 276warn() 277{ 278 if (remote) 279 printf("\n%s: ", host); 280 puts("Warning: no daemon present"); 281 current[0] = '\0'; 282} 283 284/* 285 * Print the header for the short listing format 286 */ 287void 288header() 289{ 290 printf(head0); 291 col = strlen(head0)+1; 292 blankfill(SIZCOL); 293 printf(head1); 294} 295 296void 297inform(cf) 298 char *cf; 299{ 300 register int j; 301 FILE *cfp; 302 303 /* 304 * There's a chance the control file has gone away 305 * in the meantime; if this is the case just keep going 306 */ 307 seteuid(euid); 308 if ((cfp = fopen(cf, "r")) == NULL) 309 return; 310 seteuid(uid); 311 312 if (rank < 0) 313 rank = 0; 314 if (remote || garbage || strcmp(cf, current)) 315 rank++; 316 j = 0; 317 while (getline(cfp)) { 318 switch (line[0]) { 319 case 'P': /* Was this file specified in the user's list? */ 320 if (!inlist(line+1, cf)) { 321 fclose(cfp); 322 return; 323 } 324 if (lflag) { 325 printf("\n%s: ", line+1); 326 col = strlen(line+1) + 2; 327 prank(rank); 328 blankfill(JOBCOL); 329 printf(" [job %s]\n", cf+3); 330 } else { 331 col = 0; 332 prank(rank); 333 blankfill(OWNCOL); 334 printf("%-10s %-3d ", line+1, atoi(cf+3)); 335 col += 16; 336 first = 1; 337 } 338 continue; 339 default: /* some format specifer and file name? */ 340 if (line[0] < 'a' || line[0] > 'z') 341 continue; 342 if (j == 0 || strcmp(file, line+1) != 0) { 343 (void) strncpy(file, line+1, sizeof(file) - 1); 344 file[sizeof(file) - 1] = '\0'; 345 } 346 j++; 347 continue; 348 case 'N': 349 show(line+1, file, j); 350 file[0] = '\0'; 351 j = 0; 352 } 353 } 354 fclose(cfp); 355 if (!lflag) { 356 blankfill(SIZCOL); 357 printf("%ld bytes\n", totsize); 358 totsize = 0; 359 } 360} 361 362int 363inlist(name, file) 364 char *name, *file; 365{ 366 register int *r, n; 367 register char **u, *cp; 368 369 if (users == 0 && requests == 0) 370 return(1); 371 /* 372 * Check to see if it's in the user list 373 */ 374 for (u = user; u < &user[users]; u++) 375 if (!strcmp(*u, name)) 376 return(1); 377 /* 378 * Check the request list 379 */ 380 for (n = 0, cp = file+3; isdigit(*cp); ) 381 n = n * 10 + (*cp++ - '0'); 382 for (r = requ; r < &requ[requests]; r++) 383 if (*r == n && !strcmp(cp, from)) 384 return(1); 385 return(0); 386} 387 388void 389show(nfile, file, copies) 390 register char *nfile, *file; 391 int copies; 392{ 393 if (strcmp(nfile, " ") == 0) 394 nfile = "(standard input)"; 395 if (lflag) 396 ldump(nfile, file, copies); 397 else 398 dump(nfile, file, copies); 399} 400 401/* 402 * Fill the line with blanks to the specified column 403 */ 404void 405blankfill(n) 406 register int n; 407{ 408 while (col++ < n) 409 putchar(' '); 410} 411 412/* 413 * Give the abbreviated dump of the file names 414 */ 415void 416dump(nfile, file, copies) 417 char *nfile, *file; 418 int copies; 419{ 420 register short n, fill; 421 struct stat lbuf; 422 423 /* 424 * Print as many files as will fit 425 * (leaving room for the total size) 426 */ 427 fill = first ? 0 : 2; /* fill space for ``, '' */ 428 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 429 if (col < SIZCOL) { 430 printf(" ..."), col += 4; 431 blankfill(SIZCOL); 432 } 433 } else { 434 if (first) 435 first = 0; 436 else 437 printf(", "); 438 printf("%s", nfile); 439 col += n+fill; 440 } 441 seteuid(euid); 442 if (*file && !stat(file, &lbuf)) 443 totsize += copies * lbuf.st_size; 444 seteuid(uid); 445} 446 447/* 448 * Print the long info about the file 449 */ 450void 451ldump(nfile, file, copies) 452 char *nfile, *file; 453 int copies; 454{ 455 struct stat lbuf; 456 457 putchar('\t'); 458 if (copies > 1) 459 printf("%-2d copies of %-19s", copies, nfile); 460 else 461 printf("%-32s", nfile); 462 if (*file && !stat(file, &lbuf)) 463 printf(" %qd bytes", lbuf.st_size); 464 else 465 printf(" ??? bytes"); 466 putchar('\n'); 467} 468 469/* 470 * Print the job's rank in the queue, 471 * update col for screen management 472 */ 473void 474prank(n) 475 int n; 476{ 477 char rline[100]; 478 static char *r[] = { 479 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 480 }; 481 482 if (n == 0) { 483 printf("active"); 484 col += 6; 485 return; 486 } 487 if ((n/10)%10 == 1) 488 (void)snprintf(rline, sizeof(rline), "%dth", n); 489 else 490 (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]); 491 col += strlen(rline); 492 printf("%s", rline); 493} 494