gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r30827 - msh/src


From: gnunet
Subject: [GNUnet-SVN] r30827 - msh/src
Date: Wed, 20 Nov 2013 14:58:08 +0100

Author: harsha
Date: 2013-11-20 14:58:08 +0100 (Wed, 20 Nov 2013)
New Revision: 30827

Added:
   msh/src/pmonitor.c
   msh/src/pmonitor.h
   msh/src/server.c
   msh/src/server.h
Removed:
   msh/src/mshd-server.c
   msh/src/mshd_pmonitor.c
   msh/src/mshd_pmonitor.h
Modified:
   msh/src/msh.c
   msh/src/mshd.c
   msh/src/test_pty.c
Log:
- file rename; fork upon accepting new connections


Modified: msh/src/msh.c
===================================================================
--- msh/src/msh.c       2013-11-20 10:55:44 UTC (rev 30826)
+++ msh/src/msh.c       2013-11-20 13:58:08 UTC (rev 30827)
@@ -680,8 +680,6 @@
 static int
 read_tty_settings ()
 {
-  unsigned int cnt;
-
   if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
   {
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "ioctl");
@@ -692,6 +690,7 @@
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "tcgetattr");
     return GNUNET_SYSERR;
   }
+  return GNUNET_OK;
 }
 
 

Deleted: msh/src/mshd-server.c
===================================================================
--- msh/src/mshd-server.c       2013-11-20 10:55:44 UTC (rev 30826)
+++ msh/src/mshd-server.c       2013-11-20 13:58:08 UTC (rev 30827)
@@ -1,1161 +0,0 @@
-/**
- * @file mshd-server.c
- * @brief functions implementing server functionalities of MSH daemon.  We
- *          listen for commands from locally started MSH instances and also for
- *          executing commands given by remote MSH daemons.
- * @author Sree Harsha Totakura <address@hidden> 
- */
-
-#include "common.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <termios.h>
-#include "mshd.h"
-#include "addressmap.h"
-#include "mshd_pmonitor.h"
-#include "util.h"
-
-#define TIMEOUT_SECS(s) \
-  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, s)
-
-#define LOG(kind,...)                           \
-  GNUNET_log_from (kind, "mshd-server", __VA_ARGS__)
-
-#define LOG_DEBUG(...) LOG(GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
-
-#define LOG_ERROR(...) LOG(GNUNET_ERROR_TYPE_ERROR, __VA_ARGS__)
-
-#define LOG_STRERROR(kind,cmd)                  \
-  GNUNET_log_from_strerror (kind, "mshd-error", cmd)
-
-/**
- * server handle for accepting requests from local MSH instances
- */
-static struct GNUNET_SERVER_Handle *local_serv;
-
-/**
- * server handle for acceptiong requests from remote MSHD instances
- */
-static struct GNUNET_SERVER_Handle *daemon_serv;
-
-/**
- * Notification queue for the local server
- */
-static struct GNUNET_SERVER_NotificationContext *local_serv_nc;
-
-/**
- * Notification queue for the daemon server
- */
-static struct GNUNET_SERVER_NotificationContext *daemon_serv_nc;
-
-/**
- * Our UID.  We use this for access checks
- */
-uid_t our_uid;
-
-/**
- * Our GID.  We use this for access checks
- */
-uid_t our_gid;
-
-
-/**
- * Context for connections requiring to execute commands
- */
-struct ExecCtx
-{
-  /**
-   * The client handle this context is associated with
-   */
-  struct GNUNET_SERVER_Client *client;
-  
-  /**
-   * The command strings to execute
-   */
-  char **args;
-
-  /**
-   * file handle for processes input
-   */
-  struct GNUNET_DISK_FileHandle *fin;
-
-  /**
-   * file handle for processes output
-   */
-  struct GNUNET_DISK_FileHandle *fout;
-  
-  /**
-   * input buffer.  Data from this buffer is written to proc's STDIN when it is
-   * available for writing.
-   */
-  char *buf;
-
-  /**
-   * If this session were to be interactive, the message containing the setting
-   * to use for the pseudo-tty we create
-   */
-  struct MSH_MSG_PtyMode *pty_mode;
-
-  /**
-   * The size of the input buffer
-   */
-  size_t bufsize;
-
-  /**
-   * salt hash used for authentication
-   */
-  struct GNUNET_HashCode salt;
-
-  /**
-   * timeout task
-   */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-  /**
-   * task to read the output from the process
-   */
-  GNUNET_SCHEDULER_TaskIdentifier fout_task;
-
-  /**
-   * task to write data received from the client to proc's STDIN
-   */
-  GNUNET_SCHEDULER_TaskIdentifier fin_task;
-
-  /**
-   * The pid of the child we start
-   */
-  pid_t child_pid;
-
-  /**
-   * If this is an interactive session, this is the master side of the
-   * pseudo-tty we create
-   */
-  int master;
-
-  /**
-   * Is this an interactive session?
-   */
-  int interactive;
-
-  /**
-   * Is this session authentication?
-   */
-  int authenticated;
-
-  /**
-   * If this is an interactive session, is a pseudo-tty created?
-   */
-  int pty_created;
-};
-
-
-/**
- * Destroys an execution context
- * 
- * @param ctx execution context
- */
-static void
-destroy_exec_ctx (struct ExecCtx *ctx)
-{
-  unsigned int cnt;
-
-  GNUNET_SERVER_client_drop (ctx->client);
-  if (NULL != ctx->args)
-  {
-    for (cnt = 0; NULL != ctx->args[cnt]; cnt++)
-      GNUNET_free (ctx->args[cnt]);
-    GNUNET_free (ctx->args);
-  }
-  if (0 != ctx->child_pid)
-  {
-    MSH_monitor_process_pid_cancel (ctx->child_pid);
-    GNUNET_break (0 == kill (ctx->child_pid, SIGTERM));
-  }
-  GNUNET_DISK_file_close (ctx->fin);
-  GNUNET_DISK_file_close (ctx->fout);
-  if (GNUNET_SCHEDULER_NO_TASK != ctx->timeout_task)
-    GNUNET_SCHEDULER_cancel (ctx->timeout_task);
-  if (GNUNET_SCHEDULER_NO_TASK != ctx->fout_task)
-    GNUNET_SCHEDULER_cancel (ctx->fout_task);
-  if (NULL != ctx->buf)
-    GNUNET_free (ctx->buf);
-  GNUNET_free_non_null (ctx->pty_mode);
-  GNUNET_free (ctx);
-}
-
-
-/**
- * Parse contingious 0-terminated strings from a buffer of given length
- *
- * @param buf the buffer
- * @param size the size of the buffer
- * @param s will contain the array of strings upon return
- * @return the number of strings returned in the array
- */
-static int
-parse_strings (const char *buf, size_t size, char ***s)
-{
-  const char *p;
-  char **strs;
-  size_t off;
-  unsigned int cnt;
-
-  cnt = 0;
-  strs = NULL;
-  p = NULL;  
-  for (off = 0; off < size; off++)
-  {
-    if ('\0' == buf[off])
-    {
-      if (NULL == p)
-        continue;
-      GNUNET_array_append (strs, cnt, GNUNET_strdup (p));
-      p = NULL;
-      continue;
-    }
-    if (NULL != p)
-      continue;
-    p = &buf[off];
-  }
-  if (0 < cnt)
-    GNUNET_array_append (strs, cnt, NULL);
-  *s = strs;
-  return cnt;
-}
-
-
-/**
- * Create a challenge message 
- *
- * @param ctx the execution context
- * @return the challenge message
- */
-static struct GNUNET_MessageHeader *
-create_challenge_message (struct ExecCtx *ctx)
-{
-  struct MSH_MSG_Challenge *msg;
-  uint16_t size;
-
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE, &ctx->salt);
-  size = sizeof (struct MSH_MSG_Challenge);
-  msg = GNUNET_malloc (size);
-  msg->header.type = htons (MSH_MTYPE_CHALLENGE);
-  msg->header.size = htons (size);
-  GNUNET_CRYPTO_hash_to_enc (&ctx->salt, &msg->salt);
-  LOG_DEBUG ("Challenge nonce: %104s\n", msg->salt.encoding);
-  return &msg->header;
-}
-
-
-/**
- * Functions with this signature are called whenever a message is
- * received.
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_addresslookup (void *cls, struct GNUNET_SERVER_Client *client,
-                      const struct GNUNET_MessageHeader* message)
-{
-  const struct MSH_MSG_AddressLookup *msg;
-  struct MSH_MSG_AddressLookupReply *reply;
-  struct InstanceAddr *iaddr;
-  char *emsg;
-  in_addr_t ip;
-  uint16_t port;
-  uint16_t reply_size;
-  
-  emsg = NULL;
-  port = 0;
-  msg = (const struct MSH_MSG_AddressLookup *) message;
-  ip = ntohl (msg->ip);
-  if (GNUNET_NO == reversemap_check (rmap, ip))
-  {
-    emsg = "Given IP address not present in the current mapping\n";
-    goto respond;
-  }
-  iaddr = reversemap_lookup (rmap, ip);
-  GNUNET_assert (NULL != iaddr);
-  port = instance_address_port (iaddr);
-  LOG_DEBUG ("Received ADDRESS_LOOKUP message for IP: %s and port %u\n",
-             ip2str (ip), port);
- respond:
-  reply_size = sizeof (struct MSH_MSG_AddressLookupReply);
-  if (NULL != emsg)
-    reply_size += strlen (emsg) + 1;
-  reply = GNUNET_malloc (reply_size);
-  reply->header.size = htons (reply_size);
-  reply->header.type = htons (MSH_MTYPE_ADDRESS_LOOKUP_REPLY);
-  reply->port = htons (port);
-  if (NULL != emsg)
-    (void) strcpy (reply->emsg, emsg);
-  GNUNET_SERVER_notification_context_unicast (local_serv_nc, client,
-                                              &reply->header, GNUNET_NO);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Generate the credential for the given challenge 
- *
- * @param c the challenge
- * @param cred output parameter for the credential
- */
-static void
-auth_challenge_cred (struct GNUNET_HashCode *c, struct GNUNET_HashCode *cred)
-{
-  struct GNUNET_HashCode xor;
-
-  GNUNET_CRYPTO_hash_xor (c, &shash, &xor);
-  GNUNET_CRYPTO_hash (&xor, sizeof (struct GNUNET_HashCode), cred);
-}
-
-
-/**
- * Functions with this signature are called whenever a message is
- * received.
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_auth_challenge (void *cls, struct GNUNET_SERVER_Client *client,
-                       const struct GNUNET_MessageHeader* message)
-{
-  const struct MSH_MSG_Challenge *msg;
-  struct MSH_MSG_ChallengeResponse *reply;
-  struct GNUNET_HashCode salt;
-  struct GNUNET_HashCode cred;
-
-  msg = (const struct MSH_MSG_Challenge *) message;
-  LOG_DEBUG ("Challenge nonce: %104s\n", msg->salt.encoding);
-  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_hash_from_string 
-                 ((const char *) msg->salt.encoding, &salt));
-  auth_challenge_cred (&salt, &cred);
-  reply = GNUNET_malloc (sizeof (struct MSH_MSG_ChallengeResponse));
-  reply->header.size = htons (sizeof (struct MSH_MSG_ChallengeResponse));
-  reply->header.type = htons (MSH_MTYPE_CHALLENGE_RESPONSE);
-  GNUNET_CRYPTO_hash_to_enc (&cred, &reply->auth);
-  GNUNET_SERVER_notification_context_unicast (local_serv_nc, client,
-                                              &reply->header, GNUNET_NO);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Function to call for access control checks.
- *
- * @param cls closure
- * @param ucred credentials, if available, otherwise NULL
- * @param addr address
- * @param addrlen length of address
- * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR
- *   for unknown address family (will be denied).
- */
-static int
-check_local_access (void *cls,
-              const struct GNUNET_CONNECTION_Credentials *cred,
-              const struct sockaddr * addr, socklen_t addrlen)
-{
-  if ((our_uid != cred->uid) && (our_gid != cred->gid))
-    return GNUNET_NO;
-  return GNUNET_YES;
-}
-
-
-/**
- * Callback to be called when ever a client connects to the local server
- *
- * @param cls NULL
- * @param client the client handle
- */
-static void
-local_server_connect (void *cls, struct GNUNET_SERVER_Client *client)
-{
-  if (NULL == client)           /* Server shutting down */
-    return;
-  LOG_DEBUG ("A client has been connected locally\n");
-  GNUNET_SERVER_notification_context_add (local_serv_nc, client);
-}
-
-
-/**
- * Initialise the local server
- *
- * @param unixpath the name to use while opening the abstract UNIX domain 
socket
- *   for listening
- * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
- */
-int
-init_local_server (const char *unixpath)
-{
-  struct sockaddr_un saddr;
-  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
-    {&handle_addresslookup, NULL, MSH_MTYPE_ADDRESS_LOOKUP, sizeof (struct
-    MSH_MSG_AddressLookup)},
-    {&handle_auth_challenge, NULL, MSH_MTYPE_CHALLENGE, sizeof (struct 
MSH_MSG_Challenge)},
-    {NULL, NULL, 0, 0}
-  };
-  struct sockaddr *saddrs[] = {
-    ((struct sockaddr *) &saddr),
-    NULL
-  };
-  socklen_t saddr_lens[] = {
-    sizeof (struct sockaddr_un),
-     0
-  };
-
-  our_uid = getuid ();
-  our_gid = getgid ();
-  saddr.sun_family = AF_UNIX;
-  (void) memset (saddr.sun_path, 0, sizeof (saddr.sun_path));
-  (void) strncpy (saddr.sun_path, unixpath, sizeof (saddr.sun_path) - 1);
-  local_serv = GNUNET_SERVER_create (&check_local_access, NULL,
-                                     saddrs,
-                                     saddr_lens,
-                                     GNUNET_TIME_UNIT_FOREVER_REL,
-                                     GNUNET_YES);
-  if (NULL == local_serv)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_SERVER_add_handlers (local_serv, handlers);
-  GNUNET_SERVER_connect_notify (local_serv, &local_server_connect, NULL);
-  local_serv_nc = GNUNET_SERVER_notification_context_create (local_serv, 1);
-  return GNUNET_OK;
-}
-
-
-/**
- * Shutdown the local server
- */
-void
-shutdown_local_server ()
-{
-  if (NULL != local_serv)
-  {
-    GNUNET_SERVER_destroy (local_serv);
-    local_serv = NULL;
-  }
-}
-
-
-/******************************************************************************/
-/* Daemon server.  Responsbile for executing commands submitted by remote MSH 
*/
-/* clients                                                                    
*/
-/******************************************************************************/
-
-
-/**
- * Handle session open message and start challenge authentication.
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_session_open (void *cls,
-                     struct GNUNET_SERVER_Client *client,
-                     const struct GNUNET_MessageHeader* message)
-{
-  struct ExecCtx *exec_ctx;
-  const struct MSH_MSG_SessionOpen *msg;
-  struct GNUNET_MessageHeader *reply;
-  uint16_t size;
-  
-  LOG_DEBUG ("Received a SESSION_OPEN message\n");
-  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
-  GNUNET_assert (NULL != exec_ctx);
-  if (NULL != exec_ctx->args)
-  {
-    GNUNET_break (0);
-    goto close_conn;
-  }
-  if (MSH_SESSION_TYPE_INTERACTIVE == ntohl (msg->type))
-    exec_ctx->interactive = GNUNET_YES;
-  reply = create_challenge_message (exec_ctx);
-  LOG_DEBUG ("Sending AUTH_CHALLENGE\n");
-  GNUNET_SERVER_notification_context_unicast (daemon_serv_nc, client, reply,
-                                              GNUNET_NO);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-
- close_conn:
-  GNUNET_break_op (0);
-  GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-}
-
-
-/**
- * Task to read the output from a process and send it to client
- *
- * @param cls the client context
- * @param tc scheduler task context
- */
-static void
-read_fout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct ExecCtx *exec_ctx = cls;
-  struct MSH_MSG_CmdIO *msg;
-  static char data[MAX_IO_DATA];
-  ssize_t size;
-  uint16_t msize;
-
-  exec_ctx->fout_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
-  {
-    return;
-  }
-  size = GNUNET_DISK_file_read_non_blocking (exec_ctx->fout, data, 
MAX_IO_DATA);
-  if (size <= 0)
-  {
-    GNUNET_break (GNUNET_SYSERR != size);
-    GNUNET_SERVER_client_disconnect (exec_ctx->client);
-    return;
-  }
-  msize = size + sizeof (struct MSH_MSG_CmdIO);
-  msg = GNUNET_malloc (msize);
-  msg->header.type = htons (MSH_MTYPE_CMD_STREAM_STDOUT);
-  msg->header.size = htons (msize);
-  memcpy (msg->data, data, size);
-  GNUNET_SERVER_notification_context_unicast (daemon_serv_nc, exec_ctx->client,
-                                              &msg->header, GNUNET_NO);
-  exec_ctx->fout_task = 
-      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                      exec_ctx->fout, &read_fout, exec_ctx);
-}
-
-
-/**
- * Configure the terminal for the child
- */
-static int
-parse_term_mode (const struct MSH_MSG_PtyMode *msg,
-                 struct termios *tio,
-                 struct winsize *ws,
-                 char **termstr)
-{
-  uint16_t *params;
-  char *str;
-  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)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-#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 GNUNET_SYSERR;
-  }
-  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;
-  str = ((void *) msg) + expected;
-  if ('\0' != str[(msize - expected) - 1])
-  {
-    GNUNET_break (0);
-    str = NULL;
-    return GNUNET_OK;
-  }
-  *termstr = GNUNET_strdup (str);
-  return GNUNET_OK;
-}
-
-
-/**
- * Callback that will be called when a child processes terminates.  The
- * associated client context for the client which requested this process will 
be
- * destroyed 
- *
- * @param cls the closure passed to MSH_monitor_process()
- * @param type the process status type
- * @param long the return/exit code of the process
- */
-static void
-proc_exit_cb (void *cls, enum GNUNET_OS_ProcessStatusType type, int code)
-{
-  struct ExecCtx *exec_ctx = cls;
-  
-  LOG_DEBUG ("Command `%s' exited.\n", exec_ctx->args[0]);
-  exec_ctx->child_pid = 0;
-  GNUNET_SCHEDULER_cancel (exec_ctx->fout_task);
-  exec_ctx->fout_task = GNUNET_SCHEDULER_add_now (&read_fout, exec_ctx);
-}
-
-
-/**
- * start the process from the execution process
- *
- * @param ctx the execution context
- * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
- */
-static int
-proc_exec (struct ExecCtx *ctx)
-{
-  struct GNUNET_DISK_PipeHandle *pin;
-  struct GNUNET_DISK_PipeHandle *pout;
-  struct GNUNET_OS_Process *proc;
-  char *fnpty;
-  char *termstr;
-  struct winsize ws;
-  struct termios tio;
-  int ret;
-  int slave;
-  
-  if (!ctx->interactive)
-  {
-    pin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, 0, 0);
-    pout = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_YES, 0, 0);
-    GNUNET_assert ((NULL != pin && (NULL != pout)));
-    proc = GNUNET_OS_start_process_vap (GNUNET_NO,
-                                        GNUNET_OS_INHERIT_STD_NONE,
-                                        pin,
-                                        pout,
-                                        ctx->args[0],
-                                        ctx->args);
-    if (NULL == proc)
-      return GNUNET_SYSERR;
-    ctx->child_pid = GNUNET_OS_process_get_pid (proc);
-    GNUNET_OS_process_destroy (proc);
-    MSH_monitor_process_pid (ctx->child_pid, &proc_exit_cb, ctx);
-    ctx->fin = GNUNET_DISK_pipe_detach_end (pin, GNUNET_DISK_PIPE_END_WRITE);
-    ctx->fout = GNUNET_DISK_pipe_detach_end (pout, GNUNET_DISK_PIPE_END_READ);
-    GNUNET_assert ((NULL != ctx->fin && (NULL != ctx->fout)));
-    GNUNET_assert (GNUNET_OK == GNUNET_DISK_pipe_close (pin));
-    GNUNET_assert (GNUNET_OK == GNUNET_DISK_pipe_close (pout));
-    ctx->fout_task = 
-        GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                        ctx->fout, &read_fout, ctx);
-    return GNUNET_OK;
-  }
-  if (NULL == (fnpty = ptsname (ctx->master)))
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "ptsname");
-    return GNUNET_SYSERR;
-  }
-  ret = fork ();
-  if (-1 == ret)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
-    return GNUNET_SYSERR;
-  }
-  if (0 != ret)
-  {
-    int fd;
-
-    LOG_DEBUG ("Forked child successfully\n");
-    ctx->child_pid = ret;
-    MSH_monitor_process_pid (ctx->child_pid, &proc_exit_cb, ctx);
-    /* forward streams to and from child */
-    ctx->fin = GNUNET_DISK_get_handle_from_int_fd (ctx->master);
-    fd = dup (ctx->master);
-    if (-1 == fd)
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup");
-      GNUNET_assert (0 == kill (ret, SIGTERM));
-      return GNUNET_SYSERR;
-    }
-    ctx->fout = GNUNET_DISK_get_handle_from_int_fd (fd);
-    ctx->fout_task =
-        GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 
ctx->fout,
-                                        &read_fout, ctx);
-
-    return GNUNET_OK;
-  }
-  close (ctx->master);
-  LOG_DEBUG ("Opening slave PTY %s\n", fnpty);
-  slave = open (fnpty, O_RDWR);
-  if (-1 == slave)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "open");
-    _exit (1);
-  }
-  if (-1 == tcgetattr (slave, &tio))
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "tcgetattr");
-    _exit (1);
-  }
-  termstr = NULL;
-  parse_term_mode (ctx->pty_mode, &tio, &ws, &termstr);
-  GNUNET_free (ctx->pty_mode);
-  ctx->pty_mode = NULL;
-  if (NULL != termstr)
-  {
-    GNUNET_break (0 == setenv ("TERM", termstr, 1));
-    GNUNET_free (termstr);
-  }
-  else
-    GNUNET_break (0 == setenv ("TERM", "MSH", 1));
-  if (-1 == tcsetattr (slave, TCSANOW, &tio))
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "tcsetattr");
-    //_exit (1);                /* Ignore for now */
-  }
-  if (-1 == ioctl (slave, TIOCSWINSZ, &ws))
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "ioctl");
-    _exit (1);
-  }
-  if (-1 == setsid ())
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsid");
-    _exit (1);
-  }
-  close (0);
-  close (1);
-  //close (2);
-  if ( (-1 == dup2 (slave, 0)) ||
-       (-1 == dup2 (slave, 1)) ) //||
-    //(-1 == dup2 (slave, 2)) )
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup");
-    _exit (2);
-  }
-  close (slave);
-  LOG_DEBUG ("Execing %s\n", ctx->args[0]);
-  if (-1 == execvp (ctx->args[0], ctx->args))
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "execvp");
-    _exit (1);
-  }
-  GNUNET_assert (0);            /* This should never be reached */
-}
-
-
-/**
- * Handle session open message and start challenge authentication.
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_runcmd (void *cls,
-               struct GNUNET_SERVER_Client *client,
-               const struct GNUNET_MessageHeader* message)
-{
-  const struct MSH_MSG_RunCmd *msg;
-  struct ExecCtx *exec_ctx;
-  struct GNUNET_MessageHeader *reply;
-  uint16_t size;
-  
-  LOG_DEBUG ("Received a RUN_CMD message\n");
-  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
-  GNUNET_assert (NULL != exec_ctx);
-  if (GNUNET_YES != exec_ctx->authenticated)
-  {
-    GNUNET_break_op (0);
-    goto close_conn;
-  }
-  if (exec_ctx->interactive && !exec_ctx->pty_created)
-  {
-    GNUNET_break_op (0);
-    goto close_conn;
-  }
-  if (NULL != exec_ctx->args)
-  {
-    GNUNET_break (0);
-    goto close_conn;
-  }
-  size = ntohs (message->size);
-  if ( size <= sizeof (struct MSH_MSG_RunCmd))
-  {
-    GNUNET_break_op (0);
-    goto close_conn; 
-  }
-  msg = (const struct MSH_MSG_RunCmd *) message;
-  if (0 == parse_strings (msg->cmd,
-                          size - sizeof (struct MSH_MSG_RunCmd),
-                          &exec_ctx->args))
-  {
-    GNUNET_break_op (0);
-    goto close_conn;
-  }
-  GNUNET_SCHEDULER_cancel (exec_ctx->timeout_task);
-  exec_ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  if (GNUNET_OK != proc_exec (exec_ctx))
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "Command `%s' not found or not executable\n", exec_ctx->args[0]);
-    goto close_conn;
-  }
-  reply = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
-  reply->size = htons (sizeof (struct GNUNET_MessageHeader));
-  reply->type = htons (MSH_MTYPE_EXEC_BEGIN);
-  GNUNET_SERVER_notification_context_unicast (daemon_serv_nc, exec_ctx->client,
-                                              reply, GNUNET_NO);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-  
- close_conn:
-  GNUNET_break_op (0);
-  GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-}
-
-
-/**
- * Functions with this signature are called whenever a message is
- * received.
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_auth_challenge_response (void *cls,
-                                struct GNUNET_SERVER_Client *client,
-                                const struct GNUNET_MessageHeader* message)
-{
-  const struct MSH_MSG_ChallengeResponse *msg;
-  struct GNUNET_MessageHeader *reply;
-  struct ExecCtx *exec_ctx;
-  struct GNUNET_HashCode cred;
-  struct GNUNET_CRYPTO_HashAsciiEncoded enc;
-  
-  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
-  GNUNET_assert (NULL != exec_ctx);
-  auth_challenge_cred (&exec_ctx->salt, &cred);
-  GNUNET_CRYPTO_hash_to_enc (&cred, &enc);
-  msg = (const struct MSH_MSG_ChallengeResponse *) message;
-  if (0 != memcmp (&msg->auth, &enc,
-                   sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
-  {
-    LOG_DEBUG ("Auth failed: \n"
-               "  Required: %s\n"
-               "  Given: %s\n", enc.encoding, msg->auth.encoding);
-    GNUNET_break (0);
-    goto err_ret;
-  }
-  exec_ctx->authenticated = GNUNET_YES;
-  return;
-  
- err_ret:
-  GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-}
-
-
-/**
- * Task to write data from input buffer to proc's STDIN
- *
- * @param cls the client context
- * @return tc scheduler task context
- */
-static void
-write_fin (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct ExecCtx *exec_ctx = cls;
-  ssize_t wrote;
-  
-  exec_ctx->fin_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))
-  {
-    GNUNET_free (exec_ctx->buf);
-    exec_ctx->buf = NULL;
-    exec_ctx->bufsize = 0;
-    goto err_ret;
-  }
-  wrote = GNUNET_DISK_file_write (exec_ctx->fin,
-                                  exec_ctx->buf, exec_ctx->bufsize);
-  if (GNUNET_SYSERR == wrote)
-  {
-    LOG_ERROR ("Error writing to proc's STDIN\n");
-    goto err_ret;
-  }
-  if (wrote == exec_ctx->bufsize)
-  {
-    GNUNET_free (exec_ctx->buf);
-    exec_ctx->buf = NULL;
-    exec_ctx->bufsize = 0;
-    GNUNET_SERVER_receive_done (exec_ctx->client, GNUNET_OK);
-    return;
-  }
-  GNUNET_assert (wrote < exec_ctx->bufsize);
-  exec_ctx->bufsize -= wrote;
-  exec_ctx->buf = memmove (exec_ctx->buf, exec_ctx->buf + wrote,
-                           exec_ctx->bufsize);
-  exec_ctx->buf = GNUNET_realloc (exec_ctx->buf, exec_ctx->bufsize);
-  exec_ctx->fin_task = 
-      GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                       exec_ctx->fin,
-                                       &write_fin, exec_ctx);
-  return;
-
- err_ret:
-  GNUNET_SERVER_receive_done (exec_ctx->client, GNUNET_SYSERR);
-}
-
-
-/**
- * Handler for messages with command's input stream data.  The date will be
- * written to the command's standard input stream.
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_command_input (void *cls,
-                      struct GNUNET_SERVER_Client *client,
-                      const struct GNUNET_MessageHeader* message)
-{
-  const struct MSH_MSG_CmdIO *msg;
-  struct ExecCtx *exec_ctx;
-  ssize_t wrote;
-  uint16_t size;
- 
-  LOG_DEBUG ("Received CMD_IO_STDIN message\n");
-  size = ntohs (message->size);
-  msg = (const struct MSH_MSG_CmdIO *) message;
-  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
-  GNUNET_assert (NULL != exec_ctx);
-  size -= sizeof (struct MSH_MSG_CmdIO);
-  wrote = GNUNET_DISK_file_write (exec_ctx->fin, msg->data, size);
-  if (GNUNET_SYSERR == wrote)
-  {
-    LOG_ERROR ("Error writing to proc's STDIN\n");
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  LOG_DEBUG ("Wrote %zd to proc's STDIN\n", wrote);
-  if (wrote == size)
-  {
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  GNUNET_assert (wrote < size);
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == exec_ctx->fin_task);
-  GNUNET_assert (NULL == exec_ctx->buf);
-  GNUNET_assert (0 == exec_ctx->bufsize);
-  exec_ctx->bufsize = size - wrote;
-  exec_ctx->buf = GNUNET_malloc (exec_ctx->bufsize);
-  (void) memcpy (exec_ctx->buf, msg->data + wrote, exec_ctx->bufsize);
-  exec_ctx->fin_task = 
-      GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                       exec_ctx->fin,
-                                       &write_fin, exec_ctx);
-  GNUNET_SERVER_disable_receive_done_warning (client);
-}
-
-
-/**
- * Handler for messages containing the settings to be used while creating a
- * psuedo-tty.  This message must only be received for interactive sessions
- * before #MSH_MSG_RunCmd message is received.
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_pty_mode (void *cls,
-                 struct GNUNET_SERVER_Client *client,
-                 const struct GNUNET_MessageHeader* message)
-{
-  struct winsize ws;
-  struct termios tio;
-  const struct MSH_MSG_PtyMode *msg;
-  uint16_t *params;
-  char *termstr;
-  struct ExecCtx *exec_ctx;
-  size_t expected;
-  speed_t ospeed;
-  speed_t ispeed;
-  int master;
-  unsigned int cnt;
-  unsigned int ns;
-  uint16_t size;
-
-  size = ntohs (message->size);
-  if (size <= sizeof (struct MSH_MSG_PtyMode))
-  {
-    GNUNET_break (0);
-    goto close_conn;
-  }
-  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
-  GNUNET_assert (NULL != exec_ctx);
-  msg = (const struct MSH_MSG_PtyMode *) message;
-  master = posix_openpt (O_RDWR);
-  if (-1 == master)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "posix_openpt");
-    goto close_conn;
-  }
-  if (-1 == grantpt (master))
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "grantpt");
-    goto close_conn;
-  }
-  if (-1 == unlockpt (master))
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "unlockpt");
-    goto close_conn;
-  }
-  exec_ctx->master = master;
-  exec_ctx->pty_created = GNUNET_YES;
-  exec_ctx->pty_mode = (struct MSH_MSG_PtyMode *) GNUNET_copy_message 
(message);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-  
- close_conn:
-  GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-}
-
-
-/**
- * Callback to be called when ever a client connects to the daemon server
- *
- * @param cls NULL
- * @param client the client handle
- */
-static void
-daemon_server_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
-{
-  struct ExecCtx *exec_ctx;
-  
-  if (NULL == client)
-    return;
-  LOG_DEBUG ("A remote client has disconnected\n");
-  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
-  GNUNET_assert (NULL != exec_ctx);
-  destroy_exec_ctx (exec_ctx);
-}
-
-
-/**
- * Initialises the server which spawns processes and forwards it stdin and 
stdout
- *
- * @param h the network handle of the socket to listen for incoming connections
- */
-int
-init_daemon_server ()
-{
-  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
-    {&handle_session_open, NULL, MSH_MTYPE_SESSION_OPEN,
-     sizeof (struct MSH_MSG_SessionOpen)}, 
-    {&handle_runcmd, NULL, MSH_MTYPE_RUNCMD, 0},
-    {&handle_auth_challenge_response, NULL, MSH_MTYPE_CHALLENGE_RESPONSE, 
-     sizeof (struct MSH_MSG_ChallengeResponse)},
-    {&handle_command_input, NULL, MSH_MTYPE_CMD_STREAM_STDIN, 0},
-    {&handle_pty_mode, NULL, MSH_MTYPE_PTY_MODE, 0},
-    {NULL, NULL, 0, 0}
-  };
-  
-  daemon_serv = GNUNET_SERVER_create_with_sockets (NULL,
-                                                   NULL,
-                                                   NULL,
-                                                   
GNUNET_TIME_UNIT_FOREVER_REL,
-                                                   GNUNET_YES);
-  if (NULL == daemon_serv) 
-    return GNUNET_SYSERR;
-  GNUNET_SERVER_add_handlers (daemon_serv, handlers);
-  GNUNET_SERVER_disconnect_notify (daemon_serv, &daemon_server_disconnect, 
NULL);
-  daemon_serv_nc = GNUNET_SERVER_notification_context_create (daemon_serv, 1);
-  return GNUNET_OK;
-}
-
-
-/**
- * Timeout task for timing out connections until they authenticate.  Once
- * authenticated the connection will not be timed out.
- *
- * @param cls the client context
- * @param tc scheduler task context
- */
-static void
-timeout_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct ExecCtx *exec_ctx = cls;
-
-  exec_ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  GNUNET_SERVER_client_disconnect (exec_ctx->client);
-}
-
-
-/**
- * Create a client for the daemon server from a new client connection
- *
- * @param conn the connection to derive the client from
- */
-void
-daemon_server_add_connection (struct GNUNET_CONNECTION_Handle *conn)
-{
-  struct ExecCtx *exec_ctx;
-  struct GNUNET_SERVER_Client *client;
-
-  exec_ctx = GNUNET_malloc (sizeof (struct ExecCtx));
-  client = GNUNET_SERVER_connect_socket (daemon_serv, conn);
-  exec_ctx->client = client;
-  GNUNET_SERVER_client_set_user_context (client, exec_ctx);
-  GNUNET_SERVER_notification_context_add (daemon_serv_nc, client);
-  exec_ctx->timeout_task = 
-      GNUNET_SCHEDULER_add_delayed (TIMEOUT_SECS (30), &timeout_cb, exec_ctx);
-}
-
-
-/**
- * Shutdown the daemon server
- */
-void
-shutdown_daemon_server ()
-{
-  if (NULL != daemon_serv)
-  {
-    GNUNET_SERVER_destroy (daemon_serv);
-    daemon_serv = NULL;
-  }
-  if (NULL != daemon_serv_nc)
-  {
-    GNUNET_SERVER_notification_context_destroy (daemon_serv_nc);
-    daemon_serv_nc = NULL;
-  }
-}
-
-/* End of mshd-server.c */

