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