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 */
read_spec_entry(char ** entry,char ** ptr,int * len,const char ** errbuf)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 */
read_spec_entries(char * line_buf,const char ** errbuf,int num_args,...)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