rewrite vt100 and telnet.

This commit is contained in:
Kelvin Sherlock 2018-04-21 15:30:26 -04:00
parent 9285503c5f
commit 9cc53483ad
10 changed files with 3395 additions and 3359 deletions

32
GNUmakefile Normal file
View File

@ -0,0 +1,32 @@
PROG = fctelnet
OBJS = o/fctelnet.a o/vt100.a o/telnet.a o/ansi.a o/chars.a o/marinetti.a o/display.a
OPTIMIZE ?= 79
CFLAGS = -w-1 -O $(OPTIMIZE)
CC = occ --gno
$(PROG): $(OBJS)
$(RM) o/ansi.root
$(RM) o/chars.root
$(CC) $(OBJS) -o $@
fctelnet.o: fctelnet.c marinetti.h
vt100.o: vt100.c CLAGS+=-r
ansi.o: ansi.asm
chars.o: chars.asm
marinetti.o: marinetti.c CLAGS+=-r
telnet.o: telnet.c CLAGS+=-r
o/%.a : %.c
$(CC) -c $(CFLAGS) -o $@ $^
o/%.a : %.asm
$(CC) -c $(CFLAGS) -o $@ $^
clean:
$(RM) -f *.o *.root *.a *.r
clobber: clean
$(RM) -f $(PROG)

1539
ansi.asm

File diff suppressed because it is too large Load Diff

2002
chars.asm

File diff suppressed because it is too large Load Diff

464
display.c
View File

@ -1,408 +1,56 @@
#pragma noroot
#pragma lint -1
#include <types.h>
#include <string.h>
#include <ctype.h>
#include <Event.h>
#include "Marinetti.h"
#define ESC "\x1b"
extern void ScrollRegion(word,word);
extern void ScrollDown(void);
extern void PrintChar(int the_char, unsigned int andMask);
extern void ClearScreen(void);
extern void ClearScreenFrom(int Y);
extern void ClearLine(int Y);
extern void ClearLineFrom(int Y, int X);
void handle_ansi(word code, char *buffer, word cnt);
extern void GrafOn(void) inline(0x0a04, 0xe10000);
extern void GrafOff(void) inline(0x0b04, 0xe10000);
extern pascal void SetColorTable(Word, ColorTable) inline(0x0E04,dispatcher);
extern pascal void SysBeep2(Word) inline(0x3803,dispatcher);
extern pascal void SetAllSCBs(Word) inline(0x1404,dispatcher);
extern pascal void SetMasterSCB(Word) inline(0x1604,dispatcher);
extern pascal void InitColorTable(ColorTable) inline(0x0D04,dispatcher);
extern word Xpos;
extern word Ypos;
extern word __scroll[2];
extern word and_mask;
extern word xor_mask;
word esc;
char esc_buffer[256];
struct errlist
{
Word Error;
Word MsgLen;
const char *Msg;
};
#define _ERR(n,msg) { n, sizeof(msg), msg }
struct errlist errors[] =
{
_ERR(1,"tcperrDeafDestPort"),
_ERR(2,"tcperrHostReset"),
_ERR(3,"tcperrConExists"),
_ERR(4,"tcperrConIllegal"),
_ERR(5,"tcperrNoResources"),
_ERR(6,"tcperrNoSocket"),
_ERR(7,"tcperrBadPrec"),
_ERR(8,"tcperrBadSec"),
_ERR(9,"tcperrBadConnection"),
_ERR(0x0a,"tcperrConClosing"),
_ERR(0x0b,"tcperrClosing"),
_ERR(0x0c,"tcperrConReset"),
_ERR(0x0d,"tcperrUserTimeout"),
_ERR(0x0e,"tcperrConRefused"),
{0,0,NULL}
};
void display_str(const char *buffer, word cnt);
void display_err(Word err)
{
struct errlist *l;
for (l = &errors[0]; l->Error; l++)
if (l->Error == err) break;
if (l->Error != err) return;
display_str("\r\n" "\x1b" "[1m", 6); // bold on
display_str(l->Msg, l->MsgLen); // show the string
display_str("\x1b" "[0m", 4); // bold off
}
void display_cstr(const char *cstr)
{
if (cstr && *cstr)
display_str(cstr, strlen(cstr));
}
void display_pstr(const char *pstr)
{
if (pstr && *pstr)
display_str(pstr + 1, *pstr);
}
void display_char(char c)
{
switch(c)
{
case 0x07:
SysBeep2(0);
break;
//backspace
case 0x08:
if (Xpos) Xpos--;
break;
//tab
case 0x09:
// 1, 9, 17, 25, ...
// not sure this is right
Xpos = Xpos & 0xf8;
Xpos += 8;
//TODO - wrapping
break;
// line feed
case 0x0A:
if (++Ypos > 23)
{
ScrollRegion(__scroll[0], __scroll[1]);
Ypos = 23;
}
break;
case 0x0D: //carriage return
Xpos = 0;
break;
default:
if (isprint(c));
{
// check the wrapping flag ...
if (Xpos > 80)
{
Xpos = 0;
if (++Ypos > 23)
{
ScrollRegion(__scroll[0],
__scroll[1]);
Ypos = 23;
}
}
PrintChar(c, and_mask);
Xpos++;
}
}
}
/*
* this reads text & has it drawn on the shr screen
*
*/
// todo - and_mask + xor_mask
void display_str(const char *buffer, word cnt)
{
word i;
asm
{
phk
plb
}
for ( i = 0; i < cnt; i++)
{
if (esc)
{
esc_buffer[esc++] = buffer[i];
if (isalpha(buffer[i])
|| buffer[i] == '~'
|| buffer[i] == '='
|| buffer[i] == '>'
)
{
handle_ansi(buffer[i],
esc_buffer, esc);
esc = 0;
}
}
else switch (buffer[i])
{
// bell
case 0x07:
SysBeep2(0);
break;
//backspace
case 0x08:
if (Xpos) Xpos--;
break;
//tab
case 0x09:
// 1, 9, 17, 25, ...
// not sure this is right
Xpos = Xpos & 0xf8;
Xpos += 8;
//TODO - wrapping
break;
// line feed
case 0x0A:
if (++Ypos > 23)
{
ScrollRegion(__scroll[0],
__scroll[1]);
Ypos = 23;
}
break;
case 0x0D: //carriage return
Xpos = 0;
break;
case 0x1b: //start of escape sequence
esc = 1;
esc_buffer[0] = 0x1b;
break;
default:
if (isprint(buffer[i]))
{
// check the wrapping flag ...
if (Xpos > 80)
{
Xpos = 0;
if (++Ypos > 23)
{
ScrollRegion(__scroll[0],
__scroll[1]);
Ypos = 23;
}
}
PrintChar(buffer[i], and_mask);
Xpos++;
}
}
}
}
//
// remap the iigs key to a vt100 code (if necessary) and send it out.
void send_event(EventRecord *event, Word ipid)
{
char *cp;
int len = 0;
word key;
word mods;
key = event->message;
mods = event->modifiers;
if (mods & keyPad)
{
switch (key)
{
case 0x72: // insert
cp = ESC "[2~";
len = 4;
break;
case 0x75: // delete
cp = ESC "[3~";
len = 4;
break;
case 0x73: // home
cp = ESC "[1~";
len = 4;
break;
case 0x77: // end
cp = ESC "[4~";
len = 4;
break;
case 0x74: // page up
cp = ESC "[5~";
len = 4;
break;
case 0x79: // page down
cp = ESC "[6~";
len = 4;
break;
case 0x7a: // f1
cp = mods & shiftKey ? ESC "[23~" : ESC "[11~";
len = 5;
break;
case 0x78: // f2
cp = mods & shiftKey ? ESC "[24~" : ESC "[12~";
len = 5;
break;
case 0x63: // f3
cp = mods & shiftKey ? ESC "[25~" : ESC "[13~";
len = 5;
break;
case 0x76: // f4
cp = mods & shiftKey ? ESC "[26~" : ESC "[14~";
len = 5;
break;
case 0x60: // f5
cp = mods & shiftKey ? ESC "[28~" : ESC "[15~";
len = 5;
break;
case 0x61: // f6
cp = mods & shiftKey ? ESC "[29~" : ESC "[17~";
len = 5;
break;
case 0x62: // f7
cp = mods & shiftKey ? ESC "[31~" : ESC "[18~";
len = 5;
break;
case 0x64: // f8
cp = mods & shiftKey ? ESC "[32~" : ESC "[19~";
len = 5;
break;
case 0x65: // f9
cp = mods & shiftKey ? ESC "[33~" : ESC "[20~";
len = 5;
break;
case 0x6d: // f10
cp = mods & shiftKey ? ESC "[34~" : ESC "[21~";
len = 5;
break;
case 0x67: // f11
cp = ESC "[23~";
len = 5;
break;
case 0x6f: // f12
cp = ESC "[24~";
len = 5;
break;
default: len = 0; cp = NULL;
}
}
else if (mods & controlKey)
{
cp = (char *)&event->message;
len = 1;
}
else
{
switch(key)
{
case 0x0d:
cp = "\r\n";
len = 2;
break;
case 0x08: // <--- arrow
cp = ESC "[D";
len = 3;
break;
case 0x0A: // down arrow
cp = ESC "[B";
len = 3;
break;
case 0x0B: // up arrow
cp = ESC "[A";
len = 3;
break;
case 0x15: // ---> arrow
cp = ESC "[C";
len = 3;
break;
// backspace to delete char
case 0x7f:
cp = "\x08";
len = 1;
break;
default:
cp = (char *)&event->message;
len = 1;
}
}
if (len) TCPIPWriteTCP(ipid, cp, len, false, false);
}
#pragma noroot
#include <string.h>
#include "Marinetti.h"
struct errlist {
Word Error;
Word MsgLen;
const char *Msg;
};
#define ESC "\x1b"
#define _ERR(n,msg) { n, sizeof(msg) - 1, msg }
extern void vt100_process(const unsigned char *buffer, unsigned buffer_size);
static struct errlist errors[] = {
_ERR(1,"tcperrDeafDestPort"),
_ERR(2,"tcperrHostReset"),
_ERR(3,"tcperrConExists"),
_ERR(4,"tcperrConIllegal"),
_ERR(5,"tcperrNoResources"),
_ERR(6,"tcperrNoSocket"),
_ERR(7,"tcperrBadPrec"),
_ERR(8,"tcperrBadSec"),
_ERR(9,"tcperrBadConnection"),
_ERR(0x0a,"tcperrConClosing"),
_ERR(0x0b,"tcperrClosing"),
_ERR(0x0c,"tcperrConReset"),
_ERR(0x0d,"tcperrUserTimeout"),
_ERR(0x0e,"tcperrConRefused"),
};
void display_err(Word err) {
if (err == 0 || err >= 0x0f) return;
--err;
vt100_process("\r\n" ESC "[1m", 6); // bold on
vt100_process(errors[err].Msg, errors[err].MsgLen);
vt100_process(ESC "[0m", 4); // bold off
}
void display_cstr(const char *cstr) {
if (cstr && *cstr)
vt100_process(cstr, strlen(cstr));
}
void display_pstr(const char *pstr) {
if (pstr && *pstr)
vt100_process(pstr + 1, *pstr);
}

View File

@ -1,515 +1,382 @@
#include "Marinetti.h"
#include <Locator.h>
#include <Memory.h>
#include <texttool.h>
#include <gsos.h>
#include <Event.h>
#include <fcntl.h>
#include <sgtty.h>
#include <errno.h>
#include <gno/gno.h>
#include <gno/kerntool.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/ioctl.compat.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "telnet.h"
extern void ScrollRegion(word,word);
extern void ScrollDown(void);
extern void PrintChar(int the_char, unsigned int andMask);
extern void ClearScreen(void);
extern void ClearScreenFrom(int Y);
extern void ClearLine(int Y);
extern void ClearLineFrom(int Y, int X);
extern void GrafOn(void) inline(0x0a04, 0xe10000);
extern void GrafOff(void) inline(0x0b04, 0xe10000);
extern pascal void SetColorTable(Word, ColorTable) inline(0x0E04,dispatcher);
extern pascal void SysBeep2(Word) inline(0x3803,dispatcher);
extern pascal void SetAllSCBs(Word) inline(0x1404,dispatcher);
extern pascal void SetMasterSCB(Word) inline(0x1604,dispatcher);
extern pascal void InitColorTable(ColorTable) inline(0x0D04,dispatcher);
Word MyID;
Word __gno;
Word modeTelnet = 1;
Word flagEcho = 1; // if *I* echo
void init_ansi(void);
Word ResolveHost(const char *name, cvtRecPtr cvt);
Word GetChar(word ipid, unsigned char *c);
Word UngetChar(char c);
void display_str(const char *txt, word cnt);
void display_pstr(const char *);
void display_cstr(const char *);
void display_err(Word);
void send_event(EventRecord *, Word);
#pragma databank 1
/*
* called to print connect/disconnect messages from
* Marinetti. msg is a pstring.
*/
void printCallBack(const char *msg)
{
word i;
i = *msg;
if (i)
{
display_str("\x1b" "[1m", 4); // bold on
display_str(msg + 1, i); // show the string
display_str("\x1b" "[0m\n\r", 6); // bold off
}
}
#pragma databank 0
extern word esc;
extern word Xpos;
extern word Ypos;
void init_screen(void)
{
#define WHITE 0x0fff
#define YELLOW 0x0ff0
#define BLACK 0x0000
#define BLUE 0x000f
#define GREEN 0x00f0
#define RED 0x0f00
static ColorTable ct =
{
BLACK, // background
RED, // underline / blink
BLUE, // bold
GREEN, // foreground
BLACK,
RED,
BLUE,
GREEN,
BLACK,
RED,
BLUE,
GREEN,
BLACK,
RED,
BLUE,
GREEN,
};
int i;
// linearize memory, disable shadowing.
asm
{
lda #0x00C1
sep #0x20
ora >0xe0c029
sta >0xe0c029
rep #0x20
lda #0x0008
sep #0x20
ora >0xe0c035
sta >0xe0c035
rep #0x20
}
SetMasterSCB(0xc080);
SetAllSCBs(0xc080);
//InitColorTable(ct);
for (i = 0; i < 15; i++)
SetColorTable(i, ct);
ClearScreen();
GrafOn();
}
/*
* this is (more or less) a state machine.
* old state (and character) are passed in
* new state is returned.
*
* 0 = starting state.
*/
#define SB_IAC 0xfaff
Word do_iac(Word state, char c, Word ipid)
{
static char buffer[64];
static int cnt;
if (state == 0) return c == IAC ? IAC : 0;
// FF must be escaped as FF FF within SB.
// SB_IAC means the first FF has been processed.
if (state == SB)
{
if (c == IAC) return SB_IAC;
buffer[cnt++] = c;
return SB;
}
if (state == SB_IAC)
{
// it was an escaped FF
if (c == IAC)
{
buffer[cnt++] = IAC;
return SB;
}
else state = IAC; // process below...
}
if (state == IAC)
switch (c)
{
case DONT:
case DO:
case WONT:
case WILL:
return c;
case SB:
cnt = 0;
return c;
case SE:
// buffer is the data between
// IAC SB <...> IAC SE
if (buffer[0] == TELOPT_TTYPE
&& buffer[1] == TELQUAL_SEND)
{
static char msg[] =
{
IAC, SB, TELOPT_TTYPE, TELQUAL_IS,
'V', 'T', '1', '0', '0',
IAC, SE
};
TCPIPWriteTCP(ipid, msg,
sizeof(msg), true, false);
}
else if (buffer[0] == TELOPT_NAWS
&& buffer[1] == TELQUAL_SEND)
{
static char msg[] =
{
IAC, SB, TELOPT_NAWS,
0, 80, 0, 24,
IAC, SE
};
TCPIPWriteTCP(ipid, msg,
sizeof(msg), true, false);
}
else if (buffer[0] == TELOPT_TSPEED
&& buffer[1] == TELQUAL_SEND)
{
static char msg[] =
{
IAC, SB, TELOPT_TSPEED,
'9', '6', '0', '0', ',', '9', '6', '0', '0',
IAC, SE
};
TCPIPWriteTCP(ipid, msg,
sizeof(msg), true, false);
}
cnt = 0;
return 0;
default:
return 0;
}
if (state == DO)
{
buffer[0] = IAC;
buffer[1] = WONT;
buffer[2] = c;
if (c == TELOPT_TTYPE
|| c == TELOPT_SGA
|| c == TELOPT_NAWS
|| c == TELOPT_TSPEED)
{
buffer[1] = WILL;
}
TCPIPWriteTCP(ipid, buffer, 3, true, false);
}
if (state == DONT)
{
buffer[0] = IAC;
buffer[1] = WONT;
buffer[2] = c;
TCPIPWriteTCP(ipid, buffer, 3, true, false);
}
if (state == WILL || state == WONT)
{
buffer[0] = IAC;
buffer[1] = DONT;
buffer[2] = c;
if (c == TELOPT_ECHO)
{
buffer[1] = DO;
}
cnt = 3;
TCPIPWriteTCP(ipid, buffer, cnt, true, false);
}
return 0;
}
int main(int argc, char **argv)
{
static EventRecord event;
static srBuffer sr;
static rrBuff rr;
static char str[16];
static cvtRec cvt;
static QuitRecGS qDCB = {2, 0, 0x4000};
Word iLoaded;
Word iConnected;
Word iStarted;
Word Quit;
Word ipid;
Handle dp;
int i;
Word key;
Word err;
unsigned char c;
//int fd;
int iac_state;
Xpos = Ypos = 0;
esc = 0;
//iac = 0;
iLoaded = iStarted = iConnected = false;
__gno = false;
MyID = MMStartUp();
kernStatus();
if (!_toolErr) __gno = true;
TextStartUp();
SetOutputDevice(1,3);
SetOutGlobals(0x7f, 0);
dp = NewHandle(0x0100, MyID,
attrBank | attrPage |attrNoCross | attrFixed | attrLocked,
0x000000);
HLock(dp);
EMStartUp((Word)*dp, 0x14, 0, 0, 0, 0, MyID);
if (argc != 2)
{
ErrWriteCString("Usage: marlene host[:port]\r\n");
goto _exit;
}
init_screen();
init_ansi();
TCPIPStatus();
if (_toolErr)
{
display_str("\n\rLoading Marinetti...\n\r", 23);
LoadOneTool(0x36, 0x200); //load Marinetti
if (_toolErr)
{
ErrWriteCString("Unable to load Marinetti\r\n");
goto _exit;
}
iLoaded = true;
}
// Marinetti now loaded
if (!TCPIPStatus())
{
display_str("\n\rStarting Marinetti...\n\r", 24);
TCPIPStartUp();
iStarted = true;
}
if (!TCPIPGetConnectStatus())
{
display_str("\n\rConnecting Marinetti...\n\r", 26);
TCPIPConnect(printCallBack);
if (_toolErr)
{
ErrWriteCString("Unable to establish network connection\r\n");
goto _exit;
}
iConnected = true;
}
// marinetti is now connected
if (!ResolveHost(argv[1], &cvt))
{
ErrWriteCString("Unable to resolve address\r\n");
goto _exit;
}
if (!cvt.cvtPort) cvt.cvtPort = 23;
ipid = TCPIPLogin(MyID, cvt.cvtIPAddress, cvt.cvtPort, 0, 0x0040);
display_str("\n\rConnecting to ", 16);
display_str(str, TCPIPConvertIPToCAscii(cvt.cvtIPAddress, str, 0));
TCPIPOpenTCP(ipid);
// wait for the connection to occur.
while (1)
{
TCPIPPoll();
err = TCPIPStatusTCP(ipid, &sr);
if (err)
{
display_err(err);
goto _exit1;
}
if (sr.srState == tcpsESTABLISHED) break;
//if (sr.srState == tcpsCLOSED) goto _exit1;
GetNextEvent(keyDownMask | autoKeyMask ,&event);
if (event.what != keyDownEvt) continue;
if (!(event.modifiers & appleKey)) continue;
if ((Word)event.message == '.') goto _exit1;
if ((Word)event.message == 'q') goto _exit1;
if ((Word)event.message == 'Q') goto _exit1;
}
display_str("\n\rConnected\n\r", 13);
//fd = open ("tcp.log", O_TRUNC | O_WRONLY | O_CREAT, 0777);
Quit = false;
iac_state = 0;
while (!Quit)
{
TCPIPPoll();
// check for incoming data...
// 0xffff = no data
// 0 = data
// otherwise = marinetti error.
err = GetChar(ipid, &c);
if (err && (err != 0xffff))
{
display_err(err);
Quit++;
continue;
}
if (err == 0)
{
//if (fd > 0) write(fd, &c, 1);
if (iac_state)
iac_state = do_iac(iac_state, c, ipid);
else if (modeTelnet && c == IAC)
iac_state = do_iac(0, c, ipid);
else display_str(&c, 1);
}
GetNextEvent(keyDownMask | autoKeyMask, &event);
if (event.what != keyDownEvt) continue;
c = key = event.message;
if (event.modifiers & appleKey)
{
switch (key)
{
case 'Q': // quit
case 'q':
Quit++;
break;
case 'V': // paste
case 'v':
break;
case 'Z': // suspend (gnome)
case 'z':
if (__gno)
{
static struct sgttyb sb;
static int err;
gtty(1,&sb);
sb.sg_flags &= ~RAW;
stty(1,&sb);
GrafOff();
Kkill(Kgetpid(), SIGSTOP, &err);
sb.sg_flags |= RAW;
stty(1,&sb);
GrafOn();
}
break;
}
continue;
}
else send_event(&event, ipid);
}
_exit1:
//if (fd > 0) close(fd);
TCPIPCloseTCP(ipid);
TCPIPPoll(); // wait until closed...
TCPIPLogout(ipid);
// be nice and
while (GetNextEvent(keyDownMask | autoKeyMask, &event));
display_str("\n\rPress any key to exit.\n\r", 26);
while (!GetNextEvent(keyDownMask | autoKeyMask, &event));
_exit:
if (iConnected)
TCPIPDisconnect(false, printCallBack);
if (iStarted)
TCPIPShutDown();
if (iLoaded)
UnloadOneTool(0x36);
EMShutDown();
GrafOff();
TextShutDown();
QuitGS(&qDCB);
}
#include <tcpip.h>
#include <Locator.h>
#include <Memory.h>
#include <texttool.h>
#include <gsos.h>
#include <Event.h>
#include <fcntl.h>
#include <sgtty.h>
#include <errno.h>
#include <gno/gno.h>
#include <gno/kerntool.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/ioctl.compat.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "telnet.h"
extern void ClearScreen(void);
extern pascal void GrafOn(void) inline(0x0a04, dispatcher);
extern pascal void GrafOff(void) inline(0x0b04, dispatcher);
extern pascal void SetColorTable(Word, ColorTable) inline(0x0E04,dispatcher);
extern pascal void SysBeep2(Word) inline(0x3803,dispatcher);
extern pascal void SetAllSCBs(Word) inline(0x1404,dispatcher);
extern pascal void SetMasterSCB(Word) inline(0x1604,dispatcher);
extern pascal void InitColorTable(ColorTable) inline(0x0D04,dispatcher);
Word ResolveHost(const char *name, cvtRecPtr cvt);
int WaitForStatus(word ipid, word status);
void display_pstr(const char *);
void display_cstr(const char *);
void display_err(Word);
extern void telnet_init(void);
extern void telnet_process(void);
extern void vt100_init(void);
extern void vt100_process(const unsigned char *buffer, unsigned buffer_size);
extern void vt100_event(EventRecord *event);
Word MyID;
Word __gno;
#define ESC "\x1b"
#pragma databank 1
/*
* called to print connect/disconnect messages from
* Marinetti. msg is a pstring.
*/
void printCallBack(const char *msg) {
if (msg && *msg) {
display_cstr(ESC "\n\r[1m"); // bold on
display_pstr(msg); // show the string
display_cstr(ESC "[0m\n\r"); // bold off
}
}
#pragma databank 0
static void screen_init(void) {
#define WHITE 0x0fff
#define YELLOW 0x0ff0
#define BLACK 0x0000
#define BLUE 0x000f
#define GREEN 0x00f0
#define RED 0x0f00
static ColorTable ct =
{
BLACK, // background
RED, // underline / blink
BLUE, // bold
GREEN, // foreground
BLACK,
RED,
BLUE,
GREEN,
BLACK,
RED,
BLUE,
GREEN,
BLACK,
RED,
BLUE,
GREEN,
};
unsigned i;
// linearize memory, disable shadowing.
asm
{
lda #0x00C1
sep #0x20
ora >0xe0c029
sta >0xe0c029
rep #0x20
lda #0x0008
sep #0x20
ora >0xe0c035
sta >0xe0c035
rep #0x20
}
SetMasterSCB(0xc080);
SetAllSCBs(0xc080);
//InitColorTable(ct);
for (i = 0; i < 16; i++)
SetColorTable(i, ct);
ClearScreen();
GrafOn();
}
static char out_buffer[1024];
static char out_buffer_size = 0;
static word ipid = -1;
static void flush(void) {
if (out_buffer_size) {
TCPIPWriteTCP(ipid, out_buffer, out_buffer_size, true, false);
out_buffer_size = 0;
}
}
void send(char *data, unsigned size) {
if (out_buffer_size + size > sizeof(out_buffer)) {
flush();
}
if (size > sizeof(out_buffer) / 2) {
TCPIPWriteTCP(ipid, data, size, true, false);
return;
}
memcpy(out_buffer + out_buffer_size, data, size);
out_buffer_size += size;
}
unsigned buffer_size;
unsigned char buffer[2048]; // 1500 is normal MTU size?
int main(int argc, char **argv) {
static EventRecord event;
static rrBuff rr;
static char str[16];
static cvtRec cvt;
static QuitRecGS qDCB = {2, 0, 0x4000};
Word iLoaded;
Word iConnected;
Word iStarted;
Handle dp;
Word err;
int ok;
iLoaded = iStarted = iConnected = false;
__gno = false;
ipid = -1;
MyID = MMStartUp();
kernStatus();
if (!_toolErr) __gno = true;
TextStartUp();
SetOutputDevice(1,3);
SetOutGlobals(0x7f, 0);
dp = NewHandle(0x0100, MyID,
attrBank | attrPage |attrNoCross | attrFixed | attrLocked,
0x000000);
EMStartUp((Word)*dp, 0x14, 0, 0, 0, 0, MyID);
// todo: -vt52 -> start in vt52 mode (DECANM = 0)
// todo:keypad flag of some sort?
if (argc != 2) {
ErrWriteCString("Usage: marlene host[:port]\r\n");
goto _exit;
}
screen_init();
vt100_init();
TCPIPStatus();
if (_toolErr) {
display_cstr("Loading Marinetti...\n\r");
LoadOneTool(0x36, 0x200); //load Marinetti
if (_toolErr) {
display_cstr("Unable to load Marinetti.\r\n");
goto _exit;
}
iLoaded = true;
}
// Marinetti now loaded
if (!TCPIPStatus()) {
display_cstr("Starting Marinetti...\n\r");
TCPIPStartUp();
iStarted = true;
}
if (!TCPIPGetConnectStatus()) {
display_cstr("Connecting Marinetti...\n\r");
TCPIPConnect(printCallBack);
if (_toolErr) {
display_cstr("Unable to establish network connection.\r\n");
goto _exit;
}
iConnected = true;
}
// marinetti is now connected
if (!ResolveHost(argv[1], &cvt)) {
display_cstr("Unable to resolve address.\r\n");
goto _exit;
}
if (!cvt.cvtPort) cvt.cvtPort = 23;
ipid = TCPIPLogin(MyID, cvt.cvtIPAddress, cvt.cvtPort, 0, 0x0040);
TCPIPConvertIPToCASCII(cvt.cvtIPAddress, str, 0);
display_cstr("Connecting to ");
display_cstr(str);
display_cstr("...\n\r");
TCPIPOpenTCP(ipid);
// wait for the connection to occur.
ok = WaitForStatus(ipid, TCPSESTABLISHED);
if (ok > 0) display_err(ok);
if (ok != 0) goto _exit2;
display_cstr("Connected.\n\r");
telnet_init();
//fd = open ("tcp.log", O_TRUNC | O_WRONLY | O_CREAT, 0777);
for(;;) {
static rrBuff rr;
TCPIPPoll();
rr.rrBuffCount = 0;
err = TCPIPReadTCP(ipid, 0, (Ref)buffer, sizeof(buffer), &rr);
// tcperrConClosing and tcperrClosing aren't fatal.
buffer_size = rr.rrBuffCount;
if (buffer_size) err = 0;
if (err) {
if (err == tcperrConClosing || err == tcperrClosing)
display_cstr("\r\nTCP Connection Closed.\r\n");
else
display_err(err);
goto _exit1;
}
if (buffer_size) {
telnet_process();
}
if (buffer_size) {
vt100_process(buffer, buffer_size);
}
GetNextEvent(keyDownMask | autoKeyMask, &event);
if (event.what == keyDownEvt) {
unsigned char key = event.message;
if (event.modifiers & appleKey) {
switch (key) {
case 'Q': // quit
case 'q':
goto _exit1;
break;
case 'V': // paste...
case 'v':
break;
case 'Z': // suspend (gnome)
case 'z':
if (__gno) {
static struct sgttyb sb;
static int err;
gtty(1,&sb);
sb.sg_flags &= ~RAW;
stty(1,&sb);
GrafOff();
Kkill(Kgetpid(), SIGSTOP, &err);
sb.sg_flags |= RAW;
stty(1,&sb);
GrafOn();
}
break;
}
} else {
vt100_event(&event);
}
}
flush();
}
_exit1:
flush();
display_cstr("\n\rClosing TCP Connection...\n\r");
TCPIPCloseTCP(ipid);
WaitForStatus(ipid, TCPSCLOSED);
_exit2:
_exit:
if (ipid != -1) TCPIPLogout(ipid);
if (iConnected)
TCPIPDisconnect(false, printCallBack);
if (iStarted)
TCPIPShutDown();
if (iLoaded)
UnloadOneTool(0x36);
// flush q
while (GetNextEvent(keyDownMask | autoKeyMask, &event)) ;
display_cstr("\n\rPress any key to exit.\n\r");
while (!GetNextEvent(keyDownMask | autoKeyMask, &event)) ;
EMShutDown();
DisposeHandle(dp);
GrafOff();
TextShutDown();
QuitGS(&qDCB);
return 0;
}

