home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
me34src.zip
/
me3
/
comserver
/
movedata.c
< prev
Wrap
C/C++ Source or Header
|
1995-01-14
|
7KB
|
282 lines
/* movedata.c : move data between clients and servers.
*/
/* Craig Durland Public Domain
* Distributed "as is", without warranties of any kind, but comments,
* suggestions and bug reports are welcome.
*/
/* ******************************************************************** */
/* **************************** move data ***************************** */
/* ******************************************************************** */
#ifdef __STDC__
#ifdef __hpux /* for ANSI C on HP-UX */
#define _HPUX_SOURCE
#endif /* __hpux */
#endif /* __STDC__ */
#include <stdio.h>
#include <const.h>
#include "comserver.h"
#include <errno.h>
#ifdef __STDC__
#include <stdarg.h>
#define VA_START va_start
#else /* __STDC__ */
#include <varargs.h>
#define VA_START(a,b) va_start(a)
#endif
/* Packet format:
* <magic number><packet length><packet type><bytes>
* offset: 0 1 2 3
*/
/*VARARGS3*/
#ifdef __STDC__
int CSbuild_packet(CSPacket *packet, int packet_type, char *format, ...)
#else
int CSbuild_packet(packet, packet_type, format, va_alist)
CSPacket *packet; int packet_type; char *format; va_dcl
#endif
{
char c, *ptr, *pak_ptr, *buf;
int n, size;
va_list ap;
VA_START(ap,format);
buf = packet->buf;
buf[0] = CS_MAGIC;
pak_ptr = buf + 2;
*pak_ptr++ = (char)packet_type;
size = 1; /* type */
while (c = *format++)
{
switch (c)
{
case 'n': /* number: sizeof(int) bytes */
n = va_arg(ap,int);
memcpy(pak_ptr, (char *)&n, sizeof(int));
pak_ptr += sizeof(int); size += sizeof(int);
break;
case 's': /* string: <text><trailing \0> */
ptr = va_arg(ap,char *);
strcpy(pak_ptr, ptr);
n = strlen(ptr);
pak_ptr += (n + 1); size += (n + 1);
break;
}
}
buf[1] = (char)size;
packet->size = size + 2; /* magic # and len */
packet->start = 0;
va_end(ap);
return TRUE;
}
/*VARARGS2*/
#ifdef __STDC__
static void dig_out(CSPacket *packet, char *format, ...)
#else
static void dig_out(packet, format, va_alist)
CSPacket *packet; char *format; va_dcl
#endif
{
char c, *buf;
int n, *xp;
va_list ap;
VA_START(ap,format);
buf = &packet->buf[packet->start];
n = 0;
while (c = *format++)
{
switch (c)
{
case 'b': /* byte: 1 byte int */
xp = va_arg(ap,int *);
*xp = (int)buf[0];
buf += 1; n += 1;
break;
case 'n': /* number: sizeof(int) bytes */
xp = va_arg(ap,int *);
memcpy(xp, buf, sizeof(int));
buf += sizeof(int); n += sizeof(int);
break;
case 's': /* string: <text><trailing \0> */
{
char **ptr;
ptr = va_arg(ap,char **);
*ptr = buf;
/* string is last thing in a packet, don't need to inc pak_ptr */
break;
}
}
}
packet->start += n;
va_end(ap);
}
/*
* Returns:
* -1 : error
* 0 : couldn't write all of packet
* 1 : wrote all of packet
* 2 : didn't write anything
* Notes:
* The compute server sets the socket to be nonblocking but most
* clients expect it to block. I think this will work in both cases
* but since writes to the server should always suceed, I don't
* think I have to worry about it.
* The packet better have a nonzero size. This is to make O_NDELAY
* work. I like O_NONBLOCK lots better.
*/
CSwrite_packet(packet, fd) CSPacket *packet; int fd;
{
int n, size;
char *ptr;
size = packet->size;
ptr = &packet->buf[packet->start];
n = write(fd, ptr, size);
if (n == -1)
if (errno == EAGAIN || errno == EINTR) return 2;
else { perror("write_packet "); return -1; }
if (n == 0) return 2; /* O_NDELAY hack */
packet->size -= n;
if (n == size) return 1;
/* didn't write all of the packet */
packet->start += n;
return 0;
}
/* My own blocking read.
* read() may not read all requested bytes if:
* Get an interrupt the blocking read may not complete.
* Nonblocking is turned on.
*/
static int force_read(fd, buf, z) char *buf;
{
int n;
while (TRUE)
{
n = read(fd, buf, z);
if (n == z) return TRUE;
if (n == -1)
{
if (errno == EINTR) continue; /* interrupted system call */
return FALSE;
}
if (n == 0) return FALSE;
/* sleep(1); /*!!!!???? */
z -= n; buf += n;
}
}
int CSread_packet(packet, fd, pak) CSPacket *packet; int fd; xPacket *pak;
{
char buf[10];
int size;
/* read the magic number and packet length */
#if 0
n = read(fd, buf, 2);
if (n == -1) { perror("read_packet magic"); return FALSE; }
if (n != 2) { printf("read_packet didn't read all of header: %d\n", n); return FALSE; }
if (buf[0] != CS_MAGIC)
{ printf("CSread_packet: protocal error.\n"); return FALSE; }
size = ((unsigned char *)buf)[1];
n = read(fd, packet->buf, size); /* this better block */
if (n == -1) { perror("read_packet"); return FALSE; }
if (n != size) { printf("read_packet didn't read all data: %d %d\n", n,size); return FALSE; }
#else
if (!force_read(fd, buf, 2))
{ printf("read_packet failed on header\n"); return FALSE; }
if (buf[0] != CS_MAGIC)
{ printf("CSread_packet: protocal error.\n"); return FALSE; }
size = ((unsigned char *)buf)[1];
if (!force_read(fd, packet->buf, size))
{ printf("read_packet failed reading data\n"); return FALSE; }
#endif
packet->start = 0;
dig_out(packet, "b", &pak->type);
switch(pak->type)
{
default: /* invalid type */
return FALSE;
/********************** To Server ********************************/
case CS_DIR: /* (directory path) */
dig_out(packet, "s", &pak->u.Directory.dir);
break;
case CS_COMMAND: /* (command command-name) */
dig_out(packet, "s", &pak->u.Command.command);
break;
case CS_SIGNAL: /* (signal pid signal#) */
dig_out(packet, "nn", &pak->u.Signal.pid, &pak->u.Signal.sig);
break;
case CS_CREATE_PROCESS: /* (create-process two-pipe) */
dig_out(packet, "n", &pak->u.Process.two_pipe);
break;
case CS_DISCONNECT: /* (disconnect) */
case CS_DO_IT: /* (do-it) */
break;
/******************** To Client *********************************/
case CS_ERROR: /* (error pid error#) */
dig_out(packet, "nn", &pak->u.Error.pid, &pak->u.Error.error_code);
break;
case CS_PROCESS_ID:
dig_out(packet, "n", &pak->u.Pid.pid);
break;
case CS_PROCESS_DONE: /* pid, exit_code */
dig_out(packet, "nn",
&pak->u.ProcessDone.pid, &pak->u.ProcessDone.exit_code);
break;
case CS_OUTPUT: /* pid string */
case CS_OUTPUT_ERR: /* pid string */
dig_out(packet, "ns", &pak->u.Output.pid, &pak->u.Output.text);
break;
/******************** To Both *********************************/
case CS_CLIENT_MSG:
dig_out(packet, "ns", &pak->u.ClientMsg.tag, &pak->u.ClientMsg.msg);
pak->u.ClientMsg.dud = 0;
break;
}
return TRUE;
}