From 18b3ba267cff8d71364cbabb5429eccf1e79bba4 Mon Sep 17 00:00:00 2001 From: Martin Cracauer Date: Sat, 3 Apr 1999 22:24:36 +0000 Subject: [PATCH] 1) Fix the case where a shellscript using getopt is called with a parameter that has space in it, both in getopt.c and in the manpage example. 2) Fix the example in the manpage. The set(1) command is required to return 0 (POSIX 1003.2, section 3.14.11), so you can't test for getopt's exit status like the example did: #! /bin/sh set -- `getopt abo: $*` if test $? != 0 # wrong, tests for set's exit status, which is # always zero, no for getopt(1)'s. Fixes PR bin/5845, which thought it was getopt's fault, but in fact the manpage was wrong. I also updated the example to be more useful and updated the BUGS section. PR: bin/5845 --- usr.bin/getopt/getopt.1 | 55 ++++++++++++++++++++++++++++------------- usr.bin/getopt/getopt.c | 2 +- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/usr.bin/getopt/getopt.1 b/usr.bin/getopt/getopt.1 index ebf1c653e715..39c79b1e2d19 100644 --- a/usr.bin/getopt/getopt.1 +++ b/usr.bin/getopt/getopt.1 @@ -1,11 +1,13 @@ -.Dd June 21, 1993 +.Dd April 3, 1999 .Dt GETOPT 1 .Os .Sh NAME .Nm getopt .Nd parse command options .Sh SYNOPSIS -.Nm set \-\- \`getopt Ar optstring $*\` +.Ic set \-\- \`getopt Ar optstring +.Qq $@ +\` .Sh DESCRIPTION .Nm Getopt is used to break up options in command lines for easy parsing by @@ -42,24 +44,27 @@ and the option which requires an argument. .Pp .Bd -literal -offset indent -set \-\- \`getopt abo: $*\` -if test $? != 0 +tmp=$(getopt abo: "$@") +if [ $? != 0 ] then echo 'Usage: ...' exit 2 fi +eval set \-\- $tmp for i do case "$i" in \-a|\-b) - flag=$i; shift;; + echo flag $i set; sflags="${i#-}$sflags"; shift;; \-o) - oarg=$2; shift; shift;; + echo oarg is "'"$2"'"; oarg="$2"; shift; shift;; \-\-) shift; break;; esac done +echo single-char flags: $sflags +echo oarg is "'"$oarg"'" .Ed .Pp This code will accept any of the following as equivalent: @@ -69,25 +74,46 @@ cmd \-aoarg file file cmd \-a \-o arg file file cmd \-oarg -a file file cmd \-a \-oarg \-\- file file +.Pp +Test your scripts with calls like this +.Pp +cmd \-ab \-o 'f \-z' +.Pp +to verify that they work with parameters/filenames that have +whitespace in them. .Ed .Sh SEE ALSO .Xr sh 1 , .Xr getopt 3 .Sh DIAGNOSTICS .Nm Getopt -prints an error message on the standard error output when it -encounters an option letter not included in +prints an error message on the standard error output and exits with +status > 0 when it encounters an option letter not included in .Ar optstring . .Sh HISTORY Written by Henry Spencer, working from a Bell Labs manual page. -Behavior believed identical to the Bell version. +Behavior believed identical to the Bell version. Example replaced in +.Fx +version 3.2 and 4.0. .Sh BUGS Whatever .Xr getopt 3 has. .Pp -Arguments containing white space or embedded shell metacharacters -generally will not survive intact; this looks easy to fix but isn't. +It is hard to get command switch parsing right in shell scripts, +especially with arguments containing whitespace or embedded shell +metacharacters. This version of +.Nm getopt +and the example in this manpage have been fixed to avoid traditional +problems. They have been tested with +.Fx +.Xr sh 1 +and with GNU bash. Note that bash has a builtin +.Nm getopt . +In shells with builtin +.Nm getopt +you need to call getopt with a full path to get the external version +described here. .Pp The error message for an invalid option is identified as coming from @@ -95,9 +121,4 @@ from rather than from the shell procedure containing the invocation of .Nm getopt ; -this again is hard to fix. -.Pp -The precise best way to use the -.Nm set -command to set the arguments without disrupting the value(s) of -shell options varies from one shell version to another. +this is hard to fix. diff --git a/usr.bin/getopt/getopt.c b/usr.bin/getopt/getopt.c index 060e2c9ce17f..19c21f853baf 100644 --- a/usr.bin/getopt/getopt.c +++ b/usr.bin/getopt/getopt.c @@ -17,7 +17,7 @@ char *argv[]; break; default: if (optarg != NULL) - printf(" -%c %s", c, optarg); + printf(" -%c '%s'", c, optarg); else printf(" -%c", c); break;