summaryrefslogtreecommitdiff
path: root/LibC
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-06 22:27:51 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-06 22:27:51 +0100
commit90bab5ea717682d819609e9238ab6785a450b696 (patch)
tree3351641a076ff2de7baeee33d1fc2ed4110bae24 /LibC
parente5e0bffd769ed29c42dc07e70dc40639b6ba51c7 (diff)
downloadserenity-90bab5ea717682d819609e9238ab6785a450b696.zip
Add getgrent() family of functions.
Diffstat (limited to 'LibC')
-rw-r--r--LibC/Makefile1
-rw-r--r--LibC/grp.cpp121
-rw-r--r--LibC/grp.h21
3 files changed, 143 insertions, 0 deletions
diff --git a/LibC/Makefile b/LibC/Makefile
index 03f367cf58..2650fbc886 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 0000000000..0081ea48e6
--- /dev/null
+++ b/LibC/grp.cpp
@@ -0,0 +1,121 @@
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <AK/String.h>
+
+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 0000000000..e29d4b9545
--- /dev/null
+++ b/LibC/grp.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__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