mirror of
https://github.com/ksherlock/marlene.git
synced 2024-09-12 09:54:52 +00:00
rewrite vt100 and telnet.
This commit is contained in:
parent
9285503c5f
commit
9cc53483ad
32
GNUmakefile
Normal file
32
GNUmakefile
Normal 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)
|
464
display.c
464
display.c
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
897
fctelnet.c
897
fctelnet.c
@ -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;
|
||||
}
|
||||
|
||||
|
47
makefile
47
makefile
@ -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)
|
||||
|
248
marinetti.c
248
marinetti.c
@ -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>
|
||||