2 * Configuration screens that are part of the text mode client.
16 #if TIME_WITH_SYS_TIME
17 # include <sys/time.h>
21 # include <sys/time.h>
31 #include <libcitadel.h>
34 #include "citadel_ipc.h"
35 #include "citadel_decls.h"
36 #include "tuiconfig.h"
45 /* work around solaris include files */
51 extern char tempdir[];
52 extern char *axdefs[8];
53 extern long highest_msg_read;
54 extern long maxmsgnum;
55 extern unsigned room_flags;
56 extern int screenwidth;
60 * General system configuration command
62 void do_system_configuration(CtdlIPC *ipc)
65 #define NUM_CONFIGS 68
68 char sc[NUM_CONFIGS][256];
70 struct ExpirePolicy *site_expirepolicy = NULL;
71 struct ExpirePolicy *mbx_expirepolicy = NULL;
74 int r; /* IPC response code */
75 int server_configs = 0;
77 /* Clear out the config buffers */
78 memset(&sc[0][0], 0, sizeof(sc));
80 /* Fetch the current config */
81 r = CtdlIPCGetSystemConfig(ipc, &resp, buf);
83 server_configs = num_tokens(resp, '\n');
84 for (a=0; a<server_configs; ++a) {
85 if (a < NUM_CONFIGS) {
86 extract_token(&sc[a][0], resp, a, '\n', sizeof sc[a]);
92 /* Fetch the expire policy (this will silently fail on old servers,
93 * resulting in "default" policy)
95 r = CtdlIPCGetMessageExpirationPolicy(ipc, 2, &site_expirepolicy, buf);
96 r = CtdlIPCGetMessageExpirationPolicy(ipc, 3, &mbx_expirepolicy, buf);
98 /* Identification parameters */
100 strprompt("Node name", &sc[0][0], 15);
101 strprompt("Fully qualified domain name", &sc[1][0], 63);
102 strprompt("Human readable node name", &sc[2][0], 20);
103 strprompt("Telephone number", &sc[3][0], 15);
104 strprompt("Geographic location of this system", &sc[12][0], 31);
105 strprompt("Name of system administrator", &sc[13][0], 25);
106 strprompt("Paginator prompt", &sc[10][0], 79);
108 /* Security parameters */
110 snprintf(sc[7], sizeof sc[7], "%d", (boolprompt(
111 "Require registration for new users",
113 snprintf(sc[29], sizeof sc[29], "%d", (boolprompt(
114 "Disable self-service user account creation",
116 strprompt("Initial access level for new users", &sc[6][0], 1);
117 strprompt("Access level required to create rooms", &sc[19][0], 1);
118 snprintf(sc[67], sizeof sc[67], "%d", (boolprompt(
119 "Allow anonymous guest logins",
121 snprintf(sc[4], sizeof sc[4], "%d", (boolprompt(
122 "Automatically give room aide privs to a user who creates a private room",
125 snprintf(sc[8], sizeof sc[8], "%d", (boolprompt(
126 "Automatically move problem user messages to twit room",
129 strprompt("Name of twit room", &sc[9][0], ROOMNAMELEN);
130 snprintf(sc[11], sizeof sc[11], "%d", (boolprompt(
131 "Restrict Internet mail to only those with that privilege",
133 snprintf(sc[26], sizeof sc[26], "%d", (boolprompt(
134 "Allow Aides to Zap (forget) rooms",
137 if (!IsEmptyStr(&sc[18][0])) {
143 logpages = boolprompt("Log all instant messages", logpages);
145 strprompt("Name of logging room", &sc[18][0], ROOMNAMELEN);
151 /* Commented out because this setting isn't really appropriate to
152 * change while the server is running.
154 * snprintf(sc[52], sizeof sc[52], "%d", (boolprompt(
155 * "Use system authentication",
156 * atoi(&sc[52][0]))));
161 strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
162 strprompt("Maximum concurrent sessions", &sc[14][0], 4);
163 strprompt("Maximum message length", &sc[20][0], 20);
164 strprompt("Minimum number of worker threads", &sc[21][0], 3);
165 strprompt("Maximum number of worker threads", &sc[22][0], 3);
166 snprintf(sc[43], sizeof sc[43], "%d", (boolprompt(
167 "Automatically delete committed database logs",
170 strprompt("Server IP address (* for 'any')", &sc[37][0], 15);
171 strprompt("POP3 server port (-1 to disable)", &sc[23][0], 5);
172 strprompt("POP3S server port (-1 to disable)", &sc[40][0], 5);
173 strprompt("IMAP server port (-1 to disable)", &sc[27][0], 5);
174 strprompt("IMAPS server port (-1 to disable)", &sc[39][0], 5);
175 strprompt("SMTP MTA server port (-1 to disable)", &sc[24][0], 5);
176 strprompt("SMTP MSA server port (-1 to disable)", &sc[38][0], 5);
177 strprompt("SMTPS server port (-1 to disable)", &sc[41][0], 5);
178 strprompt("Postfix TCP Dictionary Port server port (-1 to disable)", &sc[50][0], 5);
179 strprompt("ManageSieve server port (-1 to disable)", &sc[51][0], 5);
181 strprompt("XMPP (Jabber) client to server port (-1 to disable)", &sc[62][0], 5);
182 /* No prompt because we don't implement this service yet, it's just a placeholder */
183 /* strprompt("XMPP (Jabber) server to server port (-1 to disable)", &sc[63][0], 5); */
185 /* This logic flips the question around, because it's one of those
186 * situations where 0=yes and 1=no
190 a = boolprompt("Correct forged From: lines during authenticated SMTP",
193 snprintf(sc[25], sizeof sc[25], "%d", a);
195 snprintf(sc[66], sizeof sc[66], "%d", (boolprompt(
196 "Flag messages as spam instead of rejecting",
199 /* This logic flips the question around, because it's one of those
200 * situations where 0=yes and 1=no
204 a = boolprompt("Force IMAP posts in public rooms to be from the user who submitted them", a);
206 snprintf(sc[61], sizeof sc[61], "%d", a);
208 snprintf(sc[45], sizeof sc[45], "%d", (boolprompt(
209 "Allow unauthenticated SMTP clients to spoof my domains",
211 snprintf(sc[57], sizeof sc[57], "%d", (boolprompt(
212 "Perform RBL checks at greeting instead of after RCPT",
214 snprintf(sc[44], sizeof sc[44], "%d", (boolprompt(
215 "Instantly expunge deleted IMAP messages",
219 if (ipc->ServInfo.supports_ldap) {
220 a = strlen(&sc[32][0]);
221 a = (a ? 1 : 0); /* Set only to 1 or 0 */
222 a = boolprompt("Do you want to configure LDAP authentication?", a);
224 strprompt("Host name of LDAP server",
226 strprompt("Port number of LDAP service",
228 strprompt("Base DN", &sc[34][0], 255);
229 strprompt("Bind DN (or blank for anonymous bind)", &sc[35][0], 255);
230 strprompt("Password for bind DN (or blank for anonymous bind)", &sc[36][0], 255);
233 strcpy(&sc[32][0], "");
237 /* Expiry settings */
238 strprompt("Default user purge time (days)", &sc[16][0], 5);
239 strprompt("Default room purge time (days)", &sc[17][0], 5);
241 /* Angels and demons dancing in my head... */
243 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_mode);
244 strprompt("System default message expire policy (? for list)",
248 "1. Never automatically expire messages\n"
249 "2. Expire by message count\n"
250 "3. Expire by message age\n");
252 } while ((buf[0] < '1') || (buf[0] > '3'));
253 site_expirepolicy->expire_mode = buf[0] - '0';
255 /* ...lunatics and monsters underneath my bed */
256 if (site_expirepolicy->expire_mode == 2) {
257 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
258 strprompt("Keep how many messages online?", buf, 10);
259 site_expirepolicy->expire_value = atol(buf);
261 if (site_expirepolicy->expire_mode == 3) {
262 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
263 strprompt("Keep messages for how many days?", buf, 10);
264 site_expirepolicy->expire_value = atol(buf);
267 /* Media messiahs preying on my fears... */
269 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_mode);
270 strprompt("Mailbox default message expire policy (? for list)",
274 "0. Go with the system default\n"
275 "1. Never automatically expire messages\n"
276 "2. Expire by message count\n"
277 "3. Expire by message age\n");
279 } while ((buf[0] < '0') || (buf[0] > '3'));
280 mbx_expirepolicy->expire_mode = buf[0] - '0';
282 /* ...Pop culture prophets playing in my ears */
283 if (mbx_expirepolicy->expire_mode == 2) {
284 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
285 strprompt("Keep how many messages online?", buf, 10);
286 mbx_expirepolicy->expire_value = atol(buf);
288 if (mbx_expirepolicy->expire_mode == 3) {
289 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
290 strprompt("Keep messages for how many days?", buf, 10);
291 mbx_expirepolicy->expire_value = atol(buf);
294 strprompt("How often to run network jobs (in seconds)", &sc[28][0], 5);
295 strprompt("Default frequency to run POP3 collection (in seconds)", &sc[64][0], 5);
296 strprompt("Fastest frequency to run POP3 collection (in seconds)", &sc[65][0], 5);
297 strprompt("Hour to run purges (0-23)", &sc[31][0], 2);
298 snprintf(sc[42], sizeof sc[42], "%d", (boolprompt(
299 "Enable full text search index (warning: resource intensive)",
302 snprintf(sc[46], sizeof sc[46], "%d", (boolprompt(
303 "Perform journaling of email messages",
305 snprintf(sc[47], sizeof sc[47], "%d", (boolprompt(
306 "Perform journaling of non-email messages",
308 if ( (atoi(&sc[46][0])) || (atoi(&sc[47][0])) ) {
309 strprompt("Email destination of journalized messages",
313 /* Funambol push stuff */
314 int yes_funambol = 0;
315 if (strlen(sc[53]) > 0) yes_funambol = 1;
316 yes_funambol = boolprompt("Connect to an external Funambol sync server", yes_funambol);
318 strprompt("Funambol server (blank to disable)", &sc[53][0], 63);
319 strprompt("Funambol server port", &sc[54][0], 5);
320 strprompt("Funambol sync source", &sc[55][0], 63);
321 strprompt("Funambol authentication details (user:pass in Base64)", &sc[56][0],63);
330 /* External pager stuff */
332 if (strlen(sc[60]) > 0) yes_pager = 1;
333 yes_pager = boolprompt("Configure an external pager tool", yes_pager);
335 strprompt("External pager tool", &sc[60][0], 255);
341 /* Master user account */
343 if (strlen(sc[58]) > 0) yes_muacct = 1;
344 yes_muacct = boolprompt("Enable a 'master user' account", yes_muacct);
346 strprompt("Master user name", &sc[58][0], 31);
347 strprompt("Master user password", &sc[59][0], -31);
350 strcpy(&sc[58][0], "");
351 strcpy(&sc[59][0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
355 scr_printf("Save this configuration? ");
358 for (a = 0; a < NUM_CONFIGS; a++)
359 r += 1 + strlen(sc[a]);
360 resp = (char *)calloc(1, r);
362 scr_printf("Can't save config - out of memory!\n");
365 for (a = 0; a < NUM_CONFIGS; a++) {
369 r = CtdlIPCSetSystemConfig(ipc, resp, buf);
371 scr_printf("%s\n", buf);
375 r = CtdlIPCSetMessageExpirationPolicy(ipc, 2, site_expirepolicy, buf);
377 scr_printf("%s\n", buf);
380 r = CtdlIPCSetMessageExpirationPolicy(ipc, 3, mbx_expirepolicy, buf);
382 scr_printf("%s\n", buf);
386 if (site_expirepolicy) free(site_expirepolicy);
387 if (mbx_expirepolicy) free(mbx_expirepolicy);
392 * support function for do_internet_configuration()
394 void get_inet_rec_type(CtdlIPC *ipc, char *buf) {
397 keyopt(" <1> localhost (Alias for this computer)\n");
398 keyopt(" <2> smart host (Forward all outbound mail to this host)\n");
399 keyopt(" <3> fallback host (Send mail to this host only if direct delivery fails)\n");
400 keyopt(" <4> directory (Consult the Global Address Book)\n");
401 keyopt(" <5> SpamAssassin (Address of SpamAssassin server)\n");
402 keyopt(" <6> RBL (domain suffix of spam hunting RBL)\n");
403 keyopt(" <7> masq domains (Domains as which users are allowed to masquerade)\n");
404 keyopt(" <8> ClamAV (Address of ClamAV clamd server)\n");
405 sel = intprompt("Which one", 1, 1, 7);
407 case 1: strcpy(buf, "localhost");
409 case 2: strcpy(buf, "smarthost");
411 case 3: strcpy(buf, "fallbackhost");
413 case 4: strcpy(buf, "directory");
415 case 5: strcpy(buf, "spamassassin");
417 case 6: strcpy(buf, "rbl");
419 case 7: strcpy(buf, "masqdomain");
421 case 8: strcpy(buf, "clamav");
428 * Internet mail configuration
430 void do_internet_configuration(CtdlIPC *ipc)
443 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
445 while (!IsEmptyStr(resp)) {
446 extract_token(buf, resp, 0, '\n', sizeof buf);
447 remove_token(resp, 0, '\n');
449 if (num_recs == 1) recs = malloc(sizeof(char *));
450 else recs = realloc(recs, (sizeof(char *)) * num_recs);
451 recs[num_recs-1] = malloc(strlen(buf) + 1);
452 strcpy(recs[num_recs-1], buf);
455 if (resp) free(resp);
460 scr_printf("### Host or domain Record type \n");
462 scr_printf("--- -------------------------------------------------- --------------------\n");
463 for (i=0; i<num_recs; ++i) {
465 scr_printf("%3d ", i+1);
466 extract_token(buf, recs[i], 0, '|', sizeof buf);
468 scr_printf("%-50s ", buf);
469 extract_token(buf, recs[i], 1, '|', sizeof buf);
470 color(BRIGHT_MAGENTA);
471 scr_printf("%-20s\n", buf);
475 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
478 newprompt("Enter host name: ",
481 if (!IsEmptyStr(buf)) {
484 recs = malloc(sizeof(char *));
485 else recs = realloc(recs,
486 (sizeof(char *)) * num_recs);
488 get_inet_rec_type(ipc,
490 recs[num_recs-1] = strdup(buf);
495 i = intprompt("Delete which one",
499 for (j=i; j<num_recs; ++j)
505 for (i = 0; i < num_recs; i++)
506 r += 1 + strlen(recs[i]);
507 resp = (char *)calloc(1, r);
509 scr_printf("Can't save config - out of memory!\n");
512 if (num_recs) for (i = 0; i < num_recs; i++) {
513 strcat(resp, recs[i]);
516 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
518 scr_printf("%s\n", buf);
520 scr_printf("Wrote %d records.\n", num_recs);
526 quitting = !modified || boolprompt(
527 "Quit without saving", 0);
535 for (i=0; i<num_recs; ++i) free(recs[i]);
543 * Edit network configuration for room sharing, mailing lists, etc.
545 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
547 char filename[PATH_MAX];
548 char changefile[PATH_MAX];
558 char *listing = NULL;
561 if (IsEmptyStr(editor_paths[0])) {
562 scr_printf("You must have an external editor configured in"
563 " order to use this function.\n");
567 CtdlMakeTempFileName(filename, sizeof filename);
568 CtdlMakeTempFileName(changefile, sizeof changefile);
570 tempfp = fopen(filename, "w");
571 if (tempfp == NULL) {
572 scr_printf("Cannot open %s: %s\n", filename, strerror(errno));
576 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
577 fprintf(tempfp, "# %s\n", comment);
578 fprintf(tempfp, "# Specify one per line.\n"
581 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
583 while(listing && !IsEmptyStr(listing)) {
584 extract_token(buf, listing, 0, '\n', sizeof buf);
585 remove_token(listing, 0, '\n');
586 extract_token(instr, buf, 0, '|', sizeof instr);
587 if (!strcasecmp(instr, entrytype)) {
588 tokens = num_tokens(buf, '|');
589 for (i=1; i<tokens; ++i) {
590 extract_token(addr, buf, i, '|', sizeof addr);
591 fprintf(tempfp, "%s", addr);
592 if (i < (tokens-1)) {
593 fprintf(tempfp, "|");
596 fprintf(tempfp, "\n");
606 e_ex_code = 1; /* start with a failed exit code */
608 stty_ctdl(SB_RESTORE);
610 cksum = file_checksum(filename);
611 if (editor_pid == 0) {
612 chmod(filename, 0600);
613 putenv("WINDOW_TITLE=Network configuration");
614 execlp(editor_paths[0], editor_paths[0], filename, NULL);
617 if (editor_pid > 0) {
620 b = ka_wait(&e_ex_code);
621 } while ((b != editor_pid) && (b >= 0));
627 if (file_checksum(filename) == cksum) {
628 scr_printf("*** No changes to save.\n");
632 if (e_ex_code == 0) { /* Save changes */
633 changefp = fopen(changefile, "w");
635 /* Load all netconfig entries that are *not* of the type we are editing */
636 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
638 while(listing && !IsEmptyStr(listing)) {
639 extract_token(buf, listing, 0, '\n', sizeof buf);
640 remove_token(listing, 0, '\n');
641 extract_token(instr, buf, 0, '|', sizeof instr);
642 if (strcasecmp(instr, entrytype)) {
643 fprintf(changefp, "%s\n", buf);
652 /* ...and merge that with the data we just edited */
653 tempfp = fopen(filename, "r");
654 while (fgets(buf, sizeof buf, tempfp) != NULL) {
655 for (i=0; i<strlen(buf); ++i) {
656 if (buf[i] == '#') buf[i] = 0;
659 if (!IsEmptyStr(buf)) {
660 fprintf(changefp, "%s|%s\n", entrytype, buf);
666 /* now write it to the server... */
667 changefp = fopen(changefile, "r");
668 if (changefp != NULL) {
669 listing = load_message_from_file(changefp);
671 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
679 unlink(filename); /* Delete the temporary files */
685 * IGnet node configuration
687 void do_ignet_configuration(CtdlIPC *ipc) {
696 char *listing = NULL;
699 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
700 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
701 extract_token(buf, listing, 0, '\n', sizeof buf);
702 remove_token(listing, 0, '\n');
705 if (num_recs == 1) recs = malloc(sizeof(char *));
706 else recs = realloc(recs, (sizeof(char *)) * num_recs);
707 recs[num_recs-1] = malloc(SIZ);
708 strcpy(recs[num_recs-1], buf);
710 if (listing) free(listing);
723 "------------------ "
724 "-------------------------------- "
726 for (i=0; i<num_recs; ++i) {
728 scr_printf("%3d ", i+1);
729 extract_token(buf, recs[i], 0, '|', sizeof buf);
731 scr_printf("%-16s ", buf);
732 extract_token(buf, recs[i], 1, '|', sizeof buf);
733 color(BRIGHT_MAGENTA);
734 scr_printf("%-18s ", buf);
735 extract_token(buf, recs[i], 2, '|', sizeof buf);
737 scr_printf("%-32s ", buf);
738 extract_token(buf, recs[i], 3, '|', sizeof buf);
739 color(BRIGHT_MAGENTA);
740 scr_printf("%-3s\n", buf);
745 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
750 recs = malloc(sizeof(char *));
751 else recs = realloc(recs,
752 (sizeof(char *)) * num_recs);
753 newprompt("Enter node name : ", buf, 16);
755 newprompt("Enter shared secret: ",
756 &buf[strlen(buf)], 18);
758 newprompt("Enter host or IP : ",
759 &buf[strlen(buf)], 32);
761 strprompt("Enter port number : ",
762 &buf[strlen(buf)-3], 5);
763 recs[num_recs-1] = strdup(buf);
767 i = intprompt("Delete which one",
771 for (j=i; j<num_recs; ++j)
777 for (i = 0; i < num_recs; ++i)
778 r += 1 + strlen(recs[i]);
779 listing = (char*) calloc(1, r);
781 scr_printf("Can't save config - out of memory!\n");
784 if (num_recs) for (i = 0; i < num_recs; ++i) {
785 strcat(listing, recs[i]);
786 strcat(listing, "\n");
788 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
790 scr_printf("%s\n", buf);
792 scr_printf("Wrote %d records.\n", num_recs);
798 quitting = !modified || boolprompt(
799 "Quit without saving", 0);
807 for (i=0; i<num_recs; ++i) free(recs[i]);
814 * Filter list configuration
816 void do_filterlist_configuration(CtdlIPC *ipc)
826 char *listing = NULL;
829 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
830 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
831 extract_token(buf, listing, 0, '\n', sizeof buf);
832 remove_token(listing, 0, '\n');
835 if (num_recs == 1) recs = malloc(sizeof(char *));
836 else recs = realloc(recs, (sizeof(char *)) * num_recs);
837 recs[num_recs-1] = malloc(SIZ);
838 strcpy(recs[num_recs-1], buf);
840 if (listing) free(listing);
852 "---------------------------- "
853 "---------------------------- "
856 for (i=0; i<num_recs; ++i) {
858 scr_printf("%3d ", i+1);
859 extract_token(buf, recs[i], 0, '|', sizeof buf);
861 scr_printf("%-28s ", buf);
862 extract_token(buf, recs[i], 1, '|', sizeof buf);
863 color(BRIGHT_MAGENTA);
864 scr_printf("%-28s ", buf);
865 extract_token(buf, recs[i], 2, '|', sizeof buf);
867 scr_printf("%-16s\n", buf);
868 extract_token(buf, recs[i], 3, '|', sizeof buf);
872 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
877 recs = malloc(sizeof(char *));
878 else recs = realloc(recs,
879 (sizeof(char *)) * num_recs);
880 newprompt("Enter user name: ", buf, 28);
882 newprompt("Enter room name: ",
883 &buf[strlen(buf)], 28);
885 newprompt("Enter node name: ",
886 &buf[strlen(buf)], 16);
888 recs[num_recs-1] = strdup(buf);
892 i = intprompt("Delete which one",
896 for (j=i; j<num_recs; ++j)
902 for (i = 0; i < num_recs; ++i)
903 r += 1 + strlen(recs[i]);
904 listing = (char*) calloc(1, r);
906 scr_printf("Can't save config - out of memory!\n");
909 if (num_recs) for (i = 0; i < num_recs; ++i) {
910 strcat(listing, recs[i]);
911 strcat(listing, "\n");
913 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
915 scr_printf("%s\n", buf);
917 scr_printf("Wrote %d records.\n", num_recs);
923 quitting = !modified || boolprompt(
924 "Quit without saving", 0);
932 for (i=0; i<num_recs; ++i) free(recs[i]);
941 * POP3 aggregation client configuration
943 void do_pop3client_configuration(CtdlIPC *ipc)
953 char *listing = NULL;
954 char *other_listing = NULL;
958 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
960 while(listing && !IsEmptyStr(listing)) {
961 extract_token(buf, listing, 0, '\n', sizeof buf);
962 remove_token(listing, 0, '\n');
963 extract_token(instr, buf, 0, '|', sizeof instr);
964 if (!strcasecmp(instr, "pop3client")) {
967 if (num_recs == 1) recs = malloc(sizeof(char *));
968 else recs = realloc(recs, (sizeof(char *)) * num_recs);
969 recs[num_recs-1] = malloc(SIZ);
970 strcpy(recs[num_recs-1], buf);
991 "---------------------------- "
992 "---------------------------- "
996 for (i=0; i<num_recs; ++i) {
998 scr_printf("%3d ", i+1);
1000 extract_token(buf, recs[i], 1, '|', sizeof buf);
1002 scr_printf("%-28s ", buf);
1004 extract_token(buf, recs[i], 2, '|', sizeof buf);
1005 color(BRIGHT_MAGENTA);
1006 scr_printf("%-28s ", buf);
1009 scr_printf("%-15s ", (extract_int(recs[i], 4) ? "Yes" : "No") );
1010 color(BRIGHT_MAGENTA);
1011 scr_printf("%ld\n", extract_long(recs[i], 5) );
1015 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1019 if (num_recs == 1) {
1020 recs = malloc(sizeof(char *));
1023 recs = realloc(recs, (sizeof(char *)) * num_recs);
1025 strcpy(buf, "pop3client|");
1026 newprompt("Enter host name: ", &buf[strlen(buf)], 28);
1028 newprompt("Enter user name: ", &buf[strlen(buf)], 28);
1030 newprompt("Enter password : ", &buf[strlen(buf)], 16);
1032 scr_printf("Keep messages on server instead of deleting them? ");
1033 sprintf(&buf[strlen(buf)], "%d", yesno());
1035 newprompt("Enter interval : ", &buf[strlen(buf)], 5);
1037 recs[num_recs-1] = strdup(buf);
1041 i = intprompt("Delete which one",
1042 1, 1, num_recs) - 1;
1045 for (j=i; j<num_recs; ++j)
1046 recs[j] = recs[j+1];
1051 for (i = 0; i < num_recs; ++i) {
1052 r += 1 + strlen(recs[i]);
1054 listing = (char*) calloc(1, r);
1056 scr_printf("Can't save config - out of memory!\n");
1059 if (num_recs) for (i = 0; i < num_recs; ++i) {
1060 strcat(listing, recs[i]);
1061 strcat(listing, "\n");
1064 /* Retrieve all the *other* records for merging */
1065 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1067 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1068 extract_token(buf, other_listing, i, '\n', sizeof buf);
1069 if (strncasecmp(buf, "pop3client|", 11)) {
1070 listing = realloc(listing, strlen(listing) +
1072 strcat(listing, buf);
1073 strcat(listing, "\n");
1077 free(other_listing);
1078 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1083 scr_printf("%s\n", buf);
1085 scr_printf("Wrote %d records.\n", num_recs);
1091 quitting = !modified || boolprompt(
1092 "Quit without saving", 0);
1097 } while (!quitting);
1100 for (i=0; i<num_recs; ++i) free(recs[i]);
1111 * RSS feed retrieval client configuration
1113 void do_rssclient_configuration(CtdlIPC *ipc)
1123 char *listing = NULL;
1124 char *other_listing = NULL;
1128 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1130 while(listing && !IsEmptyStr(listing)) {
1131 extract_token(buf, listing, 0, '\n', sizeof buf);
1132 remove_token(listing, 0, '\n');
1133 extract_token(instr, buf, 0, '|', sizeof instr);
1134 if (!strcasecmp(instr, "rssclient")) {
1137 if (num_recs == 1) recs = malloc(sizeof(char *));
1138 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1139 recs[num_recs-1] = malloc(SIZ);
1140 strcpy(recs[num_recs-1], buf);
1152 color(BRIGHT_WHITE);
1153 scr_printf("### Feed URL\n");
1156 "---------------------------------------------------------------------------"
1159 for (i=0; i<num_recs; ++i) {
1161 scr_printf("%3d ", i+1);
1163 extract_token(buf, recs[i], 1, '|', sizeof buf);
1165 scr_printf("%-75s\n", buf);
1170 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1174 if (num_recs == 1) {
1175 recs = malloc(sizeof(char *));
1178 recs = realloc(recs, (sizeof(char *)) * num_recs);
1180 strcpy(buf, "rssclient|");
1181 newprompt("Enter feed URL: ", &buf[strlen(buf)], 75);
1183 recs[num_recs-1] = strdup(buf);
1187 i = intprompt("Delete which one", 1, 1, num_recs) - 1;
1190 for (j=i; j<num_recs; ++j)
1191 recs[j] = recs[j+1];
1196 for (i = 0; i < num_recs; ++i) {
1197 r += 1 + strlen(recs[i]);
1199 listing = (char*) calloc(1, r);
1201 scr_printf("Can't save config - out of memory!\n");
1204 if (num_recs) for (i = 0; i < num_recs; ++i) {
1205 strcat(listing, recs[i]);
1206 strcat(listing, "\n");
1209 /* Retrieve all the *other* records for merging */
1210 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1212 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1213 extract_token(buf, other_listing, i, '\n', sizeof buf);
1214 if (strncasecmp(buf, "rssclient|", 10)) {
1215 listing = realloc(listing, strlen(listing) +
1217 strcat(listing, buf);
1218 strcat(listing, "\n");
1222 free(other_listing);
1223 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1228 scr_printf("%s\n", buf);
1230 scr_printf("Wrote %d records.\n", num_recs);
1236 quitting = !modified || boolprompt(
1237 "Quit without saving", 0);
1242 } while (!quitting);
1245 for (i=0; i<num_recs; ++i) free(recs[i]);