1 /* displayq.c 4.2 83/05/13 */ 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 11 /* 12 * Stuff for handling job specifications 13 */ 14 extern char *user[]; /* users to process */ 15 extern int users; /* # of users in user array */ 16 extern int requ[]; /* job number of spool entries */ 17 extern int requests; /* # of spool requests */ 18 19 int lflag; /* long output option */ 20 char current[40]; /* current file being printed */ 21 int garbage; /* # of garbage cf files */ 22 int rank; /* order to be printed (-1=none, 0=active) */ 23 long totsize; /* total print job size in bytes */ 24 int first; /* first file in ``files'' column? */ 25 int col; /* column on screen */ 26 int SIZCOL = 62; /* start of Size column in normal */ 27 int sendtorem; /* are we sending to a remote? */ 28 char file[132]; /* print file name */ 29 30 char *head0 = "Rank Owner Job Files"; 31 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(); 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 (nitems == 0) { 109 if (sendtorem) 110 printf("\n%s: ", host); 111 printf("no entries\n"); 112 return(0); 113 } 114 fp = fopen(LO, "r"); 115 if (fp == NULL || flock(fileno(fp), FSHLOCK|FNBLOCK) == 0) { 116 if (fp != NULL) 117 fclose(fp); 118 garbage = nitems; 119 if (stat(LO, &statb) >= 0 && (statb.st_mode & 0100)) 120 printf("Warning: %s is down\n", printer); 121 else 122 printf("Warning: no daemon present\n"); 123 } else { 124 register char *cp = current; 125 126 /* skip daemon pid */ 127 while ((*cp = getc(fp)) != EOF && *cp != '\n'); 128 /* read current file name */ 129 while ((*cp = getc(fp)) != EOF && *cp != '\n') 130 cp++; 131 *cp = '\0'; 132 fclose(fp); 133 /* 134 * Print the status file to show what the daemon is doing. 135 */ 136 if (sendtorem) 137 printf("\n%s: ", host); 138 if ((fd = open(ST, FRDONLY|FSHLOCK)) >= 0) { 139 while ((i = read(fd, line, sizeof(line))) > 0) 140 (void) fwrite(line, 1, i, stdout); 141 (void) close(fd); 142 } else 143 putchar('\n'); 144 } 145 /* 146 * Now, examine the control files and print out the jobs to 147 * be done for each user. 148 */ 149 if (!lflag) 150 header(); 151 for (i = 0; i < nitems; i++) { 152 q = queue[i]; 153 inform(q->q_name); 154 free(q); 155 } 156 free(queue); 157 return(nitems-garbage); 158 } 159 160 /* 161 * Print the header for the short listing format 162 */ 163 header() 164 { 165 printf(head0); 166 col = strlen(head0)+1; 167 blankfill(SIZCOL); 168 printf(head1); 169 } 170 171 inform(cf) 172 char *cf; 173 { 174 register int j, k; 175 register char *cp; 176 FILE *cfp; 177 178 /* 179 * There's a chance the control file has gone away 180 * in the meantime; if this is the case just keep going 181 */ 182 if ((cfp = fopen(cf, "r")) == NULL) 183 return; 184 185 if (rank < 0) 186 rank = 0; 187 if (sendtorem || garbage || strcmp(cf, current)) 188 rank++; 189 j = 0; 190 while (getline(cfp)) { 191 switch (line[0]) { 192 case 'P': /* Was this file specified in the user's list? */ 193 if (!inlist(line+1, cf)) { 194 fclose(cfp); 195 return; 196 } 197 if (lflag) { 198 printf("\n%s: ", line+1); 199 col = strlen(line+1) + 2; 200 prank(rank); 201 blankfill(JOBCOL); 202 printf(" [job %s]\n", cf+3); 203 } else { 204 col = 0; 205 prank(rank); 206 blankfill(OWNCOL); 207 printf("%-10s %-3d ", line+1, atoi(cf+3)); 208 col += 16; 209 first = 1; 210 } 211 continue; 212 default: /* some format specifer and file name? */ 213 if (line[0] < 'a' || line[0] > 'z') 214 continue; 215 if (j == 0 || strcmp(file, line+1) != 0) 216 strcpy(file, line+1); 217 j++; 218 continue; 219 case 'N': 220 show(line+1, file, j); 221 file[0] = '\0'; 222 j = 0; 223 } 224 } 225 fclose(cfp); 226 if (!lflag) { 227 blankfill(SIZCOL); 228 printf("%D bytes\n", totsize); 229 totsize = 0; 230 } 231 } 232 233 inlist(name, file) 234 char *name, *file; 235 { 236 register int *r, n; 237 register char **u, *cp; 238 239 if (users == 0 && requests == 0) 240 return(1); 241 /* 242 * Check to see if it's in the user list 243 */ 244 for (u = user; u < &user[users]; u++) 245 if (!strcmp(*u, name)) 246 return(1); 247 /* 248 * Check the request list 249 */ 250 for (n = 0, cp = file+3; isdigit(*cp); ) 251 n = n * 10 + (*cp++ - '0'); 252 for (r = requ; r < &requ[requests]; r++) 253 if (*r == n && !strcmp(cp, from)) 254 return(1); 255 return(0); 256 } 257 258 show(nfile, file, copies) 259 register char *nfile, *file; 260 { 261 if (strcmp(nfile, " ") == 0) 262 nfile = "(standard input)"; 263 if (lflag) 264 ldump(nfile, file, copies); 265 else 266 dump(nfile, file, copies); 267 } 268 269 /* 270 * Fill the line with blanks to the specified column 271 */ 272 blankfill(n) 273 register int n; 274 { 275 while (col++ < n) 276 putchar(' '); 277 } 278 279 /* 280 * Give the abbreviated dump of the file names 281 */ 282 dump(nfile, file, copies) 283 char *nfile, *file; 284 { 285 register short n, fill; 286 struct stat lbuf; 287 288 /* 289 * Print as many files as will fit 290 * (leaving room for the total size) 291 */ 292 fill = first ? 0 : 2; /* fill space for ``, '' */ 293 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 294 if (col < SIZCOL) { 295 printf(" ..."), col += 4; 296 blankfill(SIZCOL); 297 } 298 } else { 299 if (first) 300 first = 0; 301 else 302 printf(", "); 303 printf("%s", nfile); 304 col += n+fill; 305 } 306 if (*file && !stat(file, &lbuf)) 307 totsize += copies * lbuf.st_size; 308 } 309 310 /* 311 * Print the long info about the file 312 */ 313 ldump(nfile, file, copies) 314 char *nfile, *file; 315 { 316 struct stat lbuf; 317 318 putchar('\t'); 319 if (copies > 1) 320 printf("%-2d copies of %-19s", copies, nfile); 321 else 322 printf("%-32s", nfile); 323 if (*file && !stat(file, &lbuf)) 324 printf(" %D bytes", lbuf.st_size); 325 else 326 printf(" ??? bytes"); 327 putchar('\n'); 328 } 329 330 /* 331 * Print the job's rank in the queue, 332 * update col for screen management 333 */ 334 prank(n) 335 { 336 char line[100]; 337 static char *r[] = { 338 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 339 }; 340 341 if (n == 0) { 342 printf("active"); 343 col += 6; 344 return; 345 } 346 if ((n/10) == 1) 347 (void) sprintf(line, "%dth", n); 348 else 349 (void) sprintf(line, "%d%s", n, r[n%10]); 350 col += strlen(line); 351 printf("%s", line); 352 } 353