rc-list - mailing list for the rc(1) shell
 help / color / mirror / Atom feed
From: Tom Culliton <culliton@clark.net>
To: byron@netapp.com, rc@hawkwind.utcs.toronto.edu
Subject: My patches for Linux, readline and signals (1 of 2)
Date: Wed, 5 Mar 1997 22:08:49 -0500	[thread overview]
Message-ID: <199703060308.WAA06759@clark.net> (raw)

(This is the first of two parts.  The first are my patches against
rc-1.5betadev-1, which are a collection of "fix only" patches from the
mailing list and my own work. The second is my Linux configuration,
which should also be generally useful for using readline and building
on Posix systems.  So without further ado...)

diff -rc rc-1.5betadev-1/builtins.c rc-1.5tjc/builtins.c
*** rc-1.5betadev-1/builtins.c	Sun Mar  6 22:32:49 1994
--- rc-1.5tjc/builtins.c	Wed Mar  5 21:02:10 1997
***************
*** 8,14 ****
  */
  
  #include <sys/ioctl.h>
- #include <setjmp.h>
  #include <errno.h>
  #include "rc.h"
  #include "jbwrap.h"
--- 8,13 ----
***************
*** 72,78 ****
  	Jbwrap j;
  	Estack e1, e2;
  	Edata jreturn, star;
! 	if (setjmp(j.j))
  		return;
  	starassign(*av, av+1, TRUE);
  	jreturn.jb = &j;
--- 71,77 ----
  	Jbwrap j;
  	Estack e1, e2;
  	Edata jreturn, star;
! 	if (rc_setjmp(j.j))
  		return;
  	starassign(*av, av+1, TRUE);
  	jreturn.jb = &j;
diff -rc rc-1.5betadev-1/except.c rc-1.5tjc/except.c
*** rc-1.5betadev-1/except.c	Sun Mar  6 22:32:50 1994
--- rc-1.5tjc/except.c	Wed Mar  5 20:38:33 1997
***************
*** 1,4 ****
- #include <setjmp.h>
  #include <signal.h>
  #include "rc.h"
  #include "jbwrap.h"
--- 1,3 ----
***************
*** 91,97 ****
  
  				interactive = estack->interactive;
  				estack = estack->prev;
! 				longjmp(j->j, 1);
  			}
  		}
  	rc_exit(1); /* top of exception stack */
--- 90,96 ----
  
  				interactive = estack->interactive;
  				estack = estack->prev;
! 				rc_longjmp(j->j, 1);
  			}
  		}
  	rc_exit(1); /* top of exception stack */
diff -rc rc-1.5betadev-1/exec.c rc-1.5tjc/exec.c
*** rc-1.5betadev-1/exec.c	Sun Mar  6 22:32:52 1994
--- rc-1.5tjc/exec.c	Wed Mar  5 20:39:26 1997
***************
*** 1,9 ****
  /* exec.c */
  #include <signal.h>
  #include <errno.h>
- #include <setjmp.h>
  #include "rc.h"
- #include "jbwrap.h"
  
  /*
     Takes an argument list and does the appropriate thing (calls a
--- 1,7 ----
diff -rc rc-1.5betadev-1/input.c rc-1.5tjc/input.c
*** rc-1.5betadev-1/input.c	Sun Mar  6 22:33:03 1994
--- rc-1.5tjc/input.c	Wed Mar  5 21:02:23 1997
***************
*** 1,7 ****
  /* input.c: i/o routines for files and pseudo-files (strings) */
  
  #include <errno.h>
- #include <setjmp.h>
  #include "rc.h"
  #include "jbwrap.h"
  
--- 1,6 ----
***************
*** 88,114 ****
  /* signal-safe readline wrapper */
  
  #ifdef READLINE
! #ifndef SVSIGS
  static char *rc_readline(char *prompt) {
  	char *r;
  	interrupt_happened = FALSE;
! 	if (!setjmp(slowbuf.j)) {
  		slow = TRUE;
  		if (!interrupt_happened)
  			r = readline(prompt);
! 		else
  			r = NULL;
! 	} else
  		r = NULL;
- 	slow = FALSE;
- 	if (r == NULL)
  		errno = EINTR;
  	sigchk();
  	return r;
  }
  #else
  #define rc_readline readline
- #endif /* SVSIGS */
  #endif /* READLINE */
  
  /*
--- 87,119 ----
  /* signal-safe readline wrapper */
  
  #ifdef READLINE
! int in_readline = 0;	/* a flag for readline clean up */
! 
  static char *rc_readline(char *prompt) {
  	char *r;
  	interrupt_happened = FALSE;
! 	if (!rc_setjmp(slowbuf.j)) {
  		slow = TRUE;
  		if (!interrupt_happened)
+ 		{
+ 			errno = 0;		/* this is relatively evil */
+ 			in_readline = TRUE;
  			r = readline(prompt);
! 			in_readline = FALSE;
! 		} else {
  			r = NULL;
! 			errno = EINTR;
! 		}
! 	} else {
  		r = NULL;
  		errno = EINTR;
+ 	}
+ 	slow = FALSE;
  	sigchk();
  	return r;
  }
  #else
  #define rc_readline readline
  #endif /* READLINE */
  
  /*
***************
*** 121,128 ****
  		while (1) {
  #ifdef READLINE
  			if (interactive && istack->fd == 0) {
! 				rlinebuf = readline(prompt);
  				if (rlinebuf == NULL) {
  					chars_in = 0;
  				} else {
  					if (*rlinebuf != '\0')
--- 126,135 ----
  		while (1) {
  #ifdef READLINE
  			if (interactive && istack->fd == 0) {
! 				rlinebuf = rc_readline(prompt);
  				if (rlinebuf == NULL) {
+ 					if (errno == EINTR)
+ 						continue;
  					chars_in = 0;
  				} else {
  					if (*rlinebuf != '\0')
***************
*** 140,145 ****
--- 147,154 ----
  				long /*ssize_t*/ r = rc_read(istack->fd, inbuf + 2, BUFSIZE);
  				sigchk();
  				if (r < 0) {
+ 					if (errno == EINTR)
+ 						continue;
  					uerror("read");
  					rc_exit(1);
  				}
***************
*** 255,261 ****
  	Edata jerror;
  	if (dashen)
  		execit = FALSE;
! 	setjmp(j.j);
  	jerror.jb = &j;
  	except(eError, jerror, &e1);
  	for (eof = FALSE; !eof;) {
--- 264,270 ----
  	Edata jerror;
  	if (dashen)
  		execit = FALSE;
! 	rc_setjmp(j.j);
  	jerror.jb = &j;
  	except(eError, jerror, &e1);
  	for (eof = FALSE; !eof;) {
***************
*** 279,288 ****
  			}
  			if ((s = varlookup("prompt")) != NULL) {
  #ifdef READLINE
! 				prompt = s->w;
! #else
! 				fprint(2, "%s", s->w);
  #endif
  				prompt2 = (s->n == NULL ? "" : s->n->w);
  			}
  		}
--- 288,298 ----
  			}
  			if ((s = varlookup("prompt")) != NULL) {
  #ifdef READLINE
! 				if (istack->fd == 0)
! 					prompt = s->w;
! 				else
  #endif
+ 					fprint(2, "%s", s->w);
  				prompt2 = (s->n == NULL ? "" : s->n->w);
  			}
  		}
***************
*** 301,306 ****
--- 311,329 ----
  	popinput();
  	unexcept(); /* eError */
  	return parsetree;
+ }
+ 
+ extern void print_prompt2() {
+ 	lineno++;
+ 	if (interactive)
+ 	{
+ #ifdef READLINE
+ 		if (istack->fd == 0)
+ 			prompt = prompt2;
+ 		else
+ #endif
+ 			fprint(2, "%s", prompt2);
+ 	}
  }
  
  /* parse a function imported from the environment */
diff -rc rc-1.5betadev-1/jbwrap.h rc-1.5tjc/jbwrap.h
*** rc-1.5betadev-1/jbwrap.h	Thu Dec 19 15:10:03 1991
--- rc-1.5tjc/jbwrap.h	Wed Mar  5 21:04:42 1997
***************
*** 1,10 ****
  /* certain braindamaged environments don't define jmp_buf as an array, so... */
  
  struct Jbwrap {
  	jmp_buf j;
  };
  
- extern Jbwrap slowbuf; /* for getting out of interrupts while performing slow i/o on BSD */
- 
  extern int setjmp(jmp_buf);
  extern void longjmp(jmp_buf, int);
--- 1,33 ----
  /* certain braindamaged environments don't define jmp_buf as an array, so... */
  
+ #include <setjmp.h>
+ #include "config.h"
+ 
+ #ifndef USESIGSETJMP
+ 
  struct Jbwrap {
  	jmp_buf j;
  };
  
  extern int setjmp(jmp_buf);
  extern void longjmp(jmp_buf, int);
+ 
+ #define rc_setjmp(a)		setjmp(a)
+ #define rc_longjmp(a, b)	longjmp(a, b)
+ 
+ #else
+ 
+ struct Jbwrap {
+ 	sigjmp_buf j;
+ };
+ 
+ /* extern int sigsetjmp(sigjmp_buf, int); */
+ /* extern void siglongjmp(sigjmp_buf, int); */
+ 
+ #define rc_setjmp(a)		sigsetjmp(a, 1)
+ #define rc_longjmp(a, b)	siglongjmp(a, b)
+ 
+ #endif
+ 
+ extern Jbwrap slowbuf; /* for getting out of interrupts while performing slow i/o on BSD */
+ 
diff -rc rc-1.5betadev-1/lex.c rc-1.5tjc/lex.c
*** rc-1.5betadev-1/lex.c	Sun Mar  6 22:33:05 1994
--- rc-1.5tjc/lex.c	Sat Feb 22 21:58:54 1997
***************
*** 336,351 ****
  		realbuf = ealloc(bufsize);
  }
  
- extern void print_prompt2() {
- 	lineno++;
- #ifdef READLINE
- 	prompt = prompt2;
- #else
- 	if (interactive)
- 		fprint(2, "%s", prompt2);
- #endif
- }
- 
  /*
     Scan in a pair of integers for redirections like >[2=1]. CLOSED represents a closed file
     descriptor (i.e., >[2=]) and UNSET represents an undesignated file descriptor (e.g.,
--- 336,341 ----
diff -rc rc-1.5betadev-1/print.c rc-1.5tjc/print.c
*** rc-1.5betadev-1/print.c	Sun Mar  6 22:33:10 1994
--- rc-1.5tjc/print.c	Wed Mar  5 21:11:13 1997
***************
*** 1,7 ****
  /* print.c -- formatted printing routines (Paul Haahr, 12/91) */
  
  #include "rc.h"
! #include <setjmp.h>
  
  #define	PRINT_ALLOCSIZE	((SIZE_T)64)
  #define	SPRINT_BUFSIZ	((SIZE_T)1024)
--- 1,7 ----
  /* print.c -- formatted printing routines (Paul Haahr, 12/91) */
  
  #include "rc.h"
! #include "jbwrap.h"
  
  #define	PRINT_ALLOCSIZE	((SIZE_T)64)
  #define	SPRINT_BUFSIZ	((SIZE_T)1024)
***************
*** 411,425 ****
  }
  
  static void snprint_grow(Format *format, SIZE_T more) {
! 	longjmp(format->u.p, 1);
  }
  
  extern int snprint(char *buf, int buflen, const char *fmt,...) {
  	int n;
! 	jmp_buf jbuf;
  	Format format;
  
! 	if (setjmp(jbuf)) {
  		*format.buf = '\0';
  		return format.buf - format.bufbegin;
  	}
--- 411,425 ----
  }
  
  static void snprint_grow(Format *format, SIZE_T more) {
! 	rc_longjmp(format->u.p, 1);
  }
  
  extern int snprint(char *buf, int buflen, const char *fmt,...) {
  	int n;
! 	Jbwrap jbuf;
  	Format format;
  
! 	if (rc_setjmp(jbuf.j)) {
  		*format.buf = '\0';
  		return format.buf - format.bufbegin;
  	}
***************
*** 429,435 ****
  	format.bufend	= buf + buflen - 1;
  	format.grow	= snprint_grow;
  	format.flushed	= 0;
! 	format.u.p	= jbuf;
  
  	va_start(format.args, fmt);
  	n = printfmt(&format, fmt);
--- 429,435 ----
  	format.bufend	= buf + buflen - 1;
  	format.grow	= snprint_grow;
  	format.flushed	= 0;
! 	format.u.p	= jbuf.j;
  
  	va_start(format.args, fmt);
  	n = printfmt(&format, fmt);
***************
*** 441,450 ****
  
  extern int sprint(char *buf, const char *fmt,...) {
  	int n;
! 	jmp_buf jbuf;
  	Format format;
  
! 	if (setjmp(jbuf)) {
  		*format.buf = '\0';
  		return format.buf - format.bufbegin;
  	}
--- 441,450 ----
  
  extern int sprint(char *buf, const char *fmt,...) {
  	int n;
! 	Jbwrap jbuf;
  	Format format;
  
! 	if (rc_setjmp(jbuf.j)) {
  		*format.buf = '\0';
  		return format.buf - format.bufbegin;
  	}
***************
*** 454,460 ****
  	format.bufend	= buf + SPRINT_BUFSIZ - 1;
  	format.grow	= snprint_grow;
  	format.flushed	= 0;
! 	format.u.p	= jbuf;
  
  	va_start(format.args, fmt);
  	n = printfmt(&format, fmt);
--- 454,460 ----
  	format.bufend	= buf + SPRINT_BUFSIZ - 1;
  	format.grow	= snprint_grow;
  	format.flushed	= 0;
! 	format.u.p	= jbuf.j;
  
  	va_start(format.args, fmt);
  	n = printfmt(&format, fmt);
diff -rc rc-1.5betadev-1/signal.c rc-1.5tjc/signal.c
*** rc-1.5betadev-1/signal.c	Sun Mar  6 22:33:16 1994
--- rc-1.5tjc/signal.c	Wed Mar  5 21:45:51 1997
***************
*** 1,7 ****
  /* signal.c: a Hugh-approved signal handler. */
  
  #include <signal.h>
- #include <setjmp.h>
  #include "rc.h"
  #include "sigmsgs.h"
  #include "jbwrap.h"
--- 1,6 ----
***************
*** 12,17 ****
--- 11,34 ----
  
  static volatile SIG_ATOMIC_T sigcount, caught[NUMOFSIGNALS];
  
+ /*
+ The situation with readline is fairly hairy... It tries to catch SIGINT,
+ SIGALRM SIGTSTP, SIGTTOU SIGTTIN, SIGCONT and SIGWINCH. The SIGWINCH
+ handler in readline assumes Berkley semantics and doesn't reset itself,
+ it also tries to daisy chain to the "old" signal handler (in this case
+ rc's catcher()), which will do lord only knows what, without cleaning up
+ the terminal settings.  The rest of the signals readline catches seem to
+ be well behaved.  However for any signal that readline doesn't catch,
+ the terminal is never reset!
+ 
+ Also for any caught signal, unless you treat it as a slow "system call"
+ and longjmp out of the signal handler, rc ignores it and resumes the
+ read.  This means that SIGINT does not abort input like it's supposed
+ to.  The way I've got it set up, all signals abort readline input and
+ clean up after themselves. I'm willing to entertain discussions on more
+ "proper" behaviour, but for now this is simple and predictable. ;-)
+ */
+ 
  extern void catcher(int s) {
  	if (caught[s] == 0) {
  		sigcount++;
***************
*** 19,27 ****
  	}
  	signal(s, catcher);
  	interrupt_happened = TRUE;
! #ifndef SVSIGS
! 	if (slow)
! 		longjmp(slowbuf.j, 1);
  #endif
  }
  
--- 36,70 ----
  	}
  	signal(s, catcher);
  	interrupt_happened = TRUE;
! #if defined(SVSIGS) || defined(READLINE)
! 	if (slow) {
! #if defined(READLINE)
! 		/* It's very important that readline is always */
! 		/* treated as a slow system call! */
! 		extern int rl_pending_input;
! 		extern int in_readline;
! 		if (in_readline) {
! 			in_readline = FALSE;	/* Not any more!!! */
! 	 		switch (s) {
! 			default:
! 				rl_clean_up_for_exit();
! 				rl_deprep_terminal();
! 				rl_clear_signals();	/* this should be OK */
! 				rl_pending_input = 0;
! 			/* readline already cleans up for these */
! 			case SIGINT:
! 			case SIGALRM:
! #if defined(SIGTSTP)
! 			case SIGTSTP:
! 			case SIGTTOU:
! 			case SIGTTIN:
! 				break;
! #endif	
! 			}
! 		}
! #endif
! 		rc_longjmp(slowbuf.j, 1);
! 	}
  #endif
  }
  
***************
*** 66,72 ****
  	void (*h)(int);
  	int i;
  	for (i = 1; i < NUMOFSIGNALS; i++) {
! 		if ((h = signal(i, SIG_DFL)) != SIG_DFL)
  			signal(i, h);
  		sighandlers[i] = h;
  	}
--- 109,115 ----
  	void (*h)(int);
  	int i;
  	for (i = 1; i < NUMOFSIGNALS; i++) {
! 		if ((h = signal(i, SIG_DFL)) != SIG_DFL && h != SIG_ERR)
  			signal(i, h);
  		sighandlers[i] = h;
  	}
diff -rc rc-1.5betadev-1/utils.c rc-1.5tjc/utils.c
*** rc-1.5betadev-1/utils.c	Sun Mar  6 22:33:19 1994
--- rc-1.5tjc/utils.c	Wed Mar  5 21:00:21 1997
***************
*** 1,7 ****
  /* utils.c: functions of general utility */
  
  #include <errno.h>
- #include <setjmp.h>
  #include "rc.h"
  #include "jbwrap.h"
  
--- 1,6 ----
***************
*** 71,77 ****
  	int i;
  	for (i = 0; remain > 0; buf += i, remain -= i) {
  		interrupt_happened = FALSE;
! 		if (!setjmp(slowbuf.j)) {
  			slow = TRUE;
  			if (interrupt_happened)
  				break;
--- 70,76 ----
  	int i;
  	for (i = 0; remain > 0; buf += i, remain -= i) {
  		interrupt_happened = FALSE;
! 		if (!rc_setjmp(slowbuf.j)) {
  			slow = TRUE;
  			if (interrupt_happened)
  				break;
***************
*** 88,94 ****
  extern int rc_read(int fd, char *buf, SIZE_T n) {
  	long /*ssize_t*/ r;
  	interrupt_happened = FALSE;
! 	if (!setjmp(slowbuf.j)) {
  		slow = TRUE;
  		if (!interrupt_happened)
  			r = read(fd, buf, n);
--- 87,93 ----
  extern int rc_read(int fd, char *buf, SIZE_T n) {
  	long /*ssize_t*/ r;
  	interrupt_happened = FALSE;
! 	if (!rc_setjmp(slowbuf.j)) {
  		slow = TRUE;
  		if (!interrupt_happened)
  			r = read(fd, buf, n);
diff -rc rc-1.5betadev-1/wait.c rc-1.5tjc/wait.c
*** rc-1.5betadev-1/wait.c	Sun Mar  6 22:33:23 1994
--- rc-1.5tjc/wait.c	Wed Mar  5 21:00:29 1997
***************
*** 1,5 ****
  #include <errno.h>
- #include <setjmp.h>
  #include "rc.h"
  #include "jbwrap.h"
  
--- 1,4 ----
***************
*** 112,118 ****
  static int rc_wait(int *stat) {
  	int r;
  	interrupt_happened = FALSE;
! 	if (!setjmp(slowbuf.j)) {
  		slow = TRUE;
  		if (!interrupt_happened)
  			r = wait(stat);
--- 111,117 ----
  static int rc_wait(int *stat) {
  	int r;
  	interrupt_happened = FALSE;
! 	if (!rc_setjmp(slowbuf.j)) {
  		slow = TRUE;
  		if (!interrupt_happened)
  			r = wait(stat);
diff -rc rc-1.5betadev-1/walk.c rc-1.5tjc/walk.c
*** rc-1.5betadev-1/walk.c	Sun Mar  6 22:33:26 1994
--- rc-1.5tjc/walk.c	Wed Mar  5 21:00:40 1997
***************
*** 1,7 ****
  /* walk.c: walks the parse tree. */
  
  #include <signal.h>
- #include <setjmp.h>
  #include "rc.h"
  #include "jbwrap.h"
  
--- 1,6 ----
***************
*** 108,114 ****
  			cond = oldcond;
  			break;
  		}
! 		if (setjmp(j.j))
  			break;
  		jbreak.jb = &j;
  		except(eBreak, jbreak, &e1);
--- 107,113 ----
  			cond = oldcond;
  			break;
  		}
! 		if (rc_setjmp(j.j))
  			break;
  		jbreak.jb = &j;
  		except(eBreak, jbreak, &e1);
***************
*** 131,137 ****
  		Jbwrap j;
  		Estack e1, e2;
  		Edata jbreak;
! 		if (setjmp(j.j))
  			break;
  		jbreak.jb = &j;
  		except(eBreak, jbreak, &e1);
--- 130,136 ----
  		Jbwrap j;
  		Estack e1, e2;
  		Edata jbreak;
! 		if (rc_setjmp(j.j))
  			break;
  		jbreak.jb = &j;
  		except(eBreak, jbreak, &e1);


                 reply	other threads:[~1997-03-06  3:09 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=199703060308.WAA06759@clark.net \
    --to=culliton@clark.net \
    --cc=byron@netapp.com \
    --cc=rc@hawkwind.utcs.toronto.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).