gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r29788 - msh/src


From: gnunet
Subject: [GNUnet-SVN] r29788 - msh/src
Date: Wed, 2 Oct 2013 17:28:18 +0200

Author: harsha
Date: 2013-10-02 17:28:18 +0200 (Wed, 02 Oct 2013)
New Revision: 29788

Added:
   msh/src/test_pty.c
Modified:
   msh/src/Makefile.am
Log:
- testing pseudo-terminal invocation


Modified: msh/src/Makefile.am
===================================================================
--- msh/src/Makefile.am 2013-10-02 14:53:13 UTC (rev 29787)
+++ msh/src/Makefile.am 2013-10-02 15:28:18 UTC (rev 29788)
@@ -1,4 +1,4 @@
-bin_PROGRAMS = mping mshd msh
+bin_PROGRAMS = mping mshd msh test-pty
 
 mping_SOURCES = mping.c
 
@@ -30,3 +30,6 @@
 
 launch_SOURCES = launch.c
 launch_LDADD = -lgnunetutil
+
+test_pty_SOURCES = test_pty.c
+test_pty_LDADD = -lgnunetutil

Added: msh/src/test_pty.c
===================================================================
--- msh/src/test_pty.c                          (rev 0)
+++ msh/src/test_pty.c  2013-10-02 15:28:18 UTC (rev 29788)
@@ -0,0 +1,264 @@
+#include "common.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <termios.h>
+
+#define LOG(kind,...)                          \
+  GNUNET_log (kind, __VA_ARGS__)
+
+#define LOG_DEBUG(...) LOG(GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
+
+#define LOG_ERROR(...) LOG(GNUNET_ERROR_TYPE_ERROR, __VA_ARGS__)
+
+/**
+ * Task to kill the child
+ */
+static GNUNET_SCHEDULER_TaskIdentifier child_death_task_id;
+
+/**
+ * Pipe used to communicate shutdown via signal.
+ */
+static struct GNUNET_DISK_PipeHandle *sigpipe;
+
+static struct GNUNET_DISK_FileHandle *chld_io;
+static struct GNUNET_DISK_FileHandle *our_in;
+
+static char **chld_argv;
+
+
+static void
+chld_read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  char buf[512];
+  ssize_t rsize;
+  ssize_t wsize;
+
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+  rsize = GNUNET_DISK_file_read (chld_io, buf, sizeof (buf));
+  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);
+    return;
+  }
+  GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, chld_io,
+                                  &chld_read_task, NULL);
+}
+
+/**
+ * Task triggered whenever we receive a SIGCHLD (child
+ * process died).
+ *
+ * @param cls closure, NULL if we need to self-restart
+ * @param tc context
+ */
+static void
+child_death_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  const struct GNUNET_DISK_FileHandle *pr;
+  ssize_t rsize;
+  ssize_t wsize;
+  char c[16];
+
+  pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
+  child_death_task_id = GNUNET_SCHEDULER_NO_TASK;
+  if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
+  {
+    child_death_task_id =
+       GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                       pr, &child_death_task, 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);
+}
+
+static void
+read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  char buf[512];
+  ssize_t rsize;
+  ssize_t wsize;
+
+  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))) )
+  {
+    rsize -= wsize;
+  }
+  if (0 != rsize)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, our_in,
+                                  &read_task, NULL);
+}
+
+
+/**
+ * Signal handler called for SIGCHLD.
+ */
+static void
+sighandler_child_death ()
+{
+  static char c;
+  int old_errno = errno;       /* back-up errno */
+
+  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 */
+}
+
+static void
+run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  child_death_task_id =
+    GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                   GNUNET_DISK_pipe_handle (sigpipe,
+                                                            
GNUNET_DISK_PIPE_END_READ),
+                                   &child_death_task, NULL);
+
+  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);
+  
+}
+
+int main(int argc, char *const argv[])
+{
+  struct GNUNET_SIGNAL_Context *shc_chld;
+  const char *ptysname;
+  int cnt;
+  int ptym;
+  int ptys;
+  int fret;
+
+  chld_argv = GNUNET_malloc (sizeof (char *) * argc);
+  for (cnt = 0; cnt < (argc - 1); cnt++)
+  {
+    chld_argv[cnt] = GNUNET_strdup (argv[cnt + 1]);
+  }
+  GNUNET_log_setup ("test-pty", "DEBUG", NULL);
+  if (NULL == (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, 
+                                           GNUNET_NO, GNUNET_NO)))
+  {
+    GNUNET_break (0);
+    return 1;
+  }
+  ptym = posix_openpt (O_RDWR);
+  if (-1 == ptym)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "posix_openpt");
+    return 1;
+  }
+  if (-1 == grantpt (ptym))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "grantpt");
+    return 1;
+  }
+  if (-1 == unlockpt (ptym))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "unlockpt");
+    return 1;
+  }
+  if (NULL == (ptysname = ptsname (ptym)))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "ptsname");
+    return 1;
+  }
+  LOG_DEBUG ("Opening slave PTY: %s\n", ptysname);
+  ptys = open (ptysname, O_RDWR);
+  if (-1 == ptys)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "open");
+    return 1;
+  }
+  shc_chld =
+      GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
+  fret = fork();
+  if (-1 == fret)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
+    return 1;
+  }
+  if (0 == fret)
+  {
+    struct termios settings;
+    pid_t mypid;
+    
+    mypid = getpid ();
+    tcgetattr (ptys, &settings);
+    settings.c_lflag &= ~(ECHO);
+    settings.c_lflag |= (ICANON | ISIG);
+    tcsetattr (ptys, TCSANOW, &settings);
+
+    close (ptym);
+    close (0);
+    close (1);
+    //close (2);
+    
+    if ( (-1 == dup (ptys)) || 
+         (-1 == dup (ptys)) ) // || (-1 == dup (ptys)) )
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup");
+      return 1;
+    }
+    close (ptys);
+    
+    if (-1 == setsid ())
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsid");
+      return 1;
+    }
+    if (-1 == ioctl (0, TIOCSCTTY, 1))
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "ioctl");
+      return 1;
+    }
+    if (-1 == tcsetpgrp(0, mypid))
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "tcsetpgrp");
+      return 1;
+    }
+    LOG_DEBUG ("Execing %s\n", chld_argv[0]);
+    if (-1 == execvp (chld_argv[0], chld_argv))
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "execvp");
+      return 1;
+    }
+  }
+  close (ptys);
+  chld_io = GNUNET_DISK_get_handle_from_int_fd (ptym);
+  our_in = GNUNET_DISK_get_handle_from_int_fd (0);
+  GNUNET_SCHEDULER_run (&run, NULL);
+  (void) wait (NULL);
+  GNUNET_DISK_file_close (chld_io);
+  GNUNET_SIGNAL_handler_uninstall (shc_chld);
+  return 0;
+}




reply via email to

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