Example #1
0
static void
babysit (int   exit_with_session,
         pid_t child_pid,
         int   read_bus_pid_fd)  /* read pid from here */
{
  DBusEnsureStandardFdsFlags flags;
  int ret;
  const char *s;

  verbose ("babysitting, exit_with_session = %d, child_pid = %ld, read_bus_pid_fd = %d\n",
           exit_with_session, (long) child_pid, read_bus_pid_fd);
  
  /* We chdir ("/") since we are persistent and daemon-like, and fork
   * again so dbus-launch can reap the parent.  However, we don't
   * setsid() or close fd 0 because the idea is to remain attached
   * to the tty and the X server in order to kill the message bus
   * when the session ends.
   */

  if (chdir ("/") < 0)
    {
      fprintf (stderr, "Could not change to root directory: %s\n",
               strerror (errno));
      exit (1);
    }

  flags = DBUS_FORCE_STDOUT_NULL;

  if (!exit_with_session)
    flags |= DBUS_FORCE_STDIN_NULL;

  s = getenv ("DBUS_DEBUG_OUTPUT");

  if (s == NULL || *s == '\0')
    flags |= DBUS_FORCE_STDERR_NULL;

  /* Close stdout/stderr so we don't block an "eval" or otherwise
   * lock up. stdout is still chaining through to dbus-launch
   * and in turn to the parent shell.
   */
  if (!_dbus_ensure_standard_fds (flags, &s))
    {
      fprintf (stderr, "%s: %s\n", s, strerror (errno));
      exit (1);
    }

  ret = fork ();

  if (ret < 0)
    {
      fprintf (stderr, "fork() failed in babysitter: %s\n",
               strerror (errno));
      exit (1);
    }

  if (ret > 0)
    {
      /* Parent reaps pre-fork part of bus daemon, then exits and is
       * reaped so the babysitter isn't a zombie
       */

      verbose ("=== Babysitter's intermediate parent continues again\n");
      
      if (do_waitpid (child_pid) < 0)
        {
          /* shouldn't happen */
          fprintf (stderr, "Failed waitpid() waiting for bus daemon's parent\n");
          exit (1);
        }

      verbose ("Babysitter's intermediate parent exiting\n");
      
      exit (0);
    }

  /* Child continues */
  verbose ("=== Babysitter process created\n");

  verbose ("Reading PID from bus\n");
      
  switch (read_pid (read_bus_pid_fd, &bus_pid_to_kill))
    {
    case READ_STATUS_OK:
      break;
    case READ_STATUS_EOF:
      fprintf (stderr, "EOF in dbus-launch reading PID from bus daemon\n");
      exit (1);
      break;
    case READ_STATUS_ERROR:
      fprintf (stderr, "Error in dbus-launch reading PID from bus daemon: %s\n",
	       strerror (errno));
      exit (1);
      break;
    }

  verbose ("Got PID %ld from daemon\n",
           (long) bus_pid_to_kill);
  
  if (exit_with_session)
    {
      /* Bus is now started and launcher has needed info;
       * we connect to X display and tty and wait to
       * kill bus if requested.
       */
      
      kill_bus_when_session_ends ();
    }

  verbose ("Babysitter exiting\n");
  
  exit (0);
}
Example #2
0
static void
babysit (int   exit_with_session,
         pid_t child_pid,
         int   read_bus_pid_fd,  /* read pid from here */
         int   write_bus_pid_fd) /* forward pid to here */
{
  int ret;
#define MAX_PID_LEN 64
  char buf[MAX_PID_LEN];
  long val;
  char *end;
  int dev_null_fd;
  const char *s;

  verbose ("babysitting, exit_with_session = %d, child_pid = %ld, read_bus_pid_fd = %d, write_bus_pid_fd = %d\n",
           exit_with_session, (long) child_pid, read_bus_pid_fd, write_bus_pid_fd);
  
  /* We chdir ("/") since we are persistent and daemon-like, and fork
   * again so dbus-launch can reap the parent.  However, we don't
   * setsid() or close fd 0 because the idea is to remain attached
   * to the tty and the X server in order to kill the message bus
   * when the session ends.
   */

  if (chdir ("/") < 0)
    {
      fprintf (stderr, "Could not change to root directory: %s\n",
               strerror (errno));
      exit (1);
    }

  /* Close stdout/stderr so we don't block an "eval" or otherwise
   * lock up. stdout is still chaining through to dbus-launch
   * and in turn to the parent shell.
   */
  dev_null_fd = open ("/dev/null", O_RDWR);
  if (dev_null_fd >= 0)
    {
      if (!exit_with_session)
        dup2 (dev_null_fd, 0);
      dup2 (dev_null_fd, 1);
      s = getenv ("DBUS_DEBUG_OUTPUT");
      if (s == NULL || *s == '\0')
        dup2 (dev_null_fd, 2);
    }
  else
    {
      fprintf (stderr, "Failed to open /dev/null: %s\n",
               strerror (errno));
      /* continue, why not */
    }
  
  ret = fork ();

  if (ret < 0)
    {
      fprintf (stderr, "fork() failed in babysitter: %s\n",
               strerror (errno));
      exit (1);
    }

  if (ret > 0)
    {
      /* Parent reaps pre-fork part of bus daemon, then exits and is
       * reaped so the babysitter isn't a zombie
       */

      verbose ("=== Babysitter's intermediate parent continues again\n");
      
      if (do_waitpid (child_pid) < 0)
        {
          /* shouldn't happen */
          fprintf (stderr, "Failed waitpid() waiting for bus daemon's parent\n");
          exit (1);
        }

      verbose ("Babysitter's intermediate parent exiting\n");
      
      exit (0);
    }

  /* Child continues */
  verbose ("=== Babysitter process created\n");

  verbose ("Reading PID from daemon\n");
  /* Now read data */
  switch (read_line (read_bus_pid_fd, buf, MAX_PID_LEN))
    {
    case READ_STATUS_OK:
      break;
    case READ_STATUS_EOF:
      fprintf (stderr, "EOF reading PID from bus daemon\n");
      exit (1);
      break;
    case READ_STATUS_ERROR:
      fprintf (stderr, "Error reading PID from bus daemon: %s\n",
               strerror (errno));
      exit (1);
      break;
    }

  end = NULL;
  val = strtol (buf, &end, 0);
  if (buf == end || end == NULL)
    {
      fprintf (stderr, "Failed to parse bus PID \"%s\": %s\n",
               buf, strerror (errno));
      exit (1);
    }

  bus_pid_to_kill = val;

  verbose ("Got PID %ld from daemon\n",
           (long) bus_pid_to_kill);
  
  /* Write data to launcher */
  write_pid (write_bus_pid_fd, bus_pid_to_kill);
  close (write_bus_pid_fd);
  
  if (exit_with_session)
    {
      /* Bus is now started and launcher has needed info;
       * we connect to X display and tty and wait to
       * kill bus if requested.
       */
      
      kill_bus_when_session_ends ();
    }

  verbose ("Babysitter exiting\n");
  
  exit (0);
}