2011-07-10 14:22:32 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
Telnet *telnet;
|
2011-07-10 14:22:32 +00:00
|
|
|
|
|
|
|
#define BUF 65536
|
|
|
|
|
|
|
|
void sigchld(int signum)
|
|
|
|
{
|
|
|
|
write(signalpipe[1], "C", 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fatal(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
2018-10-06 10:55:56 +00:00
|
|
|
fprintf(stderr, "cygtermd: ");
|
2011-07-10 14:22:32 +00:00
|
|
|
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)
|
2019-09-08 19:29:00 +00:00
|
|
|
exit(0); /* EOF on network - client went away */
|
2011-07-10 14:22:32 +00:00
|
|
|
telnet_from_net(telnet, data, len);
|
|
|
|
if (sel_write(netw, NULL, 0) > BUF)
|
2019-09-08 19:29:00 +00:00
|
|
|
sel_rfd_freeze(ptyr);
|
2011-07-10 14:22:32 +00:00
|
|
|
if (sel_write(ptyw, NULL, 0) > BUF)
|
2019-09-08 19:29:00 +00:00
|
|
|
sel_rfd_freeze(netr);
|
2011-07-10 14:22:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2019-09-08 19:29:00 +00:00
|
|
|
sel_rfd_unfreeze(ptyr);
|
2011-07-10 14:22:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2019-09-08 19:29:00 +00:00
|
|
|
exit(0); /* EOF on pty */
|
2011-07-10 14:22:32 +00:00
|
|
|
telnet_from_pty(telnet, data, len);
|
|
|
|
if (sel_write(netw, NULL, 0) > BUF)
|
2019-09-08 19:29:00 +00:00
|
|
|
sel_rfd_freeze(ptyr);
|
2011-07-10 14:22:32 +00:00
|
|
|
if (sel_write(ptyw, NULL, 0) > BUF)
|
2019-09-08 19:29:00 +00:00
|
|
|
sel_rfd_freeze(netr);
|
2011-07-10 14:22:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pty_readerr(sel_rfd *rfd, int error)
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
if (error == EIO) /* means EOF, on a pty */
|
|
|
|
exit(0);
|
2011-07-10 14:22:32 +00:00
|
|
|
fprintf(stderr, "pty: read: %s\n", strerror(errno));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pty_written(sel_wfd *wfd, size_t bufsize)
|
|
|
|
{
|
|
|
|
if (bufsize < BUF)
|
2019-09-08 19:29:00 +00:00
|
|
|
sel_rfd_unfreeze(netr);
|
2011-07-10 14:22:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (*p == 'C') {
|
|
|
|
int status;
|
|
|
|
waitpid(-1, &status, WNOHANG);
|
|
|
|
if (WIFEXITED(status) || WIFSIGNALED(status))
|
|
|
|
exit(0); /* child process vanished */
|
|
|
|
}
|
2011-07-10 14:22:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2019-09-08 19:29:00 +00:00
|
|
|
perror("pipe");
|
|
|
|
return 1;
|
2011-07-10 14:22:32 +00:00
|
|
|
}
|
|
|
|
sigr = sel_rfd_add(asel, signalpipe[0], sig_readdata,
|
2019-09-08 19:29:00 +00:00
|
|
|
sig_readerr, NULL);
|
2011-07-10 14:22:32 +00:00
|
|
|
|
|
|
|
signal(SIGCHLD, sigchld);
|
|
|
|
|
|
|
|
do {
|
2019-09-08 19:29:00 +00:00
|
|
|
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;
|
|
|
|
}
|
2011-07-10 14:22:32 +00:00
|
|
|
} while (ret == 0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|