* Authors:
* Jonathan Pryor (jonpryor@vt.edu)
*
- * Copyright (C) 2004 Jonathan Pryor
+ * Copyright (C) 2004-2005 Jonathan Pryor
*/
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
+#include "map.h"
#include "mph.h"
G_BEGIN_DECLS
-struct Mono_Posix_Syscall__Passwd {
- /* string */ char *pw_name;
- /* string */ char *pw_passwd;
- /* uid_t */ mph_uid_t pw_uid;
- /* gid_t */ mph_gid_t pw_gid;
- /* string */ char *pw_gecos;
- /* string */ char *pw_dir;
- /* string */ char *pw_shell;
- /* string */ char *_pw_buf_;
+static const mph_string_offset_t
+passwd_offsets[] = {
+ MPH_STRING_OFFSET (struct passwd, pw_name, MPH_STRING_OFFSET_PTR),
+ MPH_STRING_OFFSET (struct passwd, pw_passwd, MPH_STRING_OFFSET_PTR),
+#if HAVE_STRUCT_PASSWD_PW_GECOS
+ MPH_STRING_OFFSET (struct passwd, pw_gecos, MPH_STRING_OFFSET_PTR),
+#endif /* def HAVE_STRUCT_PASSWD_PW_GECOS */
+ MPH_STRING_OFFSET (struct passwd, pw_dir, MPH_STRING_OFFSET_PTR),
+ MPH_STRING_OFFSET (struct passwd, pw_shell, MPH_STRING_OFFSET_PTR)
+};
+
+static const mph_string_offset_t
+mph_passwd_offsets[] = {
+ MPH_STRING_OFFSET (struct Mono_Posix_Syscall__Passwd, pw_name, MPH_STRING_OFFSET_PTR),
+ MPH_STRING_OFFSET (struct Mono_Posix_Syscall__Passwd, pw_passwd, MPH_STRING_OFFSET_PTR),
+#if HAVE_STRUCT_PASSWD_PW_GECOS
+ MPH_STRING_OFFSET (struct Mono_Posix_Syscall__Passwd, pw_gecos, MPH_STRING_OFFSET_PTR),
+#endif /* def HAVE_STRUCT_PASSWD_PW_GECOS */
+ MPH_STRING_OFFSET (struct Mono_Posix_Syscall__Passwd, pw_dir, MPH_STRING_OFFSET_PTR),
+ MPH_STRING_OFFSET (struct Mono_Posix_Syscall__Passwd, pw_shell, MPH_STRING_OFFSET_PTR)
};
/*
static int
copy_passwd (struct Mono_Posix_Syscall__Passwd *to, struct passwd *from)
{
- enum {PW_NAME = 0, PW_PASSWD, PW_GECOS, PW_DIR, PW_SHELL, PW_LAST};
- size_t buflen, len[PW_LAST];
- /* bool */ unsigned char copy[PW_LAST] = {0};
- const char *source[PW_LAST];
- char **dest[PW_LAST];
- int i;
- char *cur;
+ char *buf;
+ buf = _mph_copy_structure_strings (to, mph_passwd_offsets,
+ from, passwd_offsets, sizeof(passwd_offsets)/sizeof(passwd_offsets[0]));
to->pw_uid = from->pw_uid;
to->pw_gid = from->pw_gid;
- to->pw_name = NULL;
- to->pw_passwd = NULL;
- to->pw_gecos = NULL;
- to->pw_dir = NULL;
- to->pw_shell = NULL;
- to->_pw_buf_ = NULL;
-
- source[PW_NAME] = from->pw_name;
- source[PW_PASSWD] = from->pw_passwd;
- source[PW_GECOS] = from->pw_gecos;
- source[PW_DIR] = from->pw_dir;
- source[PW_SHELL] = from->pw_shell;
-
- dest[PW_NAME] = &to->pw_name;
- dest[PW_PASSWD] = &to->pw_passwd;
- dest[PW_GECOS] = &to->pw_gecos;
- dest[PW_DIR] = &to->pw_dir;
- dest[PW_SHELL] = &to->pw_shell;
-
- buflen = PW_LAST;
-
- /* over-rigorous checking for integer overflow */
- for (i = 0; i != PW_LAST; ++i) {
- len[i] = strlen (source[i]);
- if (len[i] < INT_MAX - buflen) {
- buflen += len[i];
- copy[i] = 1;
- }
- }
-
- cur = to->_pw_buf_ = (char*) malloc (buflen);
- if (cur == NULL) {
+ to->_pw_buf_ = buf;
+ if (buf == NULL) {
return -1;
}
- for (i = 0; i != PW_LAST; ++i) {
- if (copy[i]) {
- *dest[i] = strcpy (cur, source[i]);
- cur += (len[i] + 1);
- }
- }
-
return 0;
}
return -1;
}
+ errno = 0;
pw = getpwnam (name);
if (pw == NULL)
return -1;
gint32
Mono_Posix_Syscall_getpwnam_r (const char *name,
struct Mono_Posix_Syscall__Passwd *pwbuf,
- struct passwd **pwbufp)
+ void **pwbufp)
{
char *buf, *buf2;
size_t buflen;
return -1;
}
buf = buf2;
- } while ((r = getpwnam_r (name, &_pwbuf, buf, buflen, pwbufp)) &&
+ errno = 0;
+ } while ((r = getpwnam_r (name, &_pwbuf, buf, buflen, (struct passwd**) pwbufp)) &&
recheck_range (r));
+ if (r == 0 && !(*pwbufp))
+ /* On solaris, this function returns 0 even if the entry was not found */
+ r = errno = ENOENT;
+
if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
r = errno = ENOMEM;
free (buf);
gint32
Mono_Posix_Syscall_getpwuid_r (mph_uid_t uid,
struct Mono_Posix_Syscall__Passwd *pwbuf,
- struct passwd **pwbufp)
+ void **pwbufp)
{
char *buf, *buf2;
size_t buflen;
return -1;
}
buf = buf2;
- } while ((r = getpwuid_r (uid, &_pwbuf, buf, buflen, pwbufp)) &&
+ errno = 0;
+ } while ((r = getpwuid_r (uid, &_pwbuf, buf, buflen, (struct passwd**) pwbufp)) &&
recheck_range (r));
+ if (r == 0 && !(*pwbufp))
+ /* On solaris, this function returns 0 even if the entry was not found */
+ r = errno = ENOENT;
+
if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
r = errno = ENOMEM;
free (buf);
}
#endif /* ndef HAVE_GETPWUID_R */
+#if HAVE_GETPWENT
gint32
Mono_Posix_Syscall_getpwent (struct Mono_Posix_Syscall__Passwd *pwbuf)
{
return -1;
}
+ errno = 0;
pw = getpwent ();
if (pw == NULL)
return -1;
}
return 0;
}
+#endif /* def HAVE_GETPWENT */
#ifdef HAVE_FGETPWENT
gint32
-Mono_Posix_Syscall_fgetpwent (FILE *stream, struct Mono_Posix_Syscall__Passwd *pwbuf)
+Mono_Posix_Syscall_fgetpwent (void *stream, struct Mono_Posix_Syscall__Passwd *pwbuf)
{
struct passwd *pw;
return -1;
}
- pw = fgetpwent (stream);
+ errno = 0;
+ pw = fgetpwent ((FILE*) stream);
if (pw == NULL)
return -1;
}
#endif /* ndef HAVE_FGETPWENT */
+#if HAVE_SETPWENT
+int
+Mono_Posix_Syscall_setpwent (void)
+{
+ errno = 0;
+ do {
+ setpwent ();
+ } while (errno == EINTR);
+ mph_return_if_val_in_list5(errno, EIO, EMFILE, ENFILE, ENOMEM, ERANGE);
+ return 0;
+}
+#endif /* def HAVE_SETPWENT */
+
+#if HAVE_ENDPWENT
+int
+Mono_Posix_Syscall_endpwent (void)
+{
+ errno = 0;
+ endpwent ();
+ if (errno == EIO)
+ return -1;
+ return 0;
+}
+#endif /* def HAVE_ENDPWENT */
+
G_END_DECLS
/*