# id -Gn
# id -a
# Beware 1: some systems do just 'id -G' even when 'id -Gn' is used.
-# Beware 2: the 'id -a' output format is tricky.
+# Beware 2: id -Gn or id -a format might be id(name) or name(id).
+# Beware 3: the groups= might be anywhere in the id output.
+#
+# That is, we might meet the following:
+#
+# foo bar zot # accept
+# 1 2 3 # reject
+# groups=foo(1),bar(2),zot(3) # parse
+# groups=1(foo),2(bar),3(zot) # parse
+#
+# and the groups= might be after, before, or between uid=... and gid=...
GROUPS: {
last GROUPS if ($groups = `groups 2>/dev/null`) ne '';
last GROUPS unless $groups =~ /^(\d+)(\s+\d)*$/;
}
if ($groups = `id -a 2>/dev/null` ne '') {
- if (/groups=/g && (@g = /\((.+?)\)/g)) {
- $groups = join(" ", @g);
- last GROUPS;
- }
+ # Grok format soon.
+ last GROUPS;
}
# Okay, not today.
print "1..0\n";
exit 0;
}
+# Remember that group names can contain whitespace, '-', et cetera.
+# That is: do not \w, do not \S.
+if ($groups =~ /groups=((.+?\(.+?\))(,.+?\(.+?\))*)( [ug]id=|$)/) {
+ my $gr = $1;
+ my @g0 = $gr =~ /(.+?)\((.+?)\),?/g;
+ my @g1 = @g0[ map { $_ * 2 } 0..$#g0/2 ];
+ my @g2 = @g0[ map { $_ * 2 + 1 } 0..$#g0/2 ];
+ print "# g0 = @g0\n";
+ print "# g1 = @g1\n";
+ print "# g2 = @g2\n";
+ if (grep /\D/, @g1) {
+ $groups = join(" ", @g1);
+ } elsif (grep /\D/, @g2) {
+ $groups = join(" ", @g2);
+ } else {
+ # Let's fail. We want to parse the output. Really.
+ }
+}
+
print "1..2\n";
$pwgid = $( + 0;