blob: e226d51ad91cdb6c921fbe8fba48452e0829216f [file] [log] [blame]
Richard Haines6d0b91b2015-06-04 20:03:41 +01001/*
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>
William Roberts640db2f2016-02-02 13:46:55 -080011#include <errno.h>
Richard Haines6d0b91b2015-06-04 20:03:41 +010012#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
William Roberts640db2f2016-02-02 13:46:55 -080020/*
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)
Richard Haines6d0b91b2015-06-04 20:03:41 +010030{
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') {
William Roberts640db2f2016-02-02 13:46:55 -080041 if (!isascii(**ptr)) {
42 errno = EINVAL;
43 *errbuf = "Non-ASCII characters found";
44 return -1;
45 }
Richard Haines6d0b91b2015-06-04 20:03:41 +010046 (*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 .
William Roberts640db2f2016-02-02 13:46:55 -080061 * errbuf - Double pointer used for passing back specific error messages.
Richard Haines6d0b91b2015-06-04 20:03:41 +010062 * num_args - The number of spec parameter entries to process.
63 * ... - A 'char **spec_entry' for each parameter.
William Roberts640db2f2016-02-02 13:46:55 -080064 * returns - The number of items processed. On error, it returns -1 with errno
65 * set and may set errbuf to a specific error message.
Richard Haines6d0b91b2015-06-04 20:03:41 +010066 *
67 * This function calls read_spec_entry() to do the actual string processing.
William Roberts640db2f2016-02-02 13:46:55 -080068 * As such, can return anything from that function as well.
Richard Haines6d0b91b2015-06-04 20:03:41 +010069 */
William Roberts640db2f2016-02-02 13:46:55 -080070int hidden read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...)
Richard Haines6d0b91b2015-06-04 20:03:41 +010071{
72 char **spec_entry, *buf_p;
73 int len, rc, items, entry_len = 0;
74 va_list ap;
75
William Roberts640db2f2016-02-02 13:46:55 -080076 *errbuf = NULL;
77
Richard Haines6d0b91b2015-06-04 20:03:41 +010078 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
William Roberts640db2f2016-02-02 13:46:55 -0800107 rc = read_spec_entry(spec_entry, &buf_p, &entry_len, errbuf);
Richard Haines6d0b91b2015-06-04 20:03:41 +0100108 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}