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 serv_puts("GREG _SELF_");
103 while (serv_gets(buf), strcmp(buf, "000")) {
105 strcpy(tmpname, buf);
107 strcpy(tmpaddr, buf);
109 strcpy(tmpcity, buf);
111 strcpy(tmpstate, buf);
115 strcpy(tmpphone, buf);
117 strcpy(tmpemail, buf);
121 strprompt("REAL name", tmpname, 29);
122 strprompt("Address", tmpaddr, 24);
123 strprompt("City/town", tmpcity, 14);
124 strprompt("State", tmpstate, 2);
125 strprompt("ZIP Code", tmpzip, 10);
126 strprompt("Telephone number", tmpphone, 14);
127 strprompt("Email address", tmpemail, 31);
129 /* now send the registration info back to the server */
133 printf("%s\n", &buf[4]);
148 { /* make all messages old in current room */
150 serv_puts("SLRP HIGHEST");
153 printf("%s\n", &buf[4]);
157 * only make messages old in this room that have been read
162 sprintf(buf, "SLRP %ld", highest_msg_read);
166 printf("%s\n", &buf[4]);
171 * This routine completes a client upload
173 void do_upload(int fd)
177 long transmitted_bytes, total_bytes;
181 /* learn the size of the file */
182 total_bytes = lseek(fd, 0L, 2);
185 transmitted_bytes = 0L;
186 progress(transmitted_bytes, total_bytes);
188 bytes_to_send = read(fd, tbuf, 4096);
189 if (bytes_to_send > 0) {
190 sprintf(buf, "WRIT %d", bytes_to_send);
194 bytes_expected = atoi(&buf[4]);
195 serv_write(tbuf, bytes_expected);
197 printf("%s\n", &buf[4]);
200 transmitted_bytes = transmitted_bytes + (long) bytes_to_send;
201 progress(transmitted_bytes, total_bytes);
202 } while (bytes_to_send > 0);
204 /* close the upload file, locally and at the server */
208 printf("%s\n", &buf[4]);
213 * client-based uploads (for users with their own clientware)
215 void cli_upload(void)
224 if ((room_flags & QR_UPLOAD) == 0) {
225 printf("*** You cannot upload to this room.\n");
228 newprompt("File to be uploaded: ", flnm, 55);
229 fd = open(flnm, O_RDONLY);
231 printf("Cannot open '%s': %s\n", flnm, strerror(errno));
234 printf("Enter a description of this file:\n");
235 newprompt(": ", desc, 75);
237 /* keep generating filenames in hope of finding a unique one */
241 return; /* fail if tried 10 times */
243 while ((strlen(buf) > 0) && (haschar(buf, '/')))
244 strcpy(buf, &buf[1]);
246 sprintf(&buf[strlen(buf)], "%d", a);
247 sprintf(tbuf, "UOPN %s|%s", buf, desc);
251 printf("%s\n", &buf[4]);
253 } while (buf[0] != '2');
255 /* at this point we have an open upload file at the server */
261 * Function used for various image upload commands
263 void cli_image_upload(char *keyname)
269 sprintf(buf, "UIMG 0|%s", keyname);
273 printf("%s\n", &buf[4]);
276 newprompt("Image file to be uploaded: ", flnm, 55);
277 fd = open(flnm, O_RDONLY);
279 printf("Cannot open '%s': %s\n", flnm, strerror(errno));
282 sprintf(buf, "UIMG 1|%s", keyname);
286 printf("%s\n", &buf[4]);
294 * protocol-based uploads (Xmodem, Ymodem, Zmodem)
297 { /* c = upload mode */
307 if ((room_flags & QR_UPLOAD) == 0) {
308 printf("*** You cannot upload to this room.\n");
311 /* we don't need a filename when receiving batch y/z modem */
312 if ((c == 2) || (c == 3))
315 newprompt("Enter filename: ", flnm, 15);
317 for (a = 0; a < strlen(flnm); ++a)
318 if ((flnm[a] == '/') || (flnm[a] == '\\') || (flnm[a] == '>')
319 || (flnm[a] == '?') || (flnm[a] == '*')
320 || (flnm[a] == ';') || (flnm[a] == '&'))
323 newprompt("Enter a short description of the file:\n: ", desc, 150);
325 /* create a temporary directory... */
326 if (mkdir(tempdir, 0700) != 0) {
327 printf("*** Could not create temporary directory %s: %s\n",
328 tempdir, strerror(errno));
331 /* now do the transfer ... in a separate process */
338 printf("Receiving %s - press Ctrl-D to end.\n", flnm);
339 fp = fopen(flnm, "w");
355 execlp("rx", "rx", flnm, NULL);
359 execlp("rb", "rb", NULL);
363 execlp("rz", "rz", NULL);
369 } while ((b != xfer_pid) && (b != (-1)));
373 printf("\r*** Transfer unsuccessful.\n");
377 printf("\r*** Transfer successful. Sending file(s) to server...\n");
378 sprintf(buf, "cd %s; ls", tempdir);
379 lsfp = popen(buf, "r");
381 while (fgets(flnm, 256, lsfp) != NULL) {
382 flnm[strlen(flnm) - 1] = 0;
383 sprintf(buf, "%s/%s", tempdir, flnm);
384 fd = open(buf, O_RDONLY);
388 sprintf(buf, "UOPN %s|%s", flnm, desc);
390 sprintf(&buf[strlen(buf)],
395 } while ((buf[0] != '2') && (a < 100));
398 a = read(fd, tbuf, 4096);
400 sprintf(buf, "WRIT %d", a);
410 printf("%s\n", &buf[4]);
421 void val_user(char *user, int do_validate)
428 sprintf(cmd, "GREG %s", user);
437 printf("User #%s - %s ", buf, &cmd[4]);
439 printf("PW: %s\n", buf);
456 } while (strcmp(buf, "000"));
457 printf("Current access level: %d (%s)\n", ax, axdefs[ax]);
459 printf("%-30s\n%s\n", user, &cmd[4]);
463 /* now set the access level */
464 ax = intprompt("Access level", ax, 0, 6);
465 sprintf(cmd, "VALI %s|%d", user, ax);
469 printf("%s\n", &cmd[4]);
476 { /* validate new users */
487 printf("%s\n", &cmd[4]);
489 extract(buf, cmd, 0);
490 val_user(&buf[4], 1);
492 } while (finished == 0);
501 signal(SIGINT, SIG_DFL);
502 signal(SIGQUIT, SIG_DFL);
503 execlp(getenv("SHELL"), getenv("SHELL"), NULL);
504 printf("Could not open a shell: %s\n", strerror(errno));
509 } while ((a != b) && (a != (-1)));
514 * <.A>ide <F>ile <D>elete command
516 void deletefile(void)
521 newprompt("Filename: ", filename, 31);
522 if (strlen(filename) == 0)
524 sprintf(cmd, "DELF %s", filename);
527 printf("%s\n", &cmd[4]);
531 * <.A>ide <F>ile <S>end command
533 void netsendfile(void)
535 char filename[32], destsys[20], cmd[256];
537 newprompt("Filename: ", filename, 31);
538 if (strlen(filename) == 0)
540 newprompt("System to send to: ", destsys, 19);
541 sprintf(cmd, "NETF %s|%s", filename, destsys);
544 printf("%s\n", &cmd[4]);
549 * <.A>ide <F>ile <M>ove command
554 char newroom[ROOMNAMELEN];
557 newprompt("Filename: ", filename, 63);
558 if (strlen(filename) == 0)
560 newprompt("Enter target room: ", newroom, ROOMNAMELEN - 1);
562 sprintf(cmd, "MOVF %s|%s", filename, newroom);
565 printf("%s\n", &cmd[4]);
570 * list of users who have filled out a bio
580 pprintf("%s\n", &buf[4]);
583 while (serv_gets(buf), strcmp(buf, "000")) {
584 if ((pos + strlen(buf) + 5) > screenwidth) {
588 pprintf("%s, ", buf);
589 pos = pos + strlen(buf) + 2;
591 pprintf("%c%c \n\n", 8, 8);
604 newprompt("Read bio for who ('?' for list) : ", who, 25);
606 if (!strcmp(who, "?"))
608 } while (!strcmp(who, "?"));
609 sprintf(buf, "RBIO %s", who);
613 pprintf("%s\n", &buf[4]);
616 while (serv_gets(buf), strcmp(buf, "000")) {
617 pprintf("%s\n", buf);
623 * General system configuration command
625 void do_system_configuration(void)
630 int expire_value = 0;
633 /* Clear out the config buffers */
634 memset(&sc[0][0], 0, sizeof(sc));
636 /* Fetch the current config */
637 serv_puts("CONF get");
641 while (serv_gets(buf), strcmp(buf, "000")) {
643 strcpy(&sc[a][0], buf);
647 /* Fetch the expire policy (this will silently fail on old servers,
648 * resulting in "default" policy)
650 serv_puts("GPEX site");
653 expire_mode = extract_int(&buf[4], 0);
654 expire_value = extract_int(&buf[4], 1);
658 /* Identification parameters */
660 strprompt("Node name", &sc[0][0], 15);
661 strprompt("Fully qualified domain name", &sc[1][0], 63);
662 strprompt("Human readable node name", &sc[2][0], 20);
663 strprompt("Modem dialup number", &sc[3][0], 15);
664 strprompt("Geographic location of this system", &sc[12][0], 31);
665 strprompt("Name of system administrator", &sc[13][0], 25);
666 strprompt("Paginator prompt", &sc[10][0], 79);
667 strprompt("Default moderation filter for new users", &sc[25][0], 4);
669 /* Security parameters */
671 sprintf(&sc[7][0], "%d", (boolprompt(
672 "Require registration for new users",
674 strprompt("Initial access level for new users", &sc[6][0], 1);
675 strprompt("Access level required to create rooms", &sc[19][0], 1);
676 sprintf(&sc[4][0], "%d", (boolprompt(
677 "Automatically give room aide privs to a user who creates a private room",
680 sprintf(&sc[8][0], "%d", (boolprompt(
681 "Automatically move problem user messages to twit room",
684 strprompt("Name of twit room", &sc[9][0], ROOMNAMELEN);
685 sprintf(&sc[11][0], "%d", (boolprompt(
686 "Restrict Internet mail to only those with that privilege",
689 strprompt("Name of room to log pages", &sc[18][0], ROOMNAMELEN);
694 strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
695 strprompt("Maximum concurrent sessions", &sc[14][0], 4);
696 strprompt("Maximum message length", &sc[20][0], 20);
697 strprompt("Minimum number of worker threads", &sc[21][0], 3);
698 strprompt("Maximum number of worker threads", &sc[22][0], 3);
699 strprompt("Server-to-server networking password", &sc[15][0], 19);
700 strprompt("POP3 server port (-1 to disable)", &sc[23][0], 5);
701 strprompt("SMTP server port (-1 to disable)", &sc[24][0], 5);
704 /* Expiry settings */
705 strprompt("Default user purge time (days)", &sc[16][0], 5);
706 strprompt("Default room purge time (days)", &sc[17][0], 5);
708 /* Angels and demons dancing in my head... */
710 sprintf(buf, "%d", expire_mode);
711 strprompt("System default message expire policy (? for list)",
715 printf("1. Never automatically expire messages\n");
716 printf("2. Expire by message count\n");
717 printf("3. Expire by message age\n");
719 } while ((buf[0] < 49) || (buf[0] > 51));
720 expire_mode = buf[0] - 48;
722 /* ...lunatics and monsters underneath my bed */
723 if (expire_mode == 2) {
724 sprintf(buf, "%d", expire_value);
725 strprompt("Keep how many messages online?", buf, 10);
726 expire_value = atol(buf);
728 if (expire_mode == 3) {
729 sprintf(buf, "%d", expire_value);
730 strprompt("Keep messages for how many days?", buf, 10);
731 expire_value = atol(buf);
734 printf("Save this configuration? ");
736 serv_puts("CONF set");
739 for (a = 0; a < 26; ++a)
740 serv_puts(&sc[a][0]);
743 snprintf(buf, sizeof buf, "SPEX site|%d|%d",
744 expire_mode, expire_value);
752 * support function for do_internet_configuration()
754 void get_inet_rec_type(char *buf) {
757 keyopt(" <1> localhost (Alias for this computer)\n");
758 keyopt(" <2> gateway domain (Domain for all Citadel systems)\n");
759 keyopt(" <3> smart-host (Forward all outbound mail to this host)\n");
760 sel = intprompt("Which one", 1, 1, 3);
762 case 1: strcpy(buf, "localhost");
764 case 2: strcpy(buf, "gatewaydomain");
766 case 3: strcpy(buf, "smarthost");
773 * Internet mail configuration
775 void do_internet_configuration(void) {
785 sprintf(buf, "CONF getsys|%s", INTERNETCFG);
788 if (buf[0] == '1') while (serv_gets(buf), strcmp(buf, "000")) {
790 if (num_recs == 1) recs = malloc(sizeof(char *));
791 else recs = realloc(recs, (sizeof(char *)) * num_recs);
792 recs[num_recs-1] = malloc(256);
793 strcpy(recs[num_recs-1], buf);
800 printf(" Host or domain ");
801 printf(" Record type \n");
804 printf("-------------------------------------------------- ");
805 printf("--------------------\n");
806 for (i=0; i<num_recs; ++i) {
809 extract(buf, recs[i], 0);
811 printf("%-50s ", buf);
812 extract(buf, recs[i], 1);
813 color(BRIGHT_MAGENTA);
814 printf("%-20s\n", buf);
818 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
823 recs = malloc(sizeof(char *));
824 else recs = realloc(recs,
825 (sizeof(char *)) * num_recs);
826 newprompt("Enter host name: ",
829 get_inet_rec_type(&buf[strlen(buf)]);
830 recs[num_recs-1] = strdup(buf);
833 i = intprompt("Delete which one",
837 for (j=i; j<num_recs; ++j)
841 sprintf(buf, "CONF putsys|%s",
846 for (i=0; i<num_recs; ++i) {
852 printf("%s\n", &buf[4]);
857 quitting = boolprompt(
858 "Quit without saving", 0);
863 } while (quitting == 0);
866 for (i=0; i<num_recs; ++i) free(recs[i]);