]> git.sur5r.net Git - i3/i3status/blob - config.c
Simplify config file parsing *a lot*
[i3/i3status] / config.c
1 #include <stdio.h>
2 #include <ctype.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <stdbool.h>
6 #include <sys/stat.h>
7 #include <sys/types.h>
8 #include <fcntl.h>
9 #include <glob.h>
10 #include <unistd.h>
11
12 #define _IS_CONFIG_C
13 #include "config.h"
14 #undef _IS_CONFIG_C
15
16 const char *wlan_interface;
17 const char *eth_interface;
18 char *wmii_path;
19 const char *time_format;
20 const char *battery_path;
21 bool use_colors;
22 bool get_ethspeed;
23 const char *wmii_normcolors = "#222222 #333333";
24 char order[MAX_ORDER][2];
25 const char **run_watches;
26 unsigned int num_run_watches;
27 unsigned int interval = 1;
28
29 void die(const char *fmt, ...);
30
31 /*
32  * Reads the configuration from the given file
33  *
34  */
35 int load_configuration(const char *configfile) {
36         #define OPT(x) else if (strcasecmp(dest_name, x) == 0)
37
38         /* check if the file exists */
39         struct stat buf;
40         if (stat(configfile, &buf) < 0)
41                 return -1;
42
43         int result = 0;
44         FILE *handle = fopen(configfile, "r");
45         if (handle == NULL)
46                 die("Could not open configfile");
47         char dest_name[512], dest_value[512], whole_buffer[1026];
48         struct stat stbuf;
49         while (!feof(handle)) {
50                 char *ret;
51                 if ((ret = fgets(whole_buffer, 1024, handle)) == whole_buffer) {
52                         /* sscanf implicitly strips whitespace */
53                         if (sscanf(whole_buffer, "%s %[^\n]", dest_name, dest_value) < 1)
54                                 continue;
55                 } else if (ret != NULL)
56                         die("Could not read line in configuration file");
57
58                 /* skip comments and empty lines */
59                 if (dest_name[0] == '#' || strlen(dest_name) < 3)
60                         continue;
61
62                 OPT("wlan")
63                         wlan_interface = strdup(dest_value);
64                 OPT("eth")
65                         eth_interface = strdup(dest_value);
66                 OPT("time_format")
67                         time_format = strdup(dest_value);
68                 OPT("battery_path")
69                         battery_path = strdup(dest_value);
70                 OPT("color")
71                         use_colors = true;
72                 OPT("get_ethspeed")
73                         get_ethspeed = true;
74                 OPT("normcolors")
75                         wmii_normcolors = strdup(dest_value);
76                 OPT("interval")
77                         interval = atoi(dest_value);
78                 OPT("wmii_path")
79                 {
80                         static glob_t globbuf;
81                         if (glob(dest_value, GLOB_NOCHECK | GLOB_TILDE, NULL, &globbuf) < 0)
82                                 die("glob() failed");
83                         wmii_path = strdup(globbuf.gl_pathc > 0 ? globbuf.gl_pathv[0] : dest_value);
84                         globfree(&globbuf);
85
86                         if ((stat(wmii_path, &stbuf)) == -1) {
87                                 fprintf(stderr, "Warning: wmii_path contains an invalid path\n");
88                                 free(wmii_path);
89                                 wmii_path = strdup(dest_value);
90                         }
91                         if (wmii_path[strlen(wmii_path)-1] != '/')
92                                 die("wmii_path is not terminated by /");
93                 }
94                 OPT("run_watch")
95                 {
96                         char *name = strdup(dest_value);
97                         char *path = name;
98                         while (*path != ' ')
99                                 path++;
100                         *(path++) = '\0';
101                         num_run_watches += 2;
102                         run_watches = realloc(run_watches, sizeof(char*) * num_run_watches);
103                         run_watches[num_run_watches-2] = name;
104                         run_watches[num_run_watches-1] = path;
105                 }
106                 OPT("order")
107                 {
108                         #define SET_ORDER(opt, idx) { if (strcasecmp(token, opt) == 0) sprintf(order[idx], "%d", c++); }
109                         char *walk, *token;
110                         int c = 0;
111                         walk = token = dest_value;
112                         while (*walk != '\0') {
113                                 while ((*walk != ',') && (*walk != '\0'))
114                                         walk++;
115                                 *(walk++) = '\0';
116                                 SET_ORDER("run", ORDER_RUN);
117                                 SET_ORDER("wlan", ORDER_WLAN);
118                                 SET_ORDER("eth", ORDER_ETH);
119                                 SET_ORDER("battery", ORDER_BATTERY);
120                                 SET_ORDER("load", ORDER_LOAD);
121                                 SET_ORDER("time", ORDER_TIME);
122                                 token = walk;
123                                 while (isspace((int)(*token)))
124                                         token++;
125                         }
126                 }
127                 else
128                 {
129                         result = -2;
130                         die("Unknown configfile option: %s\n", dest_name);
131                 }
132         }
133         fclose(handle);
134
135         if (wmii_path == NULL)
136                 exit(EXIT_FAILURE);
137
138         return result;
139 }