Of csh & filepointers & fopen calls ...

chris at mimsy.UUCP chris at mimsy.UUCP
Fri Feb 13 21:57:50 AEST 1987


In article <176 at quacky.mips.UUCP> dce at mips.UUCP (David Elliott) writes:
>I believe that what csh does with the extra file descriptors is to use
>them to save the values of the standard file descriptors when redirection
>and pipes are done. Without this, you have to fork each time you do
>redirection or pipes, which can cause problems when it involves control
>structures (if, while, foreach, etc.).

Indeed, csh salts away copies of its stdin, stdout, and stderr in
`high numbered' file descriptors.  In 4.1BSD these were 17, 18,
and 19, as NOFILE was 20, making [0..20) legal file descriptor
values.  These were arranged to be closed on exec() by, as I recall,
FIOCLEX ioctls on the *old* descriptors.  Dup2 originally carried
this attribute over to the new descriptors.  This behaviour was
deemed bogus, and dropped in 4.2.  It seems, however, that the 4.2
csh was converted by a process best described as `tweak it until
it works'.  No one noticed that the extra descriptors were left
behind.

I thought all this had been straightened out in 4.3BSD, but it is
possible it was overlooked.  Csh is one large series of bugs, and
desperately needs a complete overhaul.  But I do not promise to do
it.

Incidentally, it really is not necessary to move stdin &c out of
the way for redirection of internal commands.  A possible data
structure to demonstrate:

	struct cnode {	/* command node */
		int	cn_type;	/* type of this node */
		char	**cn_cmd;	/* argv */
		struct	redir *cn_redir;/* I/O redirections */
		caddr_t	cn_data;	/* type-dependent data (if any) */
	};

	/*
	 * There may be many command nodes pointing at some particular
	 * redirection node.  In particular, a redirected loop construct
	 * will have all its subcommands pointing to the same redir
	 * (unless those subcommands have also been redirected).
	 */
	struct redir {	/* redirection node */
		int	r_refcnt;	/* reference count */
		struct	redir *r_next;	/* linked list */
		int	r_type;		/* type: TIE<, TIE>; <, <<, >, >>; | */
		union {
			char	*r_fname;	/* file name for < > >> */
			int	r_hereis;	/* hereis file for << */
			/*
			 * A `tied' redirect lists an actual fd
			 * (owned by this process) and a desired
			 * or `pretend' fd, so that >'d shell
			 * constructs will list an acutal fd of
			 * whatever the shell opened, with a
			 * desired fd of 1, e.g.
			 *
			 * Tied fd's are also used as back links in
			 * pipes.
			 */
			struct {
				int	rt_realfd;	/* actual fd */
				int	rt_desfd;	/* desired fd */
			} r_tie;
			struct	cnode *r_pipe;	/* link in pipe */
		} r_redir;
	};

(How is that for convoluted? :-)  It could well be wrong, too; I
just now made it up.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
UUCP:	seismo!mimsy!chris	ARPA/CSNet:	chris at mimsy.umd.edu



More information about the Comp.unix.wizards mailing list