2 Copyright (C) 2009-2011 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* Written by Jim Meyering. */
28 #include <sys/types.h>
34 #define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
41 const char *user_name;
42 const char *group_name;
46 static struct test T[] =
48 { "", -1, -1, "", "", NULL},
49 { ":", -1, -1, "", "", NULL},
50 { "0:0", 0, 0, "", "", NULL},
51 { ":1", -1, 1, "", "", NULL},
52 { "1", 1, -1, "", "", NULL},
53 { ":+0", -1, 0, "", "", NULL},
54 { "22:42", 22, 42, "", "", NULL},
55 /* (uint32_t)-1 should be invalid everywhere */
56 { "4294967295:4294967295", 0, 0, NULL, NULL, "invalid user"},
57 /* likewise, but with only the group being invalid */
58 { "0:4294967295", 0, 0, NULL, NULL, "invalid group"},
59 { ":4294967295", 0, 0, NULL, NULL, "invalid group"},
60 /* and only the user being invalid */
61 { "4294967295:0", 0, 0, NULL, NULL, "invalid user"},
63 { "4294967296:4294967296", 0, 0, NULL, NULL, "invalid user"},
64 { "0:4294967296", 0, 0, NULL, NULL, "invalid group"},
65 { ":4294967296", 0, 0, NULL, NULL, "invalid group"},
66 { "4294967296:0", 0, 0, NULL, NULL, "invalid user"},
67 /* numeric user and no group is invalid */
68 { "4294967295:", 0, 0, NULL, NULL, "invalid spec"},
69 { "4294967296:", 0, 0, NULL, NULL, "invalid spec"},
70 { "1:", 0, 0, NULL, NULL, "invalid spec"},
71 { "+0:", 0, 0, NULL, NULL, "invalid spec"},
73 /* "username:" must expand to UID:GID where GID is username's login group */
74 /* Add an entry like the following to the table, if possible.
75 { "U_NAME:", UID,GID, U_NAME, G_NAME, NULL}, */
76 { NULL, 0, 0, NULL, NULL, ""}, /* place-holder */
78 { NULL, 0, 0, NULL, NULL, ""}
81 #define STREQ(a, b) (strcmp (a, b) == 0)
84 maybe_null (char const *s)
86 return s ? s : "NULL";
90 same_diag (char const *s, char const *t)
92 if (s == NULL && t == NULL)
94 if (s == NULL || t == NULL)
105 /* Find a UID that has both a user name and login group name,
109 for (uid = 1200; 0 < uid; uid--)
112 struct passwd *pw = getpwuid (uid);
115 if (!pw || !pw->pw_name || !(gr = getgrgid (pw->pw_gid)) || !gr->gr_name)
117 j = ARRAY_CARDINALITY (T) - 2;
118 assert (T[j].in == NULL);
119 assert (T[j+1].in == NULL);
120 len = strlen (pw->pw_name);
122 /* Store "username:" in T[j].in. */
124 char *t = xmalloc (len + 1 + 1);
125 memcpy (t, pw->pw_name, len);
132 T[j].gid = gr->gr_gid;
133 T[j].user_name = xstrdup (pw->pw_name);
134 T[j].group_name = xstrdup (gr->gr_name);
140 for (i = 0; T[i].in; i++)
142 uid_t uid = (uid_t) -1;
143 gid_t gid = (gid_t) -1;
146 char const *diag = parse_user_spec (T[i].in, &uid, &gid,
147 &user_name, &group_name);
150 if (!same_diag (diag, T[i].result))
152 printf ("%s return value mismatch: got %s, expected %s\n",
153 T[i].in, maybe_null (diag), maybe_null (T[i].result));
161 if (uid != T[i].uid || gid != T[i].gid)
163 printf ("%s mismatch (-: expected uid,gid; +:actual)\n"
164 "-%3lu,%3lu\n+%3lu,%3lu\n",
166 (unsigned long int) T[i].uid,
167 (unsigned long int) T[i].gid,
168 (unsigned long int) uid,
169 (unsigned long int) gid);
173 if (!diag && !T[i].result)
177 printf ("%s diagnostic mismatch (-: expected uid,gid; +:actual)\n"
179 T[i].in, T[i].result, diag);
189 indent-tabs-mode: nil