1/* 2 * This file contains helper functions for labeling support. 3 * 4 * Author : Richard Haines <richard_c_haines@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 */ 29static 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 */ 70int 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