{R+}
program ARKMAIL; {Copyright (c) 1989 Marc Newman
This program invokes the ARK Version .04 program to create ARKs of FIDO
mail via the submit mechanisim.  It calls itself as the last command
to process further .OUT files.  A .FLO file is created, and it
uses the POLL command to create a .OUT file
In addition, if a .FLO file is not found, all MO?,TU?,WE? etc files
are deleted.  If a .FLO file is found, it is checked to see if the
current filename is already waiting to go out, if so, the same file
is updated.  If not, it is added to (or a new .FLO created) and a
poll sent out.  This program MUST be run on the same drive/user as
the ybbaT MAIL.SYS file and all the .OUT files to be processed.
Include ARKMAIL as the command immediately before KSMAIL in your
outgoing batch file.  That way, any outgoing mail will be ARKed.

You MUST use ARK version .04, prior versions (.35) did not support
multiple drives.

You must provide a ROS.CLK insert which reads your clock and returns
a byte array consisting of:
 t[0] = seconds
 t[1] = minutes
 t[2] = hours
 t[3] = day
 t[4] = month
 t[5] = year
Note, these are integer values in BYTE format (0-255).  Year is 0-99

Marc K. Newman
The Black Box RCPM/DRBBS/ybbaT
713-480-2686 300/1200 Baud & FIDONET 1:106/601.0
Version 0.1 3/29/89

If you enjoy this program, use it and feel free to distribute it for
non-commercial use.  If you change it, I would appreciate it if you
retain this notice and give me credit for the portions of the program
I wrote.  If you want to use this program or portions thereof for
purposes, a $10/copy royalty for my trouble and work will be charged
Note, this includes use on CLUB BBSes, as they are considered businesses
be they for profit or non-profit.

Mail any royalty payments to:           Marc Newman
                                       14615 Stilesboro Court
                                       Houston, Texas 77062  }
type
    STR3 = string[3];
    STR4 = string[4];
    str8 = string[8];
    STR11 = STRING[11];
    STR16 = STRING[16];
    STR80 = STRING[80];
    byte256 = array[0..256] of byte;
    TAD_array = array[0..5] of BYTE;
const
    MAIN_DRIVE   : INTEGER = 0; {0=DRIVE A:}
    AUX_DRIVE    : INTEGER = 1; {1=DRIVE B:}
    Select_disk  : integer = $0E;
    Search_first : integer = $11;
    Search_next  : integer = $12;
    Set_DMA      : integer = $1A;
    HEX_array    : array[0..15] of CHAR =
                 ('0','1','2','3','4','5','6','7','8','9',
                 'A','B','C','D','E','F');
    VER          : STRING[3] = '0.1';
var
    OK,
    writenew,
    IN_FLO,
    found     : BOOLEAN;
    mail_sys     : byte256;
    mail_sys_file: file;
    i,
    ERROR,
    LOOP,
    START        : integer;
    MY_NET,
    MY_NODE,
    DEST_NET,
    DEST_NODE    : integer;
    SUB          : FILE;
    FLO          : FILE;
    FILENAME     : STR11;
    NEW_FILENAME : STR8;
    DELTA_NET    : STR4;
    DELTA_NODE   : STR4;
    STRING4      : STR4;
    STRING16     : STR16;
    STRING11     : STR11;
    STRING20     : STRING[20];
    STRING80     : STR80;
    TIME         : TAD_ARRAY;
    BYTE128      : ARRAY[0..128] OF BYTE;
    NEW_EXTENSION : STR3;

{$I ROS.CLK}

function weekday(month, date, year : integer) : integer;
{Zeller congruence to calculate any day of the week using
integer math.  From letter by Bob Whitefield, Decatur, AL
in the February, 1989 'Computer Language' magazine.}
var
    day : integer;
begin
    if month <= 2 then
    begin
         month := month + 12;
         year := year - 1
    end;

    Day := (date + month * 2 + (month + 1) * 6 div 10 + year +
        year div 4 - year div 100 + year div 400 + 2) mod 7;
    weekday := day
end; {Weekday}

FUNCTION HEX(x : integer) : STR4;
VAR
         Z : STR4;
begin
         Z := '    ';
         Z[4] := hex_array[LO(x) and $0F];
         Z[3] := hex_array[(LO(X) AND $F0) SHR 4];
         Z[2] := hex_array[HI(X) and $0f];
         Z[1] := hex_array[(HI(X) and $F0) SHR 4];
         HEX := COPY(Z,1,4);
end;

function inttoBCD(intg : integer) : byte;
var x,y : byte;
begin
   x := intg div 10;
   y := intg mod 10;
   inttoBCD := ((x and $0f) shl 4) + y;
end;

function DEC(X : STR4) : integer;
var
    a,y : integer;
    z : STR4;
begin
    a := 0;
    for i := 4 downto 1 do
    begin
         y := ord(x[i])-ord('0');
         if y > 9 then y := ord(x[i]) - ord('A') +10;
         a := a + (y shl ((4-i) * 4));
    end;
    dec := a;
end;

function max(i,j : integer) : integer;
begin
    if i > j then
       max := i
    else
       max := j;
end;

procedure submit(ST : STR80);
{Save command line to submit file record}
var
  len, I : byte;
  buffer : array[1..128] of byte;
begin
  writeln(st);
  bdos(select_disk,main_drive);
  if (length(st) = 0) or (st[1] = ';')
     or (st[1] = ' ') then exit;
  len := length(st);
  buffer[1] := len;
  for i := 1 to len do
      buffer[i+1] := ord(st[I]);
  buffer[len+2] := 0;
  buffer[len+3] := ord('$');
  for i := len+4 to 128 do
      buffer[i] := 0;
  blockwrite(sub, buffer,1);
end; {Submit}

procedure search_file(VAR in_file : str11;
                     var out_file : str11;
                     var found : boolean);
var
     DMA   : BYTE256;
     FCB   : ARRAY[0..25] OF BYTE ABSOLUTE $005C;
     i,
     START,
     error : integer;
begin
     error := BDos(set_dma,ADDR(DMA));
     FCB[0] := 0;
     for i := 1 to 11 do FCB[I] := ord(in_file[i]);
     error := BDos(SEARCH_FIRST,Addr(FCB));
     found := (error <> 255);
     out_file := '';
     start := error * 32;
     if found then
        for i := 1 to 11 do
            out_file := OUT_FILE + char(mem[addr(dma)+i+start]);
end;

