1 /*- 2 * Copyright (c) 1990, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #if defined(LIBC_SCCS) && !defined(lint) 9 static char sccsid[] = "@(#)pty.c 8.3 (Berkeley) 05/16/94"; 10 #endif /* LIBC_SCCS and not lint */ 11 12 #include <sys/types.h> 13 #include <sys/ioctl.h> 14 #include <sys/stat.h> 15 16 #include <errno.h> 17 #include <fcntl.h> 18 #include <grp.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include <termios.h> 23 #include <unistd.h> 24 25 openpty(amaster, aslave, name, termp, winp) 26 int *amaster, *aslave; 27 char *name; 28 struct termios *termp; 29 struct winsize *winp; 30 { 31 static char line[] = "/dev/ptyXX"; 32 register const char *cp1, *cp2; 33 register int master, slave, ttygid; 34 struct group *gr; 35 36 if ((gr = getgrnam("tty")) != NULL) 37 ttygid = gr->gr_gid; 38 else 39 ttygid = -1; 40 41 for (cp1 = "pqrs"; *cp1; cp1++) { 42 line[8] = *cp1; 43 for (cp2 = "0123456789abcdef"; *cp2; cp2++) { 44 line[5] = 'p'; 45 line[9] = *cp2; 46 if ((master = open(line, O_RDWR, 0)) == -1) { 47 if (errno == ENOENT) 48 return (-1); /* out of ptys */ 49 } else { 50 line[5] = 't'; 51 (void) chown(line, getuid(), ttygid); 52 (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP); 53 (void) revoke(line); 54 if ((slave = open(line, O_RDWR, 0)) != -1) { 55 *amaster = master; 56 *aslave = slave; 57 if (name) 58 strcpy(name, line); 59 if (termp) 60 (void) tcsetattr(slave, 61 TCSAFLUSH, termp); 62 if (winp) 63 (void) ioctl(slave, TIOCSWINSZ, 64 (char *)winp); 65 return (0); 66 } 67 (void) close(master); 68 } 69 } 70 } 71 errno = ENOENT; /* out of ptys */ 72 return (-1); 73 } 74 75 forkpty(amaster, name, termp, winp) 76 int *amaster; 77 char *name; 78 struct termios *termp; 79 struct winsize *winp; 80 { 81 int master, slave, pid; 82 83 if (openpty(&master, &slave, name, termp, winp) == -1) 84 return (-1); 85 switch (pid = fork()) { 86 case -1: 87 return (-1); 88 case 0: 89 /* 90 * child 91 */ 92 (void) close(master); 93 login_tty(slave); 94 return (0); 95 } 96 /* 97 * parent 98 */ 99 *amaster = master; 100 (void) close(slave); 101 return (pid); 102 } 103