xref: /csrg-svn/lib/libutil/pty.c (revision 67148)
142963Smarc /*-
2*67148Sbostic  * Copyright (c) 1990, 1993, 1994
361348Sbostic  *	The Regents of the University of California.  All rights reserved.
442963Smarc  *
542963Smarc  * %sccs.include.redist.c%
642963Smarc  */
742963Smarc 
842963Smarc #if defined(LIBC_SCCS) && !defined(lint)
9*67148Sbostic static char sccsid[] = "@(#)pty.c	8.3 (Berkeley) 05/16/94";
1042963Smarc #endif /* LIBC_SCCS and not lint */
1142963Smarc 
1245348Sbostic #include <sys/types.h>
13*67148Sbostic #include <sys/ioctl.h>
1445348Sbostic #include <sys/stat.h>
15*67148Sbostic 
16*67148Sbostic #include <errno.h>
1746724Sbostic #include <fcntl.h>
18*67148Sbostic #include <grp.h>
19*67148Sbostic #include <stdio.h>
20*67148Sbostic #include <stdlib.h>
21*67148Sbostic #include <string.h>
2244569Smarc #include <termios.h>
2346724Sbostic #include <unistd.h>
2442963Smarc 
openpty(amaster,aslave,name,termp,winp)2544569Smarc openpty(amaster, aslave, name, termp, winp)
2642963Smarc 	int *amaster, *aslave;
2742963Smarc 	char *name;
2844569Smarc 	struct termios *termp;
2944569Smarc 	struct winsize *winp;
3042963Smarc {
3146964Sbostic 	static char line[] = "/dev/ptyXX";
3246724Sbostic 	register const char *cp1, *cp2;
3345348Sbostic 	register int master, slave, ttygid;
3444569Smarc 	struct group *gr;
3542963Smarc 
3644569Smarc 	if ((gr = getgrnam("tty")) != NULL)
3744569Smarc 		ttygid = gr->gr_gid;
3844569Smarc 	else
3944569Smarc 		ttygid = -1;
4044569Smarc 
4142963Smarc 	for (cp1 = "pqrs"; *cp1; cp1++) {
4242963Smarc 		line[8] = *cp1;
4342963Smarc 		for (cp2 = "0123456789abcdef"; *cp2; cp2++) {
4467147Sbostic 			line[5] = 'p';
4542963Smarc 			line[9] = *cp2;
4642963Smarc 			if ((master = open(line, O_RDWR, 0)) == -1) {
4747069Smarc 				if (errno == ENOENT)
4844569Smarc 					return (-1);	/* out of ptys */
4942963Smarc 			} else {
5042963Smarc 				line[5] = 't';
5149628Smarc 				(void) chown(line, getuid(), ttygid);
5249628Smarc 				(void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
5344569Smarc 				(void) revoke(line);
5442963Smarc 				if ((slave = open(line, O_RDWR, 0)) != -1) {
5542963Smarc 					*amaster = master;
5642963Smarc 					*aslave = slave;
5742963Smarc 					if (name)
5842963Smarc 						strcpy(name, line);
5944569Smarc 					if (termp)
6044569Smarc 						(void) tcsetattr(slave,
6146724Sbostic 							TCSAFLUSH, termp);
6244569Smarc 					if (winp)
6344569Smarc 						(void) ioctl(slave, TIOCSWINSZ,
6447047Skarels 							(char *)winp);
6542963Smarc 					return (0);
6642963Smarc 				}
6744569Smarc 				(void) close(master);
6842963Smarc 			}
6942963Smarc 		}
7042963Smarc 	}
7144569Smarc 	errno = ENOENT;	/* out of ptys */
7242963Smarc 	return (-1);
7342963Smarc }
7444569Smarc 
forkpty(amaster,name,termp,winp)7544569Smarc forkpty(amaster, name, termp, winp)
7644569Smarc 	int *amaster;
7744569Smarc 	char *name;
7844569Smarc 	struct termios *termp;
7944569Smarc 	struct winsize *winp;
8044569Smarc {
8144569Smarc 	int master, slave, pid;
8244569Smarc 
8344569Smarc 	if (openpty(&master, &slave, name, termp, winp) == -1)
8444569Smarc 		return (-1);
8544569Smarc 	switch (pid = fork()) {
8644569Smarc 	case -1:
8744569Smarc 		return (-1);
8844569Smarc 	case 0:
8944569Smarc 		/*
9044569Smarc 		 * child
9144569Smarc 		 */
9244569Smarc 		(void) close(master);
9344569Smarc 		login_tty(slave);
9444569Smarc 		return (0);
9544569Smarc 	}
9644569Smarc 	/*
9744569Smarc 	 * parent
9844569Smarc 	 */
9944569Smarc 	*amaster = master;
10044569Smarc 	(void) close(slave);
10144569Smarc 	return (pid);
10244569Smarc }
103