diff --git a/AK/Compiler.h b/AK/Compiler.h index 0ae775e888..f7ebfa12d6 100644 --- a/AK/Compiler.h +++ b/AK/Compiler.h @@ -2,6 +2,7 @@ #define PACKED __attribute__ ((packed)) #define NORETURN __attribute__ ((noreturn)) +#undef ALWAYS_INLINE #define ALWAYS_INLINE __attribute__ ((always_inline)) #define NEVER_INLINE __attribute__ ((noinline)) #define MALLOC_ATTR __attribute__ ((malloc)) diff --git a/AK/String.cpp b/AK/String.cpp index e589438c1b..ccc61dd08f 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -75,4 +75,19 @@ ByteBuffer String::toByteBuffer() const return ByteBuffer::copy(reinterpret_cast(characters()), length()); } +unsigned String::toUInt(bool& ok) const +{ + unsigned value = 0; + for (size_t i = 0; i < length(); ++i) { + if (characters()[i] < '0' || characters()[i] > '9') { + ok = false; + return 0; + } + value = value * 10; + value += characters()[i] - '0'; + } + ok = true; + return value; +} + } diff --git a/AK/String.h b/AK/String.h index 023d9f300e..b639fe478c 100644 --- a/AK/String.h +++ b/AK/String.h @@ -44,6 +44,8 @@ public: { } + unsigned toUInt(bool& ok) const; + String toLowercase() const { if (!m_impl) diff --git a/Base/etc/passwd b/Base/etc/passwd new file mode 100644 index 0000000000..82d18b5b3d --- /dev/null +++ b/Base/etc/passwd @@ -0,0 +1,2 @@ +root:x:0:0:root:/:/bin/sh +andreas:x:100:100:Andreas Kling,,,:/users/andreas:/bin/sh diff --git a/Kernel/sync-sh b/Kernel/sync-sh index 99855924a2..680f3c33d2 100755 --- a/Kernel/sync-sh +++ b/Kernel/sync-sh @@ -1,6 +1,7 @@ cp -p _fs_contents.stock _fs_contents mkdir mnt mount -o loop _fs_contents mnt/ +cp -R ../Base/* mnt/ cp ../Userland/sh mnt/bin/sh cp ../Userland/id mnt/bin/id cp ../Userland/ps mnt/bin/ps diff --git a/LibC/Makefile b/LibC/Makefile index 9ff40f9ff0..39ff6620fb 100644 --- a/LibC/Makefile +++ b/LibC/Makefile @@ -19,6 +19,7 @@ LIBC_OBJS = \ signal.o \ getopt.o \ scanf.o \ + pwd.o \ entry.o OBJS = $(AK_OBJS) $(LIBC_OBJS) diff --git a/LibC/ctype.h b/LibC/ctype.h index 7d9f437aa4..0d067f33b8 100644 --- a/LibC/ctype.h +++ b/LibC/ctype.h @@ -9,7 +9,7 @@ ALWAYS_INLINE int isascii(int ch) ALWAYS_INLINE int isspace(int ch) { - return ch == ' ' || ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t' == '\v'; + return ch == ' ' || ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\v'; } ALWAYS_INLINE int islower(int c) diff --git a/LibC/pwd.cpp b/LibC/pwd.cpp new file mode 100644 index 0000000000..5ce0c360c1 --- /dev/null +++ b/LibC/pwd.cpp @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include + +struct passwd_with_strings : public passwd { + char name_buffer[256]; + char passwd_buffer[256]; + char gecos_buffer[256]; + char dir_buffer[256]; + char shell_buffer[256]; +}; + +static FILE* __pwdb_stream = nullptr; +static unsigned __pwdb_line_number = 0; +static struct passwd_with_strings* __pwdb_entry = nullptr; + +void setpwent() +{ + __pwdb_line_number = 0; + if (__pwdb_stream) { + rewind(__pwdb_stream); + } else { + __pwdb_stream = fopen("/etc/passwd", "r"); + __pwdb_entry = (struct passwd_with_strings*)mmap(nullptr, getpagesize()); + } +} + +void endpwent() +{ + __pwdb_line_number = 0; + if (__pwdb_stream) { + fclose(__pwdb_stream); + __pwdb_stream = nullptr; + } + if (__pwdb_entry) { + munmap(__pwdb_entry, getpagesize()); + __pwdb_entry = nullptr; + } +} + +struct passwd* getpwuid(uid_t uid) +{ + setpwent(); + while (auto* pw = getpwent()) { + if (pw->pw_uid == uid) + return pw; + } + return nullptr; +} + +struct passwd* getpwnam(const char* name) +{ + setpwent(); + while (auto* pw = getpwent()) { + if (!strcmp(pw->pw_name, name)) + return pw; + } + return nullptr; +} + +struct passwd* getpwent() +{ + if (!__pwdb_stream) + setpwent(); + + if (feof(__pwdb_stream)) + return nullptr; + +next_entry: + char buffer[1024]; + ++__pwdb_line_number; + char* s = fgets(buffer, sizeof(buffer), __pwdb_stream); + if (!s) + return nullptr; + if (feof(__pwdb_stream)) + return nullptr; + String line(s); + auto parts = line.split(':'); + if (parts.size() != 7) { + fprintf(stderr, "getpwent(): Malformed entry on line %u\n", __pwdb_line_number); + goto next_entry; + } + auto& e_name = parts[0]; + auto& e_passwd = parts[1]; + auto& e_uid_string = parts[2]; + auto& e_gid_string = parts[3]; + auto& e_gecos = parts[4]; + auto& e_dir = parts[5]; + auto& e_shell = parts[6]; + bool ok; + uid_t e_uid = e_uid_string.toUInt(ok); + if (!ok) { + fprintf(stderr, "getpwent(): Malformed UID on line %u\n", __pwdb_line_number); + goto next_entry; + } + gid_t e_gid = e_gid_string.toUInt(ok); + if (!ok) { + fprintf(stderr, "getpwent(): Malformed GID on line %u\n", __pwdb_line_number); + goto next_entry; + } + __pwdb_entry->pw_uid = e_uid; + __pwdb_entry->pw_gid = e_gid; + __pwdb_entry->pw_name = __pwdb_entry->name_buffer; + __pwdb_entry->pw_passwd = __pwdb_entry->passwd_buffer; + __pwdb_entry->pw_gecos = __pwdb_entry->gecos_buffer; + __pwdb_entry->pw_dir = __pwdb_entry->dir_buffer; + __pwdb_entry->pw_shell = __pwdb_entry->shell_buffer; + strncpy(__pwdb_entry->name_buffer, e_name.characters(), e_name.length()); + strncpy(__pwdb_entry->passwd_buffer, e_passwd.characters(), e_passwd.length()); + strncpy(__pwdb_entry->gecos_buffer, e_gecos.characters(), e_gecos.length()); + strncpy(__pwdb_entry->dir_buffer, e_dir.characters(), e_dir.length()); + strncpy(__pwdb_entry->shell_buffer, e_shell.characters(), e_shell.length()); + return __pwdb_entry; +} diff --git a/LibC/pwd.h b/LibC/pwd.h new file mode 100644 index 0000000000..81f1053305 --- /dev/null +++ b/LibC/pwd.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +__BEGIN_DECLS + +struct passwd { + char* pw_name; + char* pw_passwd; + uid_t pw_uid; + gid_t pw_gid; + char* pw_gecos; + char* pw_dir; + char* pw_shell; +}; + +struct passwd* getpwent(); +void setpwent(); +void endpwent(); +struct passwd* getpwnam(const char* name); +struct passwd* getpwuid(uid_t); + +__END_DECLS diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp index beea53547c..ec4d86ff41 100644 --- a/LibC/stdio.cpp +++ b/LibC/stdio.cpp @@ -42,7 +42,7 @@ char* fgets(char* buffer, int size, FILE* stream) int fgetc(FILE* stream) { char ch; - read(stream->fd, &ch, 1); + fread(&ch, sizeof(char), 1, stream); return ch; } diff --git a/LibC/stdio.h b/LibC/stdio.h index 8e61095d8f..c0c9927a6e 100644 --- a/LibC/stdio.h +++ b/LibC/stdio.h @@ -31,6 +31,9 @@ int getc(FILE*); int getchar(); FILE* fopen(const char* pathname, const char* mode); int fclose(FILE*); +void rewind(FILE*); +void clearerr(FILE*); +int feof(FILE*); size_t fread(void* ptr, size_t size, size_t nmemb, FILE*); size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE*); int fprintf(FILE*, const char* fmt, ...); diff --git a/LibC/sys/cdefs.h b/LibC/sys/cdefs.h index 68f4045e31..743ff03951 100644 --- a/LibC/sys/cdefs.h +++ b/LibC/sys/cdefs.h @@ -9,4 +9,3 @@ #define __BEGIN_DECLS #define __END_DECLS #endif - diff --git a/LibC/sys/mman.h b/LibC/sys/mman.h new file mode 100644 index 0000000000..55f7ea8ae1 --- /dev/null +++ b/LibC/sys/mman.h @@ -0,0 +1 @@ +#include diff --git a/LibC/unistd.h b/LibC/unistd.h index d9fa1da623..fcddc917e2 100644 --- a/LibC/unistd.h +++ b/LibC/unistd.h @@ -7,6 +7,7 @@ __BEGIN_DECLS extern char** environ; +inline int getpagesize() { return 4096; } uid_t getuid(); gid_t getgid(); pid_t getpid(); diff --git a/Userland/Makefile b/Userland/Makefile index 21b0b9ff91..87d1e0809f 100644 --- a/Userland/Makefile +++ b/Userland/Makefile @@ -3,7 +3,6 @@ OBJS = \ sh.o \ ps.o \ ls.o \ - pwd.o \ sleep.o \ date.o \ true.o \ @@ -21,7 +20,6 @@ APPS = \ sh \ ps \ ls \ - pwd \ sleep \ date \ true \ @@ -64,9 +62,6 @@ ps: ps.o ls: ls.o $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a -pwd: pwd.o - $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a - sleep: sleep.o $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a diff --git a/Userland/id.cpp b/Userland/id.cpp index fd76e81427..60e0b056a9 100644 --- a/Userland/id.cpp +++ b/Userland/id.cpp @@ -1,12 +1,15 @@ #include #include +#include int main(int c, char** v) { uid_t uid = getuid(); gid_t gid = getgid(); - pid_t pid = getpid(); - printf("uid=%u, gid=%u, pid=%u\n", uid, gid, pid); + + struct passwd* pw = getpwuid(uid); + + printf("uid=%u(%s), gid=%u\n", uid, pw ? pw->pw_name : "n/a", gid); return 0; } diff --git a/Userland/pwd.cpp b/Userland/pwd.cpp deleted file mode 100644 index ebb7d5b6d3..0000000000 --- a/Userland/pwd.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -int main(int c, char** v) -{ - char buffer[1024]; - char* ptr = getcwd(buffer, sizeof(buffer)); - if (!ptr) { - printf("getcwd() failed\n"); - return 1; - } - printf("%s\n", ptr); - return 0; -} -