Luna/libc/src/shadow.cpp
apio e2ff0ad273
All checks were successful
Build and test / build (push) Successful in 2m58s
libc: Propagate errors correctly in shadow functions
2024-04-18 21:25:36 +02:00

117 lines
2.8 KiB
C++

#include <fcntl.h>
#include <shadow.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static struct spwd spwd;
static FILE* f { nullptr };
static char s_buf[4096];
extern char* _strtok_once(char* str, const char* delim);
extern "C"
{
struct spwd* getspent()
{
struct spwd* result;
if (getspent_r(&spwd, s_buf, sizeof(s_buf), &result) < 0) return nullptr;
return result;
}
int getspent_r(struct spwd* spbuf, char* buf, size_t buflen, struct spwd** spbufp)
{
*spbufp = nullptr;
if (!f)
{
f = fopen("/etc/shadow", "r");
if (!f) return -1;
fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
}
return fgetspent_r(f, spbuf, buf, buflen, spbufp);
}
int fgetspent_r(FILE* stream, struct spwd* spbuf, char* buf, size_t buflen, struct spwd** spbufp)
{
*spbufp = nullptr;
while (true)
{
char* rc = fgets(buf, buflen, stream);
if (!rc) return -1;
char* name = _strtok_once(rc, ":\n");
if (!name) continue;
char* passwd = _strtok_once(nullptr, ":\n");
if (!passwd) continue;
char* lstchg = _strtok_once(nullptr, ":\n");
if (!lstchg) continue;
char* min = _strtok_once(nullptr, ":\n");
if (!min) continue;
char* max = _strtok_once(nullptr, ":\n");
if (!max) continue;
char* warn = _strtok_once(nullptr, ":\n");
if (!warn) continue;
char* inact = _strtok_once(nullptr, ":\n");
if (!inact) continue;
char* expire = _strtok_once(nullptr, ":\n");
if (!expire) continue;
char* flag = _strtok_once(nullptr, ":\n");
if (!flag) continue;
spbuf->sp_namp = name;
spbuf->sp_pwdp = passwd;
spbuf->sp_lstchg = (long)strtol(lstchg, nullptr, 10);
spbuf->sp_min = (long)strtol(min, nullptr, 10);
spbuf->sp_max = (long)strtol(max, nullptr, 10);
spbuf->sp_warn = (long)strtol(warn, nullptr, 10);
spbuf->sp_inact = (long)strtol(inact, nullptr, 10);
spbuf->sp_expire = (long)strtol(expire, nullptr, 10);
spbuf->sp_flag = (unsigned long)strtoul(flag, nullptr, 10);
*spbufp = spbuf;
return 0;
}
}
struct spwd* getspnam(const char* name)
{
setspent();
struct spwd* entry;
while ((entry = getspent()))
{
if (!strcmp(entry->sp_namp, name)) { return entry; }
}
return entry;
}
void setspent()
{
if (f) rewind(f);
}
void endspent()
{
if (f)
{
fclose(f);
f = nullptr;
}
}
}