2
0

sysutils.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Sysutils unit for netware
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. {$MODESWITCH OUT}
  16. { force ansistrings }
  17. {$H+}
  18. {$modeswitch typehelpers}
  19. {$modeswitch advancedrecords}
  20. uses DOS;
  21. {$I nwsys.inc}
  22. {$I errno.inc}
  23. {$DEFINE HAS_SLEEP}
  24. {$DEFINE HAS_OSERROR}
  25. { used OS file system APIs use ansistring }
  26. {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  27. { OS has an ansistring/single byte environment variable API }
  28. {$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
  29. {$DEFINE executeprocuni} (* Only 1 byte version of ExecuteProcess is provided by the OS *)
  30. TYPE
  31. TNetwareFindData =
  32. RECORD
  33. DirP : PNWDirEnt; { used for opendir }
  34. EntryP: PNWDirEnt; { and readdir }
  35. Magic : WORD; { to avoid abends with uninitialized TSearchRec }
  36. END;
  37. { Include platform independent interface part }
  38. {$i sysutilh.inc}
  39. { additional NetWare file flags}
  40. CONST
  41. faSHARE = $00000080; { Sharable file }
  42. faNO_SUBALLOC = $00000800; { Don't sub alloc. this file }
  43. faTRANS = $00001000; { Transactional file (TTS usable) }
  44. faREADAUD = $00004000; { Read audit }
  45. faWRITAUD = $00008000; { Write audit }
  46. faIMMPURG = $00010000; { Immediate purge }
  47. faNORENAM = $00020000; { Rename inhibit }
  48. faNODELET = $00040000; { Delete inhibit }
  49. faNOCOPY = $00080000; { Copy inhibit }
  50. faFILE_MIGRATED = $00400000; { File has been migrated }
  51. faDONT_MIGRATE = $00800000; { Don't migrate this file }
  52. faIMMEDIATE_COMPRESS = $02000000; { Compress this file immediately }
  53. faFILE_COMPRESSED = $04000000; { File is compressed }
  54. faDONT_COMPRESS = $08000000; { Don't compress this file }
  55. faCANT_COMPRESS = $20000000; { Can't compress this file }
  56. faATTR_ARCHIVE = $40000000; { Entry has had an EA modified, }
  57. { an ownerID changed, or trustee }
  58. { info changed, etc. }
  59. implementation
  60. uses
  61. sysconst;
  62. {$define FPC_FEXPAND_DRIVES}
  63. {$define FPC_FEXPAND_VOLUMES}
  64. {$define FPC_FEXPAND_NO_DEFAULT_PATHS}
  65. { Include platform independent implementation part }
  66. {$i sysutils.inc}
  67. {****************************************************************************
  68. File Functions
  69. ****************************************************************************}
  70. Function FileOpen (Const FileName : rawbytestring; Mode : Integer) : THandle;
  71. VAR NWOpenFlags : longint;
  72. SystemFileName: RawByteString;
  73. begin
  74. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  75. NWOpenFlags:=0;
  76. Case (Mode and 3) of
  77. 0 : NWOpenFlags:=NWOpenFlags or O_RDONLY;
  78. 1 : NWOpenFlags:=NWOpenFlags or O_WRONLY;
  79. 2 : NWOpenFlags:=NWOpenFlags or O_RDWR;
  80. end;
  81. FileOpen := _open (pchar(SystemFileName),NWOpenFlags,0);
  82. //!! We need to set locking based on Mode !!
  83. end;
  84. Function FileCreate (Const FileName : RawByteString) : THandle;
  85. VAR SystemFileName: RawByteString;
  86. begin
  87. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  88. FileCreate:=_open(Pchar(SystemFileName),O_RdWr or O_Creat or O_Trunc,0);
  89. end;
  90. Function FileCreate (Const FileName : RawByteString; Rights:longint) : THandle;
  91. begin
  92. FileCreate:=FileCreate (FileName);
  93. end;
  94. Function FileCreate (Const FileName : RawByteString; ShareMode: Longint; Rights:longint) : THandle;
  95. begin
  96. FileCreate:=FileCreate (FileName);
  97. end;
  98. Function FileRead (Handle : THandle; Out Buffer; Count : longint) : longint;
  99. begin
  100. FileRead:=_read (Handle,@Buffer,Count);
  101. end;
  102. Function FileWrite (Handle : THandle; const Buffer; Count : Longint) : longint;
  103. begin
  104. FileWrite:=_write (Handle,@Buffer,Count);
  105. end;
  106. Function FileSeek (Handle : THandle; FOffset,Origin : Longint) : Longint;
  107. begin
  108. FileSeek:=_lseek (Handle,FOffset,Origin);
  109. end;
  110. Function FileSeek (Handle : THandle; FOffset: Int64; Origin: Longint) : Int64;
  111. begin
  112. {$warning need to add 64bit FileSeek }
  113. FileSeek:=FileSeek(Handle,Longint(FOffset),Longint(Origin));
  114. end;
  115. Procedure FileClose (Handle : THandle);
  116. begin
  117. _close(Handle);
  118. end;
  119. Function FileTruncate (Handle : THandle; Size: Int64) : boolean;
  120. begin
  121. if Size > high (longint) then
  122. FileTruncate := false
  123. {$WARNING Possible support for 64-bit FS to be checked!}
  124. else
  125. FileTruncate:=(_chsize(Handle,Size) = 0);
  126. end;
  127. Function FileAge (Const FileName : RawByteString): Int64;
  128. var Handle: longint;
  129. begin
  130. Handle := FileOpen(FileName, 0);
  131. if Handle <> -1 then
  132. begin
  133. result := FileGetDate(Handle);
  134. FileClose(Handle);
  135. end
  136. else
  137. result := -1;
  138. end;
  139. Function FileLock (Handle,FOffset,FLen : Longint) : Longint;
  140. begin
  141. FileLock := _lock (Handle,FOffset,FLen);
  142. end;
  143. Function FileLock (Handle : Longint; FOffset,FLen : Int64) : Longint;
  144. begin
  145. {$warning need to add 64bit FileLock call }
  146. FileLock := FileLock (Handle, longint(FOffset),longint(FLen));
  147. end;
  148. Function FileUnlock (Handle,FOffset,FLen : Longint) : Longint;
  149. begin
  150. FileUnlock := _unlock (Handle,FOffset,FLen);
  151. end;
  152. Function FileUnlock (Handle : Longint; FOffset,FLen : Int64) : Longint;
  153. begin
  154. {$warning need to add 64bit FileUnlock call }
  155. FileUnlock := FileUnlock (Handle, longint(FOffset),longint(FLen));
  156. end;
  157. Function FileAge (Const FileName : String): Int64;
  158. VAR Info : NWStatBufT;
  159. PTM : PNWTM;
  160. begin
  161. If _stat (pchar(FileName),Info) <> 0 then
  162. exit(-1)
  163. else
  164. begin
  165. PTM := _localtime (Info.st_mtime);
  166. IF PTM = NIL THEN
  167. exit(-1)
  168. else
  169. WITH PTM^ DO
  170. Result:=DateTimeToFileDate(EncodeDate(tm_year+1900,tm_mon+1,tm_mday)+EncodeTime(tm_hour,tm_min,tm_sec,0));
  171. end;
  172. end;
  173. function FileGetSymLinkTarget(const FileName: RawByteString; out SymLinkRec: TRawbyteSymLinkRec): Boolean;
  174. begin
  175. Result := False;
  176. end;
  177. Function FileExists (Const FileName : RawByteString; FollowLink : Boolean) : Boolean;
  178. VAR Info : NWStatBufT;
  179. SystemFileName: RawByteString;
  180. begin
  181. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  182. FileExists:=(_stat(pchar(SystemFileName),Info) = 0);
  183. end;
  184. Function DirectoryExists (Const Directory : RawByteString; FollowLink : Boolean) : Boolean;
  185. Var
  186. Dir : RawByteString;
  187. drive : byte;
  188. FADir, StoredIORes : longint;
  189. begin
  190. Dir:=Directory;
  191. if (length(dir)=2) and (dir[2]=':') and
  192. ((dir[1] in ['A'..'Z']) or (dir[1] in ['a'..'z'])) then
  193. begin
  194. { We want to test GetCurDir }
  195. if dir[1] in ['A'..'Z'] then
  196. drive:=ord(dir[1])-ord('A')+1
  197. else
  198. drive:=ord(dir[1])-ord('a')+1;
  199. {$push}
  200. {$I-}
  201. StoredIORes:=InOutRes;
  202. InOutRes:=0;
  203. GetDir(drive,dir);
  204. if InOutRes <> 0 then
  205. begin
  206. InOutRes:=StoredIORes;
  207. result:=false;
  208. exit;
  209. end;
  210. end;
  211. {$pop}
  212. if (Length (Dir) > 1) and
  213. (Dir [Length (Dir)] in AllowDirectorySeparators) and
  214. (* Do not remove '\' after ':' (root directory of a drive)
  215. or in '\\' (invalid path, possibly broken UNC path). *)
  216. not (Dir [Length (Dir) - 1] in (AllowDriveSeparators + AllowDirectorySeparators)) then
  217. dir:=copy(dir,1,length(dir)-1);
  218. (* FileGetAttr returns -1 on error *)
  219. FADir := FileGetAttr (Dir);
  220. Result := (FADir <> -1) and
  221. ((FADir and faDirectory) = faDirectory);
  222. end;
  223. PROCEDURE find_setfields (VAR f : TAbstractSearchRec; VAR Name : RawByteString);
  224. VAR T : Dos.DateTime;
  225. BEGIN
  226. WITH F DO
  227. BEGIN
  228. IF FindData.Magic = $AD01 THEN
  229. BEGIN
  230. {attr := FindData.EntryP^.d_attr AND $FF;} // lowest 8 bit -> same as dos
  231. attr := FindData.EntryP^.d_attr; { return complete netware attributes }
  232. UnpackTime(FindData.EntryP^.d_time + (LONGINT (FindData.EntryP^.d_date) SHL 16), T);
  233. time := DateTimeToFileDate(EncodeDate(T.Year,T.Month,T.day)+EncodeTime(T.Hour,T.Min,T.Sec,0));
  234. size := FindData.EntryP^.d_size;
  235. name := FindData.EntryP^.d_nameDOS;
  236. SetCodePage(name, DefaultFileSystemCodePage, false);
  237. END ELSE
  238. BEGIN
  239. name := '';
  240. END;
  241. END;
  242. END;
  243. Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
  244. var
  245. SystemEncodedPath: RawByteString;
  246. begin
  247. IF path = '' then
  248. exit (18);
  249. SystemEncodedPath := ToSingleByteFileSystemEncodedFileName(Path);
  250. Rslt.FindData.DirP := _opendir (pchar(SystemEncodedPath));
  251. IF Rslt.FindData.DirP = NIL THEN
  252. exit (18);
  253. IF attr <> faAnyFile THEN
  254. _SetReaddirAttribute (Rslt.FindData.DirP, attr);
  255. Rslt.FindData.Magic := $AD01;
  256. Rslt.FindData.EntryP := _readdir (Rslt.FindData.DirP);
  257. if Rslt.FindData.EntryP = nil then
  258. begin
  259. _closedir (Rslt.FindData.DirP);
  260. Rslt.FindData.DirP := NIL;
  261. result := 18;
  262. end else
  263. begin
  264. find_setfields (Rslt,Name);
  265. result := 0;
  266. end;
  267. end;
  268. Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
  269. begin
  270. IF Rslt.FindData.Magic <> $AD01 THEN
  271. exit (18);
  272. Rslt.FindData.EntryP := _readdir (Rslt.FindData.DirP);
  273. IF Rslt.FindData.EntryP = NIL THEN
  274. exit (18);
  275. find_setfields (Rslt,Name);
  276. result := 0;
  277. end;
  278. Procedure InternalFindClose (var Handle: THandle; var FindData: TFindData);
  279. begin
  280. IF FindData.Magic = $AD01 THEN
  281. BEGIN
  282. IF FindData.DirP <> NIL THEN
  283. _closedir (FindData.DirP);
  284. FindData.Magic := 0;
  285. FindData.DirP := NIL;
  286. FindData.EntryP := NIL;
  287. END;
  288. end;
  289. Function FileGetDate (Handle : THandle) : Int64;
  290. Var Info : NWStatBufT;
  291. PTM : PNWTM;
  292. begin
  293. If _fstat(Handle,Info) <> 0 then
  294. Result:=-1
  295. else
  296. begin
  297. PTM := _localtime (Info.st_mtime);
  298. IF PTM = NIL THEN
  299. exit(-1)
  300. else
  301. WITH PTM^ DO
  302. Result:=DateTimeToFileDate(EncodeDate(tm_year+1900,tm_mon+1,tm_mday)+EncodeTime(tm_hour,tm_min,tm_sec,0));
  303. end;
  304. end;
  305. Function FileSetDate (Handle : THandle; Age : Int64) : Longint;
  306. begin
  307. { i think its impossible under netware from FileHandle. I dident found a way to get the
  308. complete pathname of a filehandle, that would be needed for ChangeDirectoryEntry }
  309. FileSetDate:=-1;
  310. ConsolePrintf ('warning: fpc sysutils.FileSetDate not implemented'#13#10,0);
  311. {$warning FileSetDate not implemented (i think is impossible) }
  312. end;
  313. Function FileGetAttr (Const FileName : RawByteString) : Longint;
  314. Var Info : NWStatBufT;
  315. SystemFileName: RawByteString;
  316. begin
  317. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  318. If _stat (pchar(SystemFileName),Info) <> 0 then
  319. Result:=-1
  320. Else
  321. Result := Info.st_attr AND $FFFF;
  322. end;
  323. Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
  324. VAR MS : NWModifyStructure;
  325. SystemFileName: RawByteString;
  326. begin
  327. { The Attr parameter is not used! }
  328. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  329. FillChar (MS, SIZEOF (MS), 0);
  330. if _ChangeDirectoryEntry (PChar (SystemFilename), MS, MFileAtrributesBit, 0) <> 0 then
  331. result := -1
  332. else
  333. result := 0;
  334. end;
  335. Function DeleteFile (Const FileName : RawByteString) : Boolean;
  336. var
  337. SystemFileName: RawByteString;
  338. begin
  339. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  340. Result:= (_UnLink (pchar(SystemFileName)) = 0);
  341. end;
  342. Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;
  343. var
  344. OldSystemFileName, NewSystemFileName: RawByteString;
  345. begin
  346. OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);
  347. NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName);
  348. RenameFile:=(_rename(pchar(OldSystemFileName),pchar(NewSystemFileName)) = 0);
  349. end;
  350. {****************************************************************************
  351. Disk Functions
  352. ****************************************************************************}
  353. {
  354. The Diskfree and Disksize functions need a file on the specified drive, since this
  355. is required for the statfs system call.
  356. These filenames are set in drivestr[0..26], and have been preset to :
  357. 0 - '.' (default drive - hence current dir is ok.)
  358. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  359. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  360. 3 - '/' (C: equivalent of dos is the root partition)
  361. 4..26 (can be set by you're own applications)
  362. ! Use AddDisk() to Add new drives !
  363. They both return -1 when a failure occurs.
  364. }
  365. Const
  366. FixDriveStr : array[0..3] of pchar=(
  367. '.',
  368. 'a:.',
  369. 'b:.',
  370. 'sys:/'
  371. );
  372. var
  373. Drives : byte;
  374. DriveStr : array[4..26] of pchar;
  375. Procedure AddDisk(const path:string);
  376. begin
  377. if not (DriveStr[Drives]=nil) then
  378. FreeMem(DriveStr[Drives],StrLen(DriveStr[Drives])+1);
  379. GetMem(DriveStr[Drives],length(Path)+1);
  380. StrPCopy(DriveStr[Drives],path);
  381. inc(Drives);
  382. if Drives>26 then
  383. Drives:=4;
  384. end;
  385. Function DiskFree(Drive: Byte): int64;
  386. //var fs : statfs;
  387. Begin
  388. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and fsstat(StrPas(fixdrivestr[drive]),fs)) or
  389. ((not (drivestr[Drive]=nil)) and fsstat(StrPas(drivestr[drive]),fs)) then
  390. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  391. else
  392. Diskfree:=-1;}
  393. DiskFree := -1;
  394. ConsolePrintf ('warning: fpc sysutils.diskfree not implemented'#13#10,0);
  395. {$warning DiskFree not implemented (does it make sense ?) }
  396. End;
  397. Function DiskSize(Drive: Byte): int64;
  398. //var fs : statfs;
  399. Begin
  400. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and fsstat(StrPas(fixdrivestr[drive]),fs)) or
  401. ((not (drivestr[Drive]=nil)) and fsstat(StrPas(drivestr[drive]),fs)) then
  402. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  403. else
  404. DiskSize:=-1;}
  405. DiskSize := -1;
  406. ConsolePrintf ('warning: fpc sysutils.disksize not implemented'#13#10,0);
  407. {$warning DiskSize not implemented (does it make sense ?) }
  408. End;
  409. function DirectoryExists (const Directory: string; FollowLink : Boolean): boolean;
  410. var
  411. Info : NWStatBufT;
  412. SystemFileName: RawByteString;
  413. begin
  414. SystemFileName:=ToSingleByteFileSystemEncodedFileName(Directory);
  415. If _stat (pchar(SystemFileName),Info) <> 0 then
  416. exit(false)
  417. else
  418. Exit ((Info.st_attr and faDirectory) <> 0);
  419. end;
  420. {****************************************************************************
  421. Misc Functions
  422. ****************************************************************************}
  423. procedure SysBeep;
  424. begin
  425. _RingTheBell;
  426. end;
  427. {****************************************************************************
  428. Locale Functions
  429. ****************************************************************************}
  430. Procedure GetLocalTime(var SystemTime: TSystemTime);
  431. var xx : word;
  432. begin
  433. Dos.GetTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second, xx);
  434. Dos.GetDate(SystemTime.Year, SystemTime.Month, SystemTime.Day, xx);
  435. SystemTime.MilliSecond := 0;
  436. end;
  437. Procedure InitAnsi;
  438. Var i : longint;
  439. begin
  440. { Fill table entries 0 to 127 }
  441. for i := 0 to 96 do
  442. UpperCaseTable[i] := chr(i);
  443. for i := 97 to 122 do
  444. UpperCaseTable[i] := chr(i - 32);
  445. for i := 123 to 191 do
  446. UpperCaseTable[i] := chr(i);
  447. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  448. for i := 0 to 64 do
  449. LowerCaseTable[i] := chr(i);
  450. for i := 65 to 90 do
  451. LowerCaseTable[i] := chr(i + 32);
  452. for i := 91 to 191 do
  453. LowerCaseTable[i] := chr(i);
  454. Move (CPISO88591LCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  455. end;
  456. Procedure InitInternational;
  457. begin
  458. InitInternationalGeneric;
  459. InitAnsi;
  460. end;
  461. function SysErrorMessage(ErrorCode: Integer): String;
  462. begin
  463. Result:=''; // StrError(ErrorCode);
  464. end;
  465. {****************************************************************************
  466. OS utility functions
  467. ****************************************************************************}
  468. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  469. begin
  470. Result:=_getenv(PChar(EnvVar));
  471. end;
  472. Function GetEnvironmentVariableCount : Integer;
  473. begin
  474. // Result:=FPCCountEnvVar(EnvP);
  475. Result:=0;
  476. end;
  477. Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
  478. begin
  479. // Result:=FPCGetEnvStrFromP(Envp,Index);
  480. Result:='';
  481. end;
  482. function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
  483. var
  484. e : EOSError;
  485. CommandLine: RawByteString;
  486. begin
  487. dos.exec(path,comline);
  488. if (Dos.DosError <> 0) then
  489. begin
  490. if ComLine <> '' then
  491. CommandLine := Path + ' ' + ComLine
  492. else
  493. CommandLine := Path;
  494. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,Dos.DosError]);
  495. e.ErrorCode:=Dos.DosError;
  496. raise e;
  497. end;
  498. Result := DosExitCode;
  499. end;
  500. function ExecuteProcess (const Path: RawByteString;
  501. const ComLine: array of RawByteString;Flags:TExecuteFlags=[]): integer;
  502. var
  503. CommandLine: RawByteString;
  504. I: integer;
  505. begin
  506. Commandline := '';
  507. for I := 0 to High (ComLine) do
  508. if Pos (' ', ComLine [I]) <> 0 then
  509. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  510. else
  511. CommandLine := CommandLine + ' ' + Comline [I];
  512. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  513. end;
  514. procedure Sleep(milliseconds: Cardinal);
  515. begin
  516. _delay (milliseconds);
  517. end;
  518. Function GetLastOSError : Integer;
  519. begin
  520. Result:=Integer(__get_errno_ptr^);
  521. end;
  522. {****************************************************************************
  523. Initialization code
  524. ****************************************************************************}
  525. Initialization
  526. InitExceptions; { Initialize exceptions. OS independent }
  527. InitInternational; { Initialize internationalization settings }
  528. OnBeep:=@SysBeep;
  529. Finalization
  530. FreeTerminateProcs;
  531. DoneExceptions;
  532. end.