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.12 (Berkeley) 03/20/90"; 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 /* get daemon pid */ 124 cp = current; 125 while ((*cp = getc(fp)) != EOF && *cp != '\n') 126 cp++; 127 *cp = '\0'; 128 i = atoi(current); 129 if (i <= 0 || kill(i, 0) < 0) 130 warn(); 131 else { 132 /* read current file name */ 133 cp = current; 134 while ((*cp = getc(fp)) != EOF && *cp != '\n') 135 cp++; 136 *cp = '\0'; 137 /* 138 * Print the status file. 139 */ 140 if (sendtorem) 141 printf("%s: ", host); 142 fd = open(ST, O_RDONLY); 143 if (fd >= 0) { 144 (void) flock(fd, LOCK_SH); 145 while ((i = read(fd, line, sizeof(line))) > 0) 146 (void) fwrite(line, 1, i, stdout); 147 (void) close(fd); /* unlocks as well */ 148 } else 149 putchar('\n'); 150 } 151 (void) fclose(fp); 152 } 153 /* 154 * Now, examine the control files and print out the jobs to 155 * be done for each user. 156 */ 157 if (!lflag) 158 header(); 159 for (i = 0; i < nitems; i++) { 160 q = queue[i]; 161 inform(q->q_name); 162 free(q); 163 } 164 free(queue); 165 } 166 if (!sendtorem) { 167 if (nitems == 0) 168 puts("no entries"); 169 return; 170 } 171 172 /* 173 * Print foreign queue 174 * Note that a file in transit may show up in either queue. 175 */ 176 if (nitems) 177 putchar('\n'); 178 (void) sprintf(line, "%c%s", format + '\3', RP); 179 cp = line; 180 for (i = 0; i < requests; i++) { 181 cp += strlen(cp); 182 (void) sprintf(cp, " %d", requ[i]); 183 } 184 for (i = 0; i < users; i++) { 185 cp += strlen(cp); 186 *cp++ = ' '; 187 (void) strcpy(cp, user[i]); 188 } 189 strcat(line, "\n"); 190 fd = getport(RM); 191 if (fd < 0) { 192 if (from != host) 193 printf("%s: ", host); 194 printf("connection to %s is down\n", RM); 195 } 196 else { 197 i = strlen(line); 198 if (write(fd, line, i) != i) 199 fatal("Lost connection"); 200 while ((i = read(fd, line, sizeof(line))) > 0) 201 (void) fwrite(line, 1, i, stdout); 202 (void) close(fd); 203 } 204 } 205 206 /* 207 * Print a warning message if there is no daemon present. 208 */ 209 warn() 210 { 211 if (sendtorem) 212 printf("\n%s: ", host); 213 puts("Warning: no daemon present"); 214 current[0] = '\0'; 215 } 216 217 /* 218 * Print the header for the short listing format 219 */ 220 header() 221 { 222 printf(head0); 223 col = strlen(head0)+1; 224 blankfill(SIZCOL); 225 printf(head1); 226 } 227 228 inform(cf) 229 char *cf; 230 { 231 register int j, k; 232 register char *cp; 233 FILE *cfp; 234 235 /* 236 * There's a chance the control file has gone away 237 * in the meantime; if this is the case just keep going 238 */ 239 if ((cfp = fopen(cf, "r")) == NULL) 240 return; 241 242 if (rank < 0) 243 rank = 0; 244 if (sendtorem || garbage || strcmp(cf, current)) 245 rank++; 246 j = 0; 247 while (getline(cfp)) { 248 switch (line[0]) { 249 case 'P': /* Was this file specified in the user's list? */ 250 if (!inlist(line+1, cf)) { 251 fclose(cfp); 252 return; 253 } 254 if (lflag) { 255 printf("\n%s: ", line+1); 256 col = strlen(line+1) + 2; 257 prank(rank); 258 blankfill(JOBCOL); 259 printf(" [job %s]\n", cf+3); 260 } else { 261 col = 0; 262 prank(rank); 263 blankfill(OWNCOL); 264 printf("%-10s %-3d ", line+1, atoi(cf+3)); 265 col += 16; 266 first = 1; 267 } 268 continue; 269 default: /* some format specifer and file name? */ 270 if (line[0] < 'a' || line[0] > 'z') 271 continue; 272 if (j == 0 || strcmp(file, line+1) != 0) 273 (void) strcpy(file, line+1); 274 j++; 275 continue; 276 case 'N': 277 show(line+1, file, j); 278 file[0] = '\0'; 279 j = 0; 280 } 281 } 282 fclose(cfp); 283 if (!lflag) { 284 blankfill(SIZCOL); 285 printf("%ld bytes\n", totsize); 286 totsize = 0; 287 } 288 } 289 290 inlist(name, file) 291 char *name, *file; 292 { 293 register int *r, n; 294 register char **u, *cp; 295 296 if (users == 0 && requests == 0) 297 return(1); 298 /* 299 * Check to see if it's in the user list 300 */ 301 for (u = user; u < &user[users]; u++) 302 if (!strcmp(*u, name)) 303 return(1); 304 /* 305 * Check the request list 306 */ 307 for (n = 0, cp = file+3; isdigit(*cp); ) 308 n = n * 10 + (*cp++ - '0'); 309 for (r = requ; r < &requ[requests]; r++) 310 if (*r == n && !strcmp(cp, from)) 311 return(1); 312 return(0); 313 } 314 315 show(nfile, file, copies) 316 register char *nfile, *file; 317 { 318 if (strcmp(nfile, " ") == 0) 319 nfile = "(standard input)"; 320 if (lflag) 321 ldump(nfile, file, copies); 322 else 323 dump(nfile, file, copies); 324 } 325 326 /* 327 * Fill the line with blanks to the specified column 328 */ 329 blankfill(n) 330 register int n; 331 { 332 while (col++ < n) 333 putchar(' '); 334 } 335 336 /* 337 * Give the abbreviated dump of the file names 338 */ 339 dump(nfile, file, copies) 340 char *nfile, *file; 341 { 342 register short n, fill; 343 struct stat lbuf; 344 345 /* 346 * Print as many files as will fit 347 * (leaving room for the total size) 348 */ 349 fill = first ? 0 : 2; /* fill space for ``, '' */ 350 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 351 if (col < SIZCOL) { 352 printf(" ..."), col += 4; 353 blankfill(SIZCOL); 354 } 355 } else { 356 if (first) 357 first = 0; 358 else 359 printf(", "); 360 printf("%s", nfile); 361 col += n+fill; 362 } 363 if (*file && !stat(file, &lbuf)) 364 totsize += copies * lbuf.st_size; 365 } 366 367 /* 368 * Print the long info about the file 369 */ 370 ldump(nfile, file, copies) 371 char *nfile, *file; 372 { 373 struct stat lbuf; 374 375 putchar('\t'); 376 if (copies > 1) 377 printf("%-2d copies of %-19s", copies, nfile); 378 else 379 printf("%-32s", nfile); 380 if (*file && !stat(file, &lbuf)) 381 printf(" %ld bytes", lbuf.st_size); 382 else 383 printf(" ??? bytes"); 384 putchar('\n'); 385 } 386 387 /* 388 * Print the job's rank in the queue, 389 * update col for screen management 390 */ 391 prank(n) 392 { 393 char line[100]; 394 static char *r[] = { 395 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 396 }; 397 398 if (n == 0) { 399 printf("active"); 400 col += 6; 401 return; 402 } 403 if ((n/10)%10 == 1) 404 (void) sprintf(line, "%dth", n); 405 else 406 (void) sprintf(line, "%d%s", n, r[n%10]); 407 col += strlen(line); 408 printf("%s", line); 409 } 410