//required for posix_openpt to work #define _XOPEN_SOURCE 600 #define _DEFAULT_SOURCE #include #include #include #include #include #include #include //#include #include #include #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; }