void env_init(const struct config_paths_t *paths /* or NULL */) { /* env_read_only variables can not be altered directly by the user */ const wchar_t * const ro_keys[] = { L"status", L"history", L"version", L"_", L"LINES", L"COLUMNS", L"PWD", //L"SHLVL", // will be inserted a bit lower down L"FISH_VERSION", }; for (size_t i=0; i < sizeof ro_keys / sizeof *ro_keys; i++) { env_read_only.insert(ro_keys[i]); } /* Names of all dynamically calculated variables */ env_electric.insert(L"history"); env_electric.insert(L"status"); env_electric.insert(L"umask"); env_electric.insert(L"COLUMNS"); env_electric.insert(L"LINES"); top = new env_node_t; global_env = top; global = &top->env; /* Now the environemnt variable handling is set up, the next step is to insert valid data */ /* Import environment variables */ for (char **p = (environ ? environ : __environ); p && *p; p++) { const wcstring key_and_val = str2wcstring(*p); //like foo=bar size_t eql = key_and_val.find(L'='); if (eql == wcstring::npos) { // no equals found if (is_read_only(key_and_val) || is_electric(key_and_val)) continue; env_set(key_and_val, L"", ENV_EXPORT | ENV_GLOBAL); } else { wcstring key = key_and_val.substr(0, eql); if (is_read_only(key) || is_electric(key)) continue; wcstring val = key_and_val.substr(eql + 1); if (variable_is_colon_delimited_array(key)) { std::replace(val.begin(), val.end(), L':', ARRAY_SEP); } env_set(key, val.c_str(), ENV_EXPORT | ENV_GLOBAL); } } /* Set the given paths in the environment, if we have any */ if (paths != NULL) { env_set(FISH_DATADIR_VAR, paths->data.c_str(), ENV_GLOBAL); env_set(FISH_SYSCONFDIR_VAR, paths->sysconf.c_str(), ENV_GLOBAL); env_set(FISH_HELPDIR_VAR, paths->doc.c_str(), ENV_GLOBAL); env_set(FISH_BIN_DIR, paths->bin.c_str(), ENV_GLOBAL); } /* Set up the PATH variable */ setup_path(); /* Set up the USER variable */ if (env_get_string(L"USER").missing_or_empty()) { const struct passwd *pw = getpwuid(getuid()); if (pw && pw->pw_name) { const wcstring uname = str2wcstring(pw->pw_name); env_set(L"USER", uname.c_str(), ENV_GLOBAL | ENV_EXPORT); } } /* Set up the version variables */ wcstring version = str2wcstring(get_fish_version()); env_set(L"version", version.c_str(), ENV_GLOBAL); env_set(L"FISH_VERSION", version.c_str(), ENV_GLOBAL); /* Set up SHLVL variable */ const env_var_t shlvl_str = env_get_string(L"SHLVL"); wcstring nshlvl_str = L"1"; if (! shlvl_str.missing()) { wchar_t *end; long shlvl_i = wcstol(shlvl_str.c_str(), &end, 10); while (iswspace(*end)) ++end; /* skip trailing whitespace */ if (shlvl_i >= 0 && *end == '\0') { nshlvl_str = to_string<long>(shlvl_i + 1); } } env_set(L"SHLVL", nshlvl_str.c_str(), ENV_GLOBAL | ENV_EXPORT); env_read_only.insert(L"SHLVL"); /* Set up the HOME variable */ if (env_get_string(L"HOME").missing_or_empty()) { const env_var_t unam = env_get_string(L"USER"); char *unam_narrow = wcs2str(unam.c_str()); struct passwd *pw = getpwnam(unam_narrow); if (pw->pw_dir != NULL) { const wcstring dir = str2wcstring(pw->pw_dir); env_set(L"HOME", dir.c_str(), ENV_GLOBAL | ENV_EXPORT); } free(unam_narrow); } /* Set PWD */ env_set_pwd(); /* Set up universal variables. The empty string means to use the deafult path. */ assert(s_universal_variables == NULL); s_universal_variables = new env_universal_t(L""); s_universal_variables->load(); /* Set g_log_forks */ env_var_t log_forks = env_get_string(L"fish_log_forks"); g_log_forks = ! log_forks.missing_or_empty() && from_string<bool>(log_forks); /* Set g_use_posix_spawn. Default to true. */ env_var_t use_posix_spawn = env_get_string(L"fish_use_posix_spawn"); g_use_posix_spawn = (use_posix_spawn.missing_or_empty() ? true : from_string<bool>(use_posix_spawn)); /* Set fish_bind_mode to "default" */ env_set(FISH_BIND_MODE_VAR, DEFAULT_BIND_MODE, ENV_GLOBAL); /* Now that the global scope is fully initialized, add a toplevel local scope. This same local scope will persist throughout the lifetime of the fish process, and it will ensure that `set -l` commands run at the command-line don't affect the global scope. */ env_push(false); }
int main(int argc, char *argv[]) { program_name = L"fish_indent"; set_main_thread(); setup_fork_guards(); // Using the user's default locale could be a problem if it doesn't use UTF-8 encoding. That's // because the fish project assumes Unicode UTF-8 encoding in all of its scripts. // // TODO: Auto-detect the encoding of the script. We should look for a vim style comment // (e.g., "# vim: set fileencoding=<encoding-name>:") or an emacs style comment // (e.g., "# -*- coding: <encoding-name> -*-"). setlocale(LC_ALL, ""); env_init(); // Types of output we support. enum { output_type_plain_text, output_type_file, output_type_ansi, output_type_html } output_type = output_type_plain_text; const char *output_location = ""; bool do_indent = true; const char *short_opts = "+d:hvwiD:"; const struct option long_opts[] = {{"debug-level", required_argument, NULL, 'd'}, {"debug-stack-frames", required_argument, NULL, 'D'}, {"dump-parse-tree", no_argument, NULL, 'P'}, {"no-indent", no_argument, NULL, 'i'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {"write", no_argument, NULL, 'w'}, {"html", no_argument, NULL, 1}, {"ansi", no_argument, NULL, 2}, {NULL, 0, NULL, 0}}; int opt; while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { switch (opt) { case 'P': { dump_parse_tree = true; break; } case 'h': { print_help("fish_indent", 1); exit(0); break; } case 'v': { fwprintf(stderr, _(L"%ls, version %s\n"), program_name, get_fish_version()); exit(0); break; } case 'w': { output_type = output_type_file; break; } case 'i': { do_indent = false; break; } case 1: { output_type = output_type_html; break; } case 2: { output_type = output_type_ansi; 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 { fwprintf(stderr, _(L"Invalid value '%s' for debug-level flag"), optarg); exit(1); } break; } case 'D': { char *end; long tmp; errno = 0; tmp = strtol(optarg, &end, 10); if (tmp > 0 && tmp <= 128 && !*end && !errno) { debug_stack_frames = (int)tmp; } else { fwprintf(stderr, _(L"Invalid value '%s' for debug-stack-frames flag"), optarg); exit(1); } break; } default: { // We assume getopt_long() has already emitted a diagnostic msg. exit(1); break; } } } argc -= optind; argv += optind; wcstring src; if (argc == 0) { if (output_type == output_type_file) { fwprintf(stderr, _(L"Expected file path to read/write for -w:\n\n $ %ls -w foo.fish\n"), program_name); exit(1); } src = read_file(stdin); } else if (argc == 1) { FILE *fh = fopen(*argv, "r"); if (fh) { src = read_file(fh); fclose(fh); output_location = *argv; } else { fwprintf(stderr, _(L"Opening \"%s\" failed: %s\n"), *argv, strerror(errno)); exit(1); } } else { fwprintf(stderr, _(L"Too many arguments\n")); exit(1); } const wcstring output_wtext = prettify(src, do_indent); // Maybe colorize. std::vector<highlight_spec_t> colors; if (output_type != output_type_plain_text) { highlight_shell_no_io(output_wtext, colors, output_wtext.size(), NULL, env_vars_snapshot_t::current()); } std::string colored_output; switch (output_type) { case output_type_plain_text: { colored_output = no_colorize(output_wtext); break; } case output_type_file: { FILE *fh = fopen(output_location, "w"); if (fh) { fputws(output_wtext.c_str(), fh); fclose(fh); exit(0); } else { fwprintf(stderr, _(L"Opening \"%s\" failed: %s\n"), output_location, strerror(errno)); exit(1); } break; } case output_type_ansi: { colored_output = ansi_colorize(output_wtext, colors); break; } case output_type_html: { colored_output = html_colorize(output_wtext, colors); break; } } fputws(str2wcstring(colored_output).c_str(), stdout); return 0; }
/// Parse the argument list, return the index of the first non-flag arguments. static int fish_parse_opt(int argc, char **argv, std::vector<std::string> *cmds) { const char *short_opts = "+hilnvc:p:d:D:"; const struct option long_opts[] = {{"command", required_argument, NULL, 'c'}, {"debug-level", required_argument, NULL, 'd'}, {"debug-stack-frames", 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}}; int opt; while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { switch (opt) { case 0: { fwprintf(stderr, _(L"getopt_long() unexpectedly returned zero\n")); exit(127); 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 { fwprintf(stderr, _(L"Invalid value '%s' for debug-level flag"), optarg); exit(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(stdout, _(L"%s, version %s\n"), PACKAGE_NAME, get_fish_version()); exit(0); break; } case 'D': { char *end; long tmp; errno = 0; tmp = strtol(optarg, &end, 10); if (tmp > 0 && tmp <= 128 && !*end && !errno) { debug_stack_frames = (int)tmp; } else { fwprintf(stderr, _(L"Invalid value '%s' for debug-stack-frames flag"), optarg); exit(1); } break; } default: { // We assume getopt_long() has already emitted a diagnostic msg. exit(1); break; } } } // 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; }
void env_init(const struct config_paths_t *paths /* or NULL */) { /* env_read_only variables can not be altered directly by the user */ const wchar_t * const ro_keys[] = { L"status", L"history", L"version", L"_", L"LINES", L"COLUMNS", L"PWD", L"SHLVL", L"FISH_VERSION", }; for (size_t i=0; i < sizeof ro_keys / sizeof *ro_keys; i++) { env_read_only.insert(ro_keys[i]); } /* HOME and USER should be writeable by root, since this can be a convenient way to install software. */ if (getuid() != 0) { env_read_only.insert(L"HOME"); env_read_only.insert(L"USER"); } /* Names of all dynamically calculated variables */ env_electric.insert(L"history"); env_electric.insert(L"status"); env_electric.insert(L"umask"); top = new env_node_t; global_env = top; global = &top->env; /* Now the environemnt variable handling is set up, the next step is to insert valid data */ /* Import environment variables */ for (char **p = (environ ? environ : __environ); p && *p; p++) { const wcstring key_and_val = str2wcstring(*p); //like foo=bar size_t eql = key_and_val.find(L'='); if (eql == wcstring::npos) { // no equals found env_set(key_and_val, L"", ENV_EXPORT); } else { wcstring key = key_and_val.substr(0, eql); wcstring val = key_and_val.substr(eql + 1); if (variable_can_be_array(val)) { std::replace(val.begin(), val.end(), L':', ARRAY_SEP); } env_set(key, val.c_str(), ENV_EXPORT | ENV_GLOBAL); } } /* Set the given paths in the environment, if we have any */ if (paths != NULL) { env_set(FISH_DATADIR_VAR, paths->data.c_str(), ENV_GLOBAL | ENV_EXPORT); env_set(FISH_SYSCONFDIR_VAR, paths->sysconf.c_str(), ENV_GLOBAL | ENV_EXPORT); env_set(FISH_HELPDIR_VAR, paths->doc.c_str(), ENV_GLOBAL | ENV_EXPORT); env_set(FISH_BIN_DIR, paths->bin.c_str(), ENV_GLOBAL | ENV_EXPORT); } /* Set up the PATH variable */ setup_path(); /* Set up the USER variable */ const struct passwd *pw = getpwuid(getuid()); if (pw && pw->pw_name) { const wcstring uname = str2wcstring(pw->pw_name); env_set(L"USER", uname.c_str(), ENV_GLOBAL | ENV_EXPORT); } /* Set up the version variables */ wcstring version = str2wcstring(get_fish_version()); env_set(L"version", version.c_str(), ENV_GLOBAL); env_set(L"FISH_VERSION", version.c_str(), ENV_GLOBAL); /* Set up universal variables. The empty string means to use the deafult path. */ assert(s_universal_variables == NULL); s_universal_variables = new env_universal_t(L""); /* Set up SHLVL variable */ const env_var_t shlvl_str = env_get_string(L"SHLVL"); wcstring nshlvl_str = L"1"; if (! shlvl_str.missing()) { long shlvl_i = wcstol(shlvl_str.c_str(), NULL, 10); if (shlvl_i >= 0) { nshlvl_str = to_string<long>(shlvl_i + 1); } } env_set(L"SHLVL", nshlvl_str.c_str(), ENV_GLOBAL | ENV_EXPORT); /* Set correct defaults for e.g. USER and HOME variables */ env_set_defaults(); /* Set g_log_forks */ env_var_t log_forks = env_get_string(L"fish_log_forks"); g_log_forks = ! log_forks.missing_or_empty() && from_string<bool>(log_forks); /* Set g_use_posix_spawn. Default to true. */ env_var_t use_posix_spawn = env_get_string(L"fish_use_posix_spawn"); g_use_posix_spawn = (use_posix_spawn.missing_or_empty() ? true : from_string<bool>(use_posix_spawn)); /* Set fish_bind_mode to "default" */ env_set(FISH_BIND_MODE_VAR, DEFAULT_BIND_MODE, ENV_GLOBAL); }
/** 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> *out_cmds) { int my_optind; int force_interactive=0; bool has_cmd = false; while (1) { static struct option long_options[] = { { "command", required_argument, 0, 'c' }, { "debug-level", required_argument, 0, 'd' }, { "interactive", no_argument, 0, 'i' } , { "login", no_argument, 0, 'l' }, { "no-execute", no_argument, 0, 'n' }, { "profile", required_argument, 0, 'p' }, { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'v' }, { 0, 0, 0, 0 } } ; int opt_index = 0; int opt = getopt_long(argc, argv, GETOPT_STRING, long_options, &opt_index); if (opt == -1) break; switch (opt) { case 0: { break; } case 'c': { out_cmds->push_back(optarg ? optarg : ""); has_cmd = true; is_interactive_session = 0; 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': { out_cmds->push_back("__fish_print_help fish"); has_cmd = true; break; } case 'i': { force_interactive = 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); } case '?': { exit_without_destructors(1); } } } my_optind = optind; is_login |= (strcmp(argv[0], "-fish") == 0); /* We are an interactive session if we are either forced, or have not been given an explicit command to execute and stdin is a tty. */ if (force_interactive) { is_interactive_session = true; } else if (is_interactive_session) { is_interactive_session = ! has_cmd && (my_optind == argc) && isatty(STDIN_FILENO); } return my_optind; }
int main(int argc, char *argv[]) { set_main_thread(); setup_fork_guards(); wsetlocale(LC_ALL, L""); program_name=L"fish_indent"; env_init(); input_init(); /* Types of output we support */ enum { output_type_plain_text, output_type_ansi, output_type_html } output_type = output_type_plain_text; bool do_indent = true; const char *short_opts = "+dhvi"; const struct option long_opts[] = { { "dump", no_argument, NULL, 'd' }, { "no-indent", no_argument, NULL, 'i' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "html", no_argument, NULL, 1 }, { "ansi", no_argument, NULL, 2 }, { NULL, 0, NULL, 0 } }; int opt; while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { switch (opt) { case 0: { fwprintf(stderr, _(L"getopt_long() unexpectedly returned zero\n")); exit_without_destructors(127); } case 'd': { dump_parse_tree = true; break; } case 'h': { print_help("fish_indent", 1); exit_without_destructors(0); } case 'v': { fwprintf(stderr, _(L"%ls, version %s\n"), program_name, get_fish_version()); exit(0); assert(0 && "Unreachable code reached"); break; } case 'i': { do_indent = false; break; } case 1: { output_type = output_type_html; break; } case 2: { output_type = output_type_ansi; break; } default: { // We assume getopt_long() has already emitted a diagnostic msg. exit_without_destructors(1); } } } const wcstring src = read_file(stdin); const wcstring output_wtext = prettify(src, do_indent); /* Maybe colorize */ std::vector<highlight_spec_t> colors; if (output_type != output_type_plain_text) { highlight_shell_no_io(output_wtext, colors, output_wtext.size(), NULL, env_vars_snapshot_t::current()); } std::string colored_output; switch (output_type) { case output_type_plain_text: colored_output = no_colorize(output_wtext); break; case output_type_ansi: colored_output = ansi_colorize(output_wtext, colors); break; case output_type_html: colored_output = html_colorize(output_wtext, colors); break; } fputs(colored_output.c_str(), stdout); return 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; }