/* * Csh - a shell bp PJAC * command tree execution */ #include "csh.h" rtree(tree) struct cmd *tree; { int result = 0; int xres; for(; tree ; tree = tree->cm_next){ if(result = set_redirect(tree)) break; if(tree->cm_child){ result = rtree(tree->cm_child); if(result){ unset_redirect(tree->cm_child); break; } if(tree->cm_argc <= 0){ /* no commands here */ result = unset_redirect(tree); if(result) break; continue; } } result = r_tree(tree); xres = unset_redirect(tree); if(xres && !result) result = xres; if(result) break; } return(result); } unset_redirect(tree) struct cmd *tree; { if(tree->cm_ifile && *tree->cm_ifile == '|'){ if(*IPipe){ close(0); unlink(IPipe); *IPipe = 0; } } if(tree->cm_ofile){ dup2(in_ofd, 1); /* get the fd back */ if(*tree->cm_ofile == '|'){ if(tree->cm_ofile[1] == '&') /* get stderr back */ dup2(in_efd, 2); if(!*OPipe){ puterr("Csh err: wanted to give Opipe away, non there.\n"); return(ERR); } if(*IPipe){ puterr("Csh err: Tried to fill Ipipe - already set.\n"); return(ERR); } strcpy(IPipe, OPipe); *OPipe = 0; return(OK); } if(*tree->cm_ofile == '&') dup2(in_efd, 2); } return(OK); } set_redirect(tree) struct cmd *tree; { char *file; int stde = FALSE; if(tree->cm_ifile != 0){ /* someone want's redirection */ if(*tree->cm_ifile == '|'){ /* want's piped input */ if(*IPipe == '\0'){ puterr("Csh err: Wanted pipe input, non available.\n"); return(ERR); } file = IPipe; } else file = tree->cm_ifile; close(0); if(openf(file, 0) != 0) return(ERR); } if(tree->cm_ofile == 0) return(OK); if(*tree->cm_ofile == '|'){ if(*OPipe){ puterr("Can't do multiple pipes yet.\n"); return(ERR); } close(1); if(mkopipe() != 1) return(ERR); if(tree->cm_ofile[1] == '&') dup2(1, 2); return(OK); } file = tree->cm_ofile; if(*file == '&'){ file++; stde = TRUE; } close(1); if(*file == '>'){ if(openf(++file, 2) != 1) return(ERR); } else if(openf(file, 1) != 1) return(ERR); if(stde) dup2(1, 2); return(OK); } mkopipe() { static char *pstrs[] = { "/tmp/", "/", 0, }; static int ser; char **xp; int result; for(xp = pstrs ; *xp ; xp++){ strcpy(OPipe, *xp); strcat(OPipe, my_Itoa(getpid())); strcat(OPipe, "_"); strcat(OPipe, my_Itoa(++ser)); strcat(OPipe, ".pip"); if((result = creat(OPipe, 0644)) >= 0) return(result); } puterr("Can't create pipe tmp file.\n"); return(-1); } openf(file, mode) char *file; { int result = -1; long lseek(); switch(mode){ case 0: result = open(file, 0); break; case 2: result = open(file, 1); /* fall through */ case 1: if(result < 0) result = creat(file, 0644); if(mode == 2 && result >= 0) lseek(result, 0L, 2); break; } if(result < 0){ if(mode == 0) puterr("Can't open '"); else puterr("Can't create '"); puterr(file); puterr("'.\n"); } return(result); } r_tree(tree) struct cmd *tree; { struct inbuilt *inbp, *find_inb(); struct lvars *lp; int nargs, totargs, i; char **xp; if(tree->cm_argc <= 0){ puterr("Null command.\n"); return(ERR); } for(lp = Aliases ; lp ; lp = lp->L_next) lp->L_flags &= ~L_ADONE; retry:; for(lp = Aliases ; lp ; lp = lp->L_next) if(strcmp(lp->L_name, tree->cm_argv[0]) == 0) break; if(lp != 0 && (lp->L_flags & L_ADONE) == 0){ /* got an alias, Blow the arg array */ /* find out how many arguments there are in the alias */ for(nargs = 0 ; lp->L_aval[nargs] ; nargs++); /* now blow the first arg away and replace by the other * args */ free(tree->cm_argv[0]); if(nargs == 1) /* simple case */ tree->cm_argv[0] = strsave(lp->L_aval[0]); else { totargs = nargs + tree->cm_argc; xp = (char **)mmalloc(totargs * sizeof(char *)); for(i = 0 ; i < nargs ; i++) xp[i] = strsave(lp->L_aval[i]); for(i = 1; nargs < totargs ; nargs++, i++) xp[nargs] = tree->cm_argv[i]; free( (char *)tree->cm_argv); tree->cm_argv = xp; tree->cm_argc = totargs - 1; /* -1 for argv[0] */ } lp->L_flags |= L_ADONE; goto retry; } if(tree->cm_argc <= 0) /* safety, aliases might be screwed */ return(ERR); if(xflag && (!in_cshrc || XVflag)){ for(xp = tree->cm_argv ; *xp ; ){ put_s(*xp++); if(*xp) put_s(" "); } put_s("\n"); } if(nflag) return(OK); if((inbp = find_inb(tree->cm_argv[0])) != NULL) return( (*inbp->in_prog)(tree->cm_argc, tree->cm_argv) ); else return(exec_prog(tree)); } struct inbuilt * find_inb(cmd) char *cmd; { register struct inbuilt *ip; for(ip = incmds ; ip->in_cmd != 0 ; ip++) if(strcmp(ip->in_cmd, cmd) == 0) return(ip); return(0); } /* * execute a program */ exec_prog(tree) struct cmd *tree; { char *p, *q, *s; char lpath[128]; char *tpath, **xp; int result = -1; int hash; int dnumb = 0; tpath = tree->cm_argv[0]; to_fslash(tpath); #ifdef MSDOS /* * Horrible hack time, if got a string with a space or a tab * in it, put quote marks around it so that nasty spawn will work */ for(xp = tree->cm_argv ; p = *xp ; xp++) if(!*p || index(p, ' ') || index(p, '\t')){ s = q = mmalloc(strlen(p) + 2 + 1); *q++ = '"'; while(*q = *p) q++, p++; *q++ = '"'; *q = 0; free(*xp); *xp = s; } #endif /* MSDOS */ if(index(tpath, '/') || *tpath == '.'){ strcpy(lpath, tpath); result = do_exec(lpath, tree); } else if(Path){ hash = b_hash(tpath); /* build hash number */ for(p = Path; *p;){ #ifdef MSDOS for(q = lpath ; *p && *p != ';' ; *q++ = *p++); #else for(q = lpath ; *p && *p != ':' ; *q++ = *p++); #endif if(*p) p++; if(q != lpath){ if(*lpath != '.' && h_look(dnumb++, hash) == 0) continue; *q++ = '/'; } for(s = tpath ; *q++ = *s++ ; ); result = do_exec(lpath, tree); if(result >= 0) break; if(errno == E2BIG) break; } } else { result = -1; errno = 0; } if(result >= 0) mustcd = TRUE; else { puterr(tree->cm_argv[0]); if(errno == E2BIG) puterr(": Argument list too long.\n"); else puterr(": Command not found.\n"); } return(result); } do_exec(path, tree) char *path; struct cmd *tree; { char *lasts; int result; char *dot; #ifdef MSDOS if((lasts = rindex(path, '/')) == NULL) lasts = path; if(index(lasts, '.') != NULL) return(try_it(path, tree)); strcat(lasts, ".exe"); result = try_it(path, tree); if(result >= 0) return(result); if(errno == E2BIG) return(-1); strcpy(dot = index(lasts, '.'), ".com"); result = try_it(path, tree); if(result >= 0 || errno != ENOENT) return(result); *dot = '\0'; #else result = try_it(path, tree); if(result >= 0 || errno != ENOEXEC) return(result); #endif if(is_shscript(path)) result = do_shscript(path, tree); return(result); } try_it(path, tree) char *path; struct cmd *tree; { errno = 0; #ifdef MSDOS to_bslash(path); return(spawnve(P_WAIT, path, tree->cm_argv, Real_Environ)); #else return(spawnve(path, tree->cm_argv, Real_Environ)); #endif } #ifndef MSDOS spawnve(path, args, env) char *path, **args, **env; { int (*sig2)(), (*sig3)(), (*sig15)(); int child, status, pid; #ifdef DEBUG write(2, "try_it:", 7); write(2, path, strlen(path)); write(2, "\n", 1); #endif sig2 = signal(SIGINT, SIG_IGN); sig3 = signal(SIGQUIT, SIG_IGN); sig15 = signal(SIGTERM, SIG_IGN); child = fork(); if(child == -1){ signal(SIGINT, sig2); signal(SIGQUIT, sig3); signal(SIGTERM, sig15); return(-1); } if(child == 0){ /* child time */ #ifdef DEBUG write(2, "in_child\n", 9); #endif signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); execve(path, args, env); exit(113); } #ifdef DEBUG write(2, "waiting\n", 8); #endif while( (pid = wait(&status)) != child && pid != -1); signal(SIGINT, sig2); signal(SIGQUIT, sig3); signal(SIGTERM, sig15); if(pid == -1) return(-1); if(status & 0xFF) return(status & 0xFF); status = (status >> 8) & 0xFF; if(status == 113) return(-1); return(status); } #endif is_shscript(path) char *path; { int fd; char c; if((fd = open(path, 0)) < 0) return(0); if(read(fd, &c, 1) != 1){ close(fd); return(0); } close(fd); return(c == '#'); } do_shscript(path, tree) char *path; struct cmd *tree; { char **xp, **oxp; int i; xp = (char **)mmalloc(sizeof(char *) * (tree->cm_argc+2)); for(i = 0, oxp = xp+1 ; i < tree->cm_argc ; i++, oxp++) *oxp = tree->cm_argv[i]; *oxp = 0; *xp = strsave(path); strcpy(path, SHELL); oxp = tree->cm_argv; /* save this argv */ tree->cm_argv = xp; i = try_it(path, tree); /* call the shell to exec it */ free(tree->cm_argv[0]); free( (char *)tree->cm_argv); tree->cm_argv = oxp; return(i); }