collective R54 release preparation multi-merger:

install both lksh and mksh manpages from Build.sh (Martijn Dekker)
spelling fixes (Larry Hynes)
manpage improvements (Martijn Dekker)
initial port to Harvey-OS’ APEX (Ronald G. Minnich, Elbing Miss, Álvaro Jurado)
more from komh’s OS/2 port (KO Myung-Hun)
This commit is contained in:
tg 2016-11-11 23:31:39 +00:00
parent 3aac3c30b5
commit 7b4bee7e58
13 changed files with 178 additions and 93 deletions

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.706 2016/11/07 16:55:51 tg Exp $' srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.707 2016/11/11 23:31:29 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, 2016 # 2011, 2012, 2013, 2014, 2015, 2016
@ -584,7 +584,7 @@ if test -d $tfn || test -d $tfn.exe; then
exit 1 exit 1
fi fi
rmf a.exe* a.out* conftest.c conftest.exe* *core core.* ${tfn}* *.bc *.dbg \ rmf a.exe* a.out* conftest.c conftest.exe* *core core.* ${tfn}* *.bc *.dbg \
*.ll *.o *.gen Rebuild.sh lft no signames.inc test.sh x vv.out *.ll *.o *.gen *.cat1 Rebuild.sh lft no signames.inc test.sh x vv.out
SRCS="lalloc.c eval.c exec.c expr.c funcs.c histrap.c jobs.c" SRCS="lalloc.c eval.c exec.c expr.c funcs.c histrap.c jobs.c"
SRCS="$SRCS lex.c main.c misc.c shf.c syn.c tree.c var.c" SRCS="$SRCS lex.c main.c misc.c shf.c syn.c tree.c var.c"
@ -755,6 +755,24 @@ GNU/kFreeBSD)
Haiku) Haiku)
add_cppflags -DMKSH_ASSUME_UTF8; HAVE_ISSET_MKSH_ASSUME_UTF8=1 add_cppflags -DMKSH_ASSUME_UTF8; HAVE_ISSET_MKSH_ASSUME_UTF8=1
;; ;;
Harvey)
add_cppflags -D_POSIX_SOURCE
add_cppflags -D_LIMITS_EXTENSION
add_cppflags -D_BSD_EXTENSION
add_cppflags -D_SUSV2_SOURCE
add_cppflags -D_GNU_SOURCE
add_cppflags -DMKSH_ASSUME_UTF8; HAVE_ISSET_MKSH_ASSUME_UTF8=1
add_cppflags -DMKSH_NO_CMDLINE_EDITING
add_cppflags -DMKSH__NO_SETEUGID
oswarn=' and will currently not work'
add_cppflags -DMKSH_UNEMPLOYED
add_cppflags -DMKSH_NOPROSPECTOFWORK
# these taken from Harvey-OS github and need re-checking
add_cppflags -D_setjmp=setjmp -D_longjmp=longjmp
: "${HAVE_CAN_NO_EH_FRAME=0}"
: "${HAVE_CAN_FNOSTRICTALIASING=0}"
: "${HAVE_CAN_FSTACKPROTECTORSTRONG=0}"
;;
HP-UX) HP-UX)
;; ;;
Interix) Interix)
@ -833,12 +851,14 @@ OpenBSD)
OS/2) OS/2)
HAVE_TERMIOS_H=0 HAVE_TERMIOS_H=0
HAVE_MKNOD=0 # setmode() incompatible HAVE_MKNOD=0 # setmode() incompatible
oswarn="; it is currently being ported" oswarn="; it is currently being ported, get it from"
oswarn="$oswarn${nl}https://github.com/komh/mksh-os2 in the meanwhile"
check_categories="$check_categories nosymlink" check_categories="$check_categories nosymlink"
: "${CC=gcc}" : "${CC=gcc}"
: "${SIZE=: size}" : "${SIZE=: size}"
add_cppflags -DMKSH_UNEMPLOYED add_cppflags -DMKSH_UNEMPLOYED
add_cppflags -DMKSH_NOPROSPECTOFWORK add_cppflags -DMKSH_NOPROSPECTOFWORK
add_cppflags -DMKSH_NO_LIMITS
;; ;;
OSF1) OSF1)
HAVE_SIG_T=0 # incompatible HAVE_SIG_T=0 # incompatible
@ -2347,7 +2367,7 @@ addsrcs '!' HAVE_STRLCPY strlcpy.c
addsrcs USE_PRINTF_BUILTIN printf.c addsrcs USE_PRINTF_BUILTIN printf.c
test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose" test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
add_cppflags -DMKSH_BUILD_R=539 add_cppflags -DMKSH_BUILD_R=541
$e $bi$me: Finished configuration testing, now producing output.$ao $e $bi$me: Finished configuration testing, now producing output.$ao
@ -2593,8 +2613,8 @@ esac
tcfn=$mkshexe tcfn=$mkshexe
test $cm = combine || v "$CC $CFLAGS $LDFLAGS -o $tcfn $lobjs $LIBS $ccpr" test $cm = combine || v "$CC $CFLAGS $LDFLAGS -o $tcfn $lobjs $LIBS $ccpr"
test -f $tcfn || exit 1 test -f $tcfn || exit 1
test 1 = $r || v "$NROFF -mdoc <'$srcdir/mksh.1' >$tfn.cat1" || \ test 1 = $r || v "$NROFF -mdoc <'$srcdir/lksh.1' >lksh.cat1" || rmf lksh.cat1
rmf $tfn.cat1 test 1 = $r || v "$NROFF -mdoc <'$srcdir/mksh.1' >mksh.cat1" || rmf mksh.cat1
test 0 = $eq && v $SIZE $tcfn test 0 = $eq && v $SIZE $tcfn
i=install i=install
test -f /usr/ucb/$i && i=/usr/ucb/$i test -f /usr/ucb/$i && i=/usr/ucb/$i
@ -2608,12 +2628,14 @@ if test $legacy = 0; then
fi fi
$e $e
$e Installing the manual: $e Installing the manual:
if test -f $tfn.cat1; then if test -f mksh.cat1; then
$e "# $i -c -o root -g bin -m 444 $tfn.cat1" \ $e "# $i -c -o root -g bin -m 444 lksh.cat1" \
"/usr/share/man/cat1/$tfn.0" "/usr/share/man/cat1/lksh.0"
$e "# $i -c -o root -g bin -m 444 mksh.cat1" \
"/usr/share/man/cat1/mksh.0"
$e or $e or
fi fi
$e "# $i -c -o root -g bin -m 444 $tfn.1 /usr/share/man/man1/$tfn.1" $e "# $i -c -o root -g bin -m 444 lksh.1 mksh.1 /usr/share/man/man1/"
$e $e
$e Run the regression test suite: ./test.sh $e Run the regression test suite: ./test.sh
$e Please also read the sample file dot.mkshrc and the fine manual. $e Please also read the sample file dot.mkshrc and the fine manual.

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/Makefile,v 1.153 2016/11/07 16:58:45 tg Exp $ # $MirOS: src/bin/mksh/Makefile,v 1.154 2016/11/11 23:31:30 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, 2016 # 2011, 2012, 2013, 2014, 2015, 2016
@ -57,7 +57,7 @@ CPPFLAGS+= -DMKSH_ASSUME_UTF8 -DMKSH_DISABLE_DEPRECATED \
-DHAVE_SETGROUPS=1 -DHAVE_STRERROR=0 -DHAVE_STRSIGNAL=0 \ -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=0 -DHAVE_STRSIGNAL=0 \
-DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \ -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \
-DHAVE_SYS_ERRLIST_DECL=1 -DHAVE_SYS_SIGLIST_DECL=1 \ -DHAVE_SYS_ERRLIST_DECL=1 -DHAVE_SYS_SIGLIST_DECL=1 \
-DHAVE_PERSISTENT_HISTORY=1 -DMKSH_BUILD_R=539 -DHAVE_PERSISTENT_HISTORY=1 -DMKSH_BUILD_R=541
CPPFLAGS+= -D${${PROG:L}_tf:C/(Mir${MAN:E}{0,1}){2}/4/:S/x/mksh_BUILD/:U} CPPFLAGS+= -D${${PROG:L}_tf:C/(Mir${MAN:E}{0,1}){2}/4/:S/x/mksh_BUILD/:U}
CPPFLAGS+= -I. CPPFLAGS+= -I.
COPTS+= -std=c89 -Wall COPTS+= -std=c89 -Wall

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.755 2016/11/07 16:58:45 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.756 2016/11/11 23:31:31 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://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date # (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R53 2016/11/07 @(#)MIRBSD KSH R54 2016/11/11
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 R53 2016/11/07 @(#)LEGACY KSH R54 2016/11/11
description: description:
Check version of legacy shell. Check version of legacy shell.
stdin: stdin:
@ -4948,7 +4948,7 @@ name: integer-base-check-flat
description: description:
Check behaviour does not match POSuX (except if set -o posix), Check behaviour does not match POSuX (except if set -o posix),
because a not type-safe scripting language has *no* business because a not type-safe scripting language has *no* business
interpreting the string "010" as octal numer eight (dangerous). interpreting the string "010" as octal number eight (dangerous).
stdin: stdin:
echo 1 "$("$__progname" -c 'echo :$((10))/$((010)),$((0x10)):')" . echo 1 "$("$__progname" -c 'echo :$((10))/$((010)),$((0x10)):')" .
echo 2 "$("$__progname" -o posix -c 'echo :$((10))/$((010)),$((0x10)):')" . echo 2 "$("$__progname" -o posix -c 'echo :$((10))/$((010)),$((0x10)):')" .

31
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.310 2016/11/11 21:13:21 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.311 2016/11/11 23:31:33 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
@ -258,7 +258,8 @@ x_print_expansions(int nwords, char * const *words, bool is_command)
break; break;
/* All in same directory? */ /* All in same directory? */
if (i == nwords) { if (i == nwords) {
while (prefix_len > 0 && words[0][prefix_len - 1] != '/') while (prefix_len > 0 &&
!mksh_cdirsep(words[0][prefix_len - 1]))
prefix_len--; prefix_len--;
use_copy = true; use_copy = true;
XPinit(l, nwords + 1); XPinit(l, nwords + 1);
@ -338,7 +339,7 @@ x_glob_hlp_tilde_and_rem_qchar(char *s, bool magic_flag)
* and if so, discern "~foo/bar" and "~/baz" from "~blah"; * and if so, discern "~foo/bar" and "~/baz" from "~blah";
* if we have a directory part (the former), try to expand * if we have a directory part (the former), try to expand
*/ */
if (*s == '~' && (cp = strchr(s, '/')) != NULL) { if (*s == '~' && (cp = mksh_sdirsep(s)) != NULL) {
/* ok, so split into "~foo"/"bar" or "~"/"baz" */ /* ok, so split into "~foo"/"bar" or "~"/"baz" */
*cp++ = 0; *cp++ = 0;
/* try to expand the tilde */ /* try to expand the tilde */
@ -593,7 +594,7 @@ x_locate_word(const char *buf, int buflen, int pos, int *startp,
* like file globbing. * like file globbing.
*/ */
for (p = start; p < end; p++) for (p = start; p < end; p++)
if (buf[p] == '/') if (mksh_cdirsep(buf[p]))
break; break;
iscmd = p == end; iscmd = p == end;
} }
@ -657,7 +658,7 @@ x_cf_glob(int *flagsp, const char *buf, int buflen, int pos, int *startp,
} }
} }
if (*toglob == '~' && !vstrchr(toglob, '/')) { if (*toglob == '~' && !mksh_vdirsep(toglob)) {
/* neither for '~foo' (but '~foo/bar') */ /* neither for '~foo' (but '~foo/bar') */
*flagsp |= XCF_IS_NOSPACE; *flagsp |= XCF_IS_NOSPACE;
goto dont_add_glob; goto dont_add_glob;
@ -746,13 +747,15 @@ x_basename(const char *s, const char *se)
if (s == se) if (s == se)
return (0); return (0);
/* Skip trailing slashes */ /* skip trailing directory separators */
for (p = se - 1; p > s && *p == '/'; p--) p = se - 1;
; while (p > s && mksh_cdirsep(*p))
for (; p > s && *p != '/'; p--) --p;
; /* drop last component */
if (*p == '/' && p + 1 < se) while (p > s && !mksh_cdirsep(*p))
p++; --p;
if (mksh_cdirsep(*p) && p + 1 < se)
++p;
return (p - s); return (p - s);
} }
@ -2783,7 +2786,7 @@ do_complete(
* append a space if this is a single non-directory match * append a space if this is a single non-directory match
* and not a parameter or homedir substitution * and not a parameter or homedir substitution
*/ */
if (nwords == 1 && words[0][nlen - 1] != '/' && if (nwords == 1 && !mksh_cdirsep(words[0][nlen - 1]) &&
!(flags & XCF_IS_NOSPACE)) { !(flags & XCF_IS_NOSPACE)) {
x_ins(T1space); x_ins(T1space);
} }
@ -5404,7 +5407,7 @@ complete_word(int cmd, int count)
* append a space if this is a non-directory match * append a space if this is a non-directory match
* and not a parameter or homedir substitution * and not a parameter or homedir substitution
*/ */
if (match_len > 0 && match[match_len - 1] != '/' && if (match_len > 0 && !mksh_cdirsep(match[match_len - 1]) &&
!(flags & XCF_IS_NOSPACE)) !(flags & XCF_IS_NOSPACE))
rval = putbuf(T1space, 1, false); rval = putbuf(T1space, 1, false);
} }

