/* * 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 }
/* * 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 */ }
/* * 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 */ }
/* * 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 */ }
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); }
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; }
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); }
/* * 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(); }