/*
 * Copyright (c) 1980 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

/* #ifndef lint */
/* char copyright[] = */
/* "@(#) Copyright (c) 1980 Regents of the University of California.\n\ */
/*  All rights reserved.\n"; */
/* #endif not lint */
/*  */
/* #ifndef lint */
/* static char sccsid[] = "@(#)whereis.c	5.1 (Berkeley) 5/31/85"; */
/* #endif not lint */

#include <sys/param.h>
#include <sys/dir.h>
/* #include <ndir.h> */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

static char *bindirs[] = {
	"/Users/jar/bin",
	"/Users/jar/bin/Recipes",
	"/Users/jar/lib/Recipes",
	"/Users/jar/lib/address",
	"/Users/jar/lib/crontabs",
	"/Users/jar/lib/misc",
	"/bin",
	"/etc",
	"/etc/X11/rstart",
	"/etc/X11/rstart/commands",
	"/etc/X11/rstart/commands/x11r6",
	"/etc/X11/xdm",
	"/etc/X11/xkb",
	"/etc/auth",
	"/etc/pdb",
	"/etc/periodic/daily",
	"/etc/periodic/monthly",
	"/etc/periodic/weekly",
	"/etc/postfix",
	"/opt/local/bin",
	"/opt/local/etc",
	"/opt/local/gromacs",
	"/opt/local/gromacs/bin",
	"/opt/local/gromacs/lib",
	"/opt/local/lib",
	"/opt/local/libexec",
	"/opt/local/sbin",
	"/opt/local/share/gettext",
	"/opt/local/share/gettext/intl",
	"/sbin",
	"/sw/bin",
	"/sw/etc",
	"/sw/lib",
	"/sw/lib/dpkg",
	"/sw/lib/fink",
	"/sw/lib/fink/update",
	"/sw/lib/nethack",
	"/sw/sbin",
	"/sw/share/aspell",
	"/sw/share/gettext/intl",
	"/sw/share/ghostscript/fonts",
	"/usr/X11R6/bin",
	"/usr/X11R6/lib",
	"/usr/X11R6/lib/X11/x11perfcomp",
	"/usr/bin",
	"/usr/etc",
	"/usr/lib",
	"/usr/lib/java",
	"/usr/lib/pam",
	"/usr/lib/php/build",
	"/usr/lib/ruby/1.6/powerpc-darwin7.0",
	"/usr/lib/sa",
	"/usr/lib/sasl2",
	"/usr/lib/system",
	"/usr/lib/zsh/4.1.1/zsh",
	"/usr/libexec",
	"/usr/libexec/binutils",
	"/usr/libexec/cups/backend",
	"/usr/libexec/cups/cgi-bin",
	"/usr/libexec/cups/daemon",
	"/usr/libexec/cups/filter",
	"/usr/libexec/fax",
	"/usr/libexec/gcc/darwin/ppc",
	"/usr/libexec/gcc/darwin/ppc/3.1",
	"/usr/libexec/gcc/darwin/ppc/3.3",
	"/usr/libexec/gcc/darwin/ppc/3.3-fast",
	"/usr/libexec/gdb",
	"/usr/libexec/httpd",
	"/usr/libexec/postfix",
	"/usr/local/bin",
	"/usr/local/etc",
	"/usr/local/lib",
	"/usr/local/lib/fig2dev",
	"/usr/local/teTeX/bin",
	"/usr/sbin",
	"/usr/share/automake-1.6",
	"/usr/share/libtool",
	"/usr/share/misc",
	"/var/spool/postfix/maildrop",
	0
};

static char *mandirs[] = {
	"/Users/jar/man",
	"/Users/jar/man/man1",
	"/Users/jar/man/man3",
	"/Users/jar/man/man6",
	"/usr/local/doc",
	"/usr/local/man",
	"/usr/local/man/man1",
	"/usr/local/man/man3",
	"/usr/local/man/man4",
	"/usr/local/man/man5",
	"/usr/local/share/man",
	"/usr/local/share/man/man1",
	"/usr/local/share/man/man3",
	"/usr/local/share/man/man5",
	"/usr/local/share/man/man7",
	"/usr/local/teTeX/man",
	"/usr/local/teTeX/man/man1",
	"/usr/local/teTeX/man/man5",
	"/usr/local/teTeX/man/man8",
	"/usr/share/doc",
	"/usr/share/info",
	"/usr/share/man",
	"/usr/share/man/man1",
	"/usr/share/man/man2",
	"/usr/share/man/man3",
	"/usr/share/man/man4",
	"/usr/share/man/man5",
	"/usr/share/man/man6",
	"/usr/share/man/man7",
	"/usr/share/man/man8",
	"/usr/share/man/man9",
	"/usr/share/man/mann",
	"/usr/X11R6/man",
	"/usr/X11R6/man/man1",
	"/usr/X11R6/man/man3",
	"/usr/X11R6/man/man7",
	"/opt/local/doc",
	"/opt/local/info",
	"/opt/local/share/doc",
	"/opt/local/share/info",
	"/opt/local/share/man",
	"/opt/local/share/man/man1",
	"/opt/local/share/man/man2",
	"/opt/local/share/man/man3",
	"/opt/local/share/man/man4",
	"/opt/local/share/man/man5",
	"/opt/local/share/man/man6",
	"/opt/local/share/man/man7",
	"/opt/local/share/man/man8",
	"/opt/local/share/man/man9",
	"/opt/local/share/man/mann",
	"/sw/share/doc",
	"/sw/share/info",
	"/sw/share/man",
	"/sw/share/man/man1",
	"/sw/share/man/man3",
	"/sw/share/man/man5",
	"/sw/share/man/man6",
	"/sw/share/man/man7",
	"/sw/share/man/man8",
	"/sw/share/man/mann",
	0
};

