libc: Allow empty fields in the password file
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-04-08 22:19:51 +02:00
parent 46be0bd458
commit e5a3bbcbbc
Signed by: apio
GPG Key ID: B8A7D06E42258954

View File

@ -7,6 +7,36 @@ static struct passwd pwd;
static FILE* f { nullptr };
static char buf[4096];
// Variant of strtok that returns empty tokens when there are several delimiters, instead of skipping all at once.
// Example:
// strtok("hello:world::!:", ":") -> "hello", "world", "!"
// _strtok_once("hello:world::!:", ":") -> "hello", "world", "", "!"
static char* _strtok_once(char* str, const char* delim)
{
static char* s = nullptr;
if (str) s = str;
if (!s) return nullptr;
if (*s)
{
if (*s == 0) return nullptr;
size_t use = strcspn(s, delim);
char* result = s;
if (s[use] != 0)
{
s[use] = 0;
s += (use + 1);
}
else { s = nullptr; }
return result;
}
return nullptr;
}
extern "C"
{
struct passwd* getpwent()
@ -22,25 +52,25 @@ extern "C"
char* rc = fgets(buf, sizeof(buf), f);
if (!rc) return nullptr;
char* name = strtok(rc, ":\n");
char* name = _strtok_once(rc, ":\n");
if (!name) continue;
char* passwd = strtok(nullptr, ":\n");
char* passwd = _strtok_once(nullptr, ":\n");
if (!passwd) continue;
char* uid = strtok(nullptr, ":\n");
char* uid = _strtok_once(nullptr, ":\n");
if (!uid) continue;
char* gid = strtok(nullptr, ":\n");
char* gid = _strtok_once(nullptr, ":\n");
if (!gid) continue;
char* gecos = strtok(nullptr, ":\n");
char* gecos = _strtok_once(nullptr, ":\n");
if (!gecos) continue;
char* dir = strtok(nullptr, ":\n");
char* dir = _strtok_once(nullptr, ":\n");
if (!dir) continue;
char* shell = strtok(nullptr, ":\n");
char* shell = _strtok_once(nullptr, ":\n");
if (!shell) continue;
pwd.pw_name = name;