gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r29924 - msh/src


From: gnunet
Subject: [GNUnet-SVN] r29924 - msh/src
Date: Mon, 7 Oct 2013 16:19:52 +0200

Author: harsha
Date: 2013-10-07 16:19:52 +0200 (Mon, 07 Oct 2013)
New Revision: 29924

Modified:
   msh/src/Makefile.am
   msh/src/msh_waiter.c
   msh/src/test_pty.c
Log:
- exec child with pty


Modified: msh/src/Makefile.am
===================================================================
--- msh/src/Makefile.am 2013-10-07 13:58:09 UTC (rev 29923)
+++ msh/src/Makefile.am 2013-10-07 14:19:52 UTC (rev 29924)
@@ -31,7 +31,7 @@
 launch_SOURCES = launch.c
 launch_LDADD = -lgnunetutil
 
-test_pty_SOURCES = test_pty.c
+test_pty_SOURCES = test_pty.c mtyes.h ttymodes.h ttymodes.c
 test_pty_LDADD = -lgnunetutil
 
 msh_waiter_SOURCES = msh_waiter.c mtypes.h ttymodes.h ttymodes.c

Modified: msh/src/msh_waiter.c
===================================================================
--- msh/src/msh_waiter.c        2013-10-07 13:58:09 UTC (rev 29923)
+++ msh/src/msh_waiter.c        2013-10-07 14:19:52 UTC (rev 29924)
@@ -285,8 +285,7 @@
   tmsg->ispeed = htonl (speed_to_baud (cfgetispeed (&tio)));
   tmsg->nsettings = htons (count);
 
-  ts = &tmsg->nsettings;
-  ts++;
+  ts = &tmsg[1];
 #define TTYCHAR(NAME,OP)                        \
     *(ts++) = htons (OP);                       \
     *(ts++) = htons (tio.c_cc[NAME]);

Modified: msh/src/test_pty.c
===================================================================
--- msh/src/test_pty.c  2013-10-07 13:58:09 UTC (rev 29923)
+++ msh/src/test_pty.c  2013-10-07 14:19:52 UTC (rev 29924)
@@ -1,6 +1,7 @@
 #include "common.h"
 #include <gnunet/gnunet_util_lib.h>
 #include <termios.h>
+#include "mtypes.h"
 
 /****************************************************************************/
 /* Implemented after http://rachid.koucha.free.fr/tech_corner/pty_pdip.html */
@@ -13,12 +14,24 @@
 
 #define LOG_ERROR(...) LOG(GNUNET_ERROR_TYPE_ERROR, __VA_ARGS__)
 
+#define TIMEOUT(secs) \
+  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, secs)
+
+#define DEFAULT_TIMEOUT TIMEOUT(30)
+
+#define BUF_SIZE 512
+
 /**
  * Task to kill the child
  */
-static GNUNET_SCHEDULER_TaskIdentifier child_death_task_id;
+static GNUNET_SCHEDULER_TaskIdentifier child_death_task;
 
 /**
+ * Task to read output from child
+ */
+static GNUNET_SCHEDULER_TaskIdentifier read_child_task;
+
+/**
  * Pipe used to communicate shutdown via signal.
  */
 static struct GNUNET_DISK_PipeHandle *sigpipe;
@@ -26,39 +39,162 @@
 static struct GNUNET_DISK_FileHandle *chld_io;
 static struct GNUNET_DISK_FileHandle *our_in;
 
+static struct GNUNET_CONNECTION_Handle *conn;
+
+static struct GNUNET_CONNECTION_TransmitHandle *tx;
+
 static char **chld_argv;
 
+static char *cp;
+static struct termios tio;
+static  struct winsize ws;
 
+static int in_receive;
+
+static char buf[BUF_SIZE];
+static size_t buf_off;
+
+
+/**
+ * Function to copy NULL terminated list of arguments
+ *
+ * @param argv the NULL terminated list of arguments. Cannot be NULL.
+ * @return the copied NULL terminated arguments
+ */
+static char **
+copy_argv (char *const *argv)
+{
+  char **argv_dup;
+  unsigned int argp;
+
+  GNUNET_assert (NULL != argv);
+  for (argp = 0; NULL != argv[argp]; argp++) ;
+  argv_dup = GNUNET_malloc (sizeof (char *) * (argp + 1));
+  for (argp = 0; NULL != argv[argp]; argp++)
+    argv_dup[argp] = strdup (argv[argp]);
+  return argv_dup;
+}
+
+
+/**
+ * Frees the given NULL terminated arguments
+ *
+ * @param argv the NULL terminated list of arguments
+ */
 static void