static char *srcdirs[]  = {
	"/sw/src",
	"/Users/jar/darwinports/base/src",
	"/Users/jar/darwinports/dports/devel/gettext/work/gettext-0.10.40/src",
	"/Users/jar/darwinports/dports/devel/orbit2/work/ORBit2-2.8.2/linc2/src",
	"/Users/jar/darwinports/dports/devel/orbit2/work/ORBit2-2.8.2/src",
	"/Users/jar/darwinports/dports/gnome/gnome-themes/work/gnome-themes-2.4.1/gtk-themes/Crux/src",
	"/Users/jar/darwinports/dports/gnome/gnome-themes/work/gnome-themes-2.4.1/gtk-themes/LightHouseBlue/src",
	"/Users/jar/darwinports/dports/gnome/gnome-themes/work/gnome-themes-2.4.1/gtk-themes/Mist/src",
	"/Users/jar/darwinports/dports/gnome/gnumeric/work/gnumeric-1.2.1/src",
	"/Users/jar/darwinports/dports/graphics/fontconfig/work/fontconfig-2.2.0/src",
	"/Users/jar/darwinports/dports/graphics/graphviz/work/graphviz-1.10/tools/src",
	"/Users/jar/darwinports/dports/graphics/graphviz/work/graphviz-1.10/windows/src",
	"/Users/jar/darwinports/dports/graphics/graphviz/work/graphviz-1.10/windows/tools/src",
	"/Users/jar/darwinports/dports/net/nmap/work/nmap-3.48/nsock/src",
	"/Users/jar/darwinports/dports/print/freetype/work/freetype-2.1.4/builds/amiga/src",
	"/Users/jar/darwinports/dports/print/freetype/work/freetype-2.1.4/src",
	"/Users/jar/darwinports/dports/science/gromacs/work/gromacs-3.1.5_pre1/src",
	"/Users/jar/darwinports/dports/sysutils/coreutils/work/coreutils-5.0/src",
	"/Users/jar/darwinports/dports/textproc/libxml2/work/libxml2-2.6.1/macos/src",
	"/Users/jar/darwinports/dports/textproc/scrollkeeper/work/scrollkeeper-0.3.12/cl/src",
	"/Users/jar/darwinports/dports/textproc/scrollkeeper/work/scrollkeeper-0.3.12/extract/src",
	"/Users/jar/Downloads/downloads-software-1/hfstar-folder/hfstar/src",
	"/Users/jar/Downloads/downloads-software-2/fltk-1.1.4/src",
	"/Users/jar/Downloads/downloads-software-2/ghex-2.4.1/src",
	"/Users/jar/Downloads/downloads-software-2/ghexcalc-0.1-src Folder/src",
	"/Users/jar/Downloads/downloads-software-2/xtermcontrol-2.2/src",
	"/Users/jar/src",
	"/Users/jar/src/Scripts",
	"/Users/jar/src/k-p",
	"/Users/jar/src/kinetics",
	"/Users/jar/src/luc-doc",
	"/Users/jar/src/misc",
	"/Users/jar/src/miscA.c",
	"/Users/jar/src/miscB.c",
	"/Users/jar/src/ps",
	"/Users/jar/src/recipes",
	"/Users/jar/src/vi-related",
	"/opt/local/include",
	"/opt/local/share",
	"/opt/local/src",
	"/sw/include",
	"/sw/share",
	"/sw/src",
	"/usr/include",
	"/usr/share",
	"/usr/local/include",
	"/usr/local/share",
	0
};

char	sflag = 1;
char	bflag = 1;
char	mflag = 1;
char	**Sflag;
int	Scnt;
char	**Bflag;
int	Bcnt;
char	**Mflag;
int	Mcnt;
char	uflag;

