}
#endif
+
+/* File descriptors 0, 1, and 2 should not be closed. fd_closed[]
+ tracks whether these descriptors have been closed in do_close()
+ below. */
+
+static int fd_closed[3];
+
+/* Check for some occurrences of bad file descriptors. We only check
+ whether fd 0, 1, or 2 are "closed". By "closed" we mean that these
+ descriptors aren't actually closed, but are considered to be closed
+ by this layer.
+
+ Other checks are performed by the underlying OS call. */
+
+static int
+fdbad (int fd)
+{
+ if (fd >=0 && fd <= 2 && fd_closed[fd])
+ {
+ errno = EBADF;
+ return -1;
+ }
+ return 0;
+}
+
static void
do_exit(os_emul_data *emul,
unsigned call,
status = -1;
}
#endif
- status = read (d, scratch_buffer, nbytes);
+ status = fdbad (d);
+ if (status == 0)
+ status = read (d, scratch_buffer, nbytes);
emul_write_status(processor, status, errno);
if (status > 0)
processor, cia);
/* write */
- status = write(d, scratch_buffer, nbytes);
+ status = fdbad (d);
+ if (status == 0)
+ status = write(d, scratch_buffer, nbytes);
+
emul_write_status(processor, status, errno);
free(scratch_buffer);
SYS(close);
- /* Can't combine these statements, cuz close sets errno. */
- status = close(d);
+ status = fdbad (d);
+ if (status == 0)
+ {
+ /* Do not close stdin, stdout, or stderr. GDB may still need access to
+ these descriptors. */
+ if (d == 0 || d == 1 || d == 2)
+ {
+ fd_closed[d] = 1;
+ status = 0;
+ }
+ else
+ status = close(d);
+ }
+
emul_write_status(processor, status, errno);
}
unsigned_word cia)
{
int oldd = cpu_registers(processor)->gpr[arg0];
- int status = dup(oldd);
+ int status = (fdbad (oldd) < 0) ? -1 : dup(oldd);
int err = errno;
if (WITH_TRACE && ppc_trace[trace_os_emul])
|| dir & IOC_OUT
|| !(dir & IOC_VOID))
error("do_ioctl() read or write of parameter not implemented\n");
- status = ioctl(d, request, NULL);
+ status = fdbad (d);
+ if (status == 0)
+ status = ioctl(d, request, NULL);
emul_write_status(processor, status, errno);
#endif
{
int oldd = cpu_registers(processor)->gpr[arg0];
int newd = cpu_registers(processor)->gpr[arg0+1];
- int status = dup2(oldd, newd);
+ int status = (fdbad (oldd) < 0) ? -1 : dup2(oldd, newd);
int err = errno;
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%d, %d, %d", fd, cmd, arg);
SYS(fcntl);
- status = fcntl(fd, cmd, arg);
+ status = fdbad (fd);
+ if (status == 0)
+ status = fcntl(fd, cmd, arg);
emul_write_status(processor, status, errno);
}
#endif
printf_filtered ("%d, 0x%lx", fd, (long)buf_addr);
SYS(fstatfs);
- status = fstatfs(fd, (buf_addr == 0 ? NULL : &buf));
+ status = fdbad (fd);
+ if (status == 0)
+ status = fstatfs(fd, (buf_addr == 0 ? NULL : &buf));
emul_write_status(processor, status, errno);
if (status == 0) {
if (buf_addr != 0)
SYS(fstat);
#endif
/* Can't combine these statements, cuz fstat sets errno. */
- status = fstat(fd, &buf);
+ status = fdbad (fd);
+ if (status == 0)
+ status = fstat(fd, &buf);
emul_write_status(processor, status, errno);
write_stat(stat_buf_addr, buf, processor, cia);
}
int whence = cpu_registers(processor)->gpr[arg0+4];
off_t status;
SYS(lseek);
- status = lseek(fildes, offset, whence);
+ status = fdbad (fildes);
+ if (status == 0)
+ status = lseek(fildes, offset, whence);
if (status == -1)
emul_write_status(processor, -1, errno);
else {
static emul_syscall emul_netbsd_syscalls = {
netbsd_descriptors,
- sizeof(netbsd_descriptors) / sizeof(netbsd_descriptors[0]),
+ ARRAY_SIZE (netbsd_descriptors),
netbsd_error_names,
- sizeof(netbsd_error_names) / sizeof(netbsd_error_names[0]),
+ ARRAY_SIZE (netbsd_error_names),
netbsd_signal_names,
- sizeof(netbsd_signal_names) / sizeof(netbsd_signal_names[0]),
+ ARRAY_SIZE (netbsd_signal_names),
};
emul_netbsd_init(os_emul_data *emul_data,
int nr_cpus)
{
- /* nothing yet */
+ fd_closed[0] = 0;
+ fd_closed[1] = 0;
+ fd_closed[2] = 0;
}
static void