Fix missing `break'.
[doldaconnect.git] / config / dolconf.c
CommitLineData
eb54b70d 1/*
2 * Dolda Connect - Modular multiuser Direct Connect-style client
714e16fb 3 * Copyright (C) 2007 Fredrik Tolf <fredrik@dolda2000.com>
eb54b70d 4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
19
20#include <stdlib.h>
21#include <stdio.h>
22#include <unistd.h>
23#include <string.h>
24#include <ctype.h>
25#include <signal.h>
26#include <errno.h>
27#include <gtk/gtk.h>
28#include <locale.h>
29#include <libintl.h>
30#include <pwd.h>
31#include <stdarg.h>
48b166ff 32#include <arpa/inet.h>
eb54b70d 33
34#ifdef HAVE_CONFIG_H
35#include <config.h>
36#endif
37#include <utils.h>
38
39struct validation {
40 int (*check)(const char *val);
41 char *invmsg;
42};
43
44struct cfvar {
45 char *name;
46 char *rname;
47 char *val;
48 struct validation *vld;
0fbd8398 49 GtkWidget **astw, **cfww;
eb54b70d 50};
51
52char *cfname;
53GtkWindow *rootwnd = NULL;
54GtkListStore *shares;
0fbd8398 55int state;
56int ignoreclose = 0;
57
58void astcancel(GtkWidget *widget, gpointer uudata);
59void astupdate(GtkWidget *widget, GtkWidget *page, gpointer uudata);
60void cb_ast_wnd_apply(GtkWidget *widget, gpointer uudata);
61void cb_ast_nick_changed(GtkWidget *widget, gpointer uudata);
62void cb_ast_shareadd_clicked(GtkWidget *widget, gpointer uudata);
63void cb_ast_sharerem_clicked(GtkWidget *widget, gpointer uudata);
64void cb_ast_checkports(GtkWidget *widget, gpointer uudata);
65void cb_ast_mode_nat_toggled(GtkWidget *widget, gpointer uudata);
66void cb_cfw_mode_act_toggled(GtkWidget *widget, gpointer uudata);
67void cb_cfw_orport_toggled(GtkWidget *widget, gpointer uudata);
68void cb_cfw_oraddr_toggled(GtkWidget *widget, gpointer uudata);
69void cb_cfw_uinet_toggled(GtkWidget *widget, gpointer uudata);
70void cb_cfw_save_clicked(GtkWidget *widget, gpointer uudata);
71void cb_cfw_quit_clicked(GtkWidget *widget, gpointer uudata);
72void cb_cfw_shareadd_clicked(GtkWidget *widget, gpointer uudata);
73void cb_cfw_sharerem_clicked(GtkWidget *widget, gpointer uudata);
74
75#define _(text) gettext(text)
76
77#include "dolconf-assistant.gtk"
78#include "dolconf-wnd.gtk"
eb54b70d 79
80int v_nonempty(const char *val)
81{
82 return(strlen(val) > 0);
83}
84
85int v_dcstring(const char *val)
86{
87 return((strchr(val, ' ') == NULL) &&
88 (strchr(val, '|') == NULL) &&
89 (strchr(val, '$') == NULL));
90}
91
48b166ff 92int v_natural(const char *val)
eb54b70d 93{
48b166ff 94 if(!*val)
95 return(0);
96 for(; *val; val++) {
97 if(!isdigit(*val))
eb54b70d 98 return(0);
99 }
100 return(1);
101}
102
48b166ff 103int v_integer(const char *val)
104{
105 int f, d;
106
107 for(f = 1, d = 0; *val; val++, f = 0) {
108 if(isdigit(*val)) {
109 d = 1;
110 } else if(f && (*val == '-')) {
111 } else {
112 return(0);
113 }
114 }
115 return(d);
116}
117
118int v_ipv4(const char *val)
119{
120 struct in_addr buf;
121
122 return(inet_aton(val, &buf) != 0);
123}
124
0fbd8398 125#undef _
eb54b70d 126#define _(text) text
127
128struct validation nonempty = {
129 .check = v_nonempty,
130 .invmsg = _("%s must not be empty"),
131};
132
133struct validation dcstring = {
134 .check = v_dcstring,
135 .invmsg = _("%s must not contain spaces, `|' or `$'"),
136};
137
48b166ff 138struct validation natural = {
139 .check = v_natural,
140 .invmsg = _("%s must be a natural number"),
141};
142
143struct validation integer = {
144 .check = v_integer,
145 .invmsg = _("%s must be an integer"),
146};
147
148struct validation ipv4 = {
149 .check = v_ipv4,
150 .invmsg = _("%s must be an IP address"),
eb54b70d 151};
152
153struct validation *vldxlate[] = {
48b166ff 154 &nonempty, &dcstring, &natural, &integer, &ipv4,
eb54b70d 155 NULL
156};
157
158struct cfvar config[] = {
0fbd8398 159 {"cli.defnick", _("Screen name"), "", &dcstring, &ast_nick, &cfw_nick},
48b166ff 160 {"net.mode", NULL, "0", &natural},
0fbd8398 161 {"net.visibleipv4", "IP address", "0.0.0.0", &ipv4, NULL, &cfw_extip},
48b166ff 162 {"ui.onlylocal", NULL, "0", &natural},
163 {"ui.port", NULL, "-1", &integer},
164 {"auth.authless", NULL, "0", &natural},
165 {"transfer.slots", _("Upload slots"), "6", &natural},
0fbd8398 166 {"dc.speedstring", _("Connection speed"), "DSL", &dcstring, NULL, &cfw_cntype},
167 {"dc.email", _("E-mail address"), "spam@spam.net", &dcstring, NULL, &cfw_mail},
168 {"dc.desc", _("Share description"), "", NULL, &ast_desc, &cfw_desc},
169 {"dc.tcpport", _("Direct Connect TCP port"), "0", &natural, NULL, &cfw_tcpport},
170 {"dc.udpport", _("Direct Connect UDP port"), "0", &natural, NULL, &cfw_udpport},
eb54b70d 171 {NULL}
172};
173
174#undef _
175#define _(text) gettext(text)
176
eb54b70d 177struct cfvar *findcfvar(char *name)
178{
179 struct cfvar *v;
180
181 for(v = config; v->name != NULL; v++) {
182 if(!strcmp(v->name, name))
183 return(v);
184 }
185 return(NULL);
186}
187
188void setcfvar(char *name, const char *val)
189{
190 struct cfvar *v;
191
192 v = findcfvar(name);
193 free(v->val);
194 v->val = sstrdup(val);
195}
196
197int msgbox(int type, int buttons, char *format, ...)
198{
199 GtkWidget *swnd;
200 va_list args;
201 char *buf;
202 int resp;
203
204 va_start(args, format);
205 buf = vsprintf2(format, args);
206 va_end(args);
207 swnd = gtk_message_dialog_new(rootwnd, GTK_DIALOG_MODAL, type, buttons, "%s", buf);
208 gtk_window_set_title(GTK_WINDOW(swnd), _("Dolda Connect configurator"));
209 resp = gtk_dialog_run(GTK_DIALOG(swnd));
210 gtk_widget_destroy(swnd);
211 free(buf);
212 return(resp);
213}
214
215void prepstatic(void)
216{
217 struct validation **v;
218 struct cfvar *c;
219
220 for(v = vldxlate; *v != NULL; v++)
221 (*v)->invmsg = gettext((*v)->invmsg);
222 for(c = config; c->name != NULL; c++) {
223 if(c->rname != NULL)
224 c->rname = gettext(c->rname);
225 c->val = sstrdup(c->val);
226 }
227}
228
229char *getword(char **p)
230{
231 char *buf, *p2, delim;
232 size_t len;
233
234 if(**p == '\"')
235 delim = '\"';
236 else
237 delim = ' ';
238 p2 = *p;
239 while((p2 = strchr(p2 + 1, delim)) != NULL) {
240 if(p2[-1] != '\\')
241 break;
242 }
243 if(p2 == NULL)
244 p2 = *p + strlen(*p);
0fbd8398 245 len = p2 - *p - ((*p2 == '\"')?1:0);
eb54b70d 246 buf = smalloc(len + 1);
247 memcpy(buf, *p, len);
248 buf[len] = 0;
249 *p = p2 + ((*p2 == '\"')?1:0);
250 for(p2 = buf; *p2; p2++, len--) {
251 if(*p2 == '\\')
252 memmove(p2, p2 + 1, len--);
253 }
254 return(buf);
255}
256
257char *quoteword(char *word)
258{
259 char *wp, *buf, *bp;
260 int dq, numbs, numc;
261
262 dq = 0;
263 numbs = 0;
264 numc = 0;
265 if(*word == '\0')
266 {
267 dq = 1;
268 } else {
269 for(wp = word; *wp != '\0'; wp++)
270 {
271 if(!dq && isspace(*wp))
272 dq = 1;
273 if((*wp == '\\') || (*wp == '\"'))
274 numbs++;
275 numc++;
276 }
277 }
278 if(!dq && !numbs)
279 return(NULL);
280 bp = buf = smalloc(sizeof(wchar_t) * (numc + numbs + (dq?2:0) + 1));
281 if(dq)
282 *(bp++) = '\"';
283 for(wp = word; *wp != '\0'; wp++)
284 {
285 if((*wp == '\\') || (*wp == '\"'))
286 *(bp++) = '\\';
287 *(bp++) = *wp;
288 }
289 if(dq)
290 *(bp++) = '\"';
291 *(bp++) = '\0';
292 return(buf);
293}
294
295int readconfig(void)
296{
297 int rv;
298 FILE *cf;
299 char lbuf[1024];
300 char *key, *val, *p;
301 size_t len;
302 struct cfvar *var;
303 GtkTreeIter iter;
304
305 rv = 0;
306 if((cf = fopen(cfname, "r")) == NULL) {
307 msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Could not open the configuration file for reading: %s"), strerror(errno));
308 return(-1);
309 }
310 key = val = NULL;
311 while(fgets(lbuf, sizeof(lbuf), cf) != NULL) {
312 len = strlen(lbuf);
313 if(lbuf[len - 1] == '\n')
314 lbuf[len - 1] = 0;
315 if(key != NULL) {
316 free(key);
317 key = NULL;
318 }
319 if(val != NULL) {
320 free(val);
321 val = NULL;
322 }
323 if(!strncmp(lbuf, "set ", 4)) {
324 p = lbuf + 4;
325 if(((key = getword(&p)) == NULL) || (*(p++) != ' ') || ((val = getword(&p)) == NULL)) {
326 rv = 1;
327 continue;
328 }
329 for(var = config; var->name != NULL; var++) {
330 if(!strcmp(var->name, key)) {
331 free(var->val);
332 var->val = sstrdup(val);
333 break;
334 }
335 }
336 if(var->name == NULL)
337 rv = 1;
338 } else if(!strncmp(lbuf, "share ", 6)) {
339 p = lbuf + 6;
340 if(((key = getword(&p)) == NULL) || (*(p++) != ' ') || ((val = getword(&p)) == NULL)) {
341 rv = 1;
342 continue;
343 }
344 gtk_list_store_append(shares, &iter);
345 gtk_list_store_set(shares, &iter, 0, key, 1, val, -1);
346 } else if(!lbuf[0] || lbuf[0] == '#') {
347 } else {
348 rv = 1;
349 }
350 }
351 if(key != NULL)
352 free(key);
353 if(val != NULL)
354 free(val);
355 fclose(cf);
356 return(rv);
357}
358
359void writeconfig(void)
360{
361 FILE *cf;
362 struct cfvar *var;
363 GtkTreeIter iter;
364 char *buf, *buf2;
365
366 if((cf = fopen(cfname, "w")) == NULL) {
367 msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Could not open the configuration file for writing: %s"), strerror(errno));
368 return;
369 }
370 fputs("# This file was generated by dolconf v" VERSION "\n\n", cf);
371 for(var = config; var->name != NULL; var++) {
372 fprintf(cf, "set %s ", var->name);
373 if((buf = quoteword(var->val)) == NULL) {
374 fputs(var->val, cf);
375 } else {
376 fputs(buf, cf);
377 free(buf);
378 }
379 fputc('\n', cf);
380 }
381 if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(shares), &iter)) {
382 fputc('\n', cf);
383 do {
384 fputs("share ", cf);
385 gtk_tree_model_get(GTK_TREE_MODEL(shares), &iter, 0, &buf2, -1);
386 if((buf = quoteword(buf2)) == NULL) {
387 fputs(buf2, cf);
388 } else {
389 fputs(buf, cf);
390 free(buf);
391 }
392 g_free(buf2);
393 fputc(' ', cf);
394 gtk_tree_model_get(GTK_TREE_MODEL(shares), &iter, 1, &buf2, -1);
395 if((buf = quoteword(buf2)) == NULL) {
396 fputs(buf2, cf);
397 } else {
398 fputs(buf, cf);
399 free(buf);
400 }
401 g_free(buf2);
402 fputc('\n', cf);
403 } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(shares), &iter));
404 }
405 fclose(cf);
406}
407
0fbd8398 408void fillcfw(void)
eb54b70d 409{
0fbd8398 410 struct cfvar *var;
411
412 for(var = config; var->name != NULL; var++) {
413 if(var->cfww != NULL)
414 gtk_entry_set_text(GTK_ENTRY(*(var->cfww)), var->val);
415 }
416 if(atoi(findcfvar("dc.tcpport")->val) || atoi(findcfvar("dc.udpport")->val))
417 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_orport), TRUE);
418 else
419 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_orport), FALSE);
420 if(strcmp(findcfvar("net.visibleipv4")->val, "0.0.0.0"))
421 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_oraddr), TRUE);
422 else
423 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_oraddr), FALSE);
424 if(strcmp(findcfvar("ui.port")->val, "-1")) {
425 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_uinet), TRUE);
426 if(strcmp(findcfvar("auth.authless")->val, "1"))
427 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_authless), FALSE);
428 else
429 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_authless), TRUE);
430 } else {
431 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_uinet), FALSE);
432 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_authless), FALSE);
433 }
eb54b70d 434}
435
0fbd8398 436void ast2conf(void)
eb54b70d 437{
eb54b70d 438 setcfvar("cli.defnick", gtk_entry_get_text(GTK_ENTRY(ast_nick)));
439 setcfvar("dc.desc", gtk_entry_get_text(GTK_ENTRY(ast_desc)));
48b166ff 440 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ast_mode_psv))) {
441 setcfvar("net.mode", "1");
442 } else {
443 setcfvar("net.mode", "0");
444 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ast_mode_nat))) {
445 setcfvar("net.visibleipv4", gtk_entry_get_text(GTK_ENTRY(ast_extip)));
446 setcfvar("dc.tcpport", gtk_entry_get_text(GTK_ENTRY(ast_udpport)));
447 setcfvar("dc.udpport", gtk_entry_get_text(GTK_ENTRY(ast_tcpport)));
448 } else {
449 setcfvar("net.visibleipv4", "0.0.0.0");
450 setcfvar("dc.tcpport", "0");
451 setcfvar("dc.udpport", "0");
452 }
453 }
0fbd8398 454}
455
456void cfw2conf(void)
457{
458 struct cfvar *var;
459
460 for(var = config; var->name != NULL; var++) {
461 if(var->cfww != NULL) {
462 free(var->val);
463 var->val = sstrdup(gtk_entry_get_text(GTK_ENTRY(*(var->cfww))));
464 }
465 }
466 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cfw_mode_act))) {
467 setcfvar("net.mode", "0");
468 if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cfw_orport))) {
469 setcfvar("dc.tcpport", "0");
470 setcfvar("dc.udpport", "0");
471 }
472 if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cfw_oraddr))) {
473 setcfvar("net.visibleipv4", "0.0.0.0");
474 }
475 } else {
476 setcfvar("net.mode", "1");
477 }
478 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cfw_uinet))) {
479 setcfvar("ui.port", "1500");
480 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cfw_authless)))
481 setcfvar("auth.authless", "1");
482 else
483 setcfvar("auth.authless", "0");
484 } else {
485 setcfvar("ui.port", "-1");
486 setcfvar("auth.authless", "0");
487 }
488}
489
490void astcancel(GtkWidget *widget, gpointer uudata)
491{
492 if(ignoreclose)
493 return;
494 gtk_main_quit();
495 state = -1;
496}
497
498#define bufcats(buf, str) bufcat(buf, str, strlen(str))
499
500void astupdate(GtkWidget *widget, GtkWidget *page, gpointer uudata)
501{
502 char *s, *buf;
503 size_t sdata, ssize;
504 struct cfvar *var;
505 GtkTreeIter iter;
506
507 ast2conf();
eb54b70d 508 s = NULL;
509 sdata = ssize = 0;
510 for(var = config; var->name != NULL; var++) {
511 if(var->rname == NULL)
512 continue;
513 bufcats(s, var->rname);
514 bufcats(s, ": ");
515 bufcat(s, var->val, strlen(var->val));
516 addtobuf(s, '\n');
517 }
518 if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(shares), &iter)) {
519 addtobuf(s, '\n');
520 bufcats(s, _("Shares:\n"));
521 do {
522 addtobuf(s, '\t');
523 gtk_tree_model_get(GTK_TREE_MODEL(shares), &iter, 1, &buf, -1);
524 bufcats(s, buf);
525 g_free(buf);
526 addtobuf(s, '\n');
527 } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(shares), &iter));
528 }
529 gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(ast_summary)), s, sdata);
530 free(s);
531}
532
533void cb_ast_wnd_apply(GtkWidget *widget, gpointer uudata)
534{
535 writeconfig();
536 gtk_main_quit();
0fbd8398 537 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ast_action_dolcon)))
538 state = 2;
539 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ast_action_exit)))
540 state = -1;
541 else
542 state = 0;
543 ignoreclose = 1;
eb54b70d 544}
545
546void cb_ast_nick_changed(GtkWidget *widget, gpointer uudata)
547{
548 if(v_dcstring(gtk_entry_get_text(GTK_ENTRY(ast_nick))))
549 gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page1, TRUE);
550 else
551 gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page1, FALSE);
552}
553
554int hasshare(int col, char *name)
555{
556 GtkTreeIter iter;
557 char *buf;
558
559 if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(shares), &iter)) {
560 do {
561 gtk_tree_model_get(GTK_TREE_MODEL(shares), &iter, col, &buf, -1);
562 if(!strcmp(buf, name)) {
563 g_free(buf);
564 return(1);
565 }
566 g_free(buf);
567 } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(shares), &iter));
568 }
569 return(0);
570}
571
0fbd8398 572int shareadd(void)
eb54b70d 573{
0fbd8398 574 int i, ret;
eb54b70d 575 GSList *fns, *next;
576 char *fn, *sn, *p;
577 GtkTreeIter iter;
578 GtkWidget *chd;
579 int resp;
580
581 chd = gtk_file_chooser_dialog_new(_("Shared directories"), rootwnd, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
582 gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(chd), TRUE);
583 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(chd), TRUE);
584 resp = gtk_dialog_run(GTK_DIALOG(chd));
585 if(resp != GTK_RESPONSE_ACCEPT) {
586 gtk_widget_destroy(chd);
0fbd8398 587 return(0);
eb54b70d 588 }
0fbd8398 589 ret = 0;
eb54b70d 590 fns = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(chd));
591 gtk_widget_destroy(chd);
592 while(fns != NULL) {
593 fn = fns->data;
594 if(!hasshare(1, fn)) {
595 if((p = strrchr(fn, '/')) == NULL)
596 p = fn;
597 else
598 p++;
599 sn = sstrdup(p);
600 if(hasshare(0, sn)) {
601 for(i = 2; 1; i++) {
602 free(sn);
603 sn = sprintf2("%s%i", p, i);
604 if(!hasshare(0, sn))
605 break;
606 }
607 }
608 gtk_list_store_append(shares, &iter);
609 gtk_list_store_set(shares, &iter, 0, sn, 1, fn, -1);
610 free(sn);
0fbd8398 611 ret = 1;
eb54b70d 612 }
613 g_free(fn);
614 next = fns->next;
615 g_slist_free_1(fns);
616 fns = next;
617 }
0fbd8398 618 return(ret);
619}
620
621void cb_ast_shareadd_clicked(GtkWidget *widget, gpointer uudata)
622{
623 if(shareadd())
624 gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page2, TRUE);
625}
626
627void cb_cfw_shareadd_clicked(GtkWidget *widget, gpointer uudata)
628{
629 shareadd();
eb54b70d 630}
631
632void cb_ast_sharerem_clicked(GtkWidget *widget, gpointer uudata)
633{
634 GtkTreeIter iter;
635
636 if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(ast_sharelist)), NULL, &iter))
637 gtk_list_store_remove(shares, &iter);
638 if(gtk_tree_model_iter_n_children(GTK_TREE_MODEL(shares), NULL) == 0)
639 gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page2, FALSE);
640}
641
0fbd8398 642void cb_cfw_sharerem_clicked(GtkWidget *widget, gpointer uudata)
643{
644 GtkTreeIter iter;
645
646 if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(cfw_sharelist)), NULL, &iter))
647 gtk_list_store_remove(shares, &iter);
648}
649
48b166ff 650void cb_ast_checkports(GtkWidget *widget, gpointer uudata)
651{
652 gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page3,
653 v_natural(gtk_entry_get_text(GTK_ENTRY(ast_tcpport))) &&
0fbd8398 654 (atoi(gtk_entry_get_text(GTK_ENTRY(ast_tcpport))) >= 1024) &&
48b166ff 655 v_natural(gtk_entry_get_text(GTK_ENTRY(ast_udpport))) &&
0fbd8398 656 (atoi(gtk_entry_get_text(GTK_ENTRY(ast_udpport))) >= 1024) &&
48b166ff 657 v_ipv4(gtk_entry_get_text(GTK_ENTRY(ast_extip))));
658}
659
660void cb_ast_mode_nat_toggled(GtkWidget *widget, gpointer uudata)
661{
662 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
663 gtk_widget_set_sensitive(GTK_WIDGET(ast_portbox), TRUE);
664 cb_ast_checkports(widget, NULL);
665 } else {
666 gtk_widget_set_sensitive(GTK_WIDGET(ast_portbox), FALSE);
667 gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page3, TRUE);
668 }
669}
670
0fbd8398 671void cb_cfw_mode_act_toggled(GtkWidget *widget, gpointer uudata)
672{
673 gtk_widget_set_sensitive(GTK_WIDGET(cfw_natbox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
674}
675
676void cb_cfw_orport_toggled(GtkWidget *widget, gpointer uudata)
677{
678 gtk_widget_set_sensitive(GTK_WIDGET(cfw_portbox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
679}
680
681void cb_cfw_oraddr_toggled(GtkWidget *widget, gpointer uudata)
682{
683 gtk_widget_set_sensitive(GTK_WIDGET(cfw_addrbox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
684}
685
686void cb_cfw_uinet_toggled(GtkWidget *widget, gpointer uudata)
687{
688 gtk_widget_set_sensitive(GTK_WIDGET(cfw_uibox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
689}
690
691void cb_cfw_save_clicked(GtkWidget *widget, gpointer uudata)
692{
693 struct cfvar *cv;
694
695 for(cv = config; cv->name != NULL; cv++) {
696 if((cv->vld != NULL) && !cv->vld->check(cv->val)) {
697 if(cv->rname) {
698 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, cv->vld->invmsg, cv->rname);
699 } else {
700 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Internal error (Auto-generated variable %s has an invalid value \"%s\")"), cv->name, cv->val);
701 }
702 return;
703 }
704 }
705 cfw2conf();
706 writeconfig();
707}
708
709void cb_cfw_quit_clicked(GtkWidget *widget, gpointer uudata)
710{
711 gtk_main_quit();
712 state = -1;
713}
714
eb54b70d 715int main(int argc, char **argv)
716{
714e16fb 717 int i, c, ex;
eb54b70d 718 struct passwd *pwd;
719
720 setlocale(LC_ALL, "");
721 bindtextdomain(PACKAGE, LOCALEDIR);
722 textdomain(PACKAGE);
723 prepstatic();
724
725 gtk_init(&argc, &argv);
714e16fb 726 state = -1;
727 while((c = getopt(argc, argv, "haw")) != -1) {
728 switch(c) {
729 case 'a':
730 state = 1;
731 break;
732 case 'w':
733 state = 0;
ee20b80b 734 break;
714e16fb 735 case 'h':
736 default:
737 fprintf((c == 'h')?stdout:stderr, "usage: dolconf [-haw]\n");
cab1ec0e 738 exit((c == 'h')?0:1);
714e16fb 739 }
740 }
741
eb54b70d 742 create_ast_wnd();
0fbd8398 743 create_cfw_wnd();
eb54b70d 744 shares = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
745 gtk_tree_view_set_model(GTK_TREE_VIEW(ast_sharelist), GTK_TREE_MODEL(shares));
0fbd8398 746 gtk_tree_view_set_model(GTK_TREE_VIEW(cfw_sharelist), GTK_TREE_MODEL(shares));
eb54b70d 747
748 cfname = NULL;
749 if(getenv("HOME") != NULL) {
750 cfname = sprintf2("%s/.doldacond.conf", getenv("HOME"));
751 } else {
752 if((pwd = getpwuid(getuid())) != NULL)
753 cfname = sprintf2("%s/.doldacond.conf", pwd->pw_dir);
754 }
755 if(cfname == NULL) {
756 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not get your home directory!"));
757 exit(1);
758 }
759
714e16fb 760 ex = !access(cfname, F_OK);
761 if(!ex && (state == -1)) {
762 if(msgbox(GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("It appears that you have not run this setup program before. Would you like to run the first-time setup assistant?")) == GTK_RESPONSE_YES)
0fbd8398 763 state = 1;
714e16fb 764 else
0fbd8398 765 state = 0;
714e16fb 766 }
767
768 if(ex && (state == 0)) {
eb54b70d 769 if(readconfig() == 1) {
770 if(msgbox(GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("The configuration file appears to have been edited outside the control of this program. If you continue using this program, all settings not handled by it will be lost. Do you wish to continue?")) == GTK_RESPONSE_NO)
771 exit(1);
772 }
773 }
714e16fb 774
0fbd8398 775 while(state != -1) {
776 if(state == 0) {
777 gtk_window_set_default_size(GTK_WINDOW(cfw_wnd), 500, 350);
778 gtk_widget_show(cfw_wnd);
779 fillcfw();
780 rootwnd = GTK_WINDOW(cfw_wnd);
781 gtk_main();
782 gtk_widget_hide(cfw_wnd);
783 rootwnd = NULL;
784 } else if(state == 1) {
785 gtk_window_set_default_size(GTK_WINDOW(ast_wnd), 500, 350);
786 gtk_widget_show(ast_wnd);
787 rootwnd = GTK_WINDOW(ast_wnd);
788 gtk_main();
789 gtk_widget_hide(ast_wnd);
790 ignoreclose = 0;
791 rootwnd = NULL;
792 } else if(state == 2) {
793 for(i = 3; i < FD_SETSIZE; i++)
794 close(i);
795 execlp("dolcon", "dolcon", NULL);
796 perror("dolcon");
797 exit(127);
798 } else {
799 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Internal error (Unknown state)"));
800 abort();
801 }
802 }
eb54b70d 803 return(0);
804}