Copyright (C) 1994, Digital Equipment Corp. UNSAFE MODULE-- send and receiving stuff, assume BYTESIZE(CHAR) = byte --; IMPORT Atom, AtomList, Ctypes, FilePosix, FileRd, FileWr, M3toC, OSError, OSErrorPosix, Rd, RTMisc, Text, Thread, Usocket, Wr; REVEAL T = Public BRANDED OBJECT rd: Rd.T; wr: Wr.T; OVERRIDES init := Init; close := Close; END; PROCEDURE Jv Init (t: T; pipeName: TEXT): T RAISES {OSError.E} = (* open Unix domain connection to server. *) VAR unaddr: Usocket.struct_sockaddr_un; fd : INTEGER; strlen := Text.Length(pipeName); BEGIN unaddr.sun_family := Usocket.AF_UNIX; WITH string = M3toC.TtoS(pipeName) DO RTMisc.Copy( string, ADR(unaddr.sun_path[0]), strlen + 1 (* +1 for '\0' *)); END; fd := Usocket.socket(Usocket.AF_UNIX, Usocket.SOCK_STREAM, 0); IF fd < 0 THEN OSErrorPosix.Raise(); END; WITH addr = LOOPHOLE(ADR(unaddr), UNTRACED REF Usocket.struct_sockaddr), addrlen = BYTESIZE(unaddr.sun_family) + strlen DO IF Usocket.connect(fd, addr, addrlen) < 0 THEN OSErrorPosix.Raise(); END; END; WITH file = FilePosix.NewPipe(fd, FilePosix.ReadWrite) DO t.rd := NEW(FileRd.T).init(file); t.wr := NEW(FileWr.T).init(file, FALSE); END; RETURN t; END Init; PROCEDUREClose (t: T) = BEGIN TRY Wr.Close(t.wr); Rd.Close(t.rd); EXCEPT | Thread.Alerted, Wr.Failure, Rd.Failure => (* skip *) END; END Close;
TYPE LongArrayPtr = UNTRACED REF ARRAY [0 .. ((LAST(CARDINAL) DIV BITSIZE(CHAR)) - 1)] OF CHAR;
hack to get around type system. The horrible formula for the length of the array gives the longest possible array
PROCEDURESend (t: T; buf: ADDRESS; nbytes: CARDINAL) RAISES {OSError.E, Thread.Alerted} = BEGIN TRY WITH chars = LOOPHOLE(buf, LongArrayPtr) DO Wr.PutString(t.wr, SUBARRAY(chars^, 0, nbytes)); END; Wr.Flush(t.wr); EXCEPT | Wr.Failure (e) => RAISE OSError.E(AtomList.Cons(Atom.FromText("Write"), e)); END; END Send; PROCEDURERecv (t: T; buf: ADDRESS; nbytes: CARDINAL) RAISES {OSError.E, Thread.Alerted} = VAR nchars: CARDINAL; BEGIN TRY WITH chars = LOOPHOLE(buf, LongArrayPtr) DO nchars := Rd.GetSub(t.rd, SUBARRAY(chars^, 0, nbytes)); END; IF nchars < nbytes THEN RAISE OSError.E(AtomList.List2(ServerFailure, Atom.FromText("Read"))); END; EXCEPT | Rd.Failure (e) => RAISE OSError.E(AtomList.Cons(Atom.FromText("Read"), e)); END; END Recv; BEGIN <* ASSERT BYTESIZE(CHAR) = BYTESIZE(Ctypes.char) *> (* dumb consistency check *) ServerFailure := Atom.FromText("Jv ServerFailure"); END Jv.