From 5f5d1604492ae15967f9d86f41fbeeedcae0ae2b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 8 Jul 1999 06:44:55 +0200 Subject: Import ax25-tools 0.0.3 from tarball --- user_call/user_io.c | 215 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 user_call/user_io.c (limited to 'user_call/user_io.c') diff --git a/user_call/user_io.c b/user_call/user_io.c new file mode 100644 index 0000000..2e594f6 --- /dev/null +++ b/user_call/user_io.c @@ -0,0 +1,215 @@ +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "user_io.h" + +int compression = 0; +int paclen_in = 256; +int paclen_out = 256; + +/* This is for select_loop() */ +static unsigned char buf[8192]; + +#ifdef HAVE_ZLIB_H +#include + +/* Error in (de)compression happened? */ +static int compression_error = 0; + +/* These are for the (de)compressor */ +static unsigned char input_buffer[8192]; +static unsigned char output_buffer[8192]; + +static z_stream incoming_stream; +static z_stream outgoing_stream; +#endif + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +void err(char *message) +{ + user_write(STDOUT_FILENO, message, strlen(message)); + exit(1); +} + +void init_compress(void) +{ +#ifdef HAVE_ZLIB_H + inflateInit(&incoming_stream); + deflateInit(&outgoing_stream, 9); + + incoming_stream.next_in = input_buffer; +#else + err("*** Compression support not available!!!\r\n"); +#endif +} + +void end_compress(void) +{ +#ifdef HAVE_ZLIB_H + inflateEnd(&incoming_stream); + deflateEnd(&outgoing_stream); +#endif +} + +static int flush_output(int fd, const void *buf, size_t count) +{ + int cnt = count; + + while (cnt > 0) { + write(fd, buf, min(paclen_out, cnt)); + buf += paclen_out; + cnt -= paclen_out; + } + + return count; +} + +int user_write(int fd, const void *buf, size_t count) +{ +#ifdef HAVE_ZLIB_H + int status; +#endif + + if (count == 0) + return 0; + +#ifndef HAVE_ZLIB_H + return flush_output(fd, buf, count); +#else + /* Only output to stdout can be compressed */ + if (fd != STDOUT_FILENO || !compression) + return flush_output(fd, buf, count); + + if (compression_error) { + errno = 0; + return -1; + } + + /* Input is the contents of the input buffer. */ + outgoing_stream.next_in = (unsigned char *)buf; + outgoing_stream.avail_in = count; + + /* Loop compressing until deflate() returns with avail_out != 0. */ + do { + /* Set up fixed-size output buffer. */ + outgoing_stream.next_out = output_buffer; + outgoing_stream.avail_out = sizeof(output_buffer); + + /* Compress as much data into the buffer as possible. */ + status = deflate(&outgoing_stream, Z_PARTIAL_FLUSH); + + if (status != Z_OK) { + compression_error = status; + errno = 0; + return -1; + } + + /* Now send the compressed data */ + flush_output(fd, output_buffer, sizeof(output_buffer) - outgoing_stream.avail_out); + + } while (outgoing_stream.avail_out == 0); + + return count; +#endif +} + +int user_read(int fd, void *buf, size_t count) +{ +#ifdef HAVE_ZLIB_H + int status, len; +#endif + + if (count == 0) + return 0; + +#ifndef HAVE_ZLIB_H + return read(fd, buf, count); +#else + /* Only input from stdin can be compressed */ + if (fd != STDIN_FILENO || !compression) + return read(fd, buf, count); + + if (compression_error) { + errno = 0; + return -1; + } + + incoming_stream.next_out = buf; + incoming_stream.avail_out = count; + + for (;;) { + status = inflate(&incoming_stream, Z_SYNC_FLUSH); + + if (count - incoming_stream.avail_out > 0) + return count - incoming_stream.avail_out; + + if (status != Z_OK && status != Z_BUF_ERROR) { + compression_error = status; + errno = 0; + return -1; + } + + incoming_stream.next_in = input_buffer; + incoming_stream.avail_in = 0; + + if ((len = read(fd, input_buffer, sizeof(input_buffer))) < 0) + return -1; + + incoming_stream.avail_in = len; + } + + return 0; +#endif +} + +int select_loop(int s) +{ + fd_set read_fd; + int n; + + if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { + close(s); + return -1; + } + if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) == -1) { + close(s); + return -1; + } + + /* + * Loop until one end of the connection goes away. + */ + for (;;) { + FD_ZERO(&read_fd); + FD_SET(STDIN_FILENO, &read_fd); + FD_SET(s, &read_fd); + + select(s + 1, &read_fd, NULL, NULL, NULL); + + if (FD_ISSET(s, &read_fd)) { + while ((n = user_read(s, buf, 8192)) > 0) + user_write(STDOUT_FILENO, buf, n); + if (n == 0 || errno != EAGAIN) { + close(s); + break; + } + } + + if (FD_ISSET(STDIN_FILENO, &read_fd)) { + while ((n = user_read(STDIN_FILENO, buf, 8192)) > 0) + user_write(s, buf, n); + if (n == 0 || errno != EAGAIN) { + close(s); + break; + } + } + } + + return 0; +} -- cgit v1.2.3