1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <assert.h>
4 #include <string.h>
5 #include <ctype.h>
6 
7 #include "support.h"
8 #include "ossupport.h"
9 
10 /* Zero terminate the current word. Returns -1 is *s == 0 or the next word
11    does not exist. Otherwise returns offset to the beginning of next word. */
skip_and_terminate_word(char * s,int i)12 int skip_and_terminate_word(char *s, int i)
13 {
14 	i = skipnws(s, i);
15 	if (i < 0)
16 		return -1;
17 
18 	/* Zero terminate word */
19 	s[i] = 0;
20 
21 	i = skipws(s, i + 1);
22 	if (i < 0)
23 		return -1;
24 
25 	return i;
26 }
27 
xbasename(const char * s)28 char *xbasename(const char *s)
29 {
30   char *t = strrchr(s, (int) '/');
31   if (t == NULL) {
32 	  t = (char *) s;
33   } else {
34 	  t++;
35   }
36   return t;
37 }
38 
39 /*
40  * Split a string into 2 whitespace separated fields returned in "key" and
41  * "value". If more than 2 fields are found, they are cut off by zero
42  * terminating "key" and "value" inside the string. If "value" is not found,
43  * *value is set to NULL. If "key" is not found, *key is set to NULL.
44  * If something is found, both *key and *value become pointers inside the
45  * string s.
46  *
47  * Return values:
48  *  - 0 if neither "key" nor "value" is found
49  *  - 1 if only "key" is found
50  *  - 2 if both "key" and "value" are found
51  */
get_two_ws_separated_fields(char ** key,char ** value,char * s)52 int get_two_ws_separated_fields(char **key, char **value, char *s)
53 {
54 	int i;
55 
56 	*key = NULL;
57 	*value = NULL;
58 
59 	i = skipws(s, 0);   /* Skip initial whitespace */
60 
61 	if (i < 0)
62 		return 0;   /* We got nothing */
63 
64 	*key = s + i;
65 
66 	i = skip_and_terminate_word(s, i);
67 
68 	if (i < 0)
69 		return 1;   /* We got a "key", but not a "value" */
70 
71 	*value = s + i;
72 
73 	skip_and_terminate_word(s, i);
74 
75 	return 2;           /* We got both a "key" and a "value" */
76 }
77 
78 /*
79  * Skip whitespace characters in string starting from offset i. Returns offset
80  * j >= i as the next non-whitespace character offset, or -1 if non-whitespace
81  * are not found.
82  */
skipws(const char * s,int i)83 int skipws(const char *s, int i)
84 {
85 	while (isspace(s[i]))
86 		i++;
87 
88 	if (s[i] == 0)
89 		return -1;
90 
91 	return i;
92 }
93 
94 /*
95  * Skip non-whitespace characters in string starting from offset i. Returns
96  * offset j >= i as the next whitespace character offset, or -1 if no
97  * whitespace if found.
98  */
skipnws(const char * s,int i)99 int skipnws(const char *s, int i)
100 {
101 	while (!isspace(s[i]) && s[i] != 0)
102 		i++;
103 
104 	if (s[i] == 0)
105 		return -1;
106 
107 	return i;
108 }
109 
110 
111 /* Split line with respect to white space. */
read_and_split_lines(size_t * nitems,size_t * lineno,FILE * f,const char * delim)112 char **read_and_split_lines(size_t *nitems, size_t *lineno, FILE *f,
113 			    const char *delim)
114 {
115 	char line[UADE_LINESIZE], templine[UADE_LINESIZE];
116 	char **items = NULL;
117 	size_t pos;
118 	char *sp, *s;
119 
120 	*nitems = 0;
121 
122 	while (xfgets(line, sizeof line, f) != NULL) {
123 
124 		if (lineno != NULL)
125 			(*lineno)++;
126 
127 		/* Skip, if a comment line */
128 		if (line[0] == '#')
129 			continue;
130 
131 		/* strsep() modifies line that it touches, so we make a copy
132 		   of it, and then count the number of items on the line */
133 		strlcpy(templine, line, sizeof(templine));
134 		sp = templine;
135 		while ((s = strsep(&sp, delim)) != NULL) {
136 			if (*s == 0)
137 				continue;
138 			(*nitems)++;
139 		}
140 
141 		if (*nitems > 0)
142 			break;
143 	}
144 
145 	if (*nitems == 0)
146 		return NULL;
147 
148 	if ((items = malloc(sizeof(items[0]) * (*nitems + 1))) == NULL)
149 		uadeerror("No memory for nws items.\n");
150 
151 	sp = line;
152 	pos = 0;
153 	while ((s = strsep(&sp, delim)) != NULL) {
154 		if (*s == 0)
155 			continue;
156 
157 		if ((items[pos] = strdup(s)) == NULL)
158 			uadeerror("No memory for an nws item.\n");
159 
160 		pos++;
161 	}
162 	items[pos] = NULL;
163 	assert(pos == *nitems);
164 
165 	return items;
166 }
167 
168 
xfgets(char * s,int size,FILE * stream)169 char *xfgets(char *s, int size, FILE *stream)
170 {
171 	char *ret;
172 
173 	while (1) {
174 		ret = fgets(s, size, stream);
175 		if (ret != NULL)
176 			break;
177 
178 		if (feof(stream))
179 			break;
180 	}
181 
182 	return ret;
183 }
184