📄 variables.c
字号:
/* Find out if we're supposed to be in Posix.2 mode via an environment variable. */ temp_var = find_variable ("POSIXLY_CORRECT"); if (!temp_var) temp_var = find_variable ("POSIX_PEDANTIC"); if (temp_var && imported_p (temp_var)) sv_strict_posix (temp_var->name);#if defined (HISTORY) /* Set history variables to defaults, and then do whatever we would do if the variable had just been set. Do this only in the case that we are remembering commands on the history list. */ if (remember_on_history) { name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0); set_if_not ("HISTFILE", name); free (name);#if 0 set_if_not ("HISTSIZE", "500"); sv_histsize ("HISTSIZE");#endif }#endif /* HISTORY */ /* Seed the random number generator. */ seedrand (); /* Handle some "special" variables that we may have inherited from a parent shell. */ if (interactive_shell) { temp_var = find_variable ("IGNOREEOF"); if (!temp_var) temp_var = find_variable ("ignoreeof"); if (temp_var && imported_p (temp_var)) sv_ignoreeof (temp_var->name); }#if defined (HISTORY) if (interactive_shell && remember_on_history) { sv_history_control ("HISTCONTROL"); sv_histignore ("HISTIGNORE"); sv_histtimefmt ("HISTTIMEFORMAT"); }#endif /* HISTORY */#if defined (READLINE) && defined (STRICT_POSIX) /* POSIXLY_CORRECT will only be 1 here if the shell was compiled -DSTRICT_POSIX */ if (interactive_shell && posixly_correct && no_line_editing == 0) rl_prefer_env_winsize = 1;#endif /* READLINE && STRICT_POSIX */ /* * 24 October 2001 * * I'm tired of the arguing and bug reports. Bash now leaves SSH_CLIENT * and SSH2_CLIENT alone. I'm going to rely on the shell_level check in * isnetconn() to avoid running the startup files more often than wanted. * That will, of course, only work if the user's login shell is bash, so * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined * in config-top.h. */#if 0 temp_var = find_variable ("SSH_CLIENT"); if (temp_var && imported_p (temp_var)) { VUNSETATTR (temp_var, att_exported); array_needs_making = 1; } temp_var = find_variable ("SSH2_CLIENT"); if (temp_var && imported_p (temp_var)) { VUNSETATTR (temp_var, att_exported); array_needs_making = 1; }#endif /* Get the user's real and effective user ids. */ uidset (); temp_var = find_variable ("BASH_XTRACEFD"); if (temp_var && imported_p (temp_var)) sv_xtracefd (temp_var->name); /* Initialize the dynamic variables, and seed their values. */ initialize_dynamic_variables ();}/* **************************************************************** *//* *//* Setting values for special shell variables *//* *//* **************************************************************** */static voidset_machine_vars (){ SHELL_VAR *temp_var; temp_var = set_if_not ("HOSTTYPE", HOSTTYPE); temp_var = set_if_not ("OSTYPE", OSTYPE); temp_var = set_if_not ("MACHTYPE", MACHTYPE); temp_var = set_if_not ("HOSTNAME", current_host_name);}/* Set $HOME to the information in the password file if we didn't get it from the environment. *//* This function is not static so the tilde and readline libraries can use it. */char *sh_get_home_dir (){ if (current_user.home_dir == 0) get_current_user_info (); return current_user.home_dir;}static voidset_home_var (){ SHELL_VAR *temp_var; temp_var = find_variable ("HOME"); if (temp_var == 0) temp_var = bind_variable ("HOME", sh_get_home_dir (), 0);#if 0 VSETATTR (temp_var, att_exported);#endif}/* Set $SHELL to the user's login shell if it is not already set. Call get_current_user_info if we haven't already fetched the shell. */static voidset_shell_var (){ SHELL_VAR *temp_var; temp_var = find_variable ("SHELL"); if (temp_var == 0) { if (current_user.shell == 0) get_current_user_info (); temp_var = bind_variable ("SHELL", current_user.shell, 0); }#if 0 VSETATTR (temp_var, att_exported);#endif}static char *get_bash_name (){ char *name; if ((login_shell == 1) && RELPATH(shell_name)) { if (current_user.shell == 0) get_current_user_info (); name = savestring (current_user.shell); } else if (ABSPATH(shell_name)) name = savestring (shell_name); else if (shell_name[0] == '.' && shell_name[1] == '/') { /* Fast path for common case. */ char *cdir; int len; cdir = get_string_value ("PWD"); if (cdir) { len = strlen (cdir); name = (char *)xmalloc (len + strlen (shell_name) + 1); strcpy (name, cdir); strcpy (name + len, shell_name + 1); } else name = savestring (shell_name); } else { char *tname; int s; tname = find_user_command (shell_name); if (tname == 0) { /* Try the current directory. If there is not an executable there, just punt and use the login shell. */ s = file_status (shell_name); if (s & FS_EXECABLE) { tname = make_absolute (shell_name, get_string_value ("PWD")); if (*shell_name == '.') { name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS); if (name == 0) name = tname; else free (tname); } else name = tname; } else { if (current_user.shell == 0) get_current_user_info (); name = savestring (current_user.shell); } } else { name = full_pathname (tname); free (tname); } } return (name);}voidadjust_shell_level (change) int change;{ char new_level[5], *old_SHLVL; intmax_t old_level; SHELL_VAR *temp_var; old_SHLVL = get_string_value ("SHLVL"); if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0) old_level = 0; shell_level = old_level + change; if (shell_level < 0) shell_level = 0; else if (shell_level > 1000) { internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level); shell_level = 1; } /* We don't need the full generality of itos here. */ if (shell_level < 10) { new_level[0] = shell_level + '0'; new_level[1] = '\0'; } else if (shell_level < 100) { new_level[0] = (shell_level / 10) + '0'; new_level[1] = (shell_level % 10) + '0'; new_level[2] = '\0'; } else if (shell_level < 1000) { new_level[0] = (shell_level / 100) + '0'; old_level = shell_level % 100; new_level[1] = (old_level / 10) + '0'; new_level[2] = (old_level % 10) + '0'; new_level[3] = '\0'; } temp_var = bind_variable ("SHLVL", new_level, 0); set_auto_export (temp_var);}static voidinitialize_shell_level (){ adjust_shell_level (1);}/* If we got PWD from the environment, update our idea of the current working directory. In any case, make sure that PWD exists before checking it. It is possible for getcwd () to fail on shell startup, and in that case, PWD would be undefined. If this is an interactive login shell, see if $HOME is the current working directory, and if that's not the same string as $PWD, set PWD=$HOME. */voidset_pwd (){ SHELL_VAR *temp_var, *home_var; char *temp_string, *home_string; home_var = find_variable ("HOME"); home_string = home_var ? value_cell (home_var) : (char *)NULL; temp_var = find_variable ("PWD"); if (temp_var && imported_p (temp_var) && (temp_string = value_cell (temp_var)) && same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL)) set_working_directory (temp_string); else if (home_string && interactive_shell && login_shell && same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL)) { set_working_directory (home_string); temp_var = bind_variable ("PWD", home_string, 0); set_auto_export (temp_var); } else { temp_string = get_working_directory ("shell-init"); if (temp_string) { temp_var = bind_variable ("PWD", temp_string, 0); set_auto_export (temp_var); free (temp_string); } } /* According to the Single Unix Specification, v2, $OLDPWD is an `environment variable' and therefore should be auto-exported. Make a dummy invisible variable for OLDPWD, and mark it as exported. */ temp_var = bind_variable ("OLDPWD", (char *)NULL, 0); VSETATTR (temp_var, (att_exported | att_invisible));}/* Make a variable $PPID, which holds the pid of the shell's parent. */voidset_ppid (){ char namebuf[INT_STRLEN_BOUND(pid_t) + 1], *name; SHELL_VAR *temp_var; name = inttostr (getppid (), namebuf, sizeof(namebuf)); temp_var = find_variable ("PPID"); if (temp_var) VUNSETATTR (temp_var, (att_readonly | att_exported)); temp_var = bind_variable ("PPID", name, 0); VSETATTR (temp_var, (att_readonly | att_integer));}static voiduidset (){ char buff[INT_STRLEN_BOUND(uid_t) + 1], *b; register SHELL_VAR *v; b = inttostr (current_user.uid, buff, sizeof (buff)); v = find_variable ("UID"); if (v == 0) { v = bind_variable ("UID", b, 0); VSETATTR (v, (att_readonly | att_integer)); } if (current_user.euid != current_user.uid) b = inttostr (current_user.euid, buff, sizeof (buff)); v = find_variable ("EUID"); if (v == 0) { v = bind_variable ("EUID", b, 0); VSETATTR (v, (att_readonly | att_integer)); }}#if defined (ARRAY_VARS)static voidmake_vers_array (){ SHELL_VAR *vv; ARRAY *av; char *s, d[32], b[INT_STRLEN_BOUND(int) + 1]; unbind_variable ("BASH_VERSINFO"); vv = make_new_array_variable ("BASH_VERSINFO"); av = array_cell (vv); strcpy (d, dist_version); s = strchr (d, '.'); if (s) *s++ = '\0'; array_insert (av, 0, d); array_insert (av, 1, s); s = inttostr (patch_level, b, sizeof (b)); array_insert (av, 2, s); s = inttostr (build_version, b, sizeof (b)); array_insert (av, 3, s); array_insert (av, 4, release_status); array_insert (av, 5, MACHTYPE); VSETATTR (vv, att_readonly);}#endif /* ARRAY_VARS *//* Set the environment variables $LINES and $COLUMNS in response to a window size change. */voidsh_set_lines_and_columns (lines, cols) int lines, cols;{ char val[INT_STRLEN_BOUND(int) + 1], *v;#if defined (READLINE) /* If we are currently assigning to LINES or COLUMNS, don't do anything. */ if (winsize_assignment) return;#endif v = inttostr (lines, val, sizeof (val)); bind_variable ("LINES", v, 0); v = inttostr (cols, val, sizeof (val)); bind_variable ("COLUMNS", v, 0);}/* **************************************************************** *//* *//* Printing variables and values *//* *//* **************************************************************** *//* Print LIST (a list of shell variables) to stdout in such a way that they can be read back in. */voidprint_var_list (list) register SHELL_VAR **list;{ register int i; register SHELL_VAR *var; for (i = 0; list && (var = list[i]); i++) if (invisible_p (var) == 0) print_assignment (var);}/* Print LIST (a list of shell functions) to stdout in such a way that they can be read back in. */voidprint_func_list (list) register SHELL_VAR **list;{ register int i; register SHELL_VAR *var; for (i = 0; list && (var = list[i]); i++) { printf ("%s ", var->name); print_var_function (var); printf ("\n"); }} /* Print the value of a single SHELL_VAR. No newline is output, but the variable is printed in such a way that it can be read back in. */voidprint_assignment (var) SHELL_VAR *var;{ if (var_isset (var) == 0) return; if (function_p (var)) { printf ("%s", var->name); print_var_function (var); printf ("\n"); }#if defined (ARRAY_VARS) else if (array_p (var)) print_array_assignment (var, 0); else if (assoc_p (var)) print_assoc_assignment (var, 0);#endif /* ARRAY_VARS */ else { printf ("%s=", var->name); print_var_value (var, 1); printf ("\n"); }}/* Print the value cell of VAR, a shell variable. Do not print the name, nor leading/trailing newline. If QUOTE is non-zero, and the value contains shell metacharacters, quote the value in such a way that it can be read back in. */voidprint_var_value (var, quote) SHELL_VAR *var; int quote;{ char *t; if (var_isset (var) == 0) return; if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var))) { t = ansic_quote (value_cell (var), 0, (int *)0); printf ("%s", t); free (t); } else if (quote && sh_contains_shell_metas (value_cell (var))) { t = sh_single_quote (value_cell (var)); printf ("%s", t); free (t); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -