perlman@wanginst.UUCP (Gary Perlman) (06/02/85)
pman allows quick access to specific parts of entries, rather than printing whole entries. For example, "pman who", prints the NAME and SYNOPSIS parts of what "man who" prints. Because the output is by section, and so is usually short, a pipe to a pagination program, like more, is usually unnecessary, making pman that much faster than man. There are options for compressing the output by simple reformatting, so that for many programs, the basic information is on one to three lines. pman makes comparison of program options a simple exercise. A simple system of equivalence classes: warnings = WARNING* STATUS LIMITATION* DIAGNOSTIC* + CAVEAT* BUG* NOTE* RESTRICTION* variables = FILE* ENVRON* VARIABLE* details = DESCRIPTION OPTION* NOTE* COMMENT* COMMAND* examples = EXAMPLE* HINT* xrefs = SEE_ALSO AUTHOR ALGORITHM* REFERENCE* makes it easier to find sections of interest, despite variation in section heading conventions. For example, DEC ULTRIX documentation avoids BUGS sections by calling them RESTRICTIONS or LIMITATIONS. pman is especially useful when conventional section headings are used extensively. One unconventional section I find useful for getting abbreviated on-line help is an OPTIONS section (accessed with the -o option) with just the command line options. I find this section fits nicely right after the SYNOPSIS section. Unfortunately, this section is seldom used. If you find pman useful, and would like to make it more useful, you can put an OPTION section into existing manuals entries. Please send comments and changes to me. Gary Perlman Wang Institute Tyngsboro, MA 01879 (617) 649-9731 UUCP: decvax!wanginst!perlman CSNET: perlman@wanginst #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #!/bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # Makefile # pman.1 # pman.nr # pman.c # pman.t # getopt.c # This archive created: Sun Jun 2 02:25:35 1985 # By: Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA) export PATH; PATH=/bin:$PATH echo shar: extracting "'Makefile'" '(85 characters)' if test -f 'Makefile' then echo shar: over-writing existing file "'Makefile'" fi cat << \SHAR_EOF > 'Makefile' G=getopt.o CFLAGS = -O pman: pman.o $G cc $(CFLAGS) -o pman pman.o $G test: pman.t SHAR_EOF echo shar: extracting "'pman.1'" '(3833 characters)' if test -f 'pman.1' then echo shar: over-writing existing file "'pman.1'" fi cat << \SHAR_EOF > 'pman.1' .TH PMAN 1WI "May 27, 1985" "Wang Institute" "UNIX User's Manual" .SH NAME pman \- extract selected parts of an on-line manual page .SH SYNTAX .B pman [-abcdehknosvwx] [-+ name] [section] [-] names .SH DESCRIPTION .I pman is used to print one or more parts of a .I man page, such as the NAME or EXAMPLE section. The program allows quick reference to the on-line manual, showing only parts of interest. Synonyms are used to avoid overlooking topics. A part begins with a section name, and ends with a new part. A new part is a line beginning with at least with two upper case letters (except for \fInroff\fR page breaks that may contain the upper case name of the entry). Sections are printed in the order they appear in the manual entry, not in the order requested. Blank lines are suppressed, and there is an option for extra-compact output, making pagination by programs like .I more unnecessary. .SH OPTIONS .PP The section of the manual (1-8) can be supplied after all the flag options and before the names. Otherwise, all sections are searched until an entry is found. The manual entry can be read from the standard where a single - is placed instead of a name. .de OP\"option .TP .B -\\$1 \\$2 \\$3 .. .PP Most option letters correspond to a man page section. With no options, the -n, -s, and -e options are assumed. .OP a Print all entries in a requested section or all sections of the given name. This allows searching for more than one version of an entry, which can happen with local implementations. This option implies the -h option so that the section is printed. .OP b Non-redundant blank lines are printed. By default, these are removed to compress the output. .OP c Compacted output. With this option, .I pman tries to put parts on one line. This option assumes that text is indented five spaces and may be upset by tabs in the formatted entry. .OP h Print a header with the entry's name and source section. .SS Sections .PP The following options print parts of manual entries or types of manual entries (such as all sections with warnings). .OP + name Add \fBname\fR to the list of printed parts. This allows access to sections not anticipated by .I pman, or using .I pman without having to know the options. .OP d DESCRIPTION, OPTIONS, NOTES, COMMENTS, COMMANDS (detail about the entry) .OP e EXAMPLES or HINTS .OP k KEYWORDS, NAME, or SEE ALSO .OP n NAME (name and purpose of the entry) .OP o OPTIONS (unfortunately, few files use a separate section expressly for option descriptions) .OP s SYNTAX, SYNOPSIS, or USAGE .OP v VARIABLES, ENVIRONMENT, or FILES (special variables or files used by the entry) .OP w WARNINGS, BUGS, LIMITATIONS, RESTRICTIONS, DIAGNOSTICS, CAVEATS, NOTES, and STATUS .OP x SEE ALSO, REFERENCES, ALGORITHM, and AUTHOR (cross-references) .SH EXAMPLES .de EX .nf .ta 2.5i \fB\\$1 \fR# \\$2 .fi .. .EX "pman -s echo" "SYNTAX from \fIman echo" .EX "pman -vw 1 man" "VARIABLES & WARNINGS from \fIman 1 man\fR" .EX "pman -+ 7 REQ man" "REQUESTS section on \fIman\fR macros" .EX "pman -hd w | sed 's/.^H//g'" "header & detail unhighlighted" .fi .SH FILE /usr/man/cat?/* (formatted manual entries searched for here) .SH "SEE ALSO man(1) .SH KEYWORDS help, documentation .SH AUTHOR Gary \fIP\fPerl\fPman\fP (based on a shell script by Bob Marcus) .SH BUGS .PP The compacted output may have problems when there are tabs in the formatted text. .SH RESTRICTIONS .PP .I pman will not work if sections headings are indented or contain overstriking to embolden. The filter: \fBsed 's/.^H//g'\fR can be used with the standard input option to help with this problem. .SH STATUS .PP I am open to suggestions for enhancements. Bug fixes and new features are appreciated and will be acknowledged. .PP The program has been tested on 4.2 BSD UNIX and System V. SHAR_EOF echo shar: extracting "'pman.nr'" '(4442 characters)' if test -f 'pman.nr' then echo shar: over-writing existing file "'pman.nr'" fi cat << \SHAR_EOF > 'pman.nr' PMAN(1WI) UNIX User's Manual PMAN(1WI) NAME pman - extract selected parts of an on-line manual page SYNTAX pman [-abcdehknosvwx] [-+ name] [section] [-] names DESCRIPTION pman is used to print one or more parts of a man page, such as the NAME or EXAMPLE section. The program allows quick reference to the on-line manual, showing only parts of interest. Synonyms are used to avoid overlooking topics. A part begins with a section name, and ends with a new part. A new part is a line beginning with at least with two upper case letters (except for nroff page breaks that may contain the upper case name of the entry). Sections are printed in the order they appear in the manual entry, not in the order requested. Blank lines are suppressed, and there is an option for extra-compact output, making pagination by pro- grams like more unnecessary. OPTIONS The section of the manual (1-8) can be supplied after all the flag options and before the names. Otherwise, all sec- tions are searched until an entry is found. The manual entry can be read from the standard where a single - is placed instead of a name. Most option letters correspond to a man page section. With no options, the -n, -s, and -e options are assumed. -a Print all entries in a requested section or all sec- tions of the given name. This allows searching for more than one version of an entry, which can happen with local implementations. This option implies the -h option so that the section is printed. -b Non-redundant blank lines are printed. By default, these are removed to compress the output. -c Compacted output. With this option, pman tries to put parts on one line. This option assumes that text is indented five spaces and may be upset by tabs in the formatted entry. -h Print a header with the entry's name and source sec- tion. Sections The following options print parts of manual entries or types of manual entries (such as all sections with warnings). Printed 6/2/85 May 27, 1985 1 PMAN(1WI) UNIX User's Manual PMAN(1WI) -+ name Add name to the list of printed parts. This allows access to sections not anticipated by pman, or using pman without having to know the options. -d DESCRIPTION, OPTIONS, NOTES, COMMENTS, COMMANDS (detail about the entry) -e EXAMPLES or HINTS -k KEYWORDS, NAME, or SEE ALSO -n NAME (name and purpose of the entry) -o OPTIONS (unfortunately, few files use a separate sec- tion expressly for option descriptions) -s SYNTAX, SYNOPSIS, or USAGE -v VARIABLES, ENVIRONMENT, or FILES (special variables or files used by the entry) -w WARNINGS, BUGS, LIMITATIONS, RESTRICTIONS, DIAGNOSTICS, CAVEATS, NOTES, and STATUS -x SEE ALSO, REFERENCES, ALGORITHM, and AUTHOR (cross- references) EXAMPLES pman -s echo # SYNTAX from man echo pman -vw 1 man # VARIABLES & WARNINGS from man 1 man pman -+ 7 REQ man # REQUESTS section on man macros pman -hd w | sed 's/.^H//g'# header & detail unhighlighted FILE /usr/man/cat?/* (formatted manual entries searched for here) SEE ALSO man(1) KEYWORDS help, documentation AUTHOR Gary Perlman (based on a shell script by Bob Marcus) BUGS The compacted output may have problems when there are tabs in the formatted text. RESTRICTIONS Printed 6/2/85 May 27, 1985 2 PMAN(1WI) UNIX User's Manual PMAN(1WI) pman will not work if sections headings are indented or con- tain overstriking to embolden. The filter: sed 's/.^H//g' can be used with the standard input option to help with this problem. STATUS I am open to suggestions for enhancements. Bug fixes and new features are appreciated and will be acknowledged. The program has been tested on 4.2 BSD UNIX and System V. Printed 6/2/85 May 27, 1985 3 SHAR_EOF echo shar: extracting "'pman.c'" '(13550 characters)' if test -f 'pman.c' then echo shar: over-writing existing file "'pman.c'" fi cat << \SHAR_EOF > 'pman.c' /* contents: pman main program to print sections of formatted manuals make: pman: pman.o getopt.o (putopt.o) cc -o pman pman.o getopt.o (putopt.o) compiler options: -DMONITOR="file" saves monitor info in file (local only) -DCATMANDIR="dir" looks for manual entries here author: Gary Perlman Wang Institute May 25 1985 (based on a script by Bob Marcus) assumptions: 1. section headings are on the left margin 2. section headings do not contain any overstriking as is possible with some versions of nroff possible extensions: calling pattern: the real workhorse is checklines main (argc, argv) initial (argc, argv) putopt (argc, argv, optstring, file) getopt (argc, argv, optstring) addsection (optarg) checklines (stdin, "-") getname (from file text) pman (name) findfile (section, name) printman (name, section, fullpath) printheader (name, section, fullpath) checklines (ioptr, name) getname (from file name) */ #include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/dir.h> /* directory functions/macros for portability between 4.2 BSD on older UNIX systems. syntax ends up being like 4.2 BSD. */ #ifdef MAXNAMLEN /* probably should be BSD4_2 or the like */ #define namedir(entry) (entry->d_name) #define MAXNAME 256 #else #define DIR FILE #define MAXNAME (DIRSIZ+2) #define opendir(path) fopen (path, "r") #define closedir(dirp) fclose (dirp) char *strncpy (); static char DiRtNaMe[MAXNAME]; /* name of current dir saved here */ #define namedir(entry) strncpy (DiRtNaMe, entry->d_name, DIRSIZ) struct direct * readdir (dirp) DIR *dirp; { static struct direct entry; if (dirp == NULL) return (NULL); for (;;) { if (fread (&entry, sizeof (struct direct), 1, dirp) == 0) return (NULL); if (entry.d_ino) return (&entry); } } #endif #define EOS '\0' #define MAXSECTIONS 8 /* sections 1 - 8 in manual */ #define INDENT 5 /* number of spaces man text is indented */ #define issection(s) (s[1] == EOS && *s >= '1' && (*s-'0') <= MAXSECTIONS) #define newsection(s) (isupper (s[0]) && isupper (s[1])) /* PARAMETERS */ #ifndef #define CATMANDIR "/usr/man/cat" #endif char *Catmandir = CATMANDIR; /* cat files in Catmandir[1-8] */ int Section = 0; /* manual section number */ /* OPTIONS: print the corresponding section in the UNIX manual */ int Header; /* print a header */ int Compact; /* compact output format */ int All; /* print all occurances of name */ int Blanklines; /* print blank lines */ int Name; /* NAME */ int Options; /* OPTIONS */ int Keywords; /* KEYWORDS NAME SEE ALSO */ int Syntax; /* SYNTAX SYNOPSIS USAGE */ int Description; /* DESCRIPTION */ int Variables; /* VARIABLES FILES ENVIRON */ int Warnings; /* BUGS LIMITATIONS DIAGNOSTICS WARNINGS RESTRICTION */ /* STATUS */ int Examples; /* EXAMPLES */ int Xrefs; /* SEE ALSO AUTHOR */ initial (argc, argv) char **argv; { extern char *optarg; extern int optind; int errflg = 0; int C; char *optstring = "abcdehknosvwx+:"; int popt = 0; /* have any printing options been selected? */ #define USAGE "Usage: %s [-abcdehknosvwx] [-+ name] [section] [-] names\n" #ifdef MONITOR putopt (argc, argv, optstring, MONITOR); #endif while ((C = getopt (argc, argv, optstring)) != EOF) switch (C) { default: errflg++; break; case 'a': All++; Header++; break; case 'b': Blanklines++; break; case 'c': Compact++; break; case 'd': Description++; popt++; break; case 'e': Examples++; popt++; break; case 'h': Header++; break; case 'k': Keywords++; popt++; break; case 'n': Name++; popt++; break; case 'o': Options++; popt++; break; case 's': Syntax++; popt++; break; case 'v': Variables++; popt++; break; case 'w': Warnings++; popt++; break; case 'x': Xrefs++; popt++; break; case '+': if (addsection (optarg)) popt++; else { fprintf (stderr, "%s: Can't add '%s'. ", argv[0], optarg); fprintf (stderr, "(Too many sections)\n"); errflg++; } break; } if (issection (argv[optind])) { Section = argv[optind][0] - '0'; optind++; } if (optind == argc) { fprintf (stderr, "%s: no names supplied\n", argv[0]); errflg++; } if (errflg) { fprintf (stderr, USAGE, argv[0]); exit (1); } if (popt == 0) /* no printing options selected */ Name = Syntax = Examples = 1; } main (argc, argv) char **argv; { extern int optind; char *name; initial (argc, argv); while (optind < argc) { name = argv[optind++]; if (!strcmp (name, "-")) /* process stdin */ checklines (stdin, name); else if (pman (name) == 0) { fprintf (stderr, "%s: no manual entry found for %s", argv[0], name); if (Section) fprintf (stderr, " in section %d", Section); putc ('\n', stderr); } } exit (0); } printman (name, section, fullpath) char *name; int section; char *fullpath; { FILE *ioptr; if (!fullpath || (ioptr = fopen (fullpath, "r")) == NULL) return (0); if (Header) printheader (name, section, fullpath); checklines (ioptr, name); (void) fclose (ioptr); return (1); } /* searches dir, prints, returns success */ findfile (section, name) int section; char *name; { char fullpath[BUFSIZ]; char dir[BUFSIZ]; DIR *dirp; int success = 0; (void) sprintf (dir, "%s%d", Catmandir, section); *fullpath = EOS; if (dirp = opendir (dir)) { struct direct *dp; int len = strlen (name); while (dp = readdir (dirp)) { if (begins (name, namedir(dp)) && (namedir(dp)[len] == '.' || namedir(dp)[len] == EOS)) { (void) sprintf (fullpath, "%s/%s", dir, namedir(dp)); if (printman (name, section, fullpath)) { success++; if (!All) break; } } } closedir (dirp); } return (success); } /* print what is requested from name, if possible, and return success */ pman (name) char *name; { int section; int success = 0; if (Section) return (findfile (Section, name)); /* check all sections, stop at first hit */ for (section = 1; section < MAXSECTIONS; section++) if (findfile (section, name)) { success++; if (!All) break; } return (success); } /* Data structure definition pairing parts of a manual with options There are defined parts left while the name is undefined The very last part has the printflag set to NULL */ typedef struct { int *pflag; /* if true, then print this section */ char *name; /* the name of the manual part to be printed */ } PART; #define partname(i) (Part[i].name) #define partprint(i) (*(Part[i].pflag)) #define partsleft(i) (Part[i].name) #define lastpart(i) (Part[i].pflag == NULL) int True = 1; /* dummy pflag */ PART Part[] = /* end with null elements */ { { &Name, "NAME" }, { &Keywords, "NAME" }, { &Keywords, "KEYWORD" }, { &Keywords, "SEE ALSO" }, { &Options, "OPTIONS" }, { &Syntax, "SYNTAX" }, { &Syntax, "SYNOPSIS" }, { &Syntax, "USAGE" }, { &Description, "DESCRIPTION" }, { &Description, "NOTE" }, { &Description, "COMMENT" }, { &Description, "OPTION" }, { &Description, "COMMAND" }, { &Variables, "FILE" }, { &Variables, "VARIABLE" }, { &Variables, "ENVIRON" }, { &Examples, "EXAMPLE" }, { &Examples, "HINT" }, { &Xrefs, "SEE ALSO" }, { &Xrefs, "REFERENCE" }, { &Xrefs, "ALGORITHM" }, { &Xrefs, "AUTHOR" }, { &Warnings, "WARNING" }, { &Warnings, "STATUS" }, { &Warnings, "NOTE" }, { &Warnings, "CAVEAT" }, { &Warnings, "DIAGNOSTIC" }, { &Warnings, "BUG" }, { &Warnings, "RESTRICTION" }, { &Warnings, "LIMIT" }, { &True, NULL }, /* last one must be null */ { &True, NULL }, /* extras left for + option */ { &True, NULL }, { &True, NULL }, { &True, NULL }, { &True, NULL }, { &True, NULL }, { &True, NULL }, { &True, NULL }, { &True, NULL }, { NULL, NULL } /* very last nust be NULL NULL */ }; /* checklines reads the lines from its file until exhausted, printing the sections requested. It matches the name part in the Part structure and then if that part has been asked for, it prints until the next part of the manual entry. checklines skips many unwanted lines: page numbering lines, blank lines, copyright lines, and miscallaneous page header/footer lines note: most of this program's time is spent here (esp. in fgets) */ checklines (ioptr, name) FILE *ioptr; char *name; { char line[BUFSIZ]; char NAME[BUFSIZ]; /* upper case version of name */ register int part; /* index through all the different parts */ int printing = 0; /* are we printing the lines in this part? */ int prevblank = 0; /* was previous line a blank? */ register char *ptr; getname (name, NAME, ioptr); while (fgets (ptr = line, BUFSIZ, ioptr)) { /* set ptr to first non-space character */ if (isspace (*ptr)) /* most common case first */ { while (isspace (*ptr)) ptr++; if (*ptr == EOS) /* a visually empty line */ { if (Blanklines && printing && !prevblank) prevblank = putchar ('\n'); /* else skip over blank lines */ continue; } } else if (isdigit (*ptr)) /* page number in column 0 */ continue; else if (begins ("Printed ", ptr)) continue; /* skip over page footer */ /* assert (!isspace (*ptr)); */ if (begins (NAME, ptr)) /* just a page break header */ { char *eptr = ptr; if (ptr == line) /* NAME(#) at line start */ continue; while (*eptr && !isspace (*eptr)) eptr++; /* go to first space */ while (isspace (*eptr)) eptr++; if (*eptr == EOS) /* NAME(#) at line end */ continue; } else if (begins ("(c) Digital", ptr)) continue; /* skip over DEC copyright lines */ /* we now have a printable line */ if (newsection (line)) /* see if lines will be printed */ { printing = 0; for (part = 0; partsleft (part); part++) if (begins (partname(part), line)) if (printing = partprint(part)) break; /* else continue to check for -+ option parts */ } if (printing) { if (Compact) { if (newsection (line)) { while (*ptr) ptr++; while (ptr > line && isspace (*(ptr-1))) ptr--; *ptr = EOS; printf ("%-.7s", line); } else { putchar ('\t'); if (ptr-line > INDENT) /* only skip indent */ ptr = line+INDENT; /* might foul up tabstops */ fputs (ptr, stdout); } } else fputs (line, stdout); prevblank = 0; /* previous line not a blank line */ } } } /* add a new section name to the search list and return success */ addsection (name) char *name; { int part; for (part = 0; partsleft (part); part++); /* get last part */ if (!lastpart (part)) { partname (part) = name; return (1); } else return (0); } begins (s1, s2) /* true if s1 is the beginning of s2 */ register char *s1; register char *s2; { while (*s1) if (*s1++ != *s2++) return (0); return (1); } underline (s) /* prints s underlined */ char *s; { while (*s) { if (isprint (*s) && *s != ' ') { putchar ('_'); putchar ('\b'); } putchar (*s++); } } /* print the name and section (e.g., 1local, 3g) of name */ printheader (name, section, fullpath) char *name; /* base name of man entry */ int section; /* the section number of the entry */ char *fullpath; /* the full path name of the entry */ { char header[BUFSIZ]; register char *sptr; /* eventually, a sub-section pointer */ for (sptr = fullpath; *sptr; sptr++); while (*sptr != '.' && *sptr != '/' && sptr > fullpath) sptr--; if (*sptr) sptr++; /* skip over . */ if (*sptr) sptr++; /* skip over section digit */ (void) sprintf (header, "SOURCE%c\t%s %d%s\n", (Compact ? ' ' : '\n'), name, section, sptr); underline (header); } /* get NAME used to search for lines with -man format headers */ getname (name, NAME, ioptr) char *name; /* the base name of the entry */ char *NAME; /* eventually, the upper case name with ( suffix */ FILE *ioptr; /* man file, needed if input is from stdin */ { char line[BUFSIZ]; register char *ptr; extern char *strcpy (); if (!strcmp (name, "-")) /* input will be from stdin */ { while (fgets (ptr = line, BUFSIZ, ioptr)) { while (isspace (*ptr)) ptr++; if (*ptr) /* we have the title */ { name = ptr; while (*ptr && !isspace (*ptr) && *ptr != '(') ptr++; *ptr = EOS; break; } } } (void) strcpy (NAME, name); /* copy, map to UC, and add open paren */ for (ptr = NAME; *ptr; ptr++) if (islower (*ptr)) *ptr = toupper (*ptr); *ptr++ = '('; *ptr = EOS; } SHAR_EOF echo shar: extracting "'pman.t'" '(1313 characters)' if test -f 'pman.t' then echo shar: over-writing existing file "'pman.t'" fi cat << \SHAR_EOF > 'pman.t' #! /bin/sh # test script for pman options E="echo ============ " F='mv rm cp ln find' $E ILLEGAL OPTION: pman -z $F pman -z $F $E MISSING NAMES: pman pman $E UNFOUND NAME: pman nomanual foobaz pman nomanual foobaz $E UNFOUND NAME IN SECTION: pman 5 ls pman 5 ls $E SIMPLE TEST SHOULD PRINT NAME SECTION AND EXAMPLES: pman $F pman $F $E NAME: pman -n $F pman -n $F $E COMPACT SYNTAX: pman -cs $F pman -cs $F $E PROCESSED MAN OUTPUT: pman -cnwv - '<' pman.nr pman -cnwv - < pman.nr $E HEADER WITH BLANK LINES WITH WARNINGS: pman -wbh $F pman -wbh $F $E COMPACT LISTING OF SEE ALSO FOR FILES: pman -c -+ '"SEE ALSO"' $F pman -c -+ "SEE ALSO" $F $E COMPACT VARIABLES FOR SECTION 7 MAN MACROS: pman -cv 7 man pman -cv 7 man $E REQUESTS FOR SECTION 7 MAN MACROS: pman -+ REQ 7 man pman -+ REQ 7 man $E EXAMPLES FOR SECT 3 VARARGS W/OUT SECT SUPPLIED: pman -e varargs pman -e varargs $E ABOVE, WITH -+ OPTION AND SECT SUPPLIED: pman -+ EXAMPLE 3 varargs pman -+ EXAMPLE 3 varargs $E OPTIONS AND NAME FOR FTP: pman -on ftp pman -on ftp $E FILES AND VARIABLES FOR MAIL: pman -v mail pman -v mail $E COMPACT HEADER AND WARNINGS FOR UUCP: pman -cwh uucp pman -cwh uucp $E HEADER AND XREFS WITH BLANKS FOR SH AND CSH: pman -hbx sh csh pman -hbx sh csh $E ALL VERSIONS OF MKDIR: pman -a mkdir pman -a mkdir SHAR_EOF chmod +x 'pman.t' echo shar: extracting "'getopt.c'" '(1437 characters)' if test -f 'getopt.c' then echo shar: over-writing existing file "'getopt.c'" fi cat << \SHAR_EOF > 'getopt.c' /* got this off net.sources */ #include <stdio.h> /* * get option letter from argument vector */ int opterr = 1, /* useless, never set or used */ optind = 1, /* index into parent argv vector */ optopt; /* character checked for validity */ char *optarg; /* argument associated with option */ #define BADCH (int)'?' #define EMSG "" #define tell(s) fputs(*nargv,stderr);fputs(s,stderr); \ fputc(optopt,stderr);fputc('\n',stderr);return(BADCH); getopt(nargc,nargv,ostr) int nargc; char **nargv, *ostr; { static char *place = EMSG; /* option letter processing */ register char *oli; /* option letter list index */ char *index(); if(!*place) { /* update scanning pointer */ if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF); if (*place == '-') { /* found "--" */ ++optind; return(EOF); } } /* option letter okay? */ if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) { if(!*place) ++optind; tell(": illegal option -- "); } if (*++oli != ':') { /* don't need argument */ optarg = NULL; if (!*place) ++optind; } else { /* need an argument */ if (*place) optarg = place; /* no white space */ else if (nargc <= ++optind) { /* no arg */ place = EMSG; tell(": option requires an argument -- "); } else optarg = nargv[optind]; /* white space */ place = EMSG; ++optind; } return(optopt); /* dump back option letter */ } SHAR_EOF # End of shell archive exit 0 -- Gary Perlman Wang Institute Tyngsboro, MA 01879 (617) 649-9731 UUCP: decvax!wanginst!perlman CSNET: perlman@wanginst