Avoid structure copies when looping through swb_config_options
[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 <stddef.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <getopt.h>
29
30 #include "config.h"
31
32 extern struct swb_config_option swb_config_options[];
33
34 static int get_config_value(char *name) {
35         struct swb_config cfg;
36         struct swb_config_option *optinfo;
37         ptrdiff_t i;
38         int retval = 1;
39
40         swb_config_init(&cfg);
41
42         if (!swb_config_load(&cfg))
43                 return 1;
44
45         for (optinfo = swb_config_options; optinfo->name; ++optinfo) {
46                 if (strcmp(name, optinfo->name))
47                         continue;
48
49                 i = optinfo - swb_config_options;
50                 switch (optinfo->type) {
51                   case SWB_CONFIG_OPT_STRING:
52                         printf("%s\n", *(char **)cfg.entries[i]);
53                         break;
54                   case SWB_CONFIG_OPT_INT:
55                         printf("%d\n", *(int *)cfg.entries[i]);
56                         break;
57                   default:
58                         break;
59                 }
60                 retval = 0;
61                 break;
62         }
63
64         swb_config_free(&cfg);
65
66         return retval;
67 }
68
69 static int set_config_value(char *name, char *value) {
70         struct swb_config cfg;
71         struct swb_config_option *optinfo;
72         ptrdiff_t i;
73         int retval = 1;
74
75         swb_config_init(&cfg);
76
77         if (!swb_config_load(&cfg))
78                 return 1;
79
80         for (optinfo = swb_config_options; optinfo->name; ++optinfo) {
81                 if (strcmp(name, optinfo->name))
82                         continue;
83
84                 i = optinfo - swb_config_options;
85                 switch (optinfo->type) {
86                   case SWB_CONFIG_OPT_STRING:
87                         /* Free any existing string */
88                         if (cfg.flags & optinfo->set_mask)
89                                 free(*(char **)cfg.entries[i]);
90
91                         if (strlen(value) == 0) {
92                                 /* If the new value is empty, clear the config
93                                    setting */
94                                 *(char **)cfg.entries[i] = NULL;
95                                 cfg.flags &= ~optinfo->set_mask;
96                         } else {
97                                 /* Make a copy of the string -- it's not safe
98                                    to free value, which comes from argv */
99                                 if (!(*(char **)cfg.entries[i] =
100                                       strdup(value)))
101                                         exit(1);
102                                 cfg.flags |= optinfo->set_mask;
103                         }
104                         break;
105                   case SWB_CONFIG_OPT_INT:
106                         if (strlen(value) == 0) {
107                                 /* If the new value is empty, clear the config
108                                    setting */
109                                 cfg.flags &= ~optinfo->set_mask;
110                         } else {
111                                 *(int *)cfg.entries[i] = atoi(value);
112                                 cfg.flags |= optinfo->set_mask;
113                         }
114                         break;
115                 }
116                 retval = 0;
117                 break;
118         }
119
120         if (!retval)
121                 if (!swb_config_save(&cfg))
122                         retval = 1;
123
124         swb_config_free(&cfg);
125
126         /* Try to send SIGHUP to any running browser-switchboard process
127            This causes it to reread config files if in continuous_mode, or
128            die so that the config will be reloaded on next start otherwise */
129         system("kill -HUP `pidof browser-switchboard` > /dev/null 2>&1");
130
131         return retval;
132 }
133
134 void usage(void) {
135         printf("Usage:\n");
136         printf("  browser-switchboard-config -b -- Display default browser\n");
137         printf("  browser-switchboard-config -c -- Display command used when default browser is \"other\"\n");
138         printf("  browser-switchboard-config -m -- Display continuous mode setting\n");
139         printf("  browser-switchboard-config -o option -- Display value of option\n");
140         printf("\n");
141         printf("  browser-switchboard-config -s [-b|-c|-m|-o option] value -- Set the selected option to value\n");
142         printf("\n");
143         printf("  browser-switchboard-config -h -- Show this message\n");
144 }
145
146 int main(int argc, char **argv) {
147         int opt, done = 0;
148         int set = 0;
149         char *selected_opt = NULL;
150         
151         while (!done && (opt = getopt(argc, argv, "hsbcmo:")) != -1) {
152                 switch (opt) {
153                   case 'h':
154                         usage();
155                         exit(0);
156                         break;
157                   case 's':
158                         set = 1;
159                         break;
160                   case 'b':
161                         selected_opt = "default_browser";
162                         done = 1;
163                         break;
164                   case 'c':
165                         selected_opt = "other_browser_cmd";
166                         done = 1;
167                         break;
168                   case 'm':
169                         selected_opt = "continuous_mode";
170                         done = 1;
171                         break;
172                   case 'o':
173                         selected_opt = optarg;
174                         done = 1;
175                         break;
176                   default:
177                         usage();
178                         exit(1);
179                         break;
180                 }
181         }
182
183         if (!selected_opt) {
184                 printf("Must specify one of -b, -c, -m, -o\n");
185                 usage();
186                 exit(1);
187         }
188
189         if (set) {
190                 if (optind >= argc) {
191                         printf("Value to set config option to not provided\n");
192                         usage();
193                         exit(1);
194                 }
195                 return set_config_value(selected_opt, argv[optind]);
196         } else
197                 return get_config_value(selected_opt);
198 }