3 * Configuration screens that are part of the text mode client.
17 #if TIME_WITH_SYS_TIME
18 # include <sys/time.h>
22 # include <sys/time.h>
32 #include <libcitadel.h>
35 #include "citadel_ipc.h"
36 #include "citadel_decls.h"
37 #include "tuiconfig.h"
46 /* work around solaris include files */
52 extern char tempdir[];
53 extern char *axdefs[8];
54 extern long highest_msg_read;
55 extern long maxmsgnum;
56 extern unsigned room_flags;
57 extern int screenwidth;
61 * General system configuration command
63 void do_system_configuration(CtdlIPC *ipc)
66 #define NUM_CONFIGS 61
69 char sc[NUM_CONFIGS][256];
71 struct ExpirePolicy *site_expirepolicy = NULL;
72 struct ExpirePolicy *mbx_expirepolicy = NULL;
75 int r; /* IPC response code */
76 int server_configs = 0;
78 /* Clear out the config buffers */
79 memset(&sc[0][0], 0, sizeof(sc));
81 /* Fetch the current config */
82 r = CtdlIPCGetSystemConfig(ipc, &resp, buf);
84 server_configs = num_tokens(resp, '\n');
85 for (a=0; a<server_configs; ++a) {
86 if (a < NUM_CONFIGS) {
87 extract_token(&sc[a][0], resp, a, '\n', sizeof sc[a]);
93 /* Fetch the expire policy (this will silently fail on old servers,
94 * resulting in "default" policy)
96 r = CtdlIPCGetMessageExpirationPolicy(ipc, 2, &site_expirepolicy, buf);
97 r = CtdlIPCGetMessageExpirationPolicy(ipc, 3, &mbx_expirepolicy, buf);
99 /* Identification parameters */
101 strprompt("Node name", &sc[0][0], 15);
102 strprompt("Fully qualified domain name", &sc[1][0], 63);
103 strprompt("Human readable node name", &sc[2][0], 20);
104 strprompt("Telephone number", &sc[3][0], 15);
105 strprompt("Geographic location of this system", &sc[12][0], 31);
106 strprompt("Name of system administrator", &sc[13][0], 25);
107 strprompt("Paginator prompt", &sc[10][0], 79);
109 /* Security parameters */
111 snprintf(sc[7], sizeof sc[7], "%d", (boolprompt(
112 "Require registration for new users",
114 snprintf(sc[29], sizeof sc[29], "%d", (boolprompt(
115 "Disable self-service user account creation",
117 strprompt("Initial access level for new users", &sc[6][0], 1);
118 strprompt("Access level required to create rooms", &sc[19][0], 1);
119 snprintf(sc[4], sizeof sc[4], "%d", (boolprompt(
120 "Automatically give room aide privs to a user who creates a private room",
123 snprintf(sc[8], sizeof sc[8], "%d", (boolprompt(
124 "Automatically move problem user messages to twit room",
127 strprompt("Name of twit room", &sc[9][0], ROOMNAMELEN);
128 snprintf(sc[11], sizeof sc[11], "%d", (boolprompt(
129 "Restrict Internet mail to only those with that privilege",
131 snprintf(sc[26], sizeof sc[26], "%d", (boolprompt(
132 "Allow Aides to Zap (forget) rooms",
135 if (!IsEmptyStr(&sc[18][0])) logpages = 1;
137 logpages = boolprompt("Log all pages", logpages);
139 strprompt("Name of logging room", &sc[18][0], ROOMNAMELEN);
145 /* Commented out because this setting isn't really appropriate to
146 * change while the server is running.
148 * snprintf(sc[52], sizeof sc[52], "%d", (boolprompt(
149 * "Use system authentication",
150 * atoi(&sc[52][0]))));
155 strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
156 strprompt("Maximum concurrent sessions", &sc[14][0], 4);
157 strprompt("Maximum message length", &sc[20][0], 20);
158 strprompt("Minimum number of worker threads", &sc[21][0], 3);
159 strprompt("Maximum number of worker threads", &sc[22][0], 3);
160 snprintf(sc[43], sizeof sc[43], "%d", (boolprompt(
161 "Automatically delete committed database logs",
164 strprompt("Server IP address (0.0.0.0 for 'any')", &sc[37][0], 15);
165 strprompt("POP3 server port (-1 to disable)", &sc[23][0], 5);
166 strprompt("POP3S server port (-1 to disable)", &sc[40][0], 5);
167 strprompt("IMAP server port (-1 to disable)", &sc[27][0], 5);
168 strprompt("IMAPS server port (-1 to disable)", &sc[39][0], 5);
169 strprompt("SMTP MTA server port (-1 to disable)", &sc[24][0], 5);
170 strprompt("SMTP MSA server port (-1 to disable)", &sc[38][0], 5);
171 strprompt("SMTPS server port (-1 to disable)", &sc[41][0], 5);
172 strprompt("Postfix TCP Dictionary Port server port (-1 to disable)", &sc[50][0], 5);
173 strprompt("ManageSieve server port (-1 to disable)", &sc[51][0], 5);
174 /* This logic flips the question around, because it's one of those
175 * situations where 0=yes and 1=no
179 a = boolprompt("Correct forged From: lines during authenticated SMTP",
182 snprintf(sc[25], sizeof sc[25], "%d", a);
183 snprintf(sc[45], sizeof sc[45], "%d", (boolprompt(
184 "Allow unauthenticated SMTP clients to spoof my domains",
186 snprintf(sc[57], sizeof sc[57], "%d", (boolprompt(
187 "Perform RBL checks at greeting instead of after RCPT",
189 snprintf(sc[44], sizeof sc[44], "%d", (boolprompt(
190 "Instantly expunge deleted IMAP messages",
194 if (ipc->ServInfo.supports_ldap) {
195 a = strlen(&sc[32][0]);
196 a = (a ? 1 : 0); /* Set only to 1 or 0 */
197 a = boolprompt("Connect this Citadel to an external LDAP directory", a);
199 strprompt("Host name of LDAP server",
201 strprompt("Port number of LDAP service",
203 strprompt("Base DN", &sc[34][0], 255);
204 strprompt("Bind DN", &sc[35][0], 255);
205 strprompt("Password for bind DN", &sc[36][0], 255);
208 strcpy(&sc[32][0], "");
212 /* Expiry settings */
213 strprompt("Default user purge time (days)", &sc[16][0], 5);
214 strprompt("Default room purge time (days)", &sc[17][0], 5);
216 /* Angels and demons dancing in my head... */
218 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_mode);
219 strprompt("System default message expire policy (? for list)",
223 "1. Never automatically expire messages\n"
224 "2. Expire by message count\n"
225 "3. Expire by message age\n");
227 } while ((buf[0] < '1') || (buf[0] > '3'));
228 site_expirepolicy->expire_mode = buf[0] - '0';
230 /* ...lunatics and monsters underneath my bed */
231 if (site_expirepolicy->expire_mode == 2) {
232 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
233 strprompt("Keep how many messages online?", buf, 10);
234 site_expirepolicy->expire_value = atol(buf);
236 if (site_expirepolicy->expire_mode == 3) {
237 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
238 strprompt("Keep messages for how many days?", buf, 10);
239 site_expirepolicy->expire_value = atol(buf);
242 /* Media messiahs preying on my fears... */
244 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_mode);
245 strprompt("Mailbox default message expire policy (? for list)",
249 "0. Go with the system default\n"
250 "1. Never automatically expire messages\n"
251 "2. Expire by message count\n"
252 "3. Expire by message age\n");
254 } while ((buf[0] < '0') || (buf[0] > '3'));
255 mbx_expirepolicy->expire_mode = buf[0] - '0';
257 /* ...Pop culture prophets playing in my ears */
258 if (mbx_expirepolicy->expire_mode == 2) {
259 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
260 strprompt("Keep how many messages online?", buf, 10);
261 mbx_expirepolicy->expire_value = atol(buf);
263 if (mbx_expirepolicy->expire_mode == 3) {
264 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
265 strprompt("Keep messages for how many days?", buf, 10);
266 mbx_expirepolicy->expire_value = atol(buf);
269 strprompt("How often to run network jobs (in seconds)", &sc[28][0], 5);
270 strprompt("Hour to run purges (0-23)", &sc[31][0], 2);
271 snprintf(sc[42], sizeof sc[42], "%d", (boolprompt(
272 "Enable full text search index (warning: resource intensive)",
275 snprintf(sc[46], sizeof sc[46], "%d", (boolprompt(
276 "Perform journaling of email messages",
278 snprintf(sc[47], sizeof sc[47], "%d", (boolprompt(
279 "Perform journaling of non-email messages",
281 if ( (atoi(&sc[46][0])) || (atoi(&sc[47][0])) ) {
282 strprompt("Email destination of journalized messages",
286 /* Funambol push stuff */
287 int yes_funambol = 0;
288 if (strlen(sc[53]) > 0) yes_funambol = 1;
289 yes_funambol = boolprompt("Connect to an external Funambol sync server", yes_funambol);
291 strprompt("Funambol server (blank to disable)", &sc[53][0], 63);
292 strprompt("Funambol server port", &sc[54][0], 5);
293 strprompt("Funambol sync source", &sc[55][0], 63);
294 strprompt("Funambol authentication details (user:pass in Base64)", &sc[56][0],63);
303 /* External pager stuff */
305 if (strlen(sc[60]) > 0) yes_pager = 1;
306 yes_pager = boolprompt("Configure an external pager tool", yes_pager);
308 strprompt("External pager tool", &sc[60][0], 255);
314 /* Master user account */
316 if (strlen(sc[58]) > 0) yes_muacct = 1;
317 yes_muacct = boolprompt("Enable a 'master user' account", yes_muacct);
319 strprompt("Master user name", &sc[58][0], 31);
320 strprompt("Master user password", &sc[59][0], -31);
323 strcpy(&sc[58][0], "");
324 strcpy(&sc[59][0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
328 scr_printf("Save this configuration? ");
331 for (a = 0; a < NUM_CONFIGS; a++)
332 r += 1 + strlen(sc[a]);
333 resp = (char *)calloc(1, r);
335 err_printf("Can't save config - out of memory!\n");
338 for (a = 0; a < NUM_CONFIGS; a++) {
342 r = CtdlIPCSetSystemConfig(ipc, resp, buf);
344 err_printf("%s\n", buf);
348 r = CtdlIPCSetMessageExpirationPolicy(ipc, 2, site_expirepolicy, buf);
350 err_printf("%s\n", buf);
353 r = CtdlIPCSetMessageExpirationPolicy(ipc, 3, mbx_expirepolicy, buf);
355 err_printf("%s\n", buf);
359 if (site_expirepolicy) free(site_expirepolicy);
360 if (mbx_expirepolicy) free(mbx_expirepolicy);
365 * support function for do_internet_configuration()
367 void get_inet_rec_type(CtdlIPC *ipc, char *buf) {
370 keyopt(" <1> localhost (Alias for this computer)\n");
371 keyopt(" <2> gateway domain (Domain for all Citadel systems)\n");
372 keyopt(" <3> smart-host (Forward all outbound mail to this host)\n");
373 keyopt(" <4> directory (Consult the Global Address Book)\n");
374 keyopt(" <5> SpamAssassin (Address of SpamAssassin server)\n");
375 keyopt(" <6> RBL (domain suffix of spam hunting RBL)\n");
376 keyopt(" <7> masq domains (Domains as which users are allowed to masquerade)\n");
377 sel = intprompt("Which one", 1, 1, 6);
379 case 1: strcpy(buf, "localhost");
381 case 2: strcpy(buf, "gatewaydomain");
383 case 3: strcpy(buf, "smarthost");
385 case 4: strcpy(buf, "directory");
387 case 5: strcpy(buf, "spamassassin");
389 case 6: strcpy(buf, "rbl");
391 case 7: strcpy(buf, "masqdomain");
398 * Internet mail configuration
400 void do_internet_configuration(CtdlIPC *ipc)
413 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
415 while (!IsEmptyStr(resp)) {
416 extract_token(buf, resp, 0, '\n', sizeof buf);
417 remove_token(resp, 0, '\n');
419 if (num_recs == 1) recs = malloc(sizeof(char *));
420 else recs = realloc(recs, (sizeof(char *)) * num_recs);
421 recs[num_recs-1] = malloc(strlen(buf) + 1);
422 strcpy(recs[num_recs-1], buf);
425 if (resp) free(resp);
430 scr_printf("### Host or domain Record type \n");
432 scr_printf("--- -------------------------------------------------- --------------------\n");
433 for (i=0; i<num_recs; ++i) {
435 scr_printf("%3d ", i+1);
436 extract_token(buf, recs[i], 0, '|', sizeof buf);
438 scr_printf("%-50s ", buf);
439 extract_token(buf, recs[i], 1, '|', sizeof buf);
440 color(BRIGHT_MAGENTA);
441 scr_printf("%-20s\n", buf);
445 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
448 newprompt("Enter host name: ",
451 if (!IsEmptyStr(buf)) {
454 recs = malloc(sizeof(char *));
455 else recs = realloc(recs,
456 (sizeof(char *)) * num_recs);
458 get_inet_rec_type(ipc,
460 recs[num_recs-1] = strdup(buf);
465 i = intprompt("Delete which one",
469 for (j=i; j<num_recs; ++j)
475 for (i = 0; i < num_recs; i++)
476 r += 1 + strlen(recs[i]);
477 resp = (char *)calloc(1, r);
479 err_printf("Can't save config - out of memory!\n");
482 if (num_recs) for (i = 0; i < num_recs; i++) {
483 strcat(resp, recs[i]);
486 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
488 err_printf("%s\n", buf);
490 scr_printf("Wrote %d records.\n", num_recs);
496 quitting = !modified || boolprompt(
497 "Quit without saving", 0);
505 for (i=0; i<num_recs; ++i) free(recs[i]);
513 * Edit network configuration for room sharing, mailing lists, etc.
515 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
517 char filename[PATH_MAX];
518 char changefile[PATH_MAX];
528 char *listing = NULL;
531 if (IsEmptyStr(editor_paths[0])) {
532 scr_printf("You must have an external editor configured in"
533 " order to use this function.\n");
537 CtdlMakeTempFileName(filename, sizeof filename);
538 CtdlMakeTempFileName(changefile, sizeof changefile);
540 tempfp = fopen(filename, "w");
541 if (tempfp == NULL) {
542 err_printf("Cannot open %s: %s\n", filename, strerror(errno));
546 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
547 fprintf(tempfp, "# %s\n", comment);
548 fprintf(tempfp, "# Specify one per line.\n"
551 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
553 while(listing && !IsEmptyStr(listing)) {
554 extract_token(buf, listing, 0, '\n', sizeof buf);
555 remove_token(listing, 0, '\n');
556 extract_token(instr, buf, 0, '|', sizeof instr);
557 if (!strcasecmp(instr, entrytype)) {
558 tokens = num_tokens(buf, '|');
559 for (i=1; i<tokens; ++i) {
560 extract_token(addr, buf, i, '|', sizeof addr);
561 fprintf(tempfp, "%s", addr);
562 if (i < (tokens-1)) {
563 fprintf(tempfp, "|");
566 fprintf(tempfp, "\n");
576 e_ex_code = 1; /* start with a failed exit code */
578 stty_ctdl(SB_RESTORE);
580 cksum = file_checksum(filename);
581 if (editor_pid == 0) {
582 chmod(filename, 0600);
583 putenv("WINDOW_TITLE=Network configuration");
584 execlp(editor_paths[0], editor_paths[0], filename, NULL);
587 if (editor_pid > 0) {
590 b = ka_wait(&e_ex_code);
591 } while ((b != editor_pid) && (b >= 0));
597 if (file_checksum(filename) == cksum) {
598 err_printf("*** No changes to save.\n");
602 if (e_ex_code == 0) { /* Save changes */
603 changefp = fopen(changefile, "w");
605 /* Load all netconfig entries that are *not* of the type we are editing */
606 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
608 while(listing && !IsEmptyStr(listing)) {
609 extract_token(buf, listing, 0, '\n', sizeof buf);
610 remove_token(listing, 0, '\n');
611 extract_token(instr, buf, 0, '|', sizeof instr);
612 if (strcasecmp(instr, entrytype)) {
613 fprintf(changefp, "%s\n", buf);
622 /* ...and merge that with the data we just edited */
623 tempfp = fopen(filename, "r");
624 while (fgets(buf, sizeof buf, tempfp) != NULL) {
625 for (i=0; i<strlen(buf); ++i) {
626 if (buf[i] == '#') buf[i] = 0;
629 if (!IsEmptyStr(buf)) {
630 fprintf(changefp, "%s|%s\n", entrytype, buf);
636 /* now write it to the server... */
637 changefp = fopen(changefile, "r");
638 if (changefp != NULL) {
639 listing = load_message_from_file(changefp);
641 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
649 unlink(filename); /* Delete the temporary files */
655 * IGnet node configuration
657 void do_ignet_configuration(CtdlIPC *ipc) {
666 char *listing = NULL;
669 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
670 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
671 extract_token(buf, listing, 0, '\n', sizeof buf);
672 remove_token(listing, 0, '\n');
675 if (num_recs == 1) recs = malloc(sizeof(char *));
676 else recs = realloc(recs, (sizeof(char *)) * num_recs);
677 recs[num_recs-1] = malloc(SIZ);
678 strcpy(recs[num_recs-1], buf);
680 if (listing) free(listing);
693 "------------------ "
694 "-------------------------------- "
696 for (i=0; i<num_recs; ++i) {
698 scr_printf("%3d ", i+1);
699 extract_token(buf, recs[i], 0, '|', sizeof buf);
701 scr_printf("%-16s ", buf);
702 extract_token(buf, recs[i], 1, '|', sizeof buf);
703 color(BRIGHT_MAGENTA);
704 scr_printf("%-18s ", buf);
705 extract_token(buf, recs[i], 2, '|', sizeof buf);
707 scr_printf("%-32s ", buf);
708 extract_token(buf, recs[i], 3, '|', sizeof buf);
709 color(BRIGHT_MAGENTA);
710 scr_printf("%-3s\n", buf);
715 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
720 recs = malloc(sizeof(char *));
721 else recs = realloc(recs,
722 (sizeof(char *)) * num_recs);
723 newprompt("Enter node name : ", buf, 16);
725 newprompt("Enter shared secret: ",
726 &buf[strlen(buf)], 18);
728 newprompt("Enter host or IP : ",
729 &buf[strlen(buf)], 32);
731 strprompt("Enter port number : ",
732 &buf[strlen(buf)-3], 5);
733 recs[num_recs-1] = strdup(buf);
737 i = intprompt("Delete which one",
741 for (j=i; j<num_recs; ++j)
747 for (i = 0; i < num_recs; ++i)
748 r += 1 + strlen(recs[i]);
749 listing = (char*) calloc(1, r);
751 err_printf("Can't save config - out of memory!\n");
754 if (num_recs) for (i = 0; i < num_recs; ++i) {
755 strcat(listing, recs[i]);
756 strcat(listing, "\n");
758 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
760 scr_printf("%s\n", buf);
762 scr_printf("Wrote %d records.\n", num_recs);
768 quitting = !modified || boolprompt(
769 "Quit without saving", 0);
777 for (i=0; i<num_recs; ++i) free(recs[i]);
784 * Filter list configuration
786 void do_filterlist_configuration(CtdlIPC *ipc)
796 char *listing = NULL;
799 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
800 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
801 extract_token(buf, listing, 0, '\n', sizeof buf);
802 remove_token(listing, 0, '\n');
805 if (num_recs == 1) recs = malloc(sizeof(char *));
806 else recs = realloc(recs, (sizeof(char *)) * num_recs);
807 recs[num_recs-1] = malloc(SIZ);
808 strcpy(recs[num_recs-1], buf);
810 if (listing) free(listing);
822 "---------------------------- "
823 "---------------------------- "
826 for (i=0; i<num_recs; ++i) {
828 scr_printf("%3d ", i+1);
829 extract_token(buf, recs[i], 0, '|', sizeof buf);
831 scr_printf("%-28s ", buf);
832 extract_token(buf, recs[i], 1, '|', sizeof buf);
833 color(BRIGHT_MAGENTA);
834 scr_printf("%-28s ", buf);
835 extract_token(buf, recs[i], 2, '|', sizeof buf);
837 scr_printf("%-16s\n", buf);
838 extract_token(buf, recs[i], 3, '|', sizeof buf);
842 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
847 recs = malloc(sizeof(char *));
848 else recs = realloc(recs,
849 (sizeof(char *)) * num_recs);
850 newprompt("Enter user name: ", buf, 28);
852 newprompt("Enter room name: ",
853 &buf[strlen(buf)], 28);
855 newprompt("Enter node name: ",
856 &buf[strlen(buf)], 16);
858 recs[num_recs-1] = strdup(buf);
862 i = intprompt("Delete which one",
866 for (j=i; j<num_recs; ++j)
872 for (i = 0; i < num_recs; ++i)
873 r += 1 + strlen(recs[i]);
874 listing = (char*) calloc(1, r);
876 err_printf("Can't save config - out of memory!\n");
879 if (num_recs) for (i = 0; i < num_recs; ++i) {
880 strcat(listing, recs[i]);
881 strcat(listing, "\n");
883 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
885 scr_printf("%s\n", buf);
887 scr_printf("Wrote %d records.\n", num_recs);
893 quitting = !modified || boolprompt(
894 "Quit without saving", 0);
902 for (i=0; i<num_recs; ++i) free(recs[i]);
911 * POP3 aggregation client configuration
913 void do_pop3client_configuration(CtdlIPC *ipc)
923 char *listing = NULL;
924 char *other_listing = NULL;
928 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
930 while(listing && !IsEmptyStr(listing)) {
931 extract_token(buf, listing, 0, '\n', sizeof buf);
932 remove_token(listing, 0, '\n');
933 extract_token(instr, buf, 0, '|', sizeof instr);
934 if (!strcasecmp(instr, "pop3client")) {
937 if (num_recs == 1) recs = malloc(sizeof(char *));
938 else recs = realloc(recs, (sizeof(char *)) * num_recs);
939 recs[num_recs-1] = malloc(SIZ);
940 strcpy(recs[num_recs-1], buf);
960 "---------------------------- "
961 "---------------------------- "
964 for (i=0; i<num_recs; ++i) {
966 scr_printf("%3d ", i+1);
968 extract_token(buf, recs[i], 1, '|', sizeof buf);
970 scr_printf("%-28s ", buf);
972 extract_token(buf, recs[i], 2, '|', sizeof buf);
973 color(BRIGHT_MAGENTA);
974 scr_printf("%-28s ", buf);
977 scr_printf("%-15s\n", (extract_int(recs[i], 4) ? "Yes" : "No") );
981 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
986 recs = malloc(sizeof(char *));
989 recs = realloc(recs, (sizeof(char *)) * num_recs);
991 strcpy(buf, "pop3client|");
992 newprompt("Enter host name: ", &buf[strlen(buf)], 28);
994 newprompt("Enter user name: ", &buf[strlen(buf)], 28);
996 newprompt("Enter password : ", &buf[strlen(buf)], 16);
998 scr_printf("Keep messages on server instead of deleting them? ");
999 sprintf(&buf[strlen(buf)], "%d", yesno());
1001 recs[num_recs-1] = strdup(buf);
1005 i = intprompt("Delete which one",
1006 1, 1, num_recs) - 1;
1009 for (j=i; j<num_recs; ++j)
1010 recs[j] = recs[j+1];
1015 for (i = 0; i < num_recs; ++i) {
1016 r += 1 + strlen(recs[i]);
1018 listing = (char*) calloc(1, r);
1020 err_printf("Can't save config - out of memory!\n");
1023 if (num_recs) for (i = 0; i < num_recs; ++i) {
1024 strcat(listing, recs[i]);
1025 strcat(listing, "\n");
1028 /* Retrieve all the *other* records for merging */
1029 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1031 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1032 extract_token(buf, other_listing, i, '\n', sizeof buf);
1033 if (strncasecmp(buf, "pop3client|", 11)) {
1034 listing = realloc(listing, strlen(listing) +
1036 strcat(listing, buf);
1037 strcat(listing, "\n");
1041 free(other_listing);
1042 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1047 scr_printf("%s\n", buf);
1049 scr_printf("Wrote %d records.\n", num_recs);
1055 quitting = !modified || boolprompt(
1056 "Quit without saving", 0);
1061 } while (!quitting);
1064 for (i=0; i<num_recs; ++i) free(recs[i]);
1075 * RSS feed retrieval client configuration
1077 void do_rssclient_configuration(CtdlIPC *ipc)
1087 char *listing = NULL;
1088 char *other_listing = NULL;
1092 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1094 while(listing && !IsEmptyStr(listing)) {
1095 extract_token(buf, listing, 0, '\n', sizeof buf);
1096 remove_token(listing, 0, '\n');
1097 extract_token(instr, buf, 0, '|', sizeof instr);
1098 if (!strcasecmp(instr, "rssclient")) {
1101 if (num_recs == 1) recs = malloc(sizeof(char *));
1102 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1103 recs[num_recs-1] = malloc(SIZ);
1104 strcpy(recs[num_recs-1], buf);
1116 color(BRIGHT_WHITE);
1117 scr_printf("### Feed URL\n");
1120 "---------------------------------------------------------------------------"
1123 for (i=0; i<num_recs; ++i) {
1125 scr_printf("%3d ", i+1);
1127 extract_token(buf, recs[i], 1, '|', sizeof buf);
1129 scr_printf("%-75s\n", buf);
1134 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1138 if (num_recs == 1) {
1139 recs = malloc(sizeof(char *));
1142 recs = realloc(recs, (sizeof(char *)) * num_recs);
1144 strcpy(buf, "rssclient|");
1145 newprompt("Enter feed URL: ", &buf[strlen(buf)], 75);
1147 recs[num_recs-1] = strdup(buf);
1151 i = intprompt("Delete which one", 1, 1, num_recs) - 1;
1154 for (j=i; j<num_recs; ++j)
1155 recs[j] = recs[j+1];
1160 for (i = 0; i < num_recs; ++i) {
1161 r += 1 + strlen(recs[i]);
1163 listing = (char*) calloc(1, r);
1165 err_printf("Can't save config - out of memory!\n");
1168 if (num_recs) for (i = 0; i < num_recs; ++i) {
1169 strcat(listing, recs[i]);
1170 strcat(listing, "\n");
1173 /* Retrieve all the *other* records for merging */
1174 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1176 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1177 extract_token(buf, other_listing, i, '\n', sizeof buf);
1178 if (strncasecmp(buf, "rssclient|", 10)) {
1179 listing = realloc(listing, strlen(listing) +
1181 strcat(listing, buf);
1182 strcat(listing, "\n");
1186 free(other_listing);
1187 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1192 scr_printf("%s\n", buf);
1194 scr_printf("Wrote %d records.\n", num_recs);
1200 quitting = !modified || boolprompt(
1201 "Quit without saving", 0);
1206 } while (!quitting);
1209 for (i=0; i<num_recs; ++i) free(recs[i]);