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