📄 shell.c
字号:
restore the original terminal process group. Don't do this if we're in a subshell and calling exit_shell after, for example, a failed word expansion. */ if (subshell_environment == 0) end_job_control ();#endif /* JOB_CONTROL */ /* Always return the exit status of the last command to our parent. */ sh_exit (s);}/* A wrapper for exit that (optionally) can do other things, like malloc statistics tracing. */voidsh_exit (s) int s;{#if defined (MALLOC_DEBUG) && defined (USING_BASH_MALLOC) if (malloc_trace_at_exit) trace_malloc_stats (get_name_for_error (), (char *)NULL);#endif exit (s);}/* Source the bash startup files. If POSIXLY_CORRECT is non-zero, we obey the Posix.2 startup file rules: $ENV is expanded, and if the file it names exists, that file is sourced. The Posix.2 rules are in effect for interactive shells only. (section 4.56.5.3) *//* Execute ~/.bashrc for most shells. Never execute it if ACT_LIKE_SH is set, or if NO_RC is set. If the executable file "/usr/gnu/src/bash/foo" contains: #!/usr/gnu/bin/bash echo hello then: COMMAND EXECUTE BASHRC -------------------------------- bash -c foo NO bash foo NO foo NO rsh machine ls YES (for rsh, which calls `bash -c') rsh machine foo YES (for shell started by rsh) NO (for foo!) echo ls | bash NO login NO bash YES*/static voidexecute_env_file (env_file) char *env_file;{ char *fn; if (env_file && *env_file) { fn = expand_string_unsplit_to_string (env_file, Q_DOUBLE_QUOTES); if (fn && *fn) maybe_execute_file (fn, 1); FREE (fn); }}static voidrun_startup_files (){#if defined (JOB_CONTROL) int old_job_control;#endif int sourced_login, run_by_ssh; /* get the rshd/sshd case out of the way first. */ if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 && act_like_sh == 0 && command_execution_string) {#ifdef SSH_SOURCE_BASHRC run_by_ssh = (find_variable ("SSH_CLIENT") != (SHELL_VAR *)0) || (find_variable ("SSH2_CLIENT") != (SHELL_VAR *)0);#else run_by_ssh = 0;#endif /* If we were run by sshd or we think we were run by rshd, execute ~/.bashrc if we are a top-level shell. */ if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2) {#ifdef SYS_BASHRC# if defined (__OPENNT) maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1);# else maybe_execute_file (SYS_BASHRC, 1);# endif#endif maybe_execute_file (bashrc_file, 1); return; } }#if defined (JOB_CONTROL) /* Startup files should be run without job control enabled. */ old_job_control = interactive_shell ? set_job_control (0) : 0;#endif sourced_login = 0; /* A shell begun with the --login (or -l) flag that is not in posix mode runs the login shell startup files, no matter whether or not it is interactive. If NON_INTERACTIVE_LOGIN_SHELLS is defined, run the startup files if argv[0][0] == '-' as well. */#if defined (NON_INTERACTIVE_LOGIN_SHELLS) if (login_shell && posixly_correct == 0)#else if (login_shell < 0 && posixly_correct == 0)#endif { /* We don't execute .bashrc for login shells. */ no_rc++; /* Execute /etc/profile and one of the personal login shell initialization files. */ if (no_profile == 0) { maybe_execute_file (SYS_PROFILE, 1); if (act_like_sh) /* sh */ maybe_execute_file ("~/.profile", 1); else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) && (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */ maybe_execute_file ("~/.profile", 1); } sourced_login = 1; } /* A non-interactive shell not named `sh' and not in posix mode reads and executes commands from $BASH_ENV. If `su' starts a shell with `-c cmd' and `-su' as the name of the shell, we want to read the startup files. No other non-interactive shells read any startup files. */ if (interactive_shell == 0 && !(su_shell && login_shell)) { if (posixly_correct == 0 && act_like_sh == 0 && privileged_mode == 0 && sourced_env++ == 0) execute_env_file (get_string_value ("BASH_ENV")); return; } /* Interactive shell or `-su' shell. */ if (posixly_correct == 0) /* bash, sh */ { if (login_shell && sourced_login++ == 0) { /* We don't execute .bashrc for login shells. */ no_rc++; /* Execute /etc/profile and one of the personal login shell initialization files. */ if (no_profile == 0) { maybe_execute_file (SYS_PROFILE, 1); if (act_like_sh) /* sh */ maybe_execute_file ("~/.profile", 1); else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) && (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */ maybe_execute_file ("~/.profile", 1); } } /* bash */ if (act_like_sh == 0 && no_rc == 0) {#ifdef SYS_BASHRC# if defined (__OPENNT) maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1);# else maybe_execute_file (SYS_BASHRC, 1);# endif#endif maybe_execute_file (bashrc_file, 1); } /* sh */ else if (act_like_sh && privileged_mode == 0 && sourced_env++ == 0) execute_env_file (get_string_value ("ENV")); } else /* bash --posix, sh --posix */ { /* bash and sh */ if (interactive_shell && privileged_mode == 0 && sourced_env++ == 0) execute_env_file (get_string_value ("ENV")); }#if defined (JOB_CONTROL) set_job_control (old_job_control);#endif}#if defined (RESTRICTED_SHELL)/* Return 1 if the shell should be a restricted one based on NAME or the value of `restricted'. Don't actually do anything, just return a boolean value. */intshell_is_restricted (name) char *name;{ char *temp; if (restricted) return 1; temp = base_pathname (name); if (*temp == '-') temp++; return (STREQ (temp, RESTRICTED_SHELL_NAME));}/* Perhaps make this shell a `restricted' one, based on NAME. If the basename of NAME is "rbash", then this shell is restricted. The name of the restricted shell is a configurable option, see config.h. In a restricted shell, PATH, SHELL, ENV, and BASH_ENV are read-only and non-unsettable. Do this also if `restricted' is already set to 1; maybe the shell was started with -r. */intmaybe_make_restricted (name) char *name;{ char *temp; temp = base_pathname (name); if (*temp == '-') temp++; if (restricted || (STREQ (temp, RESTRICTED_SHELL_NAME))) { set_var_read_only ("PATH"); set_var_read_only ("SHELL"); set_var_read_only ("ENV"); set_var_read_only ("BASH_ENV"); restricted = 1; } return (restricted);}#endif /* RESTRICTED_SHELL *//* Fetch the current set of uids and gids and return 1 if we're running setuid or setgid. */static intuidget (){ uid_t u; u = getuid (); if (current_user.uid != u) { FREE (current_user.user_name); FREE (current_user.shell); FREE (current_user.home_dir); current_user.user_name = current_user.shell = current_user.home_dir = (char *)NULL; } current_user.uid = u; current_user.gid = getgid (); current_user.euid = geteuid (); current_user.egid = getegid (); /* See whether or not we are running setuid or setgid. */ return (current_user.uid != current_user.euid) || (current_user.gid != current_user.egid);}voiddisable_priv_mode (){ setuid (current_user.uid); setgid (current_user.gid); current_user.euid = current_user.uid; current_user.egid = current_user.gid;}#if defined (WORDEXP_OPTION)static intrun_wordexp (words) char *words;{ int code, nw, nb; WORD_LIST *wl, *tl, *result; code = setjmp (top_level); if (code != NOT_JUMPED) { switch (code) { /* Some kind of throw to top_level has occured. */ case FORCE_EOF: return last_command_exit_value = 127; case ERREXIT: case EXITPROG: return last_command_exit_value; case DISCARD: return last_command_exit_value = 1; default: command_error ("run_wordexp", CMDERR_BADJUMP, code, 0); } } /* Run it through the parser to get a list of words and expand them */ if (words && *words) { with_input_from_string (words, "--wordexp"); if (parse_command () != 0) return (126); if (global_command == 0) { printf ("0\n0\n"); return (0); } if (global_command->type != cm_simple) return (126); wl = global_command->value.Simple->words; if (protected_mode) for (tl = wl; tl; tl = tl->next) tl->word->flags |= W_NOCOMSUB|W_NOPROCSUB; result = wl ? expand_words_no_vars (wl) : (WORD_LIST *)0; } else result = (WORD_LIST *)0; last_command_exit_value = 0; if (result == 0) { printf ("0\n0\n"); return (0); } /* Count up the number of words and bytes, and print them. Don't count the trailing NUL byte. */ for (nw = nb = 0, wl = result; wl; wl = wl->next) { nw++; nb += strlen (wl->word->word); } printf ("%u\n%u\n", nw, nb); /* Print each word on a separate line. This will have to be changed when the interface to glibc is completed. */ for (wl = result; wl; wl = wl->next) printf ("%s\n", wl->word->word); return (0);}#endif#if defined (ONESHOT)/* Run one command, given as the argument to the -c option. Tell parse_and_execute not to fork for a simple command. */static intrun_one_command (command) char *command;{ int code; code = setjmp (top_level); if (code != NOT_JUMPED) {#if defined (PROCESS_SUBSTITUTION) unlink_fifo_list ();#endif /* PROCESS_SUBSTITUTION */ switch (code) { /* Some kind of throw to top_level has occured. */ case FORCE_EOF: return last_command_exit_value = 127; case ERREXIT: case EXITPROG: return last_command_exit_value; case DISCARD: return last_command_exit_value = 1; default: command_error ("run_one_command", CMDERR_BADJUMP, code, 0); } } return (parse_and_execute (savestring (command), "-c", SEVAL_NOHIST));}#endif /* ONESHOT */static intbind_args (argv, arg_start, arg_end, start_index) char **argv; int arg_start, arg_end, start_index;{ register int i; WORD_LIST *args; for (i = arg_start, args = (WORD_LIST *)NULL; i < arg_end; i++) args = make_word_list (make_word (argv[i]), args); if (args) { args = REVERSE_LIST (args, WORD_LIST *); if (start_index == 0) /* bind to $0...$n for sh -c command */ { /* Posix.2 4.56.3 says that the first argument after sh -c command becomes $0, and the rest of the arguments become $1...$n */ shell_name = savestring (args->word->word); FREE (dollar_vars[0]); dollar_vars[0] = savestring (args->word->word); remember_args (args->next, 1); push_args (args->next); /* BASH_ARGV and BASH_ARGC */ } else /* bind to $1...$n for shell script */ { remember_args (args, 1); push_args (args); /* BASH_ARGV and BASH_ARGC */ } dispose_words (args); } return (i);}voidunbind_args (){ remember_args ((WORD_LIST *)NULL, 1); pop_args (); /* Reset BASH_ARGV and BASH_ARGC */}static voidstart_debugger (){#if defined (DEBUGGER) && defined (DEBUGGER_START_FILE) int old_errexit; old_errexit = exit_immediately_on_error; exit_immediately_on_error = 0; maybe_execute_file (DEBUGGER_START_FILE, 1); function_trace_mode = 1; exit_immediately_on_error += old_errexit;#endif}static intopen_shell_script (script_name) char *script_name;{ int fd, e, fd_is_tty; char *filename, *path_filename, *t; char sample[80]; int sample_len; struct stat sb;#if defined (ARRAY_VARS) SHELL_VAR *funcname_v, *bash_source_v, *bash_lineno_v; ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;#endif filename = savestring (script_name); fd = open (filename, O_RDONLY); if ((fd < 0) && (errno == ENOENT) && (absolute_program (filename) == 0)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -