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