Initial commit of Pollcat library
This commit is contained in:
1
example/.gitignore
vendored
Normal file
1
example/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/terminal
|
||||
43
example/Makefile
Normal file
43
example/Makefile
Normal file
@@ -0,0 +1,43 @@
|
||||
# Example Makefile
|
||||
#
|
||||
# This file is part of the Pollcat Library.
|
||||
# Copyright (C) 2022 Expatria Technologies Inc.
|
||||
# Contact: Morgan Hughes <morgan@expatria.ca>
|
||||
#
|
||||
# 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
|
||||
|
||||
TERM_OBJS := tty.o main.o serial.o command.o
|
||||
TERM_LIBS := -lpollcat
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
all: terminal
|
||||
|
||||
terminal: $(TERM_OBJS)
|
||||
$(CC) $(CFLAGS) $(LFLAGS) $^ $(TERM_LIBS) -o $@
|
||||
|
||||
install:
|
||||
false
|
||||
|
||||
clean:
|
||||
rm -f $(TERM_OBJS)
|
||||
rm -f terminal
|
||||
|
||||
%.i: %.c
|
||||
$(CC) $(CFLAGS) -E $< -o $@
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
67
example/command.c
Normal file
67
example/command.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* Library exports
|
||||
*
|
||||
* This file is part of the Pollcat Library.
|
||||
* Copyright (C) 2022 Expatria Technologies Inc.
|
||||
* Contact: Morgan Hughes <morgan@expatria.ca>
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <pollcat.h>
|
||||
|
||||
#include "terminal.h"
|
||||
|
||||
|
||||
char command_char = '\01';
|
||||
int command_mode = 0;
|
||||
|
||||
void command_help (void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\r\nMenu\r\n"
|
||||
"Q - Quit\r\n"
|
||||
"X - Exit\r\n"
|
||||
"\r\n");
|
||||
}
|
||||
|
||||
void command_recv (char c)
|
||||
{
|
||||
switch ( tolower(c) )
|
||||
{
|
||||
case 'q':
|
||||
case 'x':
|
||||
case '\x11':
|
||||
case '\x18':
|
||||
pollcat_loop_exit();
|
||||
return;
|
||||
|
||||
case '\01':
|
||||
serial_write(&c, sizeof(c));
|
||||
return;
|
||||
|
||||
default:
|
||||
command_help();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
98
example/main.c
Normal file
98
example/main.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/** Minimal terminal using pollcat - main loop
|
||||
*
|
||||
* This file is part of the Pollcat Library.
|
||||
* Copyright (C) 2022 Expatria Technologies Inc.
|
||||
* Contact: Morgan Hughes <morgan@expatria.ca>
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <pollcat.h>
|
||||
|
||||
#include "terminal.h"
|
||||
|
||||
|
||||
char *opt_node = "/dev/ttyUSB0";
|
||||
char *opt_speed = "115200N81";
|
||||
|
||||
|
||||
static void signal_fatal (int signum)
|
||||
{
|
||||
fprintf(stderr, "Fatal signal %d, exit loop\n", signum);
|
||||
pollcat_loop_exit();
|
||||
}
|
||||
|
||||
extern char *__progname;
|
||||
static void usage (void)
|
||||
{
|
||||
printf("Usage: %s [-t timeout] [-b speed] [node]\n"
|
||||
"-t timeout Timeout for poll() calls (ms)\n"
|
||||
"-b speed Speed/parity/data/stop bits (default 115200N81)\n"
|
||||
"node should be a serial device, such as /dev/ttyS0 or /dev/ttyUSB0\n",
|
||||
__progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
while ( (opt = getopt(argc, argv, "t:b:")) != -1 )
|
||||
switch ( opt )
|
||||
{
|
||||
case 't':
|
||||
pollcat_time_base = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
opt_speed = optarg;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
if ( optind < argc )
|
||||
opt_node = argv[optind];
|
||||
|
||||
if ( serial_init(opt_node, opt_speed) )
|
||||
{
|
||||
perror(opt_node);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( tty_init() )
|
||||
{
|
||||
perror("tty_init");
|
||||
return 1;
|
||||
}
|
||||
|
||||
signal(SIGTERM, signal_fatal);
|
||||
signal(SIGINT, signal_fatal);
|
||||
|
||||
while ( pollcat_loop(NULL) )
|
||||
;
|
||||
|
||||
tty_done();
|
||||
serial_done();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
244
example/serial.c
Normal file
244
example/serial.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/** minimal terminal using pollcat
|
||||
*
|
||||
* This file is part of the Pollcat Library.
|
||||
* Copyright (C) 2022 Expatria Technologies Inc.
|
||||
* Contact: Morgan Hughes <morgan@expatria.ca>
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <pollcat.h>
|
||||
|
||||
#include "terminal.h"
|
||||
|
||||
|
||||
static int fd;
|
||||
|
||||
|
||||
static void service (struct pollcat *cat)
|
||||
{
|
||||
char buff[4096];
|
||||
int ret;
|
||||
int idx;
|
||||
|
||||
if ( !(pollcat_revents(fd) & POLLIN) )
|
||||
return;
|
||||
|
||||
while ( (ret = read(fd, buff, sizeof(buff))) > 0 )
|
||||
tty_write(buff, ret);
|
||||
}
|
||||
|
||||
static const struct pollcat_ops ops =
|
||||
{
|
||||
.service = service,
|
||||
};
|
||||
|
||||
static struct pollcat cat =
|
||||
{
|
||||
.ops = &ops,
|
||||
};
|
||||
|
||||
static int serial_fl;
|
||||
static int serial_fd;
|
||||
static struct termios serial_tio;
|
||||
|
||||
int serial_init (const char *node, const char *setup)
|
||||
{
|
||||
speed_t spd;
|
||||
char *mod;
|
||||
|
||||
if ( (fd = open(node, O_RDWR, 0)) < 0 )
|
||||
return -1;
|
||||
|
||||
// set stdin nonblocking
|
||||
if ( (serial_fl = fcntl(fd, F_GETFL)) < 0 )
|
||||
return -1;
|
||||
if ( fcntl(fd, F_SETFL, serial_fl | O_NONBLOCK) < 0 )
|
||||
return -1;
|
||||
|
||||
// set stdin nonblocking
|
||||
if ( (serial_fd = fcntl(fd, F_GETFD)) < 0 )
|
||||
return -1;
|
||||
if ( fcntl(fd, F_SETFD, serial_fd | FD_CLOEXEC) < 0 )
|
||||
return -1;
|
||||
|
||||
// save old terminal modes and make raw
|
||||
if ( tcgetattr(fd, &serial_tio) )
|
||||
return -1;
|
||||
|
||||
struct termios tio = serial_tio;
|
||||
cfmakeraw(&tio);
|
||||
|
||||
switch ( strtoul(setup, &mod, 10) )
|
||||
{
|
||||
case 50: spd = B50; break;
|
||||
case 75: spd = B75; break;
|
||||
case 110: spd = B110; break;
|
||||
case 134: spd = B134; break;
|
||||
case 150: spd = B150; break;
|
||||
case 200: spd = B200; break;
|
||||
case 300: spd = B300; break;
|
||||
case 600: spd = B600; break;
|
||||
case 1200: spd = B1200; break;
|
||||
case 1800: spd = B1800; break;
|
||||
case 2400: spd = B2400; break;
|
||||
case 4800: spd = B4800; break;
|
||||
case 9600: spd = B9600; break;
|
||||
case 19200: spd = B19200; break;
|
||||
case 38400: spd = B38400; break;
|
||||
case 57600: spd = B57600; break;
|
||||
case 115200: spd = B115200; break;
|
||||
#ifdef B230400
|
||||
case 230400: spd = B230400; break;
|
||||
#endif
|
||||
#ifdef B460800
|
||||
case 460800: spd = B460800; break;
|
||||
#endif
|
||||
#ifdef B500000
|
||||
case 500000: spd = B500000; break;
|
||||
#endif
|
||||
#ifdef B576000
|
||||
case 576000: spd = B576000; break;
|
||||
#endif
|
||||
#ifdef B921600
|
||||
case 921600: spd = B921600; break;
|
||||
#endif
|
||||
#ifdef B1000000
|
||||
case 1000000: spd = B1000000; break;
|
||||
#endif
|
||||
#ifdef B1152000
|
||||
case 1152000: spd = B1152000; break;
|
||||
#endif
|
||||
#ifdef B1500000
|
||||
case 1500000: spd = B1500000; break;
|
||||
#endif
|
||||
#ifdef B2000000
|
||||
case 2000000: spd = B2000000; break;
|
||||
#endif
|
||||
#ifdef B2500000
|
||||
case 2500000: spd = B2500000; break;
|
||||
#endif
|
||||
#ifdef B3000000
|
||||
case 3000000: spd = B3000000; break;
|
||||
#endif
|
||||
#ifdef B3500000
|
||||
case 3500000: spd = B3500000; break;
|
||||
#endif
|
||||
#ifdef B4000000
|
||||
case 4000000: spd = B4000000; break;
|
||||
#endif
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if ( cfsetispeed(&tio, spd) || cfsetospeed(&tio, spd) )
|
||||
return -1;
|
||||
|
||||
while ( *mod )
|
||||
{
|
||||
switch ( toupper(*mod) )
|
||||
{
|
||||
// data bits
|
||||
case '8': tio.c_cflag &= ~CSIZE; tio.c_cflag |= CS8; break;
|
||||
case '7': tio.c_cflag &= ~CSIZE; tio.c_cflag |= CS7; break;
|
||||
case '6': tio.c_cflag &= ~CSIZE; tio.c_cflag |= CS6; break;
|
||||
case '5': tio.c_cflag &= ~CSIZE; tio.c_cflag |= CS5; break;
|
||||
|
||||
// stop bits
|
||||
case '2': tio.c_cflag |= CSTOPB; break;
|
||||
case '1': tio.c_cflag &= ~CSTOPB; break;
|
||||
|
||||
// no parity
|
||||
case 'N':
|
||||
tio.c_iflag |= IGNPAR;
|
||||
tio.c_iflag &= ~INPCK;
|
||||
tio.c_cflag &= ~(PARENB | PARODD | CMSPAR);
|
||||
break;
|
||||
|
||||
// odd parity
|
||||
case 'O':
|
||||
tio.c_iflag |= INPCK | PARMRK;
|
||||
tio.c_iflag &= ~IGNPAR;
|
||||
tio.c_cflag |= PARENB | PARODD;
|
||||
tio.c_cflag &= ~CMSPAR;
|
||||
break;
|
||||
|
||||
// even parity
|
||||
case 'E':
|
||||
tio.c_iflag |= INPCK | PARMRK;
|
||||
tio.c_iflag &= ~IGNPAR;
|
||||
tio.c_cflag |= PARENB;
|
||||
tio.c_cflag &= ~(PARODD | CMSPAR);
|
||||
break;
|
||||
|
||||
// mark parity
|
||||
case 'M':
|
||||
tio.c_iflag |= INPCK | PARMRK;
|
||||
tio.c_iflag &= ~IGNPAR;
|
||||
tio.c_cflag |= PARENB | CMSPAR | PARODD;
|
||||
break;
|
||||
|
||||
// space parity
|
||||
case 'S':
|
||||
tio.c_iflag |= INPCK | PARMRK;
|
||||
tio.c_iflag &= ~IGNPAR;
|
||||
tio.c_cflag |= PARENB | CMSPAR;
|
||||
tio.c_cflag &= ~PARODD;
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
mod++;
|
||||
}
|
||||
|
||||
if ( tcsetattr(fd, TCSANOW, &tio) )
|
||||
return -1;
|
||||
|
||||
pollcat_fd_add(fd, POLLIN);
|
||||
pollcat_iter_add(&cat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void serial_done (void)
|
||||
{
|
||||
pollcat_iter_remove(&cat);
|
||||
pollcat_fd_remove(fd);
|
||||
|
||||
if ( fcntl(fd, F_SETFL, serial_fl) < 0 )
|
||||
perror("fcntl");
|
||||
|
||||
if ( fcntl(fd, F_SETFD, serial_fd) < 0 )
|
||||
perror("fcntl");
|
||||
|
||||
if ( tcsetattr(fd, TCSANOW, &serial_tio) )
|
||||
perror("tcsetattr");
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void serial_write (const void *buff, int len)
|
||||
{
|
||||
write(fd, buff, len);
|
||||
}
|
||||
41
example/terminal.h
Normal file
41
example/terminal.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/** Minimal terminal using pollcat - prototypes
|
||||
*
|
||||
* This file is part of the Pollcat Library.
|
||||
* Copyright (C) 2022 Expatria Technologies Inc.
|
||||
* Contact: Morgan Hughes <morgan@expatria.ca>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#ifndef _INCLUDE_TERMINAL_H_
|
||||
#define _INCLUDE_TERMINAL_H_
|
||||
|
||||
/* command.c */
|
||||
extern char command_char;
|
||||
extern int command_mode;
|
||||
void command_help (void);
|
||||
void command_recv (char c);
|
||||
|
||||
/* serial.c */
|
||||
int serial_init (const char *node, const char *speed);
|
||||
void serial_done (void);
|
||||
void serial_write (const void *buf, int len);
|
||||
|
||||
/* tty.c */
|
||||
int tty_init (void);
|
||||
void tty_done (void);
|
||||
void tty_write (const void *buf, int len);
|
||||
|
||||
#endif /* _INCLUDE_TERMINAL_H_ */
|
||||
151
example/tty.c
Normal file
151
example/tty.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/** Minimal terminal using pollcat - TTY side
|
||||
*
|
||||
* This file is part of the Pollcat Library.
|
||||
* Copyright (C) 2022 Expatria Technologies Inc.
|
||||
* Contact: Morgan Hughes <morgan@expatria.ca>
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <pollcat.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user