ftp.nice.ch/pub/next/connectivity/infosystems/Archie.2.18.s.tar.gz#/Archie/ArchieDaemon.subproj/vlink_io.c

This is vlink_io.c in view mode; [Download] [Up]

#include "archied.h"

#define CHECK_IO(x)\
	if( x < 0 )\
	{\
		perror("Error: I/O failed on tcp socket");\
		exit(1);\
	}

#define CHECK_BSIZE\
	if( buffer_pos >= buffer_size )\
	{\
		fprintf(stderr, "Error: I/O buffer underflow\n");\
		exit(1);\
	}

/* The buffer into which the records are saved when reading or
	writing to the TCP socket */
static char *tcp_io_buffer = NULL;
static int buffer_pos = 0, buffer_size = 0;

int init_buffer_from_stream(int stream)
{
char bsize[sizeof(int)+1];
int bytes_read, length, position;

	/* First read the amount of data to be buffered */
	length = sizeof(int);
	bytes_read = read(stream, bsize, length);
	while( bytes_read != length )
	{
		length -= bytes_read;
		position = bytes_read;
		bytes_read = read(stream, &bsize[position], length);
	}
	buffer_size = *( (int *) bsize );
D(fprintf(stderr, "init_buffer_from_stream: bsize = %d\n", buffer_size));
	if( buffer_size < 0 )
	{
		fprintf(stderr, "Invalid buffer size read from request stream\n");
		exit(1);
	}
	else if( buffer_size == 0 )
		return -1;

	/* Initialize the buffer */
	if( tcp_io_buffer != NULL )
		free(tcp_io_buffer);
	tcp_io_buffer = (char *) malloc(buffer_size);
	if( tcp_io_buffer == NULL )
	{
		perror("Error: failed to malloc() I/O buffer");
		exit(1);
	}
	buffer_pos = 0;
	return 0;
}

void check_bsize(int length)
{
	if( buffer_pos + length >= buffer_size )
	{	/* Double the buffer size */
		buffer_size *= 2;
		tcp_io_buffer = (char *) realloc(tcp_io_buffer, buffer_size);
		if( tcp_io_buffer == NULL )
		{
			perror("Error realloc()ing I/O buffer");
			exit(1);
		}
	}
}

void buffer_string(char *string)
{
int length;

	length = strlen(string);
	check_bsize(length);

	strcpy(&tcp_io_buffer[buffer_pos], string);
	buffer_pos += length;
	tcp_io_buffer[buffer_pos ++] = NIL;
D(fprintf(stderr, "buffer_string: string = %s; bp = %d\n", string, buffer_pos));
}

void buffer_char(char c)
{
int length;

	length = 1;
	check_bsize(length);
	tcp_io_buffer[buffer_pos] = c;
	buffer_pos ++;
D(fprintf(stderr, "buffer_char: c = %d; bp = %d\n", c, buffer_pos));
}

void buffer_int(int i)
{
int length;

	length = sizeof(int);
	check_bsize(length);
	*( (int *) &tcp_io_buffer[buffer_pos] ) = i;
	buffer_pos += sizeof(int);
D(fprintf(stderr, "buffer_intr: i = %d; bp = %d\n", i, buffer_pos));
}

void write_record(int request_socket)
{
int bytes_wrote, length, position;

	/* Start with the buffer length so the client knows how much data to read */
	write(request_socket, &buffer_pos, sizeof(int));
	/* Write out the buffered record */
	length = buffer_pos;
	position = 0;
	while( length > 0 )
	{
		bytes_wrote = write(request_socket, &tcp_io_buffer[position], length);
		CHECK_IO( bytes_wrote )
		length -= bytes_wrote;
		position += bytes_wrote;
	}
D(fprintf(stderr, "write_record: record size = %d\n", buffer_pos));
}

void read_record(int request_socket)
{
int bytes_read, length, position;

	/* Read the record into the I/O buffer */
	length = buffer_size;
	position = 0;
	while( length > 0 )
	{
		bytes_read = read(request_socket, &tcp_io_buffer[position], length);
		CHECK_IO( bytes_read )
		length -= bytes_read;
		position += bytes_read;
	}
D(fprintf(stderr, "read_record: record size = %d\n", position));
}

void unbuffer_string(char **string)
{
char *next_string;
int length;

	CHECK_BSIZE
	next_string = &tcp_io_buffer[buffer_pos];
	length = strlen(next_string);
	*string = (char *) malloc(length + 1);
	if( *string == NULL )
	{
		perror("Error: failed to alloc() memory for string");
		exit(1);
	}
	strcpy(*string, next_string);
	buffer_pos += (length + 1);
}

void unbuffer_char(char *c)
{
	CHECK_BSIZE
	*c = tcp_io_buffer[buffer_pos];
	buffer_pos ++;
}

