Commit 4d44e8d2 authored by Niels Möller's avatar Niels Möller

New files.

Rev: src/client.c:1.1
Rev: src/client.h:1.1
Rev: src/lsh.c:1.1
Rev: src/read_line.c:1.1
Rev: src/read_line.h:1.1
Rev: src/session.h:1.1
Rev: src/version.h:1.1
parent b04eb460
/* client.c
*
*/
#include "client.h"
#include "version.h"
static int client_initiate(struct client_callback *closure,
int fd)
{
struct abstract_write *write = io_write(closure->backend, fd, closure->block_size,
...close);
struct session = session_alloc(...);
session->sent_version = ssh_format("SSH-" PROTOCOL_VERSION
"-" SOFTWARE_VERSION " %lS\r\n",
closure->id_comment);
/* FIXME: Retain the version string (by copying or increfing) */
#error foo
A_WRITE(write, session->sent_version);
io_read(closure->backend, fd, make_client_read_line());
}
/* This limit follows the ssh specification */
#define MAX_LINE 255
/* FIXME: Abstract this out, so that it can be used by the server as
* well. */
static int do_read_line(struct ... *closure, struct abstract_read *read)
{
int n = A_READ(read, closure->line, MAX_LINE - closure->pos);
UINT8 *eol;
UINT32 length;
if (n<0)
{
werror("do_read_1: read() failed, %s\n", strerror(errno));
return 0;
}
closure->pos += n;
/* Check for eol */
eol = memchr(closure->buffer, '\n', closure->pos);
if (!eol)
{
if (closure->pos == MAX_LINE)
{
werror("Too long line from server\n");
return NULL;
}
return closure;
}
if ( (eol > closure->buffer)
&& (eol[-1] == '\r'))
eol--;
length = eol - closure->buffer;
if ( (length >= 4) && !memcmp(closure->buffer, "SSH-", 4))
{
/* Parse and remember format string */
if ( ((length >= 8) && !memcmp(closure->buffer + 4, "2.0-", 4))
|| ((length >= 9) && !memcmp(closure->buffer +4, "1.99-", 5)))
{
session->recieved_version = ssh_format("%s", length, closure->buffer);
/* FIXME: Unget any extra data */
/* return a new read-handler */
return 0;
}
else
{
werror("Unsupported protocol version: ");
werror_safe(length, closure->buffer);
werror("\n");
return 0;
}
}
else
{
/* Display line */
werror_safe(length, closure->buffer);
memcpy(closure->buffer, closure->buffer + length, length);
closure->pos = 0;
/* Read next line */
return closure;
}
}
struct fd_callback *make_client_callback(struct io_backend *b,
UINT32 block_size)
{
struct client_callback connected = xalloc(sizeof(struct client_callback));
connected->c.f = (fd_callback_f) client_initiate;
connected->backend = b;
connected->block_size = block_size;
return (struct fd_callback *) connected;
}
/* client.h
*
*/
#ifndef LSH_CLIENT_H_INCLUDED
#define LSH_CLIENT_H_INCLUDED
#include "io.h"
struct client_callback
{
struct fd_callback c;
struct io_backend *backend;
UINT32 block_size;
};
struct fd_callback *make_client_callback(struct io_backend *b,
UINT32 block_size);
struct client_session
{
struct read_handler handler;
UINT32 *
#endif /* LSH_CLIENT_H_INCLUDED */
/* lsh.c
*
* client main program
*/
#include <getopt.h>
#include "io.h"
#include "werror.h"
#include "client.h"
#define BLOCK_SIZE 32768
/* Global variable */
struct io_backend backend;
void usage() NORETURN;
void usage()
{
exit(1);
}
int main(int argc, char **argv)
{
char *host = NULL;
char *port = "ssh";
int verbose;
int option;
struct sockaddr_in remote;
while((option = getopt(argc, argv, "dp:q")) != -1)
switch(option)
{
case 'p':
port = optarg;
break;
case 'q':
quiet_flag = 1;
break;
case 'd':
debug_flag = 1;
break;
default:
usage();
}
if ( (argc - optind) < 1)
usage();
host = argv[optind];
if (!get_inaddr(&remote, host, port, "tcp"))
{
fprintf(stderr, "No such host or service");
exit(1);
}
{
struct client_callback connected = {
{ (fd_callback_f) client_initiate },
&backend,
BLOCK_SIZE;
};
io_connect(&backend, &remote, NULL,
make_client_callback(backend, BLOCK_SIZE));
}
io_run();
return 0;
}
/* read_line.c
*
*/
#include "read_line.h"
struct string_read
{
struct abstract_read a;
struct read_line *line;
UINT32 index;
};
static int do_string_read(struct string_read *closure,
UINT8 *buffer, UINT32 length)
{
UINT32 left = closure->line->pos - closure->index;
UINT32 to_read = MIN(length, left);
memcpy(buffer, closure->buffer + index, to_read);
closure->index += to_read;
return to_read;
}
static struct read_handler *do_read_line(struct read_line *closure,
struct abstract_read *read)
{
int n = A_READ(read, closure->line, MAX_LINE - closure->pos);
UINT8 *eol;
UINT32 length;
struct read_handler *next;
if (n<0)
{
werror("do_read_line: read() failed, %s\n", strerror(errno));
return 0;
}
closure->pos += n;
/* Loop over all recieved lines */
while ( (eol = memchr(closure->buffer, '\n', closure->pos) ))
{
/* eol points at the newline character. end points at the
* character terminating the line, which may be a carriage
* return preceeding the newline. */
UINT8 *end = ( (eol > closure->buffer)
&& (eol[-1] == '\r'))
? eol - 1 : eol;
length = end - closure->buffer;
next = PROCESS_LINE(closure->handler, length, closure->buffer);
if (!next)
{
/* Read another line */
/* Number of characters that have been processed */
UINT32 done = eol - closure->buffer + 1;
UINT32 left = buffer->pos - done;
memcpy(closure->buffer, buffer + done, left);
closure->pos = left;
}
else
{
/* Read no more lines. Instead, pass remaining data to next,
* and return a new read-handler. */
if (closure->pos)
{
struct string_read read =
{ { (abstract_read_f) do_string_read },
closure,
0 };
while(next && (read->index < buffer->pos))
next = READ_HANDLER(next, &read);
}
/* No data left */
free(closure);
return next;
}
}
/* Partial line */
if (closure->pos == MAX_LINE)
{
werror("Too long line from server\n");
return NULL;
}
return &(closure->super);
}
/* read_line.h
*
* Read-handler processing a line at a time.
*/
#ifndef LSH_READ_HANDLER_H_INCLUDED
#define LSH_READ_HANDLER_H_INCLUDED
#include "abstract_io.h"
/* This limit follows the ssh specification */
#define MAX_LINE 255
struct line_handler;
typedef (struct read_handler *line_handler_f)(struct line_handler *closure,
UINT32 length,
UINT8 *line);
struct line_handler
{
line_handler_f handler;
};
#define PROCESS_LINE(handler, length, line) \
((handler)->handler((handler), (length), (line)))
struct read_line
{
struct read_handler super; /* Super type */
UINT32 pos; /* Line buffer */
UINT8 buffer[MAX_LINE];
struct line_handler *handler;
};
#endif /* LSH_READ_HANDLER_H_INCLUDED */
/* session.h
*
*/
#ifndef LSH_SESSION_H_INCLUDED
#define LSH_SESSION_H_INCLUDED
struct session
{
/* Sent and recieved version strings */
struct lsh_string *client_version;
struct lsh_string *server_version;
struct lsh_string *session_id;
struct abstract_write write; /* Socket connected to the other end */
};
#endif /* LSH_SESSION_H_INCLUDED */
/* version.h
*
*/
#define PROTOCOL_VERSION "2.0"
#define SOFTWARE_VERSION "lsh_0.0"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment