source: roaraudio/libroar/config.c @ 6076:b81c397aee90

Last change on this file since 6076:b81c397aee90 was 6052:d48765b2475e, checked in by phi, 9 years ago

updated copyright headers

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