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