pty.c revision 175350
161033Sdfr/*- 261033Sdfr * Copyright (c) 1990, 1993, 1994 361033Sdfr * The Regents of the University of California. All rights reserved. 461033Sdfr * 561033Sdfr * Redistribution and use in source and binary forms, with or without 661033Sdfr * modification, are permitted provided that the following conditions 761033Sdfr * are met: 861033Sdfr * 1. Redistributions of source code must retain the above copyright 961033Sdfr * notice, this list of conditions and the following disclaimer. 1061033Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1161033Sdfr * notice, this list of conditions and the following disclaimer in the 1261033Sdfr * documentation and/or other materials provided with the distribution. 1361033Sdfr * 4. Neither the name of the University nor the names of its contributors 1461033Sdfr * may be used to endorse or promote products derived from this software 1561033Sdfr * without specific prior written permission. 1661033Sdfr * 1761033Sdfr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1861033Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1961033Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2061033Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2161033Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2261033Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2361033Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2461033Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2561033Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2661033Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27116182Sobrien * SUCH DAMAGE. 28116182Sobrien */ 29116182Sobrien 3061033Sdfr#include <sys/cdefs.h> 3185521Sjhb__FBSDID("$FreeBSD: head/lib/libutil/pty.c 175350 2008-01-15 13:59:13Z cperciva $"); 3265822Sjhb 3385560Sjhb#if defined(LIBC_SCCS) && !defined(lint) 3461033Sdfr#if 0 35123614Sjhbstatic char sccsid[] = "@(#)pty.c 8.3 (Berkeley) 5/16/94"; 36225570Sadrian#endif 3785521Sjhb#endif /* LIBC_SCCS and not lint */ 3861033Sdfr 3985521Sjhb#include <sys/types.h> 40145729Ssam#include <sys/ioctl.h> 41154333Sscottl#include <sys/stat.h> 4285521Sjhb 43119708Sken#include <errno.h> 44154333Sscottl#include <fcntl.h> 4561033Sdfr#include <grp.h> 4669774Sphk#include <libutil.h> 47123614Sjhb#include <stdlib.h> 48123614Sjhb#include <string.h> 4967551Sjhb#include <termios.h> 50213813Smdf#include <unistd.h> 51213813Smdf 52213813Smdfint __use_pts(void); 53213813Smdf 54213813Smdfstatic int 5561033Sdfrnew_openpty(int *amaster, int *aslave, char *name, struct termios *termp, 5661033Sdfr struct winsize *winp) 5761033Sdfr{ 5861033Sdfr const char *slavename; 59213813Smdf int master, slave; 6085521Sjhb 61178015Ssam master = posix_openpt(O_RDWR); 62178015Ssam if (master == -1) 63180588Skmacy return (-1); 64154333Sscottl 65221059Skib if (grantpt(master) == -1) { 6661033Sdfr close(master); 6761033Sdfr return (-1); 68154333Sscottl } 69177621Sscottl 70177621Sscottl slavename = ptsname(master); 71154333Sscottl if (slavename == NULL) { 72221059Skib close(master); 73221059Skib return (-1); 74215021Sjmallett } 75215021Sjmallett 76215021Sjmallett if (revoke(slavename) == -1) { 77215021Sjmallett close(master); 78215021Sjmallett return (-1); 79215021Sjmallett } 80215021Sjmallett 81154167Sscottl slave = open(slavename, O_RDWR); 82215021Sjmallett if (slave == -1) { 83215021Sjmallett close(master); 84215021Sjmallett return (-1); 85215021Sjmallett } 86215021Sjmallett 87215021Sjmallett if (unlockpt(master) == -1) { 88215021Sjmallett close(master); 89154167Sscottl close(slave); 90221059Skib return (-1); 91221059Skib } 92221059Skib 93221059Skib *amaster = master; 94221059Skib *aslave = slave; 95221059Skib 96221059Skib if (name) 97221059Skib strcpy(name, ptsname(master)); 98221059Skib if (termp) 99221059Skib tcsetattr(slave, TCSAFLUSH, termp); 100221059Skib if (winp) 101154167Sscottl ioctl(slave, TIOCSWINSZ, (char *)winp); 102154167Sscottl 103154167Sscottl return (0); 104154167Sscottl} 105180588Skmacy 106154167Sscottlint 107154167Sscottlopenpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp) 108154167Sscottl{ 109154167Sscottl char line[] = "/dev/ptyXX"; 110154167Sscottl const char *cp1, *cp2; 111215750Savg int master, slave, ttygid; 112145729Ssam struct group *gr; 113154167Sscottl 11461033Sdfr if (__use_pts()) 11561033Sdfr return (new_openpty(amaster, aslave, name, termp, winp)); 116180588Skmacy 11785521Sjhb if ((gr = getgrnam("tty")) != NULL) 11861033Sdfr ttygid = gr->gr_gid; 119188058Simp else 120180588Skmacy ttygid = -1; 12161033Sdfr 122213813Smdf for (cp1 = "pqrsPQRSlmnoLMNO"; *cp1; cp1++) { 12361033Sdfr line[8] = *cp1; 12461033Sdfr for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) { 125180588Skmacy line[5] = 'p'; 126180588Skmacy line[9] = *cp2; 127154167Sscottl if ((master = open(line, O_RDWR, 0)) == -1) { 12861033Sdfr if (errno == ENOENT) 12961033Sdfr break; /* try the next pty group */ 13061033Sdfr } else { 13161033Sdfr line[5] = 't'; 132154167Sscottl (void) chown(line, getuid(), ttygid); 133154167Sscottl (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP); 134154333Sscottl (void) revoke(line); 135154167Sscottl if ((slave = open(line, O_RDWR, 0)) != -1) { 136154333Sscottl *amaster = master; 137154167Sscottl *aslave = slave; 138154167Sscottl if (name) 139154167Sscottl strcpy(name, line); 140145729Ssam if (termp) 141145729Ssam (void) tcsetattr(slave, 142145729Ssam TCSAFLUSH, termp); 143145729Ssam if (winp) 144178015Ssam (void) ioctl(slave, TIOCSWINSZ, 145145729Ssam (char *)winp); 146145729Ssam return (0); 147221059Skib } 148154333Sscottl (void) close(master); 149154333Sscottl } 150145729Ssam } 151145729Ssam } 152145729Ssam errno = ENOENT; /* out of ptys */ 15361033Sdfr return (-1); 15461033Sdfr} 15561033Sdfr 15685521Sjhbint 157154167Sscottlforkpty(int *amaster, char *name, struct termios *termp, struct winsize *winp) 158154333Sscottl{ 159178015Ssam int master, slave, pid; 160213813Smdf 161221059Skib if (openpty(&master, &slave, name, termp, winp) == -1) 16285521Sjhb return (-1); 163178015Ssam switch (pid = fork()) { 16461033Sdfr case -1: 16561033Sdfr return (-1); 16661033Sdfr case 0: 167221059Skib /* 168221059Skib * child 16961033Sdfr */ 17061033Sdfr (void) close(master); 17161033Sdfr login_tty(slave); 17261033Sdfr return (0); 17361033Sdfr } 17461033Sdfr /* 17561033Sdfr * parent 176180588Skmacy */ 177225570Sadrian *amaster = master; 178225570Sadrian (void) close(slave); 179221059Skib return (pid); 18061033Sdfr} 18161033Sdfr