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 67
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);
175 strprompt("XMPP (Jabber) client to server port (-1 to disable)", &sc[62][0], 5);
176 strprompt("XMPP (Jabber) client to server SSL port (-1 to disable)", &sc[67][0], 5);
177 /* No prompt because we don't implement this service yet, it's just a placeholder */
178 /* strprompt("XMPP (Jabber) server to server port (-1 to disable)", &sc[63][0], 5); */
180 /* This logic flips the question around, because it's one of those
181 * situations where 0=yes and 1=no
185 a = boolprompt("Correct forged From: lines during authenticated SMTP",
188 snprintf(sc[25], sizeof sc[25], "%d", a);
190 snprintf(sc[66], sizeof sc[66], "%d", (boolprompt(
191 "Flag messages as spam instead of rejecting",
194 /* This logic flips the question around, because it's one of those
195 * situations where 0=yes and 1=no
199 a = boolprompt("Force IMAP posts in public rooms to be from the user who submitted them", a);
201 snprintf(sc[61], sizeof sc[61], "%d", a);
203 snprintf(sc[45], sizeof sc[45], "%d", (boolprompt(
204 "Allow unauthenticated SMTP clients to spoof my domains",
206 snprintf(sc[57], sizeof sc[57], "%d", (boolprompt(
207 "Perform RBL checks at greeting instead of after RCPT",
209 snprintf(sc[44], sizeof sc[44], "%d", (boolprompt(
210 "Instantly expunge deleted IMAP messages",
214 if (ipc->ServInfo.supports_ldap) {
215 a = strlen(&sc[32][0]);
216 a = (a ? 1 : 0); /* Set only to 1 or 0 */
217 a = boolprompt("Connect this Citadel to an external LDAP directory", a);
219 strprompt("Host name of LDAP server",
221 strprompt("Port number of LDAP service",
223 strprompt("Base DN", &sc[34][0], 255);
224 strprompt("Bind DN", &sc[35][0], 255);
225 strprompt("Password for bind DN", &sc[36][0], 255);
228 strcpy(&sc[32][0], "");
232 /* Expiry settings */
233 strprompt("Default user purge time (days)", &sc[16][0], 5);
234 strprompt("Default room purge time (days)", &sc[17][0], 5);
236 /* Angels and demons dancing in my head... */
238 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_mode);
239 strprompt("System default message expire policy (? for list)",
243 "1. Never automatically expire messages\n"
244 "2. Expire by message count\n"
245 "3. Expire by message age\n");
247 } while ((buf[0] < '1') || (buf[0] > '3'));
248 site_expirepolicy->expire_mode = buf[0] - '0';
250 /* ...lunatics and monsters underneath my bed */
251 if (site_expirepolicy->expire_mode == 2) {
252 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
253 strprompt("Keep how many messages online?", buf, 10);
254 site_expirepolicy->expire_value = atol(buf);
256 if (site_expirepolicy->expire_mode == 3) {
257 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
258 strprompt("Keep messages for how many days?", buf, 10);
259 site_expirepolicy->expire_value = atol(buf);
262 /* Media messiahs preying on my fears... */
264 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_mode);
265 strprompt("Mailbox default message expire policy (? for list)",
269 "0. Go with the system default\n"
270 "1. Never automatically expire messages\n"
271 "2. Expire by message count\n"
272 "3. Expire by message age\n");
274 } while ((buf[0] < '0') || (buf[0] > '3'));
275 mbx_expirepolicy->expire_mode = buf[0] - '0';
277 /* ...Pop culture prophets playing in my ears */
278 if (mbx_expirepolicy->expire_mode == 2) {
279 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
280 strprompt("Keep how many messages online?", buf, 10);
281 mbx_expirepolicy->expire_value = atol(buf);
283 if (mbx_expirepolicy->expire_mode == 3) {
284 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
285 strprompt("Keep messages for how many days?", buf, 10);
286 mbx_expirepolicy->expire_value = atol(buf);
289 strprompt("How often to run network jobs (in seconds)", &sc[28][0], 5);
290 strprompt("Default frequency to run POP3 collection (in seconds)", &sc[64][0], 5);
291 strprompt("Fastest frequency to run POP3 collection (in seconds)", &sc[65][0], 5);
292 strprompt("Hour to run purges (0-23)", &sc[31][0], 2);
293 snprintf(sc[42], sizeof sc[42], "%d", (boolprompt(
294 "Enable full text search index (warning: resource intensive)",
297 snprintf(sc[46], sizeof sc[46], "%d", (boolprompt(
298 "Perform journaling of email messages",
300 snprintf(sc[47], sizeof sc[47], "%d", (boolprompt(
301 "Perform journaling of non-email messages",
303 if ( (atoi(&sc[46][0])) || (atoi(&sc[47][0])) ) {
304 strprompt("Email destination of journalized messages",
308 /* Funambol push stuff */
309 int yes_funambol = 0;
310 if (strlen(sc[53]) > 0) yes_funambol = 1;
311 yes_funambol = boolprompt("Connect to an external Funambol sync server", yes_funambol);
313 strprompt("Funambol server (blank to disable)", &sc[53][0], 63);
314 strprompt("Funambol server port", &sc[54][0], 5);
315 strprompt("Funambol sync source", &sc[55][0], 63);
316 strprompt("Funambol authentication details (user:pass in Base64)", &sc[56][0],63);
325 /* External pager stuff */
327 if (strlen(sc[60]) > 0) yes_pager = 1;
328 yes_pager = boolprompt("Configure an external pager tool", yes_pager);
330 strprompt("External pager tool", &sc[60][0], 255);
336 /* Master user account */
338 if (strlen(sc[58]) > 0) yes_muacct = 1;
339 yes_muacct = boolprompt("Enable a 'master user' account", yes_muacct);
341 strprompt("Master user name", &sc[58][0], 31);
342 strprompt("Master user password", &sc[59][0], -31);
345 strcpy(&sc[58][0], "");
346 strcpy(&sc[59][0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
350 scr_printf("Save this configuration? ");
353 for (a = 0; a < NUM_CONFIGS; a++)
354 r += 1 + strlen(sc[a]);
355 resp = (char *)calloc(1, r);
357 err_printf("Can't save config - out of memory!\n");
360 for (a = 0; a < NUM_CONFIGS; a++) {
364 r = CtdlIPCSetSystemConfig(ipc, resp, buf);
366 err_printf("%s\n", buf);
370 r = CtdlIPCSetMessageExpirationPolicy(ipc, 2, site_expirepolicy, buf);
372 err_printf("%s\n", buf);
375 r = CtdlIPCSetMessageExpirationPolicy(ipc, 3, mbx_expirepolicy, buf);
377 err_printf("%s\n", buf);
381 if (site_expirepolicy) free(site_expirepolicy);
382 if (mbx_expirepolicy) free(mbx_expirepolicy);
387 * support function for do_internet_configuration()
389 void get_inet_rec_type(CtdlIPC *ipc, char *buf) {
392 keyopt(" <1> localhost (Alias for this computer)\n");
393 keyopt(" <2> smart-host (Forward all outbound mail to this host)\n");
394 keyopt(" <3> directory (Consult the Global Address Book)\n");
395 keyopt(" <4> SpamAssassin (Address of SpamAssassin server)\n");
396 keyopt(" <5> RBL (domain suffix of spam hunting RBL)\n");
397 keyopt(" <6> masq domains (Domains as which users are allowed to masquerade)\n");
398 keyopt(" <7> ClamAV (Address of ClamAV clamd server)\n");
399 sel = intprompt("Which one", 1, 1, 7);
401 case 1: strcpy(buf, "localhost");
403 case 2: strcpy(buf, "smarthost");
405 case 3: strcpy(buf, "directory");
407 case 4: strcpy(buf, "spamassassin");
409 case 5: strcpy(buf, "rbl");
411 case 6: strcpy(buf, "masqdomain");
413 case 7: strcpy(buf, "clamav");
420 * Internet mail configuration
422 void do_internet_configuration(CtdlIPC *ipc)
435 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
437 while (!IsEmptyStr(resp)) {
438 extract_token(buf, resp, 0, '\n', sizeof buf);
439 remove_token(resp, 0, '\n');
441 if (num_recs == 1) recs = malloc(sizeof(char *));
442 else recs = realloc(recs, (sizeof(char *)) * num_recs);
443 recs[num_recs-1] = malloc(strlen(buf) + 1);
444 strcpy(recs[num_recs-1], buf);
447 if (resp) free(resp);
452 scr_printf("### Host or domain Record type \n");
454 scr_printf("--- -------------------------------------------------- --------------------\n");
455 for (i=0; i<num_recs; ++i) {
457 scr_printf("%3d ", i+1);
458 extract_token(buf, recs[i], 0, '|', sizeof buf);
460 scr_printf("%-50s ", buf);
461 extract_token(buf, recs[i], 1, '|', sizeof buf);
462 color(BRIGHT_MAGENTA);
463 scr_printf("%-20s\n", buf);
467 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
470 newprompt("Enter host name: ",
473 if (!IsEmptyStr(buf)) {
476 recs = malloc(sizeof(char *));
477 else recs = realloc(recs,
478 (sizeof(char *)) * num_recs);
480 get_inet_rec_type(ipc,
482 recs[num_recs-1] = strdup(buf);
487 i = intprompt("Delete which one",
491 for (j=i; j<num_recs; ++j)
497 for (i = 0; i < num_recs; i++)
498 r += 1 + strlen(recs[i]);
499 resp = (char *)calloc(1, r);
501 err_printf("Can't save config - out of memory!\n");
504 if (num_recs) for (i = 0; i < num_recs; i++) {
505 strcat(resp, recs[i]);
508 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
510 err_printf("%s\n", buf);
512 scr_printf("Wrote %d records.\n", num_recs);
518 quitting = !modified || boolprompt(
519 "Quit without saving", 0);
527 for (i=0; i<num_recs; ++i) free(recs[i]);
535 * Edit network configuration for room sharing, mailing lists, etc.
537 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
539 char filename[PATH_MAX];
540 char changefile[PATH_MAX];
550 char *listing = NULL;
553 if (IsEmptyStr(editor_paths[0])) {
554 scr_printf("You must have an external editor configured in"
555 " order to use this function.\n");
559 CtdlMakeTempFileName(filename, sizeof filename);
560 CtdlMakeTempFileName(changefile, sizeof changefile);
562 tempfp = fopen(filename, "w");
563 if (tempfp == NULL) {
564 err_printf("Cannot open %s: %s\n", filename, strerror(errno));
568 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
569 fprintf(tempfp, "# %s\n", comment);
570 fprintf(tempfp, "# Specify one per line.\n"
573 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
575 while(listing && !IsEmptyStr(listing)) {
576 extract_token(buf, listing, 0, '\n', sizeof buf);
577 remove_token(listing, 0, '\n');
578 extract_token(instr, buf, 0, '|', sizeof instr);
579 if (!strcasecmp(instr, entrytype)) {
580 tokens = num_tokens(buf, '|');
581 for (i=1; i<tokens; ++i) {
582 extract_token(addr, buf, i, '|', sizeof addr);
583 fprintf(tempfp, "%s", addr);
584 if (i < (tokens-1)) {
585 fprintf(tempfp, "|");
588 fprintf(tempfp, "\n");
598 e_ex_code = 1; /* start with a failed exit code */
600 stty_ctdl(SB_RESTORE);
602 cksum = file_checksum(filename);
603 if (editor_pid == 0) {
604 chmod(filename, 0600);
605 putenv("WINDOW_TITLE=Network configuration");
606 execlp(editor_paths[0], editor_paths[0], filename, NULL);
609 if (editor_pid > 0) {
612 b = ka_wait(&e_ex_code);
613 } while ((b != editor_pid) && (b >= 0));
619 if (file_checksum(filename) == cksum) {
620 err_printf("*** No changes to save.\n");
624 if (e_ex_code == 0) { /* Save changes */
625 changefp = fopen(changefile, "w");
627 /* Load all netconfig entries that are *not* of the type we are editing */
628 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
630 while(listing && !IsEmptyStr(listing)) {
631 extract_token(buf, listing, 0, '\n', sizeof buf);
632 remove_token(listing, 0, '\n');
633 extract_token(instr, buf, 0, '|', sizeof instr);
634 if (strcasecmp(instr, entrytype)) {
635 fprintf(changefp, "%s\n", buf);
644 /* ...and merge that with the data we just edited */
645 tempfp = fopen(filename, "r");
646 while (fgets(buf, sizeof buf, tempfp) != NULL) {
647 for (i=0; i<strlen(buf); ++i) {
648 if (buf[i] == '#') buf[i] = 0;
651 if (!IsEmptyStr(buf)) {
652 fprintf(changefp, "%s|%s\n", entrytype, buf);
658 /* now write it to the server... */
659 changefp = fopen(changefile, "r");
660 if (changefp != NULL) {
661 listing = load_message_from_file(changefp);
663 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
671 unlink(filename); /* Delete the temporary files */
677 * IGnet node configuration
679 void do_ignet_configuration(CtdlIPC *ipc) {
688 char *listing = NULL;
691 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
692 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
693 extract_token(buf, listing, 0, '\n', sizeof buf);
694 remove_token(listing, 0, '\n');
697 if (num_recs == 1) recs = malloc(sizeof(char *));
698 else recs = realloc(recs, (sizeof(char *)) * num_recs);
699 recs[num_recs-1] = malloc(SIZ);
700 strcpy(recs[num_recs-1], buf);
702 if (listing) free(listing);
715 "------------------ "
716 "-------------------------------- "
718 for (i=0; i<num_recs; ++i) {
720 scr_printf("%3d ", i+1);
721 extract_token(buf, recs[i], 0, '|', sizeof buf);
723 scr_printf("%-16s ", buf);
724 extract_token(buf, recs[i], 1, '|', sizeof buf);
725 color(BRIGHT_MAGENTA);
726 scr_printf("%-18s ", buf);
727 extract_token(buf, recs[i], 2, '|', sizeof buf);
729 scr_printf("%-32s ", buf);
730 extract_token(buf, recs[i], 3, '|', sizeof buf);
731 color(BRIGHT_MAGENTA);
732 scr_printf("%-3s\n", buf);
737 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
742 recs = malloc(sizeof(char *));
743 else recs = realloc(recs,
744 (sizeof(char *)) * num_recs);
745 newprompt("Enter node name : ", buf, 16);
747 newprompt("Enter shared secret: ",
748 &buf[strlen(buf)], 18);
750 newprompt("Enter host or IP : ",
751 &buf[strlen(buf)], 32);
753 strprompt("Enter port number : ",
754 &buf[strlen(buf)-3], 5);
755 recs[num_recs-1] = strdup(buf);
759 i = intprompt("Delete which one",
763 for (j=i; j<num_recs; ++j)
769 for (i = 0; i < num_recs; ++i)
770 r += 1 + strlen(recs[i]);
771 listing = (char*) calloc(1, r);
773 err_printf("Can't save config - out of memory!\n");
776 if (num_recs) for (i = 0; i < num_recs; ++i) {
777 strcat(listing, recs[i]);
778 strcat(listing, "\n");
780 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
782 scr_printf("%s\n", buf);
784 scr_printf("Wrote %d records.\n", num_recs);
790 quitting = !modified || boolprompt(
791 "Quit without saving", 0);
799 for (i=0; i<num_recs; ++i) free(recs[i]);
806 * Filter list configuration
808 void do_filterlist_configuration(CtdlIPC *ipc)
818 char *listing = NULL;
821 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
822 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
823 extract_token(buf, listing, 0, '\n', sizeof buf);
824 remove_token(listing, 0, '\n');
827 if (num_recs == 1) recs = malloc(sizeof(char *));
828 else recs = realloc(recs, (sizeof(char *)) * num_recs);
829 recs[num_recs-1] = malloc(SIZ);
830 strcpy(recs[num_recs-1], buf);
832 if (listing) free(listing);
844 "---------------------------- "
845 "---------------------------- "
848 for (i=0; i<num_recs; ++i) {
850 scr_printf("%3d ", i+1);
851 extract_token(buf, recs[i], 0, '|', sizeof buf);
853 scr_printf("%-28s ", buf);
854 extract_token(buf, recs[i], 1, '|', sizeof buf);
855 color(BRIGHT_MAGENTA);
856 scr_printf("%-28s ", buf);
857 extract_token(buf, recs[i], 2, '|', sizeof buf);
859 scr_printf("%-16s\n", buf);
860 extract_token(buf, recs[i], 3, '|', sizeof buf);
864 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
869 recs = malloc(sizeof(char *));
870 else recs = realloc(recs,
871 (sizeof(char *)) * num_recs);
872 newprompt("Enter user name: ", buf, 28);
874 newprompt("Enter room name: ",
875 &buf[strlen(buf)], 28);
877 newprompt("Enter node name: ",
878 &buf[strlen(buf)], 16);
880 recs[num_recs-1] = strdup(buf);
884 i = intprompt("Delete which one",
888 for (j=i; j<num_recs; ++j)
894 for (i = 0; i < num_recs; ++i)
895 r += 1 + strlen(recs[i]);
896 listing = (char*) calloc(1, r);
898 err_printf("Can't save config - out of memory!\n");
901 if (num_recs) for (i = 0; i < num_recs; ++i) {
902 strcat(listing, recs[i]);
903 strcat(listing, "\n");
905 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
907 scr_printf("%s\n", buf);
909 scr_printf("Wrote %d records.\n", num_recs);
915 quitting = !modified || boolprompt(
916 "Quit without saving", 0);
924 for (i=0; i<num_recs; ++i) free(recs[i]);
933 * POP3 aggregation client configuration
935 void do_pop3client_configuration(CtdlIPC *ipc)
945 char *listing = NULL;
946 char *other_listing = NULL;
950 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
952 while(listing && !IsEmptyStr(listing)) {
953 extract_token(buf, listing, 0, '\n', sizeof buf);
954 remove_token(listing, 0, '\n');
955 extract_token(instr, buf, 0, '|', sizeof instr);
956 if (!strcasecmp(instr, "pop3client")) {
959 if (num_recs == 1) recs = malloc(sizeof(char *));
960 else recs = realloc(recs, (sizeof(char *)) * num_recs);
961 recs[num_recs-1] = malloc(SIZ);
962 strcpy(recs[num_recs-1], buf);
983 "---------------------------- "
984 "---------------------------- "
988 for (i=0; i<num_recs; ++i) {
990 scr_printf("%3d ", i+1);
992 extract_token(buf, recs[i], 1, '|', sizeof buf);
994 scr_printf("%-28s ", buf);
996 extract_token(buf, recs[i], 2, '|', sizeof buf);
997 color(BRIGHT_MAGENTA);
998 scr_printf("%-28s ", buf);
1001 scr_printf("%-15s ", (extract_int(recs[i], 4) ? "Yes" : "No") );
1002 color(BRIGHT_MAGENTA);
1003 scr_printf("%ld\n", extract_long(recs[i], 5) );
1007 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1011 if (num_recs == 1) {
1012 recs = malloc(sizeof(char *));
1015 recs = realloc(recs, (sizeof(char *)) * num_recs);
1017 strcpy(buf, "pop3client|");
1018 newprompt("Enter host name: ", &buf[strlen(buf)], 28);
1020 newprompt("Enter user name: ", &buf[strlen(buf)], 28);
1022 newprompt("Enter password : ", &buf[strlen(buf)], 16);
1024 scr_printf("Keep messages on server instead of deleting them? ");
1025 sprintf(&buf[strlen(buf)], "%d", yesno());
1027 newprompt("Enter interval : ", &buf[strlen(buf)], 5);
1029 recs[num_recs-1] = strdup(buf);
1033 i = intprompt("Delete which one",
1034 1, 1, num_recs) - 1;
1037 for (j=i; j<num_recs; ++j)
1038 recs[j] = recs[j+1];
1043 for (i = 0; i < num_recs; ++i) {
1044 r += 1 + strlen(recs[i]);
1046 listing = (char*) calloc(1, r);
1048 err_printf("Can't save config - out of memory!\n");
1051 if (num_recs) for (i = 0; i < num_recs; ++i) {
1052 strcat(listing, recs[i]);
1053 strcat(listing, "\n");
1056 /* Retrieve all the *other* records for merging */
1057 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1059 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1060 extract_token(buf, other_listing, i, '\n', sizeof buf);
1061 if (strncasecmp(buf, "pop3client|", 11)) {
1062 listing = realloc(listing, strlen(listing) +
1064 strcat(listing, buf);
1065 strcat(listing, "\n");
1069 free(other_listing);
1070 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1075 scr_printf("%s\n", buf);
1077 scr_printf("Wrote %d records.\n", num_recs);
1083 quitting = !modified || boolprompt(
1084 "Quit without saving", 0);
1089 } while (!quitting);
1092 for (i=0; i<num_recs; ++i) free(recs[i]);
1103 * RSS feed retrieval client configuration
1105 void do_rssclient_configuration(CtdlIPC *ipc)
1115 char *listing = NULL;
1116 char *other_listing = NULL;
1120 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1122 while(listing && !IsEmptyStr(listing)) {
1123 extract_token(buf, listing, 0, '\n', sizeof buf);
1124 remove_token(listing, 0, '\n');
1125 extract_token(instr, buf, 0, '|', sizeof instr);
1126 if (!strcasecmp(instr, "rssclient")) {
1129 if (num_recs == 1) recs = malloc(sizeof(char *));
1130 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1131 recs[num_recs-1] = malloc(SIZ);
1132 strcpy(recs[num_recs-1], buf);
1144 color(BRIGHT_WHITE);
1145 scr_printf("### Feed URL\n");
1148 "---------------------------------------------------------------------------"
1151 for (i=0; i<num_recs; ++i) {
1153 scr_printf("%3d ", i+1);
1155 extract_token(buf, recs[i], 1, '|', sizeof buf);
1157 scr_printf("%-75s\n", buf);
1162 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1166 if (num_recs == 1) {
1167 recs = malloc(sizeof(char *));
1170 recs = realloc(recs, (sizeof(char *)) * num_recs);
1172 strcpy(buf, "rssclient|");
1173 newprompt("Enter feed URL: ", &buf[strlen(buf)], 75);
1175 recs[num_recs-1] = strdup(buf);
1179 i = intprompt("Delete which one", 1, 1, num_recs) - 1;
1182 for (j=i; j<num_recs; ++j)
1183 recs[j] = recs[j+1];
1188 for (i = 0; i < num_recs; ++i) {
1189 r += 1 + strlen(recs[i]);
1191 listing = (char*) calloc(1, r);
1193 err_printf("Can't save config - out of memory!\n");
1196 if (num_recs) for (i = 0; i < num_recs; ++i) {
1197 strcat(listing, recs[i]);
1198 strcat(listing, "\n");
1201 /* Retrieve all the *other* records for merging */
1202 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1204 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1205 extract_token(buf, other_listing, i, '\n', sizeof buf);
1206 if (strncasecmp(buf, "rssclient|", 10)) {
1207 listing = realloc(listing, strlen(listing) +
1209 strcat(listing, buf);
1210 strcat(listing, "\n");
1214 free(other_listing);
1215 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1220 scr_printf("%s\n", buf);
1222 scr_printf("Wrote %d records.\n", num_recs);
1228 quitting = !modified || boolprompt(
1229 "Quit without saving", 0);
1234 } while (!quitting);
1237 for (i=0; i<num_recs; ++i) free(recs[i]);