sysutils.pp 21 KB

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