diff --git a/AK/Vector.h b/AK/Vector.h index f57496533e..0c0a7c3e30 100644 --- a/AK/Vector.h +++ b/AK/Vector.h @@ -48,7 +48,7 @@ public: --m_size; } -private: +//private: friend class Vector; VectorImpl(size_t capacity) : m_capacity(capacity) { } @@ -235,7 +235,7 @@ public: ConstIterator begin() const { return ConstIterator(*this, 0); } ConstIterator end() const { return ConstIterator(*this, size()); } -private: +//private: static size_t paddedCapacity(size_t capacity) { return max(size_t(4), capacity + (capacity / 4) + 4); diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index 3134334ca6..37db9902df 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -289,7 +289,9 @@ bool MemoryManager::page_in_from_vnode(PageDirectory& page_directory, Region& re } remap_region_page(&page_directory, region, page_index_in_region, true); byte* dest_ptr = region.linearAddress.offset(page_index_in_region * PAGE_SIZE).asPtr(); +#ifdef MM_DEBUG dbgprintf("MM: page_in_from_vnode ready to read from vnode, will write to L%x!\n", dest_ptr); +#endif sti(); // Oh god here we go... auto nread = vnode.fileSystem()->readInodeBytes(vnode.inode, vmo.vnode_offset() + ((region.first_page_index() + page_index_in_region) * PAGE_SIZE), PAGE_SIZE, dest_ptr, nullptr); if (nread < 0) { @@ -444,7 +446,9 @@ void MemoryManager::map_region_at_address(PageDirectory* page_directory, Region& { InterruptDisabler disabler; auto& vmo = region.vmo(); +#ifdef MM_DEBUG dbgprintf("MM: map_region_at_address will map VMO pages %u - %u (VMO page count: %u)\n", region.first_page_index(), region.last_page_index(), vmo.page_count()); +#endif for (size_t i = region.first_page_index(); i <= region.last_page_index(); ++i) { auto page_laddr = laddr.offset(i * PAGE_SIZE); auto pte = ensurePTE(page_directory, page_laddr); diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 929546ef42..60a9556f1e 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -431,11 +431,13 @@ int Process::sys$execve(const char* filename, const char** argv, const char** en { VALIDATE_USER_READ(filename, strlen(filename)); if (argv) { + VALIDATE_USER_READ(argv, sizeof(const char**)); for (size_t i = 0; argv[i]; ++i) { VALIDATE_USER_READ(argv[i], strlen(argv[i])); } } if (envp) { + VALIDATE_USER_READ(envp, sizeof(const char**)); for (size_t i = 0; envp[i]; ++i) { VALIDATE_USER_READ(envp[i], strlen(envp[i])); } @@ -455,9 +457,8 @@ int Process::sys$execve(const char* filename, const char** argv, const char** en Vector environment; if (envp) { - for (size_t i = 0; envp[i]; ++i) { + for (size_t i = 0; envp[i]; ++i) environment.append(envp[i]); - } } int rc = exec(path, move(arguments), move(environment)); @@ -976,12 +977,9 @@ ssize_t Process::sys$write(int fd, const void* data, size_t size) { VALIDATE_USER_READ(data, size); #ifdef DEBUG_IO - kprintf("Process::sys$write: called(%d, %p, %u)\n", fd, data, size); + dbgprintf("%s(%u): sys$write(%d, %p, %u)\n", name().characters(), pid(), fd, data, size); #endif auto* descriptor = file_descriptor(fd); -#ifdef DEBUG_IO - kprintf("Process::sys$write: handle=%p\n", descriptor); -#endif if (!descriptor) return -EBADF; auto nwritten = descriptor->write((const byte*)data, size); @@ -992,7 +990,7 @@ ssize_t Process::sys$write(int fd, const void* data, size_t size) return -EINTR; } #ifdef DEBUG_IO - kprintf("Process::sys$write: nwritten=%u\n", nwritten); + dbgprintf("%s(%u) sys$write: nwritten=%u\n", name().characters(), pid(), nwritten); #endif return nwritten; } @@ -1001,12 +999,9 @@ ssize_t Process::sys$read(int fd, void* outbuf, size_t nread) { VALIDATE_USER_WRITE(outbuf, nread); #ifdef DEBUG_IO - kprintf("Process::sys$read: called(%d, %p, %u)\n", fd, outbuf, nread); + dbgprintf("%s(%u) sys$read(%d, %p, %u)\n", name().characters(), pid(), fd, outbuf, nread); #endif auto* descriptor = file_descriptor(fd); -#ifdef DEBUG_IO - kprintf("Process::sys$read: handle=%p\n", descriptor); -#endif if (!descriptor) return -EBADF; if (descriptor->isBlocking()) { @@ -1020,7 +1015,7 @@ ssize_t Process::sys$read(int fd, void* outbuf, size_t nread) } nread = descriptor->read((byte*)outbuf, nread); #ifdef DEBUG_IO - kprintf("Process::sys$read: nread=%u\n", nread); + dbgprintf("%s(%u) Process::sys$read: nread=%u\n", name().characters(), pid(), nread); #endif return nread; } @@ -1042,14 +1037,27 @@ int Process::sys$access(const char* pathname, int mode) ASSERT_NOT_REACHED(); } -int Process::sys$fcntl(int fd, int cmd, dword extra_arg) +int Process::sys$fcntl(int fd, int cmd, dword arg) { (void) cmd; - (void) extra_arg; + (void) arg; + dbgprintf("sys$fcntl: fd=%d, cmd=%d, arg=%u\n", fd, cmd, arg); auto* descriptor = file_descriptor(fd); if (!descriptor) return -EBADF; - ASSERT_NOT_REACHED(); + switch (cmd) { + case F_GETFD: + return descriptor->fd_flags(); + case F_SETFD: + return descriptor->set_fd_flags(arg); + case F_GETFL: + return descriptor->file_flags(); + case F_SETFL: + return descriptor->set_file_flags(arg); + default: + ASSERT_NOT_REACHED(); + } + return 0; } int Process::sys$fstat(int fd, Unix::stat* statbuf) @@ -1129,7 +1137,7 @@ int Process::sys$getcwd(char* buffer, size_t size) if (size < path.length() + 1) return -ERANGE; strcpy(buffer, path.characters()); - return -ENOTIMPL; + return 0; } size_t Process::number_of_open_file_descriptors() const @@ -1145,7 +1153,7 @@ size_t Process::number_of_open_file_descriptors() const int Process::sys$open(const char* path, int options) { #ifdef DEBUG_IO - kprintf("Process::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength); + dbgprintf("%s(%u) sys$open(\"%s\")\n", name().characters(), pid(), path); #endif VALIDATE_USER_READ(path, strlen(path)); if (number_of_open_file_descriptors() >= m_max_open_file_descriptors) @@ -1307,6 +1315,7 @@ void Process::reap(Process& process) pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options) { + //kprintf("sys$waitpid(%d, %p, %d)\n", waitee, wstatus, options); // FIXME: Respect options (void) options; if (wstatus) @@ -1314,7 +1323,7 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options) { InterruptDisabler disabler; - if (!Process::from_pid(waitee)) + if (waitee != -1 && !Process::from_pid(waitee)) return -ECHILD; } m_waitee = waitee; @@ -1326,7 +1335,9 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options) Process* waitee_process; { InterruptDisabler disabler; - waitee_process = Process::from_pid(waitee); + + // NOTE: If waitee was -1, m_waitee will have been filled in by the scheduler. + waitee_process = Process::from_pid(m_waitee); } ASSERT(waitee_process); reap(*waitee_process); @@ -1471,7 +1482,12 @@ int Process::sys$tcgetattr(int fd, Unix::termios* tp) return -EBADF; if (!descriptor->isTTY()) return -ENOTTY; - ASSERT_NOT_REACHED(); + auto& tty = *descriptor->tty(); +#ifdef TERMIOS_DEBUG + kprintf("sys$tcgetattr(fd=%d, tp=%p)\n", fd, tp); +#endif + memcpy(tp, &tty.termios(), sizeof(Unix::termios)); + return 0; } int Process::sys$tcsetattr(int fd, int optional_actions, const Unix::termios* tp) @@ -1483,7 +1499,12 @@ int Process::sys$tcsetattr(int fd, int optional_actions, const Unix::termios* tp return -EBADF; if (!descriptor->isTTY()) return -ENOTTY; - ASSERT_NOT_REACHED(); +#ifdef TERMIOS_DEBUG + kprintf("sys$tcsetattr(fd=%d, tp=%p)\n", fd, tp); +#endif + auto& tty = *descriptor->tty(); + memcpy(&tty.termios(), tp, sizeof(Unix::termios)); + return 0; } pid_t Process::sys$tcgetpgrp(int fd) @@ -1560,20 +1581,25 @@ Unix::sighandler_t Process::sys$signal(int signum, Unix::sighandler_t handler) int Process::sys$sigprocmask(int how, const Unix::sigset_t* set, Unix::sigset_t* old_set) { - VALIDATE_USER_READ(set, sizeof(Unix::sigset_t)); - if (old_set) + if (old_set) { VALIDATE_USER_READ(old_set, sizeof(Unix::sigset_t)); - *old_set = m_signal_mask; - switch (how) { - case SIG_BLOCK: - m_signal_mask &= ~(*set); - break; - case SIG_UNBLOCK: - m_signal_mask |= *set; - break; - case SIG_SETMASK: - m_signal_mask = *set; - break; + *old_set = m_signal_mask; + } + if (set) { + VALIDATE_USER_READ(set, sizeof(Unix::sigset_t)); + switch (how) { + case SIG_BLOCK: + m_signal_mask &= ~(*set); + break; + case SIG_UNBLOCK: + m_signal_mask |= *set; + break; + case SIG_SETMASK: + m_signal_mask = *set; + break; + default: + return -EINVAL; + } } return 0; } diff --git a/Kernel/Process.h b/Kernel/Process.h index 7c2058c85b..76218e85ea 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -104,6 +104,7 @@ public: template static void for_each_in_pgrp(pid_t, Callback); template static void for_each_in_state(State, Callback); template static void for_each_not_in_state(State, Callback); + template void for_each_child(Callback); bool tick() { ++m_ticks; return --m_ticksLeft; } void set_ticks_left(dword t) { m_ticksLeft = t; } @@ -360,6 +361,21 @@ inline void Process::for_each(Callback callback) } } +template +inline void Process::for_each_child(Callback callback) +{ + ASSERT_INTERRUPTS_DISABLED(); + pid_t my_pid = pid(); + for (auto* process = g_processes->head(); process;) { + auto* next_process = process->next(); + if (process->ppid() == my_pid) { + if (!callback(*process)) + break; + } + process = next_process; + } +} + template inline void Process::for_each_in_pgrp(pid_t pgid, Callback callback) { diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 69b4363ec9..a7e3ca9323 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -35,15 +35,17 @@ bool Scheduler::pick_next() } if (process.state() == Process::BlockedWait) { - auto* waitee = Process::from_pid(process.waitee()); - if (!waitee) { - kprintf("waitee %u of %s(%u) reaped before I could wait?\n", process.waitee(), process.name().characters(), process.pid()); - ASSERT_NOT_REACHED(); - } - if (waitee->state() == Process::Dead) { - process.m_waitee_status = (waitee->m_termination_status << 8) | waitee->m_termination_signal; - process.unblock(); - } + process.for_each_child([&process] (Process& child) { + if (child.state() != Process::Dead) + return true; + if (process.waitee() == -1 || process.waitee() == child.pid()) { + process.m_waitee_status = (child.m_termination_status << 8) | child.m_termination_signal; + process.m_waitee = child.pid(); + process.unblock(); + return false; + } + return true; + }); return true; } diff --git a/Kernel/TTY.cpp b/Kernel/TTY.cpp index 7aa0dd0db8..d0e66f95bf 100644 --- a/Kernel/TTY.cpp +++ b/Kernel/TTY.cpp @@ -5,6 +5,8 @@ TTY::TTY(unsigned major, unsigned minor) : CharacterDevice(major, minor) { + memset(&m_termios, 0, sizeof(m_termios)); + m_termios.c_lflag |= ISIG | ECHO; } TTY::~TTY() @@ -42,6 +44,8 @@ void TTY::emit(byte ch) void TTY::interrupt() { + if (!should_generate_signals()) + return; dbgprintf("%s: Interrupt ^C pressed!\n", ttyName().characters()); if (pgid()) { dbgprintf("%s: Send SIGINT to everyone in pgrp %d\n", ttyName().characters(), pgid()); diff --git a/Kernel/TTY.h b/Kernel/TTY.h index a54a7a1f42..ad9bc5c15e 100644 --- a/Kernel/TTY.h +++ b/Kernel/TTY.h @@ -1,6 +1,7 @@ #pragma once #include +#include class TTY : public CharacterDevice { public: @@ -15,6 +16,10 @@ public: void set_pgid(pid_t pgid) { m_pgid = pgid; } pid_t pgid() const { return m_pgid; } + Unix::termios& termios() { return m_termios; } + bool should_generate_signals() const { return m_termios.c_lflag & ISIG; } + bool should_echo_input() const { return m_termios.c_lflag & ECHO; } + protected: virtual bool isTTY() const final override { return true; } @@ -28,5 +33,6 @@ protected: private: Vector m_buffer; pid_t m_pgid { 0 }; + Unix::termios m_termios; }; diff --git a/Kernel/VirtualConsole.cpp b/Kernel/VirtualConsole.cpp index f963684ce3..16b9b9160e 100644 --- a/Kernel/VirtualConsole.cpp +++ b/Kernel/VirtualConsole.cpp @@ -261,6 +261,17 @@ void VirtualConsole::escape$H(const Vector& params) set_cursor(row - 1, col - 1); } +void VirtualConsole::escape$A(const Vector& params) +{ + int num = 1; + if (params.size() >= 1) + num = params[0]; + int new_row = (int)m_cursor_row - num; + if (new_row < 0) + new_row = 0; + set_cursor(new_row, m_cursor_column); +} + void VirtualConsole::escape$J(const Vector& params) { int mode = 0; diff --git a/Kernel/VirtualConsole.h b/Kernel/VirtualConsole.h index 8c5ce2ec8e..01d0d6662f 100644 --- a/Kernel/VirtualConsole.h +++ b/Kernel/VirtualConsole.h @@ -40,6 +40,7 @@ private: void set_cursor(unsigned row, unsigned column); void put_character_at(unsigned row, unsigned column, byte ch); + void escape$A(const Vector&); void escape$H(const Vector&); void escape$J(const Vector&); void escape$m(const Vector&); diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 641d5cdec7..1419d59ad5 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -239,8 +239,11 @@ static void init_stage2() } #endif + Vector environment; + environment.append("TERM=ansi"); + int error; - Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector(), Vector(), tty0); + Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector(), move(environment), tty0); #ifdef SPAWN_MULTIPLE_SHELLS Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector(), Vector(), tty1); Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector(), Vector(), tty2); diff --git a/Kernel/sync-local.sh b/Kernel/sync-local.sh index ee67768785..71f45073d1 100755 --- a/Kernel/sync-local.sh +++ b/Kernel/sync-local.sh @@ -5,3 +5,6 @@ cp ../../figlet-2.2.5/fonts/standard.flf mnt/$FIGLET_FONTDIR cp ../../figlet-2.2.5/fonts/big.flf mnt/$FIGLET_FONTDIR cp ../../figlet-2.2.5/fonts/slant.flf mnt/$FIGLET_FONTDIR cp ../../figlet-2.2.5/fonts/lean.flf mnt/$FIGLET_FONTDIR + +cp ../../bash-1.14.7/bash2 mnt/bin/bash + diff --git a/LibC/Makefile b/LibC/Makefile index 6e1abcb091..bbe6a1136d 100644 --- a/LibC/Makefile +++ b/LibC/Makefile @@ -28,6 +28,8 @@ LIBC_OBJS = \ ctype.o \ fcntl.o \ termios.o \ + ulimit.o \ + qsort.o \ entry.o OBJS = $(AK_OBJS) $(LIBC_OBJS) diff --git a/LibC/fcntl.cpp b/LibC/fcntl.cpp index 251b64a908..7c22b0442d 100644 --- a/LibC/fcntl.cpp +++ b/LibC/fcntl.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include extern "C" { diff --git a/LibC/qsort.cpp b/LibC/qsort.cpp new file mode 100644 index 0000000000..0f5aa398e4 --- /dev/null +++ b/LibC/qsort.cpp @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 1980, 1983, 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)qsort.c 5.9 (Berkeley) 2/23/91"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +static void insertion_sort(void* bot, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); + +void qsort(void* bot, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) +{ + if (nmemb <= 1) + return; + + insertion_sort(bot, nmemb, size, compar); +} + +void insertion_sort(void* bot, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) +{ + int cnt; + unsigned char ch; + char *s1, *s2, *t1, *t2, *top; + + /* + * A simple insertion sort (see Knuth, Vol. 3, page 81, Algorithm + * S). Insertion sort has the same worst case as most simple sorts + * (O N^2). It gets used here because it is (O N) in the case of + * sorted data. + */ + top = (char*)bot + nmemb * size; + for (t1 = (char*)bot + size; t1 < top;) { + for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2) < 0;); + if (t1 != (t2 += size)) { + /* Bubble bytes up through each element. */ + for (cnt = size; cnt--; ++t1) { + ch = *t1; + for (s1 = s2 = t1; (s2 -= size) >= t2; s1 = s2) + *s1 = *s2; + *s1 = ch; + } + } else + t1 += size; + } +} diff --git a/LibC/setjmp.cpp b/LibC/setjmp.cpp index 536e543a6e..48fed07ff8 100644 --- a/LibC/setjmp.cpp +++ b/LibC/setjmp.cpp @@ -4,7 +4,8 @@ int setjmp(jmp_buf) { - assert(false); + //assert(false); + return 0; } void longjmp(jmp_buf, int) diff --git a/LibC/signal.cpp b/LibC/signal.cpp index 362f1587dc..a59cb83c5b 100644 --- a/LibC/signal.cpp +++ b/LibC/signal.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include extern "C" { diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp index d4df7762a8..86adf972eb 100644 --- a/LibC/stdio.cpp +++ b/LibC/stdio.cpp @@ -45,6 +45,7 @@ void __stdio_init() int setvbuf(FILE* stream, char* buf, int mode, size_t size) { + fprintf(stderr, "setvbuf(%p [fd=%d], %p, %d, %u)\n", stream, stream->fd, buf, mode, size); if (mode != _IONBF && mode != _IOLBF && mode != _IOFBF) { errno = EINVAL; return -1; @@ -57,6 +58,7 @@ int setvbuf(FILE* stream, char* buf, int mode, size_t size) stream->buffer = stream->default_buffer; stream->buffer_size = BUFSIZ; } + stream->buffer_index = 0; return 0; } @@ -65,9 +67,9 @@ void setbuf(FILE* stream, char* buf) setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ); } -void setlinebuf(FILE* stream, char* buf) +void setlinebuf(FILE* stream) { - setvbuf(stream, buf, buf ? _IOLBF : _IONBF, BUFSIZ); + setvbuf(stream, nullptr, _IOLBF, 0); } int fileno(FILE* stream) @@ -138,7 +140,7 @@ int fputc(int ch, FILE* stream) stream->buffer[stream->buffer_index++] = ch; if (stream->buffer_index >= stream->buffer_size) fflush(stream); - else if (stream->mode == _IOLBF && ch == '\n') + else if (stream->mode == _IONBF || (stream->mode == _IOLBF && ch == '\n')) fflush(stream); if (stream->eof) return EOF; diff --git a/LibC/stdio.h b/LibC/stdio.h index 9547019a69..84a7e55d03 100644 --- a/LibC/stdio.h +++ b/LibC/stdio.h @@ -61,7 +61,7 @@ int sscanf (const char* buf, const char* fmt, ...); int fscanf(FILE*, const char* fmt, ...); int setvbuf(FILE*, char* buf, int mode, size_t); void setbuf(FILE*, char* buf); -void setlinebuf(FILE*, char* buf); +void setlinebuf(FILE*); __END_DECLS diff --git a/LibC/stdlib.cpp b/LibC/stdlib.cpp index 7f323c204d..195a787e14 100644 --- a/LibC/stdlib.cpp +++ b/LibC/stdlib.cpp @@ -1,9 +1,10 @@ #include -#include +#include #include #include #include #include +#include #include #include @@ -54,11 +55,12 @@ void* calloc(size_t nmemb, size_t) return nullptr; } -void* realloc(void *ptr, size_t) +void* realloc(void *ptr, size_t size) { - (void) ptr; - ASSERT_NOT_REACHED(); - return nullptr; + // FIXME: This is broken as shit. + auto* new_ptr = malloc(size); + memcpy(new_ptr, ptr, size); + return new_ptr; } void exit(int status) @@ -116,4 +118,13 @@ long atol(const char* str) return atoi(str); } +void __qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) +{ + (void) base; + (void) nmemb; + (void) size; + (void) compar; + assert(false); +} + } diff --git a/LibC/stdlib.h b/LibC/stdlib.h index b8d4174dbd..243b98693f 100644 --- a/LibC/stdlib.h +++ b/LibC/stdlib.h @@ -12,7 +12,7 @@ void* realloc(void *ptr, size_t); char* getenv(const char* name); int atoi(const char*); long atol(const char*); - +void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); void exit(int status) __NORETURN; void abort() __NORETURN; diff --git a/LibC/string.cpp b/LibC/string.cpp index e840f28e9d..1f638997ae 100644 --- a/LibC/string.cpp +++ b/LibC/string.cpp @@ -2,6 +2,7 @@ #include #include #include +#include extern "C" { @@ -97,6 +98,14 @@ void memcpy(void* dest, const void* src, size_t n) *(bdest++) = *(bsrc++); } +void memmove(void* dest, const void* src, size_t n) +{ + if (dest < src) + return memcpy(dest, src, n); + // FIXME: Implement backwards copy. + assert(false); +} + char* strcpy(char* dest, const char *src) { char* originalDest = dest; diff --git a/LibC/termcap.cpp b/LibC/termcap.cpp index 65607e287c..a5c6a6ab12 100644 --- a/LibC/termcap.cpp +++ b/LibC/termcap.cpp @@ -1,4 +1,9 @@ #include +#include +#include +#include +#include +#include extern "C" { @@ -6,5 +11,94 @@ char PC; char* UP; char* BC; +int tgetent(char* bp, const char* name) +{ + fprintf(stderr, "tgetent: bp=%p, name='%s'\n", bp, name); + if (!strcmp(name, "ansi")) { + PC = '\0'; + BC = const_cast("\033[D"); + UP = const_cast("\033[A"); + return 1; + } + assert(false); +} + +static HashMap* caps = nullptr; + +void ensure_caps() +{ + if (caps) + return; + caps = new HashMap; + caps->set("DC", "\033[%p1%dP"); + caps->set("IC", "\033[%p1%d@"); + caps->set("ce", "\033[K"); + caps->set("cl", "\033[H\033[J"); + caps->set("cr", "\015"); + caps->set("dc", "\033[P"); + caps->set("ei", ""); + caps->set("ic", ""); + caps->set("im", ""); + caps->set("kd", "\033[B"); + caps->set("kl", "\033[D"); + caps->set("kr", "\033[C"); + caps->set("ku", "\033[A"); + caps->set("ks", ""); + caps->set("ke", ""); + caps->set("le", "\033[D"); + caps->set("mm", ""); + caps->set("mo", ""); + caps->set("pc", ""); + caps->set("up", "\033[A"); + caps->set("vb", ""); + caps->set("am", ""); + + caps->set("co", "80"); + caps->set("li", "25"); +} + +char* tgetstr(char* id, char** area) +{ + ensure_caps(); + fprintf(stderr, "tgetstr: id='%s', area=%p\n", id, area); + auto it = caps->find(id); + if (it != caps->end()) { + char* ret = *area; + strcpy(*area, (*it).value.characters()); + *area += (*it).value.length() + 1; + return ret; + } + assert(false); +} + +int tgetflag(char* id) +{ + fprintf(stderr, "tgetflag: '%s'\n", id); + auto it = caps->find(id); + if (it != caps->end()) + return 1; + return 0; +} + +int tgetnum(char* id) +{ + fprintf(stderr, "tgetnum: '%s'\n", id); + auto it = caps->find(id); + if (it != caps->end()) { + return atoi((*it).value.characters()); + } + assert(false); +} + +char* tgoto(const char* cap, int col, int row) +{ + assert(false); +} + +int tputs(const char* str, int affcnt, int (*putc)(int)) +{ + assert(false); +} + } diff --git a/LibC/termcap.h b/LibC/termcap.h index d81a7cd520..f2f40ebf83 100644 --- a/LibC/termcap.h +++ b/LibC/termcap.h @@ -8,5 +8,12 @@ extern char PC; extern char* UP; extern char* BC; +int tgetent(char* bp, const char* name); +int tgetflag(char* id); +int tgetnum(char* id); +char* tgetstr(char* id, char** area); +char* tgoto(const char* cap, int col, int row); +int tputs(const char* str, int affcnt, int (*putc)(int)); + __END_DECLS diff --git a/LibC/termios.cpp b/LibC/termios.cpp index 8278faee8b..03851f20c3 100644 --- a/LibC/termios.cpp +++ b/LibC/termios.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -16,5 +17,12 @@ int tcsetattr(int fd, int optional_actions, const struct termios* t) __RETURN_WITH_ERRNO(rc, rc, -1); } +int tcflow(int fd, int action) +{ + (void) fd; + (void) action; + assert(false); +} + } diff --git a/LibC/termios.h b/LibC/termios.h index e35dc6cfff..364df493b2 100644 --- a/LibC/termios.h +++ b/LibC/termios.h @@ -20,6 +20,7 @@ struct termios { int tcgetattr(int fd, struct termios*); int tcsetattr(int fd, int optional_actions, const struct termios*); +int tcflow(int fd, int action); /* c_cc characters */ #define VINTR 0 diff --git a/LibC/ulimit.cpp b/LibC/ulimit.cpp new file mode 100644 index 0000000000..cfc3d82433 --- /dev/null +++ b/LibC/ulimit.cpp @@ -0,0 +1,14 @@ +#include +#include + +extern "C" { + +long ulimit(int cmd, long newlimit) +{ + (void) cmd; + (void) newlimit; + assert(false); +} + +} + diff --git a/LibC/ulimit.h b/LibC/ulimit.h new file mode 100644 index 0000000000..ea0a35b06f --- /dev/null +++ b/LibC/ulimit.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +__BEGIN_DECLS + +long ulimit(int cmd, long newlimit); + +__END_DECLS + diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index 7e767d72e7..09387a5f64 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -167,7 +167,8 @@ char* getcwd(char* buffer, size_t size) char* getwd(char* buf) { - return getcwd(buf, PATH_MAX); + auto* p = getcwd(buf, PATH_MAX); + return p; } int sleep(unsigned seconds) diff --git a/Userland/sh.cpp b/Userland/sh.cpp index 3fc2444237..3986f402fc 100644 --- a/Userland/sh.cpp +++ b/Userland/sh.cpp @@ -253,13 +253,13 @@ static bool handle_builtin(int argc, const char** argv, int& retval) static int try_exec(const char* path, const char** argv) { - int ret = execve(path, argv, nullptr); + int ret = execve(path, argv, const_cast(environ)); assert(ret < 0); const char* search_path = "/bin"; char pathbuf[128]; sprintf(pathbuf, "%s/%s", search_path, argv[0]); - ret = execve(pathbuf, argv, nullptr); + ret = execve(pathbuf, argv, const_cast(environ)); if (ret == -1) return -1; return ret; @@ -317,7 +317,8 @@ static int runcmd(char* cmd) tcsetpgrp(0, getpid()); if (WIFEXITED(wstatus)) { - //printf("Exited normally with status %d\n", WEXITSTATUS(wstatus)); + if (WEXITSTATUS(wstatus) != 0) + printf("Exited with status %d\n", WEXITSTATUS(wstatus)); } else { if (WIFSIGNALED(wstatus)) { switch (WTERMSIG(wstatus)) { diff --git a/VirtualFileSystem/FileDescriptor.h b/VirtualFileSystem/FileDescriptor.h index 2c02e84189..c6a6b3823f 100644 --- a/VirtualFileSystem/FileDescriptor.h +++ b/VirtualFileSystem/FileDescriptor.h @@ -46,6 +46,12 @@ public: #ifdef SERENITY bool isBlocking() const { return m_isBlocking; } void setBlocking(bool b) { m_isBlocking = b; } + + dword file_flags() const { return m_file_flags; } + int set_file_flags(dword flags) { m_file_flags = flags; return 0; } + + dword fd_flags() const { return m_fd_flags; } + int set_fd_flags(dword flags) { m_fd_flags = flags; return 0; } #endif ByteBuffer& generatorCache() { return m_generatorCache; } @@ -62,6 +68,8 @@ private: #ifdef SERENITY bool m_isBlocking { true }; + dword m_fd_flags { 0 }; + dword m_file_flags { 0 }; #endif }; diff --git a/VirtualFileSystem/UnixTypes.h b/VirtualFileSystem/UnixTypes.h index e63620693c..d47bc68253 100644 --- a/VirtualFileSystem/UnixTypes.h +++ b/VirtualFileSystem/UnixTypes.h @@ -19,6 +19,188 @@ namespace Unix { #define PROT_EXEC 0x4 #define PROT_NONE 0x0 +#define F_DUPFD 0 +#define F_GETFD 1 +#define F_SETFD 2 +#define F_GETFL 3 +#define F_SETFL 4 + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 0000400 +# define NL0 0000000 +# define NL1 0000400 +# define CRDLY 0003000 +# define CR0 0000000 +# define CR1 0001000 +# define CR2 0002000 +# define CR3 0003000 +# define TABDLY 0014000 +# define TAB0 0000000 +# define TAB1 0004000 +# define TAB2 0010000 +# define TAB3 0014000 +# define BSDLY 0020000 +# define BS0 0000000 +# define BS1 0020000 +# define FFDLY 0100000 +# define FF0 0000000 +# define FF1 0100000 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#define __MAX_BAUD B4000000 +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#if defined __USE_MISC || (defined __USE_XOPEN && !defined __USE_XOPEN2K) +# define XCASE 0000004 +#endif +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#ifdef __USE_MISC +# define ECHOCTL 0001000 +# define ECHOPRT 0002000 +# define ECHOKE 0004000 +# define FLUSHO 0010000 +# define PENDIN 0040000 +#endif +#define IEXTEN 0100000 +#ifdef __USE_MISC +# define EXTPROC 0200000 +#endif + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + typedef dword dev_t; typedef dword ino_t; typedef dword mode_t;