Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFA]: File-I/O patch
@ 2002-11-21  1:03 Corinna Vinschen
  2002-11-21 11:05 ` Andrew Cagney
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Corinna Vinschen @ 2002-11-21  1:03 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 3237 bytes --]

Hi,

the following patch is the implementation of File-I/O as proposed in
http://sources.redhat.com/ml/gdb/2002-11/msg00107.html

This implementation doesn't include the changes to gdbtk which are
required to get Console I/O working in the GUI.  These will follow
at a later time.

Note that this patch requires also the patch send in the message
http://sources.redhat.com/ml/gdb-patches/2002-11/msg00351.html 

Corinna

2002-11-21  Corinna Vinschen  <vinschen@redhat.com>

        * remote.c (remote_fileio_sig_init, remote_fileio_sig_set,
        remote_fileio_sig_exit, remote_fileio_write_bytes,
        remote_fileio_to_fio_timeval, remote_fileio_func_gettimeofday,
        remote_fileio_mode_to_target, remote_fileio_ctrl_c_signal_handler,
        remote_fileio_init_fd_map, remote_fileio_resize_fd_map,
        remote_fileio_next_free_fd, remote_fileio_fd_to_targetfd,
        remote_fileio_map_fd, remote_fileio_close_target_fd,
        remote_fileio_is_stdio, remote_fileio_oflags_to_host,
        remote_fileio_mode_to_host, remote_fileio_errno_to_target,
        remote_fileio_seek_flag_to_host, remote_fileio_extract_long,
        remote_fileio_extract_int, remote_fileio_extract_ptr_w_len,
        remote_fileio_to_be, remote_fileio_to_fio_int,
        remote_fileio_to_fio_uint, remote_fileio_to_fio_mode,
        remote_fileio_to_fio_time, remote_fileio_to_fio_long,
        remote_fileio_to_fio_ulong, remote_fileio_to_fio_stat,
        remote_fileio_reply, remote_fileio_ioerror, remote_fileio_badfd,
        remote_fileio_return_errno, remote_fileio_return_success,
        remote_fileio_func_open, remote_fileio_func_close,
        remote_fileio_func_read, remote_fileio_func_write,
        remote_fileio_func_lseek, remote_fileio_func_rename,
        remote_fileio_func_unlink, remote_fileio_func_stat,
        remote_fileio_func_fstat, remote_fileio_request,
        remote_fileio_func_system, set_system_call_allowed,
        do_remote_fileio_request, show_system_call_allowed): New functions.
        (remote_wait, remote_async_wait): Call remote_fileio_request() on
        'F' packet.
        (_initialize_remote): Add "set remote system-call-allowed" and
	"show remote system-call-allowed" commands to the UI.

2002-11-21  Martin M. Hunt  <hunt@redhat.com>

        * defs.h: Declare gdb_stdin, gdb_stdtargerr and gdb_stdtargin.
        * main.c: New ui_file gdb_stdin, gdb_stdtargerr and gdb_stdtargin.
        (captured_main): Initialize new ui_files.
        * ui-file.c: Add read and fgets input functions.
        (ui_file_new): set ui_file_fputs and ui_file_read to null functions.
        (null_file_read): New function.
        (null_file_fgets): New function.
        (ui_file_read): New function.
        (ui_file_fgets): New function.
        (set_ui_file_read): New function.
        (set_ui_file_fgets): New function.
        (stdio_file_read): New function.
        (stdio_file_fgets): New function.
        * ui-file.h: New types ui_file_read_ftype and ui_file_fgets_ftype.
        (set_ui_file_read): Declare.
        (set_ui_file_fgets): Declare.
        (ui_file_read): Declare.
        (ui_file_fgets): Declare.

-- 
Corinna Vinschen
Cygwin Developer
Red Hat, Inc.
mailto:vinschen@redhat.com

[-- Attachment #2: fileio.patch --]
[-- Type: text/plain, Size: 51357 bytes --]

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 <sys/types.h>
 #endif
+#include <sys/stat.h>
+#include <sys/wait.h>
+#ifdef __CYGWIN__
+#include <sys/cygwin.h>
+#endif
+#include <setjmp.h>
 
 #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 <errno.h>
+
 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. */

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFA]: File-I/O patch
  2002-11-21  1:03 [RFA]: File-I/O patch Corinna Vinschen
@ 2002-11-21 11:05 ` Andrew Cagney
  2002-11-21 13:04 ` Corinna Vinschen
  2003-03-07 19:31 ` Andrew Cagney
  2 siblings, 0 replies; 9+ messages in thread
From: Andrew Cagney @ 2002-11-21 11:05 UTC (permalink / raw)
  To: Corinna Vinschen; +Cc: gdb-patches

Just FYI,

Its going to be a bit before this patch, and the corresponding doco's 
remote protocol changes, get reviewed.  There are a number of other 
large contributions that should get flushed out first.  (the open risc 
architecture comes to mind).

Can I suggest, for the immedate future, either creating a bugs report or 
park these on a branch.

Andrew


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFA]: File-I/O patch
  2002-11-21  1:03 [RFA]: File-I/O patch Corinna Vinschen
  2002-11-21 11:05 ` Andrew Cagney
@ 2002-11-21 13:04 ` Corinna Vinschen
  2003-03-07 19:31 ` Andrew Cagney
  2 siblings, 0 replies; 9+ messages in thread
From: Corinna Vinschen @ 2002-11-21 13:04 UTC (permalink / raw)
  To: gdb-patches

On Thu, Nov 21, 2002 at 10:03:41AM +0100, Corinna Vinschen wrote:
> 2002-11-21  Martin M. Hunt  <hunt@redhat.com>
> 
>         * defs.h: Declare gdb_stdin, gdb_stdtargerr and gdb_stdtargin.
>         * main.c: New ui_file gdb_stdin, gdb_stdtargerr and gdb_stdtargin.
>         (captured_main): Initialize new ui_files.
>         * ui-file.c: Add read and fgets input functions.
>         (ui_file_new): set ui_file_fputs and ui_file_read to null functions.
>         (null_file_read): New function.
>         (null_file_fgets): New function.
>         (ui_file_read): New function.
>         (ui_file_fgets): New function.
>         (set_ui_file_read): New function.
>         (set_ui_file_fgets): New function.
>         (stdio_file_read): New function.
>         (stdio_file_fgets): New function.
>         * ui-file.h: New types ui_file_read_ftype and ui_file_fgets_ftype.
>         (set_ui_file_read): Declare.
>         (set_ui_file_fgets): Declare.
>         (ui_file_read): Declare.
>         (ui_file_fgets): Declare.

Another error.  The ChangeLog entry is wrong.  Please ignore all
XXX_fgets entries in the ChangeLog, these functions has been eliminated
in favor of the XXX_read funcs.

Sorry again,
Corinna

-- 
Corinna Vinschen
Cygwin Developer
Red Hat, Inc.
mailto:vinschen@redhat.com


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFA]: File-I/O patch
  2002-11-21  1:03 [RFA]: File-I/O patch Corinna Vinschen
  2002-11-21 11:05 ` Andrew Cagney
  2002-11-21 13:04 ` Corinna Vinschen
@ 2003-03-07 19:31 ` Andrew Cagney
  2003-03-10 18:26   ` Corinna Vinschen
  2 siblings, 1 reply; 9+ messages in thread
From: Andrew Cagney @ 2003-03-07 19:31 UTC (permalink / raw)
  To: gdb-patches

Corinna,

There looks to be significant common functionality between this 
"remote.c" patch and the existing "remote-sim.c" code (and for that 
matter, sim/common/callback.c).

I think the basic file io implementation should be moved out of 
"remote.c" and into "fileio.[hc]" so that both remote.c and remote-sim.c 
can share it.

Andrew


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFA]: File-I/O patch
  2003-03-07 19:31 ` Andrew Cagney
@ 2003-03-10 18:26   ` Corinna Vinschen
  2003-06-03 18:31     ` Andrew Cagney
  0 siblings, 1 reply; 9+ messages in thread
From: Corinna Vinschen @ 2003-03-10 18:26 UTC (permalink / raw)
  To: gdb-patches

On Fri, Mar 07, 2003 at 02:30:56PM -0500, Andrew Cagney wrote:
> I think the basic file io implementation should be moved out of 
> "remote.c" and into "fileio.[hc]" so that both remote.c and remote-sim.c 
> can share it.

Ok.  New ChangeLog and patch attached.

Corinna


2003-03-10  Corinna Vinschen  <vinschen@redhat.com>

	* 
        * fileio.c: New file implementing the remote File-I/O protocol.
	* fileio.h: New header file defining remote File-I/O interface.
        * remote.c (remote_write_bytes, remote_read_bytes): Remove
	static storage class.
	(remote_wait, remote_async_wait): Call remote_fileio_request() on
        'F' packet.
        (_initialize_remote): Call initialize_remote_fileio().
	* remote.h: Declare remote_write_bytes() and remote_read_bytes().

2002-11-21  Martin M. Hunt  <hunt@redhat.com>

	* Makefile.in (REMOTE_OBS): Add fileio.o
	(SFILES): Add fileio.c.
	Add dependencies for building fileio.o.  Add fileio.h to
	dependencies for building remote.o.
        * defs.h: Declare gdb_stdin, gdb_stdtargerr and gdb_stdtargin.
        * main.c: New ui_file gdb_stdin, gdb_stdtargerr and gdb_stdtargin.
        (captured_main): Initialize new ui_files.
        * ui-file.c: Add read and fgets input functions.
        (ui_file_new): set ui_file_fputs and ui_file_read to null functions.
        (null_file_read): New function.
        (ui_file_read): New function.
        (set_ui_file_read): New function.
        (stdio_file_read): New function.
        * ui-file.h: New type ui_file_read_ftype.
        (set_ui_file_read): Declare.
        (ui_file_read): Declare.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.341
diff -u -p -r1.341 Makefile.in
--- Makefile.in	5 Mar 2003 18:07:15 -0000	1.341
+++ Makefile.in	10 Mar 2003 18:07:16 -0000
@@ -400,7 +400,7 @@ SER_HARDWIRE = @SER_HARDWIRE@
 
 # The `remote' debugging target is supported for most architectures,
 # but not all (e.g. 960)
-REMOTE_OBS = remote.o dcache.o remote-utils.o tracepoint.o ax-general.o ax-gdb.o
+REMOTE_OBS = remote.o dcache.o remote-utils.o tracepoint.o ax-general.o ax-gdb.o fileio.o
 
 # This is remote-sim.o if a simulator is to be linked in.
 SIM_OBS =
@@ -516,8 +516,8 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
 	dbxread.c demangle.c disasm.c doublest.c \
 	dummy-frame.c dwarfread.c dwarf2expr.c dwarf2loc.c dwarf2read.c \
 	elfread.c environ.c eval.c event-loop.c event-top.c expprint.c \
-	f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c frame.c \
-	frame-unwind.c \
+	f-exp.y f-lang.c f-typeprint.c f-valprint.c fileio.c findvar.c \
+	frame.c frame-unwind.c \
 	gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
 	hpacc-abi.c \
 	inf-loop.c infcmd.c inflow.c infrun.c \
@@ -636,6 +636,7 @@ event_loop_h = event-loop.h
 event_top_h = event-top.h
 expression_h = expression.h $(symtab_h) $(doublest_h)
 f_lang_h = f-lang.h
+fileio_h = fileio.h
 frame_h = frame.h
 frame_unwind_h = frame-unwind.h
 gdb_events_h = gdb-events.h
@@ -1682,6 +1683,7 @@ f-valprint.o: f-valprint.c $(defs_h) $(g
 	$(f_lang_h) $(frame_h) $(gdbcore_h) $(command_h) $(block_h)
 fbsd-proc.o: fbsd-proc.c $(defs_h) $(gdbcore_h) $(inferior_h) \
 	$(gdb_string_h) $(elf_bfd_h) $(gregset_h)
+fileio.o: fileio.c $(defs_h) $(gdb_string_h) $(gdbcmd_h) $(remote_h)
 findvar.o: findvar.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(frame_h) \
 	$(value_h) $(gdbcore_h) $(inferior_h) $(target_h) $(gdb_string_h) \
 	$(gdb_assert_h) $(floatformat_h) $(symfile_h) $(regcache_h) \
@@ -2098,7 +2100,7 @@ remote.o: remote.c $(defs_h) $(gdb_strin
 	$(symfile_h) $(target_h) $(gdbcmd_h) $(objfiles_h) $(gdb_stabs_h) \
 	$(gdbthread_h) $(remote_h) $(regcache_h) $(value_h) $(gdb_assert_h) \
 	$(event_loop_h) $(event_top_h) $(inf_loop_h) $(serial_h) \
-	$(gdbcore_h)
+	$(gdbcore_h) $(fileio_h)
 rom68k-rom.o: rom68k-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
 	$(serial_h) $(regcache_h) $(value_h) $(m68k_tdep_h)
 rs6000-nat.o: rs6000-nat.c $(defs_h) $(inferior_h) $(target_h) $(gdbcore_h) \
Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.116
diff -u -p -r1.116 defs.h
--- defs.h	3 Mar 2003 20:50:18 -0000	1.116
+++ defs.h	10 Mar 2003 18:07:17 -0000
@@ -404,6 +404,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
@@ -416,6 +418,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: fileio.c
===================================================================
RCS file: fileio.c
diff -N fileio.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ fileio.c	10 Mar 2003 18:07:17 -0000
@@ -0,0 +1,1377 @@
+/* Remote File-I/O communications
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* See the GDB User Guide for details of the GDB remote protocol. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "gdbcmd.h"
+#include "remote.h"
+#include "gdb-fileio.h"
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#ifdef USG
+#include <sys/types.h>
+#endif
+#include <sys/stat.h>
+#ifdef __CYGWIN__
+#include <sys/cygwin.h>
+#endif
+#include <setjmp.h>
+#include <signal.h>
+
+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
+remote_fileio_func_unlink (char *buf)
+{
+  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);
+}
+
+static void
+remote_fileio_func_stat (char *buf)
+{
+  CORE_ADDR ptrval;
+  int ret, length, retlength;
+  char *pathname;
+  long long lnum;
+  struct stat st;
+  struct fio_stat fst;
+
+  /* 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;
+    }
+
+  /* 2. Parameter: Ptr to struct stat */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      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);
+}
+
+static void
+remote_fileio_func_fstat (char *buf)
+{
+  CORE_ADDR ptrval;
+  int fd, ret, retlength;
+  long target_fd;
+  long long lnum;
+  struct stat st;
+  struct fio_stat fst;
+  struct timeval tv;
+
+  /* 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;
+
+  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 (ret == -1)
+    {
+      remote_fileio_return_errno (-1);
+      return;
+    }
+  if (ptrval)
+    {
+      remote_fileio_to_fio_stat (&st, &fst);
+
+      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);
+}
+
+static void
+remote_fileio_func_gettimeofday (char *buf)
+{
+  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);
+}
+
+static void
+remote_fileio_func_isatty (char *buf)
+{
+  long target_fd;
+  int fd;
+
+  /* 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);
+}
+
+static void
+remote_fileio_func_system (char *buf)
+{
+  CORE_ADDR ptrval;
+  int ret, length, retlength;
+  char *cmdline;
+
+  /* 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)
+    {
+      remote_fileio_reply (-1, FILEIO_EPERM);
+      return;
+    }
+
+  /* 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));
+}
+
+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 int
+do_remote_fileio_request (struct ui_out *uiout, void *buf_arg)
+{
+  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;
+}
+
+void
+remote_fileio_request (char *buf)
+{
+  int ex;
+
+  remote_fileio_sig_init ();
+
+  remote_fio_ctrl_c_flag = 0;
+  remote_fio_no_longjmp = 0;
+
+  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;
+    }
+
+  remote_fileio_sig_exit ();
+}
+
+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 ");
+}
+
+void
+initialize_remote_fileio (struct cmd_list_element *remote_set_cmdlist,
+			  struct cmd_list_element *remote_show_cmdlist)
+{
+  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);
+}
Index: fileio.h
===================================================================
RCS file: fileio.h
diff -N fileio.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ fileio.h	10 Mar 2003 18:07:17 -0000
@@ -0,0 +1,36 @@
+/* Remote File-I/O communications
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* See the GDB User Guide for details of the GDB remote protocol. */
+
+#ifndef FILEIO_H
+#define FILEIO_H
+
+/* Unified interface to remote fileio, called in remote.c from
+   remote_wait () and remote_async_wait () */
+extern void remote_fileio_request (char *buf);
+
+/* Called from _initialize_remote () */
+extern void initialize_remote_fileio (
+  struct cmd_list_element *remote_set_cmdlist,
+  struct cmd_list_element *remote_show_cmdlist);
+
+#endif
Index: main.c
===================================================================
RCS file: /cvs/src/src/gdb/main.c,v
retrieving revision 1.31
diff -u -p -r1.31 main.c
--- main.c	2 Mar 2003 02:07:12 -0000	1.31
+++ main.c	10 Mar 2003 18:07:18 -0000
@@ -73,6 +73,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 */
 
@@ -193,6 +197,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.95
diff -u -p -r1.95 remote.c
--- remote.c	20 Feb 2003 13:43:14 -0000	1.95
+++ remote.c	10 Mar 2003 18:07:21 -0000
@@ -55,6 +55,8 @@
 
 #include "gdbcore.h" /* for exec_bfd */
 
+#include "fileio.h"
+
 /* Prototypes for local functions */
 static void cleanup_sigint_signal_handler (void *dummy);
 static void initialize_sigint_signal_handler (void);
@@ -67,10 +69,6 @@ void async_remote_interrupt_twice (gdb_c
 
 static void build_remote_gdbarch_data (void);
 
-static int remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len);
-
-static int remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len);
-
 static void remote_files_info (struct target_ops *ignore);
 
 static int remote_xfer_memory (CORE_ADDR memaddr, char *myaddr,
@@ -2945,6 +2943,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 +3197,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;
@@ -3750,7 +3754,7 @@ check_binary_download (CORE_ADDR addr)
    Returns number of bytes transferred, or 0 (setting errno) for
    error.  Only transfer a single packet. */
 
-static int
+int
 remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
 {
   unsigned char *buf;
@@ -3894,7 +3898,7 @@ remote_write_bytes (CORE_ADDR memaddr, c
    caller and its callers caller ;-) already contains code for
    handling partial reads. */
 
-static int
+int
 remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len)
 {
   char *buf;
@@ -6267,4 +6271,7 @@ Set use of remote protocol `Z' packets",
 				set_remote_protocol_Z_packet_cmd,
 				show_remote_protocol_Z_packet_cmd,
 				&remote_set_cmdlist, &remote_show_cmdlist);
+
+  /* Eventually initialize fileio.  See fileio.c */
+  initialize_remote_fileio (remote_set_cmdlist, remote_show_cmdlist);
 }
Index: remote.h
===================================================================
RCS file: /cvs/src/src/gdb/remote.h,v
retrieving revision 1.2
diff -u -p -r1.2 remote.h
--- remote.h	6 Mar 2001 08:21:16 -0000	1.2
+++ remote.h	10 Mar 2003 18:07:21 -0000
@@ -54,4 +54,8 @@ extern void remote_cisco_objfile_relocat
 
 extern void async_remote_interrupt_twice (void *arg);
 
+extern int remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len);
+
+extern int remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len);
+
 #endif
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	10 Mar 2003 18:07:21 -0000
@@ -25,9 +25,12 @@
 #include "ui-file.h"
 #include "gdb_string.h"
 
+#include <errno.h>
+
 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	10 Mar 2003 18:07:21 -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. */


-- 
Corinna Vinschen
Cygwin Developer
Red Hat, Inc.
mailto:vinschen@redhat.com


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFA]: File-I/O patch
  2003-03-10 18:26   ` Corinna Vinschen
@ 2003-06-03 18:31     ` Andrew Cagney
  2003-06-08 18:55       ` Andrew Cagney
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Cagney @ 2003-06-03 18:31 UTC (permalink / raw)
  To: gdb-patches

> On Fri, Mar 07, 2003 at 02:30:56PM -0500, Andrew Cagney wrote:
> 
>> I think the basic file io implementation should be moved out of 
>> "remote.c" and into "fileio.[hc]" so that both remote.c and remote-sim.c 
>> can share it.
> 
> 
> Ok.  New ChangeLog and patch attached.

I'm now looking carefully at the code and, sigh, as things stand, yes, 
the split isn't that simple :-(  So I'm trying to figure out the easiest 
way of getting this current code into something nearer to the expected 
structure.

What i was thinking of was:

remote-fileio.[hc]:
Would provide a target_fileio object and methods leading to something like:
- struct remote_fileio;
- struct remote_fileio *new_remote_fileio();
- create/initialize the fileio
- remote_fileio_open(fileio, const char *name, int modes)
- remote_fileio_read(fileio, CORE_ADDR addr, len)
- et.al.

remote.[hc]:
Would be responsible for the protocol and mapping the remote requests 
onto relevant remote_fileio_XXX() calls.

That way I could modify remote-sim to use those file I/O methods and 
delete the duplicated code.

Unfortunatly, the current code assumes a single target (using the global 
remote_fio_data); and the existing remote_fileio_func_open() methods 
both unpack the protocol and perform the I/O operation.  This makes 
reusing this code from remote-sim very hard.  Sigh.

I'm not sure what to do next, any suggestions?

My best guess is if the code at least addresses the global 
remote_fio_data problem it avoids problems with trying to have multiple 
targets.  The re-org needed for integrating it into remote-sim would 
have to come much much later (i.e., it probably wouldn't happen).

Andrew

> 2003-03-10  Corinna Vinschen  <vinschen@redhat.com>
> 
> 	* 
>         * fileio.c: New file implementing the remote File-I/O protocol.
> 	* fileio.h: New header file defining remote File-I/O interface.
>         * remote.c (remote_write_bytes, remote_read_bytes): Remove
> 	static storage class.
> 	(remote_wait, remote_async_wait): Call remote_fileio_request() on
>         'F' packet.
>         (_initialize_remote): Call initialize_remote_fileio().
> 	* remote.h: Declare remote_write_bytes() and remote_read_bytes().
> 
> 2002-11-21  Martin M. Hunt  <hunt@redhat.com>
> 
> 	* Makefile.in (REMOTE_OBS): Add fileio.o
> 	(SFILES): Add fileio.c.
> 	Add dependencies for building fileio.o.  Add fileio.h to
> 	dependencies for building remote.o.
>         * defs.h: Declare gdb_stdin, gdb_stdtargerr and gdb_stdtargin.
>         * main.c: New ui_file gdb_stdin, gdb_stdtargerr and gdb_stdtargin.
>         (captured_main): Initialize new ui_files.
>         * ui-file.c: Add read and fgets input functions.
>         (ui_file_new): set ui_file_fputs and ui_file_read to null functions.
>         (null_file_read): New function.
>         (ui_file_read): New function.
>         (set_ui_file_read): New function.
>         (stdio_file_read): New function.
>         * ui-file.h: New type ui_file_read_ftype.
>         (set_ui_file_read): Declare.
>         (ui_file_read): Declare.
> 



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFA]: File-I/O patch
  2003-06-03 18:31     ` Andrew Cagney
@ 2003-06-08 18:55       ` Andrew Cagney
  2003-06-10 14:44         ` Corinna Vinschen
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Cagney @ 2003-06-08 18:55 UTC (permalink / raw)
  To: Andrew Cagney, Corinna Vinschen; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 500 bytes --]

> I'm not sure what to do next, any suggestions?

None.

> My best guess is if the code at least addresses the global remote_fio_data problem it avoids problems with trying to have multiple targets.  The re-org needed for integrating it into remote-sim would have to come much much later (i.e., it probably wouldn't happen).

Corinna, can you please check this into the mainline but with the rename:

	gdb/fileio.[hc] -> gdb/remote-fileio.[hc]

commit/use the attached include/gdb/fileio.h.

Andrew


[-- Attachment #2: fileio.h --]
[-- Type: text/plain, Size: 4680 bytes --]

/* Hosted File I/O interface definitions, for GDB, the GNU Debugger.

   Copyright 2003 Free Software Fondation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  */

#ifndef GDB_FILEIO_H
#define GDB_FILEIO_H

/* The following flags are defined to be independent of the host as
   well as the target side implementation of these constants.  All
   constants are defined with a leading FILEIO_ in the name to allow
   the usage of these constants together with the corresponding
   implementation dependent constants in one module.  */

/* open(2) flags */
#define FILEIO_O_RDONLY           0x0
#define FILEIO_O_WRONLY           0x1
#define FILEIO_O_RDWR             0x2
#define FILEIO_O_APPEND           0x8
#define FILEIO_O_CREAT          0x200
#define FILEIO_O_TRUNC          0x400
#define FILEIO_O_EXCL           0x800
#define FILEIO_O_SUPPORTED	(FILEIO_O_RDONLY | FILEIO_O_WRONLY| \
				 FILEIO_O_RDWR   | FILEIO_O_APPEND| \
				 FILEIO_O_CREAT  | FILEIO_O_TRUNC| \
				 FILEIO_O_EXCL)

/* mode_t bits */
#define FILEIO_S_IFREG        0100000
#define FILEIO_S_IFDIR         040000
#define FILEIO_S_IFCHR         020000
#define FILEIO_S_IRUSR           0400
#define FILEIO_S_IWUSR           0200
#define FILEIO_S_IXUSR           0100
#define FILEIO_S_IRWXU           0700
#define FILEIO_S_IRGRP            040
#define FILEIO_S_IWGRP            020
#define FILEIO_S_IXGRP            010
#define FILEIO_S_IRWXG            070
#define FILEIO_S_IROTH             04
#define FILEIO_S_IWOTH             02
#define FILEIO_S_IXOTH             01
#define FILEIO_S_IRWXO             07
#define FILEIO_S_SUPPORTED         (FILEIO_S_IFREG|FILEIO_S_IFDIR|  \
				    FILEIO_S_IRWXU|FILEIO_S_IRWXG|  \
                                    FILEIO_S_IRWXO)

/* lseek(2) flags */
#define FILEIO_SEEK_SET             0
#define FILEIO_SEEK_CUR             1
#define FILEIO_SEEK_END             2

/* errno values */
#define FILEIO_EPERM                1
#define FILEIO_ENOENT               2
#define FILEIO_EINTR                4
#define FILEIO_EIO                  5
#define FILEIO_EBADF                9
#define FILEIO_EACCES              13
#define FILEIO_EFAULT              14
#define FILEIO_EBUSY               16
#define FILEIO_EEXIST              17
#define FILEIO_ENODEV              19
#define FILEIO_ENOTDIR             20
#define FILEIO_EISDIR              21
#define FILEIO_EINVAL              22
#define FILEIO_ENFILE              23
#define FILEIO_EMFILE              24
#define FILEIO_EFBIG               27
#define FILEIO_ENOSPC              28
#define FILEIO_ESPIPE              29
#define FILEIO_EROFS               30
#define FILEIO_ENOSYS		   88
#define FILEIO_ENAMETOOLONG        91
#define FILEIO_EUNKNOWN          9999

/* limits */
#define FILEIO_INT_MIN    -2147483648L
#define FILEIO_INT_MAX     2147483647L
#define FILEIO_UINT_MAX    4294967295UL
#define FILEIO_LONG_MIN   -9223372036854775808LL
#define FILEIO_LONG_MAX    9223372036854775807LL
#define FILEIO_ULONG_MAX   18446744073709551615ULL

#define FIO_INT_LEN   4
#define FIO_UINT_LEN  4
#define FIO_MODE_LEN  4
#define FIO_TIME_LEN  4
#define FIO_LONG_LEN  8
#define FIO_ULONG_LEN 8

typedef char fio_int_t[FIO_INT_LEN];   
typedef char fio_uint_t[FIO_UINT_LEN];
typedef char fio_mode_t[FIO_MODE_LEN];
typedef char fio_time_t[FIO_TIME_LEN];
typedef char fio_long_t[FIO_LONG_LEN];
typedef char fio_ulong_t[FIO_ULONG_LEN];

/* Struct stat as used in protocol.  For complete independence of
   host/target systems, it's defined as an array with offsets to the
   members.  */

struct fio_stat
{
  fio_uint_t  fst_dev;
  fio_uint_t  fst_ino;
  fio_mode_t  fst_mode;
  fio_uint_t  fst_nlink;
  fio_uint_t  fst_uid;
  fio_uint_t  fst_gid;
  fio_uint_t  fst_rdev;
  fio_ulong_t fst_size;
  fio_ulong_t fst_blksize;
  fio_ulong_t fst_blocks;
  fio_time_t  fst_atime;
  fio_time_t  fst_mtime;
  fio_time_t  fst_ctime;
};

struct fio_timeval
{
  fio_time_t  ftv_sec;
  fio_long_t  ftv_usec;
};

#endif /* GDB_FILEIO_H */

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFA]: File-I/O patch
  2003-06-08 18:55       ` Andrew Cagney
@ 2003-06-10 14:44         ` Corinna Vinschen
  2003-06-10 15:51           ` Andrew Cagney
  0 siblings, 1 reply; 9+ messages in thread
From: Corinna Vinschen @ 2003-06-10 14:44 UTC (permalink / raw)
  To: gdb-patches

On Sun, Jun 08, 2003 at 02:55:07PM -0400, Andrew Cagney wrote:
> Corinna, can you please check this into the mainline but with the rename:
> 
> 	gdb/fileio.[hc] -> gdb/remote-fileio.[hc]
> 
> commit/use the attached include/gdb/fileio.h.

Applied.

Corinna

-- 
Corinna Vinschen
Cygwin Developer
Red Hat, Inc.
mailto:vinschen@redhat.com


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFA]: File-I/O patch
  2003-06-10 14:44         ` Corinna Vinschen
@ 2003-06-10 15:51           ` Andrew Cagney
  0 siblings, 0 replies; 9+ messages in thread
From: Andrew Cagney @ 2003-06-10 15:51 UTC (permalink / raw)
  To: gdb-patches

> On Sun, Jun 08, 2003 at 02:55:07PM -0400, Andrew Cagney wrote:
> 
>> Corinna, can you please check this into the mainline but with the rename:
>> 
>> 	gdb/fileio.[hc] -> gdb/remote-fileio.[hc]
>> 
>> commit/use the attached include/gdb/fileio.h.

I should explain the rationale.  With out the rename, but with 
gdb-fileio.h in include/gdb/fileio.h, the source tree ends up with:

	src/gdb/fileio.h
	src/include/gdb/fileio.h

which makes for a confusing #include "gdb/fileio.h".

Andrew


> Applied.
> 
> Corinna
> 
> -- Corinna Vinschen Cygwin Developer Red Hat, Inc. mailto:vinschen@redhat.com 



^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2003-06-10 15:51 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-11-21  1:03 [RFA]: File-I/O patch Corinna Vinschen
2002-11-21 11:05 ` Andrew Cagney
2002-11-21 13:04 ` Corinna Vinschen
2003-03-07 19:31 ` Andrew Cagney
2003-03-10 18:26   ` Corinna Vinschen
2003-06-03 18:31     ` Andrew Cagney
2003-06-08 18:55       ` Andrew Cagney
2003-06-10 14:44         ` Corinna Vinschen
2003-06-10 15:51           ` Andrew Cagney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox