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