]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - contrib/cygtermd/main.c
Dedicated routines for poly1305 arithmetic.
[PuTTY.git] / contrib / cygtermd / main.c
1 /*
2  * Main program.
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stddef.h>
8 #include <stdarg.h>
9 #include <signal.h>
10 #include <string.h>
11 #include <errno.h>
12
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16
17 #include "sel.h"
18 #include "pty.h"
19 #include "telnet.h"
20
21 int signalpipe[2];
22
23 sel *asel;
24 sel_rfd *netr, *ptyr, *sigr;
25 int ptyfd;
26 sel_wfd *netw, *ptyw;
27 Telnet telnet;
28
29 #define BUF 65536
30
31 void sigchld(int signum)
32 {
33     write(signalpipe[1], "C", 1);
34 }
35
36 void fatal(const char *fmt, ...)
37 {
38     va_list ap;
39     fprintf(stderr, "FIXME: ");
40     va_start(ap, fmt);
41     vfprintf(stderr, fmt, ap);
42     va_end(ap);
43     fprintf(stderr, "\n");
44     exit(1);
45 }
46
47 void net_readdata(sel_rfd *rfd, void *data, size_t len)
48 {
49     if (len == 0)
50         exit(0);                       /* EOF on network - client went away */
51     telnet_from_net(telnet, data, len);
52     if (sel_write(netw, NULL, 0) > BUF)
53         sel_rfd_freeze(ptyr);
54     if (sel_write(ptyw, NULL, 0) > BUF)
55         sel_rfd_freeze(netr);
56 }
57
58 void net_readerr(sel_rfd *rfd, int error)
59 {
60     fprintf(stderr, "standard input: read: %s\n", strerror(errno));
61     exit(1);
62 }
63
64 void net_written(sel_wfd *wfd, size_t bufsize)
65 {
66     if (bufsize < BUF)
67         sel_rfd_unfreeze(ptyr);
68 }
69
70 void net_writeerr(sel_wfd *wfd, int error)
71 {
72     fprintf(stderr, "standard input: write: %s\n", strerror(errno));
73     exit(1);
74 }
75
76 void pty_readdata(sel_rfd *rfd, void *data, size_t len)
77 {
78     if (len == 0)
79         exit(0);                       /* EOF on pty */
80     telnet_from_pty(telnet, data, len);
81     if (sel_write(netw, NULL, 0) > BUF)
82         sel_rfd_freeze(ptyr);
83     if (sel_write(ptyw, NULL, 0) > BUF)
84         sel_rfd_freeze(netr);
85 }
86
87 void pty_readerr(sel_rfd *rfd, int error)
88 {
89     if (error == EIO)                  /* means EOF, on a pty */
90         exit(0);
91     fprintf(stderr, "pty: read: %s\n", strerror(errno));
92     exit(1);
93 }
94
95 void pty_written(sel_wfd *wfd, size_t bufsize)
96 {
97     if (bufsize < BUF)
98         sel_rfd_unfreeze(netr);
99 }
100
101 void pty_writeerr(sel_wfd *wfd, int error)
102 {
103     fprintf(stderr, "pty: write: %s\n", strerror(errno));
104     exit(1);
105 }
106
107 void sig_readdata(sel_rfd *rfd, void *data, size_t len)
108 {
109     char *p = data;
110
111     while (len > 0) {
112         if (*p == 'C') {
113             int status;
114             pid_t pid = waitpid(-1, &status, WNOHANG);
115             if (WIFEXITED(status) || WIFSIGNALED(status))
116                 exit(0);               /* child process vanished */
117         }
118     }
119 }
120
121 void sig_readerr(sel_rfd *rfd, int error)
122 {
123     fprintf(stderr, "signal pipe: read: %s\n", strerror(errno));
124     exit(1);
125 }
126
127 int main(int argc, char **argv)
128 {
129     int ret;
130     int shell_started = 0;
131     char *directory = NULL;
132     char **program_args = NULL;
133
134     if (argc > 1 && argv[1][0]) {
135         directory = argv[1];
136         argc--, argv++;
137     }
138     if (argc > 1) {
139         program_args = argv + 1;
140     }
141
142     pty_preinit();
143
144     asel = sel_new(NULL);
145     netr = sel_rfd_add(asel, 0, net_readdata, net_readerr, NULL);
146     netw = sel_wfd_add(asel, 1, net_written, net_writeerr, NULL);
147     ptyr = sel_rfd_add(asel, -1, pty_readdata, pty_readerr, NULL);
148     ptyw = sel_wfd_add(asel, -1, pty_written, pty_writeerr, NULL);
149
150     telnet = telnet_new(netw, ptyw);
151
152     if (pipe(signalpipe) < 0) {
153         perror("pipe");
154         return 1;
155     }
156     sigr = sel_rfd_add(asel, signalpipe[0], sig_readdata,
157                        sig_readerr, NULL);
158
159     signal(SIGCHLD, sigchld);
160
161     do {
162         struct shell_data shdata;
163
164         ret = sel_iterate(asel, -1);
165         if (!shell_started && telnet_shell_ok(telnet, &shdata)) {
166             ptyfd = run_program_in_pty(&shdata, directory, program_args);
167             sel_rfd_setfd(ptyr, ptyfd);
168             sel_wfd_setfd(ptyw, ptyfd);
169             shell_started = 1;
170         }
171     } while (ret == 0);
172
173     return 0;
174 }