[comp.sys.sun] SunOS 4.0 rlogin out-of-band bug

abe@mace.cc.purdue.edu (Vic Abell) (01/04/89)

The rlogin supplied with SunOS 4.0 will dump core if it receives an
out-of-band signal (SIGURG) during startup.  This happens because rlogin
enables the handling of the SIGURG signal before it initializes a jump
buffer that the SIGURG handler exits through with a long jump.  The
attached context diffs to /usr/src/ucb/rlogin.c fix the problem.

*** rlogin.c.orig	Wed Dec 21 11:10:05 1988
--- /usr/src/ucb/rlogin.c	Thu Dec 22 11:06:25 1988
***************
*** 39,44 ****
--- 39,45 ----
  int	rem;
  char	cmdchar = '~';
  int	eight;
+ jmp_buf	rcvtop;
  int	litout;
  char	*speeds[] =
      { "0", "50", "75", "110", "134", "150", "200", "300",
***************
*** 126,132 ****
  	}
  	(void) ioctl(0, TIOCGWINSZ, &winsize);
  	signal(SIGPIPE, lostpeer);
! 	signal(SIGURG, oob);
  	oldmask = sigblock(sigmask(SIGURG));
          rem = rcmd(&host, htons(port_number), pwd->pw_name,
  	    name ? name : pwd->pw_name, term, 0);
--- 127,134 ----
  	}
  	(void) ioctl(0, TIOCGWINSZ, &winsize);
  	signal(SIGPIPE, lostpeer);
! 	if (setjmp(rcvtop) == 0)
! 		signal(SIGURG, oob);
  	oldmask = sigblock(sigmask(SIGURG));
          rem = rcmd(&host, htons(port_number), pwd->pw_name,
  	    name ? name : pwd->pw_name, term, 0);
***************
*** 188,195 ****
  	}
  	if (child == 0) {
  		mode(1);
! 		sigsetmask(oldmask);
! 		if (reader() == 0) {
  			prf("Connection closed.");
  			exit(0);
  		}
--- 190,196 ----
  	}
  	if (child == 0) {
  		mode(1);
! 		if (reader(oldmask) == 0) {
  			prf("Connection closed.");
  			exit(0);
  		}
***************
*** 394,401 ****
  char	rcvbuf[8 * 1024];
  int	rcvcnt;
  int	rcvstate;
! int	ppid;
! jmp_buf	rcvtop;

  oob()
  {
--- 395,401 ----
  char	rcvbuf[8 * 1024];
  int	rcvcnt;
  int	rcvstate;
! int	ppid = -1;

  oob()
  {
***************
*** 434,440 ****
  		/*
  		 * Let server know about window size changes
  		 */
! 		kill(ppid, SIGURG);
  	}
  	if (!eight && (mark & TIOCPKT_NOSTOP)) {
  		ioctl(0, TIOCGETP, (char *)&sb);
--- 434,441 ----
  		/*
  		 * Let server know about window size changes
  		 */
! 		if (ppid != -1)
! 			kill(ppid, SIGURG);
  	}
  	if (!eight && (mark & TIOCPKT_NOSTOP)) {
  		ioctl(0, TIOCGETP, (char *)&sb);
***************
*** 493,499 ****
  /*
   * reader: read from remote: line -> 1
   */
! reader()
  {
  	/*
  	 * 4.3bsd or later and SunOS 4.0 or later use the second
--- 494,500 ----
  /*
   * reader: read from remote: line -> 1
   */
! reader(oldmask)
  {
  	/*
  	 * 4.3bsd or later and SunOS 4.0 or later use the second
***************
*** 507,516 ****
  	int n, remaining;
  	char *bufp = rcvbuf;

- 	signal(SIGTTOU, SIG_IGN);
- 	fcntl(rem, F_SETOWN, pid);
  	ppid = getppid();
! 	(void) setjmp(rcvtop);
  	for (;;) {
  		while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
  			rcvstate = WRITING;
--- 508,519 ----
  	int n, remaining;
  	char *bufp = rcvbuf;

  	ppid = getppid();
! 	if (setjmp(rcvtop) == 0) {
! 		signal(SIGTTOU, SIG_IGN);
! 		sigsetmask(oldmask);
! 		fcntl(rem, F_SETOWN, pid);
! 	}
  	for (;;) {
  		while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
  			rcvstate = WRITING;