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, 8);
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)
442 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
444 while (!IsEmptyStr(resp)) {
445 extract_token(buf, resp, 0, '\n', sizeof buf);
446 remove_token(resp, 0, '\n');
448 if (num_recs == 1) recs = malloc(sizeof(char *));
449 else recs = realloc(recs, (sizeof(char *)) * num_recs);
450 recs[num_recs-1] = malloc(strlen(buf) + 1);
451 strcpy(recs[num_recs-1], buf);
454 if (resp) free(resp);
459 scr_printf("### Host or domain Record type \n");
461 scr_printf("--- -------------------------------------------------- --------------------\n");
462 for (i=0; i<num_recs; ++i) {
464 scr_printf("%3d ", i+1);
465 extract_token(buf, recs[i], 0, '|', sizeof buf);
467 scr_printf("%-50s ", buf);
468 extract_token(buf, recs[i], 1, '|', sizeof buf);
469 color(BRIGHT_MAGENTA);
470 scr_printf("%-20s\n", buf);
474 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
477 newprompt("Enter host name: ",
480 if (!IsEmptyStr(buf)) {
483 recs = malloc(sizeof(char *));
484 else recs = realloc(recs,
485 (sizeof(char *)) * num_recs);
487 get_inet_rec_type(ipc,
489 recs[num_recs-1] = strdup(buf);
494 i = intprompt("Delete which one",
498 for (j=i; j<num_recs; ++j)
504 for (i = 0; i < num_recs; i++)
505 r += 1 + strlen(recs[i]);
506 resp = (char *)calloc(1, r);
508 scr_printf("Can't save config - out of memory!\n");
511 if (num_recs) for (i = 0; i < num_recs; i++) {
512 strcat(resp, recs[i]);
515 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
517 scr_printf("%s\n", buf);
519 scr_printf("Wrote %d records.\n", num_recs);
525 quitting = !modified || boolprompt(
526 "Quit without saving", 0);
534 for (i=0; i<num_recs; ++i) free(recs[i]);
542 * Edit network configuration for room sharing, mailing lists, etc.
544 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
546 char filename[PATH_MAX];
547 char changefile[PATH_MAX];
557 char *listing = NULL;
560 if (IsEmptyStr(editor_paths[0])) {
561 scr_printf("You must have an external editor configured in"
562 " order to use this function.\n");
566 CtdlMakeTempFileName(filename, sizeof filename);
567 CtdlMakeTempFileName(changefile, sizeof changefile);
569 tempfp = fopen(filename, "w");
570 if (tempfp == NULL) {
571 scr_printf("Cannot open %s: %s\n", filename, strerror(errno));
575 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
576 fprintf(tempfp, "# %s\n", comment);
577 fprintf(tempfp, "# Specify one per line.\n"
580 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
582 while(listing && !IsEmptyStr(listing)) {
583 extract_token(buf, listing, 0, '\n', sizeof buf);
584 remove_token(listing, 0, '\n');
585 extract_token(instr, buf, 0, '|', sizeof instr);
586 if (!strcasecmp(instr, entrytype)) {
587 tokens = num_tokens(buf, '|');
588 for (i=1; i<tokens; ++i) {
589 extract_token(addr, buf, i, '|', sizeof addr);
590 fprintf(tempfp, "%s", addr);
591 if (i < (tokens-1)) {
592 fprintf(tempfp, "|");
595 fprintf(tempfp, "\n");
605 e_ex_code = 1; /* start with a failed exit code */
606 stty_ctdl(SB_RESTORE);
608 cksum = file_checksum(filename);
609 if (editor_pid == 0) {
610 chmod(filename, 0600);
611 putenv("WINDOW_TITLE=Network configuration");
612 execlp(editor_paths[0], editor_paths[0], filename, NULL);
615 if (editor_pid > 0) {
618 b = ka_wait(&e_ex_code);
619 } while ((b != editor_pid) && (b >= 0));
624 if (file_checksum(filename) == cksum) {
625 scr_printf("*** No changes to save.\n");
629 if (e_ex_code == 0) { /* Save changes */
630 changefp = fopen(changefile, "w");
632 /* Load all netconfig entries that are *not* of the type we are editing */
633 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
635 while(listing && !IsEmptyStr(listing)) {
636 extract_token(buf, listing, 0, '\n', sizeof buf);
637 remove_token(listing, 0, '\n');
638 extract_token(instr, buf, 0, '|', sizeof instr);
639 if (strcasecmp(instr, entrytype)) {
640 fprintf(changefp, "%s\n", buf);
649 /* ...and merge that with the data we just edited */
650 tempfp = fopen(filename, "r");
651 while (fgets(buf, sizeof buf, tempfp) != NULL) {
652 for (i=0; i<strlen(buf); ++i) {
653 if (buf[i] == '#') buf[i] = 0;
656 if (!IsEmptyStr(buf)) {
657 fprintf(changefp, "%s|%s\n", entrytype, buf);
663 /* now write it to the server... */
664 changefp = fopen(changefile, "r");
665 if (changefp != NULL) {
666 listing = load_message_from_file(changefp);
668 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
676 unlink(filename); /* Delete the temporary files */
682 * IGnet node configuration
684 void do_ignet_configuration(CtdlIPC *ipc) {
692 char *listing = NULL;
695 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
696 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
697 extract_token(buf, listing, 0, '\n', sizeof buf);
698 remove_token(listing, 0, '\n');
701 if (num_recs == 1) recs = malloc(sizeof(char *));
702 else recs = realloc(recs, (sizeof(char *)) * num_recs);
703 recs[num_recs-1] = malloc(SIZ);
704 strcpy(recs[num_recs-1], buf);
706 if (listing) free(listing);
719 "------------------ "
720 "-------------------------------- "
722 for (i=0; i<num_recs; ++i) {
724 scr_printf("%3d ", i+1);
725 extract_token(buf, recs[i], 0, '|', sizeof buf);
727 scr_printf("%-16s ", buf);
728 extract_token(buf, recs[i], 1, '|', sizeof buf);
729 color(BRIGHT_MAGENTA);
730 scr_printf("%-18s ", buf);
731 extract_token(buf, recs[i], 2, '|', sizeof buf);
733 scr_printf("%-32s ", buf);
734 extract_token(buf, recs[i], 3, '|', sizeof buf);
735 color(BRIGHT_MAGENTA);
736 scr_printf("%-3s\n", buf);
741 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
746 recs = malloc(sizeof(char *));
747 else recs = realloc(recs,
748 (sizeof(char *)) * num_recs);
749 newprompt("Enter node name : ", buf, 16);
751 newprompt("Enter shared secret: ",
752 &buf[strlen(buf)], 18);
754 newprompt("Enter host or IP : ",
755 &buf[strlen(buf)], 32);
757 strprompt("Enter port number : ",
758 &buf[strlen(buf)-3], 5);
759 recs[num_recs-1] = strdup(buf);
763 i = intprompt("Delete which one",
767 for (j=i; j<num_recs; ++j)
773 for (i = 0; i < num_recs; ++i)
774 r += 1 + strlen(recs[i]);
775 listing = (char*) calloc(1, r);
777 scr_printf("Can't save config - out of memory!\n");
780 if (num_recs) for (i = 0; i < num_recs; ++i) {
781 strcat(listing, recs[i]);
782 strcat(listing, "\n");
784 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
786 scr_printf("%s\n", buf);
788 scr_printf("Wrote %d records.\n", num_recs);
794 quitting = !modified || boolprompt(
795 "Quit without saving", 0);
803 for (i=0; i<num_recs; ++i) free(recs[i]);
810 * Filter list configuration
812 void do_filterlist_configuration(CtdlIPC *ipc)
821 char *listing = NULL;
824 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
825 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
826 extract_token(buf, listing, 0, '\n', sizeof buf);
827 remove_token(listing, 0, '\n');
830 if (num_recs == 1) recs = malloc(sizeof(char *));
831 else recs = realloc(recs, (sizeof(char *)) * num_recs);
832 recs[num_recs-1] = malloc(SIZ);
833 strcpy(recs[num_recs-1], buf);
835 if (listing) free(listing);
847 "---------------------------- "
848 "---------------------------- "
851 for (i=0; i<num_recs; ++i) {
853 scr_printf("%3d ", i+1);
854 extract_token(buf, recs[i], 0, '|', sizeof buf);
856 scr_printf("%-28s ", buf);
857 extract_token(buf, recs[i], 1, '|', sizeof buf);
858 color(BRIGHT_MAGENTA);
859 scr_printf("%-28s ", buf);
860 extract_token(buf, recs[i], 2, '|', sizeof buf);
862 scr_printf("%-16s\n", buf);
863 extract_token(buf, recs[i], 3, '|', sizeof buf);
867 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
872 recs = malloc(sizeof(char *));
873 else recs = realloc(recs,
874 (sizeof(char *)) * num_recs);
875 newprompt("Enter user name: ", buf, 28);
877 newprompt("Enter room name: ",
878 &buf[strlen(buf)], 28);
880 newprompt("Enter node name: ",
881 &buf[strlen(buf)], 16);
883 recs[num_recs-1] = strdup(buf);
887 i = intprompt("Delete which one",
891 for (j=i; j<num_recs; ++j)
897 for (i = 0; i < num_recs; ++i)
898 r += 1 + strlen(recs[i]);
899 listing = (char*) calloc(1, r);
901 scr_printf("Can't save config - out of memory!\n");
904 if (num_recs) for (i = 0; i < num_recs; ++i) {
905 strcat(listing, recs[i]);
906 strcat(listing, "\n");
908 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
910 scr_printf("%s\n", buf);
912 scr_printf("Wrote %d records.\n", num_recs);
918 quitting = !modified || boolprompt(
919 "Quit without saving", 0);
927 for (i=0; i<num_recs; ++i) free(recs[i]);
936 * POP3 aggregation client configuration
938 void do_pop3client_configuration(CtdlIPC *ipc)
947 char *listing = NULL;
948 char *other_listing = NULL;
952 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
954 while(listing && !IsEmptyStr(listing)) {
955 extract_token(buf, listing, 0, '\n', sizeof buf);
956 remove_token(listing, 0, '\n');
957 extract_token(instr, buf, 0, '|', sizeof instr);
958 if (!strcasecmp(instr, "pop3client")) {
961 if (num_recs == 1) recs = malloc(sizeof(char *));
962 else recs = realloc(recs, (sizeof(char *)) * num_recs);
963 recs[num_recs-1] = malloc(SIZ);
964 strcpy(recs[num_recs-1], buf);
985 "---------------------------- "
986 "---------------------------- "
990 for (i=0; i<num_recs; ++i) {
992 scr_printf("%3d ", i+1);
994 extract_token(buf, recs[i], 1, '|', sizeof buf);
996 scr_printf("%-28s ", buf);
998 extract_token(buf, recs[i], 2, '|', sizeof buf);
999 color(BRIGHT_MAGENTA);
1000 scr_printf("%-28s ", buf);
1003 scr_printf("%-15s ", (extract_int(recs[i], 4) ? "Yes" : "No") );
1004 color(BRIGHT_MAGENTA);
1005 scr_printf("%ld\n", extract_long(recs[i], 5) );
1009 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1013 if (num_recs == 1) {
1014 recs = malloc(sizeof(char *));
1017 recs = realloc(recs, (sizeof(char *)) * num_recs);
1019 strcpy(buf, "pop3client|");
1020 newprompt("Enter host name: ", &buf[strlen(buf)], 28);
1022 newprompt("Enter user name: ", &buf[strlen(buf)], 28);
1024 newprompt("Enter password : ", &buf[strlen(buf)], 16);
1026 scr_printf("Keep messages on server instead of deleting them? ");
1027 sprintf(&buf[strlen(buf)], "%d", yesno());
1029 newprompt("Enter interval : ", &buf[strlen(buf)], 5);
1031 recs[num_recs-1] = strdup(buf);
1035 i = intprompt("Delete which one",
1036 1, 1, num_recs) - 1;
1039 for (j=i; j<num_recs; ++j)
1040 recs[j] = recs[j+1];
1045 for (i = 0; i < num_recs; ++i) {
1046 r += 1 + strlen(recs[i]);
1048 listing = (char*) calloc(1, r);
1050 scr_printf("Can't save config - out of memory!\n");
1053 if (num_recs) for (i = 0; i < num_recs; ++i) {
1054 strcat(listing, recs[i]);
1055 strcat(listing, "\n");
1058 /* Retrieve all the *other* records for merging */
1059 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1061 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1062 extract_token(buf, other_listing, i, '\n', sizeof buf);
1063 if (strncasecmp(buf, "pop3client|", 11)) {
1064 listing = realloc(listing, strlen(listing) +
1066 strcat(listing, buf);
1067 strcat(listing, "\n");
1071 free(other_listing);
1072 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1077 scr_printf("%s\n", buf);
1079 scr_printf("Wrote %d records.\n", num_recs);
1085 quitting = !modified || boolprompt(
1086 "Quit without saving", 0);
1091 } while (!quitting);
1094 for (i=0; i<num_recs; ++i) free(recs[i]);
1105 * RSS feed retrieval client configuration
1107 void do_rssclient_configuration(CtdlIPC *ipc)
1116 char *listing = NULL;
1117 char *other_listing = NULL;
1121 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1123 while(listing && !IsEmptyStr(listing)) {
1124 extract_token(buf, listing, 0, '\n', sizeof buf);
1125 remove_token(listing, 0, '\n');
1126 extract_token(instr, buf, 0, '|', sizeof instr);
1127 if (!strcasecmp(instr, "rssclient")) {
1130 if (num_recs == 1) recs = malloc(sizeof(char *));
1131 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1132 recs[num_recs-1] = malloc(SIZ);
1133 strcpy(recs[num_recs-1], buf);
1145 color(BRIGHT_WHITE);
1146 scr_printf("### Feed URL\n");
1149 "---------------------------------------------------------------------------"
1152 for (i=0; i<num_recs; ++i) {
1154 scr_printf("%3d ", i+1);
1156 extract_token(buf, recs[i], 1, '|', sizeof buf);
1158 scr_printf("%-75s\n", buf);
1163 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1167 if (num_recs == 1) {
1168 recs = malloc(sizeof(char *));
1171 recs = realloc(recs, (sizeof(char *)) * num_recs);
1173 strcpy(buf, "rssclient|");
1174 newprompt("Enter feed URL: ", &buf[strlen(buf)], 75);
1176 recs[num_recs-1] = strdup(buf);
1180 i = intprompt("Delete which one", 1, 1, num_recs) - 1;
1183 for (j=i; j<num_recs; ++j)
1184 recs[j] = recs[j+1];
1189 for (i = 0; i < num_recs; ++i) {
1190 r += 1 + strlen(recs[i]);
1192 listing = (char*) calloc(1, r);
1194 scr_printf("Can't save config - out of memory!\n");
1197 if (num_recs) for (i = 0; i < num_recs; ++i) {
1198 strcat(listing, recs[i]);
1199 strcat(listing, "\n");
1202 /* Retrieve all the *other* records for merging */
1203 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1205 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1206 extract_token(buf, other_listing, i, '\n', sizeof buf);
1207 if (strncasecmp(buf, "rssclient|", 10)) {
1208 listing = realloc(listing, strlen(listing) +
1210 strcat(listing, buf);
1211 strcat(listing, "\n");
1215 free(other_listing);
1216 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1221 scr_printf("%s\n", buf);
1223 scr_printf("Wrote %d records.\n", num_recs);
1229 quitting = !modified || boolprompt(
1230 "Quit without saving", 0);
1235 } while (!quitting);
1238 for (i=0; i<num_recs; ++i) free(recs[i]);