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