-chld_read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+free_argv (char **argv)
 {
-  char buf[512];
+  unsigned int argp;
+
+  for (argp = 0; NULL != argv[argp]; argp++)
+    GNUNET_free (argv[argp]);
+  GNUNET_free (argv);
+}
+
+
+/**
+ * shutdown task
+ */
+static void
+do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if (NULL != chld_argv)
+  {
+    free_argv (chld_argv);
+    chld_argv = NULL;
+  }
+  if (NULL != conn)
+  {
+    if (in_receive)
+      GNUNET_CONNECTION_receive_cancel (conn);
+    if (NULL != tx)
+      GNUNET_CONNECTION_notify_transmit_ready_cancel (tx);
+    GNUNET_CONNECTION_destroy (conn);
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != child_death_task)
+  {
+    GNUNET_SCHEDULER_cancel (child_death_task);
+    child_death_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  if (NULL != chld_io)
+    GNUNET_DISK_file_close (chld_io);
+}
+
+
+/**
+ * Read the child processes output and send it to over network connection to 
waiter
+ */
+static void
+read_child (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Function called to notify a client about the connection
+ * begin ready to queue more data.  "buf" will be
+ * NULL and "size" zero if the connection was closed for
+ * writing in the meantime.
+ *
+ * @param cls closure
+ * @param size number of bytes available in buf
+ * @param netbuf where the callee should write the message
+ * @return number of bytes written to buf
+ */
+static size_t
+do_tx (void *cls, size_t size, void *netbuf)
+{
+  tx = NULL;
+  if ((NULL == buf) || (0 == size))
+  {
+    LOG_ERROR ("Failure in connectivity\n");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  GNUNET_assert (buf_off <= size);
+  (void) memcpy (netbuf, buf, buf_off);
+  buf_off = 0;
+  if (GNUNET_SCHEDULER_NO_TASK != read_child_task)
+    return;
+  read_child_task = 
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, chld_io,
+                                      &read_child, NULL);
+}
+
+
+/**
+ * Read the child processes output and send it to over network connection to 
waiter
+ */
+static void
+read_child (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
   ssize_t rsize;
-  ssize_t wsize;
 
+  read_child_task = GNUNET_SCHEDULER_NO_TASK;
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
-  rsize = GNUNET_DISK_file_read (chld_io, buf, sizeof (buf));
+  if (BUF_SIZE == buf_off)
+  {
+    GNUNET_assert (NULL != tx);
+    return;
+  }
+  rsize = GNUNET_DISK_file_read (chld_io, buf + buf_off, BUF_SIZE - buf_off);
   if (rsize <= 0)
   {
     LOG_DEBUG ("Child stdout closed\n");
     return;
   }
-  wsize = 0;
-  while ((0 < rsize) && 
-         (GNUNET_SYSERR != (wsize = write (1, ((void *) buf) + wsize, rsize))) 
)
-  {
-    rsize -= wsize;
-  }
-  if (0 != rsize)
-  {
-    GNUNET_break (0);
+  buf_off += rsize;
+  if (NULL != tx)
+    GNUNET_CONNECTION_notify_transmit_ready_cancel (tx);
+  tx = GNUNET_CONNECTION_notify_transmit_ready (conn, buf_off, DEFAULT_TIMEOUT,
+                                                &do_tx, NULL);
+  if (BUF_SIZE == buf_off)
     return;
-  }
-  GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, chld_io,
-                                  &chld_read_task, NULL);
+  read_child_task = 
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, chld_io,
+                                      &read_child, NULL);
 }
 
+
 /**
  * Task triggered whenever we receive a SIGCHLD (child
  * process died).
@@ -67,7 +203,7 @@
  * @param tc context
  */
 static void
-child_death_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+child_died (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   const struct GNUNET_DISK_FileHandle *pr;
   ssize_t rsize;
@@ -75,88 +211,436 @@
   char c[16];
 
   pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
-  child_death_task_id = GNUNET_SCHEDULER_NO_TASK;
+  child_death_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
   if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
   {
-    child_death_task_id =
+    child_death_task =
        GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                       pr, &child_death_task, NULL);
+                                       pr, &child_died, NULL);
     return;
   }
   /* consume the signal */
   GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c)));
   LOG_DEBUG ("Child died\n");
   GNUNET_SCHEDULER_shutdown ();
