diff options
author | Andreas Kling <awesomekling@gmail.com> | 2018-11-06 22:27:51 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2018-11-06 22:27:51 +0100 |
commit | 90bab5ea717682d819609e9238ab6785a450b696 (patch) | |
tree | 3351641a076ff2de7baeee33d1fc2ed4110bae24 /LibC | |
parent | e5e0bffd769ed29c42dc07e70dc40639b6ba51c7 (diff) | |
download | serenity-90bab5ea717682d819609e9238ab6785a450b696.zip |
Add getgrent() family of functions.
Diffstat (limited to 'LibC')
-rw-r--r-- | LibC/Makefile | 1 | ||||
-rw-r--r-- | LibC/grp.cpp | 121 | ||||
-rw-r--r-- | LibC/grp.h | 21 |
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 |