Browse Source

Implement argc/argv support for spawned tasks.

Celebrate the new functionality with a simple /bin/cat implementation. :^)
Andreas Kling 6 years ago
parent
commit
df87dda63c
13 changed files with 105 additions and 17 deletions
  1. 3 1
      Kernel/Syscall.cpp
  2. 1 0
      Kernel/Syscall.h
  3. 34 3
      Kernel/Task.cpp
  4. 5 2
      Kernel/Task.h
  5. BIN
      Kernel/_fs_contents
  6. 1 0
      Kernel/sync-sh
  7. 6 3
      LibC/entry.cpp
  8. 2 2
      LibC/process.cpp
  9. 1 1
      LibC/process.h
  10. 2 1
      Userland/.gitignore
  11. 7 2
      Userland/Makefile
  12. 30 0
      Userland/cat.cpp
  13. 13 2
      Userland/sh.cpp

+ 3 - 1
Kernel/Syscall.cpp

@@ -65,7 +65,7 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
     case Syscall::PosixGettimeofday:
         return current->sys$gettimeofday((timeval*)arg1);
     case Syscall::Spawn:
-        return current->sys$spawn((const char*)arg1);
+        return current->sys$spawn((const char*)arg1, (const char**)arg2);
     case Syscall::GetDirEntries:
         return current->sys$get_dir_entries((int)arg1, (void*)arg2, (size_t)arg3);
     case Syscall::PosixLstat:
@@ -108,6 +108,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
         current->sys$exit((int)arg1);
         ASSERT_NOT_REACHED();
         return 0;
+    case Syscall::GetArguments:
+        return current->sys$get_arguments((int*)arg1, (char***)arg2);
     default:
         kprintf("int0x80: Unknown function %x requested {%x, %x, %x}\n", function, arg1, arg2, arg3);
         break;

+ 1 - 0
Kernel/Syscall.h

@@ -31,6 +31,7 @@ enum Function {
     PosixGetcwd = 0x1999,
     PosixGettimeofday = 0x2000,
     PosixGethostname = 0x2001,
+    GetArguments = 0x2002,
 };
 
 void initialize();

+ 34 - 3
Kernel/Task.cpp

@@ -185,18 +185,19 @@ int Task::sys$gethostname(char* buffer, size_t size)
     if (size < (hn.length() + 1))
         return -ENAMETOOLONG;
     memcpy(buffer, hn.characters(), size);
+    return 0;
 }
 
-int Task::sys$spawn(const char* path)
+int Task::sys$spawn(const char* path, const char** args)
 {
     int error = 0;
-    auto* child = Task::createUserTask(path, m_uid, m_gid, m_pid, error);
+    auto* child = Task::createUserTask(path, m_uid, m_gid, m_pid, error, args);
     if (child)
         return child->pid();
     return error;
 }
 
-Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t parentPID, int& error)
+Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t parentPID, int& error, const char** args)
 {
     auto parts = path.split('/');
     if (parts.isEmpty()) {
@@ -216,9 +217,20 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
         return nullptr;
     }
 
+    Vector<String> taskArguments;
+    if (args) {
+        for (size_t i = 0; args[i]; ++i) {
+            taskArguments.append(args[i]);
+        }
+    } else {
+        taskArguments.append(parts.last());
+    }
+
     InterruptDisabler disabler; // FIXME: Get rid of this, jesus christ. This "critical" section is HUGE.
     Task* t = new Task(parts.takeLast(), uid, gid, parentPID, Ring3);
 
+    t->m_arguments = move(taskArguments);
+
     ExecSpace space;
     space.hookableAlloc = [&] (const String& name, size_t size) {
         if (!size)
@@ -257,6 +269,25 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
     return t;
 }
 
+int Task::sys$get_arguments(int* argc, char*** argv)
+{
+    auto* region = allocateRegion(4096, "argv");
+    if (!region)
+        return -ENOMEM;
+    MemoryManager::the().mapRegion(*this, *region);
+    char* argpage = (char*)region->linearAddress.get();
+    *argc = m_arguments.size();
+    *argv = (char**)argpage;
+    char* bufptr = argpage + (sizeof(char*) * m_arguments.size());
+    for (size_t i = 0; i < m_arguments.size(); ++i) {
+        (*argv)[i] = bufptr;
+        memcpy(bufptr, m_arguments[i].characters(), m_arguments[i].length());
+        bufptr += m_arguments[i].length();
+        *(bufptr++) = '\0';
+    }
+    return 0;
+}
+
 Task* Task::createKernelTask(void (*e)(), String&& name)
 {
     Task* task = new Task(move(name), (uid_t)0, (gid_t)0, (pid_t)0, Ring0);

+ 5 - 2
Kernel/Task.h

@@ -16,7 +16,7 @@ class Task : public InlineLinkedListNode<Task> {
     friend class InlineLinkedListNode<Task>;
 public:
     static Task* createKernelTask(void (*entry)(), String&& name);
-    static Task* createUserTask(const String& path, uid_t, gid_t, pid_t parentPID, int& error);
+    static Task* createUserTask(const String& path, uid_t, gid_t, pid_t parentPID, int& error, const char** args = nullptr);
     ~Task();
 
     static Vector<Task*> allTasks();
@@ -92,7 +92,7 @@ public:
     int sys$kill(pid_t pid, int sig);
     int sys$geterror() { return m_error; }
     void sys$exit(int status);
-    int sys$spawn(const char* path);
+    int sys$spawn(const char* path, const char** args);
     pid_t sys$waitpid(pid_t);
     void* sys$mmap(void*, size_t size);
     int sys$munmap(void*, size_t size);
@@ -101,6 +101,7 @@ public:
     int sys$sleep(unsigned seconds);
     int sys$gettimeofday(timeval*);
     int sys$gethostname(char* name, size_t length);
+    int sys$get_arguments(int* argc, char*** argv);
 
     static void initialize();
 
@@ -170,6 +171,8 @@ private:
     LinearAddress m_nextRegion;
 
     pid_t m_parentPID { 0 };
+
+    Vector<String> m_arguments;
 };
 
 extern void task_init();

BIN
Kernel/_fs_contents


+ 1 - 0
Kernel/sync-sh

@@ -10,5 +10,6 @@ cp ../Userland/date mnt/bin/date
 cp ../Userland/true mnt/bin/true
 cp ../Userland/false mnt/bin/false
 cp ../Userland/hostname mnt/bin/hostname
+cp ../Userland/cat mnt/bin/cat
 umount mnt
 sync

+ 6 - 3
LibC/entry.cpp

@@ -8,9 +8,12 @@ extern "C" int _start()
 {
     errno = 0;
 
-    // FIXME: Pass appropriate argc/argv.
-    int status = main(0, nullptr);
-
+    int argc;
+    char** argv;
+    int rc = Syscall::invoke(Syscall::GetArguments, (dword)&argc, (dword)&argv);
+    int status = 254;
+    if (rc == 0)
+        status = main(argc, argv);
     Syscall::invoke(Syscall::PosixExit, status);
 
     // Birger's birthday <3

+ 2 - 2
LibC/process.cpp

@@ -4,9 +4,9 @@
 
 extern "C" {
 
-int spawn(const char* path)
+int spawn(const char* path, const char** args)
 {
-    int rc = Syscall::invoke(Syscall::Spawn, (dword)path);
+    int rc = Syscall::invoke(Syscall::Spawn, (dword)path, (dword)args);
     __RETURN_WITH_ERRNO(rc, rc, -1);
 }
 

+ 1 - 1
LibC/process.h

@@ -2,7 +2,7 @@
 
 extern "C" {
 
-int spawn(const char* path);
+int spawn(const char* path, const char** args);
 
 }
 

+ 2 - 1
Userland/.gitignore

@@ -1,3 +1,4 @@
+*.o
 id
 sh
 ps
@@ -8,4 +9,4 @@ date
 false
 true
 hostname
-*.o
+cat

+ 7 - 2
Userland/Makefile

@@ -8,7 +8,8 @@ OBJS = \
        date.o \
        true.o \
        false.o \
-       hostname.o
+       hostname.o \
+       cat.o
 
 APPS = \
        id \
@@ -20,7 +21,8 @@ APPS = \
        date \
        true \
        false \
-       hostname
+       hostname \
+       cat
 
 ARCH_FLAGS =
 STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
@@ -70,6 +72,9 @@ false: false.o
 hostname: hostname.o
 	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
 
+cat: cat.o
+	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
+
 .cpp.o:
 	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
 

+ 30 - 0
Userland/cat.cpp

@@ -0,0 +1,30 @@
+#include <LibC/stdio.h>
+#include <LibC/unistd.h>
+#include <LibC/errno.h>
+#include <LibC/string.h>
+
+int main(int argc, char** argv)
+{
+    if (argc != 2) {
+        printf("usage: cat <file>\n");
+        return 1;
+    }
+    int fd = open(argv[1]);
+    if (fd == -1) {
+        printf("failed to open %s: %s\n", argv[1], strerror(errno));
+        return 1;
+    }
+    for (;;) {
+        char buf[128];
+        ssize_t nread = read(fd, buf, sizeof(buf));
+        if (nread == 0)
+            break;
+        if (nread < 0) {
+            printf("read() error: %s\n", strerror(errno));
+            return 2;
+        }
+        for (ssize_t i = 0; i < nread; ++i)
+            putchar(buf[i]);
+    }
+    return 0;
+}

+ 13 - 2
Userland/sh.cpp

@@ -16,10 +16,21 @@ static int runcmd(char* cmd)
 {
     if (cmd[0] == 0)
         return 0;
-    //printf("command: '%s'\n", cmd);
     char buf[128];
     sprintf(buf, "/bin/%s", cmd);
-    int ret = spawn(buf);
+
+    const char* argv[32];
+    size_t argi = 1;
+    argv[0] = &buf[0];
+    size_t buflen = strlen(buf);
+    for (size_t i = 0; i < buflen; ++i) {
+        if (buf[i] == ' ') {
+            buf[i] = '\0';
+            argv[argi++] = &buf[i + 1];
+        }
+    }
+    argv[argi + 1] = nullptr;
+    int ret = spawn(argv[0], argv);
     if (ret == -1) {
         printf("spawn failed: %s (%s)\n", cmd, strerror(errno));
         return 1;