int main(int argc, char* args[]) { printf("[ibin/init] Init process started... :) Thats so good!\n"); printf("[ibin/init] Switching into TTY to VGA mode.\nIf you see this something probably went wrong.\n"); HANDLE cntrl = fmkfifo("/var/cntrl/init"); texec("/ibin/ttytovga", 0); waitResp(cntrl); setstdout("/dev/tty0"); setstdin ("/dev/keyboard"); setstderr("/dev/tty0"); printf("[init] now working on tty0\n"); print_memstat(); printf("[init] executing virtual file drivers\n"); texec("/ibin/urnd_prov", 0); waitResp(cntrl); printf("[init] switching to shell\n"); char* testparams[] = { "test1", "test2", 0 }; texec("/ibin/csh", 0); while(1); return 0; }
int main(int argc, char* args[]) { char instr[512]; char execstr[512]; while(1) { printf("$%s> ", currentPath); getln(instr); if(instr[0] == '/') { //absolute path strcpy(execstr, instr); } else //relative path (TODO .. and .) { strcpy(execstr, currentPath); //TODO for every search path, not only current path strcpy((void*)((uint32_t)execstr + strlen(currentPath)), instr); } texec(execstr, 0); } return 0; }
void /*ARGSUSED*/ doexec(Char **v, struct command *t) { struct varent *pathv; Char *blk[2], **av, *dp, **pv, *sav; int i, hashval, hashval1; sigset_t nsigset; int slash; hashval = 0; /* * Glob the command name. We will search $path even if this does something, * as in sh but not in csh. One special case: if there is no PATH, then we * execute only commands which start with '/'. */ blk[0] = t->t_dcom[0]; blk[1] = 0; gflag = 0, tglob(blk); if (gflag) { pv = globall(blk); if (pv == 0) { setname(vis_str(blk[0])); stderror(ERR_NAME | ERR_NOMATCH); } gargv = 0; } else pv = saveblk(blk); trim(pv); exerr = 0; expath = Strsave(pv[0]); Vexpath = expath; pathv = adrof(STRpath); if (pathv == 0 && expath[0] != '/') { blkfree(pv); pexerr(); } slash = any(short2str(expath), '/'); /* * Glob the argument list, if necessary. Otherwise trim off the quote bits. */ gflag = 0; av = &t->t_dcom[1]; tglob(av); if (gflag) { av = globall(av); if (av == 0) { blkfree(pv); setname(vis_str(expath)); stderror(ERR_NAME | ERR_NOMATCH); } gargv = 0; } else av = saveblk(av); blkfree(t->t_dcom); t->t_dcom = blkspl(pv, av); free(pv); free(av); av = t->t_dcom; trim(av); if (*av == NULL || **av == '\0') pexerr(); xechoit(av); /* Echo command if -x */ /* * Since all internal file descriptors are set to close on exec, we don't * need to close them explicitly here. Just reorient ourselves for error * messages. */ SHIN = 0; SHOUT = 1; SHERR = 2; OLDSTD = 0; /* * We must do this AFTER any possible forking (like `foo` in glob) so that * this shell can still do subprocesses. */ sigemptyset(&nsigset); (void)sigprocmask(SIG_SETMASK, &nsigset, NULL); /* * If no path, no words in path, or a / in the filename then restrict the * command search. */ if (pathv == 0 || pathv->vec[0] == 0 || slash) pv = justabs; else pv = pathv->vec; sav = Strspl(STRslash, *av); /* / command name for postpending */ Vsav = sav; if (havhash) hashval = hashname(*av); i = 0; hits++; do { /* * Try to save time by looking at the hash table for where this command * could be. If we are doing delayed hashing, then we put the names in * one at a time, as the user enters them. This is kinda like Korn * Shell's "tracked aliases". */ if (!slash && pv[0][0] == '/' && havhash) { hashval1 = hash(hashval, i); if (!bit(xhash, hashval1)) goto cont; } if (pv[0][0] == 0 || eq(pv[0], STRdot)) /* don't make ./xxx */ texec(*av, av); else { dp = Strspl(*pv, sav); Vdp = dp; texec(dp, av); Vdp = 0; free(dp); } misses++; cont: pv++; i++; } while (*pv); hits--; Vsav = 0; free(sav); pexerr(); /* NOTREACHED */ }
static int sys(char *str) { char *s, *t; char *argv[100], path[100]; char *inname, *outname; int append = 0; int wait_pid; int argc; if(debugflag) fprintf(diagfile, "%s\n", str); inname = NULL; outname = NULL; argv[0] = shellname; argc = 1; t = str; while( isspace((int)*t) ) ++t; while(*t) { if(*t == '<') inname = t+1; else if(*t == '>') { if(t[1] == '>') { append = YES; outname = t+2; } else { append = NO; outname = t+1; } } else argv[argc++] = t; while( !isspace((int)*t) && *t!='\0' ) ++t; if(*t) { *t++ = '\0'; while( isspace((int)*t) ) ++t; } } if(argc == 1) /* no command */ return(-1); argv[argc] = 0; s = path; t = "/usr/bin/"; while(*t) *s++ = *t++; for(t = argv[1] ; (*s++ = *t++) ; ) ; if((wait_pid = fork()) == 0) { if(inname) freopen(inname, "r", stdin); if(outname) freopen(outname, (append ? "a" : "w"), stdout); enbint(SIG_DFL); texec(path+9, argv); /* command */ texec(path+4, argv); /* /bin/command */ texec(path , argv); /* /usr/bin/command */ fatal1("Cannot load %s",path+9); } return( await(wait_pid) ); }
/* * 该函数从根节点开始深度优先遍历整个语法树,为每个命令创建进程并执行 * pf1和pf2是管道线I/O句柄,pf1表示命令输入端,pf2表示命令输出端 * pf1[0]: 管道线输入端句柄 * pf1[1]: 闲置 * pf2[0]: 闲置 * pf2[1]: 管道线输出端句柄 */ void execute(int *t, int *pf1, int *pf2) { int i, f, pv[2]; int *t1; char *cp1, *cp2; extern int errno; if(t != 0) switch(t[DTYP]) { case TCOM: cp1 = (char *)t[DCOM]; /* 以下为内置命令*/ if(equal(cp1, "chdir")) { if(t[DCOM+1] != 0) { if(chdir(t[DCOM+1]) < 0) err("chdir: bad directory"); } else err("chdir: arg count"); return; } if(equal(cp1, "shift")) { if(dolc < 1) { prs("shift: no args\n"); return; } dolv[1] = dolv[0]; dolv++; dolc--; return; } if(equal(cp1, "login")) { if(promp != 0) { close(acctf); execv("/bin/login", t+DCOM); } prs("login: cannot execute\n"); return; } if(equal(cp1, "newgrp")) { if(promp != 0) { close(acctf); execv("/bin/newgrp", t+DCOM); } prs("newgrp: cannot execute\n"); return; } if(equal(cp1, "wait")) { pwait(-1, 0); return; } if(equal(cp1, ":")) return; /* 注意,这里没有break,筛选掉内置命令后,外部命令会继续往下走*/ case TPAR: f = t[DFLG]; i = 0; if((f&FPAR) == 0) /* 除了复合命令中最后一个子命令,其它一律fork子进程*/ i = fork(); if(i == -1) { err("try again"); return; } if(i != 0) { /* 父进程代码*/ if((f&FPIN) != 0) { close(pf1[0]); /* fork之后,子进程获得父进程的管道线句柄拷贝,我们要在父进程中关闭它,以免资源泄漏*/ close(pf1[1]); /* 注意,这里只关闭pf1,因为pf1、pf2都是pv的镜像,因此关闭pf1就是关闭pf2 */ } if((f&FPRS) != 0) {/* 打印子进程pid */ prn(i); prs("\n"); } if((f&FAND) != 0) /* 后台异步进程无需等待*/ return; if((f&FPOU) == 0) /* 节点为管道线末端,等待子进程终止*/ pwait(i, t); return; } /* 以下为子进程代码,或者FPAR属性节点命令进程*/ if(t[DLEF] != 0) { close(0); i = open(t[DLEF], 0); /* 重定向stdin到左子树节点*/ if(i < 0) { prs((char *)t[DLEF]); err(": cannot open"); exit(-1); } } if(t[DRIT] != 0) { if((f&FCAT) != 0) { i = open(t[DRIT], 1); if(i >= 0) { seek(i, 0, 2); /* 追加模式*/ goto f1; } } i = creat(t[DRIT], 0666); /* 创建新的文件句柄*/ if(i < 0) { prs((char *)t[DRIT]); err(": cannot create"); exit(-1); } f1: close(1); dup(i); /* 重定向stdout到右子树节点*/ close(i); } if((f&FPIN) != 0) { close(0); dup(pf1[0]); /* 重定向stdin到管道线输入端*/ close(pf1[0]); close(pf1[1]); /* 子进程关闭管道线句柄*/ } if((f&FPOU) != 0) { close(1); dup(pf2[1]); /* 重定向stdout 到管道线输出*/ close(pf2[0]); close(pf2[1]); /* 子进程关闭管道线句柄*/ } if((f&FINT)!=0 && t[DLEF]==0 && (f&FPIN)==0) { close(0); /* 若忽略中断,且不存在管道线输入,则关闭stdin并重定向到位桶*/ open("/dev/null", 0); /* 以免来自其它进程stdin干扰,但stdout是保留的*/ } if((f&FINT) == 0 && setintr) { signal(INTR, 0); /* 无FINT标识,则恢复中断信号响应(默认是忽略的) */ signal(QUIT, 0); } if(t[DTYP] == TPAR) { /* 如果是复合类型,则执行子命令,同时下推FINT标识*/ if(t1 = (int *)t[DSPR]) t1[DFLG] |= f&FINT; execute(t1, NULL, NULL); exit(0); } close(acctf); gflg = 0; scan(t, &tglob); /* 扫描通配符*/ if(gflg) { t[DSPR] = (int)"/etc/glob"; execv(t[DSPR], t+DSPR); /* 包含通配符的命令在/etc/glob中执行*/ prs("glob: cannot execute\n"); exit(-1); } scan(t, &trim); /* 解除引用标识*/ *linep = 0; texec((char *)t[DCOM], t); /* 最先执行当前目录下的命令*/ cp1 = linep; cp2 = "/usr/bin/"; while(*cp1 = *cp2++) /* strcpy,cp1停在'\0'位置 */ cp1++; cp2 = (char *)t[DCOM]; while(*cp1++ = *cp2++); /* strcpy,'\0'结束 */ texec(linep+4, t); /* 接着执行/bin目录下的命令*/ texec(linep, t); /* 最后执行/usr/bin目录下的命令*/ prs((char *)t[DCOM]); /* 若进程异常退出,表示找不到命令,退出shell */ err(": not found"); exit(-1); case TFIL: f = t[DFLG]; pipe(pv); /* 创建管道线,pv[0]为输入句柄,pv[1]为输出句柄*/ t1 = (int *)t[DLEF]; t1[DFLG] |= FPOU | (f&(FPIN|FINT|FPRS)); execute(t1, pf1, pv); /* 对于左子树节点,pv[1]作为管道线输出句柄传入,pv[0]闲置*/ t1 = (int *)t[DRIT]; t1[DFLG] |= FPIN | (f&(FPOU|FINT|FAND|FPRS)); /* 只有管道线末端命令才能继承FAND属性,与FPOU排斥*/ execute(t1, pv, pf2); /* 对于右子树节点,pv[0]作为管道线输入句柄传入,pv[1]闲置*/ return; case TLST: f = t[DFLG]&FINT; /* 对于命令序列节点,下推FINT属性到左右子树*/ if(t1 = (int *)t[DLEF]) t1[DFLG] |= f; execute(t1, NULL, NULL); /* 先左后右依次执行 */ if(t1 = (int *)t[DRIT]) t1[DFLG] |= f; execute(t1, NULL, NULL); return; } }
void doexec(struct command *t) { tchar *sav; tchar *dp, **pv, **av; struct varent *v; bool slash; int hashval, hashval1, i; tchar *blk[2]; #ifdef TRACE tprintf("TRACE- doexec()\n"); #endif /* * Glob the command name. If this does anything, then we * will execute the command only relative to ".". One special * case: if there is no PATH, then we execute only commands * which start with '/'. */ dp = globone(t->t_dcom[0]); sav = t->t_dcom[0]; exerr = 0; t->t_dcom[0] = dp; setname(dp); xfree(sav); v = adrof(S_path /* "path" */); if (v == 0 && dp[0] != '/') { pexerr(); } slash = gflag; /* * Glob the argument list, if necessary. * Otherwise trim off the quote bits. */ gflag = 0; av = &t->t_dcom[1]; tglob(av); if (gflag) { av = glob(av); if (av == 0) error("No match"); } blk[0] = t->t_dcom[0]; blk[1] = 0; av = blkspl(blk, av); #ifdef VFORK Vav = av; #endif trim(av); slash |= any('/', av[0]); xechoit(av); /* Echo command if -x */ /* * Since all internal file descriptors are set to close on exec, * we don't need to close them explicitly here. Just reorient * ourselves for error messages. */ SHIN = 0; SHOUT = 1; SHDIAG = 2; OLDSTD = 0; /* * We must do this AFTER any possible forking (like `foo` * in glob) so that this shell can still do subprocesses. */ (void) sigsetmask(0); /* * If no path, no words in path, or a / in the filename * then restrict the command search. */ if (v == 0 || v->vec[0] == 0 || slash) pv = justabs; else pv = v->vec; sav = strspl(S_SLASH /* "/" */, *av); /* / command name for postpending */ #ifdef VFORK Vsav = sav; #endif if (havhash) hashval = hashname(*av); i = 0; #ifdef VFORK hits++; #endif do { if (!slash && pv[0][0] == '/' && havhash) { hashval1 = hash(hashval, i); if (!bit(xhash, hashval1)) goto cont; } if (pv[0][0] == 0 || eq(pv[0], S_DOT /* "." */)) { /* don't make ./xxx */ texec(t, *av, av); } else { dp = strspl(*pv, sav); #ifdef VFORK Vdp = dp; #endif texec(t, dp, av); #ifdef VFORK Vdp = 0; #endif xfree(dp); } #ifdef VFORK misses++; #endif cont: pv++; i++; } while (*pv); #ifdef VFORK hits--; #endif #ifdef VFORK Vsav = 0; Vav = 0; #endif xfree(sav); xfree((char *)av); pexerr(); }