Index: defs.h =================================================================== RCS file: /cvs/src/src/gdb/defs.h,v retrieving revision 1.102 diff -u -p -r1.102 defs.h --- defs.h 15 Oct 2002 02:16:51 -0000 1.102 +++ defs.h 21 Nov 2002 08:41:49 -0000 @@ -405,6 +405,8 @@ extern void reinitialize_more_filter (vo /* Normal results */ extern struct ui_file *gdb_stdout; +/* Input stream */ +extern struct ui_file *gdb_stdin; /* Serious error notifications */ extern struct ui_file *gdb_stderr; /* Log/debug/trace messages that should bypass normal stdout/stderr @@ -417,6 +419,8 @@ extern struct ui_file *gdb_stdlog; very near future that restriction shall be removed - either call shall be unfiltered. (cagney 1999-07-02). */ extern struct ui_file *gdb_stdtarg; +extern struct ui_file *gdb_stdtargerr; +extern struct ui_file *gdb_stdtargin; #if defined(TUI) #include "tui.h" Index: main.c =================================================================== RCS file: /cvs/src/src/gdb/main.c,v retrieving revision 1.20 diff -u -p -r1.20 main.c --- main.c 26 Sep 2002 17:46:04 -0000 1.20 +++ main.c 21 Nov 2002 08:41:49 -0000 @@ -69,6 +69,10 @@ struct ui_file *gdb_stdout; struct ui_file *gdb_stderr; struct ui_file *gdb_stdlog; struct ui_file *gdb_stdtarg; +struct ui_file *gdb_stdin; +/* target IO streams */ +struct ui_file *gdb_stdtargin; +struct ui_file *gdb_stdtargerr; /* Used to initialize error() - defined in utils.c */ @@ -197,6 +201,9 @@ captured_main (void *data) gdb_stderr = stdio_fileopen (stderr); gdb_stdlog = gdb_stderr; /* for moment */ gdb_stdtarg = gdb_stderr; /* for moment */ + gdb_stdin = stdio_fileopen (stdin); + gdb_stdtargerr = gdb_stderr; /* for moment */ + gdb_stdtargin = gdb_stdin; /* for moment */ /* initialize error() */ error_init (); Index: remote.c =================================================================== RCS file: /cvs/src/src/gdb/remote.c,v retrieving revision 1.94 diff -u -p -r1.94 remote.c --- remote.c 14 Nov 2002 00:25:03 -0000 1.94 +++ remote.c 21 Nov 2002 08:41:53 -0000 @@ -45,6 +45,12 @@ #ifdef USG #include #endif +#include +#include +#ifdef __CYGWIN__ +#include +#endif +#include #include "event-loop.h" #include "event-top.h" @@ -55,6 +61,8 @@ #include "gdbcore.h" /* for exec_bfd */ +#include "gdb-fileio.h" + /* Prototypes for local functions */ static void cleanup_sigint_signal_handler (void *dummy); static void initialize_sigint_signal_handler (void); @@ -2729,184 +2737,1481 @@ handle_remote_sigint (int sig) mark_async_signal_handler_wrapper (sigint_remote_token); } -/* Signal handler for SIGINT, installed after SIGINT has already been - sent once. It will take effect the second time that the user sends - a ^C. */ +/* Signal handler for SIGINT, installed after SIGINT has already been + sent once. It will take effect the second time that the user sends + a ^C. */ +static void +handle_remote_sigint_twice (int sig) +{ + signal (sig, handle_sigint); + sigint_remote_twice_token = + create_async_signal_handler (inferior_event_handler_wrapper, NULL); + mark_async_signal_handler_wrapper (sigint_remote_twice_token); +} + +/* Perform the real interruption of the target execution, in response + to a ^C. */ +static void +async_remote_interrupt (gdb_client_data arg) +{ + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n"); + + target_stop (); +} + +/* Perform interrupt, if the first attempt did not succeed. Just give + up on the target alltogether. */ +void +async_remote_interrupt_twice (gdb_client_data arg) +{ + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, "remote_interrupt_twice called\n"); + /* Do something only if the target was not killed by the previous + cntl-C. */ + if (target_executing) + { + interrupt_query (); + signal (SIGINT, handle_remote_sigint); + } +} + +/* Reinstall the usual SIGINT handlers, after the target has + stopped. */ +static void +cleanup_sigint_signal_handler (void *dummy) +{ + signal (SIGINT, handle_sigint); + if (sigint_remote_twice_token) + delete_async_signal_handler ((struct async_signal_handler **) & sigint_remote_twice_token); + if (sigint_remote_token) + delete_async_signal_handler ((struct async_signal_handler **) & sigint_remote_token); +} + +/* Send ^C to target to halt it. Target will respond, and send us a + packet. */ +static void (*ofunc) (int); + +/* The command line interface's stop routine. This function is installed + as a signal handler for SIGINT. The first time a user requests a + stop, we call remote_stop to send a break or ^C. If there is no + response from the target (it didn't stop when the user requested it), + we ask the user if he'd like to detach from the target. */ +static void +remote_interrupt (int signo) +{ + /* If this doesn't work, try more severe steps. */ + signal (signo, remote_interrupt_twice); + + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n"); + + target_stop (); +} + +/* The user typed ^C twice. */ + +static void +remote_interrupt_twice (int signo) +{ + signal (signo, ofunc); + interrupt_query (); + signal (signo, remote_interrupt); +} + +/* This is the generic stop called via the target vector. When a target + interrupt is requested, either by the command line or the GUI, we + will eventually end up here. */ +static void +remote_stop (void) +{ + /* Send a break or a ^C, depending on user preference. */ + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, "remote_stop called\n"); + + if (remote_break) + serial_send_break (remote_desc); + else + serial_write (remote_desc, "\003", 1); +} + +/* Ask the user what to do when an interrupt is received. */ + +static void +interrupt_query (void) +{ + target_terminal_ours (); + + if (query ("Interrupted while waiting for the program.\n\ +Give up (and stop debugging it)? ")) + { + target_mourn_inferior (); + throw_exception (RETURN_QUIT); + } + + target_terminal_inferior (); +} + +/* Enable/disable target terminal ownership. Most targets can use + terminal groups to control terminal ownership. Remote targets are + different in that explicit transfer of ownership to/from GDB/target + is required. */ + +static void +remote_async_terminal_inferior (void) +{ + /* FIXME: cagney/1999-09-27: Shouldn't need to test for + sync_execution here. This function should only be called when + GDB is resuming the inferior in the forground. A background + resume (``run&'') should leave GDB in control of the terminal and + consequently should not call this code. */ + if (!sync_execution) + return; + /* FIXME: cagney/1999-09-27: Closely related to the above. Make + calls target_terminal_*() idenpotent. The event-loop GDB talking + to an asynchronous target with a synchronous command calls this + function from both event-top.c and infrun.c/infcmd.c. Once GDB + stops trying to transfer the terminal to the target when it + shouldn't this guard can go away. */ + if (!remote_async_terminal_ours_p) + return; + delete_file_handler (input_fd); + remote_async_terminal_ours_p = 0; + initialize_sigint_signal_handler (); + /* NOTE: At this point we could also register our selves as the + recipient of all input. Any characters typed could then be + passed on down to the target. */ +} + +static void +remote_async_terminal_ours (void) +{ + /* See FIXME in remote_async_terminal_inferior. */ + if (!sync_execution) + return; + /* See FIXME in remote_async_terminal_inferior. */ + if (remote_async_terminal_ours_p) + return; + cleanup_sigint_signal_handler (NULL); + add_file_handler (input_fd, stdin_event_handler, 0); + remote_async_terminal_ours_p = 1; +} + +/* If nonzero, ignore the next kill. */ + +int kill_kludge; + +void +remote_console_output (char *msg) +{ + char *p; + + for (p = msg; p[0] && p[1]; p += 2) + { + char tb[2]; + char c = fromhex (p[0]) * 16 + fromhex (p[1]); + tb[0] = c; + tb[1] = 0; + fputs_unfiltered (tb, gdb_stdtarg); + } + gdb_flush (gdb_stdtarg); +} + +static struct { + int *fd_map; + int fd_map_size; +} remote_fio_data; + +#define FIO_FD_INVALID -1 +#define FIO_FD_CONSOLE_IN -2 +#define FIO_FD_CONSOLE_OUT -3 + +static int remote_fio_system_call_allowed = 0; + +static int +remote_fileio_init_fd_map () +{ + int i; + + if (!remote_fio_data.fd_map) + { + remote_fio_data.fd_map = (int *) xmalloc (10 * sizeof (int)); + remote_fio_data.fd_map_size = 10; + remote_fio_data.fd_map[0] = FIO_FD_CONSOLE_IN; + remote_fio_data.fd_map[1] = FIO_FD_CONSOLE_OUT; + remote_fio_data.fd_map[2] = FIO_FD_CONSOLE_OUT; + for (i = 3; i < 10; ++i) + remote_fio_data.fd_map[i] = FIO_FD_INVALID; + } + return 3; +} + +static int +remote_fileio_resize_fd_map () +{ + if (!remote_fio_data.fd_map) + return remote_fileio_init_fd_map (); + remote_fio_data.fd_map_size += 10; + remote_fio_data.fd_map = + (int *) xrealloc (remote_fio_data.fd_map, + remote_fio_data.fd_map_size * sizeof (int)); + return remote_fio_data.fd_map_size - 10; +} + +static int +remote_fileio_next_free_fd () +{ + int i; + + for (i = 0; i < remote_fio_data.fd_map_size; ++i) + if (remote_fio_data.fd_map[i] == FIO_FD_INVALID) + return i; + return remote_fileio_resize_fd_map (); +} + +static int +remote_fileio_fd_to_targetfd (int fd) +{ + int target_fd = remote_fileio_next_free_fd (); + remote_fio_data.fd_map[target_fd] = fd; + return target_fd; +} + +static int +remote_fileio_map_fd (int target_fd) +{ + remote_fileio_init_fd_map (); + if (target_fd < 0 || target_fd >= remote_fio_data.fd_map_size) + return FIO_FD_INVALID; + return remote_fio_data.fd_map[target_fd]; +} + +static void +remote_fileio_close_target_fd (int target_fd) +{ + remote_fileio_init_fd_map (); + if (target_fd >= 0 && target_fd < remote_fio_data.fd_map_size) + remote_fio_data.fd_map[target_fd] = FIO_FD_INVALID; +} + +static int +remote_fileio_oflags_to_host (long flags) +{ + int hflags = 0; + + if (flags & FILEIO_O_CREAT) + hflags |= O_CREAT; + if (flags & FILEIO_O_EXCL) + hflags |= O_EXCL; + if (flags & FILEIO_O_TRUNC) + hflags |= O_TRUNC; + if (flags & FILEIO_O_APPEND) + hflags |= O_APPEND; + if (flags & FILEIO_O_RDONLY) + hflags |= O_RDONLY; + if (flags & FILEIO_O_WRONLY) + hflags |= O_WRONLY; + if (flags & FILEIO_O_RDWR) + hflags |= O_RDWR; +/* On systems supporting binary and text mode, always open files in + binary mode. */ +#ifdef O_BINARY + hflags |= O_BINARY; +#endif + return hflags; +} + +static mode_t +remote_fileio_mode_to_host (long mode, int open_call) +{ + mode_t hmode = 0; + + if (!open_call) + { + if (mode & FILEIO_S_IFREG) + hmode |= S_IFREG; + if (mode & FILEIO_S_IFDIR) + hmode |= S_IFDIR; + if (mode & FILEIO_S_IFCHR) + hmode |= S_IFCHR; + } + if (mode & FILEIO_S_IRUSR) + hmode |= S_IRUSR; + if (mode & FILEIO_S_IWUSR) + hmode |= S_IWUSR; + if (mode & FILEIO_S_IXUSR) + hmode |= S_IXUSR; + if (mode & FILEIO_S_IRGRP) + hmode |= S_IRGRP; + if (mode & FILEIO_S_IWGRP) + hmode |= S_IWGRP; + if (mode & FILEIO_S_IXGRP) + hmode |= S_IXGRP; + if (mode & FILEIO_S_IROTH) + hmode |= S_IROTH; + if (mode & FILEIO_S_IWOTH) + hmode |= S_IWOTH; + if (mode & FILEIO_S_IXOTH) + hmode |= S_IXOTH; + return hmode; +} + +static long long +remote_fileio_mode_to_target (mode_t mode) +{ + mode_t tmode = 0; + + if (mode & S_IFREG) + tmode |= FILEIO_S_IFREG; + if (mode & S_IFDIR) + tmode |= FILEIO_S_IFDIR; + if (mode & S_IFCHR) + tmode |= FILEIO_S_IFCHR; + if (mode & S_IRUSR) + tmode |= FILEIO_S_IRUSR; + if (mode & S_IWUSR) + tmode |= FILEIO_S_IWUSR; + if (mode & S_IXUSR) + tmode |= FILEIO_S_IXUSR; + if (mode & S_IRGRP) + tmode |= FILEIO_S_IRGRP; + if (mode & S_IWGRP) + tmode |= FILEIO_S_IWGRP; + if (mode & S_IXGRP) + tmode |= FILEIO_S_IXGRP; + if (mode & S_IROTH) + tmode |= FILEIO_S_IROTH; + if (mode & S_IWOTH) + tmode |= FILEIO_S_IWOTH; + if (mode & S_IXOTH) + tmode |= FILEIO_S_IXOTH; + return tmode; +} + +static int +remote_fileio_errno_to_target (int error) +{ + switch (error) + { + case EPERM: + return FILEIO_EPERM; + case ENOENT: + return FILEIO_ENOENT; + case EINTR: + return FILEIO_EINTR; + case EIO: + return FILEIO_EIO; + case EBADF: + return FILEIO_EBADF; + case EACCES: + return FILEIO_EACCES; + case EFAULT: + return FILEIO_EFAULT; + case EBUSY: + return FILEIO_EBUSY; + case EEXIST: + return FILEIO_EEXIST; + case ENODEV: + return FILEIO_ENODEV; + case ENOTDIR: + return FILEIO_ENOTDIR; + case EISDIR: + return FILEIO_EISDIR; + case EINVAL: + return FILEIO_EINVAL; + case ENFILE: + return FILEIO_ENFILE; + case EMFILE: + return FILEIO_EMFILE; + case EFBIG: + return FILEIO_EFBIG; + case ENOSPC: + return FILEIO_ENOSPC; + case ESPIPE: + return FILEIO_ESPIPE; + case EROFS: + return FILEIO_EROFS; + case ENOSYS: + return FILEIO_ENOSYS; + case ENAMETOOLONG: + return FILEIO_ENAMETOOLONG; + } + return FILEIO_EUNKNOWN; +} + +static int +remote_fileio_seek_flag_to_host (long num, int *flag) +{ + if (!flag) + return 0; + switch (num) + { + case FILEIO_SEEK_SET: + *flag = SEEK_SET; + break; + case FILEIO_SEEK_CUR: + *flag = SEEK_CUR; + break; + case FILEIO_SEEK_END: + *flag = SEEK_END; + break; + default: + return -1; + } + return 0; +} + +static int +remote_fileio_extract_long (char **buf, long long *retlong) +{ + char *c; + int sign = 1; + + if (!buf || !*buf || !**buf || !retlong) + return -1; + c = strchr (*buf, ','); + if (c) + *c++ = '\0'; + else + c = strchr (*buf, '\0'); + while (strchr ("+-", **buf)) + { + if (**buf == '-') + sign = -sign; + ++*buf; + } + for (*retlong = 0; **buf; ++*buf) + { + *retlong <<= 4; + if (**buf >= '0' && **buf <= '9') + *retlong += **buf - '0'; + else if (**buf >= 'a' && **buf <= 'f') + *retlong += **buf - 'a' + 10; + else if (**buf >= 'A' && **buf <= 'F') + *retlong += **buf - 'A' + 10; + else + return -1; + } + *retlong *= sign; + *buf = c; + return 0; +} + +static int +remote_fileio_extract_int (char **buf, long *retint) +{ + int ret; + long long retlong; + + if (!retint) + return -1; + if (!(ret = remote_fileio_extract_long (buf, &retlong))) + *retint = (long) retlong; + return ret; +} + +static int +remote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length) +{ + char *c; + long long retlong; + + if (!buf || !*buf || !**buf || !ptrval || !length) + return -1; + c = strchr (*buf, '/'); + if (!c) + return -1; + *c++ = '\0'; + if (remote_fileio_extract_long (buf, &retlong)) + return -1; + *ptrval = (CORE_ADDR) retlong; + *buf = c; + if (remote_fileio_extract_long (buf, &retlong)) + return -1; + *length = (int) retlong; + return 0; +} + +/* Convert to big endian */ +static void +remote_fileio_to_be (long long num, char *buf, int bytes) +{ + int i; + + for (i = 0; i < bytes; ++i) + buf[i] = (num >> (8 * (bytes - i - 1))) & 0xff; +} + +static void +remote_fileio_to_fio_int (long num, fio_int_t fnum) +{ + remote_fileio_to_be ((long long) num, (char *) fnum, 4); +} + +static void +remote_fileio_to_fio_uint (long num, fio_uint_t fnum) +{ + remote_fileio_to_be ((long long) num, (char *) fnum, 4); +} + +static void +remote_fileio_to_fio_mode (mode_t num, fio_mode_t fnum) +{ + remote_fileio_to_be (remote_fileio_mode_to_target(num), (char *) fnum, 4); +} + +static void +remote_fileio_to_fio_time (time_t num, fio_time_t fnum) +{ + remote_fileio_to_be ((long long) num, (char *) fnum, 4); +} + +static void +remote_fileio_to_fio_long (long long num, fio_long_t fnum) +{ + remote_fileio_to_be (num, (char *) fnum, 8); +} + +static void +remote_fileio_to_fio_ulong (long long num, fio_ulong_t fnum) +{ + remote_fileio_to_be (num, (char *) fnum, 8); +} + +static void +remote_fileio_to_fio_stat (struct stat *st, struct fio_stat *fst) +{ + /* `st_dev' is set in the calling function */ + remote_fileio_to_fio_uint ((long) st->st_ino, fst->fst_ino); + remote_fileio_to_fio_mode (st->st_mode, fst->fst_mode); + remote_fileio_to_fio_uint ((long) st->st_nlink, fst->fst_nlink); + remote_fileio_to_fio_uint ((long) st->st_uid, fst->fst_uid); + remote_fileio_to_fio_uint ((long) st->st_gid, fst->fst_gid); + remote_fileio_to_fio_uint ((long) st->st_rdev, fst->fst_rdev); + remote_fileio_to_fio_ulong ((long long) st->st_size, fst->fst_size); + remote_fileio_to_fio_ulong ((long long) st->st_blksize, fst->fst_blksize); + remote_fileio_to_fio_ulong ((long long) st->st_blocks, fst->fst_blocks); + remote_fileio_to_fio_time (st->st_atime, fst->fst_atime); + remote_fileio_to_fio_time (st->st_mtime, fst->fst_mtime); + remote_fileio_to_fio_time (st->st_ctime, fst->fst_ctime); +} + +static void +remote_fileio_to_fio_timeval (struct timeval *tv, struct fio_timeval *ftv) +{ + remote_fileio_to_fio_time (tv->tv_sec, ftv->ftv_sec); + remote_fileio_to_fio_long (tv->tv_usec, ftv->ftv_usec); +} + +static int remote_fio_ctrl_c_flag = 0; +static int remote_fio_no_longjmp = 0; +jmp_buf remote_fio_jmp_buf; + +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) +static struct sigaction remote_fio_sa; +static struct sigaction remote_fio_osa; +#else +static void (*remote_fio_ofunc)(int); +#endif + +static void +remote_fileio_sig_init () +{ +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + remote_fio_sa.sa_handler = SIG_IGN; + sigemptyset (&remote_fio_sa.sa_mask); + remote_fio_sa.sa_flags = 0; + sigaction (SIGINT, &remote_fio_sa, &remote_fio_osa); +#else + remote_fio_ofunc = signal (SIGINT, SIG_IGN); +#endif +} + +static void +remote_fileio_sig_set (void (*sigint_func)(int)) +{ +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + remote_fio_sa.sa_handler = sigint_func; + sigemptyset (&remote_fio_sa.sa_mask); + remote_fio_sa.sa_flags = 0; + sigaction (SIGINT, &remote_fio_sa, NULL); +#else + signal (SIGINT, sigint_func); +#endif +} + +static void +remote_fileio_sig_exit () +{ +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + sigaction (SIGINT, &remote_fio_osa, NULL); +#else + signal (SIGINT, remote_fio_ofunc); +#endif +} + +static void +remote_fileio_ctrl_c_signal_handler (int signo) +{ + remote_fileio_sig_set (SIG_IGN); + remote_fio_ctrl_c_flag = 1; + if (!remote_fio_no_longjmp) + throw_exception (RETURN_QUIT); + remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler); +} + +static void +remote_fileio_reply (int retcode, int error) +{ + char buf[32]; + + remote_fileio_sig_set (SIG_IGN); + strcpy (buf, "F"); + if (retcode < 0) + { + strcat (buf, "-"); + retcode = -retcode; + } + sprintf (buf + strlen (buf), "%x", retcode); + if (error || remote_fio_ctrl_c_flag) + { + if (error && remote_fio_ctrl_c_flag) + error = FILEIO_EINTR; + if (error < 0) + { + strcat (buf, "-"); + error = -error; + } + sprintf (buf + strlen (buf), ",%x", error); + if (remote_fio_ctrl_c_flag) + strcat (buf, ",C"); + } + remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler); + putpkt (buf); +} + +static void +remote_fileio_ioerror () +{ + remote_fileio_reply (-1, FILEIO_EIO); +} + +static void +remote_fileio_badfd () +{ + remote_fileio_reply (-1, FILEIO_EBADF); +} + +static void +remote_fileio_return_errno (int retcode) +{ + remote_fileio_reply (retcode, + retcode < 0 ? remote_fileio_errno_to_target (errno) : 0); +} + +static void +remote_fileio_return_success (int retcode) +{ + remote_fileio_reply (retcode, 0); +} + +/* Wrapper function for remote_write_bytes() which has the disadvantage to + write only one packet, regardless of the requested number of bytes to + transfer. This wrapper calls remote_write_bytes() as often as needed. */ +static int +remote_fileio_write_bytes (CORE_ADDR memaddr, char *myaddr, int len) +{ + int ret = 0, written; + + while (len > 0 && (written = remote_write_bytes (memaddr, myaddr, len)) > 0) + { + len -= written; + memaddr += written; + myaddr += written; + ret += written; + } + return ret; +} + +static void +remote_fileio_func_open (char *buf) +{ + CORE_ADDR ptrval; + int length, retlength; + long num; + int flags, fd; + mode_t mode; + char *pathname; + struct stat st; + + /* 1. Parameter: Ptr to pathname / length incl. trailing zero */ + if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) + { + remote_fileio_ioerror (); + return; + } + /* 2. Parameter: open flags */ + if (remote_fileio_extract_int (&buf, &num)) + { + remote_fileio_ioerror (); + return; + } + flags = remote_fileio_oflags_to_host (num); + /* 3. Parameter: open mode */ + if (remote_fileio_extract_int (&buf, &num)) + { + remote_fileio_ioerror (); + return; + } + mode = remote_fileio_mode_to_host (num, 1); + + /* Request pathname using 'm' packet */ + pathname = alloca (length); + retlength = remote_read_bytes (ptrval, pathname, length); + if (retlength != length) + { + remote_fileio_ioerror (); + return; + } + + /* Check if pathname exists and is not a regular file or directory. If so, + return an appropriate error code. Same for trying to open directories + for writing. */ + if (!stat (pathname, &st)) + { + if (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)) + { + remote_fileio_reply (-1, FILEIO_ENODEV); + return; + } + if (S_ISDIR (st.st_mode) + && ((flags & O_WRONLY) == O_WRONLY || (flags & O_RDWR) == O_RDWR)) + { + remote_fileio_reply (-1, FILEIO_EISDIR); + return; + } + } + + remote_fio_no_longjmp = 1; + fd = open (pathname, flags, mode); + if (fd < 0) + { + remote_fileio_return_errno (-1); + return; + } + + fd = remote_fileio_fd_to_targetfd (fd); + remote_fileio_return_success (fd); +} + +static void +remote_fileio_func_close (char *buf) +{ + long num; + int fd; + + /* Parameter: file descriptor */ + if (remote_fileio_extract_int (&buf, &num)) + { + remote_fileio_ioerror (); + return; + } + if ((fd = remote_fileio_map_fd ((int) num)) == FIO_FD_INVALID) + { + remote_fileio_badfd (); + return; + } + + remote_fio_no_longjmp = 1; + if (fd != FIO_FD_CONSOLE_IN && fd != FIO_FD_CONSOLE_OUT && close (fd)) + remote_fileio_return_errno (-1); + remote_fileio_close_target_fd ((int) num); + remote_fileio_return_success (0); +} + +static void +remote_fileio_func_read (char *buf) +{ + long target_fd, num; + long long lnum; + CORE_ADDR ptrval; + int fd, ret, retlength; + char *buffer; + size_t length; + off_t old_offset, new_offset; + + /* 1. Parameter: file descriptor */ + if (remote_fileio_extract_int (&buf, &target_fd)) + { + remote_fileio_ioerror (); + return; + } + if ((fd = remote_fileio_map_fd ((int) target_fd)) == FIO_FD_INVALID) + { + remote_fileio_badfd (); + return; + } + /* 2. Parameter: buffer pointer */ + if (remote_fileio_extract_long (&buf, &lnum)) + { + remote_fileio_ioerror (); + return; + } + ptrval = (CORE_ADDR) lnum; + /* 3. Parameter: buffer length */ + if (remote_fileio_extract_int (&buf, &num)) + { + remote_fileio_ioerror (); + return; + } + length = (size_t) num; + + switch (fd) + { + case FIO_FD_CONSOLE_OUT: + remote_fileio_badfd (); + return; + case FIO_FD_CONSOLE_IN: + { + static char *remaining_buf = NULL; + static int remaining_length = 0; + + buffer = (char *) xmalloc (32768); + if (remaining_buf) + { + remote_fio_no_longjmp = 1; + if (remaining_length > length) + { + memcpy (buffer, remaining_buf, length); + memmove (remaining_buf, remaining_buf + length, + remaining_length - length); + remaining_length -= length; + ret = length; + } + else + { + memcpy (buffer, remaining_buf, remaining_length); + xfree (remaining_buf); + remaining_buf = NULL; + ret = remaining_length; + } + } + else + { + ret = ui_file_read (gdb_stdtargin, buffer, 32767); + remote_fio_no_longjmp = 1; + if (ret > 0 && (size_t)ret > length) + { + remaining_buf = (char *) xmalloc (ret - length); + remaining_length = ret - length; + memcpy (remaining_buf, buffer + length, remaining_length); + ret = length; + } + } + } + break; + default: + buffer = (char *) xmalloc (length); + /* POSIX defines EINTR behaviour of read in a weird way. It's allowed + for read() to return -1 even if "some" bytes have been read. It + has been corrected in SUSv2 but that doesn't help us much... + Therefore a complete solution must check how many bytes have been + read on EINTR to return a more reliable value to the target */ + old_offset = lseek (fd, 0, SEEK_CUR); + remote_fio_no_longjmp = 1; + ret = read (fd, buffer, length); + if (ret < 0 && errno == EINTR) + { + new_offset = lseek (fd, 0, SEEK_CUR); + /* If some data has been read, return the number of bytes read. + The Ctrl-C flag is set in remote_fileio_reply() anyway */ + if (old_offset != new_offset) + ret = new_offset - old_offset; + } + break; + } + + if (ret > 0) + { + retlength = remote_fileio_write_bytes (ptrval, buffer, ret); + if (retlength != ret) + ret = -1; /* errno has been set to EIO in remote_fileio_write_bytes() */ + } + + if (ret < 0) + remote_fileio_return_errno (-1); + else + remote_fileio_return_success (ret); + + xfree (buffer); +} + +static void +remote_fileio_func_write (char *buf) +{ + long target_fd, num; + long long lnum; + CORE_ADDR ptrval; + int fd, ret, retlength; + char *buffer; + size_t length; + + /* 1. Parameter: file descriptor */ + if (remote_fileio_extract_int (&buf, &target_fd)) + { + remote_fileio_ioerror (); + return; + } + if ((fd = remote_fileio_map_fd ((int) target_fd)) == FIO_FD_INVALID) + { + remote_fileio_badfd (); + return; + } + /* 2. Parameter: buffer pointer */ + if (remote_fileio_extract_long (&buf, &lnum)) + { + remote_fileio_ioerror (); + return; + } + ptrval = (CORE_ADDR) lnum; + /* 3. Parameter: buffer length */ + if (remote_fileio_extract_int (&buf, &num)) + { + remote_fileio_ioerror (); + return; + } + length = (size_t) num; + + buffer = (char *) xmalloc (length); + retlength = remote_read_bytes (ptrval, buffer, length); + if (retlength != length) + { + xfree (buffer); + remote_fileio_ioerror (); + return; + } + + remote_fio_no_longjmp = 1; + switch (fd) + { + case FIO_FD_CONSOLE_IN: + remote_fileio_badfd (); + return; + case FIO_FD_CONSOLE_OUT: + ui_file_write (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr, buffer, + length); + gdb_flush (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr); + ret = length; + break; + default: + ret = write (fd, buffer, length); + if (ret < 0 && errno == EACCES) + errno = EBADF; /* Cygwin returns EACCESS when writing to a R/O file.*/ + break; + } + + if (ret < 0) + remote_fileio_return_errno (-1); + else + remote_fileio_return_success (ret); + + xfree (buffer); +} + +static void +remote_fileio_func_lseek (char *buf) +{ + long num; + long long lnum; + int fd, flag; + off_t offset, ret; + + /* 1. Parameter: file descriptor */ + if (remote_fileio_extract_int (&buf, &num)) + { + remote_fileio_ioerror (); + return; + } + if ((fd = remote_fileio_map_fd ((int) num)) == FIO_FD_INVALID) + { + remote_fileio_badfd (); + return; + } + else if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT) + { + remote_fileio_reply (-1, FILEIO_ESPIPE); + return; + } + + /* 2. Parameter: offset */ + if (remote_fileio_extract_long (&buf, &lnum)) + { + remote_fileio_ioerror (); + return; + } + offset = (off_t) lnum; + /* 3. Parameter: flag */ + if (remote_fileio_extract_int (&buf, &num)) + { + remote_fileio_ioerror (); + return; + } + if (remote_fileio_seek_flag_to_host (num, &flag)) + { + remote_fileio_reply (-1, FILEIO_EINVAL); + return; + } + + remote_fio_no_longjmp = 1; + ret = lseek (fd, offset, flag); + + if (ret == (off_t) -1) + remote_fileio_return_errno (-1); + else + remote_fileio_return_success (ret); +} + +static void +remote_fileio_func_rename (char *buf) +{ + CORE_ADDR ptrval; + int length, retlength; + char *oldpath, *newpath; + int ret, of, nf; + struct stat ost, nst; + + /* 1. Parameter: Ptr to oldpath / length incl. trailing zero */ + if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) + { + remote_fileio_ioerror (); + return; + } + /* Request oldpath using 'm' packet */ + oldpath = alloca (length); + retlength = remote_read_bytes (ptrval, oldpath, length); + if (retlength != length) + { + remote_fileio_ioerror (); + return; + } + /* 2. Parameter: Ptr to newpath / length incl. trailing zero */ + if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) + { + remote_fileio_ioerror (); + return; + } + /* Request newpath using 'm' packet */ + newpath = alloca (length); + retlength = remote_read_bytes (ptrval, newpath, length); + if (retlength != length) + { + remote_fileio_ioerror (); + return; + } + + /* Only operate on regular files and directories */ + if ((!(of = stat (oldpath, &ost)) + && !S_ISREG (ost.st_mode) && !S_ISDIR (ost.st_mode)) + || (!(nf = stat (newpath, &nst)) + && !S_ISREG (nst.st_mode) && !S_ISDIR (nst.st_mode))) + { + remote_fileio_reply (-1, FILEIO_EACCES); + return; + } + + remote_fio_no_longjmp = 1; + ret = rename (oldpath, newpath); + + if (ret == -1) + { + /* Special case: newpath is a non-empty directory. Some systems + return ENOTEMPTY, some return EEXIST. We coerce that to be + always EEXIST. */ + if (errno == ENOTEMPTY) + errno = EEXIST; +#ifdef __CYGWIN__ + /* Workaround some Cygwin problems with correct errnos. */ + if (errno == EACCES) + { + if (!of && !nf && S_ISDIR (nst.st_mode)) + { + if (S_ISREG (ost.st_mode)) + errno = EISDIR; + else + { + char oldfullpath[PATH_MAX + 1]; + char newfullpath[PATH_MAX + 1]; + int len; + + cygwin_conv_to_full_posix_path (oldpath, oldfullpath); + cygwin_conv_to_full_posix_path (newpath, newfullpath); + len = strlen (oldfullpath); + if (newfullpath[len] == '/' + && !strncmp (oldfullpath, newfullpath, len)) + errno = EINVAL; + else + errno = EEXIST; + } + } + } +#endif + + remote_fileio_return_errno (-1); + } + else + remote_fileio_return_success (ret); +} + static void -handle_remote_sigint_twice (int sig) +remote_fileio_func_unlink (char *buf) { - signal (sig, handle_sigint); - sigint_remote_twice_token = - create_async_signal_handler (inferior_event_handler_wrapper, NULL); - mark_async_signal_handler_wrapper (sigint_remote_twice_token); + CORE_ADDR ptrval; + int length, retlength; + char *pathname; + int ret; + struct stat st; + + /* Parameter: Ptr to pathname / length incl. trailing zero */ + if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) + { + remote_fileio_ioerror (); + return; + } + /* Request pathname using 'm' packet */ + pathname = alloca (length); + retlength = remote_read_bytes (ptrval, pathname, length); + if (retlength != length) + { + remote_fileio_ioerror (); + return; + } + + /* Only operate on regular files (and directories, which allows to return + the correct return code) */ + if (!stat (pathname, &st) && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)) + { + remote_fileio_reply (-1, FILEIO_ENODEV); + return; + } + + remote_fio_no_longjmp = 1; + ret = unlink (pathname); + + if (ret == -1) + remote_fileio_return_errno (-1); + else + remote_fileio_return_success (ret); } -/* Perform the real interruption of the target execution, in response - to a ^C. */ static void -async_remote_interrupt (gdb_client_data arg) +remote_fileio_func_stat (char *buf) { - if (remote_debug) - fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n"); + CORE_ADDR ptrval; + int ret, length, retlength; + char *pathname; + long long lnum; + struct stat st; + struct fio_stat fst; - target_stop (); -} + /* 1. Parameter: Ptr to pathname / length incl. trailing zero */ + if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) + { + remote_fileio_ioerror (); + return; + } + /* Request pathname using 'm' packet */ + pathname = alloca (length); + retlength = remote_read_bytes (ptrval, pathname, length); + if (retlength != length) + { + remote_fileio_ioerror (); + return; + } -/* Perform interrupt, if the first attempt did not succeed. Just give - up on the target alltogether. */ -void -async_remote_interrupt_twice (gdb_client_data arg) -{ - if (remote_debug) - fprintf_unfiltered (gdb_stdlog, "remote_interrupt_twice called\n"); - /* Do something only if the target was not killed by the previous - cntl-C. */ - if (target_executing) + /* 2. Parameter: Ptr to struct stat */ + if (remote_fileio_extract_long (&buf, &lnum)) { - interrupt_query (); - signal (SIGINT, handle_remote_sigint); + remote_fileio_ioerror (); + return; + } + ptrval = (CORE_ADDR) lnum; + + remote_fio_no_longjmp = 1; + ret = stat (pathname, &st); + + if (ret == -1) + { + remote_fileio_return_errno (-1); + return; + } + /* Only operate on regular files and directories */ + if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)) + { + remote_fileio_reply (-1, FILEIO_EACCES); + return; + } + if (ptrval) + { + remote_fileio_to_fio_stat (&st, &fst); + remote_fileio_to_fio_uint (0, fst.fst_dev); + + retlength = remote_fileio_write_bytes (ptrval, (char *) &fst, sizeof fst); + if (retlength != sizeof fst) + { + remote_fileio_return_errno (-1); + return; + } } + remote_fileio_return_success (ret); } -/* Reinstall the usual SIGINT handlers, after the target has - stopped. */ static void -cleanup_sigint_signal_handler (void *dummy) +remote_fileio_func_fstat (char *buf) { - signal (SIGINT, handle_sigint); - if (sigint_remote_twice_token) - delete_async_signal_handler ((struct async_signal_handler **) & sigint_remote_twice_token); - if (sigint_remote_token) - delete_async_signal_handler ((struct async_signal_handler **) & sigint_remote_token); -} + CORE_ADDR ptrval; + int fd, ret, retlength; + long target_fd; + long long lnum; + struct stat st; + struct fio_stat fst; + struct timeval tv; -/* Send ^C to target to halt it. Target will respond, and send us a - packet. */ -static void (*ofunc) (int); + /* 1. Parameter: file descriptor */ + if (remote_fileio_extract_int (&buf, &target_fd)) + { + remote_fileio_ioerror (); + return; + } + if ((fd = remote_fileio_map_fd ((int) target_fd)) == FIO_FD_INVALID) + { + remote_fileio_badfd (); + return; + } + /* 2. Parameter: Ptr to struct stat */ + if (remote_fileio_extract_long (&buf, &lnum)) + { + remote_fileio_ioerror (); + return; + } + ptrval = (CORE_ADDR) lnum; -/* The command line interface's stop routine. This function is installed - as a signal handler for SIGINT. The first time a user requests a - stop, we call remote_stop to send a break or ^C. If there is no - response from the target (it didn't stop when the user requested it), - we ask the user if he'd like to detach from the target. */ -static void -remote_interrupt (int signo) -{ - /* If this doesn't work, try more severe steps. */ - signal (signo, remote_interrupt_twice); + remote_fio_no_longjmp = 1; + if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT) + { + remote_fileio_to_fio_uint (1, fst.fst_dev); + st.st_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR); + st.st_nlink = 1; + st.st_uid = getuid (); + st.st_gid = getgid (); + st.st_rdev = 0; + st.st_size = 0; + st.st_blksize = 512; + st.st_blocks = 0; + if (!gettimeofday (&tv, NULL)) + st.st_atime = st.st_mtime = st.st_ctime = tv.tv_sec; + else + st.st_atime = st.st_mtime = st.st_ctime = (time_t) 0; + ret = 0; + } + else + ret = fstat (fd, &st); - if (remote_debug) - fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n"); + if (ret == -1) + { + remote_fileio_return_errno (-1); + return; + } + if (ptrval) + { + remote_fileio_to_fio_stat (&st, &fst); - target_stop (); + retlength = remote_fileio_write_bytes (ptrval, (char *) &fst, sizeof fst); + if (retlength != sizeof fst) + { + remote_fileio_return_errno (-1); + return; + } + } + remote_fileio_return_success (ret); } -/* The user typed ^C twice. */ - static void -remote_interrupt_twice (int signo) +remote_fileio_func_gettimeofday (char *buf) { - signal (signo, ofunc); - interrupt_query (); - signal (signo, remote_interrupt); + long long lnum; + CORE_ADDR ptrval; + int ret, retlength; + struct timeval tv; + struct fio_timeval ftv; + + /* 1. Parameter: struct timeval pointer */ + if (remote_fileio_extract_long (&buf, &lnum)) + { + remote_fileio_ioerror (); + return; + } + ptrval = (CORE_ADDR) lnum; + /* 2. Parameter: some pointer value... */ + if (remote_fileio_extract_long (&buf, &lnum)) + { + remote_fileio_ioerror (); + return; + } + /* ...which has to be NULL */ + if (lnum) + { + remote_fileio_reply (-1, FILEIO_EINVAL); + return; + } + + remote_fio_no_longjmp = 1; + ret = gettimeofday (&tv, NULL); + + if (ret == -1) + { + remote_fileio_return_errno (-1); + return; + } + + if (ptrval) + { + remote_fileio_to_fio_timeval (&tv, &ftv); + + retlength = remote_fileio_write_bytes (ptrval, (char *) &ftv, sizeof ftv); + if (retlength != sizeof ftv) + { + remote_fileio_return_errno (-1); + return; + } + } + remote_fileio_return_success (ret); } -/* This is the generic stop called via the target vector. When a target - interrupt is requested, either by the command line or the GUI, we - will eventually end up here. */ static void -remote_stop (void) +remote_fileio_func_isatty (char *buf) { - /* Send a break or a ^C, depending on user preference. */ - if (remote_debug) - fprintf_unfiltered (gdb_stdlog, "remote_stop called\n"); + long target_fd; + int fd; - if (remote_break) - serial_send_break (remote_desc); - else - serial_write (remote_desc, "\003", 1); + /* Parameter: file descriptor */ + if (remote_fileio_extract_int (&buf, &target_fd)) + { + remote_fileio_ioerror (); + return; + } + remote_fio_no_longjmp = 1; + fd = remote_fileio_map_fd ((int) target_fd); + remote_fileio_return_success (fd == FIO_FD_CONSOLE_IN || + fd == FIO_FD_CONSOLE_OUT ? 1 : 0); } -/* Ask the user what to do when an interrupt is received. */ - static void -interrupt_query (void) +remote_fileio_func_system (char *buf) { - target_terminal_ours (); + CORE_ADDR ptrval; + int ret, length, retlength; + char *cmdline; - if (query ("Interrupted while waiting for the program.\n\ -Give up (and stop debugging it)? ")) + /* Check if system(3) has been explicitely allowed using the + `set remote system-call-allowed 1' command. If not, return + EPERM */ + if (!remote_fio_system_call_allowed) { - target_mourn_inferior (); - throw_exception (RETURN_QUIT); + remote_fileio_reply (-1, FILEIO_EPERM); + return; } - target_terminal_inferior (); + /* Parameter: Ptr to commandline / length incl. trailing zero */ + if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) + { + remote_fileio_ioerror (); + return; + } + /* Request commandline using 'm' packet */ + cmdline = alloca (length); + retlength = remote_read_bytes (ptrval, cmdline, length); + if (retlength != length) + { + remote_fileio_ioerror (); + return; + } + + remote_fio_no_longjmp = 1; + ret = system (cmdline); + + if (ret == -1) + remote_fileio_return_errno (-1); + else + remote_fileio_return_success (WEXITSTATUS (ret)); } -/* Enable/disable target terminal ownership. Most targets can use - terminal groups to control terminal ownership. Remote targets are - different in that explicit transfer of ownership to/from GDB/target - is required. */ +static struct { + char *name; + void (*func)(char *); +} remote_fio_func_map[] = { + "open", remote_fileio_func_open, + "close", remote_fileio_func_close, + "read", remote_fileio_func_read, + "write", remote_fileio_func_write, + "lseek", remote_fileio_func_lseek, + "rename", remote_fileio_func_rename, + "unlink", remote_fileio_func_unlink, + "stat", remote_fileio_func_stat, + "fstat", remote_fileio_func_fstat, + "gettimeofday", remote_fileio_func_gettimeofday, + "isatty", remote_fileio_func_isatty, + "system", remote_fileio_func_system, + NULL, NULL +}; -static void -remote_async_terminal_inferior (void) +static int +do_remote_fileio_request (struct ui_out *uiout, void *buf_arg) { - /* FIXME: cagney/1999-09-27: Shouldn't need to test for - sync_execution here. This function should only be called when - GDB is resuming the inferior in the forground. A background - resume (``run&'') should leave GDB in control of the terminal and - consequently should not call this code. */ - if (!sync_execution) - return; - /* FIXME: cagney/1999-09-27: Closely related to the above. Make - calls target_terminal_*() idenpotent. The event-loop GDB talking - to an asynchronous target with a synchronous command calls this - function from both event-top.c and infrun.c/infcmd.c. Once GDB - stops trying to transfer the terminal to the target when it - shouldn't this guard can go away. */ - if (!remote_async_terminal_ours_p) - return; - delete_file_handler (input_fd); - remote_async_terminal_ours_p = 0; - initialize_sigint_signal_handler (); - /* NOTE: At this point we could also register our selves as the - recipient of all input. Any characters typed could then be - passed on down to the target. */ + char *buf = buf_arg; + char *c; + int idx; + + remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler); + + c = strchr (++buf, ','); + if (c) + *c++ = '\0'; + else + c = strchr (buf, '\0'); + for (idx = 0; remote_fio_func_map[idx].name; ++idx) + if (!strcmp (remote_fio_func_map[idx].name, buf)) + break; + if (!remote_fio_func_map[idx].name) /* ERROR: No such function. */ + return RETURN_ERROR; + remote_fio_func_map[idx].func (c); + return 0; } static void -remote_async_terminal_ours (void) +remote_fileio_request (char *buf) { - /* See FIXME in remote_async_terminal_inferior. */ - if (!sync_execution) - return; - /* See FIXME in remote_async_terminal_inferior. */ - if (remote_async_terminal_ours_p) - return; - cleanup_sigint_signal_handler (NULL); - add_file_handler (input_fd, stdin_event_handler, 0); - remote_async_terminal_ours_p = 1; -} - -/* If nonzero, ignore the next kill. */ + int ex; -int kill_kludge; + remote_fileio_sig_init (); -void -remote_console_output (char *msg) -{ - char *p; + remote_fio_ctrl_c_flag = 0; + remote_fio_no_longjmp = 0; - for (p = msg; p[0] && p[1]; p += 2) - { - char tb[2]; - char c = fromhex (p[0]) * 16 + fromhex (p[1]); - tb[0] = c; - tb[1] = 0; - fputs_unfiltered (tb, gdb_stdtarg); + ex = catch_exceptions (uiout, do_remote_fileio_request, (void *)buf, + NULL, RETURN_MASK_ALL); + switch (ex) + { + case RETURN_ERROR: + remote_fileio_reply (-1, FILEIO_ENOSYS); + break; + case RETURN_QUIT: + remote_fileio_reply (-1, FILEIO_EINTR); + break; + default: + break; } - gdb_flush (gdb_stdtarg); + + remote_fileio_sig_exit (); } /* Wait until the remote machine stops, then return, @@ -2945,6 +4250,9 @@ remote_wait (ptid_t ptid, struct target_ case 'E': /* Error of some sort */ warning ("Remote failure reply: %s", buf); continue; + case 'F': /* File-I/O request */ + remote_fileio_request (buf); + continue; case 'T': /* Status with PC, SP, FP, ... */ { int i; @@ -3196,6 +4504,9 @@ remote_async_wait (ptid_t ptid, struct t case 'E': /* Error of some sort */ warning ("Remote failure reply: %s", buf); continue; + case 'F': /* File-I/O request */ + remote_fileio_request (buf); + continue; case 'T': /* Status with PC, SP, FP, ... */ { int i; @@ -4750,6 +6061,31 @@ remote_remove_breakpoint (CORE_ADDR addr #endif /* REMOTE_BREAKPOINT */ } +static void +set_system_call_allowed (char *args, int from_tty) +{ + if (args) + { + char *arg_end; + int val = strtoul (args, &arg_end, 10); + if (*args && *arg_end == '\0') + { + remote_fio_system_call_allowed = !!val; + return; + } + } + error ("Illegal argument for \"set remote system-call-allowed\" command"); +} + +static void +show_system_call_allowed (char *args, int from_tty) +{ + if (args) + error ("Garbage after \"show remote system-call-allowed\" command: `%s'", args); + printf_unfiltered ("Calling host system(3) call from target is %sallowed\n", + remote_fio_system_call_allowed ? "" : "not "); +} + static int watchpoint_to_Z_packet (int type) { @@ -6167,6 +7503,15 @@ in a memory packet.\n", "Set binary downloads.\n", &setlist), &showlist); #endif + + add_cmd ("system-call-allowed", no_class, + set_system_call_allowed, + "Set if the host system(3) call is allowed for the target.\n", + &remote_set_cmdlist); + add_cmd ("system-call-allowed", no_class, + show_system_call_allowed, + "Show if the host system(3) call is allowed for the target.\n", + &remote_show_cmdlist); add_info ("remote-process", remote_info_process, "Query the remote system for process info."); Index: ui-file.c =================================================================== RCS file: /cvs/src/src/gdb/ui-file.c,v retrieving revision 1.9 diff -u -p -r1.9 ui-file.c --- ui-file.c 25 Jul 2002 03:14:28 -0000 1.9 +++ ui-file.c 21 Nov 2002 08:41:53 -0000 @@ -25,9 +25,12 @@ #include "ui-file.h" #include "gdb_string.h" +#include + static ui_file_isatty_ftype null_file_isatty; static ui_file_write_ftype null_file_write; static ui_file_fputs_ftype null_file_fputs; +static ui_file_read_ftype null_file_read; static ui_file_flush_ftype null_file_flush; static ui_file_delete_ftype null_file_delete; static ui_file_rewind_ftype null_file_rewind; @@ -39,6 +42,7 @@ struct ui_file ui_file_flush_ftype *to_flush; ui_file_write_ftype *to_write; ui_file_fputs_ftype *to_fputs; + ui_file_read_ftype *to_read; ui_file_delete_ftype *to_delete; ui_file_isatty_ftype *to_isatty; ui_file_rewind_ftype *to_rewind; @@ -56,6 +60,7 @@ ui_file_new (void) set_ui_file_flush (file, null_file_flush); set_ui_file_write (file, null_file_write); set_ui_file_fputs (file, null_file_fputs); + set_ui_file_read (file, null_file_read); set_ui_file_isatty (file, null_file_isatty); set_ui_file_rewind (file, null_file_rewind); set_ui_file_put (file, null_file_put); @@ -123,6 +128,15 @@ null_file_write (struct ui_file *file, } } +static long +null_file_read (struct ui_file *file, + char *buf, + long sizeof_buf) +{ + errno = EBADF; + return 0; +} + static void null_file_fputs (const char *buf, struct ui_file *file) { @@ -186,6 +200,12 @@ ui_file_write (struct ui_file *file, file->to_write (file, buf, length_buf); } +long +ui_file_read (struct ui_file *file, char *buf, long length_buf) +{ + return file->to_read (file, buf, length_buf); +} + void fputs_unfiltered (const char *buf, struct ui_file *file) { @@ -224,6 +244,12 @@ set_ui_file_write (struct ui_file *file, } void +set_ui_file_read (struct ui_file *file, ui_file_read_ftype *read) +{ + file->to_read = read; +} + +void set_ui_file_fputs (struct ui_file *file, ui_file_fputs_ftype *fputs) { file->to_fputs = fputs; @@ -383,6 +409,7 @@ mem_file_write (struct ui_file *file, static ui_file_write_ftype stdio_file_write; static ui_file_fputs_ftype stdio_file_fputs; +static ui_file_read_ftype stdio_file_read; static ui_file_isatty_ftype stdio_file_isatty; static ui_file_delete_ftype stdio_file_delete; static struct ui_file *stdio_file_new (FILE * file, int close_p); @@ -409,6 +436,7 @@ stdio_file_new (FILE *file, int close_p) set_ui_file_flush (ui_file, stdio_file_flush); set_ui_file_write (ui_file, stdio_file_write); set_ui_file_fputs (ui_file, stdio_file_fputs); + set_ui_file_read (ui_file, stdio_file_read); set_ui_file_isatty (ui_file, stdio_file_isatty); return ui_file; } @@ -435,6 +463,16 @@ stdio_file_flush (struct ui_file *file) internal_error (__FILE__, __LINE__, "stdio_file_flush: bad magic number"); fflush (stdio->file); +} + +static long +stdio_file_read (struct ui_file *file, char *buf, long length_buf) +{ + struct stdio_file *stdio = ui_file_data (file); + if (stdio->magic != &stdio_file_magic) + internal_error (__FILE__, __LINE__, + "stdio_file_read: bad magic number"); + return read (fileno (stdio->file), buf, length_buf); } static void Index: ui-file.h =================================================================== RCS file: /cvs/src/src/gdb/ui-file.h,v retrieving revision 1.3 diff -u -p -r1.3 ui-file.h --- ui-file.h 25 Jul 2002 03:14:28 -0000 1.3 +++ ui-file.h 21 Nov 2002 08:41:53 -0000 @@ -41,6 +41,9 @@ extern void set_ui_file_write (struct ui typedef void (ui_file_fputs_ftype) (const char *, struct ui_file * stream); extern void set_ui_file_fputs (struct ui_file *stream, ui_file_fputs_ftype * fputs); +typedef long (ui_file_read_ftype) (struct ui_file * stream, char *buf, long length_buf); +extern void set_ui_file_read (struct ui_file *stream, ui_file_read_ftype *fread); + typedef int (ui_file_isatty_ftype) (struct ui_file * stream); extern void set_ui_file_isatty (struct ui_file *stream, ui_file_isatty_ftype * isatty); @@ -77,6 +80,8 @@ extern void ui_file_put (struct ui_file extern char *ui_file_xstrdup (struct ui_file *file, long *length); + +extern long ui_file_read (struct ui_file *file, char *buf, long length_buf); /* Create/open a memory based file. Can be used as a scratch buffer for collecting output. */