diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 9af8c2fcef..5314418d5d 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -112,6 +112,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3) return current->sys$get_arguments((int*)arg1, (char***)arg2); case Syscall::PosixChdir: return current->sys$chdir((const char*)arg1); + case Syscall::PosixUname: + return current->sys$uname((utsname*)arg1); default: kprintf("int0x80: Unknown function %x requested {%x, %x, %x}\n", function, arg1, arg2, arg3); break; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 9eb832e484..68a36ffd52 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -33,6 +33,7 @@ enum Function { PosixGethostname = 0x2001, GetArguments = 0x2002, PosixChdir = 0x2003, + PosixUname = 0x2004, }; void initialize(); diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index c26041d70a..b083698a94 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -26,12 +26,18 @@ static InlineLinkedList* s_tasks; static InlineLinkedList* s_deadTasks; static String* s_hostname; -static String& hostname(InterruptDisabler&) +static String& hostnameStorage(InterruptDisabler&) { ASSERT(s_hostname); return *s_hostname; } +static String getHostname() +{ + InterruptDisabler disabler; + return hostnameStorage(disabler).isolatedCopy(); +} + static bool contextSwitch(Task*); static void redoKernelTaskTSS() @@ -177,14 +183,10 @@ int Task::sys$munmap(void* addr, size_t size) int Task::sys$gethostname(char* buffer, size_t size) { - String hn; - { - InterruptDisabler disabler; - hn = hostname(disabler).isolatedCopy(); - } - if (size < (hn.length() + 1)) + auto hostname = getHostname(); + if (size < (hostname.length() + 1)) return -ENAMETOOLONG; - memcpy(buffer, hn.characters(), size); + memcpy(buffer, hostname.characters(), size); return 0; } @@ -760,6 +762,16 @@ int Task::sys$open(const char* path, size_t pathLength) return fd; } +int Task::sys$uname(utsname* buf) +{ + strcpy(buf->sysname, "Serenity"); + strcpy(buf->release, "1.0-dev"); + strcpy(buf->version, "FIXME"); + strcpy(buf->machine, "i386"); + strcpy(buf->nodename, getHostname().characters()); + return 0; +} + int Task::sys$kill(pid_t pid, int sig) { (void) sig; diff --git a/Kernel/Task.h b/Kernel/Task.h index c5a1362d14..b58b139c0c 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -104,6 +104,7 @@ public: int sys$gettimeofday(timeval*); int sys$gethostname(char* name, size_t length); int sys$get_arguments(int* argc, char*** argv); + int sys$uname(utsname*); static void initialize(); diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents index c1123370d1..d31ada7ac0 100644 Binary files a/Kernel/_fs_contents and b/Kernel/_fs_contents differ diff --git a/Kernel/sync-sh b/Kernel/sync-sh index 922f07931c..f885e7ab18 100755 --- a/Kernel/sync-sh +++ b/Kernel/sync-sh @@ -11,5 +11,6 @@ cp ../Userland/true mnt/bin/true cp ../Userland/false mnt/bin/false cp ../Userland/hostname mnt/bin/hostname cp ../Userland/cat mnt/bin/cat +cp ../Userland/uname mnt/bin/uname umount mnt sync diff --git a/Kernel/types.h b/Kernel/types.h index ac5a4feedd..63f2a22846 100644 --- a/Kernel/types.h +++ b/Kernel/types.h @@ -31,6 +31,16 @@ struct timeval { suseconds_t tv_usec; }; +#define UTSNAME_ENTRY_LEN 65 + +struct utsname { + char sysname[UTSNAME_ENTRY_LEN]; + char nodename[UTSNAME_ENTRY_LEN]; + char release[UTSNAME_ENTRY_LEN]; + char version[UTSNAME_ENTRY_LEN]; + char machine[UTSNAME_ENTRY_LEN]; +}; + struct FarPtr { DWORD offset { 0 }; WORD selector { 0 }; diff --git a/LibC/Makefile b/LibC/Makefile index c958788553..956e01894a 100644 --- a/LibC/Makefile +++ b/LibC/Makefile @@ -7,6 +7,7 @@ OBJS = \ dirent.o \ stdlib.o \ time.o \ + utsname.o \ entry.o LIBRARY = LibC.a diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp index 31f0d14d41..5ddb06b757 100644 --- a/LibC/stdio.cpp +++ b/LibC/stdio.cpp @@ -1,6 +1,8 @@ #include "stdio.h" #include "stdarg.h" #include "types.h" +#include "string.h" +#include "errno.h" #include #define ALWAYS_INLINE __attribute__ ((always_inline)) @@ -169,5 +171,10 @@ int sprintf(char* buffer, const char* fmt, ...) return ret; } +void perror(const char* s) +{ + printf("%s: %s\n", s, strerror(errno)); +} + } diff --git a/LibC/stdio.h b/LibC/stdio.h index b34e0828da..1e6a79ea71 100644 --- a/LibC/stdio.h +++ b/LibC/stdio.h @@ -5,6 +5,7 @@ extern "C" { int printf(const char* fmt, ...); int sprintf(char* buffer, const char* fmt, ...); int putchar(int ch); +void perror(const char*); } diff --git a/LibC/utsname.cpp b/LibC/utsname.cpp new file mode 100644 index 0000000000..d01232704a --- /dev/null +++ b/LibC/utsname.cpp @@ -0,0 +1,14 @@ +#include "utsname.h" +#include "errno.h" +#include + +extern "C" { + +int uname(struct utsname* buf) +{ + int rc = Syscall::invoke(Syscall::PosixUname, (dword)buf); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + +} + diff --git a/LibC/utsname.h b/LibC/utsname.h new file mode 100644 index 0000000000..d50a5a4270 --- /dev/null +++ b/LibC/utsname.h @@ -0,0 +1,17 @@ +#pragma once + +#define UTSNAME_ENTRY_LEN 65 + +extern "C" { + +struct utsname { + char sysname[UTSNAME_ENTRY_LEN]; + char nodename[UTSNAME_ENTRY_LEN]; + char release[UTSNAME_ENTRY_LEN]; + char version[UTSNAME_ENTRY_LEN]; + char machine[UTSNAME_ENTRY_LEN]; +}; + +int uname(struct utsname*); + +} diff --git a/Userland/.gitignore b/Userland/.gitignore index 2c52d710f8..fd9204f785 100644 --- a/Userland/.gitignore +++ b/Userland/.gitignore @@ -10,3 +10,4 @@ false true hostname cat +uname diff --git a/Userland/Makefile b/Userland/Makefile index d433c7422d..9798053d6d 100644 --- a/Userland/Makefile +++ b/Userland/Makefile @@ -9,7 +9,8 @@ OBJS = \ true.o \ false.o \ hostname.o \ - cat.o + cat.o \ + uname.o APPS = \ id \ @@ -22,7 +23,8 @@ APPS = \ true \ false \ hostname \ - cat + cat \ + uname ARCH_FLAGS = STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib @@ -75,6 +77,9 @@ hostname: hostname.o cat: cat.o $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a +uname: uname.o + $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a + .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Userland/uname.cpp b/Userland/uname.cpp new file mode 100644 index 0000000000..f74cd7d3a5 --- /dev/null +++ b/Userland/uname.cpp @@ -0,0 +1,46 @@ +#include +#include + +int main(int argc, char** argv) +{ + utsname uts; + int rc = uname(&uts); + if (rc < 0) { + perror("uname() failed"); + return 0; + } + bool flag_s = false; + bool flag_n = false; + bool flag_r = false; + bool flag_m = false; + if (argc == 1) { + flag_s = true; + } else { + for (int i = 1; i < argc; ++i) { + if (argv[i][0] == '-') { + for (const char* o = &argv[i][1]; *o; ++o) { + switch (*o) { + case 's': flag_s = true; break; + case 'n': flag_n = true; break; + case 'r': flag_r = true; break; + case 'm': flag_m = true; break; + case 'a': flag_s = flag_n = flag_r = flag_m = true; break; + } + } + } + } + } + if (!flag_s && !flag_n && !flag_r && !flag_m) + flag_s = true; + if (flag_s) + printf("%s ", uts.sysname); + if (flag_n) + printf("%s ", uts.nodename); + if (flag_r) + printf("%s ", uts.release); + if (flag_m) + printf("%s ", uts.machine); + printf("\n"); + return 0; +} +