ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/lib/msgio.b/
implement Msgio;
# probably need Authio or Auth instead, to include Authinfo, Certificate and signing operations?
# eliminates certificates and sigalgs from Keyring
# might be better just to have mp.m and sec.m?
# general signature module?
# Keyring->dhparams is is only needed by createsignerkey (and others creating Authinfo)
# should also improve pkcs
include "sys.m";
sys: Sys;
include "keyring.m";
include "msgio.m";
init()
{
sys = load Sys Sys->PATH;
}
seterr(r: int)
{
if(r > 0)
sys->werrstr("input or format error");
else if(r == 0)
sys->werrstr("hungup");
}
#
# i/o on a channel that might or might not retain record boundaries
#
getmsg(fd: ref Sys->FD): array of byte
{
num := array[5] of byte;
r := sys->readn(fd, num, len num);
if(r != len num) {
seterr(r);
return nil;
}
h := string num;
if(h[0] == '!')
m := int h[1:];
else
m = int h;
if(m < 0 || m > Maxmsg) {
seterr(1);
return nil;
}
buf := array[m] of byte;
r = sys->readn(fd, buf, m);
if(r != m){
seterr(r);
return nil;
}
if(h[0] == '!'){
sys->werrstr(string buf);
return nil;
}
return buf;
}
sendmsg(fd: ref Sys->FD, buf: array of byte, n: int): int
{
if(sys->fprint(fd, "%4.4d\n", n) < 0)
return -1;
return sys->write(fd, buf, n);
}
senderrmsg(fd: ref Sys->FD, s: string): int
{
buf := array of byte s;
if(sys->fprint(fd, "!%3.3d\n", len buf) < 0)
return -1;
if(sys->write(fd, buf, len buf) <= 0)
return -1;
return 0;
}
#
# i/o on a delimited channel
#
getbuf(fd: ref Sys->FD, buf: array of byte, n: int): (int, string)
{
n = sys->read(fd, buf, n);
if(n <= 0){
seterr(n);
return (-1, sys->sprint("%r"));
}
if(buf[0] == byte 0)
return (n, nil);
if(buf[0] != byte 16rFF){
# garbled, possibly the wrong encryption
return (-1, "failure");
}
# error string
if(--n < 1)
return (-1, "unknown");
return (-1, string buf[1:]);
}
getbytearray(fd: ref Sys->FD): (array of byte, string)
{
buf := array[Maxmsg] of byte;
(n, err) := getbuf(fd, buf, len buf);
if(n < 0)
return (nil, err);
return (buf[1: n], nil);
}
getstring(fd: ref Sys->FD): (string, string)
{
(a, err) := getbytearray(fd);
if(a != nil)
return (string a, err);
return (nil, err);
}
putbuf(fd: ref Sys->FD, data: array of byte, n: int): int
{
buf := array[Maxmsg] of byte;
if(n < 0) {
buf[0] = byte 16rFF;
n = -n;
}else
buf[0] = byte 0;
if(n >= Maxmsg)
n = Maxmsg-1;
buf[1:] = data;
return sys->write(fd, buf, n+1);
}
putstring(fd: ref Sys->FD, s: string): int
{
a := array of byte s;
return putbuf(fd, a, len a);
}
putbytearray(fd: ref Sys->FD, a: array of byte, n: int): int
{
if(n > len a)
n = len a;
return putbuf(fd, a, n);
}
puterror(fd: ref Sys->FD, s: string): int
{
if(s == nil)
s = "unknown";
a := array of byte s;
return putbuf(fd, a, -len a);
}