示例#1
0
文件: signal.c 项目: 217/ruby
/*
 * Many operating systems allow signals to be sent to running
 * processes. Some signals have a defined effect on the process, while
 * others may be trapped at the code level and acted upon. For
 * example, your process may trap the USR1 signal and use it to toggle
 * debugging, and may use TERM to initiate a controlled shutdown.
 *
 *     pid = fork do
 *       Signal.trap("USR1") do
 *         $debug = !$debug
 *         puts "Debug now: #$debug"
 *       end
 *       Signal.trap("TERM") do
 *         puts "Terminating..."
 *         shutdown()
 *       end
 *       # . . . do some work . . .
 *     end
 *
 *     Process.detach(pid)
 *
 *     # Controlling program:
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("TERM", pid)
 *
 * produces:
 *     Debug now: true
 *     Debug now: false
 *    Terminating...
 *
 * The list of available signal names and their interpretation is
 * system dependent. Signal delivery semantics may also vary between
 * systems; in particular signal delivery may not always be reliable.
 */
void
Init_signal(void)
{
    VALUE mSignal = rb_define_module("Signal");

    rb_define_global_function("trap", sig_trap, -1);
    rb_define_module_function(mSignal, "trap", sig_trap, -1);
    rb_define_module_function(mSignal, "list", sig_list, 0);

    rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
    rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
    rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
    rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);

    install_sighandler(SIGINT, sighandler);
#ifdef SIGHUP
    install_sighandler(SIGHUP, sighandler);
#endif
#ifdef SIGQUIT
    install_sighandler(SIGQUIT, sighandler);
#endif
#ifdef SIGTERM
    install_sighandler(SIGTERM, sighandler);
#endif
#ifdef SIGALRM
    install_sighandler(SIGALRM, sighandler);
#endif
#ifdef SIGUSR1
    install_sighandler(SIGUSR1, sighandler);
#endif
#ifdef SIGUSR2
    install_sighandler(SIGUSR2, sighandler);
#endif

#ifdef RUBY_DEBUG_ENV
    if (!ruby_enable_coredump)
#endif
    {
#ifdef SIGBUS
    install_sighandler(SIGBUS, sigbus);
#endif
#ifdef SIGSEGV
# ifdef USE_SIGALTSTACK
    rb_register_sigaltstack(GET_THREAD());
# endif
    install_sighandler(SIGSEGV, (sighandler_t)sigsegv);
#endif
    }
#ifdef SIGPIPE
    install_sighandler(SIGPIPE, sigpipe);
#endif

#if defined(SIGCLD)
    init_sigchld(SIGCLD);
#elif defined(SIGCHLD)
    init_sigchld(SIGCHLD);
#endif
}
示例#2
0
/*
 * Many operating systems allow signals to be sent to running
 * processes. Some signals have a defined effect on the process, while
 * others may be trapped at the code level and acted upon. For
 * example, your process may trap the USR1 signal and use it to toggle
 * debugging, and may use TERM to initiate a controlled shutdown.
 *
 *     pid = fork do
 *       Signal.trap("USR1") do
 *         $debug = !$debug
 *         puts "Debug now: #$debug"
 *       end
 *       Signal.trap("TERM") do
 *         puts "Terminating..."
 *         shutdown()
 *       end
 *       # . . . do some work . . .
 *     end
 *
 *     Process.detach(pid)
 *
 *     # Controlling program:
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("TERM", pid)
 *
 * produces:
 *     Debug now: true
 *     Debug now: false
 *    Terminating...
 *
 * The list of available signal names and their interpretation is
 * system dependent. Signal delivery semantics may also vary between
 * systems; in particular signal delivery may not always be reliable.
 */
void
Init_signal(void)
{
#ifndef MACOS_UNUSE_SIGNAL
    VALUE mSignal = rb_define_module("Signal");

    rb_define_global_function("trap", sig_trap, -1);
    rb_define_module_function(mSignal, "trap", sig_trap, -1);
    rb_define_module_function(mSignal, "list", sig_list, 0);

    rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
    rb_attr(rb_eSignal, rb_intern("signo"), 1, 0, 0);
    rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
    rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);

    install_sighandler(SIGINT, sighandler);
#ifdef SIGHUP
    install_sighandler(SIGHUP, sighandler);
#endif
#ifdef SIGQUIT
    install_sighandler(SIGQUIT, sighandler);
#endif
#ifdef SIGTERM
    install_sighandler(SIGTERM, sighandler);
#endif
#ifdef SIGALRM
    install_sighandler(SIGALRM, sighandler);
#endif
#ifdef SIGUSR1
    install_sighandler(SIGUSR1, sighandler);
#endif
#ifdef SIGUSR2
    install_sighandler(SIGUSR2, sighandler);
#endif

#ifdef RUBY_DEBUG_ENV
    if (!ruby_enable_coredump)
#endif
    {
#ifdef SIGBUS
    install_sighandler(SIGBUS, sigbus);
#endif
#ifdef SIGSEGV
    install_sighandler(SIGSEGV, sigsegv);
#endif
    }
#ifdef SIGPIPE
    install_sighandler(SIGPIPE, sigpipe);
#endif

#if defined(SIGCLD)
    init_sigchld(SIGCLD);
#elif defined(SIGCHLD)
    init_sigchld(SIGCHLD);
#endif

#endif /* MACOS_UNUSE_SIGNAL */
}
示例#3
0
/*
 * Many operating systems allow signals to be sent to running
 * processes. Some signals have a defined effect on the process, while
 * others may be trapped at the code level and acted upon. For
 * example, your process may trap the USR1 signal and use it to toggle
 * debugging, and may use TERM to initiate a controlled shutdown.
 *
 *     pid = fork do
 *       Signal.trap("USR1") do
 *         $debug = !$debug
 *         puts "Debug now: #$debug"
 *       end
 *       Signal.trap("TERM") do
 *         puts "Terminating..."
 *         shutdown()
 *       end
 *       # . . . do some work . . .
 *     end
 *
 *     Process.detach(pid)
 *
 *     # Controlling program:
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("TERM", pid)
 *
 * produces:
 *     Debug now: true
 *     Debug now: false
 *    Terminating...
 *
 * The list of available signal names and their interpretation is
 * system dependent. Signal delivery semantics may also vary between
 * systems; in particular signal delivery may not always be reliable.
 */
void
Init_signal(void)
{
#ifndef MACOS_UNUSE_SIGNAL
    VALUE mSignal = rb_define_module("Signal");

    rb_define_global_function("trap", sig_trap, -1);
    rb_define_module_function(mSignal, "trap", sig_trap, -1);
    rb_define_module_function(mSignal, "list", sig_list, 0);

    install_sighandler(SIGINT, sighandler);
#ifdef SIGHUP
    install_sighandler(SIGHUP, sighandler);
#endif
#ifdef SIGQUIT
    install_sighandler(SIGQUIT, sighandler);
#endif
#ifdef SIGTERM
    install_sighandler(SIGTERM, sighandler);
#endif
#ifdef SIGALRM
    install_sighandler(SIGALRM, sighandler);
#endif
#ifdef SIGUSR1
    install_sighandler(SIGUSR1, sighandler);
#endif
#ifdef SIGUSR2
    install_sighandler(SIGUSR2, sighandler);
#endif

#ifdef SIGBUS
    install_sighandler(SIGBUS, sigbus);
#endif
#ifdef SIGSEGV
    install_sighandler(SIGSEGV, sigsegv);
#endif
#ifdef SIGPIPE
    install_sighandler(SIGPIPE, sigpipe);
#endif

#if defined(SIGCLD)
    init_sigchld(SIGCLD);
#elif defined(SIGCHLD)
    init_sigchld(SIGCHLD);
#endif

#endif /* MACOS_UNUSE_SIGNAL */
}
示例#4
0
/*
 * Many operating systems allow signals to be sent to running
 * processes. Some signals have a defined effect on the process, while
 * others may be trapped at the code level and acted upon. For
 * example, your process may trap the USR1 signal and use it to toggle
 * debugging, and may use TERM to initiate a controlled shutdown.
 *
 *     pid = fork do
 *       Signal.trap("USR1") do
 *         $debug = !$debug
 *         puts "Debug now: #$debug"
 *       end
 *       Signal.trap("TERM") do
 *         puts "Terminating..."
 *         shutdown()
 *       end
 *       # . . . do some work . . .
 *     end
 *
 *     Process.detach(pid)
 *
 *     # Controlling program:
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("TERM", pid)
 *
 * produces:
 *     Debug now: true
 *     Debug now: false
 *    Terminating...
 *
 * The list of available signal names and their interpretation is
 * system dependent. Signal delivery semantics may also vary between
 * systems; in particular signal delivery may not always be reliable.
 */
void
Init_signal(void)
{
#ifndef MACOS_UNUSE_SIGNAL
    VALUE mSignal = rb_define_module("Signal");

    rb_objc_define_module_function(rb_mKernel, "trap", sig_trap, -1);
    rb_objc_define_method(*(VALUE *)mSignal, "trap", sig_trap, -1);
    rb_objc_define_method(*(VALUE *)mSignal, "list", sig_list, 0);

    rb_objc_define_method(rb_eSignal, "initialize", esignal_init, -1);
    rb_objc_define_method(rb_eSignal, "signo", esignal_signo, 0);
    rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
    rb_objc_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);

/*     install_sighandler(SIGINT, sighandler); */
/*     install_sighandler(SIGHUP, sighandler); */
/*     install_sighandler(SIGQUIT, sighandler); */
/*     install_sighandler(SIGTERM, sighandler); */
/*     install_sighandler(SIGALRM, sighandler); */
/*     install_sighandler(SIGUSR1, sighandler); */
/*     install_sighandler(SIGUSR2, sighandler); */

#ifdef RUBY_DEBUG_ENV
    if (!ruby_enable_coredump)
#endif
    install_sighandler(SIGPIPE, sigpipe);

    init_sigchld(SIGCHLD);
