123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- /*
- * Main program.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <stddef.h>
- #include <stdarg.h>
- #include <signal.h>
- #include <string.h>
- #include <errno.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include "sel.h"
- #include "pty.h"
- #include "telnet.h"
- int signalpipe[2];
- sel *asel;
- sel_rfd *netr, *ptyr, *sigr;
- int ptyfd;
- sel_wfd *netw, *ptyw;
- Telnet *telnet;
- #define BUF 65536
- void sigchld(int signum)
- {
- write(signalpipe[1], "C", 1);
- }
- void fatal(const char *fmt, ...)
- {
- va_list ap;
- fprintf(stderr, "cygtermd: ");
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fprintf(stderr, "\n");
- exit(1);
- }
- void net_readdata(sel_rfd *rfd, void *data, size_t len)
- {
- if (len == 0)
- exit(0); /* EOF on network - client went away */
- telnet_from_net(telnet, data, len);
- if (sel_write(netw, NULL, 0) > BUF)
- sel_rfd_freeze(ptyr);
- if (sel_write(ptyw, NULL, 0) > BUF)
- sel_rfd_freeze(netr);
- }
- void net_readerr(sel_rfd *rfd, int error)
- {
- fprintf(stderr, "standard input: read: %s\n", strerror(errno));
- exit(1);
- }
- void net_written(sel_wfd *wfd, size_t bufsize)
- {
- if (bufsize < BUF)
- sel_rfd_unfreeze(ptyr);
- }
- void net_writeerr(sel_wfd *wfd, int error)
- {
- fprintf(stderr, "standard input: write: %s\n", strerror(errno));
- exit(1);
- }
- void pty_readdata(sel_rfd *rfd, void *data, size_t len)
- {
- if (len == 0)
- exit(0); /* EOF on pty */
- telnet_from_pty(telnet, data, len);
- if (sel_write(netw, NULL, 0) > BUF)
- sel_rfd_freeze(ptyr);
- if (sel_write(ptyw, NULL, 0) > BUF)
- sel_rfd_freeze(netr);
- }
- void pty_readerr(sel_rfd *rfd, int error)
- {
- if (error == EIO) /* means EOF, on a pty */
- exit(0);
- fprintf(stderr, "pty: read: %s\n", strerror(errno));
- exit(1);
- }
- void pty_written(sel_wfd *wfd, size_t bufsize)
- {
- if (bufsize < BUF)
- sel_rfd_unfreeze(netr);
- }
- void pty_writeerr(sel_wfd *wfd, int error)
- {
- fprintf(stderr, "pty: write: %s\n", strerror(errno));
- exit(1);
- }
- void sig_readdata(sel_rfd *rfd, void *data, size_t len)
- {
- char *p = data;
- while (len > 0) {
- if (*p == 'C') {
- int status;
- waitpid(-1, &status, WNOHANG);
- if (WIFEXITED(status) || WIFSIGNALED(status))
- exit(0); /* child process vanished */
- }
- }
- }
- void sig_readerr(sel_rfd *rfd, int error)
- {
- fprintf(stderr, "signal pipe: read: %s\n", strerror(errno));
- exit(1);
- }
- int main(int argc, char **argv)
- {
- int ret;
- int shell_started = 0;
- char *directory = NULL;
- char **program_args = NULL;
- if (argc > 1 && argv[1][0]) {
- directory = argv[1];
- argc--, argv++;
- }
- if (argc > 1) {
- program_args = argv + 1;
- }
- pty_preinit();
- asel = sel_new(NULL);
- netr = sel_rfd_add(asel, 0, net_readdata, net_readerr, NULL);
- netw = sel_wfd_add(asel, 1, net_written, net_writeerr, NULL);
- ptyr = sel_rfd_add(asel, -1, pty_readdata, pty_readerr, NULL);
- ptyw = sel_wfd_add(asel, -1, pty_written, pty_writeerr, NULL);
- telnet = telnet_new(netw, ptyw);
- if (pipe(signalpipe) < 0) {
- perror("pipe");
- return 1;
- }
- sigr = sel_rfd_add(asel, signalpipe[0], sig_readdata,
- sig_readerr, NULL);
- signal(SIGCHLD, sigchld);
- do {
- struct shell_data shdata;
- ret = sel_iterate(asel, -1);
- if (!shell_started && telnet_shell_ok(telnet, &shdata)) {
- ptyfd = run_program_in_pty(&shdata, directory, program_args);
- sel_rfd_setfd(ptyr, ptyfd);
- sel_wfd_setfd(ptyw, ptyfd);
- shell_started = 1;
- }
- } while (ret == 0);
- return 0;
- }
|