3 * More client-side support functions.
4 * Unlike routines.c, some of these DO use global variables.
10 #include <sys/types.h>
18 #if TIME_WITH_SYS_TIME
19 # include <sys/time.h>
23 # include <sys/time.h>
35 #include "citadel_ipc.h"
36 #include "citadel_decls.h"
37 #include "routines2.h"
47 /* work around solaris include files */
53 extern char tempdir[];
54 extern char *axdefs[8];
55 extern long highest_msg_read;
56 extern long maxmsgnum;
57 extern unsigned room_flags;
58 extern int screenwidth;
62 int eopen(char *name, int mode)
65 ret = open(name, mode);
67 err_printf("Cannot open file '%s', mode=%d, errno=%d\n",
76 int room_prompt(unsigned int qrflags)
77 { /* return proper room prompt character */
80 if (qrflags & QR_DIRECTORY)
82 if ((a == ']') && (qrflags & QR_NETWORK))
84 if ((a == '>') && (qrflags & QR_NETWORK))
89 void entregis(CtdlIPC *ipc)
90 { /* register with name and address */
106 int r; /* IPC response code */
111 strcpy(tmpstate, "");
113 strcpy(tmpphone, "");
114 strcpy(tmpemail, "");
115 strcpy(tmpcountry, "");
117 r = CtdlIPCGetUserRegistration(ipc, NULL, ®, buf);
121 while (reg && !IsEmptyStr(reg)) {
123 extract_token(buf, reg, 0, '\n', sizeof buf);
124 remove_token(reg, 0, '\n');
127 safestrncpy(tmpname, buf, sizeof tmpname);
129 safestrncpy(tmpaddr, buf, sizeof tmpaddr);
131 safestrncpy(tmpcity, buf, sizeof tmpcity);
133 safestrncpy(tmpstate, buf, sizeof tmpstate);
135 safestrncpy(tmpzip, buf, sizeof tmpzip);
137 safestrncpy(tmpphone, buf, sizeof tmpphone);
139 safestrncpy(tmpemail, buf, sizeof tmpemail);
141 safestrncpy(tmpcountry, buf, sizeof tmpcountry);
145 strprompt("REAL name", tmpname, 29);
146 strprompt("Address", tmpaddr, 24);
147 strprompt("City/town", tmpcity, 14);
148 strprompt("State/province", tmpstate, 2);
149 strprompt("ZIP/Postal Code", tmpzip, 10);
150 strprompt("Country", tmpcountry, 31);
151 strprompt("Telephone number", tmpphone, 14);
155 safestrncpy(holdemail, tmpemail, sizeof holdemail);
156 strprompt("Email address", tmpemail, 31);
157 r = CtdlIPCDirectoryLookup(ipc, tmpemail, buf);
159 extract_token(diruser, buf, 0, '@', sizeof diruser);
160 extract_token(dirnode, buf, 1, '@', sizeof dirnode);
163 if ((strcasecmp(diruser, fullname))
164 || (strcasecmp(dirnode, ipc->ServInfo.nodename))) {
166 "\nYou can't use %s as your address.\n",
169 "It is already in use by %s @ %s.\n",
172 safestrncpy(tmpemail, holdemail, sizeof tmpemail);
177 /* now send the registration info back to the server */
178 reg = (char *)realloc(reg, SIZ);
180 sprintf(reg, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
181 tmpname, tmpaddr, tmpcity, tmpstate,
182 tmpzip, tmpphone, tmpemail, tmpcountry);
183 r = CtdlIPCSetRegistration(ipc, reg, buf);
185 scr_printf("%s\n", buf);
191 void updatels(CtdlIPC *ipc)
192 { /* make all messages old in current room */
194 int r; /* IPC response code */
196 if (rc_alt_semantics) {
197 if (maxmsgnum == 0 && highest_msg_read == 0) {
200 r = CtdlIPCSetLastRead(ipc, (maxmsgnum > highest_msg_read) ?
201 maxmsgnum : highest_msg_read, buf);
203 r = CtdlIPCSetLastRead(ipc, (maxmsgnum > highest_msg_read) ?
204 maxmsgnum : highest_msg_read, buf);
205 /* r = CtdlIPCSetLastRead(ipc, maxmsgnum, buf); */
206 /* This is a quick-and-dirty fix to all msgs becoming new in Mail>.
207 * It will need to be rethought when messages.c is rewritten.
211 scr_printf("%s\n", buf);
215 * only make messages old in this room that have been read
217 void updatelsa(CtdlIPC *ipc)
220 int r; /* IPC response code */
222 r = CtdlIPCSetLastRead(ipc, highest_msg_read, buf);
224 scr_printf("%s\n", &buf[4]);
229 * client-based uploads (for users with their own clientware)
231 void cli_upload(CtdlIPC *ipc)
237 int r; /* IPC response code */
241 if ((room_flags & QR_UPLOAD) == 0) {
242 scr_printf("*** You cannot upload to this room.\n");
245 newprompt("File to be uploaded: ", flnm, 55);
246 fd = open(flnm, O_RDONLY);
248 scr_printf("Cannot open '%s': %s\n", flnm, strerror(errno));
251 scr_printf("Enter a description of this file:\n");
252 newprompt(": ", desc, 75);
254 /* Keep generating filenames in hope of finding a unique one */
257 /* basename of filename */
259 if (haschar(tbuf, '/'))
260 extract_token(tbuf, flnm,
261 num_tokens(tbuf, '/') - 1,
264 /* filename.1, filename.2, etc */
266 sprintf(&tbuf[strlen(tbuf)], ".%d", a);
269 r = CtdlIPCFileUpload(ipc, tbuf, desc, flnm, progress, buf);
270 if (r / 100 == 5 || r < 0)
271 scr_printf("%s\n", buf);
276 if (a > 0) scr_printf("Saved as '%s'\n", tbuf);
281 * Function used for various image upload commands
283 void cli_image_upload(CtdlIPC *ipc, char *keyname)
289 /* Can we upload this image? */
290 r = CtdlIPCImageUpload(ipc, 0, NULL, keyname, NULL, buf);
292 err_printf("%s\n", buf);
295 newprompt("Image file to be uploaded: ", flnm, 55);
296 r = CtdlIPCImageUpload(ipc, 1, flnm, keyname, progress, buf);
298 err_printf("%s\n", buf);
300 err_printf("Cannot upload '%s': %s\n", flnm, strerror(errno));
302 /* else upload succeeded */
307 * protocol-based uploads (Xmodem, Ymodem, Zmodem)
309 void upload(CtdlIPC *ipc, int c)
310 { /* c = upload mode */
320 if ((room_flags & QR_UPLOAD) == 0) {
321 scr_printf("*** You cannot upload to this room.\n");
324 /* we don't need a filename when receiving batch y/z modem */
325 if ((c == 2) || (c == 3))
328 newprompt("Enter filename: ", flnm, 15);
330 for (a = 0; !IsEmptyStr(&flnm[a]); ++a)
331 if ((flnm[a] == '/') || (flnm[a] == '\\') || (flnm[a] == '>')
332 || (flnm[a] == '?') || (flnm[a] == '*')
333 || (flnm[a] == ';') || (flnm[a] == '&'))
336 /* create a temporary directory... */
337 if (mkdir(tempdir, 0700) != 0) {
338 scr_printf("*** Could not create temporary directory %s: %s\n",
339 tempdir, strerror(errno));
342 /* now do the transfer ... in a separate process */
349 scr_printf("Receiving %s - press Ctrl-D to end.\n", flnm);
350 fp = fopen(flnm, "w");
366 execlp("rx", "rx", flnm, NULL);
371 execlp("rb", "rb", NULL);
376 execlp("rz", "rz", NULL);
382 } while ((b != xfer_pid) && (b != (-1)));
387 scr_printf("\r*** Transfer unsuccessful.\n");
391 scr_printf("\r*** Transfer successful.\n");
392 snprintf(buf, sizeof buf, "cd %s; ls", tempdir);
393 lsfp = popen(buf, "r");
395 while (fgets(flnm, sizeof flnm, lsfp) != NULL) {
396 flnm[strlen(flnm) - 1] = 0; /* chop newline */
397 snprintf(buf, sizeof buf,
398 "Enter a short description of '%s':\n: ",
400 newprompt(buf, desc, 150);
401 snprintf(buf, sizeof buf, "%s/%s", tempdir, flnm);
402 r = CtdlIPCFileUpload(ipc, flnm, desc, buf, progress, tbuf);
403 scr_printf("%s\n", tbuf);
411 * validate a user (returns 0 for successful validation, nonzero if quitting)
413 int val_user(CtdlIPC *ipc, char *user, int do_validate)
421 int r; /* IPC response code */
424 r = CtdlIPCGetUserRegistration(ipc, user, &resp, cmd);
428 extract_token(buf, resp, 0, '\n', sizeof buf);
429 remove_token(resp, 0, '\n');
432 scr_printf("User #%s - %s ", buf, cmd);
434 scr_printf("PW: %s\n", buf);
436 scr_printf("%s\n", buf);
438 scr_printf("%s\n", buf);
440 scr_printf("%s, ", buf);
442 scr_printf("%s ", buf);
444 scr_printf("%s\n", buf);
446 scr_printf("%s\n", buf);
450 scr_printf("%s\n", buf);
452 scr_printf("%s\n", buf);
453 } while (!IsEmptyStr(resp));
455 /* TODODRW: discrepancy here. Parts of the code refer to axdefs[7] as the highest
456 * but most of it limits it to axdefs[6].
457 * Webcit limits to 6 as does the code here but there are 7 in axdefs.h
459 scr_printf("Current access level: %d (%s)\n", ax, axdefs[ax]);
461 scr_printf("%s\n%s\n", user, &cmd[4]);
463 if (resp) free(resp);
466 /* now set the access level */
468 sprintf(answer, "%d", ax);
469 strprompt("New access level (? for help, q to quit)",
471 if ((answer[0] >= '0') && (answer[0] <= '6')) {
473 r = CtdlIPCValidateUser(ipc, user, ax, cmd);
475 scr_printf("%s\n\n", cmd);
478 if (tolower(answer[0]) == 'q') {
479 scr_printf("*** Aborted.\n\n");
482 if (answer[0] == '?') {
483 scr_printf("Available access levels:\n");
484 for (a=0; a<7; ++a) {
485 scr_printf("%d - %s\n",
495 void validate(CtdlIPC *ipc)
496 { /* validate new users */
500 int r; /* IPC response code */
503 r = CtdlIPCNextUnvalidatedUser(ipc, cmd);
507 scr_printf("%s\n", cmd);
509 extract_token(buf, cmd, 0, '|', sizeof buf);
510 if (val_user(ipc, buf, 1) != 0) finished = 1;
512 } while (finished == 0);
520 stty_ctdl(SB_RESTORE);
523 signal(SIGINT, SIG_DFL);
524 signal(SIGQUIT, SIG_DFL);
525 execlp(getenv("SHELL"), getenv("SHELL"), NULL);
526 err_printf("Could not open a shell: %s\n", strerror(errno));
531 } while ((a != b) && (a != (-1)));
537 * <.A>ide <F>ile <D>elete command
539 void deletefile(CtdlIPC *ipc)
544 newprompt("Filename: ", filename, 31);
545 if (IsEmptyStr(filename))
547 CtdlIPCDeleteFile(ipc, filename, buf);
548 err_printf("%s\n", buf);
552 * <.A>ide <F>ile <S>end command
554 void netsendfile(CtdlIPC *ipc)
556 char filename[32], destsys[20], buf[256];
558 newprompt("Filename: ", filename, 31);
559 if (IsEmptyStr(filename))
561 newprompt("System to send to: ", destsys, 19);
562 CtdlIPCNetSendFile(ipc, filename, destsys, buf);
563 err_printf("%s\n", buf);
568 * <.A>ide <F>ile <M>ove command
570 void movefile(CtdlIPC *ipc)
573 char newroom[ROOMNAMELEN];
576 newprompt("Filename: ", filename, 63);
577 if (IsEmptyStr(filename))
579 newprompt("Enter target room: ", newroom, ROOMNAMELEN - 1);
580 CtdlIPCMoveFile(ipc, filename, newroom, buf);
581 err_printf("%s\n", buf);
586 * list of users who have filled out a bio
588 void list_bio(CtdlIPC *ipc)
593 int r; /* IPC response code */
595 r = CtdlIPCListUsersWithBios(ipc, &resp, buf);
597 pprintf("%s\n", buf);
600 while (resp && !IsEmptyStr(resp)) {
601 extract_token(buf, resp, 0, '\n', sizeof buf);
602 remove_token(resp, 0, '\n');
603 if ((pos + strlen(buf) + 5) > screenwidth) {
607 pprintf("%s, ", buf);
608 pos = pos + strlen(buf) + 2;
610 pprintf("%c%c \n\n", 8, 8);
611 if (resp) free(resp);
618 void read_bio(CtdlIPC *ipc)
623 int r; /* IPC response code */
626 newprompt("Read bio for who ('?' for list) : ", who, 25);
628 if (!strcmp(who, "?"))
630 } while (!strcmp(who, "?"));
632 r = CtdlIPCGetBio(ipc, who, &resp, buf);
634 pprintf("%s\n", buf);
637 while (!IsEmptyStr(resp)) {
638 extract_token(buf, resp, 0, '\n', sizeof buf);
639 remove_token(resp, 0, '\n');
640 pprintf("%s\n", buf);
642 if (resp) free(resp);
647 * General system configuration command
649 void do_system_configuration(CtdlIPC *ipc)
652 #define NUM_CONFIGS 60
655 char sc[NUM_CONFIGS][256];
657 struct ExpirePolicy *site_expirepolicy = NULL;
658 struct ExpirePolicy *mbx_expirepolicy = NULL;
661 int r; /* IPC response code */
662 int server_configs = 0;
664 /* Clear out the config buffers */
665 memset(&sc[0][0], 0, sizeof(sc));
667 /* Fetch the current config */
668 r = CtdlIPCGetSystemConfig(ipc, &resp, buf);
670 server_configs = num_tokens(resp, '\n');
671 for (a=0; a<server_configs; ++a) {
672 if (a < NUM_CONFIGS) {
673 extract_token(&sc[a][0], resp, a, '\n', sizeof sc[a]);
677 if (resp) free(resp);
679 /* Fetch the expire policy (this will silently fail on old servers,
680 * resulting in "default" policy)
682 r = CtdlIPCGetMessageExpirationPolicy(ipc, 2, &site_expirepolicy, buf);
683 r = CtdlIPCGetMessageExpirationPolicy(ipc, 3, &mbx_expirepolicy, buf);
685 /* Identification parameters */
687 strprompt("Node name", &sc[0][0], 15);
688 strprompt("Fully qualified domain name", &sc[1][0], 63);
689 strprompt("Human readable node name", &sc[2][0], 20);
690 strprompt("Telephone number", &sc[3][0], 15);
691 strprompt("Geographic location of this system", &sc[12][0], 31);
692 strprompt("Name of system administrator", &sc[13][0], 25);
693 strprompt("Paginator prompt", &sc[10][0], 79);
695 /* Security parameters */
697 snprintf(sc[7], sizeof sc[7], "%d", (boolprompt(
698 "Require registration for new users",
700 snprintf(sc[29], sizeof sc[29], "%d", (boolprompt(
701 "Disable self-service user account creation",
703 strprompt("Initial access level for new users", &sc[6][0], 1);
704 strprompt("Access level required to create rooms", &sc[19][0], 1);
705 snprintf(sc[4], sizeof sc[4], "%d", (boolprompt(
706 "Automatically give room aide privs to a user who creates a private room",
709 snprintf(sc[8], sizeof sc[8], "%d", (boolprompt(
710 "Automatically move problem user messages to twit room",
713 strprompt("Name of twit room", &sc[9][0], ROOMNAMELEN);
714 snprintf(sc[11], sizeof sc[11], "%d", (boolprompt(
715 "Restrict Internet mail to only those with that privilege",
717 snprintf(sc[26], sizeof sc[26], "%d", (boolprompt(
718 "Allow Aides to Zap (forget) rooms",
721 if (!IsEmptyStr(&sc[18][0])) logpages = 1;
723 logpages = boolprompt("Log all pages", logpages);
725 strprompt("Name of logging room", &sc[18][0], ROOMNAMELEN);
731 /* Commented out because this setting isn't really appropriate to
732 * change while the server is running.
734 * snprintf(sc[52], sizeof sc[52], "%d", (boolprompt(
735 * "Use system authentication",
736 * atoi(&sc[52][0]))));
741 strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
742 strprompt("Maximum concurrent sessions", &sc[14][0], 4);
743 strprompt("Maximum message length", &sc[20][0], 20);
744 strprompt("Minimum number of worker threads", &sc[21][0], 3);
745 strprompt("Maximum number of worker threads", &sc[22][0], 3);
746 snprintf(sc[43], sizeof sc[43], "%d", (boolprompt(
747 "Automatically delete committed database logs",
750 strprompt("Server IP address (0.0.0.0 for 'any')", &sc[37][0], 15);
751 strprompt("POP3 server port (-1 to disable)", &sc[23][0], 5);
752 strprompt("POP3S server port (-1 to disable)", &sc[40][0], 5);
753 strprompt("IMAP server port (-1 to disable)", &sc[27][0], 5);
754 strprompt("IMAPS server port (-1 to disable)", &sc[39][0], 5);
755 strprompt("SMTP MTA server port (-1 to disable)", &sc[24][0], 5);
756 strprompt("SMTP MSA server port (-1 to disable)", &sc[38][0], 5);
757 strprompt("SMTPS server port (-1 to disable)", &sc[41][0], 5);
758 strprompt("Postfix TCP Dictionary Port server port (-1 to disable)", &sc[50][0], 5);
759 strprompt("ManageSieve server port (-1 to disable)", &sc[51][0], 5);
760 /* This logic flips the question around, because it's one of those
761 * situations where 0=yes and 1=no
765 a = boolprompt("Correct forged From: lines during authenticated SMTP",
768 snprintf(sc[25], sizeof sc[25], "%d", a);
769 snprintf(sc[45], sizeof sc[45], "%d", (boolprompt(
770 "Allow unauthenticated SMTP clients to spoof my domains",
772 snprintf(sc[57], sizeof sc[57], "%d", (boolprompt(
773 "Perform RBL checks at greeting instead of after RCPT",
775 snprintf(sc[44], sizeof sc[44], "%d", (boolprompt(
776 "Instantly expunge deleted IMAP messages",
780 if (ipc->ServInfo.supports_ldap) {
781 a = strlen(&sc[32][0]);
782 a = (a ? 1 : 0); /* Set only to 1 or 0 */
783 a = boolprompt("Connect this Citadel to an external LDAP directory", a);
785 strprompt("Host name of LDAP server",
787 strprompt("Port number of LDAP service",
789 strprompt("Base DN", &sc[34][0], 255);
790 strprompt("Bind DN", &sc[35][0], 255);
791 strprompt("Password for bind DN", &sc[36][0], 255);
794 strcpy(&sc[32][0], "");
798 /* Expiry settings */
799 strprompt("Default user purge time (days)", &sc[16][0], 5);
800 strprompt("Default room purge time (days)", &sc[17][0], 5);
802 /* Angels and demons dancing in my head... */
804 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_mode);
805 strprompt("System default message expire policy (? for list)",
809 "1. Never automatically expire messages\n"
810 "2. Expire by message count\n"
811 "3. Expire by message age\n");
813 } while ((buf[0] < '1') || (buf[0] > '3'));
814 site_expirepolicy->expire_mode = buf[0] - '0';
816 /* ...lunatics and monsters underneath my bed */
817 if (site_expirepolicy->expire_mode == 2) {
818 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
819 strprompt("Keep how many messages online?", buf, 10);
820 site_expirepolicy->expire_value = atol(buf);
822 if (site_expirepolicy->expire_mode == 3) {
823 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
824 strprompt("Keep messages for how many days?", buf, 10);
825 site_expirepolicy->expire_value = atol(buf);
828 /* Media messiahs preying on my fears... */
830 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_mode);
831 strprompt("Mailbox default message expire policy (? for list)",
835 "0. Go with the system default\n"
836 "1. Never automatically expire messages\n"
837 "2. Expire by message count\n"
838 "3. Expire by message age\n");
840 } while ((buf[0] < '0') || (buf[0] > '3'));
841 mbx_expirepolicy->expire_mode = buf[0] - '0';
843 /* ...Pop culture prophets playing in my ears */
844 if (mbx_expirepolicy->expire_mode == 2) {
845 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
846 strprompt("Keep how many messages online?", buf, 10);
847 mbx_expirepolicy->expire_value = atol(buf);
849 if (mbx_expirepolicy->expire_mode == 3) {
850 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
851 strprompt("Keep messages for how many days?", buf, 10);
852 mbx_expirepolicy->expire_value = atol(buf);
855 strprompt("How often to run network jobs (in seconds)", &sc[28][0], 5);
856 strprompt("Hour to run purges (0-23)", &sc[31][0], 2);
857 snprintf(sc[42], sizeof sc[42], "%d", (boolprompt(
858 "Enable full text search index (warning: resource intensive)",
861 snprintf(sc[46], sizeof sc[46], "%d", (boolprompt(
862 "Perform journaling of email messages",
864 snprintf(sc[47], sizeof sc[47], "%d", (boolprompt(
865 "Perform journaling of non-email messages",
867 if ( (atoi(&sc[46][0])) || (atoi(&sc[47][0])) ) {
868 strprompt("Email destination of journalized messages",
872 /* Funambol push stuff */
873 int yes_funambol = 0;
874 if (strlen(sc[53]) > 0) yes_funambol = 1;
875 yes_funambol = boolprompt("Connect to an external Funambol sync server", yes_funambol);
877 strprompt("Funambol server (blank to disable)", &sc[53][0], 63);
878 strprompt("Funambol server port", &sc[54][0], 5);
879 strprompt("Funambol sync source", &sc[55][0], 63);
880 strprompt("Funambol authentication details (user:pass in Base64)", &sc[56][0],63);
889 /* Master user account */
891 if (strlen(sc[58]) > 0) yes_muacct = 1;
892 yes_muacct = boolprompt("Enable a 'master user' account", yes_muacct);
894 strprompt("Master user name", &sc[58][0], 31);
895 strprompt("Master user password", &sc[59][0], -31);
898 strcpy(&sc[58][0], "");
899 strcpy(&sc[59][0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
903 scr_printf("Save this configuration? ");
906 for (a = 0; a < NUM_CONFIGS; a++)
907 r += 1 + strlen(sc[a]);
908 resp = (char *)calloc(1, r);
910 err_printf("Can't save config - out of memory!\n");
913 for (a = 0; a < NUM_CONFIGS; a++) {
917 r = CtdlIPCSetSystemConfig(ipc, resp, buf);
919 err_printf("%s\n", buf);
923 r = CtdlIPCSetMessageExpirationPolicy(ipc, 2, site_expirepolicy, buf);
925 err_printf("%s\n", buf);
928 r = CtdlIPCSetMessageExpirationPolicy(ipc, 3, mbx_expirepolicy, buf);
930 err_printf("%s\n", buf);
934 if (site_expirepolicy) free(site_expirepolicy);
935 if (mbx_expirepolicy) free(mbx_expirepolicy);
940 * support function for do_internet_configuration()
942 void get_inet_rec_type(CtdlIPC *ipc, char *buf) {
945 keyopt(" <1> localhost (Alias for this computer)\n");
946 keyopt(" <2> gateway domain (Domain for all Citadel systems)\n");
947 keyopt(" <3> smart-host (Forward all outbound mail to this host)\n");
948 keyopt(" <4> directory (Consult the Global Address Book)\n");
949 keyopt(" <5> SpamAssassin (Address of SpamAssassin server)\n");
950 keyopt(" <6> RBL (domain suffix of spam hunting RBL)\n");
951 keyopt(" <7> masq domains (Domains as which users are allowed to masquerade)\n");
952 sel = intprompt("Which one", 1, 1, 6);
954 case 1: strcpy(buf, "localhost");
956 case 2: strcpy(buf, "gatewaydomain");
958 case 3: strcpy(buf, "smarthost");
960 case 4: strcpy(buf, "directory");
962 case 5: strcpy(buf, "spamassassin");
964 case 6: strcpy(buf, "rbl");
966 case 7: strcpy(buf, "masqdomain");
973 * Internet mail configuration
975 void do_internet_configuration(CtdlIPC *ipc)
988 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
990 while (!IsEmptyStr(resp)) {
991 extract_token(buf, resp, 0, '\n', sizeof buf);
992 remove_token(resp, 0, '\n');
994 if (num_recs == 1) recs = malloc(sizeof(char *));
995 else recs = realloc(recs, (sizeof(char *)) * num_recs);
996 recs[num_recs-1] = malloc(strlen(buf) + 1);
997 strcpy(recs[num_recs-1], buf);
1000 if (resp) free(resp);
1004 color(BRIGHT_WHITE);
1005 scr_printf("### Host or domain Record type \n");
1007 scr_printf("--- -------------------------------------------------- --------------------\n");
1008 for (i=0; i<num_recs; ++i) {
1010 scr_printf("%3d ", i+1);
1011 extract_token(buf, recs[i], 0, '|', sizeof buf);
1013 scr_printf("%-50s ", buf);
1014 extract_token(buf, recs[i], 1, '|', sizeof buf);
1015 color(BRIGHT_MAGENTA);
1016 scr_printf("%-20s\n", buf);
1020 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1023 newprompt("Enter host name: ",
1026 if (!IsEmptyStr(buf)) {
1029 recs = malloc(sizeof(char *));
1030 else recs = realloc(recs,
1031 (sizeof(char *)) * num_recs);
1033 get_inet_rec_type(ipc,
1035 recs[num_recs-1] = strdup(buf);
1040 i = intprompt("Delete which one",
1041 1, 1, num_recs) - 1;
1044 for (j=i; j<num_recs; ++j)
1045 recs[j] = recs[j+1];
1050 for (i = 0; i < num_recs; i++)
1051 r += 1 + strlen(recs[i]);
1052 resp = (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(resp, recs[i]);
1061 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
1063 err_printf("%s\n", buf);
1065 scr_printf("Wrote %d records.\n", num_recs);
1071 quitting = !modified || boolprompt(
1072 "Quit without saving", 0);
1077 } while (!quitting);
1080 for (i=0; i<num_recs; ++i) free(recs[i]);
1088 * Edit network configuration for room sharing, mailing lists, etc.
1090 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
1092 char filename[PATH_MAX];
1093 char changefile[PATH_MAX];
1103 char *listing = NULL;
1106 if (IsEmptyStr(editor_paths[0])) {
1107 scr_printf("You must have an external editor configured in"
1108 " order to use this function.\n");
1112 CtdlMakeTempFileName(filename, sizeof filename);
1113 CtdlMakeTempFileName(changefile, sizeof changefile);
1115 tempfp = fopen(filename, "w");
1116 if (tempfp == NULL) {
1117 err_printf("Cannot open %s: %s\n", filename, strerror(errno));
1121 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
1122 fprintf(tempfp, "# %s\n", comment);
1123 fprintf(tempfp, "# Specify one per line.\n"
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, entrytype)) {
1133 tokens = num_tokens(buf, '|');
1134 for (i=1; i<tokens; ++i) {
1135 extract_token(addr, buf, i, '|', sizeof addr);
1136 fprintf(tempfp, "%s", addr);
1137 if (i < (tokens-1)) {
1138 fprintf(tempfp, "|");
1141 fprintf(tempfp, "\n");
1151 e_ex_code = 1; /* start with a failed exit code */
1153 stty_ctdl(SB_RESTORE);
1154 editor_pid = fork();
1155 cksum = file_checksum(filename);
1156 if (editor_pid == 0) {
1157 chmod(filename, 0600);
1158 putenv("WINDOW_TITLE=Network configuration");
1159 execlp(editor_paths[0], editor_paths[0], filename, NULL);
1162 if (editor_pid > 0) {
1165 b = ka_wait(&e_ex_code);
1166 } while ((b != editor_pid) && (b >= 0));
1172 if (file_checksum(filename) == cksum) {
1173 err_printf("*** No changes to save.\n");
1177 if (e_ex_code == 0) { /* Save changes */
1178 changefp = fopen(changefile, "w");
1180 /* Load all netconfig entries that are *not* of the type we are editing */
1181 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1183 while(listing && !IsEmptyStr(listing)) {
1184 extract_token(buf, listing, 0, '\n', sizeof buf);
1185 remove_token(listing, 0, '\n');
1186 extract_token(instr, buf, 0, '|', sizeof instr);
1187 if (strcasecmp(instr, entrytype)) {
1188 fprintf(changefp, "%s\n", buf);
1197 /* ...and merge that with the data we just edited */
1198 tempfp = fopen(filename, "r");
1199 while (fgets(buf, sizeof buf, tempfp) != NULL) {
1200 for (i=0; i<strlen(buf); ++i) {
1201 if (buf[i] == '#') buf[i] = 0;
1204 if (!IsEmptyStr(buf)) {
1205 fprintf(changefp, "%s|%s\n", entrytype, buf);
1211 /* now write it to the server... */
1212 changefp = fopen(changefile, "r");
1213 if (changefp != NULL) {
1214 listing = load_message_from_file(changefp);
1216 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1224 unlink(filename); /* Delete the temporary files */
1230 * IGnet node configuration
1232 void do_ignet_configuration(CtdlIPC *ipc) {
1241 char *listing = NULL;
1244 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
1245 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
1246 extract_token(buf, listing, 0, '\n', sizeof buf);
1247 remove_token(listing, 0, '\n');
1250 if (num_recs == 1) recs = malloc(sizeof(char *));
1251 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1252 recs[num_recs-1] = malloc(SIZ);
1253 strcpy(recs[num_recs-1], buf);
1255 if (listing) free(listing);
1259 color(BRIGHT_WHITE);
1268 "------------------ "
1269 "-------------------------------- "
1271 for (i=0; i<num_recs; ++i) {
1273 scr_printf("%3d ", i+1);
1274 extract_token(buf, recs[i], 0, '|', sizeof buf);
1276 scr_printf("%-16s ", buf);
1277 extract_token(buf, recs[i], 1, '|', sizeof buf);
1278 color(BRIGHT_MAGENTA);
1279 scr_printf("%-18s ", buf);
1280 extract_token(buf, recs[i], 2, '|', sizeof buf);
1282 scr_printf("%-32s ", buf);
1283 extract_token(buf, recs[i], 3, '|', sizeof buf);
1284 color(BRIGHT_MAGENTA);
1285 scr_printf("%-3s\n", buf);
1290 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1295 recs = malloc(sizeof(char *));
1296 else recs = realloc(recs,
1297 (sizeof(char *)) * num_recs);
1298 newprompt("Enter node name : ", buf, 16);
1300 newprompt("Enter shared secret: ",
1301 &buf[strlen(buf)], 18);
1303 newprompt("Enter host or IP : ",
1304 &buf[strlen(buf)], 32);
1305 strcat(buf, "|504");
1306 strprompt("Enter port number : ",
1307 &buf[strlen(buf)-3], 5);
1308 recs[num_recs-1] = strdup(buf);
1312 i = intprompt("Delete which one",
1313 1, 1, num_recs) - 1;
1316 for (j=i; j<num_recs; ++j)
1317 recs[j] = recs[j+1];
1322 for (i = 0; i < num_recs; ++i)
1323 r += 1 + strlen(recs[i]);
1324 listing = (char*) calloc(1, r);
1326 err_printf("Can't save config - out of memory!\n");
1329 if (num_recs) for (i = 0; i < num_recs; ++i) {
1330 strcat(listing, recs[i]);
1331 strcat(listing, "\n");
1333 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
1335 scr_printf("%s\n", buf);
1337 scr_printf("Wrote %d records.\n", num_recs);
1343 quitting = !modified || boolprompt(
1344 "Quit without saving", 0);
1349 } while (!quitting);
1352 for (i=0; i<num_recs; ++i) free(recs[i]);
1358 * Filter list configuration
1360 void do_filterlist_configuration(CtdlIPC *ipc)
1370 char *listing = NULL;
1373 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
1374 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
1375 extract_token(buf, listing, 0, '\n', sizeof buf);
1376 remove_token(listing, 0, '\n');
1379 if (num_recs == 1) recs = malloc(sizeof(char *));
1380 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1381 recs[num_recs-1] = malloc(SIZ);
1382 strcpy(recs[num_recs-1], buf);
1384 if (listing) free(listing);
1388 color(BRIGHT_WHITE);
1396 "---------------------------- "
1397 "---------------------------- "
1400 for (i=0; i<num_recs; ++i) {
1402 scr_printf("%3d ", i+1);
1403 extract_token(buf, recs[i], 0, '|', sizeof buf);
1405 scr_printf("%-28s ", buf);
1406 extract_token(buf, recs[i], 1, '|', sizeof buf);
1407 color(BRIGHT_MAGENTA);
1408 scr_printf("%-28s ", buf);
1409 extract_token(buf, recs[i], 2, '|', sizeof buf);
1411 scr_printf("%-16s\n", buf);
1412 extract_token(buf, recs[i], 3, '|', sizeof buf);
1416 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1421 recs = malloc(sizeof(char *));
1422 else recs = realloc(recs,
1423 (sizeof(char *)) * num_recs);
1424 newprompt("Enter user name: ", buf, 28);
1426 newprompt("Enter room name: ",
1427 &buf[strlen(buf)], 28);
1429 newprompt("Enter node name: ",
1430 &buf[strlen(buf)], 16);
1432 recs[num_recs-1] = strdup(buf);
1436 i = intprompt("Delete which one",
1437 1, 1, num_recs) - 1;
1440 for (j=i; j<num_recs; ++j)
1441 recs[j] = recs[j+1];
1446 for (i = 0; i < num_recs; ++i)
1447 r += 1 + strlen(recs[i]);
1448 listing = (char*) calloc(1, r);
1450 err_printf("Can't save config - out of memory!\n");
1453 if (num_recs) for (i = 0; i < num_recs; ++i) {
1454 strcat(listing, recs[i]);
1455 strcat(listing, "\n");
1457 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
1459 scr_printf("%s\n", buf);
1461 scr_printf("Wrote %d records.\n", num_recs);
1467 quitting = !modified || boolprompt(
1468 "Quit without saving", 0);
1473 } while (!quitting);
1476 for (i=0; i<num_recs; ++i) free(recs[i]);