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