From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/11763 Path: news.gmane.org!.POSTED!not-for-mail From: Rich Felker Newsgroups: gmane.linux.lib.musl.general Subject: Re: shell needs to change fd in a FILE Date: Mon, 31 Jul 2017 16:18:27 -0400 Message-ID: <20170731201827.GA1627@brightrain.aerifal.cx> References: Reply-To: musl@lists.openwall.com NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: blaine.gmane.org 1501532324 32023 195.159.176.226 (31 Jul 2017 20:18:44 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 31 Jul 2017 20:18:44 +0000 (UTC) User-Agent: Mutt/1.5.21 (2010-09-15) To: musl@lists.openwall.com Original-X-From: musl-return-11776-gllmg-musl=m.gmane.org@lists.openwall.com Mon Jul 31 22:18:40 2017 Return-path: Envelope-to: gllmg-musl@m.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by blaine.gmane.org with smtp (Exim 4.84_2) (envelope-from ) id 1dcH9B-00080D-Eg for gllmg-musl@m.gmane.org; Mon, 31 Jul 2017 22:18:37 +0200 Original-Received: (qmail 1994 invoked by uid 550); 31 Jul 2017 20:18:40 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Original-Received: (qmail 1969 invoked from network); 31 Jul 2017 20:18:39 -0000 Content-Disposition: inline In-Reply-To: Original-Sender: Rich Felker Xref: news.gmane.org gmane.linux.lib.musl.general:11763 Archived-At: On Mon, Jul 31, 2017 at 05:05:24PM +0200, Denys Vlasenko wrote: > Hi, > > I'm using ordinary FILE i/o for reading scripts in hush shell, > instead of rolling my own implementation, so that I can reuse > buffering code in libc, through the use of fgetc(). > > This works for almost all cases, except this one: if in script > I have a redirect which says shell wants to open a fd which happens > to be equal to the fd (say, 10) shell already used for script FILE: > > exec 10>FILE > > What other shells do in this situation is they simply > dup and close script fd [in real code, they use fcntl(F_DUPFD) > instead of dup() since they want to avoid getting low fds], > so that fd is "moved" and no longer collides with the redirect. The right solution to this problem is not to actually reassign fds in the shell process at all, but instead reassign them in the child process to match their nominal (per the redirection operator) value. This is easy with fork+exec, hard or impossible to do safely with vfork+exec, and easy with posix_spawn. For commands which are internal (no child process), then, the nominal fd number is not the actual fd number but it doesn't matter; the internal logic can just remap it. Not saying you have to do it this way, but it's the clean (and the only strictly-conforming, since POSIX allows implementation-internal fd use that you *can't* safely move). > I can do this trick, but since I use FILE interface, then > I need to inform libc that it needs to use new fd for this FILE. > > "fileno(fp) = new_fd;" is non-portable and does not work in either > musl or glibc: it's a function, not a macro referencing > (fp)->field_holding_fd. > > "fclose(fp); fp = fdopen(new_fd);" is not good since fp may have > some buffered input, which will be lost by such code. I don't see how this is a problem unless you can read scripts from a non-seekable stream, which sounds really dubious. If the stream is seekable, you'll suffer a minor efficiency cost in this rare case, but it's not going to make a measurable difference in the big picture. > How about adding a "set_fileno(fp, fd)" extension to musl, > with some easy define to probe for to conditionally use it? I really don't want to get into the business of doing application-specific stdio extensions on request. We did a couple for gnulib, but that's because it's already crept into everything and the alternative was them doing awful hacks trying to poke at stdio internals. I think we can come up with a better solution here. Rich