From owner-freebsd-standards@FreeBSD.ORG Wed Nov 3 21:10:41 2004 Return-Path: Delivered-To: freebsd-standards@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id A7C0B16A4FE for ; Wed, 3 Nov 2004 21:10:41 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 6C2E443D1F for ; Wed, 3 Nov 2004 21:10:33 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) iA3LAXNS052985 for ; Wed, 3 Nov 2004 21:10:33 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.11/8.12.11/Submit) id iA3LAXFv052984; Wed, 3 Nov 2004 21:10:33 GMT (envelope-from gnats) Resent-Date: Wed, 3 Nov 2004 21:10:33 GMT Resent-Message-Id: <200411032110.iA3LAXFv052984@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-standards@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Jilles Tjoelker Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E441716A4CE for ; Wed, 3 Nov 2004 21:02:30 +0000 (GMT) Received: from mailhost.stack.nl (vaak.stack.nl [131.155.140.140]) by mx1.FreeBSD.org (Postfix) with ESMTP id 29AEA43D6B for ; Wed, 3 Nov 2004 21:02:30 +0000 (GMT) (envelope-from jilles@stack.nl) Received: from hammer.stack.nl (hammer.stack.nl [IPv6:2001:610:1108:5010::153]) by mailhost.stack.nl (Postfix) with ESMTP id 3B88F1F066 for ; Wed, 3 Nov 2004 22:02:29 +0100 (CET) Received: by hammer.stack.nl (Postfix, from userid 1677) id 19704619F; Wed, 3 Nov 2004 22:02:29 +0100 (CET) Message-Id: <20041103210229.19704619F@hammer.stack.nl> Date: Wed, 3 Nov 2004 22:02:29 +0100 (CET) From: Jilles Tjoelker To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: standards/73500: 'set +o' in /bin/sh does not include unset options X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Jilles Tjoelker List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Nov 2004 21:10:41 -0000 >Number: 73500 >Category: standards >Synopsis: 'set +o' in /bin/sh does not include unset options >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-standards >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Nov 03 21:10:33 GMT 2004 >Closed-Date: >Last-Modified: >Originator: Jilles Tjoelker >Release: FreeBSD 6.0-CURRENT amd64 >Organization: MCGV Stack >Environment: System: FreeBSD hammer.stack.nl 6.0-CURRENT FreeBSD 6.0-CURRENT #3: Mon Nov 1 18:36:46 CET 2004 marcolz@hammer.stack.nl:/usr/obj/usr/src/sys/HAMMER amd64 >Description: The output of 'set +o' only contains options that are set, not options that are unset. IEEE Std 1003.1-2001 says: +o Write the current option settings to standard output in a format that is suitable for reinput to the shell as commands that achieve the same options settings. Obviously, the current implementation does not achieve that. The man page says this which might be interpreted both ways: If +o is used without an argument, the current option settings are output in a format suitable for re-input into the shell. >How-To-Repeat: jilles@hammer /home/jilles$ /bin/sh $ set +o set -o interactive -o monitor -o stdin $ A more complicated real-world-like demonstration is the following shell script: #!/bin/sh settings="$(set +o)" set -o noglob eval "$settings" echo /* It outputs '/*' with the current version of /bin/sh. The script works correctly (shows all files directly under /) with bash-2.05b.007_2 and Solaris 10 /usr/xpg4/bin/sh. >Fix: Include unset options with '+o' in the output of 'set +o'. Patch included. --- options.c.diff begins here --- --- src/bin/sh/options.c.orig Wed Apr 7 10:12:45 2004 +++ src/bin/sh/options.c Wed Nov 3 18:42:45 2004 @@ -196,7 +196,7 @@ STATIC void minus_o(char *name, int val) { - int doneset, i; + int i; if (name == NULL) { if (val) { @@ -207,16 +207,11 @@ optlist[i].val ? "on" : "off"); } else { /* Output suitable for re-input to shell. */ - for (doneset = i = 0; i < NOPTS; i++) - if (optlist[i].val) { - if (!doneset) { - out1str("set"); - doneset = 1; - } - out1fmt(" -o %s", optlist[i].name); - } - if (doneset) - out1c('\n'); + out1str("set"); + for (i = 0; i < NOPTS; i++) + out1fmt(" %co %s", optlist[i].val ? '-' : '+', + optlist[i].name); + out1c('\n'); } } else { for (i = 0; i < NOPTS; i++) --- options.c.diff ends here --- >Release-Note: >Audit-Trail: >Unformatted: