/ util / pty.c
pty.c
  1  /*
  2   * Copyright (c) 1999, 2007 Apple Inc. All rights reserved.
  3   *
  4   * @APPLE_LICENSE_HEADER_START@
  5   * 
  6   * This file contains Original Code and/or Modifications of Original Code
  7   * as defined in and that are subject to the Apple Public Source License
  8   * Version 2.0 (the 'License'). You may not use this file except in
  9   * compliance with the License. Please obtain a copy of the License at
 10   * http://www.opensource.apple.com/apsl/ and read it before using this
 11   * file.
 12   * 
 13   * The Original Code and all software distributed under the License are
 14   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 15   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 16   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 17   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 18   * Please see the License for the specific language governing rights and
 19   * limitations under the License.
 20   * 
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  /*
 24   * Copyright (c) 1990, 1993, 1994
 25   *	The Regents of the University of California.  All rights reserved.
 26   *
 27   * Redistribution and use in source and binary forms, with or without
 28   * modification, are permitted provided that the following conditions
 29   * are met:
 30   * 1. Redistributions of source code must retain the above copyright
 31   *    notice, this list of conditions and the following disclaimer.
 32   * 2. Redistributions in binary form must reproduce the above copyright
 33   *    notice, this list of conditions and the following disclaimer in the
 34   *    documentation and/or other materials provided with the distribution.
 35   * 3. All advertising materials mentioning features or use of this software
 36   *    must display the following acknowledgement:
 37   *	This product includes software developed by the University of
 38   *	California, Berkeley and its contributors.
 39   * 4. Neither the name of the University nor the names of its contributors
 40   *    may be used to endorse or promote products derived from this software
 41   *    without specific prior written permission.
 42   *
 43   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 44   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 45   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 46   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 47   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 48   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 49   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 50   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 51   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 52   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 53   * SUCH DAMAGE.
 54   */
 55  
 56  
 57  #include <sys/types.h>
 58  #include <sys/ioctl.h>
 59  #include <sys/stat.h>
 60  
 61  #include <errno.h>
 62  #include <fcntl.h>
 63  #include <grp.h>
 64  #include <stdio.h>
 65  #include <stdlib.h>
 66  #include <string.h>
 67  #include <termios.h>
 68  #include <unistd.h>
 69  #include <util.h>
 70  #include <syslog.h>
 71  
 72  int openpty(amaster, aslave, name, termp, winp)
 73  	int *amaster, *aslave;
 74  	char *name;
 75  	struct termios *termp;
 76  	struct winsize *winp;
 77  {
 78  	int master, slave;
 79  	char sname[128];
 80  
 81  	if ((master = posix_openpt(O_RDWR|O_NOCTTY)) < 0)
 82  		return -1;
 83  	if (grantpt(master) < 0 || unlockpt(master) < 0
 84  	    || ptsname_r(master, sname, sizeof(sname)) == -1
 85  	    || (slave = open(sname, O_RDWR|O_NOCTTY, 0)) < 0) {
 86  		(void) close(master);
 87  		return -1;
 88  	}
 89  	*amaster = master;
 90  	*aslave = slave;
 91  	if (name)
 92  		strcpy(name, sname);
 93  	if (termp)
 94  		(void) tcsetattr(slave, TCSAFLUSH, termp);
 95  	if (winp)
 96  		(void) ioctl(slave, TIOCSWINSZ, (char *)winp);
 97  	return (0);
 98  }
 99  
100  int
101  forkpty(amaster, name, termp, winp)
102  	int *amaster;
103  	char *name;
104  	struct termios *termp;
105  	struct winsize *winp;
106  {
107  	int master, slave, pid;
108  
109  	if (openpty(&master, &slave, name, termp, winp) == -1)
110  		return (-1);
111  	switch (pid = fork()) {
112  	case -1:
113  		return (-1);
114  	case 0:
115  		/* 
116  		 * child
117  		 */
118  		(void) close(master);
119  		/*
120  		 * 4300297: login_tty() may fail to set the controlling tty.
121  		 * Since we have already forked, the best we can do is to 
122  		 * dup the slave as if login_tty() succeeded.
123  		 */
124  		if (login_tty(slave) < 0) {
125  			syslog(LOG_ERR, "forkpty: login_tty could't make controlling tty");
126  			(void) dup2(slave, 0);
127  			(void) dup2(slave, 1);
128  			(void) dup2(slave, 2);
129  			if (slave > 2)
130  				(void) close(slave);
131  		}
132  		return (0);
133  	}
134  	/*
135  	 * parent
136  	 */
137  	*amaster = master;
138  	(void) close(slave);
139  	return (pid);
140  }