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