From 90bab5ea717682d819609e9238ab6785a450b696 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 6 Nov 2018 22:27:51 +0100 Subject: [PATCH] Add getgrent() family of functions. --- Base/etc/group | 3 ++ LibC/Makefile | 1 + LibC/grp.cpp | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ LibC/grp.h | 21 +++++++++ Userland/id.cpp | 4 +- 5 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 Base/etc/group create mode 100644 LibC/grp.cpp create mode 100644 LibC/grp.h diff --git a/Base/etc/group b/Base/etc/group new file mode 100644 index 00000000000..48c0d4d27ed --- /dev/null +++ b/Base/etc/group @@ -0,0 +1,3 @@ +root:x:0: +wheel:x:1:andreas +users:x:100:andreas diff --git a/LibC/Makefile b/LibC/Makefile index 03f367cf58c..2650fbc886a 100644 --- a/LibC/Makefile +++ b/LibC/Makefile @@ -20,6 +20,7 @@ LIBC_OBJS = \ getopt.o \ scanf.o \ pwd.o \ + grp.o \ times.o \ termcap.o \ setjmp.o \ diff --git a/LibC/grp.cpp b/LibC/grp.cpp new file mode 100644 index 00000000000..0081ea48e65 --- /dev/null +++ b/LibC/grp.cpp @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include + +extern "C" { + +#define GRDB_STR_MAX_LEN 256 + +struct group_with_strings : public group { + char name_buffer[GRDB_STR_MAX_LEN]; + char passwd_buffer[GRDB_STR_MAX_LEN]; + char* members[32]; + char members_buffer[32][32]; +}; + +static FILE* __grdb_stream = nullptr; +static unsigned __grdb_line_number = 0; +static struct group_with_strings* __grdb_entry = nullptr; + +void setgrent() +{ + __grdb_line_number = 0; + if (__grdb_stream) { + rewind(__grdb_stream); + } else { + __grdb_stream = fopen("/etc/group", "r"); + if (!__grdb_stream) { + perror("open /etc/group"); + } + assert(__grdb_stream); + __grdb_entry = (struct group_with_strings*)mmap(nullptr, getpagesize()); + set_mmap_name(__grdb_entry, getpagesize(), "setgrent"); + } +} + +void endgrent() +{ + __grdb_line_number = 0; + if (__grdb_stream) { + fclose(__grdb_stream); + __grdb_stream = nullptr; + } + if (__grdb_entry) { + munmap(__grdb_entry, getpagesize()); + __grdb_entry = nullptr; + } +} + +struct group* getgrgid(gid_t gid) +{ + setgrent(); + while (auto* gr = getgrent()) { + if (gr->gr_gid == gid) + return gr; + } + return nullptr; +} + +struct group* getgrname(const char* name) +{ + setgrent(); + while (auto* gr = getgrent()) { + if (!strcmp(gr->gr_name, name)) + return gr; + } + return nullptr; +} + +struct group* getgrent() +{ + if (!__grdb_stream) + setgrent(); + + assert(__grdb_stream); + if (feof(__grdb_stream)) + return nullptr; + +next_entry: + char buffer[1024]; + ++__grdb_line_number; + char* s = fgets(buffer, sizeof(buffer), __grdb_stream); + if (!s) + return nullptr; + assert(__grdb_stream); + if (feof(__grdb_stream)) + return nullptr; + String line(s); + auto parts = line.split(':'); + if (parts.size() != 4) { + fprintf(stderr, "getgrent(): Malformed entry on line %u\n", __grdb_line_number); + goto next_entry; + } + auto& e_name = parts[0]; + auto& e_passwd = parts[1]; + auto& e_gid_string = parts[2]; + auto& e_members_string = parts[3]; + bool ok; + gid_t e_gid = e_gid_string.toUInt(ok); + if (!ok) { + fprintf(stderr, "getgrent(): Malformed GID on line %u\n", __grdb_line_number); + goto next_entry; + } + auto members = e_members_string.split(','); + __grdb_entry->gr_gid = e_gid; + __grdb_entry->gr_name = __grdb_entry->name_buffer; + __grdb_entry->gr_passwd = __grdb_entry->passwd_buffer; + for (size_t i = 0; i < parts.size(); ++i) { + __grdb_entry->members[i] = __grdb_entry->members_buffer[i]; + strcpy(__grdb_entry->members_buffer[i], parts[i].characters()); + } + __grdb_entry->members[parts.size()] = nullptr; + __grdb_entry->gr_mem = __grdb_entry->members; + strncpy(__grdb_entry->name_buffer, e_name.characters(), GRDB_STR_MAX_LEN); + strncpy(__grdb_entry->passwd_buffer, e_passwd.characters(), GRDB_STR_MAX_LEN); + return __grdb_entry; +} + +} diff --git a/LibC/grp.h b/LibC/grp.h new file mode 100644 index 00000000000..e29d4b95454 --- /dev/null +++ b/LibC/grp.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +__BEGIN_DECLS + +struct group { + char* gr_name; + char* gr_passwd; + gid_t gr_gid; + char** gr_mem; +}; + +struct group* getgrent(); +void setgrent(); +void endgrent(); +struct group* getgrnam(const char* name); +struct group* getgrgid(gid_t); + +__END_DECLS diff --git a/Userland/id.cpp b/Userland/id.cpp index 44a31264fc5..e82cfcf2c41 100644 --- a/Userland/id.cpp +++ b/Userland/id.cpp @@ -1,6 +1,7 @@ #include #include #include +#include int main(int c, char** v) { @@ -8,8 +9,9 @@ int main(int c, char** v) gid_t gid = getgid(); struct passwd* pw = getpwuid(uid); + struct group* gr = getgrgid(gid); - printf("uid=%u(%s), gid=%u, pid=%u\n", uid, pw ? pw->pw_name : "n/a", gid, getpid()); + printf("uid=%u(%s), gid=%u(%s)\n", uid, pw ? pw->pw_name : "n/a", gid, gr ? gr->gr_name : "n/a", getpid()); return 0; }