diff --git a/AK/String.cpp b/AK/String.cpp index 201bc8d7c1..e589438c1b 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -22,6 +22,18 @@ String String::empty() return StringImpl::theEmptyStringImpl(); } +String String::isolatedCopy() const +{ + if (!m_impl) + return { }; + if (!m_impl->length()) + return empty(); + char* buffer; + auto impl = StringImpl::createUninitialized(length(), buffer); + memcpy(buffer, m_impl->characters(), m_impl->length()); + return String(move(*impl)); +} + String String::substring(size_t start, size_t length) const { ASSERT(m_impl); diff --git a/AK/String.h b/AK/String.h index 96a193a331..8c9984c785 100644 --- a/AK/String.h +++ b/AK/String.h @@ -69,6 +69,8 @@ public: bool operator==(const String&) const; bool operator!=(const String& other) const { return !(*this == other); } + String isolatedCopy() const; + static String empty(); StringImpl* impl() { return m_impl.ptr(); } diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 4524f72682..df6fe77662 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -100,6 +100,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3) return (dword)current->sys$mmap((void*)arg1, (size_t)arg2); case Syscall::PosixMunmap: return current->sys$munmap((void*)arg1, (size_t)arg2); + case Syscall::PosixGethostname: + return current->sys$gethostname((char*)arg1, (size_t)arg2); case Syscall::PosixExit: cli(); locker.unlock(); diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 3569c91f44..1c704b2fff 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -30,6 +30,7 @@ enum Function { PosixLstat = 0x1998, PosixGetcwd = 0x1999, PosixGettimeofday = 0x2000, + PosixGethostname = 0x2001, }; void initialize(); diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 28ed1981a1..b505de76fc 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -24,6 +24,13 @@ Task* s_kernelTask; static pid_t next_pid; static InlineLinkedList* s_tasks; static InlineLinkedList* s_deadTasks; +static String* s_hostname; + +static String& hostname(InterruptDisabler&) +{ + ASSERT(s_hostname); + return *s_hostname; +} static bool contextSwitch(Task*); @@ -61,6 +68,7 @@ void Task::initialize() s_tasks = new InlineLinkedList; s_deadTasks = new InlineLinkedList; s_kernelTask = Task::createKernelTask(nullptr, "colonel"); + s_hostname = new String("birx"); redoKernelTaskTSS(); loadTaskRegister(s_kernelTask->selector()); } @@ -167,6 +175,18 @@ int Task::sys$munmap(void* addr, size_t size) return 0; } +int Task::sys$gethostname(char* buffer, size_t size) +{ + String hn; + { + InterruptDisabler disabler; + hn = hostname(disabler).isolatedCopy(); + } + if (size < (hn.length() + 1)) + return -ENAMETOOLONG; + memcpy(buffer, hn.characters(), size); +} + int Task::sys$spawn(const char* path) { int error = 0; diff --git a/Kernel/Task.h b/Kernel/Task.h index 3f855f6d2e..6cf40481b3 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -100,6 +100,7 @@ public: int sys$getcwd(char*, size_t); int sys$sleep(unsigned seconds); int sys$gettimeofday(timeval*); + int sys$gethostname(char* name, size_t length); static void initialize(); diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents index 82f977dc26..7ee095bf0e 100644 Binary files a/Kernel/_fs_contents and b/Kernel/_fs_contents differ diff --git a/Kernel/errno.h b/Kernel/errno.h index e01e73798a..6b321a05f1 100644 --- a/Kernel/errno.h +++ b/Kernel/errno.h @@ -34,5 +34,6 @@ #define EPIPE 32 // Broken pipe #define EDOM 33 // Math argument out of domain of func #define ERANGE 34 // Math result not representable +#define ENAMETOOLONG 36 // Name too long -#define EOVERFLOW 75 // Value too large for defined data type +#define EOVERFLOW 75 // Value too large for defined data type diff --git a/Kernel/sync-sh b/Kernel/sync-sh index 8b8b687be3..24ba204577 100755 --- a/Kernel/sync-sh +++ b/Kernel/sync-sh @@ -9,5 +9,6 @@ cp ../Userland/sleep mnt/bin/sleep cp ../Userland/date mnt/bin/date cp ../Userland/true mnt/bin/true cp ../Userland/false mnt/bin/false +cp ../Userland/hostname mnt/bin/hostname umount mnt sync diff --git a/LibC/errno.h b/LibC/errno.h index 5f4a403f5a..c28cb71f24 100644 --- a/LibC/errno.h +++ b/LibC/errno.h @@ -1,42 +1,6 @@ #pragma once -#define EPERM 1 // Operation not permitted -#define ENOENT 2 // No such file or directory -#define ESRCH 3 // No such process -#define EINTR 4 // Interrupted system call -#define EIO 5 // I/O error -#define ENXIO 6 // No such device or address -#define E2BIG 7 // Argument list too long -#define ENOEXEC 8 // Exec format error -#define EBADF 9 // Bad file number -#define ECHILD 10 // No child processes -#define EAGAIN 11 // Try again -#define ENOMEM 12 // Out of memory -#define EACCES 13 // Permission denied -#define EFAULT 14 // Bad address -#define ENOTBLK 15 // Block device required -#define EBUSY 16 // Device or resource busy -#define EEXIST 17 // File exists -#define EXDEV 18 // Cross-device link -#define ENODEV 19 // No such device -#define ENOTDIR 20 // Not a directory -#define EISDIR 21 // Is a directory -#define EINVAL 22 // Invalid argument -#define ENFILE 23 // File table overflow -#define EMFILE 24 // Too many open files -#define ENOTTY 25 // Not a typewriter -#define ETXTBSY 26 // Text file busy -#define EFBIG 27 // File too large -#define ENOSPC 28 // No space left on device -#define ESPIPE 29 // Illegal seek -#define EROFS 30 // Read-only file system -#define EMLINK 31 // Too many links -#define EPIPE 32 // Broken pipe -#define EDOM 33 // Math argument out of domain of func -#define ERANGE 34 // Math result not representable - -#define EOVERFLOW 75 // Value too large for defined data type - +#include #define __RETURN_WITH_ERRNO(rc, good_ret, bad_ret) \ do { \ diff --git a/LibC/string.cpp b/LibC/string.cpp index 94b4450249..06e28676e4 100644 --- a/LibC/string.cpp +++ b/LibC/string.cpp @@ -50,6 +50,7 @@ const char* strerror(int errnum) case EPIPE: return "Broken pipe"; case EDOM: return "Math argument out of domain"; case ERANGE: return "Math result not representable"; + case ENAMETOOLONG: return "Name too long"; case EOVERFLOW: return "Value too large for data type"; } printf("strerror() missing string for errnum=%d\n", errnum); diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index 82077c5a52..8a39d7f085 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -62,5 +62,11 @@ int sleep(unsigned seconds) return Syscall::invoke(Syscall::Sleep, (dword)seconds); } +int gethostname(char* buffer, size_t size) +{ + int rc = Syscall::invoke(Syscall::PosixGethostname, (dword)buffer, (dword)size); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + } diff --git a/LibC/unistd.h b/LibC/unistd.h index 2f8f1b5c4e..42e61367ad 100644 --- a/LibC/unistd.h +++ b/LibC/unistd.h @@ -14,6 +14,9 @@ pid_t waitpid(pid_t); char* getcwd(char* buffer, size_t size); int lstat(const char* path, stat* statbuf); int sleep(unsigned seconds); +int gethostname(char*, size_t); + +#define HOST_NAME_MAX 64 #define S_IFMT 0170000 #define S_IFDIR 0040000 diff --git a/Userland/.gitignore b/Userland/.gitignore index b132ad73f0..ffdbff1187 100644 --- a/Userland/.gitignore +++ b/Userland/.gitignore @@ -7,4 +7,5 @@ sleep date false true +hostname *.o diff --git a/Userland/Makefile b/Userland/Makefile index 3631838c71..c5a8b4e209 100644 --- a/Userland/Makefile +++ b/Userland/Makefile @@ -7,7 +7,8 @@ OBJS = \ sleep.o \ date.o \ true.o \ - false.o + false.o \ + hostname.o APPS = \ id \ @@ -18,7 +19,8 @@ APPS = \ sleep \ date \ true \ - false + false \ + hostname ARCH_FLAGS = STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib @@ -65,6 +67,9 @@ true: true.o false: false.o $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a +hostname: hostname.o + $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a + .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Userland/hostname.cpp b/Userland/hostname.cpp new file mode 100644 index 0000000000..f33ca87c72 --- /dev/null +++ b/Userland/hostname.cpp @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +int main(int c, char** v) +{ + char buffer[HOST_NAME_MAX]; + int rc = gethostname(buffer, sizeof(buffer)); + if (rc < 0) { + printf("gethostname() error: %s\n", strerror(errno)); + return 1; + } + printf("%s\n", buffer); + return 0; +} +