View File

@ -1,23 +1,24 @@
PROG = fctelnet
OBJS = fctelnet.o vt100.o ansi.o chars.o marinetti.o display.o
OPTIMIZE *= 79
CFLAGS = -w -O$(OPTIMIZE)
$(PROG): $(OBJS)
$(RM) ansi.root
$(RM) chars.root
$(CC) $(CFLAGS) $(OBJS) -o $@
fctelnet.o: fctelnet.c marinetti.h
vt100.o: vt100.c
ansi.o: ansi.asm
chars.o: chars.asm
marinetti.o: marinetti.c
clean:
$(RM) -f *.o *.root *.a *.r
clobber: clean
$(RM) -f $(PROG)
PROG = fctelnet
OBJS = fctelnet.o vt100.o telnet.o ansi.o chars.o marinetti.o display.o
OPTIMIZE *= 79
CFLAGS = -w -O$(OPTIMIZE)
$(PROG): $(OBJS)
$(RM) ansi.root
$(RM) chars.root
$(CC) $(CFLAGS) $(OBJS) -o $@
fctelnet.o: fctelnet.c marinetti.h
vt100.o: vt100.c
ansi.o: ansi.asm
chars.o: chars.asm
marinetti.o: marinetti.c
telnet.o: telnet.c
clean:
$(RM) -f *.o *.root *.a *.r
clobber: clean
$(RM) -f $(PROG)

