diff --git a/bin/sh/eval.c b/bin/sh/eval.c index dabc7e63dec9..8bf2d84522d6 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -442,6 +442,7 @@ expredir(n) switch (redir->type) { case NFROM: case NTO: + case NFROMTO: case NAPPEND: expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); redir->nfile.expfname = fn.list->text; diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index 5e6b3e7e7f0f..e4374412b170 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -1085,6 +1085,8 @@ cmdtxt(n) p = ">&"; i = 1; goto redir; case NFROM: p = "<"; i = 0; goto redir; + case NFROMTO: + p = "<>"; i = 0; goto redir; case NFROMFD: p = "<&"; i = 0; goto redir; redir: diff --git a/bin/sh/nodetypes b/bin/sh/nodetypes index ce82a35d266f..53dd18f40845 100644 --- a/bin/sh/nodetypes +++ b/bin/sh/nodetypes @@ -118,6 +118,7 @@ NARG narg # represents a word NTO nfile # fd> fname NFROM nfile # fd< fname +NFROMTO nfile # fd<> fname NAPPEND nfile # fd>> fname type int next nodeptr # next redirection in list diff --git a/bin/sh/parser.c b/bin/sh/parser.c index a65dfb3b4253..08d25696ffc2 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -1138,6 +1138,8 @@ parseredir: { } } else if (c == '&') np->type = NFROMFD; + else if (c == '>') + np->type = NFROMTO; else { np->type = NFROM; pungetc(); diff --git a/bin/sh/redir.c b/bin/sh/redir.c index 3ef30d0e0151..ee893f40bef2 100644 --- a/bin/sh/redir.c +++ b/bin/sh/redir.c @@ -190,6 +190,27 @@ openredirect(redir, memory) close(f); } break; + case NFROMTO: + fname = redir->nfile.expfname; +#ifdef O_CREAT + if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0) + error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); +#else + if ((f = open(fname, O_RDWR, 0666)) < 0) { + if (errno != ENOENT) + error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); + else if ((f = creat(fname, 0666)) < 0) + error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); + else { + close(f); + if ((f = open(fname, O_RDWR)) < 0) { + error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); + remove(fname); + } + } + } +#endif + goto movefd; case NTO: fname = redir->nfile.expfname; #ifdef O_CREAT diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 6e1bf1fcf479..8277ddb5da24 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -331,13 +331,14 @@ The following is a list of valid operators: .Xc Xc Xc Xc .El .It Redirection operators: -.Bl -column "XXX" "XXX" "XXX" "XXX" -offset center -compact +.Bl -column "XXX" "XXX" "XXX" "XXX" "XXX" -offset center -compact .It Xo .Li < Ta Xo .Li > Ta Xo .Li << Ta Xo -.Li >> -.Xc Xc Xc Xc +.Li >> Ta Xo +.Li <> +.Xc Xc Xc Xc Xc .It Xo .Li <& Ta Xo .Li >& Ta Xo @@ -497,6 +498,8 @@ option append stdout (or file descriptor n) to file .It Li [n]< file redirect stdin (or file descriptor n) from file +.It Li [n]<> file +redirect stdin (or file descriptor n) to and from file .It Li [n1]<&n2 duplicate stdin (or file descriptor n1) from file descriptor n2 .It Li [n]<&- diff --git a/bin/sh/show.c b/bin/sh/show.c index 4abc4c084e99..0183e6b701e2 100644 --- a/bin/sh/show.c +++ b/bin/sh/show.c @@ -157,6 +157,7 @@ shcmd(cmd, fp) case NAPPEND: s = ">>"; dftfd = 1; break; case NTOFD: s = ">&"; dftfd = 1; break; case NFROM: s = "<"; dftfd = 0; break; + case NFROMTO: s = "<>"; dftfd = 0; break; case NFROMFD: s = "<&"; dftfd = 0; break; default: s = "*error*"; dftfd = 0; break; }