1/* addstr.c
2   Add a string to a list of strings.
3
4   Copyright (C) 1992 Ian Lance Taylor
5
6   This file is part of the Taylor UUCP uuconf library.
7
8   This library is free software; you can redistribute it and/or
9   modify it under the terms of the GNU Library General Public License
10   as published by the Free Software Foundation; either version 2 of
11   the License, or (at your option) any later version.
12
13   This library is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   Library General Public License for more details.
17
18   You should have received a copy of the GNU Library General Public
19   License along with this library; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
21
22   The author of the program may be contacted at ian@airs.com.
23   */
24
25#include "uucnfi.h"
26
27#if USE_RCS_ID
28const char _uuconf_addstr_rcsid[] = "$Id: addstr.c,v 1.8 2002/03/05 19:10:42 ian Rel $";
29#endif
30
31#include <errno.h>
32
33/* When setting system information, we need to be able to distinguish
34   between a value that is not set and a value that has been set to
35   NULL.  We do this by initializing the value to point to the
36   variable _uuconf_unset, and then correcting it in the function
37   _uuconf_isystem_basic_default.  This variable is declared in this
38   file because some linkers will apparently not pull in an object
39   file which merely declarates a variable.  This functions happens to
40   be pulled in by almost everything.  */
41
42char *_uuconf_unset;
43
44/* Add a string to a list of strings.  The list is maintained as an
45   array of elements ending in NULL.  The total number of available
46   slots is always a multiple of CSLOTS, so by counting the current
47   number of elements we can tell whether a new slot is needed.  If
48   the fcopy argument is TRUE, the new string is duplicated into
49   memory.  If the fcheck argument is TRUE, this does not add a string
50   that is already in the list.  The pblock argument may be used to do
51   the allocations within a memory block.  This returns a standard
52   uuconf error code.  */
53
54#define CSLOTS (8)
55
56int
57_uuconf_iadd_string (qglobal, zadd, fcopy, fcheck, ppzstrings, pblock)
58     struct sglobal *qglobal;
59     char *zadd;
60     boolean fcopy;
61     boolean fcheck;
62     char ***ppzstrings;
63     pointer pblock;
64{
65  char **pz;
66  size_t c;
67
68  if (fcheck && *ppzstrings != NULL)
69    {
70      for (pz = *ppzstrings; *pz != NULL; pz++)
71	if (strcmp (zadd, *pz) == 0)
72	  return UUCONF_SUCCESS;
73    }
74
75  if (fcopy)
76    {
77      size_t clen;
78      char *znew;
79
80      clen = strlen (zadd) + 1;
81      znew = (char *) uuconf_malloc (pblock, clen);
82      if (znew == NULL)
83	{
84	  if (qglobal != NULL)
85	    qglobal->ierrno = errno;
86	  return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
87	}
88      memcpy ((pointer) znew, (pointer) zadd, clen);
89      zadd = znew;
90    }
91
92  pz = *ppzstrings;
93  if (pz == NULL || pz == (char **) &_uuconf_unset)
94    {
95      pz = (char **) uuconf_malloc (pblock, CSLOTS * sizeof (char *));
96      if (pz == NULL)
97	{
98	  if (qglobal != NULL)
99	    qglobal->ierrno = errno;
100	  return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
101	}
102      *ppzstrings = pz;
103    }
104  else
105    {
106      c = 0;
107      while (*pz != NULL)
108	{
109	  ++pz;
110	  ++c;
111	}
112
113      if ((c + 1) % CSLOTS == 0)
114	{
115	  char **pznew;
116
117	  pznew = (char **) uuconf_malloc (pblock,
118					   ((c + 1 + CSLOTS)
119					    * sizeof (char *)));
120	  if (pznew == NULL)
121	    {
122	      if (qglobal != NULL)
123		qglobal->ierrno = errno;
124	      return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
125	    }
126	  memcpy ((pointer) pznew, (pointer) *ppzstrings,
127		  c * sizeof (char *));
128	  uuconf_free (pblock, *ppzstrings);
129	  *ppzstrings = pznew;
130	  pz = pznew + c;
131	}
132    }
133
134  pz[0] = zadd;
135  pz[1] = NULL;
136
137  return UUCONF_SUCCESS;
138}
139