Пример #1
0
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);
}
Пример #2
0
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);
}
Пример #3
0
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;
}
Пример #4
0
/*
 * 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;
}
Пример #5
0
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*/    
}
Пример #6
0
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;
	}
}
Пример #7
0
/*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);
}
Пример #8
0
/*
 * 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)) {
Пример #9
0
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 */
}
Пример #10
0
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(&paraml);
	    cleanup_push(&paraml, lex_cleanup);
	    if (seterr)
		stderror(ERR_OLD);
	    alias(&paraml);
	    t = syntax(paraml.next, &paraml, 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(&paraml);
	}
    }
    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(); */
}
Пример #11
0
/*
 * 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;
}
Пример #12
0
/*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);
}
Пример #13
0
/*
 * 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;
}