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