1*13441Sralph /*	displayq.c	4.8	83/06/29	*/
212113Sralph /*
312113Sralph  * Routines to display the state of the queue.
412113Sralph  */
512113Sralph 
612113Sralph #include "lp.h"
712113Sralph 
813170Sralph #define JOBCOL	40		/* column for job # in -l format */
913170Sralph #define OWNCOL	7		/* start of Owner column in normal */
1013170Sralph #define SIZCOL	62		/* start of Size column in normal */
1112113Sralph 
1212113Sralph /*
1312113Sralph  * Stuff for handling job specifications
1412113Sralph  */
1512113Sralph extern char	*user[];	/* users to process */
1612113Sralph extern int	users;		/* # of users in user array */
1712113Sralph extern int	requ[];		/* job number of spool entries */
1812113Sralph extern int	requests;	/* # of spool requests */
1912113Sralph 
2012878Sralph static int	lflag;		/* long output option */
2112878Sralph static char	current[40];	/* current file being printed */
2212878Sralph static int	garbage;	/* # of garbage cf files */
2312878Sralph static int	rank;		/* order to be printed (-1=none, 0=active) */
2412878Sralph static long	totsize;	/* total print job size in bytes */
2512878Sralph static int	first;		/* first file in ``files'' column? */
2612878Sralph static int	col;		/* column on screen */
2712878Sralph static int	sendtorem;	/* are we sending to a remote? */
2812878Sralph static char	file[132];	/* print file name */
2912113Sralph 
3012878Sralph static char	*head0 = "Rank   Owner      Job  Files";
3112878Sralph static char	*head1 = "Total Size\n";
3212113Sralph 
3312113Sralph /*
3412113Sralph  * Display the current state of the queue. Format = 1 if long format.
3512113Sralph  */
3612113Sralph displayq(format)
3712113Sralph 	int format;
3812113Sralph {
3912113Sralph 	register struct queue *q;
4012113Sralph 	register int i, nitems, fd;
4112113Sralph 	struct queue **queue;
4212113Sralph 	struct stat statb;
4312113Sralph 	FILE *fp;
4412113Sralph 
4512113Sralph 	lflag = format;
4612113Sralph 	totsize = 0;
4712113Sralph 	rank = -1;
4812113Sralph 
4912113Sralph 	if ((i = pgetent(line, printer)) < 0)
5012113Sralph 		fatal("cannot open printer description file");
5112113Sralph 	else if (i == 0)
5212113Sralph 		fatal("unknown printer");
5312113Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
5412113Sralph 		LP = DEFDEVLP;
5512113Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
5612434Sralph 		RP = DEFLP;
5712113Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
5812113Sralph 		SD = DEFSPOOL;
5912113Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
6012113Sralph 		LO = DEFLOCK;
6112113Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
6212113Sralph 		ST = DEFSTAT;
6312113Sralph 	RM = pgetstr("rm", &bp);
6412113Sralph 
6512113Sralph 	/*
6612113Sralph 	 * If there is no local printer, then print the queue on
6712113Sralph 	 * the remote machine and then what's in the queue here.
6812113Sralph 	 * Note that a file in transit may not show up in either queue.
6912113Sralph 	 */
7012113Sralph 	if (*LP == '\0') {
7112113Sralph 		register char *cp;
7212113Sralph 		char c;
7312113Sralph 
7412113Sralph 		sendtorem++;
7512113Sralph 		(void) sprintf(line, "%c%s", format + '\3', RP);
7612113Sralph 		cp = line;
7712113Sralph 		for (i = 0; i < requests; i++) {
7812113Sralph 			cp += strlen(cp);
7912113Sralph 			(void) sprintf(cp, " %d", requ[i]);
8012113Sralph 		}
8112113Sralph 		for (i = 0; i < users; i++) {
8212113Sralph 			cp += strlen(cp);
8312113Sralph 			*cp++ = ' ';
8412113Sralph 			strcpy(cp, user[i]);
8512113Sralph 		}
8612113Sralph 		strcat(line, "\n");
8712531Sralph 		fd = getport(RM);
8812113Sralph 		if (fd < 0) {
8912113Sralph 			if (from != host)
9012113Sralph 				printf("%s: ", host);
9112113Sralph 			printf("connection to %s is down\n", RM);
9212113Sralph 		} else {
9312113Sralph 			i = strlen(line);
9412113Sralph 			if (write(fd, line, i) != i)
9512113Sralph 				fatal("Lost connection");
9612113Sralph 			while ((i = read(fd, line, sizeof(line))) > 0)
9712113Sralph 				(void) fwrite(line, 1, i, stdout);
9812113Sralph 			(void) close(fd);
9912113Sralph 		}
10012113Sralph 	}
10112113Sralph 	/*
10212113Sralph 	 * Find all the control files in the spooling directory
10312113Sralph 	 */
10412113Sralph 	if (chdir(SD) < 0)
10512113Sralph 		fatal("cannot chdir to spooling directory");
10612113Sralph 	if ((nitems = getq(&queue)) < 0)
10712113Sralph 		fatal("cannot examine spooling area\n");
10812740Sralph 	if (stat(LO, &statb) >= 0 && (statb.st_mode & 010)) {
10912113Sralph 		if (sendtorem)
11012113Sralph 			printf("\n%s: ", host);
11112740Sralph 		printf("Warning: %s queue is turned off\n", printer);
11212740Sralph 	}
11312740Sralph 	if (nitems == 0) {
11412740Sralph 		if (!sendtorem)
11512740Sralph 			printf("no entries\n");
11612113Sralph 		return(0);
11712113Sralph 	}
11812113Sralph 	fp = fopen(LO, "r");
119*13441Sralph 	if (fp == NULL)
120*13441Sralph 		warn();
121*13441Sralph 	else {
122*13441Sralph 		register char *cp;
12312113Sralph 
124*13441Sralph 		/* get daemon pid */
125*13441Sralph 		cp = current;
12612113Sralph 		while ((*cp = getc(fp)) != EOF && *cp != '\n')
12712113Sralph 			cp++;
12812113Sralph 		*cp = '\0';
129*13441Sralph 		i = atoi(current);
130*13441Sralph 		if (kill(i, 0) < 0)
131*13441Sralph 			warn();
132*13441Sralph 		else {
133*13441Sralph 			/* read current file name */
134*13441Sralph 			cp = current;
135*13441Sralph 			while ((*cp = getc(fp)) != EOF && *cp != '\n')
136*13441Sralph 				cp++;
137*13441Sralph 			*cp = '\0';
138*13441Sralph 			/*
139*13441Sralph 			 * Print the status file.
140*13441Sralph 			 */
141*13441Sralph 			if (sendtorem)
142*13441Sralph 				printf("\n%s: ", host);
143*13441Sralph 			fd = open(ST, O_RDONLY);
144*13441Sralph 			if (fd >= 0) {
145*13441Sralph 				(void) flock(fd, LOCK_SH);
146*13441Sralph 				while ((i = read(fd, line, sizeof(line))) > 0)
147*13441Sralph 					(void) fwrite(line, 1, i, stdout);
148*13441Sralph 				(void) close(fd);	/* unlocks as well */
149*13441Sralph 			} else
150*13441Sralph 				putchar('\n');
151*13441Sralph 		}
152*13441Sralph 		(void) fclose(fp);
15312113Sralph 	}
15412113Sralph 	/*
15512113Sralph 	 * Now, examine the control files and print out the jobs to
15612113Sralph 	 * be done for each user.
15712113Sralph 	 */
15812113Sralph 	if (!lflag)
15912113Sralph 		header();
16012113Sralph 	for (i = 0; i < nitems; i++) {
16112113Sralph 		q = queue[i];
16212113Sralph 		inform(q->q_name);
16312113Sralph 		free(q);
16412113Sralph 	}
16512113Sralph 	free(queue);
16612113Sralph 	return(nitems-garbage);
16712113Sralph }
16812113Sralph 
16912113Sralph /*
170*13441Sralph  * Print a warning message if there is no daemon present.
171*13441Sralph  */
172*13441Sralph warn()
173*13441Sralph {
174*13441Sralph 	struct stat statb;
175*13441Sralph 
176*13441Sralph 	if (sendtorem)
177*13441Sralph 		printf("\n%s: ", host);
178*13441Sralph 	if (stat(LO, &statb) >= 0 && (statb.st_mode & 0100))
179*13441Sralph 		printf("Warning: %s is down\n", printer);
180*13441Sralph 	else
181*13441Sralph 		printf("Warning: no daemon present\n");
182*13441Sralph 	current[0] = '\0';
183*13441Sralph }
184*13441Sralph 
185*13441Sralph /*
18612113Sralph  * Print the header for the short listing format
18712113Sralph  */
18812878Sralph static
18912113Sralph header()
19012113Sralph {
19112113Sralph 	printf(head0);
19212113Sralph 	col = strlen(head0)+1;
19312113Sralph 	blankfill(SIZCOL);
19412113Sralph 	printf(head1);
19512113Sralph }
19612113Sralph 
19712878Sralph static
19812113Sralph inform(cf)
19912113Sralph 	char *cf;
20012113Sralph {
20112113Sralph 	register int j, k;
20212113Sralph 	register char *cp;
20312113Sralph 	FILE *cfp;
20412113Sralph 
20512113Sralph 	/*
20612113Sralph 	 * There's a chance the control file has gone away
20712113Sralph 	 * in the meantime; if this is the case just keep going
20812113Sralph 	 */
20912113Sralph 	if ((cfp = fopen(cf, "r")) == NULL)
21012113Sralph 		return;
21112113Sralph 
21212113Sralph 	if (rank < 0)
21312113Sralph 		rank = 0;
21412113Sralph 	if (sendtorem || garbage || strcmp(cf, current))
21512113Sralph 		rank++;
21612113Sralph 	j = 0;
21712113Sralph 	while (getline(cfp)) {
21812113Sralph 		switch (line[0]) {
21912113Sralph 		case 'P': /* Was this file specified in the user's list? */
22012113Sralph 			if (!inlist(line+1, cf)) {
22112113Sralph 				fclose(cfp);
22212113Sralph 				return;
22312113Sralph 			}
22412113Sralph 			if (lflag) {
22512113Sralph 				printf("\n%s: ", line+1);
22612113Sralph 				col = strlen(line+1) + 2;
22712113Sralph 				prank(rank);
22812113Sralph 				blankfill(JOBCOL);
22912113Sralph 				printf(" [job %s]\n", cf+3);
23012113Sralph 			} else {
23112113Sralph 				col = 0;
23212113Sralph 				prank(rank);
23312113Sralph 				blankfill(OWNCOL);
23412113Sralph 				printf("%-10s %-3d  ", line+1, atoi(cf+3));
23512113Sralph 				col += 16;
23612113Sralph 				first = 1;
23712113Sralph 			}
23812113Sralph 			continue;
23912113Sralph 		default: /* some format specifer and file name? */
24012113Sralph 			if (line[0] < 'a' || line[0] > 'z')
24112113Sralph 				continue;
24212113Sralph 			if (j == 0 || strcmp(file, line+1) != 0)
24312113Sralph 				strcpy(file, line+1);
24412113Sralph 			j++;
24512113Sralph 			continue;
24612113Sralph 		case 'N':
24712113Sralph 			show(line+1, file, j);
24812113Sralph 			file[0] = '\0';
24912113Sralph 			j = 0;
25012113Sralph 		}
25112113Sralph 	}
25212113Sralph 	fclose(cfp);
25312113Sralph 	if (!lflag) {
25412113Sralph 		blankfill(SIZCOL);
25512113Sralph 		printf("%D bytes\n", totsize);
25612113Sralph 		totsize = 0;
25712113Sralph 	}
25812113Sralph }
25912113Sralph 
26012878Sralph static
26112113Sralph inlist(name, file)
26212113Sralph 	char *name, *file;
26312113Sralph {
26412113Sralph 	register int *r, n;
26512113Sralph 	register char **u, *cp;
26612113Sralph 
26712113Sralph 	if (users == 0 && requests == 0)
26812113Sralph 		return(1);
26912113Sralph 	/*
27012113Sralph 	 * Check to see if it's in the user list
27112113Sralph 	 */
27212113Sralph 	for (u = user; u < &user[users]; u++)
27312113Sralph 		if (!strcmp(*u, name))
27412113Sralph 			return(1);
27512113Sralph 	/*
27612113Sralph 	 * Check the request list
27712113Sralph 	 */
27812113Sralph 	for (n = 0, cp = file+3; isdigit(*cp); )
27912113Sralph 		n = n * 10 + (*cp++ - '0');
28012113Sralph 	for (r = requ; r < &requ[requests]; r++)
28112113Sralph 		if (*r == n && !strcmp(cp, from))
28212113Sralph 			return(1);
28312113Sralph 	return(0);
28412113Sralph }
28512113Sralph 
28612878Sralph static
28712113Sralph show(nfile, file, copies)
28812113Sralph 	register char *nfile, *file;
28912113Sralph {
29012113Sralph 	if (strcmp(nfile, " ") == 0)
29112113Sralph 		nfile = "(standard input)";
29212113Sralph 	if (lflag)
29312113Sralph 		ldump(nfile, file, copies);
29412113Sralph 	else
29512113Sralph 		dump(nfile, file, copies);
29612113Sralph }
29712113Sralph 
29812113Sralph /*
29912113Sralph  * Fill the line with blanks to the specified column
30012113Sralph  */
30112878Sralph static
30212113Sralph blankfill(n)
30312113Sralph 	register int n;
30412113Sralph {
30512113Sralph 	while (col++ < n)
30612113Sralph 		putchar(' ');
30712113Sralph }
30812113Sralph 
30912113Sralph /*
31012113Sralph  * Give the abbreviated dump of the file names
31112113Sralph  */
31212878Sralph static
31312113Sralph dump(nfile, file, copies)
31412113Sralph 	char *nfile, *file;
31512113Sralph {
31612113Sralph 	register short n, fill;
31712113Sralph 	struct stat lbuf;
31812113Sralph 
31912113Sralph 	/*
32012113Sralph 	 * Print as many files as will fit
32112113Sralph 	 *  (leaving room for the total size)
32212113Sralph 	 */
32312113Sralph 	 fill = first ? 0 : 2;	/* fill space for ``, '' */
32412113Sralph 	 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) {
32512113Sralph 		if (col < SIZCOL) {
32612113Sralph 			printf(" ..."), col += 4;
32712113Sralph 			blankfill(SIZCOL);
32812113Sralph 		}
32912113Sralph 	} else {
33012113Sralph 		if (first)
33112113Sralph 			first = 0;
33212113Sralph 		else
33312113Sralph 			printf(", ");
33412113Sralph 		printf("%s", nfile);
33512113Sralph 		col += n+fill;
33612113Sralph 	}
33712113Sralph 	if (*file && !stat(file, &lbuf))
33812113Sralph 		totsize += copies * lbuf.st_size;
33912113Sralph }
34012113Sralph 
34112113Sralph /*
34212113Sralph  * Print the long info about the file
34312113Sralph  */
34412878Sralph static
34512113Sralph ldump(nfile, file, copies)
34612113Sralph 	char *nfile, *file;
34712113Sralph {
34812113Sralph 	struct stat lbuf;
34912113Sralph 
35012113Sralph 	putchar('\t');
35112113Sralph 	if (copies > 1)
35212113Sralph 		printf("%-2d copies of %-19s", copies, nfile);
35312113Sralph 	else
35412113Sralph 		printf("%-32s", nfile);
35512113Sralph 	if (*file && !stat(file, &lbuf))
35612113Sralph 		printf(" %D bytes", lbuf.st_size);
35712113Sralph 	else
35812113Sralph 		printf(" ??? bytes");
35912113Sralph 	putchar('\n');
36012113Sralph }
36112113Sralph 
36212113Sralph /*
36312113Sralph  * Print the job's rank in the queue,
36412113Sralph  *   update col for screen management
36512113Sralph  */
36612878Sralph static
36712113Sralph prank(n)
36812113Sralph {
36912113Sralph 	char line[100];
37012113Sralph 	static char *r[] = {
37112113Sralph 		"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
37212113Sralph 	};
37312113Sralph 
37412113Sralph 	if (n == 0) {
37512113Sralph 		printf("active");
37612113Sralph 		col += 6;
37712113Sralph 		return;
37812113Sralph 	}
37912113Sralph 	if ((n/10) == 1)
38012113Sralph 		(void) sprintf(line, "%dth", n);
38112113Sralph 	else
38212113Sralph 		(void) sprintf(line, "%d%s", n, r[n%10]);
38312113Sralph 	col += strlen(line);
38412113Sralph 	printf("%s", line);
38512113Sralph }
386