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[7];
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 && strlen(reg) > 0) {
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; a < strlen(flnm); ++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 (strlen(resp));
454 scr_printf("Current access level: %d (%s)\n", ax, axdefs[ax]);
456 scr_printf("%s\n%s\n", user, &cmd[4]);
458 if (resp) free(resp);
461 /* now set the access level */
463 sprintf(answer, "%d", ax);
464 strprompt("New access level (? for help, q to quit)",
466 if ((answer[0] >= '0') && (answer[0] <= '6')) {
468 r = CtdlIPCValidateUser(ipc, user, ax, cmd);
470 scr_printf("%s\n\n", cmd);
473 if (tolower(answer[0]) == 'q') {
474 scr_printf("*** Aborted.\n\n");
477 if (answer[0] == '?') {
478 scr_printf("Available access levels:\n");
479 for (a=0; a<7; ++a) {
480 scr_printf("%d - %s\n",
490 void validate(CtdlIPC *ipc)
491 { /* validate new users */
495 int r; /* IPC response code */
498 r = CtdlIPCNextUnvalidatedUser(ipc, cmd);
502 scr_printf("%s\n", cmd);
504 extract_token(buf, cmd, 0, '|', sizeof buf);
505 if (val_user(ipc, buf, 1) != 0) finished = 1;
507 } while (finished == 0);
515 stty_ctdl(SB_RESTORE);
518 signal(SIGINT, SIG_DFL);
519 signal(SIGQUIT, SIG_DFL);
520 execlp(getenv("SHELL"), getenv("SHELL"), NULL);
521 err_printf("Could not open a shell: %s\n", strerror(errno));
526 } while ((a != b) && (a != (-1)));
532 * <.A>ide <F>ile <D>elete command
534 void deletefile(CtdlIPC *ipc)
539 newprompt("Filename: ", filename, 31);
540 if (strlen(filename) == 0)
542 CtdlIPCDeleteFile(ipc, filename, buf);
543 err_printf("%s\n", buf);
547 * <.A>ide <F>ile <S>end command
549 void netsendfile(CtdlIPC *ipc)
551 char filename[32], destsys[20], buf[SIZ];
553 newprompt("Filename: ", filename, 31);
554 if (strlen(filename) == 0)
556 newprompt("System to send to: ", destsys, 19);
557 CtdlIPCNetSendFile(ipc, filename, destsys, buf);
558 err_printf("%s\n", buf);
563 * <.A>ide <F>ile <M>ove command
565 void movefile(CtdlIPC *ipc)
568 char newroom[ROOMNAMELEN];
571 newprompt("Filename: ", filename, 63);
572 if (strlen(filename) == 0)
574 newprompt("Enter target room: ", newroom, ROOMNAMELEN - 1);
575 CtdlIPCMoveFile(ipc, filename, newroom, buf);
576 err_printf("%s\n", buf);
581 * list of users who have filled out a bio
583 void list_bio(CtdlIPC *ipc)
588 int r; /* IPC response code */
590 r = CtdlIPCListUsersWithBios(ipc, &resp, buf);
592 pprintf("%s\n", buf);
595 while (strlen(resp)) {
596 extract_token(buf, resp, 0, '\n', sizeof buf);
597 remove_token(resp, 0, '\n');
598 if ((pos + strlen(buf) + 5) > screenwidth) {
602 pprintf("%s, ", buf);
603 pos = pos + strlen(buf) + 2;
605 pprintf("%c%c \n\n", 8, 8);
606 if (resp) free(resp);
613 void read_bio(CtdlIPC *ipc)
618 int r; /* IPC response code */
621 newprompt("Read bio for who ('?' for list) : ", who, 25);
623 if (!strcmp(who, "?"))
625 } while (!strcmp(who, "?"));
627 r = CtdlIPCGetBio(ipc, who, &resp, buf);
629 pprintf("%s\n", buf);
632 while (strlen(resp)) {
633 extract_token(buf, resp, 0, '\n', sizeof buf);
634 remove_token(resp, 0, '\n');
635 pprintf("%s\n", buf);
637 if (resp) free(resp);
642 * General system configuration command
644 void do_system_configuration(CtdlIPC *ipc)
647 #define NUM_CONFIGS 46
650 char sc[NUM_CONFIGS][256];
652 struct ExpirePolicy *site_expirepolicy = NULL;
653 struct ExpirePolicy *mbx_expirepolicy = NULL;
656 int r; /* IPC response code */
657 int server_configs = 0;
659 /* Clear out the config buffers */
660 memset(&sc[0][0], 0, sizeof(sc));
662 /* Fetch the current config */
663 r = CtdlIPCGetSystemConfig(ipc, &resp, buf);
665 server_configs = num_tokens(resp, '\n');
666 for (a=0; a<server_configs; ++a) {
667 if (a < NUM_CONFIGS) {
668 extract_token(&sc[a][0], resp, a, '\n', sizeof sc[a]);
672 if (resp) free(resp);
674 /* Fetch the expire policy (this will silently fail on old servers,
675 * resulting in "default" policy)
677 r = CtdlIPCGetMessageExpirationPolicy(ipc, 2, &site_expirepolicy, buf);
678 r = CtdlIPCGetMessageExpirationPolicy(ipc, 3, &mbx_expirepolicy, buf);
680 /* Identification parameters */
682 strprompt("Node name", &sc[0][0], 15);
683 strprompt("Fully qualified domain name", &sc[1][0], 63);
684 strprompt("Human readable node name", &sc[2][0], 20);
685 strprompt("Modem dialup number", &sc[3][0], 15);
686 strprompt("Geographic location of this system", &sc[12][0], 31);
687 strprompt("Name of system administrator", &sc[13][0], 25);
688 strprompt("Paginator prompt", &sc[10][0], 79);
690 /* Security parameters */
692 snprintf(sc[7], sizeof sc[7], "%d", (boolprompt(
693 "Require registration for new users",
695 snprintf(sc[29], sizeof sc[29], "%d", (boolprompt(
696 "Disable self-service user account creation",
698 strprompt("Initial access level for new users", &sc[6][0], 1);
699 strprompt("Access level required to create rooms", &sc[19][0], 1);
700 snprintf(sc[4], sizeof sc[4], "%d", (boolprompt(
701 "Automatically give room aide privs to a user who creates a private room",
704 snprintf(sc[8], sizeof sc[8], "%d", (boolprompt(
705 "Automatically move problem user messages to twit room",
708 strprompt("Name of twit room", &sc[9][0], ROOMNAMELEN);
709 snprintf(sc[11], sizeof sc[11], "%d", (boolprompt(
710 "Restrict Internet mail to only those with that privilege",
712 snprintf(sc[26], sizeof sc[26], "%d", (boolprompt(
713 "Allow Aides to Zap (forget) rooms",
716 if (strlen(&sc[18][0]) > 0) logpages = 1;
718 logpages = boolprompt("Log all pages", logpages);
720 strprompt("Name of logging room", &sc[18][0], ROOMNAMELEN);
729 strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
730 strprompt("Maximum concurrent sessions", &sc[14][0], 4);
731 strprompt("Maximum message length", &sc[20][0], 20);
732 strprompt("Minimum number of worker threads", &sc[21][0], 3);
733 strprompt("Maximum number of worker threads", &sc[22][0], 3);
734 snprintf(sc[43], sizeof sc[43], "%d", (boolprompt(
735 "Automatically delete committed database logs",
738 strprompt("Server IP address (0.0.0.0 for 'any')", &sc[37][0], 15);
739 strprompt("POP3 server port (-1 to disable)", &sc[23][0], 5);
740 strprompt("POP3S server port (-1 to disable)", &sc[40][0], 5);
741 strprompt("IMAP server port (-1 to disable)", &sc[27][0], 5);
742 strprompt("IMAPS server port (-1 to disable)", &sc[39][0], 5);
743 strprompt("SMTP MTA server port (-1 to disable)", &sc[24][0], 5);
744 strprompt("SMTP MSA server port (-1 to disable)", &sc[38][0], 5);
745 strprompt("SMTPS server port (-1 to disable)", &sc[41][0], 5);
747 /* This logic flips the question around, because it's one of those
748 * situations where 0=yes and 1=no
752 a = boolprompt("Correct forged From: lines during authenticated SMTP",
755 snprintf(sc[25], sizeof sc[25], "%d", a);
756 snprintf(sc[45], sizeof sc[45], "%d", (boolprompt(
757 "Allow unauthenticated SMTP clients to spoof my domains",
759 snprintf(sc[44], sizeof sc[44], "%d", (boolprompt(
760 "Instantly expunge deleted IMAP messages",
764 if (ipc->ServInfo.supports_ldap) {
765 a = strlen(&sc[32][0]);
766 a = (a ? 1 : 0); /* Set only to 1 or 0 */
767 a = boolprompt("Connect this Citadel to an LDAP directory", a);
769 strprompt("Host name of LDAP server",
771 strprompt("Port number of LDAP service",
773 strprompt("Base DN", &sc[34][0], 255);
774 strprompt("Bind DN", &sc[35][0], 255);
775 strprompt("Password for bind DN", &sc[36][0], 255);
778 strcpy(&sc[32][0], "");
782 /* Expiry settings */
783 strprompt("Default user purge time (days)", &sc[16][0], 5);
784 strprompt("Default room purge time (days)", &sc[17][0], 5);
786 /* Angels and demons dancing in my head... */
788 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_mode);
789 strprompt("System default message expire policy (? for list)",
793 "1. Never automatically expire messages\n"
794 "2. Expire by message count\n"
795 "3. Expire by message age\n");
797 } while ((buf[0] < '1') || (buf[0] > '3'));
798 site_expirepolicy->expire_mode = buf[0] - '0';
800 /* ...lunatics and monsters underneath my bed */
801 if (site_expirepolicy->expire_mode == 2) {
802 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
803 strprompt("Keep how many messages online?", buf, 10);
804 site_expirepolicy->expire_value = atol(buf);
806 if (site_expirepolicy->expire_mode == 3) {
807 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
808 strprompt("Keep messages for how many days?", buf, 10);
809 site_expirepolicy->expire_value = atol(buf);
812 /* Media messiahs preying on my fears... */
814 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_mode);
815 strprompt("Mailbox default message expire policy (? for list)",
819 "0. Go with the system default\n"
820 "1. Never automatically expire messages\n"
821 "2. Expire by message count\n"
822 "3. Expire by message age\n");
824 } while ((buf[0] < '0') || (buf[0] > '3'));
825 mbx_expirepolicy->expire_mode = buf[0] - '0';
827 /* ...Pop culture prophets playing in my ears */
828 if (mbx_expirepolicy->expire_mode == 2) {
829 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
830 strprompt("Keep how many messages online?", buf, 10);
831 mbx_expirepolicy->expire_value = atol(buf);
833 if (mbx_expirepolicy->expire_mode == 3) {
834 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
835 strprompt("Keep messages for how many days?", buf, 10);
836 mbx_expirepolicy->expire_value = atol(buf);
839 strprompt("How often to run network jobs (in seconds)", &sc[28][0], 5);
840 strprompt("Hour to run purges (0-23)", &sc[31][0], 2);
841 snprintf(sc[42], sizeof sc[42], "%d", (boolprompt(
842 "Enable full text search index (warning: resource intensive)",
846 scr_printf("Save this configuration? ");
849 for (a = 0; a < NUM_CONFIGS; a++)
850 r += 1 + strlen(sc[a]);
851 resp = (char *)calloc(1, r);
853 err_printf("Can't save config - out of memory!\n");
856 for (a = 0; a < NUM_CONFIGS; a++) {
860 r = CtdlIPCSetSystemConfig(ipc, resp, buf);
862 err_printf("%s\n", buf);
866 r = CtdlIPCSetMessageExpirationPolicy(ipc, 2, site_expirepolicy, buf);
868 err_printf("%s\n", buf);
871 r = CtdlIPCSetMessageExpirationPolicy(ipc, 3, mbx_expirepolicy, buf);
873 err_printf("%s\n", buf);
881 * support function for do_internet_configuration()
883 void get_inet_rec_type(CtdlIPC *ipc, char *buf) {
886 keyopt(" <1> localhost (Alias for this computer)\n");
887 keyopt(" <2> gateway domain (Domain for all Citadel systems)\n");
888 keyopt(" <3> smart-host (Forward all outbound mail to this host)\n");
889 keyopt(" <4> directory (Consult the Global Address Book)\n");
890 keyopt(" <5> SpamAssassin (Address of SpamAssassin server)\n");
891 keyopt(" <6> RBL (domain suffix of spam hunting RBL)\n");
892 sel = intprompt("Which one", 1, 1, 6);
894 case 1: strcpy(buf, "localhost");
896 case 2: strcpy(buf, "gatewaydomain");
898 case 3: strcpy(buf, "smarthost");
900 case 4: strcpy(buf, "directory");
902 case 5: strcpy(buf, "spamassassin");
904 case 6: strcpy(buf, "rbl");
911 * Internet mail configuration
913 void do_internet_configuration(CtdlIPC *ipc)
926 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
928 while (strlen(resp)) {
929 extract_token(buf, resp, 0, '\n', sizeof buf);
930 remove_token(resp, 0, '\n');
932 if (num_recs == 1) recs = malloc(sizeof(char *));
933 else recs = realloc(recs, (sizeof(char *)) * num_recs);
934 recs[num_recs-1] = malloc(strlen(buf) + 1);
935 strcpy(recs[num_recs-1], buf);
938 if (resp) free(resp);
943 scr_printf("### Host or domain Record type \n");
945 scr_printf("--- -------------------------------------------------- --------------------\n");
946 for (i=0; i<num_recs; ++i) {
948 scr_printf("%3d ", i+1);
949 extract_token(buf, recs[i], 0, '|', sizeof buf);
951 scr_printf("%-50s ", buf);
952 extract_token(buf, recs[i], 1, '|', sizeof buf);
953 color(BRIGHT_MAGENTA);
954 scr_printf("%-20s\n", buf);
958 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
961 newprompt("Enter host name: ",
964 if (strlen(buf) > 0) {
967 recs = malloc(sizeof(char *));
968 else recs = realloc(recs,
969 (sizeof(char *)) * num_recs);
971 get_inet_rec_type(ipc,
973 recs[num_recs-1] = strdup(buf);
978 i = intprompt("Delete which one",
982 for (j=i; j<num_recs; ++j)
988 for (i = 0; i < num_recs; i++)
989 r += 1 + strlen(recs[i]);
990 resp = (char *)calloc(1, r);
992 err_printf("Can't save config - out of memory!\n");
995 if (num_recs) for (i = 0; i < num_recs; i++) {
996 strcat(resp, recs[i]);
999 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
1001 err_printf("%s\n", buf);
1003 scr_printf("Wrote %d records.\n", num_recs);
1008 quitting = !modified || boolprompt(
1009 "Quit without saving", 0);
1014 } while (!quitting);
1017 for (i=0; i<num_recs; ++i) free(recs[i]);
1025 * Edit network configuration for room sharing, mailing lists, etc.
1027 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
1029 char filename[PATH_MAX];
1030 char changefile[PATH_MAX];
1040 char *listing = NULL;
1043 if (strlen(editor_paths[0]) == 0) {
1044 scr_printf("You must have an external editor configured in"
1045 " order to use this function.\n");
1049 snprintf(filename, sizeof filename, "%s.listedit", tmpnam(NULL));
1050 snprintf(changefile, sizeof changefile, "%s.listedit", tmpnam(NULL));
1052 tempfp = fopen(filename, "w");
1053 if (tempfp == NULL) {
1054 err_printf("Cannot open %s: %s\n", filename, strerror(errno));
1058 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
1059 fprintf(tempfp, "# %s\n", comment);
1060 fprintf(tempfp, "# Specify one per line.\n"
1063 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1065 while(listing && strlen(listing)) {
1066 extract_token(buf, listing, 0, '\n', sizeof buf);
1067 remove_token(listing, 0, '\n');
1068 extract_token(instr, buf, 0, '|', sizeof instr);
1069 if (!strcasecmp(instr, entrytype)) {
1070 tokens = num_tokens(buf, '|');
1071 for (i=1; i<tokens; ++i) {
1072 extract_token(addr, buf, i, '|', sizeof addr);
1073 fprintf(tempfp, "%s", addr);
1074 if (i < (tokens-1)) {
1075 fprintf(tempfp, "|");
1078 fprintf(tempfp, "\n");
1088 e_ex_code = 1; /* start with a failed exit code */
1090 stty_ctdl(SB_RESTORE);
1091 editor_pid = fork();
1092 cksum = file_checksum(filename);
1093 if (editor_pid == 0) {
1094 chmod(filename, 0600);
1095 putenv("WINDOW_TITLE=Network configuration");
1096 execlp(editor_paths[0], editor_paths[0], filename, NULL);
1099 if (editor_pid > 0) {
1102 b = ka_wait(&e_ex_code);
1103 } while ((b != editor_pid) && (b >= 0));
1109 if (file_checksum(filename) == cksum) {
1110 err_printf("*** Not saving changes.\n");
1114 if (e_ex_code == 0) { /* Save changes */
1115 changefp = fopen(changefile, "w");
1116 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1118 while(listing && strlen(listing)) {
1119 extract_token(buf, listing, 0, '\n', sizeof buf);
1120 remove_token(listing, 0, '\n');
1121 extract_token(instr, buf, 0, '|', sizeof instr);
1122 if (strcasecmp(instr, entrytype)) {
1123 fprintf(changefp, "%s\n", buf);
1131 tempfp = fopen(filename, "r");
1132 while (fgets(buf, sizeof buf, tempfp) != NULL) {
1133 for (i=0; i<strlen(buf); ++i) {
1134 if (buf[i] == '#') buf[i] = 0;
1137 if (strlen(buf) > 0) {
1138 fprintf(changefp, "%s|%s\n", entrytype, buf);
1144 /* now write it to the server... */
1145 changefp = fopen(changefile, "r");
1146 if (changefp != NULL) {
1147 listing = load_message_from_file(changefp);
1149 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1157 unlink(filename); /* Delete the temporary files */
1163 * IGnet node configuration
1165 void do_ignet_configuration(CtdlIPC *ipc) {
1174 char *listing = NULL;
1177 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
1178 if (r / 100 == 1) while (*listing && strlen(listing)) {
1179 extract_token(buf, listing, 0, '\n', sizeof buf);
1180 remove_token(listing, 0, '\n');
1183 if (num_recs == 1) recs = malloc(sizeof(char *));
1184 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1185 recs[num_recs-1] = malloc(SIZ);
1186 strcpy(recs[num_recs-1], buf);
1188 if (listing) free(listing);
1192 color(BRIGHT_WHITE);
1201 "------------------ "
1202 "-------------------------------- "
1204 for (i=0; i<num_recs; ++i) {
1206 scr_printf("%3d ", i+1);
1207 extract_token(buf, recs[i], 0, '|', sizeof buf);
1209 scr_printf("%-16s ", buf);
1210 extract_token(buf, recs[i], 1, '|', sizeof buf);
1211 color(BRIGHT_MAGENTA);
1212 scr_printf("%-18s ", buf);
1213 extract_token(buf, recs[i], 2, '|', sizeof buf);
1215 scr_printf("%-32s ", buf);
1216 extract_token(buf, recs[i], 3, '|', sizeof buf);
1217 color(BRIGHT_MAGENTA);
1218 scr_printf("%-3s\n", buf);
1223 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1228 recs = malloc(sizeof(char *));
1229 else recs = realloc(recs,
1230 (sizeof(char *)) * num_recs);
1231 newprompt("Enter node name : ", buf, 16);
1233 newprompt("Enter shared secret: ",
1234 &buf[strlen(buf)], 18);
1236 newprompt("Enter host or IP : ",
1237 &buf[strlen(buf)], 32);
1238 strcat(buf, "|504");
1239 strprompt("Enter port number : ",
1240 &buf[strlen(buf)-3], 5);
1241 recs[num_recs-1] = strdup(buf);
1245 i = intprompt("Delete which one",
1246 1, 1, num_recs) - 1;
1249 for (j=i; j<num_recs; ++j)
1250 recs[j] = recs[j+1];
1255 for (i = 0; i < num_recs; ++i)
1256 r += 1 + strlen(recs[i]);
1257 listing = (char*) calloc(1, r);
1259 err_printf("Can't save config - out of memory!\n");
1262 if (num_recs) for (i = 0; i < num_recs; ++i) {
1263 strcat(listing, recs[i]);
1264 strcat(listing, "\n");
1266 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
1268 scr_printf("%s\n", buf);
1270 scr_printf("Wrote %d records.\n", num_recs);
1275 quitting = !modified || boolprompt(
1276 "Quit without saving", 0);
1281 } while (!quitting);
1284 for (i=0; i<num_recs; ++i) free(recs[i]);
1290 * Filter list configuration
1292 void do_filterlist_configuration(CtdlIPC *ipc)
1302 char *listing = NULL;
1305 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
1306 if (r / 100 == 1) while (*listing && strlen(listing)) {
1307 extract_token(buf, listing, 0, '\n', sizeof buf);
1308 remove_token(listing, 0, '\n');
1311 if (num_recs == 1) recs = malloc(sizeof(char *));
1312 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1313 recs[num_recs-1] = malloc(SIZ);
1314 strcpy(recs[num_recs-1], buf);
1316 if (listing) free(listing);
1320 color(BRIGHT_WHITE);
1328 "---------------------------- "
1329 "---------------------------- "
1332 for (i=0; i<num_recs; ++i) {
1334 scr_printf("%3d ", i+1);
1335 extract_token(buf, recs[i], 0, '|', sizeof buf);
1337 scr_printf("%-28s ", buf);
1338 extract_token(buf, recs[i], 1, '|', sizeof buf);
1339 color(BRIGHT_MAGENTA);
1340 scr_printf("%-28s ", buf);
1341 extract_token(buf, recs[i], 2, '|', sizeof buf);
1343 scr_printf("%-16s\n", buf);
1344 extract_token(buf, recs[i], 3, '|', sizeof buf);
1348 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1353 recs = malloc(sizeof(char *));
1354 else recs = realloc(recs,
1355 (sizeof(char *)) * num_recs);
1356 newprompt("Enter user name: ", buf, 28);
1358 newprompt("Enter room name: ",
1359 &buf[strlen(buf)], 28);
1361 newprompt("Enter node name: ",
1362 &buf[strlen(buf)], 16);
1364 recs[num_recs-1] = strdup(buf);
1368 i = intprompt("Delete which one",
1369 1, 1, num_recs) - 1;
1372 for (j=i; j<num_recs; ++j)
1373 recs[j] = recs[j+1];
1378 for (i = 0; i < num_recs; ++i)
1379 r += 1 + strlen(recs[i]);
1380 listing = (char*) calloc(1, r);
1382 err_printf("Can't save config - out of memory!\n");
1385 if (num_recs) for (i = 0; i < num_recs; ++i) {
1386 strcat(listing, recs[i]);
1387 strcat(listing, "\n");
1389 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
1391 scr_printf("%s\n", buf);
1393 scr_printf("Wrote %d records.\n", num_recs);
1398 quitting = !modified || boolprompt(
1399 "Quit without saving", 0);
1404 } while (!quitting);
1407 for (i=0; i<num_recs; ++i) free(recs[i]);