]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unix/pty.c
56d7d895d5e8fdd6b56166f54d31afd8bc16d0bd
[PuTTY.git] / unix / pty.c
1 #define _XOPEN_SOURCE
2 #include <features.h>
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9
10 #include "putty.h"
11
12 #ifndef FALSE
13 #define FALSE 0
14 #endif
15 #ifndef TRUE
16 #define TRUE 1
17 #endif
18
19 int pty_master_fd;
20
21 static void pty_size(void);
22
23 static void c_write(char *buf, int len)
24 {
25     from_backend(0, buf, len);
26 }
27
28 /*
29  * Called to set up the pty.
30  * 
31  * Returns an error message, or NULL on success.
32  *
33  * Also places the canonical host name into `realhost'. It must be
34  * freed by the caller.
35  */
36 static char *pty_init(char *host, int port, char **realhost, int nodelay)
37 {
38     int slavefd;
39     char name[FILENAME_MAX];
40     pid_t pid;
41
42     pty_master_fd = open("/dev/ptmx", O_RDWR);
43
44     if (pty_master_fd < 0) {
45         perror("/dev/ptmx: open");
46         exit(1);
47     }
48
49     if (grantpt(pty_master_fd) < 0) {
50         perror("grantpt");
51         exit(1);
52     }
53     
54     if (unlockpt(pty_master_fd) < 0) {
55         perror("unlockpt");
56         exit(1);
57     }
58
59     name[FILENAME_MAX-1] = '\0';
60     strncpy(name, ptsname(pty_master_fd), FILENAME_MAX-1);
61
62     slavefd = open(name, O_RDWR);
63     if (slavefd < 0) {
64         perror("slave pty: open");
65         return 1;
66     }
67
68     /*
69      * Fork and execute the command.
70      */
71     pid = fork();
72     if (pid < 0) {
73         perror("fork");
74         return 1;
75     }
76
77     if (pid == 0) {
78         int i;
79         /*
80          * We are the child.
81          */
82         close(pty_master_fd);
83         close(0);
84         close(1);
85         close(2);
86         fcntl(slavefd, F_SETFD, 0);    /* don't close on exec */
87         dup2(slavefd, 0);
88         dup2(slavefd, 1);
89         dup2(slavefd, 2);
90         setsid();
91         setpgrp();
92         tcsetpgrp(0, getpgrp());
93         /* Close everything _else_, for tidiness. */
94         for (i = 3; i < 1024; i++)
95             close(i);
96         execl(getenv("SHELL"), getenv("SHELL"), NULL);
97         /*
98          * If we're here, exec has gone badly foom.
99          */
100         perror("exec");
101         exit(127);
102     } else {
103         close(slavefd);
104     }
105
106     return NULL;
107 }
108
109 /*
110  * Called to send data down the pty.
111  */
112 static int pty_send(char *buf, int len)
113 {
114     while (len > 0) {
115         int ret = write(pty_master_fd, buf, len);
116         if (ret < 0) {
117             perror("write pty master");
118             exit(1);
119         }
120         buf += ret;
121         len -= ret;
122     }
123     return 0;
124 }
125
126 /*
127  * Called to query the current socket sendability status.
128  */
129 static int pty_sendbuffer(void)
130 {
131     return 0;
132 }
133
134 /*
135  * Called to set the size of the window
136  */
137 static void pty_size(void)
138 {
139     /* FIXME: will need to do TIOCSWINSZ or whatever. */
140     return;
141 }
142
143 /*
144  * Send special codes.
145  */
146 static void pty_special(Telnet_Special code)
147 {
148     /* Do nothing! */
149     return;
150 }
151
152 static Socket pty_socket(void)
153 {
154     return NULL;                       /* shouldn't ever be needed */
155 }
156
157 static int pty_sendok(void)
158 {
159     return 1;
160 }
161
162 static void pty_unthrottle(int backlog)
163 {
164     /* do nothing */
165 }
166
167 static int pty_ldisc(int option)
168 {
169     return 0;                          /* neither editing nor echoing */
170 }
171
172 static int pty_exitcode(void)
173 {
174     /* Shouldn't ever be required */
175     return 0;
176 }
177
178 Backend pty_backend = {
179     pty_init,
180     pty_send,
181     pty_sendbuffer,
182     pty_size,
183     pty_special,
184     pty_socket,
185     pty_exitcode,
186     pty_sendok,
187     pty_ldisc,
188     pty_unthrottle,
189     1
190 };