[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;
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r29788 - msh/src,
gnunet <=