示例#1
0
/// 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();
}
示例#3
0
/// 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();
}
示例#4
0
/// 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);
}
示例#6
0
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
}
示例#7
0
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
}
示例#8
0
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
}
示例#9
0
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;
}