[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC] {print,}env -0
From: |
Eric Blake |
Subject: |
Re: [RFC] {print,}env -0 |
Date: |
Tue, 27 Oct 2009 06:39:46 -0600 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.23) Gecko/20090812 Thunderbird/2.0.0.23 Mnenhy/0.7.6.666 |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
According to Jim Meyering on 10/27/2009 1:39 AM:
>>>>> env -0/--null
>>>>> printenv -0/--null
>>>>>
>>>>> as a means of unambiguously representing the current contents of the
>>>>> environment with NUL terminators instead of newlines?
> Yes, now I'm in favor of this, too.
This patch implements the option; I'm still working on developing a test
(comparing binary output takes a bit more effort) before I will commit
anything, but thought I'd at least get the review started.
- --
Don't work too hard, make some time for fun as well!
Eric Blake address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAkrm6hIACgkQ84KuGfSFAYCtXACgw4el/QauE6MpIR3tqmExTxLX
NfQAoNbWY57yRVCSmnMSWCDMm8tMitSl
=dSbs
-----END PGP SIGNATURE-----
From 128acc9e68bb1ac44efdb559f7751079f8d76ab8 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Mon, 26 Oct 2009 22:21:22 -0600
Subject: [PATCH 1/2] tests: add printenv coverage
* tests/misc/printenv: New test.
* tests/Makefile.am (TESTS): Run it.
* .gitignore: Ignore more cruft.
---
.gitignore | 1 +
tests/Makefile.am | 1 +
tests/misc/printenv | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 76 insertions(+), 0 deletions(-)
create mode 100755 tests/misc/printenv
diff --git a/.gitignore b/.gitignore
index 3ae9bf0..a284154 100644
--- a/.gitignore
+++ b/.gitignore
@@ -74,4 +74,5 @@ src/version.c
src/version.h
stamp-h1
tests/*/*.log
+tests/t?
tests/test-suite.log
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 03fe6f1..731f657 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -192,6 +192,7 @@ TESTS = \
misc/od-x8 \
misc/paste \
misc/pathchk1 \
+ misc/printenv \
misc/printf \
misc/printf-cov \
misc/printf-hex \
diff --git a/tests/misc/printenv b/tests/misc/printenv
new file mode 100755
index 0000000..0edb39e
--- /dev/null
+++ b/tests/misc/printenv
@@ -0,0 +1,74 @@
+#!/bin/sh
+# Verify behavior of printenv.
+
+# Copyright (C) 2009 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+prog="$abs_top_builddir/src/printenv"
+
+if test "$VERBOSE" = yes; then
+ set -x
+ "$prog" --version
+fi
+
+. $srcdir/test-lib.sh
+
+fail=0
+
+# Without arguments, printenv behaves like env. Some shells provide
+# printenv as a builtin, so we must test via absolute name.
+# But beware of $_, set by many shells to the last command run.
+env | grep -v '^_' > exp || framework_failure
+"$prog" | grep -v '^_' > out || fail=1
+compare exp out || fail=1
+
+# POSIX is clear that environ may, but need not be, sorted.
+# Environment variable values may contain newlines, which cannot be
+# observed by merely inspecting output from printenv.
+if "$prog" | grep '^ENV_TEST' >/dev/null ; then
+ skip_test_ "environment has potential interference from ENV_TEST*"
+fi
+
+# Printing a single variable's value.
+"$prog" ENV_TEST > out
+test $? = 1 || fail=1
+test -s out && fail=1
+echo a > exp || framework_failure
+ENV_TEST=a "$prog" ENV_TEST > out || fail=1
+compare exp out || fail=1
+
+# Printing multiple variables. Order follows command line.
+ENV_TEST1=a ENV_TEST2=b "$prog" ENV_TEST2 ENV_TEST1 > out || fail=1
+ENV_TEST1=a ENV_TEST2=b "$prog" ENV_TEST1 ENV_TEST2 >> out || fail=1
+cat <<EOF > exp || framework_failure
+b
+a
+a
+b
+EOF
+compare exp out || fail=1
+
+# Exit status reflects missing variable, but remaining arguments processed.
+ENV_TEST1=a "$prog" ENV_TEST2 ENV_TEST1 > out
+test $? = 1 || fail=1
+ENV_TEST1=a "$prog" ENV_TEST1 ENV_TEST2 >> out
+test $? = 1 || fail=1
+cat <<EOF > exp || framework_failure
+a
+a
+EOF
+compare exp out || fail=1
+
+Exit $fail
--
1.6.5.rc1
From ad7db2a0877eac5bc4195bb4add9145746c87d37 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Tue, 27 Oct 2009 06:36:40 -0600
Subject: [PATCH 2/2] env, printenv: add -0/--null option
* src/env.c (longopts): Add new option.
(usage): Document it.
(main): Implement it.
* src/printenv.c (longopts): New variable.
(usage): Document new option.
(main): Implement it.
* doc/coreutils.texi (Common options): New macro optNull.
(du invocation, env invocation, printenv invocation): Use it.
* NEWS: Mention this.
---
NEWS | 3 +++
doc/coreutils.texi | 33 ++++++++++++++++++++++-----------
src/env.c | 27 ++++++++++++++++++++++-----
src/printenv.c | 38 ++++++++++++++++++++++++++++++--------
4 files changed, 77 insertions(+), 24 deletions(-)
diff --git a/NEWS b/NEWS
index abbeb27..442ce13 100644
--- a/NEWS
+++ b/NEWS
@@ -44,6 +44,9 @@ GNU coreutils NEWS -*-
outline -*-
** New features
+ env and printenv now accept the option --null (-0), as a means to
+ avoid ambiguity with newlines embedded in the environment.
+
md5sum --check now also accepts openssl-style checksums.
So do sha1sum, sha224sum, sha384sum and sha512sum.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 138cf01..e5d0120 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -574,6 +574,18 @@ Common options
symbolic link to a directory. @xref{Target directory}.
@end macro
address@hidden optNull{cmd}
address@hidden -0
address@hidden -0
address@hidden --null
address@hidden --null
address@hidden output null-byte-terminated lines
+Output a zero byte (@acronym{ASCII} @sc{nul}) at the end of each line,
+rather than a newline. This option enables other programs to parse the
+output of @command{\cmd\} even when that output would contain data
+with embedded newlines.
address@hidden macro
+
@macro optSi
@itemx --si
@opindex --si
@@ -10376,15 +10388,7 @@ du invocation
most MAX_DEPTH levels down from the root of the hierarchy. The root
is at level 0, so @code{du --max-depth=0} is equivalent to @code{du -s}.
address@hidden -0
address@hidden -0
address@hidden --null
address@hidden --null
address@hidden output null-byte-terminated lines
-Output a zero byte (@acronym{ASCII} @sc{nul}) at the end of each line,
-rather than a newline. This option enables other programs to parse the
-output of @command{du} even when that output would contain file names
-with embedded newlines.
address@hidden
@optSi
@@ -12806,8 +12810,13 @@ printenv invocation
every environment variable. Otherwise, it prints the value of each
@var{variable} that is set, and nothing for those that are not set.
-The only options are a lone @option{--help} or @option{--version}.
address@hidden options}.
+The program accepts the following option. Also see @ref{Common options}.
+
address@hidden @samp
+
address@hidden
+
address@hidden table
@cindex exit status of @command{printenv}
Exit status:
@@ -14438,6 +14447,8 @@ env invocation
@table @samp
address@hidden
+
@item -u @var{name}
@itemx address@hidden
@opindex -u
diff --git a/src/env.c b/src/env.c
index 8d7d55e..778129b 100644
--- a/src/env.c
+++ b/src/env.c
@@ -29,6 +29,11 @@
Unset variable VARIABLE (remove it from the environment).
If VARIABLE was not set, does nothing.
+ -0
+ --null
+ When no program is specified, output environment information
+ separated by nul bytes rather than newlines.
+
variable=value (an arg containing a "=" character)
Set the environment variable VARIABLE to value VALUE. VALUE
may be of zero length ("variable="). Setting a variable to a
@@ -96,6 +101,7 @@
static struct option const longopts[] =
{
{"ignore-environment", no_argument, NULL, 'i'},
+ {"null", no_argument, NULL, '0'},
{"unset", required_argument, NULL, 'u'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
@@ -116,8 +122,9 @@ Usage: %s [OPTION]... [-] [NAME=VALUE]... [COMMAND
[ARG]...]\n"),
fputs (_("\
Set each NAME to VALUE in the environment and run COMMAND.\n\
\n\
- -i, --ignore-environment start with an empty environment\n\
- -u, --unset=NAME remove variable from the environment\n\
+ -i, --ignore-environment start with an empty environment\n\
+ -0, --null end each output line with 0 byte rather than newline\n\
+ -u, --unset=NAME remove variable from the environment\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -135,6 +142,7 @@ main (int argc, char **argv)
{
int optc;
bool ignore_environment = false;
+ bool opt_nul_terminate_output = false;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@@ -145,7 +153,7 @@ main (int argc, char **argv)
initialize_exit_failure (EXIT_CANCELED);
atexit (close_stdout);
- while ((optc = getopt_long (argc, argv, "+iu:", longopts, NULL)) != -1)
+ while ((optc = getopt_long (argc, argv, "+iu:0", longopts, NULL)) != -1)
{
switch (optc)
{
@@ -154,6 +162,9 @@ main (int argc, char **argv)
break;
case 'u':
break;
+ case '0':
+ opt_nul_terminate_output = true;
+ break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -171,7 +182,7 @@ main (int argc, char **argv)
}
optind = 0; /* Force GNU getopt to re-initialize. */
- while ((optc = getopt_long (argc, argv, "+iu:", longopts, NULL)) != -1)
+ while ((optc = getopt_long (argc, argv, "+iu:0", longopts, NULL)) != -1)
if (optc == 'u' && unsetenv (optarg))
error (EXIT_CANCELED, errno, _("cannot unset %s"), quote (optarg));
@@ -191,10 +202,16 @@ main (int argc, char **argv)
{
char *const *e = environ;
while (*e)
- puts (*e++);
+ printf ("%s%c", *e++, opt_nul_terminate_output ? '\0' : '\n');
exit (EXIT_SUCCESS);
}
+ if (opt_nul_terminate_output)
+ {
+ error (0, errno, _("cannot specify --null (-0) with command"));
+ usage (EXIT_CANCELED);
+ }
+
execvp (argv[optind], &argv[optind]);
{
diff --git a/src/printenv.c b/src/printenv.c
index dcdcb83..516b646 100644
--- a/src/printenv.c
+++ b/src/printenv.c
@@ -45,6 +45,14 @@ enum { PRINTENV_FAILURE = 2 };
proper_name ("David MacKenzie"), \
proper_name ("Richard Mlynarik")
+static struct option const longopts[] =
+{
+ {"null", no_argument, NULL, '0'},
+ {GETOPT_HELP_OPTION_DECL},
+ {GETOPT_VERSION_OPTION_DECL},
+ {NULL, 0, NULL, 0}
+};
+
void
usage (int status)
{
@@ -54,13 +62,15 @@ usage (int status)
else
{
printf (_("\
-Usage: %s [VARIABLE]...\n\
- or: %s OPTION\n\
+Usage: %s [OPTION]... [VARIABLE]...\n\
Print the values of the specified environment VARIABLE(s).\n\
If no VARIABLE is specified, print name and value pairs for them all.\n\
\n\
"),
program_name, program_name);
+ fputs (_("\
+ -0, --null end each output line with 0 byte rather than newline\n\
+"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
@@ -76,6 +86,8 @@ main (int argc, char **argv)
char *ep, *ap;
int i;
bool ok;
+ int optc;
+ bool opt_nul_terminate_output = false;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@@ -86,15 +98,24 @@ main (int argc, char **argv)
initialize_exit_failure (PRINTENV_FAILURE);
atexit (close_stdout);
- parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
- usage, AUTHORS, (char const *) NULL);
- if (getopt_long (argc, argv, "+", NULL, NULL) != -1)
- usage (PRINTENV_FAILURE);
+ while ((optc = getopt_long (argc, argv, "+iu:0", longopts, NULL)) != -1)
+ {
+ switch (optc)
+ {
+ case '0':
+ opt_nul_terminate_output = true;
+ break;
+ case_GETOPT_HELP_CHAR;
+ case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
+ default:
+ usage (PRINTENV_FAILURE);
+ }
+ }
if (optind >= argc)
{
for (env = environ; *env != NULL; ++env)
- puts (*env);
+ printf ("%s%c", *env, opt_nul_terminate_output ? '\0' : '\n');
ok = true;
}
else
@@ -113,7 +134,8 @@ main (int argc, char **argv)
{
if (*ep == '=' && *ap == '\0')
{
- puts (ep + 1);
+ printf ("%s%c", ep + 1,
+ opt_nul_terminate_output ? '\0' : '\n');
matched = true;
break;
}
--
1.6.5.rc1
- [RFC] {print,}env -0, Eric Blake, 2009/10/26
- Re: [RFC] {print,}env -0, Pádraig Brady, 2009/10/26
- Re: [RFC] {print,}env -0, Jim Meyering, 2009/10/26
- Re: [RFC] {print,}env -0, Bauke Jan Douma, 2009/10/26
- Re: [RFC] {print,}env -0, Jim Meyering, 2009/10/27
- Re: [RFC] {print,}env -0,
Eric Blake <=
- Re: [RFC] {print,}env -0, Pádraig Brady, 2009/10/27
- Re: [RFC] {print,}env -0, Jim Meyering, 2009/10/27
- Re: [RFC] {print,}env -0, Eric Blake, 2009/10/27
- Re: [RFC] {print,}env -0, Pádraig Brady, 2009/10/28
- Re: [RFC] {print,}env -0, Jim Meyering, 2009/10/28
- Re: [RFC] {print,}env -0, Eric Blake, 2009/10/28
- Re: [RFC] {print,}env -0, Jim Meyering, 2009/10/28