summaryrefslogtreecommitdiff
path: root/appl/lib
diff options
context:
space:
mode:
Diffstat (limited to 'appl/lib')
-rw-r--r--appl/lib/mkfile2
-rw-r--r--appl/lib/msgio.b152
2 files changed, 154 insertions, 0 deletions
diff --git a/appl/lib/mkfile b/appl/lib/mkfile
index 34062c42..67de72ac 100644
--- a/appl/lib/mkfile
+++ b/appl/lib/mkfile
@@ -71,6 +71,7 @@ TARG=\
login.dis\
man.dis\
mpeg.dis\
+ msgio.dis\
nametree.dis\
names.dis\
newns.dis\
@@ -237,3 +238,4 @@ lists.dis: $ROOT/module/lists.m
vac.dis: $ROOT/module/vac.m $ROOT/module/venti.m
dial.dis: $ROOT/module/dial.m
styxflush.dis: $ROOT/module/styxflush.m
+msgio.dis: $ROOT/module/msgio.m
diff --git a/appl/lib/msgio.b b/appl/lib/msgio.b
new file mode 100644
index 00000000..035b1783
--- /dev/null
+++ b/appl/lib/msgio.b
@@ -0,0 +1,152 @@
+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);
+}