80f40db35fc44c98a92dfad3693d74459f024637
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <errno.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
11 #include <glib.h>
12 #include <ncurses.h>
14 #include "config.h"
15 #include "options.h"
16 #include "support.h"
17 #include "command.h"
18 #include "conf.h"
20 #ifdef DEBUG
21 #define D(x) x
22 #else
23 #define D(x)
24 #endif
26 #define RCFILE "." PACKAGE "rc"
28 #define MAX_LINE_LENGTH 1024
29 #define COMMENT_TOKEN '#'
31 /* configuration field names */
32 #define CONF_ENABLE_COLORS "enable_colors"
33 #define CONF_AUTO_CENTER "auto_center"
35 /* configuration field names - colors */
36 #define CONF_COLOR_BACKGROUND "background_color"
37 #define CONF_COLOR_TITLE "title_color"
38 #define CONF_COLOR_LINE "line_color"
39 #define CONF_COLOR_LIST "list_color"
40 #define CONF_COLOR_PROGRESS "progress_color"
41 #define CONF_COLOR_STATUS "status_color"
42 #define CONF_COLOR_ALERT "alert_color"
43 #define CONF_KEY_DEFINITION "key"
45 typedef enum {
46 KEY_PARSER_UNKNOWN,
47 KEY_PARSER_CHAR,
48 KEY_PARSER_DEC,
49 KEY_PARSER_HEX,
50 KEY_PARSER_DONE
51 } key_parser_state_t;
53 static int
54 str2bool(char *str)
55 {
56 if( !strcasecmp(str,"no") || !strcasecmp(str,"false") ||
57 !strcasecmp(str,"off") || !strcasecmp(str,"0") )
58 return 0;
59 return 1;
60 }
62 static int
63 str2color(char *str)
64 {
65 if( !strcasecmp(str,"black") )
66 return COLOR_BLACK;
67 else if( !strcasecmp(str,"red") )
68 return COLOR_RED;
69 else if( !strcasecmp(str,"green") )
70 return COLOR_GREEN;
71 else if( !strcasecmp(str,"yellow") )
72 return COLOR_YELLOW;
73 else if( !strcasecmp(str,"blue") )
74 return COLOR_BLUE;
75 else if( !strcasecmp(str,"magenta") )
76 return COLOR_MAGENTA;
77 else if( !strcasecmp(str,"cyan") )
78 return COLOR_CYAN;
79 else if( !strcasecmp(str,"white") )
80 return COLOR_WHITE;
81 fprintf(stderr,"Warning: unknown color %s\n", str);
82 return -1;
83 }
85 static int
86 parse_key_value(char *str, size_t len, char **end)
87 {
88 int i, value;
89 key_parser_state_t state;
91 i=0;
92 value=0;
93 state=KEY_PARSER_UNKNOWN;
94 *end = str;
96 while( i<len && state!=KEY_PARSER_DONE )
97 {
98 int next = 0;
99 int c = str[i];
101 if( i+1<len )
102 next = str[i+1];
104 switch(state)
105 {
106 case KEY_PARSER_UNKNOWN:
107 if( c=='\'' )
108 state = KEY_PARSER_CHAR;
109 else if( c=='0' && next=='x' )
110 state = KEY_PARSER_HEX;
111 else if( isdigit(c) )
112 state = KEY_PARSER_DEC;
113 else {
114 fprintf(stderr, "Error: Unsupported key definition - %s\n", str);
115 return -1;
116 }
117 break;
118 case KEY_PARSER_CHAR:
119 if( next!='\'' )
120 {
121 fprintf(stderr, "Error: Unsupported key definition - %s\n", str);
122 return -1;
123 }
124 value = c;
125 *end = str+i+2;
126 state = KEY_PARSER_DONE;
127 break;
128 case KEY_PARSER_DEC:
129 value = (int) strtol(str+(i-1), end, 10);
130 state = KEY_PARSER_DONE;
131 break;
132 case KEY_PARSER_HEX:
133 if( !isdigit(next) )
134 {
135 fprintf(stderr, "Error: Digit expexted after 0x - %s\n", str);
136 return -1;
137 }
138 value = (int) strtol(str+(i+1), end, 16);
139 state = KEY_PARSER_DONE;
140 break;
141 case KEY_PARSER_DONE:
142 break;
143 }
144 i++;
145 }
147 if( *end> str+len )
148 *end = str+len;
150 return value;
151 }
153 static int
154 parse_key_definition(char *str)
155 {
156 char buf[MAX_LINE_LENGTH];
157 char *p, *end;
158 size_t len = strlen(str);
159 int i,j,key;
160 int keys[MAX_COMMAND_KEYS];
161 command_t cmd;
163 /* get the command name */
164 i=0;
165 j=0;
166 memset(buf, 0, MAX_LINE_LENGTH);
167 while( i<len && str[i]!='=' && !IS_WHITESPACE(str[i]) )
168 buf[j++] = str[i++];
169 if( (cmd=get_key_command_from_name(buf)) == CMD_NONE )
170 {
171 fprintf(stderr, "Error: Unknown key command %s\n", buf);
172 return -1;
173 }
175 /* skip whitespace */
176 while( i<len && (str[i]=='=' || IS_WHITESPACE(str[i])) )
177 i++;
179 /* get the value part */
180 memset(buf, 0, MAX_LINE_LENGTH);
181 strncpy(buf, str+i, len-i);
182 len = strlen(buf);
183 if( len==0 )
184 {
185 fprintf(stderr,"Error: Incomplete key definition - %s\n", str);
186 return -1;
187 }
189 /* parse key values */
190 i = 0;
191 key = 0;
192 len = strlen(buf);
193 p = buf;
194 end = buf+len;
195 memset(keys, 0, sizeof(int)*MAX_COMMAND_KEYS);
196 while( i<MAX_COMMAND_KEYS && p<end && (key=parse_key_value(p,len+1,&p))>=0 )
197 {
198 keys[i++] = key;
199 while( p<end && (*p==',' || *p==' ' || *p=='\t') )
200 p++;
201 len = strlen(p);
202 }
203 if( key<0 )
204 {
205 fprintf(stderr,"Error: Bad key definition - %s\n", str);
206 return -1;
207 }
209 return assign_keys(cmd, keys);
210 }
212 static int
213 read_rc_file(char *filename, options_t *options)
214 {
215 int fd;
216 int quit = 0;
217 int color = -1;
218 int free_filename = 0;
220 if( filename==NULL )
221 return -1;
223 D(printf("Reading configuration file %s\n", filename));
224 if( (fd=open(filename,O_RDONLY)) <0 )
225 {
226 D(perror(filename));
227 if( free_filename )
228 g_free(filename);
229 return -1;
230 }
232 while( !quit )
233 {
234 int i,j;
235 int len;
236 int match_found;
237 char line[MAX_LINE_LENGTH];
238 char name[MAX_LINE_LENGTH];
239 char value[MAX_LINE_LENGTH];
241 line[0] = '\0';
242 value[0] = '\0';
244 i = 0;
245 /* read a line ending with '\n' */
246 do {
247 len = read( fd, &line[i], 1 );
248 if( len == 1 )
249 i++;
250 else
251 quit = 1;
252 } while( !quit && i<MAX_LINE_LENGTH && line[i-1]!='\n' );
255 /* remove trailing whitespace */
256 line[i] = '\0';
257 i--;
258 while( i>=0 && IS_WHITESPACE(line[i]) )
259 {
260 line[i] = '\0';
261 i--;
262 }
263 len = i+1;
265 if( len>0 )
266 {
267 i = 0;
268 /* skip whitespace */
269 while( i<len && IS_WHITESPACE(line[i]) )
270 i++;
272 /* continue if this line is not a comment */
273 if( line[i] != COMMENT_TOKEN )
274 {
275 /* get the name part */
276 j=0;
277 while( i<len && line[i]!='=' && !IS_WHITESPACE(line[i]) )
278 {
279 name[j++] = line[i++];
280 }
281 name[j] = '\0';
283 /* skip '=' and whitespace */
284 while( i<len && (line[i]=='=' || IS_WHITESPACE(line[i])) )
285 i++;
287 /* get the value part */
288 j=0;
289 while( i<len )
290 {
291 value[j++] = line[i++];
292 }
293 value[j] = '\0';
295 match_found = 0;
297 if( !strcasecmp(CONF_KEY_DEFINITION, name) )
298 {
299 parse_key_definition(value);
300 match_found = 1;
301 }
302 /* enable colors */
303 else if( !strcasecmp(CONF_ENABLE_COLORS, name) )
304 {
305 options->enable_colors = str2bool(value);
306 match_found = 1;
307 }
308 /* auto center */
309 else if( !strcasecmp(CONF_AUTO_CENTER, name) )
310 {
311 options->auto_center = str2bool(value);
312 match_found = 1;
313 }
314 /* background color */
315 else if( !strcasecmp(CONF_COLOR_BACKGROUND, name) )
316 {
317 if( (color=str2color(value)) >= 0 )
318 options->bg_color = color;
319 match_found = 1;
320 }
321 /* color - top (title) window */
322 else if( !strcasecmp(CONF_COLOR_TITLE, name) )
323 {
324 if( (color=str2color(value)) >= 0 )
325 options->title_color = color;
326 match_found = 1;
327 }
328 /* color - line (title) window */
329 else if( !strcasecmp(CONF_COLOR_LINE, name) )
330 {
331 if( (color=str2color(value)) >= 0 )
332 options->line_color = color;
333 match_found = 1;
334 }
335 /* color - list window */
336 else if( !strcasecmp(CONF_COLOR_LIST, name) )
337 {
338 if( (color=str2color(value)) >= 0 )
339 options->list_color = color;
340 match_found = 1;
341 }
342 /* color - progress bar */
343 else if( !strcasecmp(CONF_COLOR_PROGRESS, name) )
344 {
345 if( (color=str2color(value)) >= 0 )
346 options->progress_color = color;
347 match_found = 1;
348 }
349 /* color - status window */
350 else if( !strcasecmp(CONF_COLOR_STATUS, name) )
351 {
352 if( (color=str2color(value)) >= 0 )
353 options->status_color = color;
354 match_found = 1;
355 }
356 /* color - alerts */
357 else if( !strcasecmp(CONF_COLOR_ALERT, name) )
358 {
359 if( (color=str2color(value)) >= 0 )
360 options->alert_color = color;
361 match_found = 1;
362 }
365 if( !match_found )
366 fprintf(stderr,
367 "Unknown configuration parameter: %s\n",
368 name);
369 #ifdef DEBUG
370 printf( " %s = %s %s\n",
371 name,
372 value,
373 match_found ? "" : "- UNKNOWN SETTING!" );
374 #endif
376 }
377 }
378 }
380 D(printf( "--\n\n" ));
382 if( free_filename )
383 g_free(filename);
385 return 0;
386 }
389 int
390 read_configuration(options_t *options)
391 {
392 char *filename = NULL;
394 /* check for user configuration ~/.ncmpc/config */
395 filename = g_build_filename(g_get_home_dir(), "." PACKAGE, "config", NULL);
396 if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) )
397 {
398 g_free(filename);
399 filename = NULL;
400 }
402 /* check for global configuration SYSCONFDIR/ncmpc/config */
403 if( filename == NULL )
404 {
405 filename = g_build_filename(SYSCONFDIR, PACKAGE, "config", NULL);
406 if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) )
407 {
408 g_free(filename);
409 filename = NULL;
410 }
411 }
413 /* load configuration */
414 if( filename )
415 {
416 read_rc_file(filename, options);
417 g_free(filename);
418 filename = NULL;
419 }
421 /* check for user key bindings ~/.ncmpc/keys */
422 filename = g_build_filename(g_get_home_dir(), "." PACKAGE, "keys", NULL);
423 if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) )
424 {
425 g_free(filename);
426 filename = NULL;
427 }
429 /* check for global key bindings SYSCONFDIR/ncmpc/keys */
430 if( filename == NULL )
431 {
432 filename = g_build_filename(SYSCONFDIR, PACKAGE, "keys", NULL);
433 if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) )
434 {
435 g_free(filename);
436 filename = NULL;
437 }
438 }
440 /* load key bindings */
441 if( filename )
442 {
443 read_rc_file(filename, options);
444 g_free(filename);
445 filename = NULL;
446 //write_key_bindings(stderr);
447 }
449 return 0;
450 }