Hi,
I'd like to propose a patch based on http://lists.gnu.org/archive/html/bug-coreutils/2011-11/msg00024.html . The -{0,1} option is only enabled for some option combinations (as discussed in above link) although I have some doubts about the usefulness of groups -0|-1 without any other arguments; on the other hand, changing the delims for the "USERNAME_1: group_1...group_n" output is IMHO very weird. However, maybe we could only print the "USERNAME: " part if more than one username is specified as an argument.
Or does "id USERNAME -Gn" suffice in this case? What do you think?

Thanks,
Ondrej.
>From 532665192de973c019fff1c0a8f46da89198abdd Mon Sep 17 00:00:00 2001
From: Ondrej Oprala <[email protected]>
Date: Tue, 28 May 2013 10:34:21 +0200
Subject: [PATCH] id,groups: allow to change output delimiters

* NEWS (New features): Mention the new options.
* doc/coreutils.texi: Likewise.
* src/group-list.h (print_group_list): Add another argument.
* src/group-list.c (print_group_list): Output delim argument instead
of default space.
* src/groups.c (main): Add new options.
* src/id.c (main): Add new option.
---
 NEWS               |  4 ++++
 doc/coreutils.texi | 19 ++++++++++++++++---
 src/group-list.c   |  6 +++---
 src/group-list.h   |  2 +-
 src/groups.c       | 23 ++++++++++++++++++++---
 src/id.c           | 15 +++++++++++++--
 6 files changed, 57 insertions(+), 12 deletions(-)

diff --git a/NEWS b/NEWS
index 721e05b..23ccf4c 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,10 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 ** New features
 
+  id and groups now accept the -1 option to list each entry on a separate
+  line. Additionally, groups now accepts the -0 option to delimit entries
+  with a null character.
+
   id -Z reports the SMACK security context where available.
 
   join accepts a new option: --zero-terminated (-z). As with the sort,uniq
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index d607eaf..2781b14 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -14451,6 +14451,10 @@ Print only the security context of the current user.
 If SELinux is disabled then print a warning and
 set the exit status to 1.
 
+@item -1
+@opindex -1
+List one group per line.
+
 @end table
 
 @exitstatus
@@ -14517,15 +14521,24 @@ the list of that user's groups and the user name is separated from the
 group list by a colon.  Synopsis:
 
 @example
-groups [@var{username}]@dots{}
+groups [@var{username} | -0 | -1 ]@dots{}
 @end example
 
 The group lists are equivalent to the output of the command @samp{id -Gn}.
 
 @primaryAndSupplementaryGroups{groups,list of users}
 
-The only options are @option{--help} and @option{--version}.  @xref{Common
-options}.
+The program accepts the following options:
+
+@table @samp
+@item -0
+@opindex -0
+Delimit groups with the null character.
+
+@item -1
+@opindex -1
+List one group per line.
+@end table
 
 @exitstatus
 
