1 /* Author: Mark Goldman <mgoldman@tresys.com>
2 * Paul Rosenfeld <prosenfeld@tresys.com>
3 *
4 * Copyright (C) 2007 Tresys Technology, LLC
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 #include "utilities.h"
21
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <ctype.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <assert.h>
29 #include <ustr.h>
30
31 #define TRUE 1
32 #define FALSE 0
33
semanage_findval(const char * file,const char * var,const char * delim)34 char *semanage_findval(const char *file, const char *var, const char *delim)
35 {
36 FILE *fd;
37 char *buff = NULL;
38 char *retval = NULL;
39 size_t buff_len = 0;
40
41 assert(file);
42 assert(var);
43
44 if ((fd = fopen(file, "r")) == NULL)
45 return NULL;
46
47 while (getline(&buff, &buff_len, fd) > 0) {
48 if (semanage_is_prefix(buff, var)) {
49 retval = semanage_split(buff, delim);
50 if (retval)
51 semanage_rtrim(retval, '\n');
52 break;
53 }
54 }
55 free(buff);
56 fclose(fd);
57
58 return retval;
59 }
60
semanage_is_prefix(const char * str,const char * prefix)61 int semanage_is_prefix(const char *str, const char *prefix)
62 {
63 if (!str) {
64 return FALSE;
65 }
66 if (!prefix) {
67 return TRUE;
68 }
69
70 return strncmp(str, prefix, strlen(prefix)) == 0;
71 }
72
semanage_split_on_space(const char * str)73 char *semanage_split_on_space(const char *str)
74 {
75 /* as per the man page, these are the isspace() chars */
76 const char *seps = "\f\n\r\t\v ";
77 size_t slen = strlen(seps);
78 size_t off = 0, rside_len = 0;
79 char *retval = NULL;
80 Ustr *ustr = USTR_NULL, *temp = USTR_NULL;
81
82 if (!str)
83 goto done;
84 if (!(ustr = ustr_dup_cstr(str)))
85 goto done;
86 temp =
87 ustr_split_spn_chrs(ustr, &off, seps, slen, USTR_NULL,
88 USTR_FLAG_SPLIT_DEF);
89 if (!temp)
90 goto done;
91 /* throw away the left hand side */
92 ustr_sc_free(&temp);
93
94 rside_len = ustr_len(ustr) - off;
95 temp = ustr_dup_subustr(ustr, off + 1, rside_len);
96 if (!temp)
97 goto done;
98 retval = strdup(ustr_cstr(temp));
99 ustr_sc_free(&temp);
100
101 done:
102 ustr_sc_free(&ustr);
103 return retval;
104 }
105
semanage_split(const char * str,const char * delim)106 char *semanage_split(const char *str, const char *delim)
107 {
108 Ustr *ustr = USTR_NULL, *temp = USTR_NULL;
109 size_t off = 0, rside_len = 0;
110 char *retval = NULL;
111
112 if (!str)
113 goto done;
114 if (!delim || !(*delim))
115 return semanage_split_on_space(str);
116 ustr = ustr_dup_cstr(str);
117 temp =
118 ustr_split_cstr(ustr, &off, delim, USTR_NULL, USTR_FLAG_SPLIT_DEF);
119 if (!temp)
120 goto done;
121 /* throw away the left hand side */
122 ustr_sc_free(&temp);
123
124 rside_len = ustr_len(ustr) - off;
125
126 temp = ustr_dup_subustr(ustr, off + 1, rside_len);
127 if (!temp)
128 goto done;
129 retval = strdup(ustr_cstr(temp));
130 ustr_sc_free(&temp);
131
132 done:
133 ustr_sc_free(&ustr);
134 return retval;
135 }
136
semanage_list_push(semanage_list_t ** list,const char * data)137 int semanage_list_push(semanage_list_t ** list, const char *data)
138 {
139 semanage_list_t *temp = NULL;
140
141 if (!data)
142 return EINVAL;
143
144 if (semanage_list_find(*list, data) != NULL)
145 return 0;
146
147 if (!(temp = malloc(sizeof(semanage_list_t))))
148 return ENOMEM;
149
150 if (!(temp->data = strdup(data))) {
151 free(temp);
152 return ENOMEM;
153 }
154 temp->next = *list;
155 *list = temp;
156
157 return 0;
158 }
159
semanage_list_pop(semanage_list_t ** list)160 char *semanage_list_pop(semanage_list_t ** list)
161 {
162 semanage_list_t *node = NULL;
163 char *data = NULL;
164
165 if (!list || !(*list))
166 return NULL;
167
168 node = (*list);
169 data = node->data;
170
171 (*list) = node->next;
172 free(node);
173
174 return data;
175 }
176
semanage_list_destroy(semanage_list_t ** list)177 void semanage_list_destroy(semanage_list_t ** list)
178 {
179 semanage_list_t *temp;
180
181 while ((temp = (*list))) {
182 free(temp->data);
183 (*list) = temp->next;
184 free(temp);
185 }
186 }
187
semanage_list_find(semanage_list_t * l,const char * data)188 semanage_list_t *semanage_list_find(semanage_list_t * l, const char *data)
189 {
190 if (!data)
191 return NULL;
192 while (l && strcmp(l->data, data))
193 l = l->next;
194
195 return l;
196 }
197
semanage_list_sort(semanage_list_t ** l)198 int semanage_list_sort(semanage_list_t ** l)
199 {
200 semanage_list_t **array = NULL;
201 semanage_list_t *temp = NULL;
202 size_t count = 0;
203 size_t i = 0;
204
205 if (!l)
206 return 0;
207
208 for (temp = *l; temp; temp = temp->next)
209 ++count;
210
211 array = malloc(sizeof(semanage_list_t *) * count);
212 if (!array)
213 return ENOMEM; /* couldn't allocate memory for sort */
214 for (temp = *l; temp; temp = temp->next) {
215 array[i++] = temp;
216 }
217
218 qsort(array, count, sizeof(semanage_list_t *),
219 (int (*)(const void *, const void *))&semanage_cmp_plist_t);
220 for (i = 0; i < (count - 1); ++i) {
221 array[i]->next = array[i + 1];
222 }
223 array[i]->next = NULL;
224 (*l) = array[0];
225 free(array);
226
227 return 0;
228 }
229
semanage_cmp_plist_t(const semanage_list_t ** x,const semanage_list_t ** y)230 int semanage_cmp_plist_t(const semanage_list_t ** x, const semanage_list_t ** y)
231 {
232 return strcmp((*x)->data, (*y)->data);
233 }
234
semanage_str_count(char * data,char what)235 int semanage_str_count(char *data, char what)
236 {
237 int count = 0;
238
239 if (!data)
240 return 0;
241 while (*data) {
242 if (*data == what)
243 ++count;
244 ++data;
245 }
246
247 return count;
248 }
249
semanage_rtrim(char * str,char trim_to)250 void semanage_rtrim(char *str, char trim_to)
251 {
252 int len = 0;
253
254 if (!str)
255 return;
256 len = strlen(str);
257
258 while (len > 0) {
259 if (str[--len] == trim_to) {
260 str[len] = '\0';
261 return;
262 }
263 }
264 }
265
266 /* list_addafter_controlmem does *NOT* duplicate the data argument
267 * use at your own risk, I am building a list out of malloc'd memory and
268 * it is only going to get stored into this list, thus when I destroy it
269 * later I won't free a ptr twice.
270 *
271 * returns the newly created node or NULL on error
272 */
list_addafter_controlmem(semanage_list_t * item,char * data)273 semanage_list_t *list_addafter_controlmem(semanage_list_t * item, char *data)
274 {
275 semanage_list_t *temp = malloc(sizeof(semanage_list_t));
276
277 if (!temp)
278 return NULL;
279 temp->data = data;
280 temp->next = item->next;
281 item->next = temp;
282
283 return temp;
284 }
285
semanage_slurp_file_filter(FILE * file,int (* pred)(const char *))286 semanage_list_t *semanage_slurp_file_filter(FILE * file,
287 int (*pred) (const char *))
288 {
289 semanage_list_t head;
290 semanage_list_t *current = &head;
291 char *line = NULL;
292 size_t buff_len = 0;
293
294 head.next = NULL; /* initialize head, we aren't going to use the data */
295 while (getline(&line, &buff_len, file) >= 0) {
296 if (pred(line)) {
297 semanage_rtrim(line, '\n');
298 current = list_addafter_controlmem(current, line);
299 if (!current)
300 break;
301 line = NULL;
302 buff_len = 0;
303 }
304 }
305 free(line);
306
307 return head.next;
308 }
309