LCOV - code coverage report
Current view: top level - bash-4.4.23/builtins - common.c (source / functions) Hit Total Coverage
Test: cov-bash.info Lines: 201 346 58.1 %
Date: 2020-10-29 14:49:28 Functions: 31 43 72.1 %

          Line data    Source code
       1             : /* common.c - utility functions for all builtins */
       2             : 
       3             : /* Copyright (C) 1987-2016 Free Software Foundation, Inc.
       4             : 
       5             :    This file is part of GNU Bash, the Bourne Again SHell.
       6             : 
       7             :    Bash is free software: you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation, either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    Bash is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include <config.h>
      22             : 
      23             : #if defined (HAVE_UNISTD_H)
      24             : #  ifdef _MINIX
      25             : #    include <sys/types.h>
      26             : #  endif
      27             : #  include <unistd.h>
      28             : #endif
      29             : 
      30             : #include <stdio.h>
      31             : #include <chartypes.h>
      32             : #include "../bashtypes.h"
      33             : #include "posixstat.h"
      34             : #include <signal.h>
      35             : 
      36             : #include <errno.h>
      37             : 
      38             : #if defined (PREFER_STDARG)
      39             : #  include <stdarg.h>
      40             : #else
      41             : #  include <varargs.h>
      42             : #endif
      43             : 
      44             : #include "../bashansi.h"
      45             : #include "../bashintl.h"
      46             : 
      47             : #define NEED_FPURGE_DECL
      48             : 
      49             : #include "../shell.h"
      50             : #include "maxpath.h"
      51             : #include "../flags.h"
      52             : #include "../jobs.h"
      53             : #include "../builtins.h"
      54             : #include "../input.h"
      55             : #include "../execute_cmd.h"
      56             : #include "../trap.h"
      57             : #include "bashgetopt.h"
      58             : #include "common.h"
      59             : #include "builtext.h"
      60             : #include <tilde/tilde.h>
      61             : 
      62             : #if defined (HISTORY)
      63             : #  include "../bashhist.h"
      64             : #endif
      65             : 
      66             : #if !defined (errno)
      67             : extern int errno;   
      68             : #endif /* !errno */
      69             : 
      70             : extern int indirection_level, subshell_environment;
      71             : extern int line_number;
      72             : extern int last_command_exit_value;
      73             : extern int trap_saved_exit_value;
      74             : extern int running_trap;
      75             : extern int posixly_correct;
      76             : extern char *this_command_name, *shell_name;
      77             : extern const char * const bash_getcwd_errstr;
      78             : 
      79             : /* Used by some builtins and the mainline code. */
      80             : sh_builtin_func_t *last_shell_builtin = (sh_builtin_func_t *)NULL;
      81             : sh_builtin_func_t *this_shell_builtin = (sh_builtin_func_t *)NULL;
      82             : 
      83             : /* **************************************************************** */
      84             : /*                                                                  */
      85             : /*           Error reporting, usage, and option processing          */
      86             : /*                                                                  */
      87             : /* **************************************************************** */
      88             : 
      89             : /* This is a lot like report_error (), but it is for shell builtins
      90             :    instead of shell control structures, and it won't ever exit the
      91             :    shell. */
      92             : 
      93             : static void
      94      113377 : builtin_error_prolog ()
      95             : {
      96      113377 :   char *name;
      97             : 
      98      113377 :   name = get_name_for_error ();
      99      113377 :   fprintf (stderr, "%s: ", name);
     100             : 
     101      113377 :   if (interactive_shell == 0)
     102      113377 :     fprintf (stderr, _("line %d: "), executing_line_number ());
     103             : 
     104      113377 :   if (this_command_name && *this_command_name)
     105      113377 :     fprintf (stderr, "%s: ", this_command_name);
     106      113377 : }
     107             : 
     108             : void
     109             : #if defined (PREFER_STDARG)
     110      113302 : builtin_error (const char *format, ...)
     111             : #else
     112             : builtin_error (format, va_alist)
     113             :      const char *format;
     114             :      va_dcl
     115             : #endif
     116             : {
     117      113302 :   va_list args;
     118             : 
     119      113302 :   builtin_error_prolog ();
     120             : 
     121      113302 :   SH_VA_START (args, format);
     122             : 
     123      113302 :   vfprintf (stderr, format, args);
     124      113302 :   va_end (args);
     125      113302 :   fprintf (stderr, "\n");
     126      113302 : }
     127             : 
     128             : void
     129             : #if defined (PREFER_STDARG)
     130          75 : builtin_warning (const char *format, ...)
     131             : #else
     132             : builtin_warning (format, va_alist)
     133             :      const char *format;
     134             :      va_dcl
     135             : #endif
     136             : {
     137          75 :   va_list args;
     138             : 
     139          75 :   builtin_error_prolog ();
     140          75 :   fprintf (stderr, _("warning: "));
     141             : 
     142          75 :   SH_VA_START (args, format);
     143             : 
     144          75 :   vfprintf (stderr, format, args);
     145          75 :   va_end (args);
     146          75 :   fprintf (stderr, "\n");
     147          75 : }
     148             : 
     149             : /* Print a usage summary for the currently-executing builtin command. */
     150             : void
     151         523 : builtin_usage ()
     152             : {
     153         523 :   if (this_command_name && *this_command_name)
     154         523 :     fprintf (stderr, _("%s: usage: "), this_command_name);
     155         523 :   fprintf (stderr, "%s\n", _(current_builtin->short_doc));
     156         523 :   fflush (stderr);
     157         523 : }
     158             : 
     159             : /* Return if LIST is NULL else barf and jump to top_level.  Used by some
     160             :    builtins that do not accept arguments. */
     161             : void
     162     6741113 : no_args (list)
     163             :      WORD_LIST *list;
     164             : {
     165     6741113 :   if (list)
     166             :     {
     167         169 :       builtin_error (_("too many arguments"));
     168         169 :       top_level_cleanup ();
     169         169 :       jump_to_top_level (DISCARD);
     170             :     }
     171     6740944 : }
     172             : 
     173             : /* Check that no options were given to the currently-executing builtin,
     174             :    and return 0 if there were options. */
     175             : int
     176    16846898 : no_options (list)
     177             :      WORD_LIST *list;
     178             : {
     179    16846898 :   int opt;
     180             : 
     181    16846898 :   reset_internal_getopt ();
     182    16846898 :   if ((opt = internal_getopt (list, "")) != -1)
     183             :     {
     184          87 :       if (opt == GETOPT_HELP)
     185             :         {
     186           0 :           builtin_help ();
     187           0 :           return (2);
     188             :         }
     189          87 :       builtin_usage ();
     190          87 :       return (1);
     191             :     }
     192             :   return (0);
     193             : }
     194             : 
     195             : void
     196           0 : sh_needarg (s)
     197             :      char *s;
     198             : {
     199           0 :   builtin_error (_("%s: option requires an argument"), s);
     200           0 : }
     201             : 
     202             : void
     203       30341 : sh_neednumarg (s)
     204             :      char *s;
     205             : {
     206       30341 :   builtin_error (_("%s: numeric argument required"), s);
     207       30341 : }
     208             : 
     209             : void
     210         182 : sh_notfound (s)
     211             :      char *s;
     212             : {
     213         182 :   builtin_error (_("%s: not found"), s);
     214         182 : }
     215             : 
     216             : /* Function called when one of the builtin commands detects an invalid
     217             :    option. */
     218             : void
     219          87 : sh_invalidopt (s)
     220             :      char *s;
     221             : {
     222          87 :   builtin_error (_("%s: invalid option"), s);
     223          87 : }
     224             : 
     225             : void
     226           0 : sh_invalidoptname (s)
     227             :      char *s;
     228             : {
     229           0 :   builtin_error (_("%s: invalid option name"), s);
     230           0 : }
     231             : 
     232             : void
     233         153 : sh_invalidid (s)
     234             :      char *s;
     235             : {
     236         153 :   builtin_error (_("`%s': not a valid identifier"), s);
     237         153 : }
     238             : 
     239             : void
     240           0 : sh_invalidnum (s)
     241             :      char *s;
     242             : {
     243           0 :   char *msg;
     244             : 
     245           0 :   if (*s == '0' && isdigit ((unsigned char)s[1]))
     246           0 :     msg = _("invalid octal number");
     247           0 :   else if (*s == '0' && s[1] == 'x')
     248           0 :     msg = _("invalid hex number");
     249             :   else
     250           0 :     msg = _("invalid number");
     251           0 :   builtin_error ("%s: %s", s, msg);
     252           0 : }
     253             : 
     254             : void
     255          75 : sh_invalidsig (s)
     256             :      char *s;
     257             : {
     258          75 :   builtin_error (_("%s: invalid signal specification"), s);
     259          75 : }
     260             : 
     261             : void
     262          45 : sh_badpid (s)
     263             :      char *s;
     264             : {
     265          45 :   builtin_error (_("`%s': not a pid or valid job spec"), s);
     266          45 : }
     267             : 
     268             : void
     269           0 : sh_readonly (s)
     270             :      const char *s;
     271             : {
     272           0 :   builtin_error (_("%s: readonly variable"), s);
     273           0 : }
     274             : 
     275             : void
     276           0 : sh_erange (s, desc)
     277             :      char *s, *desc;
     278             : {
     279           0 :   if (s)
     280           0 :     builtin_error (_("%s: %s out of range"), s, desc ? desc : _("argument"));
     281             :   else
     282           0 :     builtin_error (_("%s out of range"), desc ? desc : _("argument"));
     283           0 : }
     284             : 
     285             : #if defined (JOB_CONTROL)
     286             : void
     287         678 : sh_badjob (s)
     288             :      char *s;
     289             : {
     290         678 :   builtin_error (_("%s: no such job"), s);
     291         678 : }
     292             : 
     293             : void
     294         595 : sh_nojobs (s)
     295             :      char *s;
     296             : {
     297         595 :   if (s)
     298          50 :     builtin_error (_("%s: no job control"), s);
     299             :   else
     300         545 :     builtin_error (_("no job control"));
     301         595 : }
     302             : #endif
     303             : 
     304             : #if defined (RESTRICTED_SHELL)
     305             : void
     306           0 : sh_restricted (s)
     307             :      char *s;
     308             : {
     309           0 :   if (s)
     310           0 :     builtin_error (_("%s: restricted"), s);
     311             :   else
     312           0 :     builtin_error (_("restricted"));
     313           0 : }
     314             : #endif
     315             : 
     316             : void
     317          66 : sh_notbuiltin (s)
     318             :      char *s;
     319             : {
     320          66 :   builtin_error (_("%s: not a shell builtin"), s);
     321          66 : }
     322             : 
     323             : void
     324         106 : sh_wrerror ()
     325             : {
     326             : #if defined (DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS) && defined (EPIPE)
     327             :   if (errno != EPIPE)
     328             : #endif /* DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS && EPIPE */
     329         106 :   builtin_error (_("write error: %s"), strerror (errno));
     330         106 : }
     331             : 
     332             : void
     333           0 : sh_ttyerror (set)
     334             :      int set;
     335             : {
     336           0 :   if (set)
     337           0 :     builtin_error (_("error setting terminal attributes: %s"), strerror (errno));
     338             :   else
     339           0 :     builtin_error (_("error getting terminal attributes: %s"), strerror (errno));
     340           0 : }
     341             : 
     342             : int
     343     1910114 : sh_chkwrite (s)
     344             :      int s;
     345             : {
     346     1910114 :   QUIT;
     347     1910114 :   fflush (stdout);
     348     1910114 :   QUIT;
     349     1910114 :   if (ferror (stdout))
     350             :     {
     351         106 :       sh_wrerror ();
     352         106 :       fpurge (stdout);
     353         106 :       clearerr (stdout);
     354         106 :       return (EXECUTION_FAILURE);
     355             :     }
     356             :   return (s);
     357             : }
     358             : 
     359             : /* **************************************************************** */
     360             : /*                                                                  */
     361             : /*           Shell positional parameter manipulation                */
     362             : /*                                                                  */
     363             : /* **************************************************************** */
     364             : 
     365             : /* Convert a WORD_LIST into a C-style argv.  Return the number of elements
     366             :    in the list in *IP, if IP is non-null.  A convenience function for
     367             :    loadable builtins; also used by `test'. */
     368             : char **
     369    24005772 : make_builtin_argv (list, ip)
     370             :      WORD_LIST *list;
     371             :      int *ip;
     372             : {
     373    24005772 :   char **argv;
     374             : 
     375    24005772 :   argv = strvec_from_word_list (list, 0, 1, ip);
     376    24005772 :   argv[0] = this_command_name;
     377    24005772 :   return argv;
     378             : }
     379             : 
     380             : /* Remember LIST in $1 ... $9, and REST_OF_ARGS.  If DESTRUCTIVE is
     381             :    non-zero, then discard whatever the existing arguments are, else
     382             :    only discard the ones that are to be replaced. */
     383             : void
     384       28414 : remember_args (list, destructive)
     385             :      WORD_LIST *list;
     386             :      int destructive;
     387             : {
     388       28414 :   register int i;
     389             : 
     390      284140 :   for (i = 1; i < 10; i++)
     391             :     {
     392      255726 :       if ((destructive || list) && dollar_vars[i])
     393             :         {
     394       17708 :           free (dollar_vars[i]);
     395       17708 :           dollar_vars[i] = (char *)NULL;
     396             :         }
     397             : 
     398      255726 :       if (list)
     399             :         {
     400       17789 :           dollar_vars[i] = savestring (list->word->word);
     401       17789 :           list = list->next;
     402             :         }
     403             :     }
     404             : 
     405             :   /* If arguments remain, assign them to REST_OF_ARGS.
     406             :      Note that copy_word_list (NULL) returns NULL, and
     407             :      that dispose_words (NULL) does nothing. */
     408       28414 :   if (destructive || list)
     409             :     {
     410       28414 :       dispose_words (rest_of_args);
     411       28414 :       rest_of_args = copy_word_list (list);
     412             :     }
     413             : 
     414       28414 :   if (destructive)
     415       28414 :     set_dollar_vars_changed ();
     416             : 
     417       28414 :   invalidate_cached_quoted_dollar_at ();
     418       28414 : }
     419             : 
     420             : static int changed_dollar_vars;
     421             : 
     422             : /* Have the dollar variables been reset to new values since we last
     423             :    checked? */
     424             : int
     425        6790 : dollar_vars_changed ()
     426             : {
     427        6790 :   return (changed_dollar_vars);
     428             : }
     429             : 
     430             : void
     431    16867063 : set_dollar_vars_unchanged ()
     432             : {
     433    16867063 :   changed_dollar_vars = 0;
     434    16867063 : }
     435             : 
     436             : void
     437           0 : set_dollar_vars_changed ()
     438             : {
     439       28414 :   if (variable_context)
     440       14807 :     changed_dollar_vars |= ARGS_FUNC;
     441       13607 :   else if (this_shell_builtin == set_builtin)
     442           0 :     changed_dollar_vars |= ARGS_SETBLTIN;
     443             :   else
     444       13607 :     changed_dollar_vars |= ARGS_INVOC;
     445           0 : }
     446             : 
     447             : /* **************************************************************** */
     448             : /*                                                                  */
     449             : /*              Validating numeric input and arguments              */
     450             : /*                                                                  */
     451             : /* **************************************************************** */
     452             : 
     453             : /* Read a numeric arg for this_command_name, the name of the shell builtin
     454             :    that wants it.  LIST is the word list that the arg is to come from.
     455             :    Accept only the numeric argument; report an error if other arguments
     456             :    follow.  If FATAL is 1, call throw_to_top_level, which exits the
     457             :    shell; if it's 2, call jump_to_top_level (DISCARD), which aborts the
     458             :    current command; if FATAL is 0, return an indication of an invalid
     459             :    number by setting *NUMOK == 0 and return -1. */
     460             : int
     461         101 : get_numeric_arg (list, fatal, count)
     462             :      WORD_LIST *list;
     463             :      int fatal;
     464             :      intmax_t *count;
     465             : {
     466         101 :   char *arg;
     467             : 
     468         101 :   if (count)
     469         101 :     *count = 1;
     470             : 
     471         101 :   if (list && list->word && ISOPTION (list->word->word, '-'))
     472           0 :     list = list->next;
     473             : 
     474         101 :   if (list)
     475             :     {
     476          45 :       arg = list->word->word;
     477          45 :       if (arg == 0 || (legal_number (arg, count) == 0))
     478             :         {
     479          70 :           sh_neednumarg (list->word->word ? list->word->word : "`'");
     480          35 :           if (fatal == 0)
     481             :             return 0;
     482           0 :           else if (fatal == 1)          /* fatal == 1; abort */
     483           0 :             throw_to_top_level ();
     484             :           else                          /* fatal == 2; discard current command */
     485             :             {
     486           0 :               top_level_cleanup ();
     487           0 :               jump_to_top_level (DISCARD);
     488             :             }
     489             :         }
     490          10 :       no_args (list->next);
     491             :     }
     492             : 
     493             :   return (1);
     494             : }
     495             : 
     496             : /* Get an eight-bit status value from LIST */
     497             : int
     498     6881805 : get_exitstat (list)
     499             :      WORD_LIST *list;
     500             : {
     501     6881805 :   int status;
     502     6881805 :   intmax_t sval;
     503     6881805 :   char *arg;
     504             : 
     505     6881805 :   if (list && list->word && ISOPTION (list->word->word, '-'))
     506           9 :     list = list->next;
     507             : 
     508     6881805 :   if (list == 0)
     509             :     {
     510             :       /* If we're not running the DEBUG trap, the return builtin, when not
     511             :          given any arguments, uses the value of $? before the trap ran.  If
     512             :          given an argument, return uses it.  This means that the trap can't
     513             :          change $?.  The DEBUG trap gets to change $?, though, since that is
     514             :          part of its reason for existing, and because the extended debug mode
     515             :          does things with the return value. */
     516      110396 :       if (this_shell_builtin == return_builtin && running_trap > 0 && running_trap != DEBUG_TRAP+1)
     517           0 :         return (trap_saved_exit_value);
     518      110396 :       return (last_command_exit_value);
     519             :     }
     520             : 
     521     6771409 :   arg = list->word->word;
     522     6771409 :   if (arg == 0 || legal_number (arg, &sval) == 0)
     523             :     {
     524       30306 :       sh_neednumarg (list->word->word ? list->word->word : "`'");
     525       30306 :       return EX_BADUSAGE;
     526             :     }
     527     6741103 :   no_args (list->next);
     528             : 
     529     6740934 :   status = sval & 255;
     530     6740934 :   return status;
     531             : }
     532             : 
     533             : /* Return the octal number parsed from STRING, or -1 to indicate
     534             :    that the string contained a bad number. */
     535             : int
     536           0 : read_octal (string)
     537             :      char *string;
     538             : {
     539           0 :   int result, digits;
     540             : 
     541           0 :   result = digits = 0;
     542           0 :   while (*string && ISOCTAL (*string))
     543             :     {
     544           0 :       digits++;
     545           0 :       result = (result * 8) + (*string++ - '0');
     546           0 :       if (result > 0777)
     547             :         return -1;
     548             :     }
     549             : 
     550           0 :   if (digits == 0 || *string)
     551           0 :     result = -1;
     552             : 
     553             :   return (result);
     554             : }
     555             : 
     556             : /* **************************************************************** */
     557             : /*                                                                  */
     558             : /*           Manipulating the current working directory             */
     559             : /*                                                                  */
     560             : /* **************************************************************** */
     561             : 
     562             : /* Return a consed string which is the current working directory.
     563             :    FOR_WHOM is the name of the caller for error printing.  */
     564             : char *the_current_working_directory = (char *)NULL;
     565             : 
     566             : char *
     567           0 : get_working_directory (for_whom)
     568             :      char *for_whom;
     569             : {
     570           0 :   if (no_symbolic_links)
     571             :     {
     572           0 :       FREE (the_current_working_directory);
     573           0 :       the_current_working_directory = (char *)NULL;
     574             :     }
     575             : 
     576           0 :   if (the_current_working_directory == 0)
     577             :     {
     578             : #if defined (GETCWD_BROKEN)
     579             :       the_current_working_directory = getcwd (0, PATH_MAX);
     580             : #else
     581           0 :       the_current_working_directory = getcwd (0, 0);
     582             : #endif
     583           0 :       if (the_current_working_directory == 0)
     584             :         {
     585           0 :           fprintf (stderr, _("%s: error retrieving current directory: %s: %s\n"),
     586           0 :                    (for_whom && *for_whom) ? for_whom : get_name_for_error (),
     587           0 :                    _(bash_getcwd_errstr), strerror (errno));
     588           0 :           return (char *)NULL;
     589             :         }
     590             :     }
     591             : 
     592           0 :   return (savestring (the_current_working_directory));
     593             : }
     594             : 
     595             : /* Make NAME our internal idea of the current working directory. */
     596             : void
     597     9143282 : set_working_directory (name)
     598             :      char *name;
     599             : {
     600     9143282 :   FREE (the_current_working_directory);
     601     9143282 :   the_current_working_directory = savestring (name);
     602     9143282 : }
     603             : 
     604             : /* **************************************************************** */
     605             : /*                                                                  */
     606             : /*              Job control support functions                       */
     607             : /*                                                                  */
     608             : /* **************************************************************** */
     609             : 
     610             : #if defined (JOB_CONTROL)
     611             : int
     612         660 : get_job_by_name (name, flags)
     613             :      const char *name;
     614             :      int flags;
     615             : {
     616         660 :   register int i, wl, cl, match, job;
     617         660 :   register PROCESS *p;
     618         660 :   register JOB *j;
     619             : 
     620         660 :   job = NO_JOB;
     621         660 :   wl = strlen (name);
     622        1660 :   for (i = js.j_jobslots - 1; i >= 0; i--)
     623             :     {
     624        1000 :       j = get_job_by_jid (i);
     625        1000 :       if (j == 0 || ((flags & JM_STOPPED) && J_JOBSTATE(j) != JSTOPPED))
     626             :         continue;
     627             : 
     628           0 :       p = j->pipe;
     629           0 :       do
     630             :         {
     631           0 :           if (flags & JM_EXACT)
     632             :             {
     633           0 :               cl = strlen (p->command);
     634           0 :               match = STREQN (p->command, name, cl);
     635             :             }
     636           0 :           else if (flags & JM_SUBSTRING)
     637           0 :             match = strcasestr (p->command, name) != (char *)0;
     638             :           else
     639           0 :             match = STREQN (p->command, name, wl);
     640             : 
     641           0 :           if (match == 0)
     642             :             {
     643           0 :               p = p->next;
     644           0 :               continue;
     645             :             }
     646           0 :           else if (flags & JM_FIRSTMATCH)
     647           0 :             return i;           /* return first match */
     648           0 :           else if (job != NO_JOB)
     649             :             {
     650           0 :               if (this_shell_builtin)
     651           0 :                 builtin_error (_("%s: ambiguous job spec"), name);
     652             :               else
     653           0 :                 internal_error (_("%s: ambiguous job spec"), name);
     654           0 :               return (DUP_JOB);
     655             :             }
     656             :           else
     657             :             job = i;
     658             :         }
     659           0 :       while (p != j->pipe);
     660             :     }
     661             : 
     662             :   return (job);
     663             : }
     664             : 
     665             : /* Return the job spec found in LIST. */
     666             : int
     667         678 : get_job_spec (list)
     668             :      WORD_LIST *list;
     669             : {
     670         678 :   register char *word;
     671         678 :   int job, jflags;
     672             : 
     673         678 :   if (list == 0)
     674           0 :     return (js.j_current);
     675             : 
     676         678 :   word = list->word->word;
     677             : 
     678         678 :   if (*word == '\0')
     679             :     return (NO_JOB);
     680             : 
     681         678 :   if (*word == '%')
     682           0 :     word++;
     683             : 
     684         678 :   if (DIGIT (*word) && all_digits (word))
     685             :     {
     686          18 :       job = atoi (word);
     687          18 :       return (job > js.j_jobslots ? NO_JOB : job - 1);
     688             :     }
     689             : 
     690         660 :   jflags = 0;
     691         660 :   switch (*word)
     692             :     {
     693           0 :     case 0:
     694             :     case '%':
     695             :     case '+':
     696           0 :       return (js.j_current);
     697             : 
     698           0 :     case '-':
     699           0 :       return (js.j_previous);
     700             : 
     701           0 :     case '?':                   /* Substring search requested. */
     702           0 :       jflags |= JM_SUBSTRING;
     703           0 :       word++;
     704             :       /* FALLTHROUGH */
     705             : 
     706         660 :     default:
     707         660 :       return get_job_by_name (word, jflags);
     708             :     }
     709             : }
     710             : #endif /* JOB_CONTROL */
     711             : 
     712             : /*
     713             :  * NOTE:  `kill' calls this function with forcecols == 0
     714             :  */
     715             : int
     716           0 : display_signal_list (list, forcecols)
     717             :      WORD_LIST *list;
     718             :      int forcecols;
     719             : {
     720           0 :   register int i, column;
     721           0 :   char *name;
     722           0 :   int result, signum, dflags;
     723           0 :   intmax_t lsignum;
     724             : 
     725           0 :   result = EXECUTION_SUCCESS;
     726           0 :   if (!list)
     727             :     {
     728           0 :       for (i = 1, column = 0; i < NSIG; i++)
     729             :         {
     730           0 :           name = signal_name (i);
     731           0 :           if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
     732             :             continue;
     733             : 
     734           0 :           if (posixly_correct && !forcecols)
     735             :             {
     736             :               /* This is for the kill builtin.  POSIX.2 says the signal names
     737             :                  are displayed without the `SIG' prefix. */
     738           0 :               if (STREQN (name, "SIG", 3))
     739           0 :                 name += 3;
     740           0 :               printf ("%s%s", name, (i == NSIG - 1) ? "" : " ");
     741             :             }
     742             :           else
     743             :             {
     744           0 :               printf ("%2d) %s", i, name);
     745             : 
     746           0 :               if (++column < 5)
     747           0 :                 printf ("\t");
     748             :               else
     749             :                 {
     750           0 :                   printf ("\n");
     751           0 :                   column = 0;
     752             :                 }
     753             :             }
     754             :         }
     755             : 
     756           0 :       if ((posixly_correct && !forcecols) || column != 0)
     757           0 :         printf ("\n");
     758           0 :       return result;
     759             :     }
     760             : 
     761             :   /* List individual signal names or numbers. */
     762           0 :   while (list)
     763             :     {
     764           0 :       if (legal_number (list->word->word, &lsignum))
     765             :         {
     766             :           /* This is specified by Posix.2 so that exit statuses can be
     767             :              mapped into signal numbers. */
     768           0 :           if (lsignum > 128)
     769           0 :             lsignum -= 128;
     770           0 :           if (lsignum < 0 || lsignum >= NSIG)
     771             :             {
     772           0 :               sh_invalidsig (list->word->word);
     773           0 :               result = EXECUTION_FAILURE;
     774           0 :               list = list->next;
     775           0 :               continue;
     776             :             }
     777             : 
     778           0 :           signum = lsignum;
     779           0 :           name = signal_name (signum);
     780           0 :           if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
     781             :             {
     782           0 :               list = list->next;
     783           0 :               continue;
     784             :             }
     785             : #if defined (JOB_CONTROL)
     786             :           /* POSIX.2 says that `kill -l signum' prints the signal name without
     787             :              the `SIG' prefix. */
     788           0 :           printf ("%s\n", (this_shell_builtin == kill_builtin) ? name + 3 : name);
     789             : #else
     790             :           printf ("%s\n", name);
     791             : #endif
     792             :         }
     793             :       else
     794             :         {
     795           0 :           dflags = DSIG_NOCASE;
     796           0 :           if (posixly_correct == 0 || this_shell_builtin != kill_builtin)
     797           0 :             dflags |= DSIG_SIGPREFIX;
     798           0 :           signum = decode_signal (list->word->word, dflags);
     799           0 :           if (signum == NO_SIG)
     800             :             {
     801           0 :               sh_invalidsig (list->word->word);
     802           0 :               result = EXECUTION_FAILURE;
     803           0 :               list = list->next;
     804           0 :               continue;
     805             :             }
     806           0 :           printf ("%d\n", signum);
     807             :         }
     808           0 :       list = list->next;
     809             :     }
     810             :   return (result);
     811             : }
     812             : 
     813             : /* **************************************************************** */
     814             : /*                                                                  */
     815             : /*          Finding builtin commands and their functions            */
     816             : /*                                                                  */
     817             : /* **************************************************************** */
     818             : 
     819             : /* Perform a binary search and return the address of the builtin function
     820             :    whose name is NAME.  If the function couldn't be found, or the builtin
     821             :    is disabled or has no function associated with it, return NULL.
     822             :    Return the address of the builtin.
     823             :    DISABLED_OKAY means find it even if the builtin is disabled. */
     824             : struct builtin *
     825   408730381 : builtin_address_internal (name, disabled_okay)
     826             :      const char *name;
     827             :      int disabled_okay;
     828             : {
     829   408730381 :   int hi, lo, mid, j;
     830             : 
     831   408730381 :   hi = num_shell_builtins - 1;
     832   408730381 :   lo = 0;
     833             : 
     834  2654551723 :   while (lo <= hi)
     835             :     {
     836  2434577175 :       mid = (lo + hi) / 2;
     837             : 
     838  2434577175 :       j = shell_builtins[mid].name[0] - name[0];
     839             : 
     840  2434577175 :       if (j == 0)
     841   718262788 :         j = strcmp (shell_builtins[mid].name, name);
     842             : 
     843  2434577175 :       if (j == 0)
     844             :         {
     845             :           /* It must have a function pointer.  It must be enabled, or we
     846             :              must have explicitly allowed disabled functions to be found,
     847             :              and it must not have been deleted. */
     848   188755833 :           if (shell_builtins[mid].function &&
     849   188749758 :               ((shell_builtins[mid].flags & BUILTIN_DELETED) == 0) &&
     850   188749758 :               ((shell_builtins[mid].flags & BUILTIN_ENABLED) || disabled_okay))
     851             :             return (&shell_builtins[mid]);
     852             :           else
     853        6075 :             return ((struct builtin *)NULL);
     854             :         }
     855  2245821342 :       if (j > 0)
     856  1429077945 :         hi = mid - 1;
     857             :       else
     858   816743397 :         lo = mid + 1;
     859             :     }
     860             :   return ((struct builtin *)NULL);
     861             : }
     862             : 
     863             : /* Return the pointer to the function implementing builtin command NAME. */
     864             : sh_builtin_func_t *
     865    56778785 : find_shell_builtin (name)
     866             :      char *name;
     867             : {
     868    56778785 :   current_builtin = builtin_address_internal (name, 0);
     869    56778785 :   return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL);
     870             : }
     871             : 
     872             : /* Return the address of builtin with NAME, whether it is enabled or not. */
     873             : sh_builtin_func_t *
     874         534 : builtin_address (name)
     875             :      char *name;
     876             : {
     877         534 :   current_builtin = builtin_address_internal (name, 1);
     878         534 :   return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL);
     879             : }
     880             : 
     881             : /* Return the function implementing the builtin NAME, but only if it is a
     882             :    POSIX.2 special builtin. */
     883             : sh_builtin_func_t *
     884           0 : find_special_builtin (name)
     885             :      char *name;
     886             : {
     887           0 :   current_builtin = builtin_address_internal (name, 0);
     888           0 :   return ((current_builtin && (current_builtin->flags & SPECIAL_BUILTIN)) ?
     889           0 :                         current_builtin->function :
     890             :                         (sh_builtin_func_t *)NULL);
     891             : }
     892             :   
     893             : static int
     894  3337296661 : shell_builtin_compare (sbp1, sbp2)
     895             :      struct builtin *sbp1, *sbp2;
     896             : {
     897  3337296661 :   int result;
     898             : 
     899  3337296661 :   if ((result = sbp1->name[0] - sbp2->name[0]) == 0)
     900   859468427 :     result = strcmp (sbp1->name, sbp2->name);
     901             : 
     902  3337296661 :   return (result);
     903             : }
     904             : 
     905             : /* Sort the table of shell builtins so that the binary search will work
     906             :    in find_shell_builtin. */
     907             : void
     908     9143282 : initialize_shell_builtins ()
     909             : {
     910     9143282 :   qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin),
     911             :     (QSFUNC *)shell_builtin_compare);
     912     9143282 : }
     913             : 
     914             : #if !defined (HELP_BUILTIN)
     915             : void
     916             : builtin_help ()
     917             : {
     918             :   printf ("%s: %s\n", this_command_name, _("help not available in this version"));
     919             : }
     920             : #endif

Generated by: LCOV version 1.14.0.6.4058