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); }