From 061e445a95e92fdb94b78478510bd2c02d57e9ba Mon Sep 17 00:00:00 2001 From: =?utf8?q?Janosch=20Gr=C3=A4f?= Date: Sat, 6 Dec 2008 03:36:54 +0100 Subject: [PATCH] +execute(); +unnamed pipes (stdin,stdout,stderr); +argc/argv --- apps/Makefile | 2 + apps/include/misc.h | 10 +- apps/init/exe_elf.c | 18 +-- apps/init/exe_elf.h | 4 +- apps/init/init.c | 7 +- apps/lib/crt0/crt0.c | 55 +++++++-- apps/lib/libmeinos/execute.c | 73 ++++++++++++ apps/lib/stdlibc/files.c | 275 +++++++++++++++++++++++++++++++++++-------- apps/lib/stdlibc/stdlib.c | 7 +- kernel2/procm.c | 14 ++- 10 files changed, 392 insertions(+), 73 deletions(-) create mode 100644 apps/lib/libmeinos/execute.c diff --git a/apps/Makefile b/apps/Makefile index ec51763..e59fd5f 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -4,6 +4,7 @@ all: cp -R include/* $(GCC_TOOLCHAIN)/include/ make -C lib/ + make -C sh/ make -C com/ make -C devfs/ make -C floppy/ @@ -29,6 +30,7 @@ all: clean: make -C lib/ clean + make -C sh/ clean make -C com/ clean make -C devfs/ clean make -C floppy/ clean diff --git a/apps/include/misc.h b/apps/include/misc.h index 223c85d..067b505 100644 --- a/apps/include/misc.h +++ b/apps/include/misc.h @@ -35,7 +35,15 @@ int vfs_mount(const char *fs,const char *mountpoint,const char *dev,int readonly int vfs_unmount(const char *fs,const char *mountpoint); // Execute -int execute(const char *path,char *argv[]); +struct process_data { + int shmid_stdin; + int shmid_stdout; + int shmid_stderr; + char cmdline[0]; + //char enviroment[0]; +} *_process_data; + +pid_t execute(const char *path,char *argv[],int *stdin,int *stdout,int *stderr); // Initialization static inline void init_ready() { diff --git a/apps/init/exe_elf.c b/apps/init/exe_elf.c index b604303..c494a78 100644 --- a/apps/init/exe_elf.c +++ b/apps/init/exe_elf.c @@ -44,17 +44,21 @@ static int elf_loadseg(pid_t pid,int fh,void *mem_addr,size_t mem_size,size_t fi if (mem_addr<(void*)USERSPACE_ADDRESS) return -1; size_t i; int ret = 0; + pid_t own_pid = getpid(); - for (i=0;ifile_size?PAGE_SIZE:file_size-i*PAGE_SIZE); - proc_memunmap(getpid(),buf); - if (proc_memmap(pid,mem_addr+i,mem_getphysaddr(buf),writable,1,0)==-1) { + size_t cur_count = i>file_size?0:(i+PAGE_SIZE>file_size?file_size%PAGE_SIZE:PAGE_SIZE); + read(fh,buf,cur_count); + if (proc_memmap(pid,mem_addr+i,mem_getphysaddr(buf),writable,1,0)==0) proc_memunmap(own_pid,buf); + else { + proc_memfree(own_pid,buf); ret = -1; break; } } - return ret; } @@ -68,13 +72,13 @@ void *elf_load(pid_t pid,const char *file) { // Header read(fh,&header,sizeof(header)); - elf_validate(&header); + if (!elf_validate(&header)) return NULL; entrypoint = (void*)(header.entry); // Program Headers progheader = malloc(sizeof(elf_progheader_t)*header.phnum); lseek(fh,header.phoff,SEEK_SET); - read(fh,&progheader,sizeof(elf_progheader_t)*header.phnum); + read(fh,progheader,sizeof(elf_progheader_t)*header.phnum); for (i=0;i. */ +#include +#include #include +#include +#include #include +#include int main(int argc,char *argv[]); -int _stdlib_init(); -int _libmeinos_init(); +int _stdlib_init_pre(); ///< @see apps/lib/stdlibc/stdlib.c +int _stdlib_init_post(); ///< @see apps/lib/stdlibc/stdlib.c +int _libmeinos_init(); ///< @see apps/lib/libmeinos/misc.c + #include +static void get_cmdline(struct process_data *data,char ***_argv,int *_argc) { + char **argv = NULL; + int argc; + size_t i = 0; + + for (argc=0;data->cmdline[i]!=0;argc++) { + argv = realloc(argv,(argc+1)*sizeof(char*)); + argv[argc] = data->cmdline+i; + i += strlen(data->cmdline+i)+1; + } + + *_argv = argv; + *_argc = argc; +} + void _start() { - _stdlib_init(); + int var,argc,ret; + char **argv; + + // initialize libs + _stdlib_init_pre(); _libmeinos_init(); - // get initial data and call main - int argc = 0; - char **argv = NULL; - exit(main(argc,argv)); + // get process data + var = syscall_call(SYSCALL_PROC_GETVAR,1,getpid()); + if (var!=-1) { + _process_data = shmat(var,NULL,0); + if (_process_data!=NULL) get_cmdline(_process_data,&argv,&argc); + } + + // post initialize stdlibc + _stdlib_init_post(); + + // call main function + ret = main(argc,argv); + + // remove process data + shmdt(_process_data); + shmctl(var,IPC_RMID,NULL); - // in case exit did not work + // exit + exit(ret); while (1); } diff --git a/apps/lib/libmeinos/execute.c b/apps/lib/libmeinos/execute.c new file mode 100644 index 0000000..be0edd7 --- /dev/null +++ b/apps/lib/libmeinos/execute.c @@ -0,0 +1,73 @@ +/* + meinOS - A unix-like x86 microkernel operating system + Copyright (C) 2008 Janosch Gräf + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include + +int _create_unnamed_pipe(int read,int *_shmid); + +/** + * Creates a new process from executable file + * @param path Path to executable + * @param argv Argument vector + * @param stdin Reference for filehandle for stdin of new process + * @param stdout Reference for filehandle for stdout of new process + * @param stderr Reference for filehandle for stderr of new process + * @return PID of new process + */ +pid_t execute(const char *path,char *argv[],int *_stdin,int *_stdout,int *_stderr) { + size_t shmsize = sizeof(struct process_data)+1; + int shmid; + struct process_data *data; + size_t i; + + if (argv!=NULL) { + for (i=0;argv[i];i++) shmsize += strlen(argv[i])+1; + } + shmid = shmget(IPC_PRIVATE,shmsize,0); + + if (shmid!=-1) { + data = shmat(shmid,NULL,0); + if (data!=NULL) { + int stdin = _create_unnamed_pipe(0,&(data->shmid_stdin)); + int stdout = _create_unnamed_pipe(1,&(data->shmid_stdout)); + int stderr = _create_unnamed_pipe(1,&(data->shmid_stderr)); + if (_stdin!=NULL) *_stdin = stdin; + if (_stdout!=NULL) *_stdout = stdout; + if (_stderr!=NULL) *_stderr = stderr; + + size_t j = 0; + if (argv!=NULL) { + + for (i=0;argv[i];i++) { + strcpy(data->cmdline+j,argv[i]); + j += strlen(data->cmdline+j)+1; + } + } + data->cmdline[j] = 0; + + shmdt(data); + + return rpc_call("proc_execute",0,path,shmid); + } + } + return -1; +} diff --git a/apps/lib/stdlibc/files.c b/apps/lib/stdlibc/files.c index 108164a..7ae7bd6 100644 --- a/apps/lib/stdlibc/files.c +++ b/apps/lib/stdlibc/files.c @@ -28,6 +28,7 @@ #include #include #include +#include #include // open,close #include // read,write,seek,truncate @@ -73,6 +74,9 @@ static struct { path_t *path; } workdir; static mode_t creation_mask; +struct process_data *_process_data; + +static int _open_unnamed_pipe(int fh,int shmid); /** * Initializes File I/O @@ -80,7 +84,7 @@ static mode_t creation_mask; void _fs_init() { filelist = llist_create(); fslist = llist_create(); - lastfh = 1; + lastfh = 3; creation_mask = 0777; // Init current workdir @@ -88,6 +92,11 @@ void _fs_init() { if (path==NULL) path = "/"; memset(&workdir,0,sizeof(workdir)); chdir(path); + + // Create stdin, stdout, stderr + _open_unnamed_pipe(STDIN_FILENO,_process_data->shmid_stdin); + _open_unnamed_pipe(STDOUT_FILENO,_process_data->shmid_stdout); + _open_unnamed_pipe(STDERR_FILENO,_process_data->shmid_stderr); } /** @@ -182,6 +191,161 @@ static char *getabsolutepath(const char *relative) { } /** + * Creates an unnamed pipe + * @param read Whether creator is reader + * @return Filehandle + */ +int _create_unnamed_pipe(int read,int *_shmid) { + int shmid = shmget(IPC_PRIVATE,SHMMEM_SIZE,0); + if (shmid!=-1) { + size_t *shmbuf = shmat(shmid,NULL,0); + if (shmbuf!=NULL) { + struct filelist_item *new = malloc(sizeof(struct filelist_item)); + memset(new,0,sizeof(struct filelist_item)); + new->fh = getnew_fh(); + new->oflag = read?O_RDONLY:O_WRONLY; + new->shmid = shmid; + new->shmbuf = shmbuf; + shmbuf[0] = read; // Direction + shmbuf[1] = 0; // Reserved for error + shmbuf[2] = 0; // Reading position + shmbuf[3] = 0; // Writing position + llist_push(filelist,new); + if (_shmid!=NULL) *_shmid = shmid; + return new->fh; + } + else shmctl(shmid,IPC_RMID,NULL); + } + return -1; +} + +/** + * Destroys an unnamed pipe + * @param fh Filehandle of unnamed pipe + * @return Success? + */ +int _destroy_unnamed_pipe(int fh) { + struct filelist_item *file = filebyfh(fh); + + if (file && file->fs==NULL) { + shmdt(file->shmbuf); + shmctl(file->shmid,IPC_RMID,NULL); + llist_remove(filelist,lidxbyfh(fh)); + free(file); + return 0; + } + else errno = EBADF; + return -1; +} + +/** + * Opens an unnamed pipe + * @param fh Use this filehandle (-1 no specified filehandle) + * @param shmid SHM object the unnamed pipe uses + * @note If you specify the filehandle, be sure that it isn't used already + * @return Filehandle + */ +static int _open_unnamed_pipe(int fh,int shmid) { + size_t *shmbuf = shmat(shmid,NULL,0); + if (shmbuf!=NULL) { + if (fh==-1) fh = getnew_fh(); + struct filelist_item *new = malloc(sizeof(struct filelist_item)); + memset(new,0,sizeof(struct filelist_item)); + new->fh = fh; + new->oflag = shmbuf[0]?O_WRONLY:O_RDONLY; + new->shmid = shmid; + new->shmbuf = shmbuf; + llist_push(filelist,new); + return fh; + } + else return -1; +} + +/** + * Destroys an unnamed pipe + * @param fh Filehandle of unnamed pipe + * @return Success? + */ +static int _close_unnamed_pipe(int fh) { + struct filelist_item *file = filebyfh(fh); + + if (file && file->fs==NULL) { + shmdt(file->shmbuf); + llist_remove(filelist,lidxbyfh(fh)); + free(file); + return 0; + } + else errno = EBADF; + return -1; +} + +/** + * Reads an unnamed pipe + * @param fh Filehandle + * @param data Data buffer + * @param size How many bytes to read + * @return How many bytes read + */ +static size_t _read_unnamed_pipe(int fh,void *data,size_t size) { + struct filelist_item *file = filebyfh(fh); + ssize_t size_read = -1; + + if (file && file->fs==NULL && file->oflag==O_RDONLY) { + size_t *pos_read = file->shmbuf+2*sizeof(size_t); + size_t *pos_write = file->shmbuf+3*sizeof(size_t); + void *buffer = file->shmbuf+4*sizeof(size_t); + size_t size_free = *pos_write>=*pos_read?*pos_write-*pos_read:*pos_write+SHMMEM_SIZE-4*sizeof(int)-*pos_read; + + if (size>size_free) size = size_free; + if (*pos_write>=*pos_read) memcpy(data,buffer,size); + else { + size_t part1 = SHMMEM_SIZE-4*sizeof(int)-*pos_read; + size_t part2 = *pos_write; + memcpy(data,buffer+*pos_read,part1); + memcpy(data+part1,buffer,part2); + } + *pos_read = (*pos_read+size)%(SHMMEM_SIZE-4*sizeof(int)); + + size_read = size; + } + else errno = EBADF; + return size_read; +} + +/** + * Writes an unnamed pipe + * @param fh Filehandle + * @param data Data buffer + * @param size How many bytes to write + * @return How many bytes written + */ +static size_t _write_unnamed_pipe(int fh,const void *data,size_t size) { + struct filelist_item *file = filebyfh(fh); + ssize_t size_written = -1; + + if (file && file->fs==NULL && file->oflag==O_WRONLY) { + size_t *pos_read = file->shmbuf+2*sizeof(size_t); + size_t *pos_write = file->shmbuf+3*sizeof(size_t); + void *buffer = file->shmbuf+4*sizeof(size_t); + size_t size_free = *pos_read>*pos_write?*pos_read-*pos_write:*pos_read+SHMMEM_SIZE-4*sizeof(int)-*pos_write; + + if (size>size_free) size = size_free; + if (*pos_read>=*pos_write) memcpy(buffer,data,size); + else { + size_t part1 = SHMMEM_SIZE-4*sizeof(int)-*pos_write; + size_t part2 = *pos_read; + memcpy(buffer+*pos_write,data,part1); + memcpy(buffer,data+part1,part2); + } + *pos_write = (*pos_write+size)%(SHMMEM_SIZE-4*sizeof(int)); + + size_written = size; + } + else errno = EBADF; + return size_written; +} + +/** * Gets current workdir * @param buf Buffer to store path in * @param size Size of buffer @@ -343,6 +507,12 @@ void _close_all_filehandles() { if (S_ISREG(file->mode)) close(file->fh); else if (S_ISDIR(file->mode)) closedir(file); } + + // close stdin, stdout and stderr + _destroy_unnamed_pipe(STDIN_FILENO); + _destroy_unnamed_pipe(STDOUT_FILENO); + _destroy_unnamed_pipe(STDERR_FILENO); + } /** @@ -354,6 +524,7 @@ int close(int fildes) { int res; char *func; struct filelist_item *file = filebyfh(fildes); + if (file->fs==NULL) return _close_unnamed_pipe(fildes); if (file) { asprintf(&func,"fs_close_%x",file->fs->pid); res = rpc_call(func,0,file->fs->id,file->fs_fh); @@ -411,35 +582,38 @@ int dup2(int fildes,int fildes2) { * @param count How many bytes to read * @return How many bytes read */ -static ssize_t _read(int fildes,void *buf,size_t count) { - int res; +static ssize_t _read(struct filelist_item *file,void *buf,size_t count) { + ssize_t res; char *func; - struct filelist_item *file = filebyfh(fildes); - if (file!=NULL) { - asprintf(&func,"fs_read_%x",file->fs->pid); - res = rpc_call(func,0,file->fs->id,file->fs_fh,count); - free(func); - if (res>0) memcpy(buf,file->shmbuf,res); - } - else res = -EBADF; - errno = res<0?-res:0; - return res<0?-1:res; + asprintf(&func,"fs_read_%x",file->fs->pid); + res = rpc_call(func,0,file->fs->id,file->fs_fh,count); + free(func); + if (res>0) memcpy(buf,file->shmbuf,res); + return res; } ssize_t read(int fildes,void *buf,size_t count) { - ssize_t count_rem = count; - size_t off = 0; + struct filelist_item *file = filebyfh(fildes); + if (file->fs==NULL) return _read_unnamed_pipe(fildes,buf,count); + else if (file!=NULL) { + ssize_t count_rem = count; + size_t off = 0; + + while (count_rem>0) { + size_t count_cur = count_rem; + if (count_cur>SHMMEM_SIZE) count_cur = SHMMEM_SIZE; + count_cur = _read(file,buf+off,count_cur); + if (count_cur==-1) return -1; + count_rem -= count_cur; + if (count_cur==0) break; + off += count_cur; + } - while (count_rem>0) { - size_t count_cur = count_rem; - if (count_cur>SHMMEM_SIZE) count_cur = SHMMEM_SIZE; - count_cur = _read(fildes,buf+off,count_cur); - if (count_cur==-1) return -1; - count_rem -= count_cur; - if (count_cur==0) break; - off += count_cur; + return count-count_rem; + } + else { + errno = EBADF; + return -1; } - - return count-count_rem; } /** @@ -449,33 +623,36 @@ ssize_t read(int fildes,void *buf,size_t count) { * @param count How many bytes to write * @return How many bytes written */ -static ssize_t _write(int fildes,const void *buf,size_t count) { - int res; +static ssize_t _write(struct filelist_item *file,const void *buf,size_t count) { char *func; - struct filelist_item *file = filebyfh(fildes); - if (file) { - memcpy(file->shmbuf,buf,count); - asprintf(&func,"fs_write_%x",file->fs->pid); - res = rpc_call(func,0,file->fs->id,file->fs_fh,count); - free(func); - } - else res = -EBADF; - errno = res<0?-res:0; - return res<0?-1:res; + ssize_t res; + memcpy(file->shmbuf,buf,count); + asprintf(&func,"fs_write_%x",file->fs->pid); + res = rpc_call(func,0,file->fs->id,file->fs_fh,count); + free(func); + return res; } ssize_t write(int fildes,const void *buf,size_t count) { - ssize_t count_rem = count; - size_t off = 0; - while (count_rem>0) { - size_t count_cur = count_rem; - if (count_cur>SHMMEM_SIZE) count_cur = SHMMEM_SIZE; - count_cur = _write(fildes,buf+off,count_cur); - if (count_cur==-1) return -1; - count_rem -= count_cur; - if (count_cur==0) break; - off += count_cur; - } - return count-count_rem; + struct filelist_item *file = filebyfh(fildes); + if (file->fs==NULL) return _write_unnamed_pipe(fildes,buf,count); + else if (file) { + ssize_t count_rem = count; + size_t off = 0; + while (count_rem>0) { + size_t count_cur = count_rem; + if (count_cur>SHMMEM_SIZE) count_cur = SHMMEM_SIZE; + count_cur = _write(file,buf+off,count_cur); + if (count_cur==-1) return -1; + count_rem -= count_cur; + if (count_cur==0) break; + off += count_cur; + } + return count-count_rem; + } + else { + errno = EBADF; + return -1; + } } /** diff --git a/apps/lib/stdlibc/stdlib.c b/apps/lib/stdlibc/stdlib.c index eab2f39..597ff10 100644 --- a/apps/lib/stdlibc/stdlib.c +++ b/apps/lib/stdlibc/stdlib.c @@ -27,18 +27,21 @@ #include // some variables/functions needed -void _fs_init(); ///< @see files.c void stdio_init(); ///< @see stdio.h void env_init(); ///< @see env.c llist_t atexit_list; ///< @see stdlib.c void _close_all_filehandles(); ///< @see files.c void _signal_init(); ///< @see signal.c +void _fs_init(); ///< @see apps/lib/stdlibc/files.c -void _stdlib_init() { +void _stdlib_init_pre() { rand_seed = rand_seed%RAND_MAX; errno = 0; atexit_list = llist_create(); _signal_init(); +} + +void _stdlib_init_post() { _fs_init(); stdio_init(); env_init(); diff --git a/kernel2/procm.c b/kernel2/procm.c index 93eeffc..5436302 100644 --- a/kernel2/procm.c +++ b/kernel2/procm.c @@ -401,7 +401,7 @@ pid_t proc_getpidbyname(const char *name) { */ int proc_getvar(pid_t pid) { proc_t *proc = proc_find(pid); - if (proc!=NULL) return proc->var; + if (proc!=NULL && (proc_current->system || proc_current==proc)) return proc->var; else return -1; } @@ -567,6 +567,14 @@ int proc_memmap(pid_t proc_pid,void *virt,void *phys,int writable,int swappable, return -1; } +/** + * Allocates a page for a process + * @param proc_pid Process' PID + * @param virt Virtual address + * @param writable Whether to alloc wirtable memory + * @param swappable Whether memory should be swappable + * @return Success? + */ int proc_memalloc(pid_t proc_pid,void *virt,int writable,int swappable) { void *page = memphys_alloc(); if (proc_memmap(proc_pid,virt,page,writable,swappable,0)==0) return 0; @@ -680,11 +688,11 @@ int proc_jump(pid_t proc_pid,void *dest) { int *proc_createstack(pid_t proc_pid) { if (proc_current->system) { proc_t *proc = proc_find(proc_pid); - if (proc!=NULL && proc->addrspace->stack!=NULL) { + if (proc!=NULL && proc->addrspace->stack==NULL) { int *stack = memuser_create_stack(proc->addrspace); proc->registers.esp = (uint32_t)stack; return stack; } } return NULL; -} \ No newline at end of file +} -- 2.11.4.GIT