#include #include #include #include #include #include #include #include #include #include #include #include #if defined(linux) # include #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) # include #else # include #endif #include "bbs.h" #include "lua/lua.h" #include "lua/lualib.h" #include "lua/lauxlib.h" extern struct bbs_config conf; extern int mynode; extern int gSocket; extern int sshBBS; extern int bbs_stderr; int running_door_pid = 0; int running_door = 0; extern int timeoutpaused; 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(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) { dolog("Unable to open %s for writing!", buffer); return 1; } fprintf(fptr, "2\r\n"); // telnet type fprintf(fptr, "%d\r\n", gSocket); // socket fprintf(fptr, "38400\r\n"); // baudrate fprintf(fptr, "Magicka %d.%d\r\n", VERSION_MAJOR, VERSION_MINOR); fprintf(fptr, "%d\r\n", user->id); fprintf(fptr, "%s %s\r\n", user->firstname, user->lastname); fprintf(fptr, "%s\r\n", user->loginname); fprintf(fptr, "%d\r\n", user->sec_level); fprintf(fptr, "%d\r\n", user->timeleft); fprintf(fptr, "1\r\n"); // ansi emulation = 1 fprintf(fptr, "%d\r\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) { dolog("Unable to open %s for writing!", buffer); return 1; } strcpy(buffer, conf.sysop_name); ptr = NULL; for (i=0;ifirstname); fprintf(fptr, "%s\r\n", user->lastname); fprintf(fptr, "%s\r\n", user->location); fprintf(fptr, "1\r\n"); fprintf(fptr, "%d\r\n", user->sec_level); fprintf(fptr, "%d\r\n", user->timeleft); fprintf(fptr, "-1\r\n"); fclose(fptr); return 0; } void rundoor(struct user_record *user, char *cmd, int stdio, char *codepage) { char *arguments[4]; int door_out; char buffer[10]; if (sshBBS) { door_out = STDOUT_FILENO; } else { door_out = gSocket; } arguments[0] = strdup(cmd); sprintf(buffer, "%d", mynode); arguments[1] = strdup(buffer); sprintf(buffer, "%d", door_out); arguments[2] = strdup(buffer); arguments[3] = NULL; runexternal(user, cmd, stdio, arguments, NULL, 0, codepage); free(arguments[0]); free(arguments[1]); free(arguments[2]); } void runexternal(struct user_record *user, char *cmd, int stdio, char *argv[], char *cwd, int raw, char *codepage) { char buffer[1024]; int pid; int ret; unsigned char c; int len; int master; int slave; fd_set fdset; int t; struct winsize ws; struct sigaction sa; int door_in; int door_out; int i; int gotiac; int flush; iconv_t ic; struct timeval thetimeout; struct termios oldit; struct termios oldot; struct termios oldit2; char inbuf[256]; char outbuf[512]; int h; int g; char *ptr1; char *ptr2; char *ptr2p; size_t ouc; size_t inc; size_t sz; timeoutpaused = 1; if (write_door32sys(user) != 0) { return; } if (stdio) { if (sshBBS) { door_in = STDIN_FILENO; door_out = STDOUT_FILENO; } else { door_in = gSocket; door_out = gSocket; } ws.ws_row = 24; ws.ws_col = 80; running_door = 1; if (!sshBBS) { if (openpty(&master, &slave, NULL, NULL, &ws) == 0) { sa.sa_handler = doorchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART | SA_SIGINFO; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } if (raw) { ttySetRaw(master, &oldit2); ttySetRaw(slave, &oldit2); } pid = fork(); if (pid < 0) { return; } else if (pid == 0) { if (cwd != NULL) { chdir(cwd); } close(master); dup2(slave, 0); dup2(slave, 1); close(slave); setsid(); ioctl(0, TIOCSCTTY, 1); execvp(cmd, argv); } else { running_door_pid = pid; gotiac = 0; flush = 0; while(running_door || !flush) { FD_ZERO(&fdset); FD_SET(master, &fdset); FD_SET(door_in, &fdset); if (master > door_in) { t = master + 1; } else { t = door_in + 1; } thetimeout.tv_sec = 5; thetimeout.tv_usec = 0; ret = select(t, &fdset, NULL, NULL, &thetimeout); if (ret > 0) { if (FD_ISSET(door_in, &fdset)) { len = read(door_in, inbuf, 256); if (len == 0) { close(master); disconnect("Socket Closed"); return; } g = 0; for (h=0;hcodepage == 0) || (strcmp(codepage, "UTF-8") == 0 && user->codepage == 1)) { write(master, outbuf, g); } else { if (user->codepage == 0) { ic = iconv_open(codepage, "CP437"); } else { ic = iconv_open(codepage, "UTF-8"); } ptr1 = outbuf; ptr2 = (char *)malloc((g + 1) * 4); ptr2p = ptr2; memset(ptr2, 0, (g + 1) * 4); inc = g; ouc = (g + 1) * 4; iconv(ic, &ptr1, &inc, &ptr2, &ouc); write(master, ptr2p, ptr2 - ptr2p); free(ptr2p); iconv_close(ic); } } else if (FD_ISSET(master, &fdset)) { len = read(master, inbuf, 256); if (len == 0) { close(master); break; } g = 0; for (h=0;hcodepage == 0) || (strcmp(codepage, "UTF-8") == 0 && user->codepage == 1)) { write(door_out, outbuf, g); } else { if (user->codepage == 0) { ic = iconv_open("CP437", codepage); } else { ic = iconv_open("UTF-8", codepage); } ptr1 = outbuf; ptr2 = (char *)malloc((g + 1) * 4); ptr2p = ptr2; memset(ptr2, 0, (g + 1) * 4); inc = g; ouc = (g + 1) * 4; sz = iconv(ic, &ptr1, &inc, &ptr2, &ouc); if (sz == -1) { perror("Iconv"); } write(door_out, ptr2p, ptr2 - ptr2p); free(ptr2p); iconv_close(ic); } } } else { if (!running_door) { flush = 1; } } } } } } else { if (raw) { ttySetRaw(STDIN_FILENO, &oldit); ttySetRaw(STDOUT_FILENO, &oldot); } sa.sa_handler = doorchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART | SA_SIGINFO; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } pid = fork(); if (pid < 0) { return; } else if (pid == 0) { if (cwd != NULL) { chdir(cwd); } dup2(bbs_stderr, 2); execvp(cmd, argv); } else { while(running_door) { sleep(1); } } if (raw) { tcsetattr(STDIN_FILENO, TCSANOW, &oldit); tcsetattr(STDOUT_FILENO, TCSANOW, &oldot); } } } else { if (!sshBBS) { snprintf(buffer, 1024, "%s", cmd); for (i=1;argv[i] != NULL; i++) { snprintf(&buffer[strlen(buffer)], 1024 - strlen(buffer), " %s", argv[i]); } if (cwd != NULL) { chdir(cwd); } system(buffer); if (cwd != NULL) { chdir(conf.bbs_path); } } else { s_printf(get_string(51)); } } timeoutpaused = 0; }