Subject: bin/704: getopt and getopts are confusingly documented
To: None <gnats-admin@NetBSD.ORG>
From: None <jhawk@MIT.EDU>
List: netbsd-bugs
Date: 01/05/1995 20:50:08
>Number:         704
>Category:       bin
>Synopsis:       getopt and getopts are confusingly documented
>Confidential:   yes
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          doc-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jan  5 20:50:06 1995
>Originator:     John Hawkinson
>Organization:
MIT
>Release:        1.0
>Environment:
System: NetBSD lola-granola 1.0 NetBSD 1.0 (LOLA-DDB) #62: Thu Jan 5 20:50:44 EST 1995 jtkohl@lola-granola:/u1/usr/src/sys/arch/i386/compile/LOLA-DDB i386
Also ocurrs in today's -current.

>Description:

	There is confusion about the differences between
	getopts and getopt. sh(1) refers to getopts, but does not
	in any way tell you how to use it, relying on you to somehow
	*know* POSIX. This is unfortunate. A patch to the man page
	is attached, partially cribbed from the POSIX spec. I do not
	understand the minimal usage of macros for bold, etc. (nor the
	lack of mandoc macros) for sh(1). Is this merely an oversite?
	I assumed so and included what I thought were appropriate man(7)
	macros in my modified section (getopts).

	The documentation for getopt(1) suggests that the idiom
		set -- `getopt foo: bar`
	be used. Originally I thought this was doc bug, but
	in retrospect, I suppose it is a getopt bug. With no args
	getopt(1), returns ``--'', which results in a ``set -- --'',
	which erroniously sets $1 and increments $#. A patch removing
	the relevant printf is attached.


>How-To-Repeat:
>Fix:

===================================================================
RCS file: RCS/sh.1,v
retrieving revision 1.1
diff -c -r1.1 sh.1
*** 1.1	1995/01/05 10:15:13
--- sh.1	1995/01/06 04:00:24
***************
*** 53,59 ****
  incorporated into this shell.  We expect POSIX conformance by the
  time 4.4 BSD is released.
  This man page is not intended to be a tutorial or a complete
! specification of the shell.
  .sp 2
  .B Overview
  .sp
--- 53,60 ----
  incorporated into this shell.  We expect POSIX conformance by the
  time 4.4 BSD is released.
  This man page is not intended to be a tutorial or a complete
! specification of the shell, however some portions of it are
! derived from the POSIX specifications.
  .sp 2
  .B Overview
  .sp
***************
*** 115,121 ****
  	esac
  
  .fi
! If command line arguments besides the options have been
  specified, then the shell treats the first argument as the
  name of a file from which to read commands (a shell script), and
  the remaining arguments are set as the positional parameters
--- 116,122 ----
  	esac
  
  .fi
! If command line arguments besides the options have been
  specified, then the shell treats the first argument as the
  name of a file from which to read commands (a shell script), and
  the remaining arguments are set as the positional parameters
***************
*** 1164,1172 ****
  fg [ job ]
  Move the specified job or the current job to the
  foreground.
! .TP
! getopts optstring var
! The POSIX getopts command.
  .TP
  hash -rv command...
  The shell maintains a hash table which remembers the
--- 1165,1268 ----
  fg [ job ]
  Move the specified job or the current job to the
  foreground.
! .HP
! .I getopts
! .B optstring
! .B var
! .RE
! .RS
! .sp
! The POSIX
! .I getopts
! command, not to be confused with the
! .B Bell Labs
! -derived getopt(1).
! .I getopts
! is preferable to the getopt(1) utility due to it's handling of
! arguments containing whitespace.
! .sp
! The getopts builtin may be used to obtain options and their arguments
! from a list of parameters.  Upon invokation,
! .I getopts
! places the value of the next option ( in the shell variable specified by
! .B var
! and its index in the shell variable
! .BR OPTIND .
! Upon shell invokation, 
! .B OPTIND
! is initialized to 1.  When an option requires an argument, the
! .I getopts
! builtin will place it in the shell variable
! .BR OPTARG .
! If no option is found, or is allowed for in the syntax
! specified by
! .BR optstring ,
! then
! .B OPTARG
! will be unset.
! .sp
! .B optstring
! is a string of option characters.  If a character is followed
! by a 
! .BR : ,
! the option ought to have an argument.  Question marks and
! colons may not be used as option characters. If an option
! character is not found where expected,
! .I getopts
! will set the variable specified by
! .B var
! to
! .BR ? ;
! getopts will then unset
! .B OPTARG
! and write output to standard error, unless the first character
! of
! .B optstring
! is a
! .BR : ,
! in which case errors will be ignored.
! .sp
! After reaching the last option,
! .I getopts
! exists with a nonzero return value, with
! .B OPTINT
! set to the first non-option's index; if there are no such
! arguments, then
! .B var
! is set to
! .BR ? .
! The special option,
! .BR -- ,
! also indicates the end of options. To following script
! makes use of
! .IR getopts :
! .nf
! 
! 	while abo: name
! 	do
! 		case $name in
! 		a)	aflag=1;;
! 		b)	bflag=1;;
! 		o)	oflag=1
! 			oval="$OPTARG";;
! 		?)	printf "Usage: %s: [-a] [-b] [-o value] args" $0
! 			exit 2;;
! 		esac
! 	done
! 	if [ ! -z "$aflag" ]; then
! 		printf "Option -a specified\n"
! 	fi
! 	if [ ! -z "$bflag" ]; then
! 		printf "Option -b specified\n"
! 	fi
! 	if [ ! -z "$oflag" ]; then
! 		printf 'Option -o "%s" specified\n' "$oval"
! 	fi
! 	shift $(($OPTIND - 1))
! 	printf "Remaining arguments are: %s\n" "$*"
! 
! .fi
! .RE
  .TP
  hash -rv command...
  The shell maintains a hash table which remembers the
***************
*** 1176,1187 ****
  the last cd command are marked with an asterisk; it
  is possible for these entries to be invalid.
  .sp
! With arguments, the hash command removes the specified commands from the hash table (unless they are
! functions) and then locates them.   With the -v
! option, hash prints the locations of the commands as
! it finds them.  The -r option causes the hash command
! to delete all the entries in the hash table except
! for functions.
  .TP
  jobid [ job ]
  Print the process id's of the processes in the job.
--- 1272,1282 ----
  the last cd command are marked with an asterisk; it
  is possible for these entries to be invalid.
  .sp
! With arguments, the hash command removes the specified commands from
! the hash table (unless they are functions) and then locates them.
! With the -v option, hash prints the locations of the commands as it
! finds them.  The -r option causes the hash command to delete all the
! entries in the hash table except for functions.
  .TP
  jobid [ job ]
  Print the process id's of the processes in the job.
===================================================================
RCS file: RCS/getopt.c,v
retrieving revision 1.1
diff -c -r1.1 getopt.c
*** 1.1	1995/01/06 04:41:18
--- getopt.c	1995/01/06 04:41:35
***************
*** 26,32 ****
  				printf(" -%c", c);
  			break;
  		}
- 	printf(" --");
  	for (; optind < argc; optind++)
  		printf(" %s", argv[optind]);
  	printf("\n");
--- 26,31 ----

>Audit-Trail:
>Unformatted: