📄 common.c
字号:
/* common.c - utility functions for all builtins *//* 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/>.*/#include <config.h>#if defined (HAVE_UNISTD_H)# ifdef _MINIX# include <sys/types.h># endif# include <unistd.h>#endif#include <stdio.h>#include <chartypes.h>#include "../bashtypes.h"#include "posixstat.h"#include <signal.h>#include <errno.h>#if defined (PREFER_STDARG)# include <stdarg.h>#else# include <varargs.h>#endif#include "../bashansi.h"#include "../bashintl.h"#define NEED_FPURGE_DECL#include "../shell.h"#include "maxpath.h"#include "../flags.h"#include "../jobs.h"#include "../builtins.h"#include "../input.h"#include "../execute_cmd.h"#include "../trap.h"#include "bashgetopt.h"#include "common.h"#include "builtext.h"#include <tilde/tilde.h>#if defined (HISTORY)# include "../bashhist.h"#endif#if !defined (errno)extern int errno; #endif /* !errno */extern int indirection_level, subshell_environment;extern int line_number;extern int last_command_exit_value;extern int running_trap;extern int posixly_correct;extern char *this_command_name, *shell_name;extern const char * const bash_getcwd_errstr;/* Used by some builtins and the mainline code. */sh_builtin_func_t *last_shell_builtin = (sh_builtin_func_t *)NULL;sh_builtin_func_t *this_shell_builtin = (sh_builtin_func_t *)NULL;/* **************************************************************** *//* *//* Error reporting, usage, and option processing *//* *//* **************************************************************** *//* This is a lot like report_error (), but it is for shell builtins instead of shell control structures, and it won't ever exit the shell. */static voidbuiltin_error_prolog (){ char *name; name = get_name_for_error (); fprintf (stderr, "%s: ", name); if (interactive_shell == 0) fprintf (stderr, _("line %d: "), executing_line_number ()); if (this_command_name && *this_command_name) fprintf (stderr, "%s: ", this_command_name);}void#if defined (PREFER_STDARG)builtin_error (const char *format, ...)#elsebuiltin_error (format, va_alist) const char *format; va_dcl#endif{ va_list args; builtin_error_prolog (); SH_VA_START (args, format); vfprintf (stderr, format, args); va_end (args); fprintf (stderr, "\n");}void#if defined (PREFER_STDARG)builtin_warning (const char *format, ...)#elsebuiltin_warning (format, va_alist) const char *format; va_dcl#endif{ va_list args; builtin_error_prolog (); fprintf (stderr, _("warning: ")); SH_VA_START (args, format); vfprintf (stderr, format, args); va_end (args); fprintf (stderr, "\n");}/* Print a usage summary for the currently-executing builtin command. */voidbuiltin_usage (){ if (this_command_name && *this_command_name) fprintf (stderr, _("%s: usage: "), this_command_name); fprintf (stderr, "%s\n", _(current_builtin->short_doc)); fflush (stderr);}/* Return if LIST is NULL else barf and jump to top_level. Used by some builtins that do not accept arguments. */voidno_args (list) WORD_LIST *list;{ if (list) { builtin_error (_("too many arguments")); top_level_cleanup (); jump_to_top_level (DISCARD); }}/* Check that no options were given to the currently-executing builtin, and return 0 if there were options. */intno_options (list) WORD_LIST *list;{ reset_internal_getopt (); if (internal_getopt (list, "") != -1) { builtin_usage (); return (1); } return (0);}voidsh_needarg (s) char *s;{ builtin_error (_("%s: option requires an argument"), s);}voidsh_neednumarg (s) char *s;{ builtin_error (_("%s: numeric argument required"), s);}voidsh_notfound (s) char *s;{ builtin_error (_("%s: not found"), s);}/* Function called when one of the builtin commands detects an invalid option. */voidsh_invalidopt (s) char *s;{ builtin_error (_("%s: invalid option"), s);}voidsh_invalidoptname (s) char *s;{ builtin_error (_("%s: invalid option name"), s);}voidsh_invalidid (s) char *s;{ builtin_error (_("`%s': not a valid identifier"), s);}voidsh_invalidnum (s) char *s;{ char *msg; if (*s == '0' && isdigit (s[1])) msg = _("invalid octal number"); else if (*s == '0' && s[1] == 'x') msg = _("invalid hex number"); else msg = _("invalid number"); builtin_error ("%s: %s", s, msg);}voidsh_invalidsig (s) char *s;{ builtin_error (_("%s: invalid signal specification"), s);}voidsh_badpid (s) char *s;{ builtin_error (_("`%s': not a pid or valid job spec"), s);}voidsh_readonly (s) const char *s;{ builtin_error (_("%s: readonly variable"), s);}voidsh_erange (s, desc) char *s, *desc;{ if (s) builtin_error (_("%s: %s out of range"), s, desc ? desc : _("argument")); else builtin_error (_("%s out of range"), desc ? desc : _("argument"));}#if defined (JOB_CONTROL)voidsh_badjob (s) char *s;{ builtin_error (_("%s: no such job"), s);}voidsh_nojobs (s) char *s;{ if (s) builtin_error (_("%s: no job control"), s); else builtin_error (_("no job control"));}#endif#if defined (RESTRICTED_SHELL)voidsh_restricted (s) char *s;{ if (s) builtin_error (_("%s: restricted"), s); else builtin_error (_("restricted"));}#endifvoidsh_notbuiltin (s) char *s;{ builtin_error (_("%s: not a shell builtin"), s);}voidsh_wrerror (){#if defined (DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS) && defined (EPIPE) if (errno != EPIPE)#endif /* DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS && EPIPE */ builtin_error (_("write error: %s"), strerror (errno));}voidsh_ttyerror (set) int set;{ if (set) builtin_error (_("error setting terminal attributes: %s"), strerror (errno)); else builtin_error (_("error getting terminal attributes: %s"), strerror (errno));}intsh_chkwrite (s) int s;{ fflush (stdout); if (ferror (stdout)) { sh_wrerror (); fpurge (stdout); clearerr (stdout); return (EXECUTION_FAILURE); } return (s);}/* **************************************************************** *//* *//* Shell positional parameter manipulation *//* *//* **************************************************************** *//* Convert a WORD_LIST into a C-style argv. Return the number of elements in the list in *IP, if IP is non-null. A convenience function for loadable builtins; also used by `test'. */char **make_builtin_argv (list, ip) WORD_LIST *list; int *ip;{ char **argv; argv = strvec_from_word_list (list, 0, 1, ip); argv[0] = this_command_name; return argv;}/* Remember LIST in $1 ... $9, and REST_OF_ARGS. If DESTRUCTIVE is non-zero, then discard whatever the existing arguments are, else only discard the ones that are to be replaced. */voidremember_args (list, destructive) WORD_LIST *list; int destructive;{ register int i; for (i = 1; i < 10; i++) { if ((destructive || list) && dollar_vars[i]) { free (dollar_vars[i]); dollar_vars[i] = (char *)NULL; } if (list) { dollar_vars[i] = savestring (list->word->word); list = list->next; } } /* If arguments remain, assign them to REST_OF_ARGS. Note that copy_word_list (NULL) returns NULL, and that dispose_words (NULL) does nothing. */ if (destructive || list) { dispose_words (rest_of_args); rest_of_args = copy_word_list (list); } if (destructive) set_dollar_vars_changed ();}static int changed_dollar_vars;/* Have the dollar variables been reset to new values since we last checked? */intdollar_vars_changed (){ return (changed_dollar_vars);}voidset_dollar_vars_unchanged (){ changed_dollar_vars = 0;}voidset_dollar_vars_changed (){ if (variable_context) changed_dollar_vars |= ARGS_FUNC; else if (this_shell_builtin == set_builtin) changed_dollar_vars |= ARGS_SETBLTIN; else changed_dollar_vars |= ARGS_INVOC;}/* **************************************************************** *//* *//* Validating numeric input and arguments *//* *//* **************************************************************** *//* Read a numeric arg for this_command_name, the name of the shell builtin that wants it. LIST is the word list that the arg is to come from. Accept only the numeric argument; report an error if other arguments follow. If FATAL is 1, call throw_to_top_level, which exits the shell; if it's 2, call jump_to_top_level (DISCARD), which aborts the current command; if FATAL is 0, return an indication of an invalid
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -