Loading...
--- /dev/null
+++ Libc/Libc-1698.140.3/tests/forkpty.c
@@ -0,0 +1,52 @@
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <util.h>
+
+#include <darwintest.h>
+#include <TargetConditionals.h>
+
+T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
+
+T_DECL(forkpty_forkfail,
+ "Check for fd leak when fork() fails",
+ T_META_CHECK_LEAKS(false),
+ T_META_ENABLED(TARGET_OS_OSX))
+{
+ struct rlimit orl, nrl;
+ struct passwd *pwd;
+ pid_t pid;
+ int prevfd, fd, pty;
+
+ T_SETUPBEGIN;
+ if (geteuid() == 0) {
+ /* the setrlimit() trick won't work if we're root */
+ T_ASSERT_NOTNULL(pwd = getpwnam("nobody"), NULL);
+ T_ASSERT_POSIX_SUCCESS(setgid(pwd->pw_gid), NULL);
+ T_ASSERT_POSIX_SUCCESS(setuid(pwd->pw_uid), NULL);
+ }
+ T_ASSERT_POSIX_SUCCESS(getrlimit(RLIMIT_NPROC, &orl), NULL);
+ nrl = orl;
+ nrl.rlim_cur = 1;
+ T_ASSERT_POSIX_SUCCESS(setrlimit(RLIMIT_NPROC, &nrl), NULL);
+ T_ASSERT_POSIX_SUCCESS(fd = dup(0), NULL);
+ T_ASSERT_POSIX_SUCCESS(close(fd), NULL);
+ T_SETUPEND;
+ pid = forkpty(&pty, NULL, NULL, NULL);
+ if (pid == 0) {
+ /* child - fork() unexpectedly succeeded */
+ _exit(0);
+ }
+ T_EXPECT_POSIX_FAILURE(pid, EAGAIN, "expected fork() to fail");
+ if (pid > 0) {
+ /* parent - fork() unexpectedly succeeded */
+ (void)waitpid(pid, NULL, 0);
+ }
+ prevfd = fd;
+ T_ASSERT_POSIX_SUCCESS(fd = dup(0), NULL);
+ T_EXPECT_EQ(fd, prevfd, "expected same fd as previously");
+}