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 1, or (at your option) any later
+ 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
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
#include <config.h>
#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
# include <unistd.h>
#endif
#include <stdio.h>
-#include <sys/types.h>
-#include "../posixstat.h"
+#include <chartypes.h>
+#include "../bashtypes.h"
+#include "posixstat.h"
#include <signal.h>
+#include <errno.h>
+
#if defined (PREFER_STDARG)
# include <stdarg.h>
#else
#include "../bashansi.h"
#include "../shell.h"
-#include "../maxpath.h"
+#include "maxpath.h"
#include "../flags.h"
#include "../jobs.h"
#include "../builtins.h"
#include "../input.h"
#include "../execute_cmd.h"
#include "../trap.h"
-#include "hashcom.h"
#include "bashgetopt.h"
#include "common.h"
+#include "builtext.h"
#include <tilde/tilde.h>
#if defined (HISTORY)
# include "../bashhist.h"
#endif
-extern int no_symbolic_links, interactive, interactive_shell;
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+extern int no_symbolic_links;
extern int indirection_level, startup_state, subshell_environment;
extern int line_number;
extern int last_command_exit_value;
extern int running_trap;
-extern int hashing_enabled;
-extern int variable_context;
extern int posixly_correct;
extern char *this_command_name, *shell_name;
-extern COMMAND *global_command;
-extern HASH_TABLE *hashed_filenames;
extern char *bash_getcwd_errstr;
+/* Used by some builtins and the mainline code. */
+sh_builtin_func_t *last_shell_builtin = (sh_builtin_func_t *)NULL;
+sh_builtin_func_t *this_shell_builtin = (sh_builtin_func_t *)NULL;
+
/* **************************************************************** */
/* */
/* Error reporting, usage, and option processing */
/* **************************************************************** */
/* */
-/* Validating numeric input and arguments */
+/* Validating numeric input and arguments */
/* */
/* **************************************************************** */
/* Read a numeric arg for this_command_name, the name of the shell builtin
that wants it. LIST is the word list that the arg is to come from.
Accept only the numeric argument; report an error if other arguments
- follow. */
-int
-get_numeric_arg (list)
+ follow. If FATAL is true, call throw_to_top_level, which exits the
+ shell; if not, call jump_to_top_level (DISCARD), which aborts the
+ current command. */
+long
+get_numeric_arg (list, fatal)
WORD_LIST *list;
+ int fatal;
{
long count = 1;
if (!arg || (legal_number (arg, &count) == 0))
{
builtin_error ("bad non-numeric arg `%s'", list->word->word);
- throw_to_top_level ();
+ if (fatal)
+ throw_to_top_level ();
+ else
+ jump_to_top_level (DISCARD);
}
no_args (list->next);
}
+
return (count);
}
+/* Get an eight-bit status value from LIST */
+int
+get_exitstat (list)
+ WORD_LIST *list;
+{
+ int status;
+ long sval;
+ char *arg;
+
+ arg = list->word->word;
+ if (arg == 0 || legal_number (arg, &sval) == 0)
+ {
+ builtin_error ("bad non-numeric arg `%s'", list->word->word);
+ return 255;
+ }
+ no_args (list->next);
+
+ status = sval & 255;
+ return status;
+}
+
/* Return the octal number parsed from STRING, or -1 to indicate
that the string contained a bad number. */
int
int result, digits;
result = digits = 0;
- while (*string && *string >= '0' && *string < '8')
+ while (*string && ISOCTAL (*string))
{
digits++;
- result = (result * 8) + *string++ - '0';
+ result = (result * 8) + (*string++ - '0');
+ if (result > 0777)
+ return -1;
}
- if (!digits || result > 0777 || *string)
+ if (digits == 0 || *string)
result = -1;
return (result);
/* **************************************************************** */
/* */
-/* Command name hashing */
-/* */
-/* **************************************************************** */
-
-/* Return the full pathname that FILENAME hashes to. If FILENAME
- is hashed, but (data->flags & HASH_CHKDOT) is non-zero, check
- ./FILENAME and return that if it is executable. */
-char *
-find_hashed_filename (filename)
- char *filename;
-{
- register BUCKET_CONTENTS *item;
- char *path, *dotted_filename, *tail;
- int same;
-
- if (hashing_enabled == 0)
- return ((char *)NULL);
-
- item = find_hash_item (filename, hashed_filenames);
-
- if (item == NULL)
- return ((char *)NULL);
-
- /* If this filename is hashed, but `.' comes before it in the path,
- see if ./filename is executable. If the hashed value is not an
- absolute pathname, see if ./`hashed-value' exists. */
- path = pathdata(item)->path;
- if (pathdata(item)->flags & (HASH_CHKDOT|HASH_RELPATH))
- {
- tail = (pathdata(item)->flags & HASH_RELPATH) ? path : filename;
- dotted_filename = xmalloc (3 + strlen (tail));
- dotted_filename[0] = '.'; dotted_filename[1] = '/';
- strcpy (dotted_filename + 2, tail);
-
- if (executable_file (dotted_filename))
- return (dotted_filename);
-
- free (dotted_filename);
-
-#if 0
- if (pathdata(item)->flags & HASH_RELPATH)
- return ((char *)NULL);
-#endif
-
- /* Watch out. If this file was hashed to "./filename", and
- "./filename" is not executable, then return NULL. */
-
- /* Since we already know "./filename" is not executable, what
- we're really interested in is whether or not the `path'
- portion of the hashed filename is equivalent to the current
- directory, but only if it starts with a `.'. (This catches
- ./. and so on.) same_file () tests general Unix file
- equivalence -- same device and inode. */
- if (*path == '.')
- {
- same = 0;
- tail = (char *)strrchr (path, '/');
-
- if (tail)
- {
- *tail = '\0';
- same = same_file (".", path, (struct stat *)NULL, (struct stat *)NULL);
- *tail = '/';
- }
-
- return same ? (char *)NULL : path;
- }
- }
-
- return (path);
-}
-
-/* **************************************************************** */
-/* */
/* Manipulating the current working directory */
/* */
/* **************************************************************** */
if (the_current_working_directory == 0)
{
- the_current_working_directory = xmalloc (PATH_MAX);
+ the_current_working_directory = (char *)xmalloc (PATH_MAX);
the_current_working_directory[0] = '\0';
directory = getcwd (the_current_working_directory, PATH_MAX);
if (directory == 0)
{
- fprintf (stderr, "%s: could not get current directory: %s\n",
+ fprintf (stderr, "%s: could not get current directory: %s: %s\n",
(for_whom && *for_whom) ? for_whom : get_name_for_error (),
- the_current_working_directory[0]
- ? the_current_working_directory
- : bash_getcwd_errstr);
+ bash_getcwd_errstr, strerror (errno));
free (the_current_working_directory);
the_current_working_directory = (char *)NULL;
WORD_LIST *list;
{
register char *word;
- int job, substring;
+ int job, substring_search;
if (list == 0)
return (current_job);
if (*word == '%')
word++;
- if (digit (*word) && all_digits (word))
+ if (DIGIT (*word) && all_digits (word))
{
job = atoi (word);
- return (job - 1);
+ return (job >= job_slots ? NO_JOB : job - 1);
}
- substring = 0;
+ substring_search = 0;
switch (*word)
{
case 0:
return (previous_job);
case '?': /* Substring search requested. */
- substring++;
+ substring_search++;
word++;
/* FALLTHROUGH */
p = jobs[i]->pipe;
do
{
- if ((substring && strindex (p->command, word)) ||
+ if ((substring_search && strindex (p->command, word)) ||
(STREQN (p->command, word, wl)))
- if (job != NO_JOB)
- {
- builtin_error ("ambigious job spec: %s", word);
- return (DUP_JOB);
- }
- else
- job = i;
+ {
+ if (job != NO_JOB)
+ {
+ builtin_error ("ambigious job spec: %s", word);
+ return (DUP_JOB);
+ }
+ else
+ job = i;
+ }
p = p->next;
}
list = list->next;
continue;
}
+#if defined (JOB_CONTROL)
+ /* POSIX.2 says that `kill -l signum' prints the signal name without
+ the `SIG' prefix. */
+ printf ("%s\n", (this_shell_builtin == kill_builtin) ? name + 3 : name);
+#else
printf ("%s\n", name);
+#endif
}
else
{
}
/* Return the pointer to the function implementing builtin command NAME. */
-Function *
+sh_builtin_func_t *
find_shell_builtin (name)
char *name;
{
current_builtin = builtin_address_internal (name, 0);
- return (current_builtin ? current_builtin->function : (Function *)NULL);
+ return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL);
}
/* Return the address of builtin with NAME, whether it is enabled or not. */
-Function *
+sh_builtin_func_t *
builtin_address (name)
char *name;
{
current_builtin = builtin_address_internal (name, 1);
- return (current_builtin ? current_builtin->function : (Function *)NULL);
+ return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL);
}
/* Return the function implementing the builtin NAME, but only if it is a
POSIX.2 special builtin. */
-Function *
+sh_builtin_func_t *
find_special_builtin (name)
char *name;
{
current_builtin = builtin_address_internal (name, 0);
return ((current_builtin && (current_builtin->flags & SPECIAL_BUILTIN)) ?
current_builtin->function :
- (Function *)NULL);
+ (sh_builtin_func_t *)NULL);
}
static int
initialize_shell_builtins ()
{
qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin),
- shell_builtin_compare);
-}
-
-/* **************************************************************** */
-/* */
-/* Functions for quoting strings to be re-read as input */
-/* */
-/* **************************************************************** */
-
-/* Return a new string which is the single-quoted version of STRING.
- Used by alias and trap, among others. */
-char *
-single_quote (string)
- char *string;
-{
- register int c;
- char *result, *r, *s;
-
- result = (char *)xmalloc (3 + (4 * strlen (string)));
- r = result;
- *r++ = '\'';
-
- for (s = string; s && (c = *s); s++)
- {
- *r++ = c;
-
- if (c == '\'')
- {
- *r++ = '\\'; /* insert escaped single quote */
- *r++ = '\'';
- *r++ = '\''; /* start new quoted string */
- }
- }
-
- *r++ = '\'';
- *r = '\0';
-
- return (result);
-}
-
-/* Quote STRING using double quotes. Return a new string. */
-char *
-double_quote (string)
- char *string;
-{
- register int c;
- char *result, *r, *s;
-
- result = (char *)xmalloc (3 + (2 * strlen (string)));
- r = result;
- *r++ = '"';
-
- for (s = string; s && (c = *s); s++)
- {
- switch (c)
- {
- case '"':
- case '$':
- case '`':
- case '\\':
- *r++ = '\\';
- default:
- *r++ = c;
- break;
- }
- }
-
- *r++ = '"';
- *r = '\0';
-
- return (result);
-}
-
-/* Quote special characters in STRING using backslashes. Return a new
- string. */
-char *
-backslash_quote (string)
- char *string;
-{
- int c;
- char *result, *r, *s;
-
- result = xmalloc (2 * strlen (string) + 1);
-
- for (r = result, s = string; s && (c = *s); s++)
- {
- switch (c)
- {
- case ' ': case '\t': case '\n': /* IFS white space */
- case '\'': case '"': case '\\': /* quoting chars */
- case '|': case '&': case ';': /* shell metacharacters */
- case '(': case ')': case '<': case '>':
- case '!': case '{': case '}': /* reserved words */
- case '*': case '[': case '?': case ']': /* globbing chars */
- case '^':
- case '$': case '`': /* expansion chars */
- *r++ = '\\';
- *r++ = c;
- break;
- case '#': /* comment char */
- if (s == string)
- *r++ = '\\';
- /* FALLTHROUGH */
- default:
- *r++ = c;
- break;
- }
- }
-
- *r = '\0';
- return (result);
-}
-
-int
-contains_shell_metas (string)
- char *string;
-{
- char *s;
-
- for (s = string; s && *s; s++)
- {
- switch (*s)
- {
- case ' ': case '\t': case '\n': /* IFS white space */
- case '\'': case '"': case '\\': /* quoting chars */
- case '|': case '&': case ';': /* shell metacharacters */
- case '(': case ')': case '<': case '>':
- case '!': case '{': case '}': /* reserved words */
- case '*': case '[': case '?': case ']': /* globbing chars */
- case '^':
- case '$': case '`': /* expansion chars */
- return (1);
- case '#':
- if (s == string) /* comment char */
- return (1);
- /* FALLTHROUGH */
- default:
- break;
- }
- }
-
- return (0);
+ (QSFUNC *)shell_builtin_compare);
}