]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unix/uxpty.c
first pass
[PuTTY.git] / unix / uxpty.c
1 /*
2  * Pseudo-tty backend for pterm.
3  */
4
5 #define _GNU_SOURCE
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <signal.h>
12 #include <assert.h>
13 #include <fcntl.h>
14 #include <termios.h>
15 #include <grp.h>
16 #include <utmp.h>
17 #include <pwd.h>
18 #include <time.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/wait.h>
22 #include <sys/ioctl.h>
23 #include <errno.h>
24
25 #include "putty.h"
26 #include "tree234.h"
27
28 #ifndef OMIT_UTMP
29 #include <utmpx.h>
30 #endif
31
32 #ifndef FALSE
33 #define FALSE 0
34 #endif
35 #ifndef TRUE
36 #define TRUE 1
37 #endif
38
39 /* updwtmpx() needs the name of the wtmp file.  Try to find it. */
40 #ifndef WTMPX_FILE
41 #ifdef _PATH_WTMPX
42 #define WTMPX_FILE _PATH_WTMPX
43 #else
44 #define WTMPX_FILE "/var/log/wtmpx"
45 #endif
46 #endif
47
48 #ifndef LASTLOG_FILE
49 #ifdef _PATH_LASTLOG
50 #define LASTLOG_FILE _PATH_LASTLOG
51 #else
52 #define LASTLOG_FILE "/var/log/lastlog"
53 #endif
54 #endif
55
56 /*
57  * Set up a default for vaguely sane systems. The idea is that if
58  * OMIT_UTMP is not defined, then at least one of the symbols which
59  * enable particular forms of utmp processing should be, if only so
60  * that a link error can warn you that you should have defined
61  * OMIT_UTMP if you didn't want any. Currently HAVE_PUTUTLINE is
62  * the only such symbol.
63  */
64 #ifndef OMIT_UTMP
65 #if !defined HAVE_PUTUTLINE
66 #define HAVE_PUTUTLINE
67 #endif
68 #endif
69
70 typedef struct pty_tag *Pty;
71
72 /*
73  * The pty_signal_pipe, along with the SIGCHLD handler, must be
74  * process-global rather than session-specific.
75  */
76 static int pty_signal_pipe[2] = { -1, -1 };   /* obviously bogus initial val */
77
78 struct pty_tag {
79     Conf *conf;
80     int master_fd, slave_fd;
81     void *frontend;
82     char name[FILENAME_MAX];
83     pid_t child_pid;
84     int term_width, term_height;
85     int child_dead, finished;
86     int exit_code;
87     bufchain output_data;
88 };
89
90 /*
91  * We store our pty backends in a tree sorted by master fd, so that
92  * when we get an uxsel notification we know which backend instance
93  * is the owner of the pty that caused it.
94  */
95 static int pty_compare_by_fd(void *av, void *bv)
96 {
97     Pty a = (Pty)av;
98     Pty b = (Pty)bv;
99
100     if (a->master_fd < b->master_fd)
101         return -1;
102     else if (a->master_fd > b->master_fd)
103         return +1;
104     return 0;
105 }
106
107 static int pty_find_by_fd(void *av, void *bv)
108 {
109     int a = *(int *)av;
110     Pty b = (Pty)bv;
111
112     if (a < b->master_fd)
113         return -1;
114     else if (a > b->master_fd)
115         return +1;
116     return 0;
117 }
118
119 static tree234 *ptys_by_fd = NULL;
120
121 /*
122  * We also have a tree sorted by child pid, so that when we wait()
123  * in response to the signal we know which backend instance is the
124  * owner of the process that caused the signal.
125  */
126 static int pty_compare_by_pid(void *av, void *bv)
127 {
128     Pty a = (Pty)av;
129     Pty b = (Pty)bv;
130
131     if (a->child_pid < b->child_pid)
132         return -1;
133     else if (a->child_pid > b->child_pid)
134         return +1;
135     return 0;
136 }
137
138 static int pty_find_by_pid(void *av, void *bv)
139 {
140     pid_t a = *(pid_t *)av;
141     Pty b = (Pty)bv;
142
143     if (a < b->child_pid)
144         return -1;
145     else if (a > b->child_pid)
146         return +1;
147     return 0;
148 }
149
150 static tree234 *ptys_by_pid = NULL;
151
152 /*
153  * If we are using pty_pre_init(), it will need to have already
154  * allocated a pty structure, which we must then return from
155  * pty_init() rather than allocating a new one. Here we store that
156  * structure between allocation and use.
157  * 
158  * Note that although most of this module is entirely capable of
159  * handling multiple ptys in a single process, pty_pre_init() is
160  * fundamentally _dependent_ on there being at most one pty per
161  * process, so the normal static-data constraints don't apply.
162  * 
163  * Likewise, since utmp is only used via pty_pre_init, it too must
164  * be single-instance, so we can declare utmp-related variables
165  * here.
166  */
167 static Pty single_pty = NULL;
168
169 #ifndef OMIT_UTMP
170 static pid_t pty_utmp_helper_pid = -1;
171 static int pty_utmp_helper_pipe = -1;
172 static int pty_stamped_utmp;
173 static struct utmpx utmp_entry;
174 #endif
175
176 /*
177  * pty_argv is a grievous hack to allow a proper argv to be passed
178  * through from the Unix command line. Again, it doesn't really
179  * make sense outside a one-pty-per-process setup.
180  */
181 char **pty_argv;
182
183 char *pty_osx_envrestore_prefix;
184
185 static void pty_close(Pty pty);
186 static void pty_try_write(Pty pty);
187
188 #ifndef OMIT_UTMP
189 static void setup_utmp(char *ttyname, char *location)
190 {
191 #ifdef HAVE_LASTLOG
192     struct lastlog lastlog_entry;
193     FILE *lastlog;
194 #endif
195     struct passwd *pw;
196     struct timeval tv;
197
198     pw = getpwuid(getuid());
199     memset(&utmp_entry, 0, sizeof(utmp_entry));
200     utmp_entry.ut_type = USER_PROCESS;
201     utmp_entry.ut_pid = getpid();
202     strncpy(utmp_entry.ut_line, ttyname+5, lenof(utmp_entry.ut_line));
203     strncpy(utmp_entry.ut_id, ttyname+8, lenof(utmp_entry.ut_id));
204     strncpy(utmp_entry.ut_user, pw->pw_name, lenof(utmp_entry.ut_user));
205     strncpy(utmp_entry.ut_host, location, lenof(utmp_entry.ut_host));
206     /*
207      * Apparently there are some architectures where (struct
208      * utmpx).ut_tv is not essentially struct timeval (e.g. Linux
209      * amd64). Hence the temporary.
210      */
211     gettimeofday(&tv, NULL);
212     utmp_entry.ut_tv.tv_sec = tv.tv_sec;
213     utmp_entry.ut_tv.tv_usec = tv.tv_usec;
214
215     setutxent();
216     pututxline(&utmp_entry);
217     endutxent();
218
219     updwtmpx(WTMPX_FILE, &utmp_entry);
220
221 #ifdef HAVE_LASTLOG
222     memset(&lastlog_entry, 0, sizeof(lastlog_entry));
223     strncpy(lastlog_entry.ll_line, ttyname+5, lenof(lastlog_entry.ll_line));
224     strncpy(lastlog_entry.ll_host, location, lenof(lastlog_entry.ll_host));
225     time(&lastlog_entry.ll_time);
226     if ((lastlog = fopen(LASTLOG_FILE, "r+")) != NULL) {
227         fseek(lastlog, sizeof(lastlog_entry) * getuid(), SEEK_SET);
228         fwrite(&lastlog_entry, 1, sizeof(lastlog_entry), lastlog);
229         fclose(lastlog);
230     }
231 #endif
232
233     pty_stamped_utmp = 1;
234
235 }
236
237 static void cleanup_utmp(void)
238 {
239     struct timeval tv;
240
241     if (!pty_stamped_utmp)
242         return;
243
244     utmp_entry.ut_type = DEAD_PROCESS;
245     memset(utmp_entry.ut_user, 0, lenof(utmp_entry.ut_user));
246     gettimeofday(&tv, NULL);
247     utmp_entry.ut_tv.tv_sec = tv.tv_sec;
248     utmp_entry.ut_tv.tv_usec = tv.tv_usec;
249
250     updwtmpx(WTMPX_FILE, &utmp_entry);
251
252     memset(utmp_entry.ut_line, 0, lenof(utmp_entry.ut_line));
253     utmp_entry.ut_tv.tv_sec = 0;
254     utmp_entry.ut_tv.tv_usec = 0;
255
256     setutxent();
257     pututxline(&utmp_entry);
258     endutxent();
259
260     pty_stamped_utmp = 0;              /* ensure we never double-cleanup */
261 }
262 #endif
263
264 #ifndef NO_PTY_PRE_INIT
265 static void sigchld_handler(int signum)
266 {
267     if (write(pty_signal_pipe[1], "x", 1) <= 0)
268         /* not much we can do about it */;
269 }
270 #endif
271
272 #ifndef OMIT_UTMP
273 static void fatal_sig_handler(int signum)
274 {
275     putty_signal(signum, SIG_DFL);
276     cleanup_utmp();
277     raise(signum);
278 }
279 #endif
280
281 static int pty_open_slave(Pty pty)
282 {
283     if (pty->slave_fd < 0) {
284         pty->slave_fd = open(pty->name, O_RDWR);
285         cloexec(pty->slave_fd);
286     }
287
288     return pty->slave_fd;
289 }
290
291 static void pty_open_master(Pty pty)
292 {
293 #ifdef BSD_PTYS
294     const char chars1[] = "pqrstuvwxyz";
295     const char chars2[] = "0123456789abcdef";
296     const char *p1, *p2;
297     char master_name[20];
298     struct group *gp;
299
300     for (p1 = chars1; *p1; p1++)
301         for (p2 = chars2; *p2; p2++) {
302             sprintf(master_name, "/dev/pty%c%c", *p1, *p2);
303             pty->master_fd = open(master_name, O_RDWR);
304             if (pty->master_fd >= 0) {
305                 if (geteuid() == 0 ||
306                     access(master_name, R_OK | W_OK) == 0) {
307                     /*
308                      * We must also check at this point that we are
309                      * able to open the slave side of the pty. We
310                      * wouldn't want to allocate the wrong master,
311                      * get all the way down to forking, and _then_
312                      * find we're unable to open the slave.
313                      */
314                     strcpy(pty->name, master_name);
315                     pty->name[5] = 't'; /* /dev/ptyXX -> /dev/ttyXX */
316
317                     cloexec(pty->master_fd);
318
319                     if (pty_open_slave(pty) >= 0 &&
320                         access(pty->name, R_OK | W_OK) == 0)
321                         goto got_one;
322                     if (pty->slave_fd > 0)
323                         close(pty->slave_fd);
324                     pty->slave_fd = -1;
325                 }
326                 close(pty->master_fd);
327             }
328         }
329
330     /* If we get here, we couldn't get a tty at all. */
331     fprintf(stderr, "pterm: unable to open a pseudo-terminal device\n");
332     exit(1);
333
334     got_one:
335
336     /* We need to chown/chmod the /dev/ttyXX device. */
337     gp = getgrnam("tty");
338     chown(pty->name, getuid(), gp ? gp->gr_gid : -1);
339     chmod(pty->name, 0600);
340 #else
341
342     const int flags = O_RDWR
343 #ifdef O_NOCTTY
344         | O_NOCTTY
345 #endif
346         ;
347
348 #ifdef HAVE_POSIX_OPENPT
349 #ifdef SET_NONBLOCK_VIA_OPENPT
350     /*
351      * OS X, as of 10.10 at least, doesn't permit me to set O_NONBLOCK
352      * on pty master fds via the usual fcntl mechanism. Fortunately,
353      * it does let me work around this by adding O_NONBLOCK to the
354      * posix_openpt flags parameter, which isn't a documented use of
355      * the API but seems to work. So we'll do that for now.
356      */
357     pty->master_fd = posix_openpt(flags | O_NONBLOCK);
358 #else
359     pty->master_fd = posix_openpt(flags);
360 #endif
361
362     if (pty->master_fd < 0) {
363         perror("posix_openpt");
364         exit(1);
365     }
366 #else
367     pty->master_fd = open("/dev/ptmx", flags);
368
369     if (pty->master_fd < 0) {
370         perror("/dev/ptmx: open");
371         exit(1);
372     }
373 #endif
374
375     if (grantpt(pty->master_fd) < 0) {
376         perror("grantpt");
377         exit(1);
378     }
379     
380     if (unlockpt(pty->master_fd) < 0) {
381         perror("unlockpt");
382         exit(1);
383     }
384
385     cloexec(pty->master_fd);
386
387     pty->name[FILENAME_MAX-1] = '\0';
388     strncpy(pty->name, ptsname(pty->master_fd), FILENAME_MAX-1);
389 #endif
390
391 #ifndef SET_NONBLOCK_VIA_OPENPT
392     nonblock(pty->master_fd);
393 #endif
394
395     if (!ptys_by_fd)
396         ptys_by_fd = newtree234(pty_compare_by_fd);
397     add234(ptys_by_fd, pty);
398 }
399
400 static Pty new_pty_struct(void)
401 {
402     Pty pty = snew(struct pty_tag);
403     pty->conf = NULL;
404     bufchain_init(&pty->output_data);
405     return pty;
406 }
407
408 /*
409  * Pre-initialisation. This is here to get around the fact that GTK
410  * doesn't like being run in setuid/setgid programs (probably
411  * sensibly). So before we initialise GTK - and therefore before we
412  * even process the command line - we check to see if we're running
413  * set[ug]id. If so, we open our pty master _now_, chown it as
414  * necessary, and drop privileges. We can always close it again
415  * later. If we're potentially going to be doing utmp as well, we
416  * also fork off a utmp helper process and communicate with it by
417  * means of a pipe; the utmp helper will keep privileges in order
418  * to clean up utmp when we exit (i.e. when its end of our pipe
419  * closes).
420  */
421 void pty_pre_init(void)
422 {
423 #ifndef NO_PTY_PRE_INIT
424
425     Pty pty;
426
427 #ifndef OMIT_UTMP
428     pid_t pid;
429     int pipefd[2];
430 #endif
431
432     pty = single_pty = new_pty_struct();
433
434     /* set the child signal handler straight away; it needs to be set
435      * before we ever fork. */
436     putty_signal(SIGCHLD, sigchld_handler);
437     pty->master_fd = pty->slave_fd = -1;
438 #ifndef OMIT_UTMP
439     pty_stamped_utmp = FALSE;
440 #endif
441
442     if (geteuid() != getuid() || getegid() != getgid()) {
443         pty_open_master(pty);
444
445 #ifndef OMIT_UTMP
446         /*
447          * Fork off the utmp helper.
448          */
449         if (pipe(pipefd) < 0) {
450             perror("pterm: pipe");
451             exit(1);
452         }
453         cloexec(pipefd[0]);
454         cloexec(pipefd[1]);
455         pid = fork();
456         if (pid < 0) {
457             perror("pterm: fork");
458             exit(1);
459         } else if (pid == 0) {
460             char display[128], buffer[128];
461             int dlen, ret;
462
463             close(pipefd[1]);
464             /*
465              * Now sit here until we receive a display name from the
466              * other end of the pipe, and then stamp utmp. Unstamp utmp
467              * again, and exit, when the pipe closes.
468              */
469
470             dlen = 0;
471             while (1) {
472             
473                 ret = read(pipefd[0], buffer, lenof(buffer));
474                 if (ret <= 0) {
475                     cleanup_utmp();
476                     _exit(0);
477                 } else if (!pty_stamped_utmp) {
478                     if (dlen < lenof(display))
479                         memcpy(display+dlen, buffer,
480                                min(ret, lenof(display)-dlen));
481                     if (buffer[ret-1] == '\0') {
482                         /*
483                          * Now we have a display name. NUL-terminate
484                          * it, and stamp utmp.
485                          */
486                         display[lenof(display)-1] = '\0';
487                         /*
488                          * Trap as many fatal signals as we can in the
489                          * hope of having the best possible chance to
490                          * clean up utmp before termination. We are
491                          * unfortunately unprotected against SIGKILL,
492                          * but that's life.
493                          */
494                         putty_signal(SIGHUP, fatal_sig_handler);
495                         putty_signal(SIGINT, fatal_sig_handler);
496                         putty_signal(SIGQUIT, fatal_sig_handler);
497                         putty_signal(SIGILL, fatal_sig_handler);
498                         putty_signal(SIGABRT, fatal_sig_handler);
499                         putty_signal(SIGFPE, fatal_sig_handler);
500                         putty_signal(SIGPIPE, fatal_sig_handler);
501                         putty_signal(SIGALRM, fatal_sig_handler);
502                         putty_signal(SIGTERM, fatal_sig_handler);
503                         putty_signal(SIGSEGV, fatal_sig_handler);
504                         putty_signal(SIGUSR1, fatal_sig_handler);
505                         putty_signal(SIGUSR2, fatal_sig_handler);
506 #ifdef SIGBUS
507                         putty_signal(SIGBUS, fatal_sig_handler);
508 #endif
509 #ifdef SIGPOLL
510                         putty_signal(SIGPOLL, fatal_sig_handler);
511 #endif
512 #ifdef SIGPROF
513                         putty_signal(SIGPROF, fatal_sig_handler);
514 #endif
515 #ifdef SIGSYS
516                         putty_signal(SIGSYS, fatal_sig_handler);
517 #endif
518 #ifdef SIGTRAP
519                         putty_signal(SIGTRAP, fatal_sig_handler);
520 #endif
521 #ifdef SIGVTALRM
522                         putty_signal(SIGVTALRM, fatal_sig_handler);
523 #endif
524 #ifdef SIGXCPU
525                         putty_signal(SIGXCPU, fatal_sig_handler);
526 #endif
527 #ifdef SIGXFSZ
528                         putty_signal(SIGXFSZ, fatal_sig_handler);
529 #endif
530 #ifdef SIGIO
531                         putty_signal(SIGIO, fatal_sig_handler);
532 #endif
533                         setup_utmp(pty->name, display);
534                     }
535                 }
536             }
537         } else {
538             close(pipefd[0]);
539             pty_utmp_helper_pid = pid;
540             pty_utmp_helper_pipe = pipefd[1];
541         }
542 #endif
543     }
544
545     /* Drop privs. */
546     {
547 #ifndef HAVE_NO_SETRESUID
548         int gid = getgid(), uid = getuid();
549         int setresgid(gid_t, gid_t, gid_t);
550         int setresuid(uid_t, uid_t, uid_t);
551         if (setresgid(gid, gid, gid) < 0) {
552             perror("setresgid");
553             exit(1);
554         }
555         if (setresuid(uid, uid, uid) < 0) {
556             perror("setresuid");
557             exit(1);
558         }
559 #else
560         if (setgid(getgid()) < 0) {
561             perror("setgid");
562             exit(1);
563         }
564         if (setuid(getuid()) < 0) {
565             perror("setuid");
566             exit(1);
567         }
568 #endif
569     }
570
571 #endif /* NO_PTY_PRE_INIT */
572
573 }
574
575 int pty_real_select_result(Pty pty, int event, int status)
576 {
577     char buf[4096];
578     int ret;
579     int finished = FALSE;
580
581     if (event < 0) {
582         /*
583          * We've been called because our child process did
584          * something. `status' tells us what.
585          */
586         if ((WIFEXITED(status) || WIFSIGNALED(status))) {
587             /*
588              * The primary child process died. We could keep
589              * the terminal open for remaining subprocesses to
590              * output to, but conventional wisdom seems to feel
591              * that that's the Wrong Thing for an xterm-alike,
592              * so we bail out now (though we don't necessarily
593              * _close_ the window, depending on the state of
594              * Close On Exit). This would be easy enough to
595              * change or make configurable if necessary.
596              */
597             pty->exit_code = status;
598             pty->child_dead = TRUE;
599             del234(ptys_by_pid, pty);
600             finished = TRUE;
601         }
602     } else {
603         if (event == 1) {
604
605             ret = read(pty->master_fd, buf, sizeof(buf));
606
607             /*
608              * Clean termination condition is that either ret == 0, or ret
609              * < 0 and errno == EIO. Not sure why the latter, but it seems
610              * to happen. Boo.
611              */
612             if (ret == 0 || (ret < 0 && errno == EIO)) {
613                 /*
614                  * We assume a clean exit if the pty has closed but the
615                  * actual child process hasn't. The only way I can
616                  * imagine this happening is if it detaches itself from
617                  * the pty and goes daemonic - in which case the
618                  * expected usage model would precisely _not_ be for
619                  * the pterm window to hang around!
620                  */
621                 finished = TRUE;
622                 if (!pty->child_dead)
623                     pty->exit_code = 0;
624             } else if (ret < 0) {
625                 perror("read pty master");
626                 exit(1);
627             } else if (ret > 0) {
628                 from_backend(pty->frontend, 0, buf, ret);
629             }
630         } else if (event == 2) {
631             /*
632              * Attempt to send data down the pty.
633              */
634             pty_try_write(pty);
635         }
636     }
637
638     if (finished && !pty->finished) {
639         int close_on_exit;
640
641         uxsel_del(pty->master_fd);
642         pty_close(pty);
643         pty->master_fd = -1;
644
645         pty->finished = TRUE;
646
647         /*
648          * This is a slight layering-violation sort of hack: only
649          * if we're not closing on exit (COE is set to Never, or to
650          * Only On Clean and it wasn't a clean exit) do we output a
651          * `terminated' message.
652          */
653         close_on_exit = conf_get_int(pty->conf, CONF_close_on_exit);
654         if (close_on_exit == FORCE_OFF ||
655             (close_on_exit == AUTO && pty->exit_code != 0)) {
656             char message[512];
657             message[0] = '\0';
658             if (WIFEXITED(pty->exit_code))
659                 sprintf(message, "\r\n[pterm: process terminated with exit"
660                         " code %d]\r\n", WEXITSTATUS(pty->exit_code));
661             else if (WIFSIGNALED(pty->exit_code))
662 #ifdef HAVE_NO_STRSIGNAL
663                 sprintf(message, "\r\n[pterm: process terminated on signal"
664                         " %d]\r\n", WTERMSIG(pty->exit_code));
665 #else
666                 sprintf(message, "\r\n[pterm: process terminated on signal"
667                         " %d (%.400s)]\r\n", WTERMSIG(pty->exit_code),
668                         strsignal(WTERMSIG(pty->exit_code)));
669 #endif
670             from_backend(pty->frontend, 0, message, strlen(message));
671         }
672
673         notify_remote_exit(pty->frontend);
674     }
675
676     return !finished;
677 }
678
679 int pty_select_result(int fd, int event)
680 {
681     int ret = TRUE;
682     Pty pty;
683
684     if (fd == pty_signal_pipe[0]) {
685         pid_t pid;
686         int status;
687         char c[1];
688
689         if (read(pty_signal_pipe[0], c, 1) <= 0)
690             /* ignore error */;
691         /* ignore its value; it'll be `x' */
692
693         do {
694             pid = waitpid(-1, &status, WNOHANG);
695
696             pty = find234(ptys_by_pid, &pid, pty_find_by_pid);
697
698             if (pty)
699                 ret = ret && pty_real_select_result(pty, -1, status);
700         } while (pid > 0);
701     } else {
702         pty = find234(ptys_by_fd, &fd, pty_find_by_fd);
703
704         if (pty)
705             ret = ret && pty_real_select_result(pty, event, 0);
706     }
707
708     return ret;
709 }
710
711 static void pty_uxsel_setup(Pty pty)
712 {
713     int rwx;
714
715     rwx = 1;                           /* always want to read from pty */
716     if (bufchain_size(&pty->output_data))
717         rwx |= 2;                      /* might also want to write to it */
718     uxsel_set(pty->master_fd, rwx, pty_select_result);
719
720     /*
721      * In principle this only needs calling once for all pty
722      * backend instances, but it's simplest just to call it every
723      * time; uxsel won't mind.
724      */
725     uxsel_set(pty_signal_pipe[0], 1, pty_select_result);
726 }
727
728 /*
729  * Called to set up the pty.
730  * 
731  * Returns an error message, or NULL on success.
732  *
733  * Also places the canonical host name into `realhost'. It must be
734  * freed by the caller.
735  */
736 static const char *pty_init(void *frontend, void **backend_handle, Conf *conf,
737                             const char *host, int port, char **realhost,
738                             int nodelay, int keepalive)
739 {
740     int slavefd;
741     pid_t pid, pgrp;
742 #ifndef NOT_X_WINDOWS                  /* for Mac OS X native compilation */
743     long windowid;
744 #endif
745     Pty pty;
746
747     if (single_pty) {
748         pty = single_pty;
749         assert(pty->conf == NULL);
750     } else {
751         pty = new_pty_struct();
752         pty->master_fd = pty->slave_fd = -1;
753 #ifndef OMIT_UTMP
754         pty_stamped_utmp = FALSE;
755 #endif
756     }
757
758     pty->frontend = frontend;
759     *backend_handle = NULL;            /* we can't sensibly use this, sadly */
760
761     pty->conf = conf_copy(conf);
762     pty->term_width = conf_get_int(conf, CONF_width);
763     pty->term_height = conf_get_int(conf, CONF_height);
764
765     if (pty->master_fd < 0)
766         pty_open_master(pty);
767
768 #ifndef OMIT_UTMP
769     /*
770      * Stamp utmp (that is, tell the utmp helper process to do so),
771      * or not.
772      */
773     if (pty_utmp_helper_pipe >= 0) {   /* if it's < 0, we can't anyway */
774         if (!conf_get_int(conf, CONF_stamp_utmp)) {
775             close(pty_utmp_helper_pipe);   /* just let the child process die */
776             pty_utmp_helper_pipe = -1;
777         } else {
778             const char *location = get_x_display(pty->frontend);
779             int len = strlen(location)+1, pos = 0;   /* +1 to include NUL */
780             while (pos < len) {
781                 int ret = write(pty_utmp_helper_pipe, location+pos, len - pos);
782                 if (ret < 0) {
783                     perror("pterm: writing to utmp helper process");
784                     close(pty_utmp_helper_pipe);   /* arrgh, just give up */
785                     pty_utmp_helper_pipe = -1;
786                     break;
787                 }
788                 pos += ret;
789             }
790         }
791     }
792 #endif
793
794 #ifndef NOT_X_WINDOWS                  /* for Mac OS X native compilation */
795     windowid = get_windowid(pty->frontend);
796 #endif
797
798     /*
799      * Fork and execute the command.
800      */
801     pid = fork();
802     if (pid < 0) {
803         perror("fork");
804         exit(1);
805     }
806
807     if (pid == 0) {
808         struct termios attrs;
809
810         /*
811          * We are the child.
812          */
813
814         if (pty_osx_envrestore_prefix) {
815             int plen = strlen(pty_osx_envrestore_prefix);
816             extern char **environ;
817             char **ep;
818
819           restart_osx_env_restore:
820             for (ep = environ; *ep; ep++) {
821                 char *e = *ep;
822
823                 if (!strncmp(e, pty_osx_envrestore_prefix, plen)) {
824                     int unset = (e[plen] == 'u');
825                     char *pname = dupprintf("%.*s", (int)strcspn(e, "="), e);
826                     char *name = pname + plen + 1;
827                     char *value = e + strcspn(e, "=");
828                     if (*value) value++;
829                     value = dupstr(value);
830                     if (unset)
831                         unsetenv(name);
832                     else
833                         setenv(name, value, 1);
834                     unsetenv(pname);
835                     sfree(pname);
836                     sfree(value);
837                     goto restart_osx_env_restore;
838                 }
839             }
840         }
841
842         slavefd = pty_open_slave(pty);
843         if (slavefd < 0) {
844             perror("slave pty: open");
845             _exit(1);
846         }
847
848         close(pty->master_fd);
849         noncloexec(slavefd);
850         dup2(slavefd, 0);
851         dup2(slavefd, 1);
852         dup2(slavefd, 2);
853         close(slavefd);
854         setsid();
855 #ifdef TIOCSCTTY
856         ioctl(0, TIOCSCTTY, 1);
857 #endif
858         pgrp = getpid();
859         tcsetpgrp(0, pgrp);
860
861         /*
862          * Set up configuration-dependent termios settings on the new
863          * pty. Linux would have let us do this on the pty master
864          * before we forked, but that fails on OS X, so we do it here
865          * instead.
866          */
867         if (tcgetattr(0, &attrs) == 0) {
868             /*
869              * Set the backspace character to be whichever of ^H and
870              * ^? is specified by bksp_is_delete.
871              */
872             attrs.c_cc[VERASE] = conf_get_int(conf, CONF_bksp_is_delete)
873                 ? '\177' : '\010';
874
875             /*
876              * Set the IUTF8 bit iff the character set is UTF-8.
877              */
878 #ifdef IUTF8
879             if (frontend_is_utf8(frontend))
880                 attrs.c_iflag |= IUTF8;
881             else
882                 attrs.c_iflag &= ~IUTF8;
883 #endif
884
885             tcsetattr(0, TCSANOW, &attrs);
886         }
887
888         setpgid(pgrp, pgrp);
889         {
890             int ptyfd = open(pty->name, O_WRONLY, 0);
891             if (ptyfd >= 0)
892                 close(ptyfd);
893         }
894         setpgid(pgrp, pgrp);
895         {
896             char *term_env_var = dupprintf("TERM=%s",
897                                            conf_get_str(conf, CONF_termtype));
898             putenv(term_env_var);
899             /* We mustn't free term_env_var, as putenv links it into the
900              * environment in place.
901              */
902         }
903 #ifndef NOT_X_WINDOWS                  /* for Mac OS X native compilation */
904         {
905             char *windowid_env_var = dupprintf("WINDOWID=%ld", windowid);
906             putenv(windowid_env_var);
907             /* We mustn't free windowid_env_var, as putenv links it into the
908              * environment in place.
909              */
910         }
911         {
912             /*
913              * In case we were invoked with a --display argument that
914              * doesn't match DISPLAY in our actual environment, we
915              * should set DISPLAY for processes running inside the
916              * terminal to match the display the terminal itself is
917              * on.
918              */
919             const char *x_display = get_x_display(pty->frontend);
920             char *x_display_env_var = dupprintf("DISPLAY=%s", x_display);
921             putenv(x_display_env_var);
922             /* As above, we don't free this. */
923         }
924 #endif
925         {
926             char *key, *val;
927
928             for (val = conf_get_str_strs(conf, CONF_environmt, NULL, &key);
929                  val != NULL;
930                  val = conf_get_str_strs(conf, CONF_environmt, key, &key)) {
931                 char *varval = dupcat(key, "=", val, NULL);
932                 putenv(varval);
933                 /*
934                  * We must not free varval, since putenv links it
935                  * into the environment _in place_. Weird, but
936                  * there we go. Memory usage will be rationalised
937                  * as soon as we exec anyway.
938                  */
939             }
940         }
941
942         /*
943          * SIGINT, SIGQUIT and SIGPIPE may have been set to ignored by
944          * our parent, particularly by things like sh -c 'pterm &' and
945          * some window or session managers. SIGPIPE was also
946          * (potentially) blocked by us during startup. Reverse all
947          * this for our child process.
948          */
949         putty_signal(SIGINT, SIG_DFL);
950         putty_signal(SIGQUIT, SIG_DFL);
951         putty_signal(SIGPIPE, SIG_DFL);
952         block_signal(SIGPIPE, 0);
953         if (pty_argv) {
954             /*
955              * Exec the exact argument list we were given.
956              */
957             execvp(pty_argv[0], pty_argv);
958             /*
959              * If that fails, and if we had exactly one argument, pass
960              * that argument to $SHELL -c.
961              *
962              * This arranges that we can _either_ follow 'pterm -e'
963              * with a list of argv elements to be fed directly to
964              * exec, _or_ with a single argument containing a command
965              * to be parsed by a shell (but, in cases of doubt, the
966              * former is more reliable).
967              *
968              * A quick survey of other terminal emulators' -e options
969              * (as of Debian squeeze) suggests that:
970              *
971              *  - xterm supports both modes, more or less like this
972              *  - gnome-terminal will only accept a one-string shell command
973              *  - Eterm, kterm and rxvt will only accept a list of
974              *    argv elements (as did older versions of pterm).
975              *
976              * It therefore seems important to support both usage
977              * modes in order to be a drop-in replacement for either
978              * xterm or gnome-terminal, and hence for anyone's
979              * plausible uses of the Debian-style alias
980              * 'x-terminal-emulator'...
981              */
982             if (pty_argv[1] == NULL) {
983                 char *shell = getenv("SHELL");
984                 if (shell)
985                     execl(shell, shell, "-c", pty_argv[0], (void *)NULL);
986             }
987         } else {
988             char *shell = getenv("SHELL");
989             char *shellname;
990             if (conf_get_int(conf, CONF_login_shell)) {
991                 char *p = strrchr(shell, '/');
992                 shellname = snewn(2+strlen(shell), char);
993                 p = p ? p+1 : shell;
994                 sprintf(shellname, "-%s", p);
995             } else
996                 shellname = shell;
997             execl(getenv("SHELL"), shellname, (void *)NULL);
998         }
999
1000         /*
1001          * If we're here, exec has gone badly foom.
1002          */
1003         perror("exec");
1004         _exit(127);
1005     } else {
1006         pty->child_pid = pid;
1007         pty->child_dead = FALSE;
1008         pty->finished = FALSE;
1009         if (pty->slave_fd > 0)
1010             close(pty->slave_fd);
1011         if (!ptys_by_pid)
1012             ptys_by_pid = newtree234(pty_compare_by_pid);
1013         add234(ptys_by_pid, pty);
1014     }
1015
1016     if (pty_signal_pipe[0] < 0) {
1017         if (pipe(pty_signal_pipe) < 0) {
1018             perror("pipe");
1019             exit(1);
1020         }
1021         cloexec(pty_signal_pipe[0]);
1022         cloexec(pty_signal_pipe[1]);
1023     }
1024     pty_uxsel_setup(pty);
1025
1026     *backend_handle = pty;
1027
1028     *realhost = dupstr("");
1029
1030     return NULL;
1031 }
1032
1033 static void pty_reconfig(void *handle, Conf *conf)
1034 {
1035     Pty pty = (Pty)handle;
1036     /*
1037      * We don't have much need to reconfigure this backend, but
1038      * unfortunately we do need to pick up the setting of Close On
1039      * Exit so we know whether to give a `terminated' message.
1040      */
1041     conf_copy_into(pty->conf, conf);
1042 }
1043
1044 /*
1045  * Stub routine (never called in pterm).
1046  */
1047 static void pty_free(void *handle)
1048 {
1049     Pty pty = (Pty)handle;
1050
1051     /* Either of these may fail `not found'. That's fine with us. */
1052     del234(ptys_by_pid, pty);
1053     del234(ptys_by_fd, pty);
1054
1055     bufchain_clear(&pty->output_data);
1056
1057     conf_free(pty->conf);
1058     pty->conf = NULL;
1059
1060     if (pty == single_pty) {
1061         /*
1062          * Leave this structure around in case we need to Restart
1063          * Session.
1064          */
1065     } else {
1066         sfree(pty);
1067     }
1068 }
1069
1070 static void pty_try_write(Pty pty)
1071 {
1072     void *data;
1073     int len, ret;
1074
1075     assert(pty->master_fd >= 0);
1076
1077     while (bufchain_size(&pty->output_data) > 0) {
1078         bufchain_prefix(&pty->output_data, &data, &len);
1079         ret = write(pty->master_fd, data, len);
1080
1081         if (ret < 0 && (errno == EWOULDBLOCK)) {
1082             /*
1083              * We've sent all we can for the moment.
1084              */
1085             break;
1086         }
1087         if (ret < 0) {
1088             perror("write pty master");
1089             exit(1);
1090         }
1091         bufchain_consume(&pty->output_data, ret);
1092     }
1093
1094     pty_uxsel_setup(pty);
1095 }
1096
1097 /*
1098  * Called to send data down the pty.
1099  */
1100 static int pty_send(void *handle, const char *buf, int len)
1101 {
1102     Pty pty = (Pty)handle;
1103
1104     if (pty->master_fd < 0)
1105         return 0;                      /* ignore all writes if fd closed */
1106
1107     bufchain_add(&pty->output_data, buf, len);
1108     pty_try_write(pty);
1109
1110     return bufchain_size(&pty->output_data);
1111 }
1112
1113 static void pty_close(Pty pty)
1114 {
1115     if (pty->master_fd >= 0) {
1116         close(pty->master_fd);
1117         pty->master_fd = -1;
1118     }
1119 #ifndef OMIT_UTMP
1120     if (pty_utmp_helper_pipe >= 0) {
1121         close(pty_utmp_helper_pipe);   /* this causes utmp to be cleaned up */
1122         pty_utmp_helper_pipe = -1;
1123     }
1124 #endif
1125 }
1126
1127 /*
1128  * Called to query the current socket sendability status.
1129  */
1130 static int pty_sendbuffer(void *handle)
1131 {
1132     /* Pty pty = (Pty)handle; */
1133     return 0;
1134 }
1135
1136 /*
1137  * Called to set the size of the window
1138  */
1139 static void pty_size(void *handle, int width, int height)
1140 {
1141     Pty pty = (Pty)handle;
1142     struct winsize size;
1143
1144     pty->term_width = width;
1145     pty->term_height = height;
1146
1147     size.ws_row = (unsigned short)pty->term_height;
1148     size.ws_col = (unsigned short)pty->term_width;
1149     size.ws_xpixel = (unsigned short) pty->term_width *
1150         font_dimension(pty->frontend, 0);
1151     size.ws_ypixel = (unsigned short) pty->term_height *
1152         font_dimension(pty->frontend, 1);
1153     ioctl(pty->master_fd, TIOCSWINSZ, (void *)&size);
1154     return;
1155 }
1156
1157 /*
1158  * Send special codes.
1159  */
1160 static void pty_special(void *handle, Telnet_Special code)
1161 {
1162     /* Pty pty = (Pty)handle; */
1163     /* Do nothing! */
1164     return;
1165 }
1166
1167 /*
1168  * Return a list of the special codes that make sense in this
1169  * protocol.
1170  */
1171 static const struct telnet_special *pty_get_specials(void *handle)
1172 {
1173     /* Pty pty = (Pty)handle; */
1174     /*
1175      * Hmm. When I get round to having this actually usable, it
1176      * might be quite nice to have the ability to deliver a few
1177      * well chosen signals to the child process - SIGINT, SIGTERM,
1178      * SIGKILL at least.
1179      */
1180     return NULL;
1181 }
1182
1183 static int pty_connected(void *handle)
1184 {
1185     /* Pty pty = (Pty)handle; */
1186     return TRUE;
1187 }
1188
1189 static int pty_sendok(void *handle)
1190 {
1191     /* Pty pty = (Pty)handle; */
1192     return 1;
1193 }
1194
1195 static void pty_unthrottle(void *handle, int backlog)
1196 {
1197     /* Pty pty = (Pty)handle; */
1198     /* do nothing */
1199 }
1200
1201 static int pty_ldisc(void *handle, int option)
1202 {
1203     /* Pty pty = (Pty)handle; */
1204     return 0;                          /* neither editing nor echoing */
1205 }
1206
1207 static void pty_provide_ldisc(void *handle, void *ldisc)
1208 {
1209     /* Pty pty = (Pty)handle; */
1210     /* This is a stub. */
1211 }
1212
1213 static void pty_provide_logctx(void *handle, void *logctx)
1214 {
1215     /* Pty pty = (Pty)handle; */
1216     /* This is a stub. */
1217 }
1218
1219 static int pty_exitcode(void *handle)
1220 {
1221     Pty pty = (Pty)handle;
1222     if (!pty->finished)
1223         return -1;                     /* not dead yet */
1224     else
1225         return pty->exit_code;
1226 }
1227
1228 static int pty_cfg_info(void *handle)
1229 {
1230     /* Pty pty = (Pty)handle; */
1231     return 0;
1232 }
1233
1234 Backend pty_backend = {
1235     pty_init,
1236     pty_free,
1237     pty_reconfig,
1238     pty_send,
1239     pty_sendbuffer,
1240     pty_size,
1241     pty_special,
1242     pty_get_specials,
1243     pty_connected,
1244     pty_exitcode,
1245     pty_sendok,
1246     pty_ldisc,
1247     pty_provide_ldisc,
1248     pty_provide_logctx,
1249     pty_unthrottle,
1250     pty_cfg_info,
1251     NULL /* test_for_upstream */,
1252     "pty",
1253     -1,
1254     0
1255 };