1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-03-15 03:23:02 -05:00
putty-source/rlogin.c
Simon Tatham 0a80c983e2 Major destabilisation, phase 1. In this phase I've moved (I think)
all the global and function-static variables out of terminal.c into
a dynamically allocated data structure. Note that this does not yet
confer the ability to run more than one of them in the same process,
because other things (the line discipline, the back end) are still
global, and also in particular the address of the dynamically
allocated terminal-data structure is held in a global variable
`term'. But what I've got here represents a reasonable stopping
point at which to check things in. In _theory_ this should all still
work happily, on both Unix and Windows. In practice, who knows?

[originally from svn r2115]
2002-10-22 16:11:33 +00:00

246 lines
4.6 KiB
C

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "putty.h"
#include "terminal.h"
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#define RLOGIN_MAX_BACKLOG 4096
static Socket s = NULL;
static int rlogin_bufsize;
static void *frontend;
static void rlogin_size(void);
static void c_write(char *buf, int len)
{
int backlog = from_backend(frontend, 0, buf, len);
sk_set_frozen(s, backlog > RLOGIN_MAX_BACKLOG);
}
static int rlogin_closing(Plug plug, char *error_msg, int error_code,
int calling_back)
{
if (s) {
sk_close(s);
s = NULL;
}
if (error_msg) {
/* A socket error has occurred. */
logevent(error_msg);
connection_fatal("%s", error_msg);
} /* Otherwise, the remote side closed the connection normally. */
return 0;
}
static int rlogin_receive(Plug plug, int urgent, char *data, int len)
{
if (urgent == 2) {
char c;
c = *data++;
len--;
if (c == '\x80')
rlogin_size();
/*
* We should flush everything (aka Telnet SYNCH) if we see
* 0x02, and we should turn off and on _local_ flow control
* on 0x10 and 0x20 respectively. I'm not convinced it's
* worth it...
*/
} else {
/*
* Main rlogin protocol. This is really simple: the first
* byte is expected to be NULL and is ignored, and the rest
* is printed.
*/
static int firstbyte = 1;
if (firstbyte) {
if (data[0] == '\0') {
data++;
len--;
}
firstbyte = 0;
}
if (len > 0)
c_write(data, len);
}
return 1;
}
static void rlogin_sent(Plug plug, int bufsize)
{
rlogin_bufsize = bufsize;
}
/*
* Called to set up the rlogin connection.
*
* Returns an error message, or NULL on success.
*
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static char *rlogin_init(void *frontend_handle,
char *host, int port, char **realhost, int nodelay)
{
static struct plug_function_table fn_table = {
rlogin_closing,
rlogin_receive,
rlogin_sent
}, *fn_table_ptr = &fn_table;
SockAddr addr;
char *err;
frontend = frontend_handle;
/*
* Try to find host.
*/
{
char buf[200];
sprintf(buf, "Looking up host \"%.170s\"", host);
logevent(buf);
}
addr = sk_namelookup(host, realhost);
if ((err = sk_addr_error(addr)))
return err;
if (port < 0)
port = 513; /* default rlogin port */
/*
* Open socket.
*/
{
char buf[200], addrbuf[100];
sk_getaddr(addr, addrbuf, 100);
sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
logevent(buf);
}
s = new_connection(addr, *realhost, port, 1, 0, nodelay, &fn_table_ptr);
if ((err = sk_socket_error(s)))
return err;
sk_addr_free(addr);
/*
* Send local username, remote username, terminal/speed
*/
{
char z = 0;
char *p;
sk_write(s, &z, 1);
sk_write(s, cfg.localusername, strlen(cfg.localusername));
sk_write(s, &z, 1);
sk_write(s, cfg.username, strlen(cfg.username));
sk_write(s, &z, 1);
sk_write(s, cfg.termtype, strlen(cfg.termtype));
sk_write(s, "/", 1);
for (p = cfg.termspeed; isdigit(*p); p++);
sk_write(s, cfg.termspeed, p - cfg.termspeed);
rlogin_bufsize = sk_write(s, &z, 1);
}
return NULL;
}
/*
* Called to send data down the rlogin connection.
*/
static int rlogin_send(char *buf, int len)
{
if (s == NULL)
return 0;
rlogin_bufsize = sk_write(s, buf, len);
return rlogin_bufsize;
}
/*
* Called to query the current socket sendability status.
*/
static int rlogin_sendbuffer(void)
{
return rlogin_bufsize;
}
/*
* Called to set the size of the window
*/
static void rlogin_size(void)
{
char b[12] = { '\xFF', '\xFF', 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 };
if (s == NULL || term == NULL)
return;
b[6] = term->cols >> 8;
b[7] = term->cols & 0xFF;
b[4] = term->rows >> 8;
b[5] = term->rows & 0xFF;
rlogin_bufsize = sk_write(s, b, 12);
return;
}
/*
* Send rlogin special codes.
*/
static void rlogin_special(Telnet_Special code)
{
/* Do nothing! */
return;
}
static Socket rlogin_socket(void)
{
return s;
}
static int rlogin_sendok(void)
{
return 1;
}
static void rlogin_unthrottle(int backlog)
{
sk_set_frozen(s, backlog > RLOGIN_MAX_BACKLOG);
}
static int rlogin_ldisc(int option)
{
return 0;
}
static int rlogin_exitcode(void)
{
/* If we ever implement RSH, we'll probably need to do this properly */
return 0;
}
Backend rlogin_backend = {
rlogin_init,
rlogin_send,
rlogin_sendbuffer,
rlogin_size,
rlogin_special,
rlogin_socket,
rlogin_exitcode,
rlogin_sendok,
rlogin_ldisc,
rlogin_unthrottle,
1
};