1 /* Author: Mark Goldman <mgoldman (at) tresys.com> 2 * Paul Rosenfeld <prosenfeld (at) 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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