Modified: msh/src/mshd.c
===================================================================
--- msh/src/mshd.c      2013-11-20 10:55:44 UTC (rev 30826)
+++ msh/src/mshd.c      2013-11-20 13:58:08 UTC (rev 30827)
@@ -126,15 +126,21 @@
    * connections are used to verify which IP addresses of this instance are
    * reachable from other instances
    */
-  LISTEN_MODE_PROBE,
+  MODE_PROBE,
 
   /**
    * In this mode the listen socket accepts requests for starting remote 
processes
    */
-  LISTEN_MODE_SERV
-} listen_mode;;
+  MODE_SERV,
 
+  /**
+   * Worker mode
+   */
+  MODE_WORKER
 
+} mode;
+
+
 /**
  * Mapping for instance addresses
  */
@@ -199,7 +205,7 @@
 /**
  * Task for asynchronous accept on the socket
  */
-static GNUNET_SCHEDULER_TaskIdentifier atask;
+static GNUNET_SCHEDULER_TaskIdentifier accept_task;
 
 /**
  * Task for finalising a round
@@ -274,6 +280,43 @@
 
 
 /**
+ * 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
+free_argv (char **argv)
+{
+  unsigned int argp;
+
+  for (argp = 0; NULL != argv[argp]; argp++)
+    GNUNET_free (argv[argp]);
+  GNUNET_free (argv);
+}
+
+
+/**
  * Perform cleanup for shutdown
  *
  * @param cls NULL
@@ -283,9 +326,58 @@
 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   shutdown_task = GNUNET_SCHEDULER_NO_TASK;
-  shutdown_local_server ();
-  shutdown_daemon_server ();
-  MSH_pmonitor_shutdown ();
+  switch (mode)
+  {
+  case MODE_PROBE:
+    break;
+  case MODE_SERV:
+    shutdown_local_server ();
+    MSH_pmonitor_shutdown ();
+    break;
+  case MODE_WORKER:
+    shutdown_daemon_server ();
+    break;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != accept_task)
+  {
+    GNUNET_SCHEDULER_cancel (accept_task);
+    accept_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  if (NULL != listen_socket)
+  {
+    GNUNET_NETWORK_socket_close (listen_socket);
+    listen_socket = NULL;
+  }
+  if (NULL != bitmap)
+  {
+    bitmap_destroy (bitmap);
+    bitmap = NULL;
+  }
+  if (NULL != addrmap)
+  {
+    addressmap_destroy (addrmap);
+    addrmap = NULL;
+  }
+  if (NULL != rmap)
+  {
+    reverse_map_destroy (rmap);
+    rmap = NULL;
+  }
+  GNUNET_free_non_null (s_addrs);
+  s_addrs = NULL;
+  if (NULL != run_args)
+  {
+    free_argv (run_args);
+    run_args = NULL;
+  }
+  GNUNET_free_non_null (unixpath);
+  unixpath = NULL;
+  if (NULL != hostsfile)
+  {
+    (void) unlink (hostsfile);
+    GNUNET_free (hostsfile);
+    hostsfile = NULL;
+  }
 }
 
 
@@ -362,25 +454,56 @@
 
 
 /**
+ * Fork a worker process.  This process forks a child which initiates the MSH
+ * execution protocol.  Once the protocol authenticates the connecting client,
+ * it then forks and execs the remote command.
+ */
+static pid_t
+spawn_worker ()
+{
+  struct GNUNET_NETWORK_Handle *sock;
+  struct GNUNET_CONNECTION_Handle *conn;
+  pid_t ret;
+
+  ret = fork ();
+  if (0 != ret)
+    return ret;
+  /* Child process continues here */
+  GNUNET_assert (MODE_SERV == mode);
+  GNUNET_assert (NULL != listen_socket);
+  GNUNET_SCHEDULER_cancel (shutdown_task);
+  shutdown_task = GNUNET_SCHEDULER_NO_TASK;
+  do_shutdown (NULL, NULL);
+  sock = GNUNET_NETWORK_socket_accept (listen_socket, NULL, NULL);
+  conn = GNUNET_CONNECTION_create_from_existing (sock);
+  mode = MODE_WORKER;
+  init_daemon_server ();
+  daemon_server_add_connection (conn);
+  return 0;
+}
+
+
+/**
  * Task to call accept and close on a listening socket
  *
  * @param cls NULL
  * @param tc the scheduler task context
  */
 static void
