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