ref: a7f5ecaf636e38f407c951d0e86dcc4c4f424bd6
dir: /sys/src/ape/lib/bsd/pty.c/
/* posix */ #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/pty.h> #include "lib.h" #include "sys9.h" #include "dir.h" /* * return the name of the slave */ char* ptsname(int fd) { Dir *d; static char buf[32]; if((d = _dirfstat(fd)) == nil || strlen(d->name) < 4){ free(d); _syserrno(); return 0; } snprintf(buf, sizeof buf, "/dev/ptty%d", atoi(d->name+4)); free(d); return buf; } /* * return the name of the master */ char* ptmname(int fd) { Dir *d; static char buf[32]; if((d = _dirfstat(fd)) == nil || strlen(d->name) < 4){ free(d); _syserrno(); return 0; } snprintf(buf, sizeof buf, "/dev/ttym%d", atoi(d->name+4)); return buf; } static char ptycl[] = "/dev/ptyclone"; static char fssrv[] = "/srv/ptyfs"; static void mkserver(void) { int fd, i; char *argv[3]; fd = _OPEN(fssrv, O_RDWR); if(_MOUNT(fd, -1, "/dev", MAFTER, "") < 0) { /* * remove fssrv here, if it exists, to avoid a race * between the loop in the default case below and the * new ptyfs removing fssrv when it starts. * we otherwise might be unlucky enough to open the old * (hung channel) fssrv before ptyfs removes it and break * out of the loop with an open fd to a hung channel? */ _CLOSE(fd); _REMOVE(fssrv); switch(_RFORK(RFPROC|RFFDG)) { case -1: return; case 0: argv[0] = "ptyfs"; argv[1] = 0; _EXEC("/bin/ape/ptyfs", argv); _EXITS(0); default: for(i = 0; i < 3; i++) { fd = _OPEN(fssrv, O_RDWR); if(fd >= 0) break; _SLEEP(1000); } } if(fd < 0) return; if(_MOUNT(fd, -1, "/dev", MAFTER, "") < 0) _CLOSE(fd); } /* successful _MOUNT closes fd */ } /* * allocate a new pty */ int _getpty(void) { struct stat sb; if(stat(ptycl, &sb) < 0) mkserver(); return open(ptycl, O_RDWR); }