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 65
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 /* No prompt because we don't implement this service yet, it's just a placeholder */
177 /* strprompt("XMPP (Jabber) server to server port (-1 to disable)", &sc[63][0], 5); */
179 /* This logic flips the question around, because it's one of those
180 * situations where 0=yes and 1=no
184 a = boolprompt("Correct forged From: lines during authenticated SMTP",
187 snprintf(sc[25], sizeof sc[25], "%d", a);
189 /* This logic flips the question around, because it's one of those
190 * situations where 0=yes and 1=no
194 a = boolprompt("Force IMAP posts in public rooms to be from the user who submitted them", a);
196 snprintf(sc[61], sizeof sc[61], "%d", a);
198 snprintf(sc[45], sizeof sc[45], "%d", (boolprompt(
199 "Allow unauthenticated SMTP clients to spoof my domains",
201 snprintf(sc[57], sizeof sc[57], "%d", (boolprompt(
202 "Perform RBL checks at greeting instead of after RCPT",
204 snprintf(sc[44], sizeof sc[44], "%d", (boolprompt(
205 "Instantly expunge deleted IMAP messages",
209 if (ipc->ServInfo.supports_ldap) {
210 a = strlen(&sc[32][0]);
211 a = (a ? 1 : 0); /* Set only to 1 or 0 */
212 a = boolprompt("Connect this Citadel to an external LDAP directory", a);
214 strprompt("Host name of LDAP server",
216 strprompt("Port number of LDAP service",
218 strprompt("Base DN", &sc[34][0], 255);
219 strprompt("Bind DN", &sc[35][0], 255);
220 strprompt("Password for bind DN", &sc[36][0], 255);
223 strcpy(&sc[32][0], "");
227 /* Expiry settings */
228 strprompt("Default user purge time (days)", &sc[16][0], 5);
229 strprompt("Default room purge time (days)", &sc[17][0], 5);
231 /* Angels and demons dancing in my head... */
233 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_mode);
234 strprompt("System default message expire policy (? for list)",
238 "1. Never automatically expire messages\n"
239 "2. Expire by message count\n"
240 "3. Expire by message age\n");
242 } while ((buf[0] < '1') || (buf[0] > '3'));
243 site_expirepolicy->expire_mode = buf[0] - '0';
245 /* ...lunatics and monsters underneath my bed */
246 if (site_expirepolicy->expire_mode == 2) {
247 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
248 strprompt("Keep how many messages online?", buf, 10);
249 site_expirepolicy->expire_value = atol(buf);
251 if (site_expirepolicy->expire_mode == 3) {
252 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
253 strprompt("Keep messages for how many days?", buf, 10);
254 site_expirepolicy->expire_value = atol(buf);
257 /* Media messiahs preying on my fears... */
259 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_mode);
260 strprompt("Mailbox default message expire policy (? for list)",
264 "0. Go with the system default\n"
265 "1. Never automatically expire messages\n"
266 "2. Expire by message count\n"
267 "3. Expire by message age\n");
269 } while ((buf[0] < '0') || (buf[0] > '3'));
270 mbx_expirepolicy->expire_mode = buf[0] - '0';
272 /* ...Pop culture prophets playing in my ears */
273 if (mbx_expirepolicy->expire_mode == 2) {
274 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
275 strprompt("Keep how many messages online?", buf, 10);
276 mbx_expirepolicy->expire_value = atol(buf);
278 if (mbx_expirepolicy->expire_mode == 3) {
279 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
280 strprompt("Keep messages for how many days?", buf, 10);
281 mbx_expirepolicy->expire_value = atol(buf);
284 strprompt("How often to run network jobs (in seconds)", &sc[28][0], 5);
285 strprompt("Default frequency to run POP3 collection (in seconds)", &sc[64][0], 5);
286 strprompt("Fastest frequency to run POP3 collection (in seconds)", &sc[65][0], 5);
287 strprompt("Hour to run purges (0-23)", &sc[31][0], 2);
288 snprintf(sc[42], sizeof sc[42], "%d", (boolprompt(
289 "Enable full text search index (warning: resource intensive)",
292 snprintf(sc[46], sizeof sc[46], "%d", (boolprompt(
293 "Perform journaling of email messages",
295 snprintf(sc[47], sizeof sc[47], "%d", (boolprompt(
296 "Perform journaling of non-email messages",
298 if ( (atoi(&sc[46][0])) || (atoi(&sc[47][0])) ) {
299 strprompt("Email destination of journalized messages",
303 /* Funambol push stuff */
304 int yes_funambol = 0;
305 if (strlen(sc[53]) > 0) yes_funambol = 1;
306 yes_funambol = boolprompt("Connect to an external Funambol sync server", yes_funambol);
308 strprompt("Funambol server (blank to disable)", &sc[53][0], 63);
309 strprompt("Funambol server port", &sc[54][0], 5);
310 strprompt("Funambol sync source", &sc[55][0], 63);
311 strprompt("Funambol authentication details (user:pass in Base64)", &sc[56][0],63);
320 /* External pager stuff */
322 if (strlen(sc[60]) > 0) yes_pager = 1;
323 yes_pager = boolprompt("Configure an external pager tool", yes_pager);
325 strprompt("External pager tool", &sc[60][0], 255);
331 /* Master user account */
333 if (strlen(sc[58]) > 0) yes_muacct = 1;
334 yes_muacct = boolprompt("Enable a 'master user' account", yes_muacct);
336 strprompt("Master user name", &sc[58][0], 31);
337 strprompt("Master user password", &sc[59][0], -31);
340 strcpy(&sc[58][0], "");
341 strcpy(&sc[59][0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
345 scr_printf("Save this configuration? ");
348 for (a = 0; a < NUM_CONFIGS; a++)
349 r += 1 + strlen(sc[a]);
350 resp = (char *)calloc(1, r);
352 err_printf("Can't save config - out of memory!\n");
355 for (a = 0; a < NUM_CONFIGS; a++) {
359 r = CtdlIPCSetSystemConfig(ipc, resp, buf);
361 err_printf("%s\n", buf);
365 r = CtdlIPCSetMessageExpirationPolicy(ipc, 2, site_expirepolicy, buf);
367 err_printf("%s\n", buf);
370 r = CtdlIPCSetMessageExpirationPolicy(ipc, 3, mbx_expirepolicy, buf);
372 err_printf("%s\n", buf);
376 if (site_expirepolicy) free(site_expirepolicy);
377 if (mbx_expirepolicy) free(mbx_expirepolicy);
382 * support function for do_internet_configuration()
384 void get_inet_rec_type(CtdlIPC *ipc, char *buf) {
387 keyopt(" <1> localhost (Alias for this computer)\n");
388 keyopt(" <2> smart-host (Forward all outbound mail to this host)\n");
389 keyopt(" <3> directory (Consult the Global Address Book)\n");
390 keyopt(" <4> SpamAssassin (Address of SpamAssassin server)\n");
391 keyopt(" <5> RBL (domain suffix of spam hunting RBL)\n");
392 keyopt(" <6> masq domains (Domains as which users are allowed to masquerade)\n");
393 sel = intprompt("Which one", 1, 1, 6);
395 case 1: strcpy(buf, "localhost");
397 case 2: strcpy(buf, "smarthost");
399 case 3: strcpy(buf, "directory");
401 case 4: strcpy(buf, "spamassassin");
403 case 5: strcpy(buf, "rbl");
405 case 6: strcpy(buf, "masqdomain");
412 * Internet mail configuration
414 void do_internet_configuration(CtdlIPC *ipc)
427 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
429 while (!IsEmptyStr(resp)) {
430 extract_token(buf, resp, 0, '\n', sizeof buf);
431 remove_token(resp, 0, '\n');
433 if (num_recs == 1) recs = malloc(sizeof(char *));
434 else recs = realloc(recs, (sizeof(char *)) * num_recs);
435 recs[num_recs-1] = malloc(strlen(buf) + 1);
436 strcpy(recs[num_recs-1], buf);
439 if (resp) free(resp);
444 scr_printf("### Host or domain Record type \n");
446 scr_printf("--- -------------------------------------------------- --------------------\n");
447 for (i=0; i<num_recs; ++i) {
449 scr_printf("%3d ", i+1);
450 extract_token(buf, recs[i], 0, '|', sizeof buf);
452 scr_printf("%-50s ", buf);
453 extract_token(buf, recs[i], 1, '|', sizeof buf);
454 color(BRIGHT_MAGENTA);
455 scr_printf("%-20s\n", buf);
459 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
462 newprompt("Enter host name: ",
465 if (!IsEmptyStr(buf)) {
468 recs = malloc(sizeof(char *));
469 else recs = realloc(recs,
470 (sizeof(char *)) * num_recs);
472 get_inet_rec_type(ipc,
474 recs[num_recs-1] = strdup(buf);
479 i = intprompt("Delete which one",
483 for (j=i; j<num_recs; ++j)
489 for (i = 0; i < num_recs; i++)
490 r += 1 + strlen(recs[i]);
491 resp = (char *)calloc(1, r);
493 err_printf("Can't save config - out of memory!\n");
496 if (num_recs) for (i = 0; i < num_recs; i++) {
497 strcat(resp, recs[i]);
500 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
502 err_printf("%s\n", buf);
504 scr_printf("Wrote %d records.\n", num_recs);
510 quitting = !modified || boolprompt(
511 "Quit without saving", 0);
519 for (i=0; i<num_recs; ++i) free(recs[i]);
527 * Edit network configuration for room sharing, mailing lists, etc.
529 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
531 char filename[PATH_MAX];
532 char changefile[PATH_MAX];
542 char *listing = NULL;
545 if (IsEmptyStr(editor_paths[0])) {
546 scr_printf("You must have an external editor configured in"
547 " order to use this function.\n");
551 CtdlMakeTempFileName(filename, sizeof filename);
552 CtdlMakeTempFileName(changefile, sizeof changefile);
554 tempfp = fopen(filename, "w");
555 if (tempfp == NULL) {
556 err_printf("Cannot open %s: %s\n", filename, strerror(errno));
560 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
561 fprintf(tempfp, "# %s\n", comment);
562 fprintf(tempfp, "# Specify one per line.\n"
565 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
567 while(listing && !IsEmptyStr(listing)) {
568 extract_token(buf, listing, 0, '\n', sizeof buf);
569 remove_token(listing, 0, '\n');
570 extract_token(instr, buf, 0, '|', sizeof instr);
571 if (!strcasecmp(instr, entrytype)) {
572 tokens = num_tokens(buf, '|');
573 for (i=1; i<tokens; ++i) {
574 extract_token(addr, buf, i, '|', sizeof addr);
575 fprintf(tempfp, "%s", addr);
576 if (i < (tokens-1)) {
577 fprintf(tempfp, "|");
580 fprintf(tempfp, "\n");
590 e_ex_code = 1; /* start with a failed exit code */
592 stty_ctdl(SB_RESTORE);
594 cksum = file_checksum(filename);
595 if (editor_pid == 0) {
596 chmod(filename, 0600);
597 putenv("WINDOW_TITLE=Network configuration");
598 execlp(editor_paths[0], editor_paths[0], filename, NULL);
601 if (editor_pid > 0) {
604 b = ka_wait(&e_ex_code);
605 } while ((b != editor_pid) && (b >= 0));
611 if (file_checksum(filename) == cksum) {
612 err_printf("*** No changes to save.\n");
616 if (e_ex_code == 0) { /* Save changes */
617 changefp = fopen(changefile, "w");
619 /* Load all netconfig entries that are *not* of the type we are editing */
620 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
622 while(listing && !IsEmptyStr(listing)) {
623 extract_token(buf, listing, 0, '\n', sizeof buf);
624 remove_token(listing, 0, '\n');
625 extract_token(instr, buf, 0, '|', sizeof instr);
626 if (strcasecmp(instr, entrytype)) {
627 fprintf(changefp, "%s\n", buf);
636 /* ...and merge that with the data we just edited */
637 tempfp = fopen(filename, "r");
638 while (fgets(buf, sizeof buf, tempfp) != NULL) {
639 for (i=0; i<strlen(buf); ++i) {
640 if (buf[i] == '#') buf[i] = 0;
643 if (!IsEmptyStr(buf)) {
644 fprintf(changefp, "%s|%s\n", entrytype, buf);
650 /* now write it to the server... */
651 changefp = fopen(changefile, "r");
652 if (changefp != NULL) {
653 listing = load_message_from_file(changefp);
655 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
663 unlink(filename); /* Delete the temporary files */
669 * IGnet node configuration
671 void do_ignet_configuration(CtdlIPC *ipc) {
680 char *listing = NULL;
683 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
684 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
685 extract_token(buf, listing, 0, '\n', sizeof buf);
686 remove_token(listing, 0, '\n');
689 if (num_recs == 1) recs = malloc(sizeof(char *));
690 else recs = realloc(recs, (sizeof(char *)) * num_recs);
691 recs[num_recs-1] = malloc(SIZ);
692 strcpy(recs[num_recs-1], buf);
694 if (listing) free(listing);
707 "------------------ "
708 "-------------------------------- "
710 for (i=0; i<num_recs; ++i) {
712 scr_printf("%3d ", i+1);
713 extract_token(buf, recs[i], 0, '|', sizeof buf);
715 scr_printf("%-16s ", buf);
716 extract_token(buf, recs[i], 1, '|', sizeof buf);
717 color(BRIGHT_MAGENTA);
718 scr_printf("%-18s ", buf);
719 extract_token(buf, recs[i], 2, '|', sizeof buf);
721 scr_printf("%-32s ", buf);
722 extract_token(buf, recs[i], 3, '|', sizeof buf);
723 color(BRIGHT_MAGENTA);
724 scr_printf("%-3s\n", buf);
729 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
734 recs = malloc(sizeof(char *));
735 else recs = realloc(recs,
736 (sizeof(char *)) * num_recs);
737 newprompt("Enter node name : ", buf, 16);
739 newprompt("Enter shared secret: ",
740 &buf[strlen(buf)], 18);
742 newprompt("Enter host or IP : ",
743 &buf[strlen(buf)], 32);
745 strprompt("Enter port number : ",
746 &buf[strlen(buf)-3], 5);
747 recs[num_recs-1] = strdup(buf);
751 i = intprompt("Delete which one",
755 for (j=i; j<num_recs; ++j)
761 for (i = 0; i < num_recs; ++i)
762 r += 1 + strlen(recs[i]);
763 listing = (char*) calloc(1, r);
765 err_printf("Can't save config - out of memory!\n");
768 if (num_recs) for (i = 0; i < num_recs; ++i) {
769 strcat(listing, recs[i]);
770 strcat(listing, "\n");
772 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
774 scr_printf("%s\n", buf);
776 scr_printf("Wrote %d records.\n", num_recs);
782 quitting = !modified || boolprompt(
783 "Quit without saving", 0);
791 for (i=0; i<num_recs; ++i) free(recs[i]);
798 * Filter list configuration
800 void do_filterlist_configuration(CtdlIPC *ipc)
810 char *listing = NULL;
813 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
814 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
815 extract_token(buf, listing, 0, '\n', sizeof buf);
816 remove_token(listing, 0, '\n');
819 if (num_recs == 1) recs = malloc(sizeof(char *));
820 else recs = realloc(recs, (sizeof(char *)) * num_recs);
821 recs[num_recs-1] = malloc(SIZ);
822 strcpy(recs[num_recs-1], buf);
824 if (listing) free(listing);
836 "---------------------------- "
837 "---------------------------- "
840 for (i=0; i<num_recs; ++i) {
842 scr_printf("%3d ", i+1);
843 extract_token(buf, recs[i], 0, '|', sizeof buf);
845 scr_printf("%-28s ", buf);
846 extract_token(buf, recs[i], 1, '|', sizeof buf);
847 color(BRIGHT_MAGENTA);
848 scr_printf("%-28s ", buf);
849 extract_token(buf, recs[i], 2, '|', sizeof buf);
851 scr_printf("%-16s\n", buf);
852 extract_token(buf, recs[i], 3, '|', sizeof buf);
856 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
861 recs = malloc(sizeof(char *));
862 else recs = realloc(recs,
863 (sizeof(char *)) * num_recs);
864 newprompt("Enter user name: ", buf, 28);
866 newprompt("Enter room name: ",
867 &buf[strlen(buf)], 28);
869 newprompt("Enter node name: ",
870 &buf[strlen(buf)], 16);
872 recs[num_recs-1] = strdup(buf);
876 i = intprompt("Delete which one",
880 for (j=i; j<num_recs; ++j)
886 for (i = 0; i < num_recs; ++i)
887 r += 1 + strlen(recs[i]);
888 listing = (char*) calloc(1, r);
890 err_printf("Can't save config - out of memory!\n");
893 if (num_recs) for (i = 0; i < num_recs; ++i) {
894 strcat(listing, recs[i]);
895 strcat(listing, "\n");
897 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
899 scr_printf("%s\n", buf);
901 scr_printf("Wrote %d records.\n", num_recs);
907 quitting = !modified || boolprompt(
908 "Quit without saving", 0);
916 for (i=0; i<num_recs; ++i) free(recs[i]);
925 * POP3 aggregation client configuration
927 void do_pop3client_configuration(CtdlIPC *ipc)
937 char *listing = NULL;
938 char *other_listing = NULL;
942 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
944 while(listing && !IsEmptyStr(listing)) {
945 extract_token(buf, listing, 0, '\n', sizeof buf);
946 remove_token(listing, 0, '\n');
947 extract_token(instr, buf, 0, '|', sizeof instr);
948 if (!strcasecmp(instr, "pop3client")) {
951 if (num_recs == 1) recs = malloc(sizeof(char *));
952 else recs = realloc(recs, (sizeof(char *)) * num_recs);
953 recs[num_recs-1] = malloc(SIZ);
954 strcpy(recs[num_recs-1], buf);
975 "---------------------------- "
976 "---------------------------- "
980 for (i=0; i<num_recs; ++i) {
982 scr_printf("%3d ", i+1);
984 extract_token(buf, recs[i], 1, '|', sizeof buf);
986 scr_printf("%-28s ", buf);
988 extract_token(buf, recs[i], 2, '|', sizeof buf);
989 color(BRIGHT_MAGENTA);
990 scr_printf("%-28s ", buf);
993 scr_printf("%-15s ", (extract_int(recs[i], 4) ? "Yes" : "No") );
994 color(BRIGHT_MAGENTA);
995 scr_printf("%ld\n", extract_long(recs[i], 5) );
999 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1003 if (num_recs == 1) {
1004 recs = malloc(sizeof(char *));
1007 recs = realloc(recs, (sizeof(char *)) * num_recs);
1009 strcpy(buf, "pop3client|");
1010 newprompt("Enter host name: ", &buf[strlen(buf)], 28);
1012 newprompt("Enter user name: ", &buf[strlen(buf)], 28);
1014 newprompt("Enter password : ", &buf[strlen(buf)], 16);
1016 scr_printf("Keep messages on server instead of deleting them? ");
1017 sprintf(&buf[strlen(buf)], "%d", yesno());
1019 newprompt("Enter interval : ", &buf[strlen(buf)], 5);
1021 recs[num_recs-1] = strdup(buf);
1025 i = intprompt("Delete which one",
1026 1, 1, num_recs) - 1;
1029 for (j=i; j<num_recs; ++j)
1030 recs[j] = recs[j+1];
1035 for (i = 0; i < num_recs; ++i) {
1036 r += 1 + strlen(recs[i]);
1038 listing = (char*) calloc(1, r);
1040 err_printf("Can't save config - out of memory!\n");
1043 if (num_recs) for (i = 0; i < num_recs; ++i) {
1044 strcat(listing, recs[i]);
1045 strcat(listing, "\n");
1048 /* Retrieve all the *other* records for merging */
1049 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1051 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1052 extract_token(buf, other_listing, i, '\n', sizeof buf);
1053 if (strncasecmp(buf, "pop3client|", 11)) {
1054 listing = realloc(listing, strlen(listing) +
1056 strcat(listing, buf);
1057 strcat(listing, "\n");
1061 free(other_listing);
1062 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1067 scr_printf("%s\n", buf);
1069 scr_printf("Wrote %d records.\n", num_recs);
1075 quitting = !modified || boolprompt(
1076 "Quit without saving", 0);
1081 } while (!quitting);
1084 for (i=0; i<num_recs; ++i) free(recs[i]);
1095 * RSS feed retrieval client configuration
1097 void do_rssclient_configuration(CtdlIPC *ipc)
1107 char *listing = NULL;
1108 char *other_listing = NULL;
1112 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1114 while(listing && !IsEmptyStr(listing)) {
1115 extract_token(buf, listing, 0, '\n', sizeof buf);
1116 remove_token(listing, 0, '\n');
1117 extract_token(instr, buf, 0, '|', sizeof instr);
1118 if (!strcasecmp(instr, "rssclient")) {
1121 if (num_recs == 1) recs = malloc(sizeof(char *));
1122 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1123 recs[num_recs-1] = malloc(SIZ);
1124 strcpy(recs[num_recs-1], buf);
1136 color(BRIGHT_WHITE);
1137 scr_printf("### Feed URL\n");
1140 "---------------------------------------------------------------------------"
1143 for (i=0; i<num_recs; ++i) {
1145 scr_printf("%3d ", i+1);
1147 extract_token(buf, recs[i], 1, '|', sizeof buf);
1149 scr_printf("%-75s\n", buf);
1154 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1158 if (num_recs == 1) {
1159 recs = malloc(sizeof(char *));
1162 recs = realloc(recs, (sizeof(char *)) * num_recs);
1164 strcpy(buf, "rssclient|");
1165 newprompt("Enter feed URL: ", &buf[strlen(buf)], 75);
1167 recs[num_recs-1] = strdup(buf);
1171 i = intprompt("Delete which one", 1, 1, num_recs) - 1;
1174 for (j=i; j<num_recs; ++j)
1175 recs[j] = recs[j+1];
1180 for (i = 0; i < num_recs; ++i) {
1181 r += 1 + strlen(recs[i]);
1183 listing = (char*) calloc(1, r);
1185 err_printf("Can't save config - out of memory!\n");
1188 if (num_recs) for (i = 0; i < num_recs; ++i) {
1189 strcat(listing, recs[i]);
1190 strcat(listing, "\n");
1193 /* Retrieve all the *other* records for merging */
1194 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1196 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1197 extract_token(buf, other_listing, i, '\n', sizeof buf);
1198 if (strncasecmp(buf, "rssclient|", 10)) {
1199 listing = realloc(listing, strlen(listing) +
1201 strcat(listing, buf);
1202 strcat(listing, "\n");
1206 free(other_listing);
1207 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1212 scr_printf("%s\n", buf);
1214 scr_printf("Wrote %d records.\n", num_recs);
1220 quitting = !modified || boolprompt(
1221 "Quit without saving", 0);
1226 } while (!quitting);
1229 for (i=0; i<num_recs; ++i) free(recs[i]);