Merge remote-tracking branch 'mksh/master'

This commit is contained in:
KO Myung-Hun
2015-07-08 19:31:55 +09:00
14 changed files with 226 additions and 160 deletions

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.679 2015/05/01 16:08:26 tg Exp $' srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.681 2015/07/06 17:48:28 tg Exp $'
#- #-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014, 2015 # 2011, 2012, 2013, 2014, 2015
@ -2654,7 +2654,6 @@ MKSH_NOPROSPECTOFWORK disable jobs, co-processes, etc. (do not use)
MKSH_NOPWNAM skip PAM calls, for -static on glibc or Solaris MKSH_NOPWNAM skip PAM calls, for -static on glibc or Solaris
MKSH_NO_CMDLINE_EDITING disable command line editing code entirely MKSH_NO_CMDLINE_EDITING disable command line editing code entirely
MKSH_NO_DEPRECATED_WARNING omit warning when deprecated stuff is run MKSH_NO_DEPRECATED_WARNING omit warning when deprecated stuff is run
MKSH_NO_EXTERNAL_CAT omit hack to skip cat builtin when flags passed
MKSH_NO_LIMITS omit ulimit code MKSH_NO_LIMITS omit ulimit code
MKSH_NO_SIGSETJMP define if sigsetjmp is broken or not available MKSH_NO_SIGSETJMP define if sigsetjmp is broken or not available
MKSH_NO_SIGSUSPEND use sigprocmask+pause instead of sigsuspend MKSH_NO_SIGSUSPEND use sigprocmask+pause instead of sigsuspend

