Use computed offset instead of hand-built array for access to struct swb_config members
[browser-switch] / config-ui / browser-switchboard-config.c
1 /*
2  * browser-switchboard-config.c -- command-line configuration utility for
3  * Browser Switchboard
4  *
5  * Copyright (C) 2009-2010 Steven Luo
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20  * USA.
21  */
22
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <getopt.h>
29
30 #include "config.h"
31 #include "save-config.h"
32 #include "browsers.h"
33
34 extern struct swb_config_option swb_config_options[];
35
36 static int get_config_value(char *name) {
37         struct swb_config cfg;
38         struct swb_config_option *optinfo;
39         void *entry;
40         int retval = 1;
41
42         swb_config_init(&cfg);
43
44         if (!swb_config_load(&cfg))
45                 return 1;
46
47         for (optinfo = swb_config_options; optinfo->name; ++optinfo) {
48                 if (strcmp(name, optinfo->name))
49                         continue;
50
51                 entry = (char *)&cfg + optinfo->offset;
52                 switch (optinfo->type) {
53                   case SWB_CONFIG_OPT_STRING:
54                         if (*(char **)entry)
55                                 printf("%s\n", *(char **)entry);
56                         break;
57                   case SWB_CONFIG_OPT_INT:
58                         printf("%d\n", *(int *)entry);
59                         break;
60                   default:
61                         break;
62                 }
63                 retval = 0;
64                 break;
65         }
66
67         swb_config_free(&cfg);
68
69         return retval;
70 }
71
72 static int get_default_browser(void) {
73         struct swb_config cfg;
74         int i;
75
76         swb_config_init(&cfg);
77
78         if (!swb_config_load(&cfg))
79                 return 1;
80
81         /* Check to see if the configured default browser is installed
82            If not, report the default default browser */
83         for (i = 0; browsers[i].config; ++i) {
84                 if (strcmp(browsers[i].config, cfg.default_browser))
85                         continue;
86
87                 if (browsers[i].binary && access(browsers[i].binary, X_OK))
88                         printf("%s\n", browsers[0].config);
89                 else
90                         printf("%s\n", browsers[i].config);
91
92                 break;
93         }
94
95         if (!browsers[i].config)
96                 /* Unknown browser configured as default, report the default
97                    default browser */
98                 printf("%s\n", browsers[0].config);
99
100         swb_config_free(&cfg);
101
102         return 0;
103 }
104
105 static int set_config_value(char *name, char *value) {
106         struct swb_config orig_cfg, cfg;
107         struct swb_config_option *optinfo;
108         void *entry;
109         int retval = 1;
110
111         swb_config_init(&orig_cfg);
112
113         if (!swb_config_load(&orig_cfg))
114                 return 1;
115
116         cfg = orig_cfg;
117
118         for (optinfo = swb_config_options; optinfo->name; ++optinfo) {
119                 if (strcmp(name, optinfo->name))
120                         continue;
121
122                 entry = (char *)&cfg + optinfo->offset;
123                 switch (optinfo->type) {
124                   case SWB_CONFIG_OPT_STRING:
125                         if (strlen(value) == 0) {
126                                 /* If the new value is empty, clear the config
127                                    setting */
128                                 *(char **)entry = NULL;
129                                 cfg.flags &= ~optinfo->set_mask;
130                         } else {
131                                 /* Make a copy of the string -- it's not safe
132                                    to free value, which comes from argv */
133                                 if (!(*(char **)entry =
134                                       strdup(value)))
135                                         exit(1);
136                                 cfg.flags |= optinfo->set_mask;
137                         }
138                         break;
139                   case SWB_CONFIG_OPT_INT:
140                         if (strlen(value) == 0) {
141                                 /* If the new value is empty, clear the config
142                                    setting */
143                                 cfg.flags &= ~optinfo->set_mask;
144                         } else {
145                                 *(int *)entry = atoi(value);
146                                 cfg.flags |= optinfo->set_mask;
147                         }
148                         break;
149                 }
150                 retval = 0;
151                 break;
152         }
153
154         if (!retval)
155                 if (!swb_config_save(&cfg))
156                         retval = 1;
157
158         /* Reconfigure a running browser-switchboard, if present */
159         swb_reconfig(&orig_cfg, &cfg);
160
161         swb_config_free(&orig_cfg);
162         /* XXX can't free all of cfg, it contains pointers to memory we just
163            freed above
164         swb_config_free(&cfg); */
165         if (optinfo->name && optinfo->type == SWB_CONFIG_OPT_STRING)
166                 free(*(char **)entry);
167
168         return retval;
169 }
170
171 void usage(void) {
172         printf("Usage:\n");
173         printf("  browser-switchboard-config -b -- Display default browser\n");
174         printf("  browser-switchboard-config -c -- Display command used when default browser is \"other\"\n");
175         printf("  browser-switchboard-config -m -- Display continuous mode setting\n");
176         printf("  browser-switchboard-config -o option -- Display value of option\n");
177         printf("\n");
178         printf("  browser-switchboard-config -s [-b|-c|-m|-o option] value -- Set the selected option to value\n");
179         printf("\n");
180         printf("  browser-switchboard-config -h -- Show this message\n");
181 }
182
183 int main(int argc, char **argv) {
184         int opt, done = 0;
185         int set = 0;
186         char *selected_opt = NULL;
187
188         while (!done && (opt = getopt(argc, argv, "hsbcmo:")) != -1) {
189                 switch (opt) {
190                   case 'h':
191                         usage();
192                         exit(0);
193                         break;
194                   case 's':
195                         set = 1;
196                         break;
197                   case 'b':
198                         selected_opt = "default_browser";
199                         done = 1;
200                         break;
201                   case 'c':
202                         selected_opt = "other_browser_cmd";
203                         done = 1;
204                         break;
205                   case 'm':
206                         selected_opt = "continuous_mode";
207                         done = 1;
208                         break;
209                   case 'o':
210                         selected_opt = optarg;
211                         done = 1;
212                         break;
213                   default:
214                         usage();
215                         exit(1);
216                         break;
217                 }
218         }
219
220         if (!selected_opt) {
221                 printf("Must specify one of -b, -c, -m, -o\n");
222                 usage();
223                 exit(1);
224         }
225
226         if (set) {
227                 if (optind >= argc) {
228                         printf("Value to set config option to not provided\n");
229                         usage();
230                         exit(1);
231                 }
232                 return set_config_value(selected_opt, argv[optind]);
233         } else if (!strcmp(selected_opt, "default_browser"))
234                 /* Default browser value needs special handling */
235                 return get_default_browser();
236         else
237                 return get_config_value(selected_opt);
238 }