🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: net.emacs
Article #2134

Re: GNU Emacs hanging...

#2134
From: Chris Torek
Date: Fri, 17 Oct 1986 04:53
707 lines
17934 bytes
In article <1456@jade.BERKELEY.EDU> mwm@eris.berkeley.edu (Mike Meyer) writes:
>Ditto, except for more data points:
>
>rlogged in from either a Sun-3 any of a 4.[23] 750, a 4.3beta 8600, a
>4.3 8600, or an Ultrix 2.0beta 8800. Also from a uvax ][ to either a
>4.2 750 or a 4.3beta 8600.

I cannot quite parse that, but I gather the problem shows when running
rlogin within a window, whenever the remote host is `fast'.

>I suspect a kernel bug, myself, but would be interested to see any
>solution.

Rlogin bugs are more likely.  The 4.2 version was thoroughly broken.
The 4.3 version was significantly reworked but still not quite
right.  The Sun version was hopeless; I replaced it with a fixed 4.3
version.  I know naught of the Ultrix rlogin.

The Solution (as far as I know):

Copy your 4.3 rlogin.c and your 4.3 /usr/src/lib/libc/net/rcmd.c
files to your Sun or uVax-II.  Apply the changes shown below to
rlogin.c.  Compile rlogin.c and rcmd.c to .o's, then link together
and test.  This requires super-user privileges (alas!).  You may
discover that you need to reverse the sense of the `pid' arguments
to the fcntl(F_SETOWN) calls; I forget whether they work as is on
the Suns.  (4.2 had pid and pgrp logically reversed; `fixed in 4.3'
means `incompatible with 4.2'.  So it goes.)

You may want to pull out the `isswitch' code.  We used to use a
local hack to allow remote logins without local accounts, by adding
/etc/passwd entries of the form

	imladris::20:199:& Switch:/tmp:/usr/ucb/rswtch

Logging in as `imladris' (ah, the name evokes such memories) would
send you over to my Sun-3/50, where you would then be asked for a
login name and password.  We now have a different local hack; I just
log in as `chris@imladris' if I wish.

Anyway, here are the fixes for a 4.3 rlogin.c.  Do not be concerned
by the size: I fixed all the lint fluff, and reworked some of the
Sun-specific window code for readability.

*** /x/chris/4.3tape/src/ucb/rlogin.c	Sun Mar 30 19:39:06 1986
--- rlogin.c	Thu Aug  7 02:24:40 1986
***************
*** 22,25 ****
--- 22,27 ----
  #include <sys/file.h>
  #include <sys/socket.h>
+ #include <sys/time.h>
+ #include <sys/resource.h>
  #include <sys/wait.h>
  
***************
*** 38,42 ****
  # endif TIOCPKT_WINDOW
  
! char	*index(), *rindex(), *malloc(), *getenv();
  struct	passwd *getpwuid();
  char	*name;
--- 40,49 ----
  # endif TIOCPKT_WINDOW
  
! /* concession to sun */
! # ifndef SIGUSR1
! # define SIGUSR1 30
! # endif SIGUSR1
! 
! char	*index(), *rindex(), *malloc(), *getenv(), *strcat(), *strcpy();
  struct	passwd *getpwuid();
  char	*name;
***************
*** 43,46 ****
--- 50,54 ----
  int	rem;
  char	cmdchar = '~';
+ int	isswitch;
  int	eight;
  int	litout;
***************
*** 56,60 ****
  #endif
  #ifdef sun
- struct	ttysize winsize;
  struct winsize {
  	unsigned short ws_row, ws_col;
--- 64,67 ----
***************
*** 61,69 ****
  	unsigned short ws_xpixel, ws_ypixel;
  };
- #else sun
- struct	winsize winsize;
  #endif sun
  int	sigwinch(), oob();
  
  main(argc, argv)
  	int argc;
--- 68,101 ----
  	unsigned short ws_xpixel, ws_ypixel;
  };
  #endif sun
+ struct	winsize winsize;
  int	sigwinch(), oob();
  
+ /*
+  * The following routine provides compatibility (such as it is)
+  * between 4.2BSD Suns and others.  Suns have only a `ttysize',
+  * so we convert it to a winsize.
+  */
+ #ifdef sun
+ int
+ get_window_size(fd, wp)
+ 	int fd;
+ 	struct winsize *wp;
+ {
+ 	struct ttysize ts;
+ 	int error;
+ 
+ 	if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0)
+ 		return (error);
+ 	wp->ws_row = ts.ts_lines;
+ 	wp->ws_col = ts.ts_cols;
+ 	wp->ws_xpixel = 0;
+ 	wp->ws_ypixel = 0;
+ 	return (0);
+ }
+ #else sun
+ #define get_window_size(fd, wp)	ioctl(fd, TIOCGWINSZ, wp)
+ #endif sun
+ 
  main(argc, argv)
  	int argc;
***************
*** 85,88 ****
--- 117,143 ----
  	if (!strcmp(host, "rlogin"))
  		host = *argv++, --argc;
+ 	else if (!strcmp(host, "rswtch")) {
+ 		printf("You really don't want to run this.\n");
+ 		exit(1);
+ 	} else if (argc == 0 && host[0] == '-') {
+ 		static char namebuf[128];
+ 		char *getlogin();
+ 
+ 		/*
+ 		 * This is a hack.  If you log in with "rswtch" as
+ 		 * your shell, we assume you really want to remotely
+ 		 * log in to some other host.  This disables commands
+ 		 * and makes us prompt for a login name.
+ 		 */
+ 		if ((host = getlogin()) == NULL) {
+ 			printf("Oops - getlogin\n");
+ 			exit(1);
+ 		}
+ 		isswitch++;
+ 		(void) printf("Remote login name: ");
+ 		(void) fflush(stdout);
+ 		(void) gets(namebuf);
+ 		name = namebuf;
+ 	}
  another:
  	if (argc > 0 && !strcmp(*argv, "-d")) {
***************
*** 117,124 ****
  	if (argc > 0)
  		goto usage;
! 	pwd = getpwuid(getuid());
! 	if (pwd == 0) {
! 		fprintf(stderr, "Who are you?\n");
! 		exit(1);
  	}
  	sp = getservbyname("login", "tcp");
--- 172,181 ----
  	if (argc > 0)
  		goto usage;
! 	if (!isswitch) {
! 		pwd = getpwuid(getuid());
! 		if (pwd == 0) {
! 			fprintf(stderr, "Who are you?\n");
! 			exit(1);
! 		}
  	}
  	sp = getservbyname("login", "tcp");
***************
*** 129,146 ****
  	cp = getenv("TERM");
  	if (cp)
! 		strcpy(term, cp);
  	if (ioctl(0, TIOCGETP, &ttyb) == 0) {
! 		strcat(term, "/");
! 		strcat(term, speeds[ttyb.sg_ospeed]);
  	}
! #ifdef sun
! 	(void) ioctl(0, TIOCGSIZE, &winsize);
! #else sun
! 	(void) ioctl(0, TIOCGWINSZ, &winsize);
! #endif sun
! 	signal(SIGPIPE, lostpeer);
! 	signal(SIGURG, oob);
! 	oldmask = sigblock(sigmask(SIGURG));
!         rem = rcmd(&host, sp->s_port, pwd->pw_name,
  	    name ? name : pwd->pw_name, term, 0);
          if (rem < 0)
--- 186,199 ----
  	cp = getenv("TERM");
  	if (cp)
! 		(void) strcpy(term, cp);
  	if (ioctl(0, TIOCGETP, &ttyb) == 0) {
! 		(void) strcat(term, "/");
! 		(void) strcat(term, speeds[ttyb.sg_ospeed]);
  	}
! 	(void) get_window_size(0, &winsize);
! 	(void) signal(SIGPIPE, lostpeer);
! 	/* will use SIGUSR1 for window size hack, so hold it off */
! 	oldmask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1));
!         rem = rcmd(&host, sp->s_port, isswitch ? "anybody" : pwd->pw_name,
  	    name ? name : pwd->pw_name, term, 0);
          if (rem < 0)
