/* Configures environment variables before shellout. Should be used in pair * with cleanup_shellout_env(). */ static void setup_shellout_env(void) { const char *mount_file; const char *term_multiplexer_fmt; char *escaped_path; char *cmd; /* Need to use internal value instead of getcwd() for a symlink directory. */ env_set("PWD", curr_view->curr_dir); mount_file = fuse_get_mount_file(curr_view->curr_dir); if(mount_file == NULL) { env_remove(FUSE_FILE_ENVVAR); return; } env_set(FUSE_FILE_ENVVAR, mount_file); switch(curr_stats.term_multiplexer) { case TM_TMUX: term_multiplexer_fmt = "tmux set-environment %s %s"; break; case TM_SCREEN: term_multiplexer_fmt = "screen -X setenv %s %s"; break; default: return; } escaped_path = shell_like_escape(mount_file, 0); cmd = format_str(term_multiplexer_fmt, FUSE_FILE_ENVVAR, escaped_path); (void)vifm_system(cmd); free(cmd); free(escaped_path); }
void clear_variables(void) { int i; assert(initialized); /* free memory */ for(i = 0; i < nvars; i++) { if(vars[i].name == NULL) continue; if(vars[i].from_parent) { set_envvar(vars[i].name, vars[i].initial); } else { env_remove(vars[i].name); } free_record(&vars[i]); } nvars = 0; free(vars); vars = NULL; }
/** The set builtin. Creates, updates and erases environment variables and environemnt variable arrays. */ static int builtin_set( parser_t &parser, wchar_t **argv ) { /** Variables used for parsing the argument list */ static const struct woption long_options[] = { { L"export", no_argument, 0, 'x' } , { L"global", no_argument, 0, 'g' } , { L"local", no_argument, 0, 'l' } , { L"erase", no_argument, 0, 'e' } , { L"names", no_argument, 0, 'n' } , { L"unexport", no_argument, 0, 'u' } , { L"universal", no_argument, 0, 'U' } , { L"long", no_argument, 0, 'L' } , { L"query", no_argument, 0, 'q' } , { L"help", no_argument, 0, 'h' } , { 0, 0, 0, 0 } } ; const wchar_t *short_options = L"+xglenuULqh"; int argc = builtin_count_args(argv); /* Flags to set the work mode */ int local = 0, global = 0, exportv = 0; int erase = 0, list = 0, unexport=0; int universal = 0, query=0; bool shorten_ok = true; /* Variables used for performing the actual work */ wchar_t *dest = 0; int retcode=0; int scope; int slice=0; int i; wchar_t *bad_char; /* Parse options to obtain the requested operation and the modifiers */ woptind = 0; while (1) { int c = wgetopt_long(argc, argv, short_options, long_options, 0); if (c == -1) { break; } switch(c) { case 0: break; case 'e': erase = 1; break; case 'n': list = 1; break; case 'x': exportv = 1; break; case 'l': local = 1; break; case 'g': global = 1; break; case 'u': unexport = 1; break; case 'U': universal = 1; break; case 'L': shorten_ok = false; break; case 'q': query = 1; break; case 'h': builtin_print_help( parser, argv[0], stdout_buffer ); return 0; case '?': builtin_unknown_option( parser, argv[0], argv[woptind-1] ); return 1; default: break; } } /* Ok, all arguments have been parsed, let's validate them */ /* If we are checking the existance of a variable (-q) we can not also specify scope */ if( query && (erase || list) ) { append_format(stderr_buffer, BUILTIN_ERR_COMBO, argv[0] ); builtin_print_help( parser, argv[0], stderr_buffer ); return 1; } /* We can't both list and erase varaibles */ if( erase && list ) { append_format(stderr_buffer, BUILTIN_ERR_COMBO, argv[0] ); builtin_print_help( parser, argv[0], stderr_buffer ); return 1; } /* Variables can only have one scope */ if( local + global + universal > 1 ) { append_format(stderr_buffer, BUILTIN_ERR_GLOCAL, argv[0] ); builtin_print_help( parser, argv[0], stderr_buffer ); return 1; } /* Variables can only have one export status */ if( exportv && unexport ) { append_format(stderr_buffer, BUILTIN_ERR_EXPUNEXP, argv[0] ); builtin_print_help( parser, argv[0], stderr_buffer ); return 1; } /* Calculate the scope value for variable assignement */ scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (exportv ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL:0) | ENV_USER; if( query ) { /* Query mode. Return the number of variables that do not exist out of the specified variables. */ int i; for( i=woptind; i<argc; i++ ) { wchar_t *arg = argv[i]; int slice=0; if( !(dest = wcsdup(arg))) { DIE_MEM(); } if( wcschr( dest, L'[' ) ) { slice = 1; *wcschr( dest, L'[' )=0; } if( slice ) { std::vector<long> indexes; wcstring_list_t result; size_t j; env_var_t dest_str = env_get_string(dest); if (! dest_str.missing()) tokenize_variable_array( dest_str, result ); if( !parse_index( indexes, arg, dest, result.size() ) ) { builtin_print_help( parser, argv[0], stderr_buffer ); retcode = 1; break; } for( j=0; j < indexes.size() ; j++ ) { long idx = indexes[j]; if( idx < 1 || (size_t)idx > result.size() ) { retcode++; } } } else { if( !env_exist( arg, scope ) ) { retcode++; } } free( dest ); } return retcode; } if( list ) { /* Maybe we should issue an error if there are any other arguments? */ print_variables(0, 0, shorten_ok, scope); return 0; } if( woptind == argc ) { /* Print values of variables */ if( erase ) { append_format(stderr_buffer, _(L"%ls: Erase needs a variable name\n"), argv[0] ); builtin_print_help( parser, argv[0], stderr_buffer ); retcode = 1; } else { print_variables( 1, 1, shorten_ok, scope ); } return retcode; } if( !(dest = wcsdup(argv[woptind]))) { DIE_MEM(); } if( wcschr( dest, L'[' ) ) { slice = 1; *wcschr( dest, L'[' )=0; } if( !wcslen( dest ) ) { free( dest ); append_format(stderr_buffer, BUILTIN_ERR_VARNAME_ZERO, argv[0] ); builtin_print_help( parser, argv[0], stderr_buffer ); return 1; } if( (bad_char = wcsvarname( dest ) ) ) { append_format(stderr_buffer, BUILTIN_ERR_VARCHAR, argv[0], *bad_char ); builtin_print_help( parser, argv[0], stderr_buffer ); free( dest ); return 1; } if( slice && erase && (scope != ENV_USER) ) { free( dest ); append_format(stderr_buffer, _(L"%ls: Can not specify scope when erasing array slice\n"), argv[0] ); builtin_print_help( parser, argv[0], stderr_buffer ); return 1; } /* set assignment can work in two modes, either using slices or using the whole array. We detect which mode is used here. */ if( slice ) { /* Slice mode */ int idx_count, val_count; wcstring_list_t values; std::vector<long> indexes; wcstring_list_t result; const env_var_t dest_str = env_get_string(dest); if (! dest_str.missing()) tokenize_variable_array( dest_str, result ); for( ; woptind<argc; woptind++ ) { if( !parse_index( indexes, argv[woptind], dest, result.size() ) ) { builtin_print_help( parser, argv[0], stderr_buffer ); retcode = 1; break; } val_count = argc-woptind-1; idx_count = indexes.size(); if( !erase ) { if( val_count < idx_count ) { append_format(stderr_buffer, _(BUILTIN_SET_ARG_COUNT), argv[0] ); builtin_print_help( parser, argv[0], stderr_buffer ); retcode=1; break; } if( val_count == idx_count ) { woptind++; break; } } } if( !retcode ) { /* Slice indexes have been calculated, do the actual work */ if( erase ) { erase_values(result, indexes); my_env_set( dest, result, scope); } else { wcstring_list_t value; // al_init(&value); while( woptind < argc ) { value.push_back( argv[woptind++] ); } if( update_values( result, indexes, value ) ) { append_format(stderr_buffer, L"%ls: ", argv[0] ); append_format(stderr_buffer, ARRAY_BOUNDS_ERR ); stderr_buffer.push_back(L'\n'); } my_env_set(dest, result, scope); // al_destroy( &value ); } } // al_foreach( &result, &free ); // al_destroy( &result ); // al_destroy(&indexes); // al_destroy(&values); } else { woptind++; /* No slicing */ if( erase ) { if( woptind != argc ) { append_format(stderr_buffer, _(L"%ls: Values cannot be specfied with erase\n"), argv[0] ); builtin_print_help( parser, argv[0], stderr_buffer ); retcode=1; } else { retcode = env_remove( dest, scope ); } } else { wcstring_list_t val; for( i=woptind; i<argc; i++ ) val.push_back(argv[i]); retcode = my_env_set( dest, val, scope ); } } free( dest ); return retcode; }
int unlet_variables(const char *cmd) { int error = 0; assert(initialized); while(*cmd != '\0') { envvar_t *record; char name[VAR_NAME_MAX + 1]; char *p; int envvar = 1; /* check if its environment variable */ if(*cmd != '$') envvar = 0; else cmd++; /* copy variable name */ p = name; while(*cmd != '\0' && char_is_one_of(ENV_VAR_NAME_CHARS, *cmd) && p - name < sizeof(name) - 1) *p++ = *cmd++; *p = '\0'; if(*cmd != '\0' && !isspace(*cmd)) { text_buffer_add("Trailing characters"); error++; break; } cmd = skip_whitespace(cmd); /* currently we support only environment variables */ if(!envvar) { text_buffer_addf("%s: %s", "Unsupported variable type", name); cmd = skip_non_whitespace(cmd); error++; continue; } /* test for empty variable name */ if(name[0] == '\0') { text_buffer_addf("%s: %s", "Unsupported variable name", "empty name"); error++; continue; } record = find_record(name); if(record == NULL || record->removed) { text_buffer_addf("%s: %s", "No such variable", name); error++; continue; } if(record->from_parent) record->removed = 1; else free_record(record); env_remove(name); } return error; }
static void client_connected(struct master_service_connection *conn) { enum mail_storage_service_flags flags = MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS; string_t *instr, *keys; const char **args, *key, *value, *error, *version_line, *data_line; struct mail_storage_service_ctx *service_ctx; struct mail_storage_service_input input; struct mail_storage_service_user *user; char buf[1024]; unsigned int i, socket_count; int fd = -1; ssize_t ret; alarm(SCRIPT_LOGIN_READ_TIMEOUT_SECS); net_set_nonblock(conn->fd, FALSE); instr = t_str_new(1024); ret = fd_read(conn->fd, buf, sizeof(buf), &fd); while (ret > 0) { str_append_n(instr, buf, ret); if (buf[ret-1] == '\n' && strchr(str_c(instr), '\n')[1] != '\0') { str_truncate(instr, str_len(instr)-1); break; } ret = read(conn->fd, buf, sizeof(buf)); } version_line = str_c(instr); data_line = strchr(version_line, '\n'); if (data_line != NULL) version_line = t_strdup_until(version_line, data_line++); else version_line = NULL; if (ret > 0 || version_line != NULL) { if (version_line == NULL || !version_string_verify(version_line, "script-login", SCRIPT_LOGIN_PROTOCOL_VERSION_MAJOR)) { i_fatal("Client not compatible with this binary " "(connecting to wrong socket?)"); } } if (ret <= 0) { if (ret < 0) i_fatal("read() failed: %m"); else i_fatal("read() failed: disconnected"); } if (fd == -1) i_fatal("client fd not received"); alarm(0); /* put everything to environment */ env_clean(); keys = t_str_new(256); args = t_strsplit_tab(data_line); if (str_array_length(args) < 3) i_fatal("Missing input fields"); i = 0; memset(&input, 0, sizeof(input)); input.module = "mail"; /* need to get mail_uid, mail_gid */ input.service = "script-login"; (void)net_addr2ip(args[i++], &input.local_ip); (void)net_addr2ip(args[i++], &input.remote_ip); input.username = args[i++]; input.userdb_fields = args + i; env_put(t_strconcat("LOCAL_IP=", net_ip2addr(&input.local_ip), NULL)); env_put(t_strconcat("IP=", net_ip2addr(&input.remote_ip), NULL)); env_put(t_strconcat("USER="******"%s ", key); } } env_put(t_strconcat(ENV_USERDB_KEYS"=", str_c(keys), NULL)); master_service_init_log(master_service, t_strdup_printf("script-login(%s): ", input.username)); if (drop_to_userdb_privileges) { service_ctx = mail_storage_service_init(master_service, NULL, flags); if (mail_storage_service_lookup(service_ctx, &input, &user, &error) <= 0) i_fatal("%s", error); mail_storage_service_restrict_setenv(service_ctx, user); /* we can't exec anything in a chroot */ env_remove("RESTRICT_CHROOT"); restrict_access_by_env(getenv("HOME"), TRUE); } if (dup2(fd, STDIN_FILENO) < 0) i_fatal("dup2() failed: %m"); if (dup2(fd, STDOUT_FILENO) < 0) i_fatal("dup2() failed: %m"); if (close(fd) < 0) i_fatal("close() failed: %m"); if (conn->fd != SCRIPT_COMM_FD) { if (dup2(conn->fd, SCRIPT_COMM_FD) < 0) i_fatal("dup2() failed: %m"); if (close(conn->fd) < 0) i_fatal("close() failed: %m"); } /* close all listener sockets */ socket_count = master_service_get_socket_count(master_service); for (i = 0; i < socket_count; i++) { if (close(MASTER_LISTEN_FD_FIRST + i) < 0) i_error("close(listener) failed: %m"); } if (close(MASTER_STATUS_FD) < 0) i_error("close(status) failed: %m"); execvp_const(exec_args[0], exec_args); }
int unlet_variables(const char *cmd) { int error = 0; assert(initialized); while(*cmd != '\0') { var_t *record; char name[VAR_NAME_MAX + 1]; char *p; int envvar = 1; /* check if its environment variable */ if(*cmd != '$') envvar = 0; else cmd++; /* copy variable name */ p = name; while(*cmd != '\0' && !isspace(*cmd) && *cmd != '=' && p - name < sizeof(name) - 1) *p++ = *cmd++; *p = '\0'; /* skip spaces */ while(isspace(*cmd)) cmd++; /* currently we support only environment variables */ if(!envvar) { print_msg(1, "Unsupported variable type", name); /* skip non-spaces */ while(*cmd != '\0' && !isspace(*cmd)) cmd++; error++; continue; } /* test for empty variable name */ if(name[0] == '\0') { print_msg(1, "Unsupported variable name", "empty name"); error++; continue; } record = find_record(name); if(record == NULL || record->removed) { print_msg(1, "No such variable", name); error++; continue; } if(record->from_parent) record->removed = 1; else free_record(record); env_remove(name); } return error; }
static void setup(void) { env_remove(VAR_NAME); }
/// The set builtin creates, updates, and erases (removes, deletes) variables. int builtin_set(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); // Flags to set the work mode. int local = 0, global = 0, exportv = 0; int erase = 0, list = 0, unexport = 0; int universal = 0, query = 0; bool shorten_ok = true; bool preserve_failure_exit_status = true; const int incoming_exit_status = proc_get_last_status(); // Variables used for performing the actual work. wchar_t *dest = NULL; int retcode = STATUS_CMD_OK; int scope; int slice = 0; // Variables used for parsing the argument list. This command is atypical in using the "+" // (REQUIRE_ORDER) option for flag parsing. This is not typical of most fish commands. It means // we stop scanning for flags when the first non-flag argument is seen. static const wchar_t *short_options = L"+LUeghlnqux"; static const struct woption long_options[] = {{L"export", no_argument, NULL, 'x'}, {L"global", no_argument, NULL, 'g'}, {L"local", no_argument, NULL, 'l'}, {L"erase", no_argument, NULL, 'e'}, {L"names", no_argument, NULL, 'n'}, {L"unexport", no_argument, NULL, 'u'}, {L"universal", no_argument, NULL, 'U'}, {L"long", no_argument, NULL, 'L'}, {L"query", no_argument, NULL, 'q'}, {L"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}}; // Parse options to obtain the requested operation and the modifiers. int opt; wgetopter_t w; while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, NULL)) != -1) { switch (opt) { case 'e': { erase = 1; preserve_failure_exit_status = false; break; } case 'n': { list = 1; preserve_failure_exit_status = false; break; } case 'x': { exportv = 1; break; } case 'l': { local = 1; break; } case 'g': { global = 1; break; } case 'u': { unexport = 1; break; } case 'U': { universal = 1; break; } case 'L': { shorten_ok = false; break; } case 'q': { query = 1; preserve_failure_exit_status = false; break; } case 'h': { builtin_print_help(parser, streams, cmd, streams.out); return STATUS_CMD_OK; } case '?': { builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { DIE("unexpected retval from wgetopt_long"); break; } } } // Ok, all arguments have been parsed, let's validate them. If we are checking the existance of // a variable (-q) we can not also specify scope. if (query && (erase || list)) { streams.err.append_format(BUILTIN_ERR_COMBO, cmd); builtin_print_help(parser, streams, cmd, streams.err); return STATUS_INVALID_ARGS; } // We can't both list and erase variables. if (erase && list) { streams.err.append_format(BUILTIN_ERR_COMBO, cmd); builtin_print_help(parser, streams, cmd, streams.err); return STATUS_INVALID_ARGS; } // Variables can only have one scope. if (local + global + universal > 1) { streams.err.append_format(BUILTIN_ERR_GLOCAL, cmd); builtin_print_help(parser, streams, cmd, streams.err); return STATUS_INVALID_ARGS; } // Variables can only have one export status. if (exportv && unexport) { streams.err.append_format(BUILTIN_ERR_EXPUNEXP, argv[0]); builtin_print_help(parser, streams, cmd, streams.err); return STATUS_INVALID_ARGS; } // Calculate the scope value for variable assignement. scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (exportv ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL : 0) | ENV_USER; if (query) { // Query mode. Return the number of variables that do not exist out of the specified // variables. int i; for (i = w.woptind; i < argc; i++) { wchar_t *arg = argv[i]; int slice = 0; dest = wcsdup(arg); assert(dest); if (wcschr(dest, L'[')) { slice = 1; *wcschr(dest, L'[') = 0; } if (slice) { std::vector<long> indexes; wcstring_list_t result; size_t j; env_var_t dest_str = env_get_string(dest, scope); if (!dest_str.missing()) tokenize_variable_array(dest_str, result); if (!parse_index(indexes, arg, dest, result.size(), streams)) { builtin_print_help(parser, streams, cmd, streams.err); retcode = 1; break; } for (j = 0; j < indexes.size(); j++) { long idx = indexes[j]; if (idx < 1 || (size_t)idx > result.size()) { retcode++; } } } else { if (!env_exist(arg, scope)) { retcode++; } } free(dest); } return retcode; } if (list) { // Maybe we should issue an error if there are any other arguments? print_variables(0, 0, shorten_ok, scope, streams); return STATUS_CMD_OK; } if (w.woptind == argc) { // Print values of variables. if (erase) { streams.err.append_format(_(L"%ls: Erase needs a variable name\n"), cmd); builtin_print_help(parser, streams, cmd, streams.err); retcode = STATUS_INVALID_ARGS; } else { print_variables(1, 1, shorten_ok, scope, streams); } return retcode; } dest = wcsdup(argv[w.woptind]); assert(dest); if (wcschr(dest, L'[')) { slice = 1; *wcschr(dest, L'[') = 0; } if (!valid_var_name(dest)) { streams.err.append_format(BUILTIN_ERR_VARNAME, cmd, dest); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_INVALID_ARGS; } // Set assignment can work in two modes, either using slices or using the whole array. We detect // which mode is used here. if (slice) { // Slice mode. std::vector<long> indexes; wcstring_list_t result; const env_var_t dest_str = env_get_string(dest, scope); if (!dest_str.missing()) { tokenize_variable_array(dest_str, result); } else if (erase) { retcode = 1; } if (!retcode) { for (; w.woptind < argc; w.woptind++) { if (!parse_index(indexes, argv[w.woptind], dest, result.size(), streams)) { builtin_print_help(parser, streams, argv[0], streams.err); retcode = 1; break; } size_t idx_count = indexes.size(); size_t val_count = argc - w.woptind - 1; if (!erase) { if (val_count < idx_count) { streams.err.append_format(_(BUILTIN_SET_ARG_COUNT), argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); retcode = 1; break; } if (val_count == idx_count) { w.woptind++; break; } } } } if (!retcode) { // Slice indexes have been calculated, do the actual work. if (erase) { erase_values(result, indexes); my_env_set(dest, result, scope, streams); } else { wcstring_list_t value; while (w.woptind < argc) { value.push_back(argv[w.woptind++]); } if (update_values(result, indexes, value)) { streams.err.append_format(L"%ls: ", argv[0]); streams.err.append_format(ARRAY_BOUNDS_ERR); streams.err.push_back(L'\n'); } my_env_set(dest, result, scope, streams); } } } else { w.woptind++; // No slicing. if (erase) { if (w.woptind != argc) { streams.err.append_format(_(L"%ls: Values cannot be specfied with erase\n"), argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); retcode = 1; } else { retcode = env_remove(dest, scope); } } else { wcstring_list_t val; for (int i = w.woptind; i < argc; i++) val.push_back(argv[i]); retcode = my_env_set(dest, val, scope, streams); } } // Check if we are setting variables above the effective scope. See // https://github.com/fish-shell/fish-shell/issues/806 env_var_t global_dest = env_get_string(dest, ENV_GLOBAL); if (universal && !global_dest.missing()) { streams.err.append_format( _(L"%ls: Warning: universal scope selected, but a global variable '%ls' exists.\n"), L"set", dest); } free(dest); if (retcode == STATUS_CMD_OK && preserve_failure_exit_status) retcode = incoming_exit_status; return retcode; }
SETUP() { env_remove(VAR_A); env_remove(VAR_B); }