From owner-freebsd-bugs Sun Feb 23 13: 0:27 2003 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 7778C37B401 for ; Sun, 23 Feb 2003 13:00:22 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 0BA2F43F93 for ; Sun, 23 Feb 2003 13:00:21 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.6/8.12.6) with ESMTP id h1NL0KNS098877 for ; Sun, 23 Feb 2003 13:00:20 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.6/8.12.6/Submit) id h1NL0K5w098876; Sun, 23 Feb 2003 13:00:20 -0800 (PST) Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5430537B405 for ; Sun, 23 Feb 2003 12:52:21 -0800 (PST) Received: from Mail.Math.Princeton.EDU (mail.math.Princeton.EDU [128.112.18.14]) by mx1.FreeBSD.org (Postfix) with ESMTP id A80EE43FE0 for ; Sun, 23 Feb 2003 12:52:19 -0800 (PST) (envelope-from stalker@Math.Princeton.EDU) Received: from math.Princeton.EDU (IDENT:B/s5t5lFRCdod1N1IbJfAgLA2/cpxRdl@math.Princeton.EDU [128.112.18.16]) by Mail.Math.Princeton.EDU (8.11.6/8.11.6) with ESMTP id h1NKqI107343 for ; Sun, 23 Feb 2003 15:52:18 -0500 Received: from math.Princeton.EDU (IDENT:U36bl+bL7eypouQB3wzbkMaH1sgaSBFe@localhost.localdomain [127.0.0.1]) by math.Princeton.EDU (8.11.6/8.11.6) with ESMTP id h1NKqIG09316 for ; Sun, 23 Feb 2003 15:52:18 -0500 Message-Id: <200302232052.h1NKqIG09316@math.Princeton.EDU> Date: Sun, 23 Feb 2003 15:52:18 -0500 From: John Stalker To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: bin/48603: Getopt(1) is broken. Patch included. Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >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