OrionLibC
Barry Using POSIX names for structs 11f4683 (3 years, 1 month ago)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <grp.h>
/* Parts of a /etc/group line */
enum GroupParts {
GROUP_NAME,
GROUP_GID,
GROUP_USERS,
};
static Group entry;
static char entryName[33];
static char *entryMembers[64];
static char entryUsers[64 * 33];
/* 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 Grouop */
static Group *
line_to_group(char *line)
{
if (!*line)
return NULL;
char gidstr[8];
get_part(line, GROUP_NAME, entryName);
get_part(line, GROUP_GID, gidstr);
get_part(line, GROUP_USERS, entryUsers);
int i, j = 0;
char *prev = entryUsers;
for (i = 0; entryUsers[i]; i++) {
if (entryUsers[i] != ' ')
continue;
entryUsers[i] = '\0';
entryMembers[j] = prev;
prev = entryUsers + 1;
j++;
}
entry.gr_name = entryName;
entry.gr_gid = number(gidstr);
entry.gr_mem = entryMembers;
return &entry;
}
/* Get group file entry by name */
Group *
getgrnam(const char *name)
{
int fd = open("/etc/group", O_RDONLY);
if (fd < 0)
return (Group *) 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, GROUP_NAME, tmp);
if (!strcmp(name, tmp))
break;
}
Group *res = line_to_group(line);
free(buf);
return res;
}
/* Get group file entry by ID */
Group *
getgrgid(gid_t gid)
{
int fd = open("/etc/group", O_RDONLY);
if (fd < 0)
return (Group *) 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];
gid_t gidLine;
for (line = buf; *line; line = next_line(line)) {
get_part(line, GROUP_GID, tmp);
gidLine = number(tmp);
if (gid == gidLine)
break;
}
Group *res = line_to_group(line);
free(buf);
return res;
}