2006-09-13 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono/afaerber.git] / support / pwd.c
blob38859e0d7c61bb3522adf62da87ec0bba2fe3b0c
1 /*
2 * <pwd.h> wrapper functions.
4 * Authors:
5 * Jonathan Pryor (jonpryor@vt.edu)
7 * Copyright (C) 2004-2005 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_;
31 static const size_t
32 passwd_offsets[] = {
33 offsetof (struct passwd, pw_name),
34 offsetof (struct passwd, pw_passwd),
35 offsetof (struct passwd, pw_gecos),
36 offsetof (struct passwd, pw_dir),
37 offsetof (struct passwd, pw_shell)
40 static const size_t
41 mph_passwd_offsets[] = {
42 offsetof (struct Mono_Posix_Syscall__Passwd, pw_name),
43 offsetof (struct Mono_Posix_Syscall__Passwd, pw_passwd),
44 offsetof (struct Mono_Posix_Syscall__Passwd, pw_gecos),
45 offsetof (struct Mono_Posix_Syscall__Passwd, pw_dir),
46 offsetof (struct Mono_Posix_Syscall__Passwd, pw_shell)
50 * Copy the native `passwd' structure to it's managed representation.
52 * To minimize separate mallocs, all the strings are allocated within the same
53 * memory block (stored in _pw_buf_).
55 static int
56 copy_passwd (struct Mono_Posix_Syscall__Passwd *to, struct passwd *from)
58 char *buf;
59 buf = _mph_copy_structure_strings (to, mph_passwd_offsets,
60 from, passwd_offsets, sizeof(passwd_offsets)/sizeof(passwd_offsets[0]));
62 to->pw_uid = from->pw_uid;
63 to->pw_gid = from->pw_gid;
65 to->_pw_buf_ = buf;
66 if (buf == NULL) {
67 return -1;
70 return 0;
73 gint32
74 Mono_Posix_Syscall_getpwnam (const char *name, struct Mono_Posix_Syscall__Passwd *pwbuf)
76 struct passwd *pw;
78 if (pwbuf == NULL) {
79 errno = EFAULT;
80 return -1;
83 errno = 0;
84 pw = getpwnam (name);
85 if (pw == NULL)
86 return -1;
88 if (copy_passwd (pwbuf, pw) == -1) {
89 errno = ENOMEM;
90 return -1;
92 return 0;
95 gint32
96 Mono_Posix_Syscall_getpwuid (mph_uid_t uid, struct Mono_Posix_Syscall__Passwd *pwbuf)
98 struct passwd *pw;
100 if (pwbuf == NULL) {
101 errno = EFAULT;
102 return -1;
105 errno = 0;
106 pw = getpwuid (uid);
107 if (pw == NULL) {
108 return -1;
111 if (copy_passwd (pwbuf, pw) == -1) {
112 errno = ENOMEM;
113 return -1;
115 return 0;
118 #ifdef HAVE_GETPWNAM_R
119 gint32
120 Mono_Posix_Syscall_getpwnam_r (const char *name,
121 struct Mono_Posix_Syscall__Passwd *pwbuf,
122 void **pwbufp)
124 char *buf, *buf2;
125 size_t buflen;
126 int r;
127 struct passwd _pwbuf;
129 if (pwbuf == NULL) {
130 errno = EFAULT;
131 return -1;
134 buf = buf2 = NULL;
135 buflen = 2;
137 do {
138 buf2 = realloc (buf, buflen *= 2);
139 if (buf2 == NULL) {
140 free (buf);
141 errno = ENOMEM;
142 return -1;
144 buf = buf2;
145 errno = 0;
146 } while ((r = getpwnam_r (name, &_pwbuf, buf, buflen, (struct passwd**) pwbufp)) &&
147 recheck_range (r));
149 if (r == 0 && !(*pwbufp))
150 /* On solaris, this function returns 0 even if the entry was not found */
151 r = errno = ENOENT;
153 if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
154 r = errno = ENOMEM;
155 free (buf);
157 return r;
159 #endif /* ndef HAVE_GETPWNAM_R */
161 #ifdef HAVE_GETPWUID_R
162 gint32
163 Mono_Posix_Syscall_getpwuid_r (mph_uid_t uid,
164 struct Mono_Posix_Syscall__Passwd *pwbuf,
165 void **pwbufp)
167 char *buf, *buf2;
168 size_t buflen;
169 int r;
170 struct passwd _pwbuf;
172 if (pwbuf == NULL) {
173 errno = EFAULT;
174 return -1;
177 buf = buf2 = NULL;
178 buflen = 2;
180 do {
181 buf2 = realloc (buf, buflen *= 2);
182 if (buf2 == NULL) {
183 free (buf);
184 errno = ENOMEM;
185 return -1;
187 buf = buf2;
188 errno = 0;
189 } while ((r = getpwuid_r (uid, &_pwbuf, buf, buflen, (struct passwd**) pwbufp)) &&
190 recheck_range (r));
192 if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
193 r = errno = ENOMEM;
194 free (buf);
196 return r;
198 #endif /* ndef HAVE_GETPWUID_R */
200 gint32
201 Mono_Posix_Syscall_getpwent (struct Mono_Posix_Syscall__Passwd *pwbuf)
203 struct passwd *pw;
205 if (pwbuf == NULL) {
206 errno = EFAULT;
207 return -1;
210 errno = 0;
211 pw = getpwent ();
212 if (pw == NULL)
213 return -1;
215 if (copy_passwd (pwbuf, pw) == -1) {
216 errno = ENOMEM;
217 return -1;
219 return 0;
222 #ifdef HAVE_FGETPWENT
223 gint32
224 Mono_Posix_Syscall_fgetpwent (void *stream, struct Mono_Posix_Syscall__Passwd *pwbuf)
226 struct passwd *pw;
228 if (pwbuf == NULL) {
229 errno = EFAULT;
230 return -1;
233 errno = 0;
234 pw = fgetpwent ((FILE*) stream);
235 if (pw == NULL)
236 return -1;
238 if (copy_passwd (pwbuf, pw) == -1) {
239 errno = ENOMEM;
240 return -1;
242 return 0;
244 #endif /* ndef HAVE_FGETPWENT */
247 Mono_Posix_Syscall_setpwent (void)
249 errno = 0;
250 setpwent ();
251 return errno == 0 ? 0 : -1;
255 Mono_Posix_Syscall_endpwent (void)
257 errno = 0;
258 endpwent ();
259 return errno == 0 ? 0 : -1;
262 G_END_DECLS
265 * vim: noexpandtab