mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-29 08:29:54 +02:00
commit bash-20040408 snapshot
This commit is contained in:
@@ -9317,3 +9317,53 @@ configure.in
|
||||
|
||||
include/posixdir.h
|
||||
- use new and renamed HAVE_STRUCT_DIRENT_D_xxx defines
|
||||
|
||||
4/7
|
||||
---
|
||||
builtins/cd.def
|
||||
- ensure that we print out a non-null pathname after getting a
|
||||
directory from CDPATH and canonicalizing it (e.g., if the result
|
||||
exceeds PATH_MAX in length and the_current_working_directory is
|
||||
set to NULL)
|
||||
|
||||
4/12
|
||||
----
|
||||
print_cmd.c
|
||||
- new functionto print out assignment statements when `set -x' has
|
||||
been enabled: xtrace_print_assignment
|
||||
|
||||
externs.h
|
||||
- extern declaration for xtrace_print_assignment
|
||||
|
||||
4/13
|
||||
----
|
||||
{subst,variables}.c
|
||||
- call xtrace_print_assignment instead of using inline code
|
||||
|
||||
jobs.c
|
||||
- if turning on job control when it was previously off, set
|
||||
pipeline_pgrp to 0 in set_job_control so make_child puts
|
||||
subsequent children in their own process group
|
||||
|
||||
4/14
|
||||
----
|
||||
general.c
|
||||
- new function, legal_alias_name, called to decide whether an
|
||||
argument to add_alias is a valid alias name -- essentially any
|
||||
character except one which must be quoted to the shell parser
|
||||
and `/'
|
||||
|
||||
general.h
|
||||
- new extern declaration for legal_alias_name
|
||||
|
||||
builtins/alias.def
|
||||
- `unalias' now returns failure status if no NAME arguments are
|
||||
supplied and -a is not given
|
||||
- call legal_alias_name to make sure alias name is valid before
|
||||
calling add_alias from alias_builtin
|
||||
|
||||
4/19
|
||||
----
|
||||
include/shmbutil.h
|
||||
- include <config.h> for definition of HANDLE_MULTIBYTE rather than
|
||||
duplicating logic
|
||||
|
||||
@@ -9264,6 +9264,13 @@ expr.c
|
||||
pre-decrement work when separated from their accompanying identifier
|
||||
by whitespace
|
||||
|
||||
3/18
|
||||
----
|
||||
lib/readline/misc.c
|
||||
- in rl_maybe_unsave_line, don't force rl_replace_line to clear
|
||||
the undo_list, since it might point directly at an undo list
|
||||
from a history entry (to which we have no handle)
|
||||
|
||||
3/19
|
||||
----
|
||||
lib/readline/display.c
|
||||
@@ -9295,3 +9302,63 @@ bashhist.c
|
||||
that returned `print only' to the history list, since history_expand
|
||||
no longer does it (and, when using readline, do it only when
|
||||
rl_dispatching is zero)
|
||||
|
||||
3/22
|
||||
----
|
||||
config.h.in,aclocal.m4
|
||||
- change bash-specific functions that look in struct dirent to define
|
||||
HAVE_STRUCT_DIRENT_xxx, like AC_CHECK_MEMBERS does (though the
|
||||
functions are otherwise the same)
|
||||
- new function, BASH_STRUCT_DIRENT_D_NAMLEN, define
|
||||
HAVE_STRUCT_DIRENT_D_NAMLEN if struct dirent has a `d_namlen' member
|
||||
|
||||
configure.in
|
||||
- call BASH_STRUCT_DIRENT_D_NAMLEN
|
||||
|
||||
include/posixdir.h
|
||||
- use new and renamed HAVE_STRUCT_DIRENT_D_xxx defines
|
||||
|
||||
4/7
|
||||
---
|
||||
builtins/cd.def
|
||||
- ensure that we print out a non-null pathname after getting a
|
||||
directory from CDPATH and canonicalizing it (e.g., if the result
|
||||
exceeds PATH_MAX in length and the_current_working_directory is
|
||||
set to NULL)
|
||||
|
||||
4/12
|
||||
----
|
||||
print_cmd.c
|
||||
- new functionto print out assignment statements when `set -x' has
|
||||
been enabled: xtrace_print_assignment
|
||||
|
||||
externs.h
|
||||
- extern declaration for xtrace_print_assignment
|
||||
|
||||
4/13
|
||||
----
|
||||
{subst,variables}.c
|
||||
- call xtrace_print_assignment instead of using inline code
|
||||
|
||||
jobs.c
|
||||
- if turning on job control when it was previously off, set
|
||||
pipeline_pgrp to 0 in set_job_control so make_child puts
|
||||
subsequent children in their own process group
|
||||
|
||||
4/14
|
||||
----
|
||||
general.c
|
||||
- new function, legal_alias_name, called to decide whether an
|
||||
argument to add_alias is a valid alias name -- essentially any
|
||||
character except one which must be quoted to the shell parser
|
||||
and `/'
|
||||
|
||||
general.h
|
||||
- new extern declaration for legal_alias_name
|
||||
|
||||
builtins/alias.def
|
||||
- `unalias' now returns failure status if no NAME arguments are
|
||||
supplied and -a is not given
|
||||
- call legal_alias_name to make sure alias name is valid before
|
||||
calling add_alias from alias_builtin
|
||||
|
||||
|
||||
+14
-2
@@ -118,7 +118,13 @@ alias_builtin (list)
|
||||
name[offset] = '\0';
|
||||
value = name + offset + 1;
|
||||
|
||||
add_alias (name, value);
|
||||
if (legal_alias_name (name, 0) == 0)
|
||||
{
|
||||
builtin_error ("%s: invalid alias name", name);
|
||||
any_failed++;
|
||||
}
|
||||
else
|
||||
add_alias (name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -141,7 +147,7 @@ alias_builtin (list)
|
||||
$BUILTIN unalias
|
||||
$FUNCTION unalias_builtin
|
||||
$DEPENDS_ON ALIAS
|
||||
$SHORT_DOC unalias [-a] [name ...]
|
||||
$SHORT_DOC unalias [-a] name [name ...]
|
||||
Remove NAMEs from the list of defined aliases. If the -a option is given,
|
||||
then remove all alias definitions.
|
||||
$END
|
||||
@@ -178,6 +184,12 @@ unalias_builtin (list)
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
aflag = 0;
|
||||
while (list)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
This file is alias.def, from which is created alias.c
|
||||
It implements the builtins "alias" and "unalias" in Bash.
|
||||
|
||||
Copyright (C) 1987-2002 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 2, 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; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
$BUILTIN alias
|
||||
$FUNCTION alias_builtin
|
||||
$DEPENDS_ON ALIAS
|
||||
$PRODUCES alias.c
|
||||
$SHORT_DOC alias [-p] [name[=value] ... ]
|
||||
`alias' with no arguments or with the -p option prints the list
|
||||
of aliases in the form alias NAME=VALUE on standard output.
|
||||
Otherwise, an alias is defined for each NAME whose VALUE is given.
|
||||
A trailing space in VALUE causes the next word to be checked for
|
||||
alias substitution when the alias is expanded. Alias returns
|
||||
true unless a NAME is given for which no alias has been defined.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (ALIAS)
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
# include "../bashansi.h"
|
||||
|
||||
# include <stdio.h>
|
||||
# include "../shell.h"
|
||||
# include "../alias.h"
|
||||
# include "common.h"
|
||||
# include "bashgetopt.h"
|
||||
|
||||
/* Flags for print_alias */
|
||||
#define AL_REUSABLE 0x01
|
||||
|
||||
static void print_alias __P((alias_t *, int));
|
||||
|
||||
extern int posixly_correct;
|
||||
|
||||
/* Hack the alias command in a Korn shell way. */
|
||||
int
|
||||
alias_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int any_failed, offset, pflag, dflags;
|
||||
alias_t **alias_list, *t;
|
||||
char *name, *value;
|
||||
|
||||
dflags = posixly_correct ? 0 : AL_REUSABLE;
|
||||
pflag = 0;
|
||||
reset_internal_getopt ();
|
||||
while ((offset = internal_getopt (list, "p")) != -1)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
dflags |= AL_REUSABLE;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
list = loptend;
|
||||
|
||||
if (list == 0 || pflag)
|
||||
{
|
||||
if (aliases == 0)
|
||||
return (EXECUTION_SUCCESS);
|
||||
|
||||
alias_list = all_aliases ();
|
||||
|
||||
if (alias_list == 0)
|
||||
return (EXECUTION_SUCCESS);
|
||||
|
||||
for (offset = 0; alias_list[offset]; offset++)
|
||||
print_alias (alias_list[offset], dflags);
|
||||
|
||||
free (alias_list); /* XXX - Do not free the strings. */
|
||||
|
||||
if (list == 0)
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
any_failed = 0;
|
||||
while (list)
|
||||
{
|
||||
name = list->word->word;
|
||||
|
||||
for (offset = 0; name[offset] && name[offset] != '='; offset++)
|
||||
;
|
||||
|
||||
if (offset && name[offset] == '=')
|
||||
{
|
||||
name[offset] = '\0';
|
||||
value = name + offset + 1;
|
||||
|
||||
if (legal_alias_name (name, 0) == 0)
|
||||
{
|
||||
builtin_error ("%s: invalid alias name", name);
|
||||
any_failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
add_alias (name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = find_alias (name);
|
||||
if (t)
|
||||
print_alias (t, dflags);
|
||||
else
|
||||
{
|
||||
sh_notfound (name);
|
||||
any_failed++;
|
||||
}
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
||||
}
|
||||
#endif /* ALIAS */
|
||||
|
||||
$BUILTIN unalias
|
||||
$FUNCTION unalias_builtin
|
||||
$DEPENDS_ON ALIAS
|
||||
$SHORT_DOC unalias [-a] name [name ...]
|
||||
Remove NAMEs from the list of defined aliases. If the -a option is given,
|
||||
then remove all alias definitions.
|
||||
$END
|
||||
|
||||
#if defined (ALIAS)
|
||||
/* Remove aliases named in LIST from the aliases database. */
|
||||
int
|
||||
unalias_builtin (list)
|
||||
register WORD_LIST *list;
|
||||
{
|
||||
register alias_t *alias;
|
||||
int opt, aflag;
|
||||
|
||||
aflag = 0;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "a")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'a':
|
||||
aflag = 1;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
list = loptend;
|
||||
|
||||
if (aflag)
|
||||
{
|
||||
delete_all_aliases ();
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
aflag = 0;
|
||||
while (list)
|
||||
{
|
||||
alias = find_alias (list->word->word);
|
||||
|
||||
if (alias)
|
||||
remove_alias (alias->name);
|
||||
else
|
||||
{
|
||||
sh_notfound (list->word->word);
|
||||
aflag++;
|
||||
}
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return (aflag ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* Output ALIAS in such a way as to allow it to be read back in. */
|
||||
static void
|
||||
print_alias (alias, flags)
|
||||
alias_t *alias;
|
||||
int flags;
|
||||
{
|
||||
char *value;
|
||||
|
||||
value = sh_single_quote (alias->value);
|
||||
if (flags & AL_REUSABLE)
|
||||
printf ("alias ");
|
||||
printf ("%s=%s\n", alias->name, value);
|
||||
free (value);
|
||||
|
||||
fflush (stdout);
|
||||
}
|
||||
#endif /* ALIAS */
|
||||
+2
-2
@@ -228,8 +228,8 @@ cd_builtin (list)
|
||||
is used to find the directory to change to, the new
|
||||
directory name is echoed to stdout, whether or not
|
||||
the shell is interactive. */
|
||||
if (opt)
|
||||
printf ("%s\n", no_symlinks ? temp : the_current_working_directory);
|
||||
if (opt && (path = no_symlinks ? temp : the_current_working_directory))
|
||||
printf ("%s\n", path);
|
||||
|
||||
free (temp);
|
||||
/* Posix.2 says that after using CDPATH, the resultant
|
||||
|
||||
+4023
File diff suppressed because it is too large
Load Diff
@@ -52,6 +52,7 @@ extern void print_cond_command __P((COND_COM *));
|
||||
|
||||
/* set -x support */
|
||||
extern char *indirection_level_string __P((void));
|
||||
extern void xtrace_print_assignment __P((char *, char *, int, int));
|
||||
extern void xtrace_print_word_list __P((WORD_LIST *, int));
|
||||
extern void xtrace_print_for_command_head __P((FOR_COM *));
|
||||
#if defined (SELECT_COMMAND)
|
||||
|
||||
+375
@@ -0,0 +1,375 @@
|
||||
/* externs.h -- extern function declarations which do not appear in their
|
||||
own header file. */
|
||||
|
||||
/* Copyright (C) 1993-2002 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 2, 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; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/* Make sure that this is included *after* config.h! */
|
||||
|
||||
#if !defined (_EXTERNS_H_)
|
||||
# define _EXTERNS_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
/* Functions from expr.c. */
|
||||
extern intmax_t evalexp __P((char *, int *));
|
||||
|
||||
/* Functions from print_cmd.c. */
|
||||
extern char *make_command_string __P((COMMAND *));
|
||||
extern char *named_function_string __P((char *, COMMAND *, int));
|
||||
|
||||
extern void print_command __P((COMMAND *));
|
||||
extern void print_simple_command __P((SIMPLE_COM *));
|
||||
extern void print_word_list __P((WORD_LIST *, char *));
|
||||
|
||||
/* debugger support */
|
||||
extern void print_for_command_head __P((FOR_COM *));
|
||||
#if defined (SELECT_COMMAND)
|
||||
extern void print_select_command_head __P((SELECT_COM *));
|
||||
#endif
|
||||
extern void print_case_command_head __P((CASE_COM *));
|
||||
#if defined (DPAREN_ARITHMETIC)
|
||||
extern void print_arith_command __P((WORD_LIST *));
|
||||
#endif
|
||||
#if defined (COND_COMMAND)
|
||||
extern void print_cond_command __P((COND_COM *));
|
||||
#endif
|
||||
|
||||
/* set -x support */
|
||||
extern char *indirection_level_string __P((void));
|
||||
extern void xtrace_print_assignment __P((char *, char *, int, int));
|
||||
extern void xtrace_print_word_list __P((WORD_LIST *, int));
|
||||
extern void xtrace_print_for_command_head __P((FOR_COM *));
|
||||
#if defined (SELECT_COMMAND)
|
||||
extern void xtrace_print_select_command_head __P((SELECT_COM *));
|
||||
#endif
|
||||
extern void xtrace_print_case_command_head __P((CASE_COM *));
|
||||
#if defined (DPAREN_ARITHMETIC)
|
||||
extern void xtrace_print_arith_cmd __P((WORD_LIST *));
|
||||
#endif
|
||||
#if defined (COND_COMMAND)
|
||||
extern void xtrace_print_cond_term __P((int, int, WORD_DESC *, char *, char *));
|
||||
#endif
|
||||
|
||||
/* Functions from shell.c. */
|
||||
extern void exit_shell __P((int)) __attribute__((__noreturn__));
|
||||
extern void sh_exit __P((int)) __attribute__((__noreturn__));
|
||||
extern void disable_priv_mode __P((void));
|
||||
extern void unbind_args __P((void));
|
||||
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
extern int shell_is_restricted __P((char *));
|
||||
extern int maybe_make_restricted __P((char *));
|
||||
#endif
|
||||
|
||||
extern void unset_bash_input __P((int));
|
||||
extern void get_current_user_info __P((void));
|
||||
|
||||
/* Functions from eval.c. */
|
||||
extern int reader_loop __P((void));
|
||||
extern int parse_command __P((void));
|
||||
extern int read_command __P((void));
|
||||
|
||||
/* Functions from braces.c. */
|
||||
#if defined (BRACE_EXPANSION)
|
||||
extern char **brace_expand __P((char *));
|
||||
#endif
|
||||
|
||||
/* Miscellaneous functions from parse.y */
|
||||
extern int yyparse __P((void));
|
||||
extern int return_EOF __P((void));
|
||||
extern void reset_parser __P((void));
|
||||
extern WORD_LIST *parse_string_to_word_list __P((char *, int, const char *));
|
||||
|
||||
extern void free_pushed_string_input __P((void));
|
||||
|
||||
extern char *decode_prompt_string __P((char *));
|
||||
|
||||
extern int get_current_prompt_level __P((void));
|
||||
extern void set_current_prompt_level __P((int));
|
||||
|
||||
#if defined (HISTORY)
|
||||
extern char *history_delimiting_chars __P((void));
|
||||
#endif
|
||||
|
||||
/* Declarations for functions defined in locale.c */
|
||||
extern void set_default_locale __P((void));
|
||||
extern void set_default_locale_vars __P((void));
|
||||
extern int set_locale_var __P((char *, char *));
|
||||
extern int set_lang __P((char *, char *));
|
||||
extern char *get_locale_var __P((char *));
|
||||
extern char *localetrans __P((char *, int, int *));
|
||||
extern char *mk_msgstr __P((char *, int *));
|
||||
extern char *localeexpand __P((char *, int, int, int, int *));
|
||||
|
||||
/* Declarations for functions defined in list.c. */
|
||||
extern void list_walk __P((GENERIC_LIST *, sh_glist_func_t *));
|
||||
extern void wlist_walk __P((WORD_LIST *, sh_icpfunc_t *));
|
||||
extern GENERIC_LIST *list_reverse ();
|
||||
extern int list_length ();
|
||||
extern GENERIC_LIST *list_append ();
|
||||
extern GENERIC_LIST *list_remove ();
|
||||
|
||||
/* Declarations for functions defined in stringlib.c */
|
||||
extern int find_string_in_alist __P((char *, STRING_INT_ALIST *, int));
|
||||
extern char *find_token_in_alist __P((int, STRING_INT_ALIST *, int));
|
||||
extern int find_index_in_alist __P((char *, STRING_INT_ALIST *, int));
|
||||
|
||||
extern char *substring __P((char *, int, int));
|
||||
extern char *strsub __P((char *, char *, char *, int));
|
||||
extern char *strcreplace __P((char *, int, char *, int));
|
||||
extern void strip_leading __P((char *));
|
||||
extern void strip_trailing __P((char *, int, int));
|
||||
extern void xbcopy __P((char *, char *, int));
|
||||
|
||||
/* Functions from version.c. */
|
||||
extern char *shell_version_string __P((void));
|
||||
extern void show_shell_version __P((int));
|
||||
|
||||
/* Functions from the bash library, lib/sh/libsh.a. These should really
|
||||
go into a separate include file. */
|
||||
|
||||
/* declarations for functions defined in lib/sh/clktck.c */
|
||||
extern long get_clk_tck __P((void));
|
||||
|
||||
/* declarations for functions defined in lib/sh/clock.c */
|
||||
extern void clock_t_to_secs ();
|
||||
extern void print_clock_t ();
|
||||
|
||||
/* Declarations for functions defined in lib/sh/fmtulong.c */
|
||||
#define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
|
||||
#define FL_ADDBASE 0x02 /* add base# prefix to converted value */
|
||||
#define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
|
||||
#define FL_UNSIGNED 0x08 /* don't add any sign */
|
||||
|
||||
extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
|
||||
|
||||
/* Declarations for functions defined in lib/sh/fmtulong.c */
|
||||
#if defined (HAVE_LONG_LONG)
|
||||
extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
|
||||
#endif
|
||||
|
||||
/* Declarations for functions defined in lib/sh/fmtumax.c */
|
||||
extern char *fmtumax __P((uintmax_t, int, char *, size_t, int));
|
||||
|
||||
/* Declarations for functions defined in lib/sh/getcwd.c */
|
||||
#if !defined (HAVE_GETCWD)
|
||||
extern char *getcwd __P((char *, size_t));
|
||||
#endif
|
||||
|
||||
/* Declarations for functions defined in lib/sh/itos.c */
|
||||
extern char *inttostr __P((intmax_t, char *, size_t));
|
||||
extern char *itos __P((intmax_t));
|
||||
extern char *uinttostr __P((uintmax_t, char *, size_t));
|
||||
extern char *uitos __P((uintmax_t));
|
||||
|
||||
/* declarations for functions defined in lib/sh/makepath.c */
|
||||
#define MP_DOTILDE 0x01
|
||||
#define MP_DOCWD 0x02
|
||||
#define MP_RMDOT 0x04
|
||||
|
||||
extern char *sh_makepath __P((const char *, const char *, int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/netconn.c */
|
||||
extern int isnetconn __P((int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/netopen.c */
|
||||
extern int netopen __P((char *));
|
||||
|
||||
/* Declarations for functions defined in lib/sh/oslib.c */
|
||||
|
||||
#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
|
||||
extern int dup2 __P((int, int));
|
||||
#endif
|
||||
|
||||
#if !defined (HAVE_GETDTABLESIZE)
|
||||
extern int getdtablesize __P((void));
|
||||
#endif /* !HAVE_GETDTABLESIZE */
|
||||
|
||||
#if !defined (HAVE_GETHOSTNAME)
|
||||
extern int gethostname __P((char *, int));
|
||||
#endif /* !HAVE_GETHOSTNAME */
|
||||
|
||||
extern int getmaxgroups __P((void));
|
||||
extern long getmaxchild __P((void));
|
||||
|
||||
/* declarations for functions defined in lib/sh/pathcanon.c */
|
||||
#define PATH_CHECKDOTDOT 0x0001
|
||||
#define PATH_CHECKEXISTS 0x0002
|
||||
#define PATH_HARDPATH 0x0004
|
||||
#define PATH_NOALLOC 0x0008
|
||||
|
||||
extern char *sh_canonpath __P((char *, int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/pathphys.c */
|
||||
extern char *sh_physpath __P((char *, int));
|
||||
extern char *sh_realpath __P((const char *, char *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/setlinebuf.c */
|
||||
#ifdef NEED_SH_SETLINEBUF_DECL
|
||||
extern int sh_setlinebuf __P((FILE *));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/shmatch.c */
|
||||
extern int sh_regmatch __P((const char *, const char *, int));
|
||||
|
||||
/* defines for flags argument to sh_regmatch. */
|
||||
#define SHMAT_SUBEXP 0x001 /* save subexpressions in SH_REMATCH */
|
||||
#define SHMAT_PWARN 0x002 /* print a warning message on invalid regexp */
|
||||
|
||||
/* declarations for functions defined in lib/sh/shquote.c */
|
||||
extern char *sh_single_quote __P((char *));
|
||||
extern char *sh_double_quote __P((char *));
|
||||
extern char *sh_un_double_quote __P((char *));
|
||||
extern char *sh_backslash_quote __P((char *));
|
||||
extern char *sh_backslash_quote_for_double_quotes __P((char *));
|
||||
extern int sh_contains_shell_metas __P((char *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/spell.c */
|
||||
extern int spname __P((char *, char *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/strcasecmp.c */
|
||||
#if !defined (HAVE_STRCASECMP)
|
||||
extern int strncasecmp __P((const char *, const char *, int));
|
||||
extern int strcasecmp __P((const char *, const char *));
|
||||
#endif /* HAVE_STRCASECMP */
|
||||
|
||||
/* declarations for functions defined in lib/sh/strerror.c */
|
||||
#if !defined (strerror)
|
||||
extern char *strerror __P((int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strftime.c */
|
||||
#if !defined (HAVE_STRFTIME) && defined (NEED_STRFTIME_DECL)
|
||||
extern size_t strftime __P((char *, size_t, const char *, const struct tm *));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strindex.c */
|
||||
extern char *strindex __P((const char *, const char *));
|
||||
|
||||
/* declarations for functions and structures defined in lib/sh/stringlist.c */
|
||||
|
||||
/* This is a general-purpose argv-style array struct. */
|
||||
typedef struct _list_of_strings {
|
||||
char **list;
|
||||
int list_size;
|
||||
int list_len;
|
||||
} STRINGLIST;
|
||||
|
||||
typedef int sh_strlist_map_func_t __P((char *));
|
||||
|
||||
extern STRINGLIST *strlist_create __P((int));
|
||||
extern STRINGLIST *strlist_resize __P((STRINGLIST *, int));
|
||||
extern void strlist_flush __P((STRINGLIST *));
|
||||
extern void strlist_dispose __P((STRINGLIST *));
|
||||
extern int strlist_remove __P((STRINGLIST *, char *));
|
||||
extern STRINGLIST *strlist_copy __P((STRINGLIST *));
|
||||
extern STRINGLIST *strlist_merge __P((STRINGLIST *, STRINGLIST *));
|
||||
extern STRINGLIST *strlist_append __P((STRINGLIST *, STRINGLIST *));
|
||||
extern STRINGLIST *strlist_prefix_suffix __P((STRINGLIST *, char *, char *));
|
||||
extern void strlist_print __P((STRINGLIST *, char *));
|
||||
extern void strlist_walk __P((STRINGLIST *, sh_strlist_map_func_t *));
|
||||
extern void strlist_sort __P((STRINGLIST *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/stringvec.c */
|
||||
|
||||
extern char **strvec_create __P((int));
|
||||
extern char **strvec_resize __P((char **, int));
|
||||
extern void strvec_flush __P((char **));
|
||||
extern void strvec_dispose __P((char **));
|
||||
extern int strvec_remove __P((char **, char *));
|
||||
extern int strvec_len __P((char **));
|
||||
extern int strvec_search __P((char **, char *));
|
||||
extern char **strvec_copy __P((char **));
|
||||
extern int strvec_strcmp __P((char **, char **));
|
||||
extern void strvec_sort __P((char **));
|
||||
|
||||
extern char **strvec_from_word_list __P((WORD_LIST *, int, int, int *));
|
||||
extern WORD_LIST *strvec_to_word_list __P((char **, int, int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtod.c */
|
||||
#if !defined (HAVE_STRTOD)
|
||||
extern double strtod __P((const char *, char **));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtol.c */
|
||||
#if !HAVE_DECL_STRTOL
|
||||
extern long strtol __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtoll.c */
|
||||
#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOLL
|
||||
extern long long strtoll __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtoul.c */
|
||||
#if !HAVE_DECL_STRTOUL
|
||||
extern unsigned long strtoul __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtoull.c */
|
||||
#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOULL
|
||||
extern unsigned long long strtoull __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strimax.c */
|
||||
#if !HAVE_DECL_STRTOIMAX
|
||||
extern intmax_t strtoimax __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strumax.c */
|
||||
#if !HAVE_DECL_STRTOUMAX
|
||||
extern uintmax_t strtoumax __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtrans.c */
|
||||
extern char *ansicstr __P((char *, int, int, int *, int *));
|
||||
extern char *ansic_quote __P((char *, int, int *));
|
||||
extern int ansic_shouldquote __P((const char *));
|
||||
extern char *ansiexpand __P((char *, int, int, int *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/timeval.c. No prototypes
|
||||
so we don't have to count on having a definition of struct timeval in
|
||||
scope when this file is included. */
|
||||
extern void timeval_to_secs ();
|
||||
extern void print_timeval ();
|
||||
|
||||
/* declarations for functions defined in lib/sh/tmpfile.c */
|
||||
#define MT_USETMPDIR 0x0001
|
||||
#define MT_READWRITE 0x0002
|
||||
#define MT_USERANDOM 0x0004
|
||||
|
||||
extern char *sh_mktmpname __P((char *, int));
|
||||
extern int sh_mktmpfd __P((char *, int, char **));
|
||||
/* extern FILE *sh_mktmpfp __P((char *, int, char **)); */
|
||||
|
||||
/* declarations for functions defined in lib/sh/xstrchr.c */
|
||||
#undef xstrchr
|
||||
extern char *xstrchr __P((const char *, int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/zread.c */
|
||||
extern ssize_t zread __P((int, char *, size_t));
|
||||
extern ssize_t zreadintr __P((int, char *, size_t));
|
||||
extern ssize_t zreadc __P((int, char *));
|
||||
extern void zreset __P((void));
|
||||
extern void zsyncfd __P((int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/zwrite.c */
|
||||
extern int zwrite __P((int, char *, size_t));
|
||||
|
||||
#endif /* _EXTERNS_H_ */
|
||||
@@ -238,6 +238,22 @@ check_identifier (word, check_word)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Return 1 if STRING comprises a valid alias name. The shell accepts
|
||||
essentially all characters except those which must be quoted to the
|
||||
parser (which disqualifies them from alias expansion anyway) and `/'. */
|
||||
int
|
||||
legal_alias_name (string, flags)
|
||||
char *string;
|
||||
int flags;
|
||||
{
|
||||
register char *s;
|
||||
|
||||
for (s = string; *s; s++)
|
||||
if (shellbreak (*s) || shellxquote (*s) || shellexp (*s) || (*s == '/'))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns non-zero if STRING is an assignment statement. The returned value
|
||||
is the index of the `=' sign. */
|
||||
int
|
||||
|
||||
+958
@@ -0,0 +1,958 @@
|
||||
/* general.c -- Stuff that is used by all files. */
|
||||
|
||||
/* Copyright (C) 1987-2004 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 2, 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; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "bashtypes.h"
|
||||
#ifndef _MINIX
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#include "posixstat.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "filecntl.h"
|
||||
#include "bashansi.h"
|
||||
#include <stdio.h>
|
||||
#include "chartypes.h"
|
||||
#include <errno.h>
|
||||
|
||||
#include "bashintl.h"
|
||||
|
||||
#include "shell.h"
|
||||
#include <tilde/tilde.h>
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
extern int expand_aliases;
|
||||
extern int interrupt_immediately;
|
||||
extern int interactive_comments;
|
||||
extern int check_hashed_filenames;
|
||||
extern int source_uses_path;
|
||||
extern int source_searches_cwd;
|
||||
|
||||
static char *bash_special_tilde_expansions __P((char *));
|
||||
static int unquoted_tilde_word __P((const char *));
|
||||
static void initialize_group_array __P((void));
|
||||
|
||||
/* A standard error message to use when getcwd() returns NULL. */
|
||||
char *bash_getcwd_errstr = N_("getcwd: cannot access parent directories");
|
||||
|
||||
/* Do whatever is necessary to initialize `Posix mode'. */
|
||||
void
|
||||
posix_initialize (on)
|
||||
int on;
|
||||
{
|
||||
/* Things that should be turned on when posix mode is enabled. */
|
||||
if (on != 0)
|
||||
{
|
||||
interactive_comments = source_uses_path = expand_aliases = 1;
|
||||
}
|
||||
|
||||
/* Things that should be turned on when posix mode is disabled. */
|
||||
if (on == 0)
|
||||
{
|
||||
source_searches_cwd = 1;
|
||||
expand_aliases = interactive_shell;
|
||||
}
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions to convert to and from and display non-standard types */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
#if defined (RLIMTYPE)
|
||||
RLIMTYPE
|
||||
string_to_rlimtype (s)
|
||||
char *s;
|
||||
{
|
||||
RLIMTYPE ret;
|
||||
int neg;
|
||||
|
||||
ret = 0;
|
||||
neg = 0;
|
||||
while (s && *s && whitespace (*s))
|
||||
s++;
|
||||
if (*s == '-' || *s == '+')
|
||||
{
|
||||
neg = *s == '-';
|
||||
s++;
|
||||
}
|
||||
for ( ; s && *s && DIGIT (*s); s++)
|
||||
ret = (ret * 10) + TODIGIT (*s);
|
||||
return (neg ? -ret : ret);
|
||||
}
|
||||
|
||||
void
|
||||
print_rlimtype (n, addnl)
|
||||
RLIMTYPE n;
|
||||
int addnl;
|
||||
{
|
||||
char s[INT_STRLEN_BOUND (RLIMTYPE) + 1], *p;
|
||||
|
||||
p = s + sizeof(s);
|
||||
*--p = '\0';
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
do
|
||||
*--p = '0' - n % 10;
|
||||
while ((n /= 10) != 0);
|
||||
|
||||
*--p = '-';
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
*--p = '0' + n % 10;
|
||||
while ((n /= 10) != 0);
|
||||
}
|
||||
|
||||
printf ("%s%s", p, addnl ? "\n" : "");
|
||||
}
|
||||
#endif /* RLIMTYPE */
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Input Validation Functions */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Return non-zero if all of the characters in STRING are digits. */
|
||||
int
|
||||
all_digits (string)
|
||||
char *string;
|
||||
{
|
||||
register char *s;
|
||||
|
||||
for (s = string; *s; s++)
|
||||
if (DIGIT (*s) == 0)
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Return non-zero if the characters pointed to by STRING constitute a
|
||||
valid number. Stuff the converted number into RESULT if RESULT is
|
||||
not null. */
|
||||
int
|
||||
legal_number (string, result)
|
||||
char *string;
|
||||
intmax_t *result;
|
||||
{
|
||||
intmax_t value;
|
||||
char *ep;
|
||||
|
||||
if (result)
|
||||
*result = 0;
|
||||
|
||||
errno = 0;
|
||||
value = strtoimax (string, &ep, 10);
|
||||
if (errno)
|
||||
return 0; /* errno is set on overflow or underflow */
|
||||
|
||||
/* Skip any trailing whitespace, since strtoimax does not. */
|
||||
while (whitespace (*ep))
|
||||
ep++;
|
||||
|
||||
/* If *string is not '\0' but *ep is '\0' on return, the entire string
|
||||
is valid. */
|
||||
if (string && *string && *ep == '\0')
|
||||
{
|
||||
if (result)
|
||||
*result = value;
|
||||
/* The SunOS4 implementation of strtol() will happily ignore
|
||||
overflow conditions, so this cannot do overflow correctly
|
||||
on those systems. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Return 1 if this token is a legal shell `identifier'; that is, it consists
|
||||
solely of letters, digits, and underscores, and does not begin with a
|
||||
digit. */
|
||||
int
|
||||
legal_identifier (name)
|
||||
char *name;
|
||||
{
|
||||
register char *s;
|
||||
unsigned char c;
|
||||
|
||||
if (!name || !(c = *name) || (legal_variable_starter (c) == 0))
|
||||
return (0);
|
||||
|
||||
for (s = name + 1; (c = *s) != 0; s++)
|
||||
{
|
||||
if (legal_variable_char (c) == 0)
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Make sure that WORD is a valid shell identifier, i.e.
|
||||
does not contain a dollar sign, nor is quoted in any way. Nor
|
||||
does it consist of all digits. If CHECK_WORD is non-zero,
|
||||
the word is checked to ensure that it consists of only letters,
|
||||
digits, and underscores. */
|
||||
int
|
||||
check_identifier (word, check_word)
|
||||
WORD_DESC *word;
|
||||
int check_word;
|
||||
{
|
||||
if ((word->flags & (W_HASDOLLAR|W_QUOTED)) || all_digits (word->word))
|
||||
{
|
||||
internal_error (_("`%s': not a valid identifier"), word->word);
|
||||
return (0);
|
||||
}
|
||||
else if (check_word && legal_identifier (word->word) == 0)
|
||||
{
|
||||
internal_error (_("`%s': not a valid identifier"), word->word);
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Return 1 if STRING comprises a valid alias name. The shell accepts
|
||||
essentially all characters except those which must be quoted to the
|
||||
parser (which disqualifies them from alias expansion anyway) and `/'. */
|
||||
int
|
||||
legal_alias_name (string, flags)
|
||||
char *string;
|
||||
int flags;
|
||||
{
|
||||
register char *s;
|
||||
|
||||
for (s = string; *s; s++)
|
||||
if (shellbreak (*s) || shellquote (*s) || shellexp (*s) || (*s == '/'))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns non-zero if STRING is an assignment statement. The returned value
|
||||
is the index of the `=' sign. */
|
||||
int
|
||||
assignment (string, flags)
|
||||
const char *string;
|
||||
int flags;
|
||||
{
|
||||
register unsigned char c;
|
||||
register int newi, indx;
|
||||
|
||||
c = string[indx = 0];
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if ((legal_variable_starter (c) == 0) && (flags && c != '[')) /* ] */
|
||||
#else
|
||||
if (legal_variable_starter (c) == 0)
|
||||
#endif
|
||||
return (0);
|
||||
|
||||
while (c = string[indx])
|
||||
{
|
||||
/* The following is safe. Note that '=' at the start of a word
|
||||
is not an assignment statement. */
|
||||
if (c == '=')
|
||||
return (indx);
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if (c == '[')
|
||||
{
|
||||
newi = skipsubscript (string, indx);
|
||||
if (string[newi++] != ']')
|
||||
return (0);
|
||||
return ((string[newi] == '=') ? newi : 0);
|
||||
}
|
||||
#endif /* ARRAY_VARS */
|
||||
|
||||
/* Variable names in assignment statements may contain only letters,
|
||||
digits, and `_'. */
|
||||
if (legal_variable_char (c) == 0)
|
||||
return (0);
|
||||
|
||||
indx++;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions to manage files and file descriptors */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* A function to unset no-delay mode on a file descriptor. Used in shell.c
|
||||
to unset it on the fd passed as stdin. Should be called on stdin if
|
||||
readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
|
||||
|
||||
#if !defined (O_NDELAY)
|
||||
# if defined (FNDELAY)
|
||||
# define O_NDELAY FNDELAY
|
||||
# endif
|
||||
#endif /* O_NDELAY */
|
||||
|
||||
/* Make sure no-delay mode is not set on file descriptor FD. */
|
||||
int
|
||||
sh_unset_nodelay_mode (fd)
|
||||
int fd;
|
||||
{
|
||||
int flags, bflags;
|
||||
|
||||
if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
|
||||
return -1;
|
||||
|
||||
bflags = 0;
|
||||
|
||||
/* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
|
||||
and O_NDELAY is defined. */
|
||||
#ifdef O_NONBLOCK
|
||||
bflags |= O_NONBLOCK;
|
||||
#endif
|
||||
|
||||
#ifdef O_NDELAY
|
||||
bflags |= O_NDELAY;
|
||||
#endif
|
||||
|
||||
if (flags & bflags)
|
||||
{
|
||||
flags &= ~bflags;
|
||||
return (fcntl (fd, F_SETFL, flags));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return 1 if file descriptor FD is valid; 0 otherwise. */
|
||||
int
|
||||
sh_validfd (fd)
|
||||
int fd;
|
||||
{
|
||||
return (fcntl (fd, F_GETFD, 0) >= 0);
|
||||
}
|
||||
|
||||
/* There is a bug in the NeXT 2.1 rlogind that causes opens
|
||||
of /dev/tty to fail. */
|
||||
|
||||
#if defined (__BEOS__)
|
||||
/* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
|
||||
into a no-op. This should probably go away in the future. */
|
||||
# undef O_NONBLOCK
|
||||
# define O_NONBLOCK 0
|
||||
#endif /* __BEOS__ */
|
||||
|
||||
void
|
||||
check_dev_tty ()
|
||||
{
|
||||
int tty_fd;
|
||||
char *tty;
|
||||
|
||||
tty_fd = open ("/dev/tty", O_RDWR|O_NONBLOCK);
|
||||
|
||||
if (tty_fd < 0)
|
||||
{
|
||||
tty = (char *)ttyname (fileno (stdin));
|
||||
if (tty == 0)
|
||||
return;
|
||||
tty_fd = open (tty, O_RDWR|O_NONBLOCK);
|
||||
}
|
||||
close (tty_fd);
|
||||
}
|
||||
|
||||
/* Return 1 if PATH1 and PATH2 are the same file. This is kind of
|
||||
expensive. If non-NULL STP1 and STP2 point to stat structures
|
||||
corresponding to PATH1 and PATH2, respectively. */
|
||||
int
|
||||
same_file (path1, path2, stp1, stp2)
|
||||
char *path1, *path2;
|
||||
struct stat *stp1, *stp2;
|
||||
{
|
||||
struct stat st1, st2;
|
||||
|
||||
if (stp1 == NULL)
|
||||
{
|
||||
if (stat (path1, &st1) != 0)
|
||||
return (0);
|
||||
stp1 = &st1;
|
||||
}
|
||||
|
||||
if (stp2 == NULL)
|
||||
{
|
||||
if (stat (path2, &st2) != 0)
|
||||
return (0);
|
||||
stp2 = &st2;
|
||||
}
|
||||
|
||||
return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
|
||||
}
|
||||
|
||||
/* Move FD to a number close to the maximum number of file descriptors
|
||||
allowed in the shell process, to avoid the user stepping on it with
|
||||
redirection and causing us extra work. If CHECK_NEW is non-zero,
|
||||
we check whether or not the file descriptors are in use before
|
||||
duplicating FD onto them. MAXFD says where to start checking the
|
||||
file descriptors. If it's less than 20, we get the maximum value
|
||||
available from getdtablesize(2). */
|
||||
int
|
||||
move_to_high_fd (fd, check_new, maxfd)
|
||||
int fd, check_new, maxfd;
|
||||
{
|
||||
int script_fd, nfds, ignore;
|
||||
|
||||
if (maxfd < 20)
|
||||
{
|
||||
nfds = getdtablesize ();
|
||||
if (nfds <= 0)
|
||||
nfds = 20;
|
||||
if (nfds > HIGH_FD_MAX)
|
||||
nfds = HIGH_FD_MAX; /* reasonable maximum */
|
||||
}
|
||||
else
|
||||
nfds = maxfd;
|
||||
|
||||
for (nfds--; check_new && nfds > 3; nfds--)
|
||||
if (fcntl (nfds, F_GETFD, &ignore) == -1)
|
||||
break;
|
||||
|
||||
if (nfds > 3 && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
|
||||
{
|
||||
if (check_new == 0 || fd != fileno (stderr)) /* don't close stderr */
|
||||
close (fd);
|
||||
return (script_fd);
|
||||
}
|
||||
|
||||
/* OK, we didn't find one less than our artificial maximum; return the
|
||||
original file descriptor. */
|
||||
return (fd);
|
||||
}
|
||||
|
||||
/* Return non-zero if the characters from SAMPLE are not all valid
|
||||
characters to be found in the first line of a shell script. We
|
||||
check up to the first newline, or SAMPLE_LEN, whichever comes first.
|
||||
All of the characters must be printable or whitespace. */
|
||||
|
||||
int
|
||||
check_binary_file (sample, sample_len)
|
||||
char *sample;
|
||||
int sample_len;
|
||||
{
|
||||
register int i;
|
||||
unsigned char c;
|
||||
|
||||
for (i = 0; i < sample_len; i++)
|
||||
{
|
||||
c = sample[i];
|
||||
if (c == '\n')
|
||||
return (0);
|
||||
|
||||
if (ISSPACE (c) == 0 && ISPRINT (c) == 0)
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions to inspect pathnames */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
int
|
||||
file_isdir (fn)
|
||||
char *fn;
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
return ((stat (fn, &sb) == 0) && S_ISDIR (sb.st_mode));
|
||||
}
|
||||
|
||||
int
|
||||
file_iswdir (fn)
|
||||
char *fn;
|
||||
{
|
||||
return (file_isdir (fn) && test_eaccess (fn, W_OK) == 0);
|
||||
}
|
||||
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions to manipulate pathnames */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Turn STRING (a pathname) into an absolute pathname, assuming that
|
||||
DOT_PATH contains the symbolic location of `.'. This always
|
||||
returns a new string, even if STRING was an absolute pathname to
|
||||
begin with. */
|
||||
char *
|
||||
make_absolute (string, dot_path)
|
||||
char *string, *dot_path;
|
||||
{
|
||||
char *result;
|
||||
|
||||
if (dot_path == 0 || ABSPATH(string))
|
||||
#ifdef __CYGWIN__
|
||||
{
|
||||
char pathbuf[PATH_MAX + 1];
|
||||
|
||||
cygwin_conv_to_full_posix_path (string, pathbuf);
|
||||
result = savestring (pathbuf);
|
||||
}
|
||||
#else
|
||||
result = savestring (string);
|
||||
#endif
|
||||
else
|
||||
result = sh_makepath (dot_path, string, 0);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd'
|
||||
to decide whether or not to look up a directory name in $CDPATH. */
|
||||
int
|
||||
absolute_pathname (string)
|
||||
const char *string;
|
||||
{
|
||||
if (string == 0 || *string == '\0')
|
||||
return (0);
|
||||
|
||||
if (ABSPATH(string))
|
||||
return (1);
|
||||
|
||||
if (string[0] == '.' && PATHSEP(string[1])) /* . and ./ */
|
||||
return (1);
|
||||
|
||||
if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2])) /* .. and ../ */
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Return 1 if STRING is an absolute program name; it is absolute if it
|
||||
contains any slashes. This is used to decide whether or not to look
|
||||
up through $PATH. */
|
||||
int
|
||||
absolute_program (string)
|
||||
const char *string;
|
||||
{
|
||||
return ((char *)xstrchr (string, '/') != (char *)NULL);
|
||||
}
|
||||
|
||||
/* Return the `basename' of the pathname in STRING (the stuff after the
|
||||
last '/'). If STRING is not a full pathname, simply return it. */
|
||||
char *
|
||||
base_pathname (string)
|
||||
char *string;
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (absolute_pathname (string) == 0)
|
||||
return (string);
|
||||
|
||||
p = (char *)strrchr (string, '/');
|
||||
return (p ? ++p : string);
|
||||
}
|
||||
|
||||
/* Return the full pathname of FILE. Easy. Filenames that begin
|
||||
with a '/' are returned as themselves. Other filenames have
|
||||
the current working directory prepended. A new string is
|
||||
returned in either case. */
|
||||
char *
|
||||
full_pathname (file)
|
||||
char *file;
|
||||
{
|
||||
char *ret;
|
||||
|
||||
file = (*file == '~') ? bash_tilde_expand (file, 0) : savestring (file);
|
||||
|
||||
if (ABSPATH(file))
|
||||
return (file);
|
||||
|
||||
ret = sh_makepath ((char *)NULL, file, (MP_DOCWD|MP_RMDOT));
|
||||
free (file);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* A slightly related function. Get the prettiest name of this
|
||||
directory possible. */
|
||||
static char tdir[PATH_MAX];
|
||||
|
||||
/* Return a pretty pathname. If the first part of the pathname is
|
||||
the same as $HOME, then replace that with `~'. */
|
||||
char *
|
||||
polite_directory_format (name)
|
||||
char *name;
|
||||
{
|
||||
char *home;
|
||||
int l;
|
||||
|
||||
home = get_string_value ("HOME");
|
||||
l = home ? strlen (home) : 0;
|
||||
if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
|
||||
{
|
||||
strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
|
||||
tdir[0] = '~';
|
||||
tdir[sizeof(tdir) - 1] = '\0';
|
||||
return (tdir);
|
||||
}
|
||||
else
|
||||
return (name);
|
||||
}
|
||||
|
||||
/* Given a string containing units of information separated by colons,
|
||||
return the next one pointed to by (P_INDEX), or NULL if there are no more.
|
||||
Advance (P_INDEX) to the character after the colon. */
|
||||
char *
|
||||
extract_colon_unit (string, p_index)
|
||||
char *string;
|
||||
int *p_index;
|
||||
{
|
||||
int i, start, len;
|
||||
char *value;
|
||||
|
||||
if (string == 0)
|
||||
return (string);
|
||||
|
||||
len = strlen (string);
|
||||
if (*p_index >= len)
|
||||
return ((char *)NULL);
|
||||
|
||||
i = *p_index;
|
||||
|
||||
/* Each call to this routine leaves the index pointing at a colon if
|
||||
there is more to the path. If I is > 0, then increment past the
|
||||
`:'. If I is 0, then the path has a leading colon. Trailing colons
|
||||
are handled OK by the `else' part of the if statement; an empty
|
||||
string is returned in that case. */
|
||||
if (i && string[i] == ':')
|
||||
i++;
|
||||
|
||||
for (start = i; string[i] && string[i] != ':'; i++)
|
||||
;
|
||||
|
||||
*p_index = i;
|
||||
|
||||
if (i == start)
|
||||
{
|
||||
if (string[i])
|
||||
(*p_index)++;
|
||||
/* Return "" in the case of a trailing `:'. */
|
||||
value = (char *)xmalloc (1);
|
||||
value[0] = '\0';
|
||||
}
|
||||
else
|
||||
value = substring (string, start, i);
|
||||
|
||||
return (value);
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Tilde Initialization and Expansion */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
#if defined (PUSHD_AND_POPD)
|
||||
extern char *get_dirstack_from_string __P((char *));
|
||||
#endif
|
||||
|
||||
static char **bash_tilde_prefixes;
|
||||
static char **bash_tilde_suffixes;
|
||||
|
||||
/* If tilde_expand hasn't been able to expand the text, perhaps it
|
||||
is a special shell expansion. This function is installed as the
|
||||
tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
|
||||
If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
|
||||
directory stack. */
|
||||
static char *
|
||||
bash_special_tilde_expansions (text)
|
||||
char *text;
|
||||
{
|
||||
char *result;
|
||||
|
||||
result = (char *)NULL;
|
||||
|
||||
if (text[0] == '+' && text[1] == '\0')
|
||||
result = get_string_value ("PWD");
|
||||
else if (text[0] == '-' && text[1] == '\0')
|
||||
result = get_string_value ("OLDPWD");
|
||||
#if defined (PUSHD_AND_POPD)
|
||||
else if (DIGIT (*text) || ((*text == '+' || *text == '-') && DIGIT (text[1])))
|
||||
result = get_dirstack_from_string (text);
|
||||
#endif
|
||||
|
||||
return (result ? savestring (result) : (char *)NULL);
|
||||
}
|
||||
|
||||
/* Initialize the tilde expander. In Bash, we handle `~-' and `~+', as
|
||||
well as handling special tilde prefixes; `:~" and `=~' are indications
|
||||
that we should do tilde expansion. */
|
||||
void
|
||||
tilde_initialize ()
|
||||
{
|
||||
static int times_called = 0;
|
||||
|
||||
/* Tell the tilde expander that we want a crack first. */
|
||||
tilde_expansion_preexpansion_hook = bash_special_tilde_expansions;
|
||||
|
||||
/* Tell the tilde expander about special strings which start a tilde
|
||||
expansion, and the special strings that end one. Only do this once.
|
||||
tilde_initialize () is called from within bashline_reinitialize (). */
|
||||
if (times_called++ == 0)
|
||||
{
|
||||
bash_tilde_prefixes = strvec_create (3);
|
||||
bash_tilde_prefixes[0] = "=~";
|
||||
bash_tilde_prefixes[1] = ":~";
|
||||
bash_tilde_prefixes[2] = (char *)NULL;
|
||||
|
||||
tilde_additional_prefixes = bash_tilde_prefixes;
|
||||
|
||||
bash_tilde_suffixes = strvec_create (3);
|
||||
bash_tilde_suffixes[0] = ":";
|
||||
bash_tilde_suffixes[1] = "=~"; /* XXX - ?? */
|
||||
bash_tilde_suffixes[2] = (char *)NULL;
|
||||
|
||||
tilde_additional_suffixes = bash_tilde_suffixes;
|
||||
}
|
||||
}
|
||||
|
||||
/* POSIX.2, 3.6.1: A tilde-prefix consists of an unquoted tilde character
|
||||
at the beginning of the word, followed by all of the characters preceding
|
||||
the first unquoted slash in the word, or all the characters in the word
|
||||
if there is no slash...If none of the characters in the tilde-prefix are
|
||||
quoted, the characters in the tilde-prefix following the tilde shell be
|
||||
treated as a possible login name. */
|
||||
|
||||
#define TILDE_END(c) ((c) == '\0' || (c) == '/' || (c) == ':')
|
||||
|
||||
static int
|
||||
unquoted_tilde_word (s)
|
||||
const char *s;
|
||||
{
|
||||
const char *r;
|
||||
|
||||
for (r = s; TILDE_END(*r) == 0; r++)
|
||||
{
|
||||
switch (*r)
|
||||
{
|
||||
case '\\':
|
||||
case '\'':
|
||||
case '"':
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Tilde-expand S by running it through the tilde expansion library.
|
||||
ASSIGN_P is 1 if this is a variable assignment, so the alternate
|
||||
tilde prefixes should be enabled (`=~' and `:~', see above). */
|
||||
char *
|
||||
bash_tilde_expand (s, assign_p)
|
||||
const char *s;
|
||||
int assign_p;
|
||||
{
|
||||
int old_immed, r;
|
||||
char *ret;
|
||||
|
||||
old_immed = interrupt_immediately;
|
||||
interrupt_immediately = 1;
|
||||
tilde_additional_prefixes = assign_p ? bash_tilde_prefixes : (char **)0;
|
||||
r = (*s == '~') ? unquoted_tilde_word (s) : 1;
|
||||
ret = r ? tilde_expand (s) : savestring (s);
|
||||
interrupt_immediately = old_immed;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions to manipulate and search the group list */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
static int ngroups, maxgroups;
|
||||
|
||||
/* The set of groups that this user is a member of. */
|
||||
static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
|
||||
|
||||
#if !defined (NOGROUP)
|
||||
# define NOGROUP (gid_t) -1
|
||||
#endif
|
||||
|
||||
static void
|
||||
initialize_group_array ()
|
||||
{
|
||||
register int i;
|
||||
|
||||
if (maxgroups == 0)
|
||||
maxgroups = getmaxgroups ();
|
||||
|
||||
ngroups = 0;
|
||||
group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
|
||||
|
||||
#if defined (HAVE_GETGROUPS)
|
||||
ngroups = getgroups (maxgroups, group_array);
|
||||
#endif
|
||||
|
||||
/* If getgroups returns nothing, or the OS does not support getgroups(),
|
||||
make sure the groups array includes at least the current gid. */
|
||||
if (ngroups == 0)
|
||||
{
|
||||
group_array[0] = current_user.gid;
|
||||
ngroups = 1;
|
||||
}
|
||||
|
||||
/* If the primary group is not in the groups array, add it as group_array[0]
|
||||
and shuffle everything else up 1, if there's room. */
|
||||
for (i = 0; i < ngroups; i++)
|
||||
if (current_user.gid == (gid_t)group_array[i])
|
||||
break;
|
||||
if (i == ngroups && ngroups < maxgroups)
|
||||
{
|
||||
for (i = ngroups; i > 0; i--)
|
||||
group_array[i] = group_array[i - 1];
|
||||
group_array[0] = current_user.gid;
|
||||
ngroups++;
|
||||
}
|
||||
|
||||
/* If the primary group is not group_array[0], swap group_array[0] and
|
||||
whatever the current group is. The vast majority of systems should
|
||||
not need this; a notable exception is Linux. */
|
||||
if (group_array[0] != current_user.gid)
|
||||
{
|
||||
for (i = 0; i < ngroups; i++)
|
||||
if (group_array[i] == current_user.gid)
|
||||
break;
|
||||
if (i < ngroups)
|
||||
{
|
||||
group_array[i] = group_array[0];
|
||||
group_array[0] = current_user.gid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return non-zero if GID is one that we have in our groups list. */
|
||||
int
|
||||
#if defined (__STDC__) || defined ( _MINIX)
|
||||
group_member (gid_t gid)
|
||||
#else
|
||||
group_member (gid)
|
||||
gid_t gid;
|
||||
#endif /* !__STDC__ && !_MINIX */
|
||||
{
|
||||
#if defined (HAVE_GETGROUPS)
|
||||
register int i;
|
||||
#endif
|
||||
|
||||
/* Short-circuit if possible, maybe saving a call to getgroups(). */
|
||||
if (gid == current_user.gid || gid == current_user.egid)
|
||||
return (1);
|
||||
|
||||
#if defined (HAVE_GETGROUPS)
|
||||
if (ngroups == 0)
|
||||
initialize_group_array ();
|
||||
|
||||
/* In case of error, the user loses. */
|
||||
if (ngroups <= 0)
|
||||
return (0);
|
||||
|
||||
/* Search through the list looking for GID. */
|
||||
for (i = 0; i < ngroups; i++)
|
||||
if (gid == (gid_t)group_array[i])
|
||||
return (1);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
char **
|
||||
get_group_list (ngp)
|
||||
int *ngp;
|
||||
{
|
||||
static char **group_vector = (char **)NULL;
|
||||
register int i;
|
||||
|
||||
if (group_vector)
|
||||
{
|
||||
if (ngp)
|
||||
*ngp = ngroups;
|
||||
return group_vector;
|
||||
}
|
||||
|
||||
if (ngroups == 0)
|
||||
initialize_group_array ();
|
||||
|
||||
if (ngroups <= 0)
|
||||
{
|
||||
if (ngp)
|
||||
*ngp = 0;
|
||||
return (char **)NULL;
|
||||
}
|
||||
|
||||
group_vector = strvec_create (ngroups);
|
||||
for (i = 0; i < ngroups; i++)
|
||||
group_vector[i] = itos (group_array[i]);
|
||||
|
||||
if (ngp)
|
||||
*ngp = ngroups;
|
||||
return group_vector;
|
||||
}
|
||||
|
||||
int *
|
||||
get_group_array (ngp)
|
||||
int *ngp;
|
||||
{
|
||||
int i;
|
||||
static int *group_iarray = (int *)NULL;
|
||||
|
||||
if (group_iarray)
|
||||
{
|
||||
if (ngp)
|
||||
*ngp = ngroups;
|
||||
return (group_iarray);
|
||||
}
|
||||
|
||||
if (ngroups == 0)
|
||||
initialize_group_array ();
|
||||
|
||||
if (ngroups <= 0)
|
||||
{
|
||||
if (ngp)
|
||||
*ngp = 0;
|
||||
return (int *)NULL;
|
||||
}
|
||||
|
||||
group_iarray = (int *)xmalloc (ngroups * sizeof (int));
|
||||
for (i = 0; i < ngroups; i++)
|
||||
group_iarray[i] = (int)group_array[i];
|
||||
|
||||
if (ngp)
|
||||
*ngp = ngroups;
|
||||
return group_iarray;
|
||||
}
|
||||
@@ -277,6 +277,7 @@ extern int all_digits __P((char *));
|
||||
extern int legal_number __P((char *, intmax_t *));
|
||||
extern int legal_identifier __P((char *));
|
||||
extern int check_identifier __P((WORD_DESC *, int));
|
||||
extern int legal_alias_name __P((char *, int));
|
||||
extern int assignment __P((const char *, int));
|
||||
|
||||
extern int sh_unset_nodelay_mode __P((int));
|
||||
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
/* general.h -- defines that everybody likes to use. */
|
||||
|
||||
/* Copyright (C) 1993-2004 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 2, 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; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#if !defined (_GENERAL_H_)
|
||||
#define _GENERAL_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
#include "bashtypes.h"
|
||||
|
||||
#if defined (HAVE_SYS_RESOURCE_H) && defined (RLIMTYPE)
|
||||
# if defined (HAVE_SYS_TIME_H)
|
||||
# include <sys/time.h>
|
||||
# endif
|
||||
# include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_STRING_H)
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
#endif /* !HAVE_STRING_H */
|
||||
|
||||
#if defined (HAVE_LIMITS_H)
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* NULL pointer type. */
|
||||
#if !defined (NULL)
|
||||
# if defined (__STDC__)
|
||||
# define NULL ((void *) 0)
|
||||
# else
|
||||
# define NULL 0x0
|
||||
# endif /* !__STDC__ */
|
||||
#endif /* !NULL */
|
||||
|
||||
/* Hardly used anymore */
|
||||
#define pointer_to_int(x) (int)((char *)x - (char *)0)
|
||||
|
||||
#if defined (alpha) && defined (__GNUC__) && !defined (strchr) && !defined (__STDC__)
|
||||
extern char *strchr (), *strrchr ();
|
||||
#endif
|
||||
|
||||
#if !defined (strcpy) && (defined (HAVE_DECL_STRCPY) && !HAVE_DECL_STRCPY)
|
||||
extern char *strcpy __P((char *, const char *));
|
||||
#endif
|
||||
|
||||
#if !defined (savestring)
|
||||
# define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
|
||||
#endif
|
||||
|
||||
#ifndef member
|
||||
# define member(c, s) ((c) ? ((char *)xstrchr ((s), (c)) != (char *)NULL) : 0)
|
||||
#endif
|
||||
|
||||
#ifndef whitespace
|
||||
#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
|
||||
#endif
|
||||
|
||||
#ifndef CHAR_MAX
|
||||
# ifdef __CHAR_UNSIGNED__
|
||||
# define CHAR_MAX 0xff
|
||||
# else
|
||||
# define CHAR_MAX 0x7f
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
/* Nonzero if the integer type T is signed. */
|
||||
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
|
||||
/* Bound on length of the string representing an integer value of type T.
|
||||
Subtract one for the sign bit if T is signed;
|
||||
302 / 1000 is log10 (2) rounded up;
|
||||
add one for integer division truncation;
|
||||
add one more for a minus sign if t is signed. */
|
||||
#define INT_STRLEN_BOUND(t) \
|
||||
((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
|
||||
+ 1 + TYPE_SIGNED (t))
|
||||
|
||||
|
||||
/* Define exactly what a legal shell identifier consists of. */
|
||||
#define legal_variable_starter(c) (ISALPHA(c) || (c == '_'))
|
||||
#define legal_variable_char(c) (ISALNUM(c) || c == '_')
|
||||
|
||||
/* Definitions used in subst.c and by the `read' builtin for field
|
||||
splitting. */
|
||||
#define spctabnl(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
|
||||
|
||||
/* All structs which contain a `next' field should have that field
|
||||
as the first field in the struct. This means that functions
|
||||
can be written to handle the general case for linked lists. */
|
||||
typedef struct g_list {
|
||||
struct g_list *next;
|
||||
} GENERIC_LIST;
|
||||
|
||||
/* Here is a generic structure for associating character strings
|
||||
with integers. It is used in the parser for shell tokenization. */
|
||||
typedef struct {
|
||||
char *word;
|
||||
int token;
|
||||
} STRING_INT_ALIST;
|
||||
|
||||
/* A macro to avoid making an uneccessary function call. */
|
||||
#define REVERSE_LIST(list, type) \
|
||||
((list && list->next) ? (type)list_reverse ((GENERIC_LIST *)list) \
|
||||
: (type)(list))
|
||||
|
||||
#if __GNUC__ > 1
|
||||
# define FASTCOPY(s, d, n) __builtin_memcpy (d, s, n)
|
||||
#else /* !__GNUC__ */
|
||||
# if !defined (HAVE_BCOPY)
|
||||
# if !defined (HAVE_MEMMOVE)
|
||||
# define FASTCOPY(s, d, n) memcpy (d, s, n)
|
||||
# else
|
||||
# define FASTCOPY(s, d, n) memmove (d, s, n)
|
||||
# endif /* !HAVE_MEMMOVE */
|
||||
# else /* HAVE_BCOPY */
|
||||
# define FASTCOPY(s, d, n) bcopy (s, d, n)
|
||||
# endif /* HAVE_BCOPY */
|
||||
#endif /* !__GNUC__ */
|
||||
|
||||
/* String comparisons that possibly save a function call each. */
|
||||
#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
|
||||
#define STREQN(a, b, n) ((n == 0) ? (1) \
|
||||
: ((a)[0] == (b)[0] && strncmp(a, b, n) == 0))
|
||||
|
||||
/* More convenience definitions that possibly save system or libc calls. */
|
||||
#define STRLEN(s) (((s) && (s)[0]) ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0)
|
||||
#define FREE(s) do { if (s) free (s); } while (0)
|
||||
#define MEMBER(c, s) (((c) && c == (s)[0] && !(s)[1]) || (member(c, s)))
|
||||
|
||||
/* A fairly hairy macro to check whether an allocated string has more room,
|
||||
and to resize it using xrealloc if it does not.
|
||||
STR is the string (char *)
|
||||
CIND is the current index into the string (int)
|
||||
ROOM is the amount of additional room we need in the string (int)
|
||||
CSIZE is the currently-allocated size of STR (int)
|
||||
SINCR is how much to increment CSIZE before calling xrealloc (int) */
|
||||
|
||||
#define RESIZE_MALLOCED_BUFFER(str, cind, room, csize, sincr) \
|
||||
do { \
|
||||
if ((cind) + (room) >= csize) \
|
||||
{ \
|
||||
while ((cind) + (room) >= csize) \
|
||||
csize += (sincr); \
|
||||
str = xrealloc (str, csize); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Function pointers can be declared as (Function *)foo. */
|
||||
#if !defined (_FUNCTION_DEF)
|
||||
# define _FUNCTION_DEF
|
||||
typedef int Function ();
|
||||
typedef void VFunction ();
|
||||
typedef char *CPFunction (); /* no longer used */
|
||||
typedef char **CPPFunction (); /* no longer used */
|
||||
#endif /* _FUNCTION_DEF */
|
||||
|
||||
#ifndef SH_FUNCTION_TYPEDEF
|
||||
# define SH_FUNCTION_TYPEDEF
|
||||
|
||||
/* Shell function typedefs with prototypes */
|
||||
/* `Generic' function pointer typedefs */
|
||||
|
||||
typedef int sh_intfunc_t __P((int));
|
||||
typedef int sh_ivoidfunc_t __P((void));
|
||||
typedef int sh_icpfunc_t __P((char *));
|
||||
typedef int sh_icppfunc_t __P((char **));
|
||||
typedef int sh_iptrfunc_t __P((PTR_T));
|
||||
|
||||
typedef void sh_voidfunc_t __P((void));
|
||||
typedef void sh_vintfunc_t __P((int));
|
||||
typedef void sh_vcpfunc_t __P((char *));
|
||||
typedef void sh_vcppfunc_t __P((char **));
|
||||
typedef void sh_vptrfunc_t __P((PTR_T));
|
||||
|
||||
typedef int sh_wdesc_func_t __P((WORD_DESC *));
|
||||
typedef int sh_wlist_func_t __P((WORD_LIST *));
|
||||
|
||||
typedef int sh_glist_func_t __P((GENERIC_LIST *));
|
||||
|
||||
typedef char *sh_string_func_t __P((char *)); /* like savestring, et al. */
|
||||
|
||||
typedef int sh_msg_func_t __P((const char *, ...)); /* printf(3)-like */
|
||||
typedef void sh_vmsg_func_t __P((const char *, ...)); /* printf(3)-like */
|
||||
|
||||
/* Specific function pointer typedefs. Most of these could be done
|
||||
with #defines. */
|
||||
typedef void sh_sv_func_t __P((char *)); /* sh_vcpfunc_t */
|
||||
typedef void sh_free_func_t __P((PTR_T)); /* sh_vptrfunc_t */
|
||||
typedef void sh_resetsig_func_t __P((int)); /* sh_vintfunc_t */
|
||||
|
||||
typedef int sh_ignore_func_t __P((const char *)); /* sh_icpfunc_t */
|
||||
|
||||
typedef int sh_assign_func_t __P((const char *)); /* sh_icpfunc_t */
|
||||
|
||||
typedef int sh_builtin_func_t __P((WORD_LIST *)); /* sh_wlist_func_t */
|
||||
|
||||
#endif /* SH_FUNCTION_TYPEDEF */
|
||||
|
||||
#define NOW ((time_t) time ((time_t *) 0))
|
||||
|
||||
/* Some defines for calling file status functions. */
|
||||
#define FS_EXISTS 0x1
|
||||
#define FS_EXECABLE 0x2
|
||||
#define FS_EXEC_PREFERRED 0x4
|
||||
#define FS_EXEC_ONLY 0x8
|
||||
#define FS_DIRECTORY 0x10
|
||||
#define FS_NODIRS 0x20
|
||||
|
||||
/* Default maximum for move_to_high_fd */
|
||||
#define HIGH_FD_MAX 256
|
||||
|
||||
/* The type of function passed as the fourth argument to qsort(3). */
|
||||
#ifdef __STDC__
|
||||
typedef int QSFUNC (const void *, const void *);
|
||||
#else
|
||||
typedef int QSFUNC ();
|
||||
#endif
|
||||
|
||||
/* Some useful definitions for Unix pathnames. Argument convention:
|
||||
x == string, c == character */
|
||||
|
||||
#if !defined (__CYGWIN__)
|
||||
# define ABSPATH(x) ((x)[0] == '/')
|
||||
# define RELPATH(x) ((x)[0] != '/')
|
||||
#else /* __CYGWIN__ */
|
||||
# define ABSPATH(x) (((x)[0] && ISALPHA((unsigned char)(x)[0]) && (x)[1] == ':' && (x)[2] == '/') || (x)[0] == '/')
|
||||
# define RELPATH(x) (!(x)[0] || ((x)[1] != ':' && (x)[0] != '/'))
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
#define ROOTEDPATH(x) (ABSPATH(x))
|
||||
|
||||
#define DIRSEP '/'
|
||||
#define ISDIRSEP(c) ((c) == '/')
|
||||
#define PATHSEP(c) (ISDIRSEP(c) || (c) == 0)
|
||||
|
||||
#if 0
|
||||
/* Declarations for functions defined in xmalloc.c */
|
||||
extern PTR_T xmalloc __P((size_t));
|
||||
extern PTR_T xrealloc __P((void *, size_t));
|
||||
extern void xfree __P((void *));
|
||||
#endif
|
||||
|
||||
/* Declarations for functions defined in general.c */
|
||||
extern void posix_initialize __P((int));
|
||||
|
||||
#if defined (RLIMTYPE)
|
||||
extern RLIMTYPE string_to_rlimtype __P((char *));
|
||||
extern void print_rlimtype __P((RLIMTYPE, int));
|
||||
#endif
|
||||
|
||||
extern int all_digits __P((char *));
|
||||
extern int legal_number __P((char *, intmax_t *));
|
||||
extern int legal_identifier __P((char *));
|
||||
extern int check_identifier __P((WORD_DESC *, int));
|
||||
extern int assignment __P((const char *, int));
|
||||
|
||||
extern int sh_unset_nodelay_mode __P((int));
|
||||
extern int sh_validfd __P((int));
|
||||
extern void check_dev_tty __P((void));
|
||||
extern int move_to_high_fd __P((int, int, int));
|
||||
extern int check_binary_file __P((char *, int));
|
||||
|
||||
#ifdef _POSIXSTAT_H_
|
||||
extern int same_file __P((char *, char *, struct stat *, struct stat *));
|
||||
#endif
|
||||
|
||||
extern int file_isdir __P((char *));
|
||||
extern int file_iswdir __P((char *));
|
||||
|
||||
extern char *make_absolute __P((char *, char *));
|
||||
extern int absolute_pathname __P((const char *));
|
||||
extern int absolute_program __P((const char *));
|
||||
extern char *base_pathname __P((char *));
|
||||
extern char *full_pathname __P((char *));
|
||||
extern char *polite_directory_format __P((char *));
|
||||
|
||||
extern char *extract_colon_unit __P((char *, int *));
|
||||
|
||||
extern void tilde_initialize __P((void));
|
||||
extern char *bash_tilde_expand __P((const char *, int));
|
||||
|
||||
extern int group_member __P((gid_t));
|
||||
extern char **get_group_list __P((int *));
|
||||
extern int *get_group_array __P((int *));
|
||||
|
||||
#endif /* _GENERAL_H_ */
|
||||
+3
-41
@@ -1,6 +1,6 @@
|
||||
/* shmbutil.h -- utility functions for multibyte characters. */
|
||||
|
||||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002-2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -23,46 +23,8 @@
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
/************************************************/
|
||||
/* check multibyte capability for I18N code */
|
||||
/************************************************/
|
||||
|
||||
/* For platforms which support the ISO C amendement 1 functionality we
|
||||
support user defined character classes. */
|
||||
/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
|
||||
#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H)
|
||||
# include <wchar.h>
|
||||
# include <wctype.h>
|
||||
# if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */
|
||||
# define HANDLE_MULTIBYTE 1
|
||||
# endif
|
||||
#endif /* HAVE_WCTYPE_H && HAVE_WCHAR_H */
|
||||
|
||||
/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
|
||||
#if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T)
|
||||
# define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0)
|
||||
# define mbsrtowcs(dest, src, len, ps) (mbsrtowcs) (dest, src, len, 0)
|
||||
# define wcrtomb(s, wc, ps) (wcrtomb) (s, wc, 0)
|
||||
# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
|
||||
# define mbrlen(s, n, ps) (mbrlen) (s, n, 0)
|
||||
# define mbstate_t int
|
||||
#endif /* HANDLE_MULTIBYTE && !HAVE_MBSTATE_T */
|
||||
|
||||
/* Make sure MB_LEN_MAX is at least 16 on systems that claim to be able to
|
||||
handle multibyte chars (some systems define MB_LEN_MAX as 1) */
|
||||
#ifdef HANDLE_MULTIBYTE
|
||||
# include <limits.h>
|
||||
# if defined(MB_LEN_MAX) && (MB_LEN_MAX < 16)
|
||||
# undef MB_LEN_MAX
|
||||
# endif
|
||||
# if !defined (MB_LEN_MAX)
|
||||
# define MB_LEN_MAX 16
|
||||
# endif
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
/************************************************/
|
||||
/* end of multibyte capability checks for I18N */
|
||||
/************************************************/
|
||||
/* Include config.h for HANDLE_MULTIBYTE */
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
|
||||
|
||||
@@ -0,0 +1,470 @@
|
||||
/* shmbutil.h -- utility functions for multibyte characters. */
|
||||
|
||||
/* Copyright (C) 2002 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 2, 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; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#if !defined (_SH_MBUTIL_H_)
|
||||
#define _SH_MBUTIL_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
/************************************************/
|
||||
/* check multibyte capability for I18N code */
|
||||
/************************************************/
|
||||
|
||||
/* For platforms which support the ISO C amendement 1 functionality we
|
||||
support user defined character classes. */
|
||||
/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
|
||||
#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H)
|
||||
# include <wchar.h>
|
||||
# include <wctype.h>
|
||||
# if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */
|
||||
# define HANDLE_MULTIBYTE 1
|
||||
# endif
|
||||
#endif /* HAVE_WCTYPE_H && HAVE_WCHAR_H */
|
||||
|
||||
/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
|
||||
#if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T)
|
||||
# define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0)
|
||||
# define mbsrtowcs(dest, src, len, ps) (mbsrtowcs) (dest, src, len, 0)
|
||||
# define wcrtomb(s, wc, ps) (wcrtomb) (s, wc, 0)
|
||||
# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
|
||||
# define mbrlen(s, n, ps) (mbrlen) (s, n, 0)
|
||||
# define mbstate_t int
|
||||
#endif /* HANDLE_MULTIBYTE && !HAVE_MBSTATE_T */
|
||||
|
||||
/* Make sure MB_LEN_MAX is at least 16 on systems that claim to be able to
|
||||
handle multibyte chars (some systems define MB_LEN_MAX as 1) */
|
||||
#ifdef HANDLE_MULTIBYTE
|
||||
# include <limits.h>
|
||||
# if defined(MB_LEN_MAX) && (MB_LEN_MAX < 16)
|
||||
# undef MB_LEN_MAX
|
||||
# endif
|
||||
# if !defined (MB_LEN_MAX)
|
||||
# define MB_LEN_MAX 16
|
||||
# endif
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
/************************************************/
|
||||
/* end of multibyte capability checks for I18N */
|
||||
/************************************************/
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
|
||||
extern size_t xmbsrtowcs __P((wchar_t *, const char **, size_t, mbstate_t *));
|
||||
extern size_t xdupmbstowcs __P((wchar_t **, char ***, const char *));
|
||||
|
||||
extern char *xstrchr __P((const char *, int));
|
||||
|
||||
#ifndef MB_INVALIDCH
|
||||
#define MB_INVALIDCH(x) ((x) == (size_t)-1 || (x) == (size_t)-2)
|
||||
#define MB_NULLWCH(x) ((x) == 0)
|
||||
#endif
|
||||
|
||||
#else /* !HANDLE_MULTIBYTE */
|
||||
|
||||
#undef MB_LEN_MAX
|
||||
#undef MB_CUR_MAX
|
||||
|
||||
#define MB_LEN_MAX 1
|
||||
#define MB_CUR_MAX 1
|
||||
|
||||
#undef xstrchr
|
||||
#define xstrchr(s, c) strchr(s, c)
|
||||
|
||||
#ifndef MB_INVALIDCH
|
||||
#define MB_INVALIDCH(x) (0)
|
||||
#define MB_NULLWCH(x) (0)
|
||||
#endif
|
||||
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
/* Declare and initialize a multibyte state. Call must be terminated
|
||||
with `;'. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# define DECLARE_MBSTATE \
|
||||
mbstate_t state; \
|
||||
memset (&state, '\0', sizeof (mbstate_t))
|
||||
#else
|
||||
# define DECLARE_MBSTATE
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
/* Initialize or reinitialize a multibyte state named `state'. Call must be
|
||||
terminated with `;'. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# define INITIALIZE_MBSTATE memset (&state, '\0', sizeof (mbstate_t))
|
||||
#else
|
||||
# define INITIALIZE_MBSTATE
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
/* Advance one (possibly multi-byte) character in string _STR of length
|
||||
_STRSIZE, starting at index _I. STATE must have already been declared. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# define ADVANCE_CHAR(_str, _strsize, _i) \
|
||||
do \
|
||||
{ \
|
||||
if (MB_CUR_MAX > 1) \
|
||||
{ \
|
||||
mbstate_t state_bak; \
|
||||
size_t mblength; \
|
||||
\
|
||||
state_bak = state; \
|
||||
mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
|
||||
\
|
||||
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
|
||||
{ \
|
||||
state = state_bak; \
|
||||
(_i)++; \
|
||||
} \
|
||||
else if (mblength == 0) \
|
||||
(_i)++; \
|
||||
else \
|
||||
(_i) += mblength; \
|
||||
} \
|
||||
else \
|
||||
(_i)++; \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define ADVANCE_CHAR(_str, _strsize, _i) (_i)++
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
/* Advance one (possibly multibyte) character in the string _STR of length
|
||||
_STRSIZE.
|
||||
SPECIAL: assume that _STR will be incremented by 1 after this call. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# define ADVANCE_CHAR_P(_str, _strsize) \
|
||||
do \
|
||||
{ \
|
||||
if (MB_CUR_MAX > 1) \
|
||||
{ \
|
||||
mbstate_t state_bak; \
|
||||
size_t mblength; \
|
||||
\
|
||||
state_bak = state; \
|
||||
mblength = mbrlen ((_str), (_strsize), &state); \
|
||||
\
|
||||
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
|
||||
{ \
|
||||
state = state_bak; \
|
||||
mblength = 1; \
|
||||
} \
|
||||
else \
|
||||
(_str) += (mblength < 1) ? 0 : (mblength - 1); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define ADVANCE_CHAR_P(_str, _strsize)
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
/* Back up one (possibly multi-byte) character in string _STR of length
|
||||
_STRSIZE, starting at index _I. STATE must have already been declared. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# define BACKUP_CHAR(_str, _strsize, _i) \
|
||||
do \
|
||||
{ \
|
||||
if (MB_CUR_MAX > 1) \
|
||||
{ \
|
||||
mbstate_t state_bak; \
|
||||
size_t mblength; \
|
||||
int _x, _p; /* _x == temp index into string, _p == prev index */ \
|
||||
\
|
||||
_x = _p = 0; \
|
||||
while (_x < (_i)) \
|
||||
{ \
|
||||
state_bak = state; \
|
||||
mblength = mbrlen ((_str) + (_x), (_strsize) - (_x), &state); \
|
||||
\
|
||||
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
|
||||
{ \
|
||||
state = state_bak; \
|
||||
_x++; \
|
||||
} \
|
||||
else if (mblength == 0) \
|
||||
_x++; \
|
||||
else \
|
||||
{ \
|
||||
_p = _x; /* _p == start of prev mbchar */ \
|
||||
_x += mblength; \
|
||||
} \
|
||||
} \
|
||||
(_i) = _p; \
|
||||
} \
|
||||
else \
|
||||
(_i)--; \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define BACKUP_CHAR(_str, _strsize, _i) (_i)--
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
/* Back up one (possibly multibyte) character in the string _BASE of length
|
||||
_STRSIZE starting at _STR (_BASE <= _STR <= (_BASE + _STRSIZE) ).
|
||||
SPECIAL: DO NOT assume that _STR will be decremented by 1 after this call. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# define BACKUP_CHAR_P(_base, _strsize, _str) \
|
||||
do \
|
||||
{ \
|
||||
if (MB_CUR_MAX > 1) \
|
||||
{ \
|
||||
mbstate_t state_bak; \
|
||||
size_t mblength; \
|
||||
char *_x, _p; /* _x == temp pointer into string, _p == prev pointer */ \
|
||||
\
|
||||
_x = _p = _base; \
|
||||
while (_x < (_str)) \
|
||||
{ \
|
||||
state_bak = state; \
|
||||
mblength = mbrlen (_x, (_strsize) - _x, &state); \
|
||||
\
|
||||
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
|
||||
{ \
|
||||
state = state_bak; \
|
||||
_x++; \
|
||||
} \
|
||||
else if (mblength == 0) \
|
||||
_x++; \
|
||||
else \
|
||||
{ \
|
||||
_p = _x; /* _p == start of prev mbchar */ \
|
||||
_x += mblength; \
|
||||
} \
|
||||
} \
|
||||
(_str) = _p; \
|
||||
} \
|
||||
else \
|
||||
(_str)--; \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define BACKUP_CHAR_P(_base, _strsize, _str) (_str)--
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
/* Copy a single character from the string _SRC to the string _DST.
|
||||
_SRCEND is a pointer to the end of _SRC. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# define COPY_CHAR_P(_dst, _src, _srcend) \
|
||||
do \
|
||||
{ \
|
||||
if (MB_CUR_MAX > 1) \
|
||||
{ \
|
||||
mbstate_t state_bak; \
|
||||
size_t mblength; \
|
||||
int _k; \
|
||||
\
|
||||
state_bak = state; \
|
||||
mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
|
||||
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
|
||||
{ \
|
||||
state = state_bak; \
|
||||
mblength = 1; \
|
||||
} \
|
||||
else \
|
||||
mblength = (mblength < 1) ? 1 : mblength; \
|
||||
\
|
||||
for (_k = 0; _k < mblength; _k++) \
|
||||
*(_dst)++ = *(_src)++; \
|
||||
} \
|
||||
else \
|
||||
*(_dst)++ = *(_src)++; \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define COPY_CHAR_P(_dst, _src, _srcend) *(_dst)++ = *(_src)++
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
/* Copy a single character from the string _SRC at index _SI to the string
|
||||
_DST at index _DI. _SRCEND is a pointer to the end of _SRC. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) \
|
||||
do \
|
||||
{ \
|
||||
if (MB_CUR_MAX > 1) \
|
||||
{ \
|
||||
mbstate_t state_bak; \
|
||||
size_t mblength; \
|
||||
int _k; \
|
||||
\
|
||||
state_bak = state; \
|
||||
mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
|
||||
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
|
||||
{ \
|
||||
state = state_bak; \
|
||||
mblength = 1; \
|
||||
} \
|
||||
else \
|
||||
mblength = (mblength < 1) ? 1 : mblength; \
|
||||
\
|
||||
for (_k = 0; _k < mblength; _k++) \
|
||||
_dst[_di++] = _src[_si++]; \
|
||||
} \
|
||||
else \
|
||||
_dst[_di++] = _src[_si++]; \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) _dst[_di++] = _src[_si++]
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* The following are only guaranteed to work in subst.c *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
|
||||
do \
|
||||
{ \
|
||||
if (MB_CUR_MAX > 1) \
|
||||
{ \
|
||||
mbstate_t state_bak; \
|
||||
size_t mblength; \
|
||||
int _i; \
|
||||
\
|
||||
state_bak = state; \
|
||||
mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
|
||||
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
|
||||
{ \
|
||||
state = state_bak; \
|
||||
mblength = 1; \
|
||||
} \
|
||||
else \
|
||||
mblength = (mblength < 1) ? 1 : mblength; \
|
||||
\
|
||||
temp = xmalloc (mblength + 2); \
|
||||
temp[0] = _escchar; \
|
||||
for (_i = 0; _i < mblength; _i++) \
|
||||
temp[_i + 1] = _src[_si++]; \
|
||||
temp[mblength + 1] = '\0'; \
|
||||
\
|
||||
goto add_string; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_dst[0] = _escchar; \
|
||||
_dst[1] = _sc; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
|
||||
_dst[0] = _escchar; \
|
||||
_dst[1] = _sc
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
|
||||
do \
|
||||
{ \
|
||||
if (MB_CUR_MAX > 1) \
|
||||
{ \
|
||||
mbstate_t state_bak; \
|
||||
size_t mblength; \
|
||||
\
|
||||
state_bak = state; \
|
||||
mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
|
||||
if (mblength == (size_t)-2 || mblength == (size_t)-1) \
|
||||
{ \
|
||||
state = state_bak; \
|
||||
mblength = 1; \
|
||||
} \
|
||||
else \
|
||||
mblength = (mblength < 1) ? 1 : mblength; \
|
||||
\
|
||||
FASTCOPY(((_src) + (_si)), (_dst), mblength); \
|
||||
\
|
||||
(_dst) += mblength; \
|
||||
(_si) += mblength; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
*(_dst)++ = _src[(_si)]; \
|
||||
(_si)++; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
|
||||
*(_dst)++ = _src[(_si)]; \
|
||||
(_si)++
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
#if HANDLE_MULTIBYTE
|
||||
# define SADD_MBCHAR(_dst, _src, _si, _srcsize) \
|
||||
do \
|
||||
{ \
|
||||
if (MB_CUR_MAX > 1) \
|
||||
{ \
|
||||
int i; \
|
||||
mbstate_t state_bak; \
|
||||
size_t mblength; \
|
||||
\
|
||||
state_bak = state; \
|
||||
mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
|
||||
if (mblength == (size_t)-1 || mblength == (size_t)-2) \
|
||||
{ \
|
||||
state = state_bak; \
|
||||
mblength = 1; \
|
||||
} \
|
||||
if (mblength < 1) \
|
||||
mblength = 1; \
|
||||
\
|
||||
_dst = (char *)xmalloc (mblength + 1); \
|
||||
for (i = 0; i < mblength; i++) \
|
||||
(_dst)[i] = (_src)[(_si)++]; \
|
||||
(_dst)[mblength] = '\0'; \
|
||||
\
|
||||
goto add_string; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#else
|
||||
# define SADD_MBCHAR(_dst, _src, _si, _srcsize)
|
||||
#endif
|
||||
|
||||
/* Watch out when using this -- it's just straight textual subsitution */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# define SADD_MBQCHAR_BODY(_dst, _src, _si, _srcsize) \
|
||||
\
|
||||
int i; \
|
||||
mbstate_t state_bak; \
|
||||
size_t mblength; \
|
||||
\
|
||||
state_bak = state; \
|
||||
mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
|
||||
if (mblength == (size_t)-1 || mblength == (size_t)-2) \
|
||||
{ \
|
||||
state = state_bak; \
|
||||
mblength = 1; \
|
||||
} \
|
||||
if (mblength < 1) \
|
||||
mblength = 1; \
|
||||
\
|
||||
(_dst) = (char *)xmalloc (mblength + 2); \
|
||||
(_dst)[0] = CTLESC; \
|
||||
for (i = 0; i < mblength; i++) \
|
||||
(_dst)[i+1] = (_src)[(_si)++]; \
|
||||
(_dst)[mblength+1] = '\0'; \
|
||||
\
|
||||
goto add_string
|
||||
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
#endif /* _SH_MBUTIL_H_ */
|
||||
@@ -67,6 +67,7 @@
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
|
||||
extern size_t xmbsrtowcs __P((wchar_t *, const char **, size_t, mbstate_t *));
|
||||
extern size_t xdupmbstowcs __P((wchar_t **, char ***, const char *));
|
||||
|
||||
extern char *xstrchr __P((const char *, int));
|
||||
|
||||
|
||||
@@ -3433,6 +3433,12 @@ set_job_control (arg)
|
||||
|
||||
old = job_control;
|
||||
job_control = arg;
|
||||
|
||||
/* If we're turning on job control, reset pipeline_pgrp so make_child will
|
||||
put new child processes into the right pgrp */
|
||||
if (job_control != old && job_control)
|
||||
pipeline_pgrp = 0;
|
||||
|
||||
return (old);
|
||||
}
|
||||
|
||||
|
||||
+31
@@ -347,6 +347,37 @@ indirection_level_string ()
|
||||
return (indirection_string);
|
||||
}
|
||||
|
||||
void
|
||||
xtrace_print_assignment (name, value, assign_list, xflags)
|
||||
char *name, *value;
|
||||
int assign_list, xflags;
|
||||
{
|
||||
char *nval;
|
||||
|
||||
if (xflags)
|
||||
fprintf (stderr, "%s", indirection_level_string ());
|
||||
|
||||
/* VALUE should not be NULL when this is called. */
|
||||
if (*value == '\0' || assign_list)
|
||||
nval = value;
|
||||
else if (sh_contains_shell_metas (value))
|
||||
nval = sh_single_quote (value);
|
||||
else if (ansic_shouldquote (value))
|
||||
nval = ansic_quote (value, 0, (int *)0);
|
||||
else
|
||||
nval = value;
|
||||
|
||||
if (assign_list)
|
||||
fprintf (stderr, "%s=(%s)\n", name, nval);
|
||||
else
|
||||
fprintf (stderr, "%s=%s\n", name, nval);
|
||||
|
||||
if (nval != value)
|
||||
FREE (nval);
|
||||
|
||||
fflush (stderr);
|
||||
}
|
||||
|
||||
/* A function to print the words of a simple command when set -x is on. */
|
||||
void
|
||||
xtrace_print_word_list (list, xtflags)
|
||||
|
||||
+1282
File diff suppressed because it is too large
Load Diff
@@ -1977,8 +1977,9 @@ do_assignment_internal (string, expand)
|
||||
SHELL_VAR *entry;
|
||||
#if defined (ARRAY_VARS)
|
||||
char *t;
|
||||
int ni, assign_list = 0;
|
||||
int ni;
|
||||
#endif
|
||||
int assign_list = 0;
|
||||
|
||||
offset = assignment (string, 0);
|
||||
name = savestring (string);
|
||||
@@ -2021,14 +2022,7 @@ do_assignment_internal (string, expand)
|
||||
}
|
||||
|
||||
if (echo_command_at_execute)
|
||||
{
|
||||
#if defined (ARRAY_VARS)
|
||||
if (assign_list)
|
||||
fprintf (stderr, "%s%s=(%s)\n", indirection_level_string (), name, value);
|
||||
else
|
||||
#endif
|
||||
fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
|
||||
}
|
||||
xtrace_print_assignment (name, value, assign_list, 1);
|
||||
|
||||
#define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ static intmax_t parameter_brace_expand_length __P((char *));
|
||||
|
||||
static char *skiparith __P((char *, int));
|
||||
static int verify_substring_values __P((char *, char *, int, intmax_t *, intmax_t *));
|
||||
static int get_var_and_type __P((char *, char *, SHELL_VAR **, char **));
|
||||
static int get_var_and_type __P((char *, char *, int, SHELL_VAR **, char **));
|
||||
static char *mb_substring __P((char *, int, int));
|
||||
static char *parameter_brace_substring __P((char *, char *, char *, int));
|
||||
|
||||
@@ -1977,8 +1977,9 @@ do_assignment_internal (string, expand)
|
||||
SHELL_VAR *entry;
|
||||
#if defined (ARRAY_VARS)
|
||||
char *t;
|
||||
int ni, assign_list = 0;
|
||||
int ni;
|
||||
#endif
|
||||
int assign_list = 0;
|
||||
|
||||
offset = assignment (string, 0);
|
||||
name = savestring (string);
|
||||
@@ -2022,12 +2023,14 @@ do_assignment_internal (string, expand)
|
||||
|
||||
if (echo_command_at_execute)
|
||||
{
|
||||
#if defined (ARRAY_VARS)
|
||||
#if 0
|
||||
if (assign_list)
|
||||
fprintf (stderr, "%s%s=(%s)\n", indirection_level_string (), name, value);
|
||||
else
|
||||
fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
|
||||
#else
|
||||
xtrace_print_assignment (name, value, assign_list, 1);
|
||||
#endif
|
||||
fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
|
||||
}
|
||||
|
||||
#define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
|
||||
@@ -3530,7 +3533,7 @@ parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
|
||||
|
||||
this_command_name = varname;
|
||||
|
||||
vtype = get_var_and_type (varname, value, &v, &val);
|
||||
vtype = get_var_and_type (varname, value, quoted, &v, &val);
|
||||
if (vtype == -1)
|
||||
return ((char *)NULL);
|
||||
|
||||
@@ -4446,7 +4449,12 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
if (legal_number (name, &arg_index))
|
||||
{
|
||||
tt = get_dollar_var_value (arg_index);
|
||||
temp = tt ? quote_escapes (tt) : (char *)NULL;
|
||||
if (tt)
|
||||
temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
? quote_string (tt)
|
||||
: quote_escapes (tt);
|
||||
else
|
||||
temp = (char *)NULL;
|
||||
FREE (tt);
|
||||
}
|
||||
else if (var_is_special) /* ${@} */
|
||||
@@ -4465,7 +4473,9 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
{
|
||||
temp = array_value (name, quoted, &atype);
|
||||
if (atype == 0 && temp)
|
||||
temp = quote_escapes (temp);
|
||||
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
}
|
||||
#endif
|
||||
else if (var = find_variable (name))
|
||||
@@ -4479,7 +4489,9 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
#endif
|
||||
|
||||
if (temp)
|
||||
temp = quote_escapes (temp);
|
||||
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
}
|
||||
else
|
||||
temp = (char *)NULL;
|
||||
@@ -4501,6 +4513,15 @@ parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, c
|
||||
char *temp, *t;
|
||||
|
||||
t = parameter_brace_expand_word (name, var_is_special, quoted);
|
||||
/* Have to dequote here if necessary */
|
||||
if (t)
|
||||
{
|
||||
temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
|
||||
? dequote_string (t)
|
||||
: dequote_escapes (t);
|
||||
free (t);
|
||||
t = temp;
|
||||
}
|
||||
chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
|
||||
if (t == 0)
|
||||
return (t);
|
||||
@@ -4895,8 +4916,9 @@ verify_substring_values (value, substr, vtype, e1p, e2p)
|
||||
characters in the value are quoted with CTLESC and takes appropriate
|
||||
steps. For convenience, *VALP is set to the dequoted VALUE. */
|
||||
static int
|
||||
get_var_and_type (varname, value, varp, valp)
|
||||
get_var_and_type (varname, value, quoted, varp, valp)
|
||||
char *varname, *value;
|
||||
int quoted;
|
||||
SHELL_VAR **varp;
|
||||
char **valp;
|
||||
{
|
||||
@@ -4943,7 +4965,21 @@ get_var_and_type (varname, value, varp, valp)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if 1
|
||||
{
|
||||
if (value && vtype == VT_VARIABLE)
|
||||
{
|
||||
if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
|
||||
*valp = dequote_string (value);
|
||||
else
|
||||
*valp = dequote_escapes (value);
|
||||
}
|
||||
else
|
||||
*valp = value;
|
||||
}
|
||||
#else
|
||||
*valp = (value && vtype == VT_VARIABLE) ? dequote_escapes (value) : value;
|
||||
#endif
|
||||
|
||||
return vtype;
|
||||
}
|
||||
@@ -5002,7 +5038,7 @@ parameter_brace_substring (varname, value, substr, quoted)
|
||||
|
||||
this_command_name = varname;
|
||||
|
||||
vtype = get_var_and_type (varname, value, &v, &val);
|
||||
vtype = get_var_and_type (varname, value, quoted, &v, &val);
|
||||
if (vtype == -1)
|
||||
return ((char *)NULL);
|
||||
|
||||
@@ -5201,7 +5237,7 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
|
||||
this_command_name = varname;
|
||||
|
||||
vtype = get_var_and_type (varname, value, &v, &val);
|
||||
vtype = get_var_and_type (varname, value, quoted, &v, &val);
|
||||
if (vtype == -1)
|
||||
return ((char *)NULL);
|
||||
|
||||
@@ -5736,7 +5772,16 @@ param_expand (string, sindex, quoted, expanded_something,
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
return (interactive_shell ? &expand_param_error : &expand_param_fatal);
|
||||
}
|
||||
#if 1
|
||||
if (temp1)
|
||||
temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
? quote_string (temp1)
|
||||
: quote_escapes (temp1);
|
||||
else
|
||||
temp = (char *)NULL;
|
||||
#else
|
||||
temp = temp1 ? quote_escapes (temp1) : (char *)NULL;
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* $$ -- pid of the invoking shell. */
|
||||
@@ -5827,13 +5872,10 @@ param_expand (string, sindex, quoted, expanded_something,
|
||||
string might need it (consider "\"$@\""), but we need some
|
||||
way to signal that the final split on the first character
|
||||
of $IFS should be done, even though QUOTED is 1. */
|
||||
if (list && list->next)
|
||||
{
|
||||
if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
*quoted_dollar_at_p = 1;
|
||||
if (contains_dollar_at)
|
||||
*contains_dollar_at = 1;
|
||||
}
|
||||
|
||||
/* We want to separate the positional parameters with the first
|
||||
character of $IFS in case $IFS is something other than a space.
|
||||
@@ -5976,13 +6018,22 @@ comsub:
|
||||
{
|
||||
temp = array_reference (array_cell (var), 0);
|
||||
if (temp)
|
||||
temp = quote_escapes (temp);
|
||||
temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
else if (unbound_vars_is_error)
|
||||
goto unbound_variable;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
temp = quote_escapes (value_cell (var));
|
||||
{
|
||||
temp = value_cell (var);
|
||||
|
||||
temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
}
|
||||
|
||||
free (temp1);
|
||||
|
||||
goto return0;
|
||||
|
||||
@@ -71,6 +71,8 @@ extern int sh_syntabsiz;
|
||||
#define shellbreak(c) (sh_syntaxtab[(unsigned char)(c)] & CSHBRK)
|
||||
#define shellquote(c) (sh_syntaxtab[(unsigned char)(c)] & CQUOTE)
|
||||
|
||||
#define shellxquote(c) (sh_syntaxtab[(unsigned char)(c)] & CXQUOTE)
|
||||
|
||||
#define issyntype(c, t) ((sh_syntaxtab[(unsigned char)(c)] & (t)) != 0)
|
||||
#define notsyntype(c,t) ((sh_syntaxtab[(unsigned char)(c)] & (t)) == 0)
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/* syntax.h -- Syntax definitions for the shell */
|
||||
|
||||
/* Copyright (C) 2000 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 2, 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; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#ifndef _SYNTAX_H_
|
||||
#define _SYNTAX_H_
|
||||
|
||||
/* Defines for use by mksyntax.c */
|
||||
|
||||
#define slashify_in_quotes "\\`$\"\n"
|
||||
#define slashify_in_here_document "\\`$"
|
||||
|
||||
#define shell_meta_chars "()<>;&|"
|
||||
#define shell_break_chars "()<>;&| \t\n"
|
||||
|
||||
#define shell_quote_chars "\"`'"
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
# define shell_exp_chars "$<>"
|
||||
#else
|
||||
# define shell_exp_chars "$"
|
||||
#endif
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
# define ext_glob_chars "@*+?!"
|
||||
#else
|
||||
# define ext_glob_chars ""
|
||||
#endif
|
||||
#define shell_glob_chars "*?[]^"
|
||||
|
||||
/* Defines shared by mksyntax.c and the rest of the shell code. */
|
||||
|
||||
/* Values for character flags in syntax tables */
|
||||
|
||||
#define CWORD 0x0000 /* nothing special; an ordinary character */
|
||||
#define CSHMETA 0x0001 /* shell meta character */
|
||||
#define CSHBRK 0x0002 /* shell break character */
|
||||
#define CBACKQ 0x0004 /* back quote */
|
||||
#define CQUOTE 0x0008 /* shell quote character */
|
||||
#define CSPECL 0x0010 /* special character that needs quoting */
|
||||
#define CEXP 0x0020 /* shell expansion character */
|
||||
#define CBSDQUOTE 0x0040 /* characters escaped by backslash in double quotes */
|
||||
#define CBSHDOC 0x0080 /* characters escaped by backslash in here doc */
|
||||
#define CGLOB 0x0100 /* globbing characters */
|
||||
#define CXGLOB 0x0200 /* extended globbing characters */
|
||||
#define CXQUOTE 0x0400 /* cquote + backslash */
|
||||
#define CSPECVAR 0x0800 /* single-character shell variable name */
|
||||
#define CSUBSTOP 0x1000 /* values of OP for ${word[:]OPstuff} */
|
||||
|
||||
/* Defines for use by the rest of the shell. */
|
||||
extern int sh_syntaxtab[];
|
||||
extern int sh_syntabsiz;
|
||||
|
||||
#define shellmeta(c) (sh_syntaxtab[(unsigned char)(c)] & CSHMETA)
|
||||
#define shellbreak(c) (sh_syntaxtab[(unsigned char)(c)] & CSHBRK)
|
||||
#define shellquote(c) (sh_syntaxtab[(unsigned char)(c)] & CQUOTE)
|
||||
|
||||
#define issyntype(c, t) ((sh_syntaxtab[(unsigned char)(c)] & (t)) != 0)
|
||||
#define notsyntype(c,t) ((sh_syntaxtab[(unsigned char)(c)] & (t)) == 0)
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
# define shellexp(c) ((c) == '$' || (c) == '<' || (c) == '>')
|
||||
#else
|
||||
# define shellexp(c) ((c) == '$')
|
||||
#endif
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
# define PATTERN_CHAR(c) \
|
||||
((c) == '@' || (c) == '*' || (c) == '+' || (c) == '?' || (c) == '!')
|
||||
#else
|
||||
# define PATTERN_CHAR(c) 0
|
||||
#endif
|
||||
|
||||
#define GLOB_CHAR(c) \
|
||||
((c) == '*' || (c) == '?' || (c) == '[' || (c) == ']' || (c) == '^')
|
||||
|
||||
#define CTLESC '\001'
|
||||
#define CTLNUL '\177'
|
||||
|
||||
#if !defined (HAVE_ISBLANK) && !defined (isblank)
|
||||
# define isblank(x) ((x) == ' ' || (x) == '\t')
|
||||
#endif
|
||||
|
||||
#endif /* _SYNTAX_H_ */
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
BUILD_DIR=/usr/local/build/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
./errors.tests: line 17: alias: -x: invalid option
|
||||
alias: usage: alias [-p] [name[=value] ... ]
|
||||
./errors.tests: line 18: unalias: -x: invalid option
|
||||
unalias: usage: unalias [-a] [name ...]
|
||||
unalias: usage: unalias [-a] name [name ...]
|
||||
./errors.tests: line 19: alias: hoowah: not found
|
||||
./errors.tests: line 20: unalias: hoowah: not found
|
||||
./errors.tests: line 23: `1': not a valid identifier
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
./errors.tests: line 17: alias: -x: invalid option
|
||||
alias: usage: alias [-p] [name[=value] ... ]
|
||||
./errors.tests: line 18: unalias: -x: invalid option
|
||||
unalias: usage: unalias [-a] [name ...]
|
||||
./errors.tests: line 19: alias: hoowah: not found
|
||||
./errors.tests: line 20: unalias: hoowah: not found
|
||||
./errors.tests: line 23: `1': not a valid identifier
|
||||
declare -fr func
|
||||
./errors.tests: line 36: func: readonly function
|
||||
./errors.tests: line 39: unset: -x: invalid option
|
||||
unset: usage: unset [-f] [-v] [name ...]
|
||||
./errors.tests: line 42: unset: func: cannot unset: readonly function
|
||||
./errors.tests: line 45: declare: func: readonly function
|
||||
./errors.tests: line 49: unset: XPATH: cannot unset: readonly variable
|
||||
./errors.tests: line 52: unset: `/bin/sh': not a valid identifier
|
||||
./errors.tests: line 55: unset: cannot simultaneously unset a function and a variable
|
||||
./errors.tests: line 58: declare: -z: invalid option
|
||||
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]
|
||||
./errors.tests: line 60: declare: `-z': not a valid identifier
|
||||
./errors.tests: line 61: declare: `/bin/sh': not a valid identifier
|
||||
./errors.tests: line 65: declare: cannot use `-f' to make functions
|
||||
./errors.tests: line 68: exec: -i: invalid option
|
||||
exec: usage: exec [-cl] [-a name] file [redirection ...]
|
||||
./errors.tests: line 72: export: XPATH: not a function
|
||||
./errors.tests: line 75: break: only meaningful in a `for', `while', or `until' loop
|
||||
./errors.tests: line 76: continue: only meaningful in a `for', `while', or `until' loop
|
||||
./errors.tests: line 79: shift: label: numeric argument required
|
||||
./errors.tests: line 84: shift: too many arguments
|
||||
./errors.tests: line 90: let: expression expected
|
||||
./errors.tests: line 93: local: can only be used in a function
|
||||
./errors.tests: line 96: logout: not login shell: use `exit'
|
||||
./errors.tests: line 99: hash: notthere: not found
|
||||
./errors.tests: line 102: hash: -v: invalid option
|
||||
hash: usage: hash [-lr] [-p pathname] [-dt] [name ...]
|
||||
./errors.tests: line 106: hash: hashing disabled
|
||||
./errors.tests: line 109: export: `AA[4]': not a valid identifier
|
||||
./errors.tests: line 110: readonly: `AA[4]': not a valid identifier
|
||||
./errors.tests: line 113: [-2]: bad array subscript
|
||||
./errors.tests: line 117: AA: readonly variable
|
||||
./errors.tests: line 121: AA: readonly variable
|
||||
./errors.tests: line 129: shift: 5: shift count out of range
|
||||
./errors.tests: line 130: shift: -2: shift count out of range
|
||||
./errors.tests: line 133: shopt: no_such_option: invalid shell option name
|
||||
./errors.tests: line 134: shopt: no_such_option: invalid shell option name
|
||||
./errors.tests: line 137: umask: 09: octal number out of range
|
||||
./errors.tests: line 138: umask: `:': invalid symbolic mode character
|
||||
./errors.tests: line 139: umask: `:': invalid symbolic mode operator
|
||||
./errors.tests: line 142: umask: -i: invalid option
|
||||
umask: usage: umask [-p] [-S] [mode]
|
||||
./errors.tests: line 146: umask: `u': invalid symbolic mode character
|
||||
./errors.tests: line 155: VAR: readonly variable
|
||||
./errors.tests: line 158: declare: VAR: readonly variable
|
||||
./errors.tests: line 159: declare: VAR: readonly variable
|
||||
./errors.tests: line 161: declare: unset: not found
|
||||
./errors.tests: line 164: VAR: readonly variable
|
||||
./errors.tests: command substitution: line 168: syntax error: unexpected end of file
|
||||
./errors.tests: command substitution: line 168: syntax error near unexpected token `done'
|
||||
./errors.tests: command substitution: line 168: ` for z in 1 2 3; done '
|
||||
./errors.tests: line 171: cd: HOME not set
|
||||
./errors.tests: line 172: cd: /tmp/xyz.bash: No such file or directory
|
||||
./errors.tests: line 174: cd: OLDPWD not set
|
||||
./errors.tests: line 175: cd: /bin/sh: Not a directory
|
||||
./errors.tests: line 177: cd: /tmp/cd-notthere: No such file or directory
|
||||
./errors.tests: line 180: .: filename argument required
|
||||
.: usage: . filename [arguments]
|
||||
./errors.tests: line 181: source: filename argument required
|
||||
source: usage: source filename [arguments]
|
||||
./errors.tests: line 184: .: -i: invalid option
|
||||
.: usage: . filename [arguments]
|
||||
./errors.tests: line 187: set: -q: invalid option
|
||||
set: usage: set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
|
||||
./errors.tests: line 190: enable: sh: not a shell builtin
|
||||
./errors.tests: line 190: enable: bash: not a shell builtin
|
||||
./errors.tests: line 193: shopt: cannot set and unset shell options simultaneously
|
||||
./errors.tests: line 196: read: var: invalid timeout specification
|
||||
./errors.tests: line 199: read: `/bin/sh': not a valid identifier
|
||||
./errors.tests: line 202: VAR: readonly variable
|
||||
./errors.tests: line 205: readonly: -x: invalid option
|
||||
readonly: usage: readonly [-af] [name[=value] ...] or readonly -p
|
||||
./errors.tests: line 208: eval: -i: invalid option
|
||||
eval: usage: eval [arg ...]
|
||||
./errors.tests: line 209: command: -i: invalid option
|
||||
command: usage: command [-pVv] command [arg ...]
|
||||
./errors.tests: line 212: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
|
||||
./errors.tests: line 213: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
|
||||
./errors.tests: line 216: trap: NOSIG: invalid signal specification
|
||||
./errors.tests: line 219: trap: -s: invalid option
|
||||
trap: usage: trap [arg] [signal_spec ...] or trap -l
|
||||
./errors.tests: line 225: return: can only `return' from a function or sourced script
|
||||
./errors.tests: line 229: break: 0: loop count out of range
|
||||
./errors.tests: line 233: continue: 0: loop count out of range
|
||||
./errors.tests: line 238: builtin: bash: not a shell builtin
|
||||
./errors.tests: line 242: bg: no job control
|
||||
./errors.tests: line 243: fg: no job control
|
||||
./errors.tests: line 246: kill: -s: option requires an argument
|
||||
./errors.tests: line 248: kill: S: invalid signal specification
|
||||
./errors.tests: line 250: kill: `': not a pid or valid job spec
|
||||
kill: usage: kill [-s sigspec | -n signum | -sigspec] [pid | job]... or kill -l [sigspec]
|
||||
./errors.tests: line 255: set: trackall: invalid option name
|
||||
./errors.tests: line 262: `!!': not a valid identifier
|
||||
+3
-6
@@ -2118,12 +2118,9 @@ assign_in_env (string)
|
||||
setifs (var);
|
||||
|
||||
if (echo_command_at_execute)
|
||||
{
|
||||
/* The Korn shell prints the `+ ' in front of assignment statements,
|
||||
so we do too. */
|
||||
fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
|
||||
fflush (stderr);
|
||||
}
|
||||
/* The Korn shell prints the `+ ' in front of assignment statements,
|
||||
so we do too. */
|
||||
xtrace_print_assignment (name, value, 0, 1);
|
||||
|
||||
free (name);
|
||||
return 1;
|
||||
|
||||
+4092
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user