/**********************************************************************\
 *                              Man V1.2                              *
 *                 Copyright (C) 1989 by G. Glendown                  *
 *                                                                    *
 * This program and all documentation is placed in the public domain. *
 *No fee may be charged except for media and copying.  ArcPrep may be *
 * included on Fred Fish's distribution disk.  Any other PD-collector *
 * will have to get my permission prior to putting Man on his disks.  *
 *     Any net service may distribute Man, as long as no fee for      *
 *downloading is charged (execpt normal line costs).  You may make any*
 * changes to Man, but I would appreciate it if you could send me the *
 *  new sources (except conversions to Lattice-C or Modula-II) or at  *
 *              least a short note about what you did...              *
 *                                                                    *
 * German PD dealers:                                                 *
 *             Please read the file 'GermanDistribution'              *
\**********************************************************************/


/* ts=4 */
/*
	*	Man	V1.2
	*
	* 	Unix-style manual command controlled completely by 
	* 	the file "man:manuals"
	*
	* USAGE:
	*
	*	man <manual> [-vTextViewer] [-pPath] [-f]
	*
*/

#include <stdio.h>

#define LINE	512
#define	MAXCOM	16			/* Maximum size of command name */
#define	EMPTY	"                "
#define FNPOS	20			/* start position of command line/filename */
#define MANFILE	"man:manuals"

/* Uncomment this if you don't have my library with a new PrintF... */
/*#define PrintF printf*/
int cnt,fc;

FILE *fh,*fopen();
char *fgets();

char line[LINE],w[MAXCOM<<1];
char path[11][128];
char cmmnd[128]={"run less "};
int Status=0;
#define CUSTOMVIEW	(1<<0)
#define FIRSTONLY	(1<<1)
#define DISPLAYPATHS	(1<<2)
int pt;

char *name;

/**********************************************************************\
 *                                main                                *
 *                                                                    *
 * Does all scanning of the CLI parameters, prints the paths defined  *
 *                   and checks the 'manuals'-file.                   *
\**********************************************************************/

main(argc,argv)
int argc;
char *argv[];
{
char	*c;
int t;
	if (argc<=1) 
		PrintF("Use '%s man' to see usage of %s\n",argv[0],argv[0]),exit(0L);
	
    cnt=0;

	name=(char *)NULL;

	for (t=1;t<argc;t++) {
		if (argv[t][0]=='-') {
			switch (toupper(argv[t][1])) {
				case 'V':
					strcpy(&(cmmnd[4]),&(argv[t][2]));
					strcat(cmmnd," \0");
					Status|=CUSTOMVIEW;
					break;
				case 'P':
					strcpy(path[pt],&argv[t][2]);
					pt++;
					break;
				case 'F':
					Status|=FIRSTONLY;
					break;
				case 'D':
					Status|=DISPLAYPATHS;
					break;
				default:
					PrintF("Illegal option '%c' ignored\n",argv[t][1]);
					break;
			}
		}
		else
			name=argv[t];
	}

	if ((name==(char *)NULL)&&(!(Status&DISPLAYPATHS)))
		PrintF("No manual specified!\n"),exit(0L);

	if (fh=fopen(MANFILE,"r"))
	{
		SearchStart(fh);
		if (Status&DISPLAYPATHS) {
			PrintF("Man-Paths:\n");
			for (t=0;t<pt;t++)
				PrintF("\t%s\n",path[t]);
			PrintF("File-viewer: '%s'\n",cmmnd);
			fclose(fh);
			exit(0L);
		}
		strncpy(w,name,MAXCOM);
		strcat(w,EMPTY);
		do {
			if (!(c=fgets(line,LINE,fh)))
				PrintF("Oops! Manual-file corrupt!\n"),ex(name);
			if (strncmp(line,w,MAXCOM)==0) {
				cnt++;
				fc++;
				DisplayFile(&line[FNPOS]);
				if (Status&FIRSTONLY) 
					fclose(fh),
					exit(0L);
			}
			if (strncmp(line,"END_MAN",7)==0) ex(name);
		}
		while (1);
	}
	ex();
}

/**********************************************************************\
 *                                 ex                                 *
 *  This routine looks through all defined paths to find a file that  *
 *                   will match the filename given.                   *
 **********************************************************************
 * Parameters:                                                        *
 * - name of the manual file  (char *)                                *
\**********************************************************************/

ex(t)
char *t;
{
int g;
	if (cnt==0) {
		if (Found("man:",t)) {
			strcpy(line,"man:");
			strcat(line,t);
			DisplayFile(line);
			if (Status&FIRSTONLY) goto TheEnd;
		}
		for (g=0;g<pt;g++) {
			if (Found(path[g],t)) {
				strcpy(line,path[g]);
				strcat(line,t);
				DisplayFile(line);
				if (Status&FIRSTONLY) g=pt;
			}
		}
	}

	if (!fc) PrintF("No manuals available!\n");

TheEnd:
	if (fh) fclose(fh);
	exit();
}

/**********************************************************************\
 *                               Found                                *
 *  This routine checks, if the file is accessable in the directory   *
 *                        given as a parameter                        *
 **********************************************************************
 * Parameters:                                                        *
 * - path which is to be searched  (char *)                           *
 * - filename to look for (char *)                                    *
 **********************************************************************
 * Result:                                                            *
 *  >1< if file is found                                              *
 *  >0< file not found                                                *
\**********************************************************************/

int Found(p,n)
int *p,*n;
{
char f[256];
struct FileLock *l,*Lock();
	strcpy(f,p);
	strcat(f,n);
	l=Lock(f,ACCESS_READ);
	if (l) UnLock(l),fc++;
	if (l) return(1);
	else return(0);
}

/**********************************************************************\
 *                            DisplayFile                             *
 * This routine will call either the file viewer, or it will execute  *
 *                       the command supplied.                        *
 **********************************************************************
 * Parameters:                                                        *
 * - line  includes either the filename or the line to be executed    *
\**********************************************************************/

DisplayFile(f)
char *f;
{
int t;
char exec[256];
	t=0;
	if (*f=='!')
		Execute(&f[1],0L,0L);
	else {
		do {
			t++;
		} while ((f[t]!=' ')&&(f[t]!='\n'));
		strcpy(exec,cmmnd);
		strncat(exec,f,t);
		PrintF("%s - ",f);
		Execute(exec,0L,0L);
	}
}

/**********************************************************************\
 *                            SearchStart                             *
 *This routine scans the 'manuals'-file for the PATH and VIEW commands*
 *             and tries to find the 'START_MAN'-command.             *
 **********************************************************************
 * Parameters:                                                        *
 * - filepointer to the 'manuals'-file.                               *
\**********************************************************************/

SearchStart(fh)
struct FileHandle *fh;
{
char line[LINE],*c;
	for (;;) {
		if (c=fgets(line,LINE,fh)) {
			if (strncmp(line,"START_MAN",9)==0) return;
			if (strncmp(line,"VIEW:",5)==0) {
				if ((Status&CUSTOMVIEW)==0) {
					strcpy(cmmnd,&line[5]);
					cmmnd[strlen(cmmnd)-1]=' ';
				}
			}
			if (strncmp(line,"PATH ",5)==0) {
				if (pt<10) {
					strcpy(path[pt],&line[5]);
					path[pt][strlen(path[pt])-1]='\0';
					pt++;
				}
				else
					PrintF("Too many paths in 'man:manuals' - file!\n");
			}
		}
	}
}

