mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-02 03:52:49 -05:00
Add a directory 'contrib/cygtermd', containing the source code for my
hacky helper program to let PuTTY act as a local pterm-oid on Cygwin-enabled Windows systems. [originally from svn r9191]
This commit is contained in:
174
contrib/cygtermd/main.c
Normal file
174
contrib/cygtermd/main.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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, "FIXME: ");
|
||||
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;
|
||||
pid_t pid = 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;
|
||||
}
|
Reference in New Issue
Block a user