Author: bdonlan
Date: 2004-12-30 22:00:30 -0500 (Thu, 30 Dec 2004)
New Revision: 485
Added:
trunk/clients/havercurs/
trunk/clients/havercurs/Makefile.am
trunk/clients/havercurs/TODO
trunk/clients/havercurs/autogen.sh
trunk/clients/havercurs/configure.ac
trunk/clients/havercurs/display.c
trunk/clients/havercurs/display.h
trunk/clients/havercurs/entry.c
trunk/clients/havercurs/entry.h
trunk/clients/havercurs/event.c
trunk/clients/havercurs/event.h
trunk/clients/havercurs/lineio.c
trunk/clients/havercurs/lineio.h
trunk/clients/havercurs/main.c
trunk/clients/havercurs/mymalloc.c
trunk/clients/havercurs/mymalloc.h
trunk/clients/havercurs/net.c
trunk/clients/havercurs/net.h
Removed:
trunk/clients/ncurses/
Modified:
trunk/
Log:
[EMAIL PROTECTED]: bdonlan | 2004-12-31T02:59:11.945246Z
Renamed to havercurs
Property changes on: trunk
___________________________________________________________________
Name: svk:merge
- 1f59643a-e6e5-0310-bc24-f7d4c744f460:/haver/local/trunk:10236
27e50396-46e3-0310-8b22-ae223a1f35ce:/local:212
edfcd8bd-4ce7-0310-a97e-bb1efd40edf3:/local:238
+ 1f59643a-e6e5-0310-bc24-f7d4c744f460:/haver/local/trunk:10237
27e50396-46e3-0310-8b22-ae223a1f35ce:/local:212
edfcd8bd-4ce7-0310-a97e-bb1efd40edf3:/local:238
Property changes on: trunk/clients/havercurs
___________________________________________________________________
Name: svn:ignore
+ configure
Makefile.in
config.log
depcomp
config.guess
config.h
config.sub
ltmain.sh
.libs
.deps
Makefile
mkinstalldirs
config.status
stamp-h1
config.h.in
havercurs
autom4te.cache
libtool
missing
aclocal.m4
install-sh
Added: trunk/clients/havercurs/Makefile.am
===================================================================
--- trunk/clients/havercurs/Makefile.am 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/Makefile.am 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,11 @@
+## Process this file with automake to produce Makefile.in
+## vim: set ts=4 sw=4 si ai sta tw=104:
+
+bin_PROGRAMS = havercurs
+havercurs_SOURCES = main.c main.h \
+ display.c display.h \
+ event.c event.h \
+ entry.c entry.h \
+ mymalloc.c mymalloc.h \
+ net.c net.h \
+ lineio.c lineio.h
Property changes on: trunk/clients/havercurs/Makefile.am
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/TODO
===================================================================
--- trunk/clients/havercurs/TODO 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/TODO 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,22 @@
+Done:
+* input line
+* basic display
+* event loop (fd polling, timers)
+
+Debugging:
+* Synchronous connection
+
+Partial implementation:
+* Line-oriented buffered I/O
+
+TODO:
+* Hash table
+* /-command parser
+* Haver protocol parser
+* Authentication
+* Chat
+* Asynchronous connection and DNS
+* Input history
+* Scrollback
+* Preferences save
+* Colors
Added: trunk/clients/havercurs/autogen.sh
===================================================================
--- trunk/clients/havercurs/autogen.sh 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/autogen.sh 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,9 @@
+#!/bin/bash
+# vim: set ts=4 sw=4 expandtab si ai sta tw=104:
+export WANT_AUTOMAKE=1.7
+export WANT_AUTOCONF=1.5
+set -x
+aclocal &&
+autoheader &&
+automake --foreign --add-missing &&
+autoconf
Property changes on: trunk/clients/havercurs/autogen.sh
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/configure.ac
===================================================================
--- trunk/clients/havercurs/configure.ac 2004-12-31 03:00:15 UTC (rev
484)
+++ trunk/clients/havercurs/configure.ac 2004-12-31 03:00:30 UTC (rev
485)
@@ -0,0 +1,27 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl vim: set ts=4 sw=4 expandtab si ai sta tw=104:
+
+AC_INIT(havercurs, 0.0.1)
+AM_INIT_AUTOMAKE
+AM_CONFIG_HEADER(config.h)
+
+dnl Checks for programs.
+AC_PROG_CC
+
+dnl Checks for libraries.
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(sys/time.h assert.h ncurses.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+
+dnl Checks for library functions.
+AC_TYPE_SIGNAL
+AC_CHECK_FUNCS(gettimeofday select)
+AC_CHECK_LIB(ncurses, initscr)
+
+AC_OUTPUT(Makefile)
Property changes on: trunk/clients/havercurs/configure.ac
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/display.c
===================================================================
--- trunk/clients/havercurs/display.c 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/display.c 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,24 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#include "display.h"
+#include <ncurses.h>
+
+static WINDOW *dwin = NULL;
+
+void display_init(int lines) {
+ dwin = newwin(lines, COLS, 0, 0);
+ idlok(dwin, TRUE);
+ scrollok(dwin, TRUE);
+}
+
+void display_free(void) {
+ delwin(dwin);
+ dwin = NULL;
+}
+
+void display_print(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ vw_printw(dwin, fmt, ap);
+ va_end(ap);
+ wnoutrefresh(dwin);
+}
Property changes on: trunk/clients/havercurs/display.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/display.h
===================================================================
--- trunk/clients/havercurs/display.h 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/display.h 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,10 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#ifndef DISPLAY_H
+#define DISPLAY_H 1
+
+void display_init(int lines);
+void display_free(void);
+
+void display_print(const char *fmt, ...);
+
+#endif
Property changes on: trunk/clients/havercurs/display.h
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/entry.c
===================================================================
--- trunk/clients/havercurs/entry.c 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/entry.c 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,109 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#include "mymalloc.h"
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ncurses.h>
+
+static char *buffer = NULL;
+int pos, len, blen, win;
+
+void entry_init(void) {
+ pos = len = win = 0;
+ blen = 32;
+ buffer = mymalloc(blen);
+}
+
+void entry_free(void) {
+ free(buffer);
+ buffer = NULL;
+}
+
+int entry_get_pos(void) {
+ return pos;
+}
+
+int entry_get_len(void) {
+ return len;
+}
+
+static void checkpos(void) {
+ if (pos < 0)
+ pos = 0;
+ if (pos > len)
+ pos = len;
+}
+
+char entry_remove_ch(int offset) {
+ char c;
+ if (offset >= len || offset < 0)
+ return 0;
+ c = buffer[offset];
+ memmove(&buffer[offset], &buffer[offset + 1], len - offset - 1);
+ len--;
+ checkpos();
+ return c;
+}
+
+static void expand_buf(void) {
+ blen = (blen * 3) / 2;
+ buffer = myrealloc(buffer, blen);
+}
+
+void entry_insert_ch(int offset, char c) {
+ if (offset < 0 || offset > len) {
+ assert(0);
+ abort();
+ }
+ if (len + 1 > blen)
+ expand_buf();
+ memmove(&buffer[offset + 1], &buffer[offset], len - offset);
+ buffer[offset] = c;
+ len++;
+}
+
+int entry_move_abs(int offset) {
+ pos = offset;
+ checkpos();
+ return pos;
+}
+
+int entry_move_rel(int offset) {
+ pos += offset;
+ checkpos();
+ return pos;
+}
+
+const char *entry_get(void) {
+ if (len + 1 > blen)
+ expand_buf();
+ buffer[len] = '\0'; /* null-terminate it for the caller */
+ return buffer;
+}
+
+void entry_clear(void) {
+ len = pos = win = 0;
+}
+
+void entry_refresh(WINDOW *w, int yoff, int cols) {
+ int i, lim;
+ wmove(w, yoff, 0);
+ wclrtoeol(w);
+
+ /* Is the window sane? */
+ if (pos < win ||
+ pos > win + cols
+ )
+ {
+ win = pos - (cols / 2);
+ if (win < 0)
+ win = 0;
+ }
+
+ lim = win + cols;
+ for (i = win; i < lim && i < len; i++) {
+ addch(buffer[i]);
+ }
+ wmove(w, yoff, pos - win);
+ wnoutrefresh(w);
+}
Property changes on: trunk/clients/havercurs/entry.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/entry.h
===================================================================
--- trunk/clients/havercurs/entry.h 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/entry.h 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,22 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#ifndef ENTRY_H
+#define ENTRY_H 1
+
+void entry_init(void);
+void entry_free(void);
+
+int entry_get_pos(void);
+int entry_get_len(void);
+
+char entry_remove_ch(int offset);
+void entry_insert_ch(int offset, char c);
+
+int entry_move_abs(int offset);
+int entry_move_rel(int offset);
+
+const char *entry_get(void);
+void entry_clear(void);
+
+void entry_refresh(WINDOW *w, int yoff, int cols);
+
+#endif
Property changes on: trunk/clients/havercurs/entry.h
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/event.c
===================================================================
--- trunk/clients/havercurs/event.c 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/event.c 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,266 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#include "mymalloc.h"
+#include "event.h"
+#include <sys/time.h>
+#include <sys/select.h>
+
+typedef struct event_timer_struct {
+ struct event_timer_struct *next;
+ struct timeval when;
+ event_timer_callback *cb;
+ void *baton;
+} event_timer_t;
+
+typedef struct event_fd_struct {
+ struct event_fd_struct *next;
+ int fd;
+ int mode;
+ event_fd_callback *cb;
+ void *baton;
+} event_fd_t;
+
+static event_timer_t *t_head = NULL;
+static event_fd_t *fd_head = NULL;
+
+static fd_set cache_r, cache_w, cache_e;
+static int fd_max = 0;
+
+void event_init(void) {
+ FD_ZERO(&cache_r);
+ FD_ZERO(&cache_w);
+ FD_ZERO(&cache_e);
+}
+
+void event_free(void) {
+ event_timer_t *t_cur = t_head;
+ event_fd_t *io_cur = fd_head;
+ while (t_cur) {
+ event_timer_t *next = t_cur;
+ free(t_cur);
+ t_cur = next;
+ }
+ t_head = NULL;
+ while (io_cur) {
+ event_fd_t *next = io_cur;
+ free(io_cur);
+ io_cur = next;
+ }
+ fd_head = NULL;
+}
+
+void event_timer_abs(
+ const struct timeval *when,
+ event_timer_callback *cb,
+ void *baton
+ ) {
+ event_timer_t *new = mymalloc(sizeof *new);
+ event_timer_t *cur, *prev;
+ new->when = *when;
+ new->cb = cb;
+ new->baton = baton;
+ prev = NULL;
+ cur = t_head;
+ while (cur) {
+ if (cur->when.tv_sec < new->when.tv_sec ||
+ cur->when.tv_usec < new->when.tv_usec
+ )
+ {
+ break;
+ }
+ cur = cur->next;
+ }
+ if (prev)
+ prev->next = new;
+ else
+ t_head = new;
+ new->next = cur;
+}
+
+void event_timer_rel(
+ const struct timeval *when,
+ event_timer_callback *cb,
+ void *baton
+ )
+{
+ struct timeval absolute;
+ gettimeofday(&absolute, NULL);
+ absolute.tv_sec += when->tv_sec;
+ absolute.tv_usec += when->tv_usec;
+ if (absolute.tv_usec > 1000000) {
+ absolute.tv_sec += absolute.tv_usec / 1000000;
+ absolute.tv_usec %= 1000000;
+ }
+ event_timer_abs(&absolute, cb, baton);
+}
+
+static int check_timers(
+ const struct timeval *now,
+ const struct timeval **next
+ )
+{
+ int counter = 0;
+ const struct timeval *dummy;
+ if (!next)
+ next = &dummy;
+ while (t_head) {
+ if (t_head->when.tv_sec < now->tv_sec ||
+ (t_head->when.tv_sec == now->tv_sec &&
+ t_head->when.tv_usec < now->tv_usec
+ ))
+ {
+ event_timer_t *cur = t_head;
+ counter++;
+ t_head = cur->next;
+ cur->cb(&cur->when, cur->baton);
+ free(cur);
+ } else break;
+ }
+ if (t_head)
+ *next = &t_head->when;
+ else
+ *next = NULL;
+ return counter;
+}
+
+static void recache_fd(event_fd_t *what, int add) {
+ if (what->mode & EVENT_FD_READABLE)
+ FD_SET(what->fd, &cache_r);
+ else
+ FD_CLR(what->fd, &cache_r);
+ if (what->mode & EVENT_FD_WRITABLE)
+ FD_SET(what->fd, &cache_w);
+ else
+ FD_CLR(what->fd, &cache_w);
+ if (what->mode & EVENT_FD_ERROR)
+ FD_SET(what->fd, &cache_e);
+ else
+ FD_CLR(what->fd, &cache_e);
+
+ if (add) {
+ if (what->fd + 1 > fd_max)
+ fd_max = what->fd + 1;
+ } else {
+ if (what->fd + 1 == fd_max) {
+ event_fd_t *cur = fd_head;
+ fd_max = 0;
+ while (cur) {
+ if (cur->fd + 1 > fd_max)
+ fd_max = cur->fd + 1;
+ cur = cur->next;
+ }
+ }
+ }
+}
+
+static event_fd_t *search(int fd, event_fd_t **prev) {
+ event_fd_t *dummy, *cur;
+ if (!prev)
+ prev = &dummy;
+ cur = fd_head;
+ while (cur) {
+ if (cur->fd == fd)
+ return cur;
+ *prev = cur;
+ cur = cur->next;
+ }
+ return NULL;
+}
+
+void event_addfd(
+ int fd,
+ int mode,
+ event_fd_callback *cb,
+ void *baton
+ ) {
+ static event_fd_t *prev, *cur;
+ cur = search(fd, &prev);
+ if (!cur) {
+ cur = mymalloc(sizeof *cur);
+ cur->fd = fd;
+ if (prev) {
+ cur->next = prev->next;
+ prev->next = cur;
+ } else {
+ cur->next = fd_head;
+ fd_head = cur;
+ }
+ }
+ cur->cb = cb;
+ cur->mode = mode;
+ cur->baton = baton;
+ recache_fd(cur, 1);
+}
+
+void event_delfd(int fd) {
+ static event_fd_t *prev, *cur;
+ cur = search(fd, &prev);
+ if (!cur)
+ return;
+ if (prev)
+ prev->next = cur->next;
+ else
+ fd_head = cur->next;
+ recache_fd(cur, 0);
+}
+
+static int io_poll(struct timeval *timeout) {
+ fd_set r, w, e;
+ int count = 0;
+ int remain = 0;
+ event_fd_t *cur = fd_head;
+ r = cache_r;
+ w = cache_w;
+ e = cache_e;
+ remain = select(fd_max, &r, &w, &e, timeout);
+ while (remain > 0 && cur) {
+ int mode = 0;
+ int fd = cur->fd;
+ if (FD_ISSET(fd, &r)) {
+ remain--;
+ mode |= EVENT_FD_READABLE;
+ }
+ if (FD_ISSET(fd, &w)) {
+ remain--;
+ mode |= EVENT_FD_WRITABLE;
+ }
+ if (FD_ISSET(fd, &e)) {
+ remain--;
+ mode |= EVENT_FD_ERROR;
+ }
+ if (mode & ~cur->mode)
+ recache_fd(cur, 1);
+ mode &= cur->mode;
+ if (mode) {
+ count++;
+ cur->cb(fd, mode, cur->baton);
+ }
+ cur = cur->next;
+ }
+ return count;
+}
+
+int event_poll(int block) {
+ int counter = 0;
+ struct timeval now;
+ const struct timeval *next;
+ struct timeval tv, *p_tv = NULL;
+ gettimeofday(&now, NULL);
+ counter += check_timers(&now, &next);
+ if (block && next) {
+ tv.tv_sec = next->tv_sec - now.tv_sec;
+ tv.tv_usec = next->tv_usec - now.tv_usec;
+ if (tv.tv_usec < 0) {
+ tv.tv_sec--;
+ tv.tv_usec += 1000000;
+ }
+ p_tv = &tv;
+ }
+ if (!block) {
+ tv.tv_sec = tv.tv_usec = 0;
+ p_tv = &tv;
+ }
+ counter += io_poll(p_tv);
+ gettimeofday(&now, NULL);
+ counter += check_timers(&now, NULL);
+ return counter;
+}
Property changes on: trunk/clients/havercurs/event.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/event.h
===================================================================
--- trunk/clients/havercurs/event.h 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/event.h 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,38 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#ifndef EVENT_H
+#define EVENT_H 1
+
+#define EVENT_FD_READABLE 1
+#define EVENT_FD_WRITABLE 2
+#define EVENT_FD_ERROR 4
+
+typedef void event_fd_callback(int fd, int mode, void *baton);
+typedef void event_timer_callback(const struct timeval *when, void *baton);
+
+void event_init(void);
+void event_free(void);
+
+void event_timer_abs(
+ const struct timeval *when,
+ event_timer_callback *cb,
+ void *baton
+ );
+
+void event_timer_rel(
+ const struct timeval *when,
+ event_timer_callback *cb,
+ void *baton
+ );
+
+void event_addfd(
+ int fd,
+ int mode,
+ event_fd_callback *cb,
+ void *baton
+ );
+
+void event_delfd(int fd);
+
+int event_poll(int block);
+
+#endif
Property changes on: trunk/clients/havercurs/event.h
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/lineio.c
===================================================================
--- trunk/clients/havercurs/lineio.c 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/lineio.c 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,108 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <assert.h>
+#include "lineio.h"
+#include "mymalloc.h"
+#include "event.h"
+
+struct lineio_conn {
+ char *outbuf;
+ size_t outbuf_used, outbuf_len;
+ char *inbuf;
+ size_t inbuf_used, inbuf_len;
+
+ lineio_callback *cb;
+ void *baton;
+
+ int fd;
+};
+
+
+static void lineio_evcallback(int fd, int mode, void *baton);
+
+lineio_conn *lineio_attach(
+ int fd, lineio_callback *cb, void *baton
+ )
+{
+ lineio_conn *conn = mymalloc(sizeof *conn);
+ conn->outbuf_used = conn->inbuf_used = 0;
+ conn->inbuf_len = conn->outbuf_len = 32;
+ conn->inbuf = mymalloc(conn->inbuf_len);
+ conn->outbuf = mymalloc(conn->outbuf_len);
+
+ conn->cb = cb;
+ conn->baton = baton;
+ conn->fd = fd;
+
+ event_addfd(
+ fd,
+ EVENT_FD_READABLE | EVENT_FD_ERROR,
+ lineio_evcallback,
+ conn
+ );
+}
+
+static void lineio_evcallback(int fd, int mode, void *baton) {
+ lineio_conn *conn = baton;
+ assert(conn->fd == fd);
+ if (mode & EVENT_FD_READABLE) {
+ /* FIXME: Line buffering. This is a test hack */
+ ssize_t dlen = read(fd, conn->inbuf, conn->inbuf_len - 1);
+ if (dlen <= 0) {
+ /* badness */
+ abort();
+ }
+ conn->inbuf[dlen] = 0;
+ conn->cb(conn, fd, conn->baton, LINEIO_GOTLINE, conn->inbuf);
+ }
+ if (mode & EVENT_FD_WRITABLE) {
+ if (conn->outbuf_used) {
+ ssize_t dlen = write(fd, conn->outbuf,
conn->outbuf_used);
+ if (dlen <= 0) {
+ /* badness */
+ abort();
+ }
+ assert(dlen <= conn->outbuf_used);
+ if (conn->outbuf_used > dlen) {
+ memmove(conn->outbuf, conn->outbuf + dlen,
+ conn->outbuf_used - dlen);
+ }
+ conn->outbuf_used -= dlen;
+ } else {
+ event_addfd(
+ fd, EVENT_FD_READABLE | EVENT_FD_ERROR,
+ lineio_evcallback, conn);
+ }
+ }
+ if (mode & EVENT_FD_ERROR) {
+ /* badness */
+ abort();
+ }
+}
+
+int lineio_printf(lineio_conn *conn, char *fmt, ...) {
+ int elen;
+ va_list ap;
+
+ va_start(ap, fmt);
+ elen = vsnprintf(NULL, 0, fmt, ap);
+ if (conn->outbuf_len < conn->outbuf_used + elen) {
+ conn->outbuf_len = elen + conn->outbuf_used;
+ conn->outbuf = myrealloc(conn->outbuf, conn->outbuf_len);
+ }
+ elen = vsnprintf(
+ conn->outbuf + conn->outbuf_used,
+ conn->outbuf_len - conn->outbuf_used,
+ fmt, ap
+ );
+ conn->outbuf_used += elen;
+
+ event_addfd(
+ conn->fd,
+ EVENT_FD_READABLE | EVENT_FD_WRITABLE | EVENT_FD_ERROR,
+ lineio_evcallback,
+ conn);
+ return elen;
+}
Property changes on: trunk/clients/havercurs/lineio.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/lineio.h
===================================================================
--- trunk/clients/havercurs/lineio.h 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/lineio.h 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,23 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#ifndef LINEIO_H
+#define LINEIO_H 1
+
+enum lineio_events {
+ LINEIO_GOTLINE,
+ LINEIO_FLUSHED,
+ LINEIO_DISCON,
+ LINEIO_ERROR
+};
+
+struct lineio_conn;
+typedef struct lineio_conn lineio_conn;
+typedef void lineio_callback(
+ struct lineio_conn *conn, int fd, void *baton,
+ enum lineio_events ev, void *data
+ );
+
+lineio_conn *lineio_attach(int fd, lineio_callback *cb, void *baton);
+void lineio_detatch(lineio_conn *conn);
+int lineio_printf(lineio_conn *conn, char *fmt, ...);
+
+#endif
Property changes on: trunk/clients/havercurs/lineio.h
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/main.c
===================================================================
--- trunk/clients/havercurs/main.c 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/main.c 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,165 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#include <ncurses.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "mymalloc.h"
+#include "entry.h"
+#include "display.h"
+/*#include "io.h"*/
+#include "event.h"
+#include "net.h"
+#include "lineio.h"
+
+void finish(int);
+void handle_input(int fd, int mode, void *baton);
+void heartbeat(const struct timeval *when, void *baton);
+void heartbeat_start(int delay);
+
+lineio_conn *conn = NULL;
+
+void connected_cb(
+ void *baton, int fd, int ecode, const char *error
+);
+
+void lio_cb(
+ struct lineio_conn *conn, int fd, void *baton,
+ enum lineio_events ev, void *data);
+
+int main(void) {
+ int i;
+ signal(SIGINT, finish); /* arrange interrupts to terminate */
+ signal(SIGIO, SIG_IGN); /* we select() for async I/O */
+ initscr();
+ nonl();
+ cbreak();
+ noecho();
+ idlok(stdscr, TRUE);
+ keypad(stdscr, TRUE);
+
+ move(LINES - 2, 0);
+ for (i = 0; i < COLS; i++)
+ addch('-');
+ move(LINES - 1, 0);
+
+ entry_init();
+ event_init();
+ display_init(LINES - 2);
+
+ heartbeat_start(30);
+
+ refresh();
+
+ event_addfd(0, EVENT_FD_READABLE | EVENT_FD_ERROR, handle_input, NULL);
+
+ for (;;) {
+ int c = event_poll(1);
+ entry_refresh(stdscr, LINES - 1, COLS);
+ refresh();
+ }
+}
+
+void finish(int sig) {
+ endwin();
+ exit(0);
+}
+
+void connected_cb(
+ void *baton, int fd, int ecode, const char *error
+)
+{
+ if (fd == -1) {
+ display_print("connect error: %s\n", error);
+ return;
+ }
+ conn = lineio_attach(fd, lio_cb, NULL);
+}
+
+void lio_cb(
+ struct lineio_conn *conn, int fd, void *baton,
+ enum lineio_events ev, void *data)
+{
+ if (ev == LINEIO_GOTLINE) {
+ display_print("INPUT:\n|%s|\n", (char *)data);
+ }
+}
+
+void handle_input(int fd, int mode, void *baton) {
+ int c;
+ size_t pos, len;
+
+ mode = mode & (EVENT_FD_READABLE | EVENT_FD_ERROR);
+ if (!mode)
+ return; /* We're willing to block on stdout. */
+
+ if (mode & EVENT_FD_ERROR) {
+ endwin();
+ exit(0);
+ }
+ pos = entry_get_pos();
+ len = entry_get_len();
+
+ switch (c = getch()) {
+ case KEY_UP:
+ break;
+ case KEY_DOWN:
+ break;
+ case KEY_BACKSPACE:
+ if (pos > 0)
+ entry_remove_ch(pos - 1);
+ entry_move_abs(pos - 1);
+ break;
+ case KEY_DC:
+ if (len && pos < len)
+ entry_remove_ch(pos);
+ entry_move_abs(pos);
+ break;
+ case KEY_ENTER:
+ case '\n':
+ case '\r':
+ if (conn) {
+ display_print("OUT: %s\n", entry_get());
+ lineio_printf(conn, "%s\n", entry_get());
+ } else {
+ display_print("Not connected.\n");
+ break;
+ }
+ /* fallthru */
+ case KEY_DL:
+ entry_clear();
+ break;
+ case KEY_LEFT:
+ entry_move_rel(-1);
+ break;
+ case KEY_RIGHT:
+ entry_move_rel(1);
+ break;
+ default:
+ if (!isprint(c)) {
+ display_print("%d\n", (int)c);
+ break;
+ }
+ entry_insert_ch(pos, c);
+ entry_move_rel(1);
+ };
+}
+
+void heartbeat_start(int delay) {
+ struct timeval next = {delay, 0};
+ event_timer_rel(&next, heartbeat, NULL);
+}
+
+void heartbeat(const struct timeval *when, void *baton) {
+ const char *message = baton;
+ struct timeval next;
+ if (!message) {
+ net_async_connect(connected_cb, NULL, "localhost", 12564);
+ baton = message = "Heartbeat 1";
+ }
+ display_print("%s\n", message);
+ next.tv_sec = 1;
+ next.tv_usec = 0;
+ event_timer_rel(&next, heartbeat, baton);
+}
Property changes on: trunk/clients/havercurs/main.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/mymalloc.c
===================================================================
--- trunk/clients/havercurs/mymalloc.c 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/mymalloc.c 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,22 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#include <stdlib.h>
+#include <ncurses.h>
+#include "mymalloc.h"
+
+void *mymalloc(size_t s) {
+ void *p = malloc(s);
+ if (!p) {
+ endwin();
+ abort();
+ }
+ return p;
+}
+
+void *myrealloc(void *oldp, size_t s) {
+ void *p = realloc(oldp, s);
+ if (!p) {
+ endwin();
+ abort();
+ }
+ return p;
+}
Property changes on: trunk/clients/havercurs/mymalloc.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/mymalloc.h
===================================================================
--- trunk/clients/havercurs/mymalloc.h 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/mymalloc.h 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,10 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#ifndef MYMALLOC_H
+#define MYMALLOC_H 1
+
+#include <stdlib.h>
+
+void *mymalloc(size_t s);
+void *myrealloc(void *oldp, size_t s);
+
+#endif
Property changes on: trunk/clients/havercurs/mymalloc.h
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/net.c
===================================================================
--- trunk/clients/havercurs/net.c 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/net.c 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,46 @@
+#include "net.h"
+#include <sys/socket.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netdb.h>
+extern int h_errno;
+
+/* FIXME: not actually async */
+void net_async_connect(
+ net_conn_callback *cb, void *baton,
+ const char *host, unsigned long port
+ )
+{
+ struct hostent *h;
+ int fd;
+ int pf;
+ int ret;
+ h = gethostbyname(host);
+ if (!h) {
+ cb(baton, -1, h_errno, hstrerror(h_errno));
+ return;
+ }
+ if (h->h_addrtype == AF_INET) {
+ pf = PF_INET;
+ } else {
+ pf = PF_INET6;
+ }
+ fd = socket(pf, SOCK_STREAM, 0);
+ if (fd < 0) {
+ cb(baton, -1, errno, strerror(errno));
+ return;
+ }
+ ret = connect(fd, (const struct sockaddr *)h->h_addr_list[0],
h->h_length);
+ if (ret != 0) {
+ int err = errno;
+ close(fd);
+ cb(baton, -1, err, strerror(err));
+ return;
+ }
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+ cb(baton, fd, 0, NULL);
+}
Property changes on: trunk/clients/havercurs/net.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/havercurs/net.h
===================================================================
--- trunk/clients/havercurs/net.h 2004-12-31 03:00:15 UTC (rev 484)
+++ trunk/clients/havercurs/net.h 2004-12-31 03:00:30 UTC (rev 485)
@@ -0,0 +1,18 @@
+/* vim: set ts=4 sw=4 expandtab si ai sta tw=104: */
+#ifndef NET_H
+#define NET_H 1
+
+/* This is mostly a placeholder right now. Sometime in the future
+ * this should become truly asynchronous.
+ */
+
+typedef void net_conn_callback(
+ void *baton, int fd, int ecode, const char *error
+ );
+
+void net_async_connect(
+ net_conn_callback *cb, void *baton,
+ const char *host, unsigned long port
+ );
+
+#endif
Property changes on: trunk/clients/havercurs/net.h
___________________________________________________________________
Name: svn:eol-style
+ native