Mercurial > hg > octave-nkf > gnulib-hg
annotate lib/userspec.c @ 2272:9d6da67904b5
add FIXME comments for use of atoi
author | Jim Meyering <jim@meyering.net> |
---|---|
date | Sat, 12 Feb 2000 10:11:54 +0000 |
parents | 78563cb66dc8 |
children | ad48a40e44bb |
rev | line source |
---|---|
5 | 1 /* userspec.c -- Parse a user and group string. |
2271 | 2 Copyright (C) 1989-1992, 1997, 1998, 2000 Free Software Foundation, Inc. |
5 | 3 |
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 2, or (at your option) | |
7 any later version. | |
8 | |
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. | |
13 | |
14 You should have received a copy of the GNU General Public License | |
650
b4ef1c1a0171
update FSF address in copyright
Jim Meyering <jim@meyering.net>
parents:
499
diff
changeset
|
15 along with this program; if not, write to the Free Software Foundation, |
b4ef1c1a0171
update FSF address in copyright
Jim Meyering <jim@meyering.net>
parents:
499
diff
changeset
|
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
5 | 17 |
18 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ | |
966 | 19 |
20 #if HAVE_CONFIG_H | |
21 # include <config.h> | |
105 | 22 #endif |
23 | |
231 | 24 #ifdef __GNUC__ |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
25 # define alloca __builtin_alloca |
231 | 26 #else |
1278
9ad625a30b7d
Use #if, not #ifdef with HAVE_ macros
Jim Meyering <jim@meyering.net>
parents:
1260
diff
changeset
|
27 # if HAVE_ALLOCA_H |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
28 # include <alloca.h> |
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
29 # else |
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
30 # ifdef _AIX |
966 | 31 # pragma alloca |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
32 # else |
231 | 33 char *alloca (); |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
34 # endif |
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
35 # endif |
231 | 36 #endif |
230 | 37 |
5 | 38 #include <stdio.h> |
39 #include <sys/types.h> | |
40 #include <pwd.h> | |
41 #include <grp.h> | |
42 | |
966 | 43 #if HAVE_STRING_H |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
44 # include <string.h> |
5 | 45 #else |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
46 # include <strings.h> |
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
47 # ifndef strchr |
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
48 # define strchr index |
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
49 # endif |
5 | 50 #endif |
51 | |
966 | 52 #if STDC_HEADERS |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
53 # include <stdlib.h> |
5 | 54 #endif |
55 | |
966 | 56 #if HAVE_UNISTD_H |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
57 # include <unistd.h> |
5 | 58 #endif |
59 | |
60 #ifndef _POSIX_VERSION | |
61 struct passwd *getpwnam (); | |
62 struct group *getgrnam (); | |
63 struct group *getgrgid (); | |
64 #endif | |
65 | |
499
62aa0b766a11
[HAVE_ENDGRENT]: Define away endgrent.
Jim Meyering <jim@meyering.net>
parents:
475
diff
changeset
|
66 #ifndef HAVE_ENDGRENT |
62aa0b766a11
[HAVE_ENDGRENT]: Define away endgrent.
Jim Meyering <jim@meyering.net>
parents:
475
diff
changeset
|
67 # define endgrent() ((void) 0) |
62aa0b766a11
[HAVE_ENDGRENT]: Define away endgrent.
Jim Meyering <jim@meyering.net>
parents:
475
diff
changeset
|
68 #endif |
62aa0b766a11
[HAVE_ENDGRENT]: Define away endgrent.
Jim Meyering <jim@meyering.net>
parents:
475
diff
changeset
|
69 |
62aa0b766a11
[HAVE_ENDGRENT]: Define away endgrent.
Jim Meyering <jim@meyering.net>
parents:
475
diff
changeset
|
70 #ifndef HAVE_ENDPWENT |
62aa0b766a11
[HAVE_ENDGRENT]: Define away endgrent.
Jim Meyering <jim@meyering.net>
parents:
475
diff
changeset
|
71 # define endpwent() ((void) 0) |
5 | 72 #endif |
73 | |
230 | 74 /* Perform the equivalent of the statement `dest = strdup (src);', |
75 but obtaining storage via alloca instead of from the heap. */ | |
76 | |
77 #define V_STRDUP(dest, src) \ | |
78 do \ | |
79 { \ | |
80 int _len = strlen ((src)); \ | |
81 (dest) = (char *) alloca (_len + 1); \ | |
82 strcpy (dest, src); \ | |
83 } \ | |
84 while (0) | |
85 | |
2271 | 86 /* ISDIGIT differs from isdigit, as follows: |
87 - Its arg may be any int or unsigned int; it need not be an unsigned char. | |
88 - It's guaranteed to evaluate its argument exactly once. | |
89 - It's typically faster. | |
90 Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that | |
91 only '0' through '9' are digits. Prefer ISDIGIT to isdigit unless | |
92 it's important to use the locale's definition of `digit' even when the | |
93 host does not conform to Posix. */ | |
94 #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) | |
5 | 95 |
1347
e7dc6e5a3be5
Don't declare strdup if it's defined as a macro.
Jim Meyering <jim@meyering.net>
parents:
1278
diff
changeset
|
96 #ifndef strdup |
5 | 97 char *strdup (); |
1347
e7dc6e5a3be5
Don't declare strdup if it's defined as a macro.
Jim Meyering <jim@meyering.net>
parents:
1278
diff
changeset
|
98 #endif |
194 | 99 |
100 /* Return nonzero if STR represents an unsigned decimal integer, | |
101 otherwise return 0. */ | |
102 | |
103 static int | |
1557 | 104 is_number (const char *str) |
194 | 105 { |
106 for (; *str; str++) | |
2271 | 107 if (!ISDIGIT (*str)) |
194 | 108 return 0; |
109 return 1; | |
110 } | |
5 | 111 |
112 /* Extract from NAME, which has the form "[user][:.][group]", | |
113 a USERNAME, UID U, GROUPNAME, and GID G. | |
114 Either user or group, or both, must be present. | |
115 If the group is omitted but the ":" or "." separator is given, | |
116 use the given user's login group. | |
117 | |
118 USERNAME and GROUPNAME will be in newly malloc'd memory. | |
119 Either one might be NULL instead, indicating that it was not | |
120 given and the corresponding numeric ID was left unchanged. | |
121 | |
122 Return NULL if successful, a static error message string if not. */ | |
123 | |
194 | 124 const char * |
1580 | 125 parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid, |
126 char **username_arg, char **groupname_arg) | |
5 | 127 { |
194 | 128 static const char *tired = "virtual memory exhausted"; |
129 const char *error_msg; | |
130 char *spec; /* A copy we can write on. */ | |
5 | 131 struct passwd *pwd; |
132 struct group *grp; | |
194 | 133 char *g, *u, *separator; |
230 | 134 char *groupname; |
5 | 135 |
194 | 136 error_msg = NULL; |
230 | 137 *username_arg = *groupname_arg = NULL; |
138 groupname = NULL; | |
5 | 139 |
231 | 140 V_STRDUP (spec, spec_arg); |
194 | 141 |
142 /* Find the separator if there is one. */ | |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
143 separator = strchr (spec, ':'); |
194 | 144 if (separator == NULL) |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
145 separator = strchr (spec, '.'); |
194 | 146 |
147 /* Replace separator with a NUL. */ | |
148 if (separator != NULL) | |
149 *separator = '\0'; | |
150 | |
151 /* Set U and G to non-zero length strings corresponding to user and | |
152 group specifiers or to NULL. */ | |
153 u = (*spec == '\0' ? NULL : spec); | |
154 | |
155 g = (separator == NULL || *(separator + 1) == '\0' | |
156 ? NULL | |
157 : separator + 1); | |
158 | |
159 if (u == NULL && g == NULL) | |
160 return "can not omit both user and group"; | |
161 | |
1260
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
162 #ifdef __DJGPP__ |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
163 /* Pretend that we are the user U whose group is G. This makes |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
164 pwd and grp functions ``know'' about the UID and GID of these. */ |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
165 if (u && !is_number (u)) |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
166 setenv ("USER", u, 1); |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
167 if (g && !is_number (g)) |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
168 setenv ("GROUP", g, 1); |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
169 #endif |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
170 |
194 | 171 if (u != NULL) |
5 | 172 { |
194 | 173 pwd = getpwnam (u); |
174 if (pwd == NULL) | |
5 | 175 { |
194 | 176 |
475
7e3e0dd559c7
(isnumber): Rename to is_number.
Jim Meyering <jim@meyering.net>
parents:
432
diff
changeset
|
177 if (!is_number (u)) |
194 | 178 error_msg = "invalid user"; |
5 | 179 else |
194 | 180 { |
181 int use_login_group; | |
182 use_login_group = (separator != NULL && g == NULL); | |
183 if (use_login_group) | |
184 error_msg = "cannot get the login group of a numeric UID"; | |
185 else | |
2272
9d6da67904b5
add FIXME comments for use of atoi
Jim Meyering <jim@meyering.net>
parents:
2271
diff
changeset
|
186 { |
9d6da67904b5
add FIXME comments for use of atoi
Jim Meyering <jim@meyering.net>
parents:
2271
diff
changeset
|
187 /* FIXME: don't use atoi! */ |
9d6da67904b5
add FIXME comments for use of atoi
Jim Meyering <jim@meyering.net>
parents:
2271
diff
changeset
|
188 *uid = atoi (u); |
9d6da67904b5
add FIXME comments for use of atoi
Jim Meyering <jim@meyering.net>
parents:
2271
diff
changeset
|
189 } |
194 | 190 } |
5 | 191 } |
192 else | |
193 { | |
194 | 194 *uid = pwd->pw_uid; |
195 if (g == NULL && separator != NULL) | |
5 | 196 { |
194 | 197 /* A separator was given, but a group was not specified, |
198 so get the login group. */ | |
199 *gid = pwd->pw_gid; | |
200 grp = getgrgid (pwd->pw_gid); | |
201 if (grp == NULL) | |
202 { | |
203 /* This is enough room to hold the unsigned decimal | |
204 representation of any 32-bit quantity and the trailing | |
205 zero byte. */ | |
206 char uint_buf[21]; | |
207 sprintf (uint_buf, "%u", (unsigned) (pwd->pw_gid)); | |
230 | 208 V_STRDUP (groupname, uint_buf); |
194 | 209 } |
210 else | |
211 { | |
230 | 212 V_STRDUP (groupname, grp->gr_name); |
194 | 213 } |
214 endgrent (); | |
5 | 215 } |
194 | 216 } |
217 endpwent (); | |
5 | 218 } |
219 | |
195 | 220 if (g != NULL && error_msg == NULL) |
194 | 221 { |
222 /* Explicit group. */ | |
223 grp = getgrnam (g); | |
224 if (grp == NULL) | |
225 { | |
475
7e3e0dd559c7
(isnumber): Rename to is_number.
Jim Meyering <jim@meyering.net>
parents:
432
diff
changeset
|
226 if (!is_number (g)) |
194 | 227 error_msg = "invalid group"; |
228 else | |
2272
9d6da67904b5
add FIXME comments for use of atoi
Jim Meyering <jim@meyering.net>
parents:
2271
diff
changeset
|
229 { |
9d6da67904b5
add FIXME comments for use of atoi
Jim Meyering <jim@meyering.net>
parents:
2271
diff
changeset
|
230 /* FIXME: don't use atoi! */ |
9d6da67904b5
add FIXME comments for use of atoi
Jim Meyering <jim@meyering.net>
parents:
2271
diff
changeset
|
231 *gid = atoi (g); |
9d6da67904b5
add FIXME comments for use of atoi
Jim Meyering <jim@meyering.net>
parents:
2271
diff
changeset
|
232 } |
194 | 233 } |
234 else | |
235 *gid = grp->gr_gid; | |
236 endgrent (); /* Save a file descriptor. */ | |
5 | 237 |
194 | 238 if (error_msg == NULL) |
230 | 239 V_STRDUP (groupname, g); |
5 | 240 } |
194 | 241 |
230 | 242 if (error_msg == NULL) |
5 | 243 { |
230 | 244 if (u != NULL) |
245 { | |
246 *username_arg = strdup (u); | |
247 if (*username_arg == NULL) | |
248 error_msg = tired; | |
249 } | |
250 | |
251 if (groupname != NULL && error_msg == NULL) | |
5 | 252 { |
230 | 253 *groupname_arg = strdup (groupname); |
254 if (*groupname_arg == NULL) | |
255 { | |
256 if (*username_arg != NULL) | |
257 { | |
258 free (*username_arg); | |
259 *username_arg = NULL; | |
260 } | |
261 error_msg = tired; | |
262 } | |
5 | 263 } |
264 } | |
194 | 265 |
266 return error_msg; | |
5 | 267 } |
268 | |
232
0d9395790eb7
(main): Change #ifdef TESTING to TEST.
Jim Meyering <jim@meyering.net>
parents:
231
diff
changeset
|
269 #ifdef TEST |
194 | 270 |
966 | 271 # define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s)) |
194 | 272 |
273 int | |
274 main (int argc, char **argv) | |
275 { | |
276 int i; | |
277 | |
278 for (i = 1; i < argc; i++) | |
279 { | |
280 const char *e; | |
281 char *username, *groupname; | |
282 uid_t uid; | |
283 gid_t gid; | |
284 char *tmp; | |
5 | 285 |
194 | 286 tmp = strdup (argv[i]); |
287 e = parse_user_spec (tmp, &uid, &gid, &username, &groupname); | |
288 free (tmp); | |
289 printf ("%s: %u %u %s %s %s\n", | |
290 argv[i], | |
291 (unsigned int) uid, | |
292 (unsigned int) gid, | |
293 NULL_CHECK (username), | |
294 NULL_CHECK (groupname), | |
295 NULL_CHECK (e)); | |
296 } | |
297 | |
298 exit (0); | |
5 | 299 } |
194 | 300 |
301 #endif |