#ifndef lint
/* static char sccsid[] = "@(#)man.c	1.10 (Berkeley) 9/19/83"; */
static char sccsid[] = "@(#)kman.c	1.1 2/2/88";
#endif

#include <stdio.h>
#include <ctype.h>
#include <sgtty.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
/*
 * kman
 * This version uses more for underlining and paging.
 */
#define	MANDIR	"/u/ksos/ksos32/man"	/* this is deeply embedded */
#define	NROFFCAT "nroff -h -mank"	/* for nroffing to cat file */
#define	NROFF	"nroff -mank"		/* for nroffing to tty */
#define	MORE	"more -s"		/* paging filter */
#define	CAT	"cat -s"		/* for '-' opt (no more) */

#define TROFFCMD \
"troff -t -mank /usr/lib/tmac/tmac.vcat %s | /usr/lib/rvsort |/usr/ucb/vpr -t"

/*  for troff:
#define	TROFFCMD "troff -mank %s"
*/

#define	ALLSECT	"pufvlh"	/* order to look through sections */
/* no subsections
#define	SUBSEC1	"mcgprv"	#* subsections to try in section 1 *#
#define	SUBSEC2	"v"
#define	SUBSEC3	"jxmsnvcf"
#define	SUBSEC4	"pfvsn"
#define	SUBSEC8	"vc"
end no subsections */

int	nomore;
char	*manpath = MANDIR;
char	*strcpy();
char	*strcat();
int	remove();
int	section;
int	subsec;
int	troffit;

#define	eq(a,b)	(strcmp(a,b) == 0)

main(argc, argv)
	int argc;
	char *argv[];
{

	if (signal(SIGINT, SIG_IGN) == SIG_DFL) {
		signal(SIGINT, remove);
		signal(SIGQUIT, remove);
		signal(SIGTERM, remove);
	}
	umask(0);
	if (argc <= 1) {
		fprintf(stderr, "Usage: kman [ section ] name ...\n");
		exit(1);
	}
	argc--, argv++;
	while (argc > 0 && argv[0][0] == '-') {
		switch(argv[0][1]) {

		case 0:
			nomore++;
			break;

		case 't':
			troffit++;
			break;

		case 'P':
			argc--, argv++;
			manpath = *argv;
			break;
		}
		argc--, argv++;
	}
	if (chdir(manpath) < 0) {
		fprintf(stderr, "Can't chdir to %s.\n", manpath);
		exit(1);
	}
	if (troffit == 0 && nomore == 0 && !isatty(1))
		nomore++;
	section = 0;
	do {
		if (eq(argv[0], "local")) {
			section = 'l';
			goto sectin;
		} else if (eq(argv[0], "new")) {
			section = 'n';
			goto sectin;
		} else if (eq(argv[0], "old")) {
			section = 'o';
			goto sectin;
		} else if (eq(argv[0], "public")) {
			section = 'p';
			goto sectin;
		} else if (argv[0][0] >= '0' && argv[0][0] <= '9' && (argv[0][1] == 0 || argv[0][2] == 0)) {
			section = argv[0][0];
			subsec = argv[0][1];
sectin:
			argc--, argv++;
			if (argc == 0) {
				fprintf(stderr, "But what do you want from section %s?\n", argv[-1]);
				exit(1);
			}
			continue;
		}
		manual(section, argv[0]);
		argc--, argv++;
	} while (argc > 0);
	exit(0);
}

