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