function GET_EXTENSION(NET_NODE,FILENAME :STR8) : STR3;
const
    DAY : array[0..6] of string[2] =
        ('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
var
    i, code : integer;
    temp : string[20];
    file_id : FILE;
    TEXT_FILE : TEXT;
    OK,
    DAY_OK,
    FOUND : boolean;
    ext_day : string[2];
    extension : string[3];
    TEMP_FILE,
    filename_found : str11;
begin
    IN_FLO := FALSE;
    ext_day := day[weekday(time[4],time[3],time[5])];
    assign(file_id,char(main_drive+ord('A')) + ':' + NET_NODE+'.FLO');
    {$I-}
    reset(file_id);
    {$I+}
    ok := (ioresult = 0);
    if not OK then
    begin         {No .FLO file found, look for last extension}
         close(file_id);
         bdos(select_disk,aux_drive);
         TEMP_FILE := FILENAME+EXT_DAY+'?';
         search_file(TEMP_FILE,filename_found,FOUND);
         if FOUND then
         begin
              assign(file_id,char(aux_drive+ord('A'))+':'+
                             COPY(filename_found,1,8) +
                             '.' +
                             COPY(FILENAME_FOUND,9,3));
              erase(file_id);              {Erase last file}
              val(filename_found[11], i, code);
              i := (i + 1) mod 10;
              str(i:1, temp);
              get_extension := ext_day + temp
         end
         ELSE
         BEGIN
              {NO FILES FROM TODAY FOUND, SEE ABOUT YESTERDAY}
              get_extension := ext_day + '0';
         END;
         {SEE IF ANYTHING TO DELETE FROM PREVIOUS DAYS}
         REPEAT
               FOUND := FALSE;
               bdos(select_disk,aux_drive);
               TEMP_FILE := FILENAME+'???';
               SEARCH_FILE(TEMP_FILE,FILENAME_FOUND,FOUND);
               I := -1;
               DAY_OK := FALSE;
               REPEAT
                     I := I + 1;
                     IF COPY(FILENAME_FOUND,9,2) = DAY[I] THEN
                        DAY_OK := TRUE;
               UNTIL OK OR (I = 6);
               IF FOUND AND DAY_OK THEN
               BEGIN
                    ASSIGN(FILE_ID,CHAR(AUX_DRIVE+ORD('A'))+':'+
                           COPY(FILENAME_FOUND,1,8) + '.'+
                           COPY(FILENAME_FOUND,9,3));
                    ERASE(FILE_ID);
               END;
         UNTIL NOT FOUND;
    end
    else       {FOUND A .FLO FILE}
    begin
         close(file_id);
         assign(text_file,CHAR(MAIN_DRIVE+ORD('A')) +
               ':' + net_node+'.FLO');
         reset(text_file);
         temp := '';
         repeat
               readln(text_file,temp);
               WRITELN(TEMP);
         until eof(text_file) or
               ((copy(temp,3,8) = NET_NODE) and
                (copy(temp,12,2) = ext_day) and
                (temp[1] <> CHAR($7E)));
         close(text_file);
         extension := copy(temp,12,3);
         if copy(extension,1,2) <> ext_day then
         BEGIN
               get_extension := ext_day + '0';
               ASSIGN(FILE_ID,CHAR(AUX_DRIVE+ORD('A')) + ':' +
                      FILENAME + '.' + EXT_DAY + '0');
               {$I-}
               ERASE(FILE_ID);
               {$I+}
               OK := (IORESULT = 0);
         END
         else
         BEGIN
               IN_FLO := TRUE;
               get_extension := extension;
         END;
    END;
end;


begin
     WRITELN;
     WRITELN('ybbaT ARKMAIL Version ' + VER + ' (c) 1989 Marc Newman');
     WRITELN('The Black Box BBS (713)-480-2686 FIDO 1:106/601.0');
     WRITELN;
     assign(mail_sys_file,CHAR(MAIN_DRIVE+ORD('A'))+':'+'MAIL.SYS');
     RESET(MAIL_SYS_FILE);
     BLOCKREAD(MAIL_SYS_FILE,mail_sys,2);
     MY_NODE :=ord(MAIL_SYS[0]) + (256*ord(MAIL_SYS[1]));
     MY_NET := ord(MAIL_SYS[168])+(256*ord(MAIL_SYS[169]));
     close(mail_sys_file);
     STRING11 := '????????OUT';
     search_file(STRING11,filename,found);
     if found then
     begin
          assign(sub,CHAR(MAIN_DRIVE+ORD('A'))+':'+'$$$.SUB');
          {$I-}
          reset(sub);
          {$I+}
          OK := (IORESULT = 0);
          if OK then
              seek(sub,filesize(sub))
          else
              rewrite(sub);
          string80 := 'ARKMAIL';
          submit(STRING80);
          DEST_NET := DEC(copy(filename,1,4));
          DEST_NODE := DEC(copy(filename,5,8));
          DELTA_NET := HEX(MY_NET - DEST_NET);
          DELTA_NODE := HEX(MY_NODE - DEST_NODE);
          str(dest_net,string20);
          string20 := string20 + '/';
          str(dest_node,string11);
          string20 := string20 + string11;
          string80 := 'STATUS HOLD ' + STRING20;
          SUBMIT(STRING80);
          string80 := 'POLL ' + string20;
          submit(string80);
          GETTAD(TIME);
          NEW_FILENAME := HEX((TIME[4] shl 12) +
                      (inttobcd(TIME[3]) * 64) +
                      inttobcd(TIME[2])) +
                      HEX((inttobcd(TIME[1]) * 512) +
                      (inttobcd(TIME[0]) * 4));
          STRING80 := 'ERA '+NEW_FILENAME+'.PKT';
          SUBMIT(STRING80);
          new_extension := get_extension(filename,delta_net+delta_node);
          string80 := 'ARK -K ' + CHAR(ORD('A')+AUX_DRIVE) + ':' +
                   COPY(DELTA_NET,1,4) +
                   COPY(DELTA_NODE,1,4) + '.' +
                   new_extension + ' ' +
                   CHAR(ORD('A')+MAIN_DRIVE) + ':' +
                   copy(NEW_FILENAME,1,8)+'.PKT';
          submit(string80);
          string80 :='REN '+copy(new_filename,1,8)+'.PKT='+
                   copy(FILENAME,1,8)+'.OUT ';
          submit(string80);
          assign(FLO,CHAR(ORD('A')+MAIN_DRIVE) + ':' +
                     HEX(DEST_NET)+HEX(DEST_NODE)+'.FLO');
          {$I-}
          RESET(FLO);
          {$I+}
          OK := (IORESULT = 0);
          IF (NOT OK) THEN
          begin
               REWRITE(FLO);
               for i := 0 to 127 do BYTE128[i] := $1a;
               start := 0;
               WRITENEW := TRUE;
          end
          ELSE
          begin
               WRITENEW := FALSE;
               SEEK(FLO,MAX(FILESIZE(FLO)-1,0));
               BLOCKREAD(FLO,BYTE128,1);
               I := 0;
               REPEAT
                    START := I+1;
                    I := I + 1;
               UNTIL (BYTE128[I] = $1A) OR (I = 127);
               IF START = 127 THEN
               BEGIN
                    START := 0;
                    FOR I := 0 TO 127 DO BYTE128[I] := $1A;
                    WRITENEW := TRUE;
               END;
          end;
          STRING16 := CHAR(ORD('A') + AUX_DRIVE) + ':' +
                          COPY(DELTA_NET,1,4)+
                          COPY(DELTA_NODE,1,4)+ '.' +
                          new_extension+
                          CHR($0D) + CHR($0A);
          FOR I := 0 TO 15 DO BYTE128[START+I] := ORD(STRING16[I+1]);
          IF NOT WRITENEW THEN SEEK(FLO,MAX(FILESIZE(FLO)-1,0));
          IF NOT IN_FLO THEN BLOCKWRITE(FLO,BYTE128,1);
          CLOSE(FLO);
    CLOSE(SUB);
    end;
end.