96e77cdebdf87135035d2707cd2790a698ab2be0
[citadel.git] / citadel / routines2.c
1 /* $Id$
2  *
3  * More client-side support functions.
4  * Unlike routines.c, some of these DO use global variables.
5  *
6  */
7
8 #include "sysdep.h"
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <stdio.h>
15 #include <ctype.h>
16 #include <string.h>
17 #include <time.h>
18 #include <signal.h>
19 #include <pwd.h>
20 #include <setjmp.h>
21 #include <errno.h>
22 #include <stdarg.h>
23 #include "citadel.h"
24 #include "routines2.h"
25 #include "routines.h"
26 #include "commands.h"
27 #include "tools.h"
28 #include "messages.h"
29 #ifndef HAVE_SNPRINTF
30 #include "snprintf.h"
31 #endif
32
33 void interr(int errnum);
34 void strprompt(char *prompt, char *str, int len);
35 void newprompt(char *prompt, char *str, int len);
36 void sttybbs(int cmd);
37 int inkey(void);
38 void serv_write(char *buf, int nbytes);
39 int haschar(char *st, int ch);
40 void progress(long int curr, long int cmax);
41 int yesno(void);
42
43 extern char temp[];
44 extern char tempdir[];
45 extern char *axdefs[7];
46 extern long highest_msg_read;
47 extern long maxmsgnum;
48 extern unsigned room_flags;
49 extern int screenwidth;
50
51
52 int eopen(char *name, int mode)
53 {
54         int ret;
55         ret = open(name, mode);
56         if (ret < 0) {
57                 fprintf(stderr, "Cannot open file '%s', mode=%d, errno=%d\n",
58                         name, mode, errno);
59                 interr(errno);
60         }
61         return (ret);
62 }
63
64
65 int room_prompt(int qrflags)
66 {                               /* return proper room prompt character */
67         int a;
68         a = '>';
69         if (qrflags & QR_DIRECTORY)
70                 a = ']';
71         if ((a == ']') && (qrflags & QR_NETWORK))
72                 a = '}';
73         if ((a == '>') && (qrflags & QR_NETWORK))
74                 a = ')';
75         return (a);
76 }
77
78 void entregis(void)
79 {                               /* register with name and address */
80
81         char buf[SIZ];
82         char tmpname[SIZ];
83         char tmpaddr[SIZ];
84         char tmpcity[SIZ];
85         char tmpstate[SIZ];
86         char tmpzip[SIZ];
87         char tmpphone[SIZ];
88         char tmpemail[SIZ];
89         char tmpcountry[SIZ];
90         int a;
91
92         strcpy(tmpname, "");
93         strcpy(tmpaddr, "");
94         strcpy(tmpcity, "");
95         strcpy(tmpstate, "");
96         strcpy(tmpzip, "");
97         strcpy(tmpphone, "");
98         strcpy(tmpemail, "");
99         strcpy(tmpcountry, "");
100
101         serv_puts("GREG _SELF_");
102         serv_gets(buf);
103         if (buf[0] == '1') {
104                 a = 0;
105                 while (serv_gets(buf), strcmp(buf, "000")) {
106                         if (a == 2)
107                                 strcpy(tmpname, buf);
108                         if (a == 3)
109                                 strcpy(tmpaddr, buf);
110                         if (a == 4)
111                                 strcpy(tmpcity, buf);
112                         if (a == 5)
113                                 strcpy(tmpstate, buf);
114                         if (a == 6)
115                                 strcpy(tmpzip, buf);
116                         if (a == 7)
117                                 strcpy(tmpphone, buf);
118                         if (a == 9)
119                                 strcpy(tmpemail, buf);
120                         if (a == 10)
121                                 strcpy(tmpcountry, buf);
122                         ++a;
123                 }
124         }
125         strprompt("REAL name", tmpname, 29);
126         strprompt("Address", tmpaddr, 24);
127         strprompt("City/town", tmpcity, 14);
128         strprompt("State/province", tmpstate, 2);
129         strprompt("ZIP/Postal Code", tmpzip, 10);
130         strprompt("Country", tmpcountry, 31);
131         strprompt("Telephone number", tmpphone, 14);
132         strprompt("Email address", tmpemail, 31);
133
134         /* now send the registration info back to the server */
135         serv_puts("REGI");
136         serv_gets(buf);
137         if (buf[0] != '4') {
138                 printf("%s\n", &buf[4]);
139                 return;
140         }
141         serv_puts(tmpname);
142         serv_puts(tmpaddr);
143         serv_puts(tmpcity);
144         serv_puts(tmpstate);
145         serv_puts(tmpzip);
146         serv_puts(tmpphone);
147         serv_puts(tmpemail);
148         serv_puts(tmpcountry);
149         serv_puts("000");
150         printf("\n");
151 }
152
153 void updatels(void)
154 {                               /* make all messages old in current room */
155         char buf[SIZ];
156         serv_puts("SLRP HIGHEST");
157         serv_gets(buf);
158         if (buf[0] != '2')
159                 printf("%s\n", &buf[4]);
160 }
161
162 /*
163  * only make messages old in this room that have been read
164  */
165 void updatelsa(void)
166 {
167         char buf[SIZ];
168         sprintf(buf, "SLRP %ld", highest_msg_read);
169         serv_puts(buf);
170         serv_gets(buf);
171         if (buf[0] != '2')
172                 printf("%s\n", &buf[4]);
173 }
174
175
176 /*
177  * This routine completes a client upload
178  */
179 void do_upload(int fd)
180 {
181         char buf[SIZ];
182         char tbuf[4096];
183         long transmitted_bytes, total_bytes;
184         int bytes_to_send;
185         int bytes_expected;
186
187         /* learn the size of the file */
188         total_bytes = lseek(fd, 0L, 2);
189         lseek(fd, 0L, 0);
190
191         transmitted_bytes = 0L;
192         progress(transmitted_bytes, total_bytes);
193         do {
194                 bytes_to_send = read(fd, tbuf, 4096);
195                 if (bytes_to_send > 0) {
196                         sprintf(buf, "WRIT %d", bytes_to_send);
197                         serv_puts(buf);
198                         serv_gets(buf);
199                         if (buf[0] == '7') {
200                                 bytes_expected = atoi(&buf[4]);
201                                 serv_write(tbuf, bytes_expected);
202                         } else {
203                                 printf("%s\n", &buf[4]);
204                         }
205                 }
206                 transmitted_bytes = transmitted_bytes + (long) bytes_to_send;
207                 progress(transmitted_bytes, total_bytes);
208         } while (bytes_to_send > 0);
209
210         /* close the upload file, locally and at the server */
211         close(fd);
212         serv_puts("UCLS 1");
213         serv_gets(buf);
214         printf("%s\n", &buf[4]);
215 }
216
217
218 /*
219  * client-based uploads (for users with their own clientware)
220  */
221 void cli_upload(void)
222 {
223         char flnm[SIZ];
224         char desc[151];
225         char buf[SIZ];
226         char tbuf[SIZ];
227         int a;
228         int fd;
229
230         if ((room_flags & QR_UPLOAD) == 0) {
231                 printf("*** You cannot upload to this room.\n");
232                 return;
233         }
234         newprompt("File to be uploaded: ", flnm, 55);
235         fd = open(flnm, O_RDONLY);
236         if (fd < 0) {
237                 printf("Cannot open '%s': %s\n", flnm, strerror(errno));
238                 return;
239         }
240         printf("Enter a description of this file:\n");
241         newprompt(": ", desc, 75);
242
243         /* keep generating filenames in hope of finding a unique one */
244         a = 0;
245         do {
246                 if (a == 10)
247                         return; /* fail if tried 10 times */
248                 strcpy(buf, flnm);
249                 while ((strlen(buf) > 0) && (haschar(buf, '/')))
250                         strcpy(buf, &buf[1]);
251                 if (a > 0)
252                         sprintf(&buf[strlen(buf)], "%d", a);
253                 sprintf(tbuf, "UOPN %s|%s", buf, desc);
254                 serv_puts(tbuf);
255                 serv_gets(buf);
256                 if (buf[0] != '2')
257                         printf("%s\n", &buf[4]);
258                 ++a;
259         } while (buf[0] != '2');
260
261         /* at this point we have an open upload file at the server */
262         do_upload(fd);
263 }
264
265
266 /*
267  * Function used for various image upload commands
268  */
269 void cli_image_upload(char *keyname)
270 {
271         char flnm[SIZ];
272         char buf[SIZ];
273         int fd;
274
275         sprintf(buf, "UIMG 0|%s", keyname);
276         serv_puts(buf);
277         serv_gets(buf);
278         if (buf[0] != '2') {
279                 printf("%s\n", &buf[4]);
280                 return;
281         }
282         newprompt("Image file to be uploaded: ", flnm, 55);
283         fd = open(flnm, O_RDONLY);
284         if (fd < 0) {
285                 printf("Cannot open '%s': %s\n", flnm, strerror(errno));
286                 return;
287         }
288         sprintf(buf, "UIMG 1|%s", keyname);
289         serv_puts(buf);
290         serv_gets(buf);
291         if (buf[0] != '2') {
292                 printf("%s\n", &buf[4]);
293                 return;
294         }
295         do_upload(fd);
296 }
297
298
299 /*
300  * protocol-based uploads (Xmodem, Ymodem, Zmodem)
301  */
302 void upload(int c)
303 {                               /* c = upload mode */
304         char flnm[SIZ];
305         char desc[151];
306         char buf[SIZ];
307         char tbuf[4096];
308         int xfer_pid;
309         int a, b;
310         FILE *fp, *lsfp;
311         int fd;
312
313         if ((room_flags & QR_UPLOAD) == 0) {
314                 printf("*** You cannot upload to this room.\n");
315                 return;
316         }
317         /* we don't need a filename when receiving batch y/z modem */
318         if ((c == 2) || (c == 3))
319                 strcpy(flnm, "x");
320         else
321                 newprompt("Enter filename: ", flnm, 15);
322
323         for (a = 0; a < strlen(flnm); ++a)
324                 if ((flnm[a] == '/') || (flnm[a] == '\\') || (flnm[a] == '>')
325                     || (flnm[a] == '?') || (flnm[a] == '*')
326                     || (flnm[a] == ';') || (flnm[a] == '&'))
327                         flnm[a] = '_';
328
329         newprompt("Enter a short description of the file:\n: ", desc, 150);
330
331         /* create a temporary directory... */
332         if (mkdir(tempdir, 0700) != 0) {
333                 printf("*** Could not create temporary directory %s: %s\n",
334                        tempdir, strerror(errno));
335                 return;
336         }
337         /* now do the transfer ... in a separate process */
338         xfer_pid = fork();
339         if (xfer_pid == 0) {
340                 chdir(tempdir);
341                 switch (c) {
342                 case 0:
343                         sttybbs(0);
344                         printf("Receiving %s - press Ctrl-D to end.\n", flnm);
345                         fp = fopen(flnm, "w");
346                         do {
347                                 b = inkey();
348                                 if (b == 13) {
349                                         b = 10;
350                                         printf("\r");
351                                 }
352                                 if (b != 4) {
353                                         printf("%c", b);
354                                         putc(b, fp);
355                                 }
356                         } while (b != 4);
357                         fclose(fp);
358                         exit(0);
359                 case 1:
360                         sttybbs(3);
361                         execlp("rx", "rx", flnm, NULL);
362                         exit(1);
363                 case 2:
364                         sttybbs(3);
365                         execlp("rb", "rb", NULL);
366                         exit(1);
367                 case 3:
368                         sttybbs(3);
369                         execlp("rz", "rz", NULL);
370                         exit(1);
371                 }
372         } else
373                 do {
374                         b = ka_wait(&a);
375                 } while ((b != xfer_pid) && (b != (-1)));
376         sttybbs(0);
377
378         if (a != 0) {
379                 printf("\r*** Transfer unsuccessful.\n");
380                 nukedir(tempdir);
381                 return;
382         }
383         printf("\r*** Transfer successful.  Sending file(s) to server...\n");
384         sprintf(buf, "cd %s; ls", tempdir);
385         lsfp = popen(buf, "r");
386         if (lsfp != NULL) {
387                 while (fgets(flnm, sizeof flnm, lsfp) != NULL) {
388                         flnm[strlen(flnm) - 1] = 0;
389                         sprintf(buf, "%s/%s", tempdir, flnm);
390                         fd = open(buf, O_RDONLY);
391                         if (fd >= 0) {
392                                 a = 0;
393                                 do {
394                                         sprintf(buf, "UOPN %s|%s", flnm, desc);
395                                         if (a > 0)
396                                                 sprintf(&buf[strlen(buf)],
397                                                         ".%d", a);
398                                         ++a;
399                                         serv_puts(buf);
400                                         serv_gets(buf);
401                                 } while ((buf[0] != '2') && (a < 100));
402                                 if (buf[0] == '2')
403                                         do {
404                                                 a = read(fd, tbuf, 4096);
405                                                 if (a > 0) {
406                                                         sprintf(buf, "WRIT %d", a);
407                                                         serv_puts(buf);
408                                                         serv_gets(buf);
409                                                         if (buf[0] == '7')
410                                                                 serv_write(tbuf, a);
411                                                 }
412                                         } while (a > 0);
413                                 close(fd);
414                                 serv_puts("UCLS 1");
415                                 serv_gets(buf);
416                                 printf("%s\n", &buf[4]);
417                         }
418                 }
419                 pclose(lsfp);
420         }
421         nukedir(tempdir);
422 }
423
424 /* 
425  * validate a user
426  */
427 void val_user(char *user, int do_validate)
428 {
429         int a;
430         char cmd[SIZ];
431         char buf[SIZ];
432         int ax = 0;
433
434         sprintf(cmd, "GREG %s", user);
435         serv_puts(cmd);
436         serv_gets(cmd);
437         if (cmd[0] == '1') {
438                 a = 0;
439                 do {
440                         serv_gets(buf);
441                         ++a;
442                         if (a == 1)
443                                 printf("User #%s - %s  ", buf, &cmd[4]);
444                         if (a == 2)
445                                 printf("PW: %s\n", buf);
446                         if (a == 3)
447                                 printf("%s\n", buf);
448                         if (a == 4)
449                                 printf("%s\n", buf);
450                         if (a == 5)
451                                 printf("%s, ", buf);
452                         if (a == 6)
453                                 printf("%s ", buf);
454                         if (a == 7)
455                                 printf("%s\n", buf);
456                         if (a == 8)
457                                 printf("%s\n", buf);
458                         if (a == 9)
459                                 ax = atoi(buf);
460                         if (a == 10)
461                                 printf("%s\n", buf);
462                         if (a == 11)
463                                 printf("%s\n", buf);
464                 } while (strcmp(buf, "000"));
465                 printf("Current access level: %d (%s)\n", ax, axdefs[ax]);
466         } else {
467                 printf("%-30s\n%s\n", user, &cmd[4]);
468         }
469
470         if (do_validate) {
471                 /* now set the access level */
472                 ax = intprompt("Access level", ax, 0, 6);
473                 sprintf(cmd, "VALI %s|%d", user, ax);
474                 serv_puts(cmd);
475                 serv_gets(cmd);
476                 if (cmd[0] != '2')
477                         printf("%s\n", &cmd[4]);
478         }
479         printf("\n");
480 }
481
482
483 void validate(void)
484 {                               /* validate new users */
485         char cmd[SIZ];
486         char buf[SIZ];
487         int finished = 0;
488
489         do {
490                 serv_puts("GNUR");
491                 serv_gets(cmd);
492                 if (cmd[0] != '3')
493                         finished = 1;
494                 if (cmd[0] == '2')
495                         printf("%s\n", &cmd[4]);
496                 if (cmd[0] == '3') {
497                         extract(buf, cmd, 0);
498                         val_user(&buf[4], 1);
499                 }
500         } while (finished == 0);
501 }
502
503 void subshell(void)
504 {
505         int a, b;
506         a = fork();
507         if (a == 0) {
508                 sttybbs(SB_RESTORE);
509                 signal(SIGINT, SIG_DFL);
510                 signal(SIGQUIT, SIG_DFL);
511                 execlp(getenv("SHELL"), getenv("SHELL"), NULL);
512                 printf("Could not open a shell: %s\n", strerror(errno));
513                 exit(errno);
514         }
515         do {
516                 b = ka_wait(NULL);
517         } while ((a != b) && (a != (-1)));
518         sttybbs(0);
519 }
520
521 /*
522  * <.A>ide <F>ile <D>elete command
523  */
524 void deletefile(void)
525 {
526         char filename[32];
527         char cmd[SIZ];
528
529         newprompt("Filename: ", filename, 31);
530         if (strlen(filename) == 0)
531                 return;
532         sprintf(cmd, "DELF %s", filename);
533         serv_puts(cmd);
534         serv_gets(cmd);
535         printf("%s\n", &cmd[4]);
536 }
537
538 /*
539  * <.A>ide <F>ile <S>end command
540  */
541 void netsendfile(void)
542 {
543         char filename[32], destsys[20], cmd[SIZ];
544
545         newprompt("Filename: ", filename, 31);
546         if (strlen(filename) == 0)
547                 return;
548         newprompt("System to send to: ", destsys, 19);
549         sprintf(cmd, "NETF %s|%s", filename, destsys);
550         serv_puts(cmd);
551         serv_gets(cmd);
552         printf("%s\n", &cmd[4]);
553         return;
554 }
555
556 /*
557  * <.A>ide <F>ile <M>ove command
558  */
559 void movefile(void)
560 {
561         char filename[64];
562         char newroom[ROOMNAMELEN];
563         char cmd[SIZ];
564
565         newprompt("Filename: ", filename, 63);
566         if (strlen(filename) == 0)
567                 return;
568         newprompt("Enter target room: ", newroom, ROOMNAMELEN - 1);
569
570         sprintf(cmd, "MOVF %s|%s", filename, newroom);
571         serv_puts(cmd);
572         serv_gets(cmd);
573         printf("%s\n", &cmd[4]);
574 }
575
576
577 /* 
578  * list of users who have filled out a bio
579  */
580 void list_bio(void)
581 {
582         char buf[SIZ];
583         int pos = 1;
584
585         serv_puts("LBIO");
586         serv_gets(buf);
587         if (buf[0] != '1') {
588                 pprintf("%s\n", &buf[4]);
589                 return;
590         }
591         while (serv_gets(buf), strcmp(buf, "000")) {
592                 if ((pos + strlen(buf) + 5) > screenwidth) {
593                         pprintf("\n");
594                         pos = 1;
595                 }
596                 pprintf("%s, ", buf);
597                 pos = pos + strlen(buf) + 2;
598         }
599         pprintf("%c%c  \n\n", 8, 8);
600 }
601
602
603 /*
604  * read bio
605  */
606 void read_bio(void)
607 {
608         char who[SIZ];
609         char buf[SIZ];
610
611         do {
612                 newprompt("Read bio for who ('?' for list) : ", who, 25);
613                 pprintf("\n");
614                 if (!strcmp(who, "?"))
615                         list_bio();
616         } while (!strcmp(who, "?"));
617         sprintf(buf, "RBIO %s", who);
618         serv_puts(buf);
619         serv_gets(buf);
620         if (buf[0] != '1') {
621                 pprintf("%s\n", &buf[4]);
622                 return;
623         }
624         while (serv_gets(buf), strcmp(buf, "000")) {
625                 pprintf("%s\n", buf);
626         }
627 }
628
629
630 /* 
631  * General system configuration command
632  */
633 void do_system_configuration(void)
634 {
635         char buf[SIZ];
636         char sc[28][SIZ];
637         int expire_mode = 0;
638         int expire_value = 0;
639         int a;
640         int logpages = 0;
641
642         /* Clear out the config buffers */
643         memset(&sc[0][0], 0, sizeof(sc));
644
645         /* Fetch the current config */
646         serv_puts("CONF get");
647         serv_gets(buf);
648         if (buf[0] == '1') {
649                 a = 0;
650                 while (serv_gets(buf), strcmp(buf, "000")) {
651                         if (a < 28)
652                                 strcpy(&sc[a][0], buf);
653                         ++a;
654                 }
655         }
656         /* Fetch the expire policy (this will silently fail on old servers,
657          * resulting in "default" policy)
658          */
659         serv_puts("GPEX site");
660         serv_gets(buf);
661         if (buf[0] == '2') {
662                 expire_mode = extract_int(&buf[4], 0);
663                 expire_value = extract_int(&buf[4], 1);
664         }
665
666
667         /* Identification parameters */
668
669         strprompt("Node name", &sc[0][0], 15);
670         strprompt("Fully qualified domain name", &sc[1][0], 63);
671         strprompt("Human readable node name", &sc[2][0], 20);
672         strprompt("Modem dialup number", &sc[3][0], 15);
673         strprompt("Geographic location of this system", &sc[12][0], 31);
674         strprompt("Name of system administrator", &sc[13][0], 25);
675         strprompt("Paginator prompt", &sc[10][0], 79);
676         /* strprompt("Default moderation filter for new users", &sc[25][0], 4); */
677
678         /* Security parameters */
679
680         sprintf(&sc[7][0], "%d", (boolprompt(
681                                     "Require registration for new users",
682                                                     atoi(&sc[7][0]))));
683         strprompt("Initial access level for new users", &sc[6][0], 1);
684         strprompt("Access level required to create rooms", &sc[19][0], 1);
685         sprintf(&sc[4][0], "%d", (boolprompt(
686                                                     "Automatically give room aide privs to a user who creates a private room",
687                                                     atoi(&sc[4][0]))));
688
689         sprintf(&sc[8][0], "%d", (boolprompt(
690                  "Automatically move problem user messages to twit room",
691                                                     atoi(&sc[8][0]))));
692
693         strprompt("Name of twit room", &sc[9][0], ROOMNAMELEN);
694         sprintf(&sc[11][0], "%d", (boolprompt(
695               "Restrict Internet mail to only those with that privilege",
696                                                      atoi(&sc[11][0]))));
697         sprintf(&sc[26][0], "%d", (boolprompt(
698               "Allow Aides to Zap (forget) rooms",
699                                                      atoi(&sc[26][0]))));
700
701         if (strlen(&sc[18][0]) > 0) logpages = 1;
702         else logpages = 0;
703         logpages = boolprompt("Log all pages", logpages);
704         if (logpages) {
705                 strprompt("Name of logging room", &sc[18][0], ROOMNAMELEN);
706         }
707         else {
708                 sc[18][0] = 0;
709         }
710
711
712         /* Server tuning */
713
714         strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
715         strprompt("Maximum concurrent sessions", &sc[14][0], 4);
716         strprompt("Maximum message length", &sc[20][0], 20);
717         strprompt("Minimum number of worker threads", &sc[21][0], 3);
718         strprompt("Maximum number of worker threads", &sc[22][0], 3);
719         strprompt("Server-to-server networking password", &sc[15][0], 19);
720         strprompt("SMTP server port (-1 to disable)", &sc[24][0], 5);
721         strprompt("POP3 server port (-1 to disable)", &sc[23][0], 5);
722         strprompt("IMAP server port (-1 to disable)", &sc[27][0], 5);
723
724
725         /* Expiry settings */
726         strprompt("Default user purge time (days)", &sc[16][0], 5);
727         strprompt("Default room purge time (days)", &sc[17][0], 5);
728
729         /* Angels and demons dancing in my head... */
730         do {
731                 sprintf(buf, "%d", expire_mode);
732                 strprompt("System default message expire policy (? for list)",
733                           buf, 1);
734                 if (buf[0] == '?') {
735                         printf("\n");
736                         printf("1. Never automatically expire messages\n");
737                         printf("2. Expire by message count\n");
738                         printf("3. Expire by message age\n");
739                 }
740         } while ((buf[0] < 49) || (buf[0] > 51));
741         expire_mode = buf[0] - 48;
742
743         /* ...lunatics and monsters underneath my bed */
744         if (expire_mode == 2) {
745                 sprintf(buf, "%d", expire_value);
746                 strprompt("Keep how many messages online?", buf, 10);
747                 expire_value = atol(buf);
748         }
749         if (expire_mode == 3) {
750                 sprintf(buf, "%d", expire_value);
751                 strprompt("Keep messages for how many days?", buf, 10);
752                 expire_value = atol(buf);
753         }
754         /* Save it */
755         printf("Save this configuration? ");
756         if (yesno()) {
757                 serv_puts("CONF set");
758                 serv_gets(buf);
759                 if (buf[0] == '4') {
760                         for (a = 0; a < 28; ++a)
761                                 serv_puts(&sc[a][0]);
762                         serv_puts("000");
763                 }
764                 snprintf(buf, sizeof buf, "SPEX site|%d|%d",
765                          expire_mode, expire_value);
766                 serv_puts(buf);
767                 serv_gets(buf);
768         }
769 }
770
771
772 /*
773  * support function for do_internet_configuration()
774  */
775 void get_inet_rec_type(char *buf) {
776         int sel;
777
778         keyopt(" <1> localhost       (Alias for this computer)\n");
779         keyopt(" <2> gateway domain  (Domain for all Citadel systems)\n");
780         keyopt(" <3> smart-host      (Forward all outbound mail to this host)\n");
781         sel = intprompt("Which one", 1, 1, 3);
782         switch(sel) {
783                 case 1: strcpy(buf, "localhost");
784                         return;
785                 case 2: strcpy(buf, "gatewaydomain");
786                         return;
787                 case 3: strcpy(buf, "smarthost");
788                         return;
789         }
790 }
791
792
793 /*
794  * Internet mail configuration
795  */
796 void do_internet_configuration(void) {
797         char buf[SIZ];
798         int num_recs = 0;
799         char **recs = NULL;
800         char ch;
801         int badkey;
802         int i, j;
803         int quitting = 0;
804         
805
806         sprintf(buf, "CONF getsys|%s", INTERNETCFG);
807         serv_puts(buf);
808         serv_gets(buf);
809         if (buf[0] == '1') while (serv_gets(buf), strcmp(buf, "000")) {
810                 ++num_recs;
811                 if (num_recs == 1) recs = malloc(sizeof(char *));
812                 else recs = realloc(recs, (sizeof(char *)) * num_recs);
813                 recs[num_recs-1] = malloc(SIZ);
814                 strcpy(recs[num_recs-1], buf);
815         }
816
817         do {
818                 printf("\n");
819                 color(BRIGHT_WHITE);
820                 printf("### ");
821                 printf("                   Host or domain                  ");
822                 printf("   Record type      \n");
823                 color(DIM_WHITE);
824                 printf("--- ");
825                 printf("-------------------------------------------------- ");
826                 printf("--------------------\n");
827                 for (i=0; i<num_recs; ++i) {
828                 color(DIM_WHITE);
829                 printf("%3d ", i+1);
830                 extract(buf, recs[i], 0);
831                 color(BRIGHT_CYAN);
832                 printf("%-50s ", buf);
833                 extract(buf, recs[i], 1);
834                 color(BRIGHT_MAGENTA);
835                 printf("%-20s\n", buf);
836                 color(DIM_WHITE);
837                 }
838
839                 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
840                 switch(ch) {
841                         case 'a':
842                                 ++num_recs;
843                                 if (num_recs == 1)
844                                         recs = malloc(sizeof(char *));
845                                 else recs = realloc(recs,
846                                         (sizeof(char *)) * num_recs);
847                                 newprompt("Enter host name: ",
848                                         buf, 50);
849                                 strcat(buf, "|");
850                                 get_inet_rec_type(&buf[strlen(buf)]);
851                                 recs[num_recs-1] = strdup(buf);
852                                 break;
853                         case 'd':
854                                 i = intprompt("Delete which one",
855                                         1, 1, num_recs) - 1;
856                                 free(recs[i]);
857                                 --num_recs;
858                                 for (j=i; j<num_recs; ++j)
859                                         recs[j] = recs[j+1];
860                                 break;
861                         case 's':
862                                 sprintf(buf, "CONF putsys|%s",
863                                         INTERNETCFG);
864                                 serv_puts(buf);
865                                 serv_gets(buf);
866                                 if (buf[0] == '4') {
867                                         for (i=0; i<num_recs; ++i) {
868                                                 serv_puts(recs[i]);
869                                         }
870                                         serv_puts("000");
871                                 }
872                                 else {
873                                         printf("%s\n", &buf[4]);
874                                 }
875                                 quitting = 1;
876                                 break;
877                         case 'q':
878                                 quitting = boolprompt(
879                                         "Quit without saving", 0);
880                                 break;
881                         default:
882                                 badkey = 1;
883                 }
884         } while (quitting == 0);
885
886         if (recs != NULL) {
887                 for (i=0; i<num_recs; ++i) free(recs[i]);
888                 free(recs);
889         }
890 }