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