/* * Usurpation – null (stdio) im proto * * Copyright (C) 2019 Gediminas Jakutis * Copyright (C) 2019 Paulius Ratkevičius * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include "proto_stdio.h" #include "proto_stdio_private.h" void message_receive(char *arg) { int done = 0; while(!done) { pthread_mutex_lock(&state.out_m); if(!state.writebuf) { state.writebuf = strdup(arg); done = 1; } pthread_mutex_unlock(&state.out_m); } } char * message_send(void) { char * ret; pthread_mutex_lock(&state.out_m); ret = strdup(state.writebuf); free(state.writebuf); state.writebuf = NULL; pthread_mutex_unlock(&state.out_m); return ret; } static void *read_stdin(void *arg) { while(1) { pthread_mutex_lock(&state.in_m); if(!state.readbuf) { state.readbufsize = getline(&state.readbuf,NULL, stdin); } pthread_mutex_unlock(&state.in_m); } } static void *write_stdout(void *arg) { while(1) { pthread_mutex_lock(&state.out_m); if(state.writebuf) { printf("%s", state.writebuf); free(state.writebuf); state.writebuf = NULL; } pthread_mutex_unlock(&state.out_m); } } int proto_stdio_init(void) { int ret = 0; /* aquire the """singleton""" mutex */ if (pthread_mutex_trylock(&state.mutex)) { /* TODO: use proper error numbers */ ret = 1; } else { if ((ret = pthread_create(&state.stdio_in, NULL, read_stdin, NULL))) { proto_stdio_close(); } if ((ret = pthread_create(&state.stdio_out, NULL, write_stdout, NULL))) { proto_stdio_close(); } } return ret; } void proto_stdio_close(void) { if (pthread_mutex_trylock(&state.mutex) == EBUSY) { pthread_cancel(state.stdio_in); pthread_cancel(state.stdio_out); pthread_join(state.stdio_in, NULL); pthread_join(state.stdio_out, NULL); } pthread_mutex_unlock(&state.mutex); }