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
28 const char _uuconf_addstr_rcsid[] = "$FreeBSD$";
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 
42 char *_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 
56 int
_uuconf_iadd_string(qglobal,zadd,fcopy,fcheck,ppzstrings,pblock)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