-accept_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+accept_conn (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct ReadContext *rctx;
   struct GNUNET_CONNECTION_Handle *conn;
+  pid_t pid;
 
-  atask = GNUNET_SCHEDULER_NO_TASK;
+  accept_task = GNUNET_SCHEDULER_NO_TASK;
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
   {
     goto clo_ret;
   }
-  switch (listen_mode)
+  switch (mode)
   {
-  case LISTEN_MODE_PROBE:
+  case MODE_PROBE:
     LOG_DEBUG ("%d: Got a probe connect\n", rank);
     conn = GNUNET_CONNECTION_create_from_accept (NULL, NULL, listen_socket);
     if (NULL == conn)
@@ -395,22 +518,22 @@
                                GNUNET_TIME_UNIT_FOREVER_REL, conn_reader, 
rctx);
     GNUNET_CONTAINER_DLL_insert_tail (rhead, rtail, rctx);    
     break;
-  case LISTEN_MODE_SERV:
+  case MODE_SERV:
+    pid = spawn_worker ();
+    if (-1 == pid)
     {
-      struct GNUNET_NETWORK_Handle *client_sock;
-      struct GNUNET_CONNECTION_Handle *client_conn;
-      
-      LOG_DEBUG ("Got a command execution connection\n");
-      client_sock = GNUNET_NETWORK_socket_accept (listen_socket, NULL, NULL);
-      client_conn = GNUNET_CONNECTION_create_from_existing (client_sock);
-      daemon_server_add_connection (client_conn);
+      GNUNET_break (0);
+      GNUNET_SCHEDULER_shutdown ();
+      goto clo_ret;
     }
+    if (0 == pid)               /* state is cleared and hence we return */
+      return;
     break;
-  default:
+  case MODE_WORKER:
     GNUNET_assert (0);
   }
-  atask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                         listen_socket, &accept_task, NULL);
+  accept_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                         listen_socket, &accept_conn, NULL);
   return;
 
  clo_ret:
@@ -531,10 +654,7 @@
   LOG_DEBUG ("Verification phase complete; commencing reduction phase\n");
   GNUNET_break (GNUNET_OK == reduce_ntree ());
   addressmap_print (addrmap);
-  listen_mode = LISTEN_MODE_SERV;
   rmap = addressmap_create_reverse_mapping (addrmap);
-  shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 
-                                                &do_shutdown, NULL);
   pid = (intmax_t) getpid ();
   GNUNET_assert (0 < asprintf (&unixpath, "%ju.sock", pid));
   hostsfile = GNUNET_DISK_mktemp ("MSHD_HOSTS");
@@ -546,11 +666,11 @@
   setenv (MSHD_HOSTSFILE, hostsfile, 1);
   setenv (MSHD_SOCK_NAME, unixpath, 1);
   init_local_server (unixpath);
