1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
/*
* No copyright is claimed. This code is in the public domain; do with
* it what you wish.
*/
#include <stdlib.h>
#include <assert.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;
assert(pwdbuf);
assert(username);
*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;
}
/* Returns allocated group and allocated grpbuf to store group strings
* fields. In case of error returns NULL and set errno, for unknown group set
* errno to EINVAL
*/
struct group *xgetgrnam(const char *groupname, char **grpbuf)
{
struct group *grp = NULL, *res = NULL;
int rc;
assert(grpbuf);
assert(groupname);
*grpbuf = xmalloc(UL_GETPW_BUFSIZ);
grp = xcalloc(1, sizeof(struct group));
errno = 0;
rc = getgrnam_r(groupname, grp, *grpbuf, UL_GETPW_BUFSIZ, &res);
if (rc != 0) {
errno = rc;
goto failed;
}
if (!res) {
errno = EINVAL;
goto failed;
}
return grp;
failed:
free(grp);
free(*grpbuf);
return NULL;
}
struct passwd *xgetpwuid(uid_t uid, char **pwdbuf)
{
struct passwd *pwd = NULL, *res = NULL;
int rc;
assert(pwdbuf);
*pwdbuf = xmalloc(UL_GETPW_BUFSIZ);
pwd = xcalloc(1, sizeof(struct passwd));
errno = 0;
rc = getpwuid_r(uid, 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;
/* 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
*
* The same implementation is useful for other systems, since getlogin(3)
* shouldn't be used as actual identification.
*/
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 */
|