From 1d5cace9db9aef76f26b2d7ba54bbb76443b00b2 Mon Sep 17 00:00:00 2001
From: Daniel Baumann <daniel.baumann@progress-linux.org>
Date: Sun, 5 May 2024 20:33:23 +0200
Subject: Adding upstream version 5.0.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
---
 builtins/enable.def | 547 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 547 insertions(+)
 create mode 100644 builtins/enable.def

(limited to 'builtins/enable.def')

diff --git a/builtins/enable.def b/builtins/enable.def
new file mode 100644
index 0000000..39c3669
--- /dev/null
+++ b/builtins/enable.def
@@ -0,0 +1,547 @@
+This file is enable.def, from which is created enable.c.
+It implements the builtin "enable" in Bash.
+
+Copyright (C) 1987-2016 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Bash is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+
+$PRODUCES enable.c
+
+$BUILTIN enable
+$FUNCTION enable_builtin
+$SHORT_DOC enable [-a] [-dnps] [-f filename] [name ...]
+Enable and disable shell builtins.
+
+Enables and disables builtin shell commands.  Disabling allows you to
+execute a disk command which has the same name as a shell builtin
+without using a full pathname.
+
+Options:
+  -a	print a list of builtins showing whether or not each is enabled
+  -n	disable each NAME or display a list of disabled builtins
+  -p	print the list of builtins in a reusable format
+  -s	print only the names of Posix `special' builtins
+
+Options controlling dynamic loading:
+  -f	Load builtin NAME from shared object FILENAME
+  -d	Remove a builtin loaded with -f
+
+Without options, each NAME is enabled.
+
+To use the `test' found in $PATH instead of the shell builtin
+version, type `enable -n test'.
+
+Exit Status:
+Returns success unless NAME is not a shell builtin or an error occurs.
+$END
+
+#include <config.h>
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include "../bashansi.h"
+#include "../bashintl.h"
+
+#include "../shell.h"
+#include "../builtins.h"
+#include "../flags.h"
+#include "common.h"
+#include "bashgetopt.h"
+#include "findcmd.h"
+
+#if defined (PROGRAMMABLE_COMPLETION)
+#  include "../pcomplete.h"
+#endif
+
+#define ENABLED  1
+#define DISABLED 2
+#define SPECIAL  4
+
+#define AFLAG	0x01
+#define DFLAG	0x02
+#define FFLAG	0x04
+#define NFLAG	0x08
+#define PFLAG	0x10
+#define SFLAG	0x20
+
+#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
+static int dyn_load_builtin __P((WORD_LIST *, int, char *));
+#endif
+
+#if defined (HAVE_DLCLOSE)
+static int dyn_unload_builtin __P((char *));
+static void delete_builtin __P((struct builtin *));
+static int local_dlclose __P((void *));
+#endif
+
+#define STRUCT_SUFFIX	"_struct"
+/* for now */
+#define LOAD_SUFFIX	"_builtin_load"
+#define UNLOAD_SUFFIX	"_builtin_unload"
+
+static void list_some_builtins __P((int));
+static int enable_shell_command __P((char *, int));
+
+/* Enable/disable shell commands present in LIST.  If list is not specified,
+   then print out a list of shell commands showing which are enabled and
+   which are disabled. */
+int
+enable_builtin (list)
+     WORD_LIST *list;
+{
+  int result, flags;
+  int opt, filter;
+#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
+  char *filename;
+#endif
+
+  result = EXECUTION_SUCCESS;
+  flags = 0;
+
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "adnpsf:")) != -1)
+    {
+      switch (opt)
+	{
+	case 'a':
+	  flags |= AFLAG;
+	  break;
+	case 'n':
+	  flags |= NFLAG;
+	  break;
+	case 'p':
+	  flags |= PFLAG;
+	  break;
+	case 's':
+	  flags |= SFLAG;
+	  break;
+	case 'f':
+#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
+	  flags |= FFLAG;
+	  filename = list_optarg;
+	  break;
+#else
+	  builtin_error (_("dynamic loading not available"));
+	  return (EX_USAGE);
+#endif
+#if defined (HAVE_DLCLOSE)
+	case 'd':
+	  flags |= DFLAG;
+	  break;
+#else
+	  builtin_error (_("dynamic loading not available"));
+	  return (EX_USAGE);
+#endif /* HAVE_DLCLOSE */
+	CASE_HELPOPT;
+	default:
+	  builtin_usage ();
+	  return (EX_USAGE);
+	}
+    }
+
+  list = loptend;
+
+#if defined (RESTRICTED_SHELL)
+  /* Restricted shells cannot load new builtins. */
+  if (restricted && (flags & (FFLAG|DFLAG)))
+    {
+      sh_restricted ((char *)NULL);
+      return (EXECUTION_FAILURE);
+    }
+#endif
+
+  if (list == 0 || (flags & PFLAG))
+    {
+      filter = (flags & AFLAG) ? (ENABLED | DISABLED)
+			       : (flags & NFLAG) ? DISABLED : ENABLED;
+
+      if (flags & SFLAG)
+	filter |= SPECIAL;
+
+      list_some_builtins (filter);
+    }
+#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
+  else if (flags & FFLAG)
+    {
+      filter = (flags & NFLAG) ? DISABLED : ENABLED;
+      if (flags & SFLAG)
+	filter |= SPECIAL;
+
+      result = dyn_load_builtin (list, filter, filename);
+#if defined (PROGRAMMABLE_COMPLETION)
+      set_itemlist_dirty (&it_builtins);
+#endif
+    }
+#endif
+#if defined (HAVE_DLCLOSE)
+  else if (flags & DFLAG)
+    {
+      while (list)
+	{
+	  opt = dyn_unload_builtin (list->word->word);
+	  if (opt == EXECUTION_FAILURE)
+	    result = EXECUTION_FAILURE;
+	  list = list->next;
+	}
+#if defined (PROGRAMMABLE_COMPLETION)
+      set_itemlist_dirty (&it_builtins);
+#endif
+    }
+#endif
+  else
+    {
+      while (list)
+	{
+	  opt = enable_shell_command (list->word->word, flags & NFLAG);
+
+	  if (opt == EXECUTION_FAILURE)
+	    {
+	      sh_notbuiltin (list->word->word);
+	      result = EXECUTION_FAILURE;
+	    }
+	  list = list->next;
+	}
+    }
+  return (result);
+}
+
+/* List some builtins.
+   FILTER is a mask with two slots: ENABLED and DISABLED. */
+static void
+list_some_builtins (filter)
+     int filter;
+{
+  register int i;
+
+  for (i = 0; i < num_shell_builtins; i++)
+    {
+      if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
+	continue;
+
+      if ((filter & SPECIAL) &&
+	  (shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
+	continue;
+
+      if ((filter & ENABLED) && (shell_builtins[i].flags & BUILTIN_ENABLED))
+	printf ("enable %s\n", shell_builtins[i].name);
+      else if ((filter & DISABLED) &&
+	       ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
+	printf ("enable -n %s\n", shell_builtins[i].name);
+    }
+}
+
+/* Enable the shell command NAME.  If DISABLE_P is non-zero, then
+   disable NAME instead. */
+static int
+enable_shell_command (name, disable_p)
+     char *name;
+     int disable_p;
+{
+  struct builtin *b;
+
+  b = builtin_address_internal (name, 1);
+  if (b == 0)
+    return (EXECUTION_FAILURE);
+
+  if (disable_p)
+    b->flags &= ~BUILTIN_ENABLED;
+#if defined (RESTRICTED_SHELL)
+  else if (restricted && ((b->flags & BUILTIN_ENABLED) == 0))
+    {
+      sh_restricted ((char *)NULL);
+      return (EXECUTION_FAILURE);
+    }
+#endif
+  else
+    b->flags |= BUILTIN_ENABLED;
+
+#if defined (PROGRAMMABLE_COMPLETION)
+  set_itemlist_dirty (&it_enabled);
+  set_itemlist_dirty (&it_disabled);
+#endif
+
+  return (EXECUTION_SUCCESS);
+}
+
+#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
+
+#if defined (HAVE_DLFCN_H)
+#  include <dlfcn.h>
+#endif
+
+static int
+dyn_load_builtin (list, flags, filename)
+     WORD_LIST *list;
+     int flags;
+     char *filename;
+{
+  WORD_LIST *l;
+  void *handle;
+  
+  int total, size, new, replaced, r;
+  char *struct_name, *name, *funcname;
+  sh_load_func_t *loadfunc;
+  struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
+  char *loadables_path, *load_path;
+
+  if (list == 0)
+    return (EXECUTION_FAILURE);
+
+#ifndef RTLD_LAZY
+#define RTLD_LAZY 1
+#endif
+
+  handle = 0;
+  if (absolute_program (filename) == 0)
+    {
+      loadables_path = get_string_value ("BASH_LOADABLES_PATH");
+      if (loadables_path)
+	{
+	  load_path = find_in_path (filename, loadables_path, FS_NODIRS|FS_EXEC_PREFERRED);
+	  if (load_path)
+	    {
+#if defined (_AIX)
+	      handle = dlopen (load_path, RTLD_NOW|RTLD_GLOBAL);
+#else
+	      handle = dlopen (load_path, RTLD_LAZY);
+#endif /* !_AIX */
+	      free (load_path);
+	    }
+	}
+    }
+
+  /* Fall back to current directory for now */
+  if (handle == 0)
+#if defined (_AIX)
+    handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
+#else
+    handle = dlopen (filename, RTLD_LAZY);
+#endif /* !_AIX */
+
+  if (handle == 0)
+    {
+      name = printable_filename (filename, 0);
+      builtin_error (_("cannot open shared object %s: %s"), name, dlerror ());
+      if (name != filename)
+	free (name);
+      return (EXECUTION_FAILURE);
+    }
+
+  for (new = 0, l = list; l; l = l->next, new++)
+    ;
+  new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
+
+  /* For each new builtin in the shared object, find it and its describing
+     structure.  If this is overwriting an existing builtin, do so, otherwise
+     save the loaded struct for creating the new list of builtins. */
+  for (replaced = new = 0; list; list = list->next)
+    {
+      name = list->word->word;
+
+      size = strlen (name);
+      struct_name = (char *)xmalloc (size + 8);
+      strcpy (struct_name, name);
+      strcpy (struct_name + size, STRUCT_SUFFIX);
+
+      b = (struct builtin *)dlsym (handle, struct_name);
+      if (b == 0)
+	{
+	  name = printable_filename (filename, 0);
+	  builtin_error (_("cannot find %s in shared object %s: %s"),
+			  struct_name, name, dlerror ());
+	  if (name != filename)
+	    free (name);
+	  free (struct_name);
+	  continue;
+	}
+
+      funcname = xrealloc (struct_name, size + sizeof (LOAD_SUFFIX) + 1);
+      strcpy (funcname, name);
+      strcpy (funcname + size, LOAD_SUFFIX);
+
+      loadfunc = (sh_load_func_t *)dlsym (handle, funcname);
+      if (loadfunc)
+	{
+	  r = (*loadfunc) (name);
+	  if (r == 0)
+	    {
+	      builtin_error (_("load function for %s returns failure (%d): not loaded"), name, r);
+	      free (funcname);
+	      continue;
+	    }
+	}
+      free (funcname);
+
+      b->flags &= ~STATIC_BUILTIN;
+      if (flags & SPECIAL)
+	b->flags |= SPECIAL_BUILTIN;
+      b->handle = handle;
+
+      if (old_builtin = builtin_address_internal (name, 1))
+	{
+	  replaced++;
+	  FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
+	}
+      else
+	  new_builtins[new++] = b;
+    }
+
+  if (replaced == 0 && new == 0)
+    {
+      free (new_builtins);
+      dlclose (handle);
+      return (EXECUTION_FAILURE);
+    }
+
+  if (new)
+    {
+      total = num_shell_builtins + new;
+      size = (total + 1) * sizeof (struct builtin);
+
+      new_shell_builtins = (struct builtin *)xmalloc (size);
+      FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
+		num_shell_builtins * sizeof (struct builtin));
+      for (replaced = 0; replaced < new; replaced++)
+	FASTCOPY ((char *)new_builtins[replaced],
+		  (char *)&new_shell_builtins[num_shell_builtins + replaced],
+		  sizeof (struct builtin));
+
+      new_shell_builtins[total].name = (char *)0;
+      new_shell_builtins[total].function = (sh_builtin_func_t *)0;
+      new_shell_builtins[total].flags = 0;
+
+      if (shell_builtins != static_shell_builtins)
+	free (shell_builtins);
+
+      shell_builtins = new_shell_builtins;
+      num_shell_builtins = total;
+      initialize_shell_builtins ();
+    }
+
+  free (new_builtins);
+  return (EXECUTION_SUCCESS);
+}
+#endif
+
+#if defined (HAVE_DLCLOSE)
+static void
+delete_builtin (b)
+     struct builtin *b;
+{
+  int ind, size;
+  struct builtin *new_shell_builtins;
+
+  /* XXX - funky pointer arithmetic - XXX */
+#ifdef __STDC__
+  ind = b - shell_builtins;
+#else
+  ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
+#endif
+  size = num_shell_builtins * sizeof (struct builtin);
+  new_shell_builtins = (struct builtin *)xmalloc (size);
+
+  /* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
+  if (ind)
+    FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
+	      ind * sizeof (struct builtin));
+  /* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
+     new_shell_builtins, starting at ind. */
+  FASTCOPY ((char *)(&shell_builtins[ind+1]),
+  	    (char *)(&new_shell_builtins[ind]),
+  	    (num_shell_builtins - ind) * sizeof (struct builtin));
+
+  if (shell_builtins != static_shell_builtins)
+    free (shell_builtins);
+
+  /* The result is still sorted. */
+  num_shell_builtins--;
+  shell_builtins = new_shell_builtins;
+}
+
+/* Tenon's MachTen has a dlclose that doesn't return a value, so we
+   finesse it with a local wrapper. */
+static int
+local_dlclose (handle)
+     void *handle;
+{
+#if !defined (__MACHTEN__)
+  return (dlclose (handle));
+#else /* __MACHTEN__ */
+  dlclose (handle);
+  return ((dlerror () != NULL) ? -1 : 0);    
+#endif /* __MACHTEN__ */
+}
+
+static int
+dyn_unload_builtin (name)
+     char *name;
+{
+  struct builtin *b;
+  void *handle;
+  char *funcname;
+  sh_unload_func_t *unloadfunc;
+  int ref, i, size;
+
+  b = builtin_address_internal (name, 1);
+  if (b == 0)
+    {
+      sh_notbuiltin (name);
+      return (EXECUTION_FAILURE);
+    }
+  if (b->flags & STATIC_BUILTIN)
+    {
+      builtin_error (_("%s: not dynamically loaded"), name);
+      return (EXECUTION_FAILURE);
+    }
+
+  handle = (void *)b->handle;
+  for (ref = i = 0; i < num_shell_builtins; i++)
+    {
+      if (shell_builtins[i].handle == b->handle)
+	ref++;
+    }
+
+  /* Call any unload function */
+  size = strlen (name);
+  funcname = xmalloc (size + sizeof (UNLOAD_SUFFIX) + 1);
+  strcpy (funcname, name);
+  strcpy (funcname + size, UNLOAD_SUFFIX);
+
+  unloadfunc = (sh_unload_func_t *)dlsym (handle, funcname);
+  if (unloadfunc)
+    (*unloadfunc) (name);	/* void function */
+  free (funcname);
+
+  /* Don't remove the shared object unless the reference count of builtins
+     using it drops to zero. */
+  if (ref == 1 && local_dlclose (handle) != 0)
+    {
+      builtin_error (_("%s: cannot delete: %s"), name, dlerror ());
+      return (EXECUTION_FAILURE);
+    }
+
+  /* Now remove this entry from the builtin table and reinitialize. */
+  delete_builtin (b);
+
+  return (EXECUTION_SUCCESS);
+}
+#endif
-- 
cgit v1.2.3

