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