tholm@uvicctr.UUCP (Terrence W. Holm) (06/02/88)
EFTH Minix report #18 - June 1988 - man(1) This is an implementation of man(1) that we wrote for Minix. Please consider this a public domain program. "man" pages are included. NOTES: The man(1) script assumes that the man files are under /usr/man/cat[1-4]. Change this as required for your system. The man(1) script is too slow on an XT. The makewhatis(1) script assumes that man files begin with: NAME command(1) - what it is You will have to change the "for" loop in makewhatis(1) if your system is different. echo x - man.1 gres '^X' '' > man.1 << '/' XNAME X man(1) - print manual pages X XSYNOPSIS X man [ section ] file X man -f name X man -k key X XDESCRIPTION X The manual pages associated with "file" will be sent to X standard output. Usually the sections for commands (1), X system calls (2), subroutines (3) and structures (4) are X checked. The "section" option forces only the specified X section to be used. X X If the standard output is a terminal then more(1) is used X to display the manual pages, otherwise cat(1) is used. X X The "-f name" option generates a one line description of X what "name" is used for. This is the same as "whatis name". X X The "-k key" option displays a one line description of any X man page using the keyword "key". X X The "-f" and "-k" options search the file "/usr/man/whatis". X This file must be remade using "makewhatis" whenever a X relevant change occurs in the manual pages. X XFILES X /usr/man/cat[1-4]/*.[1-4] X /usr/man/whatis X XSEE ALSO X more(1), whatis(1) / echo x - whatis.1 gres '^X' '' > whatis.1 << '/' XNAME X whatis(1) - what is this name used for X XSYNOPSIS X whatis name X makewhatis X XDESCRIPTION X A one line description of the command, system call or X subroutine called "name" is displayed. X X The command "whatis name" is the same as "man -f name". X X This command searches the file "/usr/man/whatis" for "name". The X file must be remade using "makewhatis" whenever a relevant change X occurs in the manual pages. X XFILES X /usr/man/whatis X XSEE ALSO X man(1) / echo x - man gres '^X' '' > man << '/' X#!/bin/sh X# man(1) efth 1988-Apr-20 X# X# man [ section ] file X# man -f name X# man -k key X XMAN=/usr/man X X# Check if standard output is a terminal X Xif tty -s <&1; then X CAT=more Xelse X CAT=cat Xfi X Xif test $# -eq 1; then X for SECT in 1 2 3 4; do X if test -r $MAN/cat$SECT/$1.$SECT; then X $CAT $MAN/cat$SECT/$1.$SECT X exit 0 X fi X done X X echo "No manual entry for $1." X exit 1 Xfi X Xif test $# -ne 2; then X echo "Usage: man [ section ] file" X echo " man -f name" X echo " man -k key" X exit 1 Xfi X Xif test .$1 = .-f; then X grep "^ *$2[ (]" $MAN/whatis | $CAT X Xelif test .$1 = .-k; then X grep "$2" $MAN/whatis | $CAT X Xelse # Must be "man section file" X X if test $1 -lt 1 -o $1 -gt 4; then X echo "Sections are: (1) commands" X echo " (2) system calls" X echo " (3) subroutines" X echo " (4) structures" X exit 1 X fi X X if test -r $MAN/cat$1/$2.$1; then X $CAT $MAN/cat$1/$2.$1 X else X echo "No entry for $2 in section $1 of the manual." X exit 1 X fi X Xfi X Xexit 0 / echo x - makewhatis gres '^X' '' > makewhatis << '/' X#!/bin/sh X# makewhatis(1) efth 1988-Apr-20 X XMAN=/usr/man X Xif test `whoami` != root; then X echo "makewhatis: must be root" X exit 1 Xfi X Xif test `pwd` != $MAN; then X cd $MAN X makewhatis X exit 0 Xfi X Xrm -f whatis X Xfor file in cat?/*; do X head -2 $file | tail -1 >>whatis Xdone X Xchmod 644 whatis Xchown bin whatis / echo x - whatis gres '^X' '' > whatis << '/' X#!/bin/sh X# whatis(1) efth 1988-Apr-20 X# X# whatis name X Xman -f $1 / -------------------------------------------------------------------- Edwin L. Froese uw-beaver!ubc-cs!mprg!handel!froese Terrence W. Holm {uw-beaver,ubc-cs}!uvicctr!sirius!tholm
wkt@csadfa.cs.adfa.oz.au (Warren Toomey) (12/19/89)
Yet another man(1) program - this one keeps man files a la Unix. ------------------------- cut here ----------------------------- #!/bin/sh # to extract, remove the header and type "sh filename" if `test ! -s ./README` then echo "writing ./README" cat > ./README << '\Rogue\Monster\' Here is yet another implementation of man(1); this one knows only about files with man macros, and files without. Each manual is in a separate file, and they are kept in cat1 ... cat8, man1 ... man8 directories just like Unix. You'll need to build a `whatis' file too! And before I go, here's my implementation of apropos & whatis: alias apropos 'grep "$1" /usr/man/whatis' alias whatis 'grep "^$1" /usr/man/whatis' Does help if you have Clam :-) Finally, with regards to Andy's 1.5 manuals posting, either break them up into separate files & put them in to /usr/man/cat1, or wait a bit. I LaTeX'd all the 1.3 manuals by hand & I will try to knock up a LaTeX -> nroff converter for the manuals I created. Merry Christmas to you all! Warren Toomey - wkt@csadfa.oz.au@munnari.oz.au[@uunet] \Rogue\Monster\ else echo "will not over write ./README" fi if `test ! -s ./man.c` then echo "writing ./man.c" cat > ./man.c << '\Rogue\Monster\' #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> /* Man - find, nroff & display online manuals * * Written by Warren Toomey. Dec, 1989. * You may freely copy or give away this source as * long as this notice remains intact. * */ /* Things to do: if stdout != tty, don't page (I think?) */ #define EPAGE "PAGER=" /* Pager environment variable name */ #define EMAN "MANPATH=" /* Man path environment variable name */ #define PAGER "/usr/local/bin/less" /* Default pager */ #define MANPATH "/usr/man" /* Default man directory */ #define WHATIS "whatis" /* Whatis file */ #define NROFF "nroff -man" /* Nroff for manuals */ int fgetarg(stream,cbuf) /* Get next arg from file into cbuf, */ FILE *stream; /* returning the character that */ char *cbuf; /* terminated it. Cbuf returns NULL */ { /* if no arg. EOF is returned if no */ int ch; /* args left in file. */ int i; i=0; cbuf[i]=NULL; while (((ch=fgetc(stream))==' ') || (ch=='\t') || (ch=='\n')) if (ch=='\n') return(ch); /* Bypass leading */ /* whitespace */ if (feof(stream)) return(EOF); cbuf[i++]=ch; while (((ch=fgetc(stream))!=' ') && (ch!='\t') && (ch!='\n')) cbuf[i++]=ch; /* Get the argument */ cbuf[i]=NULL; return(ch); } char *getenval(envp,var) /* Return the variable value from envp */ char *envp[],*var; { int i; char *value; for (i=0;envp[i]!=NULL;i++) if (!strncmp(envp[i],var,strlen(var))) { value = envp[i] + strlen(var); return(value); } return(NULL); } int fsize(path,siz) /* Return the size of a file in bytes */ char *path; /* or an error if cannot stat it */ int *siz; { struct stat buf; int i=0; if (i=stat(path,&buf)) return(i); *siz= buf.st_size; return(0); } cutstring(s1,ary) /* Cut string of fields into separate */ char *s1, *ary[]; /* fields. Separator is space, tab or : */ { int i=0; ary[0]=s1; /* Set first field */ while (*s1) { if ((*s1==' ') || (*s1=='\t') || (*s1==':')) { *s1=NULL; ary[++i]= s1+1; } s1++; } } char msearch(mp,title) /* Find the section of the manual where */ char *mp, *title; /* the requested title is in */ { char whatis[100], word[100], ch=1; int size; FILE *zin; sprintf(whatis,"%s/%s",mp,WHATIS); /* find `whatis' */ if (fsize(whatis,&size)!=0) return('0'); /* Use size to search */ /* linearly or binarily */ if ((zin=fopen(whatis,"r"))==NULL) return('0'); while (ch!=EOF) /* search for title */ { ch=fgetarg(zin,word); if (!strcmp(word,title)) { while ((ch=fgetc(zin)!='(')); /* Find the digit */ ch=fgetc(zin); fclose(zin); return(ch); } /* else skip rest of line */ else while ((ch!=EOF) && (ch!='\n')) ch=fgetarg(zin,word); } return('0'); } usage() { fprintf(stderr,"Usage: man [section] title\n"); exit(0); } main(argc,argv,envp) int argc; char *argv[], *envp[]; { int i,size; char *pager, *manpath, sect, usersect; char *mandir[100]; char cmd[200]; if ((argc<2) || (argc>3)) usage(); usersect='0'; if (argc==3) { usersect=argv[1][0]; /* Get any section */ if ((usersect<'1') || (usersect>'8')) usage(); } pager=getenval(envp,EPAGE); /* Set up pager path */ if (pager==NULL) pager= PAGER; manpath=getenval(envp,EMAN); /* Set up manual path */ if (manpath==NULL) manpath= MANPATH; cutstring(manpath,mandir); /* Split man path */ for (i=0;mandir[i]!=NULL;i++) /* For every manual directory */ { /* find an entry */ sect=msearch(mandir[i],argv[argc-1]); /* If one exists */ if ((sect!='0') && ((usersect=='0') || (usersect==sect))) { sprintf(cmd,"%s/cat%c/%s.%c", /* Check cat entry */ mandir[i],sect,argv[argc-1],sect); if (fsize(cmd,&size)) /* If none, nroff */ { /* a new one */ fprintf(stderr,"Reformatting page. Please wait...\n"); sprintf(cmd,"%s %s/man%c/%s.%c | %s",NROFF, mandir[i], sect,argv[argc-1],sect,pager); system(cmd); exit(0); } else /* just page the cat file */ { sprintf(cmd,"%s %s/cat%c/%s.%c",pager, mandir[i], sect,argv[argc-1],sect); system(cmd); exit(0); } } } printf("No manual on %s\n",argv[argc-1]); exit(1); } \Rogue\Monster\ else echo "will not over write ./man.c" fi if `test ! -s ./man.1` then echo "writing ./man.1" cat > ./man.1 << '\Rogue\Monster\' .TH man 1 .SH NAME man \- find & format online manuals .SH SYNTAX man [section] title .SH DESCRIPTION .B Man finds an online manual of the given title, formats it (if necessary), and displays it on the screen. If the title occurs in several sections of the online manuals, the section argument specifies which section. .PP .B Man looks in the users environment for two variables, .B MANPATH and .B PAGER. The first holds a list of directories where manuals are kept; directories should be absolute and be separated by spaces, tabs, or colons. It can be set up from shell like .PP $ MANPATH="/usr/man /usr/local/man" ; export MANPATH .PP If no .B MANPATH variable is found, .B man defaults to .I /usr/man. .PP The .B PAGER variable indicates which pager should be used to display the manual. If none is found, .B man defaults to .I /usr/local/bin/less. .PP .B Man searches through the .I whatis file in each of the directories in .B MANPATH for an appropriate manual. This file is described in .I whatis(5). .B Man then looks for the manual in a .I catx directory; if it is there, .B man directly displays it with the pager. Otherwise, .B nroff is used to format the manual from the .I manx directory, and the output is passed to the pager. .PP If no manual is found in .I whatis, or the manual does not exist etc., .B man will give an error message and fail. .SH FILES /usr/man \- usual directory for manuals /usr/man/whatis \- file which lists all the manuals /usr/man/catx \- directories of pre-nroffed manuals /usr/man/manx \- directories of non-nroffed manuals .SH SEE ALSO nroff(1), less(1), whatis(5) \Rogue\Monster\ else echo "will not over write ./man.1" fi if `test ! -s ./whatis.5` then echo "writing ./whatis.5" cat > ./whatis.5 << '\Rogue\Monster\' .TH whatis 5 .SH NAME whatis \- list the available online manuals .SH SYNTAX /usr/man/whatis .SH DESCRIPTION .B Whatis contains a list of all the available online manuals in the manual directory, and which section each manual is in. Each line in the file contains .PP + the name of manual .PP + the section it is in [in parentheses] .PP + a short description about the manual .PP The manual name must contain no whitespace, and have no leading whitespace. The section consists of open parenthesis, single digit (plus optional single uppercase letter \- to indicate subtype), close parenthesis, and is separated from the name and description by whitespace. The description of the manual is ignored, and can be anything, but must not contain carriage returns. .SH EXAMPLE .TP 8 whatis (5) \- the entry for this manual .TP 8 man (1) \- an entry for the manual program .TP 8 man (7) \- an entry for the manual macros .TP 8 less (1L) \- the less pager, which is not standard .SH SEE ALSO man(1), nroff(1) \Rogue\Monster\ else echo "will not over write ./whatis.5" fi echo "Finished archive 1 of 1" exit Warren Toomey VK2XWT, electric guitar licker. Deep in the bowels of ADFA Comp Science. Canberra. ACT. 2600. Email: wkt@csadfa.oz.au `Worth the money but not the risk -CC'
wkt@csadfa.cs.adfa.oz.au (Warren Toomey) (01/09/90)
The README says it all :-( ..... ------------------------- cut, etc here ---------------------------- echo x - README sed '/^X/s///' > README << '/' XOOPS! Serves me right for posting something which I'd not tested fully :-( X XI have fixed my December `version' to use the section option properly, Xand to allow multi-named manuals such as string,strchr,strcat etc. XRead the whatis(5) manual! XBack to the original README... X XHere is yet another implementation of man(1); this one knows only about Xfiles with man macros, and files without. Each manual is in a separate Xfile, and they are kept in cat1 ... cat8, man1 ... man8 directories Xjust like Unix. You'll need to build a `whatis' file too! X XAnd before I go, here's my implementation of apropos & whatis: X X alias apropos 'grep "$1" /usr/man/whatis' X X alias whatis 'grep "^$1" /usr/man/whatis' X XDoes help if you have Clam :-) X XFinally, with regards to Andy's 1.5 manuals posting, either break them Xup into separate files & put them in to /usr/man/cat1, or wait a bit. XI LaTeX'd all the 1.3 manuals by hand & I will try to knock up a XLaTeX -> nroff converter for the manuals I created. X X Merry Christmas to you all! X X Warren Toomey - wkt@csadfa.oz.au@munnari.oz.au[@uunet] / echo x - man.1 sed '/^X/s///' > man.1 << '/' X.TH man 1 X.SH NAME Xman \- find & format online manuals X.SH SYNTAX Xman [section] title X.SH DESCRIPTION X.B Man Xfinds an online manual of the given title, formats it (if necessary), and Xdisplays it on the screen. If the title occurs in several sections of Xthe online manuals, Xthe section argument specifies which section. X.PP X.B Man Xlooks in the users environment for two variables, X.B MANPATH Xand X.B PAGER. XThe first holds a list of directories where manuals are kept; directories Xshould be absolute and be separated by spaces, tabs, or colons. It can be Xset up from shell like X.PP X$ MANPATH="/usr/man /usr/local/man" ; export MANPATH X.PP XIf no X.B MANPATH Xvariable is found, X.B man Xdefaults to X.I /usr/man. X.PP XThe X.B PAGER Xvariable indicates which pager should be used to display the manual. If Xnone is found, X.B man Xdefaults to X.I /usr/local/bin/less. X.PP X.B Man Xsearches through the X.I whatis Xfile in each of the directories in X.B MANPATH Xfor an appropriate manual. This file is described in X.I whatis(5). X.B Man Xthen looks for the manual in a X.I catx Xdirectory; if it is there, X.B man Xdirectly displays it with the pager. Otherwise, X.B nroff Xis used to format the manual from the X.I manx Xdirectory, and the output is passed to the pager. X.PP XIf no manual is found in X.I whatis, Xor the manual does not exist etc., X.B man Xwill give an error message and fail. X.SH FILES X/usr/man \- usual directory for manuals X X/usr/man/whatis \- file which lists all the manuals X X/usr/man/catx \- directories of pre-nroffed manuals X X/usr/man/manx \- directories of non-nroffed manuals X.SH SEE ALSO Xnroff(1), less(1), whatis(5) X / echo x - man.c sed '/^X/s///' > man.c << '/' X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X X X/* Man - find, nroff & display online manuals X * X * Written by Warren Toomey. Dec, 1989. X * You may freely copy or give away this source as X * long as this notice remains intact. X * X */ X X/* Things to do: X if stdout != tty, don't page (I think?) X*/ X X#define EPAGE "PAGER=" /* Pager environment variable name */ X#define EMAN "MANPATH=" /* Man path environment variable name */ X X#define PAGER "/usr/local/bin/less" /* Default pager */ X#define MANPATH "/usr/local/man" /* Default man directory */ X#define WHATIS "whatis" /* Whatis file */ X#define NROFF "nroff -man" /* Nroff for manuals */ X X#define WNAME 500 /* Whatis file name length */ X#define WNUM 30 /* # words on a whatis line */ X#define WSIZE 50 /* Size of each word */ X Xint fgetarg(stream,cbuf) /* Get next arg from file into cbuf, */ X FILE *stream; /* returning the character that */ X char *cbuf; /* terminated it. Cbuf returns NULL */ X { /* if no arg. EOF is returned if no */ X int ch; /* args left in file. */ X int i; /* Modified to stop on commas! */ X X i=0; cbuf[i]=NULL; X X while (((ch=fgetc(stream))==' ') || (ch=='\t') || (ch=='\n') || (ch==',')) X if (ch=='\n') return(ch); /* Bypass leading */ X /* whitespace */ X if (feof(stream)) return(EOF); X X cbuf[i++]=ch; X X while (((ch=fgetc(stream))!=' ') && (ch!='\t') && (ch!='\n') && (ch!=',')) X cbuf[i++]=ch; /* Get the argument */ X X cbuf[i]=NULL; X return(ch); X } X X X Xchar *getenval(envp,var) /* Return the variable value from envp */ X char *envp[],*var; X { X int i; X char *value; X X for (i=0;envp[i]!=NULL;i++) X if (!strncmp(envp[i],var,strlen(var))) X { value = envp[i] + strlen(var); X return(value); X } X return(NULL); X } X X X Xint fsize(path,siz) /* Return the size of a file in bytes */ X char *path; /* or an error if cannot stat it */ X int *siz; X { X struct stat buf; X int i=0; X X X if (i=stat(path,&buf)) return(i); X X *siz= buf.st_size; X return(0); X } X X Xcutstring(s1,ary) /* Cut string of fields into separate */ X char *s1, *ary[]; /* fields. Separator is space, tab or : */ X { X int i=0; X X ary[0]=s1; /* Set first field */ X while (*s1) X { X if ((*s1==' ') || (*s1=='\t') || (*s1==':')) X { X *s1=NULL; X ary[++i]= s1+1; X } X s1++; X } X } X X Xchar *msearch(mp,title,sect) /* Find the section of the manual where */ X char *mp, *title; /* the requested title is in */ X char *sect; /* returning the new title, plus sect */ X { X char whatis[WNAME], word[WNUM][WSIZE], ch; X int size,i,minus; X FILE *zin; X X sprintf(whatis,"%s/%s",mp,WHATIS); /* find `whatis' */ X X if (fsize(whatis,&size)!=0) return(NULL); /* Use size to search */ X X if ((zin=fopen(whatis,"r"))==NULL) return(NULL); X X ch='a'; X while (ch!=EOF) /* search for title */ X { X i=0; minus=0; ch=1; X while ((ch!=EOF) && (ch!='\n')) /* get a line */ X { X ch=fgetarg(zin,word[i]); X if (!strcmp(word[i],"-")) minus=i; /* looking for "-" */ X i++; X } X X if (minus!=0) X { X ch=word[--minus][1]; /* Get section number */ X X for (i= --minus;i>=0;i--) /* Now check title */ X if ((!strcmp(word[i],title)) && ((*sect=='0') || (*sect==ch))) X { *sect=ch; X fclose(zin); X return(word[0]); X } X } X } X *sect='0'; X fclose(zin); X return(NULL); X } X X X Xusage() X { X fprintf(stderr,"Usage: man [section] title\n"); X exit(0); X } X X X Xmain(argc,argv,envp) X int argc; X char *argv[], *envp[]; X { X int i,size; X char *pager, *manpath, sect, usersect; X char *mandir[100]; X char cmd[200],title[50]; X X if ((argc<2) || (argc>3)) usage(); X X usersect='0'; X if (argc==3) X { usersect=argv[1][0]; /* Get any section */ X if ((usersect<'1') || (usersect>'8')) X usage(); X } X X pager=getenval(envp,EPAGE); /* Set up pager path */ X if (pager==NULL) pager= PAGER; X X manpath=getenval(envp,EMAN); /* Set up manual path */ X if (manpath==NULL) manpath= MANPATH; X X cutstring(manpath,mandir); /* Split man path */ X X for (i=0;mandir[i]!=NULL;i++) /* For every manual directory */ X { /* find an entry */ X sect=usersect; X strcpy(title,msearch(mandir[i],argv[argc-1],§)); X X if (sect!='0') /* If a manual */ X { X sprintf(cmd,"%s/cat%c/%s.%c", /* Check cat entry */ X mandir[i],sect,title,sect); X X if (fsize(cmd,&size)) /* If none, nroff */ X { /* a new one */ X fprintf(stderr,"Reformatting page. Please wait...\n"); X sprintf(cmd,"%s %s/man%c/%s.%c | %s",NROFF, mandir[i], X sect,title,sect,pager); X X system(cmd); X exit(0); X } X else /* just page the cat file */ X { X sprintf(cmd,"%s %s/cat%c/%s.%c",pager, mandir[i], X sect,title,sect); X X system(cmd); X exit(0); X } X } X } X printf("No manual on %s\n",argv[argc-1]); X exit(1); X } / echo x - whatis.5 sed '/^X/s///' > whatis.5 << '/' X.TH whatis 5 X.SH NAME Xwhatis \- list the available online manuals X.SH SYNTAX X/usr/man/whatis X.SH DESCRIPTION X.B Whatis Xcontains a list of all the available online manuals in the manual Xdirectory, and which section each manual is in. Each line in the file Xcontains X.PP X+ the name(s) of the manual X.PP X+ the section it is in [in parentheses] X.PP X+ a minus sign X.PP X+ a short description about the manual X.PP XEach manual name must contain no whitespace, and have no leading whitespace. XThese names must be separated by whitespace, commas, or both. XThe section consists of open parenthesis, single digit (plus optional Xsingle uppercase letter \- to indicate subtype), close parenthesis, Xand is separated from the name and description by whitespace. XThe minus sign is used by X.I man(1) Xand thus is necessary! XThe description of the manual is ignored, and can be anything. It may be Xmulti-line, in which case the following lines should be indented, and must Xnot contain lone minus signs. X.SH EXAMPLE X.TP 8 Xwhatis (5) \- the entry for this manual X.TP 8 Xman (1) \- an entry for the manual program X.TP 8 Xman (7) \- an entry for the manual macros X.TP 8 Xless (1L) \- the less pager, which is not standard X.TP 8 Xstring, strchr, strlen, strcat, strcpy (3) - various C routines for the Xhandling of strings. These are all kept in the X.I string.3 Xfile in X.I /usr/man/man3 Xor X.I /usr/man/cat3 X.SH SEE ALSO Xman(1), nroff(1) / Warren Toomey VK2XWT, heavily steaming Frenchman Deep in the bowels of ADFA Comp Science. Canberra. ACT. 2600. Email: wkt@csadfa.oz.au `Sex isn't everything. Love is. - WT'