LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
# mksh source files
- LOCAL_SRC_FILES := \
+ MKSH_SRC_FILES := \
src/lalloc.c src/edit.c src/eval.c src/exec.c \
src/expr.c src/funcs.c src/histrap.c src/jobs.c \
src/lex.c src/main.c src/misc.c src/shf.c \
src/syn.c src/tree.c src/var.c
- LOCAL_SYSTEM_SHARED_LIBRARIES := libc
-
- LOCAL_C_INCLUDES := $(LOCAL_PATH)/src
-
- # Additional flags first...
- LOCAL_CFLAGS += \
- -DMKSH_DEFAULT_PROFILEDIR=\"/system/etc\" \
- -DMKSHRC_PATH=\"/system/etc/mkshrc\" \
- -DMKSH_DEFAULT_EXECSHELL=\"/system/bin/sh\" \
- -DMKSH_DEFAULT_TMPDIR=\"/data/local\" \
+ MKSH_INCLUDES := $(LOCAL_PATH)/src
- # ...then from Makefrag.inc: CFLAGS...
- LOCAL_CFLAGS += \
+ MKSH_CFLAGS += \
-Wno-deprecated-declarations \
-fno-asynchronous-unwind-tables \
-fno-strict-aliasing \
-fstack-protector -fwrapv \
# ...and CPPFLAGS.
- LOCAL_CFLAGS += \
+ MKSH_CFLAGS += \
-DDEBUG_LEAKS -DMKSH_ASSUME_UTF8 \
-DMKSH_DONT_EMIT_IDSTRING \
-DMKSH_BUILDSH \
-DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 \
-DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \
-DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 \
- -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=541
+ -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=551
+ LOCAL_SRC_FILES := $(MKSH_SRC_FILES)
+
+ LOCAL_SYSTEM_SHARED_LIBRARIES := libc
+
+ LOCAL_C_INCLUDES := $(MKSH_INCLUDES)
+
+ # Additional flags first...
+ LOCAL_CFLAGS += \
+ -DMKSH_DEFAULT_PROFILEDIR=\"/system/etc\" \
+ -DMKSHRC_PATH=\"/system/etc/mkshrc\" \
+ -DMKSH_DEFAULT_EXECSHELL=\"/system/bin/sh\" \
+ -DMKSH_DEFAULT_TMPDIR=\"/data/local\" \
+
+ LOCAL_CFLAGS += $(MKSH_CFLAGS)
+
include $(BUILD_EXECUTABLE)
+
+ ifeq ($(PRODUCT_FULL_TREBLE),true)
+ # /vendor/etc/mkshrc
+ include $(CLEAR_VARS)
+
+ LOCAL_MODULE := mkshrc_vendor
+ LOCAL_MODULE_STEM := mkshrc
+ LOCAL_MODULE_CLASS := ETC
+ LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)
+ LOCAL_SRC_FILES := $(LOCAL_MODULE)
+ include $(BUILD_PREBUILT)
+
+ # /vendor/bin/sh
+ include $(CLEAR_VARS)
+
+ LOCAL_MODULE := sh_vendor
+ LOCAL_MODULE_STEM := sh
+ LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
+ LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_EXECUTABLES)
+
+ # mksh source files
+ LOCAL_SRC_FILES := $(MKSH_SRC_FILES)
+
+ LOCAL_STATIC_LIBRARIES := libc
+
+ LOCAL_C_INCLUDES := $(MKSH_INCLUDES)
+
+ # Additional flags first...
+ LOCAL_CFLAGS += \
+ -DMKSH_DEFAULT_PROFILEDIR=\"/vendor/etc\" \
+ -DMKSHRC_PATH=\"/vendor/etc/mkshrc\" \
+ -DMKSH_DEFAULT_EXECSHELL=\"/vendor/bin/sh\" \
+ -DMKSH_DEFPATH_OVERRIDE=\"/vendor/bin:/vendor/xbin\" \
+
+ LOCAL_CFLAGS += $(MKSH_CFLAGS)
+
+ LOCAL_FORCE_STATIC_EXECUTABLE := true
+
+ include $(BUILD_EXECUTABLE)
+ endif
+
+ MKSH_SRC_FILES:=
+ MKSH_CFLAGS:=
+ MKSH_INCLUDES:=
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013, 2014, 2015, 2016
+ * 2011, 2012, 2013, 2014, 2015, 2016, 2017
* mirabilos <m@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include <locale.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/main.c,v 1.322 2016/11/11 23:48:30 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/main.c,v 1.332 2017/04/12 16:01:45 tg Exp $");
extern char **environ;
static void x_sigwinch(int);
#endif
-static const char initifs[] = "IFS= \t\n";
-
static const char initsubs[] =
"${PS2=> }"
"${PS3=#? }"
Ttypeset, "-x", "HOME", TPATH, TSHELL, NULL,
Ttypeset, "-i10", "COLUMNS", "LINES", "SECONDS", "TMOUT", NULL,
Talias,
- "integer=\\typeset -i",
- "local=\\typeset",
+ "integer=\\\\builtin typeset -i",
+ "local=\\\\builtin typeset",
/* not "alias -t --": hash -r needs to work */
- "hash=\\builtin alias -t",
- "type=\\builtin whence -v",
- "autoload=\\typeset -fu",
- "functions=\\typeset -f",
- "history=\\builtin fc -l",
- "nameref=\\typeset -n",
+ "hash=\\\\builtin alias -t",
+ "type=\\\\builtin whence -v",
+ "autoload=\\\\builtin typeset -fu",
+ "functions=\\\\builtin typeset -f",
+ "history=\\\\builtin fc -l",
+ "nameref=\\\\builtin typeset -n",
"nohup=nohup ",
- "r=\\builtin fc -e -",
- "login=\\exec login",
+ "r=\\\\builtin fc -e -",
+ "login=\\\\builtin exec login",
NULL,
/* this is what AT&T ksh seems to track, with the addition of emacs */
Talias, "-tU",
static struct env env;
struct env *e = &env;
+/* compile-time assertions */
+#define cta(name, expr) struct cta_ ## name { char t[(expr) ? 1 : -1]; }
+
+/* this one should be defined by the standard */
+cta(char_is_1_char, (sizeof(char) == 1) && (sizeof(signed char) == 1) &&
+ (sizeof(unsigned char) == 1));
+cta(char_is_8_bits, ((CHAR_BIT) == 8) && ((int)(unsigned char)0xFF == 0xFF) &&
+ ((int)(unsigned char)0x100 == 0) && ((int)(unsigned char)(int)-1 == 0xFF));
+/* the next assertion is probably not really needed */
+cta(short_is_2_char, sizeof(short) == 2);
+cta(short_size_no_matter_of_signedness, sizeof(short) == sizeof(unsigned short));
+/* the next assertion is probably not really needed */
+cta(int_is_4_char, sizeof(int) == 4);
+cta(int_size_no_matter_of_signedness, sizeof(int) == sizeof(unsigned int));
+
+cta(long_ge_int, sizeof(long) >= sizeof(int));
+cta(long_size_no_matter_of_signedness, sizeof(long) == sizeof(unsigned long));
+
+#ifndef MKSH_LEGACY_MODE
+/* the next assertion is probably not really needed */
+cta(ari_is_4_char, sizeof(mksh_ari_t) == 4);
+/* but this is */
+cta(ari_has_31_bit, 0 < (mksh_ari_t)(((((mksh_ari_t)1 << 15) << 15) - 1) * 2 + 1));
+/* the next assertion is probably not really needed */
+cta(uari_is_4_char, sizeof(mksh_uari_t) == 4);
+/* but the next three are; we REQUIRE unsigned integer wraparound */
+cta(uari_has_31_bit, 0 < (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 2 + 1));
+cta(uari_has_32_bit, 0 < (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3));
+cta(uari_wrap_32_bit,
+ (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3) >
+ (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 4));
+#endif
+/* these are always required */
+cta(ari_is_signed, (mksh_ari_t)-1 < (mksh_ari_t)0);
+cta(uari_is_unsigned, (mksh_uari_t)-1 > (mksh_uari_t)0);
+/* we require these to have the precisely same size and assume 2s complement */
+cta(ari_size_no_matter_of_signedness, sizeof(mksh_ari_t) == sizeof(mksh_uari_t));
+
+cta(sizet_size_no_matter_of_signedness, sizeof(ssize_t) == sizeof(size_t));
+cta(sizet_voidptr_same_size, sizeof(size_t) == sizeof(void *));
+cta(sizet_funcptr_same_size, sizeof(size_t) == sizeof(void (*)(void)));
+/* our formatting routines assume this */
+cta(ptr_fits_in_long, sizeof(size_t) <= sizeof(long));
+cta(ari_fits_in_long, sizeof(mksh_ari_t) <= sizeof(long));
+
static mksh_uari_t
rndsetup(void)
{
for (i = 0; i < 3; ++i)
if (!isatty(i))
setmode(i, O_BINARY);
+
+ os2_init(&argc, &argv);
#endif
/* do things like getpgrp() et al. */
}
}
+ /* override default PATH regardless of environment */
+ #ifdef MKSH_DEFPATH_OVERRIDE
+ vp = global(TPATH);
+ setstr(vp, MKSH_DEFPATH_OVERRIDE, KSH_RETURN_ERROR);
+ #endif
+
/* for security */
- typeset(initifs, 0, 0, 0, 0);
+ typeset("IFS= \t\n", 0, 0, 0, 0);
/* assign default shell variable values */
+ typeset("PATHSEP=" MKSH_PATHSEPS, 0, 0, 0, 0);
substitute(initsubs, 0);
/* Figure out the current working directory and set $PWD */
setstr(vp, current_wd, KSH_RETURN_ERROR);
for (wp = initcoms; *wp != NULL; wp++) {
- shcomexec(wp);
+ c_builtin(wp);
while (*wp != NULL)
wp++;
}
* to search for it. This changes the behaviour of a
* simple "mksh foo", but can't be helped.
*/
- s->file = search_path(argv[argi++], path, X_OK, NULL);
+ s->file = argv[argi++];
+ if (search_access(s->file, X_OK) != 0)
+ s->file = search_path(s->file, path, X_OK, NULL);
if (!s->file || !*s->file)
s->file = argv[argi - 1];
#else
}
if (restricted_shell) {
- shcomexec(restr_com);
+ c_builtin(restr_com);
/* After typeset command... */
Flag(FRESTRICTED) = 1;
}
if ((rv = main_init(argc, argv, &s, &l)) == 0) {
if (Flag(FAS_BUILTIN)) {
- rv = shcomexec(l->argv);
+ rv = c_builtin(l->argv);
} else {
- shell(s, true);
+ shell(s, 0);
/* NOTREACHED */
}
}
unwind(i);
/* NOTREACHED */
default:
- internal_errorf("include %d", i);
+ internal_errorf(Tunexpected_type, Tunwind, Tsource, i);
/* NOTREACHED */
}
}
s = pushs(SFILE, ATEMP);
s->u.shf = shf;
strdupx(s->file, name, ATEMP);
- i = shell(s, false);
+ i = shell(s, 1);
quitenv(s->u.shf);
if (old_argv) {
e->loc->argv = old_argv;
s = pushs(SSTRING, ATEMP);
s->start = s->str = comm;
s->line = line;
- rv = shell(s, false);
+ rv = shell(s, 1);
source = sold;
return (rv);
}
* run the commands from the input source, returning status.
*/
int
-shell(Source * volatile s, volatile bool toplevel)
+shell(Source * volatile s, volatile int level)
{
struct op *t;
volatile bool wastty = tobool(s->flags & SF_TTY);
volatile uint8_t attempts = 13;
- volatile bool interactive = Flag(FTALKING) && toplevel;
+ volatile bool interactive = (level == 0) && Flag(FTALKING);
volatile bool sfirst = true;
Source *volatile old_source = source;
int i;
- newenv(E_PARSE);
+ newenv(level == 2 ? E_EVAL : E_PARSE);
if (interactive)
really_exit = false;
switch ((i = kshsetjmp(e->jbuf))) {
case 0:
break;
+ case LBREAK:
+ case LCONTIN:
+ if (level != 2) {
+ source = old_source;
+ quitenv(NULL);
+ internal_errorf(Tf_cant_s, Tshell,
+ i == LBREAK ? Tbreak : Tcontinue);
+ /* NOTREACHED */
+ }
+ /* assert: interactive == false */
+ /* FALLTHROUGH */
case LINTR:
/* we get here if SIGINT not caught or ignored */
case LERROR:
default:
source = old_source;
quitenv(NULL);
- internal_errorf("shell %d", i);
+ internal_errorf(Tunexpected_type, Tunwind, Tshell, i);
/* NOTREACHED */
}
while (/* CONSTCOND */ 1) {
j_notify();
set_prompt(PS1, s);
}
- t = compile(s, sfirst);
+ t = compile(s, sfirst, true);
if (interactive)
histsave(&s->line, NULL, HIST_FLUSH, true);
sfirst = false;
* immediately after the last command
* executed.
*/
- if (toplevel)
+ if (level == 0)
unwind(LEXIT);
break;
}
case E_INCL:
case E_LOOP:
case E_ERRH:
+ case E_EVAL:
kshlongjmp(e->jbuf, i);
/* NOTREACHED */
case E_NONE:
VWARNINGF_BUILTIN, fmt, va);
va_end(va);
- /*
- * POSIX special builtins and ksh special builtins cause
- * non-interactive shells to exit. XXX may not want LERROR here
- */
+ /* POSIX special builtins cause non-interactive shells to exit */
if (builtin_spec) {
builtin_argv0 = NULL;
+ /* may not want to use LERROR here */
unwind(LERROR);
}
}
#ifdef DF
if ((lfp = getenv("SDMKSH_PATH")) == NULL) {
if ((lfp = getenv("HOME")) == NULL || !mksh_abspath(lfp))
- errorf("cannot get home directory");
+ errorf("can't get home directory");
lfp = shf_smprintf(Tf_sSs, lfp, "mksh-dbg.txt");
}
if ((shl_dbg_fd = open(lfp, O_WRONLY | O_APPEND | O_CREAT, 0600)) < 0)
- errorf("cannot open debug output file %s", lfp);
+ errorf("can't open debug output file %s", lfp);
if (shl_dbg_fd < FDBASE) {
int nfd;
nfd = fcntl(shl_dbg_fd, F_DUPFD, FDBASE);
close(shl_dbg_fd);
if ((shl_dbg_fd = nfd) == -1)
- errorf("cannot dup debug output file");
+ errorf("can't dup debug output file");
}
fcntl(shl_dbg_fd, F_SETFD, FD_CLOEXEC);
shf_fdopen(shl_dbg_fd, SHF_WR, shl_dbg);
int rv;
if (((rv = dup2(ofd, nfd)) < 0) && !errok && (errno != EBADF))
- errorf("too many files open in shell");
+ errorf(Ttoo_many_files);
#ifdef __ultrix
/*XXX imake style */
(errno == EBADF || errno == EPERM))
return (-1);
if (nfd < 0 || nfd > SHRT_MAX)
- errorf("too many files open in shell");
+ errorf(Ttoo_many_files);
fcntl(nfd, F_SETFD, FD_CLOEXEC);
return ((short)nfd);
}
pv[1] = savefd(lpv[1]);
if (pv[1] != lpv[1])
close(lpv[1]);
+#ifdef __OS2__
+ setmode(pv[0], O_BINARY);
+ setmode(pv[1], O_BINARY);
+#endif
}
void