Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Feb 2003 15:52:18 -0500
From:      John Stalker <stalker@Math.Princeton.EDU>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/48603: Getopt(1) is broken. Patch included.
Message-ID:  <200302232052.h1NKqIG09316@math.Princeton.EDU>

next in thread | raw e-mail | index | archive | help

>Number:         48603
>Category:       bin
>Synopsis:       Getopt is broken. Patch included.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Feb 23 13:00:20 PST 2003
>Closed-Date:
>Last-Modified:
>Originator:     John Stalker
>Release:        FreeBSD 4.7-STABLE i386
>Organization:
Princeton University
>Environment:
System: FreeBSD bilbo.dev.null 4.7-STABLE FreeBSD 4.7-STABLE #1: Fri Dec 27 23:0
0:21 EST 2002 root@rockhopper.dev.null:/usr/obj/usr/src/sys/BILBO i386


>Description:
Getopt(1) does not handle arguments with spaces or shell wildcards
intelligently, as its manpage admits.  The main problem is that the
manpage says to pass it arguments as $* rather than as "$@".  This
needs to be corrected, but that requires two other changes.  getopt
has to be changed so that its output is ready for reinterpretation
by the shell and the set command needs to by preceded by an eval so
that this interpretation is done correctly.
>How-To-Repeat:
Use the getopt(1) example, which has arguments "abo:", with
arguments -ab -o "this option argument has spaces in it" or
with -ab -o '/*'.
>Fix:
There are two possible fixes.  The simpler of the two is given as a
patch below.  This patches both getopt and its manpage.  It simply
modifies getopt to single-quote option arguments--handling embedded
single quotes correctly--and modifies the manpage accordingly.  One
can also modify getopt to escape anything which could confuse the
shell rather than quoting.  This is more complicated, but it might
be helpful for shell scripts written according to the onld manpage.
They can never be fixed properly, but they would cope better with
escape sequences than single quotes.  Let me know if you would like
a patch for that as well.


diff -Naur getopt.orig/getopt.1 getopt.fix1/getopt.1
--- getopt.orig/getopt.1        Sun Feb 23 10:47:37 2003
+++ getopt.fix1/getopt.1        Sun Feb 23 11:01:46 2003
@@ -7,7 +7,7 @@
 .Nm getopt
 .Nd parse command options
 .Sh SYNOPSIS
-.Nm args=\`getopt Ar optstring $*\`
+.Nm args=\`getopt Ar optstring "$@"\`
 ; errcode=$?; set \-\- $args
 .Sh DESCRIPTION
 The
@@ -46,18 +46,18 @@
 which requires an argument.
 .Pp
 .Bd -literal -offset indent
-args=\`getopt abo: $*\`
-# you should not use \`getopt abo: "$@"\` since that would parse
-# the arguments differently from what the set command below does.
+args=\`getopt abo: "$@"\`
 if [ $? != 0 ]
 then
        echo 'Usage: ...'
        exit 2
 fi
-set \-\- $args
+eval set \-\- $args
 # You cannot use the set command with a backquoted getopt directly,
 # since the exit code from getopt would be shadowed by those of set,
 # which is zero by definition.
+# Eval is needed because set will otherwise break arguments at $IFS
+# even when they are single-quoted.
 for i
 do
        case "$i"
@@ -66,8 +66,7 @@
                        echo flag $i set; sflags="${i#-}$sflags";
                        shift;;
                \-o)
-                       echo oarg is "'"$2"'"; oarg="$2"; shift;
-                       shift;;
+                       echo oarg is "'"$2"'"; oarg="$2"; shift 2;;
                \-\-)
                        shift; break;;
        esac
@@ -102,18 +101,13 @@
 Example changed in
 .Fx
 version 3.2 and 4.0.
+Modified by
+.An John Stalker.
 .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. People trying to fix
-.Nm
-or the example in this manpage should check the history of this file
-in
-.Fx .
 .Pp
 The error message for an invalid option is identified as coming
 from
@@ -121,7 +115,7 @@
 rather than from the shell procedure containing the invocation
 of
 .Nm ;
-this again is hard to fix.
+this is hard to fix.
 .Pp
 The precise best way to use the
 .Nm set
diff -Naur getopt.orig/getopt.c getopt.fix1/getopt.c
--- getopt.orig/getopt.c        Sun Feb 23 10:47:37 2003
+++ getopt.fix1/getopt.c        Sun Feb 23 09:56:22 2003
@@ -18,10 +18,18 @@
                        status = 1;     /* getopt routine gave message */
                        break;
                default:
-                       if (optarg != NULL)
-                               printf(" -%c %s", c, optarg);
-                       else
-                               printf(" -%c", c);
+                       printf(" -%c", c);
+                       if (optarg != NULL) { /* quote argument for shell */
+                               printf(" '");
+                               while (*optarg != '\0') {
+                                       if (optarg[0] == '\'')
+                                               printf("'\''");
+                                       else
+                                               printf("%c", optarg[0]);
+                                       optarg++;
+                               }
+                               printf("'");
+                       }
                        break;
                }
        printf(" --");

--
John Stalker
Department of Mathematics
Princeton University
(609)258-6469
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200302232052.h1NKqIG09316>