| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* common.c - utility functions for all builtins */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | /* Copyright (C) 1987-2010 Free Software Foundation, Inc.
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    This file is part of GNU Bash, the Bourne Again SHell. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Bash is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |    it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |    the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  |    (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Bash is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |    GNU General Public License for more details. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include <config.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #  ifdef _MINIX
 | 
					
						
							|  |  |  | #    include <sys/types.h>
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #include <chartypes.h>
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #include "../bashtypes.h"
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #include "posixstat.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include <signal.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (PREFER_STDARG)
 | 
					
						
							|  |  |  | #  include <stdarg.h>
 | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #  include <varargs.h>
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "../bashansi.h"
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #include "../bashintl.h"
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #define NEED_FPURGE_DECL
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "../shell.h"
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #include "maxpath.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "../flags.h"
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "../jobs.h"
 | 
					
						
							|  |  |  | #include "../builtins.h"
 | 
					
						
							|  |  |  | #include "../input.h"
 | 
					
						
							|  |  |  | #include "../execute_cmd.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "../trap.h"
 | 
					
						
							|  |  |  | #include "bashgetopt.h"
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "common.h"
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #include "builtext.h"
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include <tilde/tilde.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HISTORY)
 | 
					
						
							|  |  |  | #  include "../bashhist.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #if !defined (errno)
 | 
					
						
							|  |  |  | extern int errno;    | 
					
						
							|  |  |  | #endif /* !errno */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | extern int indirection_level, subshell_environment; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | extern int line_number; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | extern int last_command_exit_value; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | extern int running_trap; | 
					
						
							|  |  |  | extern int posixly_correct; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | extern char *this_command_name, *shell_name; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | extern const char * const bash_getcwd_errstr; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | /* Used by some builtins and the mainline code. */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | sh_builtin_func_t *last_shell_builtin = (sh_builtin_func_t *)NULL; | 
					
						
							|  |  |  | sh_builtin_func_t *this_shell_builtin = (sh_builtin_func_t *)NULL; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*	     Error reporting, usage, and option processing	    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* This is a lot like report_error (), but it is for shell builtins
 | 
					
						
							|  |  |  |    instead of shell control structures, and it won't ever exit the | 
					
						
							|  |  |  |    shell. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | builtin_error_prolog () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   name = get_name_for_error (); | 
					
						
							|  |  |  |   fprintf (stderr, "%s: ", name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (interactive_shell == 0) | 
					
						
							|  |  |  |     fprintf (stderr, _("line %d: "), executing_line_number ()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (this_command_name && *this_command_name) | 
					
						
							|  |  |  |     fprintf (stderr, "%s: ", this_command_name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (PREFER_STDARG)
 | 
					
						
							|  |  |  | builtin_error (const char *format, ...) | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | builtin_error (format, va_alist) | 
					
						
							|  |  |  |      const char *format; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      va_dcl | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   va_list args; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   builtin_error_prolog (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   SH_VA_START (args, format); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   vfprintf (stderr, format, args); | 
					
						
							|  |  |  |   va_end (args); | 
					
						
							|  |  |  |   fprintf (stderr, "\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | #if defined (PREFER_STDARG)
 | 
					
						
							|  |  |  | builtin_warning (const char *format, ...) | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | builtin_warning (format, va_alist) | 
					
						
							|  |  |  |      const char *format; | 
					
						
							|  |  |  |      va_dcl | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   va_list args; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   builtin_error_prolog (); | 
					
						
							|  |  |  |   fprintf (stderr, _("warning: ")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   SH_VA_START (args, format); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   vfprintf (stderr, format, args); | 
					
						
							|  |  |  |   va_end (args); | 
					
						
							|  |  |  |   fprintf (stderr, "\n"); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Print a usage summary for the currently-executing builtin command. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | builtin_usage () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (this_command_name && *this_command_name) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |     fprintf (stderr, _("%s: usage: "), this_command_name); | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   fprintf (stderr, "%s\n", _(current_builtin->short_doc)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   fflush (stderr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Return if LIST is NULL else barf and jump to top_level.  Used by some
 | 
					
						
							|  |  |  |    builtins that do not accept arguments. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | no_args (list) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (list) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       builtin_error (_("too many arguments")); | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  |       top_level_cleanup (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       jump_to_top_level (DISCARD); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Check that no options were given to the currently-executing builtin,
 | 
					
						
							|  |  |  |    and return 0 if there were options. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | no_options (list) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   reset_internal_getopt (); | 
					
						
							|  |  |  |   if (internal_getopt (list, "") != -1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       builtin_usage (); | 
					
						
							|  |  |  |       return (1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return (0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | void | 
					
						
							|  |  |  | sh_needarg (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   builtin_error (_("%s: option requires an argument"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_neednumarg (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   builtin_error (_("%s: numeric argument required"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_notfound (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   builtin_error (_("%s: not found"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Function called when one of the builtin commands detects an invalid
 | 
					
						
							|  |  |  |    option. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_invalidopt (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   builtin_error (_("%s: invalid option"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_invalidoptname (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   builtin_error (_("%s: invalid option name"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_invalidid (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   builtin_error (_("`%s': not a valid identifier"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_invalidnum (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   char *msg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (*s == '0' && isdigit (s[1])) | 
					
						
							|  |  |  |     msg = _("invalid octal number"); | 
					
						
							|  |  |  |   else if (*s == '0' && s[1] == 'x') | 
					
						
							|  |  |  |     msg = _("invalid hex number"); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     msg = _("invalid number"); | 
					
						
							|  |  |  |   builtin_error ("%s: %s", s, msg); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_invalidsig (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   builtin_error (_("%s: invalid signal specification"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_badpid (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   builtin_error (_("`%s': not a pid or valid job spec"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_readonly (s) | 
					
						
							|  |  |  |      const char *s; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   builtin_error (_("%s: readonly variable"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_erange (s, desc) | 
					
						
							|  |  |  |      char *s, *desc; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (s) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     builtin_error (_("%s: %s out of range"), s, desc ? desc : _("argument")); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     builtin_error (_("%s out of range"), desc ? desc : _("argument")); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (JOB_CONTROL)
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_badjob (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   builtin_error (_("%s: no such job"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_nojobs (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (s) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     builtin_error (_("%s: no job control"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     builtin_error (_("no job control")); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (RESTRICTED_SHELL)
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sh_restricted (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (s) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     builtin_error (_("%s: restricted"), s); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     builtin_error (_("restricted")); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | void | 
					
						
							|  |  |  | sh_notbuiltin (s) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   builtin_error (_("%s: not a shell builtin"), s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | void | 
					
						
							|  |  |  | sh_wrerror () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #if defined (DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS) && defined (EPIPE)
 | 
					
						
							|  |  |  |   if (errno != EPIPE) | 
					
						
							|  |  |  | #endif /* DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS && EPIPE */
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   builtin_error (_("write error: %s"), strerror (errno)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 22:21:29 +00:00
										 |  |  | void | 
					
						
							|  |  |  | sh_ttyerror (set) | 
					
						
							|  |  |  |      int set; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (set) | 
					
						
							|  |  |  |     builtin_error (_("error setting terminal attributes: %s"), strerror (errno)); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     builtin_error (_("error getting terminal attributes: %s"), strerror (errno)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | int | 
					
						
							|  |  |  | sh_chkwrite (s) | 
					
						
							|  |  |  |      int s; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   fflush (stdout); | 
					
						
							|  |  |  |   if (ferror (stdout)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       sh_wrerror (); | 
					
						
							|  |  |  |       fpurge (stdout); | 
					
						
							|  |  |  |       clearerr (stdout); | 
					
						
							|  |  |  |       return (EXECUTION_FAILURE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return (s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*	     Shell positional parameter manipulation		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Convert a WORD_LIST into a C-style argv.  Return the number of elements
 | 
					
						
							|  |  |  |    in the list in *IP, if IP is non-null.  A convenience function for | 
					
						
							|  |  |  |    loadable builtins; also used by `test'. */ | 
					
						
							|  |  |  | char ** | 
					
						
							|  |  |  | make_builtin_argv (list, ip) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  |      int *ip; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char **argv; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   argv = strvec_from_word_list (list, 0, 1, ip); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   argv[0] = this_command_name; | 
					
						
							|  |  |  |   return argv; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | /* Remember LIST in $1 ... $9, and REST_OF_ARGS.  If DESTRUCTIVE is
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    non-zero, then discard whatever the existing arguments are, else | 
					
						
							|  |  |  |    only discard the ones that are to be replaced. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | remember_args (list, destructive) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  |      int destructive; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 1; i < 10; i++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if ((destructive || list) && dollar_vars[i]) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  free (dollar_vars[i]); | 
					
						
							|  |  |  | 	  dollar_vars[i] = (char *)NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (list) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  dollar_vars[i] = savestring (list->word->word); | 
					
						
							|  |  |  | 	  list = list->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* If arguments remain, assign them to REST_OF_ARGS.
 | 
					
						
							|  |  |  |      Note that copy_word_list (NULL) returns NULL, and | 
					
						
							|  |  |  |      that dispose_words (NULL) does nothing. */ | 
					
						
							|  |  |  |   if (destructive || list) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       dispose_words (rest_of_args); | 
					
						
							|  |  |  |       rest_of_args = copy_word_list (list); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (destructive) | 
					
						
							|  |  |  |     set_dollar_vars_changed (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static int changed_dollar_vars; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Have the dollar variables been reset to new values since we last
 | 
					
						
							|  |  |  |    checked? */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | dollar_vars_changed () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (changed_dollar_vars); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | set_dollar_vars_unchanged () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   changed_dollar_vars = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | set_dollar_vars_changed () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (variable_context) | 
					
						
							|  |  |  |     changed_dollar_vars |= ARGS_FUNC; | 
					
						
							|  |  |  |   else if (this_shell_builtin == set_builtin) | 
					
						
							|  |  |  |     changed_dollar_vars |= ARGS_SETBLTIN; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     changed_dollar_vars |= ARGS_INVOC; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | /*		Validating numeric input and arguments		    */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 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 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    follow.  If FATAL is 1, call throw_to_top_level, which exits the | 
					
						
							|  |  |  |    shell; if it's 2, call jump_to_top_level (DISCARD), which aborts the | 
					
						
							|  |  |  |    current command; if FATAL is 0, return an indication of an invalid | 
					
						
							|  |  |  |    number by setting *NUMOK == 0 and return -1. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | get_numeric_arg (list, fatal, count) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      WORD_LIST *list; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |      int fatal; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      intmax_t *count; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   char *arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (count) | 
					
						
							|  |  |  |     *count = 1; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (list && list->word && ISOPTION (list->word->word, '-')) | 
					
						
							|  |  |  |     list = list->next; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (list) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       arg = list->word->word; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       if (arg == 0 || (legal_number (arg, count) == 0)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  sh_neednumarg (list->word->word ? list->word->word : "`'"); | 
					
						
							|  |  |  | 	  if (fatal == 0) | 
					
						
							|  |  |  | 	    return 0; | 
					
						
							|  |  |  | 	  else if (fatal == 1)		/* fatal == 1; abort */ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	    throw_to_top_level (); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  else				/* fatal == 2; discard current command */ | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  | 	    { | 
					
						
							|  |  |  | 	      top_level_cleanup (); | 
					
						
							|  |  |  | 	      jump_to_top_level (DISCARD); | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |       no_args (list->next); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   return (1); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | /* Get an eight-bit status value from LIST */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | get_exitstat (list) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int status; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   intmax_t sval; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   char *arg; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (list && list->word && ISOPTION (list->word->word, '-')) | 
					
						
							|  |  |  |     list = list->next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (list == 0) | 
					
						
							|  |  |  |     return (last_command_exit_value);       | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   arg = list->word->word; | 
					
						
							|  |  |  |   if (arg == 0 || legal_number (arg, &sval) == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       sh_neednumarg (list->word->word ? list->word->word : "`'"); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       return EX_BADUSAGE; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   no_args (list->next); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   status = sval & 255; | 
					
						
							|  |  |  |   return status; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Return the octal number parsed from STRING, or -1 to indicate
 | 
					
						
							|  |  |  |    that the string contained a bad number. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | read_octal (string) | 
					
						
							|  |  |  |      char *string; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int result, digits; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   result = digits = 0; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   while (*string && ISOCTAL (*string)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       digits++; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       result = (result * 8) + (*string++ - '0'); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       if (result > 0777) | 
					
						
							|  |  |  | 	return -1; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   if (digits == 0 || *string) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     result = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*	     Manipulating the current working directory		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Return a consed string which is the current working directory.
 | 
					
						
							|  |  |  |    FOR_WHOM is the name of the caller for error printing.  */ | 
					
						
							|  |  |  | char *the_current_working_directory = (char *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | get_working_directory (for_whom) | 
					
						
							|  |  |  |      char *for_whom; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (no_symbolic_links) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       FREE (the_current_working_directory); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       the_current_working_directory = (char *)NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (the_current_working_directory == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  | #if defined (GETCWD_BROKEN)
 | 
					
						
							|  |  |  |       the_current_working_directory = getcwd (0, PATH_MAX); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       the_current_working_directory = getcwd (0, 0); | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       if (the_current_working_directory == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  fprintf (stderr, _("%s: error retrieving current directory: %s: %s\n"), | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 		   (for_whom && *for_whom) ? for_whom : get_name_for_error (), | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 		   _(bash_getcwd_errstr), strerror (errno)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  return (char *)NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (savestring (the_current_working_directory)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Make NAME our internal idea of the current working directory. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | set_working_directory (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   FREE (the_current_working_directory); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   the_current_working_directory = savestring (name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*	     	Job control support functions			    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #if defined (JOB_CONTROL)
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | int | 
					
						
							|  |  |  | get_job_by_name (name, flags) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i, wl, cl, match, job; | 
					
						
							|  |  |  |   register PROCESS *p; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   register JOB *j; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   job = NO_JOB; | 
					
						
							|  |  |  |   wl = strlen (name); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   for (i = js.j_jobslots - 1; i >= 0; i--) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       j = get_job_by_jid (i); | 
					
						
							|  |  |  |       if (j == 0 || ((flags & JM_STOPPED) && J_JOBSTATE(j) != JSTOPPED)) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |         continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       p = j->pipe; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       do | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  | 	  if (flags & JM_EXACT) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      cl = strlen (p->command); | 
					
						
							|  |  |  | 	      match = STREQN (p->command, name, cl); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else if (flags & JM_SUBSTRING) | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | 	    match = strcasestr (p->command, name) != (char *)0; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  else | 
					
						
							|  |  |  | 	    match = STREQN (p->command, name, wl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  if (match == 0) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      p = p->next; | 
					
						
							|  |  |  | 	      continue; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else if (flags & JM_FIRSTMATCH) | 
					
						
							|  |  |  | 	    return i;		/* return first match */ | 
					
						
							|  |  |  | 	  else if (job != NO_JOB) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      if (this_shell_builtin) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	        builtin_error (_("%s: ambiguous job spec"), name); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	      else | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	        internal_error (_("%s: ambiguous job spec"), name); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	      return (DUP_JOB); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    job = i; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       while (p != j->pipe); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (job); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Return the job spec found in LIST. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | get_job_spec (list) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register char *word; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   int job, jflags; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (list == 0) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     return (js.j_current); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   word = list->word->word; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (*word == '\0') | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     return (NO_JOB); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (*word == '%') | 
					
						
							|  |  |  |     word++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   if (DIGIT (*word) && all_digits (word)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       job = atoi (word); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       return (job > js.j_jobslots ? NO_JOB : job - 1); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   jflags = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   switch (*word) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case 0: | 
					
						
							|  |  |  |     case '%': | 
					
						
							|  |  |  |     case '+': | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       return (js.j_current); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case '-': | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       return (js.j_previous); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case '?':			/* Substring search requested. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       jflags |= JM_SUBSTRING; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       word++; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       /* FALLTHROUGH */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       return get_job_by_name (word, jflags); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /* JOB_CONTROL */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * NOTE:  `kill' calls this function with forcecols == 0 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | display_signal_list (list, forcecols) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  |      int forcecols; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   register int i, column; | 
					
						
							|  |  |  |   char *name; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   int result, signum, dflags; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   intmax_t lsignum; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   result = EXECUTION_SUCCESS; | 
					
						
							|  |  |  |   if (!list) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       for (i = 1, column = 0; i < NSIG; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  name = signal_name (i); | 
					
						
							|  |  |  | 	  if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7)) | 
					
						
							|  |  |  | 	    continue; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  if (posixly_correct && !forcecols) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	    { | 
					
						
							|  |  |  | 	      /* This is for the kill builtin.  POSIX.2 says the signal names
 | 
					
						
							|  |  |  | 		 are displayed without the `SIG' prefix. */ | 
					
						
							|  |  |  | 	      if (STREQN (name, "SIG", 3)) | 
					
						
							|  |  |  | 		name += 3; | 
					
						
							|  |  |  | 	      printf ("%s%s", name, (i == NSIG - 1) ? "" : " "); | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  else | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      printf ("%2d) %s", i, name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	      if (++column < 5) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 		printf ("\t"); | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  printf ("\n"); | 
					
						
							|  |  |  | 		  column = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if ((posixly_correct && !forcecols) || column != 0) | 
					
						
							|  |  |  | 	printf ("\n"); | 
					
						
							|  |  |  |       return result; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* List individual signal names or numbers. */ | 
					
						
							|  |  |  |   while (list) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       if (legal_number (list->word->word, &lsignum)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  /* This is specified by Posix.2 so that exit statuses can be
 | 
					
						
							|  |  |  | 	     mapped into signal numbers. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  if (lsignum > 128) | 
					
						
							|  |  |  | 	    lsignum -= 128; | 
					
						
							|  |  |  | 	  if (lsignum < 0 || lsignum >= NSIG) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	      sh_invalidsig (list->word->word); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	      result = EXECUTION_FAILURE; | 
					
						
							|  |  |  | 	      list = list->next; | 
					
						
							|  |  |  | 	      continue; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  signum = lsignum; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  name = signal_name (signum); | 
					
						
							|  |  |  | 	  if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7)) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      list = list->next; | 
					
						
							|  |  |  | 	      continue; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #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
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  printf ("%s\n", name); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  dflags = DSIG_NOCASE; | 
					
						
							|  |  |  | 	  if (posixly_correct == 0 || this_shell_builtin != kill_builtin) | 
					
						
							|  |  |  | 	    dflags |= DSIG_SIGPREFIX; | 
					
						
							|  |  |  | 	  signum = decode_signal (list->word->word, dflags); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  if (signum == NO_SIG) | 
					
						
							|  |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	      sh_invalidsig (list->word->word); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	      result = EXECUTION_FAILURE; | 
					
						
							|  |  |  | 	      list = list->next; | 
					
						
							|  |  |  | 	      continue; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  printf ("%d\n", signum); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |       list = list->next; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return (result); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*	    Finding builtin commands and their functions	    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Perform a binary search and return the address of the builtin function
 | 
					
						
							|  |  |  |    whose name is NAME.  If the function couldn't be found, or the builtin | 
					
						
							|  |  |  |    is disabled or has no function associated with it, return NULL. | 
					
						
							|  |  |  |    Return the address of the builtin. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    DISABLED_OKAY means find it even if the builtin is disabled. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | struct builtin * | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | builtin_address_internal (name, disabled_okay) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  |      int disabled_okay; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int hi, lo, mid, j; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   hi = num_shell_builtins - 1; | 
					
						
							|  |  |  |   lo = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (lo <= hi) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       mid = (lo + hi) / 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       j = shell_builtins[mid].name[0] - name[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (j == 0) | 
					
						
							|  |  |  | 	j = strcmp (shell_builtins[mid].name, name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (j == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* It must have a function pointer.  It must be enabled, or we
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	     must have explicitly allowed disabled functions to be found, | 
					
						
							|  |  |  | 	     and it must not have been deleted. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  if (shell_builtins[mid].function && | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	      ((shell_builtins[mid].flags & BUILTIN_DELETED) == 0) && | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	      ((shell_builtins[mid].flags & BUILTIN_ENABLED) || disabled_okay)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	    return (&shell_builtins[mid]); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  else | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	    return ((struct builtin *)NULL); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |       if (j > 0) | 
					
						
							|  |  |  | 	hi = mid - 1; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	lo = mid + 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return ((struct builtin *)NULL); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Return the pointer to the function implementing builtin command NAME. */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | sh_builtin_func_t * | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | find_shell_builtin (name) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      char *name; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   current_builtin = builtin_address_internal (name, 0); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Return the address of builtin with NAME, whether it is enabled or not. */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | sh_builtin_func_t * | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | builtin_address (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   current_builtin = builtin_address_internal (name, 1); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Return the function implementing the builtin NAME, but only if it is a
 | 
					
						
							|  |  |  |    POSIX.2 special builtin. */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | sh_builtin_func_t * | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | find_special_builtin (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   current_builtin = builtin_address_internal (name, 0); | 
					
						
							|  |  |  |   return ((current_builtin && (current_builtin->flags & SPECIAL_BUILTIN)) ? | 
					
						
							|  |  |  |   			current_builtin->function : | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   			(sh_builtin_func_t *)NULL); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | shell_builtin_compare (sbp1, sbp2) | 
					
						
							|  |  |  |      struct builtin *sbp1, *sbp2; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((result = sbp1->name[0] - sbp2->name[0]) == 0) | 
					
						
							|  |  |  |     result = strcmp (sbp1->name, sbp2->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Sort the table of shell builtins so that the binary search will work
 | 
					
						
							|  |  |  |    in find_shell_builtin. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | initialize_shell_builtins () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin), | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     (QSFUNC *)shell_builtin_compare); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } |