/// Setup our environment (e.g., tty modes), process key strokes, then reset the environment. static void setup_and_process_keys(bool continuous_mode) { is_interactive_session = 1; // by definition this program is interactive set_main_thread(); setup_fork_guards(); proc_push_interactive(1); env_init(); reader_init(); // We need to set the shell-modes for ICRNL, // in fish-proper this is done once a command is run. tcsetattr(STDIN_FILENO, TCSANOW, &shell_modes); install_our_signal_handlers(); if (continuous_mode) { std::fwprintf(stderr, L"\n"); std::fwprintf(stderr, L"To terminate this program type \"exit\" or \"quit\" in this window,\n"); std::fwprintf(stderr, L"or press [ctrl-%c] or [ctrl-%c] twice in a row.\n", shell_modes.c_cc[VINTR] + 0x40, shell_modes.c_cc[VEOF] + 0x40); std::fwprintf(stderr, L"\n"); } process_input(continuous_mode); restore_term_mode(); restore_term_foreground_process_group(); }
/// Setup our environment (e.g., tty modes), process key strokes, then reset the environment. void setup_and_process_keys(bool continuous_mode) { is_interactive_session = 1; // by definition this is interactive set_main_thread(); setup_fork_guards(); wsetlocale(LC_ALL, L"POSIX"); program_name = L"fish_key_reader"; env_init(); reader_init(); input_init(); // Installing our handler for every signal (e.g., SIGSEGV) is dubious because it means that // signals that might generate a core dump will not do so. On the other hand this allows us // to restore the tty modes so the terminal is still usable when we die. for (int signo = 1; signo < 32; signo++) { signal(signo, signal_handler); } if (continuous_mode) { printf("\n"); printf("Type 'exit' or 'quit' to terminate this program.\n"); printf("\n"); printf("Characters such as [ctrl-D] (EOF) and [ctrl-C] (interrupt)\n"); printf("have no special meaning and will not terminate this program.\n"); printf("\n"); } else { set_wait_on_escape_ms(500); } // TODO: We really should enable keypad mode but see issue #838. process_input(continuous_mode); restore_term_mode(); }
/// Setup our environment (e.g., tty modes), process key strokes, then reset the environment. static void setup_and_process_keys(bool continuous_mode) { is_interactive_session = 1; // by definition this program is interactive setenv("LC_ALL", "POSIX", 1); // ensure we're in a single-byte locale set_main_thread(); setup_fork_guards(); env_init(); reader_init(); input_init(); proc_push_interactive(1); signal_set_handlers(); install_our_signal_handlers(); if (continuous_mode) { printf("\n"); printf("To terminate this program type \"exit\" or \"quit\" in this window,\n"); printf("or press [ctrl-C] or [ctrl-D] twice in a row.\n"); printf("\n"); } process_input(continuous_mode); restore_term_mode(); restore_term_foreground_process_group(); input_destroy(); reader_destroy(); }
/// This function is similar to launch_process, except it is not called after a fork (i.e. it only /// calls exec) and therefore it can allocate memory. static void launch_process_nofork(process_t *p) { ASSERT_IS_MAIN_THREAD(); ASSERT_IS_NOT_FORKED_CHILD(); null_terminated_array_t<char> argv_array; convert_wide_array_to_narrow(p->get_argv_array(), &argv_array); const char *const *envv = env_export_arr(); char *actual_cmd = wcs2str(p->actual_cmd); // Ensure the terminal modes are what they were before we changed them. restore_term_mode(); // Bounce to launch_process. This never returns. safe_launch_process(p, actual_cmd, argv_array.get(), envv); }
/// Make sure we cleanup before exiting if we're signaled. void signal_handler(int signo) { printf("\nExiting on receipt of signal #%d\n", signo); restore_term_mode(); exit(1); }
int main(int argc, char **argv) { int res = 1; int my_optind = 0; program_name = L"fish"; set_main_thread(); setup_fork_guards(); signal_unblock_all(); setlocale(LC_ALL, ""); fish_setlocale(); // struct stat tmp; // stat("----------FISH_HIT_MAIN----------", &tmp); if (!argv[0]) { static const char *dummy_argv[2] = {"fish", NULL}; argv = (char **)dummy_argv; //!OCLINT(parameter reassignment) argc = 1; //!OCLINT(parameter reassignment) } fish_cmd_opts_t opts; my_optind = fish_parse_opt(argc, argv, &opts); // No-exec is prohibited when in interactive mode. if (is_interactive_session && no_exec) { debug(1, _(L"Can not use the no-execute mode when running an interactive session")); no_exec = 0; } // Only save (and therefore restore) the fg process group if we are interactive. See issues // #197 and #1002. if (is_interactive_session) { save_term_foreground_process_group(); } const struct config_paths_t paths = determine_config_directory_paths(argv[0]); env_init(&paths); // Set features early in case other initialization depends on them. // Start with the ones set in the environment, then those set on the command line (so the // command line takes precedence). if (auto features_var = env_get(L"fish_features")) { for (const wcstring &s : features_var->as_list()) { mutable_fish_features().set_from_string(s); } } mutable_fish_features().set_from_string(opts.features); proc_init(); builtin_init(); misc_init(); reader_init(); parser_t &parser = parser_t::principal_parser(); const io_chain_t empty_ios; if (read_init(paths)) { // Stomp the exit status of any initialization commands (issue #635). proc_set_last_status(STATUS_CMD_OK); // Run post-config commands specified as arguments, if any. if (!opts.postconfig_cmds.empty()) { res = run_command_list(&opts.postconfig_cmds, empty_ios); } if (!opts.batch_cmds.empty()) { // Run the commands specified as arguments, if any. if (is_login) { // Do something nasty to support OpenSUSE assuming we're bash. This may modify cmds. fish_xdm_login_hack_hack_hack_hack(&opts.batch_cmds, argc - my_optind, argv + my_optind); } res = run_command_list(&opts.batch_cmds, empty_ios); reader_exit(0, 0); } else if (my_optind == argc) { // Implicitly interactive mode. res = reader_read(STDIN_FILENO, empty_ios); } else { char *file = *(argv + (my_optind++)); int fd = open(file, O_RDONLY); if (fd == -1) { perror(file); } else { // OK to not do this atomically since we cannot have gone multithreaded yet. set_cloexec(fd); wcstring_list_t list; for (char **ptr = argv + my_optind; *ptr; ptr++) { list.push_back(str2wcstring(*ptr)); } env_set(L"argv", ENV_DEFAULT, list); const wcstring rel_filename = str2wcstring(file); reader_push_current_filename(rel_filename.c_str()); res = reader_read(fd, empty_ios); if (res) { debug(1, _(L"Error while reading file %ls\n"), reader_current_filename() ? reader_current_filename() : _(L"Standard input")); } reader_pop_current_filename(); } } } int exit_status = res ? STATUS_CMD_UNKNOWN : proc_get_last_status(); // TODO: The generic process-exit event is useless and unused. // Remove this in future. proc_fire_event(L"PROCESS_EXIT", EVENT_EXIT, getpid(), exit_status); event_fire_generic(L"fish_exit"); restore_term_mode(); restore_term_foreground_process_group(); if (g_profiling_active) { parser.emit_profiling(s_profiling_output_filename); } history_save_all(); proc_destroy(); exit_without_destructors(exit_status); return EXIT_FAILURE; // above line should always exit }
int main(int argc, char **argv) { int res=1; int my_optind=0; set_main_thread(); setup_fork_guards(); wsetlocale(LC_ALL, L""); is_interactive_session=1; program_name=L"fish"; //struct stat tmp; //stat("----------FISH_HIT_MAIN----------", &tmp); std::vector<std::string> cmds; my_optind = fish_parse_opt(argc, argv, &cmds); /* No-exec is prohibited when in interactive mode */ if (is_interactive_session && no_exec) { debug(1, _(L"Can not use the no-execute mode when running an interactive session")); no_exec = 0; } /* Only save (and therefore restore) the fg process group if we are interactive. See #197, #1002 */ if (is_interactive_session) { save_term_foreground_process_group(); } const struct config_paths_t paths = determine_config_directory_paths(argv[0]); proc_init(); event_init(); wutil_init(); builtin_init(); function_init(); env_init(&paths); reader_init(); history_init(); /* For setcolor to support term256 in config.fish (#1022) */ update_fish_term256(); parser_t &parser = parser_t::principal_parser(); if (g_log_forks) printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count); const io_chain_t empty_ios; if (read_init(paths)) { /* Stop the exit status of any initialization commands (#635) */ proc_set_last_status(STATUS_BUILTIN_OK); /* Run the commands specified as arguments, if any */ if (! cmds.empty()) { /* Do something nasty to support OpenSUSE assuming we're bash. This may modify cmds. */ if (is_login) { fish_xdm_login_hack_hack_hack_hack(&cmds, argc - my_optind, argv + my_optind); } for (size_t i=0; i < cmds.size(); i++) { const wcstring cmd_wcs = str2wcstring(cmds.at(i)); res = parser.eval(cmd_wcs, empty_ios, TOP); } reader_exit(0, 0); } else { if (my_optind == argc) { res = reader_read(STDIN_FILENO, empty_ios); } else { char **ptr; char *file = *(argv+(my_optind++)); int i; int fd; if ((fd = open(file, O_RDONLY)) == -1) { wperror(L"open"); return 1; } // OK to not do this atomically since we cannot have gone multithreaded yet set_cloexec(fd); if (*(argv+my_optind)) { wcstring sb; for (i=1,ptr = argv+my_optind; *ptr; i++, ptr++) { if (i != 1) sb.append(ARRAY_SEP_STR); sb.append(str2wcstring(*ptr)); } env_set(L"argv", sb.c_str(), 0); } const wcstring rel_filename = str2wcstring(file); const wchar_t *abs_filename = wrealpath(rel_filename, NULL); if (!abs_filename) { abs_filename = wcsdup(rel_filename.c_str()); } reader_push_current_filename(intern(abs_filename)); free((void *)abs_filename); res = reader_read(fd, empty_ios); if (res) { debug(1, _(L"Error while reading file %ls\n"), reader_current_filename()?reader_current_filename(): _(L"Standard input")); } reader_pop_current_filename(); } } } proc_fire_event(L"PROCESS_EXIT", EVENT_EXIT, getpid(), res); restore_term_mode(); restore_term_foreground_process_group(); history_destroy(); proc_destroy(); builtin_destroy(); reader_destroy(); parser.destroy(); wutil_destroy(); event_destroy(); env_destroy(); if (g_log_forks) printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count); exit_without_destructors(res ? STATUS_UNKNOWN_COMMAND : proc_get_last_status()); return EXIT_FAILURE; //above line should always exit }
int main(int argc, char **argv) { int res = 1; int my_optind = 0; program_name = L"fish"; set_main_thread(); setup_fork_guards(); setlocale(LC_ALL, ""); fish_setlocale(); // struct stat tmp; // stat("----------FISH_HIT_MAIN----------", &tmp); if (!argv[0]) { static const char *dummy_argv[2] = {"fish", NULL}; argv = (char **)dummy_argv; //!OCLINT(parameter reassignment) argc = 1; //!OCLINT(parameter reassignment) } std::vector<std::string> cmds; my_optind = fish_parse_opt(argc, argv, &cmds); // No-exec is prohibited when in interactive mode. if (is_interactive_session && no_exec) { debug(1, _(L"Can not use the no-execute mode when running an interactive session")); no_exec = 0; } // Only save (and therefore restore) the fg process group if we are interactive. See issues // #197 and #1002. if (is_interactive_session) { save_term_foreground_process_group(); } const struct config_paths_t paths = determine_config_directory_paths(argv[0]); proc_init(); event_init(); builtin_init(); function_init(); env_init(&paths); reader_init(); history_init(); // For set_color to support term256 in config.fish (issue #1022). update_fish_color_support(); misc_init(); parser_t &parser = parser_t::principal_parser(); const io_chain_t empty_ios; if (read_init(paths)) { // Stomp the exit status of any initialization commands (issue #635). proc_set_last_status(STATUS_BUILTIN_OK); // Run the commands specified as arguments, if any. if (!cmds.empty()) { // Do something nasty to support OpenSUSE assuming we're bash. This may modify cmds. if (is_login) { fish_xdm_login_hack_hack_hack_hack(&cmds, argc - my_optind, argv + my_optind); } for (size_t i = 0; i < cmds.size(); i++) { const wcstring cmd_wcs = str2wcstring(cmds.at(i)); res = parser.eval(cmd_wcs, empty_ios, TOP); } reader_exit(0, 0); } else if (my_optind == argc) { // Interactive mode check_running_fishd(); res = reader_read(STDIN_FILENO, empty_ios); } else { char *file = *(argv + (my_optind++)); int fd = open(file, O_RDONLY); if (fd == -1) { perror(file); } else { // OK to not do this atomically since we cannot have gone multithreaded yet. set_cloexec(fd); if (*(argv + my_optind)) { wcstring sb; char **ptr; int i; for (i = 1, ptr = argv + my_optind; *ptr; i++, ptr++) { if (i != 1) sb.append(ARRAY_SEP_STR); sb.append(str2wcstring(*ptr)); } env_set(L"argv", sb.c_str(), 0); } const wcstring rel_filename = str2wcstring(file); reader_push_current_filename(rel_filename.c_str()); res = reader_read(fd, empty_ios); if (res) { debug(1, _(L"Error while reading file %ls\n"), reader_current_filename() ? reader_current_filename() : _(L"Standard input")); } reader_pop_current_filename(); } } } int exit_status = res ? STATUS_UNKNOWN_COMMAND : proc_get_last_status(); proc_fire_event(L"PROCESS_EXIT", EVENT_EXIT, getpid(), exit_status); restore_term_mode(); restore_term_foreground_process_group(); if (g_profiling_active) { parser.emit_profiling(s_profiling_output_filename); } history_destroy(); proc_destroy(); builtin_destroy(); reader_destroy(); event_destroy(); exit_without_destructors(exit_status); return EXIT_FAILURE; // above line should always exit }
int main (int argc, const char * argv[]) { struct termios saved_term_mode; /* saved entering terminal mode */ struct itimerval tbuf; /* interval timer structure */ struct sigaction action, nextAction; /* signal action structure */ struct sigaction temp; /* Used for swapping */ char input; /* The character input by user */ char* check; /* Used to check argv[1] */ if(argc != 2) { fprintf(stderr,"usage: %s <seconds>\n", argv[0]); exit(-1); } /* * Initialize ticks to 0. */ ticks = 1 + TICKS_PER_SECOND * (int)strtol(argv[1], &check, 10); if(*check != '\0') { /* an error probably occurred */ fprintf(stderr, "%s: malformed time.\n", argv[1]); fprintf(stderr,"usage: %s <seconds>\n", argv[0]); exit(-1); } if(ticks < 0) { fprintf(stderr, "Invalid time(%s). Must be >= 0.\n", argv[1]); fprintf(stderr,"usage: %s <seconds>\n", argv[0]); exit(-1); } /* * Set up the SIGALRM handler. */ action.sa_handler = tick; /* set tick to be the handler function */ sigemptyset(&action.sa_mask); /* clear out masked functions */ action.sa_flags = 0; /* no special handling */ nextAction = action; nextAction.sa_handler = SIG_IGN; /* * Use the sigaction function to associate the signal action with SIGALRM. */ if (sigaction(SIGALRM, &action, NULL) < 0 ) { perror("SIGALRM"); exit(-1); } /* * Define a 1/25 second timer. */ tbuf.it_interval.tv_sec = 0; tbuf.it_interval.tv_usec = MICROSEC / TICKS_PER_SECOND; tbuf.it_value.tv_sec = 1; tbuf.it_value.tv_usec = MICROSEC / TICKS_PER_SECOND; /* * Use the setitimer function to start the timer. */ if ( setitimer(ITIMER_REAL, &tbuf, NULL) == -1 ) { perror("setitimer"); exit(-1); /* should only fail for serious reasons */ } /* * Set the terminal to raw mode. */ saved_term_mode = set_raw_term_mode(); /* * Busy wait until the user types 'q'. */ while ((input = getchar()) != 'q') { if(ferror(stdin)) { clearerr(stdin); } else { switch (input) { case 'c': ticks = 0; redraw(); break; case 'r': /* Start/stop running the timer */ if (sigaction(SIGALRM, &nextAction, &action) < 0 ) { perror("SIGALRM"); exit(-1); } temp = nextAction; nextAction = action; action = temp; redraw(); break; case 'h': ticks += TICKS_PER_SECOND * 60 * 60; redraw(); break; case 'H': ticks -= TICKS_PER_SECOND * 60 * 60; redraw(); break; case 'm': ticks += TICKS_PER_SECOND * 60; redraw(); break; case 'M': ticks -= TICKS_PER_SECOND * 60; redraw(); break; case 's': ticks += TICKS_PER_SECOND; redraw(); break; case 'S': ticks -= TICKS_PER_SECOND; redraw(); break; case 't': tick(SIGALRM); break; default: /* Do nothing */ break; } } } /* * Restore the terminal to the mode it was in at program entry. */ restore_term_mode(saved_term_mode); return 0; }