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 keyopt(" <7> ClamAV (Address of ClamAV clamd server)\n");
394 sel = intprompt("Which one", 1, 1, 7);
396 case 1: strcpy(buf, "localhost");
398 case 2: strcpy(buf, "smarthost");
400 case 3: strcpy(buf, "directory");
402 case 4: strcpy(buf, "spamassassin");
404 case 5: strcpy(buf, "rbl");
406 case 6: strcpy(buf, "masqdomain");
408 case 7: strcpy(buf, "clamav");
415 * Internet mail configuration
417 void do_internet_configuration(CtdlIPC *ipc)
430 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
432 while (!IsEmptyStr(resp)) {
433 extract_token(buf, resp, 0, '\n', sizeof buf);
434 remove_token(resp, 0, '\n');
436 if (num_recs == 1) recs = malloc(sizeof(char *));
437 else recs = realloc(recs, (sizeof(char *)) * num_recs);
438 recs[num_recs-1] = malloc(strlen(buf) + 1);
439 strcpy(recs[num_recs-1], buf);
442 if (resp) free(resp);
447 scr_printf("### Host or domain Record type \n");
449 scr_printf("--- -------------------------------------------------- --------------------\n");
450 for (i=0; i<num_recs; ++i) {
452 scr_printf("%3d ", i+1);
453 extract_token(buf, recs[i], 0, '|', sizeof buf);
455 scr_printf("%-50s ", buf);
456 extract_token(buf, recs[i], 1, '|', sizeof buf);
457 color(BRIGHT_MAGENTA);
458 scr_printf("%-20s\n", buf);
462 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
465 newprompt("Enter host name: ",
468 if (!IsEmptyStr(buf)) {
471 recs = malloc(sizeof(char *));
472 else recs = realloc(recs,
473 (sizeof(char *)) * num_recs);
475 get_inet_rec_type(ipc,
477 recs[num_recs-1] = strdup(buf);
482 i = intprompt("Delete which one",
486 for (j=i; j<num_recs; ++j)
492 for (i = 0; i < num_recs; i++)
493 r += 1 + strlen(recs[i]);
494 resp = (char *)calloc(1, r);
496 err_printf("Can't save config - out of memory!\n");
499 if (num_recs) for (i = 0; i < num_recs; i++) {
500 strcat(resp, recs[i]);
503 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
505 err_printf("%s\n", buf);
507 scr_printf("Wrote %d records.\n", num_recs);
513 quitting = !modified || boolprompt(
514 "Quit without saving", 0);
522 for (i=0; i<num_recs; ++i) free(recs[i]);
530 * Edit network configuration for room sharing, mailing lists, etc.
532 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
534 char filename[PATH_MAX];
535 char changefile[PATH_MAX];
545 char *listing = NULL;
548 if (IsEmptyStr(editor_paths[0])) {
549 scr_printf("You must have an external editor configured in"
550 " order to use this function.\n");
554 CtdlMakeTempFileName(filename, sizeof filename);
555 CtdlMakeTempFileName(changefile, sizeof changefile);
557 tempfp = fopen(filename, "w");
558 if (tempfp == NULL) {
559 err_printf("Cannot open %s: %s\n", filename, strerror(errno));
563 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
564 fprintf(tempfp, "# %s\n", comment);
565 fprintf(tempfp, "# Specify one per line.\n"
568 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
570 while(listing && !IsEmptyStr(listing)) {
571 extract_token(buf, listing, 0, '\n', sizeof buf);
572 remove_token(listing, 0, '\n');
573 extract_token(instr, buf, 0, '|', sizeof instr);
574 if (!strcasecmp(instr, entrytype)) {
575 tokens = num_tokens(buf, '|');
576 for (i=1; i<tokens; ++i) {
577 extract_token(addr, buf, i, '|', sizeof addr);
578 fprintf(tempfp, "%s", addr);
579 if (i < (tokens-1)) {
580 fprintf(tempfp, "|");
583 fprintf(tempfp, "\n");
593 e_ex_code = 1; /* start with a failed exit code */
595 stty_ctdl(SB_RESTORE);
597 cksum = file_checksum(filename);
598 if (editor_pid == 0) {
599 chmod(filename, 0600);
600 putenv("WINDOW_TITLE=Network configuration");
601 execlp(editor_paths[0], editor_paths[0], filename, NULL);
604 if (editor_pid > 0) {
607 b = ka_wait(&e_ex_code);
608 } while ((b != editor_pid) && (b >= 0));
614 if (file_checksum(filename) == cksum) {
615 err_printf("*** No changes to save.\n");
619 if (e_ex_code == 0) { /* Save changes */
620 changefp = fopen(changefile, "w");
622 /* Load all netconfig entries that are *not* of the type we are editing */
623 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
625 while(listing && !IsEmptyStr(listing)) {
626 extract_token(buf, listing, 0, '\n', sizeof buf);
627 remove_token(listing, 0, '\n');
628 extract_token(instr, buf, 0, '|', sizeof instr);
629 if (strcasecmp(instr, entrytype)) {
630 fprintf(changefp, "%s\n", buf);
639 /* ...and merge that with the data we just edited */
640 tempfp = fopen(filename, "r");
641 while (fgets(buf, sizeof buf, tempfp) != NULL) {
642 for (i=0; i<strlen(buf); ++i) {
643 if (buf[i] == '#') buf[i] = 0;
646 if (!IsEmptyStr(buf)) {
647 fprintf(changefp, "%s|%s\n", entrytype, buf);
653 /* now write it to the server... */
654 changefp = fopen(changefile, "r");
655 if (changefp != NULL) {
656 listing = load_message_from_file(changefp);
658 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
666 unlink(filename); /* Delete the temporary files */
672 * IGnet node configuration
674 void do_ignet_configuration(CtdlIPC *ipc) {
683 char *listing = NULL;
686 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
687 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
688 extract_token(buf, listing, 0, '\n', sizeof buf);
689 remove_token(listing, 0, '\n');
692 if (num_recs == 1) recs = malloc(sizeof(char *));
693 else recs = realloc(recs, (sizeof(char *)) * num_recs);
694 recs[num_recs-1] = malloc(SIZ);
695 strcpy(recs[num_recs-1], buf);
697 if (listing) free(listing);
710 "------------------ "
711 "-------------------------------- "
713 for (i=0; i<num_recs; ++i) {
715 scr_printf("%3d ", i+1);
716 extract_token(buf, recs[i], 0, '|', sizeof buf);
718 scr_printf("%-16s ", buf);
719 extract_token(buf, recs[i], 1, '|', sizeof buf);
720 color(BRIGHT_MAGENTA);
721 scr_printf("%-18s ", buf);
722 extract_token(buf, recs[i], 2, '|', sizeof buf);
724 scr_printf("%-32s ", buf);
725 extract_token(buf, recs[i], 3, '|', sizeof buf);
726 color(BRIGHT_MAGENTA);
727 scr_printf("%-3s\n", buf);
732 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
737 recs = malloc(sizeof(char *));
738 else recs = realloc(recs,
739 (sizeof(char *)) * num_recs);
740 newprompt("Enter node name : ", buf, 16);
742 newprompt("Enter shared secret: ",
743 &buf[strlen(buf)], 18);
745 newprompt("Enter host or IP : ",
746 &buf[strlen(buf)], 32);
748 strprompt("Enter port number : ",
749 &buf[strlen(buf)-3], 5);
750 recs[num_recs-1] = strdup(buf);
754 i = intprompt("Delete which one",
758 for (j=i; j<num_recs; ++j)
764 for (i = 0; i < num_recs; ++i)
765 r += 1 + strlen(recs[i]);
766 listing = (char*) calloc(1, r);
768 err_printf("Can't save config - out of memory!\n");
771 if (num_recs) for (i = 0; i < num_recs; ++i) {
772 strcat(listing, recs[i]);
773 strcat(listing, "\n");
775 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
777 scr_printf("%s\n", buf);
779 scr_printf("Wrote %d records.\n", num_recs);
785 quitting = !modified || boolprompt(
786 "Quit without saving", 0);
794 for (i=0; i<num_recs; ++i) free(recs[i]);
801 * Filter list configuration
803 void do_filterlist_configuration(CtdlIPC *ipc)
813 char *listing = NULL;
816 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
817 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
818 extract_token(buf, listing, 0, '\n', sizeof buf);
819 remove_token(listing, 0, '\n');
822 if (num_recs == 1) recs = malloc(sizeof(char *));
823 else recs = realloc(recs, (sizeof(char *)) * num_recs);
824 recs[num_recs-1] = malloc(SIZ);
825 strcpy(recs[num_recs-1], buf);
827 if (listing) free(listing);
839 "---------------------------- "
840 "---------------------------- "
843 for (i=0; i<num_recs; ++i) {
845 scr_printf("%3d ", i+1);
846 extract_token(buf, recs[i], 0, '|', sizeof buf);
848 scr_printf("%-28s ", buf);
849 extract_token(buf, recs[i], 1, '|', sizeof buf);
850 color(BRIGHT_MAGENTA);
851 scr_printf("%-28s ", buf);
852 extract_token(buf, recs[i], 2, '|', sizeof buf);
854 scr_printf("%-16s\n", buf);
855 extract_token(buf, recs[i], 3, '|', sizeof buf);
859 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
864 recs = malloc(sizeof(char *));
865 else recs = realloc(recs,
866 (sizeof(char *)) * num_recs);
867 newprompt("Enter user name: ", buf, 28);
869 newprompt("Enter room name: ",
870 &buf[strlen(buf)], 28);
872 newprompt("Enter node name: ",
873 &buf[strlen(buf)], 16);
875 recs[num_recs-1] = strdup(buf);
879 i = intprompt("Delete which one",
883 for (j=i; j<num_recs; ++j)
889 for (i = 0; i < num_recs; ++i)
890 r += 1 + strlen(recs[i]);
891 listing = (char*) calloc(1, r);
893 err_printf("Can't save config - out of memory!\n");
896 if (num_recs) for (i = 0; i < num_recs; ++i) {
897 strcat(listing, recs[i]);
898 strcat(listing, "\n");
900 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
902 scr_printf("%s\n", buf);
904 scr_printf("Wrote %d records.\n", num_recs);
910 quitting = !modified || boolprompt(
911 "Quit without saving", 0);
919 for (i=0; i<num_recs; ++i) free(recs[i]);
928 * POP3 aggregation client configuration
930 void do_pop3client_configuration(CtdlIPC *ipc)
940 char *listing = NULL;
941 char *other_listing = NULL;
945 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
947 while(listing && !IsEmptyStr(listing)) {
948 extract_token(buf, listing, 0, '\n', sizeof buf);
949 remove_token(listing, 0, '\n');
950 extract_token(instr, buf, 0, '|', sizeof instr);
951 if (!strcasecmp(instr, "pop3client")) {
954 if (num_recs == 1) recs = malloc(sizeof(char *));
955 else recs = realloc(recs, (sizeof(char *)) * num_recs);
956 recs[num_recs-1] = malloc(SIZ);
957 strcpy(recs[num_recs-1], buf);
978 "---------------------------- "
979 "---------------------------- "
983 for (i=0; i<num_recs; ++i) {
985 scr_printf("%3d ", i+1);
987 extract_token(buf, recs[i], 1, '|', sizeof buf);
989 scr_printf("%-28s ", buf);
991 extract_token(buf, recs[i], 2, '|', sizeof buf);
992 color(BRIGHT_MAGENTA);
993 scr_printf("%-28s ", buf);
996 scr_printf("%-15s ", (extract_int(recs[i], 4) ? "Yes" : "No") );
997 color(BRIGHT_MAGENTA);
998 scr_printf("%ld\n", extract_long(recs[i], 5) );
1002 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1006 if (num_recs == 1) {
1007 recs = malloc(sizeof(char *));
1010 recs = realloc(recs, (sizeof(char *)) * num_recs);
1012 strcpy(buf, "pop3client|");
1013 newprompt("Enter host name: ", &buf[strlen(buf)], 28);
1015 newprompt("Enter user name: ", &buf[strlen(buf)], 28);
1017 newprompt("Enter password : ", &buf[strlen(buf)], 16);
1019 scr_printf("Keep messages on server instead of deleting them? ");
1020 sprintf(&buf[strlen(buf)], "%d", yesno());
1022 newprompt("Enter interval : ", &buf[strlen(buf)], 5);
1024 recs[num_recs-1] = strdup(buf);
1028 i = intprompt("Delete which one",
1029 1, 1, num_recs) - 1;
1032 for (j=i; j<num_recs; ++j)
1033 recs[j] = recs[j+1];
1038 for (i = 0; i < num_recs; ++i) {
1039 r += 1 + strlen(recs[i]);
1041 listing = (char*) calloc(1, r);
1043 err_printf("Can't save config - out of memory!\n");
1046 if (num_recs) for (i = 0; i < num_recs; ++i) {
1047 strcat(listing, recs[i]);
1048 strcat(listing, "\n");
1051 /* Retrieve all the *other* records for merging */
1052 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1054 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1055 extract_token(buf, other_listing, i, '\n', sizeof buf);
1056 if (strncasecmp(buf, "pop3client|", 11)) {
1057 listing = realloc(listing, strlen(listing) +
1059 strcat(listing, buf);
1060 strcat(listing, "\n");
1064 free(other_listing);
1065 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1070 scr_printf("%s\n", buf);
1072 scr_printf("Wrote %d records.\n", num_recs);
1078 quitting = !modified || boolprompt(
1079 "Quit without saving", 0);
1084 } while (!quitting);
1087 for (i=0; i<num_recs; ++i) free(recs[i]);
1098 * RSS feed retrieval client configuration
1100 void do_rssclient_configuration(CtdlIPC *ipc)
1110 char *listing = NULL;
1111 char *other_listing = NULL;
1115 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1117 while(listing && !IsEmptyStr(listing)) {
1118 extract_token(buf, listing, 0, '\n', sizeof buf);
1119 remove_token(listing, 0, '\n');
1120 extract_token(instr, buf, 0, '|', sizeof instr);
1121 if (!strcasecmp(instr, "rssclient")) {
1124 if (num_recs == 1) recs = malloc(sizeof(char *));
1125 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1126 recs[num_recs-1] = malloc(SIZ);
1127 strcpy(recs[num_recs-1], buf);
1139 color(BRIGHT_WHITE);
1140 scr_printf("### Feed URL\n");
1143 "---------------------------------------------------------------------------"
1146 for (i=0; i<num_recs; ++i) {
1148 scr_printf("%3d ", i+1);
1150 extract_token(buf, recs[i], 1, '|', sizeof buf);
1152 scr_printf("%-75s\n", buf);
1157 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1161 if (num_recs == 1) {
1162 recs = malloc(sizeof(char *));
1165 recs = realloc(recs, (sizeof(char *)) * num_recs);
1167 strcpy(buf, "rssclient|");
1168 newprompt("Enter feed URL: ", &buf[strlen(buf)], 75);
1170 recs[num_recs-1] = strdup(buf);
1174 i = intprompt("Delete which one", 1, 1, num_recs) - 1;
1177 for (j=i; j<num_recs; ++j)
1178 recs[j] = recs[j+1];
1183 for (i = 0; i < num_recs; ++i) {
1184 r += 1 + strlen(recs[i]);
1186 listing = (char*) calloc(1, r);
1188 err_printf("Can't save config - out of memory!\n");
1191 if (num_recs) for (i = 0; i < num_recs; ++i) {
1192 strcat(listing, recs[i]);
1193 strcat(listing, "\n");
1196 /* Retrieve all the *other* records for merging */
1197 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1199 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1200 extract_token(buf, other_listing, i, '\n', sizeof buf);
1201 if (strncasecmp(buf, "rssclient|", 10)) {
1202 listing = realloc(listing, strlen(listing) +
1204 strcat(listing, buf);
1205 strcat(listing, "\n");
1209 free(other_listing);
1210 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1215 scr_printf("%s\n", buf);
1217 scr_printf("Wrote %d records.\n", num_recs);
1223 quitting = !modified || boolprompt(
1224 "Quit without saving", 0);
1229 } while (!quitting);
1232 for (i=0; i<num_recs; ++i) free(recs[i]);