Date: Tue, 1 Jun 1999 09:26:23 +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: <199905311824.SAA72470@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 I wrote two short test programs and played with them a bit. The programs are attached below, for those who are interested. They were run on DOS 5.0, Windows 95 v4.00.950r7 and NT v4.00SP3. Conclusions: 1. Using the O_NOINHERIT bit only matters for the first 20 handles; handles beyond the first 20 are *never* inherited. 2. Actually, we cannot inherit more than 18 handles, since the stub of the child (if the child was compiled with v2.02 and later) will forcibly close handles 19 and 18: one handle to allow the stub to open the executable and read the COFF info, and another one for the DPMI host, in case it needs it to open a swap file (on DOS). 3. Therefore, if the application calls `fcntl' with F_SETFD for handles beyond 17, the only thing we can do is to fail the call, unless they want it non-inheritable, in which case we should return a success. Reopening the file, as I suggested earlier in this thread, won't work (of course), since you don't have the file's name to reopen it... Conversely, a call with F_SETFD for handles below 18 should always fail if the caller requests to make it non-inheritable, unless the no-inherit bit is already set in the SFT. 4. 214400 doesn't bring the inherit bit on plain DOS as well, so the only way to go is via the SFT; let's hope some future version of Windows won't break this... Handles 18 and above should always return as close-on-exec, since we cannot inherit them. Oh, and btw, I think that "regs.x.es * 16" is unsafe, since the SFT may reside in high memory (if they have DOS=HIGH in CONFIG.SYS), and then this expression might overflow. -------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include static int get_sft_entry (int fd, unsigned char sft_entry[]) { __dpmi_regs regs; unsigned char index; unsigned long es, di; /* Get the JFT entry for this handle. */ regs.x.ax = 0x1220; regs.x.bx = fd; __dpmi_int (0x2f, ®s); if (regs.x.flags & 1) { printf ("GetJFT: error code %d\n", regs.h.al); return -1; } else { /* Get the SFT entry number for this handle. */ es = regs.x.es; di = regs.x.di; index = _farpeekb (_dos_ds, es * 16 + di); regs.x.ax = 0x1216; regs.x.bx = index; __dpmi_int (0x2f, ®s); if (regs.x.flags & 1) { printf ("GetSFT: error 0x%x\n", regs.x.ax); return -1; } else { es = regs.x.es; di = regs.x.di; dosmemget (es * 16 + di, 7, sft_entry); return 0; } } } static int dev_word (int fd) { __dpmi_regs regs; regs.x.ax = 0x4400; regs.x.bx = fd; regs.x.dx = 0; __dpmi_int(0x21, ®s); if (regs.x.flags & 1) { printf ("IOCTL func 0: error code 0x%x\n", regs.x.ax); return -1; } else return regs.x.dx; } int _open (const char *filename, int oflag) { __dpmi_regs r; int use_lfn = _USE_LFN; if (filename == 0) { errno = EINVAL; return -1; } _put_path(filename); if(use_lfn) r.x.ax = 0x716c; else r.x.ax = 0x6c00; r.x.bx = oflag & 0xffff; r.x.dx = 0x11; /* Open or create */ r.x.si = __tb & 15; r.x.cx = 0; r.x.ds = __tb >> 4; __dpmi_int(0x21, &r); if(r.x.flags & 1) { errno = __doserr_to_errno(r.x.ax); return -1; } __file_handle_set(r.x.ax, O_BINARY); return r.x.ax; } int main (int argc, char *argv[]) { int fd = open (argv[0], O_RDONLY | O_BINARY | O_NOINHERIT); int fd1; int status; /* Try dup() first. */ while ((fd1 = dup (fd)) != -1) { unsigned char sft_entry[7]; int dev_info; if (get_sft_entry (fd1, sft_entry) != -1 && (dev_info = dev_word (fd1)) != -1) printf ("%d: SFT: 0x%x IOCTL: 0x%x\n", fd1, *(unsigned short *)&sft_entry[5], dev_info & 0xffff); else printf ("%d: Failure!\n", fd1); } close (21); if ((status = spawnl (P_WAIT, "tfd.exe", "tfd.exe", NULL)) != 0) fprintf (stderr, "Spawn: %d\n", status); for (fd1 = 254; fd1 > fd; fd1--) close (fd1); /* Now try the same with open(). */ while ((fd1 = open (argv[0], O_RDONLY | O_BINARY | O_NOINHERIT)) != -1) { unsigned char sft_entry[7]; int dev_info; if (get_sft_entry (fd1, sft_entry) != -1 && (dev_info = dev_word (fd1)) != -1) printf ("%d: SFT: 0x%x IOCTL: 0x%x\n", fd1, *(unsigned short *)&sft_entry[5], dev_info & 0xffff); else printf ("%d: Failure!\n", fd1); } close (21); if ((status = spawnl (P_WAIT, "tfd.exe", "tfd.exe", NULL)) != 0) fprintf (stderr, "Spawn: %d\n", status); return 0; } ---------------- tfd.c ------------------------------------------- #include #include static int dev_word (int fd) { __dpmi_regs regs; regs.x.ax = 0x4400; regs.x.bx = fd; regs.x.dx = 0; __dpmi_int(0x21, ®s); if (regs.x.flags & 1) { return -1; } else return regs.x.dx; } int main (void) { int i; for (i = 0; i < 255; i++) { int dev_info = dev_word (i); if (dev_info != -1) printf ("%d: inherited, info word: 0x%x\n", i, dev_info & 0xffff); } return 0; }