xref: /plan9/sys/src/ape/lib/bsd/pty.c (revision 7e125112574862ca44c733e2ecf7b75e72c6ed0e)
1 /* posix */
2 #include <sys/types.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <fcntl.h>
9 #include <sys/stat.h>
10 
11 #include <sys/pty.h>
12 #include "lib.h"
13 #include "sys9.h"
14 #include "dir.h"
15 
16 /*
17  * return the name of the slave
18  */
19 char*
ptsname(int fd)20 ptsname(int fd)
21 {
22 	Dir *d;
23 	static char buf[32];
24 
25 	if((d = _dirfstat(fd)) == nil || strlen(d->name) < 4){
26 		free(d);
27 		_syserrno();
28 		return 0;
29 	}
30 	snprintf(buf, sizeof buf, "/dev/ptty%d", atoi(d->name+4));
31 	free(d);
32 	return buf;
33 }
34 
35 /*
36  * return the name of the master
37  */
38 char*
ptmname(int fd)39 ptmname(int fd)
40 {
41 	Dir *d;
42 	static char buf[32];
43 
44 	if((d = _dirfstat(fd)) == nil || strlen(d->name) < 4){
45 		free(d);
46 		_syserrno();
47 		return 0;
48 	}
49 
50 	snprintf(buf, sizeof buf, "/dev/ttym%d", atoi(d->name+4));
51 	return buf;
52 }
53 
54 static char ptycl[] = "/dev/ptyclone";
55 static char fssrv[] = "/srv/ptyfs";
56 
57 static void
mkserver(void)58 mkserver(void)
59 {
60 	int fd, i;
61 	char *argv[3];
62 
63 	fd = _OPEN(fssrv, O_RDWR);
64 	if(_MOUNT(fd, -1, "/dev", MAFTER, "") < 0) {
65 		/*
66 		 * remove fssrv here, if it exists, to avoid a race
67 		 * between the loop in the default case below and the
68 		 * new ptyfs removing fssrv when it starts.
69 		 * we otherwise might be unlucky enough to open the old
70 		 * (hung channel) fssrv before ptyfs removes it and break
71 		 * out of the loop with an open fd to a hung channel?
72 		 */
73 		_CLOSE(fd);
74 		_REMOVE(fssrv);
75 		switch(_RFORK(RFPROC|RFFDG)) {
76 		case -1:
77 			return;
78 		case 0:
79 			argv[0] = "ptyfs";
80 			argv[1] = 0;
81 			_EXEC("/bin/ape/ptyfs", argv);
82 			_EXITS(0);
83 		default:
84 			for(i = 0; i < 3; i++) {
85 				fd = _OPEN(fssrv, O_RDWR);
86 				if(fd >= 0)
87 					break;
88 				_SLEEP(1000);
89 			}
90 		}
91 		if(fd < 0)
92 			return;
93 		if(_MOUNT(fd, -1, "/dev", MAFTER, "") < 0)
94 			_CLOSE(fd);
95 	}
96 	/* successful _MOUNT closes fd */
97 }
98 
99 /*
100  * allocate a new pty
101  */
102 int
_getpty(void)103 _getpty(void)
104 {
105 	struct stat sb;
106 
107 	if(stat(ptycl, &sb) < 0)
108 		mkserver();
109 
110 	return open(ptycl, O_RDWR);
111 }
112