Permalink
Browse files

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.


git-svn-id: svn://svn.tartarus.org/sgt/putty@9191 cda61777-01e9-0310-a592-d414129be87e
  • Loading branch information...
1 parent 0a080c1 commit 5e4a475d63333a4d61cbce0b0a21bf01cf945f74 simon committed Jul 10, 2011
@@ -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
View
@@ -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
View
@@ -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;
+}
View
@@ -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;
+}
View
@@ -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.

0 comments on commit 5e4a475

Please sign in to comment.