home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************\
- * File name: man.c *
- * *
- * Purpose: Provide a better user interface to read the manual *
- * pages. *
- * *
- * Programmer: Gil Kloepfer, Jr. ICUS Software Systems *
- * *
- * Revision history: 8-Jun-89 0.1 Program created [Beta release] *
- * 12-Jul-89 1.0 Program released
- * *
- * Restrictions: Requires Doug Gwyn's "dirent" subroutine package. *
- * Optionally requires "compress" package, as well *
- * as links to it called "zcat," and a text pager *
- * such as "more." Having "nroff" is also a plus. *
- * *
- * Program has been tested on the UNIX-pc 3B1. It *
- * should work on other systems, but this hasn't been *
- * tested. *
- * *
- * Usage: Invoked from the shell or a script by: *
- * $ man [section] command *
- * *
- * This manual page interface provides the following *
- * features: *
- * o You can "man" compressed manual pages *
- * o You don't have to know if the manual *
- * pages are unformatted (/usr/man/man?) *
- * or formatted (/usr/man/cat?). *
- * o You don't have to know what section *
- * the manual page is in (and it tells you *
- * which one) *
- * o You get automatic paging when you *
- * invoke man from a tty *
- * *
- * Compiled by: $ cc -v -O -o man man.c -ldirent -s *
- * *
- * Copyright/ (C) 1989 Gil Kloepfer, Jr., ICUS Software Systems *
- * Disclaimer: All Rights Reserved *
- * *
- * Permission is granted to use, copy, or redistribute*
- * this software provided that this header in its *
- * entirety is kept in the source code, that all *
- * copyright notices are left intact, and that it is *
- * not distributed or used for monetary gain of any *
- * kind without the express, written permission of *
- * the copyright holder(s). Furthermore, if this *
- * software is modified, all changes should be mailed *
- * to icus!gil. *
- * *
- * The user of this program agrees and understands *
- * that this software is distributed on an "as-is" *
- * basis, and shall not use this program as the basis *
- * for any claims, now or in the future, against *
- * any individual, organization, or entity. *
- \***************************************************************************/
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <dirent.h>
- #include <sys/stat.h>
-
- #define PROCD "/usr/man/cat" /* dir prefix for preformatted pages */
- #define NPROCD "/usr/man/man" /* dir prefix for nroff format pages */
- #define MAXPATH 128 /* maximum size of path to man page */
-
- /* undefine any of the following if your system doesn't have them */
-
- #define TYPECOMP "/usr/bin/zcat" /* command to display a compressed file */
- #define FORMAT "/usr/bin/nroff -man" /* command to format a manual page */
- #define PAGER "/usr/bin/more" /* system command to page a file */
-
- /* Don't play with these constants!! */
- #define C_PROC 1
- #define C_NPROC 2
-
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- int argno, section, kind, lookup();
- char command[20], pagename[MAXPATH];
-
- /* Process the command line arguments */
-
- switch(argc) {
- case 2: /* just the command name */
- strncpy(command,argv[1],20);
- section=0;
- break;
-
- case 3: /* the section and command name */
- sscanf(argv[1], "%d", §ion);
- strncpy(command,argv[2],20);
- break;
-
- default: /* invalid .. display the usage statement */
- fprintf(stderr,"usage: %s [section] command\n", argv[0]);
- exit(1);
- }
-
- /*
- * If the section is not specified explicitly, try to find
- * the manual page in the first directory where it's encountered.
- */
-
- if (section == 0) {
- for (section=1; section<=8; section++)
- if (lookup(command,section,pagename,&kind)) {
- fprintf(stderr,"%s: assuming %s from section %d\n",
- argv[0], command, section);
- printpage(pagename,kind);
- exit(0);
- }
- fprintf(stderr,"%s: cannot find %s in the manual\n",
- argv[0], command);
- exit(2);
- }
-
- /*
- * If the user specified a section, then see if we can find it
- * there .. if so, print the page
- */
-
- if (lookup(command,section,pagename,&kind)) {
- printpage(pagename,kind);
- exit(0);
- } else {
- fprintf(stderr,"%s: cannot find %s in section %d\n",
- argv[0], command, section);
- exit(2);
- }
- }
-
-
- /*
- * Function lookup returns 0 on failure and 1 on success. It will look
- * through the directories for section and try to find the manual page
- * for command. If it finds it, the entire filename is returned as
- * pagename. "kind" passes along whether the name was found in the
- * processed or unprocessed directory phases
- */
-
- int lookup(command,section,pagename,kind)
- char *command, *pagename;
- int section, *kind;
- {
- int passno, cmpman();
- char fullpath[MAXPATH];
- DIR *mdir;
- struct dirent *dentry;
-
- /*
- * Look through the formatted directory first to see if we
- * can get one that's formatted. The second pass gets
- * the formatted directory. This looks kludgy, but it's
- * pretty neat nevertheless.
- */
-
- for (passno=1; passno<=2; passno++) {
- switch(passno) {
- case 1: /* check formatted directory */
- sprintf(fullpath, "%s%d", PROCD, section);
- *kind = C_PROC;
- break;
-
- case 2: /* check unformatted directory */
- sprintf(fullpath, "%s%d", NPROCD, section);
- *kind = C_NPROC;
- break;
- }
-
- if ((mdir=opendir(fullpath)) != NULL)
- while ((dentry=readdir(mdir)) != NULL)
- if (cmpman(dentry->d_name,command) == 0) {
- closedir(mdir);
- sprintf(pagename, "%s/%s", fullpath,
- dentry->d_name);
- return(1);
- }
-
- closedir(mdir);
- }
- return(0);
- }
-
-
- /*
- * Compare name with command and see if it matches before the period
- * so we can crown it the matching manual page for command
- */
-
- int cmpman(name,command)
- char *name, *command;
- {
- while ((*name == *command) && *name != '\0' && *command != '\0') {
- name++;
- command++;
- }
-
- if (*name == '.' && *command == '\0') return(0); /* OK */
- if (*command == *name) return(0); /* also OK */
-
- return(1); /* all other cases fail */
- }
-
-
- /*
- * Printpage prints a manual page. It formats the page depending on
- * where it comes from, and invokes the system pager depending on
- * whether output is to a tty or a file/pipe
- */
-
- printpage(pageloc,form)
- char *pageloc;
- int form;
- {
- int compress, endstr, ttypage;
- char cmdline[512];
-
- /* See if we're dealing with a compressed file (.Z) */
-
- endstr=strlen(pageloc);
- if (pageloc[endstr-2]=='.' && pageloc[endstr-1]=='Z')
- compress=1;
- else
- compress=0;
-
- #ifndef TYPECOMP
- if (compress) {
- fprintf(stdout,"%s: compressed files not supported\n",
- argv[0]);
- exit(2);
- }
- #endif
-
- /* If we're a tty, page this using whatever our pager is */
-
- #ifdef PAGER
- if (isatty(1))
- ttypage=1;
- else
- ttypage=0;
- #else
- ttypage=0;
- #endif
-
- /*
- * Setup command line. This is some really sick code, but
- * how else are we to do it? I can think of only one way, but
- * it's kind of wasteful of system resources...
- */
-
- if (compress) {
- if (form == C_NPROC)
- sprintf(cmdline, "%s %s | %s", TYPECOMP, pageloc, FORMAT);
- else
- sprintf(cmdline, "%s %s", TYPECOMP, pageloc);
- } else {
- if (form == C_NPROC)
- sprintf(cmdline, "%s %s", FORMAT, pageloc);
- else
- sprintf(cmdline, "/bin/cat %s", pageloc);
- }
-
- if (ttypage) {
- strcat(cmdline," | ");
- strcat(cmdline,PAGER);
- }
-
- /* Invoke command */
-
- system(cmdline);
- }
-