[comp.unix.ultrix] Getting tcsh to work with ULTRIX 4.2

nsf@crl.dec.com (Neil Fishman) (06/14/91)

Hi

   I have been able to get tcsh working with ULTRIX 4.2.  However, this is 
just a workaround and more of a hack than a fix.  I'll include the context
diffs from tcsh v5.20.02 but first I'll describe the problem. (Just in case
anyone out there has the urge to fix this correctly!)

   The change that took place in login between versions 4.1 and 4.2 was that 
stdin and stdout are now set as FIOCLEX (close on exec), so that error 
messages can be logged until the last possible minute.

   In tcsh, .cshrc (or .tcshrc) are processed by having the data appear as
if it had come from stdin.  Normally, the routine srcunit() (in sh.c) saves
the original stdin and stdout file pointers, before processing this data.

   When stdin is set for FIOCLEX, however, one of the longjmp's in the
program (of which there are many - used for error trapping), is causing
srcunit() to be re-entered from the top.  Causing the saved pointers to
become trashed and forcing the exit condition.  Christos Guillemin (the
person at Cornell who maintains the sources), seemed to believe this was a
problem in which some of the variables are being stored in registers rather
than memory (which is discussed in the comments), and suggested I try to
track it down that way.  Compiling without optimization resulted in the
same problem, and I wasn't about to go tracking through the assembly
listing!

   After spending a few days trying to find the longjmp which was forcing
srcunit() to be re-entered, I finally gave up.  What I did to correct the
problem was to save the stdin pointer in srccat(), which calls srcunit(). 
Although this approach gets the shell working, it clearly fixes the
symptoms, not the cause.

   Please let me know if there are any problems with this hack.

Neil Fishman					Cambridge Research Lab
nsf@crl.dec.com					Digital Equipment Corp.

*** sh.c
***************
*** 1265,1270 ****
--- 1265,1277 ----
  	register Char *ep = Strspl(cp, dp);
  	register int unit;
  
+ 	/* Temporary variable for storing arginp while call to srcunit is
+ 	   called.  When tcsh is invoked from a program which sets stdin and
+ 	   stdout to FIOCLEX, when the .cshrc is processed, srcunit appears
+ 	   to be re-entered (via a longjmp?), which trashes the pointer 
+ 	   saved there. */
+ 	Char *temparginp = arginp;
+ 
  #ifndef R_OK
  #define R_OK 04
  #endif
***************
*** 1282,1287 ****
--- 1289,1298 ----
  #else
  	srcunit(unit, 1, 0);
  #endif
+ 
+ 	/* restore saved pointer */
+ 	arginp = temparginp;
+ 
  	return 1;
  }