-  init_daemon_server ();
   MSH_pmonitor_init ();
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == atask);
-  atask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                           listen_socket, &accept_task, NULL);
+  mode = MODE_SERV;
+  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == accept_task);
+  accept_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                           listen_socket, &accept_conn, NULL);
   if (0 == rank)
   {
     proc = GNUNET_OS_start_process_vap (GNUNET_NO,
@@ -605,8 +725,8 @@
   unsigned int cnt;
 
   finalise_task = GNUNET_SCHEDULER_NO_TASK;
-  GNUNET_SCHEDULER_cancel (atask);
-  atask = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_SCHEDULER_cancel (accept_task);
+  accept_task = GNUNET_SCHEDULER_NO_TASK;
   while (NULL != (ctx = vactx_head))
   {
     cleanup_verifyaddressctx (ctx);
@@ -986,8 +1106,8 @@
     return GNUNET_SYSERR;
   if (NULL == (riainfos = receive_addresses ()))
     return GNUNET_SYSERR;
-  atask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                         listen_socket, &accept_task, NULL);
+  accept_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                               listen_socket, &accept_conn, 
NULL);
 
   if (MPI_SUCCESS != MPI_Barrier (MPI_COMM_WORLD))
   {
@@ -1018,43 +1138,6 @@
 
 
 /**
- * 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
-free_argv (char **argv)
-{
-  unsigned int argp;
-
-  for (argp = 0; NULL != argv[argp]; argp++)
-    GNUNET_free (argv[argp]);
-  GNUNET_free (argv);
-}
-
-
-/**
  * Main function that will be run.
  *
  * @param cls closure
@@ -1110,6 +1193,8 @@
     return;
   }
   schedule_next_round ();
+  shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 
+                                                &do_shutdown, NULL);
   return;
 
  clo_ret:
@@ -1168,26 +1253,10 @@
   ret = 0;
   
  fail:
-  if (NULL != bitmap)
-  {
-    bitmap_destroy (bitmap);
-    bitmap = NULL;
-  }
-  if (NULL != addrmap)
-    addressmap_destroy (addrmap);
-  if (NULL != rmap)
-    reverse_map_destroy (rmap);
-  GNUNET_free_non_null (s_addrs);
-  if (NULL != run_args)
-    free_argv (run_args);
-  GNUNET_free_non_null (unixpath);
-  if (NULL != hostsfile)
-  {
-    (void) unlink (hostsfile);
-    GNUNET_free (hostsfile);
-  }
-  LOG_DEBUG ("Finalizing\n");
+  if (MODE_WORKER == mode)
+    return ret;
+  LOG_DEBUG ("Finalizing...\n");
   GNUNET_break (MPI_SUCCESS == MPI_Finalize());
-  LOG_DEBUG ("Returning\n");
+  LOG_DEBUG ("Done\n");
   return ret;
 }

Deleted: msh/src/mshd_pmonitor.c
===================================================================
--- msh/src/mshd_pmonitor.c     2013-11-20 10:55:44 UTC (rev 30826)
+++ msh/src/mshd_pmonitor.c     2013-11-20 13:58:08 UTC (rev 30827)
@@ -1,314 +0,0 @@
-/**
- * @file mshd_pmonitor.c
- * @brief process monitoring functions
- * @author Sree Harsha Totakura <address@hidden> 
- */
-
-#include "common.h"
-#include "gnunet/gnunet_util_lib.h"
-#include "mshd_pmonitor.h"
-
-/**
- * Generic logging shortcut
- */
-#define LOG(kind, ...)                                   \
-  GNUNET_log_from (kind, "mshd-pmonitor", __VA_ARGS__)
-
-/**
- * Debug logging shorthand
- */
-#define LOG_DEBUG(...)                          \
-  LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
-
-
-struct MonitorCtx
-{
-  /**
-   * Termination notification callback
-   */
-  MSH_ProcExitCallback cb;
-  
-  /**
-   * closure for the above callback
-   */
-  void *cls;
-};
-
-/**
- * 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;
-
-/**
- * Signal context for SIGCHLD
- */
-static struct GNUNET_SIGNAL_Context *shc_chld;
-
-/**
- * hashmap for storing process monitoring context
- */
-static struct GNUNET_CONTAINER_MultiHashMap32 *map;
-
-
-/**
- * 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;
-  struct MonitorCtx *ctx;
-  MSH_ProcExitCallback cb;
-  void *cb_cls;
-  char c[16];
-  enum GNUNET_OS_ProcessStatusType type;
-  int status;
-  pid_t cid;
-  int code;
-
-  cb = NULL;
-  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 ("Got SIGCHLD\n");
-  cid = waitpid (-1, &status, WNOHANG);
-  if (0 == cid)
-  {
-    LOG_DEBUG ("Child hasn't died.  Resuming to monitor its status\n");
-    goto resume;
-  }
-  if (-1 == cid)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "wait");
-    goto resume;
-  }
-  type = GNUNET_OS_PROCESS_UNKNOWN;
-  if (WIFEXITED (status))
-  {
-    type = GNUNET_OS_PROCESS_EXITED;
-    code = WEXITSTATUS (status);
-  }
-  if (WIFSIGNALED (status))
-  {
-    type = GNUNET_OS_PROCESS_SIGNALED;
-    code = WTERMSIG (status);
-  }
-  if (GNUNET_OS_PROCESS_UNKNOWN == type)
-  {
-    GNUNET_break (0);
-    goto resume;
-  }
-  ctx = GNUNET_CONTAINER_multihashmap32_get (map, (uint32_t) cid);
-  if (NULL == ctx)
-    goto resume;
-  cb = ctx->cb;
-  cb_cls = ctx->cls;
-  GNUNET_CONTAINER_multihashmap32_remove (map, (uint32_t) cid, ctx);
-  GNUNET_free (ctx);
-  
- resume:
-  child_death_task_id =
-      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                      pr, &child_death_task, NULL);
-  if (NULL != cb)
-    cb (cb_cls, type, code);
-}
-
-
-/**
- * Signal handler called for SIGCHLD.
- */
-static void
-sighandler_child_death ()
-{
-  static char c;
-  int old_errno;       /* back-up errno */
-
-  old_errno = errno;
-  GNUNET_break (1 ==
-                GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle
-                                        (sigpipe, GNUNET_DISK_PIPE_END_WRITE),
-                                        &c, sizeof (c)));
-  errno = old_errno;
-}
-
-
-/**
- * Initialise process monitoring subsystem.  Registers SIGCHLD signal handler
- * and the necessary pipe mechanism for reading the signal notification in a
- * safe way
- */
-void
-MSH_pmonitor_init ()
-{
-  const struct GNUNET_DISK_FileHandle *pr;
-
-  GNUNET_assert (NULL == sigpipe);
-  GNUNET_assert (NULL == shc_chld);
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == child_death_task_id);
-  GNUNET_assert (NULL != (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, 
-                                                      GNUNET_NO, GNUNET_NO)));
-  GNUNET_assert (NULL != (shc_chld = GNUNET_SIGNAL_handler_install 
-                          (GNUNET_SIGCHLD, &sighandler_child_death)));
-  pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
-  map = GNUNET_CONTAINER_multihashmap32_create (10);
-  GNUNET_assert (NULL != map);
-  child_death_task_id =
-      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                      pr, &child_death_task, NULL);
-  
-}
-
-
-/**
- * Iterator over hash map entries.
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-static int
-cleanup_iterator (void *cls, uint32_t key, void *value)
-{
-  struct MonitorCtx *ctx = value;
-
-  GNUNET_assert (GNUNET_YES == 
-                 GNUNET_CONTAINER_multihashmap32_remove (map,
-                                                         key,
-                                                         ctx));
-  GNUNET_free (ctx);
-  return GNUNET_YES;
-}
-
-
-/**
- * shutdown process monitoring subsystem
- */
-void
-MSH_pmonitor_shutdown ()
-{
-  /* fixme clear monitoring contexts */
-  GNUNET_assert (NULL != map);
-  GNUNET_break (GNUNET_SYSERR != 
-                GNUNET_CONTAINER_multihashmap32_iterate (map,
-                                                         &cleanup_iterator,
-                                                         NULL));
-  GNUNET_CONTAINER_multihashmap32_destroy (map);
-  map = NULL;
-  GNUNET_assert (NULL != sigpipe);
-  GNUNET_assert (NULL != shc_chld);
-  if (GNUNET_SCHEDULER_NO_TASK != child_death_task_id)
-  {
-    GNUNET_SCHEDULER_cancel (child_death_task_id);
-    child_death_task_id = GNUNET_SCHEDULER_NO_TASK;
-  }
-  GNUNET_SIGNAL_handler_uninstall (shc_chld);
-  shc_chld = NULL;
-  GNUNET_DISK_pipe_close (sigpipe);
-  sigpipe = NULL;
-}
-
-
-/**
- * Monitors a process for its termination.
- *
- * @param proc the process to monitor for termination
- * @param cb the callback to be called for notifying the termination of the
- *    process
- * @param cls the closure for the above callback
- */
-void
-MSH_monitor_process_pid (pid_t pid,
-                         MSH_ProcExitCallback cb, void *cls)
-{
-  struct MonitorCtx *ctx;
-
-  GNUNET_assert (NULL != map);
-  ctx = GNUNET_malloc (sizeof (struct MonitorCtx));
-  ctx->cb = cb;
-  ctx->cls = cls;
-  GNUNET_assert 
-      (GNUNET_OK ==
-       GNUNET_CONTAINER_multihashmap32_put (map, (uint32_t) pid, ctx,
-                                            
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-}
-
-
-/**
- * Monitors a process for its termination.
- *
- * @param proc the process to monitor for termination
- * @param cb the callback to be called for notifying the termination of the
- *    process
- * @param cls the closure for the above callback
- */
-void
-MSH_monitor_process (struct GNUNET_OS_Process *proc,
-                     MSH_ProcExitCallback cb, void *cls)
-{
-  pid_t pid;
-
-  pid = GNUNET_OS_process_get_pid (proc);
-  MSH_monitor_process_pid (pid, cb, cls);
-}
-
-
-/**
- * Stop monitoring a process
- *
- * @param proc
- * @return GNUNET_OK upon success; GNUNET_SYSERR if the process is not being
- *   monitored earlier
- */
-int
-MSH_monitor_process_pid_cancel (pid_t pid)
-{
-  struct MonitorCtx *ctx;
-
-  GNUNET_assert (NULL != map);  
-  ctx = GNUNET_CONTAINER_multihashmap32_get (map, (uint32_t) pid);
-  if (NULL == ctx)
-    return GNUNET_SYSERR;
-  GNUNET_assert (GNUNET_YES == 
-                 GNUNET_CONTAINER_multihashmap32_remove 
-                 (map, (uint32_t) pid, ctx));
-  GNUNET_free (ctx);
-  return GNUNET_OK;
-}
-
-
-/**
- * Stop monitoring a process
- *
- * @param proc
- * @return GNUNET_OK upon success; GNUNET_SYSERR if the process is not being
- *   monitored earlier
- */
-int
-MSH_monitor_process_cancel (struct GNUNET_OS_Process *proc)
-{
-  pid_t pid;
-  
-  pid = GNUNET_OS_process_get_pid (proc);
-  return MSH_monitor_process_pid_cancel (pid);
-}

Deleted: msh/src/mshd_pmonitor.h
===================================================================
--- msh/src/mshd_pmonitor.h     2013-11-20 10:55:44 UTC (rev 30826)
+++ msh/src/mshd_pmonitor.h     2013-11-20 13:58:08 UTC (rev 30827)
@@ -1,66 +0,0 @@
-/**
- * @file mshd_pmonitor.h
- * @brief interface for process monitoring functions
- * @author Sree Harsha Totakura <address@hidden> 
- */
-
-#ifndef MSHD_PMONITOR_H_
-#define MSHD_PMONITOR_H_
-
-#include <gnunet/gnunet_os_lib.h>
-
-/**
- * Initialise process monitoring subsystem.  Registers SIGCHLD signal handler
- * and the necessary pipe mechanism for reading the signal notification in a
- * safe way
- */
-void
-MSH_pmonitor_init ();
-
-
-/**
- * shutdown process monitoring subsystem
- */
-void
-MSH_pmonitor_shutdown ();
-
-
-/**
- * Callbacks of this type can be supplied to MSH_monitor_process() to be
- * notified when the corresponding processes exits.
- *
- * @param cls the closure passed to MSH_monitor_process()
- * @param type the process status type
- * @param long the return/exit code of the process
- */
-typedef void (*MSH_ProcExitCallback) (void *cls,
-                                      enum GNUNET_OS_ProcessStatusType type,
-                                      int code);
-
-
-/**
- * Monitors a process for its termination.
- *
- * @param proc the process to monitor for termination
- * @param cb the callback to be called for notifying the termination of the
- *    process
- * @param cls the closure for the above callback
- */
-void
-MSH_monitor_process (struct GNUNET_OS_Process *proc,
-                     MSH_ProcExitCallback cb, void *cls);
-
-
-/**
- * Stop monitoring a process
- *
- * @param proc
- * @return GNUNET_OK upon success; GNUNET_SYSERR if the process is not being
- *   monitored earlier
- */
-int
-MSH_monitor_process_cancel (struct GNUNET_OS_Process *proc);
-
-#endif  /* MSHD_PMONITOR_H_ */
-
-/* End of mshd_pmonitor.h */

Copied: msh/src/pmonitor.c (from rev 30820, msh/src/mshd_pmonitor.c)
===================================================================
--- msh/src/pmonitor.c                          (rev 0)
+++ msh/src/pmonitor.c  2013-11-20 13:58:08 UTC (rev 30827)
@@ -0,0 +1,314 @@
+/**
+ * @file pmonitor.c
+ * @brief process monitoring functions
+ * @author Sree Harsha Totakura <address@hidden> 
+ */
+
+#include "common.h"
+#include "gnunet/gnunet_util_lib.h"
+#include "pmonitor.h"
+
+/**
+ * Generic logging shortcut
+ */
+#define LOG(kind, ...)                                   \
+  GNUNET_log_from (kind, "mshd-pmonitor", __VA_ARGS__)
+
+/**
+ * Debug logging shorthand
+ */
+#define LOG_DEBUG(...)                          \
+  LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
+
+
+struct MonitorCtx
+{
+  /**
+   * Termination notification callback
+   */
+  MSH_ProcExitCallback cb;
+  
+  /**
+   * closure for the above callback
+   */
+  void *cls;
+};
+
+/**
+ * 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;
+
+/**
+ * Signal context for SIGCHLD
+ */
+static struct GNUNET_SIGNAL_Context *shc_chld;
+
+/**
+ * hashmap for storing process monitoring context
+ */
+static struct GNUNET_CONTAINER_MultiHashMap32 *map;
+
+
+/**
+ * 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;
+  struct MonitorCtx *ctx;
+  MSH_ProcExitCallback cb;
+  void *cb_cls;
+  char c[16];
+  enum GNUNET_OS_ProcessStatusType type;
+  int status;
+  pid_t cid;
+  int code;
+
+  cb = NULL;
+  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 ("Got SIGCHLD\n");
+  cid = waitpid (-1, &status, WNOHANG);
+  if (0 == cid)
+  {
+    LOG_DEBUG ("Child hasn't died.  Resuming to monitor its status\n");
+    goto resume;
+  }
+  if (-1 == cid)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "wait");
+    goto resume;
+  }
+  type = GNUNET_OS_PROCESS_UNKNOWN;
+  if (WIFEXITED (status))
+  {
+    type = GNUNET_OS_PROCESS_EXITED;
+    code = WEXITSTATUS (status);
+  }
+  if (WIFSIGNALED (status))
+  {
+    type = GNUNET_OS_PROCESS_SIGNALED;
+    code = WTERMSIG (status);
+  }
+  if (GNUNET_OS_PROCESS_UNKNOWN == type)
+  {
+    GNUNET_break (0);
+    goto resume;
+  }
+  ctx = GNUNET_CONTAINER_multihashmap32_get (map, (uint32_t) cid);
+  if (NULL == ctx)
+    goto resume;
+  cb = ctx->cb;
+  cb_cls = ctx->cls;
+  GNUNET_CONTAINER_multihashmap32_remove (map, (uint32_t) cid, ctx);
+  GNUNET_free (ctx);
+  
+ resume:
+  child_death_task_id =
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      pr, &child_death_task, NULL);
+  if (NULL != cb)
+    cb (cb_cls, type, code);
+}
+
+
+/**
+ * Signal handler called for SIGCHLD.
+ */
+static void
+sighandler_child_death ()
+{
+  static char c;
+  int old_errno;       /* back-up errno */
+
+  old_errno = errno;
+  GNUNET_break (1 ==
+                GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle
+                                        (sigpipe, GNUNET_DISK_PIPE_END_WRITE),
+                                        &c, sizeof (c)));
+  errno = old_errno;
+}
+
+
+/**
+ * Initialise process monitoring subsystem.  Registers SIGCHLD signal handler
+ * and the necessary pipe mechanism for reading the signal notification in a
+ * safe way
+ */
+void
+MSH_pmonitor_init ()
+{
+  const struct GNUNET_DISK_FileHandle *pr;
+
+  GNUNET_assert (NULL == sigpipe);
+  GNUNET_assert (NULL == shc_chld);
+  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == child_death_task_id);
+  GNUNET_assert (NULL != (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, 
+                                                      GNUNET_NO, GNUNET_NO)));
+  GNUNET_assert (NULL != (shc_chld = GNUNET_SIGNAL_handler_install 
+                          (GNUNET_SIGCHLD, &sighandler_child_death)));
+  pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
+  map = GNUNET_CONTAINER_multihashmap32_create (10);
+  GNUNET_assert (NULL != map);
+  child_death_task_id =
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      pr, &child_death_task, NULL);
+  
+}
+
+
+/**
+ * Iterator over hash map entries.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value value in the hash map
+ * @return GNUNET_YES if we should continue to
+ *         iterate,
+ *         GNUNET_NO if not.
+ */
+static int
+cleanup_iterator (void *cls, uint32_t key, void *value)
+{
+  struct MonitorCtx *ctx = value;
+
+  GNUNET_assert (GNUNET_YES == 
+                 GNUNET_CONTAINER_multihashmap32_remove (map,
+                                                         key,
+                                                         ctx));
+  GNUNET_free (ctx);
+  return GNUNET_YES;
+}
+
+
+/**
+ * shutdown process monitoring subsystem
+ */
+void
+MSH_pmonitor_shutdown ()
+{
+  /* fixme clear monitoring contexts */
+  GNUNET_assert (NULL != map);
+  GNUNET_break (GNUNET_SYSERR != 
+                GNUNET_CONTAINER_multihashmap32_iterate (map,
+                                                         &cleanup_iterator,
+                                                         NULL));
+  GNUNET_CONTAINER_multihashmap32_destroy (map);
+  map = NULL;
+  GNUNET_assert (NULL != sigpipe);
+  GNUNET_assert (NULL != shc_chld);
+  if (GNUNET_SCHEDULER_NO_TASK != child_death_task_id)
+  {
+    GNUNET_SCHEDULER_cancel (child_death_task_id);
+    child_death_task_id = GNUNET_SCHEDULER_NO_TASK;
+  }
+  GNUNET_SIGNAL_handler_uninstall (shc_chld);
+  shc_chld = NULL;
+  GNUNET_DISK_pipe_close (sigpipe);
+  sigpipe = NULL;
+}
+
+
+/**
+ * Monitors a process for its termination.
+ *
+ * @param proc the process to monitor for termination
+ * @param cb the callback to be called for notifying the termination of the
+ *    process
+ * @param cls the closure for the above callback
+ */
+void
+MSH_monitor_process_pid (pid_t pid,
+                         MSH_ProcExitCallback cb, void *cls)
+{
+  struct MonitorCtx *ctx;
+
+  GNUNET_assert (NULL != map);
+  ctx = GNUNET_malloc (sizeof (struct MonitorCtx));
+  ctx->cb = cb;
+  ctx->cls = cls;
+  GNUNET_assert 
+      (GNUNET_OK ==
+       GNUNET_CONTAINER_multihashmap32_put (map, (uint32_t) pid, ctx,
+                                            
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+}
+
+
+/**
+ * Monitors a process for its termination.
+ *
+ * @param proc the process to monitor for termination
+ * @param cb the callback to be called for notifying the termination of the
+ *    process
+ * @param cls the closure for the above callback
+ */
+void
+MSH_monitor_process (struct GNUNET_OS_Process *proc,
+                     MSH_ProcExitCallback cb, void *cls)
+{
+  pid_t pid;
+
+  pid = GNUNET_OS_process_get_pid (proc);
+  MSH_monitor_process_pid (pid, cb, cls);
+}
+
+
+/**
+ * Stop monitoring a process
+ *
+ * @param proc
+ * @return GNUNET_OK upon success; GNUNET_SYSERR if the process is not being
+ *   monitored earlier
+ */
+int
+MSH_monitor_process_pid_cancel (pid_t pid)
+{
+  struct MonitorCtx *ctx;
+
+  GNUNET_assert (NULL != map);  
+  ctx = GNUNET_CONTAINER_multihashmap32_get (map, (uint32_t) pid);
+  if (NULL == ctx)
+    return GNUNET_SYSERR;
+  GNUNET_assert (GNUNET_YES == 
+                 GNUNET_CONTAINER_multihashmap32_remove 
+                 (map, (uint32_t) pid, ctx));
+  GNUNET_free (ctx);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Stop monitoring a process
+ *
+ * @param proc
+ * @return GNUNET_OK upon success; GNUNET_SYSERR if the process is not being
+ *   monitored earlier
+ */
+int
+MSH_monitor_process_cancel (struct GNUNET_OS_Process *proc)
+{
+  pid_t pid;
+  
+  pid = GNUNET_OS_process_get_pid (proc);
+  return MSH_monitor_process_pid_cancel (pid);
+}

Copied: msh/src/pmonitor.h (from rev 30820, msh/src/mshd_pmonitor.h)
===================================================================
--- msh/src/pmonitor.h                          (rev 0)
+++ msh/src/pmonitor.h  2013-11-20 13:58:08 UTC (rev 30827)
@@ -0,0 +1,90 @@
+/**
+ * @file pmonitor.h
+ * @brief interface for process monitoring functions
+ * @author Sree Harsha Totakura <address@hidden> 
+ */
+
+#ifndef MSHD_PMONITOR_H_
+#define MSHD_PMONITOR_H_
+
+#include <gnunet/gnunet_os_lib.h>
+
+/**
+ * Initialise process monitoring subsystem.  Registers SIGCHLD signal handler
+ * and the necessary pipe mechanism for reading the signal notification in a
+ * safe way
+ */
+void
+MSH_pmonitor_init ();
+
+
+/**
+ * shutdown process monitoring subsystem
+ */
+void
+MSH_pmonitor_shutdown ();
+
+
+/**
+ * Callbacks of this type can be supplied to MSH_monitor_process() to be
+ * notified when the corresponding processes exits.
+ *
+ * @param cls the closure passed to MSH_monitor_process()
+ * @param type the process status type
+ * @param long the return/exit code of the process
+ */
+typedef void (*MSH_ProcExitCallback) (void *cls,
+                                      enum GNUNET_OS_ProcessStatusType type,
+                                      int code);
+
+
+/**
+ * Monitors a process for its termination.
+ *
+ * @param proc the process to monitor for termination
+ * @param cb the callback to be called for notifying the termination of the
+ *    process
+ * @param cls the closure for the above callback
+ */
+void
+MSH_monitor_process (struct GNUNET_OS_Process *proc,
+                     MSH_ProcExitCallback cb, void *cls);
+
+
+/**
+ * Stop monitoring a process
+ *
+ * @param proc
+ * @return GNUNET_OK upon success; GNUNET_SYSERR if the process is not being
+ *   monitored earlier
+ */
+int
+MSH_monitor_process_cancel (struct GNUNET_OS_Process *proc);
+
+
+/**
+ * Monitors a process for its termination.
+ *
+ * @param proc the process to monitor for termination
+ * @param cb the callback to be called for notifying the termination of the
+ *    process
+ * @param cls the closure for the above callback
+ */
+void
+MSH_monitor_process_pid (pid_t pid,
+                         MSH_ProcExitCallback cb, void *cls);
+
+
+/**
+ * Stop monitoring a process
+ *
+ * @param proc
+ * @return GNUNET_OK upon success; GNUNET_SYSERR if the process is not being
+ *   monitored earlier
+ */
+int
+MSH_monitor_process_pid_cancel (pid_t pid);
+
+#endif  /* MSHD_PMONITOR_H_ */
+
+/* End of pmonitor.h */

Copied: msh/src/server.c (from rev 30822, msh/src/mshd-server.c)
===================================================================
--- msh/src/server.c                            (rev 0)
+++ msh/src/server.c    2013-11-20 13:58:08 UTC (rev 30827)
@@ -0,0 +1,1156 @@
+/**
+ * @file server.c
+ * @brief functions implementing server functionalities of MSH daemon.  We
+ *          listen for commands from locally started MSH instances and also for
+ *          executing commands given by remote MSH daemons.
+ * @author Sree Harsha Totakura <address@hidden> 
+ */
+
+#include "common.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <termios.h>
+#include "mshd.h"
+#include "addressmap.h"
+#include "pmonitor.h"
+#include "util.h"
+
+#define TIMEOUT_SECS(s) \
+  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, s)
+
+#define LOG(kind,...)                           \
+  GNUNET_log_from (kind, "server", __VA_ARGS__)
+
+#define LOG_DEBUG(...) LOG(GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
+
+#define LOG_ERROR(...) LOG(GNUNET_ERROR_TYPE_ERROR, __VA_ARGS__)
+
+#define LOG_STRERROR(kind,cmd)                  \
+  GNUNET_log_from_strerror (kind, "mshd-error", cmd)
+
+/**
+ * server handle for accepting requests from local MSH instances
+ */
+static struct GNUNET_SERVER_Handle *local_serv;
+
+/**
+ * server handle for acceptiong requests from remote MSHD instances
+ */
+static struct GNUNET_SERVER_Handle *daemon_serv;
+
+/**
+ * Notification queue for the local server
+ */
+static struct GNUNET_SERVER_NotificationContext *local_serv_nc;
+
+/**
+ * Notification queue for the daemon server
+ */
+static struct GNUNET_SERVER_NotificationContext *daemon_serv_nc;
+
+/**
+ * Our UID.  We use this for access checks
+ */
+uid_t our_uid;
+
+/**
+ * Our GID.  We use this for access checks
+ */
+uid_t our_gid;
+
+
+/**
+ * Context for connections requiring to execute commands
+ */
+struct ExecCtx
+{
+  /**
+   * The client handle this context is associated with
+   */
+  struct GNUNET_SERVER_Client *client;
+  
+  /**
+   * The command strings to execute
+   */
+  char **args;
+
+  /**
+   * file handle for processes input
+   */
+  struct GNUNET_DISK_FileHandle *fin;
+
+  /**
+   * file handle for processes output
+   */
+  struct GNUNET_DISK_FileHandle *fout;
+  
+  /**
+   * input buffer.  Data from this buffer is written to proc's STDIN when it is
+   * available for writing.
+   */
+  char *buf;
+
+  /**
+   * If this session were to be interactive, the message containing the setting
+   * to use for the pseudo-tty we create
+   */
+  struct MSH_MSG_PtyMode *pty_mode;
+
+  /**
+   * The size of the input buffer
+   */
+  size_t bufsize;
+
+  /**
+   * salt hash used for authentication
+   */
+  struct GNUNET_HashCode salt;
+
+  /**
+   * timeout task
+   */
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+  /**
+   * task to read the output from the process
+   */
+  GNUNET_SCHEDULER_TaskIdentifier fout_task;
+
+  /**
+   * task to write data received from the client to proc's STDIN
+   */
+  GNUNET_SCHEDULER_TaskIdentifier fin_task;
+
+  /**
+   * The pid of the child we start
+   */
+  pid_t child_pid;
+
+  /**
+   * If this is an interactive session, this is the master side of the
+   * pseudo-tty we create
+   */
+  int master;
+
+  /**
+   * Is this an interactive session?
+   */
+  int interactive;
+
+  /**
+   * Is this session authentication?
+   */
+  int authenticated;
+
+  /**
+   * If this is an interactive session, is a pseudo-tty created?
+   */
+  int pty_created;
+};
+
+/*
+ * Converts a numeric baud rate to a POSIX speed_t.
+ */
+speed_t
+baud_to_speed(int baud);
+
+
+/**
+ * Destroys an execution context
+ * 
+ * @param ctx execution context
+ */
+static void
+destroy_exec_ctx (struct ExecCtx *ctx)
+{
+  unsigned int cnt;
+
+  GNUNET_SERVER_client_drop (ctx->client);
+  if (NULL != ctx->args)
+  {
+    for (cnt = 0; NULL != ctx->args[cnt]; cnt++)
+      GNUNET_free (ctx->args[cnt]);
+    GNUNET_free (ctx->args);
+  }
+  if (0 != ctx->child_pid)
+  {
+    MSH_monitor_process_pid_cancel (ctx->child_pid);
+    GNUNET_break (0 == kill (ctx->child_pid, SIGTERM));
+  }
+  GNUNET_DISK_file_close (ctx->fin);
+  GNUNET_DISK_file_close (ctx->fout);
+  if (GNUNET_SCHEDULER_NO_TASK != ctx->timeout_task)
+    GNUNET_SCHEDULER_cancel (ctx->timeout_task);
+  if (GNUNET_SCHEDULER_NO_TASK != ctx->fout_task)
+    GNUNET_SCHEDULER_cancel (ctx->fout_task);
+  if (NULL != ctx->buf)
+    GNUNET_free (ctx->buf);
+  GNUNET_free_non_null (ctx->pty_mode);
+  GNUNET_free (ctx);
+}
+
+
+/**
+ * Parse contingious 0-terminated strings from a buffer of given length
+ *
+ * @param buf the buffer
+ * @param size the size of the buffer
+ * @param s will contain the array of strings upon return
+ * @return the number of strings returned in the array
+ */
+static int
+parse_strings (const char *buf, size_t size, char ***s)
+{
+  const char *p;
+  char **strs;
+  size_t off;
+  unsigned int cnt;
+
+  cnt = 0;
+  strs = NULL;
+  p = NULL;  
+  for (off = 0; off < size; off++)
+  {
+    if ('\0' == buf[off])
+    {
+      if (NULL == p)
+        continue;
+      GNUNET_array_append (strs, cnt, GNUNET_strdup (p));
+      p = NULL;
+      continue;
+    }
+    if (NULL != p)
+      continue;
+    p = &buf[off];
+  }
+  if (0 < cnt)
+    GNUNET_array_append (strs, cnt, NULL);
+  *s = strs;
+  return cnt;
+}
+
+
+/**
+ * Create a challenge message 
+ *
+ * @param ctx the execution context
+ * @return the challenge message
+ */
+static struct GNUNET_MessageHeader *
+create_challenge_message (struct ExecCtx *ctx)
+{
+  struct MSH_MSG_Challenge *msg;
+  uint16_t size;
+
+  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE, &ctx->salt);
+  size = sizeof (struct MSH_MSG_Challenge);
+  msg = GNUNET_malloc (size);
+  msg->header.type = htons (MSH_MTYPE_CHALLENGE);
+  msg->header.size = htons (size);
+  GNUNET_CRYPTO_hash_to_enc (&ctx->salt, &msg->salt);
+  LOG_DEBUG ("Challenge nonce: %104s\n", msg->salt.encoding);
+  return &msg->header;
+}
+
+
+/**
+ * Functions with this signature are called whenever a message is
+ * received.
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_addresslookup (void *cls, struct GNUNET_SERVER_Client *client,
+                      const struct GNUNET_MessageHeader* message)
+{
+  const struct MSH_MSG_AddressLookup *msg;
+  struct MSH_MSG_AddressLookupReply *reply;
+  struct InstanceAddr *iaddr;
+  char *emsg;
+  in_addr_t ip;
+  uint16_t port;
+  uint16_t reply_size;
+  
+  emsg = NULL;
+  port = 0;
+  msg = (const struct MSH_MSG_AddressLookup *) message;
+  ip = ntohl (msg->ip);
+  if (GNUNET_NO == reversemap_check (rmap, ip))
+  {
+    emsg = "Given IP address not present in the current mapping\n";
+    goto respond;
+  }
+  iaddr = reversemap_lookup (rmap, ip);
+  GNUNET_assert (NULL != iaddr);
+  port = instance_address_port (iaddr);
+  LOG_DEBUG ("Received ADDRESS_LOOKUP message for IP: %s and port %u\n",
+             ip2str (ip), port);
+ respond:
+  reply_size = sizeof (struct MSH_MSG_AddressLookupReply);
+  if (NULL != emsg)
+    reply_size += strlen (emsg) + 1;
+  reply = GNUNET_malloc (reply_size);
+  reply->header.size = htons (reply_size);
+  reply->header.type = htons (MSH_MTYPE_ADDRESS_LOOKUP_REPLY);
+  reply->port = htons (port);
+  if (NULL != emsg)
+    (void) strcpy (reply->emsg, emsg);
+  GNUNET_SERVER_notification_context_unicast (local_serv_nc, client,
+                                              &reply->header, GNUNET_NO);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Generate the credential for the given challenge 
+ *
+ * @param c the challenge
+ * @param cred output parameter for the credential
+ */
+static void
+auth_challenge_cred (struct GNUNET_HashCode *c, struct GNUNET_HashCode *cred)
+{
+  struct GNUNET_HashCode xor;
+
+  GNUNET_CRYPTO_hash_xor (c, &shash, &xor);
+  GNUNET_CRYPTO_hash (&xor, sizeof (struct GNUNET_HashCode), cred);
+}
+
+
+/**
+ * Functions with this signature are called whenever a message is
+ * received.
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_auth_challenge (void *cls, struct GNUNET_SERVER_Client *client,
+                       const struct GNUNET_MessageHeader* message)
+{
+  const struct MSH_MSG_Challenge *msg;
+  struct MSH_MSG_ChallengeResponse *reply;
+  struct GNUNET_HashCode salt;
+  struct GNUNET_HashCode cred;
+
+  msg = (const struct MSH_MSG_Challenge *) message;
+  LOG_DEBUG ("Challenge nonce: %104s\n", msg->salt.encoding);
+  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_hash_from_string 
+                 ((const char *) msg->salt.encoding, &salt));
+  auth_challenge_cred (&salt, &cred);
+  reply = GNUNET_malloc (sizeof (struct MSH_MSG_ChallengeResponse));
+  reply->header.size = htons (sizeof (struct MSH_MSG_ChallengeResponse));
+  reply->header.type = htons (MSH_MTYPE_CHALLENGE_RESPONSE);
+  GNUNET_CRYPTO_hash_to_enc (&cred, &reply->auth);
+  GNUNET_SERVER_notification_context_unicast (local_serv_nc, client,
+                                              &reply->header, GNUNET_NO);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Function to call for access control checks.
+ *
+ * @param cls closure
+ * @param ucred credentials, if available, otherwise NULL
+ * @param addr address
+ * @param addrlen length of address
+ * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR
+ *   for unknown address family (will be denied).
+ */
+static int
+check_local_access (void *cls,
+              const struct GNUNET_CONNECTION_Credentials *cred,
+              const struct sockaddr * addr, socklen_t addrlen)
+{
+  if ((our_uid != cred->uid) && (our_gid != cred->gid))
+    return GNUNET_NO;
+  return GNUNET_YES;
+}
+
+
+/**
+ * Callback to be called when ever a client connects to the local server
+ *
+ * @param cls NULL
+ * @param client the client handle
+ */
+static void
+local_server_connect (void *cls, struct GNUNET_SERVER_Client *client)
+{
+  if (NULL == client)           /* Server shutting down */
+    return;
+  LOG_DEBUG ("A client has been connected locally\n");
+  GNUNET_SERVER_notification_context_add (local_serv_nc, client);
+}
+
+
+/**
+ * Initialise the local server
+ *
+ * @param unixpath the name to use while opening the abstract UNIX domain 
socket
+ *   for listening
+ * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
+ */
+int
+init_local_server (const char *unixpath)
+{
+  struct sockaddr_un saddr;
+  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
+    {&handle_addresslookup, NULL, MSH_MTYPE_ADDRESS_LOOKUP, sizeof (struct
+    MSH_MSG_AddressLookup)},
+    {&handle_auth_challenge, NULL, MSH_MTYPE_CHALLENGE, sizeof (struct 
MSH_MSG_Challenge)},
+    {NULL, NULL, 0, 0}
+  };
+  struct sockaddr *saddrs[] = {
+    ((struct sockaddr *) &saddr),
+    NULL
+  };
+  socklen_t saddr_lens[] = {
+    sizeof (struct sockaddr_un),
+     0
+  };
+
+  our_uid = getuid ();
+  our_gid = getgid ();
+  saddr.sun_family = AF_UNIX;
+  (void) memset (saddr.sun_path, 0, sizeof (saddr.sun_path));
+  (void) strncpy (saddr.sun_path, unixpath, sizeof (saddr.sun_path) - 1);
+  local_serv = GNUNET_SERVER_create (&check_local_access, NULL,
+                                     saddrs,
+                                     saddr_lens,
+                                     GNUNET_TIME_UNIT_FOREVER_REL,
+                                     GNUNET_YES);
+  if (NULL == local_serv)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_SERVER_add_handlers (local_serv, handlers);
+  GNUNET_SERVER_connect_notify (local_serv, &local_server_connect, NULL);
+  local_serv_nc = GNUNET_SERVER_notification_context_create (local_serv, 1);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Shutdown the local server
+ */
+void
+shutdown_local_server ()
+{
+  if (NULL != local_serv)
+  {
+    GNUNET_SERVER_destroy (local_serv);
+    local_serv = NULL;
+  }
+}
+
+
+/******************************************************************************/
+/* Daemon server.  Responsbile for executing commands submitted by remote MSH 
*/
+/* clients                                                                    
*/
+/******************************************************************************/
+
+
+/**
+ * Handle session open message and start challenge authentication.
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_session_open (void *cls,
+                     struct GNUNET_SERVER_Client *client,
+                     const struct GNUNET_MessageHeader* message)
+{
+  struct ExecCtx *exec_ctx;
+  const struct MSH_MSG_SessionOpen *msg;
+  struct GNUNET_MessageHeader *reply;
+  
+  LOG_DEBUG ("Received a SESSION_OPEN message\n");
+  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
+  GNUNET_assert (NULL != exec_ctx);
+  msg = (const struct MSH_MSG_SessionOpen *) message;
+  if (NULL != exec_ctx->args)
+  {
+    GNUNET_break (0);
+    goto close_conn;
+  }
+  if (MSH_SESSION_TYPE_INTERACTIVE == ntohl (msg->type))
+    exec_ctx->interactive = GNUNET_YES;
+  reply = create_challenge_message (exec_ctx);
+  LOG_DEBUG ("Sending AUTH_CHALLENGE\n");
+  GNUNET_SERVER_notification_context_unicast (daemon_serv_nc, client, reply,
+                                              GNUNET_NO);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  return;
+
+ close_conn:
+  GNUNET_break_op (0);
+  GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+}
+
+
+/**
+ * Task to read the output from a process and send it to client
+ *
+ * @param cls the client context
+ * @param tc scheduler task context
+ */
+static void
+read_fout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct ExecCtx *exec_ctx = cls;
+  struct MSH_MSG_CmdIO *msg;
+  static char data[MAX_IO_DATA];
+  ssize_t size;
+  uint16_t msize;
+
+  exec_ctx->fout_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+  {
+    return;
+  }
+  size = GNUNET_DISK_file_read_non_blocking (exec_ctx->fout, data, 
MAX_IO_DATA);
+  if (size <= 0)
+  {
+    GNUNET_break (GNUNET_SYSERR != size);
+    GNUNET_SERVER_client_disconnect (exec_ctx->client);
+    return;
+  }
+  msize = size + sizeof (struct MSH_MSG_CmdIO);
+  msg = GNUNET_malloc (msize);
+  msg->header.type = htons (MSH_MTYPE_CMD_STREAM_STDOUT);
+  msg->header.size = htons (msize);
+  memcpy (msg->data, data, size);
+  GNUNET_SERVER_notification_context_unicast (daemon_serv_nc, exec_ctx->client,
+                                              &msg->header, GNUNET_NO);
+  exec_ctx->fout_task = 
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      exec_ctx->fout, &read_fout, exec_ctx);
+}
+
+
+/**
+ * Configure the terminal for the child
+ */
+static int
+parse_term_mode (const struct MSH_MSG_PtyMode *msg,
+                 struct termios *tio,
+                 struct winsize *ws,
+                 char **termstr)
+{
+  uint16_t *params;
+  char *str;
+  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)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+#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 GNUNET_SYSERR;
+  }
+  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;
+  str = ((void *) msg) + expected;
+  if ('\0' != str[(msize - expected) - 1])
+  {
+    GNUNET_break (0);
+    str = NULL;
+    return GNUNET_OK;
+  }
+  *termstr = GNUNET_strdup (str);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Callback that will be called when a child processes terminates.  The
+ * associated client context for the client which requested this process will 
be
+ * destroyed 
+ *
+ * @param cls the closure passed to MSH_monitor_process()
+ * @param type the process status type
+ * @param long the return/exit code of the process
+ */
+static void
+proc_exit_cb (void *cls, enum GNUNET_OS_ProcessStatusType type, int code)
+{
+  struct ExecCtx *exec_ctx = cls;
+  
+  LOG_DEBUG ("Command `%s' exited.\n", exec_ctx->args[0]);
+  exec_ctx->child_pid = 0;
+  GNUNET_SCHEDULER_cancel (exec_ctx->fout_task);
+  exec_ctx->fout_task = GNUNET_SCHEDULER_add_now (&read_fout, exec_ctx);
+}
+
+
+/**
+ * start the process from the execution process
+ *
+ * @param ctx the execution context
+ * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
+ */
+static int
+proc_exec (struct ExecCtx *ctx)
+{
+  struct GNUNET_DISK_PipeHandle *pin;
+  struct GNUNET_DISK_PipeHandle *pout;
+  struct GNUNET_OS_Process *proc;
+  char *fnpty;
+  char *termstr;
+  struct winsize ws;
+  struct termios tio;
+  int ret;
+  int slave;
+  
+  if (!ctx->interactive)
+  {
+    pin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, 0, 0);
+    pout = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_YES, 0, 0);
+    GNUNET_assert ((NULL != pin && (NULL != pout)));
+    proc = GNUNET_OS_start_process_vap (GNUNET_NO,
+                                        GNUNET_OS_INHERIT_STD_NONE,
+                                        pin,
+                                        pout,
+                                        ctx->args[0],
+                                        ctx->args);
+    if (NULL == proc)
+      return GNUNET_SYSERR;
+    ctx->child_pid = GNUNET_OS_process_get_pid (proc);
+    GNUNET_OS_process_destroy (proc);
+    MSH_monitor_process_pid (ctx->child_pid, &proc_exit_cb, ctx);
+    ctx->fin = GNUNET_DISK_pipe_detach_end (pin, GNUNET_DISK_PIPE_END_WRITE);
+    ctx->fout = GNUNET_DISK_pipe_detach_end (pout, GNUNET_DISK_PIPE_END_READ);
+    GNUNET_assert ((NULL != ctx->fin && (NULL != ctx->fout)));
+    GNUNET_assert (GNUNET_OK == GNUNET_DISK_pipe_close (pin));
+    GNUNET_assert (GNUNET_OK == GNUNET_DISK_pipe_close (pout));
+    ctx->fout_task = 
+        GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                        ctx->fout, &read_fout, ctx);
+    return GNUNET_OK;
+  }
+  if (NULL == (fnpty = ptsname (ctx->master)))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "ptsname");
+    return GNUNET_SYSERR;
+  }
+  ret = fork ();
+  if (-1 == ret)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
+    return GNUNET_SYSERR;
+  }
+  if (0 != ret)
+  {
+    int fd;
+
+    LOG_DEBUG ("Forked child successfully\n");
+    ctx->child_pid = ret;
+    MSH_monitor_process_pid (ctx->child_pid, &proc_exit_cb, ctx);
+    /* forward streams to and from child */
+    ctx->fin = GNUNET_DISK_get_handle_from_int_fd (ctx->master);
+    fd = dup (ctx->master);
+    if (-1 == fd)
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup");
+      GNUNET_assert (0 == kill (ret, SIGTERM));
+      return GNUNET_SYSERR;
+    }
+    ctx->fout = GNUNET_DISK_get_handle_from_int_fd (fd);
+    ctx->fout_task =
+        GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 
ctx->fout,
+                                        &read_fout, ctx);
+
+    return GNUNET_OK;
+  }
+  close (ctx->master);
+  LOG_DEBUG ("Opening slave PTY %s\n", fnpty);
+  slave = open (fnpty, O_RDWR);
+  if (-1 == slave)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "open");
+    _exit (1);
+  }
+  if (-1 == tcgetattr (slave, &tio))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "tcgetattr");
+    _exit (1);
+  }
+  termstr = NULL;
+  parse_term_mode (ctx->pty_mode, &tio, &ws, &termstr);
+  GNUNET_free (ctx->pty_mode);
+  ctx->pty_mode = NULL;
+  if (NULL != termstr)
+  {
+    GNUNET_break (0 == setenv ("TERM", termstr, 1));
+    GNUNET_free (termstr);
+  }
+  else
+    GNUNET_break (0 == setenv ("TERM", "MSH", 1));
+  if (-1 == tcsetattr (slave, TCSANOW, &tio))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "tcsetattr");
+    //_exit (1);                /* Ignore for now */
+  }
+  if (-1 == ioctl (slave, TIOCSWINSZ, &ws))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "ioctl");
+    _exit (1);
+  }
+  if (-1 == setsid ())
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsid");
+    _exit (1);
+  }
+  close (0);
+  close (1);
+  //close (2);
+  if ( (-1 == dup2 (slave, 0)) ||
+       (-1 == dup2 (slave, 1)) ) //||
+    //(-1 == dup2 (slave, 2)) )
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup");
+    _exit (2);
+  }
+  close (slave);
+  LOG_DEBUG ("Execing %s\n", ctx->args[0]);
+  if (-1 == execvp (ctx->args[0], ctx->args))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "execvp");
+    _exit (1);
+  }
+  GNUNET_assert (0);            /* This should never be reached */
+}
+
+
+/**
+ * Handle session open message and start challenge authentication.
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_runcmd (void *cls,
+               struct GNUNET_SERVER_Client *client,
+               const struct GNUNET_MessageHeader* message)
+{
+  const struct MSH_MSG_RunCmd *msg;
+  struct ExecCtx *exec_ctx;
+  struct GNUNET_MessageHeader *reply;
+  uint16_t size;
+  
+  LOG_DEBUG ("Received a RUN_CMD message\n");
+  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
+  GNUNET_assert (NULL != exec_ctx);
+  if (GNUNET_YES != exec_ctx->authenticated)
+  {
+    GNUNET_break_op (0);
+    goto close_conn;
+  }
+  if (exec_ctx->interactive && !exec_ctx->pty_created)
+  {
+    GNUNET_break_op (0);
+    goto close_conn;
+  }
+  if (NULL != exec_ctx->args)
+  {
+    GNUNET_break (0);
+    goto close_conn;
+  }
+  size = ntohs (message->size);
+  if ( size <= sizeof (struct MSH_MSG_RunCmd))
+  {
+    GNUNET_break_op (0);
+    goto close_conn; 
+  }
+  msg = (const struct MSH_MSG_RunCmd *) message;
+  if (0 == parse_strings (msg->cmd,
+                          size - sizeof (struct MSH_MSG_RunCmd),
+                          &exec_ctx->args))
+  {
+    GNUNET_break_op (0);
+    goto close_conn;
+  }
+  GNUNET_SCHEDULER_cancel (exec_ctx->timeout_task);
+  exec_ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  if (GNUNET_OK != proc_exec (exec_ctx))
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "Command `%s' not found or not executable\n", exec_ctx->args[0]);
+    goto close_conn;
+  }
+  reply = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
+  reply->size = htons (sizeof (struct GNUNET_MessageHeader));
+  reply->type = htons (MSH_MTYPE_EXEC_BEGIN);
+  GNUNET_SERVER_notification_context_unicast (daemon_serv_nc, exec_ctx->client,
+                                              reply, GNUNET_NO);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  return;
+  
+ close_conn:
+  GNUNET_break_op (0);
+  GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+}
+
+
+/**
+ * Functions with this signature are called whenever a message is
+ * received.
+ *
+ * @param cls NULL
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_auth_challenge_response (void *cls,
+                                struct GNUNET_SERVER_Client *client,
+                                const struct GNUNET_MessageHeader* message)
+{
+  const struct MSH_MSG_ChallengeResponse *msg;
+  //struct GNUNET_MessageHeader *reply; FIXME
+  struct ExecCtx *exec_ctx;
+  struct GNUNET_HashCode cred;
+  struct GNUNET_CRYPTO_HashAsciiEncoded enc;
+  
+  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
+  GNUNET_assert (NULL != exec_ctx);
+  auth_challenge_cred (&exec_ctx->salt, &cred);
+  GNUNET_CRYPTO_hash_to_enc (&cred, &enc);
+  msg = (const struct MSH_MSG_ChallengeResponse *) message;
+  if (0 != memcmp (&msg->auth, &enc,
+                   sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
+  {
+    LOG_DEBUG ("Auth failed: \n"
+               "  Required: %s\n"
+               "  Given: %s\n", enc.encoding, msg->auth.encoding);
+    GNUNET_break (0);
+    goto err_ret;
+  }
+  exec_ctx->authenticated = GNUNET_YES;
+  return;
+  
+ err_ret:
+  GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+}
+
+
+/**
+ * Task to write data from input buffer to proc's STDIN
+ *
+ * @param cls the client context
+ * @return tc scheduler task context
+ */
+static void
+write_fin (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct ExecCtx *exec_ctx = cls;
+  ssize_t wrote;
+  
+  exec_ctx->fin_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))
+  {
+    GNUNET_free (exec_ctx->buf);
+    exec_ctx->buf = NULL;
+    exec_ctx->bufsize = 0;
+    goto err_ret;
+  }
+  wrote = GNUNET_DISK_file_write (exec_ctx->fin,
+                                  exec_ctx->buf, exec_ctx->bufsize);
+  if (GNUNET_SYSERR == wrote)
+  {
+    LOG_ERROR ("Error writing to proc's STDIN\n");
+    goto err_ret;
+  }
+  if (wrote == exec_ctx->bufsize)
+  {
+    GNUNET_free (exec_ctx->buf);
+    exec_ctx->buf = NULL;
+    exec_ctx->bufsize = 0;
+    GNUNET_SERVER_receive_done (exec_ctx->client, GNUNET_OK);
+    return;
+  }
+  GNUNET_assert (wrote < exec_ctx->bufsize);
+  exec_ctx->bufsize -= wrote;
+  exec_ctx->buf = memmove (exec_ctx->buf, exec_ctx->buf + wrote,
+                           exec_ctx->bufsize);
+  exec_ctx->buf = GNUNET_realloc (exec_ctx->buf, exec_ctx->bufsize);
+  exec_ctx->fin_task = 
+      GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                       exec_ctx->fin,
+                                       &write_fin, exec_ctx);
+  return;
+
+ err_ret:
+  GNUNET_SERVER_receive_done (exec_ctx->client, GNUNET_SYSERR);
+}
+
+
+/**
+ * Handler for messages with command's input stream data.  The date will be
+ * written to the command's standard input stream.
+ *
+ * @param cls NULL
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_command_input (void *cls,
+                      struct GNUNET_SERVER_Client *client,
+                      const struct GNUNET_MessageHeader* message)
+{
+  const struct MSH_MSG_CmdIO *msg;
+  struct ExecCtx *exec_ctx;
+  ssize_t wrote;
+  uint16_t size;
+ 
+  LOG_DEBUG ("Received CMD_IO_STDIN message\n");
+  size = ntohs (message->size);
+  msg = (const struct MSH_MSG_CmdIO *) message;
+  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
+  GNUNET_assert (NULL != exec_ctx);
+  size -= sizeof (struct MSH_MSG_CmdIO);
+  wrote = GNUNET_DISK_file_write (exec_ctx->fin, msg->data, size);
+  if (GNUNET_SYSERR == wrote)
+  {
+    LOG_ERROR ("Error writing to proc's STDIN\n");
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  LOG_DEBUG ("Wrote %zd to proc's STDIN\n", wrote);
+  if (wrote == size)
+  {
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
+  GNUNET_assert (wrote < size);
+  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == exec_ctx->fin_task);
+  GNUNET_assert (NULL == exec_ctx->buf);
+  GNUNET_assert (0 == exec_ctx->bufsize);
+  exec_ctx->bufsize = size - wrote;
+  exec_ctx->buf = GNUNET_malloc (exec_ctx->bufsize);
+  (void) memcpy (exec_ctx->buf, msg->data + wrote, exec_ctx->bufsize);
+  exec_ctx->fin_task = 
+      GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                       exec_ctx->fin,
+                                       &write_fin, exec_ctx);
+  GNUNET_SERVER_disable_receive_done_warning (client);
+}
+
+
+/**
+ * Handler for messages containing the settings to be used while creating a
+ * psuedo-tty.  This message must only be received for interactive sessions
+ * before #MSH_MSG_RunCmd message is received.
+ *
+ * @param cls NULL
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_pty_mode (void *cls,
+                 struct GNUNET_SERVER_Client *client,
+                 const struct GNUNET_MessageHeader* message)
+{
+  struct ExecCtx *exec_ctx;
+  int master;
+  uint16_t size;
+
+  size = ntohs (message->size);
+  if (size <= sizeof (struct MSH_MSG_PtyMode))
+  {
+    GNUNET_break (0);
+    goto close_conn;
+  }
+  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
+  GNUNET_assert (NULL != exec_ctx);
+  master = posix_openpt (O_RDWR);
+  if (-1 == master)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "posix_openpt");
+    goto close_conn;
+  }
+  if (-1 == grantpt (master))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "grantpt");
+    goto close_conn;
+  }
+  if (-1 == unlockpt (master))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "unlockpt");
+    goto close_conn;
+  }
+  exec_ctx->master = master;
+  exec_ctx->pty_created = GNUNET_YES;
+  exec_ctx->pty_mode = (struct MSH_MSG_PtyMode *) GNUNET_copy_message 
(message);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  return;
+  
+ close_conn:
+  GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+}
+
+
+/**
+ * Callback to be called when ever a client connects to the daemon server
+ *
+ * @param cls NULL
+ * @param client the client handle
+ */
+static void
+daemon_server_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
+{
+  struct ExecCtx *exec_ctx;
+  
+  if (NULL == client)
+    return;
+  LOG_DEBUG ("A remote client has disconnected\n");
+  exec_ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecCtx);
+  GNUNET_assert (NULL != exec_ctx);
+  destroy_exec_ctx (exec_ctx);
+}
+
+
+/**
+ * Initialises the server which spawns processes and forwards it stdin and 
stdout
+ *
+ * @param h the network handle of the socket to listen for incoming connections
+ */
+int
+init_daemon_server ()
+{
+  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
+    {&handle_session_open, NULL, MSH_MTYPE_SESSION_OPEN,
+     sizeof (struct MSH_MSG_SessionOpen)}, 
+    {&handle_runcmd, NULL, MSH_MTYPE_RUNCMD, 0},
+    {&handle_auth_challenge_response, NULL, MSH_MTYPE_CHALLENGE_RESPONSE, 
+     sizeof (struct MSH_MSG_ChallengeResponse)},
+    {&handle_command_input, NULL, MSH_MTYPE_CMD_STREAM_STDIN, 0},
+    {&handle_pty_mode, NULL, MSH_MTYPE_PTY_MODE, 0},
+    {NULL, NULL, 0, 0}
+  };
+  
+  daemon_serv = GNUNET_SERVER_create_with_sockets (NULL,
+                                                   NULL,
+                                                   NULL,
+                                                   
GNUNET_TIME_UNIT_FOREVER_REL,
+                                                   GNUNET_YES);
+  if (NULL == daemon_serv) 
+    return GNUNET_SYSERR;
+  GNUNET_SERVER_add_handlers (daemon_serv, handlers);
+  GNUNET_SERVER_disconnect_notify (daemon_serv, &daemon_server_disconnect, 
NULL);
+  daemon_serv_nc = GNUNET_SERVER_notification_context_create (daemon_serv, 1);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Timeout task for timing out connections until they authenticate.  Once
+ * authenticated the connection will not be timed out.
+ *
+ * @param cls the client context
+ * @param tc scheduler task context
+ */
+static void
+timeout_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct ExecCtx *exec_ctx = cls;
+
+  exec_ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_SERVER_client_disconnect (exec_ctx->client);
+}
+
+
+/**
+ * Create a client for the daemon server from a new client connection
+ *
+ * @param conn the connection to derive the client from
+ */
+void
+daemon_server_add_connection (struct GNUNET_CONNECTION_Handle *conn)
+{
+  struct ExecCtx *exec_ctx;
+  struct GNUNET_SERVER_Client *client;
+
+  exec_ctx = GNUNET_malloc (sizeof (struct ExecCtx));
+  client = GNUNET_SERVER_connect_socket (daemon_serv, conn);
+  exec_ctx->client = client;
+  GNUNET_SERVER_client_set_user_context (client, exec_ctx);
+  GNUNET_SERVER_notification_context_add (daemon_serv_nc, client);
+  exec_ctx->timeout_task = 
+      GNUNET_SCHEDULER_add_delayed (TIMEOUT_SECS (30), &timeout_cb, exec_ctx);
+}
+
+
+/**
+ * Shutdown the daemon server
+ */
+void
+shutdown_daemon_server ()
+{
+  if (NULL != daemon_serv)
+  {
+    GNUNET_SERVER_destroy (daemon_serv);
+    daemon_serv = NULL;
+  }
+  if (NULL != daemon_serv_nc)
+  {
+    GNUNET_SERVER_notification_context_destroy (daemon_serv_nc);
+    daemon_serv_nc = NULL;
+  }
+}
+
+/* End of server.c */

Added: msh/src/server.h
===================================================================
--- msh/src/server.h                            (rev 0)
+++ msh/src/server.h    2013-11-20 13:58:08 UTC (rev 30827)
@@ -0,0 +1,56 @@
+/**
+ * @file server.c
+ * @brief functions implementing server functionalities of MSH daemon.  We
+ *          listen for commands from locally started MSH instances and also for
+ *          executing commands given by remote MSH daemons.
+ * @author Sree Harsha Totakura <address@hidden> 
+ */
+
+#ifndef MSHD_SERVER_H_
+#define MSHD_SERVER_H_
+
+
+/**
+ * Shutdown the local server
+ */
+void
+shutdown_local_server ();
+
+
+/**
+ * Shutdown the daemon server
+ */
+void
+shutdown_daemon_server ();
+
+
+/**
+ * Create a client for the daemon server from a new client connection
+ *
+ * @param conn the connection to derive the client from
+ */
+void
+daemon_server_add_connection (struct GNUNET_CONNECTION_Handle *conn);
+
+
+/**
+ * Initialises the server which spawns processes and forwards it stdin and 
stdout
+ *
+ * @param h the network handle of the socket to listen for incoming connections
+ */
+int
+init_daemon_server ();
+
+
+/**
+ * Initialise the local server
+ *
+ * @param unixpath the name to use while opening the abstract UNIX domain 
socket
+ *   for listening
+ * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
+ */
+int
+init_local_server (const char *unixpath);
+
+
+#endif  /* MSHD_SERVER_H_ */

Modified: msh/src/test_pty.c
===================================================================
--- msh/src/test_pty.c  2013-11-20 10:55:44 UTC (rev 30826)
+++ msh/src/test_pty.c  2013-11-20 13:58:08 UTC (rev 30827)
@@ -42,7 +42,6 @@
 static struct GNUNET_DISK_PipeHandle *sigpipe;
 
 static struct GNUNET_DISK_FileHandle *chld_io;
-static struct GNUNET_DISK_FileHandle *our_in;
 
 static struct GNUNET_CONNECTION_Handle *conn;
 




reply via email to

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