summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ksh/builtins/alias.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/ksh/builtins/alias.c')
-rw-r--r--usr/src/cmd/ksh/builtins/alias.c163
1 files changed, 162 insertions, 1 deletions
diff --git a/usr/src/cmd/ksh/builtins/alias.c b/usr/src/cmd/ksh/builtins/alias.c
index b477d7353c..dd789ef844 100644
--- a/usr/src/cmd/ksh/builtins/alias.c
+++ b/usr/src/cmd/ksh/builtins/alias.c
@@ -33,8 +33,122 @@
#include <shell.h>
#include <nval.h>
+#include <cmdext.h>
#include <stdio.h>
+typedef struct {
+ const char *name;
+ int (* func)(int, char **, void *);
+} bfastpathrec;
+
+/*
+ * We've disabled the "fastpath" codepath for some commands below
+ * because it causes a paradoxon for large input files (as used by
+ * ON PerfPIT for testing). For /usr/bin/rev (where the issue was
+ * first discovered) it looks like this:
+ * - for small files like /etc/profile the fastpath is faster in a loop
+ * with 1000 iterations (8 seconds with fastpath, 14 seconds without
+ * fastpath)
+ * - for large files (/usr/pub/UTF-8 replicated until the test file
+ * reaches 24884706 bytes) the benchmark reverses: The fastpath now
+ * needs 40 seconds and without fastpath it needs 30 seconds (for 100
+ * iterations).
+ */
+#if 0
+#define ENABLE_PERFORMANCE_PARADOXON 1
+#endif
+
+/*
+ * List of libcmd builtins which do not require a |Shell_t| context.
+ * This list was automatically generated from <ast/cmdext.h>
+ */
+static const
+bfastpathrec fastpath_builtins[] =
+{
+ /* This list must be alphabetically sorted for |strcmp()| usage */
+ { "basename", b_basename },
+ { "cat", b_cat },
+ { "chgrp", b_chgrp },
+ { "chmod", b_chmod },
+ { "chown", b_chown },
+#ifdef ENABLE_PERFORMANCE_PARADOXON
+ { "cksum", b_cksum },
+#endif /* ENABLE_PERFORMANCE_PARADOXON */
+ { "cmp", b_cmp },
+ { "comm", b_comm },
+ { "cp", b_cp },
+ { "cut", b_cut },
+ { "date", b_date },
+ { "dirname", b_dirname },
+ { "egrep", b_egrep },
+ { "expr", b_expr },
+ { "fds", b_fds },
+ { "fgrep", b_fgrep },
+ { "fmt", b_fmt },
+ { "fold", b_fold },
+ { "getconf", b_getconf },
+ { "grep", b_grep },
+ { "head", b_head },
+ { "id", b_id },
+ { "join", b_join },
+ { "ln", b_ln },
+ { "logname", b_logname },
+ { "md5sum", b_md5sum },
+ { "mkdir", b_mkdir },
+ { "mkfifo", b_mkfifo },
+ { "mktemp", b_mktemp },
+ { "mv", b_mv },
+ { "paste", b_paste },
+ { "pathchk", b_pathchk },
+ { "pids", b_pids },
+ { "readlink", b_readlink },
+#ifdef ENABLE_PERFORMANCE_PARADOXON
+ { "rev", b_rev },
+#endif /* ENABLE_PERFORMANCE_PARADOXON */
+ { "rm", b_rm },
+ { "rmdir", b_rmdir },
+ { "stty", b_stty },
+#ifdef ENABLE_PERFORMANCE_PARADOXON
+ { "sum", b_sum },
+#endif /* ENABLE_PERFORMANCE_PARADOXON */
+ { "sync", b_sync },
+ { "tail", b_tail },
+ { "tee", b_tee },
+ { "tty", b_tty },
+ { "uname", b_uname },
+ { "uniq", b_uniq },
+ { "wc", b_wc },
+ { "xgrep", b_xgrep },
+ { NULL, (int (*)(int, char **, void *))NULL }
+};
+
+static inline
+const bfastpathrec *
+find_bfastpathrec(const char *name)
+{
+ unsigned int i;
+ signed int cmpres;
+ for (i = 0; fastpath_builtins[i].name != NULL; i++) {
+ cmpres = strcmp(fastpath_builtins[i].name, name);
+ if (cmpres == 0)
+ return (&fastpath_builtins[i]);
+ else if (cmpres > 0)
+ return (NULL);
+
+ }
+ return (NULL);
+}
+
+static inline
+int
+fastpath_builtin_main(const bfastpathrec *brec, int argc, char *argv[])
+{
+ setlocale(LC_ALL, ""); /* calls |_ast_setlocale()| */
+
+ return ((*brec->func)(argc, argv, NULL));
+}
+
+
/* Builtin script, original derived from alias.sh */
static const char *script = "\n"
/* Get name of builtin */
@@ -58,12 +172,27 @@ static const char *script = "\n"
"if [[ \"${cmd}\" == \"command\" ]] ; then\n"
"command \"$@\"\n"
"else\n"
+#ifdef WORKAROUND_FOR_ALIAS_CRASH
+/*
+ * Work around a crash in /usr/bin/alias when invalid options are
+ * passed (e.g. $ /usr/bin/alias -c #). The shell code will call
+ * an error handler which does a |longjmp()| but somehow the code
+ * failed to do the |setjmp()| before this point.
+ * Putting the "alias" command in a subshell avoids the crash.
+ * Real cause of the issue is under investigation and a fix be
+ * delivered with the next ast-ksh update.
+ */
+ "( \"${cmd}\" \"$@\" )\n"
+#else
"\"${cmd}\" \"$@\"\n"
+#endif /* WORKAROUND_FOR_ALIAS_CRASH */
"fi\n"
"exitval=$?";
+
+static inline
int
-main(int argc, char *argv[])
+script_builtin_main(int argc, char *argv[])
{
int i;
Shell_t *shp;
@@ -98,3 +227,35 @@ main(int argc, char *argv[])
return (exitval);
}
+
+int
+main(int argc, char *argv[])
+{
+ const char *progname;
+ const bfastpathrec *brec;
+ char execnamebuff[PATH_MAX+1];
+
+ /* Get program name */
+ if (pathprog(argv[0], execnamebuff, sizeof (execnamebuff)) <= 0)
+ error(ERROR_exit(1), "could not determinate exec name.");
+
+ progname = (const char *)strrchr(execnamebuff, '/');
+ if (progname != NULL) {
+ progname++;
+ }
+ else
+ {
+ progname = execnamebuff;
+ }
+
+ /* Execute command... */
+ if (brec = find_bfastpathrec(progname)) {
+ /* ... either via a fast path (calling the code directly) ... */
+ return (fastpath_builtin_main(brec, argc, argv));
+ }
+ else
+ {
+ /* ... or from within a full shell. */
+ return (script_builtin_main(argc, argv));
+ }
+}