1 /* displayq.c 4.1 83/04/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 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 name = "displayq"; 46 lflag = format; 47 totsize = 0; 48 rank = -1; 49 50 if ((i = pgetent(line, printer)) < 0) 51 fatal("cannot open printer description file"); 52 else if (i == 0) 53 fatal("unknown printer"); 54 if ((LP = pgetstr("lp", &bp)) == NULL) 55 LP = DEFDEVLP; 56 if ((RP = pgetstr("rp", &bp)) == NULL) 57 RP = printer; 58 if ((SD = pgetstr("sd", &bp)) == NULL) 59 SD = DEFSPOOL; 60 if ((LO = pgetstr("lo", &bp)) == NULL) 61 LO = DEFLOCK; 62 if ((ST = pgetstr("st", &bp)) == NULL) 63 ST = DEFSTAT; 64 RM = pgetstr("rm", &bp); 65 66 /* 67 * If there is no local printer, then print the queue on 68 * the remote machine and then what's in the queue here. 69 * Note that a file in transit may not show up in either queue. 70 */ 71 if (*LP == '\0') { 72 register char *cp; 73 char c; 74 75 sendtorem++; 76 (void) sprintf(line, "%c%s", format + '\3', RP); 77 cp = line; 78 for (i = 0; i < requests; i++) { 79 cp += strlen(cp); 80 (void) sprintf(cp, " %d", requ[i]); 81 } 82 for (i = 0; i < users; i++) { 83 cp += strlen(cp); 84 *cp++ = ' '; 85 strcpy(cp, user[i]); 86 } 87 strcat(line, "\n"); 88 fd = getport(); 89 if (fd < 0) { 90 if (from != host) 91 printf("%s: ", host); 92 printf("connection to %s is down\n", RM); 93 } else { 94 i = strlen(line); 95 if (write(fd, line, i) != i) 96 fatal("Lost connection"); 97 while ((i = read(fd, line, sizeof(line))) > 0) 98 (void) fwrite(line, 1, i, stdout); 99 (void) close(fd); 100 } 101 } 102 /* 103 * Find all the control files in the spooling directory 104 */ 105 if (chdir(SD) < 0) 106 fatal("cannot chdir to spooling directory"); 107 if ((nitems = getq(&queue)) < 0) 108 fatal("cannot examine spooling area\n"); 109 if (nitems == 0) { 110 if (sendtorem) 111 printf("\n%s: ", host); 112 printf("no entries\n"); 113 return(0); 114 } 115 fp = fopen(LO, "r"); 116 if (fp == NULL || flock(fileno(fp), FSHLOCK|FNBLOCK) == 0) { 117 if (fp != NULL) 118 fclose(fp); 119 garbage = nitems; 120 if (*LP && stat(LP, &statb) >= 0 && (statb.st_mode & 0777) == 0) 121 status("Warning: %s is down", printer); 122 else 123 status("Warning: no daemon present"); 124 } else { 125 register char *cp = current; 126 127 /* skip daemon pid */ 128 while ((*cp = getc(fp)) != EOF && *cp != '\n'); 129 /* read current file name */ 130 while ((*cp = getc(fp)) != EOF && *cp != '\n') 131 cp++; 132 *cp = '\0'; 133 fclose(fp); 134 } 135 /* 136 * Now, examine the control files and print out the jobs to 137 * be done for each user. 138 */ 139 if (sendtorem) 140 printf("\n%s: ", host); 141 if ((fd = open(ST, FRDONLY|FSHLOCK)) >= 0) { 142 while ((i = read(fd, line, sizeof(line))) > 0) 143 (void) fwrite(line, 1, i, stdout); 144 (void) close(fd); 145 } else 146 putchar('\n'); 147 if (!lflag) 148 header(); 149 for (i = 0; i < nitems; i++) { 150 q = queue[i]; 151 inform(q->q_name); 152 free(q); 153 } 154 free(queue); 155 return(nitems-garbage); 156 } 157 158 /* 159 * Print the header for the short listing format 160 */ 161 header() 162 { 163 printf(head0); 164 col = strlen(head0)+1; 165 blankfill(SIZCOL); 166 printf(head1); 167 } 168 169 inform(cf) 170 char *cf; 171 { 172 register int j, k; 173 register char *cp; 174 FILE *cfp; 175 176 /* 177 * There's a chance the control file has gone away 178 * in the meantime; if this is the case just keep going 179 */ 180 if ((cfp = fopen(cf, "r")) == NULL) 181 return; 182 183 if (rank < 0) 184 rank = 0; 185 if (sendtorem || garbage || strcmp(cf, current)) 186 rank++; 187 j = 0; 188 while (getline(cfp)) { 189 switch (line[0]) { 190 case 'P': /* Was this file specified in the user's list? */ 191 if (!inlist(line+1, cf)) { 192 fclose(cfp); 193 return; 194 } 195 if (lflag) { 196 printf("\n%s: ", line+1); 197 col = strlen(line+1) + 2; 198 prank(rank); 199 blankfill(JOBCOL); 200 printf(" [job %s]\n", cf+3); 201 } else { 202 col = 0; 203 prank(rank); 204 blankfill(OWNCOL); 205 printf("%-10s %-3d ", line+1, atoi(cf+3)); 206 col += 16; 207 first = 1; 208 } 209 continue; 210 default: /* some format specifer and file name? */ 211 if (line[0] < 'a' || line[0] > 'z') 212 continue; 213 if (j == 0 || strcmp(file, line+1) != 0) 214 strcpy(file, line+1); 215 j++; 216 continue; 217 case 'N': 218 show(line+1, file, j); 219 file[0] = '\0'; 220 j = 0; 221 } 222 } 223 fclose(cfp); 224 if (!lflag) { 225 blankfill(SIZCOL); 226 printf("%D bytes\n", totsize); 227 totsize = 0; 228 } 229 } 230 231 inlist(name, file) 232 char *name, *file; 233 { 234 register int *r, n; 235 register char **u, *cp; 236 237 if (users == 0 && requests == 0) 238 return(1); 239 /* 240 * Check to see if it's in the user list 241 */ 242 for (u = user; u < &user[users]; u++) 243 if (!strcmp(*u, name)) 244 return(1); 245 /* 246 * Check the request list 247 */ 248 for (n = 0, cp = file+3; isdigit(*cp); ) 249 n = n * 10 + (*cp++ - '0'); 250 for (r = requ; r < &requ[requests]; r++) 251 if (*r == n && !strcmp(cp, from)) 252 return(1); 253 return(0); 254 } 255 256 show(nfile, file, copies) 257 register char *nfile, *file; 258 { 259 if (strcmp(nfile, " ") == 0) 260 nfile = "(standard input)"; 261 if (lflag) 262 ldump(nfile, file, copies); 263 else 264 dump(nfile, file, copies); 265 } 266 267 /* 268 * Fill the line with blanks to the specified column 269 */ 270 blankfill(n) 271 register int n; 272 { 273 while (col++ < n) 274 putchar(' '); 275 } 276 277 /* 278 * Give the abbreviated dump of the file names 279 */ 280 dump(nfile, file, copies) 281 char *nfile, *file; 282 { 283 register short n, fill; 284 struct stat lbuf; 285 286 /* 287 * Print as many files as will fit 288 * (leaving room for the total size) 289 */ 290 fill = first ? 0 : 2; /* fill space for ``, '' */ 291 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 292 if (col < SIZCOL) { 293 printf(" ..."), col += 4; 294 blankfill(SIZCOL); 295 } 296 } else { 297 if (first) 298 first = 0; 299 else 300 printf(", "); 301 printf("%s", nfile); 302 col += n+fill; 303 } 304 if (*file && !stat(file, &lbuf)) 305 totsize += copies * lbuf.st_size; 306 } 307 308 /* 309 * Print the long info about the file 310 */ 311 ldump(nfile, file, copies) 312 char *nfile, *file; 313 { 314 struct stat lbuf; 315 316 putchar('\t'); 317 if (copies > 1) 318 printf("%-2d copies of %-19s", copies, nfile); 319 else 320 printf("%-32s", nfile); 321 if (*file && !stat(file, &lbuf)) 322 printf(" %D bytes", lbuf.st_size); 323 else 324 printf(" ??? bytes"); 325 putchar('\n'); 326 } 327 328 /* 329 * Print the job's rank in the queue, 330 * update col for screen management 331 */ 332 prank(n) 333 { 334 char line[100]; 335 static char *r[] = { 336 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 337 }; 338 339 if (n == 0) { 340 printf("active"); 341 col += 6; 342 return; 343 } 344 if ((n/10) == 1) 345 (void) sprintf(line, "%dth", n); 346 else 347 (void) sprintf(line, "%d%s", n, r[n%10]); 348 col += strlen(line); 349 printf("%s", line); 350 } 351