This repository has been archived by the owner on Apr 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]
- Loading branch information
Showing
11 changed files
with
1,660 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
cygtermd.exe: main.c sel.c telnet.c pty.c malloc.c | ||
gcc -o cygtermd.exe main.c sel.c telnet.c pty.c malloc.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
This directory contains 'cygtermd', a small and specialist Telnet | ||
server designed to act as middleware between PuTTY and a Cygwin shell | ||
session running on the same machine, so that PuTTY can act as an | ||
xterm-alike for Cygwin. | ||
|
||
To install it, you must compile it from source using Cygwin gcc, | ||
install it in Cygwin's /bin, and configure PuTTY to use it as a local | ||
proxy process. For detailed instructions, see the PuTTY Wishlist page | ||
at | ||
|
||
http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/cygwin-terminal-window.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* malloc.c: implementation of malloc.h | ||
*/ | ||
|
||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#include "malloc.h" | ||
|
||
extern void fatal(const char *, ...); | ||
|
||
void *smalloc(size_t size) { | ||
void *p; | ||
p = malloc(size); | ||
if (!p) { | ||
fatal("out of memory"); | ||
} | ||
return p; | ||
} | ||
|
||
void sfree(void *p) { | ||
if (p) { | ||
free(p); | ||
} | ||
} | ||
|
||
void *srealloc(void *p, size_t size) { | ||
void *q; | ||
if (p) { | ||
q = realloc(p, size); | ||
} else { | ||
q = malloc(size); | ||
} | ||
if (!q) | ||
fatal("out of memory"); | ||
return q; | ||
} | ||
|
||
char *dupstr(const char *s) { | ||
char *r = smalloc(1+strlen(s)); | ||
strcpy(r,s); | ||
return r; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* malloc.h: safe wrappers around malloc, realloc, free, strdup | ||
*/ | ||
|
||
#ifndef UMLWRAP_MALLOC_H | ||
#define UMLWRAP_MALLOC_H | ||
|
||
#include <stddef.h> | ||
|
||
/* | ||
* smalloc should guarantee to return a useful pointer - Halibut | ||
* can do nothing except die when it's out of memory anyway. | ||
*/ | ||
void *smalloc(size_t size); | ||
|
||
/* | ||
* srealloc should guaranteeably be able to realloc NULL | ||
*/ | ||
void *srealloc(void *p, size_t size); | ||
|
||
/* | ||
* sfree should guaranteeably deal gracefully with freeing NULL | ||
*/ | ||
void sfree(void *p); | ||
|
||
/* | ||
* dupstr is like strdup, but with the never-return-NULL property | ||
* of smalloc (and also reliably defined in all environments :-) | ||
*/ | ||
char *dupstr(const char *s); | ||
|
||
/* | ||
* snew allocates one instance of a given type, and casts the | ||
* result so as to type-check that you're assigning it to the | ||
* right kind of pointer. Protects against allocation bugs | ||
* involving allocating the wrong size of thing. | ||
*/ | ||
#define snew(type) \ | ||
( (type *) smalloc (sizeof (type)) ) | ||
|
||
/* | ||
* snewn allocates n instances of a given type, for arrays. | ||
*/ | ||
#define snewn(number, type) \ | ||
( (type *) smalloc ((number) * sizeof (type)) ) | ||
|
||
/* | ||
* sresize wraps realloc so that you specify the new number of | ||
* elements and the type of the element, with the same type- | ||
* checking advantages. Also type-checks the input pointer. | ||
*/ | ||
#define sresize(array, number, type) \ | ||
( (void)sizeof((array)-(type *)0), \ | ||
(type *) srealloc ((array), (number) * sizeof (type)) ) | ||
|
||
#endif /* UMLWRAP_MALLOC_H */ |
Oops, something went wrong.