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