Esempio n. 1
0
int main(int argc, char **argv)
{
    int res=1;
    int my_optind=0;

    set_main_thread();
    setup_fork_guards();

    wsetlocale(LC_ALL, L"");
    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();
    builtin_init();
    function_init();
    env_init(&paths);
    reader_init();
    history_init();
    /* For setcolor to support term256 in config.fish (#1022) */
    update_fish_color_support();

    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))
    {
        /* Stomp 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)
            {
                // Interactive mode
                check_running_fishd();
                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);

                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();

    if (g_log_forks)
        printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count);

    exit_without_destructors(exit_status);
    return EXIT_FAILURE; //above line should always exit
}
Esempio n. 2
0
int main(int argc, char **argv) {
    int res = 1;
    int my_optind = 0;

    // We can't do this at compile time due to the use of enum symbols.
    assert(EXPAND_SENTINAL >= EXPAND_RESERVED_BASE && EXPAND_SENTINAL <= EXPAND_RESERVED_END);
    assert(ANY_SENTINAL >= WILDCARD_RESERVED_BASE && ANY_SENTINAL <= WILDCARD_RESERVED_END);
    assert(R_SENTINAL >= INPUT_COMMON_BASE && R_SENTINAL <= INPUT_COMMON_END);

    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
}
Esempio n. 3
0
/**
  Parse the argument list, return the index of the first non-switch
  arguments.
 */
static int fish_parse_opt(int argc, char **argv, std::vector<std::string> *cmds)
{
    const struct option long_options[] =
    {
        { "command", required_argument, NULL, 'c' },
        { "debug-level", required_argument, NULL, 'd' },
        { "interactive", no_argument, NULL, 'i' } ,
        { "login", no_argument, NULL, 'l' },
        { "no-execute", no_argument, NULL, 'n' },
        { "profile", required_argument, NULL, 'p' },
        { "help", no_argument, NULL, 'h' },
        { "version", no_argument, NULL, 'v' },
        { NULL, 0, NULL, 0 }
    };

    while (1)
    {
        int opt = getopt_long(argc, argv, GETOPT_STRING, long_options, NULL);
        if (opt == -1)
            break;

        switch (opt)
        {
            case 0:
            {
                break;
            }

            case 'c':
            {
                cmds->push_back(optarg);
                break;
            }

            case 'd':
            {
                char *end;
                long tmp;

                errno = 0;
                tmp = strtol(optarg, &end, 10);

                if (tmp >= 0 && tmp <=10 && !*end && !errno)
                {
                    debug_level = (int)tmp;
                }
                else
                {
                    debug(0, _(L"Invalid value '%s' for debug level switch"), optarg);
                    exit_without_destructors(1);
                }
                break;
            }

            case 'h':
            {
                cmds->push_back("__fish_print_help fish");
                break;
            }

            case 'i':
            {
                is_interactive_session = 1;
                break;
            }

            case 'l':
            {
                is_login = 1;
                break;
            }

            case 'n':
            {
                no_exec = 1;
                break;
            }

            case 'p':
            {
                s_profiling_output_filename = optarg;
                g_profiling_active = true;
                break;
            }

            case 'v':
            {
                fwprintf(stderr, _(L"%s, version %s\n"), PACKAGE_NAME,
                         get_fish_version());
                exit_without_destructors(0);
            }

            default:
            {
                exit_without_destructors(1);
            }

        }
    }

    // If our command name begins with a dash that implies we're a login shell.
    is_login |= argv[0][0] == '-';

    // We are an interactive session if we have not been given an explicit
    // command or file to execute and stdin is a tty. Note that the -i or
    // --interactive options also force interactive mode.
    if (cmds->size() == 0 && optind == argc && isatty(STDIN_FILENO))
    {
        is_interactive_session = 1;
    }

    return optind;
}
Esempio n. 4
0
/**
   Connects to the fish socket and starts listening for connections
*/
static int get_socket(void)
{
    // Cygwin has random problems involving sockets. When using Cygwin,
    // allow 20 attempts at making socket correctly.
#ifdef __CYGWIN__
    int attempts = 0;
repeat:
    attempts += 1;
#endif

    int s, len, doexit = 0;
    int exitcode = EXIT_FAILURE;
    struct sockaddr_un local;
    const std::string sock_name = get_socket_filename();

    /*
       Start critical section protected by lock
    */
    std::string lockfile;
    if (! acquire_socket_lock(sock_name, &lockfile))
    {
        debug(0, L"Unable to obtain lock on socket, exiting");
        exit(EXIT_FAILURE);
    }
    debug(4, L"Acquired lockfile: %s", lockfile.c_str());

    local.sun_family = AF_UNIX;
    strcpy(local.sun_path, sock_name.c_str());
    len = sizeof(local);

    debug(1, L"Connect to socket at %s", sock_name.c_str());

    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
    {
        wperror(L"socket");
        doexit = 1;
        goto unlock;
    }

    /*
       First check whether the socket has been opened by another fishd;
       if so, exit with success status
    */
    if (connect(s, (struct sockaddr *)&local, len) == 0)
    {
        debug(1, L"Socket already exists, exiting");
        doexit = 1;
        exitcode = 0;
        goto unlock;
    }

    unlink(local.sun_path);
    if (bind(s, (struct sockaddr *)&local, len) == -1)
    {
        wperror(L"bind");
        doexit = 1;
        goto unlock;
    }

    if (make_fd_nonblocking(s) != 0)
    {
        wperror(L"fcntl");
        close(s);
        doexit = 1;
    }
    else if (listen(s, 64) == -1)
    {
        wperror(L"listen");
        doexit = 1;
    }

unlock:
    (void)unlink(lockfile.c_str());
    debug(4, L"Released lockfile: %s", lockfile.c_str());
    /*
       End critical section protected by lock
    */

    if (doexit)
    {
        // If Cygwin, only allow normal quit when made lots of attempts.
#ifdef __CYGWIN__
        if (exitcode && attempts < 20) goto repeat;
#endif
        exit_without_destructors(exitcode);
    }

    return s;
}