-  /* read any of the left over IO */
-  GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, chld_io,
-                                  &chld_read_task, NULL);
+  /* FIXME: read any of the left over output from child? */
 }
 
+
+/**
+ * Signal handler called for SIGCHLD.
+ */
 static void
-read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+sighandler_child_death ()
 {
-  char buf[512];
-  ssize_t rsize;
-  ssize_t wsize;
+  static char c;
+  int old_errno = errno;       /* back-up errno */
 
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-  rsize = GNUNET_DISK_file_read (our_in, buf, sizeof (buf));
-  if (GNUNET_SYSERR == rsize)
-    return;
-  wsize = 0;
-  while ((0 < rsize) && 
-         (GNUNET_SYSERR != (wsize = GNUNET_DISK_file_write 
-                            (chld_io, ((void *) buf) + wsize,
-                             rsize))) )
+  GNUNET_break (1 ==
+               GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle
+                                       (sigpipe, GNUNET_DISK_PIPE_END_WRITE),
+                                       &c, sizeof (c)));
+  errno = old_errno;           /* restore errno */
+}
+
+
+/**
+ * Configure the terminal for the child
+ */
+static int
+parse_term_mode (const struct MSH_MSG_PtyMode *msg)
+{
+  uint16_t *params;
+  unsigned int cnt;
+  unsigned int ns;
+  uint16_t msize;
+  size_t expected;
+  speed_t ospeed;
+  speed_t ispeed;
+
+  msize = ntohs (msg->header.size);
+  ns = ntohs (msg->nsettings);
+  expected = (sizeof (struct MSH_MSG_PtyMode) + (sizeof (uint16_t) * ns * 2));
+  if (msize < expected)
   {
-    rsize -= wsize;
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
   }
-  if (0 != rsize)
+#define PARSE_WIN_SIZE(field) \
+  ws.field = ntohs (msg->field);
+  PARSE_WIN_SIZE (ws_row);
+  PARSE_WIN_SIZE (ws_col);
+  PARSE_WIN_SIZE (ws_xpixel);
+  PARSE_WIN_SIZE (ws_ypixel);
+#undef PARSE_WIN_SIZE
+  ospeed = baud_to_speed (ntohl (msg->ospeed));
+  ispeed = baud_to_speed (ntohl (msg->ispeed));
+  if (0 != cfsetospeed (&tio, ospeed))
   {
     GNUNET_break (0);
-    return;
+    return GNUNET_SYSERR;
   }
-  GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, our_in,
-                                  &read_task, NULL);
+  if (0 != cfsetispeed (&tio, ispeed))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  params = (uint16_t *) &msg[1];
+  for (cnt = 0; cnt < ns; cnt++)
+  {
+    switch (ntohs (params[2 * cnt]))
+    {
+#define TTYCHAR(NAME,OP)                                \
+      case OP:                                          \
+        tio.c_cc[NAME] = ntohs (params[(2 * cnt)+1]);   \
+        break;
+#define TTYMODE(NAME, FIELD, OP)                \
+      case OP:                                  \
+        if (1 == ntohs (params[(2 * cnt)+1]))   \
+          tio.FIELD |= NAME;                    \
+        break;
+#include "ttymodes.h"
+#undef TTYCHAR
+#undef TTYMODE
+      
+    default:
+      GNUNET_assert (0);
+    }
+  }
+  if (0 == (msize - expected))
+    return GNUNET_OK;
+  cp = ((void *) msg) + expected;
+  if ('\0' != cp[(msize - expected) - 1])
+  {
+    GNUNET_break (0);
+    cp = NULL;
+    return GNUNET_OK;
+  }
+  cp = GNUNET_strdup (cp);
+  return GNUNET_OK;
 }
 
 
 /**
- * Signal handler called for SIGCHLD.
+ * Create pty, fork, setup the tty modes and exec the given binary
  */
+static int
+spawn_child ()
+{
+  const char *fn;
+  int master;
+  int ret;
+  
+  master = posix_openpt (O_RDWR);
+  if (-1 == master)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "posix_openpt");
+    goto err_ret;
+  }
+  if (-1 == grantpt (master))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "grantpt");
+    goto err_ret;
+  }
+  if (-1 == unlockpt (master))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "unlockpt");
+    goto err_ret;
+  }
+  if (NULL == (fn = ptsname (master)))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "ptsname");
+    goto err_ret;
+  }
+  ret = fork();
+  if (-1 == ret)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
+    goto err_ret;
+  }
+  if (0 != ret)
+  {
+    chld_io = GNUNET_DISK_get_handle_from_int_fd (master);  
+    read_child_task =
+        GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, chld_io,
+                                        &read_child, NULL);
+    return GNUNET_OK;
+  }
+  /* child process */
+  {
+    int slave;
+
+    close (master);
+    close (0);
+    close (1);
+    close (2);
+    slave = open (fn, O_RDWR);
+    if (-1 == slave)
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "open");
+      _exit (1);
+    }
+    if (-1 == tcsetattr (slave, TCSANOW, &tio))
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "tcsetattr");
+      _exit (1);
+    }
+    if (-1 == ioctl (slave, TIOCSWINSZ, &ws))
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "ioctl");
+      _exit (1);
+    }
+    if ( (-1 == dup2 (slave, 0)) ||
+         (-1 == dup2 (slave, 1)) ||
+         (-1 == dup2 (slave, 2)) )
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup");
+      _exit (1);
+    }
+    if (-1 == setsid ())
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsid");
+      _exit (1);
+    }
+    if (-1 == execvp (chld_argv[0], chld_argv))
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "execvp");
+      _exit (1);
+    }
+  }
+
+ err_ret:
+  GNUNET_SCHEDULER_shutdown ();
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Callback function for data received from the network.  Note that
+ * both "available" and "err" would be 0 if the read simply timed out.
+ *
+ * @param cls closure
+ * @param buf pointer to received data
+ * @param available number of bytes availabe in "buf",
+ *        possibly 0 (on errors)
+ * @param addr address of the sender
+ * @param addrlen size of addr
+ * @param errCode value of errno (on errors receiving)
+ */
 static void
-sighandler_child_death ()
+net_receive (void *cls, const void *buf, size_t available,
+             const struct sockaddr * addr, socklen_t addrlen, int errCode)
 {
-  static char c;
-  int old_errno = errno;       /* back-up errno */
+  static enum {
+    STATE_HEADER = 0,
+    STATE_MSG,
+    STATE_FORWARD
+  } state;
+  static struct MSH_MSG_PtyMode *msg;
+  static size_t rb;
+  struct GNUNET_TIME_Relative timeout;
+  size_t rsize;
+  
+  in_receive = 0;
+  if (0 == available)
+  {
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  switch (state)
+  {
+  case STATE_HEADER:
+    {
+      static struct GNUNET_MessageHeader hdr;
+      uint16_t msize;
 
-  GNUNET_break (1 ==
-               GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle
-                                       (sigpipe, GNUNET_DISK_PIPE_END_WRITE),
-                                       &c, sizeof (c)));
-  errno = old_errno;           /* restore errno */
+      GNUNET_assert (available <= sizeof (hdr));
+      memcpy (((void *) &hdr) + rb, buf, available);
+      rb += available;
+      timeout = DEFAULT_TIMEOUT;
+      rsize = sizeof (hdr) - rb;
+      if (0 != rsize)
+        goto read_again;
+      if (MSH_MTYPE_PTY_MODE != ntohs (hdr.type))
+      {
+        GNUNET_break_op (0);
+        GNUNET_SCHEDULER_shutdown ();
+        return;
+      }
+      msize = ntohs (hdr.size);
+      msg = GNUNET_malloc (msize);
+      memcpy (msg, &hdr, sizeof (hdr));
+      rsize = msize - sizeof (hdr);
+      state = STATE_MSG;
+      goto read_again;
+    }
+  case STATE_MSG:
+    {
+      uint16_t msize;
+      
+      msize = ntohs (msg->header.size);
+      GNUNET_assert (available <= (msize - rb));
+      memcpy (((void *) msg) + rb, buf, available);
+      rb += available;
+      timeout = DEFAULT_TIMEOUT;
+      rsize = msize - rb;
+      if (0 != rsize)
+        goto read_again;
+      parse_term_mode (msg);
+      GNUNET_free (msg);
+      msg = NULL;
+      spawn_child ();
+      state = STATE_FORWARD;
+    }
+    break;
+  case STATE_FORWARD:
+    /* receive from net and write to child pty */
+    {
+      size_t wb;
+      ssize_t ret;
+
+      wb = 0;
+      do {
+        ret = GNUNET_DISK_file_write (chld_io, buf + wb, available - wb);
+        if (GNUNET_SYSERR == ret)
+        {
+          GNUNET_break (0);
+          GNUNET_SCHEDULER_shutdown ();
+          return;
+        }
+        wb += ret;
+      } while (wb < available);
+    }
+    break;
+  }
+  rsize = BUF_SIZE;
+  timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  
+ read_again:
+  GNUNET_CONNECTION_receive (conn, rsize, timeout, &net_receive, NULL);
+  in_receive = 1;
 }
 
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
+ * @param c configuration
+ */
 static void
