sources-request@mirror.UUCP (08/28/86)
Submitted by: Rich $alz (mirror!rs) Mod.sources: Volume 7, Issue 11 Archive-name: getoptprog #!/bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # Wrapped by mirror!rs on Thu Aug 28 12:55:41 EDT 1986 # Exit status; set to 1 on "wc" errors or if would overwrite. STATUS=0 # Contents: README Makefile getopt.1 getopt.c echo x - README if test -f README ; then echo README exists, putting output in $$README OUT=$$README STATUS=1 else OUT=README fi sed 's/^XX//' > $OUT <<'@//E*O*F README//' XXThis quick throw-off is a public-domain implementation of the USG XXgetopt program. Not to be confused with the library routine, this XXprogram helps scripts parse their options/flags/arguments. XXAfter unpacking, tweak the Makefile as appropriate and run make. Copy XXthe examples from the manpage into separate files as verify that they XXwork ok. Do a "make install". For your final examination, convert XXlint to use this program. I write more Makefiles for mod.sources XXsubmissions than I care to, and sometimes I get tired of it; I XXapologize for the terseness of the one here. XXIf you don't have getopt(3) in your C run-time library, snip it off XXthe tail of the source file, and add it, or make it easily, publicly, XXavailable in some other way. XX /Rich $alz @//E*O*F README// chmod u=rw,g=rw,o=rw $OUT echo x - Makefile if test -f Makefile ; then echo Makefile exists, putting output in $$Makefile OUT=$$Makefile STATUS=1 else OUT=Makefile fi sed 's/^XX//' > $OUT <<'@//E*O*F Makefile//' XX# Pick one XXCFLAGS = -O -DINDEX=index XX#CFLAGS = -O -DINDEX=strchr XX# Pick one XXM = /usr/man/man1/getopt.1 XX#M = /usr/man/u_man/man1/getopt.1# Is this path right? XX# Where executable ends up; don't forget the trailing / XXD = /bin/ XXgetopt: getopt.c XX $(CC) $(CFLAGS) -o getopt getopt.c XXinstall: getopt XX cp getopt $Dgetopt XX strip $Dgetopt XX cp getopt.1 $M @//E*O*F Makefile// chmod u=rw,g=rw,o=rw $OUT echo x - getopt.1 if test -f getopt.1 ; then echo getopt.1 exists, putting output in $$getopt.1 OUT=$$getopt.1 STATUS=1 else OUT=getopt.1 fi sed 's/^XX//' > $OUT <<'@//E*O*F getopt.1//' XX.TH GETOPT 1 LOCAL XX.SH NAME XXgetopt \- format flags for shell scripts XX.SH SYNOPSIS XX.B getopt XXflag_spec argument ... XX.SH DESCRIPTION XX.I Getopt XXis a program intended to be called by scripts to ``canonicalize'' their XXarguments before processing them, just as the XX.IR getopt (3) XXroutine does for C programs. XX(This need for scripts is usually most noticeable in the way XX.IR lint (1) XXhandles the XX.B \-n XXflag.) XX.PP XXThe following two examples provide the initial parsing for a script XXwhich takes two flags, XX.B \-a XXand XX.BR \-b , XXthe second of which takes an argument. XX.RS XX.ta +4n +4n +4n +4n XX.nf XX# For /bin/csh... XXset argv = (`getopt "ab:" $*`) XXif ( $status ) then XX echo "Read the documentation and try again." >/dev/tty XX exit 1 XXendif XXset Aflag=0 XXset Name=NONE XXwhile "$1" != "--" XX switch ("$1") XX case '-a': XX set Aflag=1 XX breaksw XX case '-b': XX shift XX set Name=$1 XX breaksw XX endsw XX shift XXend XXshift XXecho Aflag=$Aflag / Name=$Name / Remaining args are $* XX# For /bin/sh... XXset -- `getopt "d:s" $@` XXif test $? != 0 ; then XX echo "Read the documentation and try again." XX exit 1 XXfi XXAflag=0 XXName=NONE XXfor f XXdo XX case "$f" in XX -a) Aflag=1 XX ;; XX -b) shift XX Name=$2 XX ;; XX --) break XX ;; XX esac XX shift XXdone XXshift XXecho Aflag=$Aflag / Name=$Name / Remaining args are $* XX.fi XX.RE XX.SH DIAGNOSTICS XXThe program burps the standard XX.IR getopt (3) XXdiagnostics to standard error, and exits with a non-zero status if an XXerror occurs. XXIt is arguable wrong that the diagnostics imply that the program XXis named ``getopt'' rather than the real name of the script. XXIt is undeniably AT&T\-compatible to do this, however. XX.SH "SEE ALSO" XXcsh(1), sh(1), getopt(3) XX.SH AUTHOR XX.nf XXRich $alz XXMirror Systems XX(mirror!rs, rs@mirror.TMC.COM) @//E*O*F getopt.1// chmod u=rw,g=rw,o=rw $OUT echo x - getopt.c if test -f getopt.c ; then echo getopt.c exists, putting output in $$getopt.c OUT=$$getopt.c STATUS=1 else OUT=getopt.c fi sed 's/^XX//' > $OUT <<'@//E*O*F getopt.c//' XX/* XX** GETOPT PROGRAM AND LIBRARY ROUTINE XX** XX** I wrote main() and AT&T wrote getopt() and we both put our efforts into XX** the public domain via mod.sources. XX** Rich $alz XX** Mirror Systems XX** (mirror!rs, rs@mirror.TMC.COM) XX** August 10, 1986 XX*/ XX#include <stdio.h> XX#ifndef INDEX XX#define INDEX index XX#endif XXextern char *INDEX(); XXextern int optind; XXextern char *optarg; XXmain(ac, av) XX register int ac; XX register char *av[]; XX{ XX register char *flags; XX register int c; XX /* Check usage. */ XX if (ac < 2) { XX fprintf(stderr, "usage: %s flag-specification arg-list\n", av[0]); XX exit(2); XX } XX /* Play games; remember the flags (first argument), then splice XX them out so it looks like a "standard" command vector. */ XX flags = av[1]; XX av[1] = av[0]; XX av++; XX ac--; XX /* Print flags. */ XX while ((c = getopt(ac, av, flags)) != EOF) { XX if (c == '?') XX exit(1); XX /* We assume that shells collapse multiple spaces in `` expansion. */ XX printf("-%c %s ", c, INDEX(flags, c)[1] == ':' ? optarg : ""); XX } XX /* End of flags; print rest of options. */ XX printf("-- "); XX for (av += optind; *av; av++) XX printf("%s ", *av); XX exit(0); XX} XX XX/* XX** This is the public-domain AT&T getopt(3) code. I added the XX** #ifndef stuff because I include <stdio.h> for the program; XX** getopt, per se, doesn't need it. I also added the INDEX/index XX** hack (the original used strchr, of course). And, note that XX** technically the casts in the write(2) calls shouldn't be there. XX*/ XX#ifndef NULL XX#define NULL 0 XX#endif XX#ifndef EOF XX#define EOF (-1) XX#endif XX#ifndef INDEX XX#define INDEX index XX#endif XX#define ERR(s, c) if(opterr){\ XX extern int strlen(), write();\ XX char errbuf[2];\ XX errbuf[0] = c; errbuf[1] = '\n';\ XX (void) write(2, argv[0], (unsigned)strlen(argv[0]));\ XX (void) write(2, s, (unsigned)strlen(s));\ XX (void) write(2, errbuf, 2);} XXextern int strcmp(); XXextern char *INDEX(); XXint opterr = 1; XXint optind = 1; XXint optopt; XXchar *optarg; XXint XXgetopt(argc, argv, opts) XXint argc; XXchar **argv, *opts; XX{ XX static int sp = 1; XX register int c; XX register char *cp; XX if(sp == 1) XX if(optind >= argc || XX argv[optind][0] != '-' || argv[optind][1] == '\0') XX return(EOF); XX else if(strcmp(argv[optind], "--") == NULL) { XX optind++; XX return(EOF); XX } XX optopt = c = argv[optind][sp]; XX if(c == ':' || (cp=INDEX(opts, c)) == NULL) { XX ERR(": illegal option -- ", c); XX if(argv[optind][++sp] == '\0') { XX optind++; XX sp = 1; XX } XX return('?'); XX } XX if(*++cp == ':') { XX if(argv[optind][sp+1] != '\0') XX optarg = &argv[optind++][sp+1]; XX else if(++optind >= argc) { XX ERR(": option requires an argument -- ", c); XX sp = 1; XX return('?'); XX } else XX optarg = argv[optind++]; XX sp = 1; XX } else { XX if(argv[optind][++sp] == '\0') { XX sp = 1; XX optind++; XX } XX optarg = NULL; XX } XX return(c); XX} @//E*O*F getopt.c// chmod u=rw,g=rw,o=rw $OUT echo Inspecting for damage in transit... temp=/tmp/sharin$$; dtemp=/tmp/sharout$$ trap "rm -f $temp $dtemp; exit" 0 1 2 3 15 cat > $temp <<\!!! 15 127 756 README 15 54 348 Makefile 90 292 1707 getopt.1 139 436 2832 getopt.c 259 909 5643 total !!! wc README Makefile getopt.1 getopt.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp if test -s $dtemp ; then echo "Ouch [diff of wc output]:" cat $dtemp STATUS=1 elif test $STATUS = 0 ; then echo "No problems found." else echo "WARNING -- PROBLEMS WERE FOUND..." fi exit $STATUS