commit: 5f43fd7f991c08d7b694579b643bc7423c75b957
parent: 116a1847123df86241856d5e744c0afeb35a2f78
author: Chris Noxz <chris@noxz.tech>
date: Tue, 9 Mar 2021 19:25:38 +0100
Match upstream 6.8
8 files changed, 166 insertions(+), 57 deletions(-)
diff --git a/c_sh.c b/c_sh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: c_sh.c,v 1.63 2018/04/09 17:53:36 tobias Exp $ */
+/* $OpenBSD: c_sh.c,v 1.64 2020/05/22 07:50:07 benno Exp $ */
/*
* built-in Bourne commands
@@ -425,6 +425,8 @@ int
c_eval(char **wp)
{
struct source *s;
+ struct source *saves = source;
+ int savef;
int rv;
if (ksh_getopt(wp, &builtin_opt, null) == '?')
@@ -459,7 +461,11 @@ c_eval(char **wp)
exstat = subst_exstat;
}
+ savef = Flag(FERREXIT);
+ Flag(FERREXIT) = 0;
rv = shell(s, false);
+ Flag(FERREXIT) = savef;
+ source = saves;
afree(s, ATEMP);
return (rv);
}
diff --git a/emacs.c b/emacs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: emacs.c,v 1.86 2019/04/03 14:55:12 jca Exp $ */
+/* $OpenBSD: emacs.c,v 1.87 2020/05/08 14:30:42 jca Exp $ */
/*
* Emacs-like command line editing and history
@@ -41,8 +41,10 @@ static Area aedit;
#define KEOL 1 /* ^M, ^J */
#define KINTR 2 /* ^G, ^C */
+typedef int (*kb_func)(int);
+
struct x_ftab {
- int (*xf_func)(int c);
+ kb_func xf_func;
const char *xf_name;
short xf_flags;
};
@@ -861,7 +863,7 @@ x_eot_del(int c)
return (x_del_char(c));
}
-static void *
+static kb_func
kb_find_hist_func(char c)
{
struct kb_entry *k;
@@ -1315,7 +1317,7 @@ kb_del(struct kb_entry *k)
}
static struct kb_entry *
-kb_add_string(void *func, void *args, char *str)
+kb_add_string(kb_func func, void *args, char *str)
{
unsigned int ele, count;
struct kb_entry *k;
@@ -1350,7 +1352,7 @@ kb_add_string(void *func, void *args, char *str)
}
static struct kb_entry *
-kb_add(void *func, ...)
+kb_add(kb_func func, ...)
{
va_list ap;
unsigned char ch;
diff --git a/eval.c b/eval.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: eval.c,v 1.65 2019/06/28 13:34:59 deraadt Exp $ */
+/* $OpenBSD: eval.c,v 1.66 2020/09/13 15:39:09 tb Exp $ */
/*
* Expansion - quoting, separation, substitution, globbing
@@ -47,6 +47,8 @@ typedef struct Expand {
#define IFS_WORD 0 /* word has chars (or quotes) */
#define IFS_WS 1 /* have seen IFS white-space */
#define IFS_NWS 2 /* have seen IFS non-white-space */
+#define IFS_IWS 3 /* beginning of word, ignore IFS white-space */
+#define IFS_QUOTE 4 /* beg.w/quote, becomes IFS_WORD unless "$@" */
static int varsub(Expand *, char *, char *, int *, int *);
static int comsub(Expand *, char *);
@@ -217,7 +219,17 @@ expand(char *cp, /* input word */
c = *sp++;
break;
case OQUOTE:
- word = IFS_WORD;
+ switch (word) {
+ case IFS_QUOTE:
+ /* """something */
+ word = IFS_WORD;
+ break;
+ case IFS_WORD:
+ break;
+ default:
+ word = IFS_QUOTE;
+ break;
+ }
tilde_ok = 0;
quote = 1;
continue;
@@ -297,6 +309,8 @@ expand(char *cp, /* input word */
if (f&DOBLANK)
doblank++;
tilde_ok = 0;
+ if (word == IFS_QUOTE && type != XNULLSUB)
+ word = IFS_WORD;
if (type == XBASE) { /* expand? */
if (!st->next) {
SubType *newst;
@@ -358,6 +372,11 @@ expand(char *cp, /* input word */
f |= DOTEMP_;
/* FALLTHROUGH */
default:
+ /* '-' '+' '?' */
+ if (quote)
+ word = IFS_WORD;
+ else if (dp == Xstring(ds, dp))
+ word = IFS_IWS;
/* Enable tilde expansion */
tilde_ok = 1;
f |= DOTILDE;
@@ -387,10 +406,17 @@ expand(char *cp, /* input word */
*/
x.str = trimsub(str_val(st->var),
dp, st->stype);
- if (x.str[0] != '\0' || st->quote)
+ if (x.str[0] != '\0') {
+ word = IFS_IWS;
type = XSUB;
- else
+ } else if (quote) {
+ word = IFS_WORD;
+ type = XSUB;
+ } else {
+ if (dp == Xstring(ds, dp))
+ word = IFS_IWS;
type = XNULLSUB;
+ }
if (f&DOBLANK)
doblank++;
st = st->prev;
@@ -422,6 +448,10 @@ expand(char *cp, /* input word */
if (f&DOBLANK)
doblank++;
st = st->prev;
+ if (quote || !*x.str)
+ word = IFS_WORD;
+ else
+ word = IFS_IWS;
continue;
case '?':
{
@@ -463,12 +493,8 @@ expand(char *cp, /* input word */
type = XBASE;
if (f&DOBLANK) {
doblank--;
- /* not really correct: x=; "$x$@" should
- * generate a null argument and
- * set A; "${@:+}" shouldn't.
- */
- if (dp == Xstring(ds, dp))
- word = IFS_WS;
+ if (dp == Xstring(ds, dp) && word != IFS_WORD)
+ word = IFS_IWS;
}
continue;
@@ -503,7 +529,12 @@ expand(char *cp, /* input word */
if (c == 0) {
if (quote && !x.split)
continue;
+ if (!quote && word == IFS_WS)
+ continue;
+ /* this is so we don't terminate */
c = ' ';
+ /* now force-emit a word */
+ goto emit_word;
}
if (quote && x.split) {
/* terminate word for "$@" */
@@ -554,15 +585,15 @@ expand(char *cp, /* input word */
* -----------------------------------
* IFS_WORD w/WS w/NWS w
* IFS_WS -/WS w/NWS -
- * IFS_NWS -/NWS w/NWS w
+ * IFS_NWS -/NWS w/NWS -
+ * IFS_IWS -/WS w/NWS -
* (w means generate a word)
- * Note that IFS_NWS/0 generates a word (at&t ksh
- * doesn't do this, but POSIX does).
*/
- if (word == IFS_WORD ||
- (!ctype(c, C_IFSWS) && c && word == IFS_NWS)) {
- char *p;
-
+ if ((word == IFS_WORD) || (word == IFS_QUOTE) || (c &&
+ (word == IFS_IWS || word == IFS_NWS) &&
+ !ctype(c, C_IFSWS))) {
+ char *p;
+ emit_word:
*dp++ = '\0';
p = Xclose(ds, dp);
if (fdo & DOBRACE_)
diff --git a/jobs.c b/jobs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: jobs.c,v 1.61 2019/06/28 13:34:59 deraadt Exp $ */
+/* $OpenBSD: jobs.c,v 1.62 2020/07/07 10:33:58 jca Exp $ */
/*
* Process and job control
@@ -71,6 +71,7 @@ struct proc {
#define JF_REMOVE 0x200 /* flagged for removal (j_jobs()/j_notify()) */
#define JF_USETTYMODE 0x400 /* tty mode saved if process exits normally */
#define JF_SAVEDTTYPGRP 0x800 /* j->saved_ttypgrp is valid */
+#define JF_PIPEFAIL 0x1000 /* pipefail on when job was started */
typedef struct job Job;
struct job {
@@ -426,6 +427,8 @@ exchild(struct op *t, int flags, volatile int *xerrok,
*/
j->flags = (flags & XXCOM) ? JF_XXCOM :
((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE));
+ if (Flag(FPIPEFAIL))
+ j->flags |= JF_PIPEFAIL;
timerclear(&j->usrtime);
timerclear(&j->systime);
j->state = PRUNNING;
@@ -1089,7 +1092,30 @@ j_waitj(Job *j,
j_usrtime = j->usrtime;
j_systime = j->systime;
- rv = j->status;
+
+ if (j->flags & JF_PIPEFAIL) {
+ Proc *p;
+ int status;
+
+ rv = 0;
+ for (p = j->proc_list; p != NULL; p = p->next) {
+ switch (p->state) {
+ case PEXITED:
+ status = WEXITSTATUS(p->status);
+ break;
+ case PSIGNALLED:
+ status = 128 + WTERMSIG(p->status);
+ break;
+ default:
+ status = 0;
+ break;
+ }
+ if (status)
+ rv = status;
+ }
+ } else
+ rv = j->status;
+
if (!(flags & JW_ASYNCNOTIFY) &&
(!Flag(FMONITOR) || j->state != PSTOPPED)) {
diff --git a/ksh.1 b/ksh.1
@@ -1,8 +1,8 @@
-.\" $OpenBSD: ksh.1,v 1.208 2019/11/26 22:49:01 jmc Exp $
+.\" $OpenBSD: ksh.1,v 1.210 2020/09/20 14:40:45 millert Exp $
.\"
.\" Public Domain
.\"
-.Dd $Mdocdate: November 26 2019 $
+.Dd $Mdocdate: September 20 2020 $
.Dt KSH 1
.Os
.Sh NAME
@@ -361,7 +361,9 @@ token to form pipelines, in which the standard output of each command but the
last is piped (see
.Xr pipe 2 )
to the standard input of the following command.
-The exit status of a pipeline is that of its last command.
+The exit status of a pipeline is that of its last command, unless the
+.Ic pipefail
+option is set.
A pipeline may be prefixed by the
.Ql \&!
reserved word, which causes the exit status of the pipeline to be logically
@@ -3664,6 +3666,10 @@ See the
and
.Ic pwd
commands above for more details.
+.It Ic pipefail
+The exit status of a pipeline is the exit status of the rightmost
+command in the pipeline that doesn't return 0, or 0 if all commands
+returned a 0 exit status.
.It Ic posix
Enable POSIX mode.
See
@@ -5047,6 +5053,13 @@ Erases previous character.
.It ^J | ^M
End of line.
The current line is read, parsed, and executed by the shell.
+.It ^L
+Clear the screen (if possible) and redraw the current line.
+See the
+.Em clear-screen
+command in
+.Sx Emacs editing mode
+for more information.
.It ^V
Literal next.
The next character typed is not treated specially (can be used
@@ -5504,7 +5517,9 @@ Miscellaneous vi commands
.Bl -tag -width Ds
.It ^J and ^M
The current line is read, parsed, and executed by the shell.
-.It ^L and ^R
+.It ^L
+Clear the screen (if possible) and redraw the current line.
+.It ^R
Redraw the current line.
.It Xo
.Oo Ar n Oc Ns \&.
diff --git a/misc.c b/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.73 2019/06/28 13:34:59 deraadt Exp $ */
+/* $OpenBSD: misc.c,v 1.75 2020/07/22 19:20:41 millert Exp $ */
/*
* Miscellaneous functions
@@ -149,6 +149,7 @@ const struct option sh_options[] = {
{ "notify", 'b', OF_ANY },
{ "nounset", 'u', OF_ANY },
{ "physical", 0, OF_ANY }, /* non-standard */
+ { "pipefail", 0, OF_ANY }, /* non-standard */
{ "posix", 0, OF_ANY }, /* non-standard */
{ "privileged", 'p', OF_ANY },
{ "restricted", 'r', OF_CMDLINE },
@@ -613,6 +614,9 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
break;
case '*':
+ /* collapse consecutive stars */
+ while (ISMAGIC(p[0]) && p[1] == '*')
+ p += 2;
if (p == pe)
return 1;
s--;
diff --git a/sh.h b/sh.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sh.h,v 1.75 2019/02/20 23:59:17 schwarze Exp $ */
+/* $OpenBSD: sh.h,v 1.76 2020/07/07 10:33:58 jca Exp $ */
/*
* Public Domain Bourne/Korn shell
@@ -160,6 +160,7 @@ enum sh_flag {
FNOTIFY, /* -b: asynchronous job completion notification */
FNOUNSET, /* -u: using an unset var is an error */
FPHYSICAL, /* -o physical: don't do logical cd's/pwd's */
+ FPIPEFAIL, /* -o pipefail: all commands in pipeline can affect $? */
FPOSIX, /* -o posix: be posixly correct */
FPRIVILEGED, /* -p: use suid_profile */
FRESTRICTED, /* -r: restricted shell */
diff --git a/vi.c b/vi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vi.c,v 1.56 2018/03/15 16:51:29 anton Exp $ */
+/* $OpenBSD: vi.c,v 1.57 2020/09/20 14:40:45 millert Exp $ */
/*
* vi command editing
@@ -14,12 +14,14 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
+#ifndef SMALL
+# include <term.h>
+# include <curses.h>
+#endif
#include "sh.h"
#include "edit.h"
-#define CTRL(c) (c & 0x1f)
-
struct edstate {
char *cbuf; /* main buffer to build the command line */
int cbufsize; /* number of bytes allocated for cbuf */
@@ -56,8 +58,9 @@ static int Backword(int);
static int Endword(int);
static int grabhist(int, int);
static int grabsearch(int, int, int, char *);
+static void do_clear_screen(void);
static void redraw_line(int);
-static void refresh(int);
+static void refresh_line(int);
static int outofwin(void);
static void rewindow(void);
static int newcol(int, int);
@@ -275,9 +278,9 @@ vi_hook(int ch)
case 0:
if (state == VLIT) {
es->cursor--;
- refresh(0);
+ refresh_line(0);
} else
- refresh(insert != 0);
+ refresh_line(insert != 0);
break;
case 1:
return 1;
@@ -302,7 +305,7 @@ vi_hook(int ch)
return -1;
} else if (putbuf("?", 1, 0) != 0)
return -1;
- refresh(0);
+ refresh_line(0);
}
}
}
@@ -314,7 +317,7 @@ vi_hook(int ch)
vi_error();
} else
es->cbuf[es->cursor++] = ch;
- refresh(1);
+ refresh_line(1);
state = VNORMAL;
break;
@@ -379,7 +382,7 @@ vi_hook(int ch)
if (!srchpat[0]) {
vi_error();
state = VNORMAL;
- refresh(0);
+ refresh_line(0);
return 0;
}
} else {
@@ -396,17 +399,17 @@ vi_hook(int ch)
} while (srchlen > 0 &&
isu8cont(locpat[srchlen]));
es->cursor = es->linelen;
- refresh(0);
+ refresh_line(0);
return 0;
}
restore_cbuf();
state = VNORMAL;
- refresh(0);
+ refresh_line(0);
} else if (ch == edchars.kill) {
srchlen = 0;
es->linelen = 1;
es->cursor = 1;
- refresh(0);
+ refresh_line(0);
return 0;
} else if (ch == edchars.werase) {
struct edstate new_es, *save_es;
@@ -425,7 +428,7 @@ vi_hook(int ch)
es->linelen -= char_len((unsigned char)locpat[i]);
srchlen = n;
es->cursor = es->linelen;
- refresh(0);
+ refresh_line(0);
return 0;
} else {
if (srchlen == SRCHLEN - 1)
@@ -450,7 +453,7 @@ vi_hook(int ch)
es->cbuf[es->linelen++] = ch;
}
es->cursor = es->linelen;
- refresh(0);
+ refresh_line(0);
}
return 0;
}
@@ -463,15 +466,15 @@ vi_hook(int ch)
switch (vi_cmd(argc1, curcmd)) {
case -1:
vi_error();
- refresh(0);
+ refresh_line(0);
break;
case 0:
if (insert != 0)
inslen = 0;
- refresh(insert != 0);
+ refresh_line(insert != 0);
break;
case 1:
- refresh(0);
+ refresh_line(0);
return 1;
case 2:
/* back from a 'v' command - don't redraw the screen */
@@ -486,7 +489,7 @@ vi_hook(int ch)
switch (vi_cmd(lastac, lastcmd)) {
case -1:
vi_error();
- refresh(0);
+ refresh_line(0);
break;
case 0:
if (insert != 0) {
@@ -499,10 +502,10 @@ vi_hook(int ch)
vi_error();
}
}
- refresh(0);
+ refresh_line(0);
break;
case 1:
- refresh(0);
+ refresh_line(0);
return 1;
case 2:
/* back from a 'v' command - can't happen */
@@ -655,6 +658,10 @@ vi_insert(int ch)
print_expansions(es);
break;
+ case CTRL('l'):
+ do_clear_screen();
+ break;
+
case CTRL('i'):
if (Flag(FVITABCOMPLETE)) {
complete_word(0, 0);
@@ -712,6 +719,9 @@ vi_cmd(int argcnt, const char *cmd)
switch (*cmd) {
case CTRL('l'):
+ do_clear_screen();
+ break;
+
case CTRL('r'):
redraw_line(1);
break;
@@ -1032,7 +1042,7 @@ vi_cmd(int argcnt, const char *cmd)
c1, srchpat)) < 0) {
if (c3) {
restore_cbuf();
- refresh(0);
+ refresh_line(0);
}
return -1;
} else {
@@ -1721,10 +1731,24 @@ grabsearch(int save, int start, int fwd, char *pat)
}
static void
-redraw_line(int newline)
+do_clear_screen(void)
+{
+ int neednl = 1;
+
+#ifndef SMALL
+ if (cur_term != NULL && clear_screen != NULL) {
+ if (tputs(clear_screen, 1, x_putc) != ERR)
+ neednl = 0;
+ }
+#endif
+ redraw_line(neednl);
+}
+
+static void
+redraw_line(int neednl)
{
(void) memset(wbuf[win], ' ', wbuf_len);
- if (newline) {
+ if (neednl) {
x_putc('\r');
x_putc('\n');
}
@@ -1734,7 +1758,7 @@ redraw_line(int newline)
}
static void
-refresh(int leftside)
+refresh_line(int leftside)
{
if (outofwin())
rewindow();
@@ -2037,7 +2061,7 @@ expand_word(int command)
modified = 1; hnum = hlast;
set_insert(INSERT);
lastac = 0;
- refresh(0);
+ refresh_line(0);
return rval;
}
@@ -2141,7 +2165,7 @@ complete_word(int command, int count)
modified = 1; hnum = hlast;
set_insert(INSERT);
lastac = 0; /* prevent this from being redone... */
- refresh(0);
+ refresh_line(0);
return rval;
}