TTY/PTY on Linux (Darwin vs Glibc)

I wrote up a small CLI tool that automates backing up some data in docker containers. Part of it involves attaching to the container to issue a couple commands to the service's console, which requires using a TTY/PTY. To do this on macOS, I used posix_openpt/grantpt/unlockpt/ptsname from the Darwin library, and provide the file handle to Process.

The ugly bit is that I'm now attempting to run this tool on Ubuntu 20.04, where I'm not paying for the overhead of hyperkit. My thinking was that everything I was using should be available on Linux. Unfortunately, it looks like these above functions are not part of Glibc, and I can't find any similar functions under different names that it might have exported. getpt() isn't available either.

So my next step was to create a system library module that defines _GNU_SOURCE (to light up the PTY functions I want) and imported stdlib.h and fcntl.h. Tested this using a C file with Swift's copy of clang first, including only my bridging header, and it worked fine there. However, even though Swift doesn't seem to complain about the system library itself at build time, it still complains about the missing symbols, so it's possible something with the module map is mis-configured.

In a package that only has the system library, I can't even seem to use the REPL on it like you can a package that exports a normal library, so inspecting the result there isn't seemingly working.

Is there perhaps a better way to get at a PTY on Linux? Or some way to properly test to see what is actually going on with the system library module to understand why the symbols aren't getting found?

I've moved the code I'm using to a small wrapper library to make it easier to share: GitHub - Kaiede/PtyKit: Wrapper for PTY Access in Swift

The Swift library uses explicit references to the system library, to ensure I'm not picking up the implicit Darwin import on macOS as a test. I also included the test.c file I use to test the header on Linux, using Swift's clang toolchain.

I've even confirmed that libc itself does export the symbols. Yet for some reason, I still can't see these functions from the Swift code that relies on them.

I'm afraid you're hitting SR-6772. Basically, the nature of clang modules is such that you aren't allowed to produce a different header parse for these system headers in the interface to your Cstdlib module.

You'll have to do what NIO does, and shim this code in via thunks through your C library.

I figured I couldn’t have been the first trying something like this, but was focused on the PTY aspects, and so missed the bug in my web searches. Probably doesn’t help that this was my first time trying to interop with C manually. Thanks for the details, this is exactly what I needed.

A shame these aren’t/can’t be exported by Glibc directly, like on macOS.