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