/* * 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; }
/* * create a file called ~/.cshdirs which has a sequence * of pushd commands which will restore the dir stack to * its state before exit/logout. remember that the order * is reversed in the file because we are pushing. * -strike */ void recdirs(Char *fname, int def) { int fp, ftmp, oldidfds; int cdflag = 0; struct directory *dp; unsigned int num; Char *snum; struct Strbuf qname = Strbuf_INIT; if (fname == NULL && !def) return; if (fname == NULL) { if ((fname = varval(STRdirsfile)) == STRNULL) fname = Strspl(varval(STRhome), &STRtildotdirs[1]); else fname = Strsave(fname); } else fname = globone(fname, G_ERROR); cleanup_push(fname, xfree); if ((fp = xcreat(short2str(fname), 0600)) == -1) { cleanup_until(fname); return; } if ((snum = varval(STRsavedirs)) == STRNULL || snum[0] == '\0') num = (unsigned int) ~0; else num = (unsigned int) atoi(short2str(snum)); oldidfds = didfds; didfds = 0; ftmp = SHOUT; SHOUT = fp; cleanup_push(&qname, Strbuf_cleanup); dp = dcwd->di_next; do { if (dp == &dhead) continue; if (cdflag == 0) { cdflag = 1; xprintf("cd %S\n", quote_meta(&qname, dp->di_name)); } else xprintf("pushd %S\n", quote_meta(&qname, dp->di_name)); if (num-- == 0) break; } while ((dp = dp->di_next) != dcwd->di_next); xclose(fp); SHOUT = ftmp; didfds = oldidfds; cleanup_until(fname); }
/* * Form a shell temporary file (in unit 0) from the words * of the shell input up to EOF or a line the same as "term". * Unit 0 should have been closed before this call. */ void heredoc(Char *term) { eChar c; Char *Dv[2]; struct Strbuf lbuf = Strbuf_INIT, mbuf = Strbuf_INIT; Char obuf[BUFSIZE + 1]; #define OBUF_END (obuf + sizeof(obuf) / sizeof (*obuf) - 1) Char *lbp, *obp, *mbp; Char **vp; int quoted; #ifdef HAVE_MKSTEMP char *tmp = short2str(shtemp); char *dot = strrchr(tmp, '.'); if (!dot) stderror(ERR_NAME | ERR_NOMATCH); strcpy(dot, TMP_TEMPLATE); xclose(0); if (mkstemp(tmp) == -1) stderror(ERR_SYSTEM, tmp, strerror(errno)); #else /* !HAVE_MKSTEMP */ char *tmp; # ifndef WINNT_NATIVE again: # endif /* WINNT_NATIVE */ tmp = short2str(shtemp); # if O_CREAT == 0 if (xcreat(tmp, 0600) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); # endif xclose(0); if (xopen(tmp, O_RDWR|O_CREAT|O_EXCL|O_TEMPORARY|O_LARGEFILE, 0600) == -1) { int oerrno = errno; # ifndef WINNT_NATIVE if (errno == EEXIST) { if (unlink(tmp) == -1) { xfree(shtemp); mbp = randsuf(); shtemp = Strspl(STRtmpsh, mbp); xfree(mbp); } goto again; } # endif /* WINNT_NATIVE */ (void) unlink(tmp); errno = oerrno; stderror(ERR_SYSTEM, tmp, strerror(errno)); } #endif /* HAVE_MKSTEMP */ (void) unlink(tmp); /* 0 0 inode! */ Dv[0] = term; Dv[1] = NULL; gflag = 0; trim(Dv); rscan(Dv, Dtestq); quoted = gflag; obp = obuf; obuf[BUFSIZE] = 0; inheredoc = 1; cleanup_push(&inheredoc, inheredoc_cleanup); #ifdef WINNT_NATIVE __dup_stdin = 1; #endif /* WINNT_NATIVE */ cleanup_push(&lbuf, Strbuf_cleanup); cleanup_push(&mbuf, Strbuf_cleanup); for (;;) { Char **words; /* * Read up a line */ lbuf.len = 0; for (;;) { c = readc(1); /* 1 -> Want EOF returns */ if (c == CHAR_ERR || c == '\n') break; if ((c &= TRIM) != 0) Strbuf_append1(&lbuf, (Char) c); } Strbuf_terminate(&lbuf); /* Catch EOF in the middle of a line. */ if (c == CHAR_ERR && lbuf.len != 0) c = '\n'; /* * Check for EOF or compare to terminator -- before expansion */ if (c == CHAR_ERR || eq(lbuf.s, term)) break; /* * If term was quoted or -n just pass it on */ if (quoted || noexec) { Strbuf_append1(&lbuf, '\n'); Strbuf_terminate(&lbuf); for (lbp = lbuf.s; (c = *lbp++) != 0;) { *obp++ = (Char) c; if (obp == OBUF_END) { tmp = short2str(obuf); (void) xwrite(0, tmp, strlen (tmp)); obp = obuf; } } continue; } /* * Term wasn't quoted so variable and then command expand the input * line */ Dcp = lbuf.s; Dvp = Dv + 1; mbuf.len = 0; for (;;) { c = DgetC(DODOL); if (c == DEOF) break; if ((c &= TRIM) == 0) continue; /* \ quotes \ $ ` here */ if (c == '\\') { c = DgetC(0); if (!any("$\\`", c)) unDgetC(c | QUOTE), c = '\\'; else c |= QUOTE; } Strbuf_append1(&mbuf, (Char) c); } Strbuf_terminate(&mbuf); /* * If any ` in line do command substitution */ mbp = mbuf.s; if (Strchr(mbp, '`') != NULL) { /* * 1 arg to dobackp causes substitution to be literal. Words are * broken only at newlines so that all blanks and tabs are * preserved. Blank lines (null words) are not discarded. */ words = dobackp(mbp, 1); } else /* Setup trivial vector similar to return of dobackp */ Dv[0] = mbp, Dv[1] = NULL, words = Dv; /* * Resurrect the words from the command substitution each separated by * a newline. Note that the last newline of a command substitution * will have been discarded, but we put a newline after the last word * because this represents the newline after the last input line! */ for (vp= words; *vp; vp++) { for (mbp = *vp; *mbp; mbp++) { *obp++ = *mbp & TRIM; if (obp == OBUF_END) { tmp = short2str(obuf); (void) xwrite(0, tmp, strlen (tmp)); obp = obuf; } } *obp++ = '\n'; if (obp == OBUF_END) { tmp = short2str(obuf); (void) xwrite(0, tmp, strlen (tmp)); obp = obuf; } } if (words != Dv) blkfree(words); } *obp = 0; tmp = short2str(obuf); (void) xwrite(0, tmp, strlen (tmp)); (void) lseek(0, (off_t) 0, L_SET); cleanup_until(&inheredoc); }
/*ARGSUSED*/ long xrename(int n, char *p1, char *p2) { register OFD *fd2; OFD *f1,*fd; FCB *f; DND *dn1,*dn2; const char *s1,*s2; char buf[11]; int hnew,att; long rc, h1; if (!ixsfirst(p2,0,(DTAINFO *)0L)) return(EACCDN); if ((long)(dn1 = findit(p1,&s1,0)) < 0) /* M01.01.1212.01 */ return( (long)dn1 ); if (!dn1) /* M01.01.1214.01 */ return( EPTHNF ); if ((long)(dn2 = findit(p2,&s2,0)) < 0) /* M01.01.1212.01 */ return( (long)dn2 ); if (!dn2) /* M01.01.1214.01 */ return( EPTHNF ); if (contains_illegal_characters(s2)) return( EACCDN ) ; if ((h1 = xopen(p1, 2)) < 0L) return (h1); f1 = getofd ((int)h1); fd = f1->o_dirfil; buf[0] = 0xe5; ixlseek(fd,f1->o_dirbyt); if (dn1 != dn2) { /* get old attribute */ f = (FCB *) ixread(fd,32L,NULLPTR); att = f->f_attrib; /* erase (0xe5) old file */ ixlseek(fd,f1->o_dirbyt); ixwrite(fd,1L,buf); /* copy time/date/clust, etc. */ ixlseek(fd,f1->o_dirbyt + 22); ixread(fd,10L,buf); hnew = xcreat(p2,att); fd2 = getofd(hnew); ixlseek(fd2->o_dirfil,fd2->o_dirbyt + 22); ixwrite(fd2->o_dirfil,10L,buf); fd2->o_flag &= ~O_DIRTY; xclose(hnew); ixclose(fd2->o_dirfil,CL_DIR); } else { builds(s2,buf); ixwrite(fd,11L,buf); } if ((rc = xclose((int)h1)) < 0L) return(rc); return(ixclose(fd,CL_DIR)); }