122427Sdist /*
222427Sdist  * Copyright (c) 1983 Regents of the University of California.
334203Sbostic  * All rights reserved.
434203Sbostic  *
534203Sbostic  * Redistribution and use in source and binary forms are permitted
6*34936Sbostic  * provided that the above copyright notice and this paragraph are
7*34936Sbostic  * duplicated in all such forms and that any documentation,
8*34936Sbostic  * advertising materials, and other materials related to such
9*34936Sbostic  * distribution and use acknowledge that the software was developed
10*34936Sbostic  * by the University of California, Berkeley.  The name of the
11*34936Sbostic  * University may not be used to endorse or promote products derived
12*34936Sbostic  * from this software without specific prior written permission.
13*34936Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*34936Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*34936Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1622427Sdist  */
1722427Sdist 
1813952Ssam #ifndef lint
19*34936Sbostic static char sccsid[] = "@(#)displayq.c	5.8 (Berkeley) 06/30/88";
2034203Sbostic #endif /* not lint */
2113952Ssam 
2212113Sralph /*
2312113Sralph  * Routines to display the state of the queue.
2412113Sralph  */
2512113Sralph 
2612113Sralph #include "lp.h"
2712113Sralph 
2813170Sralph #define JOBCOL	40		/* column for job # in -l format */
2913170Sralph #define OWNCOL	7		/* start of Owner column in normal */
3013170Sralph #define SIZCOL	62		/* start of Size column in normal */
3112113Sralph 
3212113Sralph /*
3312113Sralph  * Stuff for handling job specifications
3412113Sralph  */
3512113Sralph extern char	*user[];	/* users to process */
3612113Sralph extern int	users;		/* # of users in user array */
3712113Sralph extern int	requ[];		/* job number of spool entries */
3812113Sralph extern int	requests;	/* # of spool requests */
3912113Sralph 
4016758Sralph int	lflag;		/* long output option */
4116758Sralph char	current[40];	/* current file being printed */
4216758Sralph int	garbage;	/* # of garbage cf files */
4316758Sralph int	rank;		/* order to be printed (-1=none, 0=active) */
4416758Sralph long	totsize;	/* total print job size in bytes */
4516758Sralph int	first;		/* first file in ``files'' column? */
4616758Sralph int	col;		/* column on screen */
4716758Sralph int	sendtorem;	/* are we sending to a remote? */
4816758Sralph char	file[132];	/* print file name */
4912113Sralph 
5016758Sralph char	*head0 = "Rank   Owner      Job  Files";
5116758Sralph char	*head1 = "Total Size\n";
5212113Sralph 
5312113Sralph /*
5412113Sralph  * Display the current state of the queue. Format = 1 if long format.
5512113Sralph  */
5612113Sralph displayq(format)
5712113Sralph 	int format;
5812113Sralph {
5912113Sralph 	register struct queue *q;
6012113Sralph 	register int i, nitems, fd;
6130995Sbostic 	register char	*cp;
6212113Sralph 	struct queue **queue;
6312113Sralph 	struct stat statb;
6412113Sralph 	FILE *fp;
6530995Sbostic 	char c;
6612113Sralph 
6712113Sralph 	lflag = format;
6812113Sralph 	totsize = 0;
6912113Sralph 	rank = -1;
7012113Sralph 
7112113Sralph 	if ((i = pgetent(line, printer)) < 0)
7212113Sralph 		fatal("cannot open printer description file");
7312113Sralph 	else if (i == 0)
7412113Sralph 		fatal("unknown printer");
7512113Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
7612113Sralph 		LP = DEFDEVLP;
7712113Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
7812434Sralph 		RP = DEFLP;
7912113Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
8012113Sralph 		SD = DEFSPOOL;
8112113Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
8212113Sralph 		LO = DEFLOCK;
8312113Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
8412113Sralph 		ST = DEFSTAT;
8512113Sralph 	RM = pgetstr("rm", &bp);
8612113Sralph 
8712113Sralph 	/*
8825467Stef 	 * Figure out whether the local machine is the same as the remote
8925467Stef 	 * machine entry (if it exists).  If not, then ignore the local
9025467Stef 	 * queue information.
9125467Stef 	 */
9225467Stef 	 if (RM != (char *) NULL) {
9325467Stef 		char name[256];
9425467Stef 		struct hostent *hp;
9525467Stef 
9625467Stef 		/* get the standard network name of the local host */
9725467Stef 		gethostname(name, sizeof(name));
9825467Stef 		name[sizeof(name)-1] = '\0';
9925467Stef 		hp = gethostbyname(name);
10025467Stef 		if (hp == (struct hostent *) NULL) {
10125467Stef 		    printf("unable to get network name for local machine %s\n",
10225467Stef 			name);
10325467Stef 		    goto localcheck_done;
10430995Sbostic 		} else (void) strcpy(name, hp->h_name);
10525467Stef 
10625467Stef 		/* get the network standard name of RM */
10725467Stef 		hp = gethostbyname(RM);
10825467Stef 		if (hp == (struct hostent *) NULL) {
10925467Stef 		    printf("unable to get hostname for remote machine %s\n",
11025467Stef 			RM);
11125467Stef 		    goto localcheck_done;
11225467Stef 		}
11325467Stef 
11425467Stef 		/* if printer is not on local machine, ignore LP */
11530995Sbostic 		if (strcmp(name, hp->h_name)) {
11630995Sbostic 			*LP = '\0';
11730995Sbostic 			++sendtorem;
11830995Sbostic 		}
11925467Stef 	}
12025467Stef localcheck_done:
12125467Stef 
12225467Stef 	/*
12330995Sbostic 	 * Print out local queue
12412113Sralph 	 * Find all the control files in the spooling directory
12512113Sralph 	 */
12612113Sralph 	if (chdir(SD) < 0)
12712113Sralph 		fatal("cannot chdir to spooling directory");
12812113Sralph 	if ((nitems = getq(&queue)) < 0)
12912113Sralph 		fatal("cannot examine spooling area\n");
13016205Sralph 	if (stat(LO, &statb) >= 0) {
13116205Sralph 		if (statb.st_mode & 0100) {
13216205Sralph 			if (sendtorem)
13316205Sralph 				printf("%s: ", host);
13416205Sralph 			printf("Warning: %s is down: ", printer);
13516205Sralph 			fd = open(ST, O_RDONLY);
13616205Sralph 			if (fd >= 0) {
13716205Sralph 				(void) flock(fd, LOCK_SH);
13816205Sralph 				while ((i = read(fd, line, sizeof(line))) > 0)
13916205Sralph 					(void) fwrite(line, 1, i, stdout);
14016205Sralph 				(void) close(fd);	/* unlocks as well */
14116205Sralph 			} else
14216205Sralph 				putchar('\n');
14316205Sralph 		}
14416205Sralph 		if (statb.st_mode & 010) {
14516205Sralph 			if (sendtorem)
14616205Sralph 				printf("%s: ", host);
14716205Sralph 			printf("Warning: %s queue is turned off\n", printer);
14816205Sralph 		}
14912740Sralph 	}
15012113Sralph 
15130995Sbostic 	if (nitems) {
15230995Sbostic 		fp = fopen(LO, "r");
15330995Sbostic 		if (fp == NULL)
15413441Sralph 			warn();
15513441Sralph 		else {
15630995Sbostic 			register char *cp;
15730995Sbostic 
15830995Sbostic 			/* get daemon pid */
15913441Sralph 			cp = current;
16013441Sralph 			while ((*cp = getc(fp)) != EOF && *cp != '\n')
16113441Sralph 				cp++;
16213441Sralph 			*cp = '\0';
16330995Sbostic 			i = atoi(current);
16430995Sbostic 			if (i <= 0 || kill(i, 0) < 0)
16530995Sbostic 				warn();
16630995Sbostic 			else {
16730995Sbostic 				/* read current file name */
16830995Sbostic 				cp = current;
16930995Sbostic 				while ((*cp = getc(fp)) != EOF && *cp != '\n')
17030995Sbostic 					cp++;
17130995Sbostic 				*cp = '\0';
17230995Sbostic 				/*
17330995Sbostic 				 * Print the status file.
17430995Sbostic 				 */
17530995Sbostic 				if (sendtorem)
17630995Sbostic 					printf("%s: ", host);
17730995Sbostic 				fd = open(ST, O_RDONLY);
17830995Sbostic 				if (fd >= 0) {
17930995Sbostic 					(void) flock(fd, LOCK_SH);
18030995Sbostic 					while ((i = read(fd, line, sizeof(line))) > 0)
18130995Sbostic 						(void) fwrite(line, 1, i, stdout);
18230995Sbostic 					(void) close(fd);	/* unlocks as well */
18330995Sbostic 				} else
18430995Sbostic 					putchar('\n');
18530995Sbostic 			}
18630995Sbostic 			(void) fclose(fp);
18713441Sralph 		}
18830995Sbostic 		/*
18930995Sbostic 		 * Now, examine the control files and print out the jobs to
19030995Sbostic 		 * be done for each user.
19130995Sbostic 		 */
19230995Sbostic 		if (!lflag)
19330995Sbostic 			header();
19430995Sbostic 		for (i = 0; i < nitems; i++) {
19530995Sbostic 			q = queue[i];
19630995Sbostic 			inform(q->q_name);
19730995Sbostic 			free(q);
19830995Sbostic 		}
19930995Sbostic 		free(queue);
20012113Sralph 	}
20131678Skarels 	if (!sendtorem) {
20231678Skarels 		if (nitems == 0)
20331678Skarels 			puts("no entries");
20430995Sbostic 		return;
20530995Sbostic 	}
20630995Sbostic 
20712113Sralph 	/*
20830995Sbostic 	 * Print foreign queue
20930995Sbostic 	 * Note that a file in transit may show up in either queue.
21012113Sralph 	 */
21130995Sbostic 	if (nitems)
21230995Sbostic 		putchar('\n');
21330995Sbostic 	(void) sprintf(line, "%c%s", format + '\3', RP);
21430995Sbostic 	cp = line;
21530995Sbostic 	for (i = 0; i < requests; i++) {
21630995Sbostic 		cp += strlen(cp);
21730995Sbostic 		(void) sprintf(cp, " %d", requ[i]);
21812113Sralph 	}
21930995Sbostic 	for (i = 0; i < users; i++) {
22030995Sbostic 		cp += strlen(cp);
22130995Sbostic 		*cp++ = ' ';
22230995Sbostic 		(void) strcpy(cp, user[i]);
22330995Sbostic 	}
22430995Sbostic 	strcat(line, "\n");
22530995Sbostic 	fd = getport(RM);
22630995Sbostic 	if (fd < 0) {
22730995Sbostic 		if (from != host)
22830995Sbostic 			printf("%s: ", host);
22930995Sbostic 		printf("connection to %s is down\n", RM);
23030995Sbostic 	}
23130995Sbostic 	else {
23230995Sbostic 		i = strlen(line);
23330995Sbostic 		if (write(fd, line, i) != i)
23430995Sbostic 			fatal("Lost connection");
23530995Sbostic 		while ((i = read(fd, line, sizeof(line))) > 0)
23630995Sbostic 			(void) fwrite(line, 1, i, stdout);
23730995Sbostic 		(void) close(fd);
23830995Sbostic 	}
23912113Sralph }
24012113Sralph 
24112113Sralph /*
24213441Sralph  * Print a warning message if there is no daemon present.
24313441Sralph  */
24413441Sralph warn()
24513441Sralph {
24613441Sralph 	if (sendtorem)
24713441Sralph 		printf("\n%s: ", host);
24830995Sbostic 	puts("Warning: no daemon present");
24913441Sralph 	current[0] = '\0';
25013441Sralph }
25113441Sralph 
25213441Sralph /*
25312113Sralph  * Print the header for the short listing format
25412113Sralph  */
25512113Sralph header()
25612113Sralph {
25712113Sralph 	printf(head0);
25812113Sralph 	col = strlen(head0)+1;
25912113Sralph 	blankfill(SIZCOL);
26012113Sralph 	printf(head1);
26112113Sralph }
26212113Sralph 
26312113Sralph inform(cf)
26412113Sralph 	char *cf;
26512113Sralph {
26612113Sralph 	register int j, k;
26712113Sralph 	register char *cp;
26812113Sralph 	FILE *cfp;
26912113Sralph 
27012113Sralph 	/*
27112113Sralph 	 * There's a chance the control file has gone away
27212113Sralph 	 * in the meantime; if this is the case just keep going
27312113Sralph 	 */
27412113Sralph 	if ((cfp = fopen(cf, "r")) == NULL)
27512113Sralph 		return;
27612113Sralph 
27712113Sralph 	if (rank < 0)
27812113Sralph 		rank = 0;
27912113Sralph 	if (sendtorem || garbage || strcmp(cf, current))
28012113Sralph 		rank++;
28112113Sralph 	j = 0;
28212113Sralph 	while (getline(cfp)) {
28312113Sralph 		switch (line[0]) {
28412113Sralph 		case 'P': /* Was this file specified in the user's list? */
28512113Sralph 			if (!inlist(line+1, cf)) {
28612113Sralph 				fclose(cfp);
28712113Sralph 				return;
28812113Sralph 			}
28912113Sralph 			if (lflag) {
29012113Sralph 				printf("\n%s: ", line+1);
29112113Sralph 				col = strlen(line+1) + 2;
29212113Sralph 				prank(rank);
29312113Sralph 				blankfill(JOBCOL);
29412113Sralph 				printf(" [job %s]\n", cf+3);
29512113Sralph 			} else {
29612113Sralph 				col = 0;
29712113Sralph 				prank(rank);
29812113Sralph 				blankfill(OWNCOL);
29912113Sralph 				printf("%-10s %-3d  ", line+1, atoi(cf+3));
30012113Sralph 				col += 16;
30112113Sralph 				first = 1;
30212113Sralph 			}
30312113Sralph 			continue;
30412113Sralph 		default: /* some format specifer and file name? */
30512113Sralph 			if (line[0] < 'a' || line[0] > 'z')
30612113Sralph 				continue;
30712113Sralph 			if (j == 0 || strcmp(file, line+1) != 0)
30830995Sbostic 				(void) strcpy(file, line+1);
30912113Sralph 			j++;
31012113Sralph 			continue;
31112113Sralph 		case 'N':
31212113Sralph 			show(line+1, file, j);
31312113Sralph 			file[0] = '\0';
31412113Sralph 			j = 0;
31512113Sralph 		}
31612113Sralph 	}
31712113Sralph 	fclose(cfp);
31812113Sralph 	if (!lflag) {
31912113Sralph 		blankfill(SIZCOL);
32034587Sbostic 		printf("%ld bytes\n", totsize);
32112113Sralph 		totsize = 0;
32212113Sralph 	}
32312113Sralph }
32412113Sralph 
32512113Sralph inlist(name, file)
32612113Sralph 	char *name, *file;
32712113Sralph {
32812113Sralph 	register int *r, n;
32912113Sralph 	register char **u, *cp;
33012113Sralph 
33112113Sralph 	if (users == 0 && requests == 0)
33212113Sralph 		return(1);
33312113Sralph 	/*
33412113Sralph 	 * Check to see if it's in the user list
33512113Sralph 	 */
33612113Sralph 	for (u = user; u < &user[users]; u++)
33712113Sralph 		if (!strcmp(*u, name))
33812113Sralph 			return(1);
33912113Sralph 	/*
34012113Sralph 	 * Check the request list
34112113Sralph 	 */
34212113Sralph 	for (n = 0, cp = file+3; isdigit(*cp); )
34312113Sralph 		n = n * 10 + (*cp++ - '0');
34412113Sralph 	for (r = requ; r < &requ[requests]; r++)
34512113Sralph 		if (*r == n && !strcmp(cp, from))
34612113Sralph 			return(1);
34712113Sralph 	return(0);
34812113Sralph }
34912113Sralph 
35012113Sralph show(nfile, file, copies)
35112113Sralph 	register char *nfile, *file;
35212113Sralph {
35312113Sralph 	if (strcmp(nfile, " ") == 0)
35412113Sralph 		nfile = "(standard input)";
35512113Sralph 	if (lflag)
35612113Sralph 		ldump(nfile, file, copies);
35712113Sralph 	else
35812113Sralph 		dump(nfile, file, copies);
35912113Sralph }
36012113Sralph 
36112113Sralph /*
36212113Sralph  * Fill the line with blanks to the specified column
36312113Sralph  */
36412113Sralph blankfill(n)
36512113Sralph 	register int n;
36612113Sralph {
36712113Sralph 	while (col++ < n)
36812113Sralph 		putchar(' ');
36912113Sralph }
37012113Sralph 
37112113Sralph /*
37212113Sralph  * Give the abbreviated dump of the file names
37312113Sralph  */
37412113Sralph dump(nfile, file, copies)
37512113Sralph 	char *nfile, *file;
37612113Sralph {
37712113Sralph 	register short n, fill;
37812113Sralph 	struct stat lbuf;
37912113Sralph 
38012113Sralph 	/*
38112113Sralph 	 * Print as many files as will fit
38212113Sralph 	 *  (leaving room for the total size)
38312113Sralph 	 */
38412113Sralph 	 fill = first ? 0 : 2;	/* fill space for ``, '' */
38512113Sralph 	 if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) {
38612113Sralph 		if (col < SIZCOL) {
38712113Sralph 			printf(" ..."), col += 4;
38812113Sralph 			blankfill(SIZCOL);
38912113Sralph 		}
39012113Sralph 	} else {
39112113Sralph 		if (first)
39212113Sralph 			first = 0;
39312113Sralph 		else
39412113Sralph 			printf(", ");
39512113Sralph 		printf("%s", nfile);
39612113Sralph 		col += n+fill;
39712113Sralph 	}
39812113Sralph 	if (*file && !stat(file, &lbuf))
39912113Sralph 		totsize += copies * lbuf.st_size;
40012113Sralph }
40112113Sralph 
40212113Sralph /*
40312113Sralph  * Print the long info about the file
40412113Sralph  */
40512113Sralph ldump(nfile, file, copies)
40612113Sralph 	char *nfile, *file;
40712113Sralph {
40812113Sralph 	struct stat lbuf;
40912113Sralph 
41012113Sralph 	putchar('\t');
41112113Sralph 	if (copies > 1)
41212113Sralph 		printf("%-2d copies of %-19s", copies, nfile);
41312113Sralph 	else
41412113Sralph 		printf("%-32s", nfile);
41512113Sralph 	if (*file && !stat(file, &lbuf))
41634587Sbostic 		printf(" %ld bytes", lbuf.st_size);
41712113Sralph 	else
41812113Sralph 		printf(" ??? bytes");
41912113Sralph 	putchar('\n');
42012113Sralph }
42112113Sralph 
42212113Sralph /*
42312113Sralph  * Print the job's rank in the queue,
42412113Sralph  *   update col for screen management
42512113Sralph  */
42612113Sralph prank(n)
42712113Sralph {
42812113Sralph 	char line[100];
42912113Sralph 	static char *r[] = {
43012113Sralph 		"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
43112113Sralph 	};
43212113Sralph 
43312113Sralph 	if (n == 0) {
43412113Sralph 		printf("active");
43512113Sralph 		col += 6;
43612113Sralph 		return;
43712113Sralph 	}
43812113Sralph 	if ((n/10) == 1)
43912113Sralph 		(void) sprintf(line, "%dth", n);
44012113Sralph 	else
44112113Sralph 		(void) sprintf(line, "%d%s", n, r[n%10]);
44212113Sralph 	col += strlen(line);
44312113Sralph 	printf("%s", line);
44412113Sralph }
445