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 68
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[67], sizeof sc[67], "%d", (boolprompt(
120 "Allow anonymous guest logins",
122 snprintf(sc[4], sizeof sc[4], "%d", (boolprompt(
123 "Automatically give room aide privs to a user who creates a private room",
126 snprintf(sc[8], sizeof sc[8], "%d", (boolprompt(
127 "Automatically move problem user messages to twit room",
130 strprompt("Name of twit room", &sc[9][0], ROOMNAMELEN);
131 snprintf(sc[11], sizeof sc[11], "%d", (boolprompt(
132 "Restrict Internet mail to only those with that privilege",
134 snprintf(sc[26], sizeof sc[26], "%d", (boolprompt(
135 "Allow Aides to Zap (forget) rooms",
138 if (!IsEmptyStr(&sc[18][0])) {
144 logpages = boolprompt("Log all instant messages", logpages);
146 strprompt("Name of logging room", &sc[18][0], ROOMNAMELEN);
152 /* Commented out because this setting isn't really appropriate to
153 * change while the server is running.
155 * snprintf(sc[52], sizeof sc[52], "%d", (boolprompt(
156 * "Use system authentication",
157 * atoi(&sc[52][0]))));
162 strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
163 strprompt("Maximum concurrent sessions", &sc[14][0], 4);
164 strprompt("Maximum message length", &sc[20][0], 20);
165 strprompt("Minimum number of worker threads", &sc[21][0], 3);
166 strprompt("Maximum number of worker threads", &sc[22][0], 3);
167 snprintf(sc[43], sizeof sc[43], "%d", (boolprompt(
168 "Automatically delete committed database logs",
171 strprompt("Server IP address (* for 'any')", &sc[37][0], 15);
172 strprompt("POP3 server port (-1 to disable)", &sc[23][0], 5);
173 strprompt("POP3S server port (-1 to disable)", &sc[40][0], 5);
174 strprompt("IMAP server port (-1 to disable)", &sc[27][0], 5);
175 strprompt("IMAPS server port (-1 to disable)", &sc[39][0], 5);
176 strprompt("SMTP MTA server port (-1 to disable)", &sc[24][0], 5);
177 strprompt("SMTP MSA server port (-1 to disable)", &sc[38][0], 5);
178 strprompt("SMTPS server port (-1 to disable)", &sc[41][0], 5);
179 strprompt("Postfix TCP Dictionary Port server port (-1 to disable)", &sc[50][0], 5);
180 strprompt("ManageSieve server port (-1 to disable)", &sc[51][0], 5);
182 strprompt("XMPP (Jabber) client to server port (-1 to disable)", &sc[62][0], 5);
183 /* No prompt because we don't implement this service yet, it's just a placeholder */
184 /* strprompt("XMPP (Jabber) server to server port (-1 to disable)", &sc[63][0], 5); */
186 /* This logic flips the question around, because it's one of those
187 * situations where 0=yes and 1=no
191 a = boolprompt("Correct forged From: lines during authenticated SMTP",
194 snprintf(sc[25], sizeof sc[25], "%d", a);
196 snprintf(sc[66], sizeof sc[66], "%d", (boolprompt(
197 "Flag messages as spam instead of rejecting",
200 /* This logic flips the question around, because it's one of those
201 * situations where 0=yes and 1=no
205 a = boolprompt("Force IMAP posts in public rooms to be from the user who submitted them", a);
207 snprintf(sc[61], sizeof sc[61], "%d", a);
209 snprintf(sc[45], sizeof sc[45], "%d", (boolprompt(
210 "Allow unauthenticated SMTP clients to spoof my domains",
212 snprintf(sc[57], sizeof sc[57], "%d", (boolprompt(
213 "Perform RBL checks at greeting instead of after RCPT",
215 snprintf(sc[44], sizeof sc[44], "%d", (boolprompt(
216 "Instantly expunge deleted IMAP messages",
220 if (ipc->ServInfo.supports_ldap) {
221 a = strlen(&sc[32][0]);
222 a = (a ? 1 : 0); /* Set only to 1 or 0 */
223 a = boolprompt("Do you want to configure LDAP authentication?", a);
225 strprompt("Host name of LDAP server",
227 strprompt("Port number of LDAP service",
229 strprompt("Base DN", &sc[34][0], 255);
230 strprompt("Bind DN (or blank for anonymous bind)", &sc[35][0], 255);
231 strprompt("Password for bind DN (or blank for anonymous bind)", &sc[36][0], 255);
234 strcpy(&sc[32][0], "");
238 /* Expiry settings */
239 strprompt("Default user purge time (days)", &sc[16][0], 5);
240 strprompt("Default room purge time (days)", &sc[17][0], 5);
242 /* Angels and demons dancing in my head... */
244 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_mode);
245 strprompt("System default message expire policy (? for list)",
249 "1. Never automatically expire messages\n"
250 "2. Expire by message count\n"
251 "3. Expire by message age\n");
253 } while ((buf[0] < '1') || (buf[0] > '3'));
254 site_expirepolicy->expire_mode = buf[0] - '0';
256 /* ...lunatics and monsters underneath my bed */
257 if (site_expirepolicy->expire_mode == 2) {
258 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
259 strprompt("Keep how many messages online?", buf, 10);
260 site_expirepolicy->expire_value = atol(buf);
262 if (site_expirepolicy->expire_mode == 3) {
263 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
264 strprompt("Keep messages for how many days?", buf, 10);
265 site_expirepolicy->expire_value = atol(buf);
268 /* Media messiahs preying on my fears... */
270 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_mode);
271 strprompt("Mailbox default message expire policy (? for list)",
275 "0. Go with the system default\n"
276 "1. Never automatically expire messages\n"
277 "2. Expire by message count\n"
278 "3. Expire by message age\n");
280 } while ((buf[0] < '0') || (buf[0] > '3'));
281 mbx_expirepolicy->expire_mode = buf[0] - '0';
283 /* ...Pop culture prophets playing in my ears */
284 if (mbx_expirepolicy->expire_mode == 2) {
285 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
286 strprompt("Keep how many messages online?", buf, 10);
287 mbx_expirepolicy->expire_value = atol(buf);
289 if (mbx_expirepolicy->expire_mode == 3) {
290 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
291 strprompt("Keep messages for how many days?", buf, 10);
292 mbx_expirepolicy->expire_value = atol(buf);
295 strprompt("How often to run network jobs (in seconds)", &sc[28][0], 5);
296 strprompt("Default frequency to run POP3 collection (in seconds)", &sc[64][0], 5);
297 strprompt("Fastest frequency to run POP3 collection (in seconds)", &sc[65][0], 5);
298 strprompt("Hour to run purges (0-23)", &sc[31][0], 2);
299 snprintf(sc[42], sizeof sc[42], "%d", (boolprompt(
300 "Enable full text search index (warning: resource intensive)",
303 snprintf(sc[46], sizeof sc[46], "%d", (boolprompt(
304 "Perform journaling of email messages",
306 snprintf(sc[47], sizeof sc[47], "%d", (boolprompt(
307 "Perform journaling of non-email messages",
309 if ( (atoi(&sc[46][0])) || (atoi(&sc[47][0])) ) {
310 strprompt("Email destination of journalized messages",
314 /* Funambol push stuff */
315 int yes_funambol = 0;
316 if (strlen(sc[53]) > 0) yes_funambol = 1;
317 yes_funambol = boolprompt("Connect to an external Funambol sync server", yes_funambol);
319 strprompt("Funambol server (blank to disable)", &sc[53][0], 63);
320 strprompt("Funambol server port", &sc[54][0], 5);
321 strprompt("Funambol sync source", &sc[55][0], 63);
322 strprompt("Funambol authentication details (user:pass in Base64)", &sc[56][0],63);
331 /* External pager stuff */
333 if (strlen(sc[60]) > 0) yes_pager = 1;
334 yes_pager = boolprompt("Configure an external pager tool", yes_pager);
336 strprompt("External pager tool", &sc[60][0], 255);
342 /* Master user account */
344 if (strlen(sc[58]) > 0) yes_muacct = 1;
345 yes_muacct = boolprompt("Enable a 'master user' account", yes_muacct);
347 strprompt("Master user name", &sc[58][0], 31);
348 strprompt("Master user password", &sc[59][0], -31);
351 strcpy(&sc[58][0], "");
352 strcpy(&sc[59][0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
356 scr_printf("Save this configuration? ");
359 for (a = 0; a < NUM_CONFIGS; a++)
360 r += 1 + strlen(sc[a]);
361 resp = (char *)calloc(1, r);
363 err_printf("Can't save config - out of memory!\n");
366 for (a = 0; a < NUM_CONFIGS; a++) {
370 r = CtdlIPCSetSystemConfig(ipc, resp, buf);
372 err_printf("%s\n", buf);
376 r = CtdlIPCSetMessageExpirationPolicy(ipc, 2, site_expirepolicy, buf);
378 err_printf("%s\n", buf);
381 r = CtdlIPCSetMessageExpirationPolicy(ipc, 3, mbx_expirepolicy, buf);
383 err_printf("%s\n", buf);
387 if (site_expirepolicy) free(site_expirepolicy);
388 if (mbx_expirepolicy) free(mbx_expirepolicy);
393 * support function for do_internet_configuration()
395 void get_inet_rec_type(CtdlIPC *ipc, char *buf) {
398 keyopt(" <1> localhost (Alias for this computer)\n");
399 keyopt(" <2> smart host (Forward all outbound mail to this host)\n");
400 keyopt(" <3> fallback host (Send mail to this host only if direct delivery fails)\n");
401 keyopt(" <4> directory (Consult the Global Address Book)\n");
402 keyopt(" <5> SpamAssassin (Address of SpamAssassin server)\n");
403 keyopt(" <6> RBL (domain suffix of spam hunting RBL)\n");
404 keyopt(" <7> masq domains (Domains as which users are allowed to masquerade)\n");
405 keyopt(" <8> ClamAV (Address of ClamAV clamd server)\n");
406 sel = intprompt("Which one", 1, 1, 7);
408 case 1: strcpy(buf, "localhost");
410 case 2: strcpy(buf, "smarthost");
412 case 3: strcpy(buf, "fallbackhost");
414 case 4: strcpy(buf, "directory");
416 case 5: strcpy(buf, "spamassassin");
418 case 6: strcpy(buf, "rbl");
420 case 7: strcpy(buf, "masqdomain");
422 case 8: strcpy(buf, "clamav");
429 * Internet mail configuration
431 void do_internet_configuration(CtdlIPC *ipc)
444 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
446 while (!IsEmptyStr(resp)) {
447 extract_token(buf, resp, 0, '\n', sizeof buf);
448 remove_token(resp, 0, '\n');
450 if (num_recs == 1) recs = malloc(sizeof(char *));
451 else recs = realloc(recs, (sizeof(char *)) * num_recs);
452 recs[num_recs-1] = malloc(strlen(buf) + 1);
453 strcpy(recs[num_recs-1], buf);
456 if (resp) free(resp);
461 scr_printf("### Host or domain Record type \n");
463 scr_printf("--- -------------------------------------------------- --------------------\n");
464 for (i=0; i<num_recs; ++i) {
466 scr_printf("%3d ", i+1);
467 extract_token(buf, recs[i], 0, '|', sizeof buf);
469 scr_printf("%-50s ", buf);
470 extract_token(buf, recs[i], 1, '|', sizeof buf);
471 color(BRIGHT_MAGENTA);
472 scr_printf("%-20s\n", buf);
476 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
479 newprompt("Enter host name: ",
482 if (!IsEmptyStr(buf)) {
485 recs = malloc(sizeof(char *));
486 else recs = realloc(recs,
487 (sizeof(char *)) * num_recs);
489 get_inet_rec_type(ipc,
491 recs[num_recs-1] = strdup(buf);
496 i = intprompt("Delete which one",
500 for (j=i; j<num_recs; ++j)
506 for (i = 0; i < num_recs; i++)
507 r += 1 + strlen(recs[i]);
508 resp = (char *)calloc(1, r);
510 err_printf("Can't save config - out of memory!\n");
513 if (num_recs) for (i = 0; i < num_recs; i++) {
514 strcat(resp, recs[i]);
517 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
519 err_printf("%s\n", buf);
521 scr_printf("Wrote %d records.\n", num_recs);
527 quitting = !modified || boolprompt(
528 "Quit without saving", 0);
536 for (i=0; i<num_recs; ++i) free(recs[i]);
544 * Edit network configuration for room sharing, mailing lists, etc.
546 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
548 char filename[PATH_MAX];
549 char changefile[PATH_MAX];
559 char *listing = NULL;
562 if (IsEmptyStr(editor_paths[0])) {
563 scr_printf("You must have an external editor configured in"
564 " order to use this function.\n");
568 CtdlMakeTempFileName(filename, sizeof filename);
569 CtdlMakeTempFileName(changefile, sizeof changefile);
571 tempfp = fopen(filename, "w");
572 if (tempfp == NULL) {
573 err_printf("Cannot open %s: %s\n", filename, strerror(errno));
577 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
578 fprintf(tempfp, "# %s\n", comment);
579 fprintf(tempfp, "# Specify one per line.\n"
582 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
584 while(listing && !IsEmptyStr(listing)) {
585 extract_token(buf, listing, 0, '\n', sizeof buf);
586 remove_token(listing, 0, '\n');
587 extract_token(instr, buf, 0, '|', sizeof instr);
588 if (!strcasecmp(instr, entrytype)) {
589 tokens = num_tokens(buf, '|');
590 for (i=1; i<tokens; ++i) {
591 extract_token(addr, buf, i, '|', sizeof addr);
592 fprintf(tempfp, "%s", addr);
593 if (i < (tokens-1)) {
594 fprintf(tempfp, "|");
597 fprintf(tempfp, "\n");
607 e_ex_code = 1; /* start with a failed exit code */
609 stty_ctdl(SB_RESTORE);
611 cksum = file_checksum(filename);
612 if (editor_pid == 0) {
613 chmod(filename, 0600);
614 putenv("WINDOW_TITLE=Network configuration");
615 execlp(editor_paths[0], editor_paths[0], filename, NULL);
618 if (editor_pid > 0) {
621 b = ka_wait(&e_ex_code);
622 } while ((b != editor_pid) && (b >= 0));
628 if (file_checksum(filename) == cksum) {
629 err_printf("*** No changes to save.\n");
633 if (e_ex_code == 0) { /* Save changes */
634 changefp = fopen(changefile, "w");
636 /* Load all netconfig entries that are *not* of the type we are editing */
637 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
639 while(listing && !IsEmptyStr(listing)) {
640 extract_token(buf, listing, 0, '\n', sizeof buf);
641 remove_token(listing, 0, '\n');
642 extract_token(instr, buf, 0, '|', sizeof instr);
643 if (strcasecmp(instr, entrytype)) {
644 fprintf(changefp, "%s\n", buf);
653 /* ...and merge that with the data we just edited */
654 tempfp = fopen(filename, "r");
655 while (fgets(buf, sizeof buf, tempfp) != NULL) {
656 for (i=0; i<strlen(buf); ++i) {
657 if (buf[i] == '#') buf[i] = 0;
660 if (!IsEmptyStr(buf)) {
661 fprintf(changefp, "%s|%s\n", entrytype, buf);
667 /* now write it to the server... */
668 changefp = fopen(changefile, "r");
669 if (changefp != NULL) {
670 listing = load_message_from_file(changefp);
672 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
680 unlink(filename); /* Delete the temporary files */
686 * IGnet node configuration
688 void do_ignet_configuration(CtdlIPC *ipc) {
697 char *listing = NULL;
700 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
701 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
702 extract_token(buf, listing, 0, '\n', sizeof buf);
703 remove_token(listing, 0, '\n');
706 if (num_recs == 1) recs = malloc(sizeof(char *));
707 else recs = realloc(recs, (sizeof(char *)) * num_recs);
708 recs[num_recs-1] = malloc(SIZ);
709 strcpy(recs[num_recs-1], buf);
711 if (listing) free(listing);
724 "------------------ "
725 "-------------------------------- "
727 for (i=0; i<num_recs; ++i) {
729 scr_printf("%3d ", i+1);
730 extract_token(buf, recs[i], 0, '|', sizeof buf);
732 scr_printf("%-16s ", buf);
733 extract_token(buf, recs[i], 1, '|', sizeof buf);
734 color(BRIGHT_MAGENTA);
735 scr_printf("%-18s ", buf);
736 extract_token(buf, recs[i], 2, '|', sizeof buf);
738 scr_printf("%-32s ", buf);
739 extract_token(buf, recs[i], 3, '|', sizeof buf);
740 color(BRIGHT_MAGENTA);
741 scr_printf("%-3s\n", buf);
746 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
751 recs = malloc(sizeof(char *));
752 else recs = realloc(recs,
753 (sizeof(char *)) * num_recs);
754 newprompt("Enter node name : ", buf, 16);
756 newprompt("Enter shared secret: ",
757 &buf[strlen(buf)], 18);
759 newprompt("Enter host or IP : ",
760 &buf[strlen(buf)], 32);
762 strprompt("Enter port number : ",
763 &buf[strlen(buf)-3], 5);
764 recs[num_recs-1] = strdup(buf);
768 i = intprompt("Delete which one",
772 for (j=i; j<num_recs; ++j)
778 for (i = 0; i < num_recs; ++i)
779 r += 1 + strlen(recs[i]);
780 listing = (char*) calloc(1, r);
782 err_printf("Can't save config - out of memory!\n");
785 if (num_recs) for (i = 0; i < num_recs; ++i) {
786 strcat(listing, recs[i]);
787 strcat(listing, "\n");
789 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
791 scr_printf("%s\n", buf);
793 scr_printf("Wrote %d records.\n", num_recs);
799 quitting = !modified || boolprompt(
800 "Quit without saving", 0);
808 for (i=0; i<num_recs; ++i) free(recs[i]);
815 * Filter list configuration
817 void do_filterlist_configuration(CtdlIPC *ipc)
827 char *listing = NULL;
830 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
831 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
832 extract_token(buf, listing, 0, '\n', sizeof buf);
833 remove_token(listing, 0, '\n');
836 if (num_recs == 1) recs = malloc(sizeof(char *));
837 else recs = realloc(recs, (sizeof(char *)) * num_recs);
838 recs[num_recs-1] = malloc(SIZ);
839 strcpy(recs[num_recs-1], buf);
841 if (listing) free(listing);
853 "---------------------------- "
854 "---------------------------- "
857 for (i=0; i<num_recs; ++i) {
859 scr_printf("%3d ", i+1);
860 extract_token(buf, recs[i], 0, '|', sizeof buf);
862 scr_printf("%-28s ", buf);
863 extract_token(buf, recs[i], 1, '|', sizeof buf);
864 color(BRIGHT_MAGENTA);
865 scr_printf("%-28s ", buf);
866 extract_token(buf, recs[i], 2, '|', sizeof buf);
868 scr_printf("%-16s\n", buf);
869 extract_token(buf, recs[i], 3, '|', sizeof buf);
873 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
878 recs = malloc(sizeof(char *));
879 else recs = realloc(recs,
880 (sizeof(char *)) * num_recs);
881 newprompt("Enter user name: ", buf, 28);
883 newprompt("Enter room name: ",
884 &buf[strlen(buf)], 28);
886 newprompt("Enter node name: ",
887 &buf[strlen(buf)], 16);
889 recs[num_recs-1] = strdup(buf);
893 i = intprompt("Delete which one",
897 for (j=i; j<num_recs; ++j)
903 for (i = 0; i < num_recs; ++i)
904 r += 1 + strlen(recs[i]);
905 listing = (char*) calloc(1, r);
907 err_printf("Can't save config - out of memory!\n");
910 if (num_recs) for (i = 0; i < num_recs; ++i) {
911 strcat(listing, recs[i]);
912 strcat(listing, "\n");
914 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
916 scr_printf("%s\n", buf);
918 scr_printf("Wrote %d records.\n", num_recs);
924 quitting = !modified || boolprompt(
925 "Quit without saving", 0);
933 for (i=0; i<num_recs; ++i) free(recs[i]);
942 * POP3 aggregation client configuration
944 void do_pop3client_configuration(CtdlIPC *ipc)
954 char *listing = NULL;
955 char *other_listing = NULL;
959 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
961 while(listing && !IsEmptyStr(listing)) {
962 extract_token(buf, listing, 0, '\n', sizeof buf);
963 remove_token(listing, 0, '\n');
964 extract_token(instr, buf, 0, '|', sizeof instr);
965 if (!strcasecmp(instr, "pop3client")) {
968 if (num_recs == 1) recs = malloc(sizeof(char *));
969 else recs = realloc(recs, (sizeof(char *)) * num_recs);
970 recs[num_recs-1] = malloc(SIZ);
971 strcpy(recs[num_recs-1], buf);
992 "---------------------------- "
993 "---------------------------- "
997 for (i=0; i<num_recs; ++i) {
999 scr_printf("%3d ", i+1);
1001 extract_token(buf, recs[i], 1, '|', sizeof buf);
1003 scr_printf("%-28s ", buf);
1005 extract_token(buf, recs[i], 2, '|', sizeof buf);
1006 color(BRIGHT_MAGENTA);
1007 scr_printf("%-28s ", buf);
1010 scr_printf("%-15s ", (extract_int(recs[i], 4) ? "Yes" : "No") );
1011 color(BRIGHT_MAGENTA);
1012 scr_printf("%ld\n", extract_long(recs[i], 5) );
1016 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1020 if (num_recs == 1) {
1021 recs = malloc(sizeof(char *));
1024 recs = realloc(recs, (sizeof(char *)) * num_recs);
1026 strcpy(buf, "pop3client|");
1027 newprompt("Enter host name: ", &buf[strlen(buf)], 28);
1029 newprompt("Enter user name: ", &buf[strlen(buf)], 28);
1031 newprompt("Enter password : ", &buf[strlen(buf)], 16);
1033 scr_printf("Keep messages on server instead of deleting them? ");
1034 sprintf(&buf[strlen(buf)], "%d", yesno());
1036 newprompt("Enter interval : ", &buf[strlen(buf)], 5);
1038 recs[num_recs-1] = strdup(buf);
1042 i = intprompt("Delete which one",
1043 1, 1, num_recs) - 1;
1046 for (j=i; j<num_recs; ++j)
1047 recs[j] = recs[j+1];
1052 for (i = 0; i < num_recs; ++i) {
1053 r += 1 + strlen(recs[i]);
1055 listing = (char*) calloc(1, r);
1057 err_printf("Can't save config - out of memory!\n");
1060 if (num_recs) for (i = 0; i < num_recs; ++i) {
1061 strcat(listing, recs[i]);
1062 strcat(listing, "\n");
1065 /* Retrieve all the *other* records for merging */
1066 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1068 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1069 extract_token(buf, other_listing, i, '\n', sizeof buf);
1070 if (strncasecmp(buf, "pop3client|", 11)) {
1071 listing = realloc(listing, strlen(listing) +
1073 strcat(listing, buf);
1074 strcat(listing, "\n");
1078 free(other_listing);
1079 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1084 scr_printf("%s\n", buf);
1086 scr_printf("Wrote %d records.\n", num_recs);
1092 quitting = !modified || boolprompt(
1093 "Quit without saving", 0);
1098 } while (!quitting);
1101 for (i=0; i<num_recs; ++i) free(recs[i]);
1112 * RSS feed retrieval client configuration
1114 void do_rssclient_configuration(CtdlIPC *ipc)
1124 char *listing = NULL;
1125 char *other_listing = NULL;
1129 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1131 while(listing && !IsEmptyStr(listing)) {
1132 extract_token(buf, listing, 0, '\n', sizeof buf);
1133 remove_token(listing, 0, '\n');
1134 extract_token(instr, buf, 0, '|', sizeof instr);
1135 if (!strcasecmp(instr, "rssclient")) {
1138 if (num_recs == 1) recs = malloc(sizeof(char *));
1139 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1140 recs[num_recs-1] = malloc(SIZ);
1141 strcpy(recs[num_recs-1], buf);
1153 color(BRIGHT_WHITE);
1154 scr_printf("### Feed URL\n");
1157 "---------------------------------------------------------------------------"
1160 for (i=0; i<num_recs; ++i) {
1162 scr_printf("%3d ", i+1);
1164 extract_token(buf, recs[i], 1, '|', sizeof buf);
1166 scr_printf("%-75s\n", buf);
1171 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1175 if (num_recs == 1) {
1176 recs = malloc(sizeof(char *));
1179 recs = realloc(recs, (sizeof(char *)) * num_recs);
1181 strcpy(buf, "rssclient|");
1182 newprompt("Enter feed URL: ", &buf[strlen(buf)], 75);
1184 recs[num_recs-1] = strdup(buf);
1188 i = intprompt("Delete which one", 1, 1, num_recs) - 1;
1191 for (j=i; j<num_recs; ++j)
1192 recs[j] = recs[j+1];
1197 for (i = 0; i < num_recs; ++i) {
1198 r += 1 + strlen(recs[i]);
1200 listing = (char*) calloc(1, r);
1202 err_printf("Can't save config - out of memory!\n");
1205 if (num_recs) for (i = 0; i < num_recs; ++i) {
1206 strcat(listing, recs[i]);
1207 strcat(listing, "\n");
1210 /* Retrieve all the *other* records for merging */
1211 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1213 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1214 extract_token(buf, other_listing, i, '\n', sizeof buf);
1215 if (strncasecmp(buf, "rssclient|", 10)) {
1216 listing = realloc(listing, strlen(listing) +
1218 strcat(listing, buf);
1219 strcat(listing, "\n");
1223 free(other_listing);
1224 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1229 scr_printf("%s\n", buf);
1231 scr_printf("Wrote %d records.\n", num_recs);
1237 quitting = !modified || boolprompt(
1238 "Quit without saving", 0);
1243 } while (!quitting);
1246 for (i=0; i<num_recs; ++i) free(recs[i]);