Added filter engine, xterm resize.
--- a/.hgignore Fri Sep 21 16:07:13 2007 +0200
+++ b/.hgignore Sun Sep 23 23:40:36 2007 +0200
@@ -1,2 +1,2 @@
.o$
-st
+^tm$
--- a/Makefile Fri Sep 21 16:07:13 2007 +0200
+++ b/Makefile Sun Sep 23 23:40:36 2007 +0200
@@ -7,12 +7,17 @@
app_term.o \
client_term.o \
user_term.o \
- tcp_server.o
+ tcp_server.o \
+ simple_math.o \
+ xterm.o
+all: tm test_filter
tm: $(OBJECTS)
$(CC) -o $@ -lutil $^
+test_filter: test_filter.o filter.o simple_math.o filter_string.o
+
clean:
rm -f $(OBJECTS) stdinmix
@@ -29,3 +34,8 @@
client_term.o: client_term.c main.h
user_term.o: user_term.c main.h
tcp_server.o: tcp_server.c main.h handlers.h
+simple_math.o: simple_math.c main.h
+filter.o: filter.c filter.h main.h
+test_filter.o: test_filter.c filter.h
+filter_string.o: filter_string.c filter.h
+xterm.o: xterm.c main.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filter.c Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,160 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "main.h"
+
+#include "filter.h"
+
+void add_ffilter(struct FilterRules *fr, struct FFilter *ff)
+{
+ fr->nfilters += 1;
+ fr->filters = (struct FFilter **) realloc(fr->filters,
+ sizeof(*fr->filters) * fr->nfilters);
+ if (fr->filters == 0) error("realloc failed.");
+
+ fr->filters[fr->nfilters-1] = ff;
+ ff->matched = 0;
+}
+
+struct FilterRules * new_filter_rules()
+{
+ struct FilterRules *fr;
+ fr = (struct FilterRules *) malloc(sizeof(*fr));
+ if (fr == 0) error("malloc failed.");
+
+ fr->nfilters = 0;
+ fr->filters = 0; /* null for realloc */
+ fr->fbuffer = 0;
+ fr->fbuffer_len = 0;
+ fr->fbuffer_allocated = 0;
+
+ return fr;
+}
+
+/* We want to access index even before the 'buffer' limits.
+ * Those are at fr->fbuffer, and referred as -X indexes. */
+static int get_char(struct FilterRules *fr, const unsigned char *buffer, int pos)
+{
+ if (pos >= 0)
+ return buffer[pos];
+ else
+ {
+ if (-pos > fr->fbuffer_len)
+ return -1;
+ /* pos is negative */
+ return fr->fbuffer[fr->fbuffer_len + pos];
+ }
+}
+
+static int set_char(struct FilterRules *fr, unsigned char *buffer, int pos, int c)
+{
+ if (pos >= 0)
+ {
+ buffer[pos] = c;
+ return buffer[pos];
+ }
+ else
+ {
+ if (-pos > fr->fbuffer_len)
+ return -1;
+ fr->fbuffer[fr->fbuffer_len - pos] = c;
+ return fr->fbuffer[fr->fbuffer_len - pos];
+ }
+}
+
+/* Return 1 if matches */
+static int apply_ffilter(struct FilterRules *fr, struct FFilter *ff,
+ char *obuf, int *olen, const unsigned char *buffer, int pos)
+{
+ int res;
+
+ res = ff->function(ff, buffer[pos]);
+ if (res)
+ {
+ /* String matches */
+ if (ff->callback)
+ {
+ int shift;
+ shift = pos - ff->matched;
+ /* Call callback */
+ ff->callback(fr, ff, obuf, olen, buffer, shift);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static void reset_matched(struct FilterRules *fr)
+{
+ int i;
+ for (i=0; i < fr->nfilters; ++i)
+ {
+ struct FFilter *ff;
+ ff = fr->filters[i];
+ ff->matched = 0;
+ if (ff->reset)
+ ff->reset(ff);
+ }
+}
+
+void filter_stream(struct FilterRules *fr, char *obuf, int *olen, const char *buffer, int len)
+{
+ int i;
+
+ int ipos;
+ int max_matched;
+
+ *olen = 0;
+ ipos = - fr->fbuffer_len;
+ max_matched = fr->fbuffer_len;
+ for(i=0; i< len; ++i)
+ { /* each char */
+ int j;
+ int old_max_matched = max_matched;
+ int found = 0;
+ max_matched = 0;
+ /*printf("Try '%c'...\n", buffer[i]);*/
+ for (j=0; j < fr->nfilters; ++j)
+ {
+ struct FFilter *ff;
+ ff = fr->filters[j];
+ found = apply_ffilter(fr, ff, obuf, olen, buffer, i);
+ max_matched = max(max_matched, ff->matched);
+ if (found)
+ break;
+ }
+ /* Some chars may not be needed for the filters
+ * already. */
+ /*printf("ipos: %i\n", ipos);*/
+ if (found)
+ {
+ /*printf("[match!]\n");*/
+ reset_matched(fr);
+ /* The longest string will be matched, sure. Right?*/
+ ipos += max_matched;
+ max_matched = 0;
+ }
+ else
+ {
+ int freed = old_max_matched + 1 /* new char */ - max_matched;
+ for(j=0; j < freed; ++j)
+ {
+ obuf[(*olen)++] = get_char(fr, buffer, ipos++);
+ }
+ }
+ }
+ if (max_matched > fr->fbuffer_allocated)
+ {
+ fr->fbuffer = realloc(fr->fbuffer, max_matched);
+ if (fr->fbuffer == 0) error("Cannot allocate fbuffer");
+ }
+ memcpy(fr->fbuffer, buffer + len - max_matched, max_matched);
+ fr->fbuffer_len = max_matched;
+}
+
+void filter_flush(struct FilterRules *fr, char *obuf, int *olen)
+{
+ memcpy(obuf, fr->fbuffer, fr->fbuffer_len);
+ *olen = fr->fbuffer_len;
+ fr->fbuffer_len = 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filter.h Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,35 @@
+struct FilterRules;
+struct FFilter;
+
+typedef void (*Fcallback)(struct FilterRules *fr, const struct FFilter *ff,
+ char *obuf, int *olen, const char *ibuf, int pos);
+
+/* TRUE if match */
+typedef int (*Ffunction)(struct FFilter *ff, unsigned char c);
+
+typedef void (*Freset)(struct FFilter *ff);
+
+struct FFilter {
+ /* Static */
+ Ffunction function;
+ Freset reset;
+ Fcallback callback;
+
+ int matched;
+};
+
+struct FilterRules {
+ int nfilters;
+ struct FFilter **filters;
+ unsigned char *fbuffer;
+ int fbuffer_len;
+ int fbuffer_allocated;
+};
+
+void add_ffilter(struct FilterRules *fr, struct FFilter *ff);
+struct FilterRules * new_filter_rules();
+void filter_stream(struct FilterRules *fr, char *obuf, int *olen, const char *buffer, int len);
+void filter_flush(struct FilterRules *fr, char *obuf, int *olen);
+
+/* filter_string.c */
+struct FFilter *new_fstring(char *p);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filter.old Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,190 @@
+#include <stdlib.h>
+#include <string.h>
+#include "main.h"
+
+#include "filter.h"
+
+static struct FString new_fstring()
+{
+ fs->p = p;
+ fs->len = len;
+ fs->actual_pos = 0;
+ fs->next_try = (int *) malloc(
+ sizeof(*fs->next_try) * len);
+}
+
+static void prepare_next_try(char *str, int len, int *next_try)
+{
+ int s; /* skip */
+
+ /* at x = next_try[s], it means how many x characters
+ * have we matched, if we have matched (s+1)? */
+ next_try[0] = 0; /* not used */
+ for (s = 2; s <= len; ++s)
+ {
+ int i;
+ /* compare [0..s-1] to [len - s, len-1] */
+ /* strlen(cmp) = s */
+ /* String compare, exit when not equal, offset in 'i' */
+ for(i=0; i < s; ++i)
+ if (str[len-s-i] != str[i])
+ break;
+ next_try[s-1] = i;
+ }
+}
+
+void add_fstring(struct FilterRules *fr, char *p, int len, Fcallback cb)
+{
+ struct FString *fs;
+ fr->nstrings += 1;
+ fr->strings = (struct FString **) realloc(fr->strings,
+ sizeof(*fr->strings) * fr->nstrings);
+ if (fr->strings == 0) error("realloc failed.");
+
+ /* Fill the last created space */
+ fs = (struct FString *) malloc(sizeof(*fs));
+ fr->strings[fr->nstrings-1] = fs;
+ if (fs == 0) error("malloc failed.");
+
+ new_fstring(fs, p, len);
+
+ /* Prepare the next_try array */
+ prepare_next_try(p, len, fs->next_try);
+
+ fs->callback = cb;
+
+ /* We will keep the fbuffers allocated for the longest
+ * string possible */
+ if (len > fr->fbuffer_allocated)
+ {
+ fr->fbuffer_allocated = len;
+ fr->fbuffer = realloc(fr->fbuffer, len);
+ }
+}
+
+struct FilterRules * new_filter_rules()
+{
+ struct FilterRules *fr;
+ fr = (struct FilterRules *) malloc(sizeof(*fr));
+ if (fr == 0) error("malloc failed.");
+
+ fr->nstrings = 0;
+ fr->strings = 0; /* null for realloc */
+ fr->fbuffer = 0;
+ fr->fbuffer_len = 0;
+ fr->fbuffer_allocated = 0;
+
+ return fr;
+}
+
+/* We want to access index even before the 'buffer' limits.
+ * Those are at fr->fbuffer, and referred as -X indexes. */
+static int get_char(struct FilterRules *fr, const unsigned char *buffer, int pos)
+{
+ if (pos >= 0)
+ return buffer[pos];
+ else
+ {
+ if (-pos > fr->fbuffer_len)
+ return -1;
+ return fr->fbuffer[fr->fbuffer_len - pos];
+ }
+}
+
+static int set_char(struct FilterRules *fr, unsigned char *buffer, int pos, int c)
+{
+ if (pos >= 0)
+ {
+ buffer[pos] = c;
+ return buffer[pos];
+ }
+ else
+ {
+ if (-pos > fr->fbuffer_len)
+ return -1;
+ fr->fbuffer[fr->fbuffer_len - pos] = c;
+ return fr->fbuffer[fr->fbuffer_len - pos];
+ }
+}
+
+/* Return 1 if matches */
+static int filter_string(struct FilterRules *fr, struct FString *fs,
+ char *obuf, int *olen, const unsigned char *buffer, int pos)
+{
+ while (fs->actual_pos > 0 && fs->p[fs->actual_pos] != buffer[pos])
+ {
+ /* next_try maps 1..len to 0..len-1 */
+ fs->actual_pos = fs->next_try[fs->actual_pos-1];
+ }
+ if (fs->p[fs->actual_pos] == buffer[pos])
+ fs->actual_pos += 1;
+ if (fs->actual_pos == fs->len)
+ {
+ /* String matches */
+ int shift;
+ shift = pos - fs->len;
+ /* Call callback */
+ fs->callback(fr, fs, obuf, olen, buffer, shift);
+ return 1;
+ }
+ return 0;
+}
+
+static void reset_actual_pos(struct FilterRules *fr)
+{
+ int i;
+ for (i=0; i < fr->nstrings; ++i)
+ {
+ struct FString *fs;
+ fs = fr->strings[i];
+ fs->actual_pos = 0;
+ }
+}
+
+void filter_stream(struct FilterRules *fr, char *obuf, int *olen, const char *buffer, int len)
+{
+ int i;
+
+ int ipos;
+
+ *olen = 0;
+ ipos = - fr->fbuffer_len;
+ for(i=0; i< len; ++i)
+ { /* each char */
+ int j;
+ int old_maxlen = fr->maxlen_found;
+ int found;
+ fr->maxlen_found = 0;
+ for (j=0; j < fr->nstrings; ++j)
+ {
+ struct FString *fs;
+ fs = fr->strings[j];
+ found = filter_string(fr, fs, obuf, olen, buffer, i);
+ if (found)
+ break;
+ fr->maxlen_found = max(fr->maxlen_found, fs->actual_pos);
+ }
+ /* Some chars may not be needed for the filters
+ * already. */
+ if (found)
+ {
+ reset_actual_pos(fr);
+ }
+ else
+ {
+ for(j=0; j < old_maxlen + 1 - fr->maxlen_found; ++j)
+ {
+ obuf[(*olen)++] = get_char(fr, buffer, ipos++);
+ }
+ }
+ }
+ memcpy(fr->fbuffer, buffer + len - fr->maxlen_found, fr->maxlen_found);
+ fr->fbuffer_len = fr->maxlen_found;
+}
+
+void filter_flush(struct FilterRules *fr, char *obuf, int *olen)
+{
+ memcpy(obuf, fr->fbuffer, fr->fbuffer_len);
+ *olen = fr->fbuffer_len;
+ fr->fbuffer_len = 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filter_string.c Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,45 @@
+#include <stdlib.h>
+#include <string.h>
+#include "filter.h"
+
+struct FString
+{
+ struct FFilter base;
+ unsigned char *p;
+ int len;
+};
+
+static void fstring_reset(struct FFilter *ff)
+{
+ ff->matched = 0;
+}
+
+static int fstring_function(struct FFilter *ff, unsigned char c)
+{
+ struct FString *fs = (struct FString *) ff;
+
+ if (fs->p[fs->base.matched] == c)
+ fs->base.matched++;
+ else
+ /* A SAC */
+ fs->base.matched = 0;
+
+ if (fs->base.matched == fs->len)
+ return 1;
+ return 0;
+}
+
+struct FFilter *new_fstring(char *p)
+{
+ struct FString *fs;
+ fs = (struct FString *) malloc(sizeof(*fs));
+
+ fs->p = strdup(p);
+ fs->len = strlen(p);
+ fs->base.matched = 0;
+ fs->base.function = fstring_function;
+ fs->base.reset = fstring_reset;
+ fs->base.callback = 0;
+
+ return (struct FFilter *) fs;
+}
--- a/gen_sockets.c Fri Sep 21 16:07:13 2007 +0200
+++ b/gen_sockets.c Sun Sep 23 23:40:36 2007 +0200
@@ -4,14 +4,18 @@
#include "main.h"
char *stream_buffer = 0;
+char *ostream_buffer = 0;
int stream_buffer_size;
+int ostream_buffer_size;
-void init_stream_buffer()
+void init_stream_buffers()
{
if (stream_buffer == 0)
{
assert(command_line.buffer_size > 0);
stream_buffer_size = command_line.buffer_size;
+ ostream_buffer_size = command_line.buffer_size;
stream_buffer = (char *) malloc(stream_buffer_size);
+ ostream_buffer = (char *) malloc(ostream_buffer_size);
}
}
--- a/main.c Fri Sep 21 16:07:13 2007 +0200
+++ b/main.c Sun Sep 23 23:40:36 2007 +0200
@@ -27,13 +27,6 @@
static const char version[] = "0.1";
-int max(int a, int b)
-{
- if (a > b)
- return a;
- return b;
-}
-
static int showhelp(const char *pname)
{
printf("tm v%s - terminal mixer, Copyright (C) 2007 "
@@ -170,7 +163,7 @@
default_command_line();
parse_opts(argc, argv);
- init_stream_buffer();
+ init_stream_buffers();
if (command_line.is_server)
res = server();
--- a/main.h Fri Sep 21 16:07:13 2007 +0200
+++ b/main.h Sun Sep 23 23:40:36 2007 +0200
@@ -49,7 +49,9 @@
/* gen_sockets.c */
extern char *stream_buffer;
extern int stream_buffer_size;
-void init_stream_buffer();
+extern char *ostream_buffer;
+extern int ostream_buffer_size;
+void init_stream_buffers();
/* server.c */
int server();
@@ -63,3 +65,6 @@
/* server_term.c */
void prepare_user_terminal();
void restore_user_terminal();
+
+/* xterm.h */
+char * get_xterm_resize_string();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/simple_math.c Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,8 @@
+#include "main.h"
+
+int max(int a, int b)
+{
+ if (a > b)
+ return a;
+ return b;
+}
--- a/tcp_server.c Fri Sep 21 16:07:13 2007 +0200
+++ b/tcp_server.c Sun Sep 23 23:40:36 2007 +0200
@@ -3,6 +3,7 @@
#include <unistd.h>
#include <stdio.h>
#include <netinet/in.h>
+#include <string.h>
#include <sys/socket.h>
#include <sys/select.h>
@@ -158,6 +159,13 @@
{
conn_sockets[connected_sockets++] =
accept_connection(listen_socket);
+ if (command_line.s_param.run_in_subterminal)
+ {
+ char *xterm_str;
+ xterm_str = get_xterm_resize_string();
+ send(conn_sockets[connected_sockets-1],
+ xterm_str, strlen(xterm_str), 0);
+ }
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test_filter.c Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "filter.h"
+
+char base[] = "El val dilluns vaig provar el tatami d'en valeri\n";
+
+int main()
+{
+ int i;
+ char obuf[sizeof base];
+ struct FilterRules *fr;
+ struct FFilter *ff;
+ fr = new_filter_rules();
+
+ ff = new_fstring("val");
+ add_ffilter(fr, ff);
+ ff = new_fstring("tatami");
+ add_ffilter(fr, ff);
+
+ for(i=1; i < sizeof(base)-1; ++i)
+ {
+ int olen;
+ printf("test %i:\n", i);
+ if (i == 17)
+ olen=0;
+ filter_stream(fr, obuf, &olen, base, i);
+ filter_stream(fr, obuf + olen, &olen, base + i, sizeof(base) - i);
+ filter_flush(fr, obuf + olen, &olen);
+ printf("%s", obuf);
+ }
+
+ {
+ int olen = 0;
+ printf("test po litere:\n");
+ for(i=0; i < sizeof(base); ++i)
+ {
+ int tlen;
+ filter_stream(fr, obuf + olen, &tlen, base + i, 1);
+ olen += tlen;
+ }
+ filter_flush(fr, obuf + olen, &olen);
+ printf("%s", obuf);
+ }
+
+ return 0;
+}
--- a/unix_server.c Fri Sep 21 16:07:13 2007 +0200
+++ b/unix_server.c Sun Sep 23 23:40:36 2007 +0200
@@ -191,6 +191,13 @@
{
conn_sockets[connected_sockets++] =
accept_connection(listen_socket);
+ if (command_line.s_param.run_in_subterminal)
+ {
+ char *xterm_str;
+ xterm_str = get_xterm_resize_string();
+ send(conn_sockets[connected_sockets-1],
+ xterm_str, strlen(xterm_str), 0);
+ }
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xterm.c Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,23 @@
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include "main.h"
+
+static char xterm_resize_string[100];
+
+char * get_xterm_resize_string()
+{
+ struct winsize win;
+ int rows, cols;
+
+ /* Get rows and cols from our connection to the terminal: fd 1 */
+ ioctl(1, TIOCGWINSZ, (char *)&win);
+ rows = win.ws_row;
+ cols = win.ws_col;
+
+ /* Prepare the xterm resize string */
+ snprintf(xterm_resize_string, 100, "\033[8;%i;%it", rows, cols);
+
+ return xterm_resize_string;
+}