[comp.unix.programmer] What does csh require of its tty?

jc@sppip7.lkg.dec.com (05/17/91)

Well, I'm sure that the folks in comp.unix.programmer will say that
this belongs in comp.unix.shell, and vice-versa, so I'll post it to
both and maybe someone will actually know the answer..

What I'm doing is using a privately-developed comm package that has
control of a bunch of things including serial ports, and starts up
various applications.  Sort of like getty, but with quite a lot more
intelligence, so it knows how to do things like talk to modems, dial
numbers, make terminal-switching network connections, and lots of 
stuff like that.

Sometimes it has to log people in and start up their login shell.
This goes quite smoothly if the shell is sh or ksh.  But if it is
csh (as is most often the case), sometimes it works, and sometimes
csh sits there like a zombie.  Very often the zombie csh processes
are gobbling cpu time, but they don't interact with the terminal.
If I start sh on the same line, it works just fine.

I've determined that, like TFM says somewhere, csh requires the NTTY
line discipline.  It needs some other things, too.  E.g., it won't
work on a raw, non-blocking port (which some other applications like);
it puts out a steady stream of prompts, and treats each byte as a
1-char input line.  This doesn't surprise me.  But it has some other
requirements for its terminal that I can't figure out.

At the moment, I have a login here that used /bin/sh, and that worked
fine.  When I typed a "csh" command on the other end, it produced a
/bin/csh that is using time like crazy (roughly 2/3 of the cpu time)
and it hasn't given a prompt yet.  I can kill it, and the sh again
works.  But no set of options to csh seems to cause it to work.

Does anyone have any idea how to make csh work?  Is this perhaps 
documented somewhere?

This is being done on some Ultrix 3.1 and 4.1 systems, with VAX and
MIPS processors, but the intent is to port it to other systems, so
it likely doesn't matter much what these machines are.  My makeraw()
and makesane() routines already have more #ifdefs than you'd believe,
and a few more wouldn't materially affect anything.

+----------------------------------------------------------------+
Reply-to: John Chambers <jc@sppip7.lkg.dec.com> or <ub40.enet::jc> 
+----------------------------------------------------------------+

lan_csse@netrix.nac.dec.com (CSSE LAN Test Account) (05/17/91)

Here I go following up my own article...

Well, I got a bit more evidence as to why csh is hanging on some
ports and not on others.  There seems to be something bizarre with
the process groups.  Part of the evidence is that ps says:
	jc       10224  2.7  0.3   29   27 ?  S     0:02 - (sh)
I.e., it doesn't know what tty the sh is running on.  If I go to
the other machine and type "echo hi >/dev/tty" in the window that
is connected over here, it says 
	/dev/tty: cannot create
When I do the same in other windows, I get "hi" like you'd expect.

So the daemon controlling the port hasn't set up the process group
correctly.  The Ultrix tty(4) manual page says:
	A terminal's associated process group may be set using the
	TIOCSPGRP ioctl(2):
		ioctl(fildes, TIOCSPGRP, &pgrp)
The code that sets the process group looks like:
	if ((i = setpgrp(pid,pid)) == 0) {
		P2("%s  Set process group to %d",dbgtime(),pid);
		if ((i = ioctl(dev,TIOCSPGRP,&pid)) == 0) {
			P2("%s  Set process group to %d for %s",dbgtime(),pid,device);
		} else
			P1("%s  ### Can't set pgrp to %d for %s [Err %d=%s]",
				dbgtime(),pid,device,Erreason);
	} else
		P1("%s  ### Can't set process group to %d [Err %d=%s]",
			dbgtime(),pid,Erreason);
where the P*() routines are macros that are conditional prints to an
audit trail.  This audit trail shows both of the P2() messages; i.e.,
the success messages.  The value of pid is the pid of the process in
which the shell starts, dev is the file handle for the port, device
is its name, and the rest is debug stuff that I won't explain.

It's especially curious that the above code seems to work fine on some
of the Ultrices around here and not on others.  I conclude that there's
something else required to make it work, but I haven't a clue as to what
it might be.

And of course I'm still looking for a more general solution that will
work on any Unix.  On Sys/V, the equivalent of the above code is just:
	setpgrp();
and it seems to work without any hassles, for sh, csh, and ksh.

Any ideas as to what I could be doing wrong?

+----------------------------------------------------------------+
Reply-to: John Chambers <jc@sppip7.lkg.dec.com> or <ub40.enet::jc> 
+----------------------------------------------------------------+