Home | History | Annotate | Download | only in src
      1 /*
      2  * This file contains helper functions for labeling support.
      3  *
      4  * Author : Richard Haines <richard_c_haines (at) btinternet.com>
      5  */
      6 
      7 #include <stdlib.h>
      8 #include <stdarg.h>
      9 #include <ctype.h>
     10 #include <string.h>
     11 #include <errno.h>
     12 #include "label_internal.h"
     13 
     14 /*
     15  * The read_spec_entries and read_spec_entry functions may be used to
     16  * replace sscanf to read entries from spec files. The file and
     17  * property services now use these.
     18  */
     19 
     20 /*
     21  * Read an entry from a spec file (e.g. file_contexts)
     22  * entry - Buffer to allocate for the entry.
     23  * ptr - current location of the line to be processed.
     24  * returns  - 0 on success and *entry is set to be a null
     25  *            terminated value. On Error it returns -1 and
     26               errno will be set.
     27  *
     28  */
     29 static inline int read_spec_entry(char **entry, char **ptr, int *len, const char **errbuf)
     30 {
     31 	*entry = NULL;
     32 	char *tmp_buf = NULL;
     33 
     34 	while (isspace(**ptr) && **ptr != '\0')
     35 		(*ptr)++;
     36 
     37 	tmp_buf = *ptr;
     38 	*len = 0;
     39 
     40 	while (!isspace(**ptr) && **ptr != '\0') {
     41 		if (!isascii(**ptr)) {
     42 			errno = EINVAL;
     43 			*errbuf = "Non-ASCII characters found";
     44 			return -1;
     45 		}
     46 		(*ptr)++;
     47 		(*len)++;
     48 	}
     49 
     50 	if (*len) {
     51 		*entry = strndup(tmp_buf, *len);
     52 		if (!*entry)
     53 			return -1;
     54 	}
     55 
     56 	return 0;
     57 }
     58 
     59 /*
     60  * line_buf - Buffer containing the spec entries .
     61  * errbuf   - Double pointer used for passing back specific error messages.
     62  * num_args - The number of spec parameter entries to process.
     63  * ...      - A 'char **spec_entry' for each parameter.
     64  * returns  - The number of items processed. On error, it returns -1 with errno
     65  *            set and may set errbuf to a specific error message.
     66  *
     67  * This function calls read_spec_entry() to do the actual string processing.
     68  * As such, can return anything from that function as well.
     69  */
     70 int hidden read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...)
     71 {
     72 	char **spec_entry, *buf_p;
     73 	int len, rc, items, entry_len = 0;
     74 	va_list ap;
     75 
     76 	*errbuf = NULL;
     77 
     78 	len = strlen(line_buf);
     79 	if (line_buf[len - 1] == '\n')
     80 		line_buf[len - 1] = '\0';
     81 	else
     82 		/* Handle case if line not \n terminated by bumping
     83 		 * the len for the check below (as the line is NUL
     84 		 * terminated by getline(3)) */
     85 		len++;
     86 
     87 	buf_p = line_buf;
     88 	while (isspace(*buf_p))
     89 		buf_p++;
     90 
     91 	/* Skip comment lines and empty lines. */
     92 	if (*buf_p == '#' || *buf_p == '\0')
     93 		return 0;
     94 
     95 	/* Process the spec file entries */
     96 	va_start(ap, num_args);
     97 
     98 	items = 0;
     99 	while (items < num_args) {
    100 		spec_entry = va_arg(ap, char **);
    101 
    102 		if (len - 1 == buf_p - line_buf) {
    103 			va_end(ap);
    104 			return items;
    105 		}
    106 
    107 		rc = read_spec_entry(spec_entry, &buf_p, &entry_len, errbuf);
    108 		if (rc < 0) {
    109 			va_end(ap);
    110 			return rc;
    111 		}
    112 		if (entry_len)
    113 			items++;
    114 	}
    115 	va_end(ap);
    116 	return items;
    117 }
    118