122427Sdist /*
222427Sdist  * Copyright (c) 1983 Regents of the University of California.
322427Sdist  * All rights reserved.  The Berkeley software License Agreement
422427Sdist  * specifies the terms and conditions for redistribution.
522427Sdist  */
622427Sdist 
713952Ssam #ifndef lint
8*25467Stef static char sccsid[] = "@(#)displayq.c	5.1 (Berkeley) 6/6/85";
922427Sdist #endif not lint
1013952Ssam 
1112113Sralph /*
1212113Sralph  * Routines to display the state of the queue.
1312113Sralph  */
1412113Sralph 
1512113Sralph #include "lp.h"
1612113Sralph 
1713170Sralph #define JOBCOL	40		/* column for job # in -l format */
1813170Sralph #define OWNCOL	7		/* start of Owner column in normal */
1913170Sralph #define SIZCOL	62		/* start of Size column in normal */
2012113Sralph 
2112113Sralph /*
2212113Sralph  * Stuff for handling job specifications
2312113Sralph  */
2412113Sralph extern char	*user[];	/* users to process */
2512113Sralph extern int	users;		/* # of users in user array */
2612113Sralph extern int	requ[];		/* job number of spool entries */
2712113Sralph extern int	requests;	/* # of spool requests */
2812113Sralph 
2916758Sralph int	lflag;		/* long output option */
3016758Sralph char	current[40];	/* current file being printed */
3116758Sralph int	garbage;	/* # of garbage cf files */
3216758Sralph int	rank;		/* order to be printed (-1=none, 0=active) */
3316758Sralph long	totsize;	/* total print job size in bytes */
3416758Sralph int	first;		/* first file in ``files'' column? */
3516758Sralph int	col;		/* column on screen */
3616758Sralph int	sendtorem;	/* are we sending to a remote? */
3716758Sralph char	file[132];	/* print file name */
3812113Sralph 
3916758Sralph char	*head0 = "Rank   Owner      Job  Files";
4016758Sralph char	*head1 = "Total Size\n";
4112113Sralph 
4212113Sralph /*
4312113Sralph  * Display the current state of the queue. Format = 1 if long format.
4412113Sralph  */
4512113Sralph displayq(format)
4612113Sralph 	int format;
4712113Sralph {
4812113Sralph 	register struct queue *q;
4912113Sralph 	register int i, nitems, fd;
5012113Sralph 	struct queue **queue;
5112113Sralph 	struct stat statb;
5212113Sralph 	FILE *fp;
5312113Sralph 
5412113Sralph 	lflag = format;
5512113Sralph 	totsize = 0;
5612113Sralph 	rank = -1;
5712113Sralph 
5812113Sralph 	if ((i = pgetent(line, printer)) < 0)
5912113Sralph 		fatal("cannot open printer description file");
6012113Sralph 	else if (i == 0)
6112113Sralph 		fatal("unknown printer");
6212113Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
6312113Sralph 		LP = DEFDEVLP;
6412113Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
6512434Sralph 		RP = DEFLP;
6612113Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
6712113Sralph 		SD = DEFSPOOL;
6812113Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
6912113Sralph 		LO = DEFLOCK;
7012113Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
7112113Sralph 		ST = DEFSTAT;
7212113Sralph 	RM = pgetstr("rm", &bp);
7312113Sralph 
7412113Sralph 	/*
75*25467Stef 	 * Figure out whether the local machine is the same as the remote
76*25467Stef 	 * machine entry (if it exists).  If not, then ignore the local
77*25467Stef 	 * queue information.
78*25467Stef 	 */
79*25467Stef 	 if (RM != (char *) NULL) {
80*25467Stef 		char name[256];
81*25467Stef 		struct hostent *hp;
82*25467Stef 
83*25467Stef 		/* get the standard network name of the local host */
84*25467Stef 		gethostname(name, sizeof(name));
85*25467Stef 		name[sizeof(name)-1] = '\0';
86*25467Stef 		hp = gethostbyname(name);
87*25467Stef 		if (hp == (struct hostent *) NULL) {
88*25467Stef 		    printf("unable to get network name for local machine %s\n",
89*25467Stef 			name);
90*25467Stef 		    goto localcheck_done;
91*25467Stef 		} else strcpy(name, hp->h_name);
92*25467Stef 
93*25467Stef 		/* get the network standard name of RM */
94*25467Stef 		hp = gethostbyname(RM);
95*25467Stef 		if (hp == (struct hostent *) NULL) {
96*25467Stef 		    printf("unable to get hostname for remote machine %s\n",
97*25467Stef 			RM);
98*25467Stef 		    goto localcheck_done;
99*25467Stef 		}
100*25467Stef 
101*25467Stef 		/* if printer is not on local machine, ignore LP */
102*25467Stef 		if (strcmp(name, hp->h_name) != 0) *LP = '\0';
103*25467Stef 	}
104*25467Stef localcheck_done:
105*25467Stef 
106*25467Stef 	/*
10712113Sralph 	 * If there is no local printer, then print the queue on
10812113Sralph 	 * the remote machine and then what's in the queue here.
10912113Sralph 	 * Note that a file in transit may not show up in either queue.
11012113Sralph 	 */
11112113Sralph 	if (*LP == '\0') {
11212113Sralph 		register char *cp;
11312113Sralph 		char c;
11412113Sralph 
11512113Sralph 		sendtorem++;
11612113Sralph 		(void) sprintf(line, "%c%s", format + '\3', RP);
11712113Sralph 		cp = line;
11812113Sralph 		for (i = 0; i < requests; i++) {
11912113Sralph 			cp += strlen(cp);
12012113Sralph 			(void) sprintf(cp, " %d", requ[i]);
12112113Sralph 		}
12212113Sralph 		for (i = 0; i < users; i++) {
12312113Sralph 			cp += strlen(cp);
12412113Sralph 			*cp++ = ' ';
12512113Sralph 			strcpy(cp, user[i]);
12612113Sralph 		}
12712113Sralph 		strcat(line, "\n");
12812531Sralph 		fd = getport(RM);
12912113Sralph 		if (fd < 0) {
13012113Sralph 			if (from != host)
13112113Sralph 				printf("%s: ", host);
13212113Sralph 			printf("connection to %s is down\n", RM);
13312113Sralph 		} else {
13412113Sralph 			i = strlen(line);
13512113Sralph 			if (write(fd, line, i) != i)
13612113Sralph 				fatal("Lost connection");
13712113Sralph 			while ((i = read(fd, line, sizeof(line))) > 0)
13812113Sralph 				(void) fwrite(line, 1, i, stdout);
13912113Sralph 			(void) close(fd);
14012113Sralph 		}
14112113Sralph 	}
14212113Sralph 	/*
14312113Sralph 	 * Find all the control files in the spooling directory
14412113Sralph 	 */
14512113Sralph 	if (chdir(SD) < 0)
14612113Sralph 		fatal("cannot chdir to spooling directory");
14712113Sralph 	if ((nitems = getq(&queue)) < 0)
14812113Sralph 		fatal("cannot examine spooling area\n");
14916205Sralph 	if (stat(LO, &statb) >= 0) {
15016205Sralph 		if ((statb.st_mode & 0110) && sendtorem)
15116205Sralph 			printf("\n");
15216205Sralph 		if (statb.st_mode & 0100) {
15316205Sralph 			if (sendtorem)
15416205Sralph 				printf("%s: ", host);
15516205Sralph 			printf("Warning: %s is down: ", printer);
15616205Sralph 			fd = open(ST, O_RDONLY);
15716205Sralph 			if (fd >= 0) {
15816205Sralph 				(void) flock(fd, LOCK_SH);
15916205Sralph 				while ((i = read(fd, line, sizeof(line))) > 0)
16016205Sralph 					(void) fwrite(line, 1, i, stdout);
16116205Sralph 				(void) close(fd);	/* unlocks as well */
16216205Sralph 			} else
16316205Sralph 				putchar('\n');
16416205Sralph 		}
16516205Sralph 		if (statb.st_mode & 010) {
16616205Sralph 			if (sendtorem)
16716205Sralph 				printf("%s: ", host);
16816205Sralph 			printf("Warning: %s queue is turned off\n", printer);
16916205Sralph 		}
17012740Sralph 	}
17112740Sralph 	if (nitems == 0) {
17212740Sralph 		if (!sendtorem)
17312740Sralph 			printf("no entries\n");
17412113Sralph 		return(0);
17512113Sralph 	}
17612113Sralph 	fp = fopen(LO, "r");
17713441Sralph 	if (fp == NULL)
17813441Sralph 		warn();
17913441Sralph 	else {
18013441Sralph 		register char *cp;
18112113Sralph 
18213441Sralph 		/* get daemon pid */
18313441Sralph 		cp = current;
18412113Sralph 		while ((*cp = getc(fp)) != EOF && *cp != '\n')
18512113Sralph 			cp++;
18612113Sralph 		*cp = '\0';
18713441Sralph 		i = atoi(current);
18815908Sralph 		if (i <= 0 || kill(i, 0) < 0)
18913441Sralph 			warn();
19013441Sralph 		else {
19113441Sralph 			/* read current file name */
19213441Sralph 			cp = current;
19313441Sralph 			while ((*cp = getc(fp)) != EOF && *cp != '\n')
19413441Sralph 				cp++;
19513441Sralph 			*cp = '\0';
19613441Sralph 			/*
19713441Sralph 			 * Print the status file.
19813441Sralph 			 */
19913441Sralph 			if (sendtorem)
20013441Sralph 				printf("\n%s: ", host);
20113441Sralph 			fd = open(ST, O_RDONLY);
20213441Sralph 			if (fd >= 0) {
20313441Sralph 				(void) flock(fd, LOCK_SH);
20413441Sralph 				while ((i = read(fd, line, sizeof(line))) > 0)
20513441Sralph 					(void) fwrite(line, 1, i, stdout);
20613441Sralph 				(void) close(fd);	/* unlocks as well */
20713441Sralph 			} else
20813441Sralph 				putchar('\n');
20913441Sralph 		}
21013441Sralph 		(void) fclose(fp);
21112113Sralph 	}
21212113Sralph 	/*
21312113Sralph 	 * Now, examine the control files and print out the jobs to
21412113Sralph 	 * be done for each user.
21512113Sralph 	 */
21612113Sralph 	if (!lflag)
21712113Sralph 		header();
21812113Sralph 	for (i = 0; i < nitems; i++) {
21912113Sralph 		q = queue[i];
22012113Sralph 		inform(q->q_name);
22112113Sralph 		free(q);
22212113Sralph 	}
22312113Sralph 	free(queue);
22412113Sralph 	return(nitems-garbage);
22512113Sralph }
22612113Sralph 
22712113Sralph /*
22813441Sralph  * Print a warning message if there is no daemon present.
22913441Sralph  */
23013441Sralph warn()
23113441Sralph {
23213441Sralph 	if (sendtorem)
23313441Sralph 		printf("\n%s: ", host);
23416205Sralph 	printf("Warning: no daemon present\n");
23513441Sralph 	current[0] = '\0';
23613441Sralph }
23713441Sralph 
23813441Sralph /*
23912113Sralph  * Print the header for the short listing format
24012113Sralph  */
24112113Sralph header()
24212113Sralph {
24312113Sralph 	printf(head0);
24412113Sralph 	col = strlen(head0)+1;
24512113Sralph 	blankfill(SIZCOL);
24612113Sralph 	printf(head1);
24712113Sralph }
24812113Sralph 
24912113Sralph inform(cf)
25012113Sralph 	char *cf;
25112113Sralph {
25212113Sralph 	register int j, k;
25312113Sralph 	register char *cp;
25412113Sralph 	FILE *cfp;
25512113Sralph 
25612113Sralph 	/*
25712113Sralph 	 * There's a chance the control file has gone away
25812113Sralph 	 * in the meantime; if this is the case just keep going
25912113Sralph 	 */
26012113Sralph 	if ((cfp = fopen(cf, "r")) == NULL)
26112113Sralph 		return;
26212113Sralph 
26312113Sralph 	if (rank < 0)
26412113Sralph 		rank = 0;
26512113Sralph 	if (sendtorem || garbage || strcmp(cf, current))
26612113Sralph 		rank++;
26712113Sralph 	j = 0;
26812113Sralph 	while (getline(cfp)) {
26912113Sralph 		switch (line[0]) {
27012113Sralph 		case 'P': /* Was this file specified in the user's list? */
27112113Sralph 			if (!inlist(line+1, cf)) {
27212113Sralph 				fclose(cfp);
27312113Sralph 				return;
27412113Sralph 			}
27512113Sralph 			if (lflag) {
27612113Sralph 				printf("\n%s: ", line+1);
27712113Sralph 				col = strlen(line+1) + 2;
27812113Sralph 				prank(rank);
27912113Sralph 				blankfill(JOBCOL);
28012113Sralph 				printf(" [job %s]\n", cf+3);
28112113Sralph 			} else {
28212113Sralph 				col = 0;
28312113Sralph 				prank(rank);
28412113Sralph 				blankfill(OWNCOL);
28512113Sralph 				printf("%-10s %-3d  ", line+1, atoi(cf+3));
28612113Sralph 				col += 16;
28712113Sralph 				first = 1;
28812113Sralph 			}
28912113Sralph 			continue;
29012113Sralph 		default: /* some format specifer and file name? */
29112113Sralph 			if (line[0] < 'a' || line[0] > 'z')
29212113Sralph 				continue;
29312113Sralph 			if (j == 0 || strcmp(file, line+1) != 0)
29412113Sralph 				strcpy(file, line+1);
29512113Sralph 			j++;
29612113Sralph 			continue;
29712113Sralph 		case 'N':
29812113Sralph 			show(line+1, file, j);
29912113Sralph 			file[0] = '\0';
30012113Sralph 			j = 0;
30112113Sralph 		}
30212113Sralph 	}
30312113Sralph 	fclose(cfp);
30412113Sralph 	if (!lflag) {
30512113Sralph 		blankfill(SIZCOL);
30612113Sralph 		printf("%D bytes\n", totsize);
30712113Sralph 		totsize = 0;
30812113Sralph 	}
30912113Sralph }
31012113Sralph 
31112113Sralph inlist(name, file)
31212113Sralph 	char *name, *file;
31312113Sralph {
31412113Sralph 	register int *r, n;
31512113Sralph 	register char **u, *cp;
31612113Sralph 
31712113Sralph 	if (users == 0 && requests == 0)
31812113Sralph 		return(1);
31912113Sralph 	/*
32012113Sralph 	 * Check to see if it's in the user list
32112113Sralph 	 */
32212113Sralph 	for (u = user; u < &user[users]; u++)
32312113Sralph 		if (!strcmp(*u, name))
32412113Sralph 			return(1);
32512113Sralph 	/*
32612113Sralph 	 * Check the request list
32712113Sralph 	 */
32812113Sralph 	for (n = 0, cp = file+3; isdigit(*cp); )
32912113Sralph 		n = n * 10 + (*cp++ - '0');
33012113Sralph 	for (r = requ; r < &requ[requests]; r++)
33112113Sralph 		if (*r == n && !strcmp(cp, from))
33212113Sralph 			return(1);
33312113Sralph 	return(0);
33412113Sralph }
33512113Sralph 
33612113Sralph show(nfile, file, copies)
33712113Sralph 	register char *nfile, *file;
33812113Sralph {
33912113Sralph 	if (strcmp(nfile, " ") == 0)
34012113Sralph 		nfile = "(standard input)";
34112113Sralph 	if (lflag)
34212113Sralph 		ldump(nfile, file, copies);
34312113Sralph 	else
34412113Sralph 		dump(nfile, file, copies);
34512113Sralph }
34612113Sralph 
34712113Sralph /*
34812113Sralph  * Fill the line with blanks to the specified column
34912113Sralph  */
35012113Sralph blankfill(n)
35112113Sralph 	register int n;
35212113Sralph {
35312113Sralph 	while (col++ < n)
35412113Sralph 		putchar(' ');
35512113Sralph }
35612113Sralph 
35712113Sralph /*
35812113Sralph  * Give the abbreviated dump of the file names
35912113Sralph  */
36012113Sralph dump(nfile, file, copies)
36112113Sralph 	char *nfile, *file;
36212113Sralph {
36312113Sralph 	register short n, fill;
36412113Sralph 	struct stat lbuf;
36512113Sralph 
36612113Sralph 	/*
36712113Sralph 	 * Print as many files as will fit
36812113Sralph 	 *  (leaving room for the total size)
36912113Sralph 	 */
37012113Sralph 	 fill = first ? 0 : 2;	/* fill space for ``, '' */
37112113Sralph 	 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) {
37212113Sralph 		if (col < SIZCOL) {
37312113Sralph 			printf(" ..."), col += 4;
37412113Sralph 			blankfill(SIZCOL);
37512113Sralph 		}
37612113Sralph 	} else {
37712113Sralph 		if (first)
37812113Sralph 			first = 0;
37912113Sralph 		else
38012113Sralph 			printf(", ");
38112113Sralph 		printf("%s", nfile);
38212113Sralph 		col += n+fill;
38312113Sralph 	}
38412113Sralph 	if (*file && !stat(file, &lbuf))
38512113Sralph 		totsize += copies * lbuf.st_size;
38612113Sralph }
38712113Sralph 
38812113Sralph /*
38912113Sralph  * Print the long info about the file
39012113Sralph  */
39112113Sralph ldump(nfile, file, copies)
39212113Sralph 	char *nfile, *file;
39312113Sralph {
39412113Sralph 	struct stat lbuf;
39512113Sralph 
39612113Sralph 	putchar('\t');
39712113Sralph 	if (copies > 1)
39812113Sralph 		printf("%-2d copies of %-19s", copies, nfile);
39912113Sralph 	else
40012113Sralph 		printf("%-32s", nfile);
40112113Sralph 	if (*file && !stat(file, &lbuf))
40212113Sralph 		printf(" %D bytes", lbuf.st_size);
40312113Sralph 	else
40412113Sralph 		printf(" ??? bytes");
40512113Sralph 	putchar('\n');
40612113Sralph }
40712113Sralph 
40812113Sralph /*
40912113Sralph  * Print the job's rank in the queue,
41012113Sralph  *   update col for screen management
41112113Sralph  */
41212113Sralph prank(n)
41312113Sralph {
41412113Sralph 	char line[100];
41512113Sralph 	static char *r[] = {
41612113Sralph 		"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
41712113Sralph 	};
41812113Sralph 
41912113Sralph 	if (n == 0) {
42012113Sralph 		printf("active");
42112113Sralph 		col += 6;
42212113Sralph 		return;
42312113Sralph 	}
42412113Sralph 	if ((n/10) == 1)
42512113Sralph 		(void) sprintf(line, "%dth", n);
42612113Sralph 	else
42712113Sralph 		(void) sprintf(line, "%d%s", n, r[n%10]);
42812113Sralph 	col += strlen(line);
42912113Sralph 	printf("%s", line);
43012113Sralph }
431