From 5140bd2ce6102f06d487c45ee390687014aa1ea3 Mon Sep 17 00:00:00 2001 From: Mathias Gottschlag Date: Fri, 26 Dec 2008 15:04:24 +0100 Subject: [PATCH] - Implemented execp*. - Implemented kill. - Added SIGINT when Ctrl+c is pressed. --- programs/libc/crt0.c | 8 +++-- programs/libc/signal.c | 4 ++- programs/libc/unistd.c | 63 +++++++++++++++++++++++++++++++++++---- programs/shell/main.c | 24 +++++++++++---- shared/include/planlos/syscalls.h | 1 + system/include/fs/fs.h | 5 ++++ system/include/fs/request.h | 4 ++- system/include/sys/terminal.h | 2 ++ system/kernel/fs/devfs.c | 25 +++++++++++----- system/kernel/fs/fs.c | 59 +++++++++++++++++++++++++++++++----- system/kernel/fs/request.c | 15 +++++++--- system/kernel/ke/dumbmalloc.c | 28 ++++++++--------- system/kernel/ke/process.c | 29 +++++++++++++++++- system/kernel/ke/start.c | 6 ++-- system/kernel/sys/syscall.c | 24 ++++++++++++++- system/kernel/sys/terminal.c | 42 ++++++++++++++++++++++++-- 16 files changed, 283 insertions(+), 56 deletions(-) diff --git a/programs/libc/crt0.c b/programs/libc/crt0.c index 930beb4..cff6d5c 100644 --- a/programs/libc/crt0.c +++ b/programs/libc/crt0.c @@ -15,8 +15,12 @@ struct FILE void _start(int envc, char **envv, int argc, char **argv) { - environ = malloc(sizeof(char*) * (envc + 1)); - memcpy(environ, envv, sizeof(char*) * (envc + 1)); + if (envv) + { + environ = malloc(sizeof(char*) * (envc + 1)); + memcpy(environ, envv, sizeof(char*) * (envc + 1)); + } + else environ = 0; stdin = malloc(sizeof(struct FILE)); memset(stdin, 0, sizeof(struct FILE)); diff --git a/programs/libc/signal.c b/programs/libc/signal.c index 4d0b788..476041f 100644 --- a/programs/libc/signal.c +++ b/programs/libc/signal.c @@ -24,7 +24,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. int kill(pid_t pid, int sig) { - return -1; + int status; + asm volatile("int $0x80" : "=b"(status): "a"(SYS_KILL), "b"(pid), "c"(sig)); + return status; } int raise(int sig) { diff --git a/programs/libc/unistd.c b/programs/libc/unistd.c index 3fd0a44..978b752 100644 --- a/programs/libc/unistd.c +++ b/programs/libc/unistd.c @@ -34,6 +34,37 @@ pid_t fork(void) return status; } +static char *exec_get_path(const char *file, const char *paths) +{ + while (strlen(paths) > 0) + { + const char *nextpath = strchr(paths, ':'); + if (!nextpath) nextpath = paths + strlen(paths); + if (nextpath && (nextpath != paths)) + { + char *path = malloc(strlen(file) + 1 + ((uintptr_t)nextpath - (uintptr_t)paths)); + memset(path, 0, strlen(file) + 1 + ((uintptr_t)nextpath - (uintptr_t)paths)); + strncpy(path, paths, ((uintptr_t)nextpath - (uintptr_t)paths)); + strcat(path, "/"); + strcat(path, file); + // Test path + int fd = open(path, O_RDONLY); + if (fd != -1) + { + close(fd); + return path; + } + + free(path); + } + if (strchr(paths, ':')) + paths = nextpath + 1; + else + break; + } + return 0; +} + int execl(const char *path, const char *arg0, ...) { char **args = (char**)&arg0; @@ -49,7 +80,8 @@ int execle(const char *path, const char *arg0, ...) } int execlp(const char *file, const char *arg0, ...) { - return -1; + char **args = (char**)&arg0; + return execvp(file, args); } int execv(const char *path, char *const argv[]) { @@ -66,10 +98,12 @@ int execv(const char *path, char *const argv[]) } int execve(const char *path, char *const argv[], char *const env[]) { - int argcount; - for (argcount = 0; argv[argcount] != 0; argcount++); - int envcount; - for (envcount = 0; env[envcount] != 0; envcount++); + int argcount = 0; + if (argv) + for (; argv[argcount] != 0; argcount++); + int envcount = 0; + if (env) + for (; env[envcount] != 0; envcount++); int status = -1; asm volatile("int $0x80" : "=b"(status): "a"(SYS_EXEC), "b"(path), "c"(argcount), "d"(argv), "S"(envcount), "D"(env)); @@ -77,7 +111,24 @@ int execve(const char *path, char *const argv[], char *const env[]) } int execvp(const char *file, char *const argv[]) { - return -1; + char *path = 0; + if (!strchr(file, '/')) + { + char *pathvar = getenv("PATH"); + if (pathvar) + path = exec_get_path(file, pathvar); + if (!path) + path = exec_get_path(file, "/bin:/usr/bin"); + if (!path) return -1; + } + if (!path) + return execve(file, argv, 0); + else + { + int result = execve(path, argv, 0); + free(path); + return result; + } } char *getcwd(char *buf, size_t size) diff --git a/programs/shell/main.c b/programs/shell/main.c index 4197133..0e016be 100644 --- a/programs/shell/main.c +++ b/programs/shell/main.c @@ -4,9 +4,22 @@ #include #include #include +#include + +static int current_child = -1; + +void sigint_handler(int signal) +{ + if (current_child != -1) + { + kill(current_child, SIGINT); + } +} int main(int argc, char **argv) { + signal(SIGINT, sigint_handler); + char command[256] = ""; while (1) { @@ -37,17 +50,17 @@ int main(int argc, char **argv) continue; } // Execute program - int pid = fork(); - if (pid == -1) + current_child = fork(); + if (current_child == -1) { const char *msg = "Could not fork shell.\n"; write(1, msg, strlen(msg)); continue; } - else if (!pid) + else if (!current_child) { // Run program - if (execl(command, command, NULL)) + if (execlp(command, command, NULL)) { const char *msg = "Could not run program.\n"; write(1, msg, strlen(msg)); @@ -57,7 +70,8 @@ int main(int argc, char **argv) else { // Wait for program to exit - waitpid(pid, 0, 0); + waitpid(current_child, 0, 0); + current_child = -1; } } return 0; diff --git a/shared/include/planlos/syscalls.h b/shared/include/planlos/syscalls.h index d9fce84..ed4779f 100644 --- a/shared/include/planlos/syscalls.h +++ b/shared/include/planlos/syscalls.h @@ -46,6 +46,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SYS_RAISE 22 #define SYS_GETPID 23 #define SYS_TIME 24 +#define SYS_KILL 25 #endif diff --git a/system/include/fs/fs.h b/system/include/fs/fs.h index ba63dd9..d9d155f 100644 --- a/system/include/fs/fs.h +++ b/system/include/fs/fs.h @@ -43,6 +43,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define FS_DRIVER_NODATA 4 struct FsRequest; +struct KeProcess; /** * File system information. @@ -170,6 +171,10 @@ int fsUnmount(const char *path); */ FsFileHandle *fsOpen(const char *filename, uint32_t mode); /** + * Overrides the process variable for the open request. + */ +FsFileHandle *fsProcessOpen(struct KeProcess *process, const char *filename, uint32_t mode); +/** * Closes a file handle. */ int fsClose(FsFileHandle *file); diff --git a/system/include/fs/request.h b/system/include/fs/request.h index 72a5aa2..a93522a 100644 --- a/system/include/fs/request.h +++ b/system/include/fs/request.h @@ -126,8 +126,10 @@ typedef struct FsRequest * Creates a file system request. * \param request Request to be issued. * \param wait If set to 1, blocks until the request has been completed. + * \param process Used to override the process member of the request. If it is + * 0, the process is retrieved automatically. */ -int fsCreateRequest(FsRequest *request, int wait); +int fsCreateRequest(FsRequest *request, int wait, KeProcess *process); /** * Waits for a request to be completed. */ diff --git a/system/include/sys/terminal.h b/system/include/sys/terminal.h index 690c727..69a8f3f 100644 --- a/system/include/sys/terminal.h +++ b/system/include/sys/terminal.h @@ -40,6 +40,8 @@ typedef struct int echo; FsRequest **requests; int requestcount; + struct KeProcess *owner; + int opencount; } SysTextTerminal; typedef struct diff --git a/system/kernel/fs/devfs.c b/system/kernel/fs/devfs.c index dfa3c83..ca88764 100644 --- a/system/kernel/fs/devfs.c +++ b/system/kernel/fs/devfs.c @@ -77,18 +77,29 @@ static int fsDevFSRequest(struct FsFileSystem *fs, struct FsRequest *request) { // Open/close files at once case FS_REQUEST_OPEN: - request->file = fsDevFSOpen(fs, request->buffer); - if (!request->file) { - request->status = KE_ERROR_UNKNOWN; - request->return_value = -1; + request->file = fsDevFSOpen(fs, request->buffer); + if (!request->file) + { + request->status = KE_ERROR_UNKNOWN; + request->return_value = -1; + } + else + { + uint32_t fileindex = ((KeDevFSFile*)request->file)->index; + devfsfiles[fileindex]->query_request(devfsfiles[fileindex], request); + } + fsFinishRequest(request); } - fsFinishRequest(request); return 0; case FS_REQUEST_CLOSE: - fsFinishRequest(request); + { + uint32_t fileindex = ((KeDevFSFile*)request->file)->index; + devfsfiles[fileindex]->query_request(devfsfiles[fileindex], request); + fsFinishRequest(request); + } return 0; - // Pass other requests to the driver + // Pass other requests to the driver default: { uint32_t fileindex = ((KeDevFSFile*)request->file)->index; diff --git a/system/kernel/fs/fs.c b/system/kernel/fs/fs.c index 68d87b7..4bd677e 100644 --- a/system/kernel/fs/fs.c +++ b/system/kernel/fs/fs.c @@ -87,7 +87,7 @@ int fsUnmount(const char *path) FsFileHandle *fsOpen(const char *filename, uint32_t mode) { - KeExecLevel level = keGetExecutionLevel(); + /*KeExecLevel level = keGetExecutionLevel(); if (level == KE_LEVEL_HIGH) { kePrint("fsOpen called at KE_LEVEL_HIGH!\n"); @@ -125,6 +125,49 @@ FsFileHandle *fsOpen(const char *filename, uint32_t mode) fh->file->refcount = 1; fh->position = 0; fh->flags = mode; + return fh;*/ + return fsProcessOpen(0, filename, mode); +} +FsFileHandle *fsProcessOpen(struct KeProcess *process, const char *filename, uint32_t mode) +{ + KeExecLevel level = keGetExecutionLevel(); + if (level == KE_LEVEL_HIGH) + { + kePrint("fsProcessOpen called at KE_LEVEL_HIGH!\n"); + return 0; + } + // Get file system from path + uint32_t i = 0; + FsFileSystem *fs = 0; + uint32_t matched = 0; + for (i = 0; i < fs_count; i++) + { + if (strlen(file_systems[i]->path) <= matched) continue; + if (!strncmp(file_systems[i]->path, filename, strlen(file_systems[i]->path))) + { + matched = strlen(file_systems[i]->path); + fs = file_systems[i]; + } + } + if (!fs) return 0; + filename += matched; + // Send open request + FsRequest request; + memset(&request, 0, sizeof(request)); + request.type = FS_REQUEST_OPEN; + request.fs = fs; + request.bufferlength = strlen(filename) + 1; + request.buffer = (char*)filename; + request.flags = mode; + int status = fsCreateRequest(&request, 1, process); + if (status) return 0; + if (request.status || request.return_value) return 0; + // Create file handle + FsFileHandle *fh = malloc(sizeof(FsFileHandle)); + fh->file = request.file; + fh->file->refcount = 1; + fh->position = 0; + fh->flags = mode; return fh; } int fsClose(FsFileHandle *file) @@ -145,7 +188,7 @@ int fsClose(FsFileHandle *file) request.type = FS_REQUEST_CLOSE; request.fs = file->file->fs; request.file = file->file; - int status = fsCreateRequest(&request, 1); + int status = fsCreateRequest(&request, 1, 0); if (status) return KE_ERROR_UNKNOWN; if (request.status || request.return_value) return KE_ERROR_UNKNOWN; } @@ -183,7 +226,7 @@ int fsMknod(const char *filename, uint32_t mode) request.bufferlength = strlen(filename) + 1; request.buffer = (char*)filename; request.flags = mode; - int status = fsCreateRequest(&request, 1); + int status = fsCreateRequest(&request, 1, 0); if (status) return -1; if (request.status) return -1; if (request.return_value) return request.return_value; @@ -209,7 +252,7 @@ int fsWrite(FsFileHandle *file, void *buffer, int size) request.bufferlength = size; request.buffer = buffer; request.offset = file->position; - int status = fsCreateRequest(&request, 1); + int status = fsCreateRequest(&request, 1, 0); if (status) return -1; if (request.status) return -1; if (request.return_value > 0) file->position += request.return_value; @@ -233,7 +276,7 @@ int fsRead(FsFileHandle *file, void *buffer, int size, int blocking) request.bufferlength = size; request.buffer = buffer; request.offset = file->position; - int status = fsCreateRequest(&request, 1); + int status = fsCreateRequest(&request, 1, 0); if (status) return -1; if (request.status) return -1; if (request.return_value > 0) file->position += request.return_value; @@ -259,7 +302,7 @@ uint64_t fsSeek(FsFileHandle *file, int64_t offset, int whence) else request.offset = offset; request.whence = whence; - int status = fsCreateRequest(&request, 1); + int status = fsCreateRequest(&request, 1, 0); if (status) return -1; if (request.status) return -1; file->position = request.offset; @@ -282,7 +325,7 @@ int fsIOCTL(FsFileHandle *file, int requestno, ...) request.file = file->file; request.offset = requestno; request.buffer = (void*)param; - int status = fsCreateRequest(&request, 1); + int status = fsCreateRequest(&request, 1, 0); if (status) return -1; if (request.status) return -1; return request.return_value; @@ -302,7 +345,7 @@ int fsGetIOCTLSize(FsFileHandle *file, int requestno) request.fs = file->file->fs; request.file = file->file; request.offset = requestno; - int status = fsCreateRequest(&request, 1); + int status = fsCreateRequest(&request, 1, 0); if (status) return -1; if (request.status) return -1; return request.return_value; diff --git a/system/kernel/fs/request.c b/system/kernel/fs/request.c index d204d7a..173ad7b 100644 --- a/system/kernel/fs/request.c +++ b/system/kernel/fs/request.c @@ -24,17 +24,24 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "ke/errors.h" #include "ke/debug.h" -int fsCreateRequest(FsRequest *request, int wait) +int fsCreateRequest(FsRequest *request, int wait, KeProcess *process) { if (!request->fs->query_request) { kePrint("Error: Filesystem %x does not support requests.\n", request->fs); return KE_ERROR_UNKNOWN; } - if (keGetCurrentCPU()->currentthread) - request->process = keGetCurrentCPU()->currentthread->process; + if (process) + { + request->process = process; + } else - request->process = 0; + { + if (keGetCurrentCPU()->currentthread) + request->process = keGetCurrentCPU()->currentthread->process; + else + request->process = 0; + } int status = request->fs->query_request(request->fs, request); if (status) return status; if (wait) return fsWaitRequest(request); diff --git a/system/kernel/ke/dumbmalloc.c b/system/kernel/ke/dumbmalloc.c index 370d5d9..694d53c 100644 --- a/system/kernel/ke/dumbmalloc.c +++ b/system/kernel/ke/dumbmalloc.c @@ -15,19 +15,19 @@ void *malloc(size_t size) MM_MIN_KERNEL_PAGE, 1, (memsize + 0xFFF) & ~0xFFF); if (!vaddr) { - kePrint("Out of kernel space.\n"); - return 0; + kePrint("Out of kernel space.\n"); + return 0; } uint32_t i; for (i = 0; i < (memsize + 0xFFF) / 0x1000; ++i) { - uintptr_t paddr = mmAllocPhysicalMemory(0, 0, 0x1000); - if (!paddr) - { - kePrint("Out of kernel space.\n"); - return 0; - } - mmMapKernelMemory(paddr, vaddr + i * 0x1000, MM_MAP_READ | MM_MAP_WRITE); + uintptr_t paddr = mmAllocPhysicalMemory(0, 0, 0x1000); + if (!paddr) + { + kePrint("Out of kernel space.\n"); + return 0; + } + mmMapKernelMemory(paddr, vaddr + i * 0x1000, MM_MAP_READ | MM_MAP_WRITE); } keUnlockSpinlock(mmGetMemoryLock()); @@ -59,11 +59,11 @@ void free(void *ptr) uint32_t i; for (i = 0; i < (memsize + 0xFFF) / 0x1000; ++i) { - uintptr_t vaddr = (uintptr_t)addr + i * 0x1000; - uintptr_t paddr = mmKernelGetPhysAddress(vaddr); - if (paddr != 0) - mmFreePhysicalMemory(paddr, 0x1000); - mmMapKernelMemory(paddr, vaddr, MM_MAP_READ | MM_MAP_WRITE); + uintptr_t vaddr = (uintptr_t)addr + i * 0x1000; + uintptr_t paddr = mmKernelGetPhysAddress(vaddr); + if (paddr != 0) + mmFreePhysicalMemory(paddr, 0x1000); + mmMapKernelMemory(0, vaddr, 0); } keUnlockSpinlock(mmGetMemoryLock()); diff --git a/system/kernel/ke/process.c b/system/kernel/ke/process.c index 87f6470..b1b9f3d 100644 --- a/system/kernel/ke/process.c +++ b/system/kernel/ke/process.c @@ -83,6 +83,14 @@ KeProcess *keCreateProcess(void) } int keTerminateProcess(KeProcess *process) { + // Close files + KeExecLevel oldlevel = keSetExecutionLevel(KE_LEVEL_NORMAL); + uint32_t i; + for (i = 0; i < process->fdcount; i++) + { + if (process->fd[i]) fsClose(process->fd[i]); + } + keSetExecutionLevel(oldlevel); if (process->waitthread) { // Destroy process @@ -206,7 +214,8 @@ void keSendSignal(KeProcess *process, KeThread *thread, int signal) if (thread && handler && thread->userframe) { // Reset signal handler in case the handler is broken - process->signal_handlers[signal] = 0; + if (signal == SIGSEGV) + process->signal_handlers[signal] = 0; // Get user stack IntStackFrame *userframe = (IntStackFrame*)thread->userframe; uint32_t *stack = sysMapUserMemory(thread, userframe->esp - 16, 16, 1); @@ -233,11 +242,29 @@ void keSendSignal(KeProcess *process, KeThread *thread, int signal) stack[0] = handler; userframe->esp = userframe->esp - 16; userframe->eip = 0xFFFFF000; + thread->status = KE_THREAD_RUNNING; } } else { // TODO: Default actions + switch (signal) + { + case SIGINT: + { + // Unlock thread again + if (thread != cpu->currentthread) + { + keUnlockSpinlock(&thread->active); + } + // Kill process + KeThread *currentthread = cpu->currentthread; + keTerminateProcess(thread->process); + if (currentthread->process == process) + asm volatile("int $0x32"); + return; + } + } } // Unlock thread again if (thread != cpu->currentthread) diff --git a/system/kernel/ke/start.c b/system/kernel/ke/start.c index 7139314..931aa53 100644 --- a/system/kernel/ke/start.c +++ b/system/kernel/ke/start.c @@ -128,11 +128,11 @@ static void keInit2(void) { snprintf(terminal, 11, "/dev/tty%d", i); KeProcess *process = keCreateProcess(); - FsFileHandle *stdin = fsOpen(terminal, FS_OPEN_READ); + FsFileHandle *stdin = fsProcessOpen(process, terminal, FS_OPEN_READ); process->fd[0] = stdin; - FsFileHandle *stdout = fsOpen(terminal, FS_OPEN_WRITE); + FsFileHandle *stdout = fsProcessOpen(process, terminal, FS_OPEN_WRITE); process->fd[1] = stdout; - FsFileHandle *stderr = fsOpen(terminal, FS_OPEN_WRITE); + FsFileHandle *stderr = fsProcessOpen(process, terminal, FS_OPEN_WRITE); process->fd[2] = stderr; keElfMapProgram(&process->memory, program, size); uintptr_t entry = ((ElfHeader*)program)->e_entry; diff --git a/system/kernel/sys/syscall.c b/system/kernel/sys/syscall.c index 952a01e..a4e0d53 100644 --- a/system/kernel/sys/syscall.c +++ b/system/kernel/sys/syscall.c @@ -357,7 +357,6 @@ void sysExec(KeThread *thread, uintptr_t *param1, uintptr_t *param2, for (i = 0; i < argcount; i++) { ((uintptr_t*)argdata)[i] += dataaddr; - kePrint("Arg: %x\n", ((uintptr_t*)argdata)[i]); } for (i = 0; i < envcount; i++) { @@ -548,10 +547,30 @@ void sysRaise(KeThread *thread, uintptr_t *param1, uintptr_t *param2, if (signal >= NSIG) { *param1 = -1; + return; } *param1 = 0; keSendSignal(thread->process, 0, signal); } +void sysKill(KeThread *thread, uintptr_t *param1, uintptr_t *param2, + uintptr_t *param3, uintptr_t *param4, uintptr_t *param5) +{ + int pid = *param1; + int signal = *param2; + if (signal >= NSIG) + { + *param1 = -1; + return; + } + KeProcess *target = keGetProcess(pid); + if (!target) + { + *param1 = -1; + return; + } + *param1 = 0; + keSendSignal(target, 0, signal); +} void sysSyscall(KeThread *thread, uintptr_t index, uintptr_t *param1, uintptr_t *param2, uintptr_t *param3, uintptr_t *param4, uintptr_t *param5) @@ -878,6 +897,9 @@ void sysSyscall(KeThread *thread, uintptr_t index, uintptr_t *param1, case SYS_RAISE: sysRaise(thread, param1, param2, param3, param4, param5); break; + case SYS_KILL: + sysKill(thread, param1, param2, param3, param4, param5); + break; case SYS_GETPID: *param1 = thread->process->pid; break; diff --git a/system/kernel/sys/terminal.c b/system/kernel/sys/terminal.c index adb3377..706b7de 100644 --- a/system/kernel/sys/terminal.c +++ b/system/kernel/sys/terminal.c @@ -279,10 +279,40 @@ static int sysTerminalRequest(struct FsDeviceFile *file, FsRequest *request) switch (request->type) { + case FS_REQUEST_OPEN: + { + KeExecLevel oldlevel = keSetExecutionLevel(KE_LEVEL_HIGH); + keLockSpinlock(&terminallock); + if (!terminal->owner && !terminal->opencount) + { + terminal->owner = request->process; + } + if (terminal->owner == request->process) + { + terminal->opencount++; + } + keUnlockSpinlock(&terminallock); + keSetExecutionLevel(oldlevel); + fsFinishRequest(request); + } + break; + case FS_REQUEST_CLOSE: + { + KeExecLevel oldlevel = keSetExecutionLevel(KE_LEVEL_HIGH); + keLockSpinlock(&terminallock); + if (terminal->owner == request->process) + { + terminal->opencount--; + if (!terminal->opencount) terminal->owner = 0; + } + keUnlockSpinlock(&terminallock); + keSetExecutionLevel(oldlevel); + fsFinishRequest(request); + } + break; case FS_REQUEST_READ: { KeExecLevel oldlevel = keSetExecutionLevel(KE_LEVEL_HIGH); - keSetExecutionLevel(KE_LEVEL_HIGH); keLockSpinlock(&terminallock); if (!terminal->requestcount && (terminal->inputbuffer_pos >= (int)request->bufferlength)) { @@ -433,9 +463,15 @@ int sysTerminalInjectKey(int key, int modifiers, int down) { SysTextTerminal *terminal = &textterms[currentterm]; // SIGINT - if (control_pressed && (key == 'C')) + if (control_pressed && (key == 'c') && down) { - // TODO + if (terminal->owner) + { + keSendSignal(terminal->owner, 0, SIGINT); + keUnlockSpinlock(&terminallock); + keSetExecutionLevel(oldlevel); + return 0; + } } if ((key < 256) && down) { -- 2.11.4.GIT