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