jcs
/subtext
/amendments
/2
console+session: Work on functioning console, integrate ANSI parser
jcs made amendment 2 over 2 years ago
--- console.c Wed Nov 17 15:31:31 2021
+++ console.c Sun Nov 28 21:12:14 2021
@@ -21,13 +21,18 @@
#include "session.h"
#include "util.h"
+/* for monaco 9 */
+#define FONT_WIDTH 6
+#define FONT_HEIGHT 10
+
struct node_funcs console_node_funcs = {
console_output,
- console_read,
+ console_input,
};
void console_redraw(struct console *console);
void console_cursor(struct console *console, short line, short column);
+void console_parse_csi(struct console *console);
struct console *
console_init(void)
@@ -69,7 +74,7 @@ console_init(void)
console->session->cookie = (void *)console;
console->ncolumns = 80;
console->nlines = 24;
- console->old_cursor_line = -1;
+ console->attrs[0] |= (ATTR_CURSOR | ATTR_DIRTY);
return console;
}
@@ -77,6 +82,7 @@ console_init(void)
void
console_idle(struct console *console)
{
+ console_output(console->session);
}
void
@@ -92,7 +98,6 @@ console_resume(struct console *console)
void
console_update(struct console *console, EventRecord *event)
{
- Str255 buf;
Rect r;
short what = -1;
@@ -117,14 +122,33 @@ console_mouse_down(struct console *console, EventRecor
{
}
+void
+console_key_down(struct console *console, EventRecord *event)
+{
+ char k;
+
+ if (console->session->ibuflen >= sizeof(console->session->ibuf))
+ return;
+
+ k = (event->message & charCodeMask);
+ console->session->ibuf[console->session->ibuflen++] = k;
+ if (k == '\r')
+ console->session->ibuf[console->session->ibuflen++] = '\n';
+}
+
short
console_output(struct session *session)
{
- struct console *console = (struct console *)(session->cookie);
- short n, len, cursor;
+ struct console *console = (struct console *)session->cookie;
+ short n, len, cursor, iac = 0;
if (session->obuflen == 0)
return 0;
+
+ cursor = (console->cursor_line * console->ncolumns) +
+ console->cursor_column;
+ console->attrs[cursor] |= ATTR_DIRTY;
+ console->attrs[cursor] &= ~ATTR_CURSOR;
for (n = 0; n < session->obuflen; n++) {
if (console->cursor_column >= console->ncolumns &&
@@ -133,6 +157,22 @@ console_output(struct session *session)
console->cursor_line++;
}
+ if (console->in_csi) {
+ if (session->obuf[n] == '\e' ||
+ console->csilen >= sizeof(console->csi) - 1) {
+ console_parse_csi(console);
+ console->in_csi = 0;
+ console->csi[0] = '\0';
+ console->csilen = 0;
+ } else {
+ console->csi[console->csilen] = session->obuf[n];
+ console->csilen++;
+ console_parse_csi(console);
+ }
+
+ continue;
+ }
+
switch (session->obuf[n]) {
case '\r':
console->cursor_column = 0;
@@ -140,6 +180,19 @@ console_output(struct session *session)
case '\n':
console->cursor_line++;
break;
+ case '\e':
+ if (session->obuflen <= n + 1) {
+ /* lone \e at end of buffer, keep it until we see next */
+ session->obuflen = 1;
+ session->obuf[0] = '\e';
+ goto output_done;
+ }
+ if (session->obuf[n + 1] == '[') {
+ console->in_csi = 1;
+ n++;
+ continue;
+ }
+ /* escape but not CSI, fall through */
default:
cursor = (console->cursor_line * console->ncolumns) +
console->cursor_column;
@@ -150,57 +203,444 @@ console_output(struct session *session)
}
}
+
len = session->obuflen;
session->obuflen = 0;
+output_done:
+ cursor = (console->cursor_line * console->ncolumns) +
+ console->cursor_column;
+ console->attrs[cursor] |= (ATTR_DIRTY | ATTR_CURSOR);
console_redraw(console);
return len;
}
+short
+console_input(struct session *session)
+{
+ /* nothing to do, input is fed from main loop */
+ uthread_yield();
+ return 0;
+}
+
void
console_redraw(struct console *console)
{
+ Rect cursor;
short n, line = 0, column = 0;
TextFont(monaco);
TextSize(9);
- if (console->old_cursor_line != -1)
- console_cursor(console, console->old_cursor_line,
- console->old_cursor_column);
-
for (n = 0; n < sizeof(console->chars); n++) {
if (!(console->attrs[n] & ATTR_DIRTY))
continue;
line = ((n + 1) / console->ncolumns);
column = n - (line * console->ncolumns);
- MoveTo(6 + ((console->win->portRect.left + column) * 6),
- 6 + ((console->win->portRect.top + line + 1) * 10));
+ cursor.left = FONT_WIDTH + ((console->win->portRect.left +
+ column) * FONT_WIDTH);
+ cursor.top = FONT_WIDTH + ((console->win->portRect.top + line) *
+ FONT_HEIGHT);
+ cursor.right = cursor.left + FONT_WIDTH;
+ cursor.bottom = cursor.top + FONT_HEIGHT;
+
+ FillRect(&cursor, white);
+
+ MoveTo(cursor.left, cursor.top + FONT_HEIGHT - 2);
DrawChar(console->chars[n]);
console->attrs[n] &= ~ATTR_DIRTY;
+
+ if (console->attrs[n] & ATTR_CURSOR)
+ InvertRect(&cursor);
}
-
- console_cursor(console, console->cursor_line, console->cursor_column);
- console->old_cursor_line = console->cursor_line;
- console->old_cursor_column = console->cursor_column;
}
+#if 0
void
console_cursor(struct console *console, short line, short column)
{
Rect cursor;
cursor.left = 6 + ((console->win->portRect.left + column) * 6);
- cursor.top = 6 + ((console->win->portRect.top + line + 1) * 10);
+ cursor.top = 6 + ((console->win->portRect.top + line) * 10) + 2;
cursor.right = cursor.left + 6;
cursor.bottom = cursor.top + 10;
InvertRect(&cursor);
}
+#endif
-short
-console_read(struct session *session)
+void
+console_parse_csi(struct console *console)
{
- return 0;
+ short x, y, cursor;
+ short serviced = 0;
+ short param1 = -1, param2 = -1;
+ short parambuflen;
+ char parambuf[4];
+ char c;
+
+ if (console->csilen == 0)
+ return;
+
+ c = console->csi[console->csilen - 1];
+
+ if (c < 'A' || (c > 'Z' && c < 'a') || c > 'z')
+ return;
+
+ switch (c) {
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'J':
+ case 'K':
+ case 'S':
+ case 'T':
+ case 'd':
+ case 'g':
+ case 's':
+ case 'u':
+ case '7':
+ case '8':
+ /* optional multiplier */
+ if (c == 'J' || c == 'K')
+ param1 = 0;
+ else
+ param1 = 1;
+
+ if (console->csilen > 1) {
+ for (x = 0; x < console->csilen - 1, x < sizeof(parambuf); x++) {
+ parambuf[x] = console->csi[x];
+ parambuf[x + 1] = '\0';
+ }
+ param1 = atoi(parambuf);
+ }
+ break;
+ case 'H':
+ case 'f':
+ /* two optional parameters separated by ; each defaulting to 1 */
+ param1 = 1;
+ param2 = 1;
+
+ y = -1;
+ for (x = 0; x < console->csilen; x++) {
+ if (console->csi[x] == ';') {
+ y = x;
+ break;
+ }
+ }
+ if (y == -1)
+ /* CSI 17H -> CSI 17; */
+ y = console->csilen - 1;
+
+ if (y > 0) {
+ for (x = 0; x < y && x < 4; x++) {
+ parambuf[x] = console->csi[x];
+ parambuf[x + 1] = '\0';
+ }
+ param1 = atoi(parambuf);
+
+ if (y < console->csilen - 2) {
+ parambuf[0] = '\0';
+ for (x = 0; x < (console->csilen - 1 - y) && x < 4; x++) {
+ parambuf[x] = console->csi[y + 1 + x];
+ parambuf[x + 1] = '\0';
+ }
+ param2 = atoi(parambuf);
+ }
+ }
+ break;
+ }
+
+ serviced = 1;
+
+ /* uncursor */
+ cursor = (console->cursor_line * console->ncolumns) +
+ console->cursor_column;
+ console->attrs[cursor] &= ~ATTR_CURSOR;
+ console->attrs[cursor] |= ATTR_DIRTY;
+
+ switch (c) {
+ case 'A': /* CUU - cursor up, stop at top of screen */
+ for (x = 0; x < param1 && console->cursor_line > 0; x++)
+ console->cursor_line--;
+ break;
+ case 'B': /* CUD - cursor down, stop at bottom of screen */
+ for (x = 0; x < param1 &&
+ console->cursor_line < console->nlines - 1; x++)
+ console->cursor_line++;
+ break;
+ case 'C': /* CUF - cursor forward, stop at screen edge */
+ for (x = 0; x < param1 &&
+ console->cursor_column < console->ncolumns - 1; x++)
+ console->cursor_column++;
+ break;
+ case 'D': /* CUB - cursor back, stop at left edge of screen */
+ for (x = 0; x < param1 && console->cursor_column > 0; x++)
+ console->cursor_column--;
+ break;
+ case 'E': /* CNL - cursor next line */
+ console->cursor_column = 0;
+ for (x = 0; x < param1 &&
+ console->cursor_line < console->nlines - 1; x++)
+ console->cursor_line++;
+ break;
+ case 'F': /* CPL - cursor previous line */
+ console->cursor_column = 0;
+ for (x = 0; x < param1 && console->cursor_line > 0; x++)
+ console->cursor_line--;
+ break;
+ case 'G': /* CHA - cursor horizontal absolute */
+ if (param1 > console->ncolumns)
+ param1 = console->ncolumns;
+ console->cursor_column = param1;
+ break;
+ case 'H': /* CUP - cursor absolute position */
+ case 'f': /* HVP - horizontal vertical position */
+ if (param1 - 1 < 0)
+ console->cursor_line = 0;
+ else if (param1 > console->nlines)
+ console->cursor_line = console->nlines - 1;
+ else
+ console->cursor_line = param1 - 1;
+
+ if (param2 - 1 < 0)
+ console->cursor_column = 0;
+ else if (param2 > console->ncolumns)
+ console->cursor_column = console->ncolumns - 1;
+ else
+ console->cursor_column = param2 - 1;
+ break;
+ case 'J': /* ED - erase in display */
+ switch (param1) {
+ case 0:
+ /* clear from cursor to end of screen */
+#if 0
+ for (y = console->cursor_line; y < console->nlines; y++) {
+ for (x = 0; x < console->ncolumns; x++) {
+ if (y == console->cursor_line &&
+ x < console->cursor_column)
+ continue;
+
+ update_char(x, y, ' ', cur_attr, cur_color);
+ }
+ }
+#endif
+ break;
+ case 1:
+ /* clear from cursor to beginning of the screen */
+#if 0
+ for (y = console->cursor_line; y >= 0; y--) {
+ for (x = console->ncolumns; x >= 0; x--) {
+ if (y == console->cursor_line &&
+ x > console->cursor_column)
+ continue;
+
+ update_char(x, y, ' ', cur_attr, cur_color);
+ }
+ }
+#endif
+ break;
+ case 2:
+ /* clear entire screen */
+#if 0
+ for (y = 0; y < console->nlines; y++) {
+ for (x = 0; x < console->ncolumns; x++)
+ update_char(x, y, ' ', cur_attr, cur_color);
+ }
+#endif
+ break;
+ }
+ break;
+ case 'K': /* EL - erase in line */
+ switch (param1) {
+ case 0:
+ /* clear from cursor to end of line */
+ if (console->cursor_column >= console->ncolumns)
+ break;
+#if 0
+ for (x = console->cursor_column; x < console->ncolumns; x++)
+ update_char(x, console->cursor_line, ' ', cur_attr,
+ cur_color);
+#endif
+ break;
+ case 1:
+ /* clear from cursor to beginning of line */
+ if (console->cursor_column == 0)
+ break;
+#if 0
+ for (x = console->cursor_column; x >= 0; x--)
+ update_char(x, console->cursor_line, ' ', cur_attr,
+ cur_color);
+#endif
+ break;
+ case 2:
+ /* clear entire line */
+#if 0
+ for (x = 0; x < console->ncolumns - 1; x++)
+ update_char(x, console->cursor_line, ' ', cur_attr,
+ cur_color);
+#endif
+ break;
+ }
+ break;
+ case 'S': /* SU - scroll up */
+ /* TODO */
+ break;
+ case 'T': /* SD - scroll down */
+ /* TODO */
+ break;
+ case 'd': /* absolute line number */
+ if (param1 < 1)
+ console->cursor_line = 0;
+ else if (param1 > console->nlines)
+ console->cursor_line = console->nlines;
+ else
+ console->cursor_line = param1 - 1;
+ break;
+ case 'g': /* clear tabs, ignore */
+ break;
+ case 'h': /* reset, ignore */
+ break;
+ case 'm': /* graphic changes */
+ parambuf[0] = '\0';
+ parambuflen = 0;
+ param2 = console->cur_attr;
+
+ for (x = 0; x < console->csilen; x++) {
+ /* all the way to console->csilen to catch 'm' */
+ if (console->csi[x] == ';' || console->csi[x] == 'm') {
+ param1 = atoi(parambuf);
+
+ switch (param1) {
+ case 0: /* reset */
+#ifdef COLOR
+ cur_color = FG_WHITE | BG_BLACK;
+#endif
+ param2 = 0;
+ break;
+ case 1: /* bold */
+ param2 |= ATTR_BOLD;
+ break;
+ case 4: /* underline */
+ param2 |= ATTR_UNDERLINE;
+ break;
+ case 7: /* reverse */
+ param2 |= ATTR_REVERSE;
+ break;
+ case 22: /* normal color */
+ param2 = 0;
+ break;
+ case 21: /* bold off */
+ param2 &= ~ATTR_BOLD;
+ break;
+ case 24: /* underline off */
+ param2 &= ~ATTR_UNDERLINE;
+ break;
+ case 27: /* inverse off */
+ param2 &= ~ATTR_REVERSE;
+ break;
+ case 30: /* fg black */
+ case 31: /* fg red */
+ case 32: /* fg green */
+ case 33: /* fg yellow */
+ case 34: /* fg blue */
+ case 35: /* fg magenta */
+ case 36: /* fg cyan */
+ case 37: /* fg white */
+#ifdef COLOR
+ cur_color &= ~0xff;
+ cur_color |= (1 << (param1 - 30));
+#endif
+ break;
+ case 40: /* bg black */
+ case 41: /* bg red */
+ case 42: /* bg green */
+ case 43: /* bg yellow */
+ case 44: /* bg blue */
+ case 45: /* bg magenta */
+ case 46: /* bg cyan */
+ case 47: /* bg white */
+#ifdef COLOR
+ cur_color = (1 << (8 + param1 - 40)) |
+ (cur_color & 0xff);
+#endif
+ break;
+ }
+
+ parambuf[0] = '\0';
+ parambuflen = 0;
+ } else if (parambuflen < 4) {
+ parambuf[parambuflen] = console->csi[x];
+ parambuflen++;
+ parambuf[parambuflen] = '\0';
+ }
+ }
+
+ console->cur_attr = param2;
+ break;
+ case 'n': /* DSR - device status report */
+ switch (param1) {
+ case 5: /* terminal is ready */
+ session_output(console->session, "\e[0n");
+ break;
+ case 6: /* CPR - report cursor position */
+ session_output(console->session, "\e[");
+
+ sprintf(parambuf, "%d", console->cursor_line + 1);
+ for (x = 0; x < sizeof(parambuf); x++) {
+ if (parambuf[x] == '\0')
+ break;
+ session_output_char(console->session, parambuf[x]);
+ }
+ session_output_char(console->session, ';');
+
+ sprintf(parambuf, "%d", console->cursor_column + 1);
+ for (x = 0; x < sizeof(parambuf); x++) {
+ if (parambuf[x] == '\0')
+ break;
+ session_output_char(console->session, parambuf[x]);
+ }
+
+ session_output_char(console->session, 'R');
+ break;
+ }
+ break;
+ case '7': /* DECSC - save cursor */
+ case 's': /* from ANSI.SYS */
+#if 0
+ saved_cursorx = cursorx;
+ saved_cursory = cursory;
+#endif
+ break;
+ case '8': /* DECRC - restore cursor */
+ case 'u': /* from ANSI.SYS */
+#if 0
+ cursorx = saved_cursorx;
+ cursory = saved_cursory;
+#endif
+ break;
+ default:
+ /*
+ * if the last character is a letter and we haven't serviced
+ * it, assume it's a sequence we don't support and should just
+ * suppress
+ */
+ if (c < 65 || (c > 90 && c < 97) || c > 122)
+ serviced = 0;
+ }
+
+ if (serviced) {
+ cursor = (console->cursor_line * console->ncolumns) +
+ console->cursor_column;
+ console->attrs[cursor] |= (ATTR_CURSOR | ATTR_DIRTY);
+ console->csilen = 0;
+ console->csi[0] = '\0';
+ console->in_csi = 0;
+ }
}
--- console.h Wed Nov 17 15:26:21 2021
+++ console.h Sun Nov 28 13:22:53 2021
@@ -25,14 +25,19 @@ struct console {
ControlHandle scroller;
char chars[80 * 24];
char attrs[80 * 24];
-#define ATTR_DIRTY (1 << 0)
-#define ATTR_BOLD (1 << 1)
+ char cur_attr;
+#define ATTR_BOLD (1 << 0)
+#define ATTR_REVERSE (1 << 1)
+#define ATTR_UNDERLINE (1 << 2)
+#define ATTR_CURSOR (1 << 6)
+#define ATTR_DIRTY (1 << 7)
short nlines;
short ncolumns;
short cursor_line;
short cursor_column;
- short old_cursor_line;
- short old_cursor_column;
+ short in_csi;
+ short csilen;
+ char csi[32];
struct session *session;
};
@@ -42,8 +47,10 @@ void console_suspend(struct console *console);
void console_resume(struct console *console);
void console_update(struct console *console, EventRecord *event);
void console_mouse_down(struct console *console, EventRecord *event);
+void console_key_down(struct console *console, EventRecord *event);
short console_output(struct session *session);
+short console_input(struct session *session);
short console_read(struct session *session);
#endif /* __CONSOLE_H__ */
--- main.c Wed Nov 17 15:36:46 2021
+++ main.c Sun Nov 28 21:17:44 2021
@@ -20,6 +20,7 @@
#include "subtext.h"
#include "console.h"
#include "session.h"
+#include "uthread.h"
#include "util.h"
MenuHandle file_menu;
@@ -41,6 +42,8 @@ main(void)
short event_in, n;
char key;
+ uthread_init();
+
InitGraf(&thePort);
InitFonts();
FlushEvents(everyEvent, 0);
@@ -65,23 +68,25 @@ main(void)
memset(&config, 0, sizeof(config));
strcpy(config.name, "Kludge BBS");
strcpy(config.hostname, "klud.ge");
+
+ cur_console = console_init();
while (!quitting) {
- WaitNextEvent(everyEvent, &event, 5L, 0L);
+ uthread_coordinate();
+ WaitNextEvent(everyEvent, &event, 1L, 0L);
switch (event.what) {
case nullEvent:
- if (!cur_console)
- cur_console = console_init();
- console_idle(cur_console);
- for (n = 0; n < nsessions; n++)
- session_idle(sessions[n]);
+ if (cur_console)
+ console_idle(cur_console);
break;
case keyDown:
case autoKey:
key = event.message & charCodeMask;
if ((event.modifiers & cmdKey) != 0)
handle_menu(MenuKey(key));
+ else if (cur_console)
+ console_key_down(cur_console, &event);
break;
case mouseDown:
event_in = FindWindow(event.where, &event_win);
--- session.c Wed Nov 17 15:39:45 2021
+++ session.c Sun Nov 28 21:25:13 2021
@@ -21,45 +21,35 @@
#include "subtext.h"
#include "session.h"
+#include "uthread.h"
#include "util.h"
struct session **sessions = NULL;
short nsessions = 0;
char session_tbuf[512];
-void
-session_idle(struct session *s)
-{
- if (s->obuflen) {
- s->node_funcs->output(s);
- if (s->obuflen)
- return;
- }
+void session_run(struct uthread *uthread, void *arg);
- switch (s->state) {
- case SESSION_STATE_INIT:
- session_output(s, "\r\nWelcome to %s (%s)\r\n", config.name,
- s->node);
- s->state = SESSION_STATE_LOGIN;
- break;
- }
-}
-
struct session *
session_create(char *node, struct node_funcs *node_funcs)
{
struct session *session;
-
- nsessions++;
- sessions = xreallocarray(sessions, nsessions, sizeof(struct session));
+
session = xmalloczero(sizeof(struct session));
- sessions[nsessions - 1] = session;
+ session->uthread = uthread_add(session_run, session);
+ if (!session->uthread) {
+ free(session);
+ return NULL;
+ }
session->state = SESSION_STATE_INIT;
- memcpy(session->node, node, sizeof(session->node));
-
session->node_funcs = node_funcs;
+ memcpy(session->node, node, sizeof(session->node));
+ nsessions++;
+ sessions = xreallocarray(sessions, nsessions, sizeof(struct session));
+ sessions[nsessions - 1] = session;
+
return session;
}
@@ -82,6 +72,114 @@ session_output(struct session *session, const char *fo
memcpy(session->obuf + session->obuflen, session_tbuf, len);
session->obuflen += len;
-
+ session->node_funcs->output(session);
+ uthread_yield();
+
return len;
+}
+
+short
+session_output_char(struct session *session, const char c)
+{
+ session->obuf[session->obuflen++] = c;
+ session->node_funcs->output(session);
+ uthread_yield();
+
+ return 1;
+}
+
+char
+session_input_char(struct session *session)
+{
+ char ret;
+
+ while (session->ibuflen == 0)
+ session->node_funcs->input(session);
+
+ ret = session->ibuf[0];
+ if (session->ibuflen == 1)
+ session->ibuflen = 0;
+ else {
+ memmove(session->ibuf, session->ibuf + 1, session->ibuflen - 1);
+ session->ibuflen--;
+ }
+
+ return ret;
+}
+
+char *
+session_field_input(struct session *session, unsigned short len)
+{
+ short ilen = 0, ipos = 0, lastlen = 0;
+ char *field;
+ char c, redraw = 0;
+
+ field = xmalloczero(len);
+
+ for (;;) {
+ c = session_input_char(session);
+ switch (c) {
+ case 8:
+ if (ipos == 0)
+ continue;
+
+ if (ipos < ilen) {
+ /* l:3 p:2 f:ab[cursor]c -> l:2 p:2 f:a[cursor]c */
+ redraw = 1;
+ BlockMove((Ptr)(field + ipos), (Ptr)(field + ipos - 1),
+ ilen - 1);
+ }
+
+ ipos--;
+ ilen--;
+ field[ipos] = '\0';
+
+ if (redraw) {
+ /* TODO */
+ } else
+ /* back one, space, back one */
+ session_output(session, "\e[D \e[D");
+
+ break;
+ case '\n':
+ return field;
+ default:
+ if (c < 32 || c > 127)
+ break;
+ if (ilen >= len)
+ break;
+ if (ipos <= ilen)
+ /* TODO: move */
+ ;
+
+ field[ipos] = c;
+ ipos++;
+ ilen++;
+ field[ipos] = '\0';
+ session_output_char(session, c);
+ }
+ }
+
+ free(field);
+ return NULL;
+}
+
+void
+session_run(struct uthread *uthread, void *arg)
+{
+ struct session *s = (struct session *)arg;
+ char *line;
+
+ session_output(s, "\r\n"
+ "Welcome to %s (%s)\r\n"
+ "\r\n", config.name, s->node);
+
+ session_output(s, "login: ");
+ line = session_field_input(s, 50);
+ session_output(s, "\r\nHi, %s\r\n", line);
+ free(line);
+
+ for (;;) {
+ uthread_yield();
+ }
}
--- session.h Wed Nov 17 13:31:32 2021
+++ session.h Fri Nov 26 13:41:08 2021
@@ -17,26 +17,37 @@
#ifndef __SESSION_H__
#define __SESSION_H__
+#include "uthread.h"
+
enum session_state {
SESSION_STATE_INIT,
SESSION_STATE_LOGIN,
SESSION_STATE_WELCOME
};
+enum session_input_state {
+ SESSION_INPUT_NONE,
+ SESSION_INPUT_LINE,
+ SESSION_INPUT_CHAR
+};
+
+/* TODO: move these to node struct to be session->node->output(..) */
struct node_funcs {
short (*output)(struct session *session);
- short (*read)(struct session *session);
+ short (*input)(struct session *session);
};
struct session {
char node[32];
char obuf[64];
char ibuf[64];
- short state;
+ enum session_state state;
+ enum session_input_state input_state;
short obuflen;
short ibuflen;
void *cookie;
struct node_funcs *node_funcs;
+ struct uthread *uthread;
};
extern struct session **sessions;
@@ -44,6 +55,9 @@ extern short nsessions;
struct session *session_create(char *node, struct node_funcs *node_funcs);
void session_idle(struct session *session);
+char session_input_char(struct session *session);
short session_output(struct session *session, const char *format, ...);
+short session_output_char(struct session *session, const char c);
+char *session_field_input(struct session *session, unsigned short len);
#endif /* __SESSION_H__ */