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 
     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