-run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+run (void *cls, 
+     char *const *args, 
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
 {
-  child_death_task_id =
+  unsigned int argc;
+  const char *hostname;
+  const char *portstr;
+  struct sockaddr *addr;
+  struct addrinfo *res;
+  struct addrinfo hints;
+  int af_family;
+  socklen_t addrlen;
+  int ret;
+  
+  argc = 0;
+  hostname = args[argc++];
+  if (NULL == hostname)
+  {
+    GNUNET_break (0); 
+    return;
+  }
+  portstr = args[argc++];
+  if (NULL == portstr)
+  {
+    GNUNET_break (0); 
+    return;
+  }
+  if (NULL == args[argc])
+  {
+    GNUNET_break (0); 
+    return;
+  }
+  (void) memset (&hints, 0, sizeof (hints));
+  hints.ai_flags = AI_NUMERICSERV;
+  hints.ai_family = AF_INET;
+  hints.ai_socktype = SOCK_STREAM;
+  ret = getaddrinfo (hostname, portstr, &hints, &res);
+  if (0 != ret)
+  {
+    LOG_ERROR ("getaddrinfo() failed: %s\n", gai_strerror (ret));
+    return;
+  }
+  if (NULL == res)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  addrlen = res[0].ai_addrlen;
+  addr = GNUNET_malloc (addrlen);
+  memcpy (addr, res[0].ai_addr, addrlen);
+  af_family = res[0].ai_family;
+  freeaddrinfo (res);
+  conn = GNUNET_CONNECTION_create_from_sockaddr (af_family, addr, addrlen);
+  GNUNET_free (addr);
+  if (NULL == conn)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  GNUNET_CONNECTION_receive (conn, sizeof (struct GNUNET_MessageHeader),
+                             DEFAULT_TIMEOUT, &net_receive, NULL);
+  in_receive = 1;
+  child_death_task =
     GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
                                    GNUNET_DISK_pipe_handle (sigpipe,
                                                             
GNUNET_DISK_PIPE_END_READ),
-                                   &child_death_task, NULL);
+                                   &child_died, NULL);
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                &do_shutdown, NULL);
+  chld_argv = copy_argv (&args[argc]);
+  return;
 
-  GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, our_in,
-                                  &read_task, NULL);  
-  GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, chld_io,
-                                  &chld_read_task, NULL);
-  
+ err_ret:
+  GNUNET_break (0);
 }
 
+
 int main(int argc, char *const argv[])
 {
   struct GNUNET_SIGNAL_Context *shc_chld;
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  int ret;
+
+  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+    return 2;
+  if (NULL == (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, 
+                                           GNUNET_NO, GNUNET_NO)))
+  {
+    GNUNET_break (0);
+    return 1;
+  }
+  shc_chld =
+      GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
+  ret = 
+      GNUNET_PROGRAM_run (argc, argv, "test-pty",
+                         gettext_noop
+                         ("msh-waiter test program"),
+                         options, &run, NULL);
+  GNUNET_SIGNAL_handler_uninstall (shc_chld);
+  GNUNET_DISK_pipe_close (sigpipe);
+  GNUNET_free ((void *) argv);
+  return ret;
+}
+
+#if 0
   const char *ptysname;
   int cnt;
   int ptym;
@@ -253,4 +737,5 @@
   GNUNET_DISK_file_close (chld_io);
   GNUNET_SIGNAL_handler_uninstall (shc_chld);
   return 0;
-}
+
+#endif




reply via email to

[Prev in Thread] Current Thread [Next in Thread]