***************
*** 166,170 ****
  int	child;
  int	catchild();
! int	writeroob();
  
  int	defflags, tabflag;
--- 219,223 ----
  int	child;
  int	catchild();
! int	copytochild(), writeroob();
  
  int	defflags, tabflag;
***************
*** 181,185 ****
  	struct sgttyb sb;
  
! 	ioctl(0, TIOCGETP, (char *)&sb);
  	defflags = sb.sg_flags;
  	tabflag = defflags & TBDELAY;
--- 234,238 ----
  	struct sgttyb sb;
  
! 	(void) ioctl(0, TIOCGETP, (char *)&sb);
  	defflags = sb.sg_flags;
  	tabflag = defflags & TBDELAY;
***************
*** 187,198 ****
  	deferase = sb.sg_erase;
  	defkill = sb.sg_kill;
! 	ioctl(0, TIOCLGET, (char *)&deflflags);
! 	ioctl(0, TIOCGETC, (char *)&deftc);
  	notc.t_startc = deftc.t_startc;
  	notc.t_stopc = deftc.t_stopc;
! 	ioctl(0, TIOCGLTC, (char *)&defltc);
! 	signal(SIGINT, SIG_IGN);
! 	signal(SIGHUP, exit);
! 	signal(SIGQUIT, exit);
  	child = fork();
  	if (child == -1) {
--- 240,251 ----
  	deferase = sb.sg_erase;
  	defkill = sb.sg_kill;
! 	(void) ioctl(0, TIOCLGET, (char *)&deflflags);
! 	(void) ioctl(0, TIOCGETC, (char *)&deftc);
  	notc.t_startc = deftc.t_startc;
  	notc.t_stopc = deftc.t_stopc;
! 	(void) ioctl(0, TIOCGLTC, (char *)&defltc);
! 	(void) signal(SIGINT, SIG_IGN);
! 	setsignal(SIGHUP, exit);
! 	setsignal(SIGQUIT, exit);
  	child = fork();
  	if (child == -1) {
***************
*** 202,207 ****
  	if (child == 0) {
  		mode(1);
! 		sigsetmask(oldmask);
! 		if (reader() == 0) {
  			prf("Connection closed.");
  			exit(0);
--- 255,259 ----
  	if (child == 0) {
  		mode(1);
! 		if (reader(oldmask) == 0) {
  			prf("Connection closed.");
  			exit(0);
***************
*** 211,217 ****
  		exit(3);
  	}
! 	signal(SIGURG, writeroob);
! 	sigsetmask(oldmask);
! 	signal(SIGCHLD, catchild);
  	writer();
  	prf("Closed connection.");
--- 263,277 ----
  		exit(3);
  	}
! 
! 	/*
! 	 * We may still own the socket, and may have a pending SIGURG
! 	 * (or might receive one soon) that we really want to send to
! 	 * the reader.  Set a trap that simply copies such signals to
! 	 * the child.
! 	 */
! 	(void) signal(SIGURG, copytochild);
! 	(void) signal(SIGUSR1, writeroob);
! 	(void) sigsetmask(oldmask);
! 	(void) signal(SIGCHLD, catchild);
  	writer();
  	prf("Closed connection.");
***************
*** 219,229 ****
  }
  
  done(status)
  	int status;
  {
  
  	mode(0);
! 	if (child > 0 && kill(child, SIGKILL) >= 0)
! 		wait((int *)0);
  	exit(status);
  }
--- 279,308 ----
  }
  
+ /*
+  * Trap a signal, unless it is being ignored.
+  */
+ setsignal(sig, act)
+ 	int sig, (*act)();
+ {
+ 	int omask = sigblock(sigmask(sig));
+ 
+ 	if (signal(sig, act) == SIG_IGN)
+ 		(void) signal(sig, SIG_IGN);
+ 	(void) sigsetmask(omask);
+ }
+ 
  done(status)
  	int status;
  {
+ 	int w;
  
  	mode(0);
! 	if (child > 0) {
! 		/* make sure catchild does not snap it up */
! 		(void) signal(SIGCHLD, SIG_DFL);
! 		if (kill(child, SIGKILL) >= 0)
! 			while ((w = wait((union wait *)0)) > 0 && w != child)
! 				/*void*/;
! 	}
  	exit(status);
  }
***************
*** 230,233 ****
--- 309,321 ----
  
  /*
+  * Copy SIGURGs to the child process.
+  */
+ copytochild()
+ {
+ 
+ 	(void) kill(child, SIGURG);
+ }
+ 
+ /*
   * This is called when the reader process gets the out-of-band (urgent)
   * request to turn on the window-changing protocol.
***************
*** 238,242 ****
  	if (dosigwinch == 0) {
  		sendwindow();
! 		signal(SIGWINCH, sigwinch);
  	}
  	dosigwinch = 1;
--- 326,330 ----
  	if (dosigwinch == 0) {
  		sendwindow();
! 		(void) signal(SIGWINCH, sigwinch);
  	}
  	dosigwinch = 1;
***************
*** 249,253 ****
  
  again:
! 	pid = wait3(&status, WNOHANG|WUNTRACED, 0);
  	if (pid == 0)
  		return;
--- 337,341 ----
  
  again:
! 	pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0);
  	if (pid == 0)
  		return;
***************
*** 256,260 ****
  	 */
  	if (pid < 0 || pid == child && !WIFSTOPPED(status))
! 		done(status.w_termsig | status.w_retcode);
  	goto again;
  }
--- 344,348 ----
  	 */
  	if (pid < 0 || pid == child && !WIFSTOPPED(status))
! 		done((int)(status.w_termsig | status.w_retcode));
  	goto again;
  }
***************
*** 290,294 ****
  		if (bol) {
  			bol = 0;
! 			if (c == cmdchar) {
  				bol = 0;
  				local = 1;
--- 378,382 ----
  		if (bol) {
  			bol = 0;
! 			if (!isswitch && c == cmdchar) {
  				bol = 0;
  				local = 1;
***************
*** 308,312 ****
  			}
  			if (c != cmdchar)
! 				write(rem, &cmdchar, 1);
  		}
  		if (write(rem, &c, 1) == 0) {
--- 396,400 ----
  			}
  			if (c != cmdchar)
! 				(void) write(rem, &cmdchar, 1);
  		}
  		if (write(rem, &c, 1) == 0) {
***************
*** 338,342 ****
  	*p++ = '\r';
  	*p++ = '\n';
! 	write(1, buf, p - buf);
  }
  
--- 426,430 ----
  	*p++ = '\r';
  	*p++ = '\n';
! 	(void) write(1, buf, p - buf);
  }
  
***************
*** 345,351 ****
  {
  	mode(0);
! 	signal(SIGCHLD, SIG_IGN);
! 	kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
! 	signal(SIGCHLD, catchild);
  	mode(1);
  	sigwinch();			/* check for size changes */
--- 433,439 ----
  {
  	mode(0);
! 	(void) signal(SIGCHLD, SIG_IGN);
! 	(void) kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
! 	(void) signal(SIGCHLD, catchild);
  	mode(1);
  	sigwinch();			/* check for size changes */
***************
*** 352,373 ****
  }
  
- #ifdef sun
  sigwinch()
  {
- 	struct ttysize ws;
- 
- 	if (dosigwinch && ioctl(0, TIOCGSIZE, &ws) == 0 &&
- 	    bcmp(&ws, &winsize, sizeof (ws))) {
- 		winsize = ws;
- 		sendwindow();
- 	}
- }
- 
- #else sun
- sigwinch()
- {
  	struct winsize ws;
  
! 	if (dosigwinch && ioctl(0, TIOCGWINSZ, &ws) == 0 &&
  	    bcmp(&ws, &winsize, sizeof (ws))) {
  		winsize = ws;
--- 440,448 ----
  }
  
  sigwinch()
  {
  	struct winsize ws;
  
! 	if (dosigwinch && get_window_size(0, &ws) == 0 &&
  	    bcmp(&ws, &winsize, sizeof (ws))) {
  		winsize = ws;
***************
*** 375,379 ****
  	}
  }
- #endif
  
  /*
--- 450,453 ----
***************
*** 389,398 ****
  	obuf[2] = 's';
  	obuf[3] = 's';
- #ifdef sun
- 	wp->ws_row = htons(winsize.ts_lines);
- 	wp->ws_col = htons(winsize.ts_cols);
- 	wp->ws_xpixel = 0;
- 	wp->ws_ypixel = 0;
- #else sun
  	wp->ws_row = htons(winsize.ws_row);
  	wp->ws_col = htons(winsize.ws_col);
--- 463,466 ----
***************
*** 399,403 ****
  	wp->ws_xpixel = htons(winsize.ws_xpixel);
  	wp->ws_ypixel = htons(winsize.ws_ypixel);
- #endif sun
  	(void) write(rem, obuf, sizeof(obuf));
  }
--- 467,470 ----
***************
*** 409,413 ****
  #define	WRITING	2
  
! char	rcvbuf[8 * 1024];
  int	rcvcnt;
  int	rcvstate;
--- 476,480 ----
  #define	WRITING	2
  
! char	rcvbuf[32 * 1024];
  int	rcvcnt;
  int	rcvstate;
***************
*** 452,477 ****
  		 * Let server know about window size changes
  		 */
! 		kill(ppid, SIGURG);
  	}
  	if (!eight && (mark & TIOCPKT_NOSTOP)) {
! 		ioctl(0, TIOCGETP, (char *)&sb);
  		sb.sg_flags &= ~CBREAK;
  		sb.sg_flags |= RAW;
! 		ioctl(0, TIOCSETN, (char *)&sb);
  		notc.t_stopc = -1;
  		notc.t_startc = -1;
! 		ioctl(0, TIOCSETC, (char *)&notc);
  	}
  	if (!eight && (mark & TIOCPKT_DOSTOP)) {
! 		ioctl(0, TIOCGETP, (char *)&sb);
  		sb.sg_flags &= ~RAW;
  		sb.sg_flags |= CBREAK;
! 		ioctl(0, TIOCSETN, (char *)&sb);
  		notc.t_stopc = deftc.t_stopc;
  		notc.t_startc = deftc.t_startc;
! 		ioctl(0, TIOCSETC, (char *)&notc);
  	}
  	if (mark & TIOCPKT_FLUSHWRITE) {
! 		ioctl(1, TIOCFLUSH, (char *)&out);
  		for (;;) {
  			if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
--- 519,544 ----
  		 * Let server know about window size changes
  		 */
! 		(void) kill(ppid, SIGUSR1);
  	}
  	if (!eight && (mark & TIOCPKT_NOSTOP)) {
! 		(void) ioctl(0, TIOCGETP, (char *)&sb);
  		sb.sg_flags &= ~CBREAK;
  		sb.sg_flags |= RAW;
! 		(void) ioctl(0, TIOCSETN, (char *)&sb);
  		notc.t_stopc = -1;
  		notc.t_startc = -1;
! 		(void) ioctl(0, TIOCSETC, (char *)&notc);
  	}
  	if (!eight && (mark & TIOCPKT_DOSTOP)) {
! 		(void) ioctl(0, TIOCGETP, (char *)&sb);
  		sb.sg_flags &= ~RAW;
  		sb.sg_flags |= CBREAK;
! 		(void) ioctl(0, TIOCSETN, (char *)&sb);
  		notc.t_stopc = deftc.t_stopc;
  		notc.t_startc = deftc.t_startc;
! 		(void) ioctl(0, TIOCSETC, (char *)&notc);
  	}
  	if (mark & TIOCPKT_FLUSHWRITE) {
! 		(void) ioctl(1, TIOCFLUSH, (char *)&out);
  		for (;;) {
  			if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
***************
*** 495,499 ****
--- 562,571 ----
  		longjmp(rcvtop, 1);
  	}
+ 
  	/*
+ 	 * oob does not do FLUSHREAD (alas!)
+ 	 */
+ 
+ 	/*
  	 * If we filled the receive buffer while a read was pending,
  	 * longjmp to the top to restart appropriately.  Don't abort
***************
*** 507,511 ****
   * reader: read from remote: line -> 1
   */
! reader()
  {
  #if !defined(BSD) || BSD < 43
--- 579,584 ----
   * reader: read from remote: line -> 1
   */
! reader(oldmask)
! 	int oldmask;
  {
  #if !defined(BSD) || BSD < 43
***************
*** 517,524 ****
  	char *bufp = rcvbuf;
  
! 	signal(SIGTTOU, SIG_IGN);
! 	fcntl(rem, F_SETOWN, pid);
  	ppid = getppid();
  	(void) setjmp(rcvtop);
  	for (;;) {
  		while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
--- 590,599 ----
  	char *bufp = rcvbuf;
  
! 	(void) signal(SIGTTOU, SIG_IGN);
! 	(void) signal(SIGURG, oob);
  	ppid = getppid();
+ 	(void) fcntl(rem, F_SETOWN, pid);
  	(void) setjmp(rcvtop);
+ 	(void) sigsetmask(oldmask);
  	for (;;) {
  		while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
***************
*** 554,559 ****
  	int	lflags;
  
! 	ioctl(0, TIOCGETP, (char *)&sb);
! 	ioctl(0, TIOCLGET, (char *)&lflags);
  	switch (f) {
  
--- 629,634 ----
  	int	lflags;
  
! 	(void) ioctl(0, TIOCGETP, (char *)&sb);
! 	(void) ioctl(0, TIOCLGET, (char *)&lflags);
  	switch (f) {
  
***************
*** 584,591 ****
  		return;
  	}
! 	ioctl(0, TIOCSLTC, (char *)ltc);
! 	ioctl(0, TIOCSETC, (char *)tc);
! 	ioctl(0, TIOCSETN, (char *)&sb);
! 	ioctl(0, TIOCLSET, (char *)&lflags);
  }
  
--- 659,666 ----
  		return;
  	}
! 	(void) ioctl(0, TIOCSLTC, (char *)ltc);
! 	(void) ioctl(0, TIOCSETC, (char *)tc);
! 	(void) ioctl(0, TIOCSETN, (char *)&sb);
! 	(void) ioctl(0, TIOCLSET, (char *)&lflags);
  }
  
***************
*** 594,597 ****
--- 669,673 ----
  	char *f;
  {
+ 
  	fprintf(stderr, f, a1, a2, a3, a4, a5);
  	fprintf(stderr, CRLF);
***************
*** 600,604 ****
  lostpeer()
  {
! 	signal(SIGPIPE, SIG_IGN);
  	prf("\007Connection closed.");
  	done(1);
--- 676,681 ----
  lostpeer()
  {
! 
! 	(void) signal(SIGPIPE, SIG_IGN);
  	prf("\007Connection closed.");
  	done(1);
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu
Technical Details
Message-ID: <3908@umcp-cs.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!mnetor!seismo!umcp-cs!chris
References: <2536@utai.UUCP> <1456@jade.BERKELEY.EDU>

Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: arc1-ca.pugleaf.net!utzoo!mnetor!seismo!umcp-cs!chris
From: chris@umcp-cs.UUCP (Chris Torek)
Newsgroups: net.emacs
Subject: Re: GNU Emacs hanging...
Message-ID: <3908@umcp-cs.UUCP>
Date: Fri, 17-Oct-86 00:53:48 EDT
Article-I.D.: umcp-cs.3908
Posted: Fri Oct 17 00:53:48 1986
Date-Received: Fri, 17-Oct-86 04:05:08 EDT
References: <2536@utai.UUCP> <1456@jade.BERKELEY.EDU>
Organization: Computer Sci. Dept, U of Maryland, College Park, MD
Lines: 707