home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 10
/
Fresh_Fish_10_2352.bin
/
new
/
dev
/
obero
/
oberon
/
projectoberonsrc
/
mailserver.mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1994-10-18
|
13KB
|
362 lines
Syntax10.Scn.Fnt
MODULE MailServer; (*NW 17.4.89 / 10.2.94*)
IMPORT SYSTEM, Core, Files, Texts, Oberon;
VAR W: Texts.Writer;
handler: Oberon.Task;
myadr: ARRAY 16 OF CHAR;
PROCEDURE Dispatch(F: Files.File; rno, sno, hdlen: INTEGER; bdypos: LONGINT;
VAR orig, head: ARRAY OF CHAR);
(*insert external message (from msg) in recipient rno's mail file*)
VAR i, j, k, h: INTEGER;
ch: CHAR; ok: BOOLEAN;
pos, L, bdylen, tm, dt: LONGINT;
fname: Core.Name;
MF: Files.File; (*destination*)
R, Q: Files.Rider;
mrtab: Core.MResTab;
mdir: Core.MailDir;
BEGIN Core.GetFileName(rno, fname); MF := Files.Old(fname);
IF MF # NIL THEN
Files.Set(Q, MF, 0); Files.ReadBytes(Q, mrtab, 32);
Files.ReadBytes(Q, mdir, SIZE(Core.MailDir))
ELSE (*create new mailbox file*)
MF := Files.New(fname); Files.Set(Q, MF, 0); Files.Register(MF);
mdir[0].next := 0; mrtab[0] := {4 .. 31}; i := 1;
REPEAT mrtab[i] := {0 .. 31}; INC(i) UNTIL i = 7;
mrtab[7] := {0 .. 29}; i := 0;
REPEAT mdir[i].len := 0; INC(i) UNTIL i = 31
END ;
Files.Set(R, F, bdypos);
IF bdypos > 0 THEN (*find length of body*)
Files.ReadInt(R, k); Files.ReadLInt(R, bdylen)
ELSE bdylen := Files.Length(F)
END ;
ok := FALSE; i := 0;
REPEAT INC(i) UNTIL (i = 31) OR (mdir[i].len = 0);
IF i < 31 THEN (*free slot found, now find free blocks in file*)
j := -1;
REPEAT INC(j);
IF j MOD 32 IN mrtab[j DIV 32] THEN
h := j; k := SHORT((bdylen + hdlen + 255) DIV 256) + j;
LOOP INC(h);
IF h = k THEN ok := TRUE; EXIT END ;
IF (h = 256) OR ~(h MOD 32 IN mrtab[h DIV 32]) THEN j := h; EXIT END
END
END
UNTIL ok OR (j >= 255)
END ;
IF ok THEN (*insert msg in blocks j .. k-1*)
pos := LONG(j) * 256; mdir[i].pos := j;
REPEAT EXCL(mrtab[j DIV 32], j MOD 32); INC(j) UNTIL j = k;
mdir[i].len := bdylen + hdlen;
Oberon.GetClock(tm, dt);
mdir[i].time := SHORT(tm DIV 2); mdir[i].date := SHORT(dt);
j := 0;
WHILE (j < 19) & (orig[j] > " ") DO mdir[i].originator[j] := orig[j]; INC(j) END ;
mdir[i].originator[j] := 0X;
mdir[i].next := mdir[0].next; mdir[0].next := i;
Files.Set(Q, MF, 0); Files.WriteBytes(Q, mrtab, 32);
Files.WriteBytes(Q, mdir, SIZE(Core.MailDir)); Files.Set(Q, MF, pos);
j := 0;
WHILE j < hdlen DO Files.Write(Q, SYSTEM.ROT(head[j], 5)); INC(j) END ;
L := bdylen;
WHILE L > 0 DO Files.Read(R, ch); Files.Write(Q, SYSTEM.ROT(ch, 5)); DEC(L) END ;
L := (-Files.Pos(Q)) MOD 256;
WHILE L > 0 DO Files.Write(Q, 0); DEC(L) END ;
Files.Close(MF)
ELSIF (rno # sno) & (sno > 0) & (rno > 0) THEN (*return to sender*)
Dispatch(F, sno, sno, hdlen, bdypos, orig, head)
ELSIF (rno # 0) & (sno # 0) THEN (*send to postmaster*)
Dispatch(F, 0, sno, hdlen, bdypos, orig, head)
END
END Dispatch;
PROCEDURE Encode(F0: Files.File; textpos: LONGINT;
VAR orig: Core.LongName; VAR recip, subj: ARRAY OF CHAR);
(*CX-400 encode message F0 and insert it in export queue*)
VAR ch: CHAR;
i, j: INTEGER;
tm, dt, p0, p1: LONGINT;
R, Q: Files.Rider; F1: Files.File;
PROCEDURE WC(n: LONGINT);
BEGIN Files.Write(Q, CHR(n))
END WC;
PROCEDURE WI(n: INTEGER);
BEGIN Files.WriteBytes(Q, n, 2)
END WI;
PROCEDURE WL(n: LONGINT);
BEGIN Files.WriteBytes(Q, n, 4)
END WL;
BEGIN F1 := Files.New(""); Files.Set(Q, F1, 0);
WI(4000H); WL(0); (*MSG*)
WI(5000H); WL(0); (*ENV*)
WI(1010H); WI(6); (*MSGID*)
Oberon.GetClock(tm, dt); p0 := tm*dt; i := 0;
REPEAT WC(p0 MOD 10H + 41H); p0 := p0 DIV 10H; INC(i) UNTIL i = 6;
i := 0;
WHILE orig[i] > 0X DO INC(i) END ;
WI(1020H); WI(i+27); (*ORIG*)
WI(2011H); WI(2020H); WI(2030H); WI(2041H); WI(3030H); WI(i+15);
j := 0;
WHILE j < i DO Files.Write(Q, orig[j]); INC(j) END ;
j := 0;
REPEAT Files.Write(Q, myadr[j]); INC(j) UNTIL j = 15;
i := 0;
LOOP (*recipients*) j := i;
WHILE recip[j] > 1X DO INC(j) END ;
IF i = j THEN EXIT END ;
WI(1031H); WI(j-i+12); (*RECIP*)
WI(ORD(recip[j])+2010H); WI(2020H); WI(2030H); WI(2041H); WI(3030H); WI(j-i);
WHILE i < j DO Files.Write(Q, recip[i]); INC(i) END ;
INC(i)
END ;
i := 0; j := 0;
WHILE subj[j] > 0X DO INC(j) END ;
WI(1060H); WI(j); (*SUBJ*)
WHILE i < j DO Files.Write(Q, subj[i]); INC(i) END ;
WI(1090H); WI(6); (*SUBM*)
WC(dt DIV 200H); WC(dt DIV 20H MOD 10H); WC(dt MOD 20H);
WC(tm DIV 1000H); WC(tm DIV 40H MOD 40H); WC(tm MOD 40H);
p0 := Files.Pos(Q);
WI(6020H); WL(Files.Length(F0) - textpos); (*TEXT*)
Files.Set(R, F0, textpos); Files.Read(R, ch);
WHILE ~R.eof DO
IF ch >= 7FX THEN
IF ch = "
" THEN ch := "a"
ELSIF ch = "
" THEN ch := "o"
ELSIF ch = "
" THEN ch := "u"
ELSIF ch = "
" THEN ch := "A"
ELSIF ch = "
" THEN ch := "O"
ELSIF ch = "
" THEN ch := "U"
ELSE ch := "?"
END
END ;
Files.Write(Q, ch); Files.Read(R, ch)
END ;
p1 := Files.Pos(Q); Files.Set(Q, F1, 2);
WL(p1-6); WI(5000H); WL(p0-12); (*fixup*)
Files.Close(F1);
Core.InsertTask(Core.LineQueue, F1, Oberon.User, -1);
Texts.Append(Oberon.Log, W.buf)
END Encode;
PROCEDURE Decode(F: Files.File; pos: LONGINT);
(*CX-400 decode message from mail rider MR and dispatch*)
CONST bufsize = 96; msgsize = 2048;
VAR i, x, len, mx, rx, rno: INTEGER;
list, broadcast: BOOLEAN; ch, mo, yr: CHAR;
length: LONGINT;
R: Files.Rider;
rtab: ARRAY 32 OF INTEGER; (*table of recipients*)
buf, orig: ARRAY bufsize OF CHAR;
msg: ARRAY msgsize OF CHAR; (*message header*)
PROCEDURE put(ch: CHAR);
BEGIN
IF mx < msgsize THEN msg[mx] := ch; INC(mx) END
END put;
PROCEDURE PutString(s: ARRAY OF CHAR);
VAR i: INTEGER; ch: CHAR;
BEGIN i := 0;
REPEAT ch := s[i]; INC(i); put(ch)
UNTIL ch <= " "
END PutString;
PROCEDURE PutInt(n: INTEGER);
BEGIN put(CHR(n DIV 10 + 30H)); put(CHR(n MOD 10 + 30H))
END PutInt;
PROCEDURE ReadORName(len: INTEGER; VAR buf: ARRAY OF CHAR; title: ARRAY OF CHAR);
VAR x, i, L: INTEGER; ch: CHAR;
BEGIN Files.ReadInt(R, x); list := x = 2011H;
Files.ReadInt(R, x); Files.ReadInt(R, x);
Files.ReadInt(R, x); Files.ReadInt(R, L);
Files.ReadInt(R, L); i := 0;
IF x = 2041H THEN
PutString(title);
WHILE i < L DO
Files.Read(R, ch);
IF i < bufsize THEN buf[i] := ch END ;
INC(i); put(ch)
END ;
put(0DX)
ELSE
WHILE i < L DO
Files.Read(R, ch);
IF i < bufsize THEN buf[i] := ch END ;
INC(i)
END ;
END ;
IF i >= bufsize THEN i := bufsize-1 END ;
buf[i] := 0X; DEC(len, L+12);
WHILE len > 0 DO Files.Read(R, ch); DEC(len) END
END ReadORName;
BEGIN Files.Set(R, F, pos); Files.ReadInt(R, x);
Files.ReadLInt(R, length); INC(pos, length+6);
IF x = 5000H THEN (*ENV*)
mx := 0; rx := 0; broadcast := FALSE;
IF length > 40000 THEN length := 40000 END ;
LOOP
IF Files.Pos(R) >= pos THEN EXIT END ;
Files.ReadInt(R, x); Files.ReadInt(R, len);
IF x = 1020H THEN (*ORIG*)
ReadORName(len, orig, "From: ")
ELSIF x DIV 10H = 103H THEN (*RECIP*)
ReadORName(len, buf, "To: ");
IF buf = "all@cs.inf.ethz.ch" THEN broadcast := TRUE
ELSIF list THEN
rno := Core.UserNum(buf);
IF rno >= 0 THEN rtab[rx] := rno; INC(rx) END
END
ELSIF x DIV 10H = 106H THEN (*SUBJ, TITLE*)
PutString("Re: "); i := 0;
WHILE i < len DO Files.Read(R, ch); put(ch); INC(i) END ;
put(0DX)
ELSIF x = 1090H THEN (*SUBMI*)
PutString("Submission: ");
Files.Read(R, yr); Files.Read(R, mo); Files.Read(R, ch);
PutInt(ORD(ch)); put("."); PutInt(ORD(mo)); put(".");
PutInt(ORD(yr)); put(" ");
Files.Read(R, ch); PutInt(ORD(ch)); put(":");
Files.Read(R, ch); PutInt(ORD(ch)); put(":");
Files.Read(R, ch); PutInt(ORD(ch)); put(0DX)
ELSE Files.Set(R, F, Files.Pos(R) + len) (*skip*)
END
END ;
IF broadcast THEN (*broadcast*)
i := 1; rno := Core.NofUsers();
WHILE i < rno DO Dispatch(F, i, 0, mx, pos, orig, msg); INC(i) END
ELSIF rx = 0 THEN (*no valid recipient*) Dispatch(F, 0, -1, mx, pos, orig, msg)
ELSE i := 0;
REPEAT x := rtab[i]; INC(i); Dispatch(F, x, -1, mx, pos, orig, msg) UNTIL i = rx
END
END
END Decode