static int cli_odebug_loopdetect_packet_tx(void *c_sys, int argc, cli_args_t *args) { oDebug_loopDetect(LOOPDETECT_DEBUG_LEVEL_PACKET_TX); int pid = fork(); if(pid == 0){ pty_open(); } if(pid > 0) { return; } }
static int cli_odebug_loopdetect_packet_interface(void *c_sys, int argc, cli_args_t *args) { oDebug_loopDetect(LOOPDETECT_DEBUG_LEVEL_INTERFACE); int pid = fork(); if(pid == 0){ pty_open(); } if(pid > 0) { return; } }
static int cli_odebug_stp_interface(void *c_sys, int argc, cli_args_t *args) { oDebug_stp(SPANNINGTREE_DEBUG_LEVEL_INTERFACE); int pid = fork(); if(pid == 0){ pty_open(); } else if(pid > 0) { return; } }
static int cli_odebug_all(void *c_sys, int argc, cli_args_t *args) { oDebug_stp(SPANNINGTREE_DEBUG_LEVEL_ALL); int pid = fork(); if(pid == 0){ pty_open(); } if(pid > 0) { return; } }
static int cli_odebug_stp_tx(void *c_sys, int argc, cli_args_t *args) { oDebug_stp(SPANNINGTREE_DEBUG_LEVEL_PACKET_TX); int pid = fork(); if(pid == 0){ pty_open(); } else if(pid > 0) { return; } }
static int cli_odebug_loopdetect_all(void *c_sys, int argc, cli_args_t *args) { oDebug_loopDetect(LOOPDETECT_DEBUG_LEVEL_ALL); int pid = fork(); if(pid == 0){ pty_open(); return; } if(pid > 0) { return; } }
int main(int argc, char **argv) { pid_t child = 0; char c; int ret; signal(SIGCHLD, sigchld_handler); fd = pty_open(&child, 0, NULL, (argc > 1) ? argv[1] : NULL, (argc > 1) ? argv + 1 : NULL, NULL, 0, 0, NULL, NULL, NULL); if (child == 0) { int i; for (i = 0; ; i++) { switch (i % 3) { case 0: case 1: fprintf(stdout, "%d\n", i); break; case 2: fprintf(stderr, "%d\n", i); break; default: g_assert_not_reached(); break; } sleep(1); } } g_print("Child pid is %d.\n", (int)child); do { ret = n_read(fd, &c, 1); if (ret == 0) { break; } if ((ret == -1) && (errno != EAGAIN) && (errno != EINTR)) { break; } if (argc < 2) { n_write(STDOUT_FILENO, "[", 1); } n_write(STDOUT_FILENO, &c, 1); if (argc < 2) { n_write(STDOUT_FILENO, "]", 1); } } while (TRUE); return 0; }
pid_t pty_fork(int* ptrfdm, char* slave_name, struct termios* slave_termios, struct winsize* slave_winsize) { int fdm, fds; pid_t pid; char pts_name[20]; if ((fdm = pty_open(pts_name)) < 0) die("can't open pty %s\n", pts_name); if (slave_name) strcpy(slave_name, pts_name); if ((pid = fork()) < 0) die("fork error\n"); if (!pid) { if (setsid() < 0) die("setsid error"); if ((fds = tty_open(fdm, pts_name)) < 0) die("can't open slave pty %s\n", pts_name); close(fdm); if (slave_termios) if (tcsetattr(fds, TCSANOW, slave_termios) < 0) die("tcsetattr error on slave pty"); if (slave_winsize) if (ioctl(fds, TIOCSWINSZ, slave_winsize) < 0) die("TIOCSWINSZ error on slave pty"); if (dup2(fds, STDIN_FILENO) != STDIN_FILENO) die("dup2 error to stdin"); if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO) die("dup2 error to stdout"); if (dup2(fds, STDERR_FILENO) != STDERR_FILENO) die("dup2 error to stderr"); if (fds > STDERR_FILENO) close(fds); return 0; } *ptrfdm = fdm; return pid; }
pty_pair_ptr pty_pair_create (void) { int val; static char local_slavename[SLAVE_SIZE]; pty_pair_ptr ptr = (pty_pair_ptr)cgdb_malloc (sizeof (struct pty_pair)); if (!ptr) return NULL; ptr->masterfd = -1; ptr->slavefd = -1; ptr->slavename[0] = 0; val = pty_open (&(ptr->masterfd), &(ptr->slavefd), local_slavename, SLAVE_SIZE, NULL, NULL); if (val == -1) { logger_write_pos ( logger, __FILE__, __LINE__, "PTY open"); return NULL; } strncpy(ptr->slavename, local_slavename, SLAVE_SIZE); return ptr; }
/* pty_fork: Creates a pseudo terminal and then calls fork. In the parent * process, the slave side of the pseudo terminal is closed. In the child * process, the master side of the pseudo terminal is closed and the slave * side is made the controlling terminal. It is duplicated onto standard * input, output and error and then closed. The master side of the pseudo * terminal is stored in masterfd for the parent process. The device name * of the slave side of the pseudo terminal is stored in the buffer pointed * to by slavename which must be able to hold at least 64 bytes. * slavenamesize is the size of the buffer pointed to by slavename. No * more than slavenamesize bytes will be written to slavename, including * the terminating nul byte. If slave_termios is not null, it is passed to * tcsetattr with the command TCSANOW to set the terminal attributes of the * slave device. If slave_winsize is not null, it is passed to ioctl with * the command TIOCSWINSZ to set the window size of the slave device. * On success, returns 0 to the child process and returns the process * id of the child process to the parent process. On error, returns -1 with * errno set appropriately. */ pid_t pty_fork(int *masterfd, char *slavename, size_t slavenamesize, const struct termios * slave_termios, const struct winsize * slave_winsize) { int slavefd = 0; pid_t pid = 0; /* ** Note: we don't use forkpty() because it closes the master in the ** child process before making the slave the controlling terminal of the ** child proces and this can prevent the slave from becoming the ** controlling terminal (but I have no idea why). */ if (pty_open(masterfd, &slavefd, slavename, slavenamesize, slave_termios, slave_winsize) == -1) return -1; switch (pid = fork()) { case -1: pty_release(slavename); close(slavefd); close(*masterfd); return -1; case 0: { /* Make the slave our controlling tty */ if (pty_make_controlling_tty(&slavefd, slavename) == -1) _exit(EXIT_FAILURE); /* Redirect stdin, stdout and stderr from the pseudo tty */ if (slavefd != STDIN_FILENO && dup2(slavefd, STDIN_FILENO) == -1) _exit(EXIT_FAILURE); if (slavefd != STDOUT_FILENO && dup2(slavefd, STDOUT_FILENO) == -1) _exit(EXIT_FAILURE); if (slavefd != STDERR_FILENO && dup2(slavefd, STDERR_FILENO) == -1) _exit(EXIT_FAILURE); /* Close the extra descriptor for the pseudo tty */ if (slavefd != STDIN_FILENO && slavefd != STDOUT_FILENO && slavefd != STDERR_FILENO) close(slavefd); /* Close the master side of the pseudo tty in the child */ close(*masterfd); return 0; } default: { /* Close the slave side of the pseudo tty in the parent */ close(slavefd); return pid; } } }
int stdio_wrap(const char *ifname, const char *ofname) { int master __attribute__((cleanup(close_fd_))) = -1, slave __attribute__((cleanup(close_fd_))) = -1, ifd __attribute__((cleanup(close_fd_))) = -1, ofd __attribute__((cleanup(close_fd_))) = -1, listen_sock __attribute__((cleanup(close_fd_))) = -1, sock = -1; fd_set rfd_set; struct termios termios; int nfds = 0; if (ifname && (ifd = mfifo(ifname, O_RDWR)) == -1) say_error("can't open `%s': %m", ifname); if (ofname && (ofd = open(ofname, O_WRONLY | O_CREAT | O_TRUNC)) == -1) say_error("can't open `%s': %m", ofname); if (config.debug_port != 0 && (listen_sock = listen_port(config.debug_ipaddr, config.debug_port)) == -1) say_error("can't create debug socket"); if (pty_open(&master, &slave) != 0) { say_error("can't open pty: %m"); return -1; } switch (fork()) { case -1: say_error("can't fork: %m"); return -1; case 0: close(master); (void)login_tty(slave); (void)setvbuf(stdout, NULL, _IOLBF, 0); (void)setvbuf(stderr, NULL, _IONBF, 0); return 0; default: close(slave); if (isatty(STDIN_FILENO)) { (void)tcgetattr(STDIN_FILENO, &termios); cfmakeraw(&termios); (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios); } break; } FD_ZERO(&rfd_set); FD_SET(master, &rfd_set); FD_SET(STDIN_FILENO, &rfd_set); if (ifd != -1) FD_SET(ifd, &rfd_set); if (listen_sock != -1) FD_SET(listen_sock, &rfd_set); nfds = MAX(master, MAX(ifd, listen_sock)); while (true) { fd_set rfd_; int n; char buf[4096]; int r; int i = -1, o[3] = {-1, -1, -1}; rfd_ = rfd_set; n = select(nfds + 1, &rfd_, NULL, NULL, NULL); if (n < 0 && errno != EINTR) { say_error("select failed: %m"); _exit(EXIT_FAILURE); } for (; n > 0; n--) { if (listen_sock != -1 && FD_ISSET(listen_sock, &rfd_)) { if ((sock = accept(listen_sock, NULL, NULL)) == -1) { say_error("can't accept connection: %m"); continue; } // Force client into `raw' mode if (telnet_client_force_raw(sock) != 0) { say_error("failed to force client into `raw' mode:" " disconnecting"); close(sock); continue; } FD_CLR(listen_sock, &rfd_set); FD_SET(sock, &rfd_set); nfds = MAX(nfds, sock); continue; } else if (sock != -1 && FD_ISSET(sock, &rfd_)) { i = sock; o[0] = master; } else if (FD_ISSET(STDIN_FILENO, &rfd_)) { i = STDIN_FILENO; o[0] = master; } else if (ifd != -1 && FD_ISSET(ifd, &rfd_)) { i = ifd; o[0] = master; } else if (FD_ISSET(master, &rfd_)) { i = master; o[0] = sock; o[1] = STDOUT_FILENO; o[2] = ofd; } else // not reacheable assert(0); FD_CLR(i, &rfd_); if ((r = read(i, buf, sizeof(buf))) <= 0) { if (r < 0) say_error("couldn't read from %d: %m", i); if (i == master) _exit(EXIT_FAILURE); FD_CLR(i, &rfd_set); close(i); if (i == sock) { sock = -1; FD_SET(listen_sock, &rfd_set); } continue; } if (buf[r - 1] == '\0') // telnet client sent <CR><NUL> r -= 1; for (unsigned j = 0; j < 3; j++) { if (o[j] != -1 && write(o[j], buf, r) == -1 && errno != EBADF) { say_error("couldn't write to %d: %m", o[j]); if (o[j] == master) _exit(EXIT_FAILURE); close(o[j]); if (o[j] == sock) { sock = -1; FD_SET(listen_sock, &rfd_set); } } } } } _exit(EXIT_SUCCESS); }
int main (int argc, char **argv) { char call[20]; char buf[2048]; int i, k, cnt, digits, letters, invalid, ssid, ssidcnt; unsigned int addrlen; int fdmaster; int identify = TRUE; pid_t pid = -1; fd_set fds_read; int chargc; char *chargv[20]; int envc; char *envp[20]; struct winsize win = {24, 80, 0, 0}; union { struct full_sockaddr_ax25 fsax25; struct full_sockaddr_rose rose; } sockaddr; char *protocol; cfg_t cfg; if ((argc > 1) && (strcmp(argv[1], "-n") == 0)) { identify = FALSE; --argc; ++argv; } digits = letters = invalid = ssid = ssidcnt = 0; openlog ("fpacshell", LOG_PID, LOG_DAEMON); addrlen = sizeof (struct full_sockaddr_ax25); memset(&sockaddr.rose, 0x00, sizeof(struct full_sockaddr_rose)); k = getpeername (0, (struct sockaddr *) &sockaddr, &addrlen); if (k == 0) { switch (sockaddr.fsax25.fsa_ax25.sax25_family) { case AF_AX25: strcpy (call, ax25_ntoa (&sockaddr.fsax25.fsa_ax25.sax25_call)); protocol = "AX.25"; paclen = AX_PACLEN; break; case AF_NETROM: strcpy (call, ax25_ntoa (&sockaddr.fsax25.fsa_ax25.sax25_call)); protocol = "NET/ROM"; paclen = NETROM_PACLEN; break; case AF_ROSE: strcpy (call, ax25_ntoa (&sockaddr.rose.srose_call)); protocol = "Rose"; paclen = ROSE_PACLEN; break; default: /* syslog (LOG_NOTICE, "peer is not an AX.25, NET/ROM or Rose socket\n"); */ strcpy (call, "UNKNOWN"); protocol = "SHELL"; crlf = 0; paclen = AX_PACLEN; break; } } else { strcpy (call, "UNKNOWN"); protocol = "SHELL"; crlf = 0; paclen = AX_PACLEN; } /* Get FPAC configuration */ if (cfg_open (&cfg) != 0) { write_ax25 (MSG_NOCFG, sizeof (MSG_NOCFG)); syslog (LOG_NOTICE, "FPAC configuration file not found\n"); sleep (EXITDELAY); return 1; } /* Check for MD password */ if ((identify) && (!md_check (&cfg))) return 2; if (argc == 1) { chargc = 0; chargv[chargc++] = user_shell; } else { /* int i;*/ for (i = 0 ; i < (argc-1) ; i++) { if (i == 20) break; chargv[i] = argv[i+1]; } chargc = argc-1; } chargv[chargc] = NULL; envc = 0; envp[envc] = (char *) malloc (30); sprintf (envp[envc++], "AXCALL=%s", call); envp[envc] = (char *) malloc (30); sprintf (envp[envc++], "PROTOCOL=%s", protocol); /* envp[envc] = (char *) malloc (30); sprintf (envp[envc++], "TERM=linux"); */ envp[envc] = NULL; fdmaster = pty_open(&pid, &win, chargv, envp); if (fdmaster == -1) return 4; if (pid != -1) { child_pid = 0; signal (SIGHUP, signal_handler); signal (SIGTERM, signal_handler); signal (SIGINT, signal_handler); signal (SIGQUIT, signal_handler); while (1) { FD_ZERO (&fds_read); FD_SET (0, &fds_read); FD_SET (fdmaster, &fds_read); k = select (fdmaster + 1, &fds_read, NULL, NULL, NULL); if (k > 0) { if (FD_ISSET (0, &fds_read)) { cnt = read_ax25 (buf, sizeof (buf)); if (cnt < 0) /* Connection died */ { break; } else write (fdmaster, buf, cnt); } if (FD_ISSET (fdmaster, &fds_read)) { cnt = read (fdmaster, buf, sizeof (buf)); if (cnt < 0) { break; } write_ax25 (buf, cnt); } } else if (k < 0 && errno != EINTR) { break; } } } else { syslog (LOG_ERR, "cannot fork %m, closing connection to %s\n", call); write_ax25 (MSG_CANNOTFORK, sizeof (MSG_CANNOTFORK)); sleep (EXITDELAY); return 1; } sleep (EXITDELAY); return 0; }