In mini:
[mono-project.git] / support / pwd.c
blob05357f4f617603cfa866b81f2582240762da9765
1 /*
2 * <pwd.h> wrapper functions.
4 * Authors:
5 * Jonathan Pryor (jonpryor@vt.edu)
7 * Copyright (C) 2004 Jonathan Pryor
8 */
10 #include <pwd.h>
11 #include <errno.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <stdlib.h>
16 #include "mph.h"
18 G_BEGIN_DECLS
20 struct Mono_Posix_Syscall__Passwd {
21 /* string */ char *pw_name;
22 /* string */ char *pw_passwd;
23 /* uid_t */ mph_uid_t pw_uid;
24 /* gid_t */ mph_gid_t pw_gid;
25 /* string */ char *pw_gecos;
26 /* string */ char *pw_dir;
27 /* string */ char *pw_shell;
28 /* string */ char *_pw_buf_;
32 * Copy the native `passwd' structure to it's managed representation.
34 * To minimize separate mallocs, all the strings are allocated within the same
35 * memory block (stored in _pw_buf_).
37 static int
38 copy_passwd (struct Mono_Posix_Syscall__Passwd *to, struct passwd *from)
40 enum {PW_NAME = 0, PW_PASSWD, PW_GECOS, PW_DIR, PW_SHELL, PW_LAST};
41 size_t buflen, len[PW_LAST];
42 /* bool */ unsigned char copy[PW_LAST] = {0};
43 const char *source[PW_LAST];
44 char **dest[PW_LAST];
45 int i;
46 char *cur;
48 to->pw_uid = from->pw_uid;
49 to->pw_gid = from->pw_gid;
51 to->pw_name = NULL;
52 to->pw_passwd = NULL;
53 to->pw_gecos = NULL;
54 to->pw_dir = NULL;
55 to->pw_shell = NULL;
56 to->_pw_buf_ = NULL;
58 source[PW_NAME] = from->pw_name;
59 source[PW_PASSWD] = from->pw_passwd;
60 source[PW_GECOS] = from->pw_gecos;
61 source[PW_DIR] = from->pw_dir;
62 source[PW_SHELL] = from->pw_shell;
64 dest[PW_NAME] = &to->pw_name;
65 dest[PW_PASSWD] = &to->pw_passwd;
66 dest[PW_GECOS] = &to->pw_gecos;
67 dest[PW_DIR] = &to->pw_dir;
68 dest[PW_SHELL] = &to->pw_shell;
70 buflen = PW_LAST;
72 /* over-rigorous checking for integer overflow */
73 for (i = 0; i != PW_LAST; ++i) {
74 len[i] = strlen (source[i]);
75 if (len[i] < INT_MAX - buflen) {
76 buflen += len[i];
77 copy[i] = 1;
81 cur = to->_pw_buf_ = (char*) malloc (buflen);
82 if (cur == NULL) {
83 return -1;
86 for (i = 0; i != PW_LAST; ++i) {
87 if (copy[i]) {
88 *dest[i] = strcpy (cur, source[i]);
89 cur += (len[i] + 1);
93 return 0;
96 gint32
97 Mono_Posix_Syscall_getpwnam (const char *name, struct Mono_Posix_Syscall__Passwd *pwbuf)
99 struct passwd *pw;
101 if (pwbuf == NULL) {
102 errno = EFAULT;
103 return -1;
106 pw = getpwnam (name);
107 if (pw == NULL)
108 return -1;
110 if (copy_passwd (pwbuf, pw) == -1) {
111 errno = ENOMEM;
112 return -1;
114 return 0;
117 gint32
118 Mono_Posix_Syscall_getpwuid (mph_uid_t uid, struct Mono_Posix_Syscall__Passwd *pwbuf)
120 struct passwd *pw;
122 if (pwbuf == NULL) {
123 errno = EFAULT;
124 return -1;
127 errno = 0;
128 pw = getpwuid (uid);
129 if (pw == NULL) {
130 return -1;
133 if (copy_passwd (pwbuf, pw) == -1) {
134 errno = ENOMEM;
135 return -1;
137 return 0;
140 #ifdef HAVE_GETPWNAM_R
141 gint32
142 Mono_Posix_Syscall_getpwnam_r (const char *name,
143 struct Mono_Posix_Syscall__Passwd *pwbuf,
144 struct passwd **pwbufp)
146 char *buf, *buf2;
147 size_t buflen;
148 int r;
149 struct passwd _pwbuf;
151 if (pwbuf == NULL) {
152 errno = EFAULT;
153 return -1;
156 buf = buf2 = NULL;
157 buflen = 2;
159 do {
160 buf2 = realloc (buf, buflen *= 2);
161 if (buf2 == NULL) {
162 free (buf);
163 errno = ENOMEM;
164 return -1;
166 buf = buf2;
167 } while ((r = getpwnam_r (name, &_pwbuf, buf, buflen, pwbufp)) &&
168 recheck_range (r));
170 if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
171 r = errno = ENOMEM;
172 free (buf);
174 return r;
176 #endif /* ndef HAVE_GETPWNAM_R */
178 #ifdef HAVE_GETPWUID_R
179 gint32
180 Mono_Posix_Syscall_getpwuid_r (mph_uid_t uid,
181 struct Mono_Posix_Syscall__Passwd *pwbuf,
182 struct passwd **pwbufp)
184 char *buf, *buf2;
185 size_t buflen;
186 int r;
187 struct passwd _pwbuf;
189 if (pwbuf == NULL) {
190 errno = EFAULT;
191 return -1;
194 buf = buf2 = NULL;
195 buflen = 2;
197 do {
198 buf2 = realloc (buf, buflen *= 2);
199 if (buf2 == NULL) {
200 free (buf);
201 errno = ENOMEM;
202 return -1;
204 buf = buf2;
205 } while ((r = getpwuid_r (uid, &_pwbuf, buf, buflen, pwbufp)) &&
206 recheck_range (r));
208 if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
209 r = errno = ENOMEM;
210 free (buf);
212 return r;
214 #endif /* ndef HAVE_GETPWUID_R */
216 gint32
217 Mono_Posix_Syscall_getpwent (struct Mono_Posix_Syscall__Passwd *pwbuf)
219 struct passwd *pw;
221 if (pwbuf == NULL) {
222 errno = EFAULT;
223 return -1;
226 pw = getpwent ();
227 if (pw == NULL)
228 return -1;
230 if (copy_passwd (pwbuf, pw) == -1) {
231 errno = ENOMEM;
232 return -1;
234 return 0;
237 #ifdef HAVE_FGETPWENT
238 gint32
239 Mono_Posix_Syscall_fgetpwent (FILE *stream, struct Mono_Posix_Syscall__Passwd *pwbuf)
241 struct passwd *pw;
243 if (pwbuf == NULL) {
244 errno = EFAULT;
245 return -1;
248 pw = fgetpwent (stream);
249 if (pw == NULL)
250 return -1;
252 if (copy_passwd (pwbuf, pw) == -1) {
253 errno = ENOMEM;
254 return -1;
256 return 0;
258 #endif /* ndef HAVE_FGETPWENT */
260 G_END_DECLS
263 * vim: noexpandtab