void getlist(int *argcp, char ***argvp, char ***flagp, int *cntp);
void zerof();
void lookup(register char *cp);
void looksrc(char *cp);
void lookbin(char *cp);
void lookman(char *cp);
void findv(char **dirv, int dirc, char *cp);
void find(char **dirs, char *cp);
void findin(char *dir, char *cp);
int itsit(register char *cp, char *dp);

/*
 * whereis name
 * look for source, documentation and binaries
 */

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

	argc--, argv++;
	if (argc == 0) {
usage:
		fprintf(stderr, "whereis [ -sbmu ] [ -SBM dir ... -f ] name...\n");
		exit(1);
	}
	do
		if (argv[0][0] == '-') {
			register char *cp = argv[0] + 1;
			while (*cp) switch (*cp++) {

			case 'f':
				break;

			case 'S':
				getlist(&argc, &argv, &Sflag, &Scnt);
				break;

			case 'B':
				getlist(&argc, &argv, &Bflag, &Bcnt);
				break;

			case 'M':
				getlist(&argc, &argv, &Mflag, &Mcnt);
				break;

			case 's':
				zerof();
				sflag++;
				continue;

			case 'u':
				uflag++;
				continue;

			case 'b':
				zerof();
				bflag++;
				continue;

			case 'm':
				zerof();
				mflag++;
				continue;

			default:
				goto usage;
			}
			argv++;
		} else
			lookup(*argv++);
	while (--argc > 0);
}

void
getlist(argcp, argvp, flagp, cntp)
	char ***argvp;
	int *argcp;
	char ***flagp;
	int *cntp;
{

	(*argvp)++;
	*flagp = *argvp;
	*cntp = 0;
	for ((*argcp)--; *argcp > 0 && (*argvp)[0][0] != '-'; (*argcp)--)
		(*cntp)++, (*argvp)++;
	(*argcp)++;
	(*argvp)--;
}


void
zerof()
{

	if (sflag && bflag && mflag)
		sflag = bflag = mflag = 0;
}

int	count;
int	print;


void
lookup(cp)
	register char *cp;
{
	register char *dp;

	for (dp = cp; *dp; dp++)
		continue;
	for (; dp > cp; dp--) {
		if (*dp == '.') {
			*dp = 0;
			break;
		}
	}
	for (dp = cp; *dp; dp++)
		if (*dp == '/')
			cp = dp + 1;
	if (uflag) {
		print = 0;
		count = 0;
	} else
		print = 1;
again:
	if (print)
		printf("%s:", cp);
	if (sflag) {
		looksrc(cp);
		if (uflag && print == 0 && count != 1) {
			print = 1;
			goto again;
		}
	}
	count = 0;
	if (bflag) {
		lookbin(cp);
		if (uflag && print == 0 && count != 1) {
			print = 1;
			goto again;
		}
	}
	count = 0;
	if (mflag) {
		lookman(cp);
		if (uflag && print == 0 && count != 1) {
			print = 1;
			goto again;
		}
	}
	if (print)
		printf("\n");
}

void
looksrc(cp)
	char *cp;
{
	if (Sflag == 0) {
		find(srcdirs, cp);
	} else
		findv(Sflag, Scnt, cp);
}

void
lookbin(cp)
	char *cp;
{
	if (Bflag == 0)
		find(bindirs, cp);
	else
		findv(Bflag, Bcnt, cp);
}

void
lookman(cp)
	char *cp;
{
	if (Mflag == 0) {
		find(mandirs, cp);
	} else
		findv(Mflag, Mcnt, cp);
}

void
findv(dirv, dirc, cp)
	char **dirv;
	int dirc;
	char *cp;
{

	while (dirc > 0)
		findin(*dirv++, cp), dirc--;
}

void
find(dirs, cp)
	char **dirs;
	char *cp;
{

	while (*dirs)
		findin(*dirs++, cp);
}

void
findin(dir, cp)
	char *dir, *cp;
{
	DIR *dirp;
	struct direct *dp;

	dirp = opendir(dir);
	if (dirp == NULL)
		return;
	while ((dp = readdir(dirp)) != NULL) {
		if (itsit(cp, dp->d_name)) {
			count++;
			if (print)
				printf(" %s/%s", dir, dp->d_name);
		}
	}
	closedir(dirp);
}

int
itsit(cp, dp)
	register char *cp, *dp;
{
	register int i = strlen(dp);

	if (dp[0] == 's' && dp[1] == '.' && itsit(cp, dp+2))
		return (1);
	while (*cp && *dp && *cp == *dp)
		cp++, dp++, i--;
	if (*cp == 0 && *dp == 0)
		return (1);
	while (isdigit(*dp))
		dp++;
	if (*cp == 0 && *dp++ == '.') {
		--i;
		while (i > 0 && *dp)
			if (--i, *dp++ == '.')
				return (*dp++ == 'C' && *dp++ == 0);
		return (1);
	}
	return (0);
}
