diff --git a/doors.c b/doors.c new file mode 100644 index 0000000..f57db7a --- /dev/null +++ b/doors.c @@ -0,0 +1,267 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(linux) +# include +#elif defined(__OpenBSD__) || defined(__NetBSD__) +# include +#else +# include +#endif +#include "bbs.h" + +extern struct bbs_config conf; +extern int mynode; + +int running_door_pid = 0; +int running_door = 0; + +void doorchld_handler(int s) +{ + // waitpid() might overwrite errno, so we save and restore it: + while(waitpid(-1, NULL, WNOHANG) > 0); + + running_door = 0; +} + +int write_door32sys(int socket, struct user_record *user) { + struct stat s; + char buffer[256]; + FILE *fptr; + char *ptr; + int i; + + sprintf(buffer, "%s/node%d", conf.bbs_path, mynode); + + if (stat(buffer, &s) != 0) { + mkdir(buffer, 0755); + } + + sprintf(buffer, "%s/node%d/door32.sys", conf.bbs_path, mynode); + + fptr = fopen(buffer, "w"); + + if (!fptr) { + printf("Unable to open %s for writing!\n", buffer); + return 1; + } + + fprintf(fptr, "2\n"); // telnet type + fprintf(fptr, "%d\n", socket); // socket + fprintf(fptr, "38400\n"); // baudrate + fprintf(fptr, "Magicka %d.%d\n", VERSION_MAJOR, VERSION_MINOR); + fprintf(fptr, "%d\n", user->id); + fprintf(fptr, "%s %s\n", user->firstname, user->lastname); + fprintf(fptr, "%s\n", user->loginname); + fprintf(fptr, "%d\n", user->sec_level); + fprintf(fptr, "%d\n", user->timeleft); + fprintf(fptr, "1\n"); // ansi emulation = 1 + fprintf(fptr, "%d\n", mynode); + + fclose(fptr); + + // create dorinfo1.def + + sprintf(buffer, "%s/node%d", conf.bbs_path, mynode); + + if (stat(buffer, &s) != 0) { + mkdir(buffer, 0755); + } + + sprintf(buffer, "%s/node%d/dorinfo1.def", conf.bbs_path, mynode); + + fptr = fopen(buffer, "w"); + + if (!fptr) { + printf("Unable to open %s for writing!\n", buffer); + return 1; + } + + strcpy(buffer, conf.sysop_name); + + ptr = NULL; + + for (i=0;ifirstname); + fprintf(fptr, "%s\n", user->lastname); + fprintf(fptr, "%s\n", user->location); + fprintf(fptr, "1\n"); + fprintf(fptr, "30\n"); + fprintf(fptr, "%d\n", user->timeleft); + fprintf(fptr, "-1\n"); + + + fclose(fptr); + + + return 0; +} + +void rundoor(int socket, struct user_record *user, char *cmd, int stdio) { + char buffer[256]; + int pid; + char *arguments[4]; + int ret; + char c; + int len; + int status; + int master; + int slave; + fd_set fdset; + int t; + struct winsize ws; + struct sigaction sa; + + if (write_door32sys(socket, user) != 0) { + return; + } + + if (stdio) { + + arguments[0] = strdup(cmd); + sprintf(buffer, "%d", mynode); + arguments[1] = strdup(buffer); + sprintf(buffer, "%d", socket); + arguments[2] = strdup(buffer); + arguments[3] = NULL; + + ws.ws_row = 24; + ws.ws_col = 80; + + running_door = 1; + + if (openpty(&master, &slave, NULL, NULL, &ws) == 0) { + sa.sa_handler = doorchld_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + if (sigaction(SIGCHLD, &sa, NULL) == -1) { + perror("sigaction"); + exit(1); + } + + pid = fork(); + if (pid < 0) { + return; + } else if (pid == 0) { + + close(master); + dup2(slave, 0); + dup2(slave, 1); + + close(slave); + + setsid(); + + ioctl(0, TIOCSCTTY, 1); + + execvp(cmd, arguments); + } else { + running_door_pid = pid; + + while(running_door != 0) { + FD_ZERO(&fdset); + FD_SET(master, &fdset); + FD_SET(socket, &fdset); + if (master > socket) { + t = master + 1; + } else { + t = socket + 1; + } + ret = select(t, &fdset, NULL, NULL, NULL); + if (ret > 0) { + if (FD_ISSET(socket, &fdset)) { + len = read(socket, &c, 1); + if (len == 0) { + close(master); + disconnect(socket); + return; + } + write(master, &c, 1); + } else if (FD_ISSET(master, &fdset)) { + len = read(master, &c, 1); + if (len == 0) { + close(master); + break; + } + write(socket, &c, 1); + } + } + } + } + } + free(arguments[0]); + free(arguments[1]); + free(arguments[2]); + } else { + sprintf(buffer, "%s %d %d", cmd, mynode, socket); + system(buffer); + } +} + +int door_menu(int socket, struct user_record *user) { + int doquit = 0; + int dodoors = 0; + char prompt[128]; + int i; + char c; + while (!dodoors) { + s_displayansi(socket, "doors"); + + sprintf(prompt, "\e[0m\r\nTL: %dm :> ", user->timeleft); + s_putstring(socket, prompt); + + c = s_getc(socket); + + switch(tolower(c)) { + case 'q': + dodoors = 1; + break; + case 'g': + { + s_putstring(socket, "\r\nAre you sure you want to log off? (Y/N)"); + c = s_getc(socket); + if (tolower(c) == 'y') { + doquit = 1; + dodoors = 1; + } + } + break; + default: + { + for (i=0;ikey)) { + rundoor(socket, user, conf.doors[i]->command, conf.doors[i]->stdio); + break; + } + } + } + break; + } + } + + return doquit; +}