97 lines
2.0 KiB
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 */
|