summaryrefslogtreecommitdiff
path: root/ptyim.c
diff options
context:
space:
mode:
Diffstat (limited to 'ptyim.c')
-rw-r--r--ptyim.c165
1 files changed, 100 insertions, 65 deletions
diff --git a/ptyim.c b/ptyim.c
index c402684..5ff0eee 100644
--- a/ptyim.c
+++ b/ptyim.c
@@ -3,14 +3,18 @@
#define _DEFAULT_SOURCE
#include <stdio.h>
#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <fcntl.h>
#include <sys/ioctl.h>
#include <termios.h>
-#include <string.h>
+
#include <signal.h>
-#include <sys/prctl.h>
+#include <pthread.h>
+#include <semaphore.h>
+
#include "im.h"
#include "escape.h"
#define WRITE_BUFFER_LEN 128
@@ -41,7 +45,14 @@ void winchhook(int a) {
}
//child process pids
pid_t shell_pid;
-pid_t om_pid;
+pthread_t om_thread;
+pthread_t im_disp_thread;
+//stdout semaphore
+sem_t out_sem;
+//tracks whether the screen has been updated by om
+int om_updated = 1;
+
+
//return 0 on success, -1 on error
//sets the global vars pty_master and pty_slave
int make_pty() {
@@ -88,10 +99,51 @@ void condition_stdin() {
void restore_stdin() {
tcsetattr(STDIN_FILENO,TCSANOW,&stdin_termio_bk);
}
+void * om_routine( void *arg) {
+ //thread handling pty -> stdout
+ while (running) {
+ //output manager child process
+ //buffer for reading from pty_master and writing to stdout
+ char write_buffer[WRITE_BUFFER_LEN] = {0};
+ //only read/write syscalls work well for this, printfs
+ //etcs do not work, this is blocking which is why its its own
+ //thread
+ // pty_master -> STDOUT
+ int wchars_read = read(pty_master,write_buffer, WRITE_BUFFER_LEN);
+ if (wchars_read >0) {
+ out_state = update_esc_state(write_buffer, wchars_read, out_state);
+ fprintf(stderr, "%c: %d\n", write_buffer[wchars_read-1], out_state);
+ sem_wait(&out_sem);
+ write(STDOUT_FILENO,write_buffer,wchars_read);
+ sem_post(&out_sem);
+ //sets update flag, im_disp_routine will set it to 0
+ om_updated = 1;
+ }
+ }
+}
+void * im_disp_routine (void *args) {
+ while (running) {
+ // Every run of this loop, it checks to see if im_buffer has
+ // updated, if it has, and no escape sequences have been written
+ // so far, it will display the im
+ if (im_updated |om_updated) {
+ fprintf(stderr, "printing im statusline\n");
+ if (safe_state(out_state)) {
+ sem_wait(&out_sem);
+ disp_im(STDIN_FILENO, trows, tcols);
+ sem_post(&out_sem);
+ im_updated = 0;
+ om_updated = 0;
+ }
+ }
+ }
+}
//main thread exit
void exit_main() {
//kill shell , can not be blocked
kill(shell_pid, SIGKILL);
+ pthread_cancel(om_thread);
+ pthread_cancel(im_disp_thread);
//exit, only the master process should reach this point
close(pty_master);
close(pty_slave);
@@ -155,71 +207,54 @@ int main (int argc, char * argv[], char * envp[]) {
//should automatically close any file descriptors
_exit(0);
} else {
- //forks for read and write, master process handles im, child
- //process just handles transfering pty output to stdout
- om_pid = fork();
- if (om_pid == 0) {
- //sets the name for cleaner ps output
- prctl(PR_SET_NAME, "ptyim om thread");
- //output manager child process
- //runs forever until SIGKILL'd
- while (true) {
- //output manager child process
- //buffer for reading from pty_master and writing to stdout
- char write_buffer[WRITE_BUFFER_LEN] = {0};
- //only read/write syscalls work well for this, printfs
- //etcs do not work
- // pty_master -> STDOUT
- int wchars_read = read(pty_master,write_buffer, WRITE_BUFFER_LEN);
- if (wchars_read >0) {
- write(STDOUT_FILENO,write_buffer,wchars_read);
- }
- // stdin -> pty_master, im logic is also here
- }
- //child process exit
- _exit(0);
- } else {
- //master process
- //registers interrupts
- signal(SIGCHLD, childhook);
- signal(SIGWINCH, winchhook);
- //display the im for the first time
- disp_im(STDIN_FILENO, trows, tcols);
+ //creates stdout semaphire
+ if (sem_init(&out_sem, 0, 1)) {
+ fprintf(stderr, "errno: %d, Error creating output sempahore\n", errno);
+ exit_main();
+ }
+ //creates a thread that just handles pty -> stdout transfers
+ if (pthread_create(&om_thread, NULL, &om_routine, NULL) ) {
+ fprintf(stderr, "errno: %d, Error creating om thread\n", errno);
+ exit_main();
+ }
+ if (pthread_create(&im_disp_thread, NULL, &im_disp_routine, NULL) ) {
+ fprintf(stderr, "errno: %d, Error creating im display thread\n", errno);
+ exit_main();
+ }
+ //master process
+ //registers interrupts
+ signal(SIGCHLD, childhook);
+ signal(SIGWINCH, winchhook);
- //1 char buffer for reading from stdin and writing to pty_master
- char read_buffer[1] = {0};
+ //1 char buffer for reading from stdin and writing to pty_master
+ char read_buffer[1] = {0};
- //open
- while (running) {
- int rchars_read = read(STDIN_FILENO, read_buffer, 1);
- if (rchars_read > 0) {
- //feeds input char into the escape state
- //machine
- in_state = update_esc_state(read_buffer, 1, in_state);
- //skips if the char was anything but
- //normal
- if (in_state == NORMAL || in_state ==DOUBLE_ESC) {
- //feeds the input char into the im state machine
- char input_buffer[IM_TABLE_ENTRY_LEN+1] = {0};
- int im_chars = update_im_state(read_buffer[0],
- input_buffer);
- //just in case it wasn't null terminated right
- input_buffer[im_chars] = 0;
- if (im_chars >0) {
- //writes the input into pty_master if
- //there was an output from the state
- //machine
- write(pty_master,input_buffer,im_chars);
- }
- } else {
- write(pty_master,read_buffer,1);
+ //open
+ while (running) {
+ int rchars_read = read(STDIN_FILENO, read_buffer, 1);
+ if (rchars_read > 0) {
+ //feeds input char into the escape state
+ //machine
+ in_state = update_esc_state(read_buffer, 1, in_state);
+ //skips if the char was anything but
+ //normal
+ if (in_state == NORMAL || in_state ==DOUBLE_ESC) {
+ //feeds the input char into the im state machine
+ char input_buffer[IM_TABLE_ENTRY_LEN+1] = {0};
+ int im_chars = update_im_state(read_buffer[0],
+ input_buffer);
+ //just in case it wasn't null terminated right
+ input_buffer[im_chars] = 0;
+ if (im_chars >0) {
+ //writes the input into pty_master if
+ //there was an output from the state
+ //machine
+ write(pty_master,input_buffer,im_chars);
}
- //any input update will lead to a disp_im update
- disp_im(STDIN_FILENO, trows, tcols);
+ } else {
+ write(pty_master,read_buffer,1);
}
}
- //at the end of the main process, kil lthe om process
- kill(om_pid, SIGKILL);
}
}
exit_main();