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 30 #define TRUE 1 31 #define FALSE 0 32 33 char *semanage_findval(const char *file, const char *var, const char *delim) 34 { 35 FILE *fd; 36 char *buff = NULL; 37 char *retval = NULL; 38 size_t buff_len = 0; 39 40 assert(file); 41 assert(var); 42 43 if ((fd = fopen(file, "r")) == NULL) 44 return NULL; 45 46 while (getline(&buff, &buff_len, fd) > 0) { 47 if (semanage_is_prefix(buff, var)) { 48 retval = semanage_split(buff, delim); 49 if (retval) 50 semanage_rtrim(retval, '\n'); 51 break; 52 } 53 } 54 free(buff); 55 fclose(fd); 56 57 return retval; 58 } 59 60 int semanage_is_prefix(const char *str, const char *prefix) 61 { 62 if (!str) { 63 return FALSE; 64 } 65 if (!prefix) { 66 return TRUE; 67 } 68 69 return strncmp(str, prefix, strlen(prefix)) == 0; 70 } 71 72 char *semanage_split_on_space(const char *str) 73 { 74 /* as per the man page, these are the isspace() chars */ 75 const char *seps = "\f\n\r\t\v "; 76 size_t off = 0; 77 78 if (!str) 79 return NULL; 80 81 /* skip one token and the spaces before and after it */ 82 off = strspn(str, seps); 83 off += strcspn(str + off, seps); 84 off += strspn(str + off, seps); 85 return strdup(str + off); 86 } 87 88 char *semanage_split(const char *str, const char *delim) 89 { 90 char *retval; 91 92 if (!str) 93 return NULL; 94 if (!delim || !(*delim)) 95 return semanage_split_on_space(str); 96 97 retval = strstr(str, delim); 98 if (retval == NULL) 99 return NULL; 100 101 return strdup(retval + strlen(delim)); 102 } 103 104 int semanage_list_push(semanage_list_t ** list, const char *data) 105 { 106 semanage_list_t *temp = NULL; 107 108 if (!data) 109 return EINVAL; 110 111 if (semanage_list_find(*list, data) != NULL) 112 return 0; 113 114 if (!(temp = malloc(sizeof(semanage_list_t)))) 115 return ENOMEM; 116 117 if (!(temp->data = strdup(data))) { 118 free(temp); 119 return ENOMEM; 120 } 121 temp->next = *list; 122 *list = temp; 123 124 return 0; 125 } 126 127 char *semanage_list_pop(semanage_list_t ** list) 128 { 129 semanage_list_t *node = NULL; 130 char *data = NULL; 131 132 if (!list || !(*list)) 133 return NULL; 134 135 node = (*list); 136 data = node->data; 137 138 (*list) = node->next; 139 free(node); 140 141 return data; 142 } 143 144 void semanage_list_destroy(semanage_list_t ** list) 145 { 146 semanage_list_t *temp; 147 148 while ((temp = (*list))) { 149 free(temp->data); 150 (*list) = temp->next; 151 free(temp); 152 } 153 } 154 155 semanage_list_t *semanage_list_find(semanage_list_t * l, const char *data) 156 { 157 if (!data) 158 return NULL; 159 while (l && strcmp(l->data, data)) 160 l = l->next; 161 162 return l; 163 } 164 165 int semanage_list_sort(semanage_list_t ** l) 166 { 167 semanage_list_t **array = NULL; 168 semanage_list_t *temp = NULL; 169 size_t count = 0; 170 size_t i = 0; 171 172 if (!l) 173 return 0; 174 175 for (temp = *l; temp; temp = temp->next) 176 ++count; 177 178 array = malloc(sizeof(semanage_list_t *) * count); 179 if (!array) 180 return ENOMEM; /* couldn't allocate memory for sort */ 181 for (temp = *l; temp; temp = temp->next) { 182 array[i++] = temp; 183 } 184 185 qsort(array, count, sizeof(semanage_list_t *), 186 (int (*)(const void *, const void *))&semanage_cmp_plist_t); 187 for (i = 0; i < (count - 1); ++i) { 188 array[i]->next = array[i + 1]; 189 } 190 array[i]->next = NULL; 191 (*l) = array[0]; 192 free(array); 193 194 return 0; 195 } 196 197 int semanage_cmp_plist_t(const semanage_list_t ** x, const semanage_list_t ** y) 198 { 199 return strcmp((*x)->data, (*y)->data); 200 } 201 202 int semanage_str_count(const char *data, char what) 203 { 204 int count = 0; 205 206 if (!data) 207 return 0; 208 while (*data) { 209 if (*data == what) 210 ++count; 211 ++data; 212 } 213 214 return count; 215 } 216 217 void semanage_rtrim(char *str, char trim_to) 218 { 219 int len = 0; 220 221 if (!str) 222 return; 223 len = strlen(str); 224 225 while (len > 0) { 226 if (str[--len] == trim_to) { 227 str[len] = '\0'; 228 return; 229 } 230 } 231 } 232 233 char *semanage_str_replace(const char *search, const char *replace, 234 const char *src, size_t lim) 235 { 236 size_t count = 0, slen, rlen, newsize; 237 char *p, *pres, *result; 238 const char *psrc; 239 240 slen = strlen(search); 241 rlen = strlen(replace); 242 243 /* Do not support empty search strings */ 244 if (slen == 0) 245 return NULL; 246 247 /* Count the occurences of search in src and compute the new size */ 248 for (p = strstr(src, search); p != NULL; p = strstr(p + slen, search)) { 249 count++; 250 if (lim && count >= lim) 251 break; 252 } 253 if (!count) 254 return strdup(src); 255 256 /* Allocate the result string */ 257 newsize = strlen(src) + 1 + count * (rlen - slen); 258 result = malloc(newsize); 259 if (!result) 260 return NULL; 261 262 /* Fill the result */ 263 psrc = src; 264 pres = result; 265 for (p = strstr(src, search); p != NULL; p = strstr(psrc, search)) { 266 /* Copy the part which has not been modified */ 267 if (p != psrc) { 268 size_t length = (size_t)(p - psrc); 269 memcpy(pres, psrc, length); 270 pres += length; 271 } 272 /* Copy the replacement part */ 273 if (rlen != 0) { 274 memcpy(pres, replace, rlen); 275 pres += rlen; 276 } 277 psrc = p + slen; 278 count--; 279 if (!count) 280 break; 281 } 282 /* Copy the last part, after doing a sanity check */ 283 assert(pres + strlen(psrc) + 1 == result + newsize); 284 strcpy(pres, psrc); 285 return result; 286 } 287 288 /* list_addafter_controlmem does *NOT* duplicate the data argument 289 * use at your own risk, I am building a list out of malloc'd memory and 290 * it is only going to get stored into this list, thus when I destroy it 291 * later I won't free a ptr twice. 292 * 293 * returns the newly created node or NULL on error 294 */ 295 semanage_list_t *list_addafter_controlmem(semanage_list_t * item, char *data) 296 { 297 semanage_list_t *temp = malloc(sizeof(semanage_list_t)); 298 299 if (!temp) 300 return NULL; 301 temp->data = data; 302 temp->next = item->next; 303 item->next = temp; 304 305 return temp; 306 } 307 308 semanage_list_t *semanage_slurp_file_filter(FILE * file, 309 int (*pred) (const char *)) 310 { 311 semanage_list_t head; 312 semanage_list_t *current = &head; 313 char *line = NULL; 314 size_t buff_len = 0; 315 316 head.next = NULL; /* initialize head, we aren't going to use the data */ 317 while (getline(&line, &buff_len, file) >= 0) { 318 if (pred(line)) { 319 semanage_rtrim(line, '\n'); 320 current = list_addafter_controlmem(current, line); 321 if (!current) 322 break; 323 line = NULL; 324 buff_len = 0; 325 } 326 } 327 free(line); 328 329 return head.next; 330 } 331