]> granicus.if.org Git - shadow/blob - libmisc/list.c
* NEWS, libmisc/find_new_gid.c, libmisc/find_new_uid.c: Do not use
[shadow] / libmisc / list.c
1 /*
2  * Copyright (c) 1991 - 1994, Julianne Frances Haugh
3  * Copyright (c) 1996 - 1997, Marek Michałkiewicz
4  * Copyright (c) 2003 - 2005, Tomasz Kłoczko
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the copyright holders or contributors may not be used to
16  *    endorse or promote products derived from this software without
17  *    specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
23  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include <config.h>
33
34 #ident "$Id$"
35
36 #include <assert.h>
37 #include "prototypes.h"
38 #include "defines.h"
39 /*
40  * add_list - add a member to a list of group members
41  *
42  *      the array of member names is searched for the new member
43  *      name, and if not present it is added to a freshly allocated
44  *      list of users.
45  */
46 /*@only@*/ /*@out@*/char **add_list (/*@returned@*/ /*@only@*/char **list, const char *member)
47 {
48         int i;
49         char **tmp;
50
51         assert (NULL != member);
52         assert (NULL != list);
53
54         /*
55          * Scan the list for the new name.  Return the original list
56          * pointer if it is present.
57          */
58
59         for (i = 0; list[i] != (char *) 0; i++) {
60                 if (strcmp (list[i], member) == 0) {
61                         return list;
62                 }
63         }
64
65         /*
66          * Allocate a new list pointer large enough to hold all the
67          * old entries, and the new entries as well.
68          */
69
70         tmp = (char **) xmalloc ((i + 2) * sizeof member);
71
72         /*
73          * Copy the original list to the new list, then append the
74          * new member and NULL terminate the result.  This new list
75          * is returned to the invoker.
76          */
77
78         for (i = 0; list[i] != (char *) 0; i++) {
79                 tmp[i] = list[i];
80         }
81
82         tmp[i] = xstrdup (member);
83         tmp[i+1] = (char *) 0;
84
85         return tmp;
86 }
87
88 /*
89  * del_list - delete a member from a list of group members
90  *
91  *      the array of member names is searched for the old member
92  *      name, and if present it is deleted from a freshly allocated
93  *      list of users.
94  */
95
96 /*@only@*/ /*@out@*/char **del_list (/*@returned@*/ /*@only@*/char **list, const char *member)
97 {
98         int i, j;
99         char **tmp;
100
101         assert (NULL != member);
102         assert (NULL != list);
103
104         /*
105          * Scan the list for the old name.  Return the original list
106          * pointer if it is not present.
107          */
108
109         for (i = j = 0; list[i] != (char *) 0; i++) {
110                 if (strcmp (list[i], member) != 0) {
111                         j++;
112                 }
113         }
114
115         if (j == i) {
116                 return list;
117         }
118
119         /*
120          * Allocate a new list pointer large enough to hold all the
121          * old entries.
122          */
123
124         tmp = (char **) xmalloc ((j + 1) * sizeof member);
125
126         /*
127          * Copy the original list except the deleted members to the
128          * new list, then NULL terminate the result.  This new list
129          * is returned to the invoker.
130          */
131
132         for (i = j = 0; list[i] != (char *) 0; i++) {
133                 if (strcmp (list[i], member) != 0) {
134                         tmp[j] = list[i];
135                         j++;
136                 }
137         }
138
139         tmp[j] = (char *) 0;
140
141         return tmp;
142 }
143
144 /*@only@*/ /*@out@*/char **dup_list (char *const *list)
145 {
146         int i;
147         char **tmp;
148
149         assert (NULL != list);
150
151         for (i = 0; NULL != list[i]; i++);
152
153         tmp = (char **) xmalloc ((i + 1) * sizeof (char *));
154
155         i = 0;
156         while (NULL != *list) {
157                 tmp[i] = xstrdup (*list);
158                 i++;
159                 list++;
160         }
161
162         tmp[i] = (char *) 0;
163         return tmp;
164 }
165
166 bool is_on_list (char *const *list, const char *member)
167 {
168         assert (NULL != member);
169         assert (NULL != list);
170
171         while (NULL != *list) {
172                 if (strcmp (*list, member) == 0) {
173                         return true;
174                 }
175                 list++;
176         }
177
178         return false;
179 }
180
181 /*
182  * comma_to_list - convert comma-separated list to (char *) array
183  */
184
185 /*@only@*/char **comma_to_list (const char *comma)
186 {
187         char *members;
188         char **array;
189         int i;
190         const char *cp;
191         char *cp2;
192
193         assert (NULL != comma);
194
195         /*
196          * Make a copy since we are going to be modifying the list
197          */
198
199         members = xstrdup (comma);
200
201         /*
202          * Count the number of commas in the list
203          */
204
205         for (cp = members, i = 0;; i++) {
206                 cp2 = strchr (cp, ',');
207                 if (NULL != cp2) {
208                         cp = cp2 + 1;
209                 } else {
210                         break;
211                 }
212         }
213
214         /*
215          * Add 2 - one for the ending NULL, the other for the last item
216          */
217
218         i += 2;
219
220         /*
221          * Allocate the array we're going to store the pointers into.
222          */
223
224         array = (char **) xmalloc (sizeof (char *) * i);
225
226         /*
227          * Empty list is special - 0 members, not 1 empty member.  --marekm
228          */
229
230         if ('\0' == *members) {
231                 *array = (char *) 0;
232                 return array;
233         }
234
235         /*
236          * Now go walk that list all over again, this time building the
237          * array of pointers.
238          */
239
240         for (cp = members, i = 0;; i++) {
241                 array[i] = cp;
242                 cp2 = strchr (cp, ',');
243                 if (NULL != cp2) {
244                         *cp2 = '\0';
245                         cp2++;
246                         cp = cp2;
247                 } else {
248                         array[i + 1] = (char *) 0;
249                         break;
250                 }
251         }
252
253         /*
254          * Return the new array of pointers
255          */
256
257         return array;
258 }
259