util-linux/lib/pwdutils.c

97 lines
2.0 KiB
C

#include <stdlib.h>
#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 <username>\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 */