commit: bbbcad24eea02b8fc58c93bc732d3cc207af4116
parent: af6237e8bd9ae40d6b47b6d4536f0868cc19cf6c
author: Brian Callahan <bcallah@openbsd.org>
date: Sun, 23 Sep 2018 14:31:27 -0400
We're approaching OpenBSD 6.4 now; this is close to what will be
released.
Note now that oksh will use ncurses if it finds it during the
configure stage. If you don't want ncurses support (used for screen
clearing), pass the --disable-curses flag to configure.
11 files changed, 265 insertions(+), 67 deletions(-)
diff --git a/CVS/Entries b/CVS/Entries
@@ -1,46 +1,46 @@
/config.h/1.19/Tue Jan 16 02:21:56 2018//
/history.c/1.80/Tue Jan 16 02:21:56 2018//
-/emacs.c/1.84/Result of merge//
/main.c/1.92/Result of merge//
-/CONTRIBUTORS/1.10/Fri Jun 1 19:10:08 2018//
-/LEGAL/1.2/Fri Jun 1 19:10:08 2018//
-/Makefile/1.38/Fri Jun 1 19:10:21 2018//
-/NOTES/1.16/Fri Jun 1 19:10:08 2018//
-/PROJECTS/1.9/Fri Jun 1 19:10:08 2018//
-/README/1.16/Fri Jun 1 19:10:21 2018//
-/alloc.c/1.19/Fri Jun 1 19:10:08 2018//
-/c_ksh.c/1.61/Fri Jun 1 19:10:08 2018//
-/c_sh.c/1.63/Fri Jun 1 19:10:08 2018//
-/c_test.c/1.25/Fri Jun 1 19:10:08 2018//
-/c_test.h/1.4/Fri Jun 1 19:10:08 2018//
-/c_ulimit.c/1.28/Fri Jun 1 19:10:08 2018//
-/edit.c/1.65/Fri Jun 1 19:10:08 2018//
-/edit.h/1.11/Fri Jun 1 19:10:08 2018//
-/eval.c/1.60/Fri Jun 1 19:10:08 2018//
-/exec.c/1.73/Fri Jun 1 19:10:08 2018//
-/expand.h/1.15/Fri Jun 1 19:10:08 2018//
-/expr.c/1.33/Fri Jun 1 19:10:08 2018//
/io.c/1.36/Fri Jun 1 19:10:08 2018//
-/jobs.c/1.60/Fri Jun 1 19:10:08 2018//
-/ksh.1/1.200/Fri Jun 1 19:10:21 2018//
-/lex.c/1.78/Fri Jun 1 19:10:08 2018//
-/lex.h/1.21/Fri Jun 1 19:10:08 2018//
-/mail.c/1.23/Fri Jun 1 19:10:08 2018//
-/misc.c/1.70/Fri Jun 1 19:10:08 2018//
-/path.c/1.22/Fri Jun 1 19:10:08 2018//
-/sh.1/1.148/Fri Jun 1 19:10:08 2018//
-/sh.h/1.73/Fri Jun 1 19:10:08 2018//
-/shf.c/1.33/Fri Jun 1 19:10:08 2018//
-/shf.h/1.8/Fri Jun 1 19:10:08 2018//
-/syn.c/1.39/Fri Jun 1 19:10:08 2018//
-/table.c/1.25/Fri Jun 1 19:10:08 2018//
-/table.h/1.14/Fri Jun 1 19:10:08 2018//
-/trap.c/1.32/Fri Jun 1 19:10:08 2018//
-/tree.c/1.34/Fri Jun 1 19:10:08 2018//
-/tree.h/1.12/Fri Jun 1 19:10:08 2018//
/tty.c/1.17/Fri Jun 1 19:10:08 2018//
-/tty.h/1.6/Fri Jun 1 19:10:08 2018//
-/var.c/1.68/Fri Jun 1 19:10:08 2018//
-/version.c/1.12/Fri Jun 1 19:10:08 2018//
-/vi.c/1.56/Fri Jun 1 19:10:08 2018//
+/CONTRIBUTORS/1.10/Sun Sep 23 17:58:57 2018//
+/LEGAL/1.2/Sun Sep 23 17:58:57 2018//
+/Makefile/1.39/Sun Sep 23 17:59:17 2018//
+/NOTES/1.16/Sun Sep 23 17:58:57 2018//
+/PROJECTS/1.9/Sun Sep 23 17:58:57 2018//
+/README/1.16/Sun Sep 23 17:59:17 2018//
+/alloc.c/1.19/Sun Sep 23 17:58:57 2018//
+/c_ksh.c/1.61/Sun Sep 23 17:58:57 2018//
+/c_sh.c/1.63/Sun Sep 23 17:58:57 2018//
+/c_test.c/1.25/Sun Sep 23 17:58:57 2018//
+/c_test.h/1.4/Sun Sep 23 17:58:57 2018//
+/c_ulimit.c/1.28/Sun Sep 23 17:58:57 2018//
+/edit.c/1.66/Sun Sep 23 17:59:17 2018//
+/edit.h/1.12/Sun Sep 23 17:59:17 2018//
+/emacs.c/1.85/Result of merge//
+/eval.c/1.63/Sun Sep 23 17:59:17 2018//
+/exec.c/1.73/Sun Sep 23 17:58:57 2018//
+/expand.h/1.15/Sun Sep 23 17:58:57 2018//
+/expr.c/1.33/Sun Sep 23 17:58:57 2018//
+/jobs.c/1.60/Sun Sep 23 17:58:57 2018//
+/ksh.1/1.201/Sun Sep 23 17:59:17 2018//
+/lex.c/1.78/Sun Sep 23 17:58:57 2018//
+/lex.h/1.21/Sun Sep 23 17:58:57 2018//
+/mail.c/1.24/Sun Sep 23 17:59:17 2018//
+/misc.c/1.70/Sun Sep 23 17:58:57 2018//
+/path.c/1.22/Sun Sep 23 17:58:57 2018//
+/sh.1/1.148/Sun Sep 23 17:58:57 2018//
+/sh.h/1.73/Sun Sep 23 17:58:57 2018//
+/shf.c/1.33/Sun Sep 23 17:58:57 2018//
+/shf.h/1.8/Sun Sep 23 17:58:57 2018//
+/syn.c/1.39/Sun Sep 23 17:58:57 2018//
+/table.c/1.25/Sun Sep 23 17:58:57 2018//
+/table.h/1.15/Sun Sep 23 17:59:17 2018//
+/trap.c/1.32/Sun Sep 23 17:58:57 2018//
+/tree.c/1.34/Sun Sep 23 17:58:57 2018//
+/tree.h/1.12/Sun Sep 23 17:58:57 2018//
+/tty.h/1.6/Sun Sep 23 17:58:57 2018//
+/var.c/1.70/Sun Sep 23 17:59:17 2018//
+/version.c/1.12/Sun Sep 23 17:58:57 2018//
+/vi.c/1.56/Sun Sep 23 17:58:57 2018//
D
diff --git a/CVS/Entries.Log b/CVS/Entries.Log
@@ -0,0 +1,2 @@
+A D/tests////
+R D/tests////
diff --git a/configure b/configure
@@ -95,6 +95,22 @@ EOF
fi
}
+cursescheck() {
+ cat << EOF > conftest.c
+#include <term.h>
+#include <curses.h>
+int main(void){setupterm(NULL, 0, NULL);return 0;}
+EOF
+ $cc $cflags $ldflags -o conftest conftest.c -lcurses > /dev/null 2>&1
+ if [ $? -eq 0 ] ; then
+ rm -f conftest conftest.o conftest.c
+ return 0
+ else
+ rm -f conftest conftest.o conftest.c
+ return 1
+ fi
+}
+
deadcheck() {
cat << EOF > conftest.c
#include <stdlib.h>
@@ -125,6 +141,38 @@ EOF
fi
}
+ncursescheck() {
+ cat << EOF > conftest.c
+#include <term.h>
+#include <ncurses.h>
+int main(void){setupterm(NULL, 0, NULL);return 0;}
+EOF
+ $cc $cflags $ldflags -o conftest conftest.c -lncurses > /dev/null 2>&1
+ if [ $? -eq 0 ] ; then
+ rm -f conftest conftest.o conftest.c
+ return 0
+ else
+ rm -f conftest conftest.o conftest.c
+ return 1
+ fi
+}
+
+ncursesncursescheck() {
+ cat << EOF > conftest.c
+#include <ncurses/term.h>
+#include <ncurses/ncurses.h>
+int main(void){setupterm(NULL, 0, NULL);return 0;}
+EOF
+ $cc $cflags $ldflags -o conftest conftest.c -lncurses > /dev/null 2>&1
+ if [ $? -eq 0 ] ; then
+ rm -f conftest conftest.o conftest.c
+ return 0
+ else
+ rm -f conftest conftest.o conftest.c
+ return 1
+ fi
+}
+
pledgecheck() {
cat << EOF > conftest.c
#include <unistd.h>
@@ -413,6 +461,8 @@ fi
mandir="$prefix/man"
instprog="oksh"
+libs=""
+curses=1
instsh=0
static=0
@@ -426,6 +476,13 @@ do
--mandir=*)
mandir=`echo $opt | cut -d '=' -f 2`
;;
+ --disable-curses|--enable-curses)
+ if [ "x$opt" = "x--disable-curses" ] ; then
+ curses=0
+ else
+ curses=1
+ fi
+ ;;
--disable-ksh|--enable-ksh)
if [ "x$opt" = "x--enable-ksh" ] ; then
instprog="ksh"
@@ -457,6 +514,8 @@ do
echo "Top level install directory is PREFIX [$prefix]"
printf " --mandir=MANDIR "
echo "Manual pages are installed to MANDIR [$mandir]"
+ printf " --enable-curses "
+ echo "Use curses library for screen clear [default=yes]"
printf " --enable-ksh "
echo "Install executable as ksh [default=no]"
printf " --enable-sh "
@@ -580,6 +639,38 @@ else
echo "no"
fi
+printf "checking for curses library... "
+if [ $curses -eq 1 ] ; then
+ cursescheck
+ if [ $? -eq 0 ] ; then
+ libs="-lcurses"
+ echo "#define HAVE_CURSES" >> pconfig.h
+ echo "curses.h"
+ else
+ ncursescheck
+ if [ $? -eq 0 ] ; then
+ libs="-lncurses"
+ echo "#define HAVE_NCURSES" >> pconfig.h
+ echo "ncurses.h"
+ else
+ ncursesncursescheck
+ if [ $? -eq 0 ] ; then
+ libs="-lncurses"
+ echo "#define HAVE_NCURSESNCURSES" >> pconfig.h
+ echo "ncurses/ncurses.h"
+ else
+ echo "#define NO_CURSES" >> pconfig.h
+ echo "not found"
+ echo "oksh will be built without screen clearing support"
+ fi
+ fi
+ fi
+else
+ echo "#define NO_CURSES" >> pconfig.h
+ echo "disabled by user"
+ echo "oksh will be built without screen clearing support"
+fi
+
printf "checking for pledge... "
pledgecheck
if [ $? -eq 0 ] ; then
@@ -764,7 +855,7 @@ ETS = \`grep -w \${PREFIX}/bin/\${PROG} /etc/shells > /dev/null; \\
all: \${PROG}
\${PROG}: \${OBJS}
- \${CC} \${LDFLAGS} -o \${PROG} \${OBJS}
+ \${CC} \${LDFLAGS} -o \${PROG} \${OBJS} $libs
install:
install -d \${DESTDIR}\${PREFIX}/bin
diff --git a/edit.c b/edit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: edit.c,v 1.65 2018/04/09 17:53:36 tobias Exp $ */
+/* $OpenBSD: edit.c,v 1.66 2018/06/18 17:03:58 millert Exp $ */
/*
* Command line editing - common code
@@ -138,10 +138,10 @@ x_flush(void)
shf_flush(shl_out);
}
-void
+int
x_putc(int c)
{
- shf_putc(c, shl_out);
+ return shf_putc(c, shl_out);
}
void
diff --git a/edit.h b/edit.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: edit.h,v 1.11 2016/01/26 17:39:31 mmcc Exp $ */
+/* $OpenBSD: edit.h,v 1.12 2018/06/18 17:03:58 millert Exp $ */
/* NAME:
* edit.h - globals for edit modes
@@ -37,7 +37,7 @@ extern X_chars edchars;
/* edit.c */
int x_getc(void);
void x_flush(void);
-void x_putc(int);
+int x_putc(int);
void x_puts(const char *);
bool x_mode(bool);
int promptlen(const char *, const char **);
diff --git a/emacs.c b/emacs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: emacs.c,v 1.84 2018/01/16 17:17:18 jca Exp $ */
+/* $OpenBSD: emacs.c,v 1.85 2018/06/18 17:03:58 millert Exp $ */
/*
* Emacs-like command line editing and history
@@ -20,6 +20,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#if !defined(SMALL) && !defined(NO_CURSES)
+#ifdef HAVE_CURSES
+# include <term.h>
+# include <curses.h>
+#elif HAVE_NCURSES
+# include <term.h>
+# include <ncurses.h>
+#elif HAVE_NCURSESNCURSES
+# include <ncurses/term.h>
+# include <ncurses/ncurses.h>
+#endif
+#endif
#include "sys-queue.h"
#include "sh.h"
@@ -28,6 +40,7 @@
static Area aedit;
#define AEDIT &aedit /* area for kill ring and macro defns */
+#undef CTRL
#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
#define UNCTRL(x) ((x) == 0x7F ? '?' : (x) | 0x40) /* ASCII */
@@ -146,6 +159,7 @@ static int isu8cont(unsigned char);
/* proto's for keybindings */
static int x_abort(int);
static int x_beg_hist(int);
+static int x_clear_screen(int);
static int x_comp_comm(int);
static int x_comp_file(int);
static int x_complete(int);
@@ -202,6 +216,7 @@ static int x_debug_info(int);
static const struct x_ftab x_ftab[] = {
{ x_abort, "abort", 0 },
{ x_beg_hist, "beginning-of-history", 0 },
+ { x_clear_screen, "clear-screen", 0 },
{ x_comp_comm, "complete-command", 0 },
{ x_comp_file, "complete-file", 0 },
{ x_complete, "complete", 0 },
@@ -1004,12 +1019,19 @@ x_draw_line(int c)
{
x_redraw(-1);
return KSTD;
+}
+static int
+x_clear_screen(int c)
+{
+ x_redraw(-2);
+ return KSTD;
}
-/* Redraw (part of) the line. If limit is < 0, the everything is redrawn
- * on a NEW line, otherwise limit is the screen column up to which needs
- * redrawing.
+/* Redraw (part of) the line.
+ * A non-negative limit is the screen column up to which needs
+ * redrawing. A limit of -1 redraws on a new line, while a limit
+ * of -2 (attempts to) clear the screen.
*/
static void
x_redraw(int limit)
@@ -1018,9 +1040,20 @@ x_redraw(int limit)
char *cp;
x_adj_ok = 0;
- if (limit == -1)
+ if (limit == -2) {
+ int cleared = 0;
+#if !defined(SMALL) && !defined(NO_CURSES)
+ if (cur_term != NULL && clear_screen != NULL) {
+ if (tputs(clear_screen, 1, x_putc) != ERR)
+ cleared = 1;
+ }
+#endif
+ if (!cleared)
+ x_e_putc('\n');
+ }
+ else if (limit == -1)
x_e_putc('\n');
- else
+ else if (limit >= 0)
x_e_putc('\r');
x_flush();
if (xbp == xbuf) {
diff --git a/eval.c b/eval.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: eval.c,v 1.60 2018/04/09 17:53:36 tobias Exp $ */
+/* $OpenBSD: eval.c,v 1.63 2018/07/09 00:20:35 anton Exp $ */
/*
* Expansion - quoting, separation, substitution, globbing
@@ -58,6 +58,8 @@ static char *tilde(char *);
static char *homedir(char *);
static void alt_expand(XPtrV *, char *, char *, char *, int);
+static struct tbl *varcpy(struct tbl *);
+
/* compile and expand word */
char *
substitute(const char *cp, int f)
@@ -190,7 +192,8 @@ expand(char *cp, /* input word */
doblank = 0;
make_magic = 0;
word = (f&DOBLANK) ? IFS_WS : IFS_WORD;
- st_head.next = NULL;
+
+ memset(&st_head, 0, sizeof(st_head));
st = &st_head;
while (1) {
@@ -305,7 +308,7 @@ expand(char *cp, /* input word */
st->stype = stype;
st->base = Xsavepos(ds, dp);
st->f = f;
- st->var = x.var;
+ st->var = varcpy(x.var);
st->quote = quote;
/* skip qualifier(s) */
if (stype)
@@ -577,7 +580,7 @@ expand(char *cp, /* input word */
Xinit(ds, dp, 128, ATEMP);
}
if (c == 0)
- return;
+ goto done;
if (word != IFS_NWS)
word = ctype(c, C_IFSWS) ? IFS_WS : IFS_NWS;
} else {
@@ -682,6 +685,14 @@ expand(char *cp, /* input word */
word = IFS_WORD;
}
}
+
+done:
+ for (st = &st_head; st != NULL; st = st->next) {
+ if (st->var == NULL || (st->var->flag & RDONLY) == 0)
+ continue;
+
+ afree(st->var, ATEMP);
+ }
}
/*
@@ -1286,3 +1297,23 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
}
return;
}
+
+/*
+ * Copy the given variable if it's flagged as read-only.
+ * Such variables have static storage and only one can therefore be referenced
+ * at a time.
+ * This is necessary in order to allow variable expansion expressions to refer
+ * to multiple read-only variables.
+ */
+static struct tbl *
+varcpy(struct tbl *vp)
+{
+ struct tbl *cpy;
+
+ if (vp == NULL || (vp->flag & RDONLY) == 0)
+ return vp;
+
+ cpy = alloc(sizeof(struct tbl), ATEMP);
+ memcpy(cpy, vp, sizeof(struct tbl));
+ return cpy;
+}
diff --git a/ksh.1 b/ksh.1
@@ -1,8 +1,8 @@
-.\" $OpenBSD: ksh.1,v 1.200 2018/05/30 21:20:52 benno Exp $
+.\" $OpenBSD: ksh.1,v 1.201 2018/06/18 17:03:58 millert Exp $
.\"
.\" Public Domain
.\"
-.Dd $Mdocdate: May 30 2018 $
+.Dd $Mdocdate: June 18 2018 $
.Dt KSH 1
.Os
.Sh NAME
@@ -1717,6 +1717,10 @@ loops to store the value that is read from standard input.
The number of seconds since the shell started or, if the parameter has been
assigned an integer value, the number of seconds since the assignment plus the
value that was assigned.
+.It Ev TERM
+The user's terminal type.
+If set, it will be used to determine the escape sequence used to
+clear the screen.
.It Ev TMOUT
If set to a positive integer in an interactive shell, it specifies the maximum
number of seconds the shell will wait for input after printing the primary
@@ -4690,6 +4694,11 @@ Moves the cursor to the beginning of the edited input line.
Uppercase the first character in the next
.Ar n
words, leaving the cursor past the end of the last word.
+.It clear-screen:
+Clears the screen if the
+.Ev TERM
+parameter is set and the terminal supports clearing the screen, then
+reprints the prompt string and the current input line.
.It comment: ^[#
If the current line does not begin with a comment character, one is added at
the beginning of the line and the line is entered (as if return had been
diff --git a/mail.c b/mail.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mail.c,v 1.23 2018/04/09 17:53:36 tobias Exp $ */
+/* $OpenBSD: mail.c,v 1.24 2018/06/25 15:22:30 cheloha Exp $ */
/*
* Mailbox checking code by Robert J. Gibson, adapted for PD ksh by
@@ -6,6 +6,7 @@
*/
#include <sys/stat.h>
+#include <sys/time.h>
#include <string.h>
#include <time.h>
@@ -30,7 +31,7 @@ typedef struct mbox {
static mbox_t *mplist;
static mbox_t mbox;
-static time_t mlastchkd; /* when mail was last checked */
+static struct timespec mlastchkd; /* when mail was last checked */
static time_t mailcheck_interval;
static void munset(mbox_t *); /* free mlist and mval */
@@ -41,14 +42,18 @@ void
mcheck(void)
{
mbox_t *mbp;
- time_t now;
+ struct timespec elapsed, now;
struct tbl *vp;
struct stat stbuf;
+ static int first = 1;
- now = time(NULL);
- if (mlastchkd == 0)
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ if (first) {
mlastchkd = now;
- if (now - mlastchkd >= mailcheck_interval) {
+ first = 0;
+ }
+ timespecsub(&now, &mlastchkd, &elapsed);
+ if (elapsed.tv_sec >= mailcheck_interval) {
mlastchkd = now;
if (mplist)
diff --git a/table.h b/table.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: table.h,v 1.14 2018/04/09 17:53:36 tobias Exp $ */
+/* $OpenBSD: table.h,v 1.15 2018/06/18 17:03:58 millert Exp $ */
/* $From: table.h,v 1.3 1994/05/31 13:34:34 michael Exp $ */
@@ -170,6 +170,7 @@ extern const struct builtin shbuiltins [], kshbuiltins [];
#define V_TMOUT 16
#define V_TMPDIR 17
#define V_LINENO 18
+#define V_TERM 19
/* values for set_prompt() */
#define PS1 0 /* command */
diff --git a/var.c b/var.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: var.c,v 1.68 2018/04/13 18:18:36 cheloha Exp $ */
+/* $OpenBSD: var.c,v 1.70 2018/06/18 21:46:05 millert Exp $ */
#include <sys/stat.h>
#include <sys/time.h>
@@ -14,6 +14,19 @@
#include "sh.h"
+#if !defined(SMALL) && !defined(NO_CURSES)
+#ifdef HAVE_CURSES
+# include <term.h>
+# include <curses.h>
+#elif HAVE_NCURSES
+# include <term.h>
+# include <ncurses.h>
+#elif HAVE_NCURSESNCURSES
+# include <ncurses/term.h>
+# include <ncurses/ncurses.h>
+#endif
+#endif
+
/*
* Variables
*
@@ -111,12 +124,13 @@ initvar(void)
{ "SECONDS", V_SECONDS },
{ "TMOUT", V_TMOUT },
{ "LINENO", V_LINENO },
+ { "TERM", V_TERM },
{ NULL, 0 }
};
int i;
struct tbl *tp;
- ktinit(&specials, APERM, 32); /* must be 2^n (currently 17 specials) */
+ ktinit(&specials, APERM, 32); /* must be 2^n (currently 19 specials) */
for (i = 0; names[i].name; i++) {
tp = ktenter(&specials, names[i].name, hash(names[i].name));
tp->flag = DEFINED|ISSET;
@@ -1057,6 +1071,18 @@ setspec(struct tbl *vp)
user_lineno = (unsigned int) intval(vp) - current_lineno - 1;
vp->flag |= SPECIAL;
break;
+ case V_TERM:
+#if !defined(SMALL) && !defined(NO_CURSES)
+ {
+ int ret;
+
+ vp->flag &= ~SPECIAL;
+ if (setupterm(str_val(vp), shl_out->fd, &ret) == ERR)
+ del_curterm(cur_term);
+ vp->flag |= SPECIAL;
+ }
+#endif
+ break;
}
}