diff --git a/src/group-list.c b/src/group-list.c
index 7d4995b..d54b057 100644
--- a/src/group-list.c
+++ b/src/group-list.c
@@ -35,7 +35,7 @@
 extern bool
 print_group_list (const char *username,
                   uid_t ruid, gid_t rgid, gid_t egid,
-                  bool use_names)
+                  bool use_names, char delim)
 {
   bool ok = true;
   struct passwd *pwd = NULL;
@@ -52,7 +52,7 @@ print_group_list (const char *username,
 
   if (egid != rgid)
     {
-      putchar (' ');
+      putchar (delim);
       if (!print_group (egid, use_names))
         ok = false;
     }
@@ -79,7 +79,7 @@ print_group_list (const char *username,
     for (i = 0; i < n_groups; i++)
       if (groups[i] != rgid && groups[i] != egid)
         {
-          putchar (' ');
+          putchar (delim);
           if (!print_group (groups[i], use_names))
             ok = false;
         }
diff --git a/src/group-list.h b/src/group-list.h
index 3fac887..573de1d 100644
--- a/src/group-list.h
+++ b/src/group-list.h
@@ -16,4 +16,4 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 bool print_group (gid_t, bool);
-bool print_group_list (const char *, uid_t, gid_t, gid_t, bool);
+bool print_group_list (const char *, uid_t, gid_t, gid_t, bool, char);
diff --git a/src/groups.c b/src/groups.c
index 53332d5..8f5a714 100644
--- a/src/groups.c
+++ b/src/groups.c
@@ -68,6 +68,9 @@ main (int argc, char **argv)
 {
   int optc;
   bool ok = true;
+  bool one_per_line = false;
+  bool nullterm = false;
+  char delim = ' ';
   gid_t rgid, egid;
   uid_t ruid;
 
@@ -82,10 +85,18 @@ main (int argc, char **argv)
   /* Processing the arguments this way makes groups.c behave differently to
    * groups.sh if one of the arguments is "--".
    */
-  while ((optc = getopt_long (argc, argv, "", longopts, NULL)) != -1)
+  while ((optc = getopt_long (argc, argv, "01", longopts, NULL)) != -1)
     {
       switch (optc)
         {
+        case '0':
+          delim = '\0';
+          nullterm = true;
+          break;
+        case '1':
+          delim = '\n';
+          one_per_line = true;
+          break;
         case_GETOPT_HELP_CHAR;
         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
         default:
@@ -93,6 +104,9 @@ main (int argc, char **argv)
         }
     }
 
+  if (nullterm && one_per_line)
+    error (EXIT_FAILURE, 0, _("only one delimiter may be specified"));
+
   if (optind == argc)
     {
       /* No arguments.  Divulge the details of the current process. */
@@ -114,12 +128,15 @@ main (int argc, char **argv)
       if (rgid == NO_GID && errno)
         error (EXIT_FAILURE, errno, _("cannot get real GID"));
 
-      if (!print_group_list (NULL, ruid, rgid, egid, true))
+      if (!print_group_list (NULL, ruid, rgid, egid, true, delim))
         ok = false;
       putchar ('\n');
     }
   else
     {
+      if (nullterm || one_per_line)
+        error (EXIT_FAILURE, 0, _("delimiter modififers cannot be "
+                                     "combined with other arguments"));
       /* At least one argument.  Divulge the details of the specified users. */
       while (optind < argc)
         {
@@ -130,7 +147,7 @@ main (int argc, char **argv)
           rgid = egid = pwd->pw_gid;
 
           printf ("%s : ", argv[optind]);
-          if (!print_group_list (argv[optind++], ruid, rgid, egid, true))
+          if (!print_group_list (argv[optind++], ruid, rgid, egid, true, delim))
             ok = false;
           putchar ('\n');
         }
diff --git a/src/id.c b/src/id.c
index 937b723..85745e6 100644
--- a/src/id.c
+++ b/src/id.c
@@ -113,6 +113,8 @@ main (int argc, char **argv)
 #ifdef HAVE_SMACK
   int smack_enabled = (smack_smackfs_path () != NULL);
 #endif
+  char delim = ' ';
+  bool one_per_line = false;
 
   /* If true, output the list of all group IDs. -G */
   bool just_group_list = false;
@@ -123,6 +125,7 @@ main (int argc, char **argv)
   /* If true, output only the user ID(s). -u */
   bool just_user = false;
 
+
   initialize_main (&argc, &argv);
   set_program_name (argv[0]);
   setlocale (LC_ALL, "");
@@ -131,7 +134,7 @@ main (int argc, char **argv)
 
   atexit (close_stdout);
 
-  while ((optc = getopt_long (argc, argv, "agnruGZ", longopts, NULL)) != -1)
+  while ((optc = getopt_long (argc, argv, "agnruGZ1", longopts, NULL)) != -1)
     {
       switch (optc)
         {
@@ -169,6 +172,10 @@ main (int argc, char **argv)
         case 'G':
           just_group_list = true;
           break;
+        case '1':
+          delim = '\n';
+          one_per_line = true;
+          break;
         case_GETOPT_HELP_CHAR;
         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
         default:
@@ -183,6 +190,10 @@ main (int argc, char **argv)
       usage (EXIT_FAILURE);
     }
 
+  if (one_per_line && !(just_group_list))
+    error (EXIT_FAILURE, 0, _("delimiter may only be changed if the -G option "
+                              "is specified"));
+
   if (n_ids && just_context)
     error (EXIT_FAILURE, 0,
            _("cannot print security context when user specified"));
@@ -274,7 +285,7 @@ main (int argc, char **argv)
     }
   else if (just_group_list)
     {
-      if (!print_group_list (argv[optind], ruid, rgid, egid, use_name))
+      if (!print_group_list (argv[optind], ruid, rgid, egid, use_name, delim))
         ok = false;
     }
   else if (just_context)
-- 
1.7.11.7

Reply via email to