apio
e10cc2d954
All checks were successful
continuous-integration/drone/push Build is passing
Similar mechanism to TRY(), but propagating C-like errors instead of Results on failure.
116 lines
2.4 KiB
C++
116 lines
2.4 KiB
C++
#include <bits/errno-return.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <grp.h>
|
|
#include <luna/Vector.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
static struct group grp;
|
|
static FILE* f { nullptr };
|
|
static char buf[4096];
|
|
|
|
static Vector<char*> g_members;
|
|
|
|
extern char* _strtok_once(char* str, const char* delim);
|
|
|
|
extern "C"
|
|
{
|
|
static Result<struct group*> try_getgrent()
|
|
{
|
|
if (!f)
|
|
{
|
|
f = fopen("/etc/group", "r");
|
|
if (!f) return nullptr;
|
|
fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
|
|
}
|
|
|
|
while (true)
|
|
{
|
|
char* rc = fgets(buf, sizeof(buf), f);
|
|
if (!rc) return nullptr;
|
|
|
|
char* name = _strtok_once(rc, ":\n");
|
|
if (!name) continue;
|
|
|
|
char* passwd = _strtok_once(nullptr, ":\n");
|
|
if (!passwd) continue;
|
|
|
|
char* gid = _strtok_once(nullptr, ":\n");
|
|
if (!gid) continue;
|
|
|
|
char* members = _strtok_once(nullptr, ":\n");
|
|
if (!members) continue;
|
|
|
|
g_members.clear();
|
|
|
|
char* member = strtok(members, ",");
|
|
TRY(g_members.try_append(member));
|
|
|
|
if (member)
|
|
{
|
|
while (true)
|
|
{
|
|
member = strtok(nullptr, ",");
|
|
TRY(g_members.try_append(member));
|
|
if (!member) break;
|
|
}
|
|
}
|
|
|
|
grp.gr_name = name;
|
|
grp.gr_passwd = passwd;
|
|
grp.gr_gid = (gid_t)strtoul(gid, NULL, 10);
|
|
grp.gr_mem = g_members.data();
|
|
|
|
return &grp;
|
|
}
|
|
}
|
|
|
|
struct group* getgrent()
|
|
{
|
|
return TRY_OR_SET_ERRNO(try_getgrent(), group*, nullptr);
|
|
}
|
|
|
|
struct group* getgrnam(const char* name)
|
|
{
|
|
setgrent();
|
|
|
|
struct group* entry;
|
|
|
|
while ((entry = getgrent()))
|
|
{
|
|
if (!strcmp(entry->gr_name, name)) { return entry; }
|
|
}
|
|
|
|
return entry;
|
|
}
|
|
|
|
struct group* getgrgid(gid_t gid)
|
|
{
|
|
setgrent();
|
|
|
|
struct group* entry;
|
|
|
|
while ((entry = getgrent()))
|
|
{
|
|
if (entry->gr_gid == gid) { return entry; }
|
|
}
|
|
|
|
return entry;
|
|
}
|
|
|
|
void setgrent()
|
|
{
|
|
if (f) rewind(f);
|
|
}
|
|
|
|
void endgrent()
|
|
{
|
|
if (f)
|
|
{
|
|
fclose(f);
|
|
f = nullptr;
|
|
}
|
|
}
|
|
}
|