xref: /plan9/sys/src/ape/lib/bsd/pty.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1219b2ee8SDavid du Colombier /* posix */
2219b2ee8SDavid du Colombier #include <sys/types.h>
3219b2ee8SDavid du Colombier #include <unistd.h>
4219b2ee8SDavid du Colombier #include <stdlib.h>
5219b2ee8SDavid du Colombier #include <stdio.h>
6219b2ee8SDavid du Colombier #include <errno.h>
7219b2ee8SDavid du Colombier #include <string.h>
8219b2ee8SDavid du Colombier #include <fcntl.h>
9219b2ee8SDavid du Colombier #include <sys/stat.h>
10219b2ee8SDavid du Colombier 
11219b2ee8SDavid du Colombier #include <sys/pty.h>
12219b2ee8SDavid du Colombier #include "lib.h"
13219b2ee8SDavid du Colombier #include "sys9.h"
14219b2ee8SDavid du Colombier #include "dir.h"
15219b2ee8SDavid du Colombier 
16219b2ee8SDavid du Colombier /*
17219b2ee8SDavid du Colombier  * return the name of the slave
18219b2ee8SDavid du Colombier  */
19219b2ee8SDavid du Colombier char*
20219b2ee8SDavid du Colombier ptsname(int fd)
21219b2ee8SDavid du Colombier {
22*9a747e4fSDavid du Colombier 	Dir *d;
23219b2ee8SDavid du Colombier 	static char buf[32];
24219b2ee8SDavid du Colombier 
25*9a747e4fSDavid du Colombier 	if((d = _dirfstat(fd)) == nil || strlen(d->name) < 4){
26*9a747e4fSDavid du Colombier 		free(d);
27219b2ee8SDavid du Colombier 		_syserrno();
28219b2ee8SDavid du Colombier 		return 0;
29219b2ee8SDavid du Colombier 	}
30*9a747e4fSDavid du Colombier 	sprintf(buf, "/dev/ptty%d", atoi(d->name+4));
31*9a747e4fSDavid du Colombier 	free(d);
32219b2ee8SDavid du Colombier 	return buf;
33219b2ee8SDavid du Colombier }
34219b2ee8SDavid du Colombier 
35219b2ee8SDavid du Colombier /*
36219b2ee8SDavid du Colombier  * return the name of the master
37219b2ee8SDavid du Colombier  */
38219b2ee8SDavid du Colombier char*
39219b2ee8SDavid du Colombier ptmname(int fd)
40219b2ee8SDavid du Colombier {
41*9a747e4fSDavid du Colombier 	Dir *d;
42219b2ee8SDavid du Colombier 	static char buf[32];
43219b2ee8SDavid du Colombier 
44*9a747e4fSDavid du Colombier 	if((d = _dirfstat(fd)) == nil || strlen(d->name) < 4){
45*9a747e4fSDavid du Colombier 		free(d);
46219b2ee8SDavid du Colombier 		_syserrno();
47219b2ee8SDavid du Colombier 		return 0;
48219b2ee8SDavid du Colombier 	}
49219b2ee8SDavid du Colombier 
50*9a747e4fSDavid du Colombier 	sprintf(buf, "/dev/ttym%d", atoi(d->name+4));
51219b2ee8SDavid du Colombier 	return buf;
52219b2ee8SDavid du Colombier }
53219b2ee8SDavid du Colombier 
54219b2ee8SDavid du Colombier static char ptycl[] = "/dev/ptyclone";
55219b2ee8SDavid du Colombier static char fssrv[] = "/srv/ptyfs";
56219b2ee8SDavid du Colombier 
57219b2ee8SDavid du Colombier static void
58219b2ee8SDavid du Colombier mkserver(void)
59219b2ee8SDavid du Colombier {
60219b2ee8SDavid du Colombier 	int fd, i;
61*9a747e4fSDavid du Colombier 	char *argv[3];
62219b2ee8SDavid du Colombier 
63*9a747e4fSDavid du Colombier 	fd = _OPEN(fssrv, O_RDWR);
64*9a747e4fSDavid du Colombier 	if(_MOUNT(fd, -1, "/dev", MAFTER, "") < 0) {
65*9a747e4fSDavid du Colombier 		/*
66*9a747e4fSDavid du Colombier 		 * remove fssrv here, if it exists, to avoid a race
67*9a747e4fSDavid du Colombier 		 * between the loop in the default case below and the
68*9a747e4fSDavid du Colombier 		 * new ptyfs removing fssrv when it starts.
69*9a747e4fSDavid du Colombier 		 * we otherwise might be unlucky enough to open the old
70*9a747e4fSDavid du Colombier 		 * (hung channel) fssrv before ptyfs removes it and break
71*9a747e4fSDavid du Colombier 		 * out of the loop with an open fd to a hung channel?
72*9a747e4fSDavid du Colombier 		 */
73*9a747e4fSDavid du Colombier 		_CLOSE(fd);
74*9a747e4fSDavid du Colombier 		_REMOVE(fssrv);
75219b2ee8SDavid du Colombier 		switch(_RFORK(RFPROC|RFFDG)) {
76219b2ee8SDavid du Colombier 		case -1:
77219b2ee8SDavid du Colombier 			return;
78219b2ee8SDavid du Colombier 		case 0:
79219b2ee8SDavid du Colombier 			argv[0] = "ptyfs";
80219b2ee8SDavid du Colombier 			argv[1] = 0;
81219b2ee8SDavid du Colombier 			_EXEC("/bin/ape/ptyfs", argv);
82219b2ee8SDavid du Colombier 			_EXITS(0);
83219b2ee8SDavid du Colombier 		default:
84219b2ee8SDavid du Colombier 			for(i = 0; i < 3; i++) {
85*9a747e4fSDavid du Colombier 				fd = _OPEN(fssrv, O_RDWR);
86219b2ee8SDavid du Colombier 				if(fd >= 0)
87219b2ee8SDavid du Colombier 					break;
88*9a747e4fSDavid du Colombier 				_SLEEP(1000);
89219b2ee8SDavid du Colombier 			}
90219b2ee8SDavid du Colombier 		}
91219b2ee8SDavid du Colombier 		if(fd < 0)
92219b2ee8SDavid du Colombier 			return;
93*9a747e4fSDavid du Colombier 		if(_MOUNT(fd, -1, "/dev", MAFTER, "") < 0)
94*9a747e4fSDavid du Colombier 			_CLOSE(fd);
95219b2ee8SDavid du Colombier 	}
96*9a747e4fSDavid du Colombier 	/* successful _MOUNT closes fd */
97219b2ee8SDavid du Colombier }
98219b2ee8SDavid du Colombier 
99219b2ee8SDavid du Colombier /*
100219b2ee8SDavid du Colombier  * allocate a new pty
101219b2ee8SDavid du Colombier  */
102219b2ee8SDavid du Colombier int
103219b2ee8SDavid du Colombier _getpty(void)
104219b2ee8SDavid du Colombier {
105219b2ee8SDavid du Colombier 	struct stat sb;
106219b2ee8SDavid du Colombier 
107219b2ee8SDavid du Colombier 	if(stat(ptycl, &sb) < 0)
108219b2ee8SDavid du Colombier 		mkserver();
109219b2ee8SDavid du Colombier 
110219b2ee8SDavid du Colombier 	return open(ptycl, O_RDWR);
111219b2ee8SDavid du Colombier }
112