From d1ac6fb03e3110e35023f60f643f0c4d02c3d8b6 Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Sat, 24 Oct 2009 22:58:28 +0200 Subject: More work on syscalls : userland applications can run other apps. --- Source/Applications/Shell/Shell-fs.ns.cpp | 21 ++++++++ Source/Applications/Shell/Shell.ns.cpp | 5 +- Source/Applications/Shell/Shell.ns.h | 1 + Source/Kernel/Shell/KernelShell-fs.class.cpp | 3 +- Source/Kernel/SyscallManager/Ressource.class.cpp | 4 +- Source/Kernel/TaskManager/Process.class.cpp | 69 ++++++++++++++++++++++-- Source/Kernel/TaskManager/Process.class.h | 9 +++- Source/Library/Interface/Process.iface.h | 10 ++++ Source/Library/Userland/Binding/Process.class.h | 22 ++++++++ Source/Library/Userland/Start.cpp | 12 ++++- 10 files changed, 145 insertions(+), 11 deletions(-) diff --git a/Source/Applications/Shell/Shell-fs.ns.cpp b/Source/Applications/Shell/Shell-fs.ns.cpp index 1d52836..cd9de8a 100644 --- a/Source/Applications/Shell/Shell-fs.ns.cpp +++ b/Source/Applications/Shell/Shell-fs.ns.cpp @@ -1,5 +1,6 @@ #include "Shell.ns.h" #include +#include namespace Shell { @@ -112,4 +113,24 @@ void wf(Vector& args) { } } +void run(Vector& args) { + if (args.size() == 1) { + outvt << "Nothing to run...\n"; + } else { + Process p = Process::run(args[1]); + if (p.valid()) { + p.setInVT(invt); + p.setOutVT(outvt); + for (u32int i = 2; i < args.size(); i++) { + p.pushArg(args[i]); + } + p.start(); + s32int v = p.wait(); + outvt << "Return value : " << (s64int)v << "\n"; + } else { + outvt << "Error while launching process.\n"; + } + } +} + } diff --git a/Source/Applications/Shell/Shell.ns.cpp b/Source/Applications/Shell/Shell.ns.cpp index 7213094..cd091d5 100644 --- a/Source/Applications/Shell/Shell.ns.cpp +++ b/Source/Applications/Shell/Shell.ns.cpp @@ -16,8 +16,9 @@ u32int run() { {"pwd", pwd}, {"rm", rm}, {"mkdir", mkdir}, - {"cat", cat}, - {"wf", wf}, + {"cat", cat}, + {"wf", wf}, + {"run", run}, {"", 0} }; diff --git a/Source/Applications/Shell/Shell.ns.h b/Source/Applications/Shell/Shell.ns.h index a22c18d..b2dd587 100644 --- a/Source/Applications/Shell/Shell.ns.h +++ b/Source/Applications/Shell/Shell.ns.h @@ -14,4 +14,5 @@ namespace Shell { extern void mkdir(Vector& args); extern void cat(Vector& args); extern void wf(Vector& args); + extern void run(Vector& args); } diff --git a/Source/Kernel/Shell/KernelShell-fs.class.cpp b/Source/Kernel/Shell/KernelShell-fs.class.cpp index bc7e137..fa2078d 100644 --- a/Source/Kernel/Shell/KernelShell-fs.class.cpp +++ b/Source/Kernel/Shell/KernelShell-fs.class.cpp @@ -109,7 +109,8 @@ void KernelShell::run(Vector& args) { if (args.size() == 1) { *m_vt << "No app to run !\n"; } else { - Process* p = Process::run(args[1], m_cwd, 0); + Task::currProcess()->setCwd(m_cwd); + Process* p = Process::run(args[1], 0); if (p == 0) { *m_vt << "Error while launching process.\n"; } else { diff --git a/Source/Kernel/SyscallManager/Ressource.class.cpp b/Source/Kernel/SyscallManager/Ressource.class.cpp index 8862bca..ec9137b 100644 --- a/Source/Kernel/SyscallManager/Ressource.class.cpp +++ b/Source/Kernel/SyscallManager/Ressource.class.cpp @@ -1,6 +1,7 @@ #include "Ressource.class.h" #include #include +#include Ressource::Ressource(u8int type, call_t* callTable) : m_lock(MUTEX_FALSE) { m_id = Res::registerRes(this); @@ -20,8 +21,6 @@ void Ressource::addCallTable(call_t* callTable) { } u32int Ressource::doCall(u8int id, u32int a, u32int b, u32int c, u32int d, u32int e) { - if (id == 0) return m_type; - for (SimpleList *iter = m_callTables; iter != 0; iter = iter->next()) { call_t* ct = iter->v(); u32int i = 0; @@ -43,6 +42,7 @@ u32int Ressource::doCall(u8int id, u32int a, u32int b, u32int c, u32int d, u32in u32int Ressource::call(u8int id, u32int a, u32int b, u32int c, u32int d, u32int e) { if (!ISROOT && !accessible()) return (u32int) - 1; + if (id == 0) return m_type; m_lock.waitLock(); u32int r = doCall(id, a, b, c, d, e); m_lock.unlock(); diff --git a/Source/Kernel/TaskManager/Process.class.cpp b/Source/Kernel/TaskManager/Process.class.cpp index a7e7d7c..eec28d8 100644 --- a/Source/Kernel/TaskManager/Process.class.cpp +++ b/Source/Kernel/TaskManager/Process.class.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #define ISPARENT Task::currProcess()->getPid() == m_ppid @@ -20,11 +22,30 @@ call_t Process::m_callTable[] = { CALL0(PRIF_GETPPID, &Process::getPpid), CALL0(PRIF_ARGC, &Process::argcSC), CALL1(PRIF_ARGV, &Process::argvSC), + CALL0(PRIF_START, &Process::startSC), + CALL1(PRIF_AUTODELETE, &Process::autoDeleteSC), + CALL1(PRIF_PUSHARG, &Process::pushArgSC), + CALL1(PRIF_SETOUTVT, &Process::setOutVTSC), + CALL1(PRIF_SETINVT, &Process::setInVTSC), CALL0(0, 0) }; u32int Process::scall(u8int wat, u32int a, u32int b, u32int c, u32int d) { if (wat == PRIF_SGETCPR) return Task::currProcess()->resId(); + if (wat == PRIF_SRUN) { + String* e = (String*)a; + Process* p = Process::run(*e, Usr::uid()); + if (p != 0) return p->resId(); + } + if (wat == PRIF_SWAIT) { + Process* p = Res::get(a, PRIF_OBJTYPE); + if (Task::currProcess()->getPid() != p->m_ppid) return 0; + while (p->m_state != P_FINISHED and !p->m_autodelete) Task::currThread()->sleep(20); + if (p->m_autodelete) return E_AUTODELETE; + s32int ret = p->m_retval; + delete p; + return ret; + } return (u32int) - 1; } @@ -57,8 +78,8 @@ Process* Process::createKernel(String cmdline, VirtualTerminal *vt) { return p; } -Process* Process::run(String filename, FSNode* cwd, u32int uid) { - File file(filename, FM_READ, cwd); +Process* Process::run(String filename, u32int uid) { + File file(filename, FM_READ, (FSNode*)Task::currProcess()->getCwd()); if (!file.valid()) return 0; Binary* b = Binary::load(file); if (b == 0) return 0; @@ -81,6 +102,7 @@ Process::Process(String binfile, u32int uid) : Ressource(PRIF_OBJTYPE, m_callTab m_retval = 0; m_state = P_STARTING; m_uid = uid; + m_autodelete = false; m_cwd = Task::currProcess()->getCwd(); m_inVT = Task::currProcess()->getInVT(); m_outVT = Task::currProcess()->getOutVT(); @@ -128,7 +150,12 @@ void Process::registerThread(Thread* t) { void Process::threadFinishes(Thread* thread, u32int retval) { // If it is the main thread of the process, or if it pagefaulted if (thread == m_threads[0] or retval == E_PAGEFAULT or retval == E_EXIT) { - exit(); + m_retval = retval; + if (m_autodelete) { + delete this; + } else { + exit(); + } } else { //Simply unregister thread for (u32int i = 0; i < m_threads.size(); i++) { @@ -206,6 +233,42 @@ u32int Process::freePageSC(u32int pos) { m_pagedir->freeFrame(pos); return 0; } + +u32int Process::startSC() { + if (Task::currProcess()->getPid() == m_ppid) { + start(); + return 1; + } + return 0; +} + +u32int Process::autoDeleteSC(u32int d) { + if (Task::currProcess()->getPid() != m_ppid) return 2; + m_autodelete = (d != 0); + return (m_autodelete ? 1 : 0); +} + +u32int Process::pushArgSC(u32int arg) { + String* a = (String*)arg; + m_arguments.push(*a); + return 0; +} + +u32int Process::setInVTSC(u32int vtid) { + if (Task::currProcess()->getPid() != m_ppid) return 0; + VirtualTerminal* vt = Res::get(vtid, VTIF_OBJTYPE); + if (vt != 0) setInVT(vt); + return 1; +} + +u32int Process::setOutVTSC(u32int vtid) { + if (Task::currProcess()->getPid() != m_ppid) return 0; + VirtualTerminal* vt = Res::get(vtid, VTIF_OBJTYPE); + if (vt != 0) setOutVT(vt); + return 1; +} + + bool Process::accessible() { return (m_uid == Usr::uid()); } diff --git a/Source/Kernel/TaskManager/Process.class.h b/Source/Kernel/TaskManager/Process.class.h index ec5a90d..11da57b 100644 --- a/Source/Kernel/TaskManager/Process.class.h +++ b/Source/Kernel/TaskManager/Process.class.h @@ -45,6 +45,8 @@ class Process : public Ressource { VirtualTerminal *m_inVT, *m_outVT; DirectoryNode *m_cwd; + bool m_autodelete; + Heap *m_userHeap; Vector m_threads; @@ -57,13 +59,18 @@ class Process : public Ressource { u32int argvSC(u32int); u32int allocPageSC(u32int); u32int freePageSC(u32int); + u32int startSC(); //Permits parent process to start run of process + u32int autoDeleteSC(u32int); //If true, process will auto-delete when it finishes. Else, it must be deleted by parent, while waiting for it. + u32int pushArgSC(u32int); + u32int setOutVTSC(u32int); + u32int setInVTSC(u32int); bool accessible(); public: static u32int scall(u8int, u32int, u32int, u32int, u32int); static Process* createKernel(String cmdline, VirtualTerminal *vt); //Also creates a Thread for what's curently happening - static Process* run(String filename, FSNode* cwd, u32int uid); + static Process* run(String filename, u32int uid); Process(String binfile, u32int uid); ~Process(); diff --git a/Source/Library/Interface/Process.iface.h b/Source/Library/Interface/Process.iface.h index 52543aa..0152947 100644 --- a/Source/Library/Interface/Process.iface.h +++ b/Source/Library/Interface/Process.iface.h @@ -1,10 +1,14 @@ #ifndef DEF_PROCESS_IFACE_H #define DEF_PROCESS_IFACE_H +#define E_AUTODELETE 0x0FFFFF03 + #define PRIF_OBJTYPE 0x20 //S = static, GET = get, C = current, PR = process #define PRIF_SGETCPR 0 +#define PRIF_SRUN 1 +#define PRIF_SWAIT 2 #define PRIF_EXIT 0x01 #define PRIF_ALLOCPAGE 0x02 @@ -15,4 +19,10 @@ #define PRIF_ARGC 0x10 #define PRIF_ARGV 0x11 +#define PRIF_START 0x20 +#define PRIF_AUTODELETE 0x21 +#define PRIF_PUSHARG 0x28 +#define PRIF_SETOUTVT 0x29 +#define PRIF_SETINVT 0x30 + #endif diff --git a/Source/Library/Userland/Binding/Process.class.h b/Source/Library/Userland/Binding/Process.class.h index 9687ea9..a3fc569 100644 --- a/Source/Library/Userland/Binding/Process.class.h +++ b/Source/Library/Userland/Binding/Process.class.h @@ -2,6 +2,7 @@ #define DEF_PROCESS_CLASS_H #include +#include #include #include @@ -12,6 +13,9 @@ class Process : public RessourceCaller { u32int id = RessourceCaller::sCall(PRIF_OBJTYPE, PRIF_SGETCPR); return Process(id); } + static Process run(const String& app) { + return Process(sCall(PRIF_OBJTYPE, PRIF_SRUN, (u32int)&app)); + } Process(u32int id) : RessourceCaller(id, PRIF_OBJTYPE) {} void exit() { @@ -35,6 +39,24 @@ class Process : public RessourceCaller { String argv(u32int idx) { return String::unserialize(doCall(PRIF_ARGV, idx)); } + void start() { + doCall(PRIF_START); + } + s32int wait() { + return sCall(PRIF_OBJTYPE, PRIF_SWAIT, resId()); + } + void autoDelete(bool ad = true) { + doCall(PRIF_AUTODELETE, (ad ? 1 : 0)); + } + void pushArg(const String& arg) { + doCall(PRIF_PUSHARG, (u32int)&arg); + } + void setInVT(VirtualTerminal vt) { + doCall(PRIF_SETINVT, vt.resId()); + } + void setOutVT(VirtualTerminal vt) { + doCall(PRIF_SETOUTVT, vt.resId()); + } }; #endif diff --git a/Source/Library/Userland/Start.cpp b/Source/Library/Userland/Start.cpp index be4f81e..930c4dd 100644 --- a/Source/Library/Userland/Start.cpp +++ b/Source/Library/Userland/Start.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -15,14 +16,21 @@ VirtualTerminal invt(0), outvt(0); int main(const Vector& args); +void doExit(u32int v) { + asm volatile("int $66" : : "a"(v)); +} + extern "C" void start() { //Call static constructors + u32int i = 0; for(u32int * call = &start_ctors; call < &end_ctors; call++) { ((void (*)(void))*call)(); } - heap.create(0x40000000, 0x00100000, 0x00004000); //Initially create a 1M heap with 16ko index + heap.create(0x40000000, 0x00040000, 0x00004000); //Initially create a 256ko heap with 16ko index invt = VirtualTerminal::getIn(); outvt = VirtualTerminal::getOut(); + if (!invt.valid()) doExit(1); + if (!outvt.valid()) doExit(2); u32int argc = Process::get().argc(); Vector args(argc); @@ -35,7 +43,7 @@ extern "C" void start() { ((void (*)(void))*call)(); } - asm volatile("int $66" : : "a"(r)); + doExit(r); } namespace Mem { -- cgit v1.2.3