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