comparison src/cfgparser.c @ 125:e413158cae13

Add ushare project files.
author naoyan@johnstown.minaminoshima.org
date Sun, 03 Oct 2010 11:35:19 +0900
parents
children 863ac6807ee3
comparison
equal deleted inserted replaced
124:9c7bc6c0327e 125:e413158cae13
1 /*
2 * cfgparser.c : GeeXboX uShare config file parser.
3 * Originally developped for the GeeXboX project.
4 * Copyright (C) 2005-2007 Alexis Saettler <asbin@asbin.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <getopt.h>
25 #include <stdbool.h>
26 #include <limits.h>
27
28 #include "config.h"
29 #include "gettext.h"
30 #include "cfgparser.h"
31 #include "ushare.h"
32 #include "trace.h"
33 #include "osdep.h"
34
35 #define USHARE_DIR_DELIM ","
36
37 static bool
38 ignore_line (const char *line)
39 {
40 int i;
41 size_t len;
42
43 /* commented line */
44 if (line[0] == '#' )
45 return true;
46
47 len = strlen (line);
48
49 for (i = 0 ; i < (int) len ; i++ )
50 if (line[i] != ' ' && line[i] != '\t' && line[i] != '\n')
51 return false;
52
53 return true;
54 }
55
56 static char *
57 strdup_trim (const char *s)
58 {
59 size_t begin, end;
60 char *r = NULL;
61
62 if (!s)
63 return NULL;
64
65 end = strlen (s) - 1;
66
67 for (begin = 0 ; begin < end ; begin++)
68 if (s[begin] != ' ' && s[begin] != '\t' && s[begin] != '"')
69 break;
70
71 for (; begin < end ; end--)
72 if (s[end] != ' ' && s[end] != '\t' && s[end] != '"' && s[end] != '\n')
73 break;
74
75 r = strndup (s + begin, end - begin + 1);
76
77 return r;
78 }
79
80 static void
81 ushare_set_name (struct ushare_t *ut, const char *name)
82 {
83 if (!ut || !name)
84 return;
85
86 if (ut->name)
87 {
88 free (ut->name);
89 ut->name = NULL;
90 }
91
92 ut->name = strdup_trim (name);
93 }
94
95 static void
96 ushare_set_interface (struct ushare_t *ut, const char *iface)
97 {
98 if (!ut || !iface)
99 return;
100
101 if (ut->interface)
102 {
103 free (ut->interface);
104 ut->interface = NULL;
105 }
106
107 ut->interface = strdup_trim (iface);
108 }
109
110 static void
111 ushare_add_contentdir (struct ushare_t *ut, const char *dir)
112 {
113 if (!ut || !dir)
114 return;
115
116 ut->contentlist = content_add (ut->contentlist, dir);
117 }
118
119 static void
120 ushare_set_cfg_file (struct ushare_t *ut, const char *file)
121 {
122 if (!ut || !file)
123 return;
124
125 ut->cfg_file = strdup (file);
126 }
127
128 static void
129 ushare_set_dir (struct ushare_t *ut, const char *dirlist)
130 {
131 char *x = NULL, *token = NULL;
132 char *m_buffer = NULL, *buffer;
133
134 if (!ut || !dirlist)
135 return;
136
137 x = strdup_trim (dirlist);
138 if (x)
139 {
140 m_buffer = (char*) malloc (strlen (x) * sizeof (char));
141 if (m_buffer)
142 {
143 buffer = m_buffer;
144 token = strtok_r (x, USHARE_DIR_DELIM, &buffer);
145 while (token)
146 {
147 ushare_add_contentdir (ut, token);
148 token = strtok_r (NULL, USHARE_DIR_DELIM, &buffer);
149 }
150 free (m_buffer);
151 }
152 free (x);
153 }
154 }
155
156 static void
157 ushare_set_port (struct ushare_t *ut, const char *port)
158 {
159 if (!ut || !port)
160 return;
161
162 ut->port = atoi (port);
163 if (ut->port < 49152)
164 {
165 fprintf (stderr,
166 _("Warning: port doesn't fit IANA port assignements.\n"));
167
168 fprintf (stderr, _("Warning: Only Dynamic or Private Ports can be used "
169 "(from 49152 through 65535)\n"));
170 ut->port = 0;
171 }
172 }
173
174 static void
175 ushare_set_telnet_port (struct ushare_t *ut, const char *port)
176 {
177 if (!ut || !port)
178 return;
179
180 ut->telnet_port = atoi (port);
181 }
182
183 static void
184 ushare_use_web (struct ushare_t *ut, const char *val)
185 {
186 if (!ut || !val)
187 return;
188
189 ut->use_presentation = (!strcmp (val, "yes")) ? true : false;
190 }
191
192 static void
193 ushare_use_telnet (struct ushare_t *ut, const char *val)
194 {
195 if (!ut || !val)
196 return;
197
198 ut->use_telnet = (!strcmp (val, "yes")) ? true : false;
199 }
200
201 static void
202 ushare_use_xbox (struct ushare_t *ut, const char *val)
203 {
204 if (!ut || !val)
205 return;
206
207 ut->xbox360 = (!strcmp (val, "yes")) ? true : false;
208 }
209
210 static void
211 ushare_use_dlna (struct ushare_t *ut, const char *val)
212 {
213 if (!ut || !val)
214 return;
215
216 #ifdef HAVE_DLNA
217 ut->dlna_enabled = (!strcmp (val, "yes")) ? true : false;
218 #endif /* HAVE_DLNA */
219 }
220
221 static void
222 ushare_set_override_iconv_err (struct ushare_t *ut, const char *arg)
223 {
224 if (!ut)
225 return;
226
227 ut->override_iconv_err = false;
228
229 if (!strcasecmp (arg, "yes")
230 || !strcasecmp (arg, "true")
231 || !strcmp (arg, "1"))
232 ut->override_iconv_err = true;
233 }
234
235 static u_configline_t configline[] = {
236 { USHARE_NAME, ushare_set_name },
237 { USHARE_IFACE, ushare_set_interface },
238 { USHARE_PORT, ushare_set_port },
239 { USHARE_TELNET_PORT, ushare_set_telnet_port },
240 { USHARE_DIR, ushare_set_dir },
241 { USHARE_OVERRIDE_ICONV_ERR, ushare_set_override_iconv_err },
242 { USHARE_ENABLE_WEB, ushare_use_web },
243 { USHARE_ENABLE_TELNET, ushare_use_telnet },
244 { USHARE_ENABLE_XBOX, ushare_use_xbox },
245 { USHARE_ENABLE_DLNA, ushare_use_dlna },
246 { NULL, NULL },
247 };
248
249 static void
250 parse_config_line (struct ushare_t *ut, const char *line,
251 u_configline_t *configline)
252 {
253 char *s = NULL;
254
255 s = strchr (line, '=');
256 if (s && s[1] != '\0')
257 {
258 int i;
259 for (i=0 ; configline[i].name ; i++)
260 {
261 if (!strncmp (line, configline[i].name, strlen (configline[i].name)))
262 {
263 configline[i].set_var (ut, s + 1);
264 break;
265 }
266 }
267 }
268 }
269
270 int
271 parse_config_file (struct ushare_t *ut)
272 {
273 char filename[PATH_MAX];
274 FILE *conffile;
275 char *line = NULL;
276 size_t size = 0;
277 ssize_t read;
278
279 if (!ut)
280 return -1;
281
282 if (!ut->cfg_file)
283 snprintf (filename, PATH_MAX, "%s/%s", SYSCONFDIR, USHARE_CONFIG_FILE);
284 else
285 snprintf (filename, PATH_MAX, "%s", ut->cfg_file);
286
287 conffile = fopen (filename, "r");
288 if (!conffile)
289 return -1;
290
291 while ((read = getline (&line, &size, conffile)) != -1)
292 {
293 if (ignore_line (line))
294 continue;
295
296 if (line[read-1] == '\n')
297 line[read-1] = '\0';
298
299 while (line[0] == ' ' || line[0] == '\t')
300 line++;
301
302 parse_config_line (ut, line, configline);
303 }
304
305 fclose (conffile);
306
307 if (line)
308 free (line);
309
310 return 0;
311 }
312
313 inline static void
314 display_usage (void)
315 {
316 display_headers ();
317 printf ("\n");
318 printf (_("Usage: ushare [-n name] [-i interface] [-p port] [-c directory] [[-c directory]...]\n"));
319 printf (_("Options:\n"));
320 printf (_(" -n, --name=NAME\tSet UPnP Friendly Name (default is '%s')\n"),
321 DEFAULT_USHARE_NAME);
322 printf (_(" -i, --interface=IFACE\tUse IFACE Network Interface (default is '%s')\n"),
323 DEFAULT_USHARE_IFACE);
324 printf (_(" -f, --cfg=FILE\t\tConfig file to be used\n"));
325 printf (_(" -p, --port=PORT\tForces the HTTP server to run on PORT\n"));
326 printf (_(" -q, --telnet-port=PORT\tForces the TELNET server to run on PORT\n"));
327 printf (_(" -c, --content=DIR\tShare the content of DIR directory\n"));
328 printf (_(" -w, --no-web\t\tDisable the control web page (enabled by default)\n"));
329 printf (_(" -t, --no-telnet\tDisable the TELNET control (enabled by default)\n"));
330 printf (_(" -o, --override-iconv-err\tIf iconv fails parsing name, still add to media contents (hoping the renderer can handle it)\n"));
331 printf (_(" -v, --verbose\t\tSet verbose display\n"));
332 printf (_(" -x, --xbox\t\tUse XboX 360 compliant profile\n"));
333 #ifdef HAVE_DLNA
334 printf (_(" -d, --dlna\t\tUse DLNA compliant profile (PlayStation3 needs this)\n"));
335 #endif /* HAVE_DLNA */
336 printf (_(" -D, --daemon\t\tRun as a daemon\n"));
337 printf (_(" -V, --version\t\tDisplay the version of uShare and exit\n"));
338 printf (_(" -h, --help\t\tDisplay this help\n"));
339 }
340
341 int
342 parse_command_line (struct ushare_t *ut, int argc, char **argv)
343 {
344 int c, index;
345 char short_options[] = "VhvDowtxdn:i:p:q:c:f:";
346 struct option long_options [] = {
347 {"version", no_argument, 0, 'V' },
348 {"help", no_argument, 0, 'h' },
349 {"verbose", no_argument, 0, 'v' },
350 {"daemon", no_argument, 0, 'D' },
351 {"override-iconv-err", no_argument, 0, 'o' },
352 {"name", required_argument, 0, 'n' },
353 {"interface", required_argument, 0, 'i' },
354 {"port", required_argument, 0, 'p' },
355 {"telnet-port", required_argument, 0, 'q' },
356 {"content", required_argument, 0, 'c' },
357 {"no-web", no_argument, 0, 'w' },
358 {"no-telnet", no_argument, 0, 't' },
359 {"xbox", no_argument, 0, 'x' },
360 #ifdef HAVE_DLNA
361 {"dlna", no_argument, 0, 'd' },
362 #endif /* HAVE_DLNA */
363 {"cfg", required_argument, 0, 'f' },
364 {0, 0, 0, 0 }
365 };
366
367 /* command line argument processing */
368 while (true)
369 {
370 c = getopt_long (argc, argv, short_options, long_options, &index);
371
372 if (c == EOF)
373 break;
374
375 switch (c)
376 {
377 case 0:
378 /* opt = long_options[index].name; */
379 break;
380
381 case '?':
382 case 'h':
383 display_usage ();
384 return -1;
385
386 case 'V':
387 display_headers ();
388 return -1;
389
390 case 'v':
391 ut->verbose = true;
392 break;
393
394 case 'D':
395 ut->daemon = true;
396 break;
397
398 case 'o':
399 ut->override_iconv_err = true;
400 break;
401
402 case 'n':
403 ushare_set_name (ut, optarg);
404 break;
405
406 case 'i':
407 ushare_set_interface (ut, optarg);
408 break;
409
410 case 'p':
411 ushare_set_port (ut, optarg);
412 break;
413
414 case 'q':
415 ushare_set_telnet_port (ut, optarg);
416 break;
417
418 case 'c':
419 ushare_add_contentdir (ut, optarg);
420 break;
421
422 case 'w':
423 ut->use_presentation = false;
424 break;
425
426 case 't':
427 ut->use_telnet = false;
428 break;
429
430 case 'x':
431 ut->xbox360 = true;
432 break;
433
434 #ifdef HAVE_DLNA
435 case 'd':
436 ut->dlna_enabled = true;
437 break;
438 #endif /* HAVE_DLNA */
439
440 case 'f':
441 ushare_set_cfg_file (ut, optarg);
442 break;
443
444 default:
445 break;
446 }
447 }
448
449 return 0;
450 }