Skip to content

Instantly share code, notes, and snippets.

@felipec
Last active March 6, 2023 01:25
Show Gist options
  • Save felipec/8a820f3dbf67a5861491553e211400fb to your computer and use it in GitHub Desktop.
Save felipec/8a820f3dbf67a5861491553e211400fb to your computer and use it in GitHub Desktop.
zsh pty test
#define _XOPEN_SOURCE 600
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
// #define SUDO
#ifdef SUDO
char *child_argv[] = { "zsh", "-c", "sudo touch /tmp/sudo", NULL };
#else
char *child_argv[] = { "zsh", "-c", "touch /tmp/fork &", NULL };
#endif
int main(int argc, char *argv[])
{
int ret, master, slave;
#ifdef SUDO
const char *pwd;
pwd = getenv("PASSWORD");
if (!pwd) {
fprintf(stderr, "Missing PASSWORD env variable\n");
exit(1);
}
#endif
if (argc >= 1) child_argv[0] = argv[1];
master = posix_openpt(O_RDWR | O_NOCTTY);
unlockpt(master);
#ifdef TIOCGPTPEER
slave = ioctl(master, TIOCGPTPEER, O_RDWR | O_NOCTTY);
#else
slave = open(ptsname(master), O_RDWR | O_NOCTTY);
#endif
pid_t pid = fork();
if (pid) {
fd_set rfds;
int status;
close(slave);
FD_ZERO(&rfds);
FD_SET(master, &rfds);
select(master + 1, &rfds, NULL, NULL, NULL);
if (FD_ISSET(master, &rfds)) {
char input[0x1000];
ret = read(master, input, sizeof(input));
if (ret > 0)
fprintf(stdout, "out: %.*s\n", ret, input);
}
#ifdef SUDO
write(master, pwd, strlen(pwd));
write(master, "\n", 1);
#endif
waitpid(pid, &status, 0);
return (WEXITSTATUS(status));
} else {
setsid();
ioctl(slave, TIOCSCTTY, NULL);
signal(SIGHUP, SIG_IGN);
close(master);
dup2(slave, 0);
dup2(slave, 1);
dup2(slave, 2);
close(slave);
execvp(child_argv[0], child_argv);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment