Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!burl!ulysses!bellcore!decvax!decwrl!glacier!hplabs!tektronix!teklds!zeus!bobr From: bobr@zeus.UUCP (Robert Reed) Newsgroups: net.emacs Subject: Re: Time/Load bug in Gosling Message-ID: <45@zeus.UUCP> Date: Fri, 14-Mar-86 15:31:28 EST Article-I.D.: zeus.45 Posted: Fri Mar 14 15:31:28 1986 Date-Received: Mon, 17-Mar-86 03:28:58 EST References: <33800005@gypsy.UUCP> <397@mips.UUCP> Reply-To: bobr@zeus.UUCP (Robert Reed) Organization: CAE Systems Division, Tektronix, Inc., Beaverton, OR. Lines: 87 In article <397@mips.UUCP> hansen@mips.UUCP (Craig Hansen) writes: >> We are using Gosling Emacs-#264 running on a VAX 780 with 4.2BSD. Most of >> us who use Emacs also use the 'time.ml' package to display the system time >> and load at the bottom of the screen. >> >> In doing this we have noted a very strange feature which is not bothersome, >> but I would like to know why it happens. What happends is that just after the >> machine crashes or is shut down and is then brought back up, it will not >> display the time and load, but rather it will just say: >> >> (time and load) > >I've noticed a similar problem here, but for me it's more serious... The problem is that Emacs 264, when it opens a pty, only tries to open the master, not looking at whether the slave side is accessible. After a crash, the access rights of pty slaves can be left in various wierd states. Emacs tries to open the master side, succeeds, forks the process which opens the slave side but can't write to it. Time.ml initially sets the global mode string to (time and load), but no data comes throught the pty so it never gets updated. The solution is to verify that BOTH the master can be opened AND that the slave is writeable before accepting a pty/tty pair. The appropriate routine (with thanks for previous help from Chris Torek) is: static char * pty(ptyv) int *ptyv; /* Find a free pty and open it. Return the name of the slave side and stuff * the file descriptor in the supplied pointer. N.B.: we make the following * assumptions: * 1. Pty masters are /dev/pty[pqr...][0-9a-f]. * 2. Pty slave names are the same as the master but with a 't' in * place of the first 'p'. * 3. Ptys stop as soon as a "stat" call fails on the master name (names * are tried in alphabetical order). (Actually, we cheat and stat * only the first of each set of 16.) * A return value of 0 indicates no free ptys. */ { static char name[24]; register int fd; register char *p = name; struct stat stb; /* init to a generic pty name with *p the last character of the * name */ { register char *s = "/dev/ptyp"; while (*p++ = *s++) ; *p-- = 0; } /* for each block of ptys, try to open the master; if that works, make * sure the slave is accessible, then return the name of the slave */ for (;;) { register int i; *p = '0'; if (stat(name, &stb) < 0) return (0); for (i = 0; i < 16; ) { /* If the master pty can be opened and its slave is accessible * then set nonblocking IO and return the name of the * corresponding tty */ if ((fd = open(name, 2)) >= 0) { p[-4] = 't'; if (access (name, 6) == 0) { int on = 1; (void) ioctl(fd, FIONBIO, &on); *ptyv = fd; return (name); } p[-4] = 'p'; (void) close(fd); } *p = "123456789abcdef"[i++]; } p[-1]++; } }