home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / beehive / bbs / rosuncr.arc / ROSKMS.INC < prev    next >
Text File  |  1991-08-11  |  11KB  |  357 lines

  1. { ROSKMS.INC - Remote Operating System Kernel - Miscellaneous routines  }
  2.  
  3. { 09dec87 wb - access section file data from disk instead of heap to
  4.   reduce ram requirements.
  5.   07nov87 wb - Added exist function for new file find command.
  6.   11nov86 wb - Modified diskfree function & hide_release procedure for
  7.                use with Turbodos.  }
  8.  
  9. function trim(st: StrStd): StrStd;
  10. { Remove leading and trailing blanks }
  11.   var
  12.    i, j: integer;
  13.   begin
  14.     i := 1;
  15.     j := length(st);
  16.     while (st[i] = ' ') and (i <= j) do
  17.       i := succ(i);
  18.     while (st[j] = ' ') and (j >= i) do
  19.       j := pred(j);
  20.     trim := copy(st, i, succ(j - i))
  21.   end;
  22.  
  23. function exist(filen: FileName): boolean;
  24. { Return true if file exists }
  25.   var f: file;
  26.   begin
  27.     {$i-}
  28.     assign(f,filen);
  29.     reset(f);
  30.     {$i+}
  31.     if ioresult <> 0 then exist:=false
  32.     else exist:=true;
  33.   end;
  34.  
  35. procedure SetSect(Drive, User: integer);
  36. { Set to file section }
  37.   begin
  38.     BDOS(seldrive, Drive);
  39.     BDOS(getseluser, User)
  40.   end;
  41.  
  42. procedure FindSect(req: FileName; var Drive, User: integer; var found: boolean);
  43. { Find file section from requested name }
  44.   begin
  45.     reset(sect_file);
  46.     while ((req <> trim(SName)) or (SDrive = ' ')) and (not eof(sect_file)) do
  47.       readln(sect_file, SDrive, SUser, SAccs, SName, SDesc);
  48.     found := ((req = trim(SName)) and (cold or (user_rec.access >= SAccs)));
  49.     if found
  50.       then
  51.         begin
  52.           Drive := ord(SDrive)-ord('A');
  53.           User := SUser
  54.         end
  55.   end;
  56.  
  57. {
  58.   var
  59.     this: SectPtr;
  60.   begin
  61.     this := SectBase;
  62.     while (req <> this^.SectName) and (this <> nil) do
  63.       this := this^.next;
  64.     found := ((req = this^.SectName) and (cold or (user_rec.access >= this^.SectAccs)));
  65.     if found
  66.       then
  67.         begin
  68.           Drive := this^.SectDrive;
  69.           User := this^.SectUser
  70.         end
  71.   end;
  72. }
  73.  
  74. function diskfree: integer;
  75. { Compute amount of free disk space on current drive
  76.   with Turbodos get disk allocation T-function #19 }
  77.   var
  78.     blksiz,drive : byte;
  79.     size,freblks,i : integer;
  80.   begin
  81.     drive := bdos(25);  { get current drive with C-function #25 }
  82.     inline              { use Tdos call to get disk allocation }
  83.       ($0E/$13/         { ld c,19         ;c= get disk allocation T-function }
  84.        $3A/drive/       { ld a,drive      ;a= drive }
  85.        $5F/             { ld e,a          ;e= drive }
  86.        $CD/$50/00/      { call 50h        ;perform t-function }
  87.        $ED/$53/freblks/ { ld (freblks),de ;save free blocks }
  88.        $E6/$07/         { and 7           ;mask low 3 bits }
  89.        $32/blksiz);     { ld (blksiz),a   ;save block size }
  90.     size := freblks;
  91.     for i := 1 to blksiz-3 do  { 3=1k, 4=2k, 5=4k, etc.. }
  92.       size := size*2;
  93.     diskfree := size
  94.   end;
  95.  
  96. procedure hide_release(name: FileName; status: record_status);
  97. { Hide or release Turbodos file using BDOS set attributes funct #30 }
  98.   var
  99.     fcbadr,t2,i : integer;
  100.     temp_file: file;
  101.   begin
  102.     Assign(temp_file,name);
  103.     fcbadr := addr(temp_file)+12;     { i= addr of cp/m fcb }
  104.     t2 := fcbadr+10;                  { t2= addr of 2nd file type char }
  105.     if status = public
  106.       then mem[t2] := $7f and mem[t2] { turn $SYS bit off }
  107.       else mem[t2] := $80 or mem[t2]; { turn $SYS bit on }
  108.     if bdos(30,fcbadr) <> 0           { set file attributes }
  109.       then writeln(USR, name, ' not found.')
  110.   end;
  111.  
  112. function min(x, y: integer): integer;
  113. { Return minimum of two integers }
  114.   begin
  115.     if x < y
  116.       then min := x
  117.       else min := y
  118.   end;
  119.  
  120. function max(x, y: integer): integer;
  121. { Return greater of two integers }
  122.   begin
  123.     if x > y
  124.       then max := x
  125.       else max := y
  126.   end;
  127.  
  128.  
  129. function pad(st: StrStd; i: integer): StrStd;
  130. { Pad string with spaces to length of i }
  131.   begin
  132.     while length(st) < i do
  133.       st := st + ' ';
  134.     pad := st
  135.   end;
  136.  
  137. function intstr(n, w: integer): Str10;
  138. { Return a string value (width 'w')for the input integer ('n') }
  139.   var
  140.     st: Str10;
  141.   begin
  142.     str(n:w, st);
  143.     intstr := st
  144.   end;
  145.  
  146. function strint(st: Str10): integer;
  147. { Convert string to integer }
  148.   var
  149.     x, code: integer;
  150.   begin
  151.     if st[1] = '+'
  152.       then delete(st, 1, 1);
  153.     if st = ''
  154.       then code := 1
  155.       else val(st, x, code);
  156.     if code = 0
  157.       then strint := x
  158.       else strint := 0                      { Error, return with 0 }
  159.   end;
  160.  
  161. function zeller(day, month, year: integer): integer;
  162. { Compute the day of the week using Zeller's Congruence }
  163.   var
  164.     century: integer;
  165.   begin
  166.     if month > 2
  167.       then month := month - 2
  168.       else
  169.         begin
  170.           month := month + 10;
  171.           year := pred(year)
  172.         end;
  173.     century := year div 100;
  174.     year := year mod 100;
  175.     zeller := (day - 1 + ((13 * month - 1) div 5) + (5 * year div 4) +
  176.               century div 4 - 2 * century + 1) mod 7
  177.   end;
  178.  
  179. function FormTAD(t: tad_array): StrTAD;
  180. { Build printable string of current time and date }
  181.   const
  182.     day: array [0..6] of string[6] =
  183.       ('Sun','Mon','Tues','Wednes','Thurs','Fri','Satur');
  184.     month: array [1..12] of string[3] =
  185.       ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
  186.   var
  187.     i: integer;
  188.     line: StrTAD;
  189.   begin
  190.     if (t[1] in [0..59]) and (t[2] in [0..23])
  191.       then line := intstr(t[2], 2) + ':' + intstr(t[1], 2)
  192.       else line := '';
  193.     for i:= 1 to length(line) do
  194.       if line[i] = ' '
  195.         then line[i]:= '0';
  196.     if (t[3] in [1..31]) and (t[4] in [1..12]) and (t[5] in [0..99])
  197.       then FormTAD :=
  198.         line + '  ' +
  199.         day[zeller(t[3], t[4], 1900 + t[5])] + 'day  ' +
  200.         intstr(t[3], 2) + '-' + month[t[4]] + '-' + intstr(t[5], 2)
  201.       else FormTAD := 'No Date'
  202.   end;
  203.  
  204. procedure send_time(size: integer; var mm, ss: integer);
  205. { Compute the file transfer time }
  206.   var
  207.     tr_time: real;
  208.   begin
  209.     tr_time := size * 23.5 / rate;          { Factor is empirically derived  }
  210.     mm := trunc(tr_time);
  211.     ss := round(60.0 * frac(tr_time))
  212.   end;
  213.  
  214. procedure timer(var time_on, time_left: integer);
  215. { Compute the time on and the time remaining to the current user }
  216.   var
  217.     t: tad_array;
  218.   begin
  219.     GetTAD(t);
  220.     time_on := 60 * (t[2] - login_t[2]) + t[1] - login_t[1];
  221.     if time_on < 0
  222.       then time_on := time_on + 1440;
  223.     time_left := user_rec.limit + extra_time - time_on
  224.   end;
  225.  
  226. procedure log(activity: byte; text: FileName);
  227. { Update log file }
  228.   begin
  229.     seek(logr_file, FileSize(logr_file));
  230.     GetTAD(logr_rec.date);
  231.     logr_rec.action := activity;
  232.     logr_rec.user := user_loc;
  233.     logr_rec.text := text;
  234.     write(logr_file, logr_rec)
  235.   end;
  236.  
  237. procedure mesg_insert(TypMsg: byte);
  238. { Insert message into linked list }
  239.   var
  240.     this: MesgPtr;
  241.   begin
  242.     new(this);
  243.     if MesgBase = nil
  244.       then MesgBase := this
  245.       else MesgLast^.next := this;
  246.     MesgLast := this;
  247.     MesgLast^.MesgNo := summ_rec.num;
  248.     MesgLast^.SummLoc := pred(FilePos(summ_file));
  249.     MesgLast^.TypMsg := TypMsg;
  250.     MesgLast^.next := nil
  251.   end;
  252.  
  253. procedure InsertFile(fname: name_array; index, size: integer;
  254.                      var entries, total: integer; var first: FilePtr);
  255. { Insert a new file name into an alphabetic list }
  256.   var
  257.     space: integer;
  258.     f,                                      { File name entry being created }
  259.     this, last: FilePtr;                    { Followers for insertion }
  260.     fn: FileName;
  261.   begin
  262.     fn := '           ';                    { Initialize string }
  263.     move(fname, fn[1], 11);                 { Move name into place }
  264.     insert('.', fn, 9);
  265.     last := nil;
  266.     this := first;
  267.     while (this <> nil) and (this^.fname < fn) do
  268.       begin
  269.         last := this;
  270.         this := this^.next
  271.       end;
  272.     space := size shr 3;
  273.     if (size mod 8) <> 0
  274.       then space := succ(space);
  275.     if this^.fname <> fn
  276.       then
  277.         begin
  278.           entries := succ(entries);
  279.           total := total + space;
  280.           new(f);
  281.           f^.fname := fn;
  282.           f^.index := index;
  283.           f^.fsize := size;
  284.           f^.next  := this;
  285.           if last = nil
  286.             then first := f
  287.             else last^.next := f
  288.         end
  289.     else if (this^.fname = fn) and (this^.fsize < size)
  290.       then
  291.         begin
  292.           total := total + space;
  293.           space := this^.fsize shr 3;
  294.           if (this^.fsize mod 8) <> 0
  295.             then space := succ(space);
  296.           total := total - space;
  297.           this^.fsize := size
  298.         end
  299.   end;
  300.  
  301. { Notes on updcrc:
  302.  
  303.    Purists that want ROS to be written COMPLETELY in Pascal, should use the
  304.    Pascal version, but it is slower than the inline code version.  The inline
  305.    code version is, of course, Z-80 specific, but it is MUCH faster.
  306.  
  307.    The two procedures are functionally equivalent - simply comment out the
  308.    procedure you don't want to use.
  309. }
  310.  
  311. (*
  312. procedure updcrc(var crc: integer; acc: integer);
  313. { Update CRC with passed value }
  314.     var
  315.       carry: boolean;
  316.       i: integer;
  317.     begin
  318.       for i := 1 to 8 do
  319.         begin
  320.           carry := ((crc and $8000) <> 0);
  321.           crc := crc shl 1;
  322.           if (acc and $0080) <> 0
  323.             then crc := succ(crc);
  324.           acc := acc shl 1;
  325.           if carry
  326.             then crc := crc xor $1021       { Use $8005 for CRC-16 }
  327.         end
  328.     end;
  329. *)
  330.  
  331. procedure updcrc(var crc: integer; acc: integer);
  332. { Update CRC with passed value }
  333.   begin
  334.     inline($2A/crc/       {         LD      HL,(crc)    ; point to crc    }
  335.            $5E/           {         LD      E,(HL)      ; put crc into DE }
  336.            $23/           {         INC     HL          ;                 }
  337.            $56/           {         LD      D,(HL)      ;                 }
  338.            $EB/           {         EX      DE,HL       ; put it into HL  }
  339.            $ED/$4B/acc/   {         LD      BC,(acc)    ; get acc into C  }
  340.            $06/$08/       {         LD      B,8         ; shift 8 times   }
  341.            $CB/$01/       { UPDLP:  RLC     C           ; shift input     }
  342.            $ED/$6A/       {         ADC     HL,HL       ; shift crc       }
  343.            $30/$08/       {         JR      NC,SKIPIT   ; jump if no carry}
  344.            $7C/           {         LD      A,H         ; xor with $1021  }
  345.            $EE/$10/       {         XOR     10H         ; use $8005 for   }
  346.            $67/           {         LD      H,A         ;   CRC-16        }
  347.            $7D/           {         LD      A,L         ;                 }
  348.            $EE/$21/       {         XOR     21H         ;                 }
  349.            $6F/           {         LD      L,A         ;                 }
  350.            $10/$F0/       { SKIPIT: DJNZ    UPDLP       ; done?           }
  351.            $EB/           {         EX      DE,HL       ; result to DE    }
  352.            $72/           {         LD      (HL),E      ; then into       }
  353.            $2B/           {         DEC     HL          ;   into          }
  354.            $73)           {         LD      (HL),D      ;     memory      }
  355. end;
  356.  
  357.