/** Minimal terminal using pollcat - TTY side * * This file is part of the Pollcat Library. * Copyright (C) 2022 Expatria Technologies Inc. * Contact: Morgan Hughes * * The Pollcat Library is free software: you can redistribute it and/or modify it under * the terms of the the GNU Lesser General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) any later * version. * * 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 General Public License for more details. * * You should have received copies of the GNU General Public License and the GNU Lesser * General Public License along with the Pollcat Library. If not, see * https://www.gnu.org/licenses/ * * vim:ts=4:noexpandtab */ #include #include #include #include #include #include #include #include #include "terminal.h" static struct pollcat_timer timer = { 0 }; static void callback (void *arg) { command_help(); } static void service (struct pollcat *cat) { char buff[256]; char *ptr; int ret; if ( !(pollcat_revents(fileno(stdin)) & POLLIN) ) return; memset(buff, 0, sizeof(buff)); if ( (ret = read(fileno(stdin), buff, sizeof(buff) - 1)) < 0 ) { fprintf(stderr, "recv(%d): %s", ret, strerror(errno)); pollcat_loop_exit(); return; } if ( command_mode ) { pollcat_timer_detach(&timer); command_recv(buff[0]); command_mode = 0; return; } if ( !(ptr = memchr(buff, command_char, ret)) ) { serial_write(buff, ret); return; } if ( ptr > buff ) serial_write(buff, ptr - buff); if ( (1 + ptr - buff) < ret ) { pollcat_timer_detach(&timer); command_recv(ptr[1]); } else { pollcat_timer_attach(&timer, 1000, callback, NULL); command_mode = 1; } } static const struct pollcat_ops ops = { .service = service, }; struct pollcat cat = { .ops = &ops, }; static int tty_flags; static struct termios tty_tio; int tty_init (void) { char tty[256]; memset(tty, 0, sizeof(tty)); if ( readlink("/proc/self/fd/1", tty, sizeof(tty)) > 0 ) { if ( !freopen(tty, "w", stdout) || !freopen(tty, "w", stderr) ) perror(tty); setbuf(stderr, NULL); } tty_flags = fcntl(fileno(stdin), F_GETFL); if ( tty_flags < 0 ) return -1; if ( fcntl(fileno(stdin), F_SETFL, tty_flags | O_NONBLOCK) < 0 ) return -1; if ( tcgetattr(fileno(stdin), &tty_tio) ) return -1; struct termios tio = tty_tio; cfmakeraw(&tio); if ( tcsetattr(fileno(stdin), TCSANOW, &tio) ) return -1; pollcat_fd_add(fileno(stdin), POLLIN); pollcat_iter_add(&cat); command_char = '\01'; command_mode = 0; return 0; } void tty_done (void) { pollcat_iter_remove(&cat); pollcat_fd_remove(fileno(stdin)); if ( fcntl(0, F_SETFL, tty_flags) < 0 ) perror("fcntl"); if ( tcsetattr(0, TCSANOW, &tty_tio) ) perror("tcsetattr"); } void tty_write (const void *buff, int len) { write(fileno(stdout), buff, len); }