122427Sdist /*
261840Sbostic  * Copyright (c) 1983, 1993
361840Sbostic  *	The Regents of the University of California.  All rights reserved.
434203Sbostic  *
556243Selan  * %sccs.include.redist.c%
622427Sdist  */
722427Sdist 
813952Ssam #ifndef lint
9*69060Stef static char sccsid[] = "@(#)displayq.c	8.4 (Berkeley) 04/28/95";
1034203Sbostic #endif /* not lint */
1113952Ssam 
1255470Sbostic #include <sys/param.h>
1355470Sbostic #include <sys/stat.h>
14*69060Stef #include <sys/file.h>
1512113Sralph 
1655470Sbostic #include <signal.h>
1755470Sbostic #include <fcntl.h>
1855470Sbostic #include <dirent.h>
1955470Sbostic #include <unistd.h>
2055470Sbostic #include <stdio.h>
2155470Sbostic #include <stdlib.h>
2255470Sbostic #include <string.h>
2355470Sbostic #include <ctype.h>
2412113Sralph #include "lp.h"
2555470Sbostic #include "lp.local.h"
2637968Sbostic #include "pathnames.h"
2712113Sralph 
2855470Sbostic /*
2955470Sbostic  * Routines to display the state of the queue.
3055470Sbostic  */
3113170Sralph #define JOBCOL	40		/* column for job # in -l format */
3213170Sralph #define OWNCOL	7		/* start of Owner column in normal */
3313170Sralph #define SIZCOL	62		/* start of Size column in normal */
3412113Sralph 
3512113Sralph /*
3612113Sralph  * Stuff for handling job specifications
3712113Sralph  */
3812113Sralph extern int	requ[];		/* job number of spool entries */
3912113Sralph extern int	requests;	/* # of spool requests */
4056120Selan extern char    *user[];	        /* users to process */
4156120Selan extern int	users;		/* # of users in user array */
4212113Sralph 
4356120Selan static int	col;		/* column on screen */
4456120Selan static char	current[40];	/* current file being printed */
4556120Selan static char	file[132];	/* print file name */
4656120Selan static int	first;		/* first file in ``files'' column? */
4756120Selan static int	garbage;	/* # of garbage cf files */
4856120Selan static int	lflag;		/* long output option */
4956120Selan static int	rank;		/* order to be printed (-1=none, 0=active) */
5056120Selan static long	totsize;	/* total print job size in bytes */
5112113Sralph 
5256120Selan static char	*head0 = "Rank   Owner      Job  Files";
5356120Selan static char	*head1 = "Total Size\n";
5412113Sralph 
5512113Sralph /*
5612113Sralph  * Display the current state of the queue. Format = 1 if long format.
5712113Sralph  */
5855470Sbostic void
displayq(format)5912113Sralph displayq(format)
6012113Sralph 	int format;
6112113Sralph {
6212113Sralph 	register struct queue *q;
6312113Sralph 	register int i, nitems, fd;
6430995Sbostic 	register char	*cp;
6512113Sralph 	struct queue **queue;
6612113Sralph 	struct stat statb;
6712113Sralph 	FILE *fp;
6812113Sralph 
6912113Sralph 	lflag = format;
7012113Sralph 	totsize = 0;
7112113Sralph 	rank = -1;
7256120Selan 	if ((i = cgetent(&bp, printcapdb, printer)) == -2)
7356120Selan 		fatal("can't open printer description file");
7456120Selan 	else if (i == -1)
7512113Sralph 		fatal("unknown printer");
7656120Selan 	else if (i == -3)
7756120Selan 		fatal("potential reference loop detected in printcap file");
7856120Selan 	if (cgetstr(bp, "lp", &LP) < 0)
7937968Sbostic 		LP = _PATH_DEFDEVLP;
8056120Selan 	if (cgetstr(bp, "rp", &RP) < 0)
8112434Sralph 		RP = DEFLP;
8256120Selan 	if (cgetstr(bp, "sd", &SD) < 0)
8337968Sbostic 		SD = _PATH_DEFSPOOL;
8456120Selan 	if (cgetstr(bp,"lo", &LO) < 0)
8512113Sralph 		LO = DEFLOCK;
8656120Selan 	if (cgetstr(bp, "st", &ST) < 0)
8712113Sralph 		ST = DEFSTAT;
8856120Selan 	cgetstr(bp, "rm", &RM);
8938736Stef 	if (cp = checkremote())
9038736Stef 		printf("Warning: %s\n", cp);
9112113Sralph 
9212113Sralph 	/*
9330995Sbostic 	 * Print out local queue
9412113Sralph 	 * Find all the control files in the spooling directory
9512113Sralph 	 */
9612113Sralph 	if (chdir(SD) < 0)
9712113Sralph 		fatal("cannot chdir to spooling directory");
9812113Sralph 	if ((nitems = getq(&queue)) < 0)
9912113Sralph 		fatal("cannot examine spooling area\n");
10016205Sralph 	if (stat(LO, &statb) >= 0) {
10116205Sralph 		if (statb.st_mode & 0100) {
10269009Stef 			if (remote)
10316205Sralph 				printf("%s: ", host);
10416205Sralph 			printf("Warning: %s is down: ", printer);
10516205Sralph 			fd = open(ST, O_RDONLY);
10616205Sralph 			if (fd >= 0) {
10716205Sralph 				(void) flock(fd, LOCK_SH);
10816205Sralph 				while ((i = read(fd, line, sizeof(line))) > 0)
10916205Sralph 					(void) fwrite(line, 1, i, stdout);
11016205Sralph 				(void) close(fd);	/* unlocks as well */
11116205Sralph 			} else
11216205Sralph 				putchar('\n');
11316205Sralph 		}
11416205Sralph 		if (statb.st_mode & 010) {
11569009Stef 			if (remote)
11616205Sralph 				printf("%s: ", host);
11716205Sralph 			printf("Warning: %s queue is turned off\n", printer);
11816205Sralph 		}
11912740Sralph 	}
12012113Sralph 
12130995Sbostic 	if (nitems) {
12230995Sbostic 		fp = fopen(LO, "r");
12330995Sbostic 		if (fp == NULL)
12413441Sralph 			warn();
12513441Sralph 		else {
12630995Sbostic 			/* get daemon pid */
12713441Sralph 			cp = current;
12868971Stef 			while ((i = getc(fp)) != EOF && i != '\n')
12968971Stef 				*cp++ = i;
13013441Sralph 			*cp = '\0';
13130995Sbostic 			i = atoi(current);
13230995Sbostic 			if (i <= 0 || kill(i, 0) < 0)
13330995Sbostic 				warn();
13430995Sbostic 			else {
13530995Sbostic 				/* read current file name */
13630995Sbostic 				cp = current;
13768971Stef 				while ((i = getc(fp)) != EOF && i != '\n')
13868971Stef 					*cp++ = i;
13930995Sbostic 				*cp = '\0';
14030995Sbostic 				/*
14130995Sbostic 				 * Print the status file.
14230995Sbostic 				 */
14369009Stef 				if (remote)
14430995Sbostic 					printf("%s: ", host);
14530995Sbostic 				fd = open(ST, O_RDONLY);
14630995Sbostic 				if (fd >= 0) {
14730995Sbostic 					(void) flock(fd, LOCK_SH);
14830995Sbostic 					while ((i = read(fd, line, sizeof(line))) > 0)
14930995Sbostic 						(void) fwrite(line, 1, i, stdout);
15030995Sbostic 					(void) close(fd);	/* unlocks as well */
15130995Sbostic 				} else
15230995Sbostic 					putchar('\n');
15330995Sbostic 			}
15430995Sbostic 			(void) fclose(fp);
15513441Sralph 		}
15630995Sbostic 		/*
15730995Sbostic 		 * Now, examine the control files and print out the jobs to
15830995Sbostic 		 * be done for each user.
15930995Sbostic 		 */
16030995Sbostic 		if (!lflag)
16130995Sbostic 			header();
16230995Sbostic 		for (i = 0; i < nitems; i++) {
16330995Sbostic 			q = queue[i];
16430995Sbostic 			inform(q->q_name);
16530995Sbostic 			free(q);
16630995Sbostic 		}
16730995Sbostic 		free(queue);
16812113Sralph 	}
16969009Stef 	if (!remote) {
17031678Skarels 		if (nitems == 0)
17131678Skarels 			puts("no entries");
17230995Sbostic 		return;
17330995Sbostic 	}
17430995Sbostic 
17512113Sralph 	/*
17630995Sbostic 	 * Print foreign queue
17730995Sbostic 	 * Note that a file in transit may show up in either queue.
17812113Sralph 	 */
17930995Sbostic 	if (nitems)
18030995Sbostic 		putchar('\n');
18130995Sbostic 	(void) sprintf(line, "%c%s", format + '\3', RP);
18230995Sbostic 	cp = line;
18330995Sbostic 	for (i = 0; i < requests; i++) {
18430995Sbostic 		cp += strlen(cp);
18530995Sbostic 		(void) sprintf(cp, " %d", requ[i]);
18612113Sralph 	}
18730995Sbostic 	for (i = 0; i < users; i++) {
18830995Sbostic 		cp += strlen(cp);
18930995Sbostic 		*cp++ = ' ';
19030995Sbostic 		(void) strcpy(cp, user[i]);
19130995Sbostic 	}
19230995Sbostic 	strcat(line, "\n");
19369009Stef 	fd = getport(RM, 0);
19430995Sbostic 	if (fd < 0) {
19530995Sbostic 		if (from != host)
19630995Sbostic 			printf("%s: ", host);
19730995Sbostic 		printf("connection to %s is down\n", RM);
19830995Sbostic 	}
19930995Sbostic 	else {
20030995Sbostic 		i = strlen(line);
20130995Sbostic 		if (write(fd, line, i) != i)
20230995Sbostic 			fatal("Lost connection");
20330995Sbostic 		while ((i = read(fd, line, sizeof(line))) > 0)
20430995Sbostic 			(void) fwrite(line, 1, i, stdout);
20530995Sbostic 		(void) close(fd);
20630995Sbostic 	}
20712113Sralph }
20812113Sralph 
20912113Sralph /*
21013441Sralph  * Print a warning message if there is no daemon present.
21113441Sralph  */
21255470Sbostic void
warn()21313441Sralph warn()
21413441Sralph {
21569009Stef 	if (remote)
21613441Sralph 		printf("\n%s: ", host);
21730995Sbostic 	puts("Warning: no daemon present");
21813441Sralph 	current[0] = '\0';
21913441Sralph }
22013441Sralph 
22113441Sralph /*
22212113Sralph  * Print the header for the short listing format
22312113Sralph  */
22455470Sbostic void
header()22512113Sralph header()
22612113Sralph {
22712113Sralph 	printf(head0);
22812113Sralph 	col = strlen(head0)+1;
22912113Sralph 	blankfill(SIZCOL);
23012113Sralph 	printf(head1);
23112113Sralph }
23212113Sralph 
23355470Sbostic void
inform(cf)23412113Sralph inform(cf)
23512113Sralph 	char *cf;
23612113Sralph {
23755470Sbostic 	register int j;
23812113Sralph 	FILE *cfp;
23912113Sralph 
24012113Sralph 	/*
24112113Sralph 	 * There's a chance the control file has gone away
24212113Sralph 	 * in the meantime; if this is the case just keep going
24312113Sralph 	 */
24412113Sralph 	if ((cfp = fopen(cf, "r")) == NULL)
24512113Sralph 		return;
24612113Sralph 
24712113Sralph 	if (rank < 0)
24812113Sralph 		rank = 0;
24969009Stef 	if (remote || garbage || strcmp(cf, current))
25012113Sralph 		rank++;
25112113Sralph 	j = 0;
25212113Sralph 	while (getline(cfp)) {
25312113Sralph 		switch (line[0]) {
25412113Sralph 		case 'P': /* Was this file specified in the user's list? */
25512113Sralph 			if (!inlist(line+1, cf)) {
25612113Sralph 				fclose(cfp);
25712113Sralph 				return;
25812113Sralph 			}
25912113Sralph 			if (lflag) {
26012113Sralph 				printf("\n%s: ", line+1);
26112113Sralph 				col = strlen(line+1) + 2;
26212113Sralph 				prank(rank);
26312113Sralph 				blankfill(JOBCOL);
26412113Sralph 				printf(" [job %s]\n", cf+3);
26512113Sralph 			} else {
26612113Sralph 				col = 0;
26712113Sralph 				prank(rank);
26812113Sralph 				blankfill(OWNCOL);
26912113Sralph 				printf("%-10s %-3d  ", line+1, atoi(cf+3));
27012113Sralph 				col += 16;
27112113Sralph 				first = 1;
27212113Sralph 			}
27312113Sralph 			continue;
27412113Sralph 		default: /* some format specifer and file name? */
27512113Sralph 			if (line[0] < 'a' || line[0] > 'z')
27612113Sralph 				continue;
27712113Sralph 			if (j == 0 || strcmp(file, line+1) != 0)
27830995Sbostic 				(void) strcpy(file, line+1);
27912113Sralph 			j++;
28012113Sralph 			continue;
28112113Sralph 		case 'N':
28212113Sralph 			show(line+1, file, j);
28312113Sralph 			file[0] = '\0';
28412113Sralph 			j = 0;
28512113Sralph 		}
28612113Sralph 	}
28712113Sralph 	fclose(cfp);
28812113Sralph 	if (!lflag) {
28912113Sralph 		blankfill(SIZCOL);
29034587Sbostic 		printf("%ld bytes\n", totsize);
29112113Sralph 		totsize = 0;
29212113Sralph 	}
29312113Sralph }
29412113Sralph 
29555470Sbostic int
inlist(name,file)29612113Sralph inlist(name, file)
29712113Sralph 	char *name, *file;
29812113Sralph {
29912113Sralph 	register int *r, n;
30012113Sralph 	register char **u, *cp;
30112113Sralph 
30212113Sralph 	if (users == 0 && requests == 0)
30312113Sralph 		return(1);
30412113Sralph 	/*
30512113Sralph 	 * Check to see if it's in the user list
30612113Sralph 	 */
30712113Sralph 	for (u = user; u < &user[users]; u++)
30812113Sralph 		if (!strcmp(*u, name))
30912113Sralph 			return(1);
31012113Sralph 	/*
31112113Sralph 	 * Check the request list
31212113Sralph 	 */
31312113Sralph 	for (n = 0, cp = file+3; isdigit(*cp); )
31412113Sralph 		n = n * 10 + (*cp++ - '0');
31512113Sralph 	for (r = requ; r < &requ[requests]; r++)
31612113Sralph 		if (*r == n && !strcmp(cp, from))
31712113Sralph 			return(1);
31812113Sralph 	return(0);
31912113Sralph }
32012113Sralph 
32155470Sbostic void
show(nfile,file,copies)32212113Sralph show(nfile, file, copies)
32312113Sralph 	register char *nfile, *file;
32455470Sbostic 	int copies;
32512113Sralph {
32612113Sralph 	if (strcmp(nfile, " ") == 0)
32712113Sralph 		nfile = "(standard input)";
32812113Sralph 	if (lflag)
32912113Sralph 		ldump(nfile, file, copies);
33012113Sralph 	else
33112113Sralph 		dump(nfile, file, copies);
33212113Sralph }
33312113Sralph 
33412113Sralph /*
33512113Sralph  * Fill the line with blanks to the specified column
33612113Sralph  */
33755470Sbostic void
blankfill(n)33812113Sralph blankfill(n)
33912113Sralph 	register int n;
34012113Sralph {
34112113Sralph 	while (col++ < n)
34212113Sralph 		putchar(' ');
34312113Sralph }
34412113Sralph 
34512113Sralph /*
34612113Sralph  * Give the abbreviated dump of the file names
34712113Sralph  */
34855470Sbostic void
dump(nfile,file,copies)34912113Sralph dump(nfile, file, copies)
35012113Sralph 	char *nfile, *file;
35155470Sbostic 	int copies;
35212113Sralph {
35312113Sralph 	register short n, fill;
35412113Sralph 	struct stat lbuf;
35512113Sralph 
35612113Sralph 	/*
35712113Sralph 	 * Print as many files as will fit
35812113Sralph 	 *  (leaving room for the total size)
35912113Sralph 	 */
36012113Sralph 	 fill = first ? 0 : 2;	/* fill space for ``, '' */
36112113Sralph 	 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) {
36212113Sralph 		if (col < SIZCOL) {
36312113Sralph 			printf(" ..."), col += 4;
36412113Sralph 			blankfill(SIZCOL);
36512113Sralph 		}
36612113Sralph 	} else {
36712113Sralph 		if (first)
36812113Sralph 			first = 0;
36912113Sralph 		else
37012113Sralph 			printf(", ");
37112113Sralph 		printf("%s", nfile);
37212113Sralph 		col += n+fill;
37312113Sralph 	}
37412113Sralph 	if (*file && !stat(file, &lbuf))
37512113Sralph 		totsize += copies * lbuf.st_size;
37612113Sralph }
37712113Sralph 
37812113Sralph /*
37912113Sralph  * Print the long info about the file
38012113Sralph  */
38155470Sbostic void
ldump(nfile,file,copies)38212113Sralph ldump(nfile, file, copies)
38312113Sralph 	char *nfile, *file;
38455470Sbostic 	int copies;
38512113Sralph {
38612113Sralph 	struct stat lbuf;
38712113Sralph 
38812113Sralph 	putchar('\t');
38912113Sralph 	if (copies > 1)
39012113Sralph 		printf("%-2d copies of %-19s", copies, nfile);
39112113Sralph 	else
39212113Sralph 		printf("%-32s", nfile);
39312113Sralph 	if (*file && !stat(file, &lbuf))
39468971Stef 		printf(" %ld bytes", (long)lbuf.st_size);
39512113Sralph 	else
39612113Sralph 		printf(" ??? bytes");
39712113Sralph 	putchar('\n');
39812113Sralph }
39912113Sralph 
40012113Sralph /*
40112113Sralph  * Print the job's rank in the queue,
40212113Sralph  *   update col for screen management
40312113Sralph  */
40455470Sbostic void
prank(n)40512113Sralph prank(n)
40655470Sbostic 	int n;
40712113Sralph {
40855470Sbostic 	char rline[100];
40912113Sralph 	static char *r[] = {
41012113Sralph 		"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
41112113Sralph 	};
41212113Sralph 
41312113Sralph 	if (n == 0) {
41412113Sralph 		printf("active");
41512113Sralph 		col += 6;
41612113Sralph 		return;
41712113Sralph 	}
41838491Sbostic 	if ((n/10)%10 == 1)
41955470Sbostic 		(void)snprintf(rline, sizeof(rline), "%dth", n);
42012113Sralph 	else
42155470Sbostic 		(void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]);
42255470Sbostic 	col += strlen(rline);
42355470Sbostic 	printf("%s", rline);
42412113Sralph }
425