BarryServer : Git

All the code for all my projects
// BarryServer : Git / OrionLibC / blob / 2e2f919ac415da5f75aeb6b83981b659fa5072eb / grp / getgr.c

// Related

OrionLibC

Barry Using POSIX names for structs 11f4683 (2 years, 2 months 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;
}