123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2004 by the Free Pascal development team.
- Dos unit for BP7 compatible RTL (novell netware libc)
- 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.
- **********************************************************************}
- unit dos;
- interface
- uses libc;
- 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;
- size : longint;
- name : string[255];
- { Internals used by netware port only: }
- _mask : string[255];
- _dir : string[255];
- _attr : word;
- end;
- {$i dosh.inc}
- {Extra Utils}
- function weekday(y,m,d : longint) : longint;
- implementation
- uses
- strings;
- {$DEFINE HAS_GETMSCOUNT}
- {$DEFINE HAS_KEEP}
- {$DEFINE FPC_FEXPAND_DRIVES}
- {$DEFINE FPC_FEXPAND_VOLUMES}
- {$DEFINE FPC_FEXPAND_NO_DEFAULT_PATHS}
- {$i dos.inc}
- {$ASMMODE ATT}
- {*****************************************************************************
- --- Info / Date / Time ---
- ******************************************************************************}
- {$PACKRECORDS 4}
- function dosversion : word;
- var i : Tutsname;
- begin
- if Fpuname (i) >= 0 then
- dosversion := WORD (i.netware_minor) SHL 8 + i.netware_major
- else dosversion := $0005;
- end;
- function WeekDay (y,m,d:longint):longint;
- {
- Calculates th day of the week. returns -1 on error
- }
- var
- u,v : longint;
- begin
- if (m<1) or (m>12) or (y<1600) or (y>4000) or
- (d<1) or (d>30+((m+ord(m>7)) and 1)-ord(m=2)) or
- ((m*d=58) and (((y mod 4>0) or (y mod 100=0)) and (y mod 400>0))) then
- WeekDay:=-1
- else
- begin
- u:=m;
- v:=y;
- if m<3 then
- begin
- inc(u,12);
- dec(v);
- end;
- WeekDay:=(d+2*u+((3*(u+1)) div 5)+v+(v div 4)-(v div 100)+(v div 400)+1) mod 7;
- end;
- end;
- procedure getdate(var year,month,mday,wday : word);
- var
- t : TTime;
- tm : Ttm;
- begin
- time(t); localtime_r(t,tm);
- with tm do
- begin
- year := tm_year+1900;
- month := tm_mon+1;
- mday := tm_mday;
- wday := tm_wday;
- end;
- end;
- procedure setdate(year,month,day : word);
- begin
- end;
- procedure gettime(var hour,minute,second,sec100 : word);
- var
- t : TTime;
- tm : Ttm;
- begin
- time(t); localtime_r(t,tm);
- with tm do
- begin
- hour := tm_hour;
- minute := tm_min;
- second := tm_sec;
- sec100 := 0;
- end;
- end;
- procedure settime(hour,minute,second,sec100 : word);
- begin
- end;
- function GetMsCount: int64;
- var
- tv : TimeVal;
- tz : TimeZone;
- begin
- FPGetTimeOfDay (tv, tz);
- GetMsCount := int64 (tv.tv_Sec) * 1000 + tv.tv_uSec div 1000;
- end;
- {******************************************************************************
- --- Exec ---
- ******************************************************************************}
- const maxargs=256;
- procedure exec(const path : pathstr;const comline : comstr);
- var c : comstr;
- i : integer;
- args : array[0..maxargs] of pchar;
- arg0 : pathstr;
- numargs,wstat : integer;
- Wiring : TWiring;
- begin
- if pos ('.',path) = 0 then
- arg0 := fexpand(path+'.nlm'#0) else
- arg0 := fexpand (path)+#0;
- //writeln (stderr,'dos.exec (',path,',',comline,') arg0:"',copy(arg0,1,length(arg0)-1),'"');
- 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);
- Wiring.infd := StdInputHandle; //textrec(Stdin).Handle;
- Wiring.outfd:= textrec(stdout).Handle;
- Wiring.errfd:= textrec(stderr).Handle;
- //writeln (stderr,'calling procve');
- i := procve(args[0],
- PROC_CURRENT_SPACE+PROC_INHERIT_CWD,
- envP, // const char * env[] If passed as NULL, the child process inherits the parent.s environment at the time of the call.
- @Wiring, // wiring_t *wiring, Pass NULL to inherit system defaults for wiring.
- nil, // struct fd_set *fds, Not currently implemented. Pass in NULL.
- nil, // void *appdata, Not currently implemented. Pass in NULL.
- 0, // size_t appdata_size, Not currently implemented. Pass in 0
- nil, // void *reserved, Reserved. Pass NULL.
- @args); // const char *argv[]
- //writeln (stderr,'Ok');
- if i <> -1 then
- begin
- Fpwaitpid(i,@wstat,0);
- doserror := 0;
- lastdosexitcode := wstat;
- end else
- begin
- doserror := 8; // for now, what about errno ?
- end;
- 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;}
- getvolnum := -1;
- end;
- function diskfree(drive : byte) : int64;
- {VAR Buf : ARRAY [0..255] OF CHAR;
- 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 CHAR;
- 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;
- {******************************************************************************
- --- Utils ---
- ******************************************************************************}
- procedure timet2dostime (timet:longint; var dostime : longint);
- var tm : Ttm;
- begin
- localtime_r(timet,tm);
- dostime:=(tm.tm_sec shr 1)+(tm.tm_min shl 5)+(tm.tm_hour shl 11)+(tm.tm_mday shl 16)+((tm.tm_mon+1) shl 21)+((tm.tm_year+1900-1980) shl 25);
- end;
- function nwattr2dosattr (nwattr : longint) : word;
- begin
- nwattr2dosattr := 0;
- if nwattr and M_A_RDONLY > 0 then nwattr2dosattr := nwattr2dosattr + readonly;
- if nwattr and M_A_HIDDEN > 0 then nwattr2dosattr := nwattr2dosattr + hidden;
- if nwattr and M_A_SYSTEM > 0 then nwattr2dosattr := nwattr2dosattr + sysfile;
- if nwattr and M_A_SUBDIR > 0 then nwattr2dosattr := nwattr2dosattr + directory;
- if nwattr and M_A_ARCH > 0 then nwattr2dosattr := nwattr2dosattr + archive;
- end;
- {******************************************************************************
- --- Findfirst FindNext ---
- ******************************************************************************}
- {returns true if attributes match}
- function find_setfields (var f : searchRec) : boolean;
- var
- StatBuf : TStat;
- fname : string[255];
- begin
- find_setfields := false;
- with F do
- begin
- if Magic = $AD01 then
- begin
- attr := nwattr2dosattr (Pdirent(EntryP)^.d_mode);
- size := Pdirent(EntryP)^.d_size;
- name := strpas (Pdirent(EntryP)^.d_name);
- doserror := 0;
- fname := f._dir + f.name;
- if length (fname) = 255 then dec (byte(fname[0]));
- fname := fname + #0;
- if Fpstat (@fname[1],StatBuf) = 0 then
- timet2dostime (StatBuf.st_mtim.tv_sec, time)
- else
- time := 0;
- if (f._attr and hidden) = 0 then
- if attr and hidden > 0 then exit;
- if (f._attr and Directory) = 0 then
- if attr and Directory > 0 then exit;
- if (f._attr and SysFile) = 0 then
- if attr and SysFile > 0 then exit;
- find_setfields := true;
- 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 char;
- p : longint;
- begin
- IF path = '' then
- begin
- doserror := 18;
- exit;
- end;
- f._attr := attr;
- p := length (path);
- while (p > 0) and (not (path[p] in ['\','/'])) do
- dec (p);
- if p > 0 then
- begin
- f._mask := copy (path,p+1,255);
- f._dir := copy (path,1,p);
- strpcopy(path0,f._dir);
- end else
- begin
- f._mask := path;
- getdir (0,f._dir);
- if (f._dir[length(f._dir)] <> '/') and
- (f._dir[length(f._dir)] <> '\') then
- f._dir := f._dir + '/';
- strpcopy(path0,f._dir);
- end;
- if f._mask = '*' then f._mask := '';
- if f._mask = '*.*' then f._mask := '';
- //writeln (stderr,'mask: "',f._mask,'" dir:"',path0,'"');
- f._mask := f._mask + #0;
- Pdirent(f.DirP) := opendir (path0);
- if f.DirP = nil then
- doserror := 18
- else begin
- F.Magic := $AD01;
- findnext (f);
- end;
- end;
- procedure findnext(var f : searchRec);
- begin
- if F.Magic <> $AD01 then
- begin
- doserror := 18;
- exit;
- end;
- doserror:=0;
- repeat
- Pdirent(f.EntryP) := readdir (Pdirent(f.DirP));
- if F.EntryP = nil then
- doserror := 18
- else
- if find_setfields (f) then
- begin
- if f._mask = #0 then exit;
- if fnmatch(@f._mask[1],Pdirent(f.EntryP)^.d_name,FNM_CASEFOLD) = 0 then
- exit;
- end;
- until doserror <> 0;
- end;
- Procedure FindClose(Var f: SearchRec);
- begin
- if F.Magic <> $AD01 then
- begin
- doserror := 18;
- EXIT;
- end;
- doserror:=0;
- closedir (Pdirent(f.DirP));
- f.Magic := 0;
- f.DirP := NIL;
- f.EntryP := NIL;
- end;
- {******************************************************************************
- --- File ---
- ******************************************************************************}
- Function FSearch(path: pathstr; dirlist: string): pathstr;
- var
- i,p1 : longint;
- s : searchrec;
- newdir : pathstr;
- begin
- { check if the file specified exists }
- findfirst(path,anyfile,s);
- if doserror=0 then
- begin
- findclose(s);
- fsearch:=path;
- exit;
- end;
- { No wildcards allowed in these things }
- if (pos('?',path)<>0) or (pos('*',path)<>0) then
- fsearch:=''
- else
- begin
- { allow backslash as slash }
- for i:=1 to length(dirlist) do
- if dirlist[i]='\' then dirlist[i]:='/';
- 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 ['/',':'])) then
- newdir:=newdir+'/';
- findfirst(newdir+path,anyfile,s);
- if doserror=0 then
- newdir:=newdir+path
- else
- newdir:='';
- until (dirlist='') or (newdir<>'');
- fsearch:=newdir;
- end;
- findclose(s);
- end;
- {******************************************************************************
- --- Get/Set File Time,Attr ---
- ******************************************************************************}
- procedure getftime(var f;var time : longint);
- var
- StatBuf : TStat;
- begin
- doserror := 0;
- if Fpfstat (filerec (f).handle, StatBuf) = 0 then
- timet2dostime (StatBuf.st_mtim.tv_sec,time)
- else begin
- time := 0;
- doserror := ___errno^;
- end;
- end;
- procedure setftime(var f;time : longint);
- Var
- utim: utimbuf;
- DT: DateTime;
- path: pathstr;
- tm : TTm;
- Begin
- doserror:=0;
- with utim do
- begin
- actime:=libc.time(nil); // getepochtime;
- UnPackTime(Time,DT);
- with tm do
- begin
- tm_sec := DT.Sec; // seconds after the minute [0..59]
- tm_min := DT.Min; // minutes after the hour [0..59]
- tm_hour := DT.hour; // hours since midnight [0..23]
- tm_mday := DT.Day; // days of the month [1..31]
- tm_mon := DT.month-1; // months since January [0..11]
- tm_year := DT.year-1900;
- tm_wday := -1;
- tm_yday := -1;
- tm_isdst := -1;
- end;
- modtime:=mktime(tm);
- end;
- if utime(@filerec(f).name,utim)<0 then
- begin
- Time:=0;
- doserror:=3;
- end;
- end;
- procedure getfattr(var f;var attr : word);
- VAR StatBuf : TStat;
- begin
- doserror := 0;
- if Fpstat (@textrec(f).name, StatBuf) = 0 then
- attr := nwattr2dosattr (StatBuf.st_mode)
- else
- begin
- attr := 0;
- doserror := ___errno^;
- end;
- end;
- procedure setfattr(var f;attr : word);
- var
- StatBuf : TStat;
- newMode : longint;
- begin
- if Fpstat (@textrec(f).name,StatBuf) = 0 then
- begin
- newmode := StatBuf.st_mode and ($FFFF0000 - M_A_RDONLY-M_A_HIDDEN-M_A_SYSTEM-M_A_ARCH); {only this can be set by dos unit}
- newmode := newmode or M_A_BITS_SIGNIFICANT; {set netware attributes}
- if attr and readonly > 0 then
- newmode := newmode or M_A_RDONLY;
- if attr and hidden > 0 then
- newmode := newmode or M_A_HIDDEN;
- if attr and sysfile > 0 then
- newmode := newmode or M_A_SYSTEM;
- if attr and archive > 0 then
- newmode := newmode or M_A_ARCH;
- if Fpchmod (@textrec(f).name,newMode) < 0 then
- doserror := ___errno^ else
- doserror := 0;
- end else
- doserror := ___errno^;
- end;
- {******************************************************************************
- --- Environment ---
- ******************************************************************************}
- Function EnvCount: Longint;
- var
- envcnt : longint;
- p : ppchar;
- Begin
- envcnt:=0;
- p:=envp; {defined in system}
- while (p^<>nil) do
- begin
- inc(envcnt);
- inc(p);
- end;
- EnvCount := envcnt
- End;
- Function EnvStr (Index: longint): String;
- Var
- i : longint;
- p : ppchar;
- Begin
- if Index <= 0 then
- envstr:=''
- else
- begin
- p:=envp; {defined in system}
- i:=1;
- while (i<Index) and (p^<>nil) do
- begin
- inc(i);
- inc(p);
- end;
- if p=nil then
- envstr:=''
- else
- envstr:=strpas(p^)
- end;
- end;
- { works fine (at least with netware 6.5) }
- Function GetEnv(envvar: string): string;
- var envvar0 : array[0..512] of char;
- p : pchar;
- SearchElement : string[255];
- 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 := GetSearchPathElement (i, isdosPath, @SearchElement[0]);
- while res = 0 do
- begin
- if isDosPath = 0 then
- begin
- if GetEnv <> '' then GetEnv := GetEnv + ';';
- GetEnv := GetEnv + SearchElement;
- end;
- inc (i);
- res := GetSearchPathElement (i, isdosPath, @SearchElement[0]);
- end;
- for i := 1 to length(GetEnv) do
- if GetEnv[i] = '\' then
- GetEnv[i] := '/';
- end else
- begin
- strpcopy(envvar0,envvar);
- p := libc.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.
|