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])) {
141 logpages = boolprompt("Log all instant messages", logpages);
143 strprompt("Name of logging room", &sc[18][0], ROOMNAMELEN);
149 /* Commented out because this setting isn't really appropriate to
150 * change while the server is running.
152 * snprintf(sc[52], sizeof sc[52], "%d", (boolprompt(
153 * "Use system authentication",
154 * atoi(&sc[52][0]))));
159 strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
160 strprompt("Maximum concurrent sessions", &sc[14][0], 4);
161 strprompt("Maximum message length", &sc[20][0], 20);
162 strprompt("Minimum number of worker threads", &sc[21][0], 3);
163 strprompt("Maximum number of worker threads", &sc[22][0], 3);
164 snprintf(sc[43], sizeof sc[43], "%d", (boolprompt(
165 "Automatically delete committed database logs",
168 strprompt("Server IP address (* for 'any')", &sc[37][0], 15);
169 strprompt("POP3 server port (-1 to disable)", &sc[23][0], 5);
170 strprompt("POP3S server port (-1 to disable)", &sc[40][0], 5);
171 strprompt("IMAP server port (-1 to disable)", &sc[27][0], 5);
172 strprompt("IMAPS server port (-1 to disable)", &sc[39][0], 5);
173 strprompt("SMTP MTA server port (-1 to disable)", &sc[24][0], 5);
174 strprompt("SMTP MSA server port (-1 to disable)", &sc[38][0], 5);
175 strprompt("SMTPS server port (-1 to disable)", &sc[41][0], 5);
176 strprompt("Postfix TCP Dictionary Port server port (-1 to disable)", &sc[50][0], 5);
177 strprompt("ManageSieve server port (-1 to disable)", &sc[51][0], 5);
179 strprompt("XMPP (Jabber) client to server port (-1 to disable)", &sc[62][0], 5);
180 /* No prompt because we don't implement this service yet, it's just a placeholder */
181 /* strprompt("XMPP (Jabber) server to server port (-1 to disable)", &sc[63][0], 5); */
183 /* This logic flips the question around, because it's one of those
184 * situations where 0=yes and 1=no
188 a = boolprompt("Correct forged From: lines during authenticated SMTP",
191 snprintf(sc[25], sizeof sc[25], "%d", a);
193 snprintf(sc[66], sizeof sc[66], "%d", (boolprompt(
194 "Flag messages as spam instead of rejecting",
197 /* This logic flips the question around, because it's one of those
198 * situations where 0=yes and 1=no
202 a = boolprompt("Force IMAP posts in public rooms to be from the user who submitted them", a);
204 snprintf(sc[61], sizeof sc[61], "%d", a);
206 snprintf(sc[45], sizeof sc[45], "%d", (boolprompt(
207 "Allow unauthenticated SMTP clients to spoof my domains",
209 snprintf(sc[57], sizeof sc[57], "%d", (boolprompt(
210 "Perform RBL checks at greeting instead of after RCPT",
212 snprintf(sc[44], sizeof sc[44], "%d", (boolprompt(
213 "Instantly expunge deleted IMAP messages",
217 if (ipc->ServInfo.supports_ldap) {
218 a = strlen(&sc[32][0]);
219 a = (a ? 1 : 0); /* Set only to 1 or 0 */
220 a = boolprompt("Do you want to configure LDAP authentication?", a);
222 strprompt("Host name of LDAP server",
224 strprompt("Port number of LDAP service",
226 strprompt("Base DN", &sc[34][0], 255);
227 strprompt("Bind DN (or blank for anonymous bind)", &sc[35][0], 255);
228 strprompt("Password for bind DN (or blank for anonymous bind)", &sc[36][0], 255);
231 strcpy(&sc[32][0], "");
235 /* Expiry settings */
236 strprompt("Default user purge time (days)", &sc[16][0], 5);
237 strprompt("Default room purge time (days)", &sc[17][0], 5);
239 /* Angels and demons dancing in my head... */
241 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_mode);
242 strprompt("System default message expire policy (? for list)",
246 "1. Never automatically expire messages\n"
247 "2. Expire by message count\n"
248 "3. Expire by message age\n");
250 } while ((buf[0] < '1') || (buf[0] > '3'));
251 site_expirepolicy->expire_mode = buf[0] - '0';
253 /* ...lunatics and monsters underneath my bed */
254 if (site_expirepolicy->expire_mode == 2) {
255 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
256 strprompt("Keep how many messages online?", buf, 10);
257 site_expirepolicy->expire_value = atol(buf);
259 if (site_expirepolicy->expire_mode == 3) {
260 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
261 strprompt("Keep messages for how many days?", buf, 10);
262 site_expirepolicy->expire_value = atol(buf);
265 /* Media messiahs preying on my fears... */
267 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_mode);
268 strprompt("Mailbox default message expire policy (? for list)",
272 "0. Go with the system default\n"
273 "1. Never automatically expire messages\n"
274 "2. Expire by message count\n"
275 "3. Expire by message age\n");
277 } while ((buf[0] < '0') || (buf[0] > '3'));
278 mbx_expirepolicy->expire_mode = buf[0] - '0';
280 /* ...Pop culture prophets playing in my ears */
281 if (mbx_expirepolicy->expire_mode == 2) {
282 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
283 strprompt("Keep how many messages online?", buf, 10);
284 mbx_expirepolicy->expire_value = atol(buf);
286 if (mbx_expirepolicy->expire_mode == 3) {
287 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
288 strprompt("Keep messages for how many days?", buf, 10);
289 mbx_expirepolicy->expire_value = atol(buf);
292 strprompt("How often to run network jobs (in seconds)", &sc[28][0], 5);
293 strprompt("Default frequency to run POP3 collection (in seconds)", &sc[64][0], 5);
294 strprompt("Fastest frequency to run POP3 collection (in seconds)", &sc[65][0], 5);
295 strprompt("Hour to run purges (0-23)", &sc[31][0], 2);
296 snprintf(sc[42], sizeof sc[42], "%d", (boolprompt(
297 "Enable full text search index (warning: resource intensive)",
300 snprintf(sc[46], sizeof sc[46], "%d", (boolprompt(
301 "Perform journaling of email messages",
303 snprintf(sc[47], sizeof sc[47], "%d", (boolprompt(
304 "Perform journaling of non-email messages",
306 if ( (atoi(&sc[46][0])) || (atoi(&sc[47][0])) ) {
307 strprompt("Email destination of journalized messages",
311 /* Funambol push stuff */
312 int yes_funambol = 0;
313 if (strlen(sc[53]) > 0) yes_funambol = 1;
314 yes_funambol = boolprompt("Connect to an external Funambol sync server", yes_funambol);
316 strprompt("Funambol server (blank to disable)", &sc[53][0], 63);
317 strprompt("Funambol server port", &sc[54][0], 5);
318 strprompt("Funambol sync source", &sc[55][0], 63);
319 strprompt("Funambol authentication details (user:pass in Base64)", &sc[56][0],63);
328 /* External pager stuff */
330 if (strlen(sc[60]) > 0) yes_pager = 1;
331 yes_pager = boolprompt("Configure an external pager tool", yes_pager);
333 strprompt("External pager tool", &sc[60][0], 255);
339 /* Master user account */
341 if (strlen(sc[58]) > 0) yes_muacct = 1;
342 yes_muacct = boolprompt("Enable a 'master user' account", yes_muacct);
344 strprompt("Master user name", &sc[58][0], 31);
345 strprompt("Master user password", &sc[59][0], -31);
348 strcpy(&sc[58][0], "");
349 strcpy(&sc[59][0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
353 scr_printf("Save this configuration? ");
356 for (a = 0; a < NUM_CONFIGS; a++)
357 r += 1 + strlen(sc[a]);
358 resp = (char *)calloc(1, r);
360 err_printf("Can't save config - out of memory!\n");
363 for (a = 0; a < NUM_CONFIGS; a++) {
367 r = CtdlIPCSetSystemConfig(ipc, resp, buf);
369 err_printf("%s\n", buf);
373 r = CtdlIPCSetMessageExpirationPolicy(ipc, 2, site_expirepolicy, buf);
375 err_printf("%s\n", buf);
378 r = CtdlIPCSetMessageExpirationPolicy(ipc, 3, mbx_expirepolicy, buf);
380 err_printf("%s\n", buf);
384 if (site_expirepolicy) free(site_expirepolicy);
385 if (mbx_expirepolicy) free(mbx_expirepolicy);
390 * support function for do_internet_configuration()
392 void get_inet_rec_type(CtdlIPC *ipc, char *buf) {
395 keyopt(" <1> localhost (Alias for this computer)\n");
396 keyopt(" <2> smart host (Forward all outbound mail to this host)\n");
397 keyopt(" <3> fallback host (Send mail to this host only if direct delivery fails)\n");
398 keyopt(" <4> directory (Consult the Global Address Book)\n");
399 keyopt(" <5> SpamAssassin (Address of SpamAssassin server)\n");
400 keyopt(" <6> RBL (domain suffix of spam hunting RBL)\n");
401 keyopt(" <7> masq domains (Domains as which users are allowed to masquerade)\n");
402 keyopt(" <8> ClamAV (Address of ClamAV clamd server)\n");
403 sel = intprompt("Which one", 1, 1, 7);
405 case 1: strcpy(buf, "localhost");
407 case 2: strcpy(buf, "smarthost");
409 case 3: strcpy(buf, "fallbackhost");
411 case 4: strcpy(buf, "directory");
413 case 5: strcpy(buf, "spamassassin");
415 case 6: strcpy(buf, "rbl");
417 case 7: strcpy(buf, "masqdomain");
419 case 8: strcpy(buf, "clamav");
426 * Internet mail configuration
428 void do_internet_configuration(CtdlIPC *ipc)
441 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
443 while (!IsEmptyStr(resp)) {
444 extract_token(buf, resp, 0, '\n', sizeof buf);
445 remove_token(resp, 0, '\n');
447 if (num_recs == 1) recs = malloc(sizeof(char *));
448 else recs = realloc(recs, (sizeof(char *)) * num_recs);
449 recs[num_recs-1] = malloc(strlen(buf) + 1);
450 strcpy(recs[num_recs-1], buf);
453 if (resp) free(resp);
458 scr_printf("### Host or domain Record type \n");
460 scr_printf("--- -------------------------------------------------- --------------------\n");
461 for (i=0; i<num_recs; ++i) {
463 scr_printf("%3d ", i+1);
464 extract_token(buf, recs[i], 0, '|', sizeof buf);
466 scr_printf("%-50s ", buf);
467 extract_token(buf, recs[i], 1, '|', sizeof buf);
468 color(BRIGHT_MAGENTA);
469 scr_printf("%-20s\n", buf);
473 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
476 newprompt("Enter host name: ",
479 if (!IsEmptyStr(buf)) {
482 recs = malloc(sizeof(char *));
483 else recs = realloc(recs,
484 (sizeof(char *)) * num_recs);
486 get_inet_rec_type(ipc,
488 recs[num_recs-1] = strdup(buf);
493 i = intprompt("Delete which one",
497 for (j=i; j<num_recs; ++j)
503 for (i = 0; i < num_recs; i++)
504 r += 1 + strlen(recs[i]);
505 resp = (char *)calloc(1, r);
507 err_printf("Can't save config - out of memory!\n");
510 if (num_recs) for (i = 0; i < num_recs; i++) {
511 strcat(resp, recs[i]);
514 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
516 err_printf("%s\n", buf);
518 scr_printf("Wrote %d records.\n", num_recs);
524 quitting = !modified || boolprompt(
525 "Quit without saving", 0);
533 for (i=0; i<num_recs; ++i) free(recs[i]);
541 * Edit network configuration for room sharing, mailing lists, etc.
543 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
545 char filename[PATH_MAX];
546 char changefile[PATH_MAX];
556 char *listing = NULL;
559 if (IsEmptyStr(editor_paths[0])) {
560 scr_printf("You must have an external editor configured in"
561 " order to use this function.\n");
565 CtdlMakeTempFileName(filename, sizeof filename);
566 CtdlMakeTempFileName(changefile, sizeof changefile);
568 tempfp = fopen(filename, "w");
569 if (tempfp == NULL) {
570 err_printf("Cannot open %s: %s\n", filename, strerror(errno));
574 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
575 fprintf(tempfp, "# %s\n", comment);
576 fprintf(tempfp, "# Specify one per line.\n"
579 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
581 while(listing && !IsEmptyStr(listing)) {
582 extract_token(buf, listing, 0, '\n', sizeof buf);
583 remove_token(listing, 0, '\n');
584 extract_token(instr, buf, 0, '|', sizeof instr);
585 if (!strcasecmp(instr, entrytype)) {
586 tokens = num_tokens(buf, '|');
587 for (i=1; i<tokens; ++i) {
588 extract_token(addr, buf, i, '|', sizeof addr);
589 fprintf(tempfp, "%s", addr);
590 if (i < (tokens-1)) {
591 fprintf(tempfp, "|");
594 fprintf(tempfp, "\n");
604 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));
625 if (file_checksum(filename) == cksum) {
626 err_printf("*** No changes to save.\n");
630 if (e_ex_code == 0) { /* Save changes */
631 changefp = fopen(changefile, "w");
633 /* Load all netconfig entries that are *not* of the type we are editing */
634 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
636 while(listing && !IsEmptyStr(listing)) {
637 extract_token(buf, listing, 0, '\n', sizeof buf);
638 remove_token(listing, 0, '\n');
639 extract_token(instr, buf, 0, '|', sizeof instr);
640 if (strcasecmp(instr, entrytype)) {
641 fprintf(changefp, "%s\n", buf);
650 /* ...and merge that with the data we just edited */
651 tempfp = fopen(filename, "r");
652 while (fgets(buf, sizeof buf, tempfp) != NULL) {
653 for (i=0; i<strlen(buf); ++i) {
654 if (buf[i] == '#') buf[i] = 0;
657 if (!IsEmptyStr(buf)) {
658 fprintf(changefp, "%s|%s\n", entrytype, buf);
664 /* now write it to the server... */
665 changefp = fopen(changefile, "r");
666 if (changefp != NULL) {
667 listing = load_message_from_file(changefp);
669 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
677 unlink(filename); /* Delete the temporary files */
683 * IGnet node configuration
685 void do_ignet_configuration(CtdlIPC *ipc) {
694 char *listing = NULL;
697 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
698 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
699 extract_token(buf, listing, 0, '\n', sizeof buf);
700 remove_token(listing, 0, '\n');
703 if (num_recs == 1) recs = malloc(sizeof(char *));
704 else recs = realloc(recs, (sizeof(char *)) * num_recs);
705 recs[num_recs-1] = malloc(SIZ);
706 strcpy(recs[num_recs-1], buf);
708 if (listing) free(listing);
721 "------------------ "
722 "-------------------------------- "
724 for (i=0; i<num_recs; ++i) {
726 scr_printf("%3d ", i+1);
727 extract_token(buf, recs[i], 0, '|', sizeof buf);
729 scr_printf("%-16s ", buf);
730 extract_token(buf, recs[i], 1, '|', sizeof buf);
731 color(BRIGHT_MAGENTA);
732 scr_printf("%-18s ", buf);
733 extract_token(buf, recs[i], 2, '|', sizeof buf);
735 scr_printf("%-32s ", buf);
736 extract_token(buf, recs[i], 3, '|', sizeof buf);
737 color(BRIGHT_MAGENTA);
738 scr_printf("%-3s\n", buf);
743 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
748 recs = malloc(sizeof(char *));
749 else recs = realloc(recs,
750 (sizeof(char *)) * num_recs);
751 newprompt("Enter node name : ", buf, 16);
753 newprompt("Enter shared secret: ",
754 &buf[strlen(buf)], 18);
756 newprompt("Enter host or IP : ",
757 &buf[strlen(buf)], 32);
759 strprompt("Enter port number : ",
760 &buf[strlen(buf)-3], 5);
761 recs[num_recs-1] = strdup(buf);
765 i = intprompt("Delete which one",
769 for (j=i; j<num_recs; ++j)
775 for (i = 0; i < num_recs; ++i)
776 r += 1 + strlen(recs[i]);
777 listing = (char*) calloc(1, r);
779 err_printf("Can't save config - out of memory!\n");
782 if (num_recs) for (i = 0; i < num_recs; ++i) {
783 strcat(listing, recs[i]);
784 strcat(listing, "\n");
786 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
788 scr_printf("%s\n", buf);
790 scr_printf("Wrote %d records.\n", num_recs);
796 quitting = !modified || boolprompt(
797 "Quit without saving", 0);
805 for (i=0; i<num_recs; ++i) free(recs[i]);
812 * Filter list configuration
814 void do_filterlist_configuration(CtdlIPC *ipc)
824 char *listing = NULL;
827 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
828 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
829 extract_token(buf, listing, 0, '\n', sizeof buf);
830 remove_token(listing, 0, '\n');
833 if (num_recs == 1) recs = malloc(sizeof(char *));
834 else recs = realloc(recs, (sizeof(char *)) * num_recs);
835 recs[num_recs-1] = malloc(SIZ);
836 strcpy(recs[num_recs-1], buf);
838 if (listing) free(listing);
850 "---------------------------- "
851 "---------------------------- "
854 for (i=0; i<num_recs; ++i) {
856 scr_printf("%3d ", i+1);
857 extract_token(buf, recs[i], 0, '|', sizeof buf);
859 scr_printf("%-28s ", buf);
860 extract_token(buf, recs[i], 1, '|', sizeof buf);
861 color(BRIGHT_MAGENTA);
862 scr_printf("%-28s ", buf);
863 extract_token(buf, recs[i], 2, '|', sizeof buf);
865 scr_printf("%-16s\n", buf);
866 extract_token(buf, recs[i], 3, '|', sizeof buf);
870 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
875 recs = malloc(sizeof(char *));
876 else recs = realloc(recs,
877 (sizeof(char *)) * num_recs);
878 newprompt("Enter user name: ", buf, 28);
880 newprompt("Enter room name: ",
881 &buf[strlen(buf)], 28);
883 newprompt("Enter node name: ",
884 &buf[strlen(buf)], 16);
886 recs[num_recs-1] = strdup(buf);
890 i = intprompt("Delete which one",
894 for (j=i; j<num_recs; ++j)
900 for (i = 0; i < num_recs; ++i)
901 r += 1 + strlen(recs[i]);
902 listing = (char*) calloc(1, r);
904 err_printf("Can't save config - out of memory!\n");
907 if (num_recs) for (i = 0; i < num_recs; ++i) {
908 strcat(listing, recs[i]);
909 strcat(listing, "\n");
911 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
913 scr_printf("%s\n", buf);
915 scr_printf("Wrote %d records.\n", num_recs);
921 quitting = !modified || boolprompt(
922 "Quit without saving", 0);
930 for (i=0; i<num_recs; ++i) free(recs[i]);
939 * POP3 aggregation client configuration
941 void do_pop3client_configuration(CtdlIPC *ipc)
951 char *listing = NULL;
952 char *other_listing = NULL;
956 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
958 while(listing && !IsEmptyStr(listing)) {
959 extract_token(buf, listing, 0, '\n', sizeof buf);
960 remove_token(listing, 0, '\n');
961 extract_token(instr, buf, 0, '|', sizeof instr);
962 if (!strcasecmp(instr, "pop3client")) {
965 if (num_recs == 1) recs = malloc(sizeof(char *));
966 else recs = realloc(recs, (sizeof(char *)) * num_recs);
967 recs[num_recs-1] = malloc(SIZ);
968 strcpy(recs[num_recs-1], buf);
989 "---------------------------- "
990 "---------------------------- "
994 for (i=0; i<num_recs; ++i) {
996 scr_printf("%3d ", i+1);
998 extract_token(buf, recs[i], 1, '|', sizeof buf);
1000 scr_printf("%-28s ", buf);
1002 extract_token(buf, recs[i], 2, '|', sizeof buf);
1003 color(BRIGHT_MAGENTA);
1004 scr_printf("%-28s ", buf);
1007 scr_printf("%-15s ", (extract_int(recs[i], 4) ? "Yes" : "No") );
1008 color(BRIGHT_MAGENTA);
1009 scr_printf("%ld\n", extract_long(recs[i], 5) );
1013 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1017 if (num_recs == 1) {
1018 recs = malloc(sizeof(char *));
1021 recs = realloc(recs, (sizeof(char *)) * num_recs);
1023 strcpy(buf, "pop3client|");
1024 newprompt("Enter host name: ", &buf[strlen(buf)], 28);
1026 newprompt("Enter user name: ", &buf[strlen(buf)], 28);
1028 newprompt("Enter password : ", &buf[strlen(buf)], 16);
1030 scr_printf("Keep messages on server instead of deleting them? ");
1031 sprintf(&buf[strlen(buf)], "%d", yesno());
1033 newprompt("Enter interval : ", &buf[strlen(buf)], 5);
1035 recs[num_recs-1] = strdup(buf);
1039 i = intprompt("Delete which one",
1040 1, 1, num_recs) - 1;
1043 for (j=i; j<num_recs; ++j)
1044 recs[j] = recs[j+1];
1049 for (i = 0; i < num_recs; ++i) {
1050 r += 1 + strlen(recs[i]);
1052 listing = (char*) calloc(1, r);
1054 err_printf("Can't save config - out of memory!\n");
1057 if (num_recs) for (i = 0; i < num_recs; ++i) {
1058 strcat(listing, recs[i]);
1059 strcat(listing, "\n");
1062 /* Retrieve all the *other* records for merging */
1063 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1065 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1066 extract_token(buf, other_listing, i, '\n', sizeof buf);
1067 if (strncasecmp(buf, "pop3client|", 11)) {
1068 listing = realloc(listing, strlen(listing) +
1070 strcat(listing, buf);
1071 strcat(listing, "\n");
1075 free(other_listing);
1076 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1081 scr_printf("%s\n", buf);
1083 scr_printf("Wrote %d records.\n", num_recs);
1089 quitting = !modified || boolprompt(
1090 "Quit without saving", 0);
1095 } while (!quitting);
1098 for (i=0; i<num_recs; ++i) free(recs[i]);
1109 * RSS feed retrieval client configuration
1111 void do_rssclient_configuration(CtdlIPC *ipc)
1121 char *listing = NULL;
1122 char *other_listing = NULL;
1126 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1128 while(listing && !IsEmptyStr(listing)) {
1129 extract_token(buf, listing, 0, '\n', sizeof buf);
1130 remove_token(listing, 0, '\n');
1131 extract_token(instr, buf, 0, '|', sizeof instr);
1132 if (!strcasecmp(instr, "rssclient")) {
1135 if (num_recs == 1) recs = malloc(sizeof(char *));
1136 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1137 recs[num_recs-1] = malloc(SIZ);
1138 strcpy(recs[num_recs-1], buf);
1150 color(BRIGHT_WHITE);
1151 scr_printf("### Feed URL\n");
1154 "---------------------------------------------------------------------------"
1157 for (i=0; i<num_recs; ++i) {
1159 scr_printf("%3d ", i+1);
1161 extract_token(buf, recs[i], 1, '|', sizeof buf);
1163 scr_printf("%-75s\n", buf);
1168 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1172 if (num_recs == 1) {
1173 recs = malloc(sizeof(char *));
1176 recs = realloc(recs, (sizeof(char *)) * num_recs);
1178 strcpy(buf, "rssclient|");
1179 newprompt("Enter feed URL: ", &buf[strlen(buf)], 75);
1181 recs[num_recs-1] = strdup(buf);
1185 i = intprompt("Delete which one", 1, 1, num_recs) - 1;
1188 for (j=i; j<num_recs; ++j)
1189 recs[j] = recs[j+1];
1194 for (i = 0; i < num_recs; ++i) {
1195 r += 1 + strlen(recs[i]);
1197 listing = (char*) calloc(1, r);
1199 err_printf("Can't save config - out of memory!\n");
1202 if (num_recs) for (i = 0; i < num_recs; ++i) {
1203 strcat(listing, recs[i]);
1204 strcat(listing, "\n");
1207 /* Retrieve all the *other* records for merging */
1208 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1210 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1211 extract_token(buf, other_listing, i, '\n', sizeof buf);
1212 if (strncasecmp(buf, "rssclient|", 10)) {
1213 listing = realloc(listing, strlen(listing) +
1215 strcat(listing, buf);
1216 strcat(listing, "\n");
1220 free(other_listing);
1221 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1226 scr_printf("%s\n", buf);
1228 scr_printf("Wrote %d records.\n", num_recs);
1234 quitting = !modified || boolprompt(
1235 "Quit without saving", 0);
1240 } while (!quitting);
1243 for (i=0; i<num_recs; ++i) free(recs[i]);