xref: /plan9/sys/src/ape/lib/bsd/pty.c (revision 7e125112574862ca44c733e2ecf7b75e72c6ed0e)
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*
ptsname(int fd)20219b2ee8SDavid du Colombier ptsname(int fd)
21219b2ee8SDavid du Colombier {
229a747e4fSDavid du Colombier 	Dir *d;
23219b2ee8SDavid du Colombier 	static char buf[32];
24219b2ee8SDavid du Colombier 
259a747e4fSDavid du Colombier 	if((d = _dirfstat(fd)) == nil || strlen(d->name) < 4){
269a747e4fSDavid du Colombier 		free(d);
27219b2ee8SDavid du Colombier 		_syserrno();
28219b2ee8SDavid du Colombier 		return 0;
29219b2ee8SDavid du Colombier 	}
30*7e125112SDavid du Colombier 	snprintf(buf, sizeof buf, "/dev/ptty%d", atoi(d->name+4));
319a747e4fSDavid 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*
ptmname(int fd)39219b2ee8SDavid du Colombier ptmname(int fd)
40219b2ee8SDavid du Colombier {
419a747e4fSDavid du Colombier 	Dir *d;
42219b2ee8SDavid du Colombier 	static char buf[32];
43219b2ee8SDavid du Colombier 
449a747e4fSDavid du Colombier 	if((d = _dirfstat(fd)) == nil || strlen(d->name) < 4){
459a747e4fSDavid du Colombier 		free(d);
46219b2ee8SDavid du Colombier 		_syserrno();
47219b2ee8SDavid du Colombier 		return 0;
48219b2ee8SDavid du Colombier 	}
49219b2ee8SDavid du Colombier 
50*7e125112SDavid du Colombier 	snprintf(buf, sizeof 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
mkserver(void)58219b2ee8SDavid du Colombier mkserver(void)
59219b2ee8SDavid du Colombier {
60219b2ee8SDavid du Colombier 	int fd, i;
619a747e4fSDavid du Colombier 	char *argv[3];
62219b2ee8SDavid du Colombier 
639a747e4fSDavid du Colombier 	fd = _OPEN(fssrv, O_RDWR);
649a747e4fSDavid du Colombier 	if(_MOUNT(fd, -1, "/dev", MAFTER, "") < 0) {
659a747e4fSDavid du Colombier 		/*
669a747e4fSDavid du Colombier 		 * remove fssrv here, if it exists, to avoid a race
679a747e4fSDavid du Colombier 		 * between the loop in the default case below and the
689a747e4fSDavid du Colombier 		 * new ptyfs removing fssrv when it starts.
699a747e4fSDavid du Colombier 		 * we otherwise might be unlucky enough to open the old
709a747e4fSDavid du Colombier 		 * (hung channel) fssrv before ptyfs removes it and break
719a747e4fSDavid du Colombier 		 * out of the loop with an open fd to a hung channel?
729a747e4fSDavid du Colombier 		 */
739a747e4fSDavid du Colombier 		_CLOSE(fd);
749a747e4fSDavid 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++) {
859a747e4fSDavid du Colombier 				fd = _OPEN(fssrv, O_RDWR);
86219b2ee8SDavid du Colombier 				if(fd >= 0)
87219b2ee8SDavid du Colombier 					break;
889a747e4fSDavid du Colombier 				_SLEEP(1000);
89219b2ee8SDavid du Colombier 			}
90219b2ee8SDavid du Colombier 		}
91219b2ee8SDavid du Colombier 		if(fd < 0)
92219b2ee8SDavid du Colombier 			return;
939a747e4fSDavid du Colombier 		if(_MOUNT(fd, -1, "/dev", MAFTER, "") < 0)
949a747e4fSDavid du Colombier 			_CLOSE(fd);
95219b2ee8SDavid du Colombier 	}
969a747e4fSDavid 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
_getpty(void)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