This file is alias.def, from which is created alias.c
It implements the builtins "alias" and "unalias" in Bash.

Copyright (C) 1987-2023 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/>.

$BUILTIN alias
$FUNCTION alias_builtin
$DEPENDS_ON ALIAS
$PRODUCES alias.c
$SHORT_DOC alias [-p] [name[=value] ... ]
Define or display aliases.

Without arguments, `alias' prints the list of aliases in the reusable
form `alias NAME=VALUE' on standard output.

Otherwise, an alias is defined for each NAME whose VALUE is given.
A trailing space in VALUE causes the next word to be checked for
alias substitution when the alias is expanded.

Options:
  -p	print all defined aliases in a reusable format

Exit Status:
alias returns true unless a NAME is supplied for which no alias has been
defined.
$END

#include <config.h>

#if defined (ALIAS)

#if defined (HAVE_UNISTD_H)
#  ifdef _MINIX
#    include <sys/types.h>
#  endif
#  include <unistd.h>
#endif

#  include "../bashansi.h"
#  include "../bashintl.h"

#  include <stdio.h>
#  include "../shell.h"
#  include "../alias.h"
#  include "common.h"
#  include "bashgetopt.h"

/* Flags for print_alias */
#define AL_REUSABLE	0x01

static int print_alias (alias_t *, int);

/* Hack the alias command in a Korn shell way. */
int
alias_builtin (WORD_LIST *list)
{
  int any_failed, offset, pflag, dflags;
  alias_t **alias_list, *t;
  char *name, *value;

  dflags = posixly_correct ? 0 : AL_REUSABLE;
  pflag = 0;
  reset_internal_getopt ();
  while ((offset = internal_getopt (list, "p")) != -1)
    {
      switch (offset)
	{
	case 'p':
	  pflag = 1;
	  dflags |= AL_REUSABLE;
	  break;
	CASE_HELPOPT;
	default:
	  builtin_usage ();
	  return (EX_USAGE);
	}
    }

  list = loptend;

  if (list == 0 || pflag)
    {
      if (aliases == 0)
	return (EXECUTION_SUCCESS);

      alias_list = all_aliases ();

      if (alias_list == 0)
	return (EXECUTION_SUCCESS);

      any_failed = EXECUTION_SUCCESS;
      for (offset = 0; alias_list[offset]; offset++)
	if (any_failed = print_alias (alias_list[offset], dflags) != EXECUTION_SUCCESS)
	  break;

      free (alias_list);	/* XXX - Do not free the strings. */

      return (any_failed != EXECUTION_SUCCESS ? EXECUTION_FAILURE : sh_chkwrite (EXECUTION_SUCCESS));
    }

  any_failed = 0;
  while (list)
    {
      name = list->word->word;

      for (offset = 0; name[offset] && name[offset] != '='; offset++)
	;

      if (offset && name[offset] == '=')
	{
	  name[offset] = '\0';
	  value = name + offset + 1;

	  if (valid_alias_name (name, 0) == 0)
	    {
	      builtin_error (_("`%s': invalid alias name"), name);
	      any_failed++;
	    }
	  else
	    add_alias (name, value);
	}
      else
	{
	  t = find_alias (name);
	  if (t)
	    {
	      if (print_alias (t, dflags) != EXECUTION_SUCCESS)
		return (EXECUTION_FAILURE);
	    }
	  else
	    {
	      sh_notfound (name);
	      any_failed++;
	    }
	}
      list = list->next;
    }

  return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
#endif /* ALIAS */

$BUILTIN unalias
$FUNCTION unalias_builtin
$DEPENDS_ON ALIAS
$SHORT_DOC unalias [-a] name [name ...]
Remove each NAME from the list of defined aliases.

Options:
  -a	remove all alias definitions

Return success unless a NAME is not an existing alias.
$END

#if defined (ALIAS)
/* Remove aliases named in LIST from the aliases database. */
int
unalias_builtin (WORD_LIST *list)
{
  alias_t *alias;
  int opt, aflag;

  aflag = 0;
  reset_internal_getopt ();
  while ((opt = internal_getopt (list, "a")) != -1)
    {
      switch (opt)
	{
	case 'a':
	  aflag = 1;
	  break;
	CASE_HELPOPT;
	default:
	  builtin_usage ();
	  return (EX_USAGE);
	}
    }

  list = loptend;

  if (aflag)
    {
      delete_all_aliases ();
      return (EXECUTION_SUCCESS);
    }

  if (list == 0)
    {
      builtin_usage ();
      return (EX_USAGE);
    }

  aflag = 0;
  while (list)
    {
      if (remove_alias (list->word->word) < 0)
	{
	  sh_notfound (list->word->word);
	  aflag++;
	}

      list = list->next;
    }

  return (aflag ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}

/* Output ALIAS in such a way as to allow it to be read back in. */
static int
print_alias (alias_t *alias, int flags)
{
  char *value;

  value = sh_single_quote (alias->value);
  if (flags & AL_REUSABLE)
    printf ("alias %s", (alias->name && alias->name[0] == '-') ? "-- " : "");
  printf ("%s=%s\n", alias->name, value);
  free (value);

  return (sh_chkwrite (EXECUTION_SUCCESS));
}
#endif /* ALIAS */
