Dolconf should run autolauncher instead of dolcon.
[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{
642 shareadd();
eb54b70d 643}
644
645void cb_ast_sharerem_clicked(GtkWidget *widget, gpointer uudata)
646{
647 GtkTreeIter iter;
648
649 if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(ast_sharelist)), NULL, &iter))
650 gtk_list_store_remove(shares, &iter);
651 if(gtk_tree_model_iter_n_children(GTK_TREE_MODEL(shares), NULL) == 0)
652 gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page2, FALSE);
653}
654
0fbd8398 655void cb_cfw_sharerem_clicked(GtkWidget *widget, gpointer uudata)
656{
657 GtkTreeIter iter;
658
659 if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(cfw_sharelist)), NULL, &iter))
660 gtk_list_store_remove(shares, &iter);
661}
662
48b166ff 663void cb_ast_checkports(GtkWidget *widget, gpointer uudata)
664{
665 gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page3,
666 v_natural(gtk_entry_get_text(GTK_ENTRY(ast_tcpport))) &&
0fbd8398 667 (atoi(gtk_entry_get_text(GTK_ENTRY(ast_tcpport))) >= 1024) &&
48b166ff 668 v_natural(gtk_entry_get_text(GTK_ENTRY(ast_udpport))) &&
0fbd8398 669 (atoi(gtk_entry_get_text(GTK_ENTRY(ast_udpport))) >= 1024) &&
48b166ff 670 v_ipv4(gtk_entry_get_text(GTK_ENTRY(ast_extip))));
671}
672
673void cb_ast_mode_nat_toggled(GtkWidget *widget, gpointer uudata)
674{
675 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
676 gtk_widget_set_sensitive(GTK_WIDGET(ast_portbox), TRUE);
677 cb_ast_checkports(widget, NULL);
678 } else {
679 gtk_widget_set_sensitive(GTK_WIDGET(ast_portbox), FALSE);
680 gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page3, TRUE);
681 }
682}
683
0fbd8398 684void cb_cfw_mode_act_toggled(GtkWidget *widget, gpointer uudata)
685{
686 gtk_widget_set_sensitive(GTK_WIDGET(cfw_natbox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
687}
688
689void cb_cfw_orport_toggled(GtkWidget *widget, gpointer uudata)
690{
691 gtk_widget_set_sensitive(GTK_WIDGET(cfw_portbox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
692}
693
694void cb_cfw_oraddr_toggled(GtkWidget *widget, gpointer uudata)
695{
696 gtk_widget_set_sensitive(GTK_WIDGET(cfw_addrbox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
697}
698
699void cb_cfw_uinet_toggled(GtkWidget *widget, gpointer uudata)
700{
701 gtk_widget_set_sensitive(GTK_WIDGET(cfw_uibox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
702}
703
c3aa1aa0 704void cb_cfw_hup_activate(GtkWidget *widget, gpointer uudata)
705{
706 int tag;
707 struct dc_response *resp;
708
709 if(dc_connectsync2(dc_srv_local, DC_LATEST) < 0) {
710 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not connect to server"));
711 return;
712 }
713 if(dc_login(NULL, 1, dc_convnone, NULL) != DC_LOGIN_ERR_SUCCESS) {
714 dc_disconnect();
715 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not connect to server"));
716 return;
717 }
718 tag = dc_queuecmd(NULL, NULL, L"hup", NULL);
719 if((resp = dc_gettaggedrespsync(tag)) != NULL) {
720 if(resp->code != 200)
721 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not connect to server"));
722 dc_freeresp(resp);
723 }
724 dc_disconnect();
725}
726
c8394dc9 727void cb_cfw_save_activate(GtkWidget *widget, gpointer uudata)
0fbd8398 728{
729 struct cfvar *cv;
730
958a04bd 731 if((cv = cfwvalid()) != NULL) {
732 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, cv->vld->invmsg, cv->rname);
733 return;
0fbd8398 734 }
735 cfw2conf();
736 writeconfig();
737}
738
c8394dc9 739void cb_cfw_quit_activate(GtkWidget *widget, gpointer uudata)
0fbd8398 740{
958a04bd 741 cfw2conf();
742 if(dirty) {
1a724a90 743 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 744 return;
745 }
0fbd8398 746 gtk_main_quit();
747 state = -1;
748}
749
eb54b70d 750int main(int argc, char **argv)
751{
714e16fb 752 int i, c, ex;
eb54b70d 753 struct passwd *pwd;
754
755 setlocale(LC_ALL, "");
756 bindtextdomain(PACKAGE, LOCALEDIR);
757 textdomain(PACKAGE);
758 prepstatic();
c3aa1aa0 759 dc_init();
eb54b70d 760
761 gtk_init(&argc, &argv);
714e16fb 762 state = -1;
763 while((c = getopt(argc, argv, "haw")) != -1) {
764 switch(c) {
765 case 'a':
766 state = 1;
767 break;
768 case 'w':
769 state = 0;
ee20b80b 770 break;
714e16fb 771 case 'h':
289fa2ea 772 printf("usage: dolconf [-haw]\n");
773 printf("\t-h\tDisplay this help message\n");
774 printf("\t-a\tGo directly to the assistant\n");
775 printf("\t-w\tGo directly to the standard window\n");
776 exit(0);
714e16fb 777 default:
289fa2ea 778 fprintf(stderr, "usage: dolconf [-haw]\n");
779 exit(1);
714e16fb 780 }
781 }
782
eb54b70d 783 create_ast_wnd();
0fbd8398 784 create_cfw_wnd();
eb54b70d 785 shares = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
786 gtk_tree_view_set_model(GTK_TREE_VIEW(ast_sharelist), GTK_TREE_MODEL(shares));
0fbd8398 787 gtk_tree_view_set_model(GTK_TREE_VIEW(cfw_sharelist), GTK_TREE_MODEL(shares));
eb54b70d 788
789 cfname = NULL;
790 if(getenv("HOME") != NULL) {
791 cfname = sprintf2("%s/.doldacond.conf", getenv("HOME"));
792 } else {
793 if((pwd = getpwuid(getuid())) != NULL)
794 cfname = sprintf2("%s/.doldacond.conf", pwd->pw_dir);
795 }
796 if(cfname == NULL) {
797 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not get your home directory!"));
798 exit(1);
799 }
800
714e16fb 801 ex = !access(cfname, F_OK);
c8394dc9 802 if(state == -1) {
803 if(!ex) {
804 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)
805 state = 1;
806 else
807 state = 0;
808 } else {
0fbd8398 809 state = 0;
c8394dc9 810 }
714e16fb 811 }
812
813 if(ex && (state == 0)) {
eb54b70d 814 if(readconfig() == 1) {
815 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)
816 exit(1);
817 }
818 }
714e16fb 819
0fbd8398 820 while(state != -1) {
821 if(state == 0) {
822 gtk_window_set_default_size(GTK_WINDOW(cfw_wnd), 500, 350);
823 gtk_widget_show(cfw_wnd);
824 fillcfw();
825 rootwnd = GTK_WINDOW(cfw_wnd);
826 gtk_main();
827 gtk_widget_hide(cfw_wnd);
828 rootwnd = NULL;
829 } else if(state == 1) {
830 gtk_window_set_default_size(GTK_WINDOW(ast_wnd), 500, 350);
831 gtk_widget_show(ast_wnd);
832 rootwnd = GTK_WINDOW(ast_wnd);
833 gtk_main();
834 gtk_widget_hide(ast_wnd);
835 ignoreclose = 0;
836 rootwnd = NULL;
837 } else if(state == 2) {
838 for(i = 3; i < FD_SETSIZE; i++)
839 close(i);
11146491
FT
840 execlp("dolcon-launch", "dolcon-launch", NULL);
841 perror("dolcon-launch");
0fbd8398 842 exit(127);
843 } else {
844 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Internal error (Unknown state)"));
845 abort();
846 }
847 }
eb54b70d 848 return(0);
849}
b1099f1f
FT
850
851#include "dolconf-assistant.gtk"
852#include "dolconf-wnd.gtk"