View File

@ -1,137 +1,111 @@
#pragma noroot
#pragma lint -1
#include <Event.h>
#include "Marinetti.h"
#include <stdlib.h>
#include <string.h>
static char * __c2pstrMalloc(const char *cp)
{
Word len;
char *ret;
len = strlen(cp);
ret = (char *)malloc(len + 2);
if (ret)
{
ret[0] = len;
memmove(&ret[1], cp, len+1); // copy over NULL too
}
return ret;
}
//
// returns true if resolved, false if not
//
// name is a c-string
// todo - add /etc/host support
Word ResolveHost(const char *name, cvtRecPtr cvt)
{
dnrBuffer dnr;
char *pstr;
Word port;
EventRecord event;
cvt->cvtIPAddress = 0;
cvt->cvtPort = 0;
if (!name || !*name) return false;
pstr = __c2pstrMalloc(name);
if (!pstr) return false;
port = TCPIPMangleDomainName(0xf800, pstr);
// check if name is a dotted decimal or a host...
if (TCPIPValidateIPString(pstr))
{
TCPIPConvertIPToHex(cvt, pstr);
cvt->cvtPort = port;
free (pstr);
return true;
}
else
{
TCPIPDNRNameToIP(pstr, &dnr);
if (_toolErr)
{
free(pstr);
return false;
}
while (dnr.DNRStatus == DNRPending)
{
TCPIPPoll();
GetNextEvent(keyDownMask | autoKeyMask, &event);
if ((event.what == keyDownEvt)
&& (event.modifiers & appleKey)
&& ((Word)event.message == '.'))
{
TCPIPCancelDNR(&dnr);
break;
}
}
if (dnr.DNRStatus == DNROK)
{
cvt->cvtIPAddress = dnr.DNRIPAddress;
cvt->cvtPort = port;
free(pstr);
return true;
}
}
free(pstr);
return false;
}
/*
* pcnt is the next place to store data
* bptr is the current ptr.
*/
static unsigned char buffer[1024];
static unsigned char pushback[1024];
static int pcnt = 0;
static int bcnt = 0;
static int bptr = 0;
static rrBuff rr;
Word GetChar(word ipid, unsigned char *c)
{
word err;
*c = 0;
if (pcnt)
{
*c = pushback[--pcnt];
return 0;
}
if (!bcnt)
{
err = TCPIPReadTCP(ipid, 0, (Ref)buffer, 1024, &rr);
bcnt = rr.rrBuffCount;
bptr = 0;
if (err) return err;
}
if (bcnt)
{
bcnt--;
*c = buffer[bptr++];
return 0;
}
return 0xffff;
}
void UngetChar(char c)
{
pushback[pcnt++] = c;
}
#pragma noroot
#pragma lint -1
#include <Event.h>
#include "Marinetti.h"
#include <stdlib.h>
#include <string.h>
static char * __c2pstrMalloc(const char *cp)
{
Word len;
char *ret;
len = strlen(cp);
ret = (char *)malloc(len + 2);
if (ret)
{
ret[0] = len;
memmove(&ret[1], cp, len+1); // copy over NULL too
}
return ret;
}
//
// returns true if resolved, false if not
//
// name is a c-string
// todo - add /etc/host support
Word ResolveHost(const char *name, cvtRecPtr cvt)
{
dnrBuffer dnr;
char *pstr;
Word port;
EventRecord event;
cvt->cvtIPAddress = 0;
cvt->cvtPort = 0;
if (!name || !*name) return false;
pstr = __c2pstrMalloc(name);
if (!pstr) return false;
port = TCPIPMangleDomainName(0xf800, pstr);
// check if name is a dotted decimal or a host...
if (TCPIPValidateIPString(pstr))
{
TCPIPConvertIPToHex(cvt, pstr);
cvt->cvtPort = port;
free (pstr);
return true;
}
else
{
TCPIPDNRNameToIP(pstr, &dnr);
if (_toolErr) {
free(pstr);
return false;
}
while (dnr.DNRStatus == DNRPending) {
TCPIPPoll();
GetNextEvent(keyDownMask | autoKeyMask, &event);
if ((event.what == keyDownEvt)
&& (event.modifiers & appleKey)
&& ((Word)event.message == '.')) {
TCPIPCancelDNR(&dnr);
break;
}
}
if (dnr.DNRStatus == DNROK) {
cvt->cvtIPAddress = dnr.DNRIPAddress;
cvt->cvtPort = port;
free(pstr);
return true;
}
}
free(pstr);
return false;
}
int WaitForStatus(word ipid, word status) {
static srBuffer sr;
EventRecord event;
Word err;
for(;;) {
TCPIPPoll();
err = TCPIPStatusTCP(ipid, &sr);
if (err) return err;
if (sr.srState == status) return 0;
GetNextEvent(keyDownMask | autoKeyMask, &event);
if (event.what != keyDownEvt) continue;
if (!(event.modifiers & appleKey)) continue;
if ((Word)event.message == '.') return -1;
//if ((Word)event.message == 'q') return -1;
//if ((Word)event.message == 'Q') return -1;
}
return 0;
}

View File

@ -1,139 +1,139 @@
#ifndef __TCPIP_H__
#define __TCPIP_H__
#include <types.h>
struct dnrBuffer
{
Word DNRStatus;
LongWord DNRIPAddress;
};
typedef struct dnrBuffer dnrBuffer, *dnrBufferPtr, **dnrBufferHndl;
#define DNRPending 0x0000
#define DNROK 0x0001
#define DNRFailed 0x0002
#define DNRNoDNSEntry 0x0003
#define DNRCancelled 0x0004
struct srBuffer
{
Word srState;
Word srNetworkError;
LongWord srSndQueued;
LongWord srRcvQueued;
LongWord srDestIP;
Word srDestPort;
Word srConnectType;
Word srAcceptCount;
};
typedef struct srBuffer srBuffer, *srBufferPtr, **srBufferHndl;
struct rrBuff
{
LongWord rrBuffCount;
Handle rrBuffHandle;
Word rrMoreFlag;
Word rrPushFlag;
Word rrUrgentFlag;
};
typedef struct rrBuff rrBuff, *rrBuffPtr, **rrBuffHndl;
struct cvtRec
{
LongWord cvtIPAddress;
Word cvtPort;
};
typedef struct cvtRec cvtRec, *cvtRecPtr, **cvtRecHndl;
/*
* TCP states
*/
#define tcpsCLOSED 0x0000
#define tcpsLISTEN 0x0001
#define tcpsSYNSENT 0x0002
#define tcpsSYNRCVD 0x0003
#define tcpsESTABLISHED 0x0004
#define tcpsFINWAIT1 0x0005
#define tcpsFINWAIT2 0x0006
#define tcpsCLOSEWAIT 0x0007
#define tcpsLASTACK 0x0008
#define tcpsCLOSING 0x0009
#define tcpsTIMEWAIT 0x000A
pascal void TCPIPStartUp(void)
inline(0x0236 ,0xe10000);
pascal void TCPIPShutDown(void)
inline(0x0336 ,0xe10000);
pascal Word TCPIPStatus(void)
inline(0x0636 ,0xe10000);
pascal Word TCPIPGetConnectStatus(void)
inline(0x0936, 0xe10000);
pascal void TCPIPConvertIPToHex(cvtRecPtr, const char *)
inline(0x0d36 ,0xe10000);
pascal void TCPIPConvertIPCToHex(cvtRecPtr, const char *)
inline(0x3f36 ,0xe10000);
pascal Word TCPIPConvertIPToAscii(LongWord, const char *, Word)
inline(0x0e36 ,0xe10000);
pascal Word TCPIPConvertIPToCAscii(LongWord, const char *, Word)
inline(0x5836 ,0xe10000);
pascal Word TCPIPMangleDomainName(Word, char *)
inline(0x5936 ,0xe10000);
pascal Word TCPIPValidateIPString(const char *)
inline(0x4836 ,0xe10000);
pascal Word TCPIPValidateIPCString(const char *)
inline(0x1536 ,0xe10000);
pascal void TCPIPConnect(void *)
inline(0x1236 ,0xe10000);
pascal void TCPIPDisconnect(word, void *)
inline(0x1336 ,0xe10000);
pascal void TCPIPCancelDNR(dnrBufferPtr)
inline(0x2036 ,0xe10000);
pascal void TCPIPDNRNameToIP(const char *, dnrBufferPtr)
inline(0x2136 ,0xe10000);
pascal void TCPIPPoll(void)
inline(0x2236 ,0xe10000);
pascal Word TCPIPLogin(Word, LongWord, Word, Word, Word)
inline(0x2336 ,0xe10000);
pascal void TCPIPLogout(Word)
inline(0x2436 ,0xe10000);
pascal Word TCPIPOpenTCP(Word)
inline(0x2C36 ,0xe10000);
pascal Word TCPIPWriteTCP(Word, void *, LongWord, Word, Word)
inline(0x2D36 ,0xe10000);
pascal Word TCPIPReadTCP(Word, Word, Ref, LongWord, rrBuffPtr)
inline(0x2E36 ,0xe10000);
pascal Word TCPIPCloseTCP(Word)
inline(0x2F36 ,0xe10000);
pascal Word TCPIPStatusTCP(Word, srBufferPtr)
inline(0x3136, 0xe10000);
#endif
#ifndef __TCPIP_H__
#define __TCPIP_H__
#include <types.h>
struct dnrBuffer
{
Word DNRStatus;
LongWord DNRIPAddress;
};
typedef struct dnrBuffer dnrBuffer, *dnrBufferPtr, **dnrBufferHndl;
#define DNRPending 0x0000
#define DNROK 0x0001
#define DNRFailed 0x0002
#define DNRNoDNSEntry 0x0003
#define DNRCancelled 0x0004
struct srBuffer
{
Word srState;
Word srNetworkError;
LongWord srSndQueued;
LongWord srRcvQueued;
LongWord srDestIP;
Word srDestPort;
Word srConnectType;
Word srAcceptCount;
};
typedef struct srBuffer srBuffer, *srBufferPtr, **srBufferHndl;
struct rrBuff
{
LongWord rrBuffCount;
Handle rrBuffHandle;
Word rrMoreFlag;
Word rrPushFlag;
Word rrUrgentFlag;
};
typedef struct rrBuff rrBuff, *rrBuffPtr, **rrBuffHndl;
struct cvtRec
{
LongWord cvtIPAddress;
Word cvtPort;
};
typedef struct cvtRec cvtRec, *cvtRecPtr, **cvtRecHndl;
/*
* TCP states
*/
#define tcpsCLOSED 0x0000
#define tcpsLISTEN 0x0001
#define tcpsSYNSENT 0x0002
#define tcpsSYNRCVD 0x0003
#define tcpsESTABLISHED 0x0004
#define tcpsFINWAIT1 0x0005
#define tcpsFINWAIT2 0x0006
#define tcpsCLOSEWAIT 0x0007
#define tcpsLASTACK 0x0008
#define tcpsCLOSING 0x0009
#define tcpsTIMEWAIT 0x000A
pascal void TCPIPStartUp(void)
inline(0x0236 ,0xe10000);
pascal void TCPIPShutDown(void)
inline(0x0336 ,0xe10000);
pascal Word TCPIPStatus(void)
inline(0x0636 ,0xe10000);
pascal Word TCPIPGetConnectStatus(void)
inline(0x0936, 0xe10000);
pascal void TCPIPConvertIPToHex(cvtRecPtr, const char *)
inline(0x0d36 ,0xe10000);
pascal void TCPIPConvertIPCToHex(cvtRecPtr, const char *)
inline(0x3f36 ,0xe10000);
pascal Word TCPIPConvertIPToAscii(LongWord, const char *, Word)
inline(0x0e36 ,0xe10000);
pascal Word TCPIPConvertIPToCAscii(LongWord, const char *, Word)
inline(0x5836 ,0xe10000);
pascal Word TCPIPMangleDomainName(Word, char *)
inline(0x5936 ,0xe10000);
pascal Word TCPIPValidateIPString(const char *)
inline(0x4836 ,0xe10000);
pascal Word TCPIPValidateIPCString(const char *)
inline(0x1536 ,0xe10000);
pascal void TCPIPConnect(void *)
inline(0x1236 ,0xe10000);
pascal void TCPIPDisconnect(word, void *)
inline(0x1336 ,0xe10000);
pascal void TCPIPCancelDNR(dnrBufferPtr)
inline(0x2036 ,0xe10000);
pascal void TCPIPDNRNameToIP(const char *, dnrBufferPtr)
inline(0x2136 ,0xe10000);
pascal void TCPIPPoll(void)
inline(0x2236 ,0xe10000);
pascal Word TCPIPLogin(Word, LongWord, Word, Word, Word)
inline(0x2336 ,0xe10000);
pascal void TCPIPLogout(Word)
inline(0x2436 ,0xe10000);
pascal Word TCPIPOpenTCP(Word)
inline(0x2C36 ,0xe10000);
pascal Word TCPIPWriteTCP(Word, void *, LongWord, Word, Word)
inline(0x2D36 ,0xe10000);
pascal Word TCPIPReadTCP(Word, Word, Ref, LongWord, rrBuffPtr)
inline(0x2E36 ,0xe10000);
pascal Word TCPIPCloseTCP(Word)
inline(0x2F36 ,0xe10000);
pascal Word TCPIPStatusTCP(Word, srBufferPtr)
inline(0x3136, 0xe10000);
#endif

