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