Mercurial > hg > octave-kai > gnulib-hg
annotate lib/userspec.c @ 194:1a1e462a2bea
.
author | Jim Meyering <jim@meyering.net> |
---|---|
date | Mon, 14 Mar 1994 18:41:13 +0000 (1994-03-14) |
parents | e03c39815941 |
children | ed9f884b64fc |
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 #if defined (CONFIG_BROKETS) | |
22 /* We use <config.h> instead of "config.h" so that a compilation | |
126 | 23 using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h |
24 (which it would do because it found this file in $srcdir). */ | |
105 | 25 #include <config.h> |
26 #else | |
27 #include "config.h" | |
28 #endif | |
29 #endif | |
30 | |
5 | 31 #include <stdio.h> |
32 #include <sys/types.h> | |
33 #include <pwd.h> | |
34 #include <grp.h> | |
35 | |
52
d9ca5dc520bf
* system.h [rindex, incl, bcopy, bzero]: Ditto.
Jim Meyering <jim@meyering.net>
parents:
5
diff
changeset
|
36 #if defined(STDC_HEADERS) || defined(HAVE_STRING_H) |
5 | 37 #include <string.h> |
52
d9ca5dc520bf
* system.h [rindex, incl, bcopy, bzero]: Ditto.
Jim Meyering <jim@meyering.net>
parents:
5
diff
changeset
|
38 #ifndef index |
5 | 39 #define index strchr |
52
d9ca5dc520bf
* system.h [rindex, incl, bcopy, bzero]: Ditto.
Jim Meyering <jim@meyering.net>
parents:
5
diff
changeset
|
40 #endif |
5 | 41 #else |
42 #include <strings.h> | |
43 #endif | |
44 | |
45 #ifdef STDC_HEADERS | |
46 #include <stdlib.h> | |
47 #else | |
48 char *malloc (); | |
49 #endif | |
50 | |
51 #ifdef HAVE_UNISTD_H | |
52 #include <unistd.h> | |
53 #endif | |
54 | |
55 #ifndef _POSIX_VERSION | |
56 struct passwd *getpwnam (); | |
57 struct group *getgrnam (); | |
58 struct group *getgrgid (); | |
59 #endif | |
60 | |
61 #ifdef _POSIX_SOURCE | |
62 #define endpwent() | |
63 #define endgrent() | |
64 #endif | |
65 | |
66 #define isdigit(c) ((c) >= '0' && (c) <= '9') | |
67 | |
68 char *strdup (); | |
194 | 69 |
70 /* Return nonzero if STR represents an unsigned decimal integer, | |
71 otherwise return 0. */ | |
72 | |
73 static int | |
74 isnumber (str) | |
75 const char *str; | |
76 { | |
77 for (; *str; str++) | |
78 if (!isdigit (*str)) | |
79 return 0; | |
80 return 1; | |
81 } | |
5 | 82 |
83 /* Extract from NAME, which has the form "[user][:.][group]", | |
84 a USERNAME, UID U, GROUPNAME, and GID G. | |
85 Either user or group, or both, must be present. | |
86 If the group is omitted but the ":" or "." separator is given, | |
87 use the given user's login group. | |
88 | |
89 USERNAME and GROUPNAME will be in newly malloc'd memory. | |
90 Either one might be NULL instead, indicating that it was not | |
91 given and the corresponding numeric ID was left unchanged. | |
92 | |
93 Return NULL if successful, a static error message string if not. */ | |
94 | |
194 | 95 const char * |
96 parse_user_spec (spec_arg, uid, gid, username, groupname) | |
97 const char *spec_arg; | |
5 | 98 uid_t *uid; |
99 gid_t *gid; | |
100 char **username, **groupname; | |
101 { | |
194 | 102 static const char *tired = "virtual memory exhausted"; |
103 const char *error_msg; | |
104 char *spec; /* A copy we can write on. */ | |
105 int spec_len; | |
5 | 106 struct passwd *pwd; |
107 struct group *grp; | |
194 | 108 char *g, *u, *separator; |
5 | 109 |
194 | 110 error_msg = NULL; |
5 | 111 *username = *groupname = NULL; |
112 | |
194 | 113 spec_len = strlen (spec_arg); |
114 spec = (char *) alloca (strlen (spec_arg) + 1); | |
115 strcpy (spec, spec_arg); | |
116 | |
117 /* Find the separator if there is one. */ | |
118 separator = index (spec, ':'); | |
119 if (separator == NULL) | |
120 separator = index (spec, '.'); | |
121 | |
122 /* Replace separator with a NUL. */ | |
123 if (separator != NULL) | |
124 *separator = '\0'; | |
125 | |
126 /* Set U and G to non-zero length strings corresponding to user and | |
127 group specifiers or to NULL. */ | |
128 u = (*spec == '\0' ? NULL : spec); | |
129 | |
130 g = (separator == NULL || *(separator + 1) == '\0' | |
131 ? NULL | |
132 : separator + 1); | |
133 | |
134 if (u == NULL && g == NULL) | |
135 return "can not omit both user and group"; | |
136 | |
137 if (u != NULL) | |
5 | 138 { |
194 | 139 pwd = getpwnam (u); |
140 if (pwd == NULL) | |
5 | 141 { |
194 | 142 |
143 if (!isnumber (u)) | |
144 error_msg = "invalid user"; | |
5 | 145 else |
194 | 146 { |
147 int use_login_group; | |
148 use_login_group = (separator != NULL && g == NULL); | |
149 if (use_login_group) | |
150 error_msg = "cannot get the login group of a numeric UID"; | |
151 else | |
152 *uid = atoi (u); | |
153 } | |
5 | 154 } |
155 else | |
156 { | |
194 | 157 *uid = pwd->pw_uid; |
158 if (g == NULL && separator != NULL) | |
5 | 159 { |
194 | 160 /* A separator was given, but a group was not specified, |
161 so get the login group. */ | |
162 *gid = pwd->pw_gid; | |
163 grp = getgrgid (pwd->pw_gid); | |
164 if (grp == NULL) | |
165 { | |
166 /* This is enough room to hold the unsigned decimal | |
167 representation of any 32-bit quantity and the trailing | |
168 zero byte. */ | |
169 char uint_buf[21]; | |
170 sprintf (uint_buf, "%u", (unsigned) (pwd->pw_gid)); | |
171 *groupname = strdup (uint_buf); | |
172 } | |
173 else | |
174 { | |
175 *groupname = strdup (grp->gr_name); | |
176 } | |
177 if (*groupname == NULL) | |
178 error_msg = tired; | |
179 endgrent (); | |
5 | 180 } |
194 | 181 } |
182 endpwent (); | |
183 | |
184 if (error_msg == NULL) | |
185 { | |
186 *username = strdup (u); | |
187 if (*username == NULL) | |
188 error_msg = tired; | |
5 | 189 } |
190 } | |
191 | |
194 | 192 if (g != NULL) |
193 { | |
194 /* Explicit group. */ | |
195 grp = getgrnam (g); | |
196 if (grp == NULL) | |
197 { | |
198 if (!isnumber (g)) | |
199 error_msg = "invalid group"; | |
200 else | |
201 *gid = atoi (g); | |
202 } | |
203 else | |
204 *gid = grp->gr_gid; | |
205 endgrent (); /* Save a file descriptor. */ | |
5 | 206 |
194 | 207 if (error_msg == NULL) |
208 { | |
209 *groupname = strdup (g); | |
210 if (*groupname == NULL) | |
211 return tired; | |
212 } | |
5 | 213 } |
194 | 214 |
215 if (error_msg) | |
5 | 216 { |
194 | 217 if (*groupname != NULL) |
5 | 218 { |
194 | 219 free (*groupname); |
220 *groupname = NULL; | |
221 } | |
222 if (*username != NULL) | |
223 { | |
224 free (*username); | |
225 *username = NULL; | |
5 | 226 } |
227 } | |
194 | 228 |
229 return error_msg; | |
5 | 230 } |
231 | |
194 | 232 #ifdef TESTING |
233 | |
234 #define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s)) | |
235 | |
236 int | |
237 main (int argc, char **argv) | |
238 { | |
239 int i; | |
240 | |
241 for (i = 1; i < argc; i++) | |
242 { | |
243 const char *e; | |
244 char *username, *groupname; | |
245 uid_t uid; | |
246 gid_t gid; | |
247 char *tmp; | |
5 | 248 |
194 | 249 tmp = strdup (argv[i]); |
250 e = parse_user_spec (tmp, &uid, &gid, &username, &groupname); | |
251 free (tmp); | |
252 printf ("%s: %u %u %s %s %s\n", | |
253 argv[i], | |
254 (unsigned int) uid, | |
255 (unsigned int) gid, | |
256 NULL_CHECK (username), | |
257 NULL_CHECK (groupname), | |
258 NULL_CHECK (e)); | |
259 } | |
260 | |
261 exit (0); | |
5 | 262 } |
194 | 263 |
264 #endif |