Mercurial > hg > octave-kai > gnulib-hg
annotate lib/userspec.c @ 499:62aa0b766a11
[HAVE_ENDGRENT]: Define away endgrent.
[HAVE_ENDPWENT]: Define away endpwent.
author | Jim Meyering <jim@meyering.net> |
---|---|
date | Wed, 18 Oct 1995 15:59:12 +0000 |
parents | 7e3e0dd559c7 |
children | b4ef1c1a0171 |
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 | |
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 | |
156 if (u != NULL) | |
5 | 157 { |
194 | 158 pwd = getpwnam (u); |
159 if (pwd == NULL) | |
5 | 160 { |
194 | 161 |
475
7e3e0dd559c7
(isnumber): Rename to is_number.
Jim Meyering <jim@meyering.net>
parents:
432
diff
changeset
|
162 if (!is_number (u)) |
194 | 163 error_msg = "invalid user"; |
5 | 164 else |
194 | 165 { |
166 int use_login_group; | |
167 use_login_group = (separator != NULL && g == NULL); | |
168 if (use_login_group) | |
169 error_msg = "cannot get the login group of a numeric UID"; | |
170 else | |
171 *uid = atoi (u); | |
172 } | |
5 | 173 } |
174 else | |
175 { | |
194 | 176 *uid = pwd->pw_uid; |
177 if (g == NULL && separator != NULL) | |
5 | 178 { |
194 | 179 /* A separator was given, but a group was not specified, |
180 so get the login group. */ | |
181 *gid = pwd->pw_gid; | |
182 grp = getgrgid (pwd->pw_gid); | |
183 if (grp == NULL) | |
184 { | |
185 /* This is enough room to hold the unsigned decimal | |
186 representation of any 32-bit quantity and the trailing | |
187 zero byte. */ | |
188 char uint_buf[21]; | |
189 sprintf (uint_buf, "%u", (unsigned) (pwd->pw_gid)); | |
230 | 190 V_STRDUP (groupname, uint_buf); |
194 | 191 } |
192 else | |
193 { | |
230 | 194 V_STRDUP (groupname, grp->gr_name); |
194 | 195 } |
196 endgrent (); | |
5 | 197 } |
194 | 198 } |
199 endpwent (); | |
5 | 200 } |
201 | |
195 | 202 if (g != NULL && error_msg == NULL) |
194 | 203 { |
204 /* Explicit group. */ | |
205 grp = getgrnam (g); | |
206 if (grp == NULL) | |
207 { | |
475
7e3e0dd559c7
(isnumber): Rename to is_number.
Jim Meyering <jim@meyering.net>
parents:
432
diff
changeset
|
208 if (!is_number (g)) |
194 | 209 error_msg = "invalid group"; |
210 else | |
211 *gid = atoi (g); | |
212 } | |
213 else | |
214 *gid = grp->gr_gid; | |
215 endgrent (); /* Save a file descriptor. */ | |
5 | 216 |
194 | 217 if (error_msg == NULL) |
230 | 218 V_STRDUP (groupname, g); |
5 | 219 } |
194 | 220 |
230 | 221 if (error_msg == NULL) |
5 | 222 { |
230 | 223 if (u != NULL) |
224 { | |
225 *username_arg = strdup (u); | |
226 if (*username_arg == NULL) | |
227 error_msg = tired; | |
228 } | |
229 | |
230 if (groupname != NULL && error_msg == NULL) | |
5 | 231 { |
230 | 232 *groupname_arg = strdup (groupname); |
233 if (*groupname_arg == NULL) | |
234 { | |
235 if (*username_arg != NULL) | |
236 { | |
237 free (*username_arg); | |
238 *username_arg = NULL; | |
239 } | |
240 error_msg = tired; | |
241 } | |
5 | 242 } |
243 } | |
194 | 244 |
245 return error_msg; | |
5 | 246 } |
247 | |
232
0d9395790eb7
(main): Change #ifdef TESTING to TEST.
Jim Meyering <jim@meyering.net>
parents:
231
diff
changeset
|
248 #ifdef TEST |
194 | 249 |
250 #define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s)) | |
251 | |
252 int | |
253 main (int argc, char **argv) | |
254 { | |
255 int i; | |
256 | |
257 for (i = 1; i < argc; i++) | |
258 { | |
259 const char *e; | |
260 char *username, *groupname; | |
261 uid_t uid; | |
262 gid_t gid; | |
263 char *tmp; | |
5 | 264 |
194 | 265 tmp = strdup (argv[i]); |
266 e = parse_user_spec (tmp, &uid, &gid, &username, &groupname); | |
267 free (tmp); | |
268 printf ("%s: %u %u %s %s %s\n", | |
269 argv[i], | |
270 (unsigned int) uid, | |
271 (unsigned int) gid, | |
272 NULL_CHECK (username), | |
273 NULL_CHECK (groupname), | |
274 NULL_CHECK (e)); | |
275 } | |
276 | |
277 exit (0); | |
5 | 278 } |
194 | 279 |
280 #endif |