Dolconf should run autolauncher instead of dolcon.
[doldaconnect.git] / config / util / dolconf.c
... / ...
CommitLineData
1/*
2 * Dolda Connect - Modular multiuser Direct Connect-style client
3 * Copyright (C) 2007 Fredrik Tolf <fredrik@dolda2000.com>
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 <gdk/gdkkeysyms.h>
29#include <locale.h>
30#include <libintl.h>
31#include <pwd.h>
32#include <stdarg.h>
33#include <arpa/inet.h>
34#include <doldaconnect/uilib.h>
35#include <doldaconnect/uimisc.h>
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;
52 GtkWidget **astw, **cfww;
53};
54
55char *cfname;
56GtkWindow *rootwnd = NULL;
57GtkListStore *shares;
58int state, dirty = 1;
59int ignoreclose = 0;
60
61#define _(text) gettext(text)
62
63#include "dolconf-assistant.gtkh"
64#include "dolconf-wnd.gtkh"
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
78int v_natural(const char *val)
79{
80 if(!*val)
81 return(0);
82 for(; *val; val++) {
83 if(!isdigit(*val))
84 return(0);
85 }
86 return(1);
87}
88
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
111#undef _
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
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"),
137};
138
139struct validation *vldxlate[] = {
140 &nonempty, &dcstring, &natural, &integer, &ipv4,
141 NULL
142};
143
144struct cfvar config[] = {
145 {"cli.defnick", _("Screen name"), "", &dcstring, &ast_nick, &cfw_nick},
146 {"net.mode", NULL, "0", &natural},
147 {"net.visibleipv4", "IP address", "0.0.0.0", &ipv4, NULL, &cfw_extip},
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},
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},
157 {NULL}
158};
159
160#undef _
161#define _(text) gettext(text)
162
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);
179 if(!strcmp(v->val, val))
180 return;
181 free(v->val);
182 v->val = sstrdup(val);
183 dirty = 1;
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);
234 len = p2 - *p - ((*p2 == '\"')?1:0);
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);
345 dirty = 0;
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);
396 dirty = 0;
397}
398
399void fillcfw(void)
400{
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 }
425}
426
427void ast2conf(void)
428{
429 setcfvar("cli.defnick", gtk_entry_get_text(GTK_ENTRY(ast_nick)));
430 setcfvar("dc.desc", gtk_entry_get_text(GTK_ENTRY(ast_desc)));
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 }
445}
446
447void cfw2conf(void)
448{
449 struct cfvar *var;
450 const char *val;
451
452 for(var = config; var->name != NULL; var++) {
453 if(var->cfww != NULL) {
454 val = gtk_entry_get_text(GTK_ENTRY(*(var->cfww)));
455 if(!strcmp(var->val, val))
456 continue;
457 free(var->val);
458 var->val = sstrdup(val);
459 dirty = 1;
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
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
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();
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();
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;
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
585int shareadd(void)
586{
587 int i, ret;
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);
600 return(0);
601 }
602 ret = 0;
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);
624 ret = 1;
625 }
626 g_free(fn);
627 next = fns->next;
628 g_slist_free_1(fns);
629 fns = next;
630 }
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();
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
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
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))) &&
667 (atoi(gtk_entry_get_text(GTK_ENTRY(ast_tcpport))) >= 1024) &&
668 v_natural(gtk_entry_get_text(GTK_ENTRY(ast_udpport))) &&
669 (atoi(gtk_entry_get_text(GTK_ENTRY(ast_udpport))) >= 1024) &&
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
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
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
727void cb_cfw_save_activate(GtkWidget *widget, gpointer uudata)
728{
729 struct cfvar *cv;
730
731 if((cv = cfwvalid()) != NULL) {
732 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, cv->vld->invmsg, cv->rname);
733 return;
734 }
735 cfw2conf();
736 writeconfig();
737}
738
739void cb_cfw_quit_activate(GtkWidget *widget, gpointer uudata)
740{
741 cfw2conf();
742 if(dirty) {
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)
744 return;
745 }
746 gtk_main_quit();
747 state = -1;
748}
749
750int main(int argc, char **argv)
751{
752 int i, c, ex;
753 struct passwd *pwd;
754
755 setlocale(LC_ALL, "");
756 bindtextdomain(PACKAGE, LOCALEDIR);
757 textdomain(PACKAGE);
758 prepstatic();
759 dc_init();
760
761 gtk_init(&argc, &argv);
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;
770 break;
771 case 'h':
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);
777 default:
778 fprintf(stderr, "usage: dolconf [-haw]\n");
779 exit(1);
780 }
781 }
782
783 create_ast_wnd();
784 create_cfw_wnd();
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));
787 gtk_tree_view_set_model(GTK_TREE_VIEW(cfw_sharelist), GTK_TREE_MODEL(shares));
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
801 ex = !access(cfname, F_OK);
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 {
809 state = 0;
810 }
811 }
812
813 if(ex && (state == 0)) {
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 }
819
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);
840 execlp("dolcon-launch", "dolcon-launch", NULL);
841 perror("dolcon-launch");
842 exit(127);
843 } else {
844 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Internal error (Unknown state)"));
845 abort();
846 }
847 }
848 return(0);
849}
850
851#include "dolconf-assistant.gtk"
852#include "dolconf-wnd.gtk"