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 42
650 char sc[NUM_CONFIGS][SIZ];
652 struct ExpirePolicy *site_expirepolicy = NULL;
653 struct ExpirePolicy *mbx_expirepolicy = NULL;
656 int r; /* IPC response code */
658 /* Clear out the config buffers */
659 memset(&sc[0][0], 0, sizeof(sc));
661 /* Fetch the current config */
662 r = CtdlIPCGetSystemConfig(ipc, &resp, buf);
665 while (strlen(resp)) {
666 extract_token(buf, resp, 0, '\n', sizeof buf);
667 remove_token(resp, 0, '\n');
668 if (a < NUM_CONFIGS) {
669 strcpy(&sc[a][0], buf);
674 if (resp) free(resp);
676 /* Fetch the expire policy (this will silently fail on old servers,
677 * resulting in "default" policy)
679 r = CtdlIPCGetMessageExpirationPolicy(ipc, 2, &site_expirepolicy, buf);
680 r = CtdlIPCGetMessageExpirationPolicy(ipc, 3, &mbx_expirepolicy, buf);
682 /* Identification parameters */
684 strprompt("Node name", &sc[0][0], 15);
685 strprompt("Fully qualified domain name", &sc[1][0], 63);
686 strprompt("Human readable node name", &sc[2][0], 20);
687 strprompt("Modem dialup number", &sc[3][0], 15);
688 strprompt("Geographic location of this system", &sc[12][0], 31);
689 strprompt("Name of system administrator", &sc[13][0], 25);
690 strprompt("Paginator prompt", &sc[10][0], 79);
692 /* Security parameters */
694 snprintf(sc[7], sizeof sc[7], "%d", (boolprompt(
695 "Require registration for new users",
697 snprintf(sc[29], sizeof sc[29], "%d", (boolprompt(
698 "Disable self-service user account creation",
700 strprompt("Initial access level for new users", &sc[6][0], 1);
701 strprompt("Access level required to create rooms", &sc[19][0], 1);
702 snprintf(sc[4], sizeof sc[4], "%d", (boolprompt(
703 "Automatically give room aide privs to a user who creates a private room",
706 snprintf(sc[8], sizeof sc[8], "%d", (boolprompt(
707 "Automatically move problem user messages to twit room",
710 strprompt("Name of twit room", &sc[9][0], ROOMNAMELEN);
711 snprintf(sc[11], sizeof sc[11], "%d", (boolprompt(
712 "Restrict Internet mail to only those with that privilege",
714 snprintf(sc[26], sizeof sc[26], "%d", (boolprompt(
715 "Allow Aides to Zap (forget) rooms",
718 if (strlen(&sc[18][0]) > 0) logpages = 1;
720 logpages = boolprompt("Log all pages", logpages);
722 strprompt("Name of logging room", &sc[18][0], ROOMNAMELEN);
731 strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
732 strprompt("Maximum concurrent sessions", &sc[14][0], 4);
733 strprompt("Maximum message length", &sc[20][0], 20);
734 strprompt("Minimum number of worker threads", &sc[21][0], 3);
735 strprompt("Maximum number of worker threads", &sc[22][0], 3);
737 strprompt("Server IP address (0.0.0.0 for 'any')", &sc[37][0], 15);
738 strprompt("POP3 server port (-1 to disable)", &sc[23][0], 5);
739 strprompt("POP3S server port (-1 to disable)", &sc[40][0], 5);
740 strprompt("IMAP server port (-1 to disable)", &sc[27][0], 5);
741 strprompt("IMAPS server port (-1 to disable)", &sc[39][0], 5);
742 strprompt("SMTP MTA server port (-1 to disable)", &sc[24][0], 5);
743 strprompt("SMTP MSA server port (-1 to disable)", &sc[38][0], 5);
744 strprompt("SMTPS server port (-1 to disable)", &sc[41][0], 5);
746 /* This logic flips the question around, because it's one of those
747 * situations where 0=yes and 1=no
751 a = boolprompt("Correct forged From: lines during authenticated SMTP",
754 snprintf(sc[25], sizeof sc[25], "%d", a);
757 if (ipc->ServInfo.supports_ldap) {
758 a = strlen(&sc[32][0]);
759 a = (a ? 1 : 0); /* Set only to 1 or 0 */
760 a = boolprompt("Connect this Citadel to an LDAP directory", a);
762 strprompt("Host name of LDAP server",
764 strprompt("Port number of LDAP service",
766 strprompt("Base DN", &sc[34][0], 255);
767 strprompt("Bind DN", &sc[35][0], 255);
768 strprompt("Password for bind DN", &sc[36][0], 255);
771 strcpy(&sc[32][0], "");
775 /* Expiry settings */
776 strprompt("Default user purge time (days)", &sc[16][0], 5);
777 strprompt("Default room purge time (days)", &sc[17][0], 5);
779 /* Angels and demons dancing in my head... */
781 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_mode);
782 strprompt("System default message expire policy (? for list)",
786 "1. Never automatically expire messages\n"
787 "2. Expire by message count\n"
788 "3. Expire by message age\n");
790 } while ((buf[0] < '1') || (buf[0] > '3'));
791 site_expirepolicy->expire_mode = buf[0] - '0';
793 /* ...lunatics and monsters underneath my bed */
794 if (site_expirepolicy->expire_mode == 2) {
795 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
796 strprompt("Keep how many messages online?", buf, 10);
797 site_expirepolicy->expire_value = atol(buf);
799 if (site_expirepolicy->expire_mode == 3) {
800 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
801 strprompt("Keep messages for how many days?", buf, 10);
802 site_expirepolicy->expire_value = atol(buf);
805 /* Media messiahs preying on my fears... */
807 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_mode);
808 strprompt("Mailbox default message expire policy (? for list)",
812 "0. Go with the system default\n"
813 "1. Never automatically expire messages\n"
814 "2. Expire by message count\n"
815 "3. Expire by message age\n");
817 } while ((buf[0] < '0') || (buf[0] > '3'));
818 mbx_expirepolicy->expire_mode = buf[0] - '0';
820 /* ...Pop culture prophets playing in my ears */
821 if (mbx_expirepolicy->expire_mode == 2) {
822 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
823 strprompt("Keep how many messages online?", buf, 10);
824 mbx_expirepolicy->expire_value = atol(buf);
826 if (mbx_expirepolicy->expire_mode == 3) {
827 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
828 strprompt("Keep messages for how many days?", buf, 10);
829 mbx_expirepolicy->expire_value = atol(buf);
832 strprompt("How often to run network jobs (in seconds)", &sc[28][0], 5);
833 strprompt("Hour to run purges (0-23)", &sc[31][0], 2);
836 scr_printf("Save this configuration? ");
839 for (a = 0; a < NUM_CONFIGS; a++)
840 r += 1 + strlen(sc[a]);
841 resp = (char *)calloc(1, r);
843 err_printf("Can't save config - out of memory!\n");
846 for (a = 0; a < NUM_CONFIGS; a++) {
850 r = CtdlIPCSetSystemConfig(ipc, resp, buf);
852 err_printf("%s\n", buf);
856 r = CtdlIPCSetMessageExpirationPolicy(ipc, 2, site_expirepolicy, buf);
858 err_printf("%s\n", buf);
861 r = CtdlIPCSetMessageExpirationPolicy(ipc, 3, mbx_expirepolicy, buf);
863 err_printf("%s\n", buf);
871 * support function for do_internet_configuration()
873 void get_inet_rec_type(CtdlIPC *ipc, char *buf) {
876 keyopt(" <1> localhost (Alias for this computer)\n");
877 keyopt(" <2> gateway domain (Domain for all Citadel systems)\n");
878 keyopt(" <3> smart-host (Forward all outbound mail to this host)\n");
879 keyopt(" <4> directory (Consult the Global Address Book)\n");
880 keyopt(" <5> SpamAssassin (Address of SpamAssassin server)\n");
881 keyopt(" <6> RBL (domain suffix of spam hunting RBL)\n");
882 sel = intprompt("Which one", 1, 1, 6);
884 case 1: strcpy(buf, "localhost");
886 case 2: strcpy(buf, "gatewaydomain");
888 case 3: strcpy(buf, "smarthost");
890 case 4: strcpy(buf, "directory");
892 case 5: strcpy(buf, "spamassassin");
894 case 6: strcpy(buf, "rbl");
901 * Internet mail configuration
903 void do_internet_configuration(CtdlIPC *ipc)
916 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
918 while (strlen(resp)) {
919 extract_token(buf, resp, 0, '\n', sizeof buf);
920 remove_token(resp, 0, '\n');
922 if (num_recs == 1) recs = malloc(sizeof(char *));
923 else recs = realloc(recs, (sizeof(char *)) * num_recs);
924 recs[num_recs-1] = malloc(strlen(buf) + 1);
925 strcpy(recs[num_recs-1], buf);
928 if (resp) free(resp);
933 scr_printf("### Host or domain Record type \n");
935 scr_printf("--- -------------------------------------------------- --------------------\n");
936 for (i=0; i<num_recs; ++i) {
938 scr_printf("%3d ", i+1);
939 extract_token(buf, recs[i], 0, '|', sizeof buf);
941 scr_printf("%-50s ", buf);
942 extract_token(buf, recs[i], 1, '|', sizeof buf);
943 color(BRIGHT_MAGENTA);
944 scr_printf("%-20s\n", buf);
948 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
951 newprompt("Enter host name: ",
954 if (strlen(buf) > 0) {
957 recs = malloc(sizeof(char *));
958 else recs = realloc(recs,
959 (sizeof(char *)) * num_recs);
961 get_inet_rec_type(ipc,
963 recs[num_recs-1] = strdup(buf);
968 i = intprompt("Delete which one",
972 for (j=i; j<num_recs; ++j)
978 for (i = 0; i < num_recs; i++)
979 r += 1 + strlen(recs[i]);
980 resp = (char *)calloc(1, r);
982 err_printf("Can't save config - out of memory!\n");
985 if (num_recs) for (i = 0; i < num_recs; i++) {
986 strcat(resp, recs[i]);
989 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
991 err_printf("%s\n", buf);
993 scr_printf("Wrote %d records.\n", num_recs);
998 quitting = !modified || boolprompt(
999 "Quit without saving", 0);
1004 } while (!quitting);
1007 for (i=0; i<num_recs; ++i) free(recs[i]);
1015 * Edit network configuration for room sharing, mailing lists, etc.
1017 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
1019 char filename[PATH_MAX];
1020 char changefile[PATH_MAX];
1030 char *listing = NULL;
1033 if (strlen(editor_paths[0]) == 0) {
1034 scr_printf("You must have an external editor configured in"
1035 " order to use this function.\n");
1039 snprintf(filename, sizeof filename, "%s.listedit", tmpnam(NULL));
1040 snprintf(changefile, sizeof changefile, "%s.listedit", tmpnam(NULL));
1042 tempfp = fopen(filename, "w");
1043 if (tempfp == NULL) {
1044 err_printf("Cannot open %s: %s\n", filename, strerror(errno));
1048 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
1049 fprintf(tempfp, "# %s\n", comment);
1050 fprintf(tempfp, "# Specify one per line.\n"
1053 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1055 while(listing && strlen(listing)) {
1056 extract_token(buf, listing, 0, '\n', sizeof buf);
1057 remove_token(listing, 0, '\n');
1058 extract_token(instr, buf, 0, '|', sizeof instr);
1059 if (!strcasecmp(instr, entrytype)) {
1060 tokens = num_tokens(buf, '|');
1061 for (i=1; i<tokens; ++i) {
1062 extract_token(addr, buf, i, '|', sizeof addr);
1063 fprintf(tempfp, "%s", addr);
1064 if (i < (tokens-1)) {
1065 fprintf(tempfp, "|");
1068 fprintf(tempfp, "\n");
1078 e_ex_code = 1; /* start with a failed exit code */
1080 stty_ctdl(SB_RESTORE);
1081 editor_pid = fork();
1082 cksum = file_checksum(filename);
1083 if (editor_pid == 0) {
1084 chmod(filename, 0600);
1085 putenv("WINDOW_TITLE=Network configuration");
1086 execlp(editor_paths[0], editor_paths[0], filename, NULL);
1089 if (editor_pid > 0) {
1092 b = ka_wait(&e_ex_code);
1093 } while ((b != editor_pid) && (b >= 0));
1099 if (file_checksum(filename) == cksum) {
1100 err_printf("*** Not saving changes.\n");
1104 if (e_ex_code == 0) { /* Save changes */
1105 changefp = fopen(changefile, "w");
1106 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1108 while(listing && strlen(listing)) {
1109 extract_token(buf, listing, 0, '\n', sizeof buf);
1110 remove_token(listing, 0, '\n');
1111 extract_token(instr, buf, 0, '|', sizeof instr);
1112 if (strcasecmp(instr, entrytype)) {
1113 fprintf(changefp, "%s\n", buf);
1121 tempfp = fopen(filename, "r");
1122 while (fgets(buf, sizeof buf, tempfp) != NULL) {
1123 for (i=0; i<strlen(buf); ++i) {
1124 if (buf[i] == '#') buf[i] = 0;
1127 if (strlen(buf) > 0) {
1128 fprintf(changefp, "%s|%s\n", entrytype, buf);
1134 /* now write it to the server... */
1135 changefp = fopen(changefile, "r");
1136 if (changefp != NULL) {
1137 listing = load_message_from_file(changefp);
1139 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1147 unlink(filename); /* Delete the temporary files */
1153 * IGnet node configuration
1155 void do_ignet_configuration(CtdlIPC *ipc) {
1164 char *listing = NULL;
1167 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
1168 if (r / 100 == 1) while (*listing && strlen(listing)) {
1169 extract_token(buf, listing, 0, '\n', sizeof buf);
1170 remove_token(listing, 0, '\n');
1173 if (num_recs == 1) recs = malloc(sizeof(char *));
1174 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1175 recs[num_recs-1] = malloc(SIZ);
1176 strcpy(recs[num_recs-1], buf);
1178 if (listing) free(listing);
1182 color(BRIGHT_WHITE);
1191 "------------------ "
1192 "-------------------------------- "
1194 for (i=0; i<num_recs; ++i) {
1196 scr_printf("%3d ", i+1);
1197 extract_token(buf, recs[i], 0, '|', sizeof buf);
1199 scr_printf("%-16s ", buf);
1200 extract_token(buf, recs[i], 1, '|', sizeof buf);
1201 color(BRIGHT_MAGENTA);
1202 scr_printf("%-18s ", buf);
1203 extract_token(buf, recs[i], 2, '|', sizeof buf);
1205 scr_printf("%-32s ", buf);
1206 extract_token(buf, recs[i], 3, '|', sizeof buf);
1207 color(BRIGHT_MAGENTA);
1208 scr_printf("%-3s\n", buf);
1213 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1218 recs = malloc(sizeof(char *));
1219 else recs = realloc(recs,
1220 (sizeof(char *)) * num_recs);
1221 newprompt("Enter node name : ", buf, 16);
1223 newprompt("Enter shared secret: ",
1224 &buf[strlen(buf)], 18);
1226 newprompt("Enter host or IP : ",
1227 &buf[strlen(buf)], 32);
1228 strcat(buf, "|504");
1229 strprompt("Enter port number : ",
1230 &buf[strlen(buf)-3], 5);
1231 recs[num_recs-1] = strdup(buf);
1235 i = intprompt("Delete which one",
1236 1, 1, num_recs) - 1;
1239 for (j=i; j<num_recs; ++j)
1240 recs[j] = recs[j+1];
1245 for (i = 0; i < num_recs; ++i)
1246 r += 1 + strlen(recs[i]);
1247 listing = (char*) calloc(1, r);
1249 err_printf("Can't save config - out of memory!\n");
1252 if (num_recs) for (i = 0; i < num_recs; ++i) {
1253 strcat(listing, recs[i]);
1254 strcat(listing, "\n");
1256 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
1258 scr_printf("%s\n", buf);
1260 scr_printf("Wrote %d records.\n", num_recs);
1265 quitting = !modified || boolprompt(
1266 "Quit without saving", 0);
1271 } while (!quitting);
1274 for (i=0; i<num_recs; ++i) free(recs[i]);
1280 * Filter list configuration
1282 void do_filterlist_configuration(CtdlIPC *ipc)
1292 char *listing = NULL;
1295 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
1296 if (r / 100 == 1) while (*listing && strlen(listing)) {
1297 extract_token(buf, listing, 0, '\n', sizeof buf);
1298 remove_token(listing, 0, '\n');
1301 if (num_recs == 1) recs = malloc(sizeof(char *));
1302 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1303 recs[num_recs-1] = malloc(SIZ);
1304 strcpy(recs[num_recs-1], buf);
1306 if (listing) free(listing);
1310 color(BRIGHT_WHITE);
1318 "---------------------------- "
1319 "---------------------------- "
1322 for (i=0; i<num_recs; ++i) {
1324 scr_printf("%3d ", i+1);
1325 extract_token(buf, recs[i], 0, '|', sizeof buf);
1327 scr_printf("%-28s ", buf);
1328 extract_token(buf, recs[i], 1, '|', sizeof buf);
1329 color(BRIGHT_MAGENTA);
1330 scr_printf("%-28s ", buf);
1331 extract_token(buf, recs[i], 2, '|', sizeof buf);
1333 scr_printf("%-16s\n", buf);
1334 extract_token(buf, recs[i], 3, '|', sizeof buf);
1338 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1343 recs = malloc(sizeof(char *));
1344 else recs = realloc(recs,
1345 (sizeof(char *)) * num_recs);
1346 newprompt("Enter user name: ", buf, 28);
1348 newprompt("Enter room name: ",
1349 &buf[strlen(buf)], 28);
1351 newprompt("Enter node name: ",
1352 &buf[strlen(buf)], 16);
1354 recs[num_recs-1] = strdup(buf);
1358 i = intprompt("Delete which one",
1359 1, 1, num_recs) - 1;
1362 for (j=i; j<num_recs; ++j)
1363 recs[j] = recs[j+1];
1368 for (i = 0; i < num_recs; ++i)
1369 r += 1 + strlen(recs[i]);
1370 listing = (char*) calloc(1, r);
1372 err_printf("Can't save config - out of memory!\n");
1375 if (num_recs) for (i = 0; i < num_recs; ++i) {
1376 strcat(listing, recs[i]);
1377 strcat(listing, "\n");
1379 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
1381 scr_printf("%s\n", buf);
1383 scr_printf("Wrote %d records.\n", num_recs);
1388 quitting = !modified || boolprompt(
1389 "Quit without saving", 0);
1394 } while (!quitting);
1397 for (i=0; i<num_recs; ++i) free(recs[i]);