1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)displayq.c 5.11 (Berkeley) 08/22/89"; 20 #endif /* not lint */ 21 22 /* 23 * Routines to display the state of the queue. 24 */ 25 26 #include "lp.h" 27 #include "pathnames.h" 28 29 #define JOBCOL 40 /* column for job # in -l format */ 30 #define OWNCOL 7 /* start of Owner column in normal */ 31 #define SIZCOL 62 /* start of Size column in normal */ 32 33 /* 34 * Stuff for handling job specifications 35 */ 36 extern char *user[]; /* users to process */ 37 extern int users; /* # of users in user array */ 38 extern int requ[]; /* job number of spool entries */ 39 extern int requests; /* # of spool requests */ 40 41 int lflag; /* long output option */ 42 char current[40]; /* current file being printed */ 43 int garbage; /* # of garbage cf files */ 44 int rank; /* order to be printed (-1=none, 0=active) */ 45 long totsize; /* total print job size in bytes */ 46 int first; /* first file in ``files'' column? */ 47 int col; /* column on screen */ 48 char file[132]; /* print file name */ 49 50 char *head0 = "Rank Owner Job Files"; 51 char *head1 = "Total Size\n"; 52 53 /* 54 * Display the current state of the queue. Format = 1 if long format. 55 */ 56 displayq(format) 57 int format; 58 { 59 register struct queue *q; 60 register int i, nitems, fd; 61 register char *cp; 62 struct queue **queue; 63 struct stat statb; 64 FILE *fp; 65 char c; 66 67 lflag = format; 68 totsize = 0; 69 rank = -1; 70 71 if ((i = pgetent(line, printer)) < 0) 72 fatal("cannot open printer description file"); 73 else if (i == 0) 74 fatal("unknown printer"); 75 if ((LP = pgetstr("lp", &bp)) == NULL) 76 LP = _PATH_DEFDEVLP; 77 if ((RP = pgetstr("rp", &bp)) == NULL) 78 RP = DEFLP; 79 if ((SD = pgetstr("sd", &bp)) == NULL) 80 SD = _PATH_DEFSPOOL; 81 if ((LO = pgetstr("lo", &bp)) == NULL) 82 LO = DEFLOCK; 83 if ((ST = pgetstr("st", &bp)) == NULL) 84 ST = DEFSTAT; 85 RM = pgetstr("rm", &bp); 86 if (cp = checkremote()) 87 printf("Warning: %s\n", cp); 88 89 /* 90 * Print out local queue 91 * Find all the control files in the spooling directory 92 */ 93 if (chdir(SD) < 0) 94 fatal("cannot chdir to spooling directory"); 95 if ((nitems = getq(&queue)) < 0) 96 fatal("cannot examine spooling area\n"); 97 if (stat(LO, &statb) >= 0) { 98 if (statb.st_mode & 0100) { 99 if (sendtorem) 100 printf("%s: ", host); 101 printf("Warning: %s is down: ", printer); 102 fd = open(ST, O_RDONLY); 103 if (fd >= 0) { 104 (void) flock(fd, LOCK_SH); 105 while ((i = read(fd, line, sizeof(line))) > 0) 106 (void) fwrite(line, 1, i, stdout); 107 (void) close(fd); /* unlocks as well */ 108 } else 109 putchar('\n'); 110 } 111 if (statb.st_mode & 010) { 112 if (sendtorem) 113 printf("%s: ", host); 114 printf("Warning: %s queue is turned off\n", printer); 115 } 116 } 117 118 if (nitems) { 119 fp = fopen(LO, "r"); 120 if (fp == NULL) 121 warn(); 122 else { 123 register char *cp; 124 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 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 header() 223 { 224 printf(head0); 225 col = strlen(head0)+1; 226 blankfill(SIZCOL); 227 printf(head1); 228 } 229 230 inform(cf) 231 char *cf; 232 { 233 register int j, k; 234 register char *cp; 235 FILE *cfp; 236 237 /* 238 * There's a chance the control file has gone away 239 * in the meantime; if this is the case just keep going 240 */ 241 if ((cfp = fopen(cf, "r")) == NULL) 242 return; 243 244 if (rank < 0) 245 rank = 0; 246 if (sendtorem || garbage || strcmp(cf, current)) 247 rank++; 248 j = 0; 249 while (getline(cfp)) { 250 switch (line[0]) { 251 case 'P': /* Was this file specified in the user's list? */ 252 if (!inlist(line+1, cf)) { 253 fclose(cfp); 254 return; 255 } 256 if (lflag) { 257 printf("\n%s: ", line+1); 258 col = strlen(line+1) + 2; 259 prank(rank); 260 blankfill(JOBCOL); 261 printf(" [job %s]\n", cf+3); 262 } else { 263 col = 0; 264 prank(rank); 265 blankfill(OWNCOL); 266 printf("%-10s %-3d ", line+1, atoi(cf+3)); 267 col += 16; 268 first = 1; 269 } 270 continue; 271 default: /* some format specifer and file name? */ 272 if (line[0] < 'a' || line[0] > 'z') 273 continue; 274 if (j == 0 || strcmp(file, line+1) != 0) 275 (void) strcpy(file, line+1); 276 j++; 277 continue; 278 case 'N': 279 show(line+1, file, j); 280 file[0] = '\0'; 281 j = 0; 282 } 283 } 284 fclose(cfp); 285 if (!lflag) { 286 blankfill(SIZCOL); 287 printf("%ld bytes\n", totsize); 288 totsize = 0; 289 } 290 } 291 292 inlist(name, file) 293 char *name, *file; 294 { 295 register int *r, n; 296 register char **u, *cp; 297 298 if (users == 0 && requests == 0) 299 return(1); 300 /* 301 * Check to see if it's in the user list 302 */ 303 for (u = user; u < &user[users]; u++) 304 if (!strcmp(*u, name)) 305 return(1); 306 /* 307 * Check the request list 308 */ 309 for (n = 0, cp = file+3; isdigit(*cp); ) 310 n = n * 10 + (*cp++ - '0'); 311 for (r = requ; r < &requ[requests]; r++) 312 if (*r == n && !strcmp(cp, from)) 313 return(1); 314 return(0); 315 } 316 317 show(nfile, file, copies) 318 register char *nfile, *file; 319 { 320 if (strcmp(nfile, " ") == 0) 321 nfile = "(standard input)"; 322 if (lflag) 323 ldump(nfile, file, copies); 324 else 325 dump(nfile, file, copies); 326 } 327 328 /* 329 * Fill the line with blanks to the specified column 330 */ 331 blankfill(n) 332 register int n; 333 { 334 while (col++ < n) 335 putchar(' '); 336 } 337 338 /* 339 * Give the abbreviated dump of the file names 340 */ 341 dump(nfile, file, copies) 342 char *nfile, *file; 343 { 344 register short n, fill; 345 struct stat lbuf; 346 347 /* 348 * Print as many files as will fit 349 * (leaving room for the total size) 350 */ 351 fill = first ? 0 : 2; /* fill space for ``, '' */ 352 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 353 if (col < SIZCOL) { 354 printf(" ..."), col += 4; 355 blankfill(SIZCOL); 356 } 357 } else { 358 if (first) 359 first = 0; 360 else 361 printf(", "); 362 printf("%s", nfile); 363 col += n+fill; 364 } 365 if (*file && !stat(file, &lbuf)) 366 totsize += copies * lbuf.st_size; 367 } 368 369 /* 370 * Print the long info about the file 371 */ 372 ldump(nfile, file, copies) 373 char *nfile, *file; 374 { 375 struct stat lbuf; 376 377 putchar('\t'); 378 if (copies > 1) 379 printf("%-2d copies of %-19s", copies, nfile); 380 else 381 printf("%-32s", nfile); 382 if (*file && !stat(file, &lbuf)) 383 printf(" %ld bytes", lbuf.st_size); 384 else 385 printf(" ??? bytes"); 386 putchar('\n'); 387 } 388 389 /* 390 * Print the job's rank in the queue, 391 * update col for screen management 392 */ 393 prank(n) 394 { 395 char line[100]; 396 static char *r[] = { 397 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 398 }; 399 400 if (n == 0) { 401 printf("active"); 402 col += 6; 403 return; 404 } 405 if ((n/10)%10 == 1) 406 (void) sprintf(line, "%dth", n); 407 else 408 (void) sprintf(line, "%d%s", n, r[n%10]); 409 col += strlen(line); 410 printf("%s", line); 411 } 412