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