Commit 5bb13c27 authored by Niels Möller's avatar Niels Möller
Browse files

*** empty log message ***

Rev: src/format.c:1.1
Rev: src/format.h:1.1
Rev: src/parse.c:1.1
Rev: src/parse.h:1.1
parent 1a411a7f
/* format.c
*
*/
#include "format.h"
struct simple_packet *ssh_format(char *format, ...)
{
va_list args;
UINT32 length;
struct simple_packet *packet;
va_start(args, format);
length = ssh_vformat_length(format, args);
va_end(args);
packet = simple_packet_alloc(length);
va_start(args, format);
ssh_vformat(format, packet->data, args);
va_end(args);
return packet;
}
UINT32 *ssh_vformat_length(char *f, va_list args)
{
UINT32 length = 0;
while(*f)
{
if (*f == '%')
{
int literal = 0;
f++;
if (*f == 'l')
{
literal = 1;
f++;
}
switch(*f)
{
default:
fatal("ssh_vformat_length: bad format string");
break;
case 'c':
(void) va_arg(args, UINT8);
/* Fall through */
case '%':
f++;
length++;
break;
case 'i':
(void) va_arg(args, UINT32);
f++;
length += 4;
break;
case 's':
{
UINT32 length += va_arg(args, UINT32); /* String length */
(void) va_arg(args, UIN8 *); /* data */
f++;
if (!literal)
length += 4;
}
break;
case 'a':
{
int atom = va_arg(args, int);
assert(atom);
length += get_atom_length(atom);
if (!literal)
length += 4;
f++;
}
break;
case 'A':
{
int atom;
while(atom = va_arg(args, int))
length += get_atom_length(atom) + 1;
/* One ','-character less than the number of atoms */
length--;
if (!literal)
length += 4;
f++;
}
break;
case 'n':
{
mpz_t n = va_arg(args, mpz_t);
/* Calculate length of written number */
#error foo
if (!literal)
length += 4;
f++;
}
break;
}
}
else
{
length++;
f++;
}
}
return length;
}
void ssh_vformat(char *f, UINT *buffer, va_list args)
{
while(*f)
{
if (*f == '%')
{
int literal = 0;
f++;
if (*f == 'l')
{
literal = 1;
f++;
}
switch(*f)
{
default:
fatal("ssh_vformat: bad format string");
break;
case 'c':
*buffer++ = va_arg(args, UINT8);
f++;
break;
case '%':
*buffer++ = '%';
f++;
break;
case 'i':
{
UINT32 i = va_arg(args, UINT32);
WRITE_UINT32(buffer, i);
buffer += 4;
f++;
}
break;
case 's':
{
UINT32 length += va_arg(args, UINT32);
UINT8 *data = va_arg(args, UIN8 *);
if (!literal)
{
WRITE_UINT32(buffer, length);
buffer += 4;
}
memcpy(buffer, data, length);
buffer += length;
f++;
}
break;
case 'a':
{
int atom = va_arg(args, int);
assert(atom);
length += get_atom_length(atom);
if (!literal)
{
WRITE_UINT32(buffer, length);
buffer += 4;
}
memcpy(buffer, get_atom_name(atom), length);
buffer += length;
f++;
}
break;
case 'A':
{
int atom;
int first = 1;
UINT8 *start = buffer; /* Where to store the length */
if (!literal)
buffer += 4;
atom = va_arg(args, int);
if (atom)
{
UINT32 length = get_atom_length(atom);
memcpy(buffer, get_atom_name(atom), length);
buffer += length;
while(atom = va_arg(args, int))
{
*buffer++ = ',';
length = get_atom_length(atom);
memcpy(buffer, get_atom_name(atom), length);
buffer += length;
}
}
if (!literal)
{
total = buffer - start - 4;
WRITE_UINT32(start, total);
}
f++;
}
break;
case 'n':
{
mpz_t n = va_arg(args, mpz_t);
UINT32 length;
/* Calculate length of written number */
#error foo
if (!literal)
{
WRITE_UINT32(buffer, length);
buffer += 4;
}
/* Write digits */
f++;
}
break;
}
}
*buffer++ = *f++;
}
/* format.h
*
* Create a packet from a format string and arguments.
*/
#ifndef LSH_FORMAT_H_INCLUDED
#define LSH_FORMAT_H_INCLUDED
#include <stdarg.h>
/* Format strings can contain the following %-specifications:
*
* %% Insert a %-sign
*
* %c Insert an 8-bit character
*
* %i Insert an 32-bit integer, in network byte order
*
* %s Insert a string, given by a length and a pointer.
*
* %a Insert a string containing one atom.
*
* %A Insert a string containing a list of atoms. The corresponding
* argument sublist should be terminated with a zero.
*
* %n Insert a string containing a bignum.
*
* There is one valid modifier, "l" (as in literal). It is applicable
* to the s, a, A and n specifiers, and outputs strings *without* a
* length field.
*/
UINT32 ssh_vformat_length(char *format, va_list args);
void ssh_vformat(char *format, UINT *buffer, va_list args);
struct simple_packet *ssh_format(char *format, ...);
#endif /* LSH_FORMAT_H_INCLUDED */
/* parse.c
*
*/
#include "parse.h"
void simple_buffer_init(struct simple_buffer *buffer,
UINT32 capacity, UINT8 *data)
{
buffer->capacity = capacity;
buffer->pos = 0;
buffer->data = data;
}
#define BUFFER_LEFT (buffer->capacity - buffer->pos)
#define HERE (buffer->data + buffer->pos)
#define ADVANCE(n) (buffer->pos += (n))
int parse_uint32(struct simple_buffer *buffer, UINT32 *result)
{
if (BUFFER_LEFT < 4)
return 0;
*result = READ_INT32(HERE);
ADVANCE(4);
return 1;
}
int parse_string(struct simple_buffer *buffer,
UINT32 *length, UINT8 **start)
{
UINT32 l;
if (!parse_uint32(buffer, &l))
return 0;
if (BUFFER_LEFT < length)
return 0;
*length = l;
*start = HERE;
ADVANCE(l);
}
/* Initializes subbuffer to parse a string from buffer */
int parse_sub_buffer(struct simple_buffer *buffer,
struct simple_buffer *subbuffer)
{
UINT32 length;
UINT8 *data;
if (!parse_string(buffer, &length, &data))
return 0;
simple_buffer_init(subbuffer, length, data);
return 1;
}
int parse_uint8(struct simple_buffer *buffer, uint8 *result)
{
if (!LEFT)
return 0;
*result = HERE[0];
ADVANCE(1);
return 1;
}
int parse_bignum(struct simple_buffer *buffer, mpz_t result)
{
UINT32 length;
UINT8 *digits;
if (!parse_string(buffer, &length, &data))
return 0;
/* init mpz */
#error
}
/* Returns 1 on success, 0 on failure, and -1 at end of buffer.
* Unknown atoms sets result to zero. */
/* NOTE: This functions record the fact that it has read to the end of
* the buffer by setting the position to *beyond* the end of the
* buffer. */
int parse_next_atom(struct simple_buffer *buffer, int *result)
{
UINT32 i;
if (buffer->pos > buffer->capacity)
return -1;
for(i = 0; i < left; i++)
if (HERE[i] == ',')
{
*result = lookup_atom(HERE, i);
ADVANCE[i+1];
return 1;
}
*result = lookup(HERE, i);
ADVANCE(i+1); /* Beyond end of buffer */
return 1;
}
/* Returns success (i.e. 1) iff there is no data left */
int parse_eod(struct simple_buffer *buffer);
{
return !LEFT;
}
/* parse.h
*
* Parses the data formats used in ssh packets.
*/
#ifndef LSH_PARSE_H_INCLUDED
#define LSH_PARSE_H_INCLUDED
/* Simple buffer */
struct simple_buffer
{
UNIT32 capacity;
UINT32 pos;
UINT8 *data;
};
void simple_buffer_init(struct simple_buffer *buffer,
UINT32 capacity, UINT8 *data);
/* Returns 1 on success, 0 on failure */
int parse_uint32(struct simple_buffer *buffer, UINT32 *result);
int parse_string(struct simple_buffer *buffer,
UINT32 *length, UINT8 **start);
/* Initializes subbuffer to parse a string from buffer */
int parse_sub_buffer(struct simple_buffer *buffer,
struct simple_buffer *subbuffer);
int parse_uint8(struct simple_buffer *buffer, uint8 *result);
#define parse_boolean parse_uint8
int parse_bignum(struct simple_buffer *buffer, mpz_t result);
/* Returns 1 on success, 0 on failure, and -1 at end of buffer.
* Unknown atoms sets result to zero. */
int parse_next_atom(struct simple_buffer *buffer, int *result);
/* Returns success (i.e. 1) iff there is no data left */
int parse_eod(struct simple_buffer *buffer);
#if 0
/* Returns the number of octets that were actually written into the buffer */
UINT32 simple_buffer_write(struct simple_buffer *buffer,
UINT32 length, UINT32 *data);
UINT32 simple_buffer_avail(struct simple_buffer *buffer);
#endif
#endif /* LSH_PARSE_H_INCLUDED */
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