xref: /openbsd-src/lib/libutil/pty.c (revision 78fa49ead5f0889b599940410aaa89ed00d2943e)
1*78fa49eaSmillert /*	$OpenBSD: pty.c,v 1.22 2022/04/20 14:00:19 millert Exp $	*/
21477552aSderaadt 
3df930be7Sderaadt /*-
4df930be7Sderaadt  * Copyright (c) 1990, 1993
5df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
6df930be7Sderaadt  *
7df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
8df930be7Sderaadt  * modification, are permitted provided that the following conditions
9df930be7Sderaadt  * are met:
10df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
11df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
12df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
13df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
14df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
156580fee3Smillert  * 3. Neither the name of the University nor the names of its contributors
16df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
17df930be7Sderaadt  *    without specific prior written permission.
18df930be7Sderaadt  *
19df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29df930be7Sderaadt  * SUCH DAMAGE.
30df930be7Sderaadt  */
31df930be7Sderaadt 
32df930be7Sderaadt #include <sys/types.h>
33df930be7Sderaadt #include <sys/stat.h>
34df930be7Sderaadt #include <sys/ioctl.h>
35df930be7Sderaadt #include <fcntl.h>
36df930be7Sderaadt #include <termios.h>
37df930be7Sderaadt #include <errno.h>
38df930be7Sderaadt #include <unistd.h>
39df930be7Sderaadt #include <stdio.h>
40df930be7Sderaadt #include <string.h>
41df930be7Sderaadt #include <grp.h>
423113de35Smillert #include <sys/tty.h>
43ad69070aSdownsj 
44ad69070aSdownsj #include "util.h"
45df930be7Sderaadt 
46df930be7Sderaadt int
getptmfd(void)47c2a62bf3Snicm getptmfd(void)
48c2a62bf3Snicm {
49c2a62bf3Snicm 	return (open(PATH_PTMDEV, O_RDWR|O_CLOEXEC));
50c2a62bf3Snicm }
51c2a62bf3Snicm 
52c2a62bf3Snicm int
openpty(int * amaster,int * aslave,char * name,const struct termios * termp,const struct winsize * winp)53*78fa49eaSmillert openpty(int *amaster, int *aslave, char *name, const struct termios *termp,
54*78fa49eaSmillert     const struct winsize *winp)
55df930be7Sderaadt {
56c2a62bf3Snicm 	int ptmfd;
57c2a62bf3Snicm 
58c2a62bf3Snicm 	if ((ptmfd = getptmfd()) == -1)
59c2a62bf3Snicm 		return (-1);
60c2a62bf3Snicm 	if (fdopenpty(ptmfd, amaster, aslave, name, termp, winp) == -1) {
61c2a62bf3Snicm 		close(ptmfd);
62c2a62bf3Snicm 		return (-1);
63c2a62bf3Snicm 	}
64c2a62bf3Snicm 	close(ptmfd);
65c2a62bf3Snicm 	return (0);
66c2a62bf3Snicm }
67c2a62bf3Snicm 
68c2a62bf3Snicm int
fdopenpty(int ptmfd,int * amaster,int * aslave,char * name,const struct termios * termp,const struct winsize * winp)69c2a62bf3Snicm fdopenpty(int ptmfd, int *amaster, int *aslave, char *name,
70*78fa49eaSmillert     const struct termios *termp, const struct winsize *winp)
71c2a62bf3Snicm {
72c2a62bf3Snicm 	int master, slave;
733113de35Smillert 	struct ptmget ptm;
74df930be7Sderaadt 
751477552aSderaadt 	/*
76422e80e5Smatthew 	 * Use /dev/ptm and the PTMGET ioctl to get a properly set up and
77422e80e5Smatthew 	 * owned pty/tty pair.
783113de35Smillert 	 */
79c2a62bf3Snicm 	if (ioctl(ptmfd, PTMGET, &ptm) == -1)
80422e80e5Smatthew 		return (-1);
81c2a62bf3Snicm 
823113de35Smillert 	master = ptm.cfd;
833113de35Smillert 	slave = ptm.sfd;
843113de35Smillert 	if (name) {
853113de35Smillert 		/*
863113de35Smillert 		 * Manual page says "at least 16 characters".
873113de35Smillert 		 */
883113de35Smillert 		strlcpy(name, ptm.sn, 16);
893113de35Smillert 	}
903113de35Smillert 	*amaster = master;
913113de35Smillert 	*aslave = slave;
923113de35Smillert 	if (termp)
933113de35Smillert 		(void) tcsetattr(slave, TCSAFLUSH, termp);
943113de35Smillert 	if (winp)
955a996c84Sderaadt 		(void) ioctl(slave, TIOCSWINSZ, winp);
963113de35Smillert 	return (0);
97df930be7Sderaadt }
98df930be7Sderaadt 
99df930be7Sderaadt pid_t
forkpty(int * amaster,char * name,const struct termios * termp,const struct winsize * winp)100*78fa49eaSmillert forkpty(int *amaster, char *name, const struct termios *termp,
101*78fa49eaSmillert     const struct winsize *winp)
102df930be7Sderaadt {
103c2a62bf3Snicm 	int ptmfd;
104c2a62bf3Snicm 	pid_t pid;
105c2a62bf3Snicm 
106c2a62bf3Snicm 	if ((ptmfd = getptmfd()) == -1)
107c2a62bf3Snicm 		return (-1);
108c2a62bf3Snicm 	if ((pid = fdforkpty(ptmfd, amaster, name, termp, winp)) == -1) {
109c2a62bf3Snicm 		close(ptmfd);
110c2a62bf3Snicm 		return (-1);
111c2a62bf3Snicm 	}
112c2a62bf3Snicm 	close(ptmfd);
113c2a62bf3Snicm 	return (pid);
114c2a62bf3Snicm }
115c2a62bf3Snicm 
116c2a62bf3Snicm pid_t
fdforkpty(int ptmfd,int * amaster,char * name,const struct termios * termp,const struct winsize * winp)117*78fa49eaSmillert fdforkpty(int ptmfd, int *amaster, char *name, const struct termios *termp,
118*78fa49eaSmillert     const struct winsize *winp)
119c2a62bf3Snicm {
120df930be7Sderaadt 	int master, slave;
121df930be7Sderaadt 	pid_t pid;
122df930be7Sderaadt 
123c2a62bf3Snicm 	if (fdopenpty(ptmfd, &master, &slave, name, termp, winp) == -1)
124df930be7Sderaadt 		return (-1);
125df930be7Sderaadt 	switch (pid = fork()) {
126df930be7Sderaadt 	case -1:
1272a10db81Smatthew 		(void) close(master);
1282a10db81Smatthew 		(void) close(slave);
129df930be7Sderaadt 		return (-1);
130df930be7Sderaadt 	case 0:
131df930be7Sderaadt 		/*
132df930be7Sderaadt 		 * child
133df930be7Sderaadt 		 */
134df930be7Sderaadt 		(void) close(master);
135df930be7Sderaadt 		login_tty(slave);
136df930be7Sderaadt 		return (0);
137df930be7Sderaadt 	}
138df930be7Sderaadt 	/*
139df930be7Sderaadt 	 * parent
140df930be7Sderaadt 	 */
141df930be7Sderaadt 	*amaster = master;
142df930be7Sderaadt 	(void) close(slave);
143df930be7Sderaadt 	return (pid);
144df930be7Sderaadt }
145