Module Name: src Committed By: kre Date: Sun Nov 10 01:22:24 UTC 2024
Modified Files: src/bin/sh: eval.c redir.c redir.h sh.1 show.c Log Message: exec builtin command redirection fixes Several changes, all related to the exec special built in command, or to close on exec, one way or another. (Except a few white space and comment additions, KNF, etc) 1. The bug found by Edgar Fuß reported in: http://mail-index.netbsd.org/tech-userlevel/2024/11/05/msg014588.html has been fixed, now "exec N>whatever" will set close-on-exec for fd N (as do ksh versions, and allowed by POSIX, though other shells do not) which has happened now for many years. But "exec cmd N>whatever" (which looks like the same command when redirections are processed) which was setting close-on-exec on N, now no longer does, so fd N can be passed to cmd as an open fd. For anyone who cares, the big block of change just after "case CMDBUILTIN:" in evalcommand() in eval.c is the fix for this (one line replaced by about 90 ... though most of that is comments or #if 0'd example code for later). It is a bit ugly, and will get worse if our exec command ever gets any options, as others have, but it does work. 2. when the exec builtin utility is used to alter the shell's redirections it is now "all or nothing". Previously the redirections were executed left to right. If one failed, no more were attempted, but the earlier ones remained. This makes no practical difference to a non-interactive shell, as a redirection error causes that shell to exit, but it makes a difference to interactive shells. Now if a redirection fails, any earlier ones which had been performed are undone. Note however that side-effects of redirections (like creating, or truncating, files in the filesystem, cannot be reversed - just the shell's file descriptors returned to how they were before the error). Similarly usage errors on exec now exist .. our exec takes no options (but does handle "--" as POSIX says it must - has done for ages). Until now, that was the only magic piece of exec, running exec -a name somecommand (which several other shells support) would attempt to exec the "-a" command, and most likely fail, causing immediate exit from the shell. Now that is a usage error - a non-interactive shell still exits, as exec is a special builtin, and any error from a special builtin causes a non-interactive shell to exit. But now, an interactive shell will no longer exit (and any redirections that were on the command will be undone, the same as for a redirection error). 3. When a "close on exec" file descriptor is temporarily saved, so the same fd can be redirected for another command (only built-in commands and functions matter, redirects for file system commands happen after a fork() and at that stage if anything goes wrong, the child simply exits - but for non-forking commands, doing something like printf >file required the previous stdout to be saved elsewhere, "file" opened to be the new stdout, then when printf is finished, the old stdout moved back. Anyway, if the fd being moved had close on exec set, then when it was moved back, the close on exec was lost. That is now fixed. 4. The fdflags command no longer allows setting close on exec on stdin, stdout, or stderr - POSIX requires that those 3 fd's always be open (to something) when any normal command is invoked. With close-on-exec set on one of these, that is impossible, so simply refuse it (when "exec N>file" sets close on exec, it only does it for N>2). Minor changes (should be invisible) a. The shell now keeps track of the highest fd number it sees doing normal operations (there are a few internal pipe() calls that aren't monitored and a couple of others, but in general the shell will now know the highest fd it ever saw allocated to it). This is mostly for debugging. b. calls to fcntl() passing an int as the "arg" are now all properly cast to the void * that the fcntl kernel is expecting to receive. I suspect that makes no actual difference to anything, but ... To generate a diff of this commit: cvs rdiff -u -r1.194 -r1.195 src/bin/sh/eval.c cvs rdiff -u -r1.72 -r1.73 src/bin/sh/redir.c cvs rdiff -u -r1.26 -r1.27 src/bin/sh/redir.h cvs rdiff -u -r1.267 -r1.268 src/bin/sh/sh.1 cvs rdiff -u -r1.56 -r1.57 src/bin/sh/show.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.