Home | History | Annotate | Download | only in src
      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