3 * More client-side support functions.
4 * Unlike routines.c, some of these DO use global variables.
11 #include <sys/types.h>
24 #include "routines2.h"
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);
38 void serv_write(char *buf, int nbytes);
39 int haschar(char *st, int ch);
40 void progress(long int curr, long int cmax);
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;
52 int eopen(char *name, int mode)
55 ret = open(name, mode);
57 fprintf(stderr, "Cannot open file '%s', mode=%d, errno=%d\n",
65 int room_prompt(int qrflags)
66 { /* return proper room prompt character */
69 if (qrflags & QR_DIRECTORY)
71 if ((a == ']') && (qrflags & QR_NETWORK))
73 if ((a == '>') && (qrflags & QR_NETWORK))
79 { /* register with name and address */
99 strcpy(tmpcountry, "");
101 serv_puts("GREG _SELF_");
105 while (serv_gets(buf), strcmp(buf, "000")) {
107 strcpy(tmpname, buf);
109 strcpy(tmpaddr, buf);
111 strcpy(tmpcity, buf);
113 strcpy(tmpstate, buf);
117 strcpy(tmpphone, buf);
119 strcpy(tmpemail, buf);
121 strcpy(tmpcountry, buf);
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);
134 /* now send the registration info back to the server */
138 printf("%s\n", &buf[4]);
148 serv_puts(tmpcountry);
154 { /* make all messages old in current room */
156 serv_puts("SLRP HIGHEST");
159 printf("%s\n", &buf[4]);
163 * only make messages old in this room that have been read
168 sprintf(buf, "SLRP %ld", highest_msg_read);
172 printf("%s\n", &buf[4]);
177 * This routine completes a client upload
179 void do_upload(int fd)
183 long transmitted_bytes, total_bytes;
187 /* learn the size of the file */
188 total_bytes = lseek(fd, 0L, 2);
191 transmitted_bytes = 0L;
192 progress(transmitted_bytes, total_bytes);
194 bytes_to_send = read(fd, tbuf, 4096);
195 if (bytes_to_send > 0) {
196 sprintf(buf, "WRIT %d", bytes_to_send);
200 bytes_expected = atoi(&buf[4]);
201 serv_write(tbuf, bytes_expected);
203 printf("%s\n", &buf[4]);
206 transmitted_bytes = transmitted_bytes + (long) bytes_to_send;
207 progress(transmitted_bytes, total_bytes);
208 } while (bytes_to_send > 0);
210 /* close the upload file, locally and at the server */
214 printf("%s\n", &buf[4]);
219 * client-based uploads (for users with their own clientware)
221 void cli_upload(void)
230 if ((room_flags & QR_UPLOAD) == 0) {
231 printf("*** You cannot upload to this room.\n");
234 newprompt("File to be uploaded: ", flnm, 55);
235 fd = open(flnm, O_RDONLY);
237 printf("Cannot open '%s': %s\n", flnm, strerror(errno));
240 printf("Enter a description of this file:\n");
241 newprompt(": ", desc, 75);
243 /* keep generating filenames in hope of finding a unique one */
247 return; /* fail if tried 10 times */
249 while ((strlen(buf) > 0) && (haschar(buf, '/')))
250 strcpy(buf, &buf[1]);
252 sprintf(&buf[strlen(buf)], "%d", a);
253 sprintf(tbuf, "UOPN %s|%s", buf, desc);
257 printf("%s\n", &buf[4]);
259 } while (buf[0] != '2');
261 /* at this point we have an open upload file at the server */
267 * Function used for various image upload commands
269 void cli_image_upload(char *keyname)
275 sprintf(buf, "UIMG 0|%s", keyname);
279 printf("%s\n", &buf[4]);
282 newprompt("Image file to be uploaded: ", flnm, 55);
283 fd = open(flnm, O_RDONLY);
285 printf("Cannot open '%s': %s\n", flnm, strerror(errno));
288 sprintf(buf, "UIMG 1|%s", keyname);
292 printf("%s\n", &buf[4]);
300 * protocol-based uploads (Xmodem, Ymodem, Zmodem)
303 { /* c = upload mode */
313 if ((room_flags & QR_UPLOAD) == 0) {
314 printf("*** You cannot upload to this room.\n");
317 /* we don't need a filename when receiving batch y/z modem */
318 if ((c == 2) || (c == 3))
321 newprompt("Enter filename: ", flnm, 15);
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] == '&'))
329 newprompt("Enter a short description of the file:\n: ", desc, 150);
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));
337 /* now do the transfer ... in a separate process */
344 printf("Receiving %s - press Ctrl-D to end.\n", flnm);
345 fp = fopen(flnm, "w");
361 execlp("rx", "rx", flnm, NULL);
365 execlp("rb", "rb", NULL);
369 execlp("rz", "rz", NULL);
375 } while ((b != xfer_pid) && (b != (-1)));
379 printf("\r*** Transfer unsuccessful.\n");
383 printf("\r*** Transfer successful. Sending file(s) to server...\n");
384 sprintf(buf, "cd %s; ls", tempdir);
385 lsfp = popen(buf, "r");
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);
394 sprintf(buf, "UOPN %s|%s", flnm, desc);
396 sprintf(&buf[strlen(buf)],
401 } while ((buf[0] != '2') && (a < 100));
404 a = read(fd, tbuf, 4096);
406 sprintf(buf, "WRIT %d", a);
416 printf("%s\n", &buf[4]);
427 void val_user(char *user, int do_validate)
434 sprintf(cmd, "GREG %s", user);
443 printf("User #%s - %s ", buf, &cmd[4]);
445 printf("PW: %s\n", buf);
464 } while (strcmp(buf, "000"));
465 printf("Current access level: %d (%s)\n", ax, axdefs[ax]);
467 printf("%-30s\n%s\n", user, &cmd[4]);
471 /* now set the access level */
472 ax = intprompt("Access level", ax, 0, 6);
473 sprintf(cmd, "VALI %s|%d", user, ax);
477 printf("%s\n", &cmd[4]);
484 { /* validate new users */
495 printf("%s\n", &cmd[4]);
497 extract(buf, cmd, 0);
498 val_user(&buf[4], 1);
500 } while (finished == 0);
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));
517 } while ((a != b) && (a != (-1)));
522 * <.A>ide <F>ile <D>elete command
524 void deletefile(void)
529 newprompt("Filename: ", filename, 31);
530 if (strlen(filename) == 0)
532 sprintf(cmd, "DELF %s", filename);
535 printf("%s\n", &cmd[4]);
539 * <.A>ide <F>ile <S>end command
541 void netsendfile(void)
543 char filename[32], destsys[20], cmd[SIZ];
545 newprompt("Filename: ", filename, 31);
546 if (strlen(filename) == 0)
548 newprompt("System to send to: ", destsys, 19);
549 sprintf(cmd, "NETF %s|%s", filename, destsys);
552 printf("%s\n", &cmd[4]);
557 * <.A>ide <F>ile <M>ove command
562 char newroom[ROOMNAMELEN];
565 newprompt("Filename: ", filename, 63);
566 if (strlen(filename) == 0)
568 newprompt("Enter target room: ", newroom, ROOMNAMELEN - 1);
570 sprintf(cmd, "MOVF %s|%s", filename, newroom);
573 printf("%s\n", &cmd[4]);
578 * list of users who have filled out a bio
588 pprintf("%s\n", &buf[4]);
591 while (serv_gets(buf), strcmp(buf, "000")) {
592 if ((pos + strlen(buf) + 5) > screenwidth) {
596 pprintf("%s, ", buf);
597 pos = pos + strlen(buf) + 2;
599 pprintf("%c%c \n\n", 8, 8);
612 newprompt("Read bio for who ('?' for list) : ", who, 25);
614 if (!strcmp(who, "?"))
616 } while (!strcmp(who, "?"));
617 sprintf(buf, "RBIO %s", who);
621 pprintf("%s\n", &buf[4]);
624 while (serv_gets(buf), strcmp(buf, "000")) {
625 pprintf("%s\n", buf);
631 * General system configuration command
633 void do_system_configuration(void)
638 int expire_value = 0;
642 /* Clear out the config buffers */
643 memset(&sc[0][0], 0, sizeof(sc));
645 /* Fetch the current config */
646 serv_puts("CONF get");
650 while (serv_gets(buf), strcmp(buf, "000")) {
652 strcpy(&sc[a][0], buf);
656 /* Fetch the expire policy (this will silently fail on old servers,
657 * resulting in "default" policy)
659 serv_puts("GPEX site");
662 expire_mode = extract_int(&buf[4], 0);
663 expire_value = extract_int(&buf[4], 1);
667 /* Identification parameters */
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);
678 /* Security parameters */
680 sprintf(&sc[7][0], "%d", (boolprompt(
681 "Require registration for new users",
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",
689 sprintf(&sc[8][0], "%d", (boolprompt(
690 "Automatically move problem user messages to twit room",
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",
697 sprintf(&sc[26][0], "%d", (boolprompt(
698 "Allow Aides to Zap (forget) rooms",
701 if (strlen(&sc[18][0]) > 0) logpages = 1;
703 logpages = boolprompt("Log all pages", logpages);
705 strprompt("Name of logging room", &sc[18][0], ROOMNAMELEN);
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);
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);
729 /* Angels and demons dancing in my head... */
731 sprintf(buf, "%d", expire_mode);
732 strprompt("System default message expire policy (? for list)",
736 printf("1. Never automatically expire messages\n");
737 printf("2. Expire by message count\n");
738 printf("3. Expire by message age\n");
740 } while ((buf[0] < 49) || (buf[0] > 51));
741 expire_mode = buf[0] - 48;
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);
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);
755 printf("Save this configuration? ");
757 serv_puts("CONF set");
760 for (a = 0; a < 28; ++a)
761 serv_puts(&sc[a][0]);
764 snprintf(buf, sizeof buf, "SPEX site|%d|%d",
765 expire_mode, expire_value);
773 * support function for do_internet_configuration()
775 void get_inet_rec_type(char *buf) {
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);
783 case 1: strcpy(buf, "localhost");
785 case 2: strcpy(buf, "gatewaydomain");
787 case 3: strcpy(buf, "smarthost");
794 * Internet mail configuration
796 void do_internet_configuration(void) {
806 sprintf(buf, "CONF getsys|%s", INTERNETCFG);
809 if (buf[0] == '1') while (serv_gets(buf), strcmp(buf, "000")) {
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);
821 printf(" Host or domain ");
822 printf(" Record type \n");
825 printf("-------------------------------------------------- ");
826 printf("--------------------\n");
827 for (i=0; i<num_recs; ++i) {
830 extract(buf, recs[i], 0);
832 printf("%-50s ", buf);
833 extract(buf, recs[i], 1);
834 color(BRIGHT_MAGENTA);
835 printf("%-20s\n", buf);
839 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
844 recs = malloc(sizeof(char *));
845 else recs = realloc(recs,
846 (sizeof(char *)) * num_recs);
847 newprompt("Enter host name: ",
850 get_inet_rec_type(&buf[strlen(buf)]);
851 recs[num_recs-1] = strdup(buf);
854 i = intprompt("Delete which one",
858 for (j=i; j<num_recs; ++j)
862 sprintf(buf, "CONF putsys|%s",
867 for (i=0; i<num_recs; ++i) {
873 printf("%s\n", &buf[4]);
878 quitting = boolprompt(
879 "Quit without saving", 0);
884 } while (quitting == 0);
887 for (i=0; i<num_recs; ++i) free(recs[i]);