citadel
About: Citadel is an advanced messaging and collaboration system for groupware and BBS applications (preferred OS: Linux).
  Fossies Dox: citadel.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

setup.c
Go to the documentation of this file.
1/*
2 * Citadel setup utility
3 *
4 * Copyright (c) 1987-2021 by the citadel.org team
5 *
6 * This program is open source software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#define SHOW_ME_VAPPEND_PRINTF
16#include <stdlib.h>
17#include <unistd.h>
18#include <stdio.h>
19#include <string.h>
20#include <ctype.h>
21#include <fcntl.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <sys/wait.h>
25#include <signal.h>
26#include <netdb.h>
27#include <errno.h>
28#include <limits.h>
29#include <pwd.h>
30#include <time.h>
31#include <sys/socket.h>
32#include <sys/un.h>
33#include <assert.h>
34#include <libcitadel.h>
35#include "citadel.h"
36#include "axdefs.h"
37#include "sysdep.h"
38#include "citadel_dirs.h"
39
40#ifdef ENABLE_NLS
41#ifdef HAVE_XLOCALE_H
42#include <xlocale.h>
43#endif
44#include <libintl.h>
45#include <locale.h>
46#define _(string) gettext(string)
47#else
48#define _(string) (string)
49#endif
50
51#define SERVICE_NAME "citadel"
52#define PROTO_NAME "tcp"
53#define NSSCONF "/etc/nsswitch.conf"
54
55typedef enum _SetupStep {
59 eUID = 3,
68 eMaxQuestions = 12
70
71///"CREATE_XINETD_ENTRY";
72/* Environment variables, don't translate! */
73const char *EnvNames [eMaxQuestions] = {
74 "HOME_DIRECTORY",
75 "SYSADMIN_NAME",
76 "SYSADMIN_PW",
77 "CITADEL_UID",
78 "IP_ADDR",
79 "CITADEL_PORT",
80 "ENABLE_UNIX_AUTH",
81 "LDAP_HOST",
82 "LDAP_PORT",
83 "LDAP_BASE_DN",
84 "LDAP_BIND_DN",
85 "LDAP_BIND_PW"
86};
87
88int setup_type = (-1);
93int serv_sock = (-1) ;
94
97
99
100void SetTitles(void)
101{
102 int have_run_dir;
103#ifndef HAVE_RUN_DIR
104 have_run_dir = 1;
105#else
106 have_run_dir = 0;
107#endif
108
109#ifdef ENABLE_NLS
110 setlocale(LC_MESSAGES, getenv("LANG"));
111 bindtextdomain("citadel-setup", LOCALEDIR"/locale");
112 textdomain("citadel-setup");
113 bind_textdomain_codeset("citadel-setup","UTF8");
114#endif
115
116 setup_titles[eCitadelHomeDir] = _("Citadel Home Directory");
117 if (have_run_dir)
119"Enter the full pathname of the directory in which the Citadel\n"
120"installation you are creating or updating resides. If you\n"
121"specify a directory other than the default, you will need to\n"
122"specify the -h flag to the server when you start it up.\n");
123 else
125"Enter the subdirectory name for an alternate installation of "
126"Citadel. To do a default installation just leave it blank."
127"If you specify a directory other than the default, you will need to\n"
128"specify the -h flag to the server when you start it up.\n"
129"note that it may not have a leading /");
130
131 setup_titles[eSysAdminName] = _("Citadel administrator username:");
133"Please enter the name of the Citadel user account that should be granted "
134"administrative privileges once created. If using internal authentication "
135"this user account will be created if it does not exist. For external "
136"authentication this user account has to exist.");
137
138 setup_titles[eSysAdminPW] = _("Administrator password:");
140"Enter a password for the system administrator. When setup\n"
141"completes it will attempt to create the administrator user\n"
142"and set the password specified here.\n");
143
144 setup_titles[eUID] = _("Citadel User ID:");
145 setup_text[eUID] = _(
146"Citadel needs to run under its own user ID. This would\n"
147"typically be called \"citadel\", but if you are running Citadel\n"
148"as a public site, you might also call it \"bbs\" or \"guest\".\n"
149"The server will run under this user ID. Please specify that\n"
150"user ID here. You may specify either a user name or a numeric\n"
151"UID.\n");
152
153 setup_titles[eIP_ADDR] = _("Listening address for the Citadel server:");
155"Please specify the IP address which the server should be listening to. "
156"You can name a specific IPv4 or IPv6 address, or you can specify\n"
157"\"*\" for \"any address\", \"::\" for \"any IPv6 address\", or \"0.0.0.0\"\n"
158"for \"any IPv4 address\". If you leave this blank, Citadel will\n"
159"listen on all addresses. "
160"This can usually be left to the default unless multiple instances of Citadel "
161"are running on the same computer.");
162
163 setup_titles[eCTDL_Port] = _("Server port number:");
165"Specify the TCP port number on which your server will run.\n"
166"Normally, this will be port 504, which is the official port\n"
167"assigned by the IANA for Citadel servers. You will only need\n"
168"to specify a different port number if you run multiple instances\n"
169"of Citadel on the same computer and there is something else\n"
170"already using port 504.\n");
171
172 setup_titles[eAuthType] = _("Authentication method to use:");
174"Please choose the user authentication mode. By default Citadel will use its "
175"own internal user accounts database. If you choose Host, Citadel users will "
176"have accounts on the host system, authenticated via /etc/passwd or a PAM "
177"source. LDAP chooses an RFC 2307 compliant directory server, the last option "
178"chooses the nonstandard MS Active Directory LDAP scheme."
179"\n"
180"Do not change this option unless you are sure it is required, since changing "
181"back requires a full reinstall of Citadel."
182"\n"
183" 0. Self contained authentication\n"
184" 1. Host system integrated authentication\n"
185" 2. External LDAP - RFC 2307 POSIX schema\n"
186" 3. External LDAP - MS Active Directory schema\n"
187"\n"
188"For help: http://www.citadel.org/doku.php/faq:installation:authmodes\n"
189"\n"
190"ANSWER \"0\" UNLESS YOU COMPLETELY UNDERSTAND THIS OPTION.\n");
191
192 setup_titles[eLDAP_Host] = _("LDAP host:");
194"Please enter the host name or IP address of your LDAP server.\n");
195
196 setup_titles[eLDAP_Port] = _("LDAP port number:");
198"Please enter the port number of the LDAP service (usually 389).\n");
199
200 setup_titles[eLDAP_Base_DN] = _("LDAP base DN:");
202"Please enter the Base DN to search for authentication\n"
203"(for example: dc=example,dc=com)\n");
204
205 setup_titles[eLDAP_Bind_DN] = _("LDAP bind DN:");
207"Please enter the DN of an account to use for binding to the LDAP server for "
208"performing queries. The account does not require any other privileges. If "
209"your LDAP server allows anonymous queries, you can leave this blank.\n");
210
211 setup_titles[eLDAP_Bind_PW] = _("LDAP bind password:");
213"If you entered a Bind DN in the previous question, you must now enter\n"
214"the password associated with that account. Otherwise, you can leave this\n"
215"blank.\n");
216
217#if 0
218// Debug loading of locales... Strace does a better job though.
219 printf("Message catalog directory: %s\n", bindtextdomain("citadel-setup", LOCALEDIR"/locale"));
220 printf("Text domain: %s\n", textdomain("citadel-setup"));
221 printf("Text domain Charset: %s\n", bind_textdomain_codeset("citadel-setup","UTF8"));
222 {
223 int i;
224 for (i = 0; i < eMaxQuestions; i++)
225 printf("%s - %s\n", setup_titles[i], _(setup_titles[i]));
226 exit(0);
227 }
228#endif
229}
230
231
232void title(const char *text) {
233 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<%s>\n", text);
234}
235
236
237int yesno(const char *question, int default_value) {
238 int answer = 0;
239 char buf[SIZ];
240
241 do {
242 printf("%s\n%s [%s] --> ", question, _("Yes/No"), ( default_value ? _("Yes") : _("No") ));
243 if (fgets(buf, sizeof buf, stdin)) {
244 answer = tolower(buf[0]);
245 if ((buf[0]==0) || (buf[0]==13) || (buf[0]==10)) {
246 answer = default_value;
247 }
248 else if (answer == 'y') {
249 answer = 1;
250 }
251 else if (answer == 'n') {
252 answer = 0;
253 }
254 }
255 } while ((answer < 0) || (answer > 1));
256 return (answer);
257}
258
259
260void important_message(const char *title, const char *msgtext) {
261 char buf[SIZ];
262
263 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
264 printf(" %s \n\n%s\n\n", title, msgtext);
265 printf("%s", _("Press return to continue..."));
266 if (fgets(buf, sizeof buf, stdin)) {
267 ;
268 }
269}
270
271
272void important_msgnum(int msgnum) {
273 important_message(_("Important Message"), setup_text[msgnum]);
274}
275
276
277void display_error(char *error_message_format, ...) {
278 StrBuf *Msg;
279 va_list arg_ptr;
280
281 Msg = NewStrBuf();
282 va_start(arg_ptr, error_message_format);
283 StrBufVAppendPrintf(Msg, error_message_format, arg_ptr);
284 va_end(arg_ptr);
285
286 important_message(_("Error"), ChrPtr(Msg));
287 FreeStrBuf(&Msg);
288}
289
290
291void progress(char *text, long int curr, long int cmax) {
292 static long dots_printed = 0L;
293 long a = 0;
294
295 if (curr == 0) {
296 printf("%s\n", text);
297 printf("....................................................");
298 printf("..........................\r");
299 dots_printed = 0;
300 } else if (curr == cmax) {
301 printf("\r%79s\n", "");
302 } else {
303 a = (curr * 100) / cmax;
304 a = a * 78;
305 a = a / 100;
306 while (dots_printed < a) {
307 printf("*");
308 ++dots_printed;
309 }
310 }
311 fflush(stdout);
312}
313
314
315int uds_connectsock(char *sockpath) {
316 int s;
317 struct sockaddr_un addr;
318
319 memset(&addr, 0, sizeof(addr));
320 addr.sun_family = AF_UNIX;
321 strcpy(addr.sun_path, sockpath);
322
323 s = socket(AF_UNIX, SOCK_STREAM, 0);
324 if (s < 0) {
325 return(-1);
326 }
327
328 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
329 close(s);
330 return(-1);
331 }
332
333 return s;
334}
335
336
337/*
338 * input binary data from socket
339 */
340void serv_read(char *buf, int bytes) {
341 int len, rlen;
342
343 len = 0;
344 while (len < bytes) {
345 rlen = read(serv_sock, &buf[len], bytes - len);
346 if (rlen < 1) {
347 return;
348 }
349 len = len + rlen;
350 }
351}
352
353
354/*
355 * send binary to server
356 */
357void serv_write(char *buf, int nbytes) {
358 int bytes_written = 0;
359 int retval;
360 while (bytes_written < nbytes) {
361 retval = write(serv_sock, &buf[bytes_written], nbytes - bytes_written);
362 if (retval < 1) {
363 return;
364 }
365 bytes_written = bytes_written + retval;
366 }
367}
368
369
370/*
371 * input string from socket - implemented in terms of serv_read()
372 */
373void serv_gets(char *buf) {
374 int i;
375
376 /* Read one character at a time.
377 */
378 for (i = 0;; i++) {
379 serv_read(&buf[i], 1);
380 if (buf[i] == '\n' || i == (SIZ-1))
381 break;
382 }
383
384 /* If we got a long line, discard characters until the newline.
385 */
386 if (i == (SIZ-1)) {
387 while (buf[i] != '\n') {
388 serv_read(&buf[i], 1);
389 }
390 }
391
392 /* Strip all trailing nonprintables (crlf)
393 */
394 buf[i] = 0;
395}
396
397
398/*
399 * send line to server - implemented in terms of serv_write()
400 */
401void serv_puts(char *buf) {
402 serv_write(buf, strlen(buf));
403 serv_write("\n", 1);
404}
405
406
407/*
408 * Convenience functions to get/set system configuration entries
409 */
410void getconf_str(char *buf, char *key) {
411 char cmd[SIZ];
412 char ret[SIZ];
413
414 sprintf(cmd, "CONF GETVAL|%s", key);
415 serv_puts(cmd);
416 serv_gets(ret);
417 if (ret[0] == '2') {
418 extract_token(buf, &ret[4], 0, '|', SIZ);
419 }
420 else {
421 strcpy(buf, "");
422 }
423}
424
425
426int getconf_int(char *key) {
427 char buf[SIZ];
428 getconf_str(buf, key);
429 return atoi(buf);
430}
431
432
433void setconf_str(char *key, char *val) {
434 char buf[SIZ];
435
436 sprintf(buf, "CONF PUTVAL|%s|%s", key, val);
437 serv_puts(buf);
438 serv_gets(buf);
439}
440
441
442void setconf_int(char *key, int val) {
443 char buf[SIZ];
444
445 sprintf(buf, "CONF PUTVAL|%s|%d", key, val);
446 serv_puts(buf);
447 serv_gets(buf);
448}
449
450
451/*
452 * On systems which use xinetd, see if we can offer to install Citadel as
453 * the default telnet target.
454 */
456{
457 char *filename = "/etc/xinetd.d/telnet";
458 FILE *fp;
459 char buf[SIZ];
460 int already_citadel = 0;
461 int rv;
462
463 fp = fopen(filename, "r+");
464 if (fp == NULL) return; /* Not there. Oh well... */
465
466 while (fgets(buf, sizeof buf, fp) != NULL) {
467 if (strstr(buf, "/citadel") != NULL) {
468 already_citadel = 1;
469 }
470 }
471 fclose(fp);
472 if (already_citadel) return; /* Already set up this way. */
473
474 /* Otherwise, prompt the user to create an entry. */
475 if (getenv("CREATE_XINETD_ENTRY") != NULL) {
476 if (strcasecmp(getenv("CREATE_XINETD_ENTRY"), "yes")) {
477 return;
478 }
479 }
480 else {
481 snprintf(buf, sizeof buf,
482 _("Setup can configure the \"xinetd\" service to automatically\n"
483 "connect incoming telnet sessions to Citadel, bypassing the\n"
484 "host system login: prompt. Would you like to do this?\n"
485 )
486 );
487 if (yesno(buf, 1) == 0) {
488 return;
489 }
490 }
491
492 fp = fopen(filename, "w");
493 fprintf(fp,
494 "# description: telnet service for Citadel users\n"
495 "service telnet\n"
496 "{\n"
497 " disable = no\n"
498 " flags = REUSE\n"
499 " socket_type = stream\n"
500 " wait = no\n"
501 " user = root\n"
502 " server = /usr/sbin/in.telnetd\n"
503 " server_args = -h -L %s/citadel\n"
504 " log_on_failure += USERID\n"
505 "}\n",
507 );
508 fclose(fp);
509
510 /* Now try to restart the service. This will not have the intended effect on Solaris, but who uses Solaris anymore? */
511 rv = system("systemctl restart xinetd >/dev/null 2>&1");
512 if (rv != 0) {
513 rv = system("service xinetd restart >/dev/null 2>&1");
514 }
515 if (rv != 0) {
516 display_error(_("failed to restart xinetd.\n"));
517 }
518}
519
520
521void strprompt(const char *prompt_title, const char *prompt_text, char *Target, char *DefValue)
522{
523 char buf[SIZ] = "";
524 char setupmsg[SIZ];
525
526 strcpy(setupmsg, "");
527
528 title(prompt_title);
529 printf("\n%s\n", prompt_text);
530 printf("%s\n%s\n", _("This is currently set to:"), Target);
531 printf("%s\n", _("Enter new value or press return to leave unchanged:"));
532 if (fgets(buf, sizeof buf, stdin)) {
533 buf[strlen(buf) - 1] = 0;
534 }
535 if (!IsEmptyStr(buf)) {
536 strcpy(Target, buf);
537 }
538}
539
540
541void set_bool_val(int msgpos, int *ip, char *DefValue) {
542 title(setup_titles[msgpos]);
543 *ip = yesno(setup_text[msgpos], *ip);
544}
545
546
547void set_str_val(int msgpos, char *Target, char *DefValue)
548{
549 strprompt(setup_titles[msgpos],
550 setup_text[msgpos],
551 Target,
552 DefValue
553 );
554}
555
556
557/* like set_str_val() but for numeric values */
558void set_int_val(int msgpos, int *target, char *default_value)
559{
560 char buf[32];
561 sprintf(buf, "%d", *target);
562 do {
563 set_str_val(msgpos, buf, default_value);
564 } while ( (strcmp(buf, "0")) && (atoi(buf) == 0) );
565 *target = atoi(buf);
566}
567
568
569void edit_value(int curr)
570{
571 struct passwd *pw = NULL;
572 char ctdluidname[256];
573 char buf[SIZ];
574 char *default_value = NULL;
575 int ctdluid = 0;
576 int portnum = 0;
577 int auth = 0;
578 int lportnum = 0;
579
580 if (default_value == NULL) {
581 default_value = "";
582 }
583
584 switch (curr) {
585
586 case eSysAdminName:
587 getconf_str(admin_name, "c_sysadm");
588 set_str_val(curr, admin_name, default_value);
589 setconf_str("c_sysadm", admin_name);
590 break;
591
592 case eSysAdminPW:
593 set_str_val(curr, admin_pass, default_value);
594 break;
595
596 case eUID:
597 ctdluid = getconf_int("c_ctdluid");
598 pw = getpwuid(ctdluid);
599 if (pw == NULL) {
600 set_int_val(curr, &ctdluid, default_value);
601 }
602 else {
603 strcpy(ctdluidname, pw->pw_name);
604 set_str_val(curr, ctdluidname, default_value);
605 pw = getpwnam(ctdluidname);
606 if (pw != NULL) {
607 ctdluid = pw->pw_uid;
608 }
609 else if (atoi(ctdluidname) > 0) {
610 ctdluid = atoi(ctdluidname);
611 }
612 }
613 setconf_int("c_ctdluid", ctdluid);
614 break;
615
616 case eIP_ADDR:
617 getconf_str(buf, "c_ip_addr");
618 set_str_val(curr, buf, default_value);
619 setconf_str("c_ip_addr", buf);
620 break;
621
622 case eCTDL_Port:
623 portnum = getconf_int("c_port_number");
624 set_int_val(curr, &portnum, default_value);
625 setconf_int("c_port_number", portnum);
626 break;
627
628 case eAuthType:
629 auth = getconf_int("c_auth_mode");
630 set_int_val(curr, &auth, default_value);
631 setconf_int("c_auth_mode", auth);
632 break;
633
634 case eLDAP_Host:
635 getconf_str(buf, "c_ldap_host");
636 if (IsEmptyStr(buf)) {
637 strcpy(buf, "localhost");
638 }
639 set_str_val(curr, buf, default_value);
640 setconf_str("c_ldap_host", buf);
641 break;
642
643 case eLDAP_Port:
644 lportnum = getconf_int("c_ldap_port");
645 if (lportnum == 0) {
646 lportnum = 389;
647 }
648 set_int_val(curr, &lportnum, default_value);
649 setconf_int("c_ldap_port", lportnum);
650 break;
651
652 case eLDAP_Base_DN:
653 getconf_str(buf, "c_ldap_base_dn");
654 set_str_val(curr, buf, default_value);
655 setconf_str("c_ldap_base_dn", buf);
656 break;
657
658 case eLDAP_Bind_DN:
659 getconf_str(buf, "c_ldap_bind_dn");
660 set_str_val(curr, buf, default_value);
661 setconf_str("c_ldap_bind_dn", buf);
662 break;
663
664 case eLDAP_Bind_PW:
665 getconf_str(buf, "c_ldap_bind_pw");
666 set_str_val(curr, buf, default_value);
667 setconf_str("c_ldap_bind_pw", buf);
668 break;
669 }
670}
671
672
673/*
674 * Messages that are no longer in use.
675 * We keep them here so we don't lose the translations if we need them later.
676 */
677#if 0
678important_message(_("Setup finished"),
679_("Setup of the Citadel server is complete.\n"
680"If you will be using WebCit, please run its\n"
681"setup program now; otherwise, run './citadel'\n"
682"to log in.\n"));
683important_message(_("Setup failed"),
684_("Setup is finished, but the Citadel server failed to start.\n"
685"Go back and check your configuration.\n");
686important_message(_("Setup finished"),
687_("Setup is finished. You may now start the server."));
688#endif
689
690
691int main(int argc, char *argv[])
692{
693 int a, i;
694 int curr;
695 char buf[1024];
696 char aaa[128];
697 char ctdldir[PATH_MAX]=CTDLDIR;
698 struct passwd *pw;
699 gid_t gid;
700 char *activity = NULL;
701
702 /* Keep a mild groove on */
703 program_title = _("Citadel setup program");
704
705 /* set an invalid setup type */
706 setup_type = (-1);
707
708 /* parse command line args */
709 for (a = 0; a < argc; ++a) {
710 if (!strncmp(argv[a], "-u", 2)) {
711 strcpy(aaa, argv[a]);
712 strcpy(aaa, &aaa[2]);
713 setup_type = atoi(aaa);
714 }
715 else if (!strncmp(argv[a], "-h", 2)) {
716 safestrncpy(ctdldir, &argv[a][2], sizeof ctdldir);
717 }
718 }
719
720 if (chdir(ctdldir) != 0) {
721 fprintf(stderr, "sendcommand: %s: %s\n", ctdldir, strerror(errno));
722 exit(errno);
723 }
724
725 SetTitles();
726
727 /*
728 * Connect to the running Citadel server.
729 */
730 char *connectingmsg = _("Connecting to Citadel server");
731 for (i=0; ((i<30) && (serv_sock < 0)) ; ++i) { /* wait for server to start up */
732 progress(connectingmsg, i, 30);
734 sleep(1);
735 }
736 progress(connectingmsg, 30, 30);
737
738 if (serv_sock < 0) {
740 "%s: %s %s\n",
741 _("Setup could not connect to a running Citadel server."),
742 strerror(errno), file_citadel_admin_socket
743 );
744 exit(1);
745 }
746
747 /*
748 * read the server greeting
749 */
750 serv_gets(buf);
751 if (buf[0] != '2') {
752 display_error("%s\n", buf);
753 exit(2);
754 }
755
756 /*
757 * Are we connected to the correct Citadel server?
758 */
759 serv_puts("INFO");
760 serv_gets(buf);
761 if (buf[0] != '1') {
762 display_error("%s\n", buf);
763 exit(3);
764 }
765 a = 0;
766 while (serv_gets(buf), strcmp(buf, "000")) {
767 if (a == 5) {
768 if (atoi(buf) != REV_LEVEL) {
769 display_error("%s\n",
770 _("Your setup program and Citadel server are from different versions.")
771 );
772 exit(4);
773 }
774 }
775 ++a;
776 }
777
778 printf("\n\n\n *** %s ***\n\n", program_title);
779
780 /* Go through a series of dialogs prompting for config info */
781 for (curr = 1; curr < eMaxQuestions; ++curr) {
782 edit_value(curr);
783
784 if ( (curr == eAuthType)
785 && (getconf_int("c_auth_mode") != AUTHMODE_LDAP)
786 && (getconf_int("c_auth_mode") != AUTHMODE_LDAP_AD)
787 ) {
788 curr += 5; /* skip LDAP questions if we're not authenticating against LDAP */
789 }
790
791 if (curr == eSysAdminName) {
792 if (getconf_int("c_auth_mode") == AUTHMODE_NATIVE) {
793 /* for native auth mode, fetch the admin's existing pw */
794 snprintf(buf, sizeof buf, "AGUP %s", admin_name);
795 serv_puts(buf);
796 serv_gets(buf);
797 if (buf[0] == '2') {
798 extract_token(admin_pass, &buf[4], 1, '|', sizeof admin_pass);
799 }
800 }
801 else {
802 ++curr; /* skip the password question for non-native auth modes */
803 }
804 }
805 }
806
807 if ((pw = getpwuid( getconf_int("c_ctdluid") )) == NULL) {
808 gid = getgid();
809 } else {
810 gid = pw->pw_gid;
811 }
812
813 if (create_run_directories(getconf_int("c_ctdluid"), gid) != 0) {
814 display_error("%s\n", _("failed to create directories"));
815 }
816
817 activity = _("Reconfiguring Citadel server");
818 progress(activity, 0, 5);
819 sleep(1); /* Let the message appear briefly */
820
821 /*
822 * Create the administrator account. It's ok if the command fails if this user already exists.
823 */
824 if (getconf_int("c_auth_mode") == AUTHMODE_NATIVE) {
825 progress(activity, 1, 5);
826 snprintf(buf, sizeof buf, "CREU %s|%s", admin_name, admin_pass);
827 serv_puts(buf);
828 progress(activity, 2, 5);
829 serv_gets(buf);
830 }
831 progress(activity, 3, 5);
832
833 /*
834 * Assign the desired password and access level to the administrator account.
835 */
836 if (getconf_int("c_auth_mode") == AUTHMODE_NATIVE) {
837 snprintf(buf, sizeof buf, "AGUP %s", admin_name);
838 serv_puts(buf);
839 progress(activity, 4, 5);
840 serv_gets(buf);
841 if (buf[0] == '2') {
842 int admin_flags = extract_int(&buf[4], 2);
843 int admin_times_called = extract_int(&buf[4], 3);
844 int admin_msgs_posted = extract_int(&buf[4], 4);
845 snprintf(buf, sizeof buf, "ASUP %s|%s|%d|%d|%d|6",
846 admin_name, admin_pass, admin_flags, admin_times_called, admin_msgs_posted
847 );
848 serv_puts(buf);
849 serv_gets(buf);
850 }
851 }
852 progress(activity, 5, 5);
853
854 check_xinetd_entry(); /* Check /etc/xinetd.d/telnet */
855
856 /*
857 * Restart citserver
858 */
859 activity = _("Restarting Citadel server to apply changes");
860 progress(activity, 0, 51);
861
862 serv_puts("TIME");
863 serv_gets(buf);
864 long original_start_time = extract_long(&buf[4], 3);
865
866 progress(activity, 1, 51);
867 serv_puts("DOWN 1");
868 progress(activity, 2, 51);
869 serv_gets(buf);
870 if (buf[0] != '2') {
871 display_error("%s\n", buf);
872 exit(6);
873 }
874
875 close(serv_sock);
876 serv_sock = (-1);
877
878 for (i=3; i<=6; ++i) { /* wait for server to shut down */
879 progress(activity, i, 51);
880 sleep(1);
881 }
882
883 for (i=7; ((i<=48) && (serv_sock < 0)) ; ++i) { /* wait for server to start up */
884 progress(activity, i, 51);
886 sleep(1);
887 }
888
889 progress(activity, 49, 51);
890 serv_gets(buf);
891
892 progress(activity, 50, 51);
893 serv_puts("TIME");
894 serv_gets(buf);
895 long new_start_time = extract_long(&buf[4], 3);
896
897 close(serv_sock);
898 progress(activity, 51, 51);
899
900 if ((original_start_time == new_start_time) || (new_start_time <= 0)) {
901 display_error("%s\n", _("Setup failed to restart Citadel server. Please restart it manually."));
902 exit(7);
903 }
904
905 exit(0);
906 return 0;
907}
#define REV_LEVEL
Definition: citadel.h:35
#define AUTHMODE_LDAP
Definition: citadel.h:175
#define AUTHMODE_NATIVE
Definition: citadel.h:173
#define AUTHMODE_LDAP_AD
Definition: citadel.h:176
int create_run_directories(long UID, long GID)
Definition: citadel_dirs.c:60
#define ctdl_bin_dir
Definition: citadel_dirs.h:21
#define file_citadel_admin_socket
Definition: citadel_dirs.h:30
uid_t ctdluid
Definition: server_main.c:30
void set_bool_val(int msgpos, int *ip, char *DefValue)
Definition: setup.c:541
void title(const char *text)
Definition: setup.c:232
int main(int argc, char *argv[])
Definition: setup.c:691
int enable_home
Definition: setup.c:89
void edit_value(int curr)
Definition: setup.c:569
enum _SetupStep eSetupStep
const char * setup_titles[eMaxQuestions]
Definition: setup.c:95
int uds_connectsock(char *sockpath)
Definition: setup.c:315
void check_xinetd_entry(void)
Definition: setup.c:455
char admin_cmd[4096]
Definition: setup.c:92
void set_str_val(int msgpos, char *Target, char *DefValue)
Definition: setup.c:547
void getconf_str(char *buf, char *key)
Definition: setup.c:410
void SetTitles(void)
Definition: setup.c:100
void progress(char *text, long int curr, long int cmax)
Definition: setup.c:291
int serv_sock
Definition: setup.c:93
void important_msgnum(int msgnum)
Definition: setup.c:272
void serv_puts(char *buf)
Definition: setup.c:401
char admin_pass[4096]
Definition: setup.c:91
int setup_type
Definition: setup.c:88
void important_message(const char *title, const char *msgtext)
Definition: setup.c:260
char admin_name[4096]
Definition: setup.c:90
void display_error(char *error_message_format,...)
Definition: setup.c:277
_SetupStep
Definition: setup.c:55
@ eSysAdminPW
Definition: setup.c:58
@ eLDAP_Host
Definition: setup.c:63
@ eLDAP_Bind_PW
Definition: setup.c:67
@ eLDAP_Bind_DN
Definition: setup.c:66
@ eCTDL_Port
Definition: setup.c:61
@ eUID
Definition: setup.c:59
@ eSysAdminName
Definition: setup.c:57
@ eLDAP_Port
Definition: setup.c:64
@ eLDAP_Base_DN
Definition: setup.c:65
@ eMaxQuestions
Definition: setup.c:68
@ eCitadelHomeDir
Definition: setup.c:56
@ eAuthType
Definition: setup.c:62
@ eIP_ADDR
Definition: setup.c:60
void strprompt(const char *prompt_title, const char *prompt_text, char *Target, char *DefValue)
Definition: setup.c:521
#define _(string)
Definition: setup.c:48
int yesno(const char *question, int default_value)
Definition: setup.c:237
void setconf_str(char *key, char *val)
Definition: setup.c:433
void serv_write(char *buf, int nbytes)
Definition: setup.c:357
void serv_gets(char *buf)
Definition: setup.c:373
void set_int_val(int msgpos, int *target, char *default_value)
Definition: setup.c:558
char * program_title
Definition: setup.c:98
const char * setup_text[eMaxQuestions]
Definition: setup.c:96
void serv_read(char *buf, int bytes)
Definition: setup.c:340
void setconf_int(char *key, int val)
Definition: setup.c:442
int getconf_int(char *key)
Definition: setup.c:426
const char * EnvNames[eMaxQuestions]
"CREATE_XINETD_ENTRY";
Definition: setup.c:73
int snprintf(char *buf, size_t max, const char *fmt,...)
Definition: snprintf.c:69
#define SIZ
Definition: sysconfig.h:33