summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorgjb <gjb@FreeBSD.org>2016-02-02 22:27:48 +0000
committergjb <gjb@FreeBSD.org>2016-02-02 22:27:48 +0000
commitefd5551e55b056811a107b33e1c30676ee37d0e8 (patch)
tree5ea64f05cc16d8a5032524fdefec823e707e1ff3 /bin
parenta6998ad84f9722c560a80302a74fa495e818a153 (diff)
parent6d511d769313fd1dae574a1d395369df219e86b6 (diff)
downloadFreeBSD-src-efd5551e55b056811a107b33e1c30676ee37d0e8.zip
FreeBSD-src-efd5551e55b056811a107b33e1c30676ee37d0e8.tar.gz
MFH
Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'bin')
-rw-r--r--bin/csh/iconv_stub.c6
-rw-r--r--bin/sh/redir.c29
-rw-r--r--bin/sh/sh.125
-rw-r--r--bin/test/test.c164
4 files changed, 141 insertions, 83 deletions
diff --git a/bin/csh/iconv_stub.c b/bin/csh/iconv_stub.c
index d1a9e47..e20608c 100644
--- a/bin/csh/iconv_stub.c
+++ b/bin/csh/iconv_stub.c
@@ -36,9 +36,9 @@
#undef iconv_close
#define ICONVLIB "libiconv.so"
-#define ICONV_ENGINE "iconv"
-#define ICONV_OPEN "iconv_open"
-#define ICONV_CLOSE "iconv_close"
+#define ICONV_ENGINE "libiconv"
+#define ICONV_OPEN "libiconv_open"
+#define ICONV_CLOSE "libiconv_close"
typedef iconv_t iconv_open_t(const char *, const char *);
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index 95d3238..0a7aa96 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -70,6 +70,7 @@ struct redirtab {
struct redirtab *next;
int renamed[10];
int fd0_redirected;
+ unsigned int empty_redirs;
};
@@ -82,6 +83,9 @@ static struct redirtab *redirlist;
*/
static int fd0_redirected = 0;
+/* Number of redirtabs that have not been allocated. */
+static unsigned int empty_redirs = 0;
+
static void openredirect(union node *, char[10 ]);
static int openhere(union node *);
@@ -115,12 +119,17 @@ redirect(union node *redir, int flags)
memory[i] = 0;
memory[1] = flags & REDIR_BACKQ;
if (flags & REDIR_PUSH) {
- sv = ckmalloc(sizeof (struct redirtab));
- for (i = 0 ; i < 10 ; i++)
- sv->renamed[i] = EMPTY;
- sv->fd0_redirected = fd0_redirected;
- sv->next = redirlist;
- redirlist = sv;
+ empty_redirs++;
+ if (redir != NULL) {
+ sv = ckmalloc(sizeof (struct redirtab));
+ for (i = 0 ; i < 10 ; i++)
+ sv->renamed[i] = EMPTY;
+ sv->fd0_redirected = fd0_redirected;
+ sv->empty_redirs = empty_redirs - 1;
+ sv->next = redirlist;
+ redirlist = sv;
+ empty_redirs = 0;
+ }
}
for (n = redir ; n ; n = n->nfile.next) {
fd = n->nfile.fd;
@@ -303,6 +312,12 @@ popredir(void)
struct redirtab *rp = redirlist;
int i;
+ INTOFF;
+ if (empty_redirs > 0) {
+ empty_redirs--;
+ INTON;
+ return;
+ }
for (i = 0 ; i < 10 ; i++) {
if (rp->renamed[i] != EMPTY) {
if (rp->renamed[i] >= 0) {
@@ -313,8 +328,8 @@ popredir(void)
}
}
}
- INTOFF;
fd0_redirected = rp->fd0_redirected;
+ empty_redirs = rp->empty_redirs;
redirlist = rp->next;
ckfree(rp);
INTON;
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 14ae898..9406779 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$
.\"
-.Dd August 29, 2015
+.Dd January 30, 2016
.Dt SH 1
.Os
.Sh NAME
@@ -1952,13 +1952,20 @@ Execute the specified built-in command,
This is useful when the user wishes to override a shell function
with the same name as a built-in command.
.It Ic cd Oo Fl L | P Oc Oo Fl e Oc Op Ar directory
+.It Ic cd Fl
Switch to the specified
.Ar directory ,
-or to the directory specified in the
+to the directory specified in the
.Va HOME
environment variable if no
.Ar directory
-is specified.
+is specified or
+to the directory specified in the
+.Va OLDPWD
+environment variable if
+.Ar directory
+is
+.Fl .
If
.Ar directory
does not begin with
@@ -1982,10 +1989,12 @@ the
.Ic cd
command will print out the name of the directory
that it actually switched to
-if this is different from the name that the user gave.
-These may be different either because the
+if the
.Va CDPATH
-mechanism was used or because a symbolic link was crossed.
+mechanism was used or if
+.Ar directory
+was
+.Fl .
.Pp
If the
.Fl P
@@ -2774,6 +2783,10 @@ Initialization file for interactive shells.
Locale settings.
These are inherited by children of the shell,
and is used in a limited manner by the shell itself.
+.It Ev OLDPWD
+The previous current directory.
+This is used and updated by
+.Ic cd .
.It Ev PWD
An absolute pathname for the current directory,
possibly containing symbolic links.
diff --git a/bin/test/test.c b/bin/test/test.c
index 46e9999..48b718e 100644
--- a/bin/test/test.c
+++ b/bin/test/test.c
@@ -120,51 +120,53 @@ enum token {
#define TOKEN_TYPE(token) ((token) & 0xff00)
-static struct t_op {
- char op_text[4];
+static const struct t_op {
+ char op_text[2];
short op_num;
-} const ops [] = {
- {"-r", FILRD},
- {"-w", FILWR},
- {"-x", FILEX},
- {"-e", FILEXIST},
- {"-f", FILREG},
- {"-d", FILDIR},
- {"-c", FILCDEV},
- {"-b", FILBDEV},
- {"-p", FILFIFO},
- {"-u", FILSUID},
- {"-g", FILSGID},
- {"-k", FILSTCK},
- {"-s", FILGZ},
- {"-t", FILTT},
- {"-z", STREZ},
- {"-n", STRNZ},
- {"-h", FILSYM}, /* for backwards compat */
- {"-O", FILUID},
- {"-G", FILGID},
- {"-L", FILSYM},
- {"-S", FILSOCK},
+} ops1[] = {
{"=", STREQ},
- {"==", STREQ},
- {"!=", STRNE},
{"<", STRLT},
{">", STRGT},
- {"-eq", INTEQ},
- {"-ne", INTNE},
- {"-ge", INTGE},
- {"-gt", INTGT},
- {"-le", INTLE},
- {"-lt", INTLT},
- {"-nt", FILNT},
- {"-ot", FILOT},
- {"-ef", FILEQ},
{"!", UNOT},
- {"-a", BAND},
- {"-o", BOR},
{"(", LPAREN},
{")", RPAREN},
- {"", 0}
+}, opsm1[] = {
+ {"r", FILRD},
+ {"w", FILWR},
+ {"x", FILEX},
+ {"e", FILEXIST},
+ {"f", FILREG},
+ {"d", FILDIR},
+ {"c", FILCDEV},
+ {"b", FILBDEV},
+ {"p", FILFIFO},
+ {"u", FILSUID},
+ {"g", FILSGID},
+ {"k", FILSTCK},
+ {"s", FILGZ},
+ {"t", FILTT},
+ {"z", STREZ},
+ {"n", STRNZ},
+ {"h", FILSYM}, /* for backwards compat */
+ {"O", FILUID},
+ {"G", FILGID},
+ {"L", FILSYM},
+ {"S", FILSOCK},
+ {"a", BAND},
+ {"o", BOR},
+}, ops2[] = {
+ {"==", STREQ},
+ {"!=", STRNE},
+}, opsm2[] = {
+ {"eq", INTEQ},
+ {"ne", INTNE},
+ {"ge", INTGE},
+ {"gt", INTGT},
+ {"le", INTLE},
+ {"lt", INTLT},
+ {"nt", FILNT},
+ {"ot", FILOT},
+ {"ef", FILEQ},
};
static int nargc;
@@ -416,35 +418,71 @@ filstat(char *nm, enum token mode)
}
}
-static enum token
-t_lex(char *s)
+static int
+find_op_1char(const struct t_op *op, const struct t_op *end, const char *s)
{
- struct t_op const *op = ops;
+ char c;
- if (s == 0) {
- return EOI;
+ c = s[0];
+ while (op != end) {
+ if (c == *op->op_text)
+ return op->op_num;
+ op++;
}
- while (*op->op_text) {
- if (strcmp(s, op->op_text) == 0) {
- if (((TOKEN_TYPE(op->op_num) == UNOP ||
- TOKEN_TYPE(op->op_num) == BUNOP)
- && isunopoperand()) ||
- (op->op_num == LPAREN && islparenoperand()) ||
- (op->op_num == RPAREN && isrparenoperand()))
- break;
+ return OPERAND;
+}
+
+static int
+find_op_2char(const struct t_op *op, const struct t_op *end, const char *s)
+{
+ while (op != end) {
+ if (s[0] == op->op_text[0] && s[1] == op->op_text[1])
return op->op_num;
- }
op++;
}
return OPERAND;
}
static int
+find_op(const char *s)
+{
+ if (s[0] == '\0')
+ return OPERAND;
+ else if (s[1] == '\0')
+ return find_op_1char(ops1, (&ops1)[1], s);
+ else if (s[2] == '\0')
+ return s[0] == '-' ? find_op_1char(opsm1, (&opsm1)[1], s + 1) :
+ find_op_2char(ops2, (&ops2)[1], s);
+ else if (s[3] == '\0')
+ return s[0] == '-' ? find_op_2char(opsm2, (&opsm2)[1], s + 1) :
+ OPERAND;
+ else
+ return OPERAND;
+}
+
+static enum token
+t_lex(char *s)
+{
+ int num;
+
+ if (s == 0) {
+ return EOI;
+ }
+ num = find_op(s);
+ if (((TOKEN_TYPE(num) == UNOP || TOKEN_TYPE(num) == BUNOP)
+ && isunopoperand()) ||
+ (num == LPAREN && islparenoperand()) ||
+ (num == RPAREN && isrparenoperand()))
+ return OPERAND;
+ return num;
+}
+
+static int
isunopoperand(void)
{
- struct t_op const *op = ops;
char *s;
char *t;
+ int num;
if (nargc == 1)
return 1;
@@ -452,20 +490,16 @@ isunopoperand(void)
if (nargc == 2)
return parenlevel == 1 && strcmp(s, ")") == 0;
t = *(t_wp + 2);
- while (*op->op_text) {
- if (strcmp(s, op->op_text) == 0)
- return TOKEN_TYPE(op->op_num) == BINOP &&
- (parenlevel == 0 || t[0] != ')' || t[1] != '\0');
- op++;
- }
- return 0;
+ num = find_op(s);
+ return TOKEN_TYPE(num) == BINOP &&
+ (parenlevel == 0 || t[0] != ')' || t[1] != '\0');
}
static int
islparenoperand(void)
{
- struct t_op const *op = ops;
char *s;
+ int num;
if (nargc == 1)
return 1;
@@ -474,12 +508,8 @@ islparenoperand(void)
return parenlevel == 1 && strcmp(s, ")") == 0;
if (nargc != 3)
return 0;
- while (*op->op_text) {
- if (strcmp(s, op->op_text) == 0)
- return TOKEN_TYPE(op->op_num) == BINOP;
- op++;
- }
- return 0;
+ num = find_op(s);
+ return TOKEN_TYPE(num) == BINOP;
}
static int
OpenPOWER on IntegriCloud