12
check.t
View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.694 2015/05/23 17:43:18 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.699 2015/07/06 17:48:29 tg Exp $
# -*- mode: sh -*- # -*- mode: sh -*-
#- #-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@ -30,7 +30,7 @@
# (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date # (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R51 2015/05/23 @(#)MIRBSD KSH R51 2015/07/06
description: description:
Check version of shell. Check version of shell.
stdin: stdin:
@ -39,7 +39,7 @@ name: KSH_VERSION
category: shell:legacy-no category: shell:legacy-no
--- ---
expected-stdout: expected-stdout:
@(#)LEGACY KSH R51 2015/05/23 @(#)LEGACY KSH R51 2015/07/06
description: description:
Check version of legacy shell. Check version of legacy shell.
stdin: stdin:
@ -3583,7 +3583,7 @@ expected-stdout:
a new line a new line
1 echo abc def 1 echo abc def
2 echo FOOBAR def 2 echo FOOBAR def
3 echo a new line echo a new line
expected-stderr-pattern: expected-stderr-pattern:
/^X*echo FOOBAR def\necho a new line\nX*$/ /^X*echo FOOBAR def\necho a new line\nX*$/
--- ---
@ -3665,7 +3665,7 @@ expected-stdout:
a new line a new line
1 echo abc def 1 echo abc def
2 echo FOOBAR def 2 echo FOOBAR def
3 echo a new line echo a new line
expected-stderr-pattern: expected-stderr-pattern:
/^X*13\n32\necho FOOBAR def\necho a new line\nX*$/ /^X*13\n32\necho FOOBAR def\necho a new line\nX*$/
--- ---
@ -8599,6 +8599,7 @@ description:
Ensure concatenating behaviour matches other shells Ensure concatenating behaviour matches other shells
stdin: stdin:
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
showargs 0 ""$@
x=; showargs 1 "$x"$@ x=; showargs 1 "$x"$@
set A; showargs 2 "${@:+}" set A; showargs 2 "${@:+}"
n() { echo "$#"; } n() { echo "$#"; }
@ -8618,6 +8619,7 @@ stdin:
n "$@" n "$@"
n "$@""$e" n "$@""$e"
expected-stdout: expected-stdout:
<0> <> .
<1> <> . <1> <> .
<2> <> . <2> <> .
2 2

View File

@ -1,5 +1,5 @@
# $Id$ # $Id$
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.97 2015/04/29 20:56:18 tg Exp $ # $MirOS: src/bin/mksh/dot.mkshrc,v 1.99 2015/07/05 19:02:16 tg Exp $
#- #-
# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, # Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014, 2015 # 2011, 2012, 2013, 2014, 2015
@ -67,8 +67,9 @@ else
\typeset -Uui16 -Z11 pos=0 \typeset -Uui16 -Z11 pos=0
\typeset -Uui16 -Z5 hv=2147483647 \typeset -Uui16 -Z5 hv=2147483647
\typeset dasc line i \typeset dasc line i
\set +U
\cat "$@" | { \set +U; if \read -arN -1 line; then \cat "$@" | if \read -arN -1 line; then
\typeset -i1 'line[*]' \typeset -i1 'line[*]'
i=0 i=0
while (( i < ${#line[*]} )); do while (( i < ${#line[*]} )); do
@ -95,7 +96,7 @@ else
\builtin print -n -- '- ' \builtin print -n -- '- '
done done
(( hv == 2147483647 )) || \builtin print -r -- "$dasc|" (( hv == 2147483647 )) || \builtin print -r -- "$dasc|"
fi; } fi
} }
fi fi
@ -112,7 +113,7 @@ function chpwd {
\: \:
} }
\chpwd . \chpwd .
function cd { cd() {
\builtin cd "$@" || \return $? \builtin cd "$@" || \return $?
\chpwd "$@" \chpwd "$@"
} }
@ -271,8 +272,8 @@ function smores {
# base64 encoder and decoder, RFC compliant, NUL safe, not EBCDIC safe # base64 encoder and decoder, RFC compliant, NUL safe, not EBCDIC safe
function Lb64decode { function Lb64decode {
[[ -o utf8-mode ]]; \typeset u=$? c s="$*" t
\set +U \set +U
\typeset c s="$*" t
[[ -n $s ]] || { s=$(\cat; \builtin print x); s=${s%x}; } [[ -n $s ]] || { s=$(\cat; \builtin print x); s=${s%x}; }
\typeset -i i=0 j=0 n=${#s} p=0 v x \typeset -i i=0 j=0 n=${#s} p=0 v x
\typeset -i16 o \typeset -i16 o
@ -303,14 +304,13 @@ function Lb64decode {
t= t=
done done
\builtin print -n $t \builtin print -n $t
(( u )) || \set -U
} }
\set -A Lb64encode_tbl -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \ \set -A Lb64encode_tbl -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + / a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /
function Lb64encode { function Lb64encode {
[[ -o utf8-mode ]]; \typeset u=$? c s t
\set +U \set +U
\typeset c s t
if (( $# )); then if (( $# )); then
\read -raN-1 s <<<"$*" \read -raN-1 s <<<"$*"
\unset s[${#s[*]}-1] \unset s[${#s[*]}-1]
@ -339,7 +339,6 @@ function Lb64encode {
t= t=
fi fi
done done
(( u )) || \set -U
} }
# Better Avalanche for the Jenkins Hash # Better Avalanche for the Jenkins Hash
@ -348,8 +347,8 @@ function Lbafh_init {
Lbafh_v=0 Lbafh_v=0
} }
function Lbafh_add { function Lbafh_add {
[[ -o utf8-mode ]]; \typeset u=$? s
\set +U \set +U
\typeset s
if (( $# )); then if (( $# )); then
\read -raN-1 s <<<"$*" \read -raN-1 s <<<"$*"
\unset s[${#s[*]}-1] \unset s[${#s[*]}-1]
@ -362,8 +361,6 @@ function Lbafh_add {
((# Lbafh_v = (Lbafh_v + s[i++] + 1) * 1025 )) ((# Lbafh_v = (Lbafh_v + s[i++] + 1) * 1025 ))
((# Lbafh_v ^= Lbafh_v >> 6 )) ((# Lbafh_v ^= Lbafh_v >> 6 ))
done done
(( u )) || \set -U
} }
function Lbafh_finish { function Lbafh_finish {
\typeset -Ui t \typeset -Ui t
@ -378,10 +375,11 @@ function Lbafh_finish {
# strip comments (and leading/trailing whitespace if IFS is set) from # strip comments (and leading/trailing whitespace if IFS is set) from
# any file(s) given as argument, or stdin if none, and spew to stdout # any file(s) given as argument, or stdin if none, and spew to stdout
function Lstripcom { function Lstripcom {
\cat "$@" | { \set -o noglob; while \read _line; do \set -o noglob
\cat "$@" | while \read _line; do
_line=${_line%%#*} _line=${_line%%#*}
[[ -n $_line ]] && \builtin print -r -- $_line [[ -n $_line ]] && \builtin print -r -- $_line
done; } done
} }
# give MidnightBSD's laffer1 a bit of csh feeling # give MidnightBSD's laffer1 a bit of csh feeling

8
edit.c
View File

@ -28,7 +28,7 @@
#ifndef MKSH_NO_CMDLINE_EDITING #ifndef MKSH_NO_CMDLINE_EDITING
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.286 2015/05/03 11:28:53 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.287 2015/07/05 19:37:13 tg Exp $");
/* /*
* in later versions we might use libtermcap for this, but since external * in later versions we might use libtermcap for this, but since external
@ -3101,7 +3101,7 @@ x_edit_line(int c MKSH_A_UNUSED)
} }
if (modified) { if (modified) {
*xep = '\0'; *xep = '\0';
histsave(&source->line, xbuf, true, true); histsave(&source->line, xbuf, HIST_STORE, true);
x_arg = 0; x_arg = 0;
} else } else
x_arg = source->line - (histptr - x_histp); x_arg = source->line - (histptr - x_histp);
@ -4390,8 +4390,8 @@ vi_cmd(int argcnt, const char *cmd)
return (-1); return (-1);
if (modified) { if (modified) {
es->cbuf[es->linelen] = '\0'; es->cbuf[es->linelen] = '\0';
histsave(&source->line, es->cbuf, true, histsave(&source->line, es->cbuf,
true); HIST_STORE, true);
} else } else
argcnt = source->line + 1 - argcnt = source->line + 1 -
(hlast - hnum); (hlast - hnum);

15
eval.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.169 2015/05/23 17:43:19 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.170 2015/07/06 17:45:33 tg Exp $");
/* /*
* string expansion * string expansion
@ -291,21 +291,14 @@ expand(
c = *sp++; c = *sp++;
break; break;
case OQUOTE: case OQUOTE:
switch (word) { if (word != IFS_WORD)
case IFS_QUOTE:
/* """something */
word = IFS_WORD;
break;
case IFS_WORD:
break;
default:
word = IFS_QUOTE; word = IFS_QUOTE;
break;
}
tilde_ok = 0; tilde_ok = 0;
quote = 1; quote = 1;
continue; continue;
case CQUOTE: case CQUOTE:
if (word == IFS_QUOTE)
word = IFS_WORD;
quote = st->quotew; quote = st->quotew;
continue; continue;
case COMSUB: case COMSUB:

46
exec.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.152 2015/04/29 18:32:43 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.155 2015/07/06 17:48:31 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL #ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL UNIXROOT "/bin/sh" #define MKSH_DEFAULT_EXECSHELL UNIXROOT "/bin/sh"
@ -41,8 +41,8 @@ static const char *dbteste_getopnd(Test_env *, Test_op, bool);
static void dbteste_error(Test_env *, int, const char *); static void dbteste_error(Test_env *, int, const char *);
static int search_access(const char *, int); static int search_access(const char *, int);
/* XXX: horrible kludge to fit within the framework */ /* XXX: horrible kludge to fit within the framework */
static char *plain_fmt_entry(char *, size_t, unsigned int, const void *); static void plain_fmt_entry(char *, size_t, unsigned int, const void *);
static char *select_fmt_entry(char *, size_t, unsigned int, const void *); static void select_fmt_entry(char *, size_t, unsigned int, const void *);
/* /*
* execute command tree * execute command tree
@ -551,6 +551,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
} }
if ((tp = findcom(cp, FC_BI)) == NULL) if ((tp = findcom(cp, FC_BI)) == NULL)
errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin"); errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin");
if (tp->type == CSHELL && tp->val.f == c_cat)
break;
continue; continue;
} else if (tp->val.f == c_exec) { } else if (tp->val.f == c_exec) {
if (ap[1] == NULL) if (ap[1] == NULL)
@ -607,25 +609,19 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
subst_exstat = 0; subst_exstat = 0;
break; break;
} }
#ifndef MKSH_NO_EXTERNAL_CAT
} else if (tp->val.f == c_cat) { } else if (tp->val.f == c_cat) {
/* /* if we have any flags, do not use the builtin */
* if we have any flags, do not use the builtin
* in theory, we could allow -u, but that would
* mean to use ksh_getopt here and possibly ad-
* ded complexity and more code and isn't worth
* additional hassle (and the builtin must call
* ksh_getopt already but can't come back here)
*/
if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' && if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' &&
/* argument, begins with -, is not - or -- */ /* argument, begins with -, is not - or -- */
(ap[1][1] != '-' || ap[1][2] != '\0')) (ap[1][1] != '-' || ap[1][2] != '\0')) {
/* don't look for builtins or functions */ struct tbl *ext_cat;
fcflags = FC_PATH;
else ext_cat = findcom(Tcat, FC_PATH | FC_FUNC);
/* go on, use the builtin */ if (ext_cat && (ext_cat->type != CTALIAS ||
(ext_cat->flag & ISSET)))
tp = ext_cat;
}
break; break;
#endif
} else if (tp->val.f == c_trap) { } else if (tp->val.f == c_trap) {
t->u.evalflags &= ~DOTCOMEXEC; t->u.evalflags &= ~DOTCOMEXEC;
break; break;
@ -705,6 +701,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
/* shell built-in */ /* shell built-in */
case CSHELL: case CSHELL:
do_call_builtin:
rv = call_builtin(tp, (const char **)ap, null, resetspec); rv = call_builtin(tp, (const char **)ap, null, resetspec);
if (resetspec && tp->val.f == c_shift) { if (resetspec && tp->val.f == c_shift) {
l_expand->argc = l_assign->argc; l_expand->argc = l_assign->argc;
@ -729,6 +726,11 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
break; break;
} }
if (include(tp->u.fpath, 0, NULL, false) < 0) { if (include(tp->u.fpath, 0, NULL, false) < 0) {
if (!strcmp(cp, Tcat)) {
no_cat_in_FPATH:
tp = findcom(Tcat, FC_BI);
goto do_call_builtin;
}
warningf(true, "%s: %s %s %s: %s", cp, warningf(true, "%s: %s %s %s: %s", cp,
"can't open", "function definition file", "can't open", "function definition file",
tp->u.fpath, cstrerror(errno)); tp->u.fpath, cstrerror(errno));
@ -737,6 +739,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
} }
if (!(ftp = findfunc(cp, hash(cp), false)) || if (!(ftp = findfunc(cp, hash(cp), false)) ||
!(ftp->flag & ISSET)) { !(ftp->flag & ISSET)) {
if (!strcmp(cp, Tcat))
goto no_cat_in_FPATH;
warningf(true, "%s: %s %s", cp, warningf(true, "%s: %s %s", cp,
"function not defined by", tp->u.fpath); "function not defined by", tp->u.fpath);
rv = 127; rv = 127;
@ -1657,7 +1661,7 @@ struct select_menu_info {
}; };
/* format a single select menu item */ /* format a single select menu item */
static char * static void
select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg) select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
{ {
const struct select_menu_info *smi = const struct select_menu_info *smi =
@ -1665,7 +1669,6 @@ select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
shf_snprintf(buf, buflen, "%*u) %s", shf_snprintf(buf, buflen, "%*u) %s",
smi->num_width, i + 1, smi->args[i]); smi->num_width, i + 1, smi->args[i]);
return (buf);
} }
/* /*
@ -1711,11 +1714,10 @@ pr_menu(const char * const *ap)
true); true);
} }
static char * static void
plain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg) plain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
{ {
strlcpy(buf, ((const char * const *)arg)[i], buflen); strlcpy(buf, ((const char * const *)arg)[i], buflen);
return (buf);
} }
void void

23
funcs.c
View File

@ -38,7 +38,7 @@
#endif #endif
#endif #endif
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.272 2015/05/01 23:16:29 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.277 2015/07/06 17:48:32 tg Exp $");
#if HAVE_KILLPG #if HAVE_KILLPG
/* /*
@ -99,7 +99,7 @@ const struct builtin mkshbuiltins[] = {
{Talias, c_alias}, {Talias, c_alias},
{"*=break", c_brkcont}, {"*=break", c_brkcont},
{Tgbuiltin, c_builtin}, {Tgbuiltin, c_builtin},
{"cat", c_cat}, {Tcat, c_cat},
{"cd", c_cd}, {"cd", c_cd},
/* dash compatibility hack */ /* dash compatibility hack */
{"chdir", c_cd}, {"chdir", c_cd},
@ -227,7 +227,7 @@ static int test_primary(Test_env *, bool);
static Test_op ptest_isa(Test_env *, Test_meta); static Test_op ptest_isa(Test_env *, Test_meta);
static const char *ptest_getopnd(Test_env *, Test_op, bool); static const char *ptest_getopnd(Test_env *, Test_op, bool);
static void ptest_error(Test_env *, int, const char *); static void ptest_error(Test_env *, int, const char *);
static char *kill_fmt_entry(char *, size_t, unsigned int, const void *); static void kill_fmt_entry(char *, size_t, unsigned int, const void *);
static void p_time(struct shf *, bool, long, int, int, static void p_time(struct shf *, bool, long, int, int,
const char *, const char *); const char *, const char *);
@ -445,7 +445,7 @@ c_print(const char **wp)
if (flags & PO_HIST) { if (flags & PO_HIST) {
Xput(xs, xp, '\0'); Xput(xs, xp, '\0');
histsave(&source->line, Xstring(xs, xp), true, false); histsave(&source->line, Xstring(xs, xp), HIST_STORE, false);
Xfree(xs, xp); Xfree(xs, xp);
} else { } else {
int len = Xlength(xs, xp); int len = Xlength(xs, xp);
@ -541,7 +541,7 @@ c_whence(const char **wp)
uint32_t h = 0; uint32_t h = 0;
tp = NULL; tp = NULL;
if ((iam_whence || vflag) && !pflag) if (!pflag)
tp = ktsearch(&keywords, id, h = hash(id)); tp = ktsearch(&keywords, id, h = hash(id));
if (!tp && !pflag) { if (!tp && !pflag) {
tp = ktsearch(&aliases, id, h ? h : hash(id)); tp = ktsearch(&aliases, id, h ? h : hash(id));
@ -1310,7 +1310,7 @@ c_fgbg(const char **wp)
#endif #endif
/* format a single kill item */ /* format a single kill item */
static char * static void
kill_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg) kill_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
{ {
const struct kill_info *ki = (const struct kill_info *)arg; const struct kill_info *ki = (const struct kill_info *)arg;
@ -1320,7 +1320,6 @@ kill_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
ki->num_width, i, ki->num_width, i,
ki->name_width, sigtraps[i].name, ki->name_width, sigtraps[i].name,
sigtraps[i].mess); sigtraps[i].mess);
return (buf);
} }
int int
@ -1967,8 +1966,9 @@ c_read(const char **wp)
break; break;
case 0: case 0:
/* timeout expired for this call */ /* timeout expired for this call */
rv = 1; bytesread = 0;
goto c_read_out; /* fake EOF read; all cases return 1 */
goto c_read_didread;
default: default:
bi_errorf("%s: %s", Tselect, cstrerror(errno)); bi_errorf("%s: %s", Tselect, cstrerror(errno));
rv = 2; rv = 2;
@ -1993,6 +1993,7 @@ c_read(const char **wp)
goto c_read_readloop; goto c_read_readloop;
} }
c_read_didread:
switch (readmode) { switch (readmode) {
case READALL: case READALL:
if (bytesread == 0) { if (bytesread == 0) {
@ -2015,7 +2016,7 @@ c_read(const char **wp)
if (bytesread == 0) { if (bytesread == 0) {
/* end of file reached */ /* end of file reached */
rv = 1; rv = 1;
xp = Xstring(xs, xp); /* may be partial read: $? = 1, but content */
goto c_read_readdone; goto c_read_readdone;
} }
xp += bytesread; xp += bytesread;
@ -2078,7 +2079,7 @@ c_read(const char **wp)
} }
if (savehist) if (savehist)
histsave(&source->line, Xstring(xs, xp), true, false); histsave(&source->line, Xstring(xs, xp), HIST_STORE, false);
ccp = cp = Xclose(xs, xp); ccp = cp = Xclose(xs, xp);
expanding = false; expanding = false;

103
histrap.c
View File

@ -27,7 +27,7 @@
#include <sys/file.h> #include <sys/file.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.143 2015/04/29 20:44:35 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.148 2015/07/05 19:53:45 tg Exp $");
Trap sigtraps[ksh_NSIG + 1]; Trap sigtraps[ksh_NSIG + 1];
static struct sigaction Sigact_ign; static struct sigaction Sigact_ign;
@ -38,7 +38,7 @@ static int writehistline(int, int, const char *);
static void writehistfile(int, const char *); static void writehistfile(int, const char *);
#endif #endif
static int hist_execute(char *); static int hist_execute(char *, Area *);
static char **hist_get(const char *, bool, bool); static char **hist_get(const char *, bool, bool);
static char **hist_get_oldest(void); static char **hist_get_oldest(void);
@ -84,6 +84,9 @@ static const char TFCEDIT_dollaru[] = "${FCEDIT:-/bin/ed} $_";
/* maximum considered size of persistent history file */ /* maximum considered size of persistent history file */
#define MKSH_MAXHISTFSIZE ((off_t)1048576 * 96) #define MKSH_MAXHISTFSIZE ((off_t)1048576 * 96)
/* hidden option */
#define HIST_DISCARD 5
int int
c_fc(const char **wp) c_fc(const char **wp)
{ {
@ -223,7 +226,7 @@ c_fc(const char **wp)
xp += len; xp += len;
line = Xclose(xs, xp); line = Xclose(xs, xp);
} }
return (hist_execute(line)); return (hist_execute(line, ATEMP));
} }
if (editor && (lflag || nflag)) { if (editor && (lflag || nflag)) {
@ -360,18 +363,17 @@ c_fc(const char **wp)
shf_close(shf); shf_close(shf);
*xp = '\0'; *xp = '\0';
strip_nuls(Xstring(xs, xp), Xlength(xs, xp)); strip_nuls(Xstring(xs, xp), Xlength(xs, xp));
return (hist_execute(Xstring(xs, xp))); return (hist_execute(Xstring(xs, xp), hist_source->areap));
} }
} }
/* Save cmd in history, execute cmd (cmd gets trashed) */ /* save cmd in history, execute cmd (cmd gets afreed) */
static int static int
hist_execute(char *cmd) hist_execute(char *cmd, Area *areap)
{ {
static int last_line = -1; static int last_line = -1;
Source *sold; Source *sold;
int ret; int ret;
char *p, *q;
/* Back up over last histsave */ /* Back up over last histsave */
if (histptr >= history && last_line != hist_source->line) { if (histptr >= history && last_line != hist_source->line) {
@ -381,22 +383,12 @@ hist_execute(char *cmd)
last_line = hist_source->line; last_line = hist_source->line;
} }
for (p = cmd; p; p = q) { histsave(&hist_source->line, cmd, HIST_STORE, true);
if ((q = strchr(p, '\n'))) { /* now *histptr == cmd without all trailing newlines */
/* kill the newline */ afree(cmd, areap);
*q++ = '\0'; cmd = *histptr;
if (!*q) /* pdksh says POSIX doesnt say this is done, testsuite needs it */
/* ignore trailing newline */ shellf("%s\n", cmd);
q = NULL;
}
histsave(&hist_source->line, p, true, true);
/* POSIX doesn't say this is done... */
shellf("%s\n", p);
if (q)
/* restore \n (trailing \n not restored) */
q[-1] = '\n';
}
/*- /*-
* Commands are executed here instead of pushing them onto the * Commands are executed here instead of pushing them onto the
@ -578,6 +570,7 @@ sethistfile(const char *name)
afree(hname, APERM); afree(hname, APERM);
hname = NULL; hname = NULL;
/* let's reset the history */ /* let's reset the history */
histsave(NULL, NULL, HIST_DISCARD, true);
histptr = history - 1; histptr = history - 1;
hist_source->line = 0; hist_source->line = 0;
} }
@ -612,6 +605,8 @@ histsync(void)
{ {
bool changed = false; bool changed = false;
/* called by histsave(), may not HIST_DISCARD, caller should flush */
if (histfd != -1) { if (histfd != -1) {
int lno = hist_source->line; int lno = hist_source->line;
@ -631,15 +626,38 @@ histsync(void)
* save command in history * save command in history
*/ */
void void
histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups) histsave(int *lnp, const char *cmd, int svmode, bool ignoredups)
{ {
char **hp; static char *enqueued = NULL;
char *c, *cp; char **hp, *c;
const char *ccp;
strdupx(c, cmd, APERM); if (svmode == HIST_DISCARD) {
if ((cp = strchr(c, '\n')) != NULL) afree(enqueued, APERM);
*cp = '\0'; enqueued = NULL;
return;
}
if (svmode == HIST_APPEND) {
if (!enqueued)
svmode = HIST_STORE;
} else if (enqueued) {
c = enqueued;
enqueued = NULL;
--*lnp;
histsave(lnp, c, HIST_STORE, true);
afree(c, APERM);
}
if (svmode == HIST_FLUSH)
return;
ccp = cmd + strlen(cmd);
while (ccp > cmd && ccp[-1] == '\n')
--ccp;
strndupx(c, cmd, ccp - cmd, APERM);
if (svmode != HIST_APPEND) {
if (ignoredups && !strcmp(c, *histptr) if (ignoredups && !strcmp(c, *histptr)
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
&& !histsync() && !histsync()
@ -649,12 +667,33 @@ histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups)
return; return;
} }
++*lnp; ++*lnp;
}
#if HAVE_PERSISTENT_HISTORY #if HAVE_PERSISTENT_HISTORY
if (dowrite && histfd != -1) if (svmode == HIST_STORE && histfd != -1)
writehistfile(*lnp, c); writehistfile(*lnp, c);
#endif #endif
if (svmode == HIST_QUEUE || svmode == HIST_APPEND) {
size_t nenq, ncmd;
if (!enqueued) {
if (*c)
enqueued = c;
else
afree(c, APERM);
return;
}
nenq = strlen(enqueued);
ncmd = strlen(c);
enqueued = aresize(enqueued, nenq + 1 + ncmd + 1, APERM);
enqueued[nenq] = '\n';
memcpy(enqueued + nenq + 1, c, ncmd + 1);
afree(c, APERM);
return;
}
hp = histptr; hp = histptr;
if (++hp >= history + histsize) { if (++hp >= history + histsize) {
@ -707,6 +746,8 @@ hist_init(Source *s)
enum { hist_init_first, hist_init_retry, hist_init_restore } hs; enum { hist_init_first, hist_init_retry, hist_init_restore } hs;
#endif #endif
histsave(NULL, NULL, HIST_DISCARD, true);
if (Flag(FTALKING) == 0) if (Flag(FTALKING) == 0)
return; return;
@ -864,7 +905,7 @@ histload(Source *s, unsigned char *base, size_t bytes)
} }
} else { } else {
s->line = lno--; s->line = lno--;
histsave(&lno, (char *)(base + 4), false, false); histsave(&lno, (char *)(base + 4), HIST_NOTE, false);
} }
/* advance base pointer past NUL */ /* advance base pointer past NUL */
bytes -= ++cp - base; bytes -= ++cp - base;

22
lex.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.201 2015/04/29 20:07:33 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.204 2015/07/05 19:53:46 tg Exp $");
/* /*
* states while lexing word * states while lexing word
@ -1461,16 +1461,23 @@ getsc_line(Source *s)
if (s->type == SFILE) if (s->type == SFILE)
shf_fdclose(s->u.shf); shf_fdclose(s->u.shf);
s->str = NULL; s->str = NULL;
} else if (interactive && *s->str && } else if (interactive && *s->str) {
(cur_prompt != PS1 || !ctype(*s->str, C_IFS | C_IFSWS))) { if (cur_prompt != PS1)
histsave(&s->line, s->str, true, true); histsave(&s->line, s->str, HIST_APPEND, true);
else if (!ctype(*s->str, C_IFS | C_IFSWS))
histsave(&s->line, s->str, HIST_QUEUE, true);
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
else
goto check_for_sole_return;
} else if (interactive && cur_prompt == PS1) { } else if (interactive && cur_prompt == PS1) {
check_for_sole_return:
cp = Xstring(s->xs, xp); cp = Xstring(s->xs, xp);
while (*cp && ctype(*cp, C_IFSWS)) while (*cp && ctype(*cp, C_IFSWS))
++cp; ++cp;
if (!*cp) if (!*cp) {
histsave(&s->line, NULL, HIST_FLUSH, true);
histsync(); histsync();
}
#endif #endif
} }
if (interactive) if (interactive)
@ -1495,6 +1502,7 @@ set_prompt(int to, Source *s)
struct shf *shf; struct shf *shf;
char * volatile ps1; char * volatile ps1;
Area *saved_atemp; Area *saved_atemp;
int saved_lineno;
ps1 = str_val(global("PS1")); ps1 = str_val(global("PS1"));
shf = shf_sopen(NULL, strlen(ps1) * 2, shf = shf_sopen(NULL, strlen(ps1) * 2,
@ -1506,6 +1514,9 @@ set_prompt(int to, Source *s)
shf_fprintf(shf, "%lu", s ? shf_fprintf(shf, "%lu", s ?
(unsigned long)s->line + 1 : 0UL); (unsigned long)s->line + 1 : 0UL);
ps1 = shf_sclose(shf); ps1 = shf_sclose(shf);
saved_lineno = current_lineno;
if (s)
current_lineno = s->line + 1;
saved_atemp = ATEMP; saved_atemp = ATEMP;
newenv(E_ERRH); newenv(E_ERRH);
if (kshsetjmp(e->jbuf)) { if (kshsetjmp(e->jbuf)) {
@ -1521,6 +1532,7 @@ set_prompt(int to, Source *s)
char *cp = substitute(ps1, 0); char *cp = substitute(ps1, 0);
strdupx(prompt, cp, saved_atemp); strdupx(prompt, cp, saved_atemp);
} }
current_lineno = saved_lineno;
quitenv(NULL); quitenv(NULL);
} }
break; break;

6
main.c
View File

@ -34,7 +34,7 @@
#include <locale.h> #include <locale.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.293 2015/04/29 20:07:33 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/main.c,v 1.295 2015/07/06 17:48:34 tg Exp $");
extern char **environ; extern char **environ;
@ -87,7 +87,7 @@ static const char *initcoms[] = {
NULL, NULL,
/* this is what AT&T ksh seems to track, with the addition of emacs */ /* this is what AT&T ksh seems to track, with the addition of emacs */
Talias, "-tU", Talias, "-tU",
"cat", "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls", Tcat, "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls",
"make", "mv", "pr", "rm", "sed", "sh", "vi", "who", NULL, "make", "mv", "pr", "rm", "sed", "sh", "vi", "who", NULL,
NULL NULL
}; };
@ -825,6 +825,8 @@ shell(Source * volatile s, volatile bool toplevel)
set_prompt(PS1, s); set_prompt(PS1, s);
} }
t = compile(s, sfirst); t = compile(s, sfirst);
if (interactive)
histsave(&s->line, NULL, HIST_FLUSH, true);
sfirst = false; sfirst = false;
if (!t) if (!t)
goto source_no_tree; goto source_no_tree;

View File

@ -1,6 +1,6 @@
/*- /*-
* Copyright © 2011, 2014 * Copyright © 2011, 2014, 2015
* Thorsten Glaser <tg@mirbsd.org> * Thorsten “mirabilos” Glaser <tg@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
* are retained or reproduced in an accompanying document, permission * are retained or reproduced in an accompanying document, permission
@ -44,7 +44,7 @@
#include <sys/types.h> #include <sys/types.h>
__RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.4 2015/05/30 22:14:06 tg Exp $");
/*- /*-
* BAFH itself is defined by the following primitives: * BAFH itself is defined by the following primitives:
@ -61,7 +61,8 @@ __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
* the context is (still) zero, adding a NUL byte is not ignored. * the context is (still) zero, adding a NUL byte is not ignored.
* *
* • BAFHror(eax,cl) evaluates to the unsigned 32-bit integer “eax”, * • BAFHror(eax,cl) evaluates to the unsigned 32-bit integer “eax”,
* rotated right by “cl” ∈ [0;31]; no casting, be careful! * rotated right by “cl” ∈ [0; 31] (no casting, be careful!) where
* “eax” must be uint32_t and “cl” an in-range integer.
* *
* • BAFHFinish(ctx) avalanches the context around so every sub-byte * • BAFHFinish(ctx) avalanches the context around so every sub-byte
* depends on all input octets; afterwards, the context variables * depends on all input octets; afterwards, the context variables
@ -88,7 +89,7 @@ __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
* • BAFHHostStr(ctx,buf) does the same for C strings. * • BAFHHostStr(ctx,buf) does the same for C strings.
* *
* All macros may use ctx multiple times in their expansion, but all * All macros may use ctx multiple times in their expansion, but all
* other arguments are always evaluated at most once. * other arguments are always evaluated at most once except BAFHror.
* *
* To stay portable, never use the BAFHHost*() macros (these are for * To stay portable, never use the BAFHHost*() macros (these are for
* host-local entropy shuffling), and encode numbers using ULEB128. * host-local entropy shuffling), and encode numbers using ULEB128.
@ -206,6 +207,7 @@ __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
} BAFHHost_v; \ } BAFHHost_v; \
\ \
BAFHUpdate_s = (const void *)(s); \ BAFHUpdate_s = (const void *)(s); \
BAFHHost_v.as_u32 = 0; \
if ((BAFHHost_v.as_u8[0] = *BAFHUpdate_s) != 0) \ if ((BAFHHost_v.as_u8[0] = *BAFHUpdate_s) != 0) \
++BAFHUpdate_s; \ ++BAFHUpdate_s; \
if ((BAFHHost_v.as_u8[1] = *BAFHUpdate_s) != 0) \ if ((BAFHHost_v.as_u8[1] = *BAFHUpdate_s) != 0) \

45
misc.c
View File

@ -30,7 +30,7 @@
#include <grp.h> #include <grp.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.232 2015/05/01 23:16:30 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.236 2015/07/05 14:58:33 tg Exp $");
#define KSH_CHVT_FLAG #define KSH_CHVT_FLAG
#ifdef MKSH_SMALL #ifdef MKSH_SMALL
@ -173,11 +173,11 @@ struct options_info {
int opts[NELEM(options)]; int opts[NELEM(options)];
}; };
static char *options_fmt_entry(char *, size_t, unsigned int, const void *); static void options_fmt_entry(char *, size_t, unsigned int, const void *);
static void printoptions(bool); static void printoptions(bool);
/* format a single select menu item */ /* format a single select menu item */
static char * static void
options_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg) options_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
{ {
const struct options_info *oi = (const struct options_info *)arg; const struct options_info *oi = (const struct options_info *)arg;
@ -185,7 +185,6 @@ options_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
shf_snprintf(buf, buflen, "%-*s %s", shf_snprintf(buf, buflen, "%-*s %s",
oi->opt_width, OFN(oi->opts[i]), oi->opt_width, OFN(oi->opts[i]),
Flag(oi->opts[i]) ? "on" : "off"); Flag(oi->opts[i]) ? "on" : "off");
return (buf);
} }
static void static void
@ -1227,7 +1226,7 @@ print_value_quoted(struct shf *shf, const char *s)
*/ */
void void
print_columns(struct shf *shf, unsigned int n, print_columns(struct shf *shf, unsigned int n,
char *(*func)(char *, size_t, unsigned int, const void *), void (*func)(char *, size_t, unsigned int, const void *),
const void *arg, size_t max_oct, size_t max_colz, bool prefcol) const void *arg, size_t max_oct, size_t max_colz, bool prefcol)
{ {
unsigned int i, r, c, rows, cols, nspace, max_col; unsigned int i, r, c, rows, cols, nspace, max_col;
@ -1256,17 +1255,20 @@ print_columns(struct shf *shf, unsigned int n,
str = alloc(max_oct, ATEMP); str = alloc(max_oct, ATEMP);
/* /*
* We use (max_col + 1) to consider the space separator. * We use (max_col + 2) to consider the separator space.
* Note that no space is printed after the last column * Note that no spaces are printed after the last column
* to avoid problems with terminals that have auto-wrap. * to avoid problems with terminals that have auto-wrap,
* but we need to also take this into account in x_cols.
*/ */
cols = x_cols / (max_col + 1); cols = (x_cols + 1) / (max_col + 2);
/* if we can only print one column anyway, skip the goo */ /* if we can only print one column anyway, skip the goo */
if (cols < 2) { if (cols < 2) {
for (i = 0; i < n; ++i) for (i = 0; i < n; ++i) {
shf_fprintf(shf, "%s\n", (*func)(str, max_oct, i, arg);
(*func)(str, max_oct, i, arg)); shf_puts(str, shf);
shf_putc('\n', shf);
}
goto out; goto out;
} }
@ -1277,18 +1279,19 @@ print_columns(struct shf *shf, unsigned int n,
} }
nspace = (x_cols - max_col * cols) / cols; nspace = (x_cols - max_col * cols) / cols;
if (nspace < 2)
nspace = 2;
max_col = -max_col; max_col = -max_col;
if (nspace <= 0)
nspace = 1;
for (r = 0; r < rows; r++) { for (r = 0; r < rows; r++) {
for (c = 0; c < cols; c++) { for (c = 0; c < cols; c++) {
i = c * rows + r; if ((i = c * rows + r) >= n)
if (i < n) { break;
shf_fprintf(shf, "%*s", max_col, (*func)(str, max_oct, i, arg);
(*func)(str, max_oct, i, arg)); if (i + rows >= n)
if (c + 1 < cols) shf_puts(str, shf);
shf_fprintf(shf, "%*s", nspace, null); else
} shf_fprintf(shf, "%*s%*s",
max_col, str, nspace, null);
} }
shf_putchar('\n', shf); shf_putchar('\n', shf);
} }

33
mksh.1
View File

@ -1,5 +1,5 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.367 2015/05/23 17:43:20 tg Exp $ .\" $MirOS: src/bin/mksh/mksh.1,v 1.373 2015/07/06 17:48:35 tg Exp $
.\" $OpenBSD: ksh.1,v 1.159 2015/03/25 12:10:52 jca Exp $ .\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $
.\"- .\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
.\" 2010, 2011, 2012, 2013, 2014, 2015 .\" 2010, 2011, 2012, 2013, 2014, 2015
@ -74,7 +74,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to .\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always. .\" use our own definition. And .Dd must come *first*, always.
.\" .\"
.Dd $Mdocdate: May 23 2015 $ .Dd $Mdocdate: July 6 2015 $
.\" .\"
.\" Check which macro package we use, and do other -mdoc setup. .\" Check which macro package we use, and do other -mdoc setup.
.\" .\"
@ -476,7 +476,7 @@ and
.Ql } .Ql }
delimit delimit
.Xr csh 1 Ns -style .Xr csh 1 Ns -style
alterations (see alternations (see
.Sx Brace expansion .Sx Brace expansion
below); below);
and finally, and finally,
@ -1859,7 +1859,8 @@ below for more information.
.It Ev HISTFILE .It Ev HISTFILE
The name of the file used to store command history. The name of the file used to store command history.
When assigned to or unset, the file is opened, history is truncated When assigned to or unset, the file is opened, history is truncated
then loaded from the file; subsequent new lines are appended. then loaded from the file; subsequent new commands (possibly consisting
of several lines) are appended once they successfully compiled.
Also, several invocations of the shell will share history if their Also, several invocations of the shell will share history if their
.Ev HISTFILE .Ev HISTFILE
parameters all point to the same file. parameters all point to the same file.
@ -2145,7 +2146,7 @@ The
.Ic alias Fl d .Ic alias Fl d
command may be used to list, change, and add to this cache (e.g.\& command may be used to list, change, and add to this cache (e.g.\&
.Ic alias \-d fac=/usr/local/facilities; cd \*(TIfac/bin ) . .Ic alias \-d fac=/usr/local/facilities; cd \*(TIfac/bin ) .
.Ss Brace expansion (alteration) .Ss Brace expansion (alternation)
Brace expressions take the following form: Brace expressions take the following form:
.Bd -unfilled -offset indent .Bd -unfilled -offset indent
.Sm off .Sm off
@ -3160,15 +3161,13 @@ If a
is a single dash is a single dash
.Pq Sq - .Pq Sq -
or absent, read from standard input. or absent, read from standard input.
Unless compiled with
.Dv MKSH_NO_EXTERNAL_CAT ,
if any options are given, an external
.Xr cat 1
utility is invoked instead if called from the shell.
For direct builtin calls, the For direct builtin calls, the
.Tn POSIX .Tn POSIX
.Fl u .Fl u
option is supported as a no-op. option is supported as a no-op.
For calls from shell, if any options are given, an external
.Xr cat 1
utility is preferred over the builtin.
.Pp .Pp
.It Xo .It Xo
.Ic cd .Ic cd
@ -3296,9 +3295,9 @@ option is given, instead of executing
.Ar cmd , .Ar cmd ,
information about what would be executed is given (and the same is done for information about what would be executed is given (and the same is done for
.Ar arg ... ) . .Ar arg ... ) .
For special and regular built-in commands and functions, their names are simply For builtins, functions and keywords, their names are simply printed;
printed; for aliases, a command that defines them is printed; and for commands for aliases, a command that defines them is printed;
found by searching the for utilities found by searching the
.Ev PATH .Ev PATH
parameter, the full path of the command is printed. parameter, the full path of the command is printed.
If no command is found If no command is found
@ -3832,7 +3831,8 @@ if empty, instead of the ASCII newline character as input line delimiter.
.It Fl N Ar z .It Fl N Ar z
Instead of reading till end-of-line, read exactly Instead of reading till end-of-line, read exactly
.Ar z .Ar z
bytes; less if EOF or a timeout occurs. bytes.
If EOF or a timeout occurs, a partial read is returned with exit status 1.
.It Fl n Ar z .It Fl n Ar z
Instead of reading till end-of-line, read up to Instead of reading till end-of-line, read up to
.Ar z .Ar z
@ -3851,6 +3851,9 @@ The argument must immediately follow the option character.
Interrupt reading after Interrupt reading after
.Ar n .Ar n
seconds (specified as positive decimal value with an optional fractional part). seconds (specified as positive decimal value with an optional fractional part).
The exit status of
.Nm read
is 1 if the timeout occurred, but partial reads may still be returned.
.It Fl r .It Fl r
Normally, the ASCII backslash character escapes the special Normally, the ASCII backslash character escapes the special
meaning of the following character and is stripped from the input; meaning of the following character and is stripped from the input;

16
sh.h
View File

@ -172,9 +172,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.730 2015/05/23 17:43:22 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.734 2015/07/06 17:48:37 tg Exp $");
#endif #endif
#define MKSH_VERSION "R51 2015/05/23" #define MKSH_VERSION "R51 2015/07/06"
/* arithmetic types: C implementation */ /* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES #if !HAVE_CAN_INTTYPES
@ -861,6 +861,7 @@ EXTERN const char T_typeset[] E_INIT("=typeset");
#define Ttypeset (T_typeset + 1) /* "typeset" */ #define Ttypeset (T_typeset + 1) /* "typeset" */
EXTERN const char Talias[] E_INIT("alias"); EXTERN const char Talias[] E_INIT("alias");
EXTERN const char Tunalias[] E_INIT("unalias"); EXTERN const char Tunalias[] E_INIT("unalias");
EXTERN const char Tcat[] E_INIT("cat");
EXTERN const char Tsgset[] E_INIT("*=set"); EXTERN const char Tsgset[] E_INIT("*=set");
#define Tset (Tsgset + 2) /* "set" */ #define Tset (Tsgset + 2) /* "set" */
EXTERN const char Tsgexport[] E_INIT("*=export"); EXTERN const char Tsgexport[] E_INIT("*=export");
@ -1665,6 +1666,13 @@ EXTERN char **history; /* saved commands */
EXTERN char **histptr; /* last history item */ EXTERN char **histptr; /* last history item */
EXTERN mksh_ari_t histsize; /* history size */ EXTERN mksh_ari_t histsize; /* history size */
/* flags to histsave */
#define HIST_FLUSH 0
#define HIST_QUEUE 1
#define HIST_APPEND 2
#define HIST_STORE 3
#define HIST_NOTE 4
/* user and system time of last j_waitjed job */ /* user and system time of last j_waitjed job */
EXTERN struct timeval j_usrtime, j_systime; EXTERN struct timeval j_usrtime, j_systime;
@ -1791,7 +1799,7 @@ void hist_init(Source *);
#if HAVE_PERSISTENT_HISTORY #if HAVE_PERSISTENT_HISTORY
void hist_finish(void); void hist_finish(void);
#endif #endif
void histsave(int *, const char *, bool, bool); void histsave(int *, const char *, int, bool);
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
bool histsync(void); bool histsync(void);
#endif #endif
@ -1934,7 +1942,7 @@ int ksh_getopt(const char **, Getopt *, const char *);
void print_value_quoted(struct shf *, const char *); void print_value_quoted(struct shf *, const char *);
char *quote_value(const char *); char *quote_value(const char *);
void print_columns(struct shf *, unsigned int, void print_columns(struct shf *, unsigned int,
char *(*)(char *, size_t, unsigned int, const void *), void (*)(char *, size_t, unsigned int, const void *),
const void *, size_t, size_t, bool); const void *, size_t, size_t, bool);
void strip_nuls(char *, size_t) void strip_nuls(char *, size_t)
MKSH_A_BOUNDED(__string__, 1, 2); MKSH_A_BOUNDED(__string__, 1, 2);