summaryrefslogtreecommitdiff
path: root/ptyim.c
diff options
context:
space:
mode:
authorHaoran S. Diao (刁浩然) <0@hairydiode.xyz>2025-09-05 23:33:59 -0700
committerHaoran S. Diao (刁浩然) <0@hairydiode.xyz>2025-09-05 23:33:59 -0700
commit33c523fdef955c60fb81ccf3e30b8eace12933c9 (patch)
tree8c01ced33af089f64bb845710432aec996038749 /ptyim.c
tty intercept works
Diffstat (limited to 'ptyim.c')
-rw-r--r--ptyim.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/ptyim.c b/ptyim.c
new file mode 100644
index 0000000..047bb25
--- /dev/null
+++ b/ptyim.c
@@ -0,0 +1,147 @@
+//required for posix_openpt to work
+#define _XOPEN_SOURCE 600
+#define _DEFAULT_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+//#include <asm/termbits.h>
+#include <string.h>
+#include <signal.h>
+#include "im.h"
+int running = 1;
+//hook for when the pty child process dies
+void childhook(int a) {
+ running = 0;
+}
+int pty_slave = -1;
+//hook for SIGWINCH
+void winchhook(int a) {
+ struct winsize sz;
+ ioctl(STDIN_FILENO, TIOCGWINSZ, &sz);
+ ioctl(pty_slave, TIOCSWINSZ, &sz);
+
+}
+int main (int argc, char * argv[], char * envp[]) {
+ printf("%s: %d\n", "a", im_search("a",0,IM_TABLE_LEN));
+ printf("%s: %d\n", "bb", im_search("bb",0,IM_TABLE_LEN));
+ printf("%s: %d\n", "c", im_search("c",0,IM_TABLE_LEN));
+ printf("%s: %d\n", "ba", im_search("ba",0,IM_TABLE_LEN));
+ //creates the pty master
+ int pty_master = posix_openpt(O_RDWR);
+ if (pty_master < 0) {
+ fprintf(stderr, "errno: %d, failed to create pty master", errno);
+ return errno;
+ }
+ //makes it nonblocking
+ fcntl(pty_master, F_SETFL,O_NONBLOCK);
+ //make it raw
+ struct termios stdin_termio;
+ struct termios stdin_termio_bk;
+ tcgetattr(STDIN_FILENO,&stdin_termio);
+ tcgetattr(STDIN_FILENO,&stdin_termio_bk);
+ cfmakeraw(&stdin_termio);
+ tcsetattr(STDIN_FILENO,TCSANOW,&stdin_termio);
+ //make it nonblocking
+ fcntl(STDIN_FILENO, F_SETFL,O_NONBLOCK);
+
+
+ if ( unlockpt(pty_master) <0) {
+ fprintf(stderr, "errno: %d, failed to unlock pty slave", errno);
+ return errno;
+ }
+ //gets slave path
+ char * pty_slave_fn = ptsname(pty_master);
+ printf("Slave name %s\n", pty_slave_fn);
+ //tries to open pty slave
+ pty_slave = open(pty_slave_fn, O_RDWR);
+ if (pty_slave < 0) {
+ fprintf(stderr, "errno: %d, failed to open pty slave '%s'",\
+ errno, pty_slave_fn);
+ return errno;
+ }
+ //make the pty slave the same line discipline stdin was
+ tcsetattr(pty_slave,TCSANOW,&stdin_termio_bk);
+ //syncs the window sizes for the first time
+ winchhook(0);
+ //forks for running bash
+ pid_t mypid = fork();
+ printf("forked w/ pid %d\n", mypid);
+ if (mypid == 0) {
+
+ //set self to be session leader
+ if (setsid() <0) {
+ fprintf(stderr, "failed to make new session\n");
+ }
+ //all the stand streams
+ freopen(pty_slave_fn, "r", stdin);
+ freopen(pty_slave_fn, "w", stdout);
+ freopen(pty_slave_fn, "w", stderr);
+ //must be a session leader to set the controlling terminal
+ if (ioctl(pty_slave, TIOCSCTTY, 0)) {
+ fprintf(stderr, "errno: %d, failed to set controlling tty\n", errno);
+ }
+
+
+
+ /*
+ * Opens up the Shell now
+ */
+
+ //opens up the slave pty
+ //needs to fork
+ //then set its own process group
+ //need to set the terminal
+ //exec bash then
+ //gets the shell to use, order is
+ // argument 1, then $SHELL< then /bin/sh
+ char * shellpath = "/bin/sh";
+ if (argc >1) {
+ shellpath = argv[1];
+ } else if (getenv("SHELL") != NULL) {
+ shellpath = getenv("SHELL");
+ }
+ //gets the terminal environmental variabke, 32 should be enough
+ char env_term[32] = "TERM=";
+ strcat(env_term, getenv("TERM"));
+ char env_home[32] = "HOME=";
+ strcat(env_home, getenv("HOME"));
+ char * shell_envs[3] = {env_term,env_home, NULL};
+ char * shell_args[2] = {shellpath, NULL};
+ //if (execve(shellpath,shell_args, shell_envs) == -1) {
+ if (execve(shellpath,shell_args, envp) == -1) {
+ fprintf(stderr, "errno: %d, Failed to start shell '%s'\n", errno, shellpath);
+ return errno;
+ }
+ //should automatically close any file descriptors
+ _exit(0);
+ } else {
+ signal(SIGCHLD, childhook);
+ signal(SIGWINCH, winchhook);
+ char readbuffer[1] = {0};
+ int chars_read = 0;
+ //open
+ while (running) {
+ //just relay everything for now
+ //read uses file descriptors and is a system call
+ chars_read = read(pty_master,readbuffer,1);
+ if (chars_read >0) {
+ write(STDIN_FILENO,readbuffer,1);
+ }
+ //relays input from stdin
+ char input_buffer[IM_TABLE_ENTRY_LEN] = {0};
+
+ chars_read = read(STDIN_FILENO, readbuffer, 1);
+ if (chars_read > 0) {
+ write(pty_master,readbuffer,1);
+ }
+ }
+ }
+ close(pty_master);
+ tcsetattr(STDIN_FILENO,TCSANOW,&stdin_termio_bk);
+ //close(pty_slave);
+ return 0;
+}