166
telnet.h
View File

@ -1,83 +1,83 @@
#ifndef __TELNET_H__
#define __TELNET_H__
#define IAC 255 /* interpret as command: */
#define DONT 254 /* you are not to use option */
#define DO 253 /* please, you use option */
#define WONT 252 /* I won't use option */
#define WILL 251 /* I will use option */
#define SB 250 /* interpret as subnegotiation */
#define GA 249 /* you may reverse the line */
#define EL 248 /* erase the current line */
#define EC 247 /* erase the current character */
#define AYT 246 /* are you there */
#define AO 245 /* abort output--but let prog finish */
#define IP 244 /* interrupt process--permanently */
#define BREAK 243 /* break */
#define DM 242 /* data mark--for connect. cleaning */
#define NOP 241 /* nop */
#define SE 240 /* end sub negotiation */
#define EOR 239 /* end of record (transparent mode) */
#define ABORT 238 /* Abort process */
#define SUSP 237 /* Suspend process */
#define xEOF 236 /* End of file: EOF is already used... */
#define SYNCH 242 /* for telfunc calls */
#define TELCMD_FIRST xEOF
#define TELCMD_LAST IAC
#define TELCMD_OK(x) ((x) <= TELCMD_LAST && (x) >= TELCMD_FIRST)
#define TELCMD(x) telcmds[(x)-TELCMD_FIRST]
/* telnet options */
#define TELOPT_BINARY 0 /* 8-bit data path */
#define TELOPT_ECHO 1 /* echo */
#define TELOPT_RCP 2 /* prepare to reconnect */
#define TELOPT_SGA 3 /* suppress go ahead */
#define TELOPT_NAMS 4 /* approximate message size */
#define TELOPT_STATUS 5 /* give status */
#define TELOPT_TM 6 /* timing mark */
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
#define TELOPT_NAOL 8 /* negotiate about output line width */
#define TELOPT_NAOP 9 /* negotiate about output page size */
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
#define TELOPT_XASCII 17 /* extended ascic character set */
#define TELOPT_LOGOUT 18 /* force logout */
#define TELOPT_BM 19 /* byte macro */
#define TELOPT_DET 20 /* data entry terminal */
#define TELOPT_SUPDUP 21 /* supdup protocol */
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
#define TELOPT_SNDLOC 23 /* send location */
#define TELOPT_TTYPE 24 /* terminal type */
#define TELOPT_EOR 25 /* end or record */
#define TELOPT_TUID 26 /* TACACS user identification */
#define TELOPT_OUTMRK 27 /* output marking */
#define TELOPT_TTYLOC 28 /* terminal location number */
#define TELOPT_3270REGIME 29 /* 3270 regime */
#define TELOPT_X3PAD 30 /* X.3 PAD */
#define TELOPT_NAWS 31 /* window size */
#define TELOPT_TSPEED 32 /* terminal speed */
#define TELOPT_LFLOW 33 /* remote flow control */
#define TELOPT_LINEMODE 34 /* Linemode option */
#define TELOPT_XDISPLOC 35
#define TELOPT_OLD_ENVIRON 36
#define TELOPT_AUTHENTICATION 37 /* authenticate */
#define TELOPT_ENCRYPT 38 /* encryption */
#define TELOPT_NEW_ENVIRON 39
#define TELOPT_EXOPL 255 /* extended-options-list */
#define TELQUAL_IS 0
#define TELQUAL_SEND 1
#define TELQUAL_INFO 2
#define TELQUAL_REPLY 2
#define TELQUAL_NAME 3
#endif
#ifndef __TELNET_H__
#define __TELNET_H__
#define IAC 255 /* interpret as command: */
#define DONT 254 /* you are not to use option */
#define DO 253 /* please, you use option */
#define WONT 252 /* I won't use option */
#define WILL 251 /* I will use option */
#define SB 250 /* interpret as subnegotiation */
#define GA 249 /* you may reverse the line */
#define EL 248 /* erase the current line */
#define EC 247 /* erase the current character */
#define AYT 246 /* are you there */
#define AO 245 /* abort output--but let prog finish */
#define IP 244 /* interrupt process--permanently */
#define BREAK 243 /* break */
#define DM 242 /* data mark--for connect. cleaning */
#define NOP 241 /* nop */
#define SE 240 /* end sub negotiation */
#define EOR 239 /* end of record (transparent mode) */
#define ABORT 238 /* Abort process */
#define SUSP 237 /* Suspend process */
#define xEOF 236 /* End of file: EOF is already used... */
#define SYNCH 242 /* for telfunc calls */
#define TELCMD_FIRST xEOF
#define TELCMD_LAST IAC
#define TELCMD_OK(x) ((x) <= TELCMD_LAST && (x) >= TELCMD_FIRST)
#define TELCMD(x) telcmds[(x)-TELCMD_FIRST]
/* telnet options */
#define TELOPT_BINARY 0 /* 8-bit data path */
#define TELOPT_ECHO 1 /* echo */
#define TELOPT_RCP 2 /* prepare to reconnect */
#define TELOPT_SGA 3 /* suppress go ahead */
#define TELOPT_NAMS 4 /* approximate message size */
#define TELOPT_STATUS 5 /* give status */
#define TELOPT_TM 6 /* timing mark */
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
#define TELOPT_NAOL 8 /* negotiate about output line width */
#define TELOPT_NAOP 9 /* negotiate about output page size */
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
#define TELOPT_XASCII 17 /* extended ascic character set */
#define TELOPT_LOGOUT 18 /* force logout */
#define TELOPT_BM 19 /* byte macro */
#define TELOPT_DET 20 /* data entry terminal */
#define TELOPT_SUPDUP 21 /* supdup protocol */
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
#define TELOPT_SNDLOC 23 /* send location */
#define TELOPT_TTYPE 24 /* terminal type */
#define TELOPT_EOR 25 /* end or record */
#define TELOPT_TUID 26 /* TACACS user identification */
#define TELOPT_OUTMRK 27 /* output marking */
#define TELOPT_TTYLOC 28 /* terminal location number */
#define TELOPT_3270REGIME 29 /* 3270 regime */
#define TELOPT_X3PAD 30 /* X.3 PAD */
#define TELOPT_NAWS 31 /* window size */
#define TELOPT_TSPEED 32 /* terminal speed */
#define TELOPT_LFLOW 33 /* remote flow control */
#define TELOPT_LINEMODE 34 /* Linemode option */
#define TELOPT_XDISPLOC 35
#define TELOPT_OLD_ENVIRON 36
#define TELOPT_AUTHENTICATION 37 /* authenticate */
#define TELOPT_ENCRYPT 38 /* encryption */
#define TELOPT_NEW_ENVIRON 39
#define TELOPT_EXOPL 255 /* extended-options-list */
#define TELQUAL_IS 0
#define TELQUAL_SEND 1
#define TELQUAL_INFO 2
#define TELQUAL_REPLY 2
#define TELQUAL_NAME 3
#endif

1081
vt100.c

File diff suppressed because it is too large Load Diff