This source file includes following definitions.
- is_number
- parse_with_separator
- parse_user_spec
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22
23 #include "userspec.h"
24
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <pwd.h>
29 #include <grp.h>
30
31 #if HAVE_SYS_PARAM_H
32 # include <sys/param.h>
33 #endif
34
35 #include <limits.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include <unistd.h>
40
41 #include "intprops.h"
42 #include "inttostr.h"
43 #include "xalloc.h"
44 #include "xstrtol.h"
45
46 #include "gettext.h"
47 #define _(msgid) gettext (msgid)
48 #define N_(msgid) msgid
49
50 #ifndef HAVE_ENDGRENT
51 # define endgrent() ((void) 0)
52 #endif
53
54 #ifndef HAVE_ENDPWENT
55 # define endpwent() ((void) 0)
56 #endif
57
58 #ifndef UID_T_MAX
59 # define UID_T_MAX TYPE_MAXIMUM (uid_t)
60 #endif
61
62 #ifndef GID_T_MAX
63 # define GID_T_MAX TYPE_MAXIMUM (gid_t)
64 #endif
65
66
67 #ifndef MAXUID
68 # define MAXUID UID_T_MAX
69 #endif
70 #ifndef MAXGID
71 # define MAXGID GID_T_MAX
72 #endif
73
74 #ifdef __DJGPP__
75
76
77
78
79
80
81
82
83 # define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
84
85
86
87 static bool
88 is_number (const char *str)
89 {
90 do
91 {
92 if (!ISDIGIT (*str))
93 return false;
94 }
95 while (*++str);
96
97 return true;
98 }
99 #endif
100
101 static char const *
102 parse_with_separator (char const *spec, char const *separator,
103 uid_t *uid, gid_t *gid,
104 char **username, char **groupname)
105 {
106 static const char *E_invalid_user = N_("invalid user");
107 static const char *E_invalid_group = N_("invalid group");
108 static const char *E_bad_spec = N_("invalid spec");
109
110 const char *error_msg;
111 struct passwd *pwd;
112 struct group *grp;
113 char *u;
114 char const *g;
115 char *gname = NULL;
116 uid_t unum = *uid;
117 gid_t gnum = gid ? *gid : -1;
118
119 error_msg = NULL;
120 if (username)
121 *username = NULL;
122 if (groupname)
123 *groupname = NULL;
124
125
126
127
128
129 u = NULL;
130 if (separator == NULL)
131 {
132 if (*spec)
133 u = xstrdup (spec);
134 }
135 else
136 {
137 idx_t ulen = separator - spec;
138 if (ulen != 0)
139 {
140 u = ximemdup (spec, ulen + 1);
141 u[ulen] = '\0';
142 }
143 }
144
145 g = (separator == NULL || *(separator + 1) == '\0'
146 ? NULL
147 : separator + 1);
148
149 #ifdef __DJGPP__
150
151
152 if (u && !is_number (u))
153 setenv ("USER", u, 1);
154 if (g && !is_number (g))
155 setenv ("GROUP", g, 1);
156 #endif
157
158 if (u != NULL)
159 {
160
161 pwd = (*u == '+' ? NULL : getpwnam (u));
162 if (pwd == NULL)
163 {
164 bool use_login_group = (separator != NULL && g == NULL);
165 if (use_login_group)
166 {
167
168
169 error_msg = E_bad_spec;
170 }
171 else
172 {
173 unsigned long int tmp;
174 if (xstrtoul (u, NULL, 10, &tmp, "") == LONGINT_OK
175 && tmp <= MAXUID && (uid_t) tmp != (uid_t) -1)
176 unum = tmp;
177 else
178 error_msg = E_invalid_user;
179 }
180 }
181 else
182 {
183 unum = pwd->pw_uid;
184 if (g == NULL && separator != NULL)
185 {
186
187
188 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
189 gnum = pwd->pw_gid;
190 grp = getgrgid (gnum);
191 gname = xstrdup (grp ? grp->gr_name : umaxtostr (gnum, buf));
192 endgrent ();
193 }
194 }
195 endpwent ();
196 }
197
198 if (g != NULL && error_msg == NULL)
199 {
200
201
202 grp = (*g == '+' ? NULL : getgrnam (g));
203 if (grp == NULL)
204 {
205 unsigned long int tmp;
206 if (xstrtoul (g, NULL, 10, &tmp, "") == LONGINT_OK
207 && tmp <= MAXGID && (gid_t) tmp != (gid_t) -1)
208 gnum = tmp;
209 else
210 error_msg = E_invalid_group;
211 }
212 else
213 gnum = grp->gr_gid;
214 endgrent ();
215 gname = xstrdup (g);
216 }
217
218 if (error_msg == NULL)
219 {
220 *uid = unum;
221 if (gid)
222 *gid = gnum;
223 if (username)
224 {
225 *username = u;
226 u = NULL;
227 }
228 if (groupname)
229 {
230 *groupname = gname;
231 gname = NULL;
232 }
233 }
234
235 free (u);
236 free (gname);
237 return error_msg ? _(error_msg) : NULL;
238 }
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258 char const *
259 parse_user_spec (char const *spec, uid_t *uid, gid_t *gid,
260 char **username, char **groupname)
261 {
262 char const *colon = gid ? strchr (spec, ':') : NULL;
263 char const *error_msg =
264 parse_with_separator (spec, colon, uid, gid, username, groupname);
265
266 if (gid && !colon && error_msg)
267 {
268
269
270
271
272
273
274 char const *dot = strchr (spec, '.');
275 if (dot
276 && ! parse_with_separator (spec, dot, uid, gid, username, groupname))
277 error_msg = NULL;
278 }
279
280 return error_msg;
281 }
282
283 #ifdef TEST
284
285 # define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s))
286
287 int
288 main (int argc, char **argv)
289 {
290 int i;
291
292 for (i = 1; i < argc; i++)
293 {
294 const char *e;
295 char *username, *groupname;
296 uid_t uid;
297 gid_t gid;
298 char *tmp;
299
300 tmp = strdup (argv[i]);
301 e = parse_user_spec (tmp, &uid, &gid, &username, &groupname);
302 free (tmp);
303 printf ("%s: %lu %lu %s %s %s\n",
304 argv[i],
305 (unsigned long int) uid,
306 (unsigned long int) gid,
307 NULL_CHECK (username),
308 NULL_CHECK (groupname),
309 NULL_CHECK (e));
310 }
311
312 exit (0);
313 }
314
315 #endif
316
317
318
319
320
321