Implementing ptsname_r on OSX with Rust
I've been working on a project with rust that requires creating a pseudo-terminal and like many others, I've run into a lot of problems with the functions available to get a pair of master/slave fds for my PTY.
openpty
int ;
This function seems like a good fit at first glance but the documentation contains this disclaimer:
Nobody knows how much space should be reserved for name. So, calling openpty() or forkpty() with non-NULL name may not be secure.
Well that's unfortunate. What else we got?
ptsname
char *;
This method returns a pointer to a static buffer that is overwritten on each call. This makes it not thread safe without some locking semantics which is also less than ideal.
ptsname_r
int ;
Now that's more like it! Writes a buffer we choose so we can avoid avoid the thread-safety issues of a static buffer and it let's us specify the length. Signed, sealed, delivered, right?
Hold up a minute there kiddo!
- Posix Standard
Turns out, ptsname_r is a Linux extension. I needed this library to work on my shiny new work MacBook. So what are we to do?
Reinvent the wheel with system calls!
- Author of this blog post
We know that ptsname must be getting that data from somewhere before it writes to that pesky static buffer. So why not call it ourselves? On OSX, we can use ioctl to call TIOCPTYGNAME, which will write the TTY name to a buffer we control. The interface, however, does not let you specify a buffer size.
Lucky for us, the size is defined in sys/ttycom.h as 128. So now all we need to do is implement that in rust:
Now I'm still finding my bearings when it comes to Rust so if anyone has any critiques of the above code, please let me know.
The above is hastily modified from the application I'm working on so it may not work verbatim but the output of my tests in my library show us that it works!
Output:
Perfect! Now that we've got that squared away we can focus our time on appeasing the borrow checker.