manual(sec, name)
	char sec;
	char *name;
{
	char section = sec;
	char work[100], work2[100], cmdbuf[150];
	int ss;
	struct stat stbuf, stbuf2;
/*	int last;			no subsections */
	char *sp = ALLSECT;

	strcpy(work, "manx/");
	strcat(work, name);
	strcat(work, ".n");
/*	last = strlen(work) - 1;	no subsections */
	if (section == 0) {
		ss = 0;
		for (section = *sp++; section; section = *sp++) {
			work[3] = section;
			if (stat(work, &stbuf) >= 0)
				break;
/* no subsections
			if (work[last] >= '1' && work[last] <= '8') {
				char *cp;
search:
				switch (work[last]) {
				case '1': cp = SUBSEC1; break;
				case '2': cp = SUBSEC2; break;
				case '3': cp = SUBSEC3; break;
				case '4': cp = SUBSEC4; break;
				case '8': cp = SUBSEC8; break;
				}
				while (*cp) {
					work[last+1] = *cp++;
					if (stat(work, &stbuf) >= 0) {
						ss = work[last+1];
						goto found;
					}
				}
				if (ss == 0)
					work[last+1] = 0;
			}
end no subsections */
		}
		if (section == 0) {
			if (sec == 0)
				printf("No manual entry for %s.\n", name);
			else
				printf("No entry for %s in section %c of the manual.\n", name, sec);
			return;
		}
	} else {
		work[3] = section;
		if (stat(work, &stbuf) < 0) {
/* no subsections
			if ((section >= '1' && section <= '8') && subsec == 0) {
				sp = "\0";
				goto search;
			}
end no subsections */
			printf("No entry for %s in section %c", name, section);
			if (subsec)
				putchar(subsec);
			printf(" of the manual.\n");
			return;
		}
	}
found:
	if (troffit)
		troff(work);
	else {
		FILE *it;
		char abuf[BUFSIZ];

		if (!nomore) {
			if ((it = fopen(work, "r")) == NULL) {
				perror(work);
				exit(1);
			}
			if (fgets(abuf, BUFSIZ-1, it) &&
			   abuf[0] == '.' && abuf[1] == 's' &&
			   abuf[2] == 'o' && abuf[3] == ' ') {
				register char *cp = abuf+strlen(".so ");
				char *dp;

				while (*cp && *cp != '\n')
					cp++;
				*cp = 0;
				while (cp > abuf && *--cp != '/')
					;
				dp = ".so man";
				if (cp != abuf+strlen(dp)+1) {
tohard:
					nomore = 1;
					strcpy(work, abuf+4);
					goto hardway;
				}
				for (cp = abuf; *cp == *dp && *cp; cp++, dp++)
					;
				if (*dp)
					goto tohard;
				strcpy(work, cp-3);
			}
			fclose(it);
			strcpy(work2, "cat");
			strcpy(work2+3, work+3);
			work2[4] = 0;
			if (stat(work2, &stbuf2) < 0)
				goto hardway;
			strcpy(work2+3, work+3);
			if (stat(work2, &stbuf2) < 0 || stbuf2.st_mtime < stbuf.st_mtime) {
				printf("Reformatting page.  Wait...");
				fflush(stdout);
				unlink(work2);
				sprintf(cmdbuf,
			"%s %s > /tmp/man%d; trap '' 1 15; mv /tmp/man%d %s",
				    NROFFCAT, work, getpid(), getpid(), work2);
				if (system(cmdbuf)) {
					printf(" aborted (sorry)\n");
					remove();
					/*NOTREACHED*/
				}
				printf(" done\n");
			}
			strcpy(work, work2);
		}
hardway:
		nroff(work);
	}
}

nroff(cp)
	char *cp;
{
	char cmd[BUFSIZ];

	if (cp[0] == 'c')
		sprintf(cmd, "%s %s", nomore? CAT : MORE, cp);
	else
		sprintf(cmd, nomore? "%s %s" : "%s %s|%s", NROFF, cp, MORE);
	system(cmd);
}

troff(cp)
	char *cp;
{
	char cmdbuf[BUFSIZ];

	sprintf(cmdbuf, TROFFCMD, cp);
	system(cmdbuf);
}

remove()
{
	char name[15];

	sprintf(name, "/tmp/man%d", getpid());
	unlink(name);
	exit(1);
}

system(s)
char *s;
{
	int status, pid, w;

	if ((pid = vfork()) == 0) {
		execl("/bin/sh", "sh", "-c", s, 0);
		_exit(127);
	}
	while ((w = wait(&status)) != pid && w != -1)
		;
	if (w == -1)
		status = -1;
	return (status);
}
