?? shell.c
字號:
/* shell.c -- GNU's idea of the POSIX shell specification. *//* Copyright (C) 1987-2010 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. Bash is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Bash is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Bash. If not, see <http://www.gnu.org/licenses/>.*//* Birthdate: Sunday, January 10th, 1988. Initial author: Brian Fox*/#define INSTALL_DEBUG_MODE#include "config.h"#include "bashtypes.h"#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)# include <sys/file.h>#endif#include "posixstat.h"#include "posixtime.h"#include "bashansi.h"#include <stdio.h>#include <signal.h>#include <errno.h>#include "filecntl.h"#include <pwd.h>#if defined (HAVE_UNISTD_H)# include <unistd.h>#endif#include "bashintl.h"#define NEED_SH_SETLINEBUF_DECL /* used in externs.h */#include "shell.h"#include "flags.h"#include "trap.h"#include "mailcheck.h"#include "builtins.h"#include "builtins/common.h"#if defined (JOB_CONTROL)#include "jobs.h"#endif /* JOB_CONTROL */#include "input.h"#include "execute_cmd.h"#include "findcmd.h"#if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)# include <malloc/shmalloc.h>#endif#if defined (HISTORY)# include "bashhist.h"# include <readline/history.h>#endif#if defined (READLINE)# include "bashline.h"#endif#include <tilde/tilde.h>#include <glob/strmatch.h>#if defined (__OPENNT)# include <opennt/opennt.h>#endif#if !defined (HAVE_GETPW_DECLS)extern struct passwd *getpwuid ();#endif /* !HAVE_GETPW_DECLS */#if !defined (errno)extern int errno;#endif#if defined (NO_MAIN_ENV_ARG)extern char **environ; /* used if no third argument to main() */#endifextern char *dist_version, *release_status;extern int patch_level, build_version;extern int shell_level;extern int subshell_environment;extern int last_command_exit_value;extern int line_number;extern int expand_aliases;extern int array_needs_making;extern int gnu_error_format;extern char *primary_prompt, *secondary_prompt;extern char *this_command_name;/* Non-zero means that this shell has already been run; i.e. you should call shell_reinitialize () if you need to start afresh. */int shell_initialized = 0;COMMAND *global_command = (COMMAND *)NULL;/* Information about the current user. */struct user_info current_user ={ (uid_t)-1, (uid_t)-1, (gid_t)-1, (gid_t)-1, (char *)NULL, (char *)NULL, (char *)NULL};/* The current host's name. */char *current_host_name = (char *)NULL;/* Non-zero means that this shell is a login shell. Specifically: 0 = not login shell. 1 = login shell from getty (or equivalent fake out) -1 = login shell from "--login" (or -l) flag. -2 = both from getty, and from flag. */int login_shell = 0;/* Non-zero means that at this moment, the shell is interactive. In general, this means that the shell is at this moment reading input from the keyboard. */int interactive = 0;/* Non-zero means that the shell was started as an interactive shell. */int interactive_shell = 0;/* Non-zero means to send a SIGHUP to all jobs when an interactive login shell exits. */int hup_on_exit = 0;/* Non-zero means to list status of running and stopped jobs at shell exit */int check_jobs_at_exit = 0;/* Non-zero means to change to a directory name supplied as a command name */int autocd = 0;/* Tells what state the shell was in when it started: 0 = non-interactive shell script 1 = interactive 2 = -c command 3 = wordexp evaluation This is a superset of the information provided by interactive_shell.*/int startup_state = 0;/* Special debugging helper. */int debugging_login_shell = 0;/* The environment that the shell passes to other commands. */char **shell_environment;/* Non-zero when we are executing a top-level command. */int executing = 0;/* The number of commands executed so far. */int current_command_number = 1;/* Non-zero is the recursion depth for commands. */int indirection_level = 0;/* The name of this shell, as taken from argv[0]. */char *shell_name = (char *)NULL;/* time in seconds when the shell was started */time_t shell_start_time;/* Are we running in an emacs shell window? */int running_under_emacs;/* Do we have /dev/fd? */#ifdef HAVE_DEV_FDint have_devfd = HAVE_DEV_FD;#elseint have_devfd = 0;#endif/* The name of the .(shell)rc file. */static char *bashrc_file = "~/.bashrc";/* Non-zero means to act more like the Bourne shell on startup. */static int act_like_sh;/* Non-zero if this shell is being run by `su'. */static int su_shell;/* Non-zero if we have already expanded and sourced $ENV. */static int sourced_env;/* Is this shell running setuid? */static int running_setuid;/* Values for the long-winded argument names. */static int debugging; /* Do debugging things. */static int no_rc; /* Don't execute ~/.bashrc */static int no_profile; /* Don't execute .profile */static int do_version; /* Display interesting version info. */static int make_login_shell; /* Make this shell be a `-bash' shell. */static int want_initial_help; /* --help option */int debugging_mode = 0; /* In debugging mode with --debugger */int no_line_editing = 0; /* Don't do fancy line editing. */int dump_translatable_strings; /* Dump strings in $"...", don't execute. */int dump_po_strings; /* Dump strings in $"..." in po format */int wordexp_only = 0; /* Do word expansion only */int protected_mode = 0; /* No command substitution with --wordexp */#if defined (STRICT_POSIX)int posixly_correct = 1; /* Non-zero means posix.2 superset. */#elseint posixly_correct = 0; /* Non-zero means posix.2 superset. */#endif/* Some long-winded argument names. These are obviously new. */#define Int 1#define Charp 2static const struct { const char *name; int type; int *int_value; char **char_value;} long_args[] = { { "debug", Int, &debugging, (char **)0x0 },#if defined (DEBUGGER) { "debugger", Int, &debugging_mode, (char **)0x0 },#endif { "dump-po-strings", Int, &dump_po_strings, (char **)0x0 }, { "dump-strings", Int, &dump_translatable_strings, (char **)0x0 }, { "help", Int, &want_initial_help, (char **)0x0 }, { "init-file", Charp, (int *)0x0, &bashrc_file }, { "login", Int, &make_login_shell, (char **)0x0 }, { "noediting", Int, &no_line_editing, (char **)0x0 }, { "noprofile", Int, &no_profile, (char **)0x0 }, { "norc", Int, &no_rc, (char **)0x0 }, { "posix", Int, &posixly_correct, (char **)0x0 }, { "protected", Int, &protected_mode, (char **)0x0 }, { "rcfile", Charp, (int *)0x0, &bashrc_file },#if defined (RESTRICTED_SHELL) { "restricted", Int, &restricted, (char **)0x0 },#endif { "verbose", Int, &echo_input_at_read, (char **)0x0 }, { "version", Int, &do_version, (char **)0x0 },#if defined (WORDEXP_OPTION) { "wordexp", Int, &wordexp_only, (char **)0x0 },#endif { (char *)0x0, Int, (int *)0x0, (char **)0x0 }};/* These are extern so execute_simple_command can set them, and then longjmp back to main to execute a shell script, instead of calling main () again and resulting in indefinite, possibly fatal, stack growth. */procenv_t subshell_top_level;int subshell_argc;char **subshell_argv;char **subshell_envp;char *exec_argv0;#if defined (BUFFERED_INPUT)/* The file descriptor from which the shell is reading input. */int default_buffered_input = -1;#endif/* The following two variables are not static so they can show up in $-. */int read_from_stdin; /* -s flag supplied */int want_pending_command; /* -c flag supplied *//* This variable is not static so it can be bound to $BASH_EXECUTION_STRING */char *command_execution_string; /* argument to -c option */int malloc_trace_at_exit = 0;static int shell_reinitialized = 0;static FILE *default_input;static STRING_INT_ALIST *shopt_alist;static int shopt_ind = 0, shopt_len = 0;static int parse_long_options __P((char **, int, int));static int parse_shell_options __P((char **, int, int));static int bind_args __P((char **, int, int, int));static void start_debugger __P((void));static void add_shopt_to_alist __P((char *, int));static void run_shopt_alist __P((void));static void execute_env_file __P((char *));static void run_startup_files __P((void));static int open_shell_script __P((char *));static void set_bash_input __P((void));static int run_one_command __P((char *));#if defined (WORDEXP_OPTION)static int run_wordexp __P((char *));#endifstatic int uidget __P((void));static void init_interactive __P((void));static void init_noninteractive __P((void));static void init_interactive_script __P((void));static void set_shell_name __P((char *));static void shell_initialize __P((void));static void shell_reinitialize __P((void));static void show_shell_usage __P((FILE *, int));#ifdef __CYGWIN__static void_cygwin32_check_tmp (){ struct stat sb; if (stat ("/tmp", &sb) < 0) internal_warning (_("could not find /tmp, please create!")); else { if (S_ISDIR (sb.st_mode) == 0) internal_warning (_("/tmp must be a valid directory name")); }}#endif /* __CYGWIN__ */#if defined (NO_MAIN_ENV_ARG)/* systems without third argument to main() */intmain (argc, argv) int argc; char **argv;#else /* !NO_MAIN_ENV_ARG */intmain (argc, argv, env) int argc; char **argv, **env;#endif /* !NO_MAIN_ENV_ARG */{ register int i; int code, old_errexit_flag;#if defined (RESTRICTED_SHELL) int saverst;#endif volatile int locally_skip_execution; volatile int arg_index, top_level_arg_index;#ifdef __OPENNT char **env; env = environ;#endif /* __OPENNT */ USE_VAR(argc); USE_VAR(argv); USE_VAR(env); USE_VAR(code); USE_VAR(old_errexit_flag);#if defined (RESTRICTED_SHELL) USE_VAR(saverst);#endif /* Catch early SIGINTs. */ code = setjmp (top_level); if (code) exit (2); xtrace_init ();#if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)# if 1 malloc_set_register (1);# endif#endif check_dev_tty ();#ifdef __CYGWIN__ _cygwin32_check_tmp ();#endif /* __CYGWIN__ */ /* Wait forever if we are debugging a login shell. */ while (debugging_login_shell) sleep (3); set_default_locale (); running_setuid = uidget (); if (getenv ("POSIXLY_CORRECT") || getenv ("POSIX_PEDANTIC")) posixly_correct = 1;#if defined (USE_GNU_MALLOC_LIBRARY) mcheck (programming_error, (void (*) ())0);#endif /* USE_GNU_MALLOC_LIBRARY */ if (setjmp (subshell_top_level)) { argc = subshell_argc; argv = subshell_argv; env = subshell_envp; sourced_env = 0; } shell_reinitialized = 0; /* Initialize `local' variables for all `invocations' of main (). */ arg_index = 1; if (arg_index > argc) arg_index = argc; command_execution_string = (char *)NULL; want_pending_command = locally_skip_execution = read_from_stdin = 0; default_input = stdin;#if defined (BUFFERED_INPUT) default_buffered_input = -1;#endif /* Fix for the `infinite process creation' bug when running shell scripts from startup files on System V. */ login_shell = make_login_shell = 0; /* If this shell has already been run, then reinitialize it to a vanilla state. */ if (shell_initialized || shell_name) { /* Make sure that we do not infinitely recurse as a login shell. */ if (*shell_name == '-') shell_name++; shell_reinitialize (); if (setjmp (top_level)) exit (2); } shell_environment = env; set_shell_name (argv[0]); shell_start_time = NOW; /* NOW now defined in general.h */ /* Parse argument flags from the input line. */ /* Find full word arguments first. */ arg_index = parse_long_options (argv, arg_index, argc); if (want_initial_help) { show_shell_usage (stdout, 1); exit (EXECUTION_SUCCESS); } if (do_version) { show_shell_version (1);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -