Date: Sun, 30 May 1999 12:09:00 +0300 (IDT) From: Eli Zaretskii X-Sender: eliz AT is To: "Mark E." cc: djgpp-workers AT delorie DOT com Subject: Re: enhancements to fcntl.c In-Reply-To: <199905280131.BAA105100@out2.ibm.net> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Reply-To: djgpp-workers AT delorie DOT com X-Mailing-List: djgpp-workers AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk On Thu, 27 May 1999, Mark E. wrote: > Bash uses fcntl with F_GETFD to check if a file descriptor is valid. To > support this in a future port, I enhanced fcntl to check if the > descriptor is valid. Thanks. > /* Get the SFT entry for the handle. */ > regs.x.ax = 0x1216; > regs.x.bx = index; > __dpmi_int (0x2f, ®s); Does this work on Windows? An alternative method implemented in `fstat' doesn't work reliably there, so I'm interested to know. Also, Windows 9X has a dedicated function of Int 21h to get access bits by a handle (`fstat' uses it as well). Perhaps it is better to use that method when we run on Windows 9X, since it is documented by Microsoft, instead of using undocumented internal DOS functions. > /* Before proceeding, verify the descriptor is valid. */ > if (!is_used_fd(fd)) > { > errno = EINVAL; > return -1; > } I think EBADF is a better value for errno here. Also, I suggest to call __doserr_to_errno after every __dpmi_int call that returns error code in AX (when it returns with carry set). That way, you won't need to worry about setting errno explicitly. > case F_SETFD: > { > int flag; > > /* Return error if any descriptor flags are passed, since > DOS doesn't support them. */ > va_start (ap, cmd); > flag = va_arg(ap, int); > va_end(ap); > return (flag ? -1 : 0); > } There are some subtleties here that could be used to make the emulation better. First, DOS only passes the first 20 handles to the child process, so any handle beyond 20 should accept (and ignore) non-zero FLAG. Second, you could get fancy and allow changing the FD_CLOSEXEC bit by using the no-inherit flag accepted by functions 6Ch and 716Ch of Interrupt 21h. To do that, you'd have to reopen the file using these functions, lseek to the current file position, then dup2 the old handle using the new one. (Don't forget to copy the text/binary mode and read/write access bits correctly!). It's possible that you might be able to change the inheritance bit by calling the IOCTL function 01 (Int 21h/AX=4401h). My references seem to indicate that function 4400 returns bit 12 set for files open with the no-inherit bit. Perhaps setting that bit and calling 4401 will make the file non-inheritable? It's worth trying, I think. > case F_GETFD: > /* DOS does not support FD_CLOEXEC or any other descriptor flags, > so there are no flags to return. */ > return 0; You should be able to use 214401 to get the no-inherit bit, see above (the SFT entry holds the device info word at offset 05, so you could use that as well, but in my experience going the documented way is better). If this somehow doesn't work, I think the default should be 0 for handles below 20, 1 otherwise. > case F_SETFL: > return 0; Reopening the file might do a better job; see above. > /* Ignore read locks because DOS/Windows support only write locks > for record locking. */ > if (lock_req->l_type == F_UNLCK) > { > ret = _dos_unlock(fd, pos, len); > } > else if (lock_req->l_type == F_WRLCK) > { > ret = _dos_lock(fd, pos, len); > if (ret == 0 && cmd == F_GETLK) > _dos_unlock(fd, pos, len); > } > return ret; > } > } > return -1; I think it's better to set errno to ENOSYS in all cases where you fail the call because DOS/Windows don't implement the feature.