2
0

sysutils.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2004 by the Free Pascal development team.
  4. Sysutils unit for netware (libc)
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit sysutils;
  12. interface
  13. {$MODE objfpc}
  14. {$MODESWITCH OUT}
  15. { force ansistrings }
  16. {$H+}
  17. {$modeswitch typehelpers}
  18. {$modeswitch advancedrecords}
  19. uses Libc,DOS;
  20. TYPE
  21. TNetwareLibcFindData =
  22. RECORD
  23. DirP : Pdirent; { used for opendir }
  24. EntryP: Pdirent; { and readdir }
  25. Magic : longint; { to avoid abends with uninitialized TSearchRec }
  26. _mask : RawByteString; { search mask i.e. *.* }
  27. _dir : RawByteString; { directory where to search }
  28. _attr : longint; { specified attribute }
  29. fname : string; { full pathname of found file }
  30. END;
  31. {$DEFINE HAS_SLEEP}
  32. {$DEFINE HAS_OSERROR}
  33. { Include platform independent interface part }
  34. {$i sysutilh.inc}
  35. { additional NetWare file flags}
  36. CONST
  37. faSHARE = M_A_SHARE shr 16; // Sharable file
  38. //faNO_SUBALLOC = $00000800; // Don't sub alloc. this file
  39. faTRANS = M_A_TRANS shr 16; // Transactional file (TTS usable)
  40. //faREADAUD = $00004000; // clib only: Read audit
  41. //faWRITAUD = $00008000; // clib only: Write audit
  42. faIMMPURG = M_A_IMMPURG shr 16; // Immediate purge
  43. faNORENAM = M_A_NORENAM shr 16; // Rename inhibit
  44. faNODELET = M_A_NODELET shr 16; // Delete inhibit
  45. faNOCOPY = M_A_NOCOPY shr 16; // Copy inhibit
  46. //faFILE_MIGRATED = $00400000; // clib only: File has been migrated
  47. //faDONT_MIGRATE = $00800000; // clib only: Don't migrate this file
  48. faIMMEDIATE_COMPRESS = M_A_IMMCOMPRESS shr 16; // Compress this file immediately
  49. faFILE_COMPRESSED = M_A_FILE_COMPRESSED shr 16; // File is compressed
  50. faDONT_COMPRESS = M_A_DONT_COMPRESS shr 16; // Don't compress this file
  51. faCANT_COMPRESS = M_A_CANT_COMPRESS shr 16; // Can't compress this file
  52. //faATTR_ARCHIVE = $40000000; // clib only: Entry has had an EA modified,
  53. // an ownerID changed, or trustee
  54. // info changed, etc.
  55. faSetNetwareAttrs = M_A_BITS_SIGNIFICANT; // if this is set, netware flags are changed also
  56. implementation
  57. uses
  58. sysconst;
  59. {$DEFINE FPC_FEXPAND_DRIVES}
  60. {$DEFINE FPC_FEXPAND_VOLUMES}
  61. {$DEFINE FPC_FEXPAND_NO_DEFAULT_PATHS}
  62. { used OS file system APIs use ansistring }
  63. {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  64. { OS has an ansistring/single byte environment variable API }
  65. {$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
  66. { used OS file system APIs use ansistring }
  67. {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  68. { Include platform independent implementation part }
  69. {$i sysutils.inc}
  70. {****************************************************************************
  71. File Functions
  72. ****************************************************************************}
  73. Function FileOpen (Const FileName : rawbytestring; Mode : Integer) : THandle;
  74. VAR NWOpenFlags : longint;
  75. SystemFileName: RawByteString;
  76. begin
  77. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  78. NWOpenFlags:=0;
  79. Case (Mode and 3) of
  80. 0 : NWOpenFlags:=NWOpenFlags or O_RDONLY;
  81. 1 : NWOpenFlags:=NWOpenFlags or O_WRONLY;
  82. 2 : NWOpenFlags:=NWOpenFlags or O_RDWR;
  83. end;
  84. FileOpen := Fpopen (pchar(SystemFileName),NWOpenFlags);
  85. //!! We need to set locking based on Mode !!
  86. end;
  87. Function FileCreate (Const FileName : RawByteString) : THandle;
  88. var SystemFileName: RawByteString;
  89. begin
  90. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  91. FileCreate:=Fpopen(Pchar(SystemFileName),O_RdWr or O_Creat or O_Trunc or O_Binary);
  92. if FileCreate >= 0 then
  93. FileSetAttr (Filename, 0); // dont know why but open always sets ReadOnly flag
  94. end;
  95. Function FileCreate (Const FileName : RawByteString; rights:longint) : THandle;
  96. begin
  97. FileCreate:=FileCreate (FileName);
  98. end;
  99. Function FileCreate (Const FileName : RawByteString; ShareMode:longint; rights : longint) : THandle;
  100. begin
  101. FileCreate:=FileCreate (FileName);
  102. end;
  103. Function FileRead (Handle : THandle; Out Buffer; Count : longint) : Longint;
  104. begin
  105. FileRead:=libc.fpread (Handle,@Buffer,Count);
  106. end;
  107. Function FileWrite (Handle : THandle; const Buffer; Count : Longint) : Longint;
  108. begin
  109. FileWrite:=libc.fpwrite (Handle,@Buffer,Count);
  110. end;
  111. Function FileSeek (Handle : THandle; FOffset,Origin : Longint) : Longint;
  112. begin
  113. FileSeek:=libc.fplseek (Handle,FOffset,Origin);
  114. end;
  115. Function FileSeek (Handle : THandle; FOffset: Int64; Origin: Longint) : Int64;
  116. begin
  117. FileSeek:=libc.fplseek64 (Handle,FOffset,Origin);
  118. end;
  119. Procedure FileClose (Handle : THandle);
  120. begin
  121. libc.fpclose(Handle);
  122. end;
  123. Function FileTruncate (Handle : THandle; Size: Int64) : boolean;
  124. begin
  125. if Size > high (longint) then
  126. FileTruncate := false
  127. {$WARNING Possible support for 64-bit FS to be checked!}
  128. else
  129. FileTruncate:=(libc.fpchsize(Handle,Size) = 0);
  130. end;
  131. Function FileLock (Handle : THandle; FOffset,FLen : Longint) : Longint;
  132. begin
  133. {$warning FileLock not implemented}
  134. //FileLock := _lock (Handle,FOffset,FLen);
  135. FileLock := -1;
  136. end;
  137. Function FileLock (Handle : THandle; FOffset,FLen : Int64) : Longint;
  138. begin
  139. {$warning need to add 64bit FileLock call }
  140. //FileLock := FileLock (Handle, longint(FOffset),longint(FLen));
  141. FileLock := -1;
  142. end;
  143. Function FileUnlock (Handle : THandle; FOffset,FLen : Longint) : Longint;
  144. begin
  145. //FileUnlock := _unlock (Handle,FOffset,FLen);
  146. {$warning FileUnLock not implemented}
  147. FileUnlock := -1;
  148. end;
  149. Function FileUnlock (Handle : THandle; FOffset,FLen : Int64) : Longint;
  150. begin
  151. {$warning need to add 64bit FileUnlock call }
  152. //FileUnlock := FileUnlock (Handle, longint(FOffset),longint(FLen));
  153. FileUnlock := -1;
  154. end;
  155. Function FileAge (Const FileName : RawByteString): Int64;
  156. var Info : TStat;
  157. TM : TTM;
  158. SystemFileName: RawByteString;
  159. begin
  160. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  161. If Fpstat (pchar(SystemFileName),Info) <> 0 then
  162. exit(-1)
  163. else
  164. begin
  165. localtime_r (Info.st_mtim.tv_sec,tm);
  166. with TM do
  167. result:=DateTimeToFileDate(EncodeDate(tm_year+1900,tm_mon+1,tm_mday)+EncodeTime(tm_hour,tm_min,tm_sec,0));
  168. end;
  169. end;
  170. function FileGetSymLinkTarget(const FileName: RawByteString; out SymLinkRec: TRawbyteSymLinkRec): Boolean;
  171. begin
  172. Result := False;
  173. end;
  174. Function FileExists (Const FileName : RawByteString; FollowLink : Boolean) : Boolean;
  175. VAR Info : TStat;
  176. SystemFileName: RawByteString;
  177. begin
  178. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  179. FileExists:=(Fpstat(pchar(SystemFileName),Info) = 0);
  180. end;
  181. Function UnixToWinAge(UnixAge : time_t): Longint;
  182. Var tm : TTm;
  183. begin
  184. libc.localtime_r (UnixAge, tm);
  185. with tm do
  186. Result:=DateTimeToFileDate(EncodeDate(tm_year+1900,tm_mon+1,tm_mday)+EncodeTime(tm_hour,tm_min,tm_sec,0));
  187. end;
  188. {returns true if attributes match}
  189. function find_setfields (var f : TsearchRec; var AttrsOk : boolean; var Name : RawByteString) : longint;
  190. var
  191. StatBuf : TStat;
  192. fname : RawByteString;
  193. begin
  194. result := 0;
  195. with F do
  196. begin
  197. if FindData.Magic = $AD02 then
  198. begin
  199. attr := (Pdirent(FindData.EntryP)^.d_mode shr 16) and $ffff;
  200. size := Pdirent(FindData.EntryP)^.d_size;
  201. name := Pdirent(FindData.EntryP)^.d_name;
  202. SetCodePage(name, DefaultFileSystemCodePage, False);
  203. fname := FindData._dir + name;
  204. if Fpstat (pchar(fname),StatBuf) = 0 then
  205. time := UnixToWinAge (StatBuf.st_mtim.tv_sec)
  206. else
  207. time := 0;
  208. AttrsOk := false;
  209. if (f.FindData._attr and faHidden) = 0 then
  210. if attr and faHidden > 0 then exit;
  211. if (f.FindData._attr and faDirectory) = 0 then
  212. if attr and faDirectory > 0 then exit;
  213. if (f.FindData._attr and faSysFile) = 0 then
  214. if attr and faSysFile > 0 then exit;
  215. AttrsOk := true;
  216. end else
  217. begin
  218. name :='';
  219. result := 18;
  220. end;
  221. end;
  222. end;
  223. Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
  224. var
  225. SystemEncodedPath: RawByteString;
  226. path0 : string;
  227. p : longint;
  228. begin
  229. IF path = '' then
  230. begin
  231. result := 18;
  232. exit;
  233. end;
  234. SystemEncodedPath := ToSingleByteEncodedFileName(Path);
  235. Rslt.FindData._attr := attr;
  236. p := length (SystemEncodedPath);
  237. while (p > 0) and (not (SystemEncodedPath[p] in AllowDirectorySeparators)) do
  238. dec (p);
  239. if p > 0 then
  240. begin
  241. Rslt.FindData._mask := copy (SystemEncodedPath,p+1,high (longint));
  242. Rslt.FindData._dir := copy (SystemEncodedPath,1,p);
  243. end else
  244. begin
  245. Rslt.FindData._mask := SystemEncodedPath;
  246. Rslt.FindData._dir := GetCurrentDir;
  247. if (Rslt.FindData._dir[length(Rslt.FindData._dir)] <> '/') and
  248. (Rslt.FindData._dir[length(Rslt.FindData._dir)] <> '\') then
  249. Rslt.FindData._dir := Rslt.FindData._dir + '/';
  250. end;
  251. if Rslt.FindData._mask = '*' then Rslt.FindData._mask := '';
  252. if Rslt.FindData._mask = '*.*' then Rslt.FindData._mask := '';
  253. //writeln (stderr,'mask: "',Rslt._mask,'" dir:"',path0,'"');
  254. Pdirent(Rslt.FindData.DirP) := opendir (pchar(Rslt.FindData._dir));
  255. if Rslt.FindData.DirP = nil then
  256. result := 18
  257. else begin
  258. Rslt.FindData.Magic := $AD02;
  259. result := findnext (Rslt);
  260. end;
  261. end;
  262. Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
  263. var attrsOk : boolean;
  264. begin
  265. if Rslt.FindData.Magic <> $AD02 then
  266. begin
  267. result := 18;
  268. exit;
  269. end;
  270. result:=0;
  271. repeat
  272. Pdirent(Rslt.FindData.EntryP) := readdir (Pdirent(Rslt.FindData.DirP));
  273. if Rslt.FindData.EntryP = nil then
  274. result := 18
  275. else
  276. result := find_setfields (Rslt,attrsOk,Name);
  277. if (result = 0) and (attrsOk) then
  278. begin
  279. if Rslt.FindData._mask = #0 then exit;
  280. if fnmatch(@Rslt.FindData._mask[1],Pdirent(Rslt.FindData.EntryP)^.d_name,FNM_CASEFOLD) = 0 then
  281. exit;
  282. end;
  283. until result <> 0;
  284. end;
  285. Procedure InternalFindClose (var Handle: THandle; var FindData: TFindData);
  286. begin
  287. if FindData.Magic <> $AD02 then exit;
  288. doserror:=0;
  289. closedir (Pdirent(FindData.DirP));
  290. FillChar (FindData,sizeof(FindData),0);
  291. end;
  292. Function FileGetDate (Handle : THandle) : Int64;
  293. Var Info : TStat;
  294. _PTM : PTM;
  295. begin
  296. If Fpfstat(Handle,Info) <> 0 then
  297. Result:=-1
  298. else
  299. begin
  300. _PTM := localtime (Info.st_mtim.tv_sec);
  301. IF _PTM = NIL THEN
  302. exit(-1)
  303. else
  304. with _PTM^ do
  305. Result:=DateTimeToFileDate(EncodeDate(tm_year+1900,tm_mon+1,tm_mday)+EncodeTime(tm_hour,tm_min,tm_sec,0));
  306. end;
  307. end;
  308. Function FileSetDate (Handle : THandle; Age : Longint) : Longint;
  309. Begin
  310. {dont know how to do that, utime needs filename}
  311. result := -1;
  312. end;
  313. Function FileGetAttr (Const FileName : RawByteString) : Longint;
  314. Var Info : TStat;
  315. SystemFileName: RawByteString;
  316. begin
  317. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  318. If Fpstat (pchar(SystemFileName),Info) <> 0 then
  319. Result:=-1
  320. Else
  321. Result := (Info.st_mode shr 16) and $ffff;
  322. end;
  323. Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
  324. var
  325. StatBuf : TStat;
  326. newMode : longint;
  327. SystemFileName: RawByteString;
  328. begin
  329. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  330. if Fpstat (pchar(SystemFilename),StatBuf) = 0 then
  331. begin
  332. {what should i do here ?
  333. only support sysutils-standard attributes or also support the extensions defined
  334. only for netware libc ?
  335. For now i allow the complete attributes if the bit faSetNetwareAttrs is set. Otherwise
  336. only the standard attributes can be modified}
  337. if attr and faSetNetwareAttrs > 0 then
  338. begin
  339. newmode := ((attr shl 16) and $ffff0000) or M_A_BITS_SIGNIFICANT;
  340. end else
  341. begin
  342. attr := (attr and $2f) shl 16;
  343. newmode := StatBuf.st_mode and ($ffff0000-M_A_RDONLY-M_A_HIDDEN- M_A_SYSTEM-M_A_SUBDIR-M_A_ARCH);
  344. newmode := newmode or (attr shl 16) or M_A_BITS_SIGNIFICANT;
  345. end;
  346. if Fpchmod (pchar(SystemFilename),newMode) < 0 then
  347. result := ___errno^ else
  348. result := 0;
  349. end else
  350. result := ___errno^;
  351. end;
  352. Function DeleteFile (Const FileName : RawByteString) : Boolean;
  353. var
  354. SystemFileName: RawByteString;
  355. begin
  356. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  357. Result:= (libc.UnLink (pchar(SystemFileName)) = 0);
  358. end;
  359. Function RenameFile (Const OldName, NewName : String) : Boolean;
  360. var
  361. OldSystemFileName, NewSystemFileName: RawByteString;
  362. begin
  363. OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);
  364. NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName);
  365. RenameFile:=(libc.rename(pchar(OldSystemFileName),pchar(NewSystemFileName)) = 0);
  366. end;
  367. {****************************************************************************
  368. Disk Functions
  369. ****************************************************************************}
  370. {
  371. The Diskfree and Disksize functions need a file on the specified drive, since this
  372. is required for the statfs system call.
  373. These filenames are set in drivestr[0..26], and have been preset to :
  374. 0 - '.' (default drive - hence current dir is ok.)
  375. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  376. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  377. 3 - '/' (C: equivalent of dos is the root partition)
  378. 4..26 (can be set by you're own applications)
  379. ! Use AddDisk() to Add new drives !
  380. They both return -1 when a failure occurs.
  381. }
  382. Const
  383. FixDriveStr : array[0..3] of pchar=(
  384. '.',
  385. 'a:.',
  386. 'b:.',
  387. 'sys:/'
  388. );
  389. var
  390. Drives : byte;
  391. DriveStr : array[4..26] of pchar;
  392. Procedure AddDisk(const path:string);
  393. begin
  394. if not (DriveStr[Drives]=nil) then
  395. FreeMem(DriveStr[Drives],StrLen(DriveStr[Drives])+1);
  396. GetMem(DriveStr[Drives],length(Path)+1);
  397. StrPCopy(DriveStr[Drives],path);
  398. inc(Drives);
  399. if Drives>26 then
  400. Drives:=4;
  401. end;
  402. Function DiskFree(Drive: Byte): int64;
  403. //var fs : Tstatfs;
  404. Begin
  405. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and fsstat(StrPas(fixdrivestr[drive]),fs)) or
  406. ((not (drivestr[Drive]=nil)) and fsstat(StrPas(drivestr[drive]),fs)) then
  407. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  408. else
  409. Diskfree:=-1;}
  410. DiskFree := -1;
  411. ConsolePrintf ('warning: fpc sysutils.diskfree not implemented'#13#10);
  412. {$warning DiskFree not implemented (does it make sense ?) }
  413. End;
  414. Function DiskSize(Drive: Byte): int64;
  415. //var fs : statfs;
  416. Begin
  417. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and fsstat(StrPas(fixdrivestr[drive]),fs)) or
  418. ((not (drivestr[Drive]=nil)) and fsstat(StrPas(drivestr[drive]),fs)) then
  419. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  420. else
  421. DiskSize:=-1;}
  422. DiskSize := -1;
  423. ConsolePrintf ('warning: fpc sysutils.disksize not implemented'#13#10);
  424. {$warning DiskSize not implemented (does it make sense ?) }
  425. End;
  426. function DirectoryExists (const Directory: RawByteString; FollowLink : Boolean): boolean;
  427. var
  428. Info : TStat;
  429. SystemFileName: RawByteString;
  430. begin
  431. SystemFileName:=ToSingleByteFileSystemEncodedFileName(Directory);
  432. If Fpstat (pchar(SystemFileName),Info) <> 0 then
  433. exit(false)
  434. else
  435. Exit ((Info.st_mode and M_A_SUBDIR) <> 0);
  436. end;
  437. {****************************************************************************
  438. Misc Functions
  439. ****************************************************************************}
  440. procedure SysBeep;
  441. begin
  442. RingBell;
  443. end;
  444. {****************************************************************************
  445. Locale Functions
  446. ****************************************************************************}
  447. Procedure GetLocalTime(var SystemTime: TSystemTime);
  448. var t : TTime_t;
  449. tm: Ttm;
  450. begin
  451. libc.time(t);
  452. libc.localtime_r(t,tm);
  453. with SystemTime do
  454. begin
  455. Hour := tm.tm_hour;
  456. Minute := tm.tm_min;
  457. Second := tm.tm_sec;
  458. MilliSecond := 0;
  459. Day := tm.tm_mday;
  460. Month := tm.tm_mon+1;
  461. Year := tm.tm_year+1900;
  462. end;
  463. end;
  464. Procedure InitAnsi;
  465. Var i : longint;
  466. begin
  467. { Fill table entries 0 to 127 }
  468. for i := 0 to 96 do
  469. UpperCaseTable[i] := chr(i);
  470. for i := 97 to 122 do
  471. UpperCaseTable[i] := chr(i - 32);
  472. for i := 123 to 191 do
  473. UpperCaseTable[i] := chr(i);
  474. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  475. for i := 0 to 64 do
  476. LowerCaseTable[i] := chr(i);
  477. for i := 65 to 90 do
  478. LowerCaseTable[i] := chr(i + 32);
  479. for i := 91 to 191 do
  480. LowerCaseTable[i] := chr(i);
  481. Move (CPISO88591LCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  482. end;
  483. Procedure InitInternational;
  484. begin
  485. InitInternationalGeneric;
  486. InitAnsi;
  487. end;
  488. function SysErrorMessage(ErrorCode: Integer): String;
  489. begin
  490. Result:=''; // only found perror that prints the message
  491. end;
  492. {****************************************************************************
  493. OS utility functions
  494. ****************************************************************************}
  495. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  496. begin
  497. Result:=libc.getenv(PChar(EnvVar));
  498. end;
  499. Function GetEnvironmentVariableCount : Integer;
  500. begin
  501. Result:=FPCCountEnvVar(EnvP);
  502. end;
  503. Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
  504. begin
  505. Result:=FPCGetEnvStrFromP(Envp,Index);
  506. end;
  507. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString;Flags:TExecuteFlags=[]):integer;
  508. var
  509. params:array of AnsiString;
  510. count,i: longint;
  511. Buf : pchar;
  512. p : pchar;
  513. CLine: AnsiString;
  514. begin
  515. cLine := ComLine;
  516. buf:=pchar(CLine);
  517. count:=0;
  518. while(buf^<>#0) do
  519. begin
  520. while (buf^ in [' ',#9,#10]) do
  521. inc(buf);
  522. inc(count);
  523. while not (buf^ in [' ',#0,#9,#10]) do
  524. inc(buf);
  525. end;
  526. i := 0;
  527. setlength(params,count);
  528. buf:=pchar(CLine);
  529. while(buf^<>#0) do
  530. begin
  531. while (buf^ in [' ',#9,#10]) do
  532. inc(buf);
  533. p := buf;
  534. while not (buf^ in [' ',#0,#9,#10]) do
  535. inc(buf);
  536. if buf^ <> #0 then
  537. begin
  538. buf^ := #0;
  539. inc(buf);
  540. end;
  541. params[i]:=p;
  542. inc(i);
  543. end;
  544. result := ExecuteProcess (Path, params);
  545. end;
  546. Function GetLastOSError : Integer;
  547. begin
  548. Result:=Integer(GetLastError);
  549. end;
  550. {******************************************************************************
  551. --- Exec ---
  552. ******************************************************************************}
  553. const maxargs=256;
  554. function ExecuteProcess (const Path: AnsiString;
  555. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  556. var c : comstr;
  557. i : integer;
  558. args : array[0..maxargs+1] of pchar;
  559. arg0 : string;
  560. numargs,wstat : integer;
  561. Wiring : TWiring;
  562. newPath : string;
  563. e : EOSError;
  564. begin
  565. if pos ('.',path) = 0 then
  566. arg0 := fexpand(path+'.nlm')
  567. else
  568. arg0 := fexpand (path);
  569. args[0] := pchar(arg0);
  570. numargs := 0;
  571. for I := 0 to High (ComLine) do
  572. if numargs < maxargs then
  573. begin
  574. inc(numargs);
  575. args[numargs] := pchar(ComLine[i]);
  576. end;
  577. args[numargs+1] := nil;
  578. Wiring.infd := StdInputHandle; //textrec(Stdin).Handle;
  579. Wiring.outfd:= textrec(stdout).Handle;
  580. Wiring.errfd:= textrec(stderr).Handle;
  581. i := procve(args[0],
  582. PROC_CURRENT_SPACE+PROC_INHERIT_CWD,
  583. envP, // const char * env[] If passed as NULL, the child process inherits the parent.s environment at the time of the call.
  584. @Wiring, // wiring_t *wiring, Pass NULL to inherit system defaults for wiring.
  585. nil, // struct fd_set *fds, Not currently implemented. Pass in NULL.
  586. nil, // void *appdata, Not currently implemented. Pass in NULL.
  587. 0, // size_t appdata_size, Not currently implemented. Pass in 0
  588. nil, // void *reserved, Reserved. Pass NULL.
  589. @args); // const char *argv[]
  590. if i <> -1 then
  591. begin
  592. Fpwaitpid(i,@wstat,0);
  593. result := wstat;
  594. end else
  595. begin
  596. e:=EOSError.CreateFmt(SExecuteProcessFailed,[arg0,___errno^]);
  597. e.ErrorCode:=___errno^;
  598. raise e;
  599. end;
  600. end;
  601. procedure Sleep(milliseconds: Cardinal);
  602. begin
  603. libc._delay (milliseconds);
  604. end;
  605. {****************************************************************************
  606. Initialization code
  607. ****************************************************************************}
  608. Initialization
  609. InitExceptions; { Initialize exceptions. OS independent }
  610. InitInternational; { Initialize internationalization settings }
  611. Finalization
  612. FreeTerminateProcs;
  613. DoneExceptions;
  614. end.