Mercurial > hg > octave-kai > gnulib-hg
annotate lib/userspec.c @ 475:7e3e0dd559c7
(isnumber): Rename to is_number.
(parse_user_spec): Rename uses, too.
author | Jim Meyering <jim@meyering.net> |
---|---|
date | Sat, 05 Aug 1995 03:13:16 +0000 |
parents | a56993d69333 |
children | 62aa0b766a11 |
rev | line source |
---|---|
5 | 1 /* userspec.c -- Parse a user and group string. |
2 Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. | |
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 | |
15 along with this program; if not, write to the Free Software | |
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
17 | |
18 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ | |
19 | |
105 | 20 #ifdef HAVE_CONFIG_H |
21 #include <config.h> | |
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 |
231 | 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 | |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
43 #ifdef HAVE_STRING_H |
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 | |
52 #ifdef 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 | |
56 #ifdef 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 | |
66 #ifdef _POSIX_SOURCE | |
67 #define endpwent() | |
68 #define endgrent() | |
69 #endif | |
70 | |
230 | 71 /* Perform the equivalent of the statement `dest = strdup (src);', |
72 but obtaining storage via alloca instead of from the heap. */ | |
73 | |
74 #define V_STRDUP(dest, src) \ | |
75 do \ | |
76 { \ | |
77 int _len = strlen ((src)); \ | |
78 (dest) = (char *) alloca (_len + 1); \ | |
79 strcpy (dest, src); \ | |
80 } \ | |
81 while (0) | |
82 | |
5 | 83 #define isdigit(c) ((c) >= '0' && (c) <= '9') |
84 | |
85 char *strdup (); | |
194 | 86 |
87 /* Return nonzero if STR represents an unsigned decimal integer, | |
88 otherwise return 0. */ | |
89 | |
90 static int | |
475
7e3e0dd559c7
(isnumber): Rename to is_number.
Jim Meyering <jim@meyering.net>
parents:
432
diff
changeset
|
91 is_number (str) |
194 | 92 const char *str; |
93 { | |
94 for (; *str; str++) | |
95 if (!isdigit (*str)) | |
96 return 0; | |
97 return 1; | |
98 } | |
5 | 99 |
100 /* Extract from NAME, which has the form "[user][:.][group]", | |
101 a USERNAME, UID U, GROUPNAME, and GID G. | |
102 Either user or group, or both, must be present. | |
103 If the group is omitted but the ":" or "." separator is given, | |
104 use the given user's login group. | |
105 | |
106 USERNAME and GROUPNAME will be in newly malloc'd memory. | |
107 Either one might be NULL instead, indicating that it was not | |
108 given and the corresponding numeric ID was left unchanged. | |
109 | |
110 Return NULL if successful, a static error message string if not. */ | |
111 | |
194 | 112 const char * |
230 | 113 parse_user_spec (spec_arg, uid, gid, username_arg, groupname_arg) |
194 | 114 const char *spec_arg; |
5 | 115 uid_t *uid; |
116 gid_t *gid; | |
230 | 117 char **username_arg, **groupname_arg; |
5 | 118 { |
194 | 119 static const char *tired = "virtual memory exhausted"; |
120 const char *error_msg; | |
121 char *spec; /* A copy we can write on. */ | |
5 | 122 struct passwd *pwd; |
123 struct group *grp; | |
194 | 124 char *g, *u, *separator; |
230 | 125 char *groupname; |
5 | 126 |
194 | 127 error_msg = NULL; |
230 | 128 *username_arg = *groupname_arg = NULL; |
129 groupname = NULL; | |
5 | 130 |
231 | 131 V_STRDUP (spec, spec_arg); |
194 | 132 |
133 /* 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
|
134 separator = strchr (spec, ':'); |
194 | 135 if (separator == NULL) |
432
a56993d69333
(parse_user_spec): Use strchr, not index.
Jim Meyering <jim@meyering.net>
parents:
316
diff
changeset
|
136 separator = strchr (spec, '.'); |
194 | 137 |
138 /* Replace separator with a NUL. */ | |
139 if (separator != NULL) | |
140 *separator = '\0'; | |
141 | |
142 /* Set U and G to non-zero length strings corresponding to user and | |
143 group specifiers or to NULL. */ | |
144 u = (*spec == '\0' ? NULL : spec); | |
145 | |
146 g = (separator == NULL || *(separator + 1) == '\0' | |
147 ? NULL | |
148 : separator + 1); | |
149 | |
150 if (u == NULL && g == NULL) | |
151 return "can not omit both user and group"; | |
152 | |
153 if (u != NULL) | |
5 | 154 { |
194 | 155 pwd = getpwnam (u); |
156 if (pwd == NULL) | |
5 | 157 { |
194 | 158 |
475
7e3e0dd559c7
(isnumber): Rename to is_number.
Jim Meyering <jim@meyering.net>
parents:
432
diff
changeset
|
159 if (!is_number (u)) |
194 | 160 error_msg = "invalid user"; |
5 | 161 else |
194 | 162 { |
163 int use_login_group; | |
164 use_login_group = (separator != NULL && g == NULL); | |
165 if (use_login_group) | |
166 error_msg = "cannot get the login group of a numeric UID"; | |
167 else | |
168 *uid = atoi (u); | |
169 } | |
5 | 170 } |
171 else | |
172 { | |
194 | 173 *uid = pwd->pw_uid; |
174 if (g == NULL && separator != NULL) | |
5 | 175 { |
194 | 176 /* A separator was given, but a group was not specified, |
177 so get the login group. */ | |
178 *gid = pwd->pw_gid; | |
179 grp = getgrgid (pwd->pw_gid); | |
180 if (grp == NULL) | |
181 { | |
182 /* This is enough room to hold the unsigned decimal | |
183 representation of any 32-bit quantity and the trailing | |
184 zero byte. */ | |
185 char uint_buf[21]; | |
186 sprintf (uint_buf, "%u", (unsigned) (pwd->pw_gid)); | |
230 | 187 V_STRDUP (groupname, uint_buf); |
194 | 188 } |
189 else | |
190 { | |
230 | 191 V_STRDUP (groupname, grp->gr_name); |
194 | 192 } |
193 endgrent (); | |
5 | 194 } |
194 | 195 } |
196 endpwent (); | |
5 | 197 } |
198 | |
195 | 199 if (g != NULL && error_msg == NULL) |
194 | 200 { |
201 /* Explicit group. */ | |
202 grp = getgrnam (g); | |
203 if (grp == NULL) | |
204 { | |
475
7e3e0dd559c7
(isnumber): Rename to is_number.
Jim Meyering <jim@meyering.net>
parents:
432
diff
changeset
|
205 if (!is_number (g)) |
194 | 206 error_msg = "invalid group"; |
207 else | |
208 *gid = atoi (g); | |
209 } | |
210 else | |
211 *gid = grp->gr_gid; | |
212 endgrent (); /* Save a file descriptor. */ | |
5 | 213 |
194 | 214 if (error_msg == NULL) |
230 | 215 V_STRDUP (groupname, g); |
5 | 216 } |
194 | 217 |
230 | 218 if (error_msg == NULL) |
5 | 219 { |
230 | 220 if (u != NULL) |
221 { | |
222 *username_arg = strdup (u); | |
223 if (*username_arg == NULL) | |
224 error_msg = tired; | |
225 } | |
226 | |
227 if (groupname != NULL && error_msg == NULL) | |
5 | 228 { |
230 | 229 *groupname_arg = strdup (groupname); |
230 if (*groupname_arg == NULL) | |
231 { | |
232 if (*username_arg != NULL) | |
233 { | |
234 free (*username_arg); | |
235 *username_arg = NULL; | |
236 } | |
237 error_msg = tired; | |
238 } | |
5 | 239 } |
240 } | |
194 | 241 |
242 return error_msg; | |
5 | 243 } |
244 | |
232
0d9395790eb7
(main): Change #ifdef TESTING to TEST.
Jim Meyering <jim@meyering.net>
parents:
231
diff
changeset
|
245 #ifdef TEST |
194 | 246 |
247 #define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s)) | |
248 | |
249 int | |
250 main (int argc, char **argv) | |
251 { | |
252 int i; | |
253 | |
254 for (i = 1; i < argc; i++) | |
255 { | |
256 const char *e; | |
257 char *username, *groupname; | |
258 uid_t uid; | |
259 gid_t gid; | |
260 char *tmp; | |
5 | 261 |
194 | 262 tmp = strdup (argv[i]); |
263 e = parse_user_spec (tmp, &uid, &gid, &username, &groupname); | |
264 free (tmp); | |
265 printf ("%s: %u %u %s %s %s\n", | |
266 argv[i], | |
267 (unsigned int) uid, | |
268 (unsigned int) gid, | |
269 NULL_CHECK (username), | |
270 NULL_CHECK (groupname), | |
271 NULL_CHECK (e)); | |
272 } | |
273 | |
274 exit (0); | |
5 | 275 } |
194 | 276 |
277 #endif |