rc

[fork] interactive rc shell
Log | Files | Refs | README | LICENSE

commit 27c900d6ae9cd0dcf4bc97bc9b8c1882e40ccfa8
parent 3202133256713848312dddefba2250a6803bfec6
Author: Toby Goodwin <toby@paccrat.org>
Date:   Fri, 15 May 2015 19:36:55 +0100

snapshot from cvs: 2005-03-03

Diffstat:
MMakefile.am | 14++++++--------
Mbuiltins.c | 2+-
Mconfigure.ac | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Medit-gnu.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Medit-null.c | 59+++++++++++------------------------------------------------
Mhash.c | 11-----------
Mheredoc.c | 2+-
Minput.c | 84+++++++++++++++++++++++++++++--------------------------------------------------
Mlex.c | 10+++++-----
Mrc.1 | 9++++++++-
Mrc.h | 35+----------------------------------
Msignal.c | 19+++++++------------
Mvar.c | 8++++----
Mwhich.c | 20+++++++++++++++++++-
14 files changed, 227 insertions(+), 229 deletions(-)

diff --git a/Makefile.am b/Makefile.am @@ -1,5 +1,7 @@ ## Process this file with automake to produce Makefile.in +EDIT=@EDIT@ + if AMC_HISTORY man_MANS = rc.1 history.1 HISTORY = history @@ -11,10 +13,6 @@ if AMC_NO_HASHBANG EXECVE = execve.o endif -if AMC_READLINE -READLINE = readline.o -endif - if AMC_RESTART SYSTEM = system-bsd.o else @@ -26,12 +24,12 @@ noinst_PROGRAMS = mksignal mkstatval tripping $(HISTORY) rc_SOURCES = builtins.c except.c exec.c fn.c footobar.c getopt.c glob.c glom.c hash.c heredoc.c input.c lex.c list.c main.c match.c nalloc.c open.c parse.c print.c redir.c signal.c status.c tree.c utils.c var.c wait.c walk.c which.c -EXTRA_rc_SOURCES = addon.c execve.c readline.c system.c system-bsd.c +EXTRA_rc_SOURCES = addon.c edit-bsd.c edit-gnu.c edit-null.c execve.c system.c system-bsd.c -rc_DEPENDENCIES = sigmsgs.o $(ADDON) $(EXECVE) $(READLINE) $(SYSTEM) -rc_LDADD = sigmsgs.o $(ADDON) $(EXECVE) $(READLINE) $(SYSTEM) +rc_DEPENDENCIES = sigmsgs.o $(ADDON) $(EDIT) $(EXECVE) $(SYSTEM) +rc_LDADD = sigmsgs.o $(ADDON) $(EDIT) $(EXECVE) $(SYSTEM) -noinst_HEADERS = getgroups.h jbwrap.h parse.h proto.h rc.h rlimit.h stat.h wait.h +noinst_HEADERS = edit.h getgroups.h input.h jbwrap.h parse.h proto.h rc.h rlimit.h stat.h wait.h BUILT_SOURCES = sigmsgs.c diff --git a/builtins.c b/builtins.c @@ -395,8 +395,8 @@ extern void b_dot(char **av) { return; } starassign(*av, av+1, TRUE); - pushfd(fd); interactive = i; + pushfd(fd); star.name = "*"; except(eVarstack, star, &e); doit(TRUE); diff --git a/configure.ac b/configure.ac @@ -6,9 +6,9 @@ AC_DEFINE_UNQUOTED(RELDATE, "$RELDATE", [Release date]) dnl Automake stuff. dnl Use this one for snapshots... -dnl AM_INIT_AUTOMAKE(rc, 1.7s`echo $RELDATE |sed 's/-//g'`) +AM_INIT_AUTOMAKE(rc, 1.7s`echo $RELDATE |sed 's/-//g'`) dnl ...and this one for releases -AM_INIT_AUTOMAKE(rc, 1.7.1) +dnl AM_INIT_AUTOMAKE(rc, 1.7.1) AM_CONFIG_HEADER(config.h) @@ -90,7 +90,7 @@ no) RC_SYS_MKNOD_FIFO ;; esac dnl Now handle arguments. -AC_ARG_ENABLE(builtin-echo, [ --disable-builtin-echo Don't include \`echo' as a builtin], +AC_ARG_ENABLE(builtin-echo, [ --disable-builtin-echo Don't include `echo' as a builtin], test "x$enableval" != "xno" && AC_DEFINE(RC_ECHO, 1, [Define to 1 to include `echo' as a builtin.]), AC_DEFINE(RC_ECHO)) @@ -104,7 +104,7 @@ AC_ARG_ENABLE(protect-env, [ --disable-protect-env Don't protect environment AC_ARG_ENABLE(def-interp, [ --enable-def-interp=/bin/foo - Use /bin/foo as default interpreter [/bin/sh]], + Use /bin/foo as default interpreter [[/bin/sh]]], [ case "$enableval" in no) @@ -120,8 +120,8 @@ AC_ARG_ENABLE(def-interp, AC_ARG_ENABLE(def-path, [ --enable-def-path=\"/usr/local/bin/\",\"/usr/bin\" - Default path [All of these that exist - (/usr/local/bin /usr/bin /usr/bsd /usr/ucb /bin .)]], + Default path [[All of these that exist + (/usr/local/bin /usr/bin /usr/bsd /usr/ucb /bin .)]]], [ case "$enableval" in no|yes) ;; @@ -156,7 +156,7 @@ AC_ARG_WITH(history, AM_CONDITIONAL(AMC_HISTORY, test "$rc_history" = yes) -AC_ARG_WITH(addon, [ --with-addon[=foo.c] Extra builtins, from addon.c by default ],[ +AC_ARG_WITH(addon, [ --with-addon[[=foo.c]] Extra builtins, from addon.c by default ],[ case "$withval" in yes) ADDON=addon.o ;; no) ADDON='' ;; @@ -170,32 +170,69 @@ esac AC_SUBST(ADDON) -AC_ARG_WITH(editline, [ --with-editline Simmule Turner's line editing], - AC_CHECK_LIB(edit, readline, - AC_DEFINE(EDITLINE, 1, [Define to 1 if you are using `editline' or `vrl'.]) LIBS="$LIBS -ledit", - AC_MSG_ERROR(editline library not found))) +EDIT=edit-null.o +AC_ARG_WITH(edit, [ --with-edit=(bsd,edit,gnu,vrl) Command line editing library], [ + case $withval in + yes) + AC_MSG_ERROR(must specify which library) + # might consider searching + ;; + bsd) + EDIT=edit-bsd.o + RC_LIB_TGETENT + AC_CHECK_LIB(edit, el_init, [ + LIBS="$LIBS -ledit $rc_lib_tgetent" + ], AC_MSG_ERROR(editline library not found), $rc_lib_tgetent) + ;; + gnu) + EDIT=edit-gnu.o + RC_LIB_TGETENT + AC_CHECK_LIB(readline, readline, [ + LIBS="$LIBS -lreadline $rc_lib_tgetent" + ], AC_MSG_ERROR(readline library not found), $rc_lib_tgetent) + AC_TRY_LINK([ + #include <stdio.h> + #include <readline/readline.h> + ], [ + rl_catch_signals = 0; + ], [], AC_MSG_ERROR(readline >= 4.0 not found)) + ;; + no|null) + ;; + edit|vrl) + EDIT=edit-$withval.o + ;; + *) + AC_MSG_ERROR(unknown editing library $withval) + ;; + esac +]) +AC_SUBST(EDIT) +dnl AC_CHECK_LIB(edit, readline, +dnl AC_DEFINE(EDITLINE, 1, [Define to 1 if you are using `editline' or `vrl'.]) LIBS="$LIBS -ledit", +dnl AC_MSG_ERROR(editline library not found))) -if test "${with_vrl+set}" = set -o "${with_readline+set}" = set; then - RC_LIB_TGETENT -fi +dnl if test "${with_vrl+set}" = set -o "${with_readline+set}" = set; then +dnl RC_LIB_TGETENT +dnl fi -AC_ARG_WITH(vrl, [ --with-vrl Gert-Jan Vons's line editing], - AC_CHECK_LIB(vrl, readline, - AC_DEFINE(EDITLINE) LIBS="$LIBS -lvrl $rc_lib_tgetent", - AC_MSG_ERROR(vrl library not found), $rc_lib_tgetent)) +dnl AC_ARG_WITH(vrl, [ --with-vrl Gert-Jan Vons's line editing], +dnl AC_CHECK_LIB(vrl, readline, +dnl AC_DEFINE(EDITLINE) LIBS="$LIBS -lvrl $rc_lib_tgetent", +dnl AC_MSG_ERROR(vrl library not found), $rc_lib_tgetent)) dnl There are (at least) two incompatible versions of readline, and we dnl need to know which one we are using. We don't support readline 2.0. -AC_ARG_WITH(readline, [ --with-readline Bloated GNU line editing], [ - AC_CHECK_LIB(readline, readline, [ - AC_DEFINE(READLINE, 1, [Define to 1 if you are using GNU `readline'.]) - LIBS="$LIBS -lreadline $rc_lib_tgetent" - AC_CHECK_LIB(readline, _rl_clean_up_for_exit, , AC_DEFINE(READLINE_OLD, 1, [Define to 1 for older versions GNU `readline'.]), $rc_lib_tgetent) - ], AC_MSG_ERROR(readline library not found), $rc_lib_tgetent) -]) -AM_CONDITIONAL(AMC_READLINE, test "${with_readline+set}" = set) +dnl AC_ARG_WITH(readline, [ --with-readline Bloated GNU line editing], [ +dnl AC_CHECK_LIB(readline, readline, [ +dnl AC_DEFINE(READLINE, 1, [Define to 1 if you are using GNU `readline'.]) +dnl LIBS="$LIBS -lreadline $rc_lib_tgetent" +dnl AC_CHECK_LIB(readline, _rl_clean_up_for_exit, , AC_DEFINE(READLINE_OLD, 1, [Define to 1 for older versions GNU `readline'.]), $rc_lib_tgetent) +dnl ], AC_MSG_ERROR(readline library not found), $rc_lib_tgetent) +dnl ]) +dnl AM_CONDITIONAL(AMC_READLINE, test "${with_readline+set}" = set) dnl For some reason CPPFLAGS doesn't get propagated. -AC_SUBST(CPPFLAGS) +dnl AC_SUBST(CPPFLAGS) AC_OUTPUT(Makefile) diff --git a/edit-gnu.c b/edit-gnu.c @@ -1,38 +1,84 @@ #include "rc.h" +#include <errno.h> #include <stdio.h> #include <readline/readline.h> +#include <readline/history.h> -#include "jbwrap.h" +#include "edit.h" -struct Jbwrap rl_buf; -volatile sig_atomic_t rl_active; +bool editing = 1; + +struct cookie { + char *buffer; +}; + +void *edit_begin(int fd) { + List *hist; + struct cookie *c; -void edit_init(void *ignored) { rl_catch_signals = 0; + + hist = varlookup("history"); + if (hist != NULL) + if (read_history(hist->w) != 0 && errno != ENOENT) /* ignore if missing */ + uerror(hist->w); + + c = ealloc(sizeof *c); + c->buffer = NULL; + return c; } -char *edit_getline(void *ignored, char *prompt) { - char *r = NULL; - int s; - - if ((s = sigsetjmp(rl_buf.j, 1)) == 0) { - rl_active = TRUE; - r = readline(prompt); - } else { - rl_free_line_state(); - rl_cleanup_after_signal(); - rl_active = FALSE; - rc_raise(eError); - } +static void edit_catcher(int sig) { + write(2, "\n", 1); + rc_raise(eError); +} + +static char *prompt; + +char *edit_alloc(void *cookie, int *count) { + struct cookie *c = cookie; + void (*oldint)(int), (*oldquit)(int); + + oldint = sys_signal(SIGINT, edit_catcher); + oldquit = sys_signal(SIGQUIT, edit_catcher); + + c->buffer = readline(prompt); - if (r) { - r = erealloc(r, strlen(r) + 2); /* 1 for \n + 1 for \0 */ - strcat(r, "\n"); + sys_signal(SIGINT, oldint); + sys_signal(SIGQUIT, oldquit); + + if (c->buffer) { + *count = strlen(c->buffer); + if (*count) + add_history(c->buffer); + c->buffer[*count] = '\n'; + ++*count; /* include the \n */ } - return r; + return c->buffer; +} + +void edit_prompt(void *cookie, char *pr) { + prompt = pr; +} + +void edit_free(void *cookie) { + struct cookie *c = cookie; + + efree(c->buffer); + /* Set c->buffer to NULL, allowing us to "overfree" it. This + is a bit of a kludge, but it's otherwise hard to deal with + the case where a signal causes an early return from + readline. */ + c->buffer = NULL; +} + +void edit_end(void *cookie) { + struct cookie *c = cookie; + + efree(c); } -void edit_free(void *ignored, void *buffer) { - efree(buffer); +void edit_reset(void *cookie) { + rl_reset_terminal(NULL); } diff --git a/edit-null.c b/edit-null.c @@ -8,65 +8,28 @@ bool editing = 0; -void *edit_init(int fd) { - /* this function deliberately left blank */ +void *edit_begin(int fd) { + assert(0); /* should never be called */ return NULL; } char *edit_alloc(void *cookie, int *count) { - char *buf; - int size, used; - ssize_t r; - - used = 0; - size = 1; - buf = ealloc(size + 1); /* leave room for terminating \0 */ - do { - if (used >= size) { /* >= leaves room for terminating \0 */ - size = size * 2; - buf = erealloc(buf, size); - } - do { - r = rc_read(0, buf + used, size - used); - sigchk(); - if (r == -1) - switch (errno) { - case EAGAIN: - if (!makeblocking(0)) - panic("not O_NONBLOCK"); - errno = EINTR; - break; - case EIO: - if (makesamepgrp(0)) - errno = EINTR; - else - errno = EIO; - break; - } - } while (r < 0 && errno == EINTR); - - if (r == 0) - return NULL; - - used += r; - buf[used] = '\0'; - } while (strchr(buf, '\n') == NULL); - - *count = used; - if (used) - return buf; - else - return NULL; + assert(0); /* should never be called */ + return NULL; } void edit_prompt(void *cookie, char *prompt) { - fprint(2, "%s", prompt); + assert(0); /* should never be called */ } void edit_free(void *buffer) { - efree(buffer); + assert(0); /* should never be called */ } void edit_end(void *cookie) { - /* this function deliberately left blank */ + assert(0); /* should never be called */ +} + +void edit_reset(void *cookie) { + assert(0); /* should never be called */ } diff --git a/hash.c b/hash.c @@ -315,14 +315,3 @@ extern void whatare_all_vars(bool showfn, bool showvar) { if (fp[i].name != NULL && fp[i].name != dead) prettyprint_fn(1, fp[i].name, fnlookup(fp[i].name)); } - -/* fake getenv() for readline() follows: */ - -#if EDITLINE || READLINE -extern char *getenv(const char *name) { - List *s; - if (name == NULL || vp == NULL || (s = varlookup((char *) name)) == NULL) - return NULL; - return s->w; -} -#endif diff --git a/heredoc.c b/heredoc.c @@ -42,7 +42,7 @@ static char *readheredoc(char *eof) { bufend = &buf[bufsize]; \ } for (;;) { - print_prompt2(); + nextline(); for (s = (unsigned char *) eof; (c = gchar()) == *s; s++) ; if (*s == '\0' && (c == '\n' || c == EOF)) { diff --git a/input.c b/input.c @@ -8,31 +8,28 @@ #include "input.h" #include "jbwrap.h" -/* - NB: character unget is supported for up to two characters, but NOT - in the case of EOF. Since EOF does not fit in a char, it is easiest - to support only one unget of EOF. -*/ +/* How many characters can we unget? */ +enum { UNGETSIZE = 2 }; typedef enum inputtype { iFd, iString, iEdit } inputtype; typedef struct Input { - bool saved, eofread; + bool saved; inputtype t; - int fd, index, read, lineno, last; + int fd, index, read, ungetcount, lineno, last; char *ibuf; void *cookie; + int ungetbuf[UNGETSIZE]; int (*gchar)(void); - void (*ugchar)(int); } Input; #define BUFSIZE ((size_t) 256) static char *inbuf; static size_t istacksize, chars_out, chars_in; -static bool eofread = FALSE, save_lineno = TRUE; +static bool save_lineno = TRUE; static Input *istack, *itop; int lastchar; @@ -40,24 +37,15 @@ int lastchar; static char *prompt, *prompt2; extern void ugchar(int c) { - if (c == EOF) - eofread = TRUE; - else - (*istack->ugchar)(c); -} - -static void fdstringugchar(int c) { - assert(chars_out); - inbuf[--chars_out] = c; + assert(istack->ungetcount < UNGETSIZE); + istack->ungetbuf[istack->ungetcount++] = c; } extern int gchar() { int c; - if (eofread) { - eofread = FALSE; - return lastchar = EOF; - } + if (istack->ungetcount) + return lastchar = istack->ungetbuf[--istack->ungetcount]; while ((c = (*istack->gchar)()) == '\0') pr_error("warning: null character ignored", 0); @@ -65,6 +53,7 @@ extern int gchar() { return c; } + /* get the next character from a string. */ static int stringgchar() { @@ -82,7 +71,7 @@ static void history() { return; for (a = 0; a < chars_in; a++) { - char c = inbuf[a+2]; + char c = inbuf[a]; /* skip empty lines and comments */ if (c == '#' || c == '\n') @@ -92,11 +81,10 @@ static void history() { if (c != ' ' && c != '\t') { char *name = hist->w; int fd = rc_open(name, rAppend); - if (fd < 0) { + if (fd < 0) uerror(name); - varrm(name, TRUE); - } else { - writeall(fd, inbuf + 2, chars_in); + else { + writeall(fd, inbuf, chars_in); close(fd); } break; @@ -104,13 +92,14 @@ static void history() { } } + /* read a character from a file descriptor */ static int fdgchar() { - if (chars_out >= chars_in + 2) { /* replenish empty buffer */ + if (chars_out >= chars_in) { /* replenish empty buffer */ ssize_t r; do { - r = rc_read(istack->fd, inbuf + 2, BUFSIZE); + r = rc_read(istack->fd, inbuf, BUFSIZE); sigchk(); if (r == -1) switch (errno) { @@ -134,31 +123,18 @@ static int fdgchar() { chars_in = (size_t) r; if (chars_in == 0) return lastchar = EOF; - chars_out = 2; + chars_out = 0; if (dashvee) - writeall(2, inbuf + 2, chars_in); + writeall(2, inbuf, chars_in); history(); } return lastchar = inbuf[chars_out++]; } -enum { UNGETSIZE = 2 }; -static int ungetbuf[UNGETSIZE]; -static int ungetcount = 0; - -static void editugchar(int c) { - fprint(2, "in editugchar, with c = %d and ungetcount = %d\n", c, ungetcount); - assert(ungetcount < UNGETSIZE); - ungetbuf[ungetcount++] = c; -} - /* read a character from a line-editing file descriptor */ static int editgchar() { - if (ungetcount) - return lastchar = ungetbuf[--ungetcount]; - if (chars_out >= chars_in) { /* replenish empty buffer */ edit_free(istack->cookie); inbuf = edit_alloc(istack->cookie, &chars_in); @@ -182,11 +158,12 @@ void termchange(void) { edit_reset(istack->cookie); } + /* set up the input stack, and put a "dead" input at the bottom, so that yyparse will always read eof */ extern void initinput() { istack = itop = ealloc(istacksize = 256 * sizeof (Input)); - istack->eofread = TRUE; + ugchar(EOF); } /* push an input source onto the stack. set up a new input buffer, and set gchar() */ @@ -199,15 +176,15 @@ static void pushcommon() { istack->lineno = lineno; istack->saved = save_lineno; istack->last = lastchar; - istack->eofread = eofread; istack++; idiff = istack - itop; if (idiff >= istacksize / sizeof (Input)) { itop = erealloc(itop, istacksize *= 2); istack = itop + idiff; } - chars_out = 2; + chars_out = 0; chars_in = 0; + istack->ungetcount = 0; } extern void pushfd(int fd) { @@ -218,13 +195,11 @@ extern void pushfd(int fd) { if (editing && interactive && isatty(fd)) { istack->t = iEdit; istack->gchar = editgchar; - istack->ugchar = editugchar; istack->cookie = edit_begin(fd); } else { istack->t = iFd; istack->gchar = fdgchar; - istack->ugchar = fdstringugchar; - inbuf = ealloc(BUFSIZE + 2); + inbuf = ealloc(BUFSIZE); } } @@ -232,15 +207,15 @@ extern void pushstring(char **a, bool save) { pushcommon(); istack->t = iString; save_lineno = save; - inbuf = mprint("..%A", a); + inbuf = mprint("%A", a); istack->gchar = stringgchar; - istack->ugchar = fdstringugchar; if (save_lineno) lineno = 1; else --lineno; } + /* remove an input source from the stack. restore associated variables etc. */ extern void popinput() { @@ -251,7 +226,6 @@ extern void popinput() { efree(inbuf); --istack; lastchar = istack->last; - eofread = istack->eofread; inbuf = istack->ibuf; chars_out = istack->index; chars_in = istack->read; @@ -262,6 +236,7 @@ extern void popinput() { save_lineno = istack->saved; } + /* flush input characters upto newline. Used by scanerror() */ extern void skiptonl() { @@ -274,6 +249,7 @@ extern void skiptonl() { ugchar(c); } + /* the wrapper loop in rc: prompt for commands until EOF, calling yyparse and walk() */ extern Node *doit(bool clobberexecit) { @@ -367,6 +343,8 @@ extern void closefds() { } } +/* print (or set) prompt(2) */ + extern void nextline() { lineno++; if (interactive) { diff --git a/lex.c b/lex.c @@ -99,8 +99,8 @@ extern int yylex() { meta = (dollar ? dnw : nw); dollar = FALSE; if (newline) { - --lineno; /* slight space optimization; print_prompt2() always increments lineno */ - print_prompt2(); + --lineno; /* slight space optimization; nextline() always increments lineno */ + nextline(); newline = FALSE; } top: while ((c = gchar()) == ' ' || c == '\t') @@ -120,7 +120,7 @@ top: while ((c = gchar()) == ' ' || c == '\t') } while ((c = gchar()) != EOF && !meta[(unsigned char) c]); while (c == '\\') { if ((c = gchar()) == '\n') { - print_prompt2(); + nextline(); c = ' '; /* Pretend a space was read */ break; } else { @@ -198,7 +198,7 @@ top: while ((c = gchar()) == ' ' || c == '\t') while ((c = gchar()) != '\'' || (c = gchar()) == '\'') { buf[i++] = c; if (c == '\n') - print_prompt2(); + nextline(); if (c == EOF) { w = NW; scanerror("eof in quoted string"); @@ -215,7 +215,7 @@ top: while ((c = gchar()) == ' ' || c == '\t') return WORD; case '\\': if ((c = gchar()) == '\n') { - print_prompt2(); + nextline(); goto top; /* Pretend it was just another space. */ } ugchar(c); diff --git a/rc.1 b/rc.1 @@ -2056,8 +2056,15 @@ The .Cr limit builtin silently ignores extra arguments. .PP +Backquote substitution never produces empty strings - multiple +consecutive occurrences of the separator are treated the same as a +single occurrence. +.Ds +.Cr "ifs=! { x = `{echo -n a!!b}; whatis x }" +.Cr "x=(a b) # NOT x=(a '' b)" +.PP Bug reports should be mailed to -.Cr "<tjg@star.le.ac.uk>" . +.Cr "<tjg@ast.cam.ac.uk>" . .SH INCOMPATIBILITIES Here is a list of features which distinguish this incarnation of .I rc diff --git a/rc.h b/rc.h @@ -46,10 +46,6 @@ typedef enum bool { FALSE, TRUE } bool; -typedef enum inputtype { - iFd, iString -} inputtype; - typedef enum redirtype { rFrom, rCreate, rAppend, rHeredoc, rHerestring } redirtype; @@ -326,38 +322,8 @@ extern int yyparse(void); extern void initparse(void); /* readline */ - -#if READLINE - -/* Including the real readline .h files is too complicated, so we just -declare what we actually use. */ - -extern void add_history(char *); -extern char *readline(char *); -extern int rl_clear_signals(void); -extern int rl_pending_input; -extern int rl_reset_terminal(char *); - -#if READLINE_OLD -extern void rl_clean_up_for_exit(void); -extern void rl_deprep_terminal(void); -#else -extern void _rl_clean_up_for_exit(void); -extern void (*rl_deprep_term_function)(void); -#endif - -extern char *rc_readline(char *); - extern volatile sig_atomic_t rl_active; extern struct Jbwrap rl_buf; -#endif - -#if EDITLINE -extern char *readline(char *); -extern void add_history(char *); -#define rc_readline readline -#endif - /* redir.c */ extern void doredirs(void); @@ -368,6 +334,7 @@ extern void initsignal(void); extern void catcher(int); extern void sigchk(void); extern void (*rc_signal(int, void (*)(int)))(int); +extern void (*sys_signal(int, void (*)(int)))(int); extern void (*sighandlers[])(int); diff --git a/signal.c b/signal.c @@ -9,7 +9,7 @@ #include "jbwrap.h" #if HAVE_SIGACTION -static void (*sys_signal(int signum, void (*handler)(int)))(int) { +void (*sys_signal(int signum, void (*handler)(int)))(int) { struct sigaction new, old; new.sa_handler = handler; @@ -19,7 +19,9 @@ static void (*sys_signal(int signum, void (*handler)(int)))(int) { return old.sa_handler; } #else -#define sys_signal(sig, func) (signal((sig), (func))) +void (*sys_signal(int signum, void (*handler)(int)))(int) { + return signal(signum, handler); +} #endif void (*sighandlers[NUMOFSIGNALS])(int); @@ -33,11 +35,6 @@ extern void catcher(int s) { } sys_signal(s, catcher); -#if READLINE - if (rl_active) - siglongjmp(rl_buf.j, s); -#endif /* READLINE */ - #if HAVE_RESTARTABLE_SYSCALLS if (slow) { siglongjmp(slowbuf.j, s); @@ -73,13 +70,11 @@ extern void (*rc_signal(int s, void (*h)(int)))(int) { void (*old)(int); sigchk(); old = sighandlers[s]; - if (h == SIG_DFL || h == SIG_IGN) { - sighandlers[s] = h; + sighandlers[s] = h; + if (h == SIG_DFL || h == SIG_IGN) sys_signal(s, h); - } else { - sighandlers[s] = h; + else sys_signal(s, catcher); - } return old; } diff --git a/var.c b/var.c @@ -2,6 +2,8 @@ #include "rc.h" +#include "input.h" + static void colonassign(char *, List *, bool); static void listassign(char *, List *, bool); static int hasalias(char *); @@ -19,10 +21,8 @@ extern void varassign(char *name, List *def, bool stack) { new->def = newdef; new->extdef = NULL; set_exportable(name, TRUE); -#if READLINE - if (interactive && (streq(name, "TERM") || streq(name, "TERMCAP"))) - rl_reset_terminal(NULL); -#endif + if (streq(name, "TERM") || streq(name, "TERMCAP")) + termchange(); } /* assign a variable in string form. Check to see if it is aliased (e.g., PATH and path) */ diff --git a/which.c b/which.c @@ -70,6 +70,24 @@ static bool rc_access(char *path, bool verbose) { return FALSE; } +static char *protect(char *in) { + char *out = ealloc(strlen(in) * 2 + 1); + + int i; + int p = 0; + + for (i = 0; i < strlen(in); ++i) { + if (isprint(in[i])) { + out[p++] = in[i]; + ++p; + } else { + out[p++] = '\\'; + out[p++] = '?'; + } + } + return out; /* XXXX */ +} + /* return a full pathname by searching $path, and by checking the status of the file */ extern char *which(char *name, bool verbose) { @@ -120,6 +138,6 @@ extern char *which(char *name, bool verbose) { return test; } if (verbose) - fprint(2, "%s not found\n", name); + fprint(2, "rc: cannot find `%s'\n", protect(name)); return NULL; }