Mercurial > hg > octave-lojdl > gnulib-hg
annotate lib/userspec.c @ 1260:7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
about any arbitrary user and group by pretending to be the user
and to belong to the group specified in `spec_arg' argument.
author | Jim Meyering <jim@meyering.net> |
---|---|
date | Tue, 10 Mar 1998 22:49:04 +0000 |
parents | 2db1c866ccce |
children | 9ad625a30b7d |
rev | line source |
---|---|
5 | 1 /* userspec.c -- Parse a user and group string. |
966 | 2 Copyright (C) 1989, 1990, 1991, 1992, 1997 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 |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
27 # ifdef HAVE_ALLOCA_H |
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 | |
5 | 86 #define isdigit(c) ((c) >= '0' && (c) <= '9') |
87 | |
88 char *strdup (); | |
194 | 89 |
90 /* Return nonzero if STR represents an unsigned decimal integer, | |
91 otherwise return 0. */ | |
92 | |
93 static int | |
475
7e3e0dd559c7
(isnumber): Rename to is_number.
Jim Meyering <jim@meyering.net>
parents:
432
diff
changeset
|
94 is_number (str) |
194 | 95 const char *str; |
96 { | |
97 for (; *str; str++) | |
98 if (!isdigit (*str)) | |
99 return 0; | |
100 return 1; | |
101 } | |
5 | 102 |
103 /* Extract from NAME, which has the form "[user][:.][group]", | |
104 a USERNAME, UID U, GROUPNAME, and GID G. | |
105 Either user or group, or both, must be present. | |
106 If the group is omitted but the ":" or "." separator is given, | |
107 use the given user's login group. | |
108 | |
109 USERNAME and GROUPNAME will be in newly malloc'd memory. | |
110 Either one might be NULL instead, indicating that it was not | |
111 given and the corresponding numeric ID was left unchanged. | |
112 | |
113 Return NULL if successful, a static error message string if not. */ | |
114 | |
194 | 115 const char * |
230 | 116 parse_user_spec (spec_arg, uid, gid, username_arg, groupname_arg) |
194 | 117 const char *spec_arg; |
5 | 118 uid_t *uid; |
119 gid_t *gid; | |
230 | 120 char **username_arg, **groupname_arg; |
5 | 121 { |
194 | 122 static const char *tired = "virtual memory exhausted"; |
123 const char *error_msg; | |
124 char *spec; /* A copy we can write on. */ | |
5 | 125 struct passwd *pwd; |
126 struct group *grp; | |
194 | 127 char *g, *u, *separator; |
230 | 128 char *groupname; |
5 | 129 |
194 | 130 error_msg = NULL; |
230 | 131 *username_arg = *groupname_arg = NULL; |
132 groupname = NULL; | |
5 | 133 |
231 | 134 V_STRDUP (spec, spec_arg); |
194 | 135 |
136 /* 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
|
137 separator = strchr (spec, ':'); |
194 | 138 if (separator == NULL) |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
139 separator = strchr (spec, '.'); |
194 | 140 |
141 /* Replace separator with a NUL. */ | |
142 if (separator != NULL) | |
143 *separator = '\0'; | |
144 | |
145 /* Set U and G to non-zero length strings corresponding to user and | |
146 group specifiers or to NULL. */ | |
147 u = (*spec == '\0' ? NULL : spec); | |
148 | |
149 g = (separator == NULL || *(separator + 1) == '\0' | |
150 ? NULL | |
151 : separator + 1); | |
152 | |
153 if (u == NULL && g == NULL) | |
154 return "can not omit both user and group"; | |
155 | |
1260
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
156 #ifdef __DJGPP__ |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
157 /* 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
|
158 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
|
159 if (u && !is_number (u)) |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
160 setenv ("USER", u, 1); |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
161 if (g && !is_number (g)) |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
162 setenv ("GROUP", g, 1); |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
163 #endif |
7aff74949325
(parse_user_spec) [__DJGPP__]: Make function know
Jim Meyering <jim@meyering.net>
parents:
966
diff
changeset
|
164 |
194 | 165 if (u != NULL) |
5 | 166 { |
194 | 167 pwd = getpwnam (u); |
168 if (pwd == NULL) | |
5 | 169 { |
194 | 170 |
475
7e3e0dd559c7
(isnumber): Rename to is_number.
Jim Meyering <jim@meyering.net>
parents:
432
diff
changeset
|
171 if (!is_number (u)) |
194 | 172 error_msg = "invalid user"; |
5 | 173 else |
194 | 174 { |
175 int use_login_group; | |
176 use_login_group = (separator != NULL && g == NULL); | |
177 if (use_login_group) | |
178 error_msg = "cannot get the login group of a numeric UID"; | |
179 else | |
180 *uid = atoi (u); | |
181 } | |
5 | 182 } |
183 else | |
184 { | |
194 | 185 *uid = pwd->pw_uid; |
186 if (g == NULL && separator != NULL) | |
5 | 187 { |
194 | 188 /* A separator was given, but a group was not specified, |
189 so get the login group. */ | |
190 *gid = pwd->pw_gid; | |
191 grp = getgrgid (pwd->pw_gid); | |
192 if (grp == NULL) | |
193 { | |
194 /* This is enough room to hold the unsigned decimal | |
195 representation of any 32-bit quantity and the trailing | |
196 zero byte. */ | |
197 char uint_buf[21]; | |
198 sprintf (uint_buf, "%u", (unsigned) (pwd->pw_gid)); | |
230 | 199 V_STRDUP (groupname, uint_buf); |
194 | 200 } |
201 else | |
202 { | |
230 | 203 V_STRDUP (groupname, grp->gr_name); |
194 | 204 } |
205 endgrent (); | |
5 | 206 } |
194 | 207 } |
208 endpwent (); | |
5 | 209 } |
210 | |
195 | 211 if (g != NULL && error_msg == NULL) |
194 | 212 { |
213 /* Explicit group. */ | |
214 grp = getgrnam (g); | |
215 if (grp == NULL) | |
216 { | |
475
7e3e0dd559c7
(isnumber): Rename to is_number.
Jim Meyering <jim@meyering.net>
parents:
432
diff
changeset
|
217 if (!is_number (g)) |
194 | 218 error_msg = "invalid group"; |
219 else | |
220 *gid = atoi (g); | |
221 } | |
222 else | |
223 *gid = grp->gr_gid; | |
224 endgrent (); /* Save a file descriptor. */ | |
5 | 225 |
194 | 226 if (error_msg == NULL) |
230 | 227 V_STRDUP (groupname, g); |
5 | 228 } |
194 | 229 |
230 | 230 if (error_msg == NULL) |
5 | 231 { |
230 | 232 if (u != NULL) |
233 { | |
234 *username_arg = strdup (u); | |
235 if (*username_arg == NULL) | |
236 error_msg = tired; | |
237 } | |
238 | |
239 if (groupname != NULL && error_msg == NULL) | |
5 | 240 { |
230 | 241 *groupname_arg = strdup (groupname); |
242 if (*groupname_arg == NULL) | |
243 { | |
244 if (*username_arg != NULL) | |
245 { | |
246 free (*username_arg); | |
247 *username_arg = NULL; | |
248 } | |
249 error_msg = tired; | |
250 } | |
5 | 251 } |
252 } | |
194 | 253 |
254 return error_msg; | |
5 | 255 } |
256 | |
232
0d9395790eb7
(main): Change #ifdef TESTING to TEST.
Jim Meyering <jim@meyering.net>
parents:
231
diff
changeset
|
257 #ifdef TEST |
194 | 258 |
966 | 259 # define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s)) |
194 | 260 |
261 int | |
262 main (int argc, char **argv) | |
263 { | |
264 int i; | |
265 | |
266 for (i = 1; i < argc; i++) | |
267 { | |
268 const char *e; | |
269 char *username, *groupname; | |
270 uid_t uid; | |
271 gid_t gid; | |
272 char *tmp; | |
5 | 273 |
194 | 274 tmp = strdup (argv[i]); |
275 e = parse_user_spec (tmp, &uid, &gid, &username, &groupname); | |
276 free (tmp); | |
277 printf ("%s: %u %u %s %s %s\n", | |
278 argv[i], | |
279 (unsigned int) uid, | |
280 (unsigned int) gid, | |
281 NULL_CHECK (username), | |
282 NULL_CHECK (groupname), | |
283 NULL_CHECK (e)); | |
284 } | |
285 | |
286 exit (0); | |
5 | 287 } |
194 | 288 |
289 #endif |