Skip to content

Instantly share code, notes, and snippets.

@CarterLi
Created November 29, 2024 07:11
Show Gist options
  • Save CarterLi/73d9aa41991deb9174782451b733dc0f to your computer and use it in GitHub Desktop.
Save CarterLi/73d9aa41991deb9174782451b733dc0f to your computer and use it in GitHub Desktop.
#include <unistd.h>
#include <stdbool.h>
#include <assert.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/poll.h>
#ifdef __APPLE__
static inline int pipe2(int *fds, int flags)
{
if(pipe(fds) == -1)
return -1;
fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL) | flags);
fcntl(fds[1], F_SETFL, fcntl(fds[1], F_GETFL) | flags);
return 0;
}
#endif
static inline bool wrapClose(int* pfd)
{
assert(pfd);
if (*pfd < 0)
return false;
close(*pfd);
return true;
}
#define FF_AUTO_CLOSE_FD __attribute__((__cleanup__(wrapClose)))
int main(void)
{
int pipes[2];
const int timeout = 5000;
if(pipe2(pipes, O_CLOEXEC) == -1)
return 1; // "pipe() failed";
pid_t childPid = fork();
if(childPid == -1)
{
close(pipes[0]);
close(pipes[1]);
return 2; // "fork() failed";
}
//Child
if(childPid == 0)
{
int nullFile = open("/dev/null", O_WRONLY | O_CLOEXEC);
dup2(pipes[1], STDOUT_FILENO);
dup2(nullFile, STDERR_FILENO);
setenv("LANG", "C", 1);
char* exe = "/usr/bin/ssh-agent";
execvp(exe, (char* []) { exe, NULL });
_exit(127);
}
//Parent
close(pipes[1]);
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
char str[8192];
while(1)
{
if (timeout >= 0)
{
struct pollfd pollfd = { childPipeFd, POLLIN, 0 };
if (poll(&pollfd, 1, timeout) == 0)
{
kill(childPid, SIGTERM);
waitpid(childPid, NULL, 0);
return 3; // "poll(&pollfd, 1, timeout) timeout";
}
else if (pollfd.revents & POLLERR)
{
kill(childPid, SIGTERM);
waitpid(childPid, NULL, 0);
return 4; //"poll(&pollfd, 1, timeout) error";
}
}
ssize_t nRead = read(childPipeFd, str, sizeof(str));
if (nRead > 0)
fwrite(str, (size_t) nRead, 1, stdout);
else if (nRead == 0)
{
int stat_loc = 0;
if (waitpid(childPid, &stat_loc, 0) == childPid)
{
if (!WIFEXITED(stat_loc))
return 5; //"child process exited abnormally";
if (WEXITSTATUS(stat_loc) == 127)
return 6; //"command was not found";
return 0;
}
return 7; // "waitpid() failed";
}
else if (nRead < 0)
break;
};
return 8; // "read(childPipeFd, str, FF_PIPE_BUFSIZ) failed";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment