{ This file is part of the Free Pascal run time library. Copyright (c) 1999-2000 by the Free Pascal development team. Dos unit for BP7 compatible RTL (novell netware) See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} {$IFNDEF FPC_DOTTEDUNITS} unit dos; {$ENDIF FPC_DOTTEDUNITS} interface Type searchrec = packed record DirP : POINTER; { used for opendir } EntryP: POINTER; { and readdir } Magic : WORD; fill : array[1..11] of byte; attr : byte; time : longint; { reserved : word; not in DJGPP V2 } size : longint; name : string[255]; { NW uses only [12] but more can't hurt } end; {$i dosh.inc} implementation {$IFDEF FPC_DOTTEDUNITS} uses System.Strings, NetWareApi.nwserv; {$ELSE FPC_DOTTEDUNITS} uses strings, nwserv; {$ENDIF FPC_DOTTEDUNITS} {$DEFINE HAS_GETMSCOUNT} {$DEFINE HAS_GETCBREAK} {$DEFINE HAS_SETCBREAK} {$DEFINE HAS_KEEP} {$define FPC_FEXPAND_DRIVES} {$define FPC_FEXPAND_VOLUMES} {$define FPC_FEXPAND_NO_DEFAULT_PATHS} {$I dos.inc} {$ASMMODE ATT} {$I nwsys.inc } {***************************************************************************** --- Info / Date / Time --- ******************************************************************************} {$PACKRECORDS 4} function dosversion : word; VAR F : FILE_SERV_INFO; begin IF GetServerInformation(SIZEOF(F),@F) = 0 THEN dosversion := WORD (F.netwareVersion) SHL 8 + F.netwareSubVersion; end; procedure getdate(var year,month,mday,wday : word); VAR N : NWdateAndTime; begin GetFileServerDateAndTime (N); wday:=N.DayOfWeek; year:=1900 + N.Year; month:=N.Month; mday:=N.Day; end; procedure setdate(year,month,day : word); VAR N : NWdateAndTime; begin GetFileServerDateAndTime (N); SetFileServerDateAndTime(year,month,day,N.Hour,N.Minute,N.Second); end; procedure gettime(var hour,minute,second,sec100 : word); VAR N : NWdateAndTime; begin GetFileServerDateAndTime (N); hour := N.Hour; Minute:= N.Minute; Second := N.Second; sec100 := 0; end; procedure settime(hour,minute,second,sec100 : word); VAR N : NWdateAndTime; begin GetFileServerDateAndTime (N); SetFileServerDateAndTime(N.year,N.month,N.day,hour,minute,second); end; function GetMsCount: int64; begin GetMsCount := int64 (Nwserv.GetCurrentTicks) * 55; end; {****************************************************************************** --- Exec --- ******************************************************************************} const maxargs=256; procedure exec(const path : pathstr;const comline : comstr); var c : comstr; i : integer; args : array[0..maxargs] of PAnsiChar; arg0 : pathstr; numargs : integer; begin //writeln ('dos.exec (',path,',',comline,')'); arg0 := fexpand (path)+#0; args[0] := @arg0[1]; numargs := 0; c:=comline; i:=1; while i<=length(c) do begin if c[i]<>' ' then begin {Commandline argument found. append #0 and set pointer in args } inc(numargs); args[numargs]:=@c[i]; while (i<=length(c)) and (c[i]<>' ') do inc(i); c[i] := #0; end; inc(i); end; args[numargs+1] := nil; i := spawnvp (P_WAIT,args[0],@args); if i >= 0 then begin doserror := 0; lastdosexitcode := i; end else begin doserror := 8; // for now, what about errno ? end; end; procedure getcbreak(var breakvalue : boolean); begin breakvalue := _SetCtrlCharCheckMode (false); { get current setting } if breakvalue then _SetCtrlCharCheckMode (breakvalue); { and restore old setting } end; procedure setcbreak(breakvalue : boolean); begin _SetCtrlCharCheckMode (breakvalue); end; {****************************************************************************** --- Disk --- ******************************************************************************} function getvolnum (drive : byte) : longint; var dir : STRING[255]; P,PS, V : LONGINT; begin if drive = 0 then begin // get volume name from current directory (i.e. SERVER-NAME/VOL2:TEST) getdir (0,dir); p := pos (':', dir); if p = 0 then begin getvolnum := -1; exit; end; byte (dir[0]) := p-1; dir[p] := #0; PS := pos ('/', dir); INC (PS); if _GetVolumeNumber (@dir[PS], V) <> 0 then getvolnum := -1 else getvolnum := V; end else getvolnum := drive-1; end; function diskfree(drive : byte) : int64; VAR Buf : ARRAY [0..255] OF AnsiChar; TotalBlocks : WORD; SectorsPerBlock : WORD; availableBlocks : WORD; totalDirectorySlots : WORD; availableDirSlots : WORD; volumeisRemovable : WORD; volumeNumber : LONGINT; begin volumeNumber := getvolnum (drive); if volumeNumber >= 0 then begin {i think thats not the right function but for others i need a connection handle} if _GetVolumeInfoWithNumber (byte(volumeNumber),@Buf, TotalBlocks, SectorsPerBlock, availableBlocks, totalDirectorySlots, availableDirSlots, volumeisRemovable) = 0 THEN begin diskfree := int64 (availableBlocks) * int64 (SectorsPerBlock) * 512; end else diskfree := 0; end else diskfree := 0; end; function disksize(drive : byte) : int64; VAR Buf : ARRAY [0..255] OF AnsiChar; TotalBlocks : WORD; SectorsPerBlock : WORD; availableBlocks : WORD; totalDirectorySlots : WORD; availableDirSlots : WORD; volumeisRemovable : WORD; volumeNumber : LONGINT; begin volumeNumber := getvolnum (drive); if volumeNumber >= 0 then begin {i think thats not the right function but for others i need a connection handle} if _GetVolumeInfoWithNumber (byte(volumeNumber),@Buf, TotalBlocks, SectorsPerBlock, availableBlocks, totalDirectorySlots, availableDirSlots, volumeisRemovable) = 0 THEN begin disksize := int64 (TotalBlocks) * int64 (SectorsPerBlock) * 512; end else disksize := 0; end else disksize := 0; end; {****************************************************************************** --- Findfirst FindNext --- ******************************************************************************} PROCEDURE find_setfields (VAR f : searchRec); BEGIN WITH F DO BEGIN IF Magic = $AD01 THEN BEGIN attr := WORD (PNWDirEnt(EntryP)^.d_attr); // lowest 16 bit -> same as dos time := PNWDirEnt(EntryP)^.d_time + (LONGINT (PNWDirEnt(EntryP)^.d_date) SHL 16); size := PNWDirEnt(EntryP)^.d_size; name := strpas (PNWDirEnt(EntryP)^.d_name); if name = '' then name := strpas (PNWDirEnt(EntryP)^.d_nameDOS); doserror := 0; END ELSE BEGIN FillChar (f,SIZEOF(f),0); doserror := 18; END; END; END; procedure findfirst(const path : pathstr;attr : word;var f : searchRec); var path0 : array[0..256] of AnsiChar; begin IF path = '' then begin doserror := 18; exit; end; strpcopy(path0,path); PNWDirEnt(f.DirP) := _opendir (path0); IF f.DirP = NIL THEN doserror := 18 ELSE BEGIN IF attr <> anyfile THEN _SetReaddirAttribute (PNWDirEnt(f.DirP), attr); F.Magic := $AD01; PNWDirEnt(f.EntryP) := _readdir (PNWDirEnt(f.DirP)); IF F.EntryP = NIL THEN BEGIN _closedir (PNWDirEnt(f.DirP)); f.Magic := 0; doserror := 18; END ELSE find_setfields (f); END; end; procedure findnext(var f : searchRec); begin IF F.Magic <> $AD01 THEN BEGIN doserror := 18; EXIT; END; doserror:=0; PNWDirEnt(f.EntryP) := _readdir (PNWDirEnt(f.DirP)); IF F.EntryP = NIL THEN doserror := 18 ELSE find_setfields (f); end; Procedure FindClose(Var f: SearchRec); begin IF F.Magic <> $AD01 THEN BEGIN doserror := 18; EXIT; END; doserror:=0; _closedir (PNWDirEnt(f.DirP)); f.Magic := 0; f.DirP := NIL; f.EntryP := NIL; end; {****************************************************************************** --- File --- ******************************************************************************} Function FSearch(path: pathstr; dirlist: string): pathstr; var p1 : longint; s : searchrec; newdir : pathstr; begin { No wildcards allowed in these things } if (pos('?',path)<>0) or (pos('*',path)<>0) then begin fsearch:=''; exit; end; { check if the file specified exists } findfirst(path,anyfile and not(directory),s); if doserror=0 then begin findclose(s); fsearch:=path; exit; end; findclose(s); { allow backslash as slash } DoDirSeparators(dirlist); repeat p1:=pos(';',dirlist); if p1<>0 then begin newdir:=copy(dirlist,1,p1-1); delete(dirlist,1,p1); end else begin newdir:=dirlist; dirlist:=''; end; if (newdir<>'') and (not (newdir[length(newdir)] in [DirectorySeparator,DriveSeparator])) then newdir:=newdir+DirectorySeparator; findfirst(newdir+path,anyfile and not(directory),s); if doserror=0 then newdir:=newdir+path else newdir:=''; findclose(s); until (dirlist='') or (newdir<>''); fsearch:=newdir; end; {****************************************************************************** --- Get/Set File Time,Attr --- ******************************************************************************} procedure getftime(var f;var time : longint); VAR StatBuf : NWStatBufT; T : DateTime; DosDate, DosTime : WORD; begin IF _fstat (FileRec (f).Handle, StatBuf) = 0 THEN BEGIN _ConvertTimeToDos (StatBuf.st_mtime, DosDate, DosTime); time := DosTime + (LONGINT (DosDate) SHL 16); END ELSE time := 0; end; procedure setftime(var f;time : longint); begin {is there a netware function to do that ?????} ConsolePrintf ('warning: fpc dos.setftime not implemented'#13#10); end; procedure getfattr(var f;var attr : word); VAR StatBuf : NWStatBufT; begin IF _fstat (FileRec (f).Handle, StatBuf) = 0 THEN BEGIN attr := word (StatBuf.st_attr); END ELSE attr := 0; end; procedure setfattr(var f;attr : word); begin {is there a netware function to do that ?????} ConsolePrintf ('warning: fpc dos.setfattr not implemented'#13#10); end; {****************************************************************************** --- Environment --- ******************************************************************************} function envcount : longint; begin envcount := 0; {is there a netware function to do that ?????} ConsolePrintf ('warning: fpc dos.envcount not implemented'#13#10); end; function envstr (index: longint) : string; begin envstr := ''; {is there a netware function to do that ?????} ConsolePrintf ('warning: fpc dos.envstr not implemented'#13#10); end; { works fine (at least with netware 6.5) } Function GetEnv(envvar: string): string; var envvar0 : array[0..512] of AnsiChar; p : PAnsiChar; i,isDosPath,res : longint; begin if upcase(envvar) = 'PATH' then begin // netware does not have search paths in the environment var PATH // return it here (needed for the compiler) GetEnv := ''; i := 1; res := _NWGetSearchPathElement (i, isdosPath, @envvar0[0]); while res = 0 do begin if GetEnv <> '' then GetEnv := GetEnv + ';'; GetEnv := GetEnv + strpas(envvar0); inc (i); res := _NWGetSearchPathElement (i, isdosPath, @envvar0[0]); end; DoDirSeparators(getenv); end else begin strpcopy(envvar0,envvar); p := _getenv (envvar0); if p = NIL then GetEnv := '' else GetEnv := strpas (p); end; end; {****************************************************************************** --- Not Supported --- ******************************************************************************} Procedure keep(exitcode : word); Begin { simply wait until nlm will be unloaded } while true do _delay (60000); End; end.