(root)/
util-linux-2.39/
lib/
pwdutils.c
       1  /*
       2   * No copyright is claimed.  This code is in the public domain; do with
       3   * it what you wish.
       4   */
       5  #include <stdlib.h>
       6  #include <assert.h>
       7  
       8  #include "c.h"
       9  #include "pwdutils.h"
      10  #include "xalloc.h"
      11  
      12  /* Returns allocated passwd and allocated pwdbuf to store passwd strings
      13   * fields. In case of error returns NULL and set errno, for unknown user set
      14   * errno to EINVAL
      15   */
      16  struct passwd *xgetpwnam(const char *username, char **pwdbuf)
      17  {
      18  	struct passwd *pwd = NULL, *res = NULL;
      19  	int rc;
      20  
      21  	assert(pwdbuf);
      22  	assert(username);
      23  
      24  	*pwdbuf = xmalloc(UL_GETPW_BUFSIZ);
      25  	pwd = xcalloc(1, sizeof(struct passwd));
      26  
      27  	errno = 0;
      28  	rc = getpwnam_r(username, pwd, *pwdbuf, UL_GETPW_BUFSIZ, &res);
      29  	if (rc != 0) {
      30  		errno = rc;
      31  		goto failed;
      32  	}
      33  	if (!res) {
      34  		errno = EINVAL;
      35  		goto failed;
      36  	}
      37  	return pwd;
      38  failed:
      39  	free(pwd);
      40  	free(*pwdbuf);
      41  	return NULL;
      42  }
      43  
      44  /* Returns allocated group and allocated grpbuf to store group strings
      45   * fields. In case of error returns NULL and set errno, for unknown group set
      46   * errno to EINVAL
      47   */
      48  struct group *xgetgrnam(const char *groupname, char **grpbuf)
      49  {
      50  	struct group *grp = NULL, *res = NULL;
      51  	int rc;
      52  
      53  	assert(grpbuf);
      54  	assert(groupname);
      55  
      56  	*grpbuf = xmalloc(UL_GETPW_BUFSIZ);
      57  	grp = xcalloc(1, sizeof(struct group));
      58  
      59  	errno = 0;
      60  	rc = getgrnam_r(groupname, grp, *grpbuf, UL_GETPW_BUFSIZ, &res);
      61  	if (rc != 0) {
      62  		errno = rc;
      63  		goto failed;
      64  	}
      65  	if (!res) {
      66  		errno = EINVAL;
      67  		goto failed;
      68  	}
      69  	return grp;
      70  failed:
      71  	free(grp);
      72  	free(*grpbuf);
      73  	return NULL;
      74  }
      75  
      76  struct passwd *xgetpwuid(uid_t uid, char **pwdbuf)
      77  {
      78  	struct passwd *pwd = NULL, *res = NULL;
      79  	int rc;
      80  
      81  	assert(pwdbuf);
      82  
      83  	*pwdbuf = xmalloc(UL_GETPW_BUFSIZ);
      84  	pwd = xcalloc(1, sizeof(struct passwd));
      85  
      86  	errno = 0;
      87  	rc = getpwuid_r(uid, pwd, *pwdbuf, UL_GETPW_BUFSIZ, &res);
      88  	if (rc != 0) {
      89  		errno = rc;
      90  		goto failed;
      91  	}
      92  	if (!res) {
      93  		errno = EINVAL;
      94  		goto failed;
      95  	}
      96  	return pwd;
      97  failed:
      98  	free(pwd);
      99  	free(*pwdbuf);
     100  	return NULL;
     101  }
     102  
     103  char *xgetlogin(void)
     104  {
     105  	struct passwd *pw = NULL;
     106  	uid_t ruid;
     107  
     108  	/* GNU Hurd implementation has an extension where a process can exist in a
     109  	 * non-conforming environment, and thus be outside the realms of POSIX
     110  	 * process identifiers; on this platform, getuid() fails with a status of
     111  	 * (uid_t)(-1) and sets errno if a program is run from a non-conforming
     112  	 * environment.
     113  	 *
     114  	 * http://austingroupbugs.net/view.php?id=511
     115  	 *
     116  	 * The same implementation is useful for other systems, since getlogin(3)
     117  	 * shouldn't be used as actual identification.
     118  	 */
     119  	errno = 0;
     120  	ruid = getuid();
     121  
     122  	if (errno == 0)
     123  		pw = getpwuid(ruid);
     124  	if (pw && pw->pw_name && *pw->pw_name)
     125  		return xstrdup(pw->pw_name);
     126  
     127  	return NULL;
     128  }
     129  
     130  #ifdef TEST_PROGRAM
     131  int main(int argc, char *argv[])
     132  {
     133  	char *buf = NULL;
     134  	struct passwd *pwd = NULL;
     135  
     136  	if (argc != 2) {
     137  		fprintf(stderr, "usage: %s <username>\n", argv[0]);
     138  		return EXIT_FAILURE;
     139  	}
     140  
     141  	pwd = xgetpwnam(argv[1], &buf);
     142  	if (!pwd)
     143  		err(EXIT_FAILURE, "failed to get %s pwd entry", argv[1]);
     144  
     145  	printf("Username: %s\n", pwd->pw_name);
     146  	printf("UID:      %d\n", pwd->pw_uid);
     147  	printf("HOME:     %s\n", pwd->pw_dir);
     148  	printf("GECO:     %s\n", pwd->pw_gecos);
     149  
     150  	free(pwd);
     151  	free(buf);
     152  
     153  	printf("Current:  %s\n", (buf = xgetlogin()));
     154  	free(buf);
     155  
     156  	return EXIT_SUCCESS;
     157  }
     158  #endif /* TEST_PROGRAM */