displayq.c revision 15638
198944Sobrien/* 298944Sobrien * Copyright (c) 1983, 1993 398944Sobrien * The Regents of the University of California. All rights reserved. 498944Sobrien * 598944Sobrien * Redistribution and use in source and binary forms, with or without 698944Sobrien * modification, are permitted provided that the following conditions 798944Sobrien * are met: 898944Sobrien * 1. Redistributions of source code must retain the above copyright 998944Sobrien * notice, this list of conditions and the following disclaimer. 1098944Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1198944Sobrien * notice, this list of conditions and the following disclaimer in the 1298944Sobrien * documentation and/or other materials provided with the distribution. 1398944Sobrien * 3. All advertising materials mentioning features or use of this software 1498944Sobrien * must display the following acknowledgement: 1598944Sobrien * This product includes software developed by the University of 1698944Sobrien * California, Berkeley and its contributors. 1798944Sobrien * 4. Neither the name of the University nor the names of its contributors 1898944Sobrien * may be used to endorse or promote products derived from this software 1998944Sobrien * without specific prior written permission. 2098944Sobrien * 2198944Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2298944Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2398944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2498944Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25130803Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26130803Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2798944Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28130803Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2998944Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30130803Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3198944Sobrien * SUCH DAMAGE. 3298944Sobrien */ 3398944Sobrien 34130803Smarcel#ifndef lint 35130803Smarcelstatic char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95"; 3698944Sobrien#endif /* not lint */ 37130803Smarcel 38130803Smarcel#include <sys/param.h> 3998944Sobrien#include <sys/stat.h> 40130803Smarcel#include <sys/file.h> 4198944Sobrien 42130803Smarcel#include <signal.h> 4398944Sobrien#include <fcntl.h> 44130803Smarcel#include <dirent.h> 45130803Smarcel#include <unistd.h> 4698944Sobrien#include <stdio.h> 47130803Smarcel#include <stdlib.h> 48130803Smarcel#include <string.h> 4998944Sobrien#include <ctype.h> 50130803Smarcel#include "lp.h" 5198944Sobrien#include "lp.local.h" 52130803Smarcel#include "pathnames.h" 53130803Smarcel 5498944Sobrien/* 55130803Smarcel * Routines to display the state of the queue. 5698944Sobrien */ 5798944Sobrien#define JOBCOL 40 /* column for job # in -l format */ 5898944Sobrien#define OWNCOL 7 /* start of Owner column in normal */ 5998944Sobrien#define SIZCOL 62 /* start of Size column in normal */ 6098944Sobrien 6198944Sobrien/* 6298944Sobrien * Stuff for handling job specifications 6398944Sobrien */ 6498944Sobrienextern int requ[]; /* job number of spool entries */ 6598944Sobrienextern int requests; /* # of spool requests */ 6698944Sobrienextern char *user[]; /* users to process */ 6798944Sobrienextern int users; /* # of users in user array */ 6898944Sobrien 6998944Sobrienstatic int col; /* column on screen */ 7098944Sobrienstatic char current[40]; /* current file being printed */ 7198944Sobrienstatic char file[132]; /* print file name */ 7298944Sobrienstatic int first; /* first file in ``files'' column? */ 7398944Sobrienstatic int garbage; /* # of garbage cf files */ 7498944Sobrienstatic int lflag; /* long output option */ 7598944Sobrienstatic int rank; /* order to be printed (-1=none, 0=active) */ 7698944Sobrienstatic long totsize; /* total print job size in bytes */ 7798944Sobrien 7898944Sobrienstatic char *head0 = "Rank Owner Job Files"; 7998944Sobrienstatic char *head1 = "Total Size\n"; 8098944Sobrien 8198944Sobrien/* 8298944Sobrien * Display the current state of the queue. Format = 1 if long format. 8398944Sobrien */ 8498944Sobrienvoid 8598944Sobriendisplayq(format) 8698944Sobrien int format; 8798944Sobrien{ 8898944Sobrien register struct queue *q; 8998944Sobrien register int i, nitems, fd; 9098944Sobrien register char *cp; 9198944Sobrien struct queue **queue; 9298944Sobrien struct stat statb; 9398944Sobrien FILE *fp; 9498944Sobrien 9598944Sobrien lflag = format; 96 totsize = 0; 97 rank = -1; 98 if ((i = cgetent(&bp, printcapdb, printer)) == -2) 99 fatal("can't open printer description file"); 100 else if (i == -1) 101 fatal("unknown printer"); 102 else if (i == -3) 103 fatal("potential reference loop detected in printcap file"); 104 if (cgetstr(bp, "lp", &LP) < 0) 105 LP = _PATH_DEFDEVLP; 106 if (cgetstr(bp, "rp", &RP) < 0) 107 RP = DEFLP; 108 if (cgetstr(bp, "sd", &SD) < 0) 109 SD = _PATH_DEFSPOOL; 110 if (cgetstr(bp,"lo", &LO) < 0) 111 LO = DEFLOCK; 112 if (cgetstr(bp, "st", &ST) < 0) 113 ST = DEFSTAT; 114 cgetstr(bp, "rm", &RM); 115 if (cp = checkremote()) 116 printf("Warning: %s\n", cp); 117 118 /* 119 * Print out local queue 120 * Find all the control files in the spooling directory 121 */ 122 if (chdir(SD) < 0) 123 fatal("cannot chdir to spooling directory"); 124 if ((nitems = getq(&queue)) < 0) 125 fatal("cannot examine spooling area\n"); 126 if (stat(LO, &statb) >= 0) { 127 if (statb.st_mode & 0100) { 128 if (remote) 129 printf("%s: ", host); 130 printf("Warning: %s is down: ", printer); 131 fd = open(ST, O_RDONLY); 132 if (fd >= 0) { 133 (void) flock(fd, LOCK_SH); 134 while ((i = read(fd, line, sizeof(line))) > 0) 135 (void) fwrite(line, 1, i, stdout); 136 (void) close(fd); /* unlocks as well */ 137 } else 138 putchar('\n'); 139 } 140 if (statb.st_mode & 010) { 141 if (remote) 142 printf("%s: ", host); 143 printf("Warning: %s queue is turned off\n", printer); 144 } 145 } 146 147 if (nitems) { 148 fp = fopen(LO, "r"); 149 if (fp == NULL) 150 warn(); 151 else { 152 /* get daemon pid */ 153 cp = current; 154 while ((i = getc(fp)) != EOF && i != '\n') 155 *cp++ = i; 156 *cp = '\0'; 157 i = atoi(current); 158 if (i <= 0 || kill(i, 0) < 0) 159 warn(); 160 else { 161 /* read current file name */ 162 cp = current; 163 while ((i = getc(fp)) != EOF && i != '\n') 164 *cp++ = i; 165 *cp = '\0'; 166 /* 167 * Print the status file. 168 */ 169 if (remote) 170 printf("%s: ", host); 171 fd = open(ST, O_RDONLY); 172 if (fd >= 0) { 173 (void) flock(fd, LOCK_SH); 174 while ((i = read(fd, line, sizeof(line))) > 0) 175 (void) fwrite(line, 1, i, stdout); 176 (void) close(fd); /* unlocks as well */ 177 } else 178 putchar('\n'); 179 } 180 (void) fclose(fp); 181 } 182 /* 183 * Now, examine the control files and print out the jobs to 184 * be done for each user. 185 */ 186 if (!lflag) 187 header(); 188 for (i = 0; i < nitems; i++) { 189 q = queue[i]; 190 inform(q->q_name); 191 free(q); 192 } 193 free(queue); 194 } 195 if (!remote) { 196 if (nitems == 0) 197 puts("no entries"); 198 return; 199 } 200 201 /* 202 * Print foreign queue 203 * Note that a file in transit may show up in either queue. 204 */ 205 if (nitems) 206 putchar('\n'); 207 (void) sprintf(line, "%c%s", format + '\3', RP); 208 cp = line; 209 for (i = 0; i < requests; i++) { 210 cp += strlen(cp); 211 (void) sprintf(cp, " %d", requ[i]); 212 } 213 for (i = 0; i < users; i++) { 214 cp += strlen(cp); 215 *cp++ = ' '; 216 (void) strcpy(cp, user[i]); 217 } 218 strcat(line, "\n"); 219 fd = getport(RM, 0); 220 if (fd < 0) { 221 if (from != host) 222 printf("%s: ", host); 223 printf("connection to %s is down\n", RM); 224 } 225 else { 226 i = strlen(line); 227 if (write(fd, line, i) != i) 228 fatal("Lost connection"); 229 while ((i = read(fd, line, sizeof(line))) > 0) 230 (void) fwrite(line, 1, i, stdout); 231 (void) close(fd); 232 } 233} 234 235/* 236 * Print a warning message if there is no daemon present. 237 */ 238void 239warn() 240{ 241 if (remote) 242 printf("\n%s: ", host); 243 puts("Warning: no daemon present"); 244 current[0] = '\0'; 245} 246 247/* 248 * Print the header for the short listing format 249 */ 250void 251header() 252{ 253 printf(head0); 254 col = strlen(head0)+1; 255 blankfill(SIZCOL); 256 printf(head1); 257} 258 259void 260inform(cf) 261 char *cf; 262{ 263 register int j; 264 FILE *cfp; 265 266 /* 267 * There's a chance the control file has gone away 268 * in the meantime; if this is the case just keep going 269 */ 270 if ((cfp = fopen(cf, "r")) == NULL) 271 return; 272 273 if (rank < 0) 274 rank = 0; 275 if (remote || garbage || strcmp(cf, current)) 276 rank++; 277 j = 0; 278 while (getline(cfp)) { 279 switch (line[0]) { 280 case 'P': /* Was this file specified in the user's list? */ 281 if (!inlist(line+1, cf)) { 282 fclose(cfp); 283 return; 284 } 285 if (lflag) { 286 printf("\n%s: ", line+1); 287 col = strlen(line+1) + 2; 288 prank(rank); 289 blankfill(JOBCOL); 290 printf(" [job %s]\n", cf+3); 291 } else { 292 col = 0; 293 prank(rank); 294 blankfill(OWNCOL); 295 printf("%-10s %-3d ", line+1, atoi(cf+3)); 296 col += 16; 297 first = 1; 298 } 299 continue; 300 default: /* some format specifer and file name? */ 301 if (line[0] < 'a' || line[0] > 'z') 302 continue; 303 if (j == 0 || strcmp(file, line+1) != 0) 304 (void) strcpy(file, line+1); 305 j++; 306 continue; 307 case 'N': 308 show(line+1, file, j); 309 file[0] = '\0'; 310 j = 0; 311 } 312 } 313 fclose(cfp); 314 if (!lflag) { 315 blankfill(SIZCOL); 316 printf("%ld bytes\n", totsize); 317 totsize = 0; 318 } 319} 320 321int 322inlist(name, file) 323 char *name, *file; 324{ 325 register int *r, n; 326 register char **u, *cp; 327 328 if (users == 0 && requests == 0) 329 return(1); 330 /* 331 * Check to see if it's in the user list 332 */ 333 for (u = user; u < &user[users]; u++) 334 if (!strcmp(*u, name)) 335 return(1); 336 /* 337 * Check the request list 338 */ 339 for (n = 0, cp = file+3; isdigit(*cp); ) 340 n = n * 10 + (*cp++ - '0'); 341 for (r = requ; r < &requ[requests]; r++) 342 if (*r == n && !strcmp(cp, from)) 343 return(1); 344 return(0); 345} 346 347void 348show(nfile, file, copies) 349 register char *nfile, *file; 350 int copies; 351{ 352 if (strcmp(nfile, " ") == 0) 353 nfile = "(standard input)"; 354 if (lflag) 355 ldump(nfile, file, copies); 356 else 357 dump(nfile, file, copies); 358} 359 360/* 361 * Fill the line with blanks to the specified column 362 */ 363void 364blankfill(n) 365 register int n; 366{ 367 while (col++ < n) 368 putchar(' '); 369} 370 371/* 372 * Give the abbreviated dump of the file names 373 */ 374void 375dump(nfile, file, copies) 376 char *nfile, *file; 377 int copies; 378{ 379 register short n, fill; 380 struct stat lbuf; 381 382 /* 383 * Print as many files as will fit 384 * (leaving room for the total size) 385 */ 386 fill = first ? 0 : 2; /* fill space for ``, '' */ 387 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { 388 if (col < SIZCOL) { 389 printf(" ..."), col += 4; 390 blankfill(SIZCOL); 391 } 392 } else { 393 if (first) 394 first = 0; 395 else 396 printf(", "); 397 printf("%s", nfile); 398 col += n+fill; 399 } 400 if (*file && !stat(file, &lbuf)) 401 totsize += copies * lbuf.st_size; 402} 403 404/* 405 * Print the long info about the file 406 */ 407void 408ldump(nfile, file, copies) 409 char *nfile, *file; 410 int copies; 411{ 412 struct stat lbuf; 413 414 putchar('\t'); 415 if (copies > 1) 416 printf("%-2d copies of %-19s", copies, nfile); 417 else 418 printf("%-32s", nfile); 419 if (*file && !stat(file, &lbuf)) 420 printf(" %ld bytes", (long)lbuf.st_size); 421 else 422 printf(" ??? bytes"); 423 putchar('\n'); 424} 425 426/* 427 * Print the job's rank in the queue, 428 * update col for screen management 429 */ 430void 431prank(n) 432 int n; 433{ 434 char rline[100]; 435 static char *r[] = { 436 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 437 }; 438 439 if (n == 0) { 440 printf("active"); 441 col += 6; 442 return; 443 } 444 if ((n/10)%10 == 1) 445 (void)snprintf(rline, sizeof(rline), "%dth", n); 446 else 447 (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]); 448 col += strlen(rline); 449 printf("%s", rline); 450} 451