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 else if (!sendtorem) { 191 puts("no entries"); 192 return; 193 } 194 195 /* 196 * Print foreign queue 197 * Note that a file in transit may show up in either queue. 198 */ 199 if (nitems) 200 putchar('\n'); 201 (void) sprintf(line, "%c%s", format + '\3', RP); 202 cp = line; 203 for (i = 0; i < requests; i++) { 204 cp += strlen(cp); 205 (void) sprintf(cp, " %d", requ[i]); 206 } 207 for (i = 0; i < users; i++) { 208 cp += strlen(cp); 209 *cp++ = ' '; 210 (void) strcpy(cp, user[i]); 211 } 212 strcat(line, "\n"); 213 fd = getport(RM); 214 if (fd < 0) { 215 if (from != host) 216 printf("%s: ", host); 217 printf("connection to %s is down\n", RM); 218 } 219 else { 220 i = strlen(line); 221 if (write(fd, line, i) != i) 222 fatal("Lost connection"); 223 while ((i = read(fd, line, sizeof(line))) > 0) 224 (void) fwrite(line, 1, i, stdout); 225 (void) close(fd); 226 } 227 } 228 229 /* 230 * Print a warning message if there is no daemon present. 231 */ 232 warn() 233 { 234 if (sendtorem) 235 printf("\n%s: ", host); 236 puts("Warning: no daemon present"); 237 current[0] = '\0'; 238 } 239 240 /* 241 * Print the header for the short listing format 242 */ 243 header() 244 { 245 printf(head0); 246 col = strlen(head0)+1; 247 blankfill(SIZCOL); 248 printf(head1); 249 } 250 251 inform(cf) 252 char *cf; 253 { 254 register int j, k; 255 register char *cp; 256 FILE *cfp; 257 258 /* 259 * There's a chance the control file has gone away 260 * in the meantime; if this is the case just keep going 261 */ 262 if ((cfp = fopen(cf, "r")) == NULL) 263 return; 264 265 if (rank < 0) 266 rank = 0; 267 if (sendtorem || garbage || strcmp(cf, current)) 268 rank++; 269 j = 0; 270 while (getline(cfp)) { 271 switch (line[0]) { 272 case 'P': /* Was this file specified in the user's list? */ 273 if (!inlist(line+1, cf)) { 274 fclose(cfp); 275 return; 276 } 277 if (lflag) { 278 printf("\n%s: ", line+1); 279 col = strlen(line+1) + 2; 280 prank(rank); 281 blankfill(JOBCOL); 282 printf(" [job %s]\n", cf+3); 283 } else { 284 col = 0; 285 prank(rank); 286 blankfill(OWNCOL); 287 printf("%-10s %-3d ", line+1, atoi(cf+3)); 288 col += 16; 289 first = 1; 290 } 291 continue; 292 default: /* some format specifer and file name? */ 293 if (line[0] < 'a' || line[0] > 'z') 294 continue; 295 if (j == 0 || strcmp(file, line+1) != 0) 296 (void) strcpy(file, line+1); 297 j++; 298 continue; 299 case 'N': 300 show(line+1, file, j); 301 file[0] = '\0'; 302 j = 0; 303 } 304 } 305 fclose(cfp); 306 if (!lflag) { 307 blankfill(SIZCOL); 308 printf("%D bytes\n", totsize); 309 totsize = 0; 310 } 311 } 312 313 inlist(name, file) 314 char *name, *file; 315 { 316 register int *r, n; 317 register char **u, *cp; 318 319 if (users == 0 && requests == 0) 320 return(1); 321 /* 322 * Check to see if it's in the user list 323 */ 324 for (u = user; u < &user[users]; u++) 325 if (!strcmp(*u, name)) 326 return(1); 327 /* 328 * Check the request list 329 */ 330 for (n = 0, cp = file+3; isdigit(*cp); ) 331 n = n * 10 + (*cp++ - '0'); 332 for (r = requ; r < &requ[requests]; r++) 333 if (*r == n && !strcmp(cp, from)) 334 return(1); 335 return(0); 336 } 337 338 show(nfile, file, copies) 339 register char *nfile, *file; 340 { 341 if (strcmp(nfile, " ") == 0) 342 nfile = "(standard input)"; 343 if (lflag) 344 ldump(nfile, file, copies); 345 else 346 dump(nfile, file, copies); 347 } 348 349 /* 350 * Fill the line with blanks to the specified column 351 */ 352 blankfill(n) 353 register int n; 354 { 355 while (col++ < n) 356 putchar(' '); 357 } 358 359 /* 360 * Give the abbreviated dump of the file names 361 */ 362 dump(nfile, file, copies) 363 char *nfile, *file; 364 { 365 register short n, fill; 366 struct stat lbuf; 367 368 /* 369 * Print as many files as will fit 370 * (leaving room for the total size) 371 */ 372 fill = first ? 0 : 2; /* fill space for ``, '' */ 373 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 374 if (col < SIZCOL) { 375 printf(" ..."), col += 4; 376 blankfill(SIZCOL); 377 } 378 } else { 379 if (first) 380 first = 0; 381 else 382 printf(", "); 383 printf("%s", nfile); 384 col += n+fill; 385 } 386 if (*file && !stat(file, &lbuf)) 387 totsize += copies * lbuf.st_size; 388 } 389 390 /* 391 * Print the long info about the file 392 */ 393 ldump(nfile, file, copies) 394 char *nfile, *file; 395 { 396 struct stat lbuf; 397 398 putchar('\t'); 399 if (copies > 1) 400 printf("%-2d copies of %-19s", copies, nfile); 401 else 402 printf("%-32s", nfile); 403 if (*file && !stat(file, &lbuf)) 404 printf(" %D bytes", lbuf.st_size); 405 else 406 printf(" ??? bytes"); 407 putchar('\n'); 408 } 409 410 /* 411 * Print the job's rank in the queue, 412 * update col for screen management 413 */ 414 prank(n) 415 { 416 char line[100]; 417 static char *r[] = { 418 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 419 }; 420 421 if (n == 0) { 422 printf("active"); 423 col += 6; 424 return; 425 } 426 if ((n/10) == 1) 427 (void) sprintf(line, "%dth", n); 428 else 429 (void) sprintf(line, "%d%s", n, r[n%10]); 430 col += strlen(line); 431 printf("%s", line); 432 } 433