mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 01:02:24 +00:00
Lots of MacTCP networking stuff. I think all the code's written, but it
doesn't actually work yet. Also the telnet backend is still single-session, and I haven't even touched the ssh one. Oh, and the "Main" segment just overflowed 32k, so we have extra linker incantations. I'm off to the pub now. [originally from svn r156]
This commit is contained in:
parent
efc9e4260c
commit
0256bceece
13
Makefile.mpw
13
Makefile.mpw
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile.mpw,v 1.1.2.11 1999/04/03 21:53:29 ben Exp $
|
||||
# $Id: Makefile.mpw,v 1.1.2.12 1999/04/04 18:23:33 ben Exp $
|
||||
# This is the Makefile for building PuTTY for the Mac OS.
|
||||
# Users of non-Mac systems will see some pretty strange characters around.
|
||||
|
||||
@ -13,8 +13,10 @@ COptions = {Includes} {Sym
|
||||
PPCCOptions = {Includes} {Sym¥PPC} -w 35
|
||||
|
||||
Objects¥68K = ¶
|
||||
dnr.c.o ¶
|
||||
mac.c.o ¶
|
||||
maccfg.c.o ¶
|
||||
macnet.c.o ¶
|
||||
macterm.c.o ¶
|
||||
misc.c.o ¶
|
||||
# ssh.c.o ¶
|
||||
@ -24,13 +26,15 @@ Objects
|
||||
# sshrand.c.o ¶
|
||||
# sshrsa.c.o ¶
|
||||
# sshsha.c.o ¶
|
||||
# telnet.c.o ¶
|
||||
telnet.c.o ¶
|
||||
terminal.c.o ¶
|
||||
testback.c.o
|
||||
|
||||
Objects¥PPC = ¶
|
||||
dnr.c.x ¶
|
||||
mac.c.x ¶
|
||||
maccfg.c.x ¶
|
||||
macnet.c.x ¶
|
||||
macterm.c.x ¶
|
||||
misc.c.x ¶
|
||||
# ssh.c.x ¶
|
||||
@ -40,7 +44,7 @@ Objects
|
||||
# sshrand.c.x ¶
|
||||
# sshrsa.c.x ¶
|
||||
# sshsha.c.x ¶
|
||||
# telnet.c.x ¶
|
||||
telnet.c.x ¶
|
||||
terminal.c.x ¶
|
||||
testback.c.x
|
||||
|
||||
@ -89,11 +93,13 @@ PuTTY.68k
|
||||
ILink ¶
|
||||
-o {Targ} {Sym¥68K} ¶
|
||||
-t 'APPL' -c 'pTTY' ¶
|
||||
-br 68k -model far ¶
|
||||
-newerdeps {NewerDeps}
|
||||
ELSE
|
||||
ILink ¶
|
||||
-o {Targ} {Sym¥68K} ¶
|
||||
-t 'APPL' -c 'pTTY' ¶
|
||||
-br 68k -model far¶
|
||||
{Objects¥68K} ¶
|
||||
{Libs¥68K}
|
||||
END
|
||||
@ -118,6 +124,7 @@ PuTTY
|
||||
setfile -t XCOF {Targ}
|
||||
{PPCC} {default}.c -o {Targ} {PPCCOptions}
|
||||
|
||||
dnr.c.o dnr.c.x Ä
|
||||
mac.c.o mac.c.x Ä putty.h mac.h macresid.h
|
||||
maccfg.c.o maccfg.c.x Ä putty.h mac.h macresid.h
|
||||
macnet.c.o macnet.c.x Ä putty.h
|
||||
|
3
mac.c
3
mac.c
@ -1,4 +1,4 @@
|
||||
/* $Id: mac.c,v 1.1.2.23 1999/04/02 12:58:02 ben Exp $ */
|
||||
/* $Id: mac.c,v 1.1.2.24 1999/04/04 18:23:33 ben Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1999 Ben Harris
|
||||
* All rights reserved.
|
||||
@ -159,6 +159,7 @@ static void mac_eventloop(void) {
|
||||
mac_adjustcursor(cursrgn);
|
||||
if (gotevent)
|
||||
mac_event(&event);
|
||||
macnet_eventcheck();
|
||||
}
|
||||
DisposeRgn(cursrgn);
|
||||
}
|
||||
|
2
mac.h
2
mac.h
@ -30,6 +30,8 @@ extern void mac_keyterm(WindowPtr, EventRecord *);
|
||||
extern void mac_menuterm(WindowPtr, short, short);
|
||||
/* from maccfg.c */
|
||||
extern void mac_loadconfig(Config *);
|
||||
/* from macnet.c */
|
||||
extern void macnet_eventcheck(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
160
macnet.c
160
macnet.c
@ -1,4 +1,4 @@
|
||||
/* $Id: macnet.c,v 1.1.2.2 1999/04/03 21:53:29 ben Exp $ */
|
||||
/* $Id: macnet.c,v 1.1.2.3 1999/04/04 18:23:34 ben Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1999 Ben Harris
|
||||
* All rights reserved.
|
||||
@ -73,21 +73,17 @@ typedef struct Socket {
|
||||
TCPiopb spareiopb; /* for closing etc */
|
||||
hostInfo hostinfo;
|
||||
int port;
|
||||
// unsigned char *inbuf;
|
||||
// int inbuf_head, inbuf_reap, inbuf_size;
|
||||
// unsigned char *outbuf;
|
||||
// int outbuf_head, outbuf_reap, outbuf_size;
|
||||
ProcessSerialNumber psn;
|
||||
Session *s;
|
||||
UInt32 a5;
|
||||
qHdr sendq; /* Blocks waiting to be sent */
|
||||
qHdr freeq; /* Blocks sent, waiting to be freed */
|
||||
long a5;
|
||||
QHdr sendq; /* Blocks waiting to be sent */
|
||||
} Socket;
|
||||
|
||||
typedef struct {
|
||||
QElem qelem;
|
||||
int flags;
|
||||
int len;
|
||||
wdsEntry wds;
|
||||
short wdsterm;
|
||||
} Send_Buffer;
|
||||
|
||||
/*
|
||||
@ -112,9 +108,11 @@ static int mtcp_initted = FALSE;
|
||||
|
||||
static OSErr macnet_init(void);
|
||||
static pascal void macnet_resolved(hostInfo *, char *);
|
||||
static void macnet_opened(TCPiopb*);
|
||||
static void macnet_sent(TCPiopb*);
|
||||
static void macnet_closed(TCPiopb*);
|
||||
static void macnet_completed_open(TCPiopb*);
|
||||
static void macnet_completed_send(TCPiopb*);
|
||||
static void macnet_sent(Socket *);
|
||||
static void macnet_startsend(Socket *);
|
||||
static void macnet_completed_close(TCPiopb*);
|
||||
static pascal void macnet_asr(StreamPtr, unsigned short, Ptr, unsigned short,
|
||||
ICMPReport *);
|
||||
static void macnet_sendevent(Socket *, Net_Event_Type);
|
||||
@ -122,21 +120,22 @@ static void macnet_sendevent(Socket *, Net_Event_Type);
|
||||
#if TARGET_RT_MAC_CFM
|
||||
static RoutineDescriptor macnet_resolved_upp =
|
||||
BUILD_ROUTINE_DESCRIPTOR(uppResultProcInfo, (ProcPtr)macnet_resolved);
|
||||
static RoutineDescriptor macnet_opened_upp =
|
||||
static RoutineDescriptor macnet_completed_open_upp =
|
||||
BUILD_ROUTINE_DESCRIPTOR(uppTCPIOCompletionProcInfo,
|
||||
(ProcPtr)macnet_opened);
|
||||
static RoutineDescriptor macnet_sent_upp =
|
||||
BUILD_ROUTINE_DESCRIPTOR(uppTCPIOCompletionProcInfo, (ProcPtr)macnet_sent);
|
||||
static RoutineDescriptor macnet_closed_upp =
|
||||
(ProcPtr)macnet_completed_open);
|
||||
static RoutineDescriptor macnet_complete_send_upp =
|
||||
BUILD_ROUTINE_DESCRIPTOR(uppTCPIOCompletionProcInfo,
|
||||
(ProcPtr)macnet_closed);
|
||||
(ProcPtr)macnet_completed_send);
|
||||
static RoutineDescriptor macnet_completed_close_upp =
|
||||
BUILD_ROUTINE_DESCRIPTOR(uppTCPIOCompletionProcInfo,
|
||||
(ProcPtr)macnet_completed_close);
|
||||
static RoutineDescriptor macnet_asr_upp =
|
||||
BUILD_ROUTINE_DESCRIPTOR(uppTCPNotifyProcInfo, (ProcPtr)macnet_asr);
|
||||
#else
|
||||
#define macnet_resolved_upp macnet_resolved
|
||||
#define macnet_opened_upp macnet_opened
|
||||
#define macnet_sent_upp macnet_sent
|
||||
#define macnet_closed_upp macnet_closed
|
||||
#define macnet_completed_open_upp macnet_completed_open
|
||||
#define macnet_completed_send_upp macnet_completed_send
|
||||
#define macnet_completed_close_upp macnet_completed_close
|
||||
#define macnet_asr_upp macnet_asr
|
||||
#endif
|
||||
|
||||
@ -153,13 +152,18 @@ static OSErr macnet_init(void) {
|
||||
NetEvent *eventblock;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* FIXME: This is hideously broken, in that we're meant to faff
|
||||
* with unit numbers and stuff, and we blatantly don't.
|
||||
*/
|
||||
err = opendriver(".IPP", &mtcp_refnum);
|
||||
if (err != noErr)
|
||||
return err;
|
||||
err = OpenResolver(NULL);
|
||||
if (err != noErr)
|
||||
return err;
|
||||
/* Set up the event queues, and fill the free queue with events */
|
||||
/* Set up the event queues, and fill the free queue with events
|
||||
*/
|
||||
macnet_eventq.qFlags = 0;
|
||||
macnet_eventq.qHead = macnet_eventq.qTail = NULL;
|
||||
macnet_freeq.qFlags = 0;
|
||||
@ -168,6 +172,7 @@ static OSErr macnet_init(void) {
|
||||
for (i = 0; i < NUM_EVENTS; i++)
|
||||
Enqueue(&eventblock[i].qelem, &macnet_freeq);
|
||||
mtcp_initted = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Socket *net_open(Session *s, char *host, int port) {
|
||||
@ -217,9 +222,11 @@ Socket *net_open(Session *s, char *host, int port) {
|
||||
static pascal void macnet_resolved(hostInfo *hi, char *cookie) {
|
||||
Socket *sock = (Socket *)cookie;
|
||||
OSErr err;
|
||||
UInt32 olda5;
|
||||
#if !TARGET_RT_CFM
|
||||
long olda5;
|
||||
|
||||
olda5 = SetA5(sock->a5);
|
||||
#endif
|
||||
/*
|
||||
* We've resolved a name, so now we'd like to connect to it (or
|
||||
* report an error).
|
||||
@ -227,7 +234,7 @@ static pascal void macnet_resolved(hostInfo *hi, char *cookie) {
|
||||
switch (sock->hostinfo.rtnCode) {
|
||||
case noErr:
|
||||
/* Open a connection */
|
||||
sock->iopb.ioCompletion = macnet_opened_upp;
|
||||
sock->iopb.ioCompletion = macnet_completed_open_upp;
|
||||
sock->iopb.csCode = TCPActiveOpen;
|
||||
sock->iopb.csParam.open.validityFlags = typeOfService;
|
||||
sock->iopb.csParam.open.commandTimeoutValue = 0; /* unused */
|
||||
@ -249,14 +256,18 @@ static pascal void macnet_resolved(hostInfo *hi, char *cookie) {
|
||||
macnet_sendevent(sock, NE_NOHOST);
|
||||
break;
|
||||
}
|
||||
#if !TARGET_RT_CFM
|
||||
SetA5(olda5);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void macnet_opened(TCPiopb *iopb) {
|
||||
static void macnet_completed_open(TCPiopb *iopb) {
|
||||
Socket *sock = (Socket *)iopb->csParam.open.userDataPtr;
|
||||
UInt32 olda5;
|
||||
#if !TARGET_RT_CFM
|
||||
long olda5;
|
||||
|
||||
olda5 = SetA5(sock->a5);
|
||||
#endif
|
||||
switch (iopb->ioResult) {
|
||||
case noErr:
|
||||
macnet_sendevent(sock, NE_OPEN);
|
||||
@ -265,16 +276,20 @@ static void macnet_opened(TCPiopb *iopb) {
|
||||
macnet_sendevent(sock, NE_NOOPEN);
|
||||
break;
|
||||
}
|
||||
#if !TARGET_RT_CFM
|
||||
SetA5(olda5);
|
||||
#endif
|
||||
}
|
||||
|
||||
static pascal void macnet_asr(StreamPtr tcpstream, unsigned short eventcode,
|
||||
Ptr cookie, unsigned short terminreason,
|
||||
ICMPReport *icmpmsg) {
|
||||
Socket *sock = (Socket *)cookie;
|
||||
UInt32 olda5;
|
||||
#if !TARGET_RT_CFM
|
||||
long olda5;
|
||||
|
||||
olda5 = SetA5(sock->a5);
|
||||
#endif
|
||||
switch (eventcode) {
|
||||
case TCPClosing:
|
||||
macnet_sendevent(sock, NE_CLOSING);
|
||||
@ -306,23 +321,87 @@ static pascal void macnet_asr(StreamPtr tcpstream, unsigned short eventcode,
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if !TARGET_RT_CFM
|
||||
SetA5(olda5);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a block of data.
|
||||
*/
|
||||
|
||||
int net_send(Socket *sock, void *buf, int buflen, int flags) {{
|
||||
int net_send(Socket *sock, void *buf, int buflen, int flags) {
|
||||
OSErr err;
|
||||
Send_Buffer *buff;
|
||||
|
||||
buff = smalloc(sizeof(Send_Buffer) + buflen);
|
||||
buff->flags = flags;
|
||||
buff->len = buflen;
|
||||
memcpy(buff + 1, buf, buflen);
|
||||
buff->wds.length = buflen;
|
||||
buff->wds.ptr = (Ptr)&buff[1]; /* after the end of the struct */
|
||||
buff->wdsterm = 0;
|
||||
memcpy(&buff[1], buf, buflen);
|
||||
Enqueue(&buff->qelem, &sock->sendq);
|
||||
macnet_start(sock);
|
||||
/* Kick off the transmit if the queue was empty */
|
||||
if (sock->sendq.qHead == &buff->qelem)
|
||||
macnet_startsend(sock);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called once every time round the event loop to check for
|
||||
* network events and handle them.
|
||||
*/
|
||||
void macnet_eventcheck() {
|
||||
NetEvent *ne;
|
||||
|
||||
if (!mtcp_initted)
|
||||
return;
|
||||
ne = (NetEvent *)macnet_eventq.qHead;
|
||||
if (ne == NULL)
|
||||
return;
|
||||
Dequeue(&ne->qelem, &macnet_eventq);
|
||||
switch (ne->type) {
|
||||
case NE_SENT:
|
||||
macnet_sent(ne->sock);
|
||||
break;
|
||||
default:
|
||||
(ne->sock->s->back->msg)(ne->sock->s, ne->sock, ne->type);
|
||||
break;
|
||||
}
|
||||
Enqueue(&ne->qelem, &macnet_freeq);
|
||||
}
|
||||
|
||||
/*
|
||||
* The block at the head of the send queue has finished sending, so we
|
||||
* can free it. Kick off the next transmission if there is one.
|
||||
*/
|
||||
static void macnet_sent(Socket *sock) {
|
||||
Send_Buffer *buff;
|
||||
|
||||
assert(sock->sendq.qHead != NULL);
|
||||
buff = (Send_Buffer *)sock->sendq.qHead;
|
||||
Dequeue(&buff->qelem, &sock->sendq);
|
||||
sfree(buff);
|
||||
if (sock->sendq.qHead != NULL)
|
||||
macnet_startsend(sock);
|
||||
}
|
||||
|
||||
/*
|
||||
* There's a block on the head of the send queue which needs to be
|
||||
* sent.
|
||||
*/
|
||||
|
||||
static void macnet_startsend(Socket *sock) {
|
||||
Send_Buffer *buff;
|
||||
OSErr err;
|
||||
|
||||
buff = (Send_Buffer *)sock->sendq.qHead;
|
||||
sock->iopb.csCode = TCPSend;
|
||||
sock->iopb.csParam.send.validityFlags = 0;
|
||||
sock->iopb.csParam.send.pushFlag = buff->flags & SEND_PUSH ? true : false;
|
||||
sock->iopb.csParam.send.urgentFlag = buff->flags & SEND_URG ? true : false;
|
||||
sock->iopb.csParam.send.wdsPtr = (Ptr)&buff->wds;
|
||||
sock->iopb.csParam.send.userDataPtr = (char *)sock;
|
||||
err = PBControlAsync((ParmBlkPtr)&sock->iopb);
|
||||
}
|
||||
|
||||
int net_recv(Socket *sock, void *buf, int buflen, int flags) {
|
||||
@ -331,7 +410,8 @@ int net_recv(Socket *sock, void *buf, int buflen, int flags) {
|
||||
int avail, want, got;
|
||||
|
||||
memcpy(&iopb, &sock->iopb, sizeof(TCPiopb));
|
||||
/* Work out if there's anything to recieve (we don't want to block) */
|
||||
/* Work out if there's anything to recieve (we don't want to block)
|
||||
*/
|
||||
iopb.csCode = TCPStatus;
|
||||
err = PBControlSync((ParmBlkPtr)&iopb);
|
||||
if (err != noErr)
|
||||
@ -341,12 +421,12 @@ int net_recv(Socket *sock, void *buf, int buflen, int flags) {
|
||||
return 0;
|
||||
want = avail < buflen ? avail : buflen;
|
||||
iopb.csCode = TCPRcv;
|
||||
iopb.csParam.receive.buffPtr = buf;
|
||||
iopb.csParam.receive.buffLen = want;
|
||||
iopb.csParam.receive.rcvBuff = buf;
|
||||
iopb.csParam.receive.rcvBuffLen = want;
|
||||
err = PBControlSync((ParmBlkPtr)&iopb);
|
||||
if (err != noErr)
|
||||
return 0;
|
||||
return iopb.csParam.receive.buffLen;
|
||||
return iopb.csParam.receive.rcvBuffLen;
|
||||
}
|
||||
|
||||
|
||||
@ -360,7 +440,7 @@ void net_close(Socket *sock) {
|
||||
* free it, which we can't do at interrupt time).
|
||||
*/
|
||||
memcpy(&sock->spareiopb, &sock->iopb, sizeof(TCPiopb));
|
||||
sock->spareiopb.ioCompletion = macnet_closed_upp;
|
||||
sock->spareiopb.ioCompletion = macnet_completed_close_upp;
|
||||
sock->spareiopb.csCode = TCPClose;
|
||||
sock->spareiopb.csParam.close.validityFlags = 0;
|
||||
sock->spareiopb.csParam.close.userDataPtr = (char *)sock;
|
||||
@ -376,11 +456,13 @@ void net_close(Socket *sock) {
|
||||
}
|
||||
}
|
||||
|
||||
static void macnet_closed(TCPiopb* iopb) {
|
||||
static void macnet_completed_close(TCPiopb* iopb) {
|
||||
Socket *sock = (Socket *)iopb->csParam.close.userDataPtr;
|
||||
UInt32 olda5;
|
||||
#if !TARGET_RT_CFM
|
||||
long olda5;
|
||||
|
||||
olda5 = SetA5(sock->a5);
|
||||
#endif
|
||||
switch (iopb->ioResult) {
|
||||
case noErr:
|
||||
macnet_sendevent(sock, NE_CLOSED);
|
||||
@ -392,7 +474,9 @@ static void macnet_closed(TCPiopb* iopb) {
|
||||
macnet_sendevent(sock, NE_DIED);
|
||||
break;
|
||||
}
|
||||
#if !TARGET_RT_CFM
|
||||
SetA5(olda5);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
20
macterm.c
20
macterm.c
@ -1,4 +1,4 @@
|
||||
/* $Id: macterm.c,v 1.1.2.33 1999/03/30 19:44:51 ben Exp $ */
|
||||
/* $Id: macterm.c,v 1.1.2.34 1999/04/04 18:23:34 ben Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1999 Simon Tatham
|
||||
* Copyright (c) 1999 Ben Harris
|
||||
@ -140,7 +140,7 @@ void mac_newsession(void) {
|
||||
s = smalloc(sizeof(*s));
|
||||
memset(s, 0, sizeof(*s));
|
||||
mac_loadconfig(&s->cfg);
|
||||
s->back = &hexdump_backend;
|
||||
s->back = &telnet_backend;
|
||||
|
||||
/* XXX: Own storage management? */
|
||||
if (mac_gestalts.qdvers == gestaltOriginalQD)
|
||||
@ -158,11 +158,12 @@ void mac_newsession(void) {
|
||||
SetPalette(s->window, s->palette, TRUE);
|
||||
ActivatePalette(s->window);
|
||||
ShowWindow(s->window);
|
||||
starttime = TickCount();
|
||||
display_resource(s, 'pTST', 128);
|
||||
sprintf(msg, "Elapsed ticks: %d\015\012", TickCount() - starttime);
|
||||
inbuf_putstr(s, msg);
|
||||
term_out(s);
|
||||
s->back->init(s);
|
||||
/* starttime = TickCount(); */
|
||||
/* display_resource(s, 'pTST', 128); */
|
||||
/* sprintf(msg, "Elapsed ticks: %d\015\012", TickCount() - starttime); */
|
||||
/* inbuf_putstr(s, msg); */
|
||||
/* term_out(s); */
|
||||
}
|
||||
|
||||
static void mac_initfont(Session *s) {
|
||||
@ -1011,6 +1012,11 @@ void do_scroll(Session *s, int topline, int botline, int lines) {
|
||||
DisposeRgn(update);
|
||||
}
|
||||
|
||||
void lognegot(/*Session *s,*/ const char *str) {
|
||||
|
||||
/* XXX Do something */
|
||||
}
|
||||
|
||||
/*
|
||||
* Emacs magic:
|
||||
* Local Variables:
|
||||
|
20
putty.h
20
putty.h
@ -102,6 +102,7 @@ typedef enum {
|
||||
NE_NOOPEN, /* Connection failed to open for some other reason */
|
||||
NE_DATA, /* Incoming normal data */
|
||||
NE_URGENT, /* Incoming urgent data */
|
||||
NE_SENT, /* Used internally by Mac network stack */
|
||||
NE_CLOSING, /* Connection closed by remote host */
|
||||
NE_CLOSED, /* Connection close completed */
|
||||
NE_TIMEOUT, /* Remote host vanished */
|
||||
@ -109,10 +110,14 @@ typedef enum {
|
||||
NE_DIED, /* Connection has failed for some other reason */
|
||||
} Net_Event_Type;
|
||||
|
||||
#ifdef macintosh
|
||||
typedef Socket *SOCKET;
|
||||
#define INVALID_SOCKET NULL
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char *(*init) (Session *, char *host, int port);
|
||||
int (*msg)(Session *, Socket *, Net_Event_Type);
|
||||
char *(*init) (Session *);
|
||||
int (*msg)(Session *, SOCKET, Net_Event_Type);
|
||||
void (*send) (Session *, char *buf, int len);
|
||||
void (*size) (Session *);
|
||||
void (*special) (Session *, Telnet_Special code);
|
||||
@ -281,14 +286,15 @@ extern void pre_paint(Session *);
|
||||
extern void post_paint(Session *);
|
||||
extern void palette_set(Session *, int, int, int, int);
|
||||
extern void palette_reset(Session *);
|
||||
void write_clip (void *, int);
|
||||
void get_clip (void **, int *);
|
||||
extern void write_clip (void *, int);
|
||||
extern void get_clip (void **, int *);
|
||||
extern void do_scroll(Session *, int, int, int);
|
||||
void fatalbox (const char *, ...);
|
||||
extern void fatalbox(const char *, ...);
|
||||
#ifdef macintosh
|
||||
#pragma noreturn (fatalbox)
|
||||
#endif
|
||||
extern void beep (Session *s);
|
||||
extern void beep(Session *s);
|
||||
extern void lognegot(const char *);
|
||||
|
||||
/*
|
||||
* Exports from the network system
|
||||
@ -298,6 +304,8 @@ extern Socket *net_open(Session *, char *host, int port);
|
||||
extern char *net_realname(Socket *);
|
||||
extern int net_recv(Socket *, void *, int, int);
|
||||
extern int net_send(Socket *, void *, int, int);
|
||||
#define SEND_PUSH 0x01
|
||||
#define SEND_URG 0x02
|
||||
extern void net_close(Socket *); /* ask the remote end to close */
|
||||
extern void net_destroy(Socket *); /* Tidy up */
|
||||
|
||||
|
212
telnet.c
212
telnet.c
@ -1,15 +1,17 @@
|
||||
#ifdef macintosh
|
||||
#include <mac.h>
|
||||
#else /* not macintosh */
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
#endif /* not macintosh */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
static SOCKET s = INVALID_SOCKET;
|
||||
/* kludge till we decide where to put telnet state */
|
||||
static Session *sess;
|
||||
|
||||
#define IAC 255 /* interpret as command: */
|
||||
#define DONT 254 /* you are not to use option */
|
||||
@ -102,7 +104,7 @@ static char *telopt(int opt) {
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
static void telnet_size(void);
|
||||
static void telnet_size(Session *ignored);
|
||||
|
||||
struct Opt {
|
||||
int send; /* what we initially send */
|
||||
@ -135,19 +137,19 @@ static int in_synch;
|
||||
#endif
|
||||
|
||||
static int sb_opt, sb_len;
|
||||
static char *sb_buf = NULL;
|
||||
static unsigned char *sb_buf = NULL;
|
||||
static int sb_size = 0;
|
||||
#define SB_DELTA 1024
|
||||
|
||||
static void try_write (void) {
|
||||
while (outbuf_head != outbuf_reap) {
|
||||
int end = (outbuf_reap < outbuf_head ? outbuf_head : OUTBUF_SIZE);
|
||||
int len = end - outbuf_reap;
|
||||
while (sess->outbuf_head != sess->outbuf_reap) {
|
||||
int end = (sess->outbuf_reap < sess->outbuf_head ? sess->outbuf_head : OUTBUF_SIZE);
|
||||
int len = end - sess->outbuf_reap;
|
||||
int ret;
|
||||
|
||||
ret = send (s, outbuf+outbuf_reap, len, 0);
|
||||
ret = net_send (s, sess->outbuf+sess->outbuf_reap, len, 0);
|
||||
if (ret > 0)
|
||||
outbuf_reap = (outbuf_reap + ret) & OUTBUF_MASK;
|
||||
sess->outbuf_reap = (sess->outbuf_reap + ret) & OUTBUF_MASK;
|
||||
if (ret < len)
|
||||
return;
|
||||
}
|
||||
@ -156,10 +158,10 @@ static void try_write (void) {
|
||||
static void s_write (void *buf, int len) {
|
||||
unsigned char *p = buf;
|
||||
while (len--) {
|
||||
int new_head = (outbuf_head + 1) & OUTBUF_MASK;
|
||||
if (new_head != outbuf_reap) {
|
||||
outbuf[outbuf_head] = *p++;
|
||||
outbuf_head = new_head;
|
||||
int new_head = (sess->outbuf_head + 1) & OUTBUF_MASK;
|
||||
if (new_head != sess->outbuf_reap) {
|
||||
sess->outbuf[sess->outbuf_head] = *p++;
|
||||
sess->outbuf_head = new_head;
|
||||
}
|
||||
}
|
||||
try_write();
|
||||
@ -167,11 +169,11 @@ static void s_write (void *buf, int len) {
|
||||
|
||||
static void c_write (char *buf, int len) {
|
||||
while (len--) {
|
||||
int new_head = (inbuf_head + 1) & INBUF_MASK;
|
||||
int new_head = (sess->inbuf_head + 1) & INBUF_MASK;
|
||||
int c = (unsigned char) *buf;
|
||||
if (new_head != inbuf_reap) {
|
||||
inbuf[inbuf_head] = *buf++;
|
||||
inbuf_head = new_head;
|
||||
if (new_head != sess->inbuf_reap) {
|
||||
sess->inbuf[sess->inbuf_head] = *buf++;
|
||||
sess->inbuf_head = new_head;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -201,7 +203,7 @@ static void deactivate_option (struct Opt *o) {
|
||||
|
||||
static void activate_option (struct Opt *o) {
|
||||
if (o->send == WILL && o->option == TELOPT_NAWS)
|
||||
telnet_size();
|
||||
telnet_size(sess);
|
||||
if (o->send == WILL &&
|
||||
(o->option == TELOPT_NEW_ENVIRON ||
|
||||
o->option == TELOPT_OLD_ENVIRON)) {
|
||||
@ -276,27 +278,27 @@ static void process_subneg (void) {
|
||||
switch (sb_opt) {
|
||||
case TELOPT_TSPEED:
|
||||
if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) {
|
||||
char logbuf[sizeof(cfg.termspeed)+80];
|
||||
char logbuf[sizeof(sess->cfg.termspeed)+80];
|
||||
b[0] = IAC; b[1] = SB; b[2] = TELOPT_TSPEED;
|
||||
b[3] = TELQUAL_IS;
|
||||
strcpy(b+4, cfg.termspeed);
|
||||
n = 4 + strlen(cfg.termspeed);
|
||||
strcpy((char *)b+4, sess->cfg.termspeed);
|
||||
n = 4 + strlen(sess->cfg.termspeed);
|
||||
b[n] = IAC; b[n+1] = SE;
|
||||
s_write (b, n+2);
|
||||
lognegot("server:\tSB TSPEED SEND");
|
||||
sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed);
|
||||
sprintf(logbuf, "client:\tSB TSPEED IS %s", sess->cfg.termspeed);
|
||||
lognegot (logbuf);
|
||||
} else
|
||||
lognegot ("server:\tSB TSPEED <something weird>");
|
||||
break;
|
||||
case TELOPT_TTYPE:
|
||||
if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) {
|
||||
char logbuf[sizeof(cfg.termtype)+80];
|
||||
char logbuf[sizeof(sess->cfg.termtype)+80];
|
||||
b[0] = IAC; b[1] = SB; b[2] = TELOPT_TTYPE;
|
||||
b[3] = TELQUAL_IS;
|
||||
for (n = 0; cfg.termtype[n]; n++)
|
||||
b[n+4] = (cfg.termtype[n] >= 'a' && cfg.termtype[n] <= 'z' ?
|
||||
cfg.termtype[n] + 'A'-'a' : cfg.termtype[n]);
|
||||
for (n = 0; sess->cfg.termtype[n]; n++)
|
||||
b[n+4] = (sess->cfg.termtype[n] >= 'a' && sess->cfg.termtype[n] <= 'z' ?
|
||||
sess->cfg.termtype[n] + 'A'-'a' : sess->cfg.termtype[n]);
|
||||
b[n+4] = IAC; b[n+5] = SE;
|
||||
s_write (b, n+6);
|
||||
b[n+4] = 0;
|
||||
@ -316,7 +318,7 @@ static void process_subneg (void) {
|
||||
sprintf (logbuf, "server:\tSB %s SEND", telopt(sb_opt));
|
||||
lognegot (logbuf);
|
||||
if (sb_opt == TELOPT_OLD_ENVIRON) {
|
||||
if (cfg.rfc_environ) {
|
||||
if (sess->cfg.rfc_environ) {
|
||||
value = RFC_VALUE;
|
||||
var = RFC_VAR;
|
||||
} else {
|
||||
@ -347,7 +349,7 @@ static void process_subneg (void) {
|
||||
b[0] = IAC; b[1] = SB; b[2] = sb_opt;
|
||||
b[3] = TELQUAL_IS;
|
||||
n = 4;
|
||||
e = cfg.environmt;
|
||||
e = sess->cfg.environmt;
|
||||
while (*e) {
|
||||
b[n++] = var;
|
||||
while (*e && *e != '\t') b[n++] = *e++;
|
||||
@ -356,10 +358,10 @@ static void process_subneg (void) {
|
||||
while (*e) b[n++] = *e++;
|
||||
e++;
|
||||
}
|
||||
if (*cfg.username) {
|
||||
if (*sess->cfg.username) {
|
||||
b[n++] = var; b[n++] = 'U'; b[n++] = 'S';
|
||||
b[n++] = 'E'; b[n++] = 'R'; b[n++] = value;
|
||||
e = cfg.username;
|
||||
e = sess->cfg.username;
|
||||
while (*e) b[n++] = *e++;
|
||||
}
|
||||
b[n++] = IAC; b[n++] = SE;
|
||||
@ -373,9 +375,9 @@ static void process_subneg (void) {
|
||||
}
|
||||
|
||||
static enum {
|
||||
TOPLEVEL, SEENIAC, SEENWILL, SEENWONT, SEENDO, SEENDONT,
|
||||
TELNET_TOPLEVEL, SEENIAC, SEENWILL, SEENWONT, SEENDO, SEENDONT,
|
||||
SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR
|
||||
} telnet_state = TOPLEVEL;
|
||||
} telnet_state = TELNET_TOPLEVEL;
|
||||
|
||||
static void do_telnet_read (char *buf, int len) {
|
||||
unsigned char b[10];
|
||||
@ -384,10 +386,10 @@ static void do_telnet_read (char *buf, int len) {
|
||||
int c = (unsigned char) *buf++;
|
||||
|
||||
switch (telnet_state) {
|
||||
case TOPLEVEL:
|
||||
case TELNET_TOPLEVEL:
|
||||
case SEENCR:
|
||||
if (c == NUL && telnet_state == SEENCR)
|
||||
telnet_state = TOPLEVEL;
|
||||
telnet_state = TELNET_TOPLEVEL;
|
||||
else if (c == IAC)
|
||||
telnet_state = SEENIAC;
|
||||
else {
|
||||
@ -395,11 +397,11 @@ static void do_telnet_read (char *buf, int len) {
|
||||
#if 0
|
||||
if (!in_synch)
|
||||
#endif
|
||||
c_write (b, 1);
|
||||
c_write ((char *)b, 1);
|
||||
if (c == CR)
|
||||
telnet_state = SEENCR;
|
||||
else
|
||||
telnet_state = TOPLEVEL;
|
||||
telnet_state = TELNET_TOPLEVEL;
|
||||
}
|
||||
break;
|
||||
case SEENIAC:
|
||||
@ -408,23 +410,23 @@ static void do_telnet_read (char *buf, int len) {
|
||||
else if (c == WILL) telnet_state = SEENWILL;
|
||||
else if (c == WONT) telnet_state = SEENWONT;
|
||||
else if (c == SB) telnet_state = SEENSB;
|
||||
else telnet_state = TOPLEVEL;/* ignore _everything_ else! */
|
||||
else telnet_state = TELNET_TOPLEVEL;/* ignore _everything_ else! */
|
||||
break;
|
||||
case SEENWILL:
|
||||
proc_rec_opt (WILL, c);
|
||||
telnet_state = TOPLEVEL;
|
||||
telnet_state = TELNET_TOPLEVEL;
|
||||
break;
|
||||
case SEENWONT:
|
||||
proc_rec_opt (WONT, c);
|
||||
telnet_state = TOPLEVEL;
|
||||
telnet_state = TELNET_TOPLEVEL;
|
||||
break;
|
||||
case SEENDO:
|
||||
proc_rec_opt (DO, c);
|
||||
telnet_state = TOPLEVEL;
|
||||
telnet_state = TELNET_TOPLEVEL;
|
||||
break;
|
||||
case SEENDONT:
|
||||
proc_rec_opt (DONT, c);
|
||||
telnet_state = TOPLEVEL;
|
||||
telnet_state = TELNET_TOPLEVEL;
|
||||
break;
|
||||
case SEENSB:
|
||||
sb_opt = c;
|
||||
@ -437,7 +439,7 @@ static void do_telnet_read (char *buf, int len) {
|
||||
else {
|
||||
subneg_addchar:
|
||||
if (sb_len >= sb_size) {
|
||||
char *newbuf;
|
||||
unsigned char *newbuf;
|
||||
sb_size += SB_DELTA;
|
||||
newbuf = (sb_buf ?
|
||||
realloc(sb_buf, sb_size) :
|
||||
@ -457,7 +459,7 @@ static void do_telnet_read (char *buf, int len) {
|
||||
goto subneg_addchar; /* yes, it's a hack, I know, but... */
|
||||
else {
|
||||
process_subneg();
|
||||
telnet_state = TOPLEVEL;
|
||||
telnet_state = TELNET_TOPLEVEL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -471,84 +473,11 @@ static void do_telnet_read (char *buf, int len) {
|
||||
*
|
||||
* Returns an error message, or NULL on success.
|
||||
*
|
||||
* Also places the canonical host name into `realhost'.
|
||||
*/
|
||||
static char *telnet_init (HWND hwnd, char *host, int port, char **realhost) {
|
||||
SOCKADDR_IN addr;
|
||||
struct hostent *h;
|
||||
unsigned long a;
|
||||
static char *telnet_init (Session *this_sess) {
|
||||
|
||||
/*
|
||||
* Try to find host.
|
||||
*/
|
||||
if ( (a = inet_addr(host)) == (unsigned long) INADDR_NONE) {
|
||||
if ( (h = gethostbyname(host)) == NULL)
|
||||
switch (WSAGetLastError()) {
|
||||
case WSAENETDOWN: return "Network is down";
|
||||
case WSAHOST_NOT_FOUND: case WSANO_DATA:
|
||||
return "Host does not exist";
|
||||
case WSATRY_AGAIN: return "Host not found";
|
||||
default: return "gethostbyname: unknown error";
|
||||
}
|
||||
memcpy (&a, h->h_addr, sizeof(a));
|
||||
*realhost = h->h_name;
|
||||
} else
|
||||
*realhost = host;
|
||||
a = ntohl(a);
|
||||
|
||||
if (port < 0)
|
||||
port = 23; /* default telnet port */
|
||||
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s == INVALID_SOCKET)
|
||||
switch (WSAGetLastError()) {
|
||||
case WSAENETDOWN: return "Network is down";
|
||||
case WSAEAFNOSUPPORT: return "TCP/IP support not present";
|
||||
default: return "socket(): unknown error";
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
BOOL b = TRUE;
|
||||
setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (void *)&b, sizeof(b));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Bind to local address.
|
||||
*/
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
addr.sin_port = htons(0);
|
||||
if (bind (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
|
||||
switch (WSAGetLastError()) {
|
||||
case WSAENETDOWN: return "Network is down";
|
||||
default: return "bind(): unknown error";
|
||||
}
|
||||
|
||||
/*
|
||||
* Connect to remote address.
|
||||
*/
|
||||
addr.sin_addr.s_addr = htonl(a);
|
||||
addr.sin_port = htons((short)port);
|
||||
if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
|
||||
switch (WSAGetLastError()) {
|
||||
case WSAENETDOWN: return "Network is down";
|
||||
case WSAECONNREFUSED: return "Connection refused";
|
||||
case WSAENETUNREACH: return "Network is unreachable";
|
||||
case WSAEHOSTUNREACH: return "No route to host";
|
||||
default: return "connect(): unknown error";
|
||||
}
|
||||
|
||||
if (WSAAsyncSelect (s, hwnd, WM_NETEVENT, FD_READ |
|
||||
FD_WRITE | FD_OOB | FD_CLOSE) == SOCKET_ERROR)
|
||||
switch (WSAGetLastError()) {
|
||||
case WSAENETDOWN: return "Network is down";
|
||||
default: return "WSAAsyncSelect(): unknown error";
|
||||
}
|
||||
sess = this_sess;
|
||||
s = net_open(sess, sess->cfg.host, sess->cfg.port);
|
||||
|
||||
/*
|
||||
* Initialise option states.
|
||||
@ -575,23 +504,18 @@ static char *telnet_init (HWND hwnd, char *host, int port, char **realhost) {
|
||||
* Process a WM_NETEVENT message. Will return 0 if the connection
|
||||
* has closed, or <0 for a socket error.
|
||||
*/
|
||||
static int telnet_msg (WPARAM wParam, LPARAM lParam) {
|
||||
static int telnet_msg (Session *sess, SOCKET sock, Net_Event_Type ne) {
|
||||
int ret;
|
||||
char buf[256];
|
||||
|
||||
if (s == INVALID_SOCKET) /* how the hell did we get here?! */
|
||||
return -5000;
|
||||
|
||||
if (WSAGETSELECTERROR(lParam) != 0)
|
||||
return -WSAGETSELECTERROR(lParam);
|
||||
|
||||
switch (WSAGETSELECTEVENT(lParam)) {
|
||||
case FD_READ:
|
||||
ret = recv(s, buf, sizeof(buf), 0);
|
||||
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
return 1;
|
||||
switch (ne) {
|
||||
case NE_DATA:
|
||||
ret = net_recv(s, buf, sizeof(buf), 0);
|
||||
if (ret < 0) /* any _other_ error */
|
||||
return -10000-WSAGetLastError();
|
||||
return -1;
|
||||
if (ret == 0) {
|
||||
s = INVALID_SOCKET;
|
||||
return 0; /* can't happen, in theory */
|
||||
@ -608,24 +532,20 @@ static int telnet_msg (WPARAM wParam, LPARAM lParam) {
|
||||
#endif
|
||||
do_telnet_read (buf, ret);
|
||||
return 1;
|
||||
case FD_OOB:
|
||||
case NE_URGENT:
|
||||
do {
|
||||
ret = recv(s, buf, sizeof(buf), 0);
|
||||
ret = net_recv(s, buf, sizeof(buf), 0);
|
||||
} while (ret > 0);
|
||||
telnet_state = TOPLEVEL;
|
||||
telnet_state = TELNET_TOPLEVEL;
|
||||
do {
|
||||
ret = recv(s, buf, 1, MSG_OOB);
|
||||
ret = net_recv(s, buf, 1, /*MSG_OOB*/ 0);
|
||||
if (ret > 0)
|
||||
do_telnet_read (buf, ret);
|
||||
} while (ret > 0);
|
||||
if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
return -30000-WSAGetLastError();
|
||||
if (ret < 0)
|
||||
return -3;
|
||||
return 1;
|
||||
case FD_WRITE:
|
||||
if (outbuf_head != outbuf_reap)
|
||||
try_write();
|
||||
return 1;
|
||||
case FD_CLOSE:
|
||||
case NE_CLOSING:
|
||||
s = INVALID_SOCKET;
|
||||
return 0;
|
||||
}
|
||||
@ -635,7 +555,7 @@ static int telnet_msg (WPARAM wParam, LPARAM lParam) {
|
||||
/*
|
||||
* Called to send data down the Telnet connection.
|
||||
*/
|
||||
static void telnet_send (char *buf, int len) {
|
||||
static void telnet_send (Session *this_sess, char *buf, int len) {
|
||||
char *p;
|
||||
static unsigned char iac[2] = { IAC, IAC };
|
||||
static unsigned char cr[2] = { CR, NUL };
|
||||
@ -660,15 +580,15 @@ static void telnet_send (char *buf, int len) {
|
||||
/*
|
||||
* Called to set the size of the window from Telnet's POV.
|
||||
*/
|
||||
static void telnet_size(void) {
|
||||
static void telnet_size(Session *sess) {
|
||||
unsigned char b[16];
|
||||
char logbuf[50];
|
||||
|
||||
if (s == INVALID_SOCKET || o_naws.state != ACTIVE)
|
||||
return;
|
||||
b[0] = IAC; b[1] = SB; b[2] = TELOPT_NAWS;
|
||||
b[3] = cols >> 8; b[4] = cols & 0xFF;
|
||||
b[5] = rows >> 8; b[6] = rows & 0xFF;
|
||||
b[3] = sess->cols >> 8; b[4] = sess->cols & 0xFF;
|
||||
b[5] = sess->rows >> 8; b[6] = sess->rows & 0xFF;
|
||||
b[7] = IAC; b[8] = SE;
|
||||
s_write (b, 9);
|
||||
sprintf(logbuf, "client:\tSB NAWS %d,%d",
|
||||
@ -680,7 +600,7 @@ static void telnet_size(void) {
|
||||
/*
|
||||
* Send Telnet special codes.
|
||||
*/
|
||||
static void telnet_special (Telnet_Special code) {
|
||||
static void telnet_special (Session *sess, Telnet_Special code) {
|
||||
unsigned char b[2];
|
||||
|
||||
if (s == INVALID_SOCKET)
|
||||
@ -701,9 +621,9 @@ static void telnet_special (Telnet_Special code) {
|
||||
case TS_EOR: b[1] = EOR; s_write (b, 2); break;
|
||||
case TS_EOF: b[1] = xEOF; s_write (b, 2); break;
|
||||
case TS_SYNCH:
|
||||
outbuf_head = outbuf_reap = 0;
|
||||
sess->outbuf_head = sess->outbuf_reap = 0;
|
||||
b[0] = DM;
|
||||
send (s, b, 1, MSG_OOB);
|
||||
net_send (s, b, 1, SEND_URG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
10
testback.c
10
testback.c
@ -1,4 +1,4 @@
|
||||
/* $Id: testback.c,v 1.1.2.5 1999/03/29 19:50:24 ben Exp $ */
|
||||
/* $Id: testback.c,v 1.1.2.6 1999/04/04 18:23:35 ben Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1999 Simon Tatham
|
||||
* Copyright (c) 1999 Ben Harris
|
||||
@ -33,8 +33,8 @@
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
static char *null_init(Session *, char *, int, char **);
|
||||
static int null_msg(Session *);
|
||||
static char *null_init(Session *);
|
||||
static int null_msg(Session *, Socket *, Net_Event_Type);
|
||||
static void null_send(Session *, char *, int);
|
||||
static void loop_send(Session *, char *, int);
|
||||
static void hexdump_send(Session *, char *, int);
|
||||
@ -53,12 +53,12 @@ Backend hexdump_backend = {
|
||||
null_init, null_msg, hexdump_send, null_size, null_special
|
||||
};
|
||||
|
||||
static char *null_init(Session *s, char *host, int port, char **realhost) {
|
||||
static char *null_init(Session *s) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int null_msg(Session *s) {
|
||||
static int null_msg(Session *s, Socket *sock, Net_Event_Type ne) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user