From e4d0298d1bf0d8d8d0a5981011f7d3e4050dd2d1 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Thu, 24 May 2018 19:54:42 +0200 Subject: [PATCH] core: Support fork, waitpid, execve. * stage0/x86.M1 (SYS_fork, SYS_waitpid, SYS_execve): New define. * lib/linux-gcc.c (fork, waitpid, execve): New function. * lib/linux-mes.c (fork, waitpid, execve): New function. * lib/libc.c (wait): New function. * include/unistd.h (fork, execve): Declare. * include/sys/wait.h (waitpid, wait): Declare. * module/mes/posix.mes (search-path, execlp, system*, waitpid): New function. * src/posix.c (primitive_fork, execl): New function. --- include/sys/wait.h | 15 ++++++++-- include/unistd.h | 4 ++- lib/libc.c | 6 ++++ lib/linux-gcc.c | 68 +++++++++++++++++++++++++++++++++++++++++++- lib/linux-mes.c | 29 +++++++++++++++++++ module/mes/posix.mes | 24 ++++++++++++++++ src/posix.c | 50 ++++++++++++++++++++++++++++---- stage0/x86.M1 | 3 ++ 8 files changed, 188 insertions(+), 11 deletions(-) diff --git a/include/sys/wait.h b/include/sys/wait.h index f90c419d..37bb299c 100644 --- a/include/sys/wait.h +++ b/include/sys/wait.h @@ -1,6 +1,6 @@ /* -*-comment-start: "//";comment-end:""-*- * Mes --- Maxwell Equations of Software - * Copyright © 2017 Jan (janneke) Nieuwenhuizen + * Copyright © 2017,2018 Jan (janneke) Nieuwenhuizen * * This file is part of Mes. * @@ -23,7 +23,16 @@ #if __GNUC__ && POSIX #undef __MES_SYS_WAIT_H #include_next -#endif // (__GNUC__ && POSIX) +#else // !(__GNUC__ && POSIX) + +#ifndef __MES_PID_T +#define __MES_PID_T +typedef int pid_t; +#endif + +pid_t waitpid (pid_t pid, int *status_ptr, int options); +pid_t wait (int *status_ptr); + +#endif // !(__GNUC__ && POSIX) #endif // __MES_SYS_WAIT_H - diff --git a/include/unistd.h b/include/unistd.h index 1c4086ad..dc11ec78 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -1,6 +1,6 @@ /* -*-comment-start: "//";comment-end:""-*- * Mes --- Maxwell Equations of Software - * Copyright © 2017 Jan (janneke) Nieuwenhuizen + * Copyright © 2017,2018 Jan (janneke) Nieuwenhuizen * * This file is part of Mes. * @@ -49,7 +49,9 @@ typedef long ssize_t; int access (char const *s, int mode); int close (int fd); +int execve (char const *file, char *const argv[], char *const env[]); int execvp (char const *file, char *const argv[]); +int fork (); char *getcwd (char *buf, size_t size); int isatty (int fd); off_t lseek (int fd, off_t offset, int whence); diff --git a/lib/libc.c b/lib/libc.c index 7f0bf1c1..63939565 100644 --- a/lib/libc.c +++ b/lib/libc.c @@ -444,4 +444,10 @@ isatty (int fd) return ioctl (fd, TCGETS, 0) & 0xf0; } +int +wait (int *status_ptr) +{ + return waitpid (-1, status_ptr, 0); +} + #endif //!POSIX diff --git a/lib/linux-gcc.c b/lib/linux-gcc.c index 4f357b10..3dfbf623 100644 --- a/lib/linux-gcc.c +++ b/lib/linux-gcc.c @@ -1,6 +1,6 @@ /* -*-comment-start: "//";comment-end:""-*- * Mes --- Maxwell Equations of Software - * Copyright © 2016,2017 Jan (janneke) Nieuwenhuizen + * Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen * * This file is part of Mes. * @@ -21,9 +21,29 @@ #include #include #include +#include +#include #if !POSIX +int +fork () +{ +#if !__TINYC__ + int r; + //syscall (SYS_fork, fd)); + asm ( + "mov $0x02,%%eax\n\t" + "int $0x80\n\t" + "mov %%eax,%0\n\t" + : "=r" (r) + : //no inputs + : "eax" + ); + return r; +#endif +} + int read (int fd, void* buf, size_t n) { @@ -77,6 +97,52 @@ open (char const *s, int flags, ...) #endif } +pid_t +waitpid (pid_t pid, int *status_ptr, int options) +{ +#if !__TINYC__ + int r; + //syscall (SYS_execve, file_name, argv, env)); + asm ( + "mov %1,%%ebx\n\t" + "mov %2,%%ecx\n\t" + "mov %3,%%edx\n\t" + + "mov $0x07,%%eax\n\t" + "int $0x80\n\t" + + "mov %%eax,%0\n\t" + : "=r" (r) + : "" (pid), "" (status_ptr), "" (options) + : "eax", "ebx", "ecx", "edx" + ); + return r; +#endif +} + +int +execve (char const* file_name, char *const argv[], char *const env[]) +{ +#if !__TINYC__ + int r; + //syscall (SYS_execve, file_name, argv, env)); + asm ( + "mov %1,%%ebx\n\t" + "mov %2,%%ecx\n\t" + "mov %3,%%edx\n\t" + + "mov $0x0b,%%eax\n\t" + "int $0x80\n\t" + + "mov %%eax,%0\n\t" + : "=r" (r) + : "" (file_name), "" (argv), "" (env) + : "eax", "ebx", "ecx", "edx" + ); + return r; +#endif +} + int chmod (char const *s, int mode) { diff --git a/lib/linux-mes.c b/lib/linux-mes.c index 75dee3a9..f525381e 100644 --- a/lib/linux-mes.c +++ b/lib/linux-mes.c @@ -18,6 +18,13 @@ * along with Mes. If not, see . */ +void +fork () +{ + asm ("mov____$i32,%eax SYS_fork"); + asm ("int____$0x80"); +} + void read () { @@ -40,6 +47,28 @@ open () asm ("int____$0x80"); } +void +waitpid () +{ + asm ("mov____0x8(%ebp),%ebx !8"); + asm ("mov____0x8(%ebp),%ecx !12"); + asm ("mov____0x8(%ebp),%edx !16"); + + asm ("mov____$i32,%eax SYS_waitpid"); + asm ("int____$0x80"); +} + +void +execve () +{ + asm ("mov____0x8(%ebp),%ebx !8"); + asm ("mov____0x8(%ebp),%ecx !12"); + asm ("mov____0x8(%ebp),%edx !16"); + + asm ("mov____$i32,%eax SYS_execve"); + asm ("int____$0x80"); +} + void chmod () { diff --git a/module/mes/posix.mes b/module/mes/posix.mes index 1eec487a..5c039a60 100644 --- a/module/mes/posix.mes +++ b/module/mes/posix.mes @@ -31,3 +31,27 @@ (if (and ext (string-suffix? ext base)) (string-drop-right base (string-length ext)) base))) + +(define (search-path path file-name) + (if (access? file-name R_OK) file-name + (let loop ((path path)) + (and (pair? path) + (let ((f (string-append (car path) "/" file-name))) + (if (access? f R_OK) f + (loop (cdr path)))))))) + +(define (execlp file-name args) + (let ((executable (if (string-index file-name #\/) file-name + (search-path (string-split (getenv "PATH") #\:) file-name)))) + (execl executable args))) + +(define (system* file-name . args) + (let ((pid (primitive-fork))) + (cond ((zero? pid) (apply execlp file-name (list args))) + ((= -1 pid) (error "fork failed:" file-name)) + (else (let ((pid+status (waitpid 0))) + (cdr pid+status)))))) + +(define (waitpid pid . options) + (let ((options (if (null? options) 0 (car options)))) + (core:waitpid pid options))) diff --git a/src/posix.c b/src/posix.c index 2d483c9a..41772f60 100644 --- a/src/posix.c +++ b/src/posix.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include @@ -139,11 +140,9 @@ write_byte (SCM x) ///((arity . n)) char string_to_cstring_buf[1024]; char const* -string_to_cstring (SCM s) +string_to_cstring_ (SCM s, char *buf) { - //static char buf[1024]; - //char *p = buf; - char *p = string_to_cstring_buf; + char *p = buf; s = STRING(s); while (s != cell_nil) { @@ -151,8 +150,13 @@ string_to_cstring (SCM s) s = cdr (s); } *p = 0; - //return buf; - return string_to_cstring_buf; + return buf; +} + +char const* +string_to_cstring (SCM s) +{ + return string_to_cstring_ (s, string_to_cstring_buf); } SCM @@ -256,3 +260,37 @@ isatty_p (SCM port) { return isatty (VALUE (port)) ? cell_t : cell_f; } + +SCM +primitive_fork () +{ + return MAKE_NUMBER (fork ()); +} + +SCM +execl_ (SCM file_name, SCM args) ///((name . "execl")) +{ + char *c_argv[10]; + int i = 0; + int n = 0; + c_argv[i++] = string_to_cstring_ (file_name, string_to_cstring_buf+n); + n += length__ (STRING (file_name)) + 1; + while (args != cell_nil) + { + assert (TYPE (CAR (args)) == TSTRING); + assert (i < 20); + c_argv[i++] = string_to_cstring_ (CAR (args), string_to_cstring_buf+n); + n += length__ (STRING (CAR (args))) + 1; + args = CDR (args); + } + c_argv[i] = 0; + return MAKE_NUMBER (execve (c_argv[0], c_argv, g_environment)); +} + +SCM +waitpid_ (SCM pid, SCM options) +{ + int status; + int child = waitpid (VALUE (pid), &status, VALUE (options)); + return cons (MAKE_NUMBER (child), MAKE_NUMBER (status)); +} diff --git a/stage0/x86.M1 b/stage0/x86.M1 index 268f3277..3c1e0f6f 100644 --- a/stage0/x86.M1 +++ b/stage0/x86.M1 @@ -215,11 +215,14 @@ DEFINE movzwl_0x8(%ebp),%eax 0fb745 DEFINE movzwl_0x8(%ebp),%eax 0fb745 DEFINE SYS_exit 01000000 +DEFINE SYS_fork 02000000 DEFINE SYS_read 03000000 DEFINE SYS_write 04000000 DEFINE SYS_open 05000000 DEFINE SYS_close 06000000 +DEFINE SYS_waitpid 07000000 DEFINE SYS_unlink 0a000000 +DEFINE SYS_execve 0b000000 DEFINE SYS_chmod 0f000000 DEFINE SYS_lseek 13000000 DEFINE SYS_access 21000000