OrionLibC
Barry Using POSIX names for structs 11f4683 (3 years, 1 month 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;
}