#include #include "c.h" #include "pwdutils.h" #include "xalloc.h" /* Returns allocated passwd and allocated pwdbuf to store passwd strings * fields. In case of error returns NULL and set errno, for unknown user set * errno to EINVAL */ struct passwd *xgetpwnam(const char *username, char **pwdbuf) { struct passwd *pwd = NULL, *res = NULL; int rc; if (!pwdbuf || !username) return NULL; *pwdbuf = xmalloc(UL_GETPW_BUFSIZ); pwd = xcalloc(1, sizeof(struct passwd)); errno = 0; rc = getpwnam_r(username, pwd, *pwdbuf, UL_GETPW_BUFSIZ, &res); if (rc != 0) { errno = rc; goto failed; } if (!res) { errno = EINVAL; goto failed; } return pwd; failed: free(pwd); free(*pwdbuf); return NULL; } char *xgetlogin(void) { struct passwd *pw = NULL; uid_t ruid; char *user; user = getlogin(); if (user) return xstrdup(user); /* GNU Hurd implementation has an extension where a process can exist in a * non-conforming environment, and thus be outside the realms of POSIX * process identifiers; on this platform, getuid() fails with a status of * (uid_t)(-1) and sets errno if a program is run from a non-conforming * environment. * * http://austingroupbugs.net/view.php?id=511 */ errno = 0; ruid = getuid(); if (errno == 0) pw = getpwuid(ruid); if (pw && pw->pw_name && *pw->pw_name) return xstrdup(pw->pw_name); return NULL; } #ifdef TEST_PROGRAM int main(int argc, char *argv[]) { char *buf = NULL; struct passwd *pwd = NULL; if (argc != 2) { fprintf(stderr, "usage: %s \n", argv[0]); return EXIT_FAILURE; } pwd = xgetpwnam(argv[1], &buf); if (!pwd) err(EXIT_FAILURE, "failed to get %s pwd entry", argv[1]); printf("Username: %s\n", pwd->pw_name); printf("UID: %d\n", pwd->pw_uid); printf("HOME: %s\n", pwd->pw_dir); printf("GECO: %s\n", pwd->pw_gecos); free(pwd); free(buf); printf("Current: %s\n", (buf = xgetlogin())); free(buf); return EXIT_SUCCESS; } #endif /* TEST_PROGRAM */