source: roaraudio/libroar/config.c @ 5884:2cea563f456d

Last change on this file since 5884:2cea563f456d was 5884:2cea563f456d, checked in by phi, 11 years ago

small updated: avoid generation of invalid paths as well as adding support for magic keyword "universal" for product parameter

File size: 22.5 KB
Line 
1//config.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2013
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38#define LEN_AUTHFILE 1024
39
40static struct roar_libroar_config_codec *
41           roar_libroar_config_codec_get_conf(int32_t codec, int create, struct roar_libroar_config * config);
42
43
44struct roar_libroar_config * roar_libroar_get_config_ptr(void) {
45 static struct roar_libroar_config config;
46 static int    inited = 0;
47 static char   authfile[LEN_AUTHFILE];
48 const  char * home;
49
50 if ( !inited ) {
51  memset(&config, 0, sizeof(config));
52
53#ifdef ROAR_SUPPORT_TRAP
54  config.trap_policy      = ROAR_TRAP_IGNORE;
55#endif
56  config.opmode           = ROAR_LIBROAR_CONFIG_OPMODE_NORMAL;
57  config.server           = NULL;
58  config.authfile         = NULL;
59  config.forkapi          = NULL;
60  config.connect_internal = NULL;
61  config.daemonimage      = NULL;
62  config.protocolversion  = -1; // use default.
63
64  home = roar_env_get_home(0);
65  if ( home != NULL ) {
66   snprintf(authfile, sizeof(authfile)-1, "%s/.roarauth", home);
67   authfile[sizeof(authfile)-1] = 0;
68   config.authfile    = authfile;
69   config.serversfile = NULL;
70  }
71
72  inited++;
73 }
74
75 return &config;
76}
77
78struct roar_libroar_config * roar_libroar_get_config(void) {
79 struct roar_libroar_config * config = roar_libroar_get_config_ptr();
80 static int inited = 0;
81 const char * next;
82 char * buf;
83
84 if ( !inited ) {
85  inited++; // we do this early so we can use ROAR_{DBG,INFO,WARN,ERR}() in roar_libroar_config_parse().
86
87  next = roar_env_get("ROAR_OPTIONS");
88
89  if ( next != NULL ) {
90   if ( (buf = roar_mm_strdup(next)) != NULL ) {
91    roar_libroar_config_parse(buf, " ");
92    roar_mm_free(buf);
93   }
94  }
95 }
96
97 return config;
98}
99
100int    roar_libroar_reset_config(void) {
101 struct roar_libroar_config * config = roar_libroar_get_config_ptr();
102
103 if ( config->codecs.codec != NULL ) {
104  roar_mm_free(config->codecs.codec);
105  config->codecs.num = 0;
106 }
107
108 if ( config->x11.display != NULL )
109  roar_mm_free(config->x11.display);
110 config->x11.display = NULL;
111
112 if ( config->daemonimage != NULL )
113  roar_mm_free(config->daemonimage);
114 config->daemonimage = NULL;
115
116 return 0;
117}
118
119#define _P_FP(v)   ((int)(atof((v))*256.0))
120#define _P_INT(v)  (atoi((v)))
121#define _P_BOOL(v) (*(v) == 'y' || *(v) == 'j' || *(v) == 't' || *(v) == '1' ? 1 : 0)
122
123static int roar_libroar_config_parse_codec(struct roar_libroar_config * config, char * txt) {
124 struct roar_libroar_config_codec * codec_cfg;
125 int32_t codec;
126 char * codec_str, * option_str, * value_str;
127 char * toksave = NULL;
128
129 ROAR_DBG("roar_libroar_config_parse_codec(config=%p, txt='%s') = ?", config, txt);
130
131 if ( config == NULL || txt == NULL )
132  return -1;
133
134 ROAR_DBG("roar_libroar_config_parse_codec(config=%p, txt='%s') = ?", config, txt);
135
136 codec_str = roar_mm_strtok_r(txt, ":", &toksave);
137
138 if ( codec_str == NULL )
139  return -1;
140
141 option_str = roar_mm_strtok_r(NULL, ":", &toksave);
142
143 if ( option_str == NULL )
144  return -1;
145
146 value_str = roar_mm_strtok_r(NULL, ":", &toksave);
147
148 if ( value_str == NULL )
149  return -1;
150
151 ROAR_DBG("roar_libroar_config_parse_codec(config=%p, txt='%s') = ?", config, txt);
152
153 if ( (codec = roar_str2codec(codec_str)) == -1 ) {
154  ROAR_WARN("roar_libroar_config_parse_codec(*): Unknown codec: %s", codec_str);
155  return -1;
156 }
157
158 ROAR_DBG("roar_libroar_config_parse_codec(config=%p, txt='%s'): codec=%i", config, txt, codec);
159
160 if ( (codec_cfg = roar_libroar_config_codec_get_conf(codec, 1, config)) == NULL )
161  return -1;
162
163 ROAR_DBG("roar_libroar_config_parse_codec(config=%p, txt='%s'): codec=%i, codec_cfg=%p", config, txt, codec, codec_cfg);
164
165 if ( !strcmp(option_str, "q") || !strcmp(option_str, "quality") ) {
166  codec_cfg->para_set |= ROAR_LIBROAR_CONFIG_PSET_Q;
167  codec_cfg->q = _P_FP(value_str);
168 } else if ( !strcmp(option_str, "complexity") ) {
169  codec_cfg->para_set |= ROAR_LIBROAR_CONFIG_PSET_COMPLEXITY;
170  codec_cfg->complexity = _P_FP(value_str);
171 } else if ( !strcmp(option_str, "dtx") ) {
172  codec_cfg->para_set |= ROAR_LIBROAR_CONFIG_PSET_DTX;
173  codec_cfg->dtx = _P_BOOL(value_str);
174 } else if ( !strcmp(option_str, "cc-max") ) {
175  codec_cfg->para_set |= ROAR_LIBROAR_CONFIG_PSET_MAX_CC;
176  codec_cfg->max_cc = _P_INT(value_str);
177 } else if ( !strcmp(option_str, "vbr") ) {
178  codec_cfg->para_set |= ROAR_LIBROAR_CONFIG_PSET_VBR;
179  codec_cfg->vbr = _P_BOOL(value_str);
180 } else if ( !strcmp(option_str, "mode") ) {
181  if ( !strcmp(value_str, "nb") ) {
182   codec_cfg->para_set |= ROAR_LIBROAR_CONFIG_PSET_MODE;
183   codec_cfg->mode      = ROAR_LIBROAR_CONFIG_MODE_NB;
184  } else if ( !strcmp(value_str, "wb") ) {
185   codec_cfg->para_set |= ROAR_LIBROAR_CONFIG_PSET_MODE;
186   codec_cfg->mode      = ROAR_LIBROAR_CONFIG_MODE_WB;
187  } else if ( !strcmp(value_str, "uwb") ) {
188   codec_cfg->para_set |= ROAR_LIBROAR_CONFIG_PSET_MODE;
189   codec_cfg->mode      = ROAR_LIBROAR_CONFIG_MODE_UWB;
190  } else {
191   ROAR_WARN("roar_libroar_config_parse_codec(*): Unknown codec mode: %s", value_str);
192   return -1;
193  }
194 } else {
195  ROAR_WARN("roar_libroar_config_parse_codec(*): Unknown codec option: %s", option_str);
196  return -1;
197 }
198
199 return 0;
200}
201
202int    roar_libroar_config_parse(char * txt, char * delm) {
203 struct roar_libroar_config * config = roar_libroar_get_config_ptr();
204 ssize_t len;
205 char * k, * v, * next = txt;
206
207 while (next != NULL) {
208  k = next;
209
210  if ( delm == NULL ) {
211   // no delm -> we have only one option
212   next = NULL;
213  } else {
214   next = strstr(next, delm);
215  }
216
217  if ( next != NULL ) {
218   *next = 0;
219    next++;
220  }
221
222  ROAR_DBG("roar_libroar_config_parse(*): k='%s'", k);
223
224  // strip leading spaces:
225  while ( *k == ' ' ) k++;
226
227  ROAR_DBG("roar_libroar_config_parse(*): k='%s'", k);
228
229  // strip tailing new lions:
230  len = roar_mm_strlen(k);
231  if ( len != -1 )
232   for (len--; len && (k[len] == '\r' || k[len] == '\n'); len--)
233    k[len] = 0;
234
235  ROAR_DBG("roar_libroar_config_parse(*): k='%s'", k);
236
237  // comments
238  if ( *k == '#' )
239   continue;
240
241  ROAR_DBG("roar_libroar_config_parse(*): k='%s'", k);
242
243  // empty options:
244  if ( *k == 0 )
245   continue;
246
247  if ( (v = strstr(k, ":")) != NULL ) {
248   *v = 0;
249    v++;
250  }
251
252  ROAR_DBG("roar_libroar_config_parse(*): k='%s', v='%s'", k, v);
253
254  if ( !strcmp(k, "workaround") ) {
255   if ( !strcmp(v, "use-execed") ) {
256    config->workaround.workarounds |= ROAR_LIBROAR_CONFIG_WAS_USE_EXECED;
257   } else if ( !strcmp(v, "no-slp") ) {
258    config->workaround.workarounds |= ROAR_LIBROAR_CONFIG_WAS_NO_SLP;
259   } else {
260    ROAR_WARN("roar_libroar_config_parse(*): Unknown workaround option: %s", v);
261   }
262  } else if ( !strcmp(k, "warning") || !strcmp(k, "warn") ) {
263   if ( !strcmp(v, "sysio") ) {
264    config->warnings.sysio = ROAR_WARNING_ALWAYS;
265   } else if ( !strcmp(v, "obsolete") ) {
266    config->warnings.obsolete = ROAR_WARNING_ALWAYS;
267   } else if ( !strcmp(v, "all") ) {
268    config->warnings.sysio    = ROAR_WARNING_ALWAYS;
269    config->warnings.obsolete = ROAR_WARNING_ALWAYS;
270   } else {
271    ROAR_WARN("roar_libroar_config_parse(*): Unknown warning option: %s", v);
272   }
273  } else if ( !strcmp(k, "opmode") ) {
274   if ( !strcmp(v, "normal") ) {
275    config->opmode = ROAR_LIBROAR_CONFIG_OPMODE_NORMAL;
276   } else if ( !strcmp(v, "funny") ) {
277    config->opmode = ROAR_LIBROAR_CONFIG_OPMODE_FUNNY;
278   } else if ( !strcmp(v, "ms") ) {
279    config->opmode = ROAR_LIBROAR_CONFIG_OPMODE_MS;
280   } else {
281    ROAR_WARN("roar_libroar_config_parse(*): Unknown opmode: %s", v);
282   }
283#ifdef ROAR_SUPPORT_TRAP
284  } else if ( !strcmp(k, "trap-policy") ) {
285   if ( !strcmp(v, "ignore") ) {
286    config->trap_policy = ROAR_TRAP_IGNORE;
287   } else if ( !strcmp(v, "warn") ) {
288    config->trap_policy = ROAR_TRAP_WARN;
289   } else if ( !strcmp(v, "abort") ) {
290    config->trap_policy = ROAR_TRAP_ABORT;
291#ifdef SIGKILL
292   } else if ( !strcmp(v, "kill") ) {
293    config->trap_policy = ROAR_TRAP_KILL;
294#endif
295#ifdef SIGSTOP
296   } else if ( !strcmp(v, "stop") ) {
297    config->trap_policy = ROAR_TRAP_STOP;
298#endif
299   } else if ( !strcmp(v, "die") ) {
300    config->trap_policy = ROAR_TRAP_DIE;
301   } else {
302    ROAR_WARN("roar_libroar_config_parse(*): Unknown trap policy: %s", v);
303   }
304#endif
305  } else if ( !strcmp(k, "force-rate") ) {
306   config->info.rate = roar_str2rate(v);
307  } else if ( !strcmp(k, "force-bits") ) {
308   config->info.bits = roar_str2bits(v);
309  } else if ( !strcmp(k, "force-channels") ) {
310   config->info.channels = roar_str2channels(v);
311  } else if ( !strcmp(k, "force-codec") ) {
312   config->info.codec = roar_str2codec(v);
313  } else if ( !strcmp(k, "codec") ) {
314   if ( roar_libroar_config_parse_codec(config, v) == -1 ) {
315    ROAR_WARN("roar_libroar_config_parse(*): Error parsing codec config option");
316   }
317  } else if ( !strcmp(k, "set-server") ) {
318   if ( roar_libroar_get_server() == NULL )
319    roar_libroar_set_server(v);
320  } else if ( !strcmp(k, "set-authfile") ) {
321   strncpy(config->authfile, v, LEN_AUTHFILE-1);
322   config->authfile[LEN_AUTHFILE-1] = 0;
323  } else if ( !strcmp(k, "x11-display") ) {
324   if ( config->x11.display != NULL )
325    roar_mm_free(config->x11.display);
326   config->x11.display = roar_mm_strdup(v);
327  } else if ( !strcmp(k, "daemonimage") ) {
328   if ( config->daemonimage != NULL )
329    roar_mm_free(config->daemonimage);
330   config->daemonimage = roar_mm_strdup(v);
331  } else if ( !strcmp(k, "serverflags") ) {
332   if ( !strcmp(v, "nonblock") ) {
333    config->serverflags |= ROAR_ENUM_FLAG_NONBLOCK;
334   } else if ( !strcmp(v, "hardnonblock") ) {
335    config->serverflags |= ROAR_ENUM_FLAG_HARDNONBLOCK;
336   } else if ( !strcmp(v, "localonly") ) {
337    config->serverflags |= ROAR_ENUM_FLAG_LOCALONLY;
338   } else {
339    ROAR_WARN("roar_libroar_config_parse(*): Unknown serverflag: %s", v);
340   }
341  } else if ( !strcmp(k, "protocolversion") ) {
342   config->protocolversion = atoi(v);
343  } else {
344   ROAR_WARN("roar_libroar_config_parse(*): Unknown option: %s", k);
345  }
346 }
347
348 return 0;
349}
350
351struct roar_libroar_config_codec * roar_libroar_config_codec_get(int32_t codec, int create) {
352 struct roar_libroar_config * config = roar_libroar_get_config();
353 return roar_libroar_config_codec_get_conf(codec, create, config);
354}
355
356static struct roar_libroar_config_codec *
357           roar_libroar_config_codec_get_conf(int32_t codec, int create, struct roar_libroar_config * config) {
358 size_t i;
359 int need_new = 1;
360
361 ROAR_DBG("roar_libroar_config_codec_get_conf(codec=%i, create=%i, config=%p) = ?", codec, create, config);
362
363 if ( codec < 0 || create < 0 )
364  return NULL;
365
366 ROAR_DBG("roar_libroar_config_codec_get_conf(codec=%i, create=%i, config=%p) = ?", codec, create, config);
367
368 if ( config->codecs.num == 0 ) {
369  // no match case:
370  if ( !create )
371   return NULL;
372 } else {
373  for (i = 0; i < config->codecs.num; i++) {
374   if ( config->codecs.codec[i].codec == (uint32_t)codec )
375    return &(config->codecs.codec[i]);
376   if ( config->codecs.codec[i].codec == (uint32_t)-1 )
377    need_new = 0;
378  }
379 }
380
381 ROAR_DBG("roar_libroar_config_codec_get_conf(codec=%i, create=%i, config=%p) = ?", codec, create, config);
382
383 if ( !create )
384  return NULL;
385
386 if ( !need_new ) {
387  for (i = 0; i < config->codecs.num; i++) {
388   if ( config->codecs.codec[i].codec == (uint32_t)-1 ) {
389    memset(&(config->codecs.codec[i]), 0, sizeof(struct roar_libroar_config_codec));
390    config->codecs.codec[i].codec = codec;
391    return &(config->codecs.codec[i]);
392   }
393  }
394 }
395
396 if ( config->codecs.num == 0 ) {
397  config->codecs.codec = roar_mm_malloc(16*sizeof(struct roar_libroar_config_codec));
398 } else {
399  config->codecs.codec = roar_mm_realloc(config->codecs.codec, (config->codecs.num+16)*sizeof(struct roar_libroar_config_codec));
400 }
401
402 if ( config->codecs.codec == NULL )
403  return NULL;
404
405 memset(&(config->codecs.codec[config->codecs.num]), 0, 16);
406 for (i = config->codecs.num; i < (config->codecs.num+16); i++) {
407  config->codecs.codec[i].codec = (uint32_t)-1;
408 }
409
410 i = config->codecs.num;
411 config->codecs.num += 16;
412
413 memset(&(config->codecs.codec[i]), 0, sizeof(struct roar_libroar_config_codec));
414 config->codecs.codec[i].codec = codec;
415
416 return &(config->codecs.codec[i]);
417}
418
419int    roar_libroar_set_server(const char * server) {
420 roar_libroar_get_config_ptr()->server = server;
421 return 0;
422}
423
424const char * roar_libroar_get_server(void) {
425 return roar_libroar_get_config_ptr()->server;
426}
427
428int    roar_libroar_set_forkapi(const struct roar_libroar_forkapi * api) {
429 roar_libroar_get_config_ptr()->forkapi = api;
430 return 0;
431}
432
433int    roar_libroar_set_connect_internal(struct roar_vio_calls * (*func)(struct roar_connection * con, const char * server, int type, int flags, uint_least32_t timeout)) {
434 roar_libroar_get_config_ptr()->connect_internal = func;
435 return 0;
436}
437
438void   roar_libroar_nowarn(void) {
439 roar_libroar_get_config_ptr()->nowarncounter++;
440}
441
442void   roar_libroar_warn(void) {
443 struct roar_libroar_config * cfg = roar_libroar_get_config_ptr();
444
445 if ( cfg->nowarncounter == 0 ) {
446  ROAR_WARN("roar_libroar_warn(): Re-Enabling already enabled warnings! (Application error?)");
447  return;
448 }
449
450 cfg->nowarncounter--;
451}
452
453static const struct pathinfo {
454 const char * name;
455 const char * path;
456 const int    with_product; // 0 = no, 1 = yes, 2 = just product.
457 const int    with_provider;
458} __paths[] = {
459 // prefixes:
460 {"prefix",             ROAR_PREFIX, 0, 0},
461 {"prefix-bin",         ROAR_PREFIX_BIN, 0, 0},
462 {"prefix-sbin",        ROAR_PREFIX_SBIN, 0, 0},
463 {"prefix-lib",         ROAR_PREFIX_LIB, 0, 0},
464 {"prefix-inc",         ROAR_PREFIX_INC, 0, 0},
465 {"prefix-man",         ROAR_PREFIX_MAN, 0, 0},
466 {"prefix-man1",        ROAR_PREFIX_MAN "/man1", 0, 0},
467 {"prefix-man2",        ROAR_PREFIX_MAN "/man2", 0, 0},
468 {"prefix-man3",        ROAR_PREFIX_MAN "/man3", 0, 0},
469 {"prefix-man4",        ROAR_PREFIX_MAN "/man4", 0, 0},
470 {"prefix-man5",        ROAR_PREFIX_MAN "/man5", 0, 0},
471 {"prefix-man6",        ROAR_PREFIX_MAN "/man6", 0, 0},
472 {"prefix-man7",        ROAR_PREFIX_MAN "/man7", 0, 0},
473 {"prefix-man8",        ROAR_PREFIX_MAN "/man8", 0, 0},
474 {"prefix-man9",        ROAR_PREFIX_MAN "/man9", 0, 0},
475 {"prefix-pc",          ROAR_PREFIX_PC, 0, 0},
476 {"prefix-ckport",      ROAR_PREFIX_CKPORT, 0, 0},
477 {"prefix-sysconf",     ROAR_PREFIX_SYSCONF, 2, 0},
478 {"prefix-dev",         ROAR_PREFIX_DEV, 0, 0},
479 {"prefix-doc",         ROAR_PREFIX_DOC, 2, 0},
480 {"prefix-tmp",         ROAR_PREFIX_TMP, 0, 0},
481 {"prefix-var",         ROAR_PREFIX_VAR, 0, 0},
482 {"prefix-cache",       ROAR_PREFIX_CACHE, 2, 0},
483 {"prefix-data",        ROAR_PREFIX_DATA, 2, 0},
484 {"prefix-lock",        ROAR_PREFIX_LOCK, 0, 0},
485 {"prefix-log",         ROAR_PREFIX_LOG, 0, 0},
486 {"prefix-mail",        ROAR_PREFIX_MAIL, 0, 0},
487 {"prefix-run",         ROAR_PREFIX_RUN, 0, 0},
488 {"prefix-spool",       ROAR_PREFIX_SPOOL, 2, 0},
489 {"prefix-comp-libs",   ROAR_PREFIX_COMP_LIBS, 0, 0},
490 {"prefix-comp-bins",   ROAR_PREFIX_COMP_BINS, 0, 0},
491 {"prefix-plugins",     ROAR_PREFIX_PLUGINS, 1, 1},
492 {"prefix-buildsystem", ROAR_PREFIX_BUILDSYSTEM, 0, 0},
493
494 // bins:
495 {"bin-default-daemonimage", "roard", 0, 0},
496
497#ifdef ROAR_HAVE_BIN_SH
498 {"bin-sh",             ROAR_HAVE_BIN_SH, 0, 0},
499#endif
500#ifdef ROAR_HAVE_BIN_OGG123
501 {"bin-ogg123",         ROAR_HAVE_BIN_OGG123, 0, 0},
502#endif
503#ifdef ROAR_HAVE_BIN_FLAC
504 {"bin-flac",           ROAR_HAVE_BIN_FLAC, 0, 0},
505#endif
506#ifdef ROAR_HAVE_BIN_TIMIDITY
507 {"bin-timidity",       ROAR_HAVE_BIN_TIMIDITY, 0, 0},
508#endif
509#ifdef ROAR_HAVE_BIN_CDPARANOIA
510 {"bin-cdparanoia",     ROAR_HAVE_BIN_CDPARANOIA, 0, 0},
511#endif
512#ifdef ROAR_HAVE_BIN_GNUPLOT
513 {"bin-gnuplot",        ROAR_HAVE_BIN_GNUPLOT, 0, 0},
514#endif
515#ifdef ROAR_HAVE_BIN_SSH
516 {"bin-ssh",            ROAR_HAVE_BIN_SSH, 0, 0},
517#endif
518#ifdef ROAR_HAVE_BIN_PINENTRY
519 {"bin-pinentry",       ROAR_HAVE_BIN_PINENTRY, 0, 0},
520#endif
521#ifdef ROAR_HAVE_BIN_SSH_ASKPASS
522 {"bin-ssh-askpass",    ROAR_HAVE_BIN_SSH_ASKPASS, 0, 0},
523#endif
524#ifdef ROAR_HAVE_BIN_GTK_LED_ASKPASS
525 {"bin-gtk-led-askpass", ROAR_HAVE_BIN_GTK_LED_ASKPASS, 0, 0},
526#endif
527#ifdef ROAR_HAVE_BIN_X11_SSH_ASKPASS
528 {"bin-x11-ssh-askpass", ROAR_HAVE_BIN_X11_SSH_ASKPASS, 0, 0},
529#endif
530#ifdef ROAR_HAVE_BIN_GNOME_SSH_ASKPASS
531 {"bin-gnome-ssh-askpass", ROAR_HAVE_BIN_GNOME_SSH_ASKPASS, 0, 0},
532#endif
533#ifdef ROAR_HAVE_BIN_GPG
534 {"bin-gpg",            ROAR_HAVE_BIN_GPG, 0, 0},
535#endif
536#ifdef ROAR_HAVE_BIN_EJECT
537 {"bin-eject",          ROAR_HAVE_BIN_EJECT, 0, 0},
538#endif
539
540 // devices:
541 {"dev-stdin",                  ROAR_PREFIX_DEV "/stdin", 0, 0},
542 {"dev-default-pwmled",         ROAR_PREFIX_DEV "/ttyS0", 0, 0},
543 {"dev-default-dmx4linux",      ROAR_PREFIX_DEV "/dmx", 0, 0},
544
545#ifdef ROAR_DEFAULT_CDROM
546 {"dev-default-cdrom",          ROAR_DEFAULT_CDROM, 0, 0},
547#endif
548#ifdef ROAR_DEFAULT_TTY
549 {"dev-default-tty",            ROAR_DEFAULT_TTY, 0, 0},
550#endif
551#ifdef ROAR_DEFAULT_OSS_DEV
552 {"dev-default-oss-dev",        ROAR_DEFAULT_OSS_DEV, 0, 0},
553#endif
554#ifdef ROAR_DEFAULT_OSS_MIX_DEV
555 {"dev-default-oss-mix-dev",    ROAR_DEFAULT_OSS_MIX_DEV, 0, 0},
556#endif
557
558 // proc:
559#ifdef ROAR_PROC_NET_DECNET
560 {"proc-net-decnet",            ROAR_PROC_NET_DECNET, 0, 0},
561#endif
562#ifdef ROAR_PROC_NET_DECNET_NEIGH
563 {"proc-net-decnet-neigh",      ROAR_PROC_NET_DECNET_NEIGH, 0, 0},
564#endif
565#ifdef ROAR_PROC_NET_ARP
566 {"proc-net-arp",               ROAR_PROC_NET_ARP, 0, 0},
567#endif
568
569 // sysconf:
570 {"sysconf-hosts",              ROAR_PREFIX_SYSCONF "/hosts", 0, 0},
571 {"sysconf-roarserver",         ROAR_PREFIX_SYSCONF "/roarserver", 0, 0},
572
573 // special dirs:
574 {"dir-nx-home",                "/NX-HOME-DIR", 0, 0}
575};
576
577static int __product2path(char * path, size_t pathlen, int null_as_universal, const char * product, int type) {
578 const char * c;
579 const char * e;
580 const char * s;
581 const char * b;
582
583 if ( product != NULL && !strcmp(product, "universal") ) {
584  null_as_universal = 1;
585  product = NULL;
586 }
587
588 if ( product == NULL ) {
589  if ( null_as_universal ) {
590   if ( type == 2 ) {
591    snprintf(path, pathlen, "/universal");
592   } else {
593    snprintf(path, pathlen, "/universal/universal");
594   }
595  } else {
596   path[0] = 0;
597  }
598  return 0;
599 }
600
601 b = strstr(product, " ");
602 c = strstr(product, "<");
603 e = strstr(product, ">");
604
605 if ( b == NULL || c == NULL || e == NULL || c < b || e < c ) {
606  roar_err_set(ROAR_ERROR_ILLSEQ);
607  return -1;
608 }
609
610 c++;
611
612 s = strstr(c, "/");
613
614 if ( type == 2 ) {
615  snprintf(path, pathlen, "/%.*s", (int)(size_t)(b-product), product);
616 } else if ( s == NULL ) {
617  snprintf(path, pathlen, "/unreg-%.*s/%.*s", (int)(size_t)(e-c), c, (int)(size_t)(b-product), product);
618 } else {
619  snprintf(path, pathlen, "/%.*s-%.*s/%.*s", (int)(size_t)(s-c), c, (int)(size_t)(e-s-1), s+1, (int)(size_t)(b-product), product);
620 }
621
622 return 0;
623}
624
625static int __provider2path(char * path, size_t pathlen, const char * provider) {
626 const char * c;
627 const char * e;
628 const char * s;
629
630 if ( provider == NULL ) {
631  path[0] = 0;
632  return 0;
633 }
634
635 c = strstr(provider, "<");
636 e = strstr(provider, ">");
637
638 if ( c == NULL || e == NULL || e < c ) {
639  roar_err_set(ROAR_ERROR_ILLSEQ);
640  return -1;
641 }
642
643 c++;
644
645 s = strstr(c, "/");
646
647 if ( s == NULL ) {
648  snprintf(path, pathlen, "/unreg-%.*s", (int)(size_t)(e-c), c);
649 } else {
650  snprintf(path, pathlen, "/%.*s-%.*s", (int)(size_t)(s-c), c, (int)(size_t)(e-s-1), s+1);
651 }
652
653 return 0;
654
655 roar_err_set(ROAR_ERROR_NOTSUP);
656 return -1;
657}
658
659static const struct pathinfo * __lookup_path(const char * name) {
660 size_t i;
661
662 if ( name == NULL ) {
663  roar_err_set(ROAR_ERROR_FAULT);
664  return NULL;
665 }
666
667 for (i = 0; i < (sizeof(__paths)/sizeof(*__paths)); i++)
668  if ( !strcmp(__paths[i].name, name) )
669   return &(__paths[i]);
670
671 roar_err_set(ROAR_ERROR_NOENT);
672 return NULL;
673}
674
675void __strip_double_slashes(char * p) {
676 const char * in = p;
677
678 for (; *in; in++, p++) {
679  *p = *in;
680  if ( *in == '/' )
681   for (; in[1] == '/'; in++);
682 }
683
684 *p = 0;
685}
686
687char * roar_libroar_get_path(const char * name, int null_as_universal, const char * product, const char * provider) {
688 const struct pathinfo * path;
689 char buf_product[384];
690 char buf_provider[384];
691 ssize_t len_prefix, len_product, len_provider;
692 char * ret, * p;
693
694 ROAR_DBG("roar_libroar_get_path(name='%s', null_as_universal=%i, product='%s', provider='%s') = ?", name, null_as_universal, product, provider);
695
696 path = __lookup_path(name);
697 if ( path == NULL )
698  return NULL;
699
700 if ( ((null_as_universal || product != NULL) && !path->with_product) ||
701      (provider != NULL && !path->with_provider) ||
702      (!null_as_universal && product == NULL && provider != NULL) ) {
703  roar_err_set(ROAR_ERROR_INVAL);
704  return NULL;
705 }
706
707 if ( __product2path(buf_product, sizeof(buf_product), null_as_universal, product, path->with_product) == -1 )
708  return NULL;
709
710 if ( __provider2path(buf_provider, sizeof(buf_provider), provider) == -1 )
711  return NULL;
712
713 len_prefix = roar_mm_strlen(path->path);
714 len_product = roar_mm_strlen(buf_product);
715 len_provider = roar_mm_strlen(buf_provider);
716
717 p = ret = roar_mm_malloc(len_prefix+len_product+len_provider+1);
718 if ( ret == NULL )
719  return NULL;
720
721 memcpy(p, path->path, len_prefix);
722 p += len_prefix;
723 if ( p[-1] == '/' )
724  p--;
725 memcpy(p, buf_product, len_product);
726 p += len_product;
727 memcpy(p, buf_provider, len_provider);
728 p += len_provider;
729
730 *p = 0;
731
732 __strip_double_slashes(ret);
733
734 return ret;
735}
736
737const char * roar_libroar_get_path_static(const char * name) {
738 const struct pathinfo * path;
739
740 path = __lookup_path(name);
741 if ( path == NULL )
742  return NULL;
743
744 return path->path;
745}
746
747ssize_t roar_libroar_list_path(const char ** list, size_t len, size_t offset) {
748 size_t i;
749 ssize_t idx = 0;
750
751 ROAR_DBG("roar_libroar_list_path(list=%p, len=%lu, offset=%lu) = ?", list, (long unsigned int)len, (long unsigned int)offset);
752
753 if ( list == NULL ) {
754  roar_err_set(ROAR_ERROR_FAULT);
755  return -1;
756 }
757
758 if ( len == 0 )
759  return 0;
760
761 if ( offset >= (sizeof(__paths)/sizeof(*__paths)) )
762  return 0;
763
764 for (i = offset; idx < len && i < (sizeof(__paths)/sizeof(*__paths)); i++) {
765  list[idx++] = __paths[i].name;
766 }
767
768 return idx;
769}
770
771//ll
Note: See TracBrowser for help on using the repository browser.