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