#endif /* !MACOS_UNUSE_SIGNAL */
}
示例#5
0
文件: main.c 项目: BrEacK/mc
int
main (int argc, char *argv[])
{
    GError *error = NULL;
    int exit_code = EXIT_FAILURE;

    /* We had LC_CTYPE before, LC_ALL includs LC_TYPE as well */
    (void) setlocale (LC_ALL, "");
    (void) bindtextdomain ("mc", LOCALEDIR);
    (void) textdomain ("mc");

    /* do this before args parsing */
    str_init_strings (NULL);

    if (!mc_args_parse (&argc, &argv, "mc", &error))
    {
      startup_exit_falure:
        fprintf (stderr, _("Failed to run:\n%s\n"), error->message);
        g_error_free (error);
        g_free (shell);
      startup_exit_ok:
        str_uninit_strings ();
        return exit_code;
    }

    /* do this before mc_args_show_info () to view paths in the --datadir-info output */
    OS_Setup ();

    if (!g_path_is_absolute (mc_config_get_home_dir ()))
    {
        error = g_error_new (MC_ERROR, 0, "%s: %s", _("Home directory path is not absolute"),
                             mc_config_get_home_dir ());
        mc_event_deinit (NULL);
        goto startup_exit_falure;
    }

    if (!mc_args_show_info ())
    {
        exit_code = EXIT_SUCCESS;
        goto startup_exit_ok;
    }

    if (!events_init (&error))
        goto startup_exit_falure;

    mc_config_init_config_paths (&error);
    if (error == NULL && mc_config_deprecated_dir_present ())
        mc_config_migrate_from_old_place (&error);
    if (error != NULL)
    {
        mc_event_deinit (NULL);
        goto startup_exit_falure;
    }

    vfs_init ();
    vfs_plugins_init ();
    vfs_setup_work_dir ();

    /* do this after vfs initialization due to mc_setctl() call in mc_setup_by_args() */
    if (!mc_setup_by_args (argc, argv, &error))
    {
        vfs_shut ();
        mc_event_deinit (NULL);
        goto startup_exit_falure;
    }

    /* check terminal type
     * $TEMR must be set and not empty
     * mc_global.tty.xterm_flag is used in init_key() and tty_init()
     * Do this after mc_args_handle() where mc_args__force_xterm is set up.
     */
    mc_global.tty.xterm_flag = tty_check_term (mc_args__force_xterm);

    /* NOTE: This has to be called before tty_init or whatever routine
       calls any define_sequence */
    init_key ();

    /* Must be done before installing the SIGCHLD handler [[FIXME]] */
    handle_console (CONSOLE_INIT);

#ifdef HAVE_SUBSHELL_SUPPORT
    /* Don't use subshell when invoked as viewer or editor */
    if (mc_global.mc_run_mode != MC_RUN_FULL)
        mc_global.tty.use_subshell = FALSE;

    if (mc_global.tty.use_subshell)
        subshell_get_console_attributes ();
#endif /* HAVE_SUBSHELL_SUPPORT */

    /* Install the SIGCHLD handler; must be done before init_subshell() */
    init_sigchld ();

    /* We need this, since ncurses endwin () doesn't restore the signals */
    save_stop_handler ();

    /* Must be done before init_subshell, to set up the terminal size: */
    /* FIXME: Should be removed and LINES and COLS computed on subshell */
    tty_init (!mc_args__nomouse, mc_global.tty.xterm_flag);

    load_setup ();

    /* start check mc_global.display_codepage and mc_global.source_codepage */
    check_codeset ();

    /* Removing this from the X code let's us type C-c */
    load_key_defs ();

    load_keymap_defs (!mc_args__nokeymap);

    macros_list = g_array_new (TRUE, FALSE, sizeof (macros_t));

    tty_init_colors (mc_global.tty.disable_colors, mc_args__force_colors);

    mc_skin_init (&error);
    if (error != NULL)
    {
        message (D_ERROR, _("Warning"), "%s", error->message);
        g_error_free (error);
        error = NULL;
    }

    mc_filehighlight = mc_fhl_new (TRUE);
    dlg_set_default_colors ();

#ifdef HAVE_SUBSHELL_SUPPORT
    /* Done here to ensure that the subshell doesn't  */
    /* inherit the file descriptors opened below, etc */
    if (mc_global.tty.use_subshell)
        init_subshell ();

#endif /* HAVE_SUBSHELL_SUPPORT */

    /* Also done after init_subshell, to save any shell init file messages */
    if (mc_global.tty.console_flag != '\0')
        handle_console (CONSOLE_SAVE);

    if (mc_global.tty.alternate_plus_minus)
        application_keypad_mode ();

#ifdef HAVE_SUBSHELL_SUPPORT
    if (mc_global.tty.use_subshell)
    {
        mc_prompt = strip_ctrl_codes (subshell_prompt);
        if (mc_prompt == NULL)
            mc_prompt = (geteuid () == 0) ? "# " : "$ ";
    }
    else
#endif /* HAVE_SUBSHELL_SUPPORT */
        mc_prompt = (geteuid () == 0) ? "# " : "$ ";

    /* Program main loop */
    if (mc_global.midnight_shutdown)
        exit_code = EXIT_SUCCESS;
    else
        exit_code = do_nc ()? EXIT_SUCCESS : EXIT_FAILURE;

    /* Save the tree store */
    (void) tree_store_save ();

    free_keymap_defs ();

    /* Virtual File System shutdown */
    vfs_shut ();

    flush_extension_file ();    /* does only free memory */

    mc_fhl_free (&mc_filehighlight);
    mc_skin_deinit ();
    tty_colors_done ();

    tty_shutdown ();

    done_setup ();

    if (mc_global.tty.console_flag != '\0' && (quit & SUBSHELL_EXIT) == 0)
        handle_console (CONSOLE_RESTORE);
    if (mc_global.tty.alternate_plus_minus)
        numeric_keypad_mode ();

    (void) signal (SIGCHLD, SIG_DFL);   /* Disable the SIGCHLD handler */

    if (mc_global.tty.console_flag != '\0')
        handle_console (CONSOLE_DONE);

    if (mc_global.mc_run_mode == MC_RUN_FULL && mc_args__last_wd_file != NULL
        && last_wd_string != NULL && !print_last_revert)
    {
        int last_wd_fd;

        last_wd_fd = open (mc_args__last_wd_file, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
                           S_IRUSR | S_IWUSR);
        if (last_wd_fd != -1)
        {
            ssize_t ret1;
            int ret2;
            ret1 = write (last_wd_fd, last_wd_string, strlen (last_wd_string));
            ret2 = close (last_wd_fd);
        }
    }
    g_free (last_wd_string);

    g_free (shell);

    done_key ();

    if (macros_list != NULL)
    {
        guint i;
        macros_t *macros;
        for (i = 0; i < macros_list->len; i++)
        {
            macros = &g_array_index (macros_list, struct macros_t, i);
            if (macros != NULL && macros->macro != NULL)
                (void) g_array_free (macros->macro, FALSE);
        }
        (void) g_array_free (macros_list, TRUE);
    }
示例#6
0
rktio_process_result_t *rktio_process(rktio_t *rktio,
                                      const char *command, int argc, rktio_const_string_t *argv,
                                      rktio_fd_t *stdout_fd, rktio_fd_t *stdin_fd, rktio_fd_t *stderr_fd,
                                      rktio_process_t *group_proc,
                                      const char *current_directory, rktio_envvars_t *envvars,
                                      int flags)
{
  rktio_process_result_t *result;
  intptr_t to_subprocess[2], from_subprocess[2], err_subprocess[2];
  int pid;
#if defined(RKTIO_SYSTEM_UNIX)
# if !defined(CENTRALIZED_SIGCHILD)
  System_Child *sc;
# endif
#else
  void *sc = 0;
#endif
  void *env;
  rktio_process_t *subproc;
#if defined(RKTIO_SYSTEM_WINDOWS)
  intptr_t spawn_status;
#endif
  int new_process_group = (flags & RKTIO_PROCESS_NEW_GROUP);
  int stderr_is_stdout = (flags & RKTIO_PROCESS_STDOUT_AS_STDERR);
#if defined(RKTIO_SYSTEM_WINDOWS)
  int windows_exact_cmdline = (flags & RKTIO_PROCESS_WINDOWS_EXACT_CMDLINE);
  int windows_chain_termination_to_child = (flags & RKTIO_PROCESS_WINDOWS_CHAIN_TERMINATION);
  int i;
#endif

  /* avoid compiler warnings: */
  to_subprocess[0] = -1;
  to_subprocess[1] = -1;
  from_subprocess[0] = -1;
  from_subprocess[1] = -1;
  err_subprocess[0] = -1;
  err_subprocess[1] = -1;

  /*--------------------------------------*/
  /*          Create needed pipes         */
  /*--------------------------------------*/

  if (stdout_fd) {
    from_subprocess[1] = rktio_fd_system_fd(rktio, stdout_fd);
    RKTIO_COPY_FOR_SUBPROCESS(from_subprocess, 1);
  } else if (rktio_make_os_pipe(rktio, from_subprocess, RKTIO_NO_INHERIT_INPUT)) {
    return NULL;
  }

  if (stdin_fd) {
    to_subprocess[0] = rktio_fd_system_fd(rktio, stdin_fd);
    RKTIO_COPY_FOR_SUBPROCESS(to_subprocess, 0);
  } else if (rktio_make_os_pipe(rktio, to_subprocess, RKTIO_NO_INHERIT_OUTPUT)) {
    if (stdout_fd) { RKTIO_CLOSE_SUBPROCESS_COPY(from_subprocess, 1); }
    return NULL;
  }

  if (stderr_fd) {
    err_subprocess[1] = rktio_fd_system_fd(rktio, stderr_fd);
    RKTIO_COPY_FOR_SUBPROCESS(err_subprocess, 1);
  } else if (stderr_is_stdout) {
    err_subprocess[0] = from_subprocess[0];
    err_subprocess[1] = from_subprocess[1];
  } else if (rktio_make_os_pipe(rktio, err_subprocess, RKTIO_NO_INHERIT_INPUT)) {
    if (stdout_fd) { RKTIO_CLOSE_SUBPROCESS_COPY(from_subprocess, 1); }
    if (stdin_fd) { RKTIO_CLOSE_SUBPROCESS_COPY(to_subprocess, 0); }
    return NULL;
  }

  if (envvars)
    env = rktio_envvars_to_block(rktio, envvars);
  else
    env = NULL;

#if defined(RKTIO_SYSTEM_WINDOWS)

  /*--------------------------------------*/
  /*        Execute: Windows              */
  /*--------------------------------------*/

  /* Windows: quasi-stdin is locked, and we'll say it doesn't matter */
  fflush(stdin);
  fflush(stdout);
  fflush(stderr);

  {
    char **new_argv;

    if (!windows_exact_cmdline) {
      /* protect spaces, etc. in the arguments: */
      new_argv = malloc(sizeof(char *) * argc);
      for (i = 0; i < argc; i++) {
	new_argv[i] = cmdline_protect(argv[i]);
      }
      argv = new_argv;
    }

    pid = 0;

    spawn_status = do_spawnv(rktio,
                             command, argc, (const char * const *)argv,
			     windows_exact_cmdline,
			     to_subprocess[0],
			     from_subprocess[1],
			     err_subprocess[1],
			     &pid,
                             new_process_group,
                             windows_chain_termination_to_child,
                             env, current_directory);

    if (!windows_exact_cmdline) {
      for (i = 0; i < argc; i++) {
        free(argv[i]);
      }
      free(argv);
    }

    if (spawn_status != -1)
      sc = (void *)spawn_status;
  }

#else


  /*--------------------------------------*/
  /*            Execute: Unix             */
  /*--------------------------------------*/

  {
#if defined(CENTRALIZED_SIGCHILD)
    centralized_starting_child();
#else
    sc = malloc(sizeof(System_Child));
    sc->id = 0;
    sc->done = 0;

    block_child_signals(rktio, 1);

    /* Relies on signals blocked: */
    init_sigchld(rktio);
#endif

#if defined(__QNX__)
    pid = vfork();
#elif defined(SUBPROCESS_USE_FORK1)
    pid = fork1();
#else
    pid = fork();
#endif

    

    if (pid > 0) {
      /* This is the original process, which needs to manage the 
         newly created child process. */
      
      if (new_process_group || group_proc) {
        /* there's a race condition between this use and the exec(),
           and there's a race condition between the other setpgid() in
           the child processand sending signals from the parent
           process; so, we set in both, and at least one will
           succeed; we could perform better error checking, since
           EACCES is the only expected error */
        int pgid = pid;
        if (group_proc)
          pgid = group_proc->pid;
        setpgid(pid, pgid); /* note: silent failure */
      }

#if defined(CENTRALIZED_SIGCHILD)
      {
        rktio_signal_handle_t *signal_fd;
        int status;
        signal_fd = rktio_get_signal_handle(rktio);
        centralized_register_child(pid, new_process_group || group_proc, signal_fd, &status);

        /* printf("SUBPROCESS  %i\n", pid); */
      }
#else
      sc->next = rktio->system_children;
      rktio->system_children = sc;
      sc->id = pid;
#endif
    } else if (!pid) {
      /* This is the new child process */
      if (new_process_group || group_proc) {
        /* see also setpgid above */
        int actual_pid = getpid();
        int pgid = actual_pid;
        if (group_proc)
          pgid = group_proc->pid;
        setpgid(actual_pid, pgid); /* note: silent failure */
      }
    } else {
      get_posix_error();
    }

#if !defined(CENTRALIZED_SIGCHILD)
    block_child_signals(rktio, 0);
#else
    if (!pid)
      centralized_unblock_child_signal();
    else if (pid == -1)
      centralized_ended_child();
#endif
  }

  switch (pid)
    {
    case -1:
      /* Close all created descriptors */
      if (!stdin_fd) {
	rktio_reliably_close(to_subprocess[0]);
	rktio_reliably_close(to_subprocess[1]);
      } else {
	RKTIO_CLOSE_SUBPROCESS_COPY(to_subprocess, 0);
      }
      if (!stdout_fd) {
	rktio_reliably_close(from_subprocess[0]);
	rktio_reliably_close(from_subprocess[1]);
      } else {
	RKTIO_CLOSE_SUBPROCESS_COPY(from_subprocess, 1);
      }
      if (!stderr_fd) {
        if (!stderr_is_stdout) {
          rktio_reliably_close(err_subprocess[0]);
          rktio_reliably_close(err_subprocess[1]);
        }
      } else {
	RKTIO_CLOSE_SUBPROCESS_COPY(err_subprocess, 1);
      }
      return NULL;

    case 0: /* child */

      {
        int errid;
        
	/* Copy pipe descriptors to stdin and stdout */
	do {
	  errid = MSC_IZE(dup2)(to_subprocess[0], 0);
	} while (errid == -1 && errno == EINTR);
	do {
	  errid = MSC_IZE(dup2)(from_subprocess[1], 1);
	} while (errid == -1 && errno == EINTR);
	do {
	  errid = MSC_IZE(dup2)(err_subprocess[1], 2);
	} while (errid == -1 && errno == EINTR);

	/* Close unwanted descriptors */
	if (!stdin_fd) {
	  rktio_reliably_close(to_subprocess[0]);
	  rktio_reliably_close(to_subprocess[1]);
	}
	if (!stdout_fd) {
	  rktio_reliably_close(from_subprocess[0]);
	  rktio_reliably_close(from_subprocess[1]);
	}
	if (!stderr_fd) {
          if (!stderr_is_stdout) {
            rktio_reliably_close(err_subprocess[0]);
            rktio_reliably_close(err_subprocess[1]);
          }
	}

        rktio_close_fds_after_fork(0, 1, 2);
      }

      /* Set real CWD: */
      if (!rktio_set_current_directory(rktio, current_directory)) {
        fprintf(stderr, "racket: chdir failed to: %s\n", current_directory);
        _exit(1);
      }

      /* Exec new process */

      {
	int err, i;
        rktio_const_string_t *new_argv;

        /* add a NULL terminator */
        new_argv = malloc(sizeof(char *) * (argc + 1));
        for (i = 0; i < argc; i++) {
          new_argv[i] = argv[i];
        }
        new_argv[i] = NULL;

        if (!env)
          env = rktio_get_environ_array();
        
	err = MSC_IZE(execve)(command, (char **)new_argv, (char **)env);
        if (err)
          err = errno;

        if (envvars)
          free(env);

	/* If we get here it failed; give up */

        fprintf(stderr, "exec failed (%s%serrno=%d)\n", 
                strerror(err), "; ",
                err);

	_exit(1);
      }

    default: /* parent */

      break;
    }
#endif

  /*--------------------------------------*/
  /*      Close unneeded descriptors      */
  /*--------------------------------------*/

  free(env);

  if (!stdin_fd)
    RKTIO_CLOSE(to_subprocess[0]);
  else
    RKTIO_CLOSE_SUBPROCESS_COPY(to_subprocess, 0);
  
  if (!stdout_fd) 
    RKTIO_CLOSE(from_subprocess[1]);
  else
    RKTIO_CLOSE_SUBPROCESS_COPY(from_subprocess, 1);
  
  if (!stderr_fd) {
    if (!stderr_is_stdout)
      RKTIO_CLOSE(err_subprocess[1]);
  } else
    RKTIO_CLOSE_SUBPROCESS_COPY(err_subprocess, 1);

  /*--------------------------------------*/
  /*  Create new file-descriptor objects  */
  /*--------------------------------------*/

  result = malloc(sizeof(rktio_process_result_t));

  if (!stdout_fd)
    result->stdout_fd = rktio_system_fd(rktio, from_subprocess[0], RKTIO_OPEN_READ);
  else
    result->stdout_fd = NULL;
  if (!stdin_fd)
    result->stdin_fd = rktio_system_fd(rktio, to_subprocess[1], RKTIO_OPEN_WRITE);
  else
    result->stdin_fd = NULL;
  if (!stderr_fd && !stderr_is_stdout)
    result->stderr_fd = rktio_system_fd(rktio, err_subprocess[0], RKTIO_OPEN_READ);
  else
    result->stderr_fd = NULL;

  /*--------------------------------------*/
  /*          Return result info          */
  /*--------------------------------------*/

  subproc = malloc(sizeof(rktio_process_t));
  memset(subproc, 0, sizeof(rktio_process_t));
#if !defined(CENTRALIZED_SIGCHILD)
  subproc->handle = (void *)sc;
#endif
  subproc->pid = pid;
  subproc->is_group = new_process_group;
  subproc->in_group = (new_process_group || group_proc);

  result->process = subproc;

  return result;
}
示例#7
0
文件: main.c 项目: V07D/mc
int
main (int argc, char *argv[])
{
    GError *mcerror = NULL;
    gboolean config_migrated = FALSE;
    char *config_migrate_msg;
    int exit_code = EXIT_FAILURE;

    mc_global.timer = mc_timer_new ();

    /* We had LC_CTYPE before, LC_ALL includs LC_TYPE as well */
#ifdef HAVE_SETLOCALE
    (void) setlocale (LC_ALL, "");
#endif
    (void) bindtextdomain (PACKAGE, LOCALEDIR);
    (void) textdomain (PACKAGE);

    /* do this before args parsing */
    str_init_strings (NULL);

    if (!mc_args_parse (&argc, &argv, "mc", &mcerror))
    {
      startup_exit_falure:
        fprintf (stderr, _("Failed to run:\n%s\n"), mcerror->message);
        g_error_free (mcerror);
        g_free (mc_global.tty.shell);
      startup_exit_ok:
        str_uninit_strings ();
        mc_timer_destroy (mc_global.timer);
        return exit_code;
    }

    /* do this before mc_args_show_info () to view paths in the --datadir-info output */
    OS_Setup ();

    if (!g_path_is_absolute (mc_config_get_home_dir ()))
    {
        mc_propagate_error (&mcerror, 0, "%s: %s", _("Home directory path is not absolute"),
                            mc_config_get_home_dir ());
        mc_event_deinit (NULL);
        goto startup_exit_falure;
    }

    if (!mc_args_show_info ())
    {
        exit_code = EXIT_SUCCESS;
        goto startup_exit_ok;
    }

    if (!events_init (&mcerror))
        goto startup_exit_falure;

    mc_config_init_config_paths (&mcerror);
    config_migrated = mc_config_migrate_from_old_place (&mcerror, &config_migrate_msg);
    if (mcerror != NULL)
    {
        mc_event_deinit (NULL);
        goto startup_exit_falure;
    }

    vfs_init ();
    vfs_plugins_init ();

    load_setup ();

    /* Must be done after load_setup because depends on mc_global.vfs.cd_symlinks */
    vfs_setup_work_dir ();

    /* Resolve the other_dir panel option. Must be done after vfs_setup_work_dir */
    {
        char *buffer;
        vfs_path_t *vpath;

        buffer = mc_config_get_string (mc_panels_config, "Dirs", "other_dir", ".");
        vpath = vfs_path_from_str (buffer);
        if (vfs_file_is_local (vpath))
            saved_other_dir = buffer;
        else
            g_free (buffer);
        vfs_path_free (vpath);
    }

    /* Set up temporary directory after VFS initialization */
    mc_tmpdir ();

    /* do this after vfs initialization and vfs working directory setup
       due to mc_setctl() and mcedit_arg_vpath_new() calls in mc_setup_by_args() */
    if (!mc_setup_by_args (argc, argv, &mcerror))
    {
        vfs_shut ();
        done_setup ();
        g_free (saved_other_dir);
        mc_event_deinit (NULL);
        goto startup_exit_falure;
    }

    /* check terminal type
     * $TEMR must be set and not empty
     * mc_global.tty.xterm_flag is used in init_key() and tty_init()
     * Do this after mc_args_handle() where mc_args__force_xterm is set up.
     */
    mc_global.tty.xterm_flag = tty_check_term (mc_args__force_xterm);

    /* NOTE: This has to be called before tty_init or whatever routine
       calls any define_sequence */
    init_key ();

    /* Must be done before installing the SIGCHLD handler [[FIXME]] */
    handle_console (CONSOLE_INIT);

#ifdef ENABLE_SUBSHELL
    /* Don't use subshell when invoked as viewer or editor */
    if (mc_global.mc_run_mode != MC_RUN_FULL)
        mc_global.tty.use_subshell = FALSE;

    if (mc_global.tty.use_subshell)
        subshell_get_console_attributes ();
#endif /* ENABLE_SUBSHELL */

    /* Install the SIGCHLD handler; must be done before init_subshell() */
    init_sigchld ();

    /* We need this, since ncurses endwin () doesn't restore the signals */
    save_stop_handler ();

    /* Must be done before init_subshell, to set up the terminal size: */
    /* FIXME: Should be removed and LINES and COLS computed on subshell */
    tty_init (!mc_args__nomouse, mc_global.tty.xterm_flag);

    /* start check mc_global.display_codepage and mc_global.source_codepage */
    check_codeset ();

    /* Removing this from the X code let's us type C-c */
    load_key_defs ();

    load_keymap_defs (!mc_args__nokeymap);

    macros_list = g_array_new (TRUE, FALSE, sizeof (macros_t));

    tty_init_colors (mc_global.tty.disable_colors, mc_args__force_colors);

    mc_skin_init (NULL, &mcerror);
    dlg_set_default_colors ();
    input_set_default_colors ();
    if (mc_global.mc_run_mode == MC_RUN_FULL)
        command_set_default_colors ();

    mc_error_message (&mcerror);

#ifdef ENABLE_SUBSHELL
    /* Done here to ensure that the subshell doesn't  */
    /* inherit the file descriptors opened below, etc */
    if (mc_global.tty.use_subshell)
        init_subshell ();
#endif /* ENABLE_SUBSHELL */

    /* Also done after init_subshell, to save any shell init file messages */
    if (mc_global.tty.console_flag != '\0')
        handle_console (CONSOLE_SAVE);

    if (mc_global.tty.alternate_plus_minus)
        application_keypad_mode ();

    /* Done after subshell initialization to allow select and paste text by mouse
       w/o Shift button in subshell in the native console */
    init_mouse ();

    /* Done after do_enter_ca_mode (tty_init) because in VTE bracketed mode is
       separate for the normal and alternate screens */
    enable_bracketed_paste ();

    /* subshell_prompt is NULL here */
    mc_prompt = (geteuid () == 0) ? "# " : "$ ";

    if (config_migrated)
    {
        message (D_ERROR, _("Warning"), "%s", config_migrate_msg);
        g_free (config_migrate_msg);
    }

    /* Program main loop */
    if (mc_global.midnight_shutdown)
        exit_code = EXIT_SUCCESS;
    else
        exit_code = do_nc ()? EXIT_SUCCESS : EXIT_FAILURE;

    /* Save the tree store */
    (void) tree_store_save ();

    free_keymap_defs ();

    /* Virtual File System shutdown */
    vfs_shut ();

    flush_extension_file ();    /* does only free memory */

    mc_skin_deinit ();
    tty_colors_done ();

    tty_shutdown ();

    done_setup ();

    if (mc_global.tty.console_flag != '\0' && (quit & SUBSHELL_EXIT) == 0)
        handle_console (CONSOLE_RESTORE);
    if (mc_global.tty.alternate_plus_minus)
        numeric_keypad_mode ();

    (void) signal (SIGCHLD, SIG_DFL);   /* Disable the SIGCHLD handler */

    if (mc_global.tty.console_flag != '\0')
        handle_console (CONSOLE_DONE);

    if (mc_global.mc_run_mode == MC_RUN_FULL && mc_args__last_wd_file != NULL
        && last_wd_string != NULL && !print_last_revert)
    {
        int last_wd_fd;

        last_wd_fd = open (mc_args__last_wd_file, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
                           S_IRUSR | S_IWUSR);
        if (last_wd_fd != -1)
        {
            ssize_t ret1;
            int ret2;
            ret1 = write (last_wd_fd, last_wd_string, strlen (last_wd_string));
            ret2 = close (last_wd_fd);
            (void) ret1;
            (void) ret2;
        }
    }
    g_free (last_wd_string);

    g_free (mc_global.tty.shell);

    done_key ();

    if (macros_list != NULL)
    {
        guint i;
        for (i = 0; i < macros_list->len; i++)
        {
            macros_t *macros;

            macros = &g_array_index (macros_list, struct macros_t, i);
            if (macros != NULL && macros->macro != NULL)
                (void) g_array_free (macros->macro, FALSE);
        }
        (void) g_array_free (macros_list, TRUE);
    }
示例#8
0
/*
 * Many operating systems allow signals to be sent to running
 * processes. Some signals have a defined effect on the process, while
 * others may be trapped at the code level and acted upon. For
 * example, your process may trap the USR1 signal and use it to toggle
 * debugging, and may use TERM to initiate a controlled shutdown.
 *
 *     pid = fork do
 *       Signal.trap("USR1") do
 *         $debug = !$debug
 *         puts "Debug now: #$debug"
 *       end
 *       Signal.trap("TERM") do
 *         puts "Terminating..."
 *         shutdown()
 *       end
 *       # . . . do some work . . .
 *     end
 *
 *     Process.detach(pid)
 *
 *     # Controlling program:
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("TERM", pid)
 *
 * produces:
 *     Debug now: true
 *     Debug now: false
 *    Terminating...
 *
 * The list of available signal names and their interpretation is
 * system dependent. Signal delivery semantics may also vary between
 * systems; in particular signal delivery may not always be reliable.
 */
void
Init_signal(void)
{
    VALUE mSignal = rb_define_module("Signal");

    rb_define_global_function("trap", sig_trap, -1);
    rb_define_module_function(mSignal, "trap", sig_trap, -1);
    rb_define_module_function(mSignal, "list", sig_list, 0);
    rb_define_module_function(mSignal, "signame", sig_signame, 1);

    rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
    rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
    rb_alias(rb_eSignal, rb_intern_const("signm"), rb_intern_const("message"));
    rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);

    /* At this time, there is no subthread. Then sigmask guarantee atomics. */
    rb_disable_interrupt();

    install_sighandler(SIGINT, sighandler);
#ifdef SIGHUP
    install_sighandler(SIGHUP, sighandler);
#endif
#ifdef SIGQUIT
    install_sighandler(SIGQUIT, sighandler);
#endif
#ifdef SIGTERM
    install_sighandler(SIGTERM, sighandler);
#endif
#ifdef SIGALRM
    install_sighandler(SIGALRM, sighandler);
#endif
#ifdef SIGUSR1
    install_sighandler(SIGUSR1, sighandler);
#endif
#ifdef SIGUSR2
    install_sighandler(SIGUSR2, sighandler);
#endif

    if (!ruby_enable_coredump) {
#ifdef SIGBUS
	install_sighandler(SIGBUS, (sighandler_t)sigbus);
#endif
#ifdef SIGILL
	install_sighandler(SIGILL, (sighandler_t)sigill);
#endif
#ifdef SIGSEGV
# ifdef USE_SIGALTSTACK
	rb_register_sigaltstack(GET_THREAD());
# endif
	install_sighandler(SIGSEGV, (sighandler_t)sigsegv);
#endif
    }
#ifdef SIGPIPE
    install_sighandler(SIGPIPE, SIG_IGN);
#endif

#if defined(SIGCLD)
    init_sigchld(SIGCLD);
#elif defined(SIGCHLD)
    init_sigchld(SIGCHLD);
#endif

    rb_enable_interrupt();
}