Deal with the appalling mouse pointer colours. (Why doesn't GTK let
[u/mdw/putty] / unix / pty.c
CommitLineData
054d8535 1#define _XOPEN_SOURCE
2#include <features.h>
3
1709795f 4#include <stdio.h>
5#include <stdlib.h>
054d8535 6#include <string.h>
7#include <unistd.h>
8#include <fcntl.h>
1709795f 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
054d8535 19int pty_master_fd;
20
1709795f 21static void pty_size(void);
22
23static 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 */
36static char *pty_init(char *host, int port, char **realhost, int nodelay)
37{
054d8535 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
1709795f 106 return NULL;
107}
108
109/*
110 * Called to send data down the pty.
111 */
112static int pty_send(char *buf, int len)
113{
054d8535 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 }
1709795f 123 return 0;
124}
125
126/*
127 * Called to query the current socket sendability status.
128 */
129static int pty_sendbuffer(void)
130{
131 return 0;
132}
133
134/*
135 * Called to set the size of the window
136 */
137static void pty_size(void)
138{
139 /* FIXME: will need to do TIOCSWINSZ or whatever. */
140 return;
141}
142
143/*
144 * Send special codes.
145 */
146static void pty_special(Telnet_Special code)
147{
148 /* Do nothing! */
149 return;
150}
151
152static Socket pty_socket(void)
153{
154 return NULL; /* shouldn't ever be needed */
155}
156
157static int pty_sendok(void)
158{
159 return 1;
160}
161
162static void pty_unthrottle(int backlog)
163{
164 /* do nothing */
165}
166
167static int pty_ldisc(int option)
168{
169 return 0; /* neither editing nor echoing */
170}
171
172static int pty_exitcode(void)
173{
174 /* Shouldn't ever be required */
175 return 0;
176}
177
178Backend 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};