1 char *ckptyv = "Pseudoterminal support, 9.0.101, 13 Jun 2011";
3 /* C K U P T Y -- C-Kermit pseudoterminal control functions for UNIX */
5 /* Last update: Mon Jun 13 11:32:52 2011 */
8 Copyright 1995 by the Massachusetts Institute of Technology.
10 Permission to use, copy, modify, and distribute this software and its
11 documentation for any purpose and without fee is hereby granted, provided
12 that the above copyright notice appear in all copies and that both that
13 copyright notice and this permission notice appear in supporting
14 documentation, and that the name of M.I.T. not be used in advertising or
15 publicity pertaining to distribution of the software without specific,
16 written prior permission. Furthermore if you modify this software you must
17 label your software as modified software and not distribute it in such a
18 fashion that it might be confused with the original M.I.T. software.
19 M.I.T. makes no representations about the suitability of this software for
20 any purpose. It is provided "as is" without express or implied warranty.
22 Modified for use in C-Kermit, and new material added, by:
24 Jeffrey Altman <jaltman@secure-endpoints.com>
25 Secure Endpoints Inc., New York City
28 Parameterized for pty file descriptor and function code,
29 Frank da Cruz, Columbia University, New York City
34 Built and tested successully on:
35 . 4.4BSD, including BSDI/OS, NetBSD, FreeBSD, OpenBSD, Mac OS X
38 . Digital UNIX 3.2 and 4.0
39 . HP-UX 9.00 and later
45 . QNX 4.25 (except PTY process termination not detected)
53 . SCO UNIX 3.2v4.2 (compile fails with syntax error in <memory.h>)
54 . HP-UX 8.00 and earlier (no vhangup or ptsname routines)
58 #include "ckcdeb.h" /* To pick up NETPTY definition */
60 #ifndef NETPTY /* Selector for PTY support */
62 char * ptyver = "No PTY support";
64 #else /* (rest of this module...) */
66 char * ptyver = "PTY support 8.0.016, 22 Aug 2007";
68 /* These will no doubt need adjustment... */
104 #endif /* BSD44ORPOSIX */
109 #endif /* USE_TERMIO */
116 #define POSIX_TERMIOS /* Seems to be a misnomer */
117 #endif /* USE_TERMIO */
120 #ifndef GETPGRP_ONEARG
121 #define GETPGRP_ONEARG
122 #endif /* GETPGRP_ONEARG */
125 #ifdef WANT_UTMP /* See ckupty.h */
127 WANT_UTMP is not defined because (a) the utmp/wtmp junk is the most
128 nonportable part of this module, and (b) we're not logging anybody
129 in, we're just running a process, and don't need to write utmp/wtmp records.
131 #ifndef HAVE_SETUTXENT /* Who has <utmpx.h> */
133 #define HAVE_SETUTXENT
136 #define HAVE_SETUTXENT
139 #define HAVE_SETUTXENT
142 #define HAVE_SETUTXENT
145 #define HAVE_SETUTXENT
148 #define HAVE_SETUTXENT
150 #endif /* UNIXWARE */
152 #endif /* CK_SCOV5 */
155 #endif /* HAVE_SETUTXENT */
157 #ifndef HAVE_UTHOST /* Does utmp include ut_host[]? */
158 #ifdef HAVE_SETUTXENT /* utmpx always does */
161 #ifdef LINUX /* Linux does */
164 #ifdef SUNOS4 /* SunOS does */
167 #ifdef AIX41 /* AIX 4.1 and later do */
172 #endif /* HAVE_SETUTXENT */
173 #endif /* HAVE_UTHOST */
178 #endif /* NO_UT_HOST */
179 #endif /* HAVE_UT_HOST */
181 #endif /* WANT_UTMP */
185 #define HAVE_SYS_SELECT_H
186 #define HAVE_GETUTENT
187 #define HAVE_SETUTENT
197 #endif /* HAVE_PTYTRAP */
205 #endif /* HAVE_PTYTRAP */
226 #define PUSH_TTCOMPAT
243 #endif /* HAVE_PTMX */
247 #endif /* HAVE_STREAMS */
255 #define O_NDELAY O_NONBLOCK
256 #endif /* O_NONBLOCK */
257 #endif /* O_NDELAY */
258 #else /* PTYNOBLOCK */
261 #endif /* O_NDELAY */
263 #endif /* PTYNOBLOCK */
270 #include <sys/wait.h>
271 #endif /* CK_WAIT_H */
276 #endif /* INIT_SPTY */
278 #include <sys/stream.h>
282 /* Make sure we don't get the BSD version */
284 #ifdef HAVE_SYS_TTY_H
285 #include "/usr/include/sys/tty.h"
286 #endif /* HAVE_SYS_TTY_H */
288 #ifdef HAS_PTYVAR /* Where is this set? */
290 #include <sys/ptyvar.h>
292 #else /* HAS_PTYVAR */
294 #ifndef TIOCPKT_FLUSHWRITE
295 #define TIOCPKT_FLUSHWRITE 0x02
296 #define TIOCPKT_NOSTOP 0x10
297 #define TIOCPKT_DOSTOP 0x20
298 #define TIOCPKT_IOCTL 0x40
299 #endif /* TIOCPKT_FLUSHWRITE */
301 #endif /* HAS_PTYVAR */
305 #endif /* HAVE_TTY_H */
308 Because of the way ptyibuf is used with streams messages, we need
309 ptyibuf+1 to be on a full-word boundary. The following weirdness
310 is simply to make that happen.
312 long ptyibufbuf[BUFSIZ/sizeof(long)+1];
313 char *ptyibuf = ((char *)&ptyibufbuf[1])-1;
314 char *ptyip = ((char *)&ptyibufbuf[1])-1;
315 char ptyibuf2[BUFSIZ];
316 unsigned char ctlbuf[BUFSIZ];
317 struct strbuf strbufc, strbufd;
321 #else /* ! STREAMSPTY */
323 /* I/O data buffers, pointers, and counters. */
325 char ptyibuf[BUFSIZ], *ptyip = ptyibuf;
326 char ptyibuf2[BUFSIZ];
328 #endif /* ! STREAMSPTY */
339 #define cfsetospeed(tp,val) (tp)->sg.sg_ospeed = (val)
340 #define cfsetispeed(tp,val) (tp)->sg.sg_ispeed = (val)
341 #define cfgetospeed(tp) (tp)->sg.sg_ospeed
342 #define cfgetispeed(tp) (tp)->sg.sg_ispeed
344 #else /* USE_TERMIO */
347 #define termios termio
348 #endif /* SYSV_TERMIO */
354 #define TCSANOW TCSETS
355 #define TCSADRAIN TCSETSW
356 #define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
361 #define TCSANOW TCSETA
362 #define TCSADRAIN TCSETAW
363 #define tcgetattr(f,t) ioctl(f,TCGETA,(char *)t)
365 #define TCSANOW TIOCSETA
366 #define TCSADRAIN TIOCSETAW
367 #define tcgetattr(f,t) ioctl(f,TIOCGETA,(char *)t)
372 #define tcsetattr(f,a,t) ioctl(f,a,t)
373 #define cfsetospeed(tp,val) (tp)->c_cflag &= ~CBAUD;(tp)->c_cflag|=(val)
374 #define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
377 #define cfsetispeed(tp,val) \
378 (tp)->c_cflag &= ~CIBAUD; (tp)->c_cflag |= ((val)<<IBSHIFT)
379 #define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
381 #define cfsetispeed(tp,val) (tp)->c_cflag &= ~CBAUD; (tp)->c_cflag|=(val)
382 #define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
387 struct termios termbuf, termbuf2; /* pty control structure */
390 static int spty = -1;
391 #endif /* INIT_SPTY */
393 #endif /* USE_TERMIO */
403 /* Variables available to other modules */
405 int pty_fork_active = 0; /* pty fork is active */
406 PID_T pty_fork_pid = -1; /* pty fork pid */
407 int pty_slave_fd = -1; /* pty slave file descriptor */
408 int pty_master_fd = -1; /* pty master file descriptor */
410 /* termbuf routines (begin) */
416 These three routines are used to get and set the "termbuf" structure
417 to and from the kernel. init_termbuf() gets the current settings.
418 copy_termbuf() hands in a new "termbuf" to write to the kernel, and
419 set_termbuf() writes the structure into the kernel.
422 init_termbuf(fd) int fd; {
429 debug(F100,"init_termbuf HAVE_STREAMS","",0);
431 debug(F100,"init_termbuf HAVE_STREAMS NOT DEFINED","",0);
432 #endif /* HAVE_STREAMS */
434 debug(F100,"init_termbuf STREAMSPTY","",0);
436 debug(F100,"init_termbuf STREAMSPTY NOT DEFINED","",0);
437 #endif /* STREAMSPTY */
439 debug(F100,"init_termbuf INIT_SPTY","",0);
441 debug(F100,"init_termbuf INIT_SPTY NOT DEFINED","",0);
442 #endif /* INIT_SPTY */
444 debug(F101,"init_termbuf ttyfd","",ttyfd);
446 debug(F101,"init_termbuf spty","",spty);
447 #endif /* INIT_SPTY */
449 memset(&termbuf,0,sizeof(termbuf));
450 memset(&termbuf2,0,sizeof(termbuf2));
452 rc = ioctl(ttyfd, TIOCGETP, (char *)&termbuf.sg);
453 rc |= ioctl(ttyfd, TIOCGETC, (char *)&termbuf.tc);
454 rc |= ioctl(ttyfd, TIOCGLTC, (char *)&termbuf.ltc);
456 rc |= ioctl(ttyfd, TIOCGSTATE, (char *)&termbuf.state);
457 #endif /* TIOCGSTATE */
458 #else /* USE_TERMIO */
461 rc = tcgetattr(spty, &termbuf);
462 debug(F111,"init_termbuf() tcgetattr(spty)",ckitoa(rc),errno);
464 rc = tcgetattr(ttyfd, &termbuf);
465 debug(F111,"init_termbuf() tcgetattr(ttyfd)",ckitoa(rc),errno);
466 #endif /* INIT_SPTY */
467 #endif /* USE_TERMIO */
474 copy_termbuf(cp, len) char *cp; int len; {
475 if (len > sizeof(termbuf))
476 len = sizeof(termbuf);
477 memcpy((char *)&termbuf, cp, len);
480 #endif /* TIOCPKT_IOCTL */
483 set_termbuf(fd) int fd; { /* Only make the necessary changes. */
488 debug(F101,"set_termbuf ttyfd","",ttyfd);
490 debug(F101,"set_termbuf spty","",spty);
491 #endif /* INIT_SPTY */
494 debug(F100,"set_termbuf USE_TERMIO","",0);
495 if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
496 ioctl(ttyfd, TIOCSETN, (char *)&termbuf.sg);
497 if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
498 ioctl(ttyfd, TIOCSETC, (char *)&termbuf.tc);
499 if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
500 sizeof(termbuf.ltc)))
501 ioctl(ttyfd, TIOCSLTC, (char *)&termbuf.ltc);
502 if (termbuf.lflags != termbuf2.lflags)
503 ioctl(ttyfd, TIOCLSET, (char *)&termbuf.lflags);
504 #else /* USE_TERMIO */
505 x = memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf));
506 debug(F101,"set_termbuf !USE_TERMIO memcmp","",x);
507 x = 1; /* Force this */
512 debug(F100,"set_termbuf INIT_SPTY","",0);
513 x = tcsetattr(spty, TCSANOW, &termbuf);
514 debug(F111,"set_termbuf tcsetattr(spty)",ckitoa(x),errno);
516 debug(F100,"set_termbuf !INIT_SPTY","",0);
517 x = tcsetattr(ttyfd, TCSANOW, &termbuf);
518 debug(F111,"set_termbuf tcsetattr(ttyfd)",ckitoa(x),errno);
519 #endif /* INIT_SPTY */
521 #endif /* USE_TERMIO */
523 /* termbuf routines (end) */
530 /* Initialize "sa" structure. */
531 sigemptyset(&sa.sa_mask);
533 sa.sa_handler = SIG_IGN;
534 sigaction(SIGHUP, &sa, (struct sigaction *)0);
536 sa.sa_handler = SIG_DFL;
537 sigaction(SIGHUP, &sa, (struct sigaction *)0);
538 #else /* CK_POSIX_SIG */
539 signal(SIGHUP,SIG_IGN);
541 signal(SIGHUP,SIG_DFL);
542 #endif /* CK_POSIX_SIG */
543 #endif /* CK_VHANGUP */
547 This routine is called twice. It's not particularly important that the
548 setsid() or TIOCSCTTY ioctls succeed (they may not the second time), but
549 rather that we have a controlling terminal at the end. It is assumed that
550 vhangup doesn't exist and confuse the process's notion of controlling
551 terminal on any system without TIOCNOTTY. That is, either vhangup() leaves
552 the controlling terminal in tact, breaks the association completely, or the
553 system provides TIOCNOTTY to get things back into a reasonable state. In
554 practice, vhangup() either breaks the association completely or doesn't
555 effect controlling terminals, so this condition is met.
558 ptyint_void_association() {
562 "ptyint_void_association()",
567 #endif /* HAVE_SETSID */
570 /* Void tty association first */
572 con_fd = open("/dev/tty", O_RDWR);
574 "ptyint_void_association() open(/dev/tty,O_RDWR)",
578 ioctl(con_fd, TIOCNOTTY, 0);
582 else debug(F101, "ptyint_void_association() open() errno","",errno);
584 #endif /* TIOCNOTTY */
585 #endif /* NO_DEVTTY */
589 /* PID may be zero for unknown.*/
592 pty_cleanup(slave, pid, update_utmp) char *slave; int pid; int update_utmp; {
595 #endif /* VHANG_LAST */
597 debug(F111,"pty_cleanup()",slave,pid);
600 pty_update_utmp(PTY_DEAD_PROCESS,
605 PTY_UTMP_USERNAME_VALID
607 #endif /* WANT_UTMP */
617 Revoke isn't guaranteed to send a SIGHUP to the processes it
618 dissociates from the terminal. The best solution without a Posix
619 mechanism for forcing a hangup is to killpg() the process group of the
620 pty. This will at least kill the shell and hopefully, the child
621 processes. This is not always the case, however. If the shell puts
622 each job in a process group and doesn't pass along SIGHUP, all
623 processes may not die.
629 kill(-(pid), SIGHUP);
630 #endif /*HAVE_KILLPG*/
632 #else /* HAVE_REVOKE*/
639 sigaddset(&new, SIGCHLD);
640 sigprocmask(SIG_BLOCK, &new, &old);
641 #else /*CK_POSIX_SIG*/
642 int mask = sigblock(sigmask(SIGCHLD));
643 #endif /*CK_POSIX_SIG*/
644 switch (retval = fork()) {
647 sigprocmask(SIG_SETMASK, &old, 0);
648 #else /*CK_POSIX_SIG*/
650 #endif /*CK_POSIX_SIG*/
653 ptyint_void_association();
654 if (retval = (pty_open_ctty(slave, &fd, -1)))
661 waitpid(retval, &status, 0);
662 #else /*HAVE_WAITPID*/
664 #endif /* HAVE_WAITPID */
666 sigprocmask(SIG_SETMASK, &old, 0);
667 #else /*CK_POSIX_SIG*/
669 #endif /*CK_POSIX_SIG*/
673 #endif /*VHANG_LAST*/
674 #endif /* HAVE_REVOKE*/
676 slave[strlen("/dev/")] = 'p';
681 #endif /* HAVE_STREAMS */
686 pty_getpty(fd, slave, slavelength) int slavelength; int *fd; char *slave; {
694 #endif /* HAVE__GETPTY */
695 #endif /* HAVE_OPENPTY */
697 char *slaveret; /* Temp to hold pointer to slave */
698 #endif /*HAVE__GETPTY*/
704 debug(F100,"HAVE_OPENPTY","",0);
718 #else /* HAVE_OPENPTY */
722 This code is included for Irix; as of version 5.3, Irix has /dev/ptmx, but
723 it fails to work properly; even after calling unlockpt, root gets permission
724 denied opening the pty. The code to support _getpty should be removed if
725 Irix gets working streams ptys in favor of maintaining the least needed code
728 debug(F100,"HAVE__GETPTY","",0);
729 if ((slaveret = _getpty(fd, O_RDWR | O_NDELAY, 0600, 0)) == 0) {
731 return(PTY_GETPTY_NOPTY);
733 if (strlen(slaveret) > slavelength - 1) {
736 return(PTY_GETPTY_SLAVE_TOOLONG);
738 ckstrncpy(slave, slaveret, slavelength);
742 #else /* HAVE__GETPTY */
744 *fd = open("/dev/ptym/clone", O_RDWR|O_NDELAY); /* HPUX */
746 debug(F110,"pty_getpty()","open(/dev/ptym/clone) success",0);
751 debug(F100,"HAVE_PTMX","",0);
752 *fd = open("/dev/ptmx",O_RDWR|O_NDELAY);
754 debug(F110,"pty_getpty()","open(/dev/ptmx) success",0);
757 #endif /* HAVE_PTMX */
759 *fd = open("/dev/ptc", O_RDWR|O_NDELAY); /* AIX */
761 debug(F110,"pty_getpty()","open(/dev/ptc) success",0);
764 *fd = open("/dev/pty", O_RDWR|O_NDELAY); /* sysvimp */
766 debug(F110,"pty_getpty()","open(/dev/pty) success",0);
769 /* This would be the pty master */
770 debug(F101,"pty_getpty fd(A)","",*fd);
776 debug(F100,"HAVE_GRANTPT","",0);
777 if (grantpt(*fd) || unlockpt(*fd))
778 return(PTY_GETPTY_STREAMS);
779 #endif /* HAVE_PTMX */
780 #endif /* HAVE_GRANTPT */
783 debug(F100,"HAVE_PTSNAME","",0);
784 p = (char *)ptsname(*fd);
785 debug(F110,"pty_getpty() ptsname()",p,0);
788 debug(F100,"HAVE_TTYNAME","",0);
790 debug(F110,"pty_getpty() ttyname()",p,0);
792 /* If we don't have either what do we do? */
793 return(PTY_GETPTY_NOPTY); /* punt */
794 #endif /* HAVE_TTYNAME */
795 #endif /* HAVE_PTSNAME */
797 if (strlen(p) > slavelength - 1) {
800 return(PTY_GETPTY_SLAVE_TOOLONG);
802 ckstrncpy(slave, p, slavelength);
805 if (fstat(*fd, &stb) < 0) {
807 return(PTY_GETPTY_FSTAT);
809 ptynum = (int)(stb.st_rdev&0xFF);
810 sprintf(slavebuf, "/dev/ttyp%x", ptynum); /* safe */
811 if (strlen(slavebuf) > slavelength - 1) {
814 return(PTY_GETPTY_SLAVE_TOOLONG);
816 debug(F110,"pty_getpty() slavebuf",slavebuf,0);
817 ckstrncpy(slave, slavebuf, slavelength);
820 for (cp = "pqrstuvwxyzPQRST";*cp; cp++) {
821 sprintf(slavebuf,"/dev/ptyXX"); /* safe */
822 slavebuf[sizeof("/dev/pty") - 1] = *cp;
823 slavebuf[sizeof("/dev/ptyp") - 1] = '0';
824 if (stat(slavebuf, &stb) < 0)
826 for (i = 0; i < 16; i++) {
827 slavebuf[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i];
829 *fd = open(slavebuf, O_RDWR|O_NDELAY);
831 debug(F111,"pty_getpty() pty master open error",
835 debug(F111,"pty_getpty() found pty master",slavebuf,*fd);
836 slavebuf[sizeof("/dev/") - 1] = 't'; /* got pty */
837 if (strlen(slavebuf) > slavelength -1) {
840 return(PTY_GETPTY_SLAVE_TOOLONG);
842 ckstrncpy(slave, slavebuf, slavelength);
843 debug(F110,"pty_getpty slave name",slave,0);
848 return(PTY_GETPTY_NOPTY);
850 #endif /*HAVE__GETPTY*/
851 #endif /* HAVE_OPENPTY */
858 debug(F100,"HAVE_PTYM","",0);
859 tty_bank = &master_name[strlen("/dev/ptym/pty")];
860 tty_num = &master_name[strlen("/dev/ptym/ptyX")];
861 slave_bank = &slave_name[strlen("/dev/pty/tty")];
862 slave_num = &slave_name[strlen("/dev/pty/ttyX")];
868 The following is an array of modules that should be pushed on the stream.
869 See configure.in for caviats and notes about when this array is used and not
873 #ifndef HAVE_LINE_PUSH
874 static char *push_list[] = {
886 #endif /* HAVE_LINE_PUSH */
887 #endif /* HAVE_STREAMS */
890 pty_initialize_slave (fd) int fd; {
893 struct termios new_termio;
899 #endif /* POSIX_TERMIOS */
905 #endif /* POSIX_TERMIOS */
907 debug(F111,"pty_initialize_slave()","fd",fd);
910 #ifdef HAVE_LINE_PUSH
911 while (ioctl(fd,I_POP,0) == 0) ; /* Clear out any old lined's */
913 if (line_push(fd) < 0) {
914 debug(F110,"pty_initialize_slave()","line_push() failed",0);
917 return(PTY_OPEN_SLAVE_LINE_PUSHFAIL);
919 #else /*No line_push */
921 char **module = &push_list[0];
923 if (ioctl(fd, I_PUSH, *(module++)) < 0) {
924 debug(F110,"pty_initialize_slave()","ioctl(I_PUSH) failed",0);
925 return(PTY_OPEN_SLAVE_PUSH_FAIL);
930 #endif /*HAVE_STREAMS*/
932 Under Ultrix 3.0, the pgrp of the slave pty terminal needs to be set
933 explicitly. Why rlogind works at all without this on 4.3BSD is a mystery.
935 #ifdef GETPGRP_ONEARG
936 pid = getpgrp(getpid());
939 #endif /* GETPGRP_ONEARG */
941 debug(F111,"pty_initialize_slave()","pid",pid);
944 ioctl(fd, TIOCSPGRP, &pid);
945 #endif /* TIOCSPGRP */
951 rc = tcgetattr(fd,&new_termio);
952 debug(F111,"pty_initialize_slave tcgetattr(fd)",ckitoa(rc),errno);
954 new_termio.c_cc[VMIN] = 1;
955 new_termio.c_cc[VTIME] = 0;
956 rc = tcsetattr(fd,TCSANOW,&new_termio);
957 debug(F111,"pty_initialize_slave tcsetattr(fd)",ckitoa(rc),errno);
960 #endif /* POSIX_TERMIOS */
966 pty_logwtmp (tty, user, host) char *user, *tty, *host; {
968 logwtmp(tty,user,host);
974 int loggingin = user[0]; /* Will be empty for logout */
977 strncpy(ut.ut_host, host, sizeof(ut.ut_host));
978 #endif /* NO_UT_HOST */
980 strncpy(ut.ut_line, tty, sizeof(ut.ut_line));
981 ut.ut_time = time(0);
984 ut.ut_pid = getpid();
985 strncpy(ut.ut_user, user, sizeof(ut.ut_user));
987 tmpx = tty + strlen(tty) - 2;
988 ckmakmsg(utmp_id,5,"kr",tmpx,NULL,NULL);
989 strncpy(ut.ut_id, utmp_id, sizeof(ut.ut_id));
990 ut.ut_pid = (loggingin ? getpid() : 0);
991 ut.ut_type = (loggingin ? USER_PROCESS : DEAD_PROCESS);
993 strncpy(ut.ut_name, user, sizeof(ut.ut_name));
994 #endif /* NO_UT_PID */
996 return(ptyint_update_wtmp(&ut, host, user));
998 #endif /* HAVE_LOGWTMP */
1000 #endif /* WANT_UTMP */
1003 This routine is called twice. It's not particularly important that the
1004 setsid() or TIOCSCTTY ioctls succeed (they may not the second time), but
1005 rather that we have a controlling terminal at the end. It is assumed that
1006 vhangup doesn't exist and confuse the process's notion of controlling
1007 terminal on any system without TIOCNOTTY. That is, either vhangup() leaves
1008 the controlling terminal in tact, breaks the association completely, or the
1009 system provides TIOCNOTTY to get things back into a reasonable state. In
1010 practice, vhangup() either breaks the association completely or doesn't
1011 effect controlling terminals, so this condition is met.
1014 pty_open_ctty(slave, fd, fc) char * slave; int *fd; int fc; {
1017 debug(F110,"pty_open_ctty() slave",slave,0);
1019 /* First, dissociate from previous terminal */
1021 if ((retval = ptyint_void_association()) != 0) {
1024 "ptyint_void_association() failed",
1031 The Ultrix (and other BSD tty drivers) require the process group
1032 to be zero in order to acquire the new tty as a controlling tty.
1035 debug(F101,"pty_open_ctty MUST_SETPGRP setpgrp(0,0)","",errno);
1036 #endif /* MUST_SETPGRP */
1039 *fd = open(slave, O_RDWR);
1040 debug(F111,"pty_open_ctty open(slave) fd",slave,*fd);
1042 debug(F111,"pty_open_ctty() open failure", slave, errno);
1043 return(PTY_OPEN_SLAVE_OPENFAIL);
1046 /* This forces the job to have a controlling terminal. */
1048 *fd = open(slave, O_RDWR);
1049 debug(F111,"pty_open_ctty close/open(slave) fd",slave,*fd);
1051 /* This shows that /dev/tty exists */
1054 x = open("/dev/tty", O_RDWR);
1055 debug(F111,"pty_open_ctty open(/dev/tty) fd",slave,x);
1056 if (x < 0) debug(F111,"pty_open_ctty open(/dev/tty) errno","",errno);
1057 debug(F110,"pty_open_ctty ttyname(/dev/tty)",ttyname(x),0);
1058 if (x > -1) close(x);
1061 #endif /* SOLARIS */
1064 setpgrp(0, getpid());
1065 #endif /* MUST_SETPGRP */
1073 #endif /* COMMENT */
1075 /* TIOCSCTTY = Make this the job's controlling terminal */
1077 retval = ioctl(*fd, TIOCSCTTY, 0); /* Don't check return.*/
1078 debug(F111,"pty_open_ctty() ioctl TIOCSCTTY",ckitoa(retval),errno);
1080 #endif /* TIOCSCTTY */
1085 pty_open_slave(slave, fd, fc) char *slave; int *fd; int fc; {
1089 struct sigaction sa;
1091 sigemptyset(&sa.sa_mask); /* Initialize "sa" structure. */
1093 #endif /* CK_POSIX_SIG */
1096 First, chmod and chown the slave. If we have vhangup then we really need
1097 pty_open_ctty to make sure our controlling terminal is the pty we're
1098 opening. However, if we are using revoke or nothing then we just need a
1099 file descriiptor for the pty. Considering some OSes in this category break
1100 on the second call to open_ctty (currently OSF but others may), we simply
1101 use a descriptor if we can.
1104 if ((retval = pty_open_ctty(slave, &vfd, fc)) != 0) {
1106 "pty_open_slave() VHANG_FIRST",
1107 "pty_open_ctty() failed",
1114 "pty_open_slave() VHANG_FIRST",
1115 "PTY_OPEN_SLAVE_OPENFAIL",
1118 return(PTY_OPEN_SLAVE_OPENFAIL);
1120 #endif /* VHANG_FIRST */
1122 if (slave == NULL || *slave == '\0') {
1123 debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_TOOSHORT",0);
1124 return(PTY_OPEN_SLAVE_TOOSHORT);
1128 if (chmod(slave, 0)) {
1129 debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_CHMODFAIL",0);
1130 return(PTY_OPEN_SLAVE_CHMODFAIL);
1132 if (chown(slave, 0, 0 ) == -1 ) {
1133 debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_CHOWNFAIL",0);
1134 return(PTY_OPEN_SLAVE_CHOWNFAIL);
1140 #endif /* VHANG_FIRST */
1142 if ((retval = ptyint_void_association()) != 0) {
1145 "ptyint_void_association() failed",
1152 if (revoke (slave) < 0 ) {
1153 debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_REVOKEFAIL",0);
1154 return(PTY_OPEN_SLAVE_REVOKEFAIL);
1156 #endif /* HAVE_REVOKE */
1158 /* Open the pty for real. */
1160 retval = pty_open_ctty(slave, fd, fc);
1161 debug(F111,"pty_open_slave retval",slave,retval);
1162 debug(F111,"pty_open_slave fd",slave,*fd);
1164 debug(F111,"pty_open_slave()","pty_open_ctty() failed",retval);
1165 return(PTY_OPEN_SLAVE_OPENFAIL);
1167 pty_slave_fd = *fd; /* This is not visible to the upper fork */
1168 debug(F111,"pty_open_slave fd ctty'd",slave,pty_slave_fd);
1169 retval = pty_initialize_slave(*fd);
1170 debug(F111,"pty_open_slave fd init'd",slave,pty_slave_fd);
1172 debug(F111,"pty_open_slave()","pty_initialize_slave() failed",retval);
1175 /* (VOID)pty_make_raw(*fd); */
1177 debug(F100,"pty_open_slave OK","",*fd);
1185 #define UTMP_FILE _PATH_UTMP
1186 #endif /* _PATH_UTMP */
1187 #endif /* UTMP_FILE */
1189 /* If it is *still* missing, assume /etc/utmp */
1192 #define UTMP_FILE "/etc/utmp"
1193 #endif /* UTMP_FILE */
1196 #define WTMP_REQUIRES_USERNAME
1197 #endif /* NO_UT_PID */
1200 pty_update_utmp(process_type, pid, username, line, host, flags)
1203 char *username, *line, *host;
1205 /* pty_update_utmp */ {
1206 struct utmp ent, ut;
1207 #ifndef HAVE_SETUTENT
1210 #endif /* HAVE_SETUTENT */
1211 #ifdef HAVE_SETUTXENT
1213 #endif /* HAVE_SETUTXENT */
1217 #endif /* NO_UT_PID */
1221 debug(F100,"pty_update_utmp()","",0);
1222 strncpy(ent.ut_line, line+sizeof("/dev/")-1, sizeof(ent.ut_line));
1223 ent.ut_time = time(0);
1226 if (process_type == PTY_LOGIN_PROCESS)
1228 #else /* NO_UT_PID */
1232 switch (process_type) {
1233 case PTY_LOGIN_PROCESS:
1234 ent.ut_type = LOGIN_PROCESS;
1236 case PTY_USER_PROCESS:
1237 ent.ut_type = USER_PROCESS;
1239 case PTY_DEAD_PROCESS:
1240 ent.ut_type = DEAD_PROCESS;
1243 return(PTY_UPDATE_UTMP_PROCTYPE_INVALID);
1245 #endif /*NO_UT_PID*/
1249 strncpy(ent.ut_host, host, sizeof(ent.ut_host));
1251 ent.ut_host[0] = '\0';
1252 #endif /* NO_UT_HOST */
1255 if (!strcmp (line, "/dev/console")) {
1268 strncpy(ent.ut_id, s, 4);
1272 tmpx = line + strlen(line)-1;
1273 if (*(tmpx-1) != '/') tmpx--; /* last 2 chars unless it's a '/' */
1275 ckstrncpy(utmp_id, tmpx, 5);
1277 ckmakmsg(utmp_id,5,"kl",tmpx,NULL,NULL);
1279 strncpy(ent.ut_id, utmp_id, sizeof(ent.ut_id));
1281 strncpy(ent.ut_user, username, sizeof(ent.ut_user));
1285 strncpy(ent.ut_name, username, sizeof(ent.ut_name));
1287 #endif /* NO_UT_PID */
1290 strncpy(userbuf, username, sizeof(userbuf));
1294 #ifdef HAVE_SETUTENT
1296 utmpname(UTMP_FILE);
1299 If we need to preserve the user name in the wtmp structure and Our flags
1300 tell us we can obtain it from the utmp and we succeed in obtaining it, we
1301 then save the utmp structure we obtain, write out the utmp structure and
1302 change the username pointer so it is used by update_wtmp.
1305 #ifdef WTMP_REQUIRES_USERNAME
1306 if ((!username[0]) && (flags&PTY_UTMP_USERNAME_VALID) &&line) {
1308 strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1309 utptr = getutline(&ut);
1311 strncpy(userbuf,utptr->ut_user,sizeof(ut.ut_user));
1313 #endif /* WTMP_REQUIRES_USERNAME */
1318 #ifdef HAVE_SETUTXENT
1320 #ifdef HAVE_GETUTMPX
1321 getutmpx(&ent, &utx);
1322 #else /* HAVE_GETUTMPX */
1323 /* For platforms like HPUX and Dec Unix which don't have getutmpx */
1324 strncpy(utx.ut_user, ent.ut_user, sizeof(ent.ut_user));
1325 strncpy(utx.ut_id, ent.ut_id, sizeof(ent.ut_id));
1326 strncpy(utx.ut_line, ent.ut_line, sizeof(ent.ut_line));
1327 utx.ut_pid = pid; /* kludge for Irix, etc. to avoid trunc. */
1328 utx.ut_type = ent.ut_type;
1329 #ifdef UT_EXIT_STRUCTURE_DIFFER
1330 utx.ut_exit.ut_exit = ent.ut_exit.e_exit;
1331 #else /* UT_EXIT_STRUCTURE_DIFFER */
1332 /* KLUDGE for now; eventually this will be a feature test... See PR#[40] */
1334 utx.ut_exit.__e_termination = ent.ut_exit.e_termination;
1335 utx.ut_exit.__e_exit = ent.ut_exit.e_exit;
1337 /* XXX do nothing for now; we don't even know the struct member exists */
1339 #endif /* UT_EXIT_STRUCTURE_DIFFER */
1340 utx.ut_tv.tv_sec = ent.ut_time;
1341 utx.ut_tv.tv_usec = 0;
1342 #endif /* HAVE_GETUTMPX */
1344 strncpy(utx.ut_host, host, sizeof(utx.ut_host));
1349 #endif /* HAVE_SETUTXENT */
1351 #else /* HAVE_SETUTENT */
1352 if (flags&PTY_TTYSLOT_USABLE) {
1357 if ((fd = open(UTMP_FILE, O_RDWR)) < 0)
1360 lseek(fd, (off_t)(lc * sizeof(struct utmp)), SEEK_SET) != -1;
1366 ) != sizeof(struct utmp)
1369 if (strncmp(ut.ut_line, ent.ut_line, sizeof(ut.ut_line)) == 0) {
1371 #ifdef WTMP_REQUIRES_USERNAME
1372 if (!username&&(flags&PTY_UTMP_USERNAME_VALID))
1373 strncpy(userbuf, ut.ut_user, sizeof(ut.ut_user));
1374 #endif /* WTMP_REQUIRES_USERNAME */
1380 if (tty > 0 && (fd = open(UTMP_FILE, O_WRONLY, 0)) >= 0) {
1381 lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
1382 write(fd, (char *)&ent, sizeof(struct utmp));
1385 #endif /* HAVE_SETUTENT */
1387 /* Don't record LOGIN_PROCESS entries. */
1388 if (process_type == PTY_LOGIN_PROCESS)
1391 return(ptyint_update_wtmp(&ent, host, userbuf));
1395 #define WTMP_FILE _PATH_WTMP
1396 #endif /* _PATH_WTMP */
1397 #endif /* WTMP_FILE */
1401 #ifdef HAVE_UPDWTMPX
1402 #define WTMPX_FILE _PATH_WTMPX
1403 #endif /* HAVE_UPDWTMPX */
1404 #endif /* _PATH_WTMPX */
1405 #endif /* WTMPX_FILE */
1407 /* If it is *still* missing, assume /usr/adm/wtmp */
1410 #define WTMP_FILE "/usr/adm/wtmp"
1411 #endif /* WTMP_FILE */
1414 /* The following test can not be made portably */
1416 /* #if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) */
1418 This is ugly, but the lack of standardization in the utmp/utmpx space, and
1419 what glibc implements and doesn't make available, is even worse.
1421 /* #undef HAVE_UPDWTMPX */ /* Don't use updwtmpx for glibc 2.1 */
1422 /* #endif */ /* __GLIBC__ etc */
1427 #undef HAVE_UPDWTMPX /* Don't use updwtmpx for glibc period */
1428 #endif /* __GLIBC__ */
1429 #endif /* COMMENT */
1432 ptyint_update_wtmp(ent,host,user) struct utmp *ent; char *host; char *user; {
1437 #ifdef HAVE_UPDWTMPX
1440 getutmpx(ent, &utx);
1442 strncpy(utx.ut_host, host, sizeof(utx.ut_host) );
1446 strncpy(utx.ut_user, user, sizeof(utx.ut_user));
1447 updwtmpx(WTMPX_FILE, &utx);
1448 #endif /* HAVE_UPDWTMPX */
1451 #ifndef HAVE_UPDWTMPX
1452 /* This is already performed byupdwtmpx if present.*/
1453 updwtmp(WTMP_FILE, ent);
1454 #endif /* HAVE_UPDWTMPX*/
1455 #else /* HAVE_UPDWTMP */
1457 if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) >= 0) {
1458 if (!fstat(fd, &statb)) {
1459 memset((char *)&ut, 0, sizeof(ut));
1461 strncpy(ut.ut_id, ent->ut_id, sizeof (ut.ut_id));
1463 strncpy(ut.ut_line, ent->ut_line, sizeof(ut.ut_line));
1464 strncpy(ut.ut_name, ent->ut_name, sizeof(ut.ut_name));
1466 strncpy(ut.ut_host, ent->ut_host, sizeof(ut.ut_host));
1467 #endif /* NO_UT_HOST */
1470 ut.ut_time = uttime;
1472 #ifdef HAVE_GETUTENT
1476 ut.ut_pid = getpid();
1478 ut.ut_type = USER_PROCESS;
1480 ut.ut_type = ent->ut_type;
1488 ut.ut_type = DEAD_PROCESS; /* For Linux brokenness*/
1492 #endif /* USER_PROCESS */
1493 #endif /* HAVE_GETUTENT */
1495 if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
1496 sizeof(struct utmp))
1498 ftruncate(fd, statb.st_size);
1500 chsize(fd, statb.st_size);
1501 #endif /* COHERENT */
1505 #endif /* HAVE_UPDWTMP */
1506 return(0); /* no current failure cases; file not found is not failure! */
1508 #endif /* WANT_UTMP */
1510 /* This is for ancient Unixes that don't have these tty symbols defined. */
1513 #define PENDIN ICANON
1516 #define FLUSHO ICANON
1519 #define IMAXBEL ICANON
1520 #endif /* IMAXBEL */
1522 #define EXTPROC ICANON
1523 #endif /* EXTPROC */
1525 static char Xline[17] = { 0, 0 };
1528 Open the slave side of the pty, and do any initialization that is necessary.
1529 The return value fd is a file descriptor for the slave side.
1530 fc = function code from do_pty() (q.v.)
1533 getptyslave(fd, fc) int * fd, fc; {
1539 extern int cmd_rows, cmd_cols;
1540 #endif /* TIOCGWINSZ */
1543 debug(F111,"getptyslave()","ttyfd",ttyfd);
1545 * Opening the slave side may cause initilization of the
1546 * kernel tty structure. We need remember the state of:
1547 * if linemode was turned on
1548 * terminal window size
1550 * so that we can reset them if we need to.
1552 if ((retval = pty_open_slave(Xline, &t, fc)) != 0) {
1555 debug(F111,"getptyslave()","Unable to open slave",retval);
1558 debug(F111,"getptyslave","t",t);
1561 debug(F111,"getptyslave","spty",spty);
1562 #endif /* INIT_SPTY */
1564 if (ioctl(t,I_PUSH,"pckt") < 0) {
1565 debug(F111,"getptyslave()","ioctl(I_PUSH) failed",errno);
1567 fatal("I_PUSH pckt");
1570 #endif /* STREAMSPTY */
1572 /* Set up the tty modes as we like them to be. */
1574 /* Originally like this... But this is the master - we want the slave */
1575 /* Anyway, this fails on Solaris and probably other System V OS's */
1576 init_termbuf(ttyfd);
1579 #endif /* COMMENT */
1581 if (cmd_rows || cmd_cols) {
1582 memset((char *)&ws, 0, sizeof(ws));
1583 ws.ws_col = cmd_cols;
1584 ws.ws_row = cmd_rows;
1585 debug(F101,"getptyslave() doing TIOCSWINSZ...","",t);
1586 ioctl(t, TIOCSWINSZ, (char *)&ws);
1588 #endif /* TIOCGWINSZ */
1590 /* For external protocols, put the pty in no-echo mode */
1592 debug(F100,"getptyslave() setting rawmode","",0);
1594 termbuf.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
1595 termbuf.c_iflag &= ~(INPCK|IGNPAR|IMAXBEL|IXANY|IXON|IXOFF);
1596 termbuf.c_iflag |= IGNBRK;
1598 termbuf.c_iflag &= ~IUCLC;
1602 termbuf.c_oflag &= ~OPOST;
1604 termbuf.c_oflag &= ~OXTABS;
1607 termbuf.c_oflag &= ~ONOCR;
1610 termbuf.c_oflag &= ~ONLRET;
1613 termbuf.c_oflag &= ~ONLCR;
1617 termbuf.c_lflag &= ~ECHO;
1619 termbuf.c_lflag &= ~ECHOE;
1622 termbuf.c_lflag &= ~ECHONL;
1625 termbuf.c_lflag &= ~ECHOPRT;
1626 #endif /* ECHOPRT */
1628 termbuf.c_lflag &= ~ECHOKE;
1631 termbuf.c_lflag &= ~ECHOCTL;
1632 #endif /* ECHOCTL */
1634 termbuf.c_lflag &= ~ALTWERASE;
1635 #endif /* ALTWERASE */
1637 termbuf.c_lflag &= ~EXTPROC;
1638 #endif /* EXTPROC */
1639 termbuf.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
1642 termbuf.c_lflag |= NOKERNINFO;
1643 #endif /* NOKERNINFO */
1644 /* termbuf.c_lflag |= NOFLSH; */
1645 termbuf.c_lflag &= ~NOFLSH;
1648 termbuf.c_cflag &= ~(CSIZE|PARENB|PARODD);
1649 termbuf.c_cflag |= CS8|CREAD;
1651 termbuf.c_cc[VMIN] = 1;
1653 } else { /* Regular interactive use */
1654 debug(F100,"getptyslave() setting cooked mode","",0);
1656 /* Settings for sgtty based systems */
1659 termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
1660 #endif /* USE_TERMIO */
1666 /* Settings for UNICOS and HPUX */
1669 termbuf.c_oflag = OPOST|ONLCR|TAB3;
1670 termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
1671 termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
1672 termbuf.c_cflag = EXTB|HUPCL|CS8;
1675 termbuf.c_oflag = OPOST|ONLCR|TAB3;
1676 termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
1677 termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
1678 termbuf.c_cflag = EXTB|HUPCL|CS8;
1682 Settings for all other termios/termio based systems, other than
1683 4.4BSD. In 4.4BSD the kernel does the initial terminal setup.
1687 termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG;
1688 termbuf.c_oflag |= ONLCR|OXTABS|OPOST;
1689 termbuf.c_iflag |= ICRNL|IGNPAR;
1690 termbuf.c_cflag |= HUPCL;
1691 termbuf.c_iflag &= ~IXOFF;
1694 termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG;
1695 termbuf.c_oflag |= ONLCR|OXTABS|OPOST;
1696 termbuf.c_iflag |= ICRNL|IGNPAR;
1697 termbuf.c_cflag |= HUPCL;
1698 termbuf.c_iflag &= ~IXOFF;
1700 #endif /* USE_TERMIO */
1705 /* Set the tty modes, and make this our controlling tty. */
1707 /* But this is the master - we want the slave */
1711 #endif /* COMMENT */
1720 } else if (fc == 1) {
1721 /* For external protocols, send stderr to /dev/null */
1725 char * s = "/dev/null";
1727 xx = open(s, O_WRONLY);
1729 char * s = "pty.log";
1731 xx = open(s, O_CREAT, 0644);
1732 #endif /* COMMENT */
1733 debug(F111,"getptyslave redirect stderr",s,errno);
1735 #endif /* COMMENT */
1751 To be called to determine if a trap is pending on a pty
1752 if and only if select() cannot be used.
1755 pty_trap_pending(fd) int fd; {
1759 rc = ioctl(fd, TIOCTRAPSTATUS, (char *)&pending, sizeof(pending));
1761 debug(F101,"pty_trap_pending()","",pending);
1764 debug(F111,"pty_trap_pending()","ioctl() failed",rc);
1770 To be called after select() has returned indicating that an exception is
1771 waiting on a pty. It should be called with the file descriptor of the pty.
1772 Returns -1 on error; 0 if pty is still open; 1 if pty has closed.
1775 pty_trap_handler(fd) int fd; {
1776 struct request_info ri;
1778 memset(&ri,0,sizeof(ri));
1779 if (ioctl(fd,TIOCREQCHECK,(char *)&ri, sizeof(ri)) != 0) {
1780 debug(F111,"pty_trap_handler()","ioctl(TIOCREQCHECK) failed",errno);
1783 switch (ri.request) {
1785 debug(F110,"pty_trap_handler()","an open() call",0);
1788 debug(F110,"pty_trap_handler()","a close() call",0);
1791 debug(F110,"pty_trap_handler()","an ioctl() call",0);
1792 ri.errno_error = EINVAL;
1794 if (ioctl(fd, TIOCREQSET, (char *)&ri,sizeof(ri)) != 0) {
1795 debug(F111,"pty_trap_handler()","ioctl(TIOCREQSET) failed",errno);
1798 if (ri.request == TIOCCLOSE)
1803 #endif /* HAVE_PTYTRAP */
1806 exec_cmd(s) char * s; {
1807 struct stringarray * q;
1808 char ** args = NULL;
1813 q = cksplit(1,0,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",7,0,0);
1816 args = q->a_head + 1;
1822 for (i = 0; i <= n; i++) {
1824 debug(F111,"exec_cmd arg","NULL",i);
1827 debug(F111,"exec_cmd arg",args[i],i);
1828 if (i == n && args[i]) {
1829 debug(F101,"exec_cmd SUBSTITUTING NULL","",i);
1830 if (strlen(args[i]) == 0)
1831 makestr(&(args[i]),NULL);
1839 execvp(args[0],args);
1842 /* Get a pty, scan input lines. */
1843 /* fc = 0 for interactive access; fc = 1 for running external protocols */
1845 static int pty_fc = -1; /* Global copy of fc */
1848 do_pty(fd, cmd, fc) int * fd; char * cmd; int fc; {
1854 #endif /* HAVE_PTYTRAP */
1856 debug(F101,"CKUPTY.C do_pty fc","",fc);
1864 msg = 0; /* Message counter */
1865 pty_init(); /* Find an available pty to use. */
1868 if ((retval = pty_getpty(&ttyfd, Xline, 20)) != 0) {
1871 debug(F111,"do_pty()","pty_getpty() fails",retval);
1876 debug(F111,"do_pty() Xline",Xline,ttyfd);
1880 Ignoring SIGTTOU keeps the kernel from blocking us. we tweak the tty with
1881 an ioctl() (in ttioct() in /sys/tty.c in a BSD kernel)
1883 signal(SIGTTOU, SIG_IGN);
1884 #endif /* SIGTTOU */
1886 /* Start up the command on the slave side of the terminal */
1888 if (pipe(syncpipe) < 0) {
1889 debug(F110,"do_pty()","pipe() fails",0);
1890 perror("pipe() failed");
1892 debug(F111,"do_pty()","pipe fails",errno);
1895 if ((i = fork()) < 0) {
1896 /* XXX - need to clean up the allocated pty */
1897 perror("fork() failed");
1899 debug(F111,"do_pty()","fork fails",errno);
1902 if (i) { /* Wait for child before writing to parent side of pty. */
1906 #endif /* HAVE_PTYTRAP */
1909 if (read(syncpipe[0], &c, 1) == 0) { /* Slave side died */
1910 perror("Pipe read() failed");
1912 debug(F110,"do_pty()","Slave fails to initialize",0);
1916 pty_fork_pid = i; /* So we can clean it up later */
1917 pty_fork_active = 1;
1918 debug(F101,"do_pty pty_fork_pid","",pty_fork_pid);
1920 /* HPUX does not allow the master to read end of file. */
1921 /* Therefore, we must determine that the slave has been */
1922 /* closed by trapping the call to close(). */
1924 x = ioctl(ttyfd, TIOCTRAP, (char *)&on);
1925 debug(F111,"do_pty ioctl(TIOCTRAP)",ckitoa(x),errno);
1926 #endif /* HAVE_PTYTRAP */
1927 debug(F111,"do_pty()","synchronized - pty_fork_pid",pty_fork_pid);
1931 debug(F101,"do_pty getptyslave ttyfd A","",ttyfd);
1932 debug(F110,"do_pty()","Slave starts",0);
1933 x = getptyslave(&ttyfd,fc);
1934 debug(F101,"do_pty getptyslave","",x);
1936 debug(F101,"do_pty getptyslave ttyfd B","",ttyfd);
1938 pty_update_utmp(PTY_USER_PROCESS,
1945 #endif /* WANT_UTMP */
1946 /* Notify our parent we're ready to continue.*/
1947 debug(F110,"do_pty()","slave synchronizing",0);
1948 write(syncpipe[1],"y",1);
1952 debug(F110,"do_pty cmd",cmd,"");
1954 debug(F111,"do_pty()","exec_cmd() returns - why?",errno);
1957 debug(F110,"do_pty()","getptyslave() fails - exiting",0);
1963 } /* end of do_pty() */
1968 msg = 0; /* Message counter */
1969 debug(F101,"end_pty pty_fork_pid","",pty_fork_pid);
1970 if (Xline[0] && pty_fork_pid >= 0) {
1971 pty_cleanup(Xline,pty_fork_pid,1);
1974 pty_fork_active = 0;
1975 debug(F101,"end_pty pty_fork_active","",pty_fork_active);