void mypipe(int *pv) { if (pipe(pv) < 0) goto oops; pv[0] = dmove(pv[0], -1); pv[1] = dmove(pv[1], -1); if (pv[0] >= 0 && pv[1] >= 0) return; oops: stderror(ERR_PIPE); }
void mypipe(int *pv) { if (pipe(pv) < 0) goto oops; (void)close_on_exec(pv[0] = dmove(pv[0], -1), 1); (void)close_on_exec(pv[1] = dmove(pv[1], -1), 1); if (pv[0] >= 0 && pv[1] >= 0) return; if (pv[0] >= 0) xclose(pv[0]); if (pv[1] >= 0) xclose(pv[1]); oops: stderror(ERR_PIPE); }
char move(int x, int y, char player) { char vsplayer = (player == 'W') ? 'B' : 'W'; board[x][y] = player; if (board[x-1][y-1]==vsplayer) dmove(x-1, y-1, player, 1); if (board[x-1][y]==vsplayer) dmove(x-1, y, player, 2); if (board[x-1][y+1]==vsplayer) dmove(x-1, y+1, player, 3); if (board[x][y-1]==vsplayer) dmove(x, y-1, player, 4); if (board[x][y+1]==vsplayer) dmove(x, y+1, player, 5); if (board[x+1][y-1]==vsplayer) dmove(x+1, y-1, player, 6); if (board[x+1][y]==vsplayer) dmove(x+1, y, player, 7); if (board[x+1][y+1]==vsplayer) dmove(x+1, y+1, player, 8); return vsplayer; }
/* * Source to a file putting the file descriptor in a safe place (> 2). */ static int srcfile(const char *f, int onlyown, int flag) { int unit; if ((unit = open(f, O_RDONLY)) == -1) return 0; unit = dmove(unit, -1); (void) ioctl(unit, FIOCLEX, NULL); srcunit(unit, onlyown, flag); return 1; }
void donefds(void) { xclose(0); xclose(1); xclose(2); didfds = 0; #ifdef NISPLUS { int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); (void)dcopy(fd, 1); (void)dcopy(fd, 2); (void)dmove(fd, 0); } #endif /*NISPLUS*/ }
void dmove(int x, int y, char player, int direction) { // printf("dmove!\n"); char vsplayer = (player == 'W') ? 'B' : 'W'; int x1, y1; x1 = x; y1 = y; switch (direction){ case 1: x1--; y1--; break; case 2: x1--; break; case 3: x1--; y1++; break; case 4: y1--; break; case 5: y1++; break; case 6: x1++; y1--; break; case 7: x1++; break; case 8: x1++; y1++; break; } if ((x1>0)&&(y1>0)&&(x1<9)&&(y1<9)){ if (board[x1][y1] == vsplayer) dmove(x1, y1, player, direction); if (board[x1][y1] == player) board[x][y] = player; } }
/*ARGSUSED*/ void execash(Char **t, struct command *kp) { jmp_buf osetexit; sig_t osigint, osigquit, osigterm; int my_reenter, odidfds, oOLDSTD, oSHERR, oSHIN, oSHOUT; int saveDIAG, saveIN, saveOUT, saveSTD; if (chkstop == 0 && setintr) panystop(0); /* * Hmm, we don't really want to do that now because we might * fail, but what is the choice */ rechist(); osigint = signal(SIGINT, parintr); osigquit = signal(SIGQUIT, parintr); osigterm = signal(SIGTERM, parterm); odidfds = didfds; oSHIN = SHIN; oSHOUT = SHOUT; oSHERR = SHERR; oOLDSTD = OLDSTD; saveIN = dcopy(SHIN, -1); saveOUT = dcopy(SHOUT, -1); saveDIAG = dcopy(SHERR, -1); saveSTD = dcopy(OLDSTD, -1); lshift(kp->t_dcom, 1); getexit(osetexit); if ((my_reenter = setexit()) == 0) { SHIN = dcopy(0, -1); SHOUT = dcopy(1, -1); SHERR = dcopy(2, -1); didfds = 0; doexec(t, kp); } (void)signal(SIGINT, osigint); (void)signal(SIGQUIT, osigquit); (void)signal(SIGTERM, osigterm); doneinp = 0; didfds = odidfds; (void)close(SHIN); (void)close(SHOUT); (void)close(SHERR); (void)close(OLDSTD); SHIN = dmove(saveIN, oSHIN); SHOUT = dmove(saveOUT, oSHOUT); SHERR = dmove(saveDIAG, oSHERR); OLDSTD = dmove(saveSTD, oOLDSTD); resexit(osetexit); if (my_reenter) stderror(ERR_SILENT); }
/* * Perform io redirection. * We may or maynot be forked here. */ static void doio(struct command *t, int *pipein, int *pipeout) { Char *cp; int fd, flags; flags = t->t_dflg; if (didfds || (flags & F_REPEAT)) return; if ((flags & F_READ) == 0) {/* F_READ already done */ if (t->t_dlef) { char tmp[MAXPATHLEN+1]; /* * so < /dev/std{in,out,err} work */ (void)dcopy(SHIN, 0); (void)dcopy(SHOUT, 1); (void)dcopy(SHERR, 2); cp = splicepipe(t, t->t_dlef); (void)strlcpy(tmp, short2str(cp), sizeof(tmp)); xfree((ptr_t) cp); if ((fd = open(tmp, O_RDONLY)) < 0) { stderror(ERR_SYSTEM, tmp, strerror(errno)); /* NOTREACHED */ } (void)dmove(fd, 0); } else if (flags & F_PIPEIN) { (void)close(0); (void)dup(pipein[0]); (void)close(pipein[0]); (void)close(pipein[1]); } else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { (void)close(0); (void)open(_PATH_DEVNULL, O_RDONLY); } else { (void)close(0); (void)dup(OLDSTD); (void)ioctl(0, FIONCLEX, NULL); } } if (t->t_drit) { char tmp[MAXPATHLEN+1]; cp = splicepipe(t, t->t_drit); (void)strlcpy(tmp, short2str(cp), sizeof(tmp)); xfree((ptr_t) cp); /* * so > /dev/std{out,err} work */ (void)dcopy(SHOUT, 1); (void)dcopy(SHERR, 2); if ((flags & F_APPEND) && #ifdef O_APPEND (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0); #else (fd = open(tmp, O_WRONLY)) >= 0) (void)lseek(1, (off_t) 0, SEEK_END); #endif else { if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) {
int main(int argc, char *argv[]) { struct sigaction oact; Char *cp; char *tcp, **tempv; const char *ecp; sigset_t nsigset; int f; cshin = stdin; cshout = stdout; csherr = stderr; setprogname(argv[0]); settimes(); /* Immed. estab. timing base */ /* * Initialize non constant strings */ #ifdef _PATH_BSHELL STR_BSHELL = SAVE(_PATH_BSHELL); #endif #ifdef _PATH_CSHELL STR_SHELLPATH = SAVE(_PATH_CSHELL); #endif STR_environ = blk2short(environ); environ = short2blk(STR_environ); /* So that we can free it */ STR_WORD_CHARS = SAVE(WORD_CHARS); HIST = '!'; HISTSUB = '^'; word_chars = STR_WORD_CHARS; tempv = argv; if (eq(str2short(tempv[0]), STRaout)) /* A.out's are quittable */ quitit = 1; uid = getuid(); gid = getgid(); euid = geteuid(); egid = getegid(); /* * We are a login shell if: 1. we were invoked as -<something> and we had * no arguments 2. or we were invoked only with the -l flag */ loginsh = (**tempv == '-' && argc == 1) || (argc == 2 && tempv[1][0] == '-' && tempv[1][1] == 'l' && tempv[1][2] == '\0'); if (loginsh && **tempv != '-') { /* * Mangle the argv space */ tempv[1][0] = '\0'; tempv[1][1] = '\0'; tempv[1] = NULL; for (tcp = *tempv; *tcp++;) continue; for (tcp--; tcp >= *tempv; tcp--) tcp[1] = tcp[0]; *++tcp = '-'; argc--; } if (loginsh) (void)time(&chktim); AsciiOnly = 1; #ifdef NLS (void)setlocale(LC_ALL, ""); { int k; for (k = 0200; k <= 0377 && !Isprint(k); k++) continue; AsciiOnly = k > 0377; } #else AsciiOnly = getenv("LANG") == NULL && getenv("LC_CTYPE") == NULL; #endif /* NLS */ /* * Move the descriptors to safe places. The variable didfds is 0 while we * have only FSH* to work with. When didfds is true, we have 0,1,2 and * prefer to use these. */ initdesc(); /* * XXX: This is to keep programs that use stdio happy. * what we really want is freunopen() .... * Closing cshin cshout and csherr (which are really stdin stdout * and stderr at this point and then reopening them in the same order * gives us again stdin == cshin stdout == cshout and stderr == csherr. * If that was not the case builtins like printf that use stdio * would break. But in any case we could fix that with memcpy and * a bit of pointer manipulation... * Fortunately this is not needed under the current implementation * of stdio. */ (void)fclose(cshin); (void)fclose(cshout); (void)fclose(csherr); if (!(cshin = funopen2((void *) &SHIN, readf, writef, seekf, NULL, closef))) exit(1); if (!(cshout = funopen2((void *) &SHOUT, readf, writef, seekf, NULL, closef))) exit(1); if (!(csherr = funopen2((void *) &SHERR, readf, writef, seekf, NULL, closef))) exit(1); (void)setvbuf(cshin, NULL, _IOLBF, 0); (void)setvbuf(cshout, NULL, _IOLBF, 0); (void)setvbuf(csherr, NULL, _IOLBF, 0); /* * Initialize the shell variables. ARGV and PROMPT are initialized later. * STATUS is also munged in several places. CHILD is munged when * forking/waiting */ set(STRstatus, Strsave(STR0)); if ((ecp = getenv("HOME")) != NULL) cp = quote(SAVE(ecp)); else cp = NULL; if (cp == NULL) fast = 1; /* No home -> can't read scripts */ else set(STRhome, cp); dinit(cp); /* dinit thinks that HOME == cwd in a login * shell */ /* * Grab other useful things from the environment. Should we grab * everything?? */ if ((ecp = getenv("LOGNAME")) != NULL || (ecp = getenv("USER")) != NULL) set(STRuser, quote(SAVE(ecp))); if ((ecp = getenv("TERM")) != NULL) set(STRterm, quote(SAVE(ecp))); /* * Re-initialize path if set in environment */ if ((ecp = getenv("PATH")) == NULL) { #ifdef _PATH_DEFPATH importpath(str2short(_PATH_DEFPATH)); #else setq(STRpath, defaultpath(), &shvhed); #endif } else { importpath(str2short(ecp)); } set(STRshell, Strsave(STR_SHELLPATH)); doldol = putn((int) getpid()); /* For $$ */ shtemp = Strspl(STRtmpsh, doldol); /* For << */ /* * Record the interrupt states from the parent process. If the parent is * non-interruptible our hand must be forced or we (and our children) won't * be either. Our children inherit termination from our parent. We catch it * only if we are the login shell. */ /* parents interruptibility */ (void)sigaction(SIGINT, NULL, &oact); parintr = oact.sa_handler; (void)sigaction(SIGTERM, NULL, &oact); parterm = oact.sa_handler; /* catch these all, login shell or not */ (void)signal(SIGHUP, phup); /* exit processing on HUP */ (void)signal(SIGXCPU, phup); /* ...and on XCPU */ (void)signal(SIGXFSZ, phup); /* ...and on XFSZ */ /* * Process the arguments. * * Note that processing of -v/-x is actually delayed till after script * processing. * * We set the first character of our name to be '-' if we are a shell * running interruptible commands. Many programs which examine ps'es * use this to filter such shells out. */ argc--, tempv++; while (argc > 0 && (tcp = tempv[0])[0] == '-' && *++tcp != '\0' && !batch) { do switch (*tcp++) { case 0: /* - Interruptible, no prompt */ prompt = 0; setintr = 1; nofile = 1; break; case 'b': /* -b Next arg is input file */ batch = 1; break; case 'c': /* -c Command input from arg */ if (argc == 1) xexit(0); argc--, tempv++; arginp = SAVE(tempv[0]); prompt = 0; nofile = 1; break; case 'e': /* -e Exit on any error */ exiterr = 1; break; case 'f': /* -f Fast start */ fast = 1; break; case 'i': /* -i Interactive, even if !intty */ intact = 1; nofile = 1; break; case 'm': /* -m read .cshrc (from su) */ mflag = 1; break; case 'n': /* -n Don't execute */ noexec = 1; break; case 'q': /* -q (Undoc'd) ... die on quit */ quitit = 1; break; case 's': /* -s Read from std input */ nofile = 1; break; case 't': /* -t Read one line from input */ onelflg = 2; prompt = 0; nofile = 1; break; case 'v': /* -v Echo hist expanded input */ nverbose = 1; /* ... later */ break; case 'x': /* -x Echo just before execution */ nexececho = 1; /* ... later */ break; case 'V': /* -V Echo hist expanded input */ setNS(STRverbose); /* NOW! */ break; case 'X': /* -X Echo just before execution */ setNS(STRecho); /* NOW! */ break; } while (*tcp); tempv++, argc--; } if (quitit) /* With all due haste, for debugging */ (void)signal(SIGQUIT, SIG_DFL); /* * Unless prevented by -, -c, -i, -s, or -t, if there are remaining * arguments the first of them is the name of a shell file from which to * read commands. */ if (nofile == 0 && argc > 0) { nofile = open(tempv[0], O_RDONLY); if (nofile < 0) { child = 1; /* So this doesn't return */ stderror(ERR_SYSTEM, tempv[0], strerror(errno)); } ffile = SAVE(tempv[0]); /* * Replace FSHIN. Handle /dev/std{in,out,err} specially * since once they are closed we cannot open them again. * In that case we use our own saved descriptors */ if ((SHIN = dmove(nofile, FSHIN)) < 0) switch(nofile) { case 0: SHIN = FSHIN; break; case 1: SHIN = FSHOUT; break; case 2: SHIN = FSHERR; break; default: stderror(ERR_SYSTEM, tempv[0], strerror(errno)); /* NOTREACHED */ } (void)ioctl(SHIN, FIOCLEX, NULL); prompt = 0; /* argc not used any more */ tempv++; } intty = isatty(SHIN); intty |= intact; if (intty || (intact && isatty(SHOUT))) { if (!batch && (uid != euid || gid != egid)) { errno = EACCES; child = 1; /* So this doesn't return */ stderror(ERR_SYSTEM, "csh", strerror(errno)); } } /* * Decide whether we should play with signals or not. If we are explicitly * told (via -i, or -) or we are a login shell (arg0 starts with -) or the * input and output are both the ttys("csh", or "csh</dev/ttyx>/dev/ttyx") * Note that in only the login shell is it likely that parent may have set * signals to be ignored */ if (loginsh || intact || (intty && isatty(SHOUT))) setintr = 1; settell(); /* * Save the remaining arguments in argv. */ setq(STRargv, blk2short(tempv), &shvhed); /* * Set up the prompt. */ if (prompt) { set(STRprompt, Strsave(uid == 0 ? STRsymhash : STRsymcent)); /* that's a meta-questionmark */ set(STRprompt2, Strsave(STRmquestion)); } /* * If we are an interactive shell, then start fiddling with the signals; * this is a tricky game. */ shpgrp = getpgrp(); opgrp = tpgrp = -1; if (setintr) { **argv = '-'; if (!quitit) /* Wary! */ (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGINT, pintr); sigemptyset(&nsigset); (void)sigaddset(&nsigset, SIGINT); (void)sigprocmask(SIG_BLOCK, &nsigset, NULL); (void)signal(SIGTERM, SIG_IGN); if (quitit == 0 && arginp == 0) { (void)signal(SIGTSTP, SIG_IGN); (void)signal(SIGTTIN, SIG_IGN); (void)signal(SIGTTOU, SIG_IGN); /* * Wait till in foreground, in case someone stupidly runs csh & * dont want to try to grab away the tty. */ if (isatty(FSHERR)) f = FSHERR; else if (isatty(FSHOUT)) f = FSHOUT; else if (isatty(OLDSTD)) f = OLDSTD; else f = -1; retry: if ((tpgrp = tcgetpgrp(f)) != -1) { if (tpgrp != shpgrp) { sig_t old = signal(SIGTTIN, SIG_DFL); (void)kill(0, SIGTTIN); (void)signal(SIGTTIN, old); goto retry; } opgrp = shpgrp; shpgrp = getpid(); tpgrp = shpgrp; /* * Setpgid will fail if we are a session leader and * mypid == mypgrp (POSIX 4.3.3) */ if (opgrp != shpgrp) if (setpgid(0, shpgrp) == -1) goto notty; /* * We do that after we set our process group, to make sure * that the process group belongs to a process in the same * session as the tty (our process and our group) (POSIX 7.2.4) */ if (tcsetpgrp(f, shpgrp) == -1) goto notty; (void)ioctl(dcopy(f, FSHTTY), FIOCLEX, NULL); } if (tpgrp == -1) { notty: (void)fprintf(csherr, "Warning: no access to tty (%s).\n", strerror(errno)); (void)fprintf(csherr, "Thus no job control in this shell.\n"); } } } if ((setintr == 0) && (parintr == SIG_DFL)) setintr = 1; (void)signal(SIGCHLD, pchild); /* while signals not ready */ /* * Set an exit here in case of an interrupt or error reading the shell * start-up scripts. */ reenter = setexit(); /* PWP */ haderr = 0; /* In case second time through */ if (!fast && reenter == 0) { /* Will have value(STRhome) here because set fast if don't */ { sig_t oparintr; sigset_t osigset; int osetintr; oparintr = parintr; osetintr = setintr; sigemptyset(&nsigset); (void)sigaddset(&nsigset, SIGINT); (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); setintr = 0; parintr = SIG_IGN; /* Disable onintr */ #ifdef _PATH_DOTCSHRC (void)srcfile(_PATH_DOTCSHRC, 0, 0); #endif if (!fast && !arginp && !onelflg) dohash(NULL, NULL); #ifdef _PATH_DOTLOGIN if (loginsh) (void)srcfile(_PATH_DOTLOGIN, 0, 0); #endif (void)sigprocmask(SIG_SETMASK, &osigset, NULL); setintr = osetintr; parintr = oparintr; } (void)srccat(value(STRhome), STRsldotcshrc); if (!fast && !arginp && !onelflg && !havhash) dohash(NULL, NULL); /* * Source history before .login so that it is available in .login */ if ((cp = value(STRhistfile)) != STRNULL) tildehist[2] = cp; dosource(tildehist, NULL); if (loginsh) (void)srccat(value(STRhome), STRsldotlogin); } /* * Now are ready for the -v and -x flags */ if (nverbose) setNS(STRverbose); if (nexececho) setNS(STRecho); /* * All the rest of the world is inside this call. The argument to process * indicates whether it should catch "error unwinds". Thus if we are a * interactive shell our call here will never return by being blown past on * an error. */ process(setintr); /* * Mop-up. */ if (intty) { if (loginsh) { (void)fprintf(cshout, "logout\n"); (void)close(SHIN); child = 1; goodbye(); } else { (void)fprintf(cshout, "exit\n"); } } rechist(); exitstat(); /* NOTREACHED */ }
static void backeval(struct blk_buf *bb, struct Strbuf *word, Char *cp, int literal) { ssize_t icnt; Char c, *ip; struct command faket; int hadnl; int pvec[2], quoted; Char *fakecom[2], ibuf[BUFSIZE]; char tibuf[BUFSIZE]; hadnl = 0; icnt = 0; quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; faket.t_dtyp = NODE_COMMAND; faket.t_dflg = F_BACKQ; faket.t_dlef = 0; faket.t_drit = 0; faket.t_dspr = 0; faket.t_dcom = fakecom; fakecom[0] = STRfakecom1; fakecom[1] = 0; /* * We do the psave job to temporarily change the current job so that the * following fork is considered a separate job. This is so that when * backquotes are used in a builtin function that calls glob the "current * job" is not corrupted. We only need one level of pushed jobs as long as * we are sure to fork here. */ psavejob(); cleanup_push(&faket, psavejob_cleanup); /* faket is only a marker */ /* * It would be nicer if we could integrate this redirection more with the * routines in sh.sem.c by doing a fake execute on a builtin function that * was piped out. */ mypipe(pvec); cleanup_push(&pvec[0], open_cleanup); cleanup_push(&pvec[1], open_cleanup); if (pfork(&faket, -1) == 0) { jmp_buf_t osetexit; struct command *t; size_t omark; xclose(pvec[0]); (void) dmove(pvec[1], 1); (void) dmove(SHDIAG, 2); initdesc(); closem(); arginp = cp; for (arginp = cp; *cp; cp++) { *cp &= TRIM; if (is_set(STRcsubstnonl) && (*cp == '\n' || *cp == '\r')) *cp = ' '; } /* * In the child ``forget'' everything about current aliases or * eval vectors. */ alvec = NULL; evalvec = NULL; alvecp = NULL; evalp = NULL; omark = cleanup_push_mark(); getexit(osetexit); for (;;) { (void) setexit(); justpr = 0; if (haderr) { /* unwind */ doneinp = 0; cleanup_pop_mark(omark); resexit(osetexit); reset(); } if (seterr) { xfree(seterr); seterr = NULL; } (void) lex(¶ml); cleanup_push(¶ml, lex_cleanup); if (seterr) stderror(ERR_OLD); alias(¶ml); t = syntax(paraml.next, ¶ml, 0); if (t == NULL) return; cleanup_push(t, syntax_cleanup); /* The F_BACKQ flag must set so the job output is correct if * printexitvalue is set. If it's not set, the job output * will have "Exit N" appended where N is the exit status. */ t->t_dflg = F_BACKQ|F_NOFORK; if (seterr) stderror(ERR_OLD); #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif execute(t, -1, NULL, NULL, TRUE); cleanup_until(¶ml); } } cleanup_until(&pvec[1]); c = 0; ip = NULL; do { ssize_t cnt = 0; char *tmp; tmp = tibuf; for (;;) { while (icnt == 0) { int i, eof; ip = ibuf; icnt = xread(pvec[0], tmp, tibuf + BUFSIZE - tmp); eof = 0; if (icnt <= 0) { if (tmp == tibuf) goto eof; icnt = 0; eof = 1; } icnt += tmp - tibuf; i = 0; tmp = tibuf; while (tmp < tibuf + icnt) { int len; len = normal_mbtowc(&ip[i], tmp, tibuf + icnt - tmp); if (len == -1) { reset_mbtowc(); if (!eof && (size_t)(tibuf + icnt - tmp) < MB_CUR_MAX) { break; /* Maybe a partial character */ } ip[i] = (unsigned char) *tmp | INVALID_BYTE; /* Error */ } if (len <= 0) len = 1; i++; tmp += len; } if (tmp != tibuf) memmove (tibuf, tmp, tibuf + icnt - tmp); tmp = tibuf + (tibuf + icnt - tmp); icnt = i; } if (hadnl) break; --icnt; c = (*ip++ & TRIM); if (c == 0) break; #if defined(WINNT_NATIVE) || defined(__CYGWIN__) if (c == '\r') c = ' '; #endif /* WINNT_NATIVE || __CYGWIN__ */ if (c == '\n') { /* * Continue around the loop one more time, so that we can eat * the last newline without terminating this word. */ hadnl = 1; continue; } if (!quoted && (c == ' ' || c == '\t')) break; cnt++; Strbuf_append1(word, c | quoted); } /* * Unless at end-of-file, we will form a new word here if there were * characters in the word, or in any case when we take text literally. * If we didn't make empty words here when literal was set then we * would lose blank lines. */ if (c != 0 && (cnt || literal)) pword(bb, word); hadnl = 0; } while (c > 0); eof: cleanup_until(&pvec[0]); pwait(); cleanup_until(&faket); /* psavejob_cleanup(); */ }
/* * Perform io redirection. * We may or maynot be forked here. */ static void doio(struct command *t, int *pipein, int *pipeout) { int fd; Char *cp; unsigned long flags = t->t_dflg; if (didfds || (flags & F_REPEAT)) return; if ((flags & F_READ) == 0) {/* F_READ already done */ if (t->t_dlef) { char *tmp; /* * so < /dev/std{in,out,err} work */ (void) dcopy(SHIN, 0); (void) dcopy(SHOUT, 1); (void) dcopy(SHDIAG, 2); cp = splicepipe(t, t->t_dlef); tmp = strsave(short2str(cp)); xfree(cp); cleanup_push(tmp, xfree); if ((fd = xopen(tmp, O_RDONLY|O_LARGEFILE)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); cleanup_until(tmp); /* allow input files larger than 2Gb */ #ifndef WINNT_NATIVE (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_LARGEFILE); #endif /*!WINNT_NATIVE*/ (void) dmove(fd, 0); } else if (flags & F_PIPEIN) { xclose(0); TCSH_IGNORE(dup(pipein[0])); xclose(pipein[0]); xclose(pipein[1]); } else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { xclose(0); (void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); } else { xclose(0); TCSH_IGNORE(dup(OLDSTD)); #if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) /* * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved * across dup()s, so we have to UNSET it here or else we get a * command with NO stdin, stdout, or stderr at all (a bad thing * indeed) */ (void) close_on_exec(0, 0); #endif /* CLOSE_ON_EXEC && CLEX_DUPS */ } } if (t->t_drit) { char *tmp; cp = splicepipe(t, t->t_drit); tmp = strsave(short2str(cp)); xfree(cp); cleanup_push(tmp, xfree); /* * so > /dev/std{out,err} work */ (void) dcopy(SHOUT, 1); (void) dcopy(SHDIAG, 2); if ((flags & F_APPEND) != 0) { #ifdef O_APPEND fd = xopen(tmp, O_WRONLY|O_APPEND|O_LARGEFILE); #else /* !O_APPEND */ fd = xopen(tmp, O_WRONLY|O_LARGEFILE); (void) lseek(fd, (off_t) 0, L_XTND); #endif /* O_APPEND */ } else fd = 0; if ((flags & F_APPEND) == 0 || fd == -1) { if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { if (flags & F_APPEND) stderror(ERR_SYSTEM, tmp, strerror(errno)); chkclob(tmp); } if ((fd = xcreat(tmp, 0666)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); /* allow input files larger than 2Gb */ #ifndef WINNT_NATIVE (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_LARGEFILE); #endif /*!WINNT_NATIVE*/ } cleanup_until(tmp); (void) dmove(fd, 1); is1atty = isatty(1); } else if (flags & F_PIPEOUT) { xclose(1); TCSH_IGNORE(dup(pipeout[1])); is1atty = 0; } else { xclose(1); TCSH_IGNORE(dup(SHOUT)); is1atty = isoutatty; # if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) (void) close_on_exec(1, 0); # endif /* CLOSE_ON_EXEC && CLEX_DUPS */ } xclose(2); if (flags & F_STDERR) { TCSH_IGNORE(dup(1)); is2atty = is1atty; } else { TCSH_IGNORE(dup(SHDIAG)); is2atty = isdiagatty; # if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) (void) close_on_exec(2, 0); # endif /* CLOSE_ON_EXEC && CLEX_DUPS */ } didfds = 1; }
/*ARGSUSED*/ void dobs2cmd(Char **v, struct command *c) { Char *cp, **globbed; int i = 0, len = 0; char *cmd = NULL; int pvec[2]; struct command faket; Char *fakecom[2]; char tibuf[BUFSIZE]; int icnt, old_pintr_disabled; static const Char STRbs2cmd[] = { 'b','s','2','c','m','d','\0' }; v++; if (setintr) pintr_push_enable(&old_pintr_disabled); v = glob_all_or_error(v); if (setintr) cleanup_until(&old_pintr_disabled); globbed = v; cleanup_push(globbed, blk_cleanup); /* First round: count the string lengths */ for (i=0; v[i]; ++i) { len += Strlen(v[i]) + (v[i+1] != NULL); } cmd = xmalloc(len+1); /* 1 for the final '\0' *//* FIXME: memory leak? */ /* 2nd round: fill cmd buffer */ i = 0; while ((cp = *v++) != 0) { int c; while (c = *cp++) cmd[i++] = (char)c; if (*v) cmd[i++] = ' '; } cmd[i] = '\0'; /* Make upper case */ bs2upcase(cmd); faket.t_dtyp = NODE_COMMAND; faket.t_dflg = F_BACKQ|F_STDERR; faket.t_dlef = 0; faket.t_drit = 0; faket.t_dspr = 0; faket.t_dcom = fakecom; fakecom[0] = (Char *)STRbs2cmd; fakecom[1] = 0; mypipe(pvec); cleanup_push(&pvec[0], open_cleanup); cleanup_push(&pvec[1], open_cleanup); if (pfork(&faket, -1) == 0) { sigset_t set; /* child */ xclose(pvec[0]); (void) dmove(pvec[1], 1); (void) dmove(SHDIAG, 2); initdesc(); sigemptyset(&set); sigaddset(&set, SIGINT); (void)sigprocmask(SIG_UNBLOCK, &set, NULL); #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif xexit(bs2cmdlist(cmd)); } cleanup_until(&pvec[1]); for(;;) { int old_pintr_disabled; if (setintr) pintr_push_enable(&old_pintr_disabled); icnt = xread(pvec[0], tibuf, sizeof(tibuf)); if (setintr) cleanup_until(&old_pintr_disabled); if (icnt <= 0) break; for (i = 0; i < icnt; i++) xputchar((unsigned char) tibuf[i]); } cleanup_until(&pvec[0]); pwait(); flush(); cleanup_until(globbed); }
/* * Perform io redirection. * We may or maynot be forked here. */ static void doio(struct command *t, int *pipein, int *pipeout) { int fd; Char *cp; int flags = t->t_dflg; if (didfds || (flags & F_REPEAT)) return; if ((flags & F_READ) == 0) {/* F_READ already done */ if (t->t_dlef) { char tmp[PATH_MAX]; /* * so < /dev/std{in,out,err} work */ (void) dcopy(SHIN, 0); (void) dcopy(SHOUT, 1); (void) dcopy(SHERR, 2); cp = splicepipe(t, t->t_dlef); strlcpy(tmp, short2str(cp), sizeof tmp); xfree(cp); if ((fd = open(tmp, O_RDONLY)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); (void) dmove(fd, 0); } else if (flags & F_PIPEIN) { (void) close(0); (void) dup(pipein[0]); (void) close(pipein[0]); (void) close(pipein[1]); } else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { (void) close(0); (void) open(_PATH_DEVNULL, O_RDONLY); } else { (void) close(0); (void) dup(OLDSTD); (void) ioctl(STDIN_FILENO, FIONCLEX, NULL); } } if (t->t_drit) { char tmp[PATH_MAX]; cp = splicepipe(t, t->t_drit); strlcpy(tmp, short2str(cp), sizeof tmp); xfree(cp); /* * so > /dev/std{out,err} work */ (void) dcopy(SHOUT, 1); (void) dcopy(SHERR, 2); if ((flags & F_APPEND) && (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0); else { if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { if (flags & F_APPEND) stderror(ERR_SYSTEM, tmp, strerror(errno)); chkclob(tmp); } if ((fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); } (void) dmove(fd, 1); } else if (flags & F_PIPEOUT) { (void) close(1); (void) dup(pipeout[1]); } else { (void) close(1); (void) dup(SHOUT); (void) ioctl(STDOUT_FILENO, FIONCLEX, NULL); } (void) close(2); if (flags & F_STDERR) { (void) dup(1); } else { (void) dup(SHERR); (void) ioctl(STDERR_FILENO, FIONCLEX, NULL); } didfds = 1; }