14
eval.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.193 2016/09/01 12:59:09 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.194 2016/11/11 23:31:34 tg Exp $");
/* /*
* string expansion * string expansion
@ -1576,7 +1576,7 @@ globit(XString *xs, /* dest string */
* SunOS 4.1.3 does this... * SunOS 4.1.3 does this...
*/ */
if ((check & GF_EXCHECK) && xp > Xstring(*xs, xp) && if ((check & GF_EXCHECK) && xp > Xstring(*xs, xp) &&
xp[-1] == '/' && !S_ISDIR(lstatb.st_mode) && mksh_cdirsep(xp[-1]) && !S_ISDIR(lstatb.st_mode) &&
(!S_ISLNK(lstatb.st_mode) || (!S_ISLNK(lstatb.st_mode) ||
stat_check() < 0 || !S_ISDIR(statb.st_mode))) stat_check() < 0 || !S_ISDIR(statb.st_mode)))
return; return;
@ -1586,7 +1586,7 @@ globit(XString *xs, /* dest string */
* directory * directory
*/ */
if (((check & GF_MARKDIR) && (check & GF_GLOBBED)) && if (((check & GF_MARKDIR) && (check & GF_GLOBBED)) &&
xp > Xstring(*xs, xp) && xp[-1] != '/' && xp > Xstring(*xs, xp) && !mksh_cdirsep(xp[-1]) &&
(S_ISDIR(lstatb.st_mode) || (S_ISDIR(lstatb.st_mode) ||
(S_ISLNK(lstatb.st_mode) && stat_check() > 0 && (S_ISLNK(lstatb.st_mode) && stat_check() > 0 &&
S_ISDIR(statb.st_mode)))) { S_ISDIR(statb.st_mode)))) {
@ -1601,11 +1601,11 @@ globit(XString *xs, /* dest string */
if (xp > Xstring(*xs, xp)) if (xp > Xstring(*xs, xp))
*xp++ = '/'; *xp++ = '/';
while (*sp == '/') { while (mksh_cdirsep(*sp)) {
Xcheck(*xs, xp); Xcheck(*xs, xp);
*xp++ = *sp++; *xp++ = *sp++;
} }
np = strchr(sp, '/'); np = mksh_sdirsep(sp);
if (np != NULL) { if (np != NULL) {
se = np; se = np;
/* don't assume '/', can be multiple kinds */ /* don't assume '/', can be multiple kinds */
@ -1713,8 +1713,8 @@ maybe_expand_tilde(const char *p, XString *dsp, char **dpp, bool isassign)
Xinit(ts, tp, 16, ATEMP); Xinit(ts, tp, 16, ATEMP);
/* : only for DOASNTILDE form */ /* : only for DOASNTILDE form */
while (p[0] == CHAR && p[1] != '/' && (!isassign || p[1] != ':')) while (p[0] == CHAR && !mksh_cdirsep(p[1]) &&
{ (!isassign || p[1] != ':')) {
Xcheck(ts, tp); Xcheck(ts, tp);
*tp++ = p[1]; *tp++ = p[1];
p += 2; p += 2;

14
exec.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.185 2016/11/11 21:13:23 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.186 2016/11/11 23:31:34 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL #ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh" #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
@ -672,7 +672,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
rv = subst_exstat; rv = subst_exstat;
goto Leave; goto Leave;
} else if (!tp) { } else if (!tp) {
if (Flag(FRESTRICTED) && vstrchr(cp, '/')) { if (Flag(FRESTRICTED) && mksh_vdirsep(cp)) {
warningf(true, Tf_sD_s, cp, "restricted"); warningf(true, Tf_sD_s, cp, "restricted");
rv = 1; rv = 1;
goto Leave; goto Leave;
@ -1123,7 +1123,7 @@ findcom(const char *name, int flags)
char *fpath; char *fpath;
union mksh_cchack npath; union mksh_cchack npath;
if (vstrchr(name, '/')) { if (mksh_vdirsep(name)) {
insert = 0; insert = 0;
/* prevent FPATH search below */ /* prevent FPATH search below */
flags &= ~FC_FUNC; flags &= ~FC_FUNC;
@ -1240,8 +1240,12 @@ search_access(const char *fn, int mode)
eno = errno; eno = errno;
return (eno ? eno : EACCES); return (eno ? eno : EACCES);
} }
#ifdef __OS2__
/* treat all files as executable on OS/2 */
sb.st_mode &= S_IXUSR | S_IXGRP | S_IXOTH;
#endif
if (mode == X_OK && (!S_ISREG(sb.st_mode) || if (mode == X_OK && (!S_ISREG(sb.st_mode) ||
!(sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))) !(sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
/* access(2) may say root can execute everything */ /* access(2) may say root can execute everything */
return (S_ISDIR(sb.st_mode) ? EISDIR : EACCES); return (S_ISDIR(sb.st_mode) ? EISDIR : EACCES);
return (0); return (0);
@ -1263,7 +1267,7 @@ search_path(const char *name, const char *lpath,
size_t namelen; size_t namelen;
int ec = 0, ev; int ec = 0, ev;
if (vstrchr(name, '/')) { if (mksh_vdirsep(name)) {
if ((ec = search_access(name, mode)) == 0) { if ((ec = search_access(name, mode)) == 0) {
search_path_ok: search_path_ok:
if (errnop) if (errnop)

8
lksh.1
View File

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/lksh.1,v 1.19 2016/08/25 16:21:33 tg Exp $ .\" $MirOS: src/bin/mksh/lksh.1,v 1.20 2016/11/11 23:31:35 tg Exp $
.\"- .\"-
.\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2016 .\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2016
.\" mirabilos <m@mirbsd.org> .\" mirabilos <m@mirbsd.org>
@ -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: August 25 2016 $ .Dd $Mdocdate: November 11 2016 $
.\" .\"
.\" Check which macro package we use, and do other -mdoc setup. .\" Check which macro package we use, and do other -mdoc setup.
.\" .\"
@ -221,8 +221,8 @@ for the versions this document applies to.
.Nm .Nm
uses uses
.Tn POSIX .Tn POSIX
arithmetics, which has quite a few implications: arithmetic, which has quite a few implications:
The data type for arithmetics is the host The data type for arithmetic operations is the host
.Tn ISO .Tn ISO
C C
.Vt long .Vt long

4
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.320 2016/10/26 22:55:51 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/main.c,v 1.321 2016/11/11 23:31:35 tg Exp $");
extern char **environ; extern char **environ;
@ -227,7 +227,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
ccp = kshname; ccp = kshname;
goto begin_parsing_kshname; goto begin_parsing_kshname;
while ((i = ccp[argi++])) { while ((i = ccp[argi++])) {
if (i == '/') { if (mksh_cdirsep(i)) {
ccp += argi; ccp += argi;
begin_parsing_kshname: begin_parsing_kshname:
argi = 0; argi = 0;

32
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.248 2016/11/11 21:13:25 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.249 2016/11/11 23:31:35 tg Exp $");
#define KSH_CHVT_FLAG #define KSH_CHVT_FLAG
#ifdef MKSH_SMALL #ifdef MKSH_SMALL
@ -391,7 +391,7 @@ parse_args(const char **argv,
*/ */
if (*p != '-') if (*p != '-')
for (q = p; *q; ) for (q = p; *q; )
if (*q++ == '/') if (mksh_cdirsep(*q++))
p = q; p = q;
Flag(FLOGIN) = (*p == '-'); Flag(FLOGIN) = (*p == '-');
opts = cmd_opts; opts = cmd_opts;
@ -1443,14 +1443,14 @@ do_realpath(const char *upath)
while (*ip) { while (*ip) {
/* skip slashes in input */ /* skip slashes in input */
while (*ip == '/') while (mksh_cdirsep(*ip))
++ip; ++ip;
if (!*ip) if (!*ip)
break; break;
/* get next pathname component from input */ /* get next pathname component from input */
tp = ip; tp = ip;
while (*ip && *ip != '/') while (*ip && !mksh_cdirsep(*ip))
++ip; ++ip;
len = ip - tp; len = ip - tp;
@ -1462,7 +1462,7 @@ do_realpath(const char *upath)
else if (len == 2 && tp[1] == '.') { else if (len == 2 && tp[1] == '.') {
/* strip off last pathname component */ /* strip off last pathname component */
while (xp > Xstring(xs, xp)) while (xp > Xstring(xs, xp))
if (*--xp == '/') if (mksh_cdirsep(*--xp))
break; break;
/* then continue with the next one */ /* then continue with the next one */
continue; continue;
@ -1485,7 +1485,7 @@ do_realpath(const char *upath)
/* lstat failed */ /* lstat failed */
if (errno == ENOENT) { if (errno == ENOENT) {
/* because the pathname does not exist */ /* because the pathname does not exist */
while (*ip == '/') while (mksh_cdirsep(*ip))
/* skip any trailing slashes */ /* skip any trailing slashes */
++ip; ++ip;
/* no more components left? */ /* no more components left? */
@ -1545,6 +1545,7 @@ do_realpath(const char *upath)
/* assert: xp == xs.beg => start of path */ /* assert: xp == xs.beg => start of path */
/* exactly two leading slashes? (SUSv4 3.266) */ /* exactly two leading slashes? (SUSv4 3.266) */
/* @komh do NOT use mksh_cdirsep() here */
if (ip[1] == '/' && ip[2] != '/') { if (ip[1] == '/' && ip[2] != '/') {
/* keep them, e.g. for UNC pathnames */ /* keep them, e.g. for UNC pathnames */
Xput(xs, xp, '/'); Xput(xs, xp, '/');
@ -1570,7 +1571,7 @@ do_realpath(const char *upath)
* if source path had a trailing slash, check if target path * if source path had a trailing slash, check if target path
* is not a non-directory existing file * is not a non-directory existing file
*/ */
if (ip > ipath && ip[-1] == '/') { if (ip > ipath && mksh_cdirsep(ip[-1])) {
if (stat(Xstring(xs, xp), &sb)) { if (stat(Xstring(xs, xp), &sb)) {
if (errno != ENOENT) if (errno != ENOENT)
goto notfound; goto notfound;
@ -1639,7 +1640,7 @@ make_path(const char *cwd, const char *file,
if (c == '.') if (c == '.')
c = file[2]; c = file[2];
if (c == '/' || c == '\0') if (mksh_cdirsep(c) || c == '\0')
use_cdpath = false; use_cdpath = false;
} }
@ -1661,7 +1662,7 @@ make_path(const char *cwd, const char *file,
XcheckN(*xsp, xp, len); XcheckN(*xsp, xp, len);
memcpy(xp, cwd, len); memcpy(xp, cwd, len);
xp += len; xp += len;
if (cwd[len - 1] != '/') if (!mksh_cdirsep(cwd[len - 1]))
Xput(*xsp, xp, '/'); Xput(*xsp, xp, '/');
} }
*phys_pathp = Xlength(*xsp, xp); *phys_pathp = Xlength(*xsp, xp);
@ -1669,7 +1670,7 @@ make_path(const char *cwd, const char *file,
XcheckN(*xsp, xp, plen); XcheckN(*xsp, xp, plen);
memcpy(xp, plist, plen); memcpy(xp, plist, plen);
xp += plen; xp += plen;
if (plist[plen - 1] != '/') if (!mksh_cdirsep(plist[plen - 1]))
Xput(*xsp, xp, '/'); Xput(*xsp, xp, '/');
rval = 1; rval = 1;
} }
@ -1711,9 +1712,14 @@ simplify_path(char *p)
return; return;
case '/': case '/':
/* exactly two leading slashes? (SUSv4 3.266) */ /* exactly two leading slashes? (SUSv4 3.266) */
/* @komh no mksh_cdirsep() here! */
if (p[1] == '/' && p[2] != '/') if (p[1] == '/' && p[2] != '/')
/* keep them, e.g. for UNC pathnames */ /* keep them, e.g. for UNC pathnames */
++p; ++p;
#ifdef __OS2__
/* FALLTHROUGH */
case '\\':
#endif
needslash = true; needslash = true;
break; break;
default: default:
@ -1723,14 +1729,14 @@ simplify_path(char *p)
while (*ip) { while (*ip) {
/* skip slashes in input */ /* skip slashes in input */
while (*ip == '/') while (mksh_cdirsep(*ip))
++ip; ++ip;
if (!*ip) if (!*ip)
break; break;
/* get next pathname component from input */ /* get next pathname component from input */
tp = ip; tp = ip;
while (*ip && *ip != '/') while (*ip && !mksh_cdirsep(*ip))
++ip; ++ip;
len = ip - tp; len = ip - tp;
@ -1750,7 +1756,7 @@ simplify_path(char *p)
strip_last_component: strip_last_component:
/* strip off last pathname component */ /* strip off last pathname component */
while (dp > sp) while (dp > sp)
if (*--dp == '/') if (mksh_cdirsep(*--dp))
break; break;
} else { } else {
/* relative path, at its beginning */ /* relative path, at its beginning */

34
mksh.1
View File

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.419 2016/11/11 22:17:09 tg Exp $ .\" $MirOS: src/bin/mksh/mksh.1,v 1.420 2016/11/11 23:31:36 tg Exp $
.\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer 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,
@ -1060,7 +1060,7 @@ For
and and
.Dq Li \eu#### , .Dq Li \eu#### ,
.Dq # .Dq #
means a hexadecimal digit, of thich there may be none up to four or eight; means a hexadecimal digit, of which there may be none up to four or eight;
these escapes translate a Unicode codepoint to UTF-8. these escapes translate a Unicode codepoint to UTF-8.
Furthermore, Furthermore,
.Dq Li \eE .Dq Li \eE
@ -2602,7 +2602,7 @@ This also affects implicit conversion to integer, for example as done by the
.Ic let .Ic let
command. command.
.Em Never .Em Never
use unchecked user input, e.g. from the environment, in arithmetics! use unchecked user input, e.g. from the environment, in an arithmetic context!
.Pp .Pp
Expressions are calculated using signed arithmetic and the Expressions are calculated using signed arithmetic and the
.Vt mksh_ari_t .Vt mksh_ari_t
@ -4899,7 +4899,7 @@ If necessary, values are either truncated or space padded
to fit the field width. to fit the field width.
.It Fl l .It Fl l
Lower case attribute. Lower case attribute.
All upper case characters in values are converted to lower case. All upper case ASCII characters in values are converted to lower case.
(In the original Korn shell, this parameter meant (In the original Korn shell, this parameter meant
.Dq long integer .Dq long integer
when used with the when used with the
@ -4923,7 +4923,7 @@ is lazily evaluated at the time
.Ar name .Ar name
is accessed. is accessed.
This can be used by functions to access variables whose names are This can be used by functions to access variables whose names are
passed as parametres, instead of using passed as parameters, instead of using
.Ic eval . .Ic eval .
.It Fl p .It Fl p
Print complete Print complete
@ -4964,7 +4964,7 @@ option).
This option is not in the original Korn shell. This option is not in the original Korn shell.
.It Fl u .It Fl u
Upper case attribute. Upper case attribute.
All lower case characters in values are converted to upper case. All lower case ASCII characters in values are converted to upper case.
(In the original Korn shell, this parameter meant (In the original Korn shell, this parameter meant
.Dq unsigned integer .Dq unsigned integer
when used with the when used with the
@ -5381,11 +5381,11 @@ to behave even more
compliant in places where the defaults or opinions differ. compliant in places where the defaults or opinions differ.
Note that Note that
.Nm mksh .Nm mksh
will still operate with unsigned 32-bit arithmetics; use will still operate with unsigned 32-bit arithmetic; use
.Nm lksh .Nm lksh
if arithmetics on the host if arithmetic on the host
.Vt long .Vt long
data type, complete with ISO C Undefined Behaviour, are required; data type, complete with ISO C Undefined Behaviour, is required;
refer to the refer to the
.Xr lksh 1 .Xr lksh 1
manual page for details. manual page for details.
@ -5586,7 +5586,7 @@ Moves the cursor to the beginning of the edited input line.
.Op Ar n .Op Ar n
.No \*(ha[C , \*(ha[c .No \*(ha[C , \*(ha[c
.Xc .Xc
Uppercase the first character in the next Uppercase the first ASCII character in the next
.Ar n .Ar n
words, leaving the cursor past the end of the last word. words, leaving the cursor past the end of the last word.
.It clear\-screen: \*(ha[\*(haL .It clear\-screen: \*(ha[\*(haL
@ -6586,8 +6586,8 @@ This shell is based on the public domain 7th edition Bourne shell clone by
.An Charles Forsyth , .An Charles Forsyth ,
who kindly agreed to, in countries where the Public Domain status of the work who kindly agreed to, in countries where the Public Domain status of the work
may not be valid, grant a copyright licence to the general public to deal in may not be valid, grant a copyright licence to the general public to deal in
the work without restriction and permission to sublicence derivates under the the work without restriction and permission to sublicence derivatives under
terms of any (OSI approved) Open Source licence, the terms of any (OSI approved) Open Source licence,
and parts of the BRL shell by and parts of the BRL shell by
.An Doug A. Gwyn , .An Doug A. Gwyn ,
.An Doug Kingston , .An Doug Kingston ,
@ -6629,7 +6629,7 @@ The complete legalese is at:
has a different scope model from has a different scope model from
.At .At
.Nm ksh , .Nm ksh ,
which leads to subtile differences in semantics for identical builtins. which leads to subtle differences in semantics for identical builtins.
This can cause issues with a This can cause issues with a
.Ic nameref .Ic nameref
to suddenly point to a local variable by accident; fixing this is hard. to suddenly point to a local variable by accident; fixing this is hard.
@ -6644,9 +6644,9 @@ foo \*(Ba bar \*(Ba& read \-p baz # will, however, do so
.Ed .Ed
.Pp .Pp
.Nm mksh .Nm mksh
provides a consistent set of 32-bit integer arithmetics, both signed provides a consistent 32-bit integer arithmetic implementation, both
and unsigned, with defined wraparound and sign of the result of a signed and unsigned, with sign of the result of a remainder operation
remainder operation, even (defying POSIX) on 36-bit and 64-bit systems. and wraparound defined, even (defying POSIX) on 36-bit and 64-bit systems.
.Pp .Pp
.Nm mksh .Nm mksh
provides a consistent, clear interface normally. provides a consistent, clear interface normally.
@ -6701,7 +6701,7 @@ The truncation process involved when changing
.Ev HISTFILE .Ev HISTFILE
does not free old history entries (leaks memory) and leaks does not free old history entries (leaks memory) and leaks
old entries into the new history if their line numbers are old entries into the new history if their line numbers are
not overwritten by same-numer entries from the persistent not overwritten by same-number entries from the persistent
history file; truncating the on-disc file to history file; truncating the on-disc file to
.Ev HISTSIZE .Ev HISTSIZE
lines has always been broken and prone to history file corruption lines has always been broken and prone to history file corruption

44
sh.h
View File

@ -175,9 +175,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.790 2016/11/07 16:58:48 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.791 2016/11/11 23:31:38 tg Exp $");
#endif #endif
#define MKSH_VERSION "R53 2016/11/07" #define MKSH_VERSION "R54 2016/11/11"
/* arithmetic types: C implementation */ /* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES #if !HAVE_CAN_INTTYPES
@ -578,7 +578,7 @@ char *ucstrstr(char *, const char *);
#define mkssert(e) do { } while (/* CONSTCOND */ 0) #define mkssert(e) do { } while (/* CONSTCOND */ 0)
#endif #endif
#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 539) #if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 541)
#error Must run Build.sh to compile this. #error Must run Build.sh to compile this.
extern void thiswillneverbedefinedIhope(void); extern void thiswillneverbedefinedIhope(void);
int int
@ -1350,7 +1350,7 @@ EXTERN mksh_ari_t x_lins E_INIT(24);
/* Determine the location of the system (common) profile */ /* Determine the location of the system (common) profile */
#ifndef MKSH_DEFAULT_PROFILEDIR #ifndef MKSH_DEFAULT_PROFILEDIR
#define MKSH_DEFAULT_PROFILEDIR "/etc" #define MKSH_DEFAULT_PROFILEDIR MKSH_UNIXROOT "/etc"
#endif #endif
#define MKSH_SYSTEM_PROFILE MKSH_DEFAULT_PROFILEDIR "/profile" #define MKSH_SYSTEM_PROFILE MKSH_DEFAULT_PROFILEDIR "/profile"
@ -1748,8 +1748,6 @@ typedef struct XString {
Area *areap; Area *areap;
} XString; } XString;
typedef char *XStringP;
/* initialise expandable string */ /* initialise expandable string */
#define XinitN(xs, length, area) do { \ #define XinitN(xs, length, area) do { \
(xs).len = (length); \ (xs).len = (length); \
@ -1825,6 +1823,15 @@ typedef struct {
#define XPclose(x) aresize2((x).beg, XPsize(x), sizeof(void *), ATEMP) #define XPclose(x) aresize2((x).beg, XPsize(x), sizeof(void *), ATEMP)
#define XPfree(x) afree((x).beg, ATEMP) #define XPfree(x) afree((x).beg, ATEMP)
/* for print_columns */
struct columnise_opts {
struct shf *shf;
char linesep;
bool do_last;
bool prefcol;
};
/* /*
* Lexer internals * Lexer internals
*/ */
@ -2021,7 +2028,7 @@ void flushcom(bool);
int search_access(const char *, int); int search_access(const char *, int);
const char *search_path(const char *, const char *, int, int *); const char *search_path(const char *, const char *, int, int *);
void pr_menu(const char * const *); void pr_menu(const char * const *);
void pr_list(char * const *); void pr_list(struct columnise_opts *, char * const *);
int herein(struct ioword *, char **); int herein(struct ioword *, char **);
/* expr.c */ /* expr.c */
int evaluate(const char *, mksh_ari_t *, int, bool); int evaluate(const char *, mksh_ari_t *, int, bool);
@ -2122,8 +2129,8 @@ void runtrap(Trap *, bool);
void cleartraps(void); void cleartraps(void);
void restoresigs(void); void restoresigs(void);
void settrap(Trap *, const char *); void settrap(Trap *, const char *);
int block_pipe(void); bool block_pipe(void);
void restore_pipe(int); void restore_pipe(void);
int setsig(Trap *, sig_t, int); int setsig(Trap *, sig_t, int);
void setexecsig(Trap *, int); void setexecsig(Trap *, int);
#if HAVE_FLOCK || HAVE_LOCK_FCNTL #if HAVE_FLOCK || HAVE_LOCK_FCNTL
@ -2237,9 +2244,9 @@ void ksh_getopt_reset(Getopt *, int);
int ksh_getopt(const char **, Getopt *, const char *); 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 columnise_opts *, unsigned int,
void (*)(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);
void strip_nuls(char *, size_t) void strip_nuls(char *, size_t)
MKSH_A_BOUNDED(__string__, 1, 2); MKSH_A_BOUNDED(__string__, 1, 2);
ssize_t blocking_read(int, char *, size_t) ssize_t blocking_read(int, char *, size_t)
@ -2420,13 +2427,26 @@ extern int tty_init_fd(void); /* initialise tty_fd, tty_devtty */
}) })
#define mksh_abspath(s) __extension__({ \ #define mksh_abspath(s) __extension__({ \
const char *mksh_abspath_s = (s); \ const char *mksh_abspath_s = (s); \
(mksh_abspath_s[0] == '/' || (ksh_isalphx(mksh_abspath_s[0]) && \ (mksh_cdirsep(mksh_abspath_s[0]) || \
(ksh_isalphx(mksh_abspath_s[0]) && \
mksh_abspath_s[1] == ':')); \ mksh_abspath_s[1] == ':')); \
}) })
#define mksh_cdirsep(c) __extension__({ \
char mksh_cdirsep_c = (c); \
(mksh_cdirsep_c == '/' || mksh_cdirsep_c == '\\'); \
})
/*
* I've seen mksh_sdirsep(s) and mksh_vdirsep(s) but need to think
* more about the OS/2 port (and, possibly, toy with it) before I
* can merge this upstream, but good job so far @komh, thanks!
*/
#else #else
#define binopen2(path,flags) open((path), (flags) | O_BINARY) #define binopen2(path,flags) open((path), (flags) | O_BINARY)
#define binopen3(path,flags,mode) open((path), (flags) | O_BINARY, (mode)) #define binopen3(path,flags,mode) open((path), (flags) | O_BINARY, (mode))
#define mksh_abspath(s) ((s)[0] == '/') #define mksh_abspath(s) ((s)[0] == '/')
#define mksh_cdirsep(c) ((c) == '/')
#define mksh_sdirsep(s) strchr((s), '/')
#define mksh_vdirsep(s) vstrchr((s), '/')
#endif #endif
/* be sure not to interfere with anyone else's idea about EXTERN */ /* be sure not to interfere with anyone else's idea about EXTERN */

25
var.c
View File

@ -28,7 +28,7 @@
#include <sys/sysctl.h> #include <sys/sysctl.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.208 2016/10/22 23:56:50 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/var.c,v 1.209 2016/11/11 23:31:39 tg Exp $");
/*- /*-
* Variables * Variables
@ -133,7 +133,7 @@ initvar(void)
struct tbl *tp; struct tbl *tp;
ktinit(APERM, &specials, ktinit(APERM, &specials,
/* currently 15 specials: 75% of 32 = 2^5 */ /* currently 18 specials: 75% of 32 = 2^5 */
5); 5);
while (i < V_MAX - 1) { while (i < V_MAX - 1) {
tp = ktenter(&specials, initvar_names[i], tp = ktenter(&specials, initvar_names[i],
@ -1149,6 +1149,13 @@ makenv(void)
/* setstr can't fail here */ /* setstr can't fail here */
setstr(vp, val, KSH_RETURN_ERROR); setstr(vp, val, KSH_RETURN_ERROR);
} }
#ifdef __OS2__
/* these special variables are not exported */
if (!strcmp(vp->name, "BEGINLIBPATH") ||
!strcmp(vp->name, "ENDLIBPATH") ||
!strcmp(vp->name, "LIBPATHSTRICT"))
continue;
#endif
XPput(denv, vp->val.s); XPput(denv, vp->val.s);
} }
if (l->flags & BF_STOPENV) if (l->flags & BF_STOPENV)
@ -1274,6 +1281,13 @@ setspec(struct tbl *vp)
int st; int st;
switch ((st = special(vp->name))) { switch ((st = special(vp->name))) {
#ifdef __OS2__
case V_BEGINLIBPATH:
case V_ENDLIBPATH:
case V_LIBPATHSTRICT:
setextlibpath(vp->name, str_val(vp));
return;
#endif
#if HAVE_PERSISTENT_HISTORY #if HAVE_PERSISTENT_HISTORY
case V_HISTFILE: case V_HISTFILE:
sethistfile(str_val(vp)); sethistfile(str_val(vp));
@ -1396,6 +1410,13 @@ unsetspec(struct tbl *vp)
*/ */
switch (special(vp->name)) { switch (special(vp->name)) {
#ifdef __OS2__
case V_BEGINLIBPATH:
case V_ENDLIBPATH:
case V_LIBPATHSTRICT:
setextlibpath(vp->name, "");
return;
#endif
#if HAVE_PERSISTENT_HISTORY #if HAVE_PERSISTENT_HISTORY
case V_HISTFILE: case V_HISTFILE:
sethistfile(NULL); sethistfile(NULL);

View File

@ -19,7 +19,7 @@
*/ */
#if defined(VARSPEC_DEFNS) #if defined(VARSPEC_DEFNS)
__RCSID("$MirOS: src/bin/mksh/var_spec.h,v 1.9 2016/07/25 21:02:13 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/var_spec.h,v 1.10 2016/11/11 23:31:39 tg Exp $");
#define FN(name) /* nothing */ #define FN(name) /* nothing */
#elif defined(VARSPEC_ENUMS) #elif defined(VARSPEC_ENUMS)
#define FN(name) V_##name, #define FN(name) V_##name,
@ -40,13 +40,22 @@ F0(NONE)
/* 1 and up are special variables */ /* 1 and up are special variables */
FN(BASHPID) FN(BASHPID)
#ifdef __OS2__
FN(BEGINLIBPATH)
#endif
FN(COLUMNS) FN(COLUMNS)
#ifdef __OS2__
FN(ENDLIBPATH)
#endif
FN(EPOCHREALTIME) FN(EPOCHREALTIME)
#if HAVE_PERSISTENT_HISTORY #if HAVE_PERSISTENT_HISTORY
FN(HISTFILE) FN(HISTFILE)
#endif #endif
FN(HISTSIZE) FN(HISTSIZE)
FN(IFS) FN(IFS)
#ifdef __OS2__
FN(LIBPATHSTRICT)
#endif
FN(LINENO) FN(LINENO)
FN(LINES) FN(LINES)
FN(OPTIND) FN(OPTIND)