LIRC libraries
LinuxInfraredRemoteControl
lirc_options.c
Go to the documentation of this file.
1 /****************************************************************************
2 ** lirc_options.c **********************************************************
3 ****************************************************************************
4 *
5 * options.c - global options access.
6 *
7 */
8 
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
17 
18 #include <getopt.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #if defined(__linux__)
22 #include <linux/types.h>
23 #endif
24 
25 #include "ciniparser.h"
26 #include "lirc_options.h"
27 #include "lirc_log.h"
28 
29 static const logchannel_t logchannel = LOG_LIB;
30 
31 dictionary* lirc_options = NULL;
32 
33 /* Environment variable which if set enables some debug output. */
34 static const char* const LIRC_DEBUG_OPTIONS = "LIRC_DEBUG_OPTIONS";
35 
36 static int depth = 0;
37 
38 static int options_debug = -1;
39 
40 loglevel_t options_set_loglevel(const char* optarg)
41 {
42  char s[4];
43  loglevel_t level;
44 
45  level = string2loglevel(optarg);
46  if (level == LIRC_BADLEVEL)
47  return level;
48  snprintf(s, sizeof(s), "%d", level);
49  options_set_opt("lircd:debug", s);
50  return level;
51 }
52 
53 
54 void options_set_opt(const char* key, const char* value)
55 {
56  if (dictionary_set(lirc_options, key, value) != 0)
57  log_warn("Cannot set option %s to %s\n", key, value);
58 }
59 
60 
61 const char* options_getstring(const char* const key)
62 {
63  return ciniparser_getstring(lirc_options, key, 0);
64 }
65 
66 
67 int options_getint(const char* const key)
68 {
69  return ciniparser_getint(lirc_options, key, 0);
70 }
71 
72 
73 int options_getboolean(const char* const key)
74 {
75  return ciniparser_getboolean(lirc_options, key, 0);
76 }
77 
78 
79 static char* parse_O_arg(int argc, char** argv)
80 {
81  char* path = NULL;
82  int i;
83  const int opt_len = strlen("--options_file");
84 
85  for (i = 0; i < argc; i += 1) {
86  if (strncmp(argv[i], "-O", 2) != 0 &&
87  strncmp(argv[i], "--options-file", opt_len) != 0)
88  continue;
89  if (strchr(argv[i], '=') != NULL) {
90  path = strchr(argv[i], '=') + 1;
91  } else if (strncmp(argv[i], "-O", 2) == 0 &&
92  strlen(argv[i]) > 2
93  ) {
94  path = argv[i] + 2;
95  } else if (i + 1 < argc) {
96  path = argv[i + 1];
97  } else {
98  return NULL;
99  }
100  if (path && access(path, R_OK) != 0) {
101  fprintf(stderr, "Cannot open options file %s for read\n",
102  path);
103  return NULL;
104  }
105  return path;
106  }
107  return NULL;
108 }
109 
110 
111 void options_load(int argc, char** const argv,
112  const char* path_arg,
113  void (*parse_options)(int, char** const))
114 {
115  char buff[128];
116  char buff2[128];
117  const char* path = path_arg;
118 
119  if (depth > 1) {
120  log_warn("Error:Cowardly refusing to process"
121  " options-file option within a file\n");
122  return;
123  }
124  depth += 1;
125  setenv("POSIXLY_CORRECT", "1", 1);
126  if (path == NULL)
127  path = parse_O_arg(argc, argv);
128  if (path == NULL) {
129  path = getenv(LIRC_OPTIONS_VAR);
130  path = (path == NULL ? LIRC_OPTIONS_PATH : path);
131  }
132  if (*path != '/') {
133  if (getcwd(buff2, sizeof(buff2)) == NULL)
134  log_perror_warn("options_load: getcwd():");
135  snprintf(buff, sizeof(buff), "%s/%s", buff2, path);
136  path = buff;
137  }
138  if (access(path, R_OK) == 0) {
139  lirc_options = ciniparser_load(path);
140  if (lirc_options == NULL) {
141  log_warn("Cannot load options file %s\n", path);
142  lirc_options = dictionary_new(0);
143  }
144  } else {
145  fprintf(stderr, "Warning: cannot open %s\n", path);
146  log_warn("Cannot open %s\n", path);
147  lirc_options = dictionary_new(0);
148  }
149  if (parse_options != NULL)
150  parse_options(argc, argv);
151  if (options_debug == -1)
152  options_debug = getenv(LIRC_DEBUG_OPTIONS) != NULL;
153  if (options_debug && lirc_options != NULL) {
154  fprintf(stderr, "Dumping parsed option values:\n");
155  ciniparser_dump(lirc_options, stderr);
156  }
157 }
158 
159 
161 {
162  const char* s;
163  loglevel_t level = LIRC_BADLEVEL;
164  char buff[64];
165 
166  s = getenv("LIRC_LOGLEVEL");
167  level = string2loglevel(s);
168  if (level != LIRC_BADLEVEL)
169  return level;
170  if (lirc_options == NULL)
171  options_load(0, NULL, NULL, NULL);
172  if (level == LIRC_BADLEVEL && app != NULL) {
173  snprintf(buff, sizeof(buff), "%s:debug", app);
174  s = ciniparser_getstring(lirc_options, buff, NULL);
175  level = string2loglevel(s);
176  }
177  if (level == LIRC_BADLEVEL) {
178  s = ciniparser_getstring(lirc_options, "lircd:debug", "debug");
179  level = string2loglevel(s);
180  if (level == LIRC_BADLEVEL)
181  level = LIRC_DEBUG;
182  }
183  return level;
184 }
185 
186 
187 void options_add_defaults(const char* const defaults[])
188 {
189  int i;
190  const char* key;
191  const char* value;
192 
193  for (i = 0; defaults[i] != NULL; i += 2) {
194  key = defaults[i];
195  value = defaults[i + 1];
196  if (ciniparser_getstring(lirc_options, key, NULL) == NULL)
197  options_set_opt((char*)key, (char*)value);
198  }
199 }
200 
201 void options_unload(void)
202 {
203  depth = 0;
204  options_debug = -1;
205  if (lirc_options != NULL) {
206  dictionary_del(lirc_options);
207  lirc_options = NULL;
208  }
209 }
const char * ciniparser_getstring(dictionary *d, const char *key, char *def)
Get the string associated to a key.
Definition: ciniparser.c:286
int dictionary_set(dictionary *d, const char *key, const char *val)
Set a value in a dictionary.
Definition: dictionary.c:147
dictionary * ciniparser_load(const char *ininame)
Parse an ini file and return an allocated dictionary object.
Definition: ciniparser.c:368
Logging functionality.
int ciniparser_getint(dictionary *d, const char *key, int notfound)
Get the string associated to a key, convert to an int.
Definition: ciniparser.c:300
Options management: options file, parse and retrieve.
#define log_warn(fmt,...)
Log a warning message.
Definition: lirc_log.h:109
loglevel_t options_set_loglevel(const char *optarg)
Parse and store a loglevel, returning value (possibly LIRC_BADLEVEL).
Definition: lirc_options.c:40
dictionary * dictionary_new(int size)
Create a new dictionary object.
Definition: dictionary.c:92
logchannel_t
Log channels used to filter messages.
Definition: lirc_log.h:53
loglevel_t
The defined loglevels.
Definition: lirc_log.h:36
void dictionary_del(dictionary *d)
Delete a dictionary object.
Definition: dictionary.c:109
#define LIRC_OPTIONS_VAR
Environment variable overriding options file path.
Definition: lirc_config.h:72
loglevel_t options_get_app_loglevel(const char *app)
Return loglevel based on (falling priority)
Definition: lirc_options.c:160
#define LIRC_OPTIONS_PATH
Default options file path.
Definition: lirc_config.h:69
void ciniparser_dump(dictionary *d, FILE *f)
Dump a dictionary to an opened file pointer.
Definition: ciniparser.c:227
Dictionary object.
Definition: dictionary.h:67
#define log_perror_warn(fmt,...)
perror wrapper logging with level LIRC_WARNING.
Definition: lirc_log.h:94
Parser for ini files.
int ciniparser_getboolean(dictionary *d, const char *key, int notfound)
Get the string associated to a key, convert to a boolean.
Definition: ciniparser.c:324
loglevel_t string2loglevel(const char *s)
Convert a string, either a number or 'info', 'trace1', error etc.
Definition: lirc_log.c:234