[comp.sources.misc] v07i091: Enhanced man

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (07/22/89)

Posting-number: Volume 7, Issue 91
Submitted-by: gil@limbic.UUCP (Gil Kloepfer Jr.)
Archive-name: man.7300

[Note that this has also been posted to unix-pc.sources]
[[Crossposting between unmoderated and moderated groups is discouraged
  in general.  ++bsa]]

Here is a utility that I hacked for my UNIX-pc without a decent man(1)
utility.  I've heard that some others are also missing this utility,
or have a braindamaged one.  I'm passing it along to comp.sources.misc
in case others have a use for it.  I've only tested it on my UNIX-pc,
but it should work with little or no changes on most unices (plural
of unix?).

Note that to link the program, you'll need Doug Gwyn's dirent package,
previously posted to the net.  All other information is in the README
file, packaged with the shar.

========
| Gil Kloepfer, Jr.
| ICUS Software Systems/Bowne Management Systems (depending on where I am)
| ...icus!limbic!gil   or    gil@icus.islp.ny.us

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README man.c
# Wrapped by gil@limbic on Wed Jul 12 13:21:43 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(2273 characters\)
sed "s/^X//" >README <<'END_OF_README'
XREADME file for man v1.0  -- Last updated 7/12/89
X
XThe following is my interpretation of the UNIX "man" command.  Although
Xit isn't very robust, it does handle some very useful cases which occur
Xwhen trying to get stored manual pages, such as:
X
X[from the source]
X
X	o  You can "man" compressed manual pages 
X	o  You don't have to know if the manual
X	   pages are unformatted (/usr/man/man?)
X	   or formatted (/usr/man/cat?).
X	o  You don't have to know what section
X	   the manual page is in (and it tells you
X	   which one)
X	o  You get automatic paging when you
X	   invoke man from a tty
X
X
XI didn't bother with a makefile since there is only one source file
Xhere.  It compiles by:
X
X	$ cc -O -o man man.c -ldirent -s
X
XUse whatever other favorite options you like.  Install it in /usr/local/bin
Xor /usr/lbin (whichever you use on your system).  It does not require any
Xs-bits to be set.
X
XIMPORTANT NOTE:  As noted above, this requires that Doug Gwyn's "dirent"
Xsubroutine library be installed.  I didn't include it with this distribution!
XIf you require it, drop me a note.  If I get enough notes, I'll repost the
Xsource.
X
XCONFIGURATION HINTS:  In the source there are 3 "#define"s which define
Xthe pager, compressed file "cat" program, and the name of your nroff
Xprogram.  These should be defined however you like them, or undefined if
Xyou don't have them.  There are two "#define"s which define where the
Xmanual pages are located -- in /usr/man/man? and /usr/man/cat? .  Set
Xthese to the way your system is configured.
X
XOne more bit of background-- as you might notice from some of the code,
Xthis program was a bit of a hack.  I was tired of not having "man" work
Xthis way, so I hacked this up quickly.  There were several individuals
Xinterested in the program, so I decided to post it.  In any event, if
Xyou think it needs more functionality or should be modified to do a
Xparticular thing differently, don't complain to me about it.  Make the
Xchange and send me the diffs so I can get some patches on the net and
Xeveryone can benefit!
X
XAlso note that the code has only been tested and used on my UNIX-pc, but
Xit seems that it should run under almost any Unix environment.
X
XHope this is of use to lots of you.
X
X
XGil Kloepfer, Jr.   ICUS Software Systems
X...!icus!limbic!gil
END_OF_README
if test 2273 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f man.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"man.c\"
else
echo shar: Extracting \"man.c\" \(7578 characters\)
sed "s/^X//" >man.c <<'END_OF_man.c'
X/***************************************************************************\
X * File name:		man.c					   	   *
X *									   *
X * Purpose:		Provide a better user interface to read the manual *
X *			pages.						   *
X *									   *
X * Programmer:		Gil Kloepfer, Jr.  ICUS Software Systems	   *
X *									   *
X * Revision history:	 8-Jun-89  0.1	 Program created [Beta release]	   *
X * 			12-Jul-89  1.0	 Program released
X *									   *
X * Restrictions:	Requires Doug Gwyn's "dirent" subroutine package.  *
X *			Optionally requires "compress" package, as well    *
X *			as links to it called "zcat," and a text pager     *
X *			such as	"more."  Having "nroff" is also a plus.	   *
X *									   *
X *			Program has been tested on the UNIX-pc 3B1.  It    *
X *			should work on other systems, but this hasn't been *
X *			tested.						   *
X *									   *
X * Usage:		Invoked from the shell or a script by:		   *
X *				$ man [section] command			   *
X *									   *
X *			This manual page interface provides the following  *
X *			features:					   *
X *			 	o  You can "man" compressed manual pages   *
X *				o  You don't have to know if the manual    *
X *				   pages are unformatted (/usr/man/man?)   *
X *				   or formatted (/usr/man/cat?).	   *
X *				o  You don't have to know what section     *
X *				   the manual page is in (and it tells you *
X *				   which one)				   *
X *				o  You get automatic paging when you       *
X *				   invoke man from a tty		   *
X *									   *
X * Compiled by:		$ cc -v -O -o man man.c -ldirent -s		   *
X *									   *
X * Copyright/		(C) 1989 Gil Kloepfer, Jr., ICUS Software Systems  *
X * Disclaimer:		All Rights Reserved				   *
X *									   *
X *			Permission is granted to use, copy, or redistribute*
X *			this software provided that this header in its     *
X *			entirety is kept in the source code, that all      *
X *			copyright notices are left intact, and that it is  *
X *			not distributed or used for monetary gain of any   *
X *			kind without the express, written permission of    *
X *			the copyright holder(s).  Furthermore, if this     *
X *			software is modified, all changes should be mailed *
X *			to icus!gil.					   *
X *									   *
X *			The user of this program agrees and understands    *
X *			that this software is distributed on an "as-is"    *
X *			basis, and shall not use this program as the basis *
X *			for any claims, now or in the future, against      *
X *			any individual, organization, or entity.	   *
X\***************************************************************************/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <dirent.h>
X#include <sys/stat.h>
X
X#define	PROCD		"/usr/man/cat"	/* dir prefix for preformatted pages */
X#define	NPROCD		"/usr/man/man"	/* dir prefix for nroff format pages */
X#define	MAXPATH		128		/* maximum size of path to man page */
X
X/* undefine any of the following if your system doesn't have them */
X
X#define	TYPECOMP	"/usr/bin/zcat"	/* command to display a compressed file */
X#define	FORMAT		"/usr/bin/nroff -man" /* command to format a manual page */
X#define	PAGER		"/usr/bin/more"	/* system command to page a file */
X
X/* Don't play with these constants!! */
X#define	C_PROC		1
X#define	C_NPROC		2
X
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	int	argno, section, kind, lookup();
X	char	command[20], pagename[MAXPATH];
X
X	/* Process the command line arguments */
X
X	switch(argc) {
X	case 2:  /* just the command name */
X		strncpy(command,argv[1],20);
X		section=0;
X		break;
X
X	case 3:  /* the section and command name */
X		sscanf(argv[1], "%d", &section);
X		strncpy(command,argv[2],20);
X		break;
X
X	default:  /* invalid .. display the usage statement */
X		fprintf(stderr,"usage: %s [section] command\n", argv[0]);
X		exit(1);
X	}
X
X	/*
X	 * If the section is not specified explicitly, try to find
X	 * the manual page in the first directory where it's encountered.
X	 */
X
X	if (section == 0) {
X		for (section=1; section<=8; section++)
X			if (lookup(command,section,pagename,&kind)) {
X				fprintf(stderr,"%s: assuming %s from section %d\n",
X					argv[0], command, section);
X				printpage(pagename,kind);
X				exit(0);
X			}
X		fprintf(stderr,"%s: cannot find %s in the manual\n",
X				argv[0], command);
X		exit(2);
X	}
X
X	/*
X	 * If the user specified a section, then see if we can find it
X	 * there .. if so, print the page
X	 */
X
X	if (lookup(command,section,pagename,&kind)) {
X		printpage(pagename,kind);
X		exit(0);
X	} else {
X		fprintf(stderr,"%s: cannot find %s in section %d\n",
X			argv[0], command, section);
X		exit(2);
X	}
X}
X
X
X/*
X * Function lookup returns 0 on failure and 1 on success.  It will look
X * through the directories for section and try to find the manual page
X * for command.  If it finds it, the entire filename is returned as
X * pagename.  "kind" passes along whether the name was found in the
X * processed or unprocessed directory phases
X */
X
Xint lookup(command,section,pagename,kind)
Xchar *command, *pagename;
Xint section, *kind;
X{
X	int	passno, cmpman();
X	char	fullpath[MAXPATH];
X	DIR	*mdir;
X	struct dirent *dentry;
X
X	/*
X	 * Look through the formatted directory first to see if we
X	 * can get one that's formatted.  The second pass gets
X	 * the formatted directory.  This looks kludgy, but it's
X	 * pretty neat nevertheless.
X	 */
X
X	for (passno=1; passno<=2; passno++) {
X		switch(passno) {
X		case 1:  /* check formatted directory */
X			sprintf(fullpath, "%s%d", PROCD, section);
X			*kind = C_PROC;
X			break;
X
X		case 2:  /* check unformatted directory */
X			sprintf(fullpath, "%s%d", NPROCD, section);
X			*kind = C_NPROC;
X			break;
X		}
X
X		if ((mdir=opendir(fullpath)) != NULL)
X			while ((dentry=readdir(mdir)) != NULL)
X				if (cmpman(dentry->d_name,command) == 0) {
X					closedir(mdir);
X					sprintf(pagename, "%s/%s", fullpath,
X						dentry->d_name);
X					return(1);
X				}
X
X		closedir(mdir);
X	}
X	return(0);
X}
X
X
X/*
X * Compare name with command and see if it matches before the period
X * so we can crown it the matching manual page for command
X */
X
Xint cmpman(name,command)
Xchar *name, *command;
X{
X	while ((*name == *command) && *name != '\0' && *command != '\0') {
X		name++;
X		command++;
X	}
X
X	if (*name == '.' && *command == '\0') return(0);  /* OK */
X	if (*command == *name) return(0);  /* also OK */
X
X	return(1);  /* all other cases fail */
X}
X
X
X/*
X * Printpage prints a manual page.  It formats the page depending on
X * where it comes from, and invokes the system pager depending on
X * whether output is to a tty or a file/pipe
X */
X
Xprintpage(pageloc,form)
Xchar *pageloc;
Xint form;
X{
X	int	compress, endstr, ttypage;
X	char	cmdline[512];
X
X	/* See if we're dealing with a compressed file (.Z) */
X
X	endstr=strlen(pageloc);
X	if (pageloc[endstr-2]=='.' && pageloc[endstr-1]=='Z')
X		compress=1;
X	else
X		compress=0;
X
X#ifndef	TYPECOMP
X	if (compress) {
X		fprintf(stdout,"%s: compressed files not supported\n",
X				argv[0]);
X		exit(2);
X	}
X#endif
X
X	/* If we're a tty, page this using whatever our pager is */
X
X#ifdef PAGER
X	if (isatty(1))
X		ttypage=1;
X	else
X		ttypage=0;
X#else
X	ttypage=0;
X#endif
X
X	/*
X	 * Setup command line.  This is some really sick code, but
X	 * how else are we to do it?  I can think of only one way, but
X	 * it's kind of wasteful of system resources...
X	 */
X
X	if (compress) {
X		if (form == C_NPROC)
X			sprintf(cmdline, "%s %s | %s", TYPECOMP, pageloc, FORMAT);
X		else
X			sprintf(cmdline, "%s %s", TYPECOMP, pageloc);
X	} else {
X		if (form == C_NPROC)
X			sprintf(cmdline, "%s %s", FORMAT, pageloc);
X		else
X			sprintf(cmdline, "/bin/cat %s", pageloc);
X	}
X
X	if (ttypage) {
X		strcat(cmdline," | ");
X		strcat(cmdline,PAGER);
X	}
X
X	/* Invoke command */
X
X	system(cmdline);
X}
END_OF_man.c
if test 7578 -ne `wc -c <man.c`; then
    echo shar: \"man.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0