void unbuffer_int(int *i)
{
	CHECK_BSIZE
	*i = *( (int *) &tcp_io_buffer[buffer_pos] );
	buffer_pos += sizeof(int);
}

void archive_vlink(VLINK vlink, int request_socket)
{
int bytes_wrote, length, position;
PATTRIB info;

	/* Initialize the buffer */
	if( tcp_io_buffer == NULL )
	{
		buffer_size = 1024;
		tcp_io_buffer = (char *) malloc(buffer_size);
		if( tcp_io_buffer == NULL )
		{
			perror("Error: failed to malloc() I/O buffer");
			exit(1);
		}
	}
	buffer_pos = 0;

	/* Save the record list in the buffer */
	while( vlink != NULL )
	{
		/* Name */
		buffer_string(vlink->name);
		free(vlink->name);
		/* Filename */
		buffer_string(vlink->filename);
		free(vlink->filename);
		/* Hostname */
		buffer_string(vlink->host);
		free(vlink->host);
		/* File type */
		buffer_string(vlink->type);
		free(vlink->type);

		/* File attributes */
		info = vlink->lattrib;
		while( info != NULL )
		{
			buffer_string(info->aname);
			buffer_string(info->value.ascii);
			free(info->aname);
			free(info->value.ascii);
			info = info->next;
			if( info != NULL && info->previous != NULL )
				free(info->previous);
		}

		/* End of VLINK marker */
		buffer_string("VLINK_END");

		/* Next record */
		vlink = vlink->next;
		if( vlink != NULL && vlink->previous != NULL )
			free(vlink->previous);
	}

	/* Write the buffer to the tcp stream */
	write_record(request_socket);
} /* End archive_vlink() */

VLINK unarchive_vlink(int request_socket)
{
VLINK vlink_head, vlink, next_vlink;
PATTRIB info, next_info;

/* Read the VLINK response from the tcp stream into the I/O buffer */
	if( init_buffer_from_stream(request_socket) < 0 )
		return NULL;

	/* Read the record from the tcp stream */
	read_record(request_socket);

	/* Read the record from the buffer */
	vlink = (VLINK) malloc(sizeof(VLINK_ST));
	vlink_head = vlink;
	while( buffer_pos < buffer_size )
	{
		/* Name */
		unbuffer_string(&vlink->name);
		/* Filename */
		unbuffer_string(&vlink->filename);
		/* Hostname */
		unbuffer_string(&vlink->host);
		/* File type */
		unbuffer_string(&vlink->type);

		/* File attributes */
		info = (PATTRIB) malloc(sizeof(PATTRIB_ST));
		vlink->lattrib = info;
		while( 1 )
		{
		char *attr_name;
			unbuffer_string(&attr_name);
			if( strcmp("VLINK_END", attr_name) == 0 )
				break;
			info->aname = attr_name;
			unbuffer_string(&info->value.ascii);
			next_info = (PATTRIB) malloc(sizeof(PATTRIB_ST));
			next_info->next = NULL;
			next_info->previous = info;
			info->next = next_info;
			info = next_info;
		}
		/* Free last element in the list */
		next_info = info->previous;
		free( next_info->next );
		next_info->next = NULL;

		/* Next record */
		if( buffer_pos < buffer_size )
		{
			next_vlink = (VLINK) malloc(sizeof(VLINK_ST));
			next_vlink->next = NULL;
			next_vlink->previous = vlink;
			vlink->next = next_vlink;
			vlink = next_vlink;
		}
	}

	return vlink_head;
} /* End unarchive_vlink() */

int write_request(QueryRequestPtr query, int request_socket)
{
	/* Initialize the buffer */
	if( tcp_io_buffer == NULL )
	{
		buffer_size = 1024;
		tcp_io_buffer = (char *) malloc(buffer_size);
		if( tcp_io_buffer == NULL )
		{
			perror("Error: failed to malloc() I/O buffer");
			exit(1);
		}
	}
	buffer_pos = 0;

	/* Save the record list to the buffer */
	buffer_string(query->host);
	buffer_string(query->qstring);
	buffer_int(query->max_hits);
	buffer_char(query->query);
	buffer_int(query->flags);

	/* Write the buffer to the tcp stream */
	write_record(request_socket);
} /* End write_request() */

int read_request(QueryRequestPtr query, int request_socket)
{
int bytes_read, length, position;

	if( init_buffer_from_stream(request_socket) < 0 )
		return -1;

	/* Read the record from the socket */
	read_record(request_socket);

	/* Read the record from the buffer */
	unbuffer_string(&query->host);
	unbuffer_string(&query->qstring);
	unbuffer_int(&query->max_hits);
	unbuffer_char(&query->query);
	unbuffer_int(&query->flags);

	return 0;
} /* End read_request() */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.