BarryServer : Git

All the code for all my projects
// BarryServer : Git / OrionLibC / blob / master / pwd / getpw.c

// Related

OrionLibC

Barry Using POSIX names for structs 11f4683 (2 years, 2 months ago)
#include <sys/limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>

#include <stdio.h>

/* Parts of a /etc/passwd line */
enum PasswordParts {
	PASSWD_USERNAME,
	PASSWD_PASSWORD,
	PASSWD_UID,
	PASSWD_GID,
	PASSWD_INFO,
	PASSWD_HOMEDIR,
	PASSWD_SHELL,
};

static Passwd entry;
static char entryUsername[33];
static char entryPassword[128];
static char entryInfo[1024];
static char entryHomeDir[PATH_MAX];
static char entryShell[PATH_MAX];

/* Get part of a password line */
static char *
get_part(char *line, int index, char *buf)
{
	int i, len = 0;
	char *start;
	for (i = 0; i < index; i++)
		while (*line++ != ':');
	start = line;
	while (*line != ':' && *line != '\n') {
		line++;
		len++;
	}
	memcpy(buf, start, len);
	buf[len] = '\0';
	return buf;
}

/* Convert a string to a number */
static int
number(char *str)
{
	int num = 0, col = 1, len;
	for (len = 0; str[len] >= '0' && str[len] <= '9'; len++);
	while (len--) {
		num += (str[len] - '0') * col;
		col *= 10;
	}
	return num;
}

/* Move to next line */
static char *
next_line(char *line)
{
	while (*line++ != '\n');
	return line;
}

/* Convert line to Passwd */
static Passwd *
line_to_passwd(char *line)
{
	if (!*line)
		return NULL;

	char uidstr[8], gidstr[8];
	get_part(line, PASSWD_USERNAME, entryUsername);
	get_part(line, PASSWD_PASSWORD, entryPassword);
	get_part(line, PASSWD_UID, uidstr);
	get_part(line, PASSWD_GID, gidstr);
	get_part(line, PASSWD_INFO, entryInfo);
	get_part(line, PASSWD_HOMEDIR, entryHomeDir);
	get_part(line, PASSWD_SHELL, entryShell);

	entry.pw_name = entryUsername;
	entry.pw_passwd = entryPassword;
	entry.pw_uid = number(uidstr);
	entry.pw_gid = number(gidstr);
	entry.pw_gecos = entryInfo;
	entry.pw_dir = entryHomeDir;
	entry.pw_shell = entryShell;

	return &entry;
}

/* Get password file entry by name */
Passwd *
getpwnam(const char *username)
{

	int fd = open("/etc/passwd", O_RDONLY);
	if (fd < 0)
		return (Passwd *) fd;
	size_t sz = lseek(fd, 0, SEEK_END);
	lseek(fd, 0, SEEK_SET);
	char *buf = malloc(sz);
	read(fd, buf, sz);
	close(fd);

	char *line, tmp[33];
	for (line = buf; *line; line = next_line(line)) {
		get_part(line, PASSWD_USERNAME, tmp);
		if (!strcmp(username, tmp))
			break;
	}

	Passwd *res = line_to_passwd(line);

	free(buf);
	return res;
}

/* Get password file entry by ID */
Passwd *
getpwuid(uid_t uid)
{
	int fd = open("/etc/passwd", O_RDONLY);
	if (fd < 0)
		return (Passwd *) fd;
	size_t sz = lseek(fd, 0, SEEK_END);
	lseek(fd, 0, SEEK_SET);
	char *buf = malloc(sz);
	read(fd, buf, sz);
	close(fd);

	char *line, tmp[8];
	uid_t uidLine;
	for (line = buf; *line; line = next_line(line)) {
		get_part(line, PASSWD_UID, tmp);
		uidLine = number(tmp);
		if (uid == uidLine)
			break;
	}

	Passwd *res = line_to_passwd(line);

	free(buf);
	return res;
}