1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif /* HAVE_CONFIG_H */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <sys/wait.h>
11 #include <errno.h>
12 #include <assert.h>
13 #if WITH_INTERNAL_GETOPT
14 #include "libc/getopt.h"
15 #else
16 #ifdef HAVE_GETOPT_H
17 #include <getopt.h>
18 #endif
19 #endif
20 
21 #include "lub/types.h"
22 #include "lub/argv.h"
23 #include "lub/string.h"
24 #include "lub/conv.h"
25 #include "private.h"
26 
27 /*-------------------------------------------------------- */
konf_query_new(void)28 konf_query_t *konf_query_new(void)
29 {
30 	konf_query_t *this;
31 
32 	if (!(this = malloc(sizeof(*this))))
33 		return NULL;
34 
35 	this->op = KONF_QUERY_OP_NONE;
36 	this->pattern = NULL;
37 	this->priority = 0;
38 	this->seq = BOOL_FALSE;
39 	this->seq_num = 0;
40 	this->pwdc = 0;
41 	this->pwd = NULL;
42 	this->line = NULL;
43 	this->path = NULL;
44 	this->splitter = BOOL_TRUE;
45 	this->unique = BOOL_TRUE;
46 	this->depth = -1;
47 
48 	return this;
49 }
50 
51 /*-------------------------------------------------------- */
konf_query_add_pwd(konf_query_t * this,char * str)52 void konf_query_add_pwd(konf_query_t *this, char *str)
53 {
54 	size_t new_size;
55 	char **tmp;
56 
57 	if (!this)
58 		return;
59 
60 	new_size = ((this->pwdc + 1) * sizeof(char *));
61 
62 	/* resize the pwd vector */
63 	tmp = realloc(this->pwd, new_size);
64 	assert(tmp);
65 	this->pwd = tmp;
66 	/* insert reference to the pwd component */
67 	this->pwd[this->pwdc++] = strdup(str);
68 }
69 
70 /*-------------------------------------------------------- */
konf_query_free(konf_query_t * this)71 void konf_query_free(konf_query_t *this)
72 {
73 	unsigned i;
74 
75 	free(this->pattern);
76 	free(this->line);
77 	free(this->path);
78 	if (this->pwdc > 0) {
79 		for (i = 0; i < this->pwdc; i++)
80 			free(this->pwd[i]);
81 		free(this->pwd);
82 	}
83 
84 	free(this);
85 }
86 
87 /*-------------------------------------------------------- */
88 /* Parse query */
konf_query_parse(konf_query_t * this,int argc,char ** argv)89 int konf_query_parse(konf_query_t *this, int argc, char **argv)
90 {
91 	int i = 0;
92 	int pwdc = 0;
93 
94 	static const char *shortopts = "suoedtp:q:r:l:f:inh:";
95 #ifdef HAVE_GETOPT_LONG
96 	static const struct option longopts[] = {
97 		{"set",		0, NULL, 's'},
98 		{"unset",	0, NULL, 'u'},
99 		{"ok",		0, NULL, 'o'},
100 		{"error",	0, NULL, 'e'},
101 		{"dump",	0, NULL, 'd'},
102 		{"stream",	0, NULL, 't'},
103 		{"priority",	1, NULL, 'p'},
104 		{"seq",		1, NULL, 'q'},
105 		{"pattern",	1, NULL, 'r'},
106 		{"line",	1, NULL, 'l'},
107 		{"file",	1, NULL, 'f'},
108 		{"splitter",	0, NULL, 'i'},
109 		{"non-unique",	0, NULL, 'n'},
110 		{"depth",	1, NULL, 'h'},
111 		{NULL,		0, NULL, 0}
112 	};
113 #endif
114 
115 	optind = 0; /* It must be 1 for QNX6. This system has no getopt.h */
116 	while(1) {
117 		int opt;
118 #ifdef HAVE_GETOPT_LONG
119 		opt = getopt_long(argc, argv, shortopts, longopts, NULL);
120 #else
121 		opt = getopt(argc, argv, shortopts);
122 #endif
123 		if (-1 == opt)
124 			break;
125 		switch (opt) {
126 		case 'o':
127 			this->op = KONF_QUERY_OP_OK;
128 			break;
129 		case 'e':
130 			this->op = KONF_QUERY_OP_ERROR;
131 			break;
132 		case 's':
133 			this->op = KONF_QUERY_OP_SET;
134 			break;
135 		case 'u':
136 			this->op = KONF_QUERY_OP_UNSET;
137 			break;
138 		case 'd':
139 			this->op = KONF_QUERY_OP_DUMP;
140 			break;
141 		case 't':
142 			this->op = KONF_QUERY_OP_STREAM;
143 			break;
144 		case 'p':
145 			{
146 			unsigned short val = 0;
147 			if (lub_conv_atous(optarg, &val, 0) < 0)
148 				break;
149 			this->priority = val;
150 			break;
151 			}
152 		case 'q':
153 			{
154 			unsigned short val = 0;
155 			this->seq = BOOL_TRUE;
156 			if (lub_conv_atous(optarg, &val, 0) < 0)
157 				break;
158 			this->seq_num = val;
159 			break;
160 			}
161 		case 'r':
162 			this->pattern = strdup(optarg);
163 			break;
164 		case 'l':
165 			this->line = strdup(optarg);
166 			break;
167 		case 'f':
168 			this->path = strdup(optarg);
169 			break;
170 		case 'i':
171 			this->splitter = BOOL_FALSE;
172 			break;
173 		case 'n':
174 			this->unique = BOOL_FALSE;
175 			break;
176 		case 'h':
177 			{
178 			unsigned short val = 0;
179 			if (lub_conv_atous(optarg, &val, 0) < 0)
180 				break;
181 			this->depth = val;
182 			break;
183 			}
184 		default:
185 			break;
186 		}
187 	}
188 
189 	/* Check options */
190 	if (KONF_QUERY_OP_NONE == this->op)
191 		return -1;
192 	if (KONF_QUERY_OP_SET == this->op) {
193 		if (!this->pattern)
194 			return -1;
195 		if (!this->line)
196 			return -1;
197 	}
198 
199 	if ((pwdc = argc - optind) < 0)
200 		return -1;
201 
202 	for (i = 0; i < pwdc; i++)
203 		konf_query_add_pwd(this, argv[optind + i]);
204 
205 	return 0;
206 }
207 
208 /*-------------------------------------------------------- */
209 /* Parse query string */
konf_query_parse_str(konf_query_t * this,char * str)210 int konf_query_parse_str(konf_query_t *this, char *str)
211 {
212 	int res;
213 	lub_argv_t *lub_argv;
214 	char **str_argv;
215 	int str_argc;
216 
217 	/* Make args from string */
218 	lub_argv = lub_argv_new(str, 0);
219 	str_argv = lub_argv__get_argv(lub_argv, "");
220 	str_argc = lub_argv__get_count(lub_argv) + 1;
221 
222 	/* Parse query */
223 	res = konf_query_parse(this, str_argc, str_argv);
224 	lub_argv__free_argv(str_argv);
225 	lub_argv_delete(lub_argv);
226 
227 	return res;
228 }
229 
230 /*-------------------------------------------------------- */
konf_query__get_pwd(konf_query_t * this,unsigned index)231 char * konf_query__get_pwd(konf_query_t *this, unsigned index)
232 {
233 	if (!this)
234 		return NULL;
235 	if (index >= this->pwdc)
236 		return NULL;
237 
238 	return this->pwd[index];
239 }
240 
241 /*-------------------------------------------------------- */
konf_query__get_pwdc(konf_query_t * this)242 int konf_query__get_pwdc(konf_query_t *this)
243 {
244 	return this->pwdc;
245 }
246 
247 /*-------------------------------------------------------- */
konf_query__get_op(konf_query_t * this)248 konf_query_op_e konf_query__get_op(konf_query_t *this)
249 {
250 	return this->op;
251 }
252 
253 /*-------------------------------------------------------- */
konf_query__get_path(konf_query_t * this)254 char * konf_query__get_path(konf_query_t *this)
255 {
256 	return this->path;
257 }
258 
259 /*-------------------------------------------------------- */
konf_query__get_pattern(konf_query_t * this)260 const char * konf_query__get_pattern(konf_query_t *this)
261 {
262 	return this->pattern;
263 }
264 
265 /*-------------------------------------------------------- */
konf_query__get_line(konf_query_t * this)266 const char * konf_query__get_line(konf_query_t *this)
267 {
268 	return this->line;
269 }
270 
271 /*-------------------------------------------------------- */
konf_query__get_priority(konf_query_t * this)272 unsigned short konf_query__get_priority(konf_query_t *this)
273 {
274 	return this->priority;
275 }
276 
277 /*-------------------------------------------------------- */
konf_query__get_splitter(konf_query_t * this)278 bool_t konf_query__get_splitter(konf_query_t *this)
279 {
280 	return this->splitter;
281 }
282 
283 /*-------------------------------------------------------- */
konf_query__get_seq(konf_query_t * this)284 bool_t konf_query__get_seq(konf_query_t *this)
285 {
286 	return this->seq;
287 }
288 
289 /*-------------------------------------------------------- */
konf_query__get_seq_num(konf_query_t * this)290 unsigned short konf_query__get_seq_num(konf_query_t *this)
291 {
292 	return this->seq_num;
293 }
294 
295 /*-------------------------------------------------------- */
konf_query__get_unique(konf_query_t * this)296 bool_t konf_query__get_unique(konf_query_t *this)
297 {
298 	return this->unique;
299 }
300 
301 /*-------------------------------------------------------- */
konf_query__get_depth(konf_query_t * this)302 int konf_query__get_depth(konf_query_t *this)
303 {
304 	return this->depth;
305 }
306