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 this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #ifndef lint 14 static char sccsid[] = "@(#)displayq.c 5.7 (Berkeley) 06/01/88"; 15 #endif /* not lint */ 16 17 /* 18 * Routines to display the state of the queue. 19 */ 20 21 #include "lp.h" 22 23 #define JOBCOL 40 /* column for job # in -l format */ 24 #define OWNCOL 7 /* start of Owner column in normal */ 25 #define SIZCOL 62 /* start of Size column in normal */ 26 27 /* 28 * Stuff for handling job specifications 29 */ 30 extern char *user[]; /* users to process */ 31 extern int users; /* # of users in user array */ 32 extern int requ[]; /* job number of spool entries */ 33 extern int requests; /* # of spool requests */ 34 35 int lflag; /* long output option */ 36 char current[40]; /* current file being printed */ 37 int garbage; /* # of garbage cf files */ 38 int rank; /* order to be printed (-1=none, 0=active) */ 39 long totsize; /* total print job size in bytes */ 40 int first; /* first file in ``files'' column? */ 41 int col; /* column on screen */ 42 int sendtorem; /* are we sending to a remote? */ 43 char file[132]; /* print file name */ 44 45 char *head0 = "Rank Owner Job Files"; 46 char *head1 = "Total Size\n"; 47 48 /* 49 * Display the current state of the queue. Format = 1 if long format. 50 */ 51 displayq(format) 52 int format; 53 { 54 register struct queue *q; 55 register int i, nitems, fd; 56 register char *cp; 57 struct queue **queue; 58 struct stat statb; 59 FILE *fp; 60 char c; 61 62 lflag = format; 63 totsize = 0; 64 rank = -1; 65 66 if ((i = pgetent(line, printer)) < 0) 67 fatal("cannot open printer description file"); 68 else if (i == 0) 69 fatal("unknown printer"); 70 if ((LP = pgetstr("lp", &bp)) == NULL) 71 LP = DEFDEVLP; 72 if ((RP = pgetstr("rp", &bp)) == NULL) 73 RP = DEFLP; 74 if ((SD = pgetstr("sd", &bp)) == NULL) 75 SD = DEFSPOOL; 76 if ((LO = pgetstr("lo", &bp)) == NULL) 77 LO = DEFLOCK; 78 if ((ST = pgetstr("st", &bp)) == NULL) 79 ST = DEFSTAT; 80 RM = pgetstr("rm", &bp); 81 82 /* 83 * Figure out whether the local machine is the same as the remote 84 * machine entry (if it exists). If not, then ignore the local 85 * queue information. 86 */ 87 if (RM != (char *) NULL) { 88 char name[256]; 89 struct hostent *hp; 90 91 /* get the standard network name of the local host */ 92 gethostname(name, sizeof(name)); 93 name[sizeof(name)-1] = '\0'; 94 hp = gethostbyname(name); 95 if (hp == (struct hostent *) NULL) { 96 printf("unable to get network name for local machine %s\n", 97 name); 98 goto localcheck_done; 99 } else (void) strcpy(name, hp->h_name); 100 101 /* get the network standard name of RM */ 102 hp = gethostbyname(RM); 103 if (hp == (struct hostent *) NULL) { 104 printf("unable to get hostname for remote machine %s\n", 105 RM); 106 goto localcheck_done; 107 } 108 109 /* if printer is not on local machine, ignore LP */ 110 if (strcmp(name, hp->h_name)) { 111 *LP = '\0'; 112 ++sendtorem; 113 } 114 } 115 localcheck_done: 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 register char *cp; 152 153 /* get daemon pid */ 154 cp = current; 155 while ((*cp = getc(fp)) != EOF && *cp != '\n') 156 cp++; 157 *cp = '\0'; 158 i = atoi(current); 159 if (i <= 0 || kill(i, 0) < 0) 160 warn(); 161 else { 162 /* read current file name */ 163 cp = current; 164 while ((*cp = getc(fp)) != EOF && *cp != '\n') 165 cp++; 166 *cp = '\0'; 167 /* 168 * Print the status file. 169 */ 170 if (sendtorem) 171 printf("%s: ", host); 172 fd = open(ST, O_RDONLY); 173 if (fd >= 0) { 174 (void) flock(fd, LOCK_SH); 175 while ((i = read(fd, line, sizeof(line))) > 0) 176 (void) fwrite(line, 1, i, stdout); 177 (void) close(fd); /* unlocks as well */ 178 } else 179 putchar('\n'); 180 } 181 (void) fclose(fp); 182 } 183 /* 184 * Now, examine the control files and print out the jobs to 185 * be done for each user. 186 */ 187 if (!lflag) 188 header(); 189 for (i = 0; i < nitems; i++) { 190 q = queue[i]; 191 inform(q->q_name); 192 free(q); 193 } 194 free(queue); 195 } 196 if (!sendtorem) { 197 if (nitems == 0) 198 puts("no entries"); 199 return; 200 } 201 202 /* 203 * Print foreign queue 204 * Note that a file in transit may show up in either queue. 205 */ 206 if (nitems) 207 putchar('\n'); 208 (void) sprintf(line, "%c%s", format + '\3', RP); 209 cp = line; 210 for (i = 0; i < requests; i++) { 211 cp += strlen(cp); 212 (void) sprintf(cp, " %d", requ[i]); 213 } 214 for (i = 0; i < users; i++) { 215 cp += strlen(cp); 216 *cp++ = ' '; 217 (void) strcpy(cp, user[i]); 218 } 219 strcat(line, "\n"); 220 fd = getport(RM); 221 if (fd < 0) { 222 if (from != host) 223 printf("%s: ", host); 224 printf("connection to %s is down\n", RM); 225 } 226 else { 227 i = strlen(line); 228 if (write(fd, line, i) != i) 229 fatal("Lost connection"); 230 while ((i = read(fd, line, sizeof(line))) > 0) 231 (void) fwrite(line, 1, i, stdout); 232 (void) close(fd); 233 } 234 } 235 236 /* 237 * Print a warning message if there is no daemon present. 238 */ 239 warn() 240 { 241 if (sendtorem) 242 printf("\n%s: ", host); 243 puts("Warning: no daemon present"); 244 current[0] = '\0'; 245 } 246 247 /* 248 * Print the header for the short listing format 249 */ 250 header() 251 { 252 printf(head0); 253 col = strlen(head0)+1; 254 blankfill(SIZCOL); 255 printf(head1); 256 } 257 258 inform(cf) 259 char *cf; 260 { 261 register int j, k; 262 register char *cp; 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 320 inlist(name, file) 321 char *name, *file; 322 { 323 register int *r, n; 324 register char **u, *cp; 325 326 if (users == 0 && requests == 0) 327 return(1); 328 /* 329 * Check to see if it's in the user list 330 */ 331 for (u = user; u < &user[users]; u++) 332 if (!strcmp(*u, name)) 333 return(1); 334 /* 335 * Check the request list 336 */ 337 for (n = 0, cp = file+3; isdigit(*cp); ) 338 n = n * 10 + (*cp++ - '0'); 339 for (r = requ; r < &requ[requests]; r++) 340 if (*r == n && !strcmp(cp, from)) 341 return(1); 342 return(0); 343 } 344 345 show(nfile, file, copies) 346 register char *nfile, *file; 347 { 348 if (strcmp(nfile, " ") == 0) 349 nfile = "(standard input)"; 350 if (lflag) 351 ldump(nfile, file, copies); 352 else 353 dump(nfile, file, copies); 354 } 355 356 /* 357 * Fill the line with blanks to the specified column 358 */ 359 blankfill(n) 360 register int n; 361 { 362 while (col++ < n) 363 putchar(' '); 364 } 365 366 /* 367 * Give the abbreviated dump of the file names 368 */ 369 dump(nfile, file, copies) 370 char *nfile, *file; 371 { 372 register short n, fill; 373 struct stat lbuf; 374 375 /* 376 * Print as many files as will fit 377 * (leaving room for the total size) 378 */ 379 fill = first ? 0 : 2; /* fill space for ``, '' */ 380 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 381 if (col < SIZCOL) { 382 printf(" ..."), col += 4; 383 blankfill(SIZCOL); 384 } 385 } else { 386 if (first) 387 first = 0; 388 else 389 printf(", "); 390 printf("%s", nfile); 391 col += n+fill; 392 } 393 if (*file && !stat(file, &lbuf)) 394 totsize += copies * lbuf.st_size; 395 } 396 397 /* 398 * Print the long info about the file 399 */ 400 ldump(nfile, file, copies) 401 char *nfile, *file; 402 { 403 struct stat lbuf; 404 405 putchar('\t'); 406 if (copies > 1) 407 printf("%-2d copies of %-19s", copies, nfile); 408 else 409 printf("%-32s", nfile); 410 if (*file && !stat(file, &lbuf)) 411 printf(" %ld bytes", lbuf.st_size); 412 else 413 printf(" ??? bytes"); 414 putchar('\n'); 415 } 416 417 /* 418 * Print the job's rank in the queue, 419 * update col for screen management 420 */ 421 prank(n) 422 { 423 char line[100]; 424 static char *r[] = { 425 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 426 }; 427 428 if (n == 0) { 429 printf("active"); 430 col += 6; 431 return; 432 } 433 if ((n/10) == 1) 434 (void) sprintf(line, "%dth", n); 435 else 436 (void) sprintf(line, "%d%s", n, r[n%10]); 437 col += strlen(line); 438 printf("%s", line); 439 } 440