Blame string/envz.c

Packit Service 82fcde
/* Routines for dealing with '\0' separated environment vectors
Packit Service 82fcde
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Written by Miles Bader <miles@gnu.org>
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <malloc.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
Packit Service 82fcde
#include <envz.h>
Packit Service 82fcde
Packit Service 82fcde
/* The character separating names from values in an envz.  */
Packit Service 82fcde
#define SEP '='
Packit Service 82fcde

Packit Service 82fcde
/* Returns a pointer to the entry in ENVZ for NAME, or 0 if there is none.
Packit Service 82fcde
   If NAME contains the separator character, only the portion before it is
Packit Service 82fcde
   used in the comparison.  */
Packit Service 82fcde
char *
Packit Service 82fcde
envz_entry (const char *envz, size_t envz_len, const char *name)
Packit Service 82fcde
{
Packit Service 82fcde
  while (envz_len)
Packit Service 82fcde
    {
Packit Service 82fcde
      const char *p = name;
Packit Service 82fcde
      const char *entry = envz;	/* Start of this entry. */
Packit Service 82fcde
Packit Service 82fcde
      /* See how far NAME and ENTRY match.  */
Packit Service 82fcde
      while (envz_len && *p == *envz && *p && *p != SEP)
Packit Service 82fcde
	p++, envz++, envz_len--;
Packit Service 82fcde
Packit Service 82fcde
      if ((*envz == '\0' || *envz == SEP) && (*p == '\0' || *p == SEP))
Packit Service 82fcde
	/* Bingo! */
Packit Service 82fcde
	return (char *) entry;
Packit Service 82fcde
Packit Service 82fcde
      /* No match, skip to the next entry.  */
Packit Service 82fcde
      while (envz_len && *envz)
Packit Service 82fcde
	envz++, envz_len--;
Packit Service 82fcde
      if (envz_len)
Packit Service 82fcde
	envz++, envz_len--;	/* skip '\0' */
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (envz_entry)
Packit Service 82fcde
Packit Service 82fcde
/* Returns a pointer to the value portion of the entry in ENVZ for NAME, or 0
Packit Service 82fcde
   if there is none.  */
Packit Service 82fcde
char *
Packit Service 82fcde
envz_get (const char *envz, size_t envz_len, const char *name)
Packit Service 82fcde
{
Packit Service 82fcde
  char *entry = envz_entry (envz, envz_len, name);
Packit Service 82fcde
  if (entry)
Packit Service 82fcde
    {
Packit Service 82fcde
      while (*entry && *entry != SEP)
Packit Service 82fcde
	entry++;
Packit Service 82fcde
      if (*entry)
Packit Service 82fcde
	entry++;
Packit Service 82fcde
      else
Packit Service 82fcde
	entry = 0;		/* A null entry.  */
Packit Service 82fcde
    }
Packit Service 82fcde
  return entry;
Packit Service 82fcde
}
Packit Service 82fcde

Packit Service 82fcde
/* Remove the entry for NAME from ENVZ & ENVZ_LEN, if any.  */
Packit Service 82fcde
void
Packit Service 82fcde
envz_remove (char **envz, size_t *envz_len, const char *name)
Packit Service 82fcde
{
Packit Service 82fcde
  char *entry = envz_entry (*envz, *envz_len, name);
Packit Service 82fcde
  if (entry)
Packit Service 82fcde
    argz_delete (envz, envz_len, entry);
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (envz_remove)
Packit Service 82fcde
Packit Service 82fcde
/* Adds an entry for NAME with value VALUE to ENVZ & ENVZ_LEN.  If an entry
Packit Service 82fcde
   with the same name already exists in ENVZ, it is removed.  If VALUE is
Packit Service 82fcde
   NULL, then the new entry will a special null one, for which envz_get will
Packit Service 82fcde
   return NULL, although envz_entry will still return an entry; this is handy
Packit Service 82fcde
   because when merging with another envz, the null entry can override an
Packit Service 82fcde
   entry in the other one.  Null entries can be removed with envz_strip ().  */
Packit Service 82fcde
error_t
Packit Service 82fcde
envz_add (char **envz, size_t *envz_len, const char *name, const char *value)
Packit Service 82fcde
{
Packit Service 82fcde
  envz_remove (envz, envz_len, name);
Packit Service 82fcde
Packit Service 82fcde
  if (value)
Packit Service 82fcde
    /* Add the new value, if there is one.  */
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t name_len = strlen (name);
Packit Service 82fcde
      size_t value_len = strlen (value);
Packit Service 82fcde
      size_t old_envz_len = *envz_len;
Packit Service 82fcde
      size_t new_envz_len = old_envz_len + name_len + 1 + value_len + 1;
Packit Service 82fcde
      char *new_envz = realloc (*envz, new_envz_len);
Packit Service 82fcde
Packit Service 82fcde
      if (new_envz)
Packit Service 82fcde
	{
Packit Service 82fcde
	  memcpy (new_envz + old_envz_len, name, name_len);
Packit Service 82fcde
	  new_envz[old_envz_len + name_len] = SEP;
Packit Service 82fcde
	  memcpy (new_envz + old_envz_len + name_len + 1, value, value_len);
Packit Service 82fcde
	  new_envz[new_envz_len - 1] = 0;
Packit Service 82fcde
Packit Service 82fcde
	  *envz = new_envz;
Packit Service 82fcde
	  *envz_len = new_envz_len;
Packit Service 82fcde
Packit Service 82fcde
	  return 0;
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	return ENOMEM;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    /* Add a null entry.  */
Packit Service 82fcde
    return __argz_add (envz, envz_len, name);
Packit Service 82fcde
}
Packit Service 82fcde

Packit Service 82fcde
/* Adds each entry in ENVZ2 to ENVZ & ENVZ_LEN, as if with envz_add().  If
Packit Service 82fcde
   OVERRIDE is true, then values in ENVZ2 will supersede those with the same
Packit Service 82fcde
   name in ENV, otherwise not.  */
Packit Service 82fcde
error_t
Packit Service 82fcde
envz_merge (char **envz, size_t *envz_len, const char *envz2,
Packit Service 82fcde
	    size_t envz2_len, int override)
Packit Service 82fcde
{
Packit Service 82fcde
  error_t err = 0;
Packit Service 82fcde
Packit Service 82fcde
  while (envz2_len && ! err)
Packit Service 82fcde
    {
Packit Service 82fcde
      char *old = envz_entry (*envz, *envz_len, envz2);
Packit Service 82fcde
      size_t new_len = strlen (envz2) + 1;
Packit Service 82fcde
Packit Service 82fcde
      if (! old)
Packit Service 82fcde
	err = __argz_append (envz, envz_len, envz2, new_len);
Packit Service 82fcde
      else if (override)
Packit Service 82fcde
	{
Packit Service 82fcde
	  argz_delete (envz, envz_len, old);
Packit Service 82fcde
	  err = __argz_append (envz, envz_len, envz2, new_len);
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      envz2 += new_len;
Packit Service 82fcde
      envz2_len -= new_len;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return err;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Remove null entries.  */
Packit Service 82fcde
void
Packit Service 82fcde
envz_strip (char **envz, size_t *envz_len)
Packit Service 82fcde
{
Packit Service 82fcde
  char *entry = *envz;
Packit Service 82fcde
  size_t left = *envz_len;
Packit Service 82fcde
  while (left)
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t entry_len = strlen (entry) + 1;
Packit Service 82fcde
      left -= entry_len;
Packit Service 82fcde
      if (! strchr (entry, SEP))
Packit Service 82fcde
	/* Null entry. */
Packit Service 82fcde
	memmove (entry, entry + entry_len, left);
Packit Service 82fcde
      else
Packit Service 82fcde
	entry += entry_len;
Packit Service 82fcde
    }
Packit Service 82fcde
  *envz_len = entry - *envz;
Packit Service 82fcde
}