]> git.sur5r.net Git - i3/i3status/blob - config.c
da1d387f589e02fc0bc5fa16162aa5a9aa474e41
[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 const char *wmii_path;
19 const char *time_format;
20 const char *battery_path;
21 bool use_colors;
22 const char *wmii_normcolors = "#222222 #333333";
23 char order[MAX_ORDER][2];
24 const char **run_watches;
25 unsigned int num_run_watches;
26 int interval = 1;
27
28 void die(const char *fmt, ...);
29
30 /*
31  * This function exists primarily for resolving ~ in pathnames. However, you
32  * can also specify ~/Movies/ *, which will only return the first match!
33  *
34  */
35 char *glob_path(const char *path) {
36         static glob_t globbuf;
37         if (glob(path, GLOB_NOCHECK | GLOB_TILDE, NULL, &globbuf) < 0)
38                 die("glob() failed");
39         char *result = strdup(globbuf.gl_pathc > 0 ? globbuf.gl_pathv[0] : path);
40         globfree(&globbuf);
41         return result;
42 }
43
44 /*
45  * Loads configuration from configfile
46  *
47  */
48 static void get_next_config_entry(FILE *handle, char **dest_name, char **dest_value, char *whole_buffer, int whole_buffer_size) {
49         char *ret;
50         if ((ret = fgets(whole_buffer, whole_buffer_size, handle)) == whole_buffer) {
51                 char *c = whole_buffer;
52                 /* Skip whitespaces in the beginning */
53                 while (isspace((int)*c) && *c != '\0')
54                         c++;
55                 *dest_name = c;
56                 while (!isspace((int)*c))
57                         c++;
58                 /* Terminate string as soon as whitespaces begin or it's terminated anyway */
59                 *(c++) = '\0';
60
61                 /* Same for the value: strip whitespaces */
62                 while (isspace((int)*c) && *c != '\0')
63                         c++;
64                 *dest_value = c;
65                 /* Whitespace is allowed, newline/carriage return is not */
66                 while ((*c != '\n') && (*c != '\r') && (*c != '\0'))
67                         c++;
68                 *c = 0;
69         } else if (ret != NULL)
70                 die("Could not read line in configuration file");
71 }
72
73 /*
74  * Reads the configuration from the given file
75  *
76  */
77 int load_configuration(const char *configfile) {
78         #define OPT(x) else if (strcasecmp(dest_name, x) == 0)
79
80         /* Check if the file exists */
81         struct stat buf;
82         if (stat(configfile, &buf) < 0)
83                 return -1;
84
85         int result = 0;
86         FILE *handle = fopen(configfile, "r");
87         if (handle == NULL)
88                 die("Could not open configfile");
89         char *dest_name = NULL, *dest_value = NULL, whole_buffer[1026];
90         struct stat stbuf;
91         while (!feof(handle)) {
92                 get_next_config_entry(handle, &dest_name, &dest_value, whole_buffer, 1024);
93                 /* No more entries? We're done! */
94                 if (dest_name == NULL)
95                         break;
96                 /* Skip comments and empty lines */
97                 if (dest_name[0] == '#' || strlen(dest_name) < 3)
98                         continue;
99
100                 OPT("wlan")
101                 {
102                         wlan_interface = strdup(dest_value);
103                 }
104                 OPT("eth")
105                 {
106                         eth_interface = strdup(dest_value);
107                 }
108                 OPT("wmii_path")
109                 {
110                         char *globbed = glob_path(dest_value);
111                         if ((stat(globbed, &stbuf)) == -1)
112                                 die("wmii_path contains an invalid path");
113                         if (globbed[strlen(globbed)-1] != '/')
114                                 die("wmii_path is not terminated by /");
115                         wmii_path = globbed;
116                 }
117                 OPT("time_format")
118                 {
119                         time_format = strdup(dest_value);
120                 }
121                 OPT("battery_path")
122                 {
123                         if ((stat(dest_value, &stbuf)) == -1)
124                                 die("battery_path contains an invalid path");
125                         battery_path = strdup(dest_value);
126                 }
127                 OPT("run_watch")
128                 {
129                         char *name = strdup(dest_value);
130                         char *path = name;
131                         while (*path != ' ')
132                                 path++;
133                         *(path++) = '\0';
134                         num_run_watches += 2;
135                         run_watches = realloc(run_watches, sizeof(char*) * num_run_watches);
136                         run_watches[num_run_watches-2] = name;
137                         run_watches[num_run_watches-1] = path;
138                 }
139                 OPT("order")
140                 {
141                         #define SET_ORDER(opt, idx) { if (strcasecmp(token, opt) == 0) sprintf(order[idx], "%d", c++); }
142                         char *walk, *token;
143                         int c = 0;
144                         walk = token = dest_value;
145                         while (*walk != '\0') {
146                                 while ((*walk != ',') && (*walk != '\0'))
147                                         walk++;
148                                 *(walk++) = '\0';
149                                 SET_ORDER("run", ORDER_RUN);
150                                 SET_ORDER("wlan", ORDER_WLAN);
151                                 SET_ORDER("eth", ORDER_ETH);
152                                 SET_ORDER("battery", ORDER_BATTERY);
153                                 SET_ORDER("load", ORDER_LOAD);
154                                 SET_ORDER("time", ORDER_TIME);
155                                 token = walk;
156                                 while (isspace((int)(*token)))
157                                         token++;
158                         }
159                 }
160                 OPT("color")
161                 {
162                         use_colors = true;
163                 }
164                 OPT("normcolors")
165                 {
166                         wmii_normcolors = strdup(dest_value);
167                 }
168                 OPT("interval")
169                 {
170                         interval = atoi(dest_value);
171                 }
172                 else
173                 {
174                         result = -2;
175                         die("Unknown configfile option: %s\n", dest_name);
176                 }
177                 dest_name = dest_value = NULL;
178         }
179         fclose(handle);
180
181         if (wmii_path == NULL)
182                 exit(-4);
183
184         return result;
185 }