dos.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2001 by members of the Free Pascal
  4. development team
  5. DOS unit template based on POSIX
  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 Dos;
  13. Interface
  14. {$goto on}
  15. Const
  16. FileNameLen = 255;
  17. Type
  18. SearchRec = packed Record
  19. {Fill : array[1..21] of byte; Fill replaced with below}
  20. DirPtr : pointer; {directory pointer for reading directory}
  21. SearchAttr : Byte; {attribute we are searching for}
  22. Fill : Array[1..16] of Byte; {future use}
  23. {End of fill}
  24. Attr : Byte; {attribute of found file}
  25. Time : LongInt; {last modify date of found file}
  26. Size : LongInt; {file size of found file}
  27. Reserved : Word; {future use}
  28. Name : String[FileNameLen]; {name of found file}
  29. SearchSpec : String[FileNameLen]; {search pattern}
  30. SearchDir : String[FileNameLen]; { path we are searching in }
  31. End;
  32. {$DEFINE HAS_FILENAMELEN}
  33. {$I dosh.inc}
  34. Procedure AddDisk(const path:string);
  35. Implementation
  36. Uses
  37. strings,posix;
  38. (* Potentially needed FPC_FEXPAND_* defines should be defined here. *)
  39. {$I dos.inc}
  40. { Used by AddDisk(), DiskFree() and DiskSize() }
  41. const
  42. Drives : byte = 4;
  43. MAX_DRIVES = 26;
  44. var
  45. DriveStr : array[4..MAX_DRIVES] of pchar;
  46. Function StringToPPChar(Var S:STring; var count : longint):ppchar;
  47. {
  48. Create a PPChar to structure of pchars which are the arguments specified
  49. in the string S. Especially usefull for creating an ArgV for Exec-calls
  50. }
  51. var
  52. nr : longint;
  53. Buf : ^char;
  54. p : ppchar;
  55. begin
  56. s:=s+#0;
  57. buf:=@s[1];
  58. nr:=0;
  59. while(buf^<>#0) do
  60. begin
  61. while (buf^ in [' ',#8,#10]) do
  62. inc(buf);
  63. inc(nr);
  64. while not (buf^ in [' ',#0,#8,#10]) do
  65. inc(buf);
  66. end;
  67. getmem(p,nr*4);
  68. StringToPPChar:=p;
  69. if p=nil then
  70. begin
  71. Errno:=sys_enomem;
  72. count := 0;
  73. exit;
  74. end;
  75. buf:=@s[1];
  76. while (buf^<>#0) do
  77. begin
  78. while (buf^ in [' ',#8,#10]) do
  79. begin
  80. buf^:=#0;
  81. inc(buf);
  82. end;
  83. p^:=buf;
  84. inc(p);
  85. p^:=nil;
  86. while not (buf^ in [' ',#0,#8,#10]) do
  87. inc(buf);
  88. end;
  89. count := nr;
  90. end;
  91. {$i dos_beos.inc} { include OS specific stuff }
  92. {******************************************************************************
  93. --- Info / Date / Time ---
  94. ******************************************************************************}
  95. var
  96. TZSeconds : longint; { offset to add/ subtract from Epoch to get local time }
  97. tzdaylight : boolean;
  98. tzname : array[boolean] of pchar;
  99. type
  100. GTRec = packed Record
  101. Year,
  102. Month,
  103. MDay,
  104. WDay,
  105. Hour,
  106. Minute,
  107. Second : Word;
  108. End;
  109. Const
  110. {Date Calculation}
  111. C1970 = 2440588;
  112. D0 = 1461;
  113. D1 = 146097;
  114. D2 = 1721119;
  115. function WeekDay (y,m,d:longint):longint;
  116. {
  117. Calculates th day of the week. returns -1 on error
  118. }
  119. var
  120. u,v : longint;
  121. begin
  122. if (m<1) or (m>12) or (y<1600) or (y>4000) or
  123. (d<1) or (d>30+((m+ord(m>7)) and 1)-ord(m=2)) or
  124. ((m*d=58) and (((y mod 4>0) or (y mod 100=0)) and (y mod 400>0))) then
  125. WeekDay:=-1
  126. else
  127. begin
  128. u:=m;
  129. v:=y;
  130. if m<3 then
  131. begin
  132. inc(u,12);
  133. dec(v);
  134. end;
  135. WeekDay:=(d+2*u+((3*(u+1)) div 5)+v+(v div 4)-(v div 100)+(v div 400)+1) mod 7;
  136. end;
  137. end;
  138. Procedure JulianToGregorian(JulianDN:LongInt;Var Year,Month,Day:Word);
  139. Var
  140. YYear,XYear,Temp,TempMonth : LongInt;
  141. Begin
  142. Temp:=((JulianDN-D2) shl 2)-1;
  143. JulianDN:=Temp Div D1;
  144. XYear:=(Temp Mod D1) or 3;
  145. YYear:=(XYear Div D0);
  146. Temp:=((((XYear mod D0)+4) shr 2)*5)-3;
  147. Day:=((Temp Mod 153)+5) Div 5;
  148. TempMonth:=Temp Div 153;
  149. If TempMonth>=10 Then
  150. Begin
  151. inc(YYear);
  152. dec(TempMonth,12);
  153. End;
  154. inc(TempMonth,3);
  155. Month := TempMonth;
  156. Year:=YYear+(JulianDN*100);
  157. end;
  158. Procedure EpochToLocal(epoch:time_t;var year,month,day,hour,minute,second:Word);
  159. {
  160. Transforms Epoch time into local time (hour, minute,seconds)
  161. }
  162. Var
  163. DateNum: time_t;
  164. Begin
  165. Epoch:=Epoch+TZSeconds;
  166. Datenum:=(Epoch Div 86400) + c1970;
  167. JulianToGregorian(DateNum,Year,Month,day);
  168. Epoch:=Abs(Epoch Mod 86400);
  169. Hour:=Epoch Div 3600;
  170. Epoch:=Epoch Mod 3600;
  171. Minute:=Epoch Div 60;
  172. Second:=Epoch Mod 60;
  173. End;
  174. Procedure GetDate(Var Year, Month, MDay, WDay: Word);
  175. var
  176. hour,minute,second : word;
  177. timeval : time_t;
  178. Begin
  179. timeval := sys_time(timeval);
  180. { convert the GMT time to local time }
  181. EpochToLocal(timeval,year,month,mday,hour,minute,second);
  182. Wday:=weekday(Year,Month,MDay);
  183. end;
  184. Procedure SetDate(Year, Month, Day: Word);
  185. Begin
  186. {!!}
  187. End;
  188. Procedure GetTime(Var Hour, Minute, Second, Sec100: Word);
  189. var
  190. timeval : time_t;
  191. year,month,day: word;
  192. Begin
  193. timeval := sys_time(timeval);
  194. EpochToLocal(timeval,year,month,day,hour,minute,second);
  195. Sec100 := 0;
  196. end;
  197. Procedure SetTime(Hour, Minute, Second, Sec100: Word);
  198. Begin
  199. {!!}
  200. End;
  201. Procedure UnixDateToDt(SecsPast: LongInt; Var Dt: DateTime);
  202. Begin
  203. EpochToLocal(SecsPast,dt.Year,dt.Month,dt.Day,dt.Hour,dt.Min,dt.Sec);
  204. End;
  205. {$ifndef DOS_HAS_EXEC}
  206. {******************************************************************************
  207. --- Exec ---
  208. ******************************************************************************}
  209. Function InternalWaitProcess(Pid:pid_t):Longint; { like WaitPid(PID,@result,0) Handling of Signal interrupts (errno=EINTR), returning the Exitcode of Process (>=0) or -Status if terminated}
  210. var r,s : cint;
  211. begin
  212. repeat
  213. s:=$7F00;
  214. r:=sys_WaitPid(Pid,s,0);
  215. until (r<>-1) or (Errno<>Sys_EINTR);
  216. { When r = -1 or r = 0, no status is available, so there was an error. }
  217. if (r=-1) or (r=0) then
  218. InternalWaitProcess:=-1 { return -1 to indicate an error }
  219. else
  220. begin
  221. { process terminated normally }
  222. if wifexited(s)<>0 then
  223. begin
  224. { get status code }
  225. InternalWaitProcess := wexitstatus(s);
  226. exit;
  227. end;
  228. { process terminated due to a signal }
  229. if wifsignaled(s)<>0 then
  230. begin
  231. { get signal number }
  232. InternalWaitProcess := wstopsig(s);
  233. exit;
  234. end;
  235. InternalWaitProcess:=-1;
  236. end;
  237. end;
  238. Procedure Exec (Const Path: PathStr; Const ComLine: ComStr);
  239. var
  240. pid : pid_t;
  241. tmp : string;
  242. p : ppchar;
  243. count: longint;
  244. // The Error-Checking in the previous Version failed, since halt($7F) gives an WaitPid-status of $7F00
  245. F: File;
  246. Begin
  247. {$IFOPT I+}
  248. {$DEFINE IOCHECK}
  249. {$ENDIF}
  250. {$I-}
  251. { verify if the file to execute exists }
  252. Assign(F,Path);
  253. Reset(F,1);
  254. if IOResult <> 0 then
  255. { file not found }
  256. begin
  257. DosError := 2;
  258. exit;
  259. end
  260. else
  261. Close(F);
  262. {$IFDEF IOCHECK}
  263. {$I+}
  264. {$UNDEF IOCHECK}
  265. {$ENDIF}
  266. LastDosExitCode:=0;
  267. { Fork the process }
  268. pid:=sys_Fork;
  269. if pid=0 then
  270. begin
  271. {The child does the actual execution, and then exits}
  272. tmp := Path+' '+ComLine;
  273. p:=StringToPPChar(tmp,count);
  274. if (p<>nil) and (p^<>nil) then
  275. begin
  276. sys_Execve(p^,p,Envp);
  277. end;
  278. {If the execve fails, we return an exitvalue of 127, to let it be known}
  279. sys_exit(127);
  280. end
  281. else
  282. if pid=-1 then {Fork failed - parent only}
  283. begin
  284. DosError:=8;
  285. exit
  286. end;
  287. {We're in the parent, let's wait.}
  288. LastDosExitCode:=InternalWaitProcess(pid); // WaitPid and result-convert
  289. if (LastDosExitCode>=0) and (LastDosExitCode<>127) then DosError:=0 else
  290. DosError:=8; // perhaps one time give an better error
  291. End;
  292. {$ENDIF}
  293. {******************************************************************************
  294. --- Disk ---
  295. ******************************************************************************}
  296. Procedure AddDisk(const path:string);
  297. begin
  298. if not (DriveStr[Drives]=nil) then
  299. FreeMem(DriveStr[Drives],StrLen(DriveStr[Drives])+1);
  300. GetMem(DriveStr[Drives],length(Path)+1);
  301. StrPCopy(DriveStr[Drives],path);
  302. inc(Drives);
  303. if Drives>26 then
  304. Drives:=4;
  305. end;
  306. {******************************************************************************
  307. --- Findfirst FindNext ---
  308. ******************************************************************************}
  309. Function FNMatch(const Pattern,Name:string):Boolean;
  310. Var
  311. LenPat,LenName : longint;
  312. Function DoFNMatch(i,j:longint):Boolean;
  313. Var
  314. Found : boolean;
  315. Begin
  316. Found:=true;
  317. While Found and (i<=LenPat) Do
  318. Begin
  319. Case Pattern[i] of
  320. '?' : Found:=(j<=LenName);
  321. '*' : Begin
  322. {find the next character in pattern, different of ? and *}
  323. while Found and (i<LenPat) do
  324. begin
  325. inc(i);
  326. case Pattern[i] of
  327. '*' : ;
  328. '?' : begin
  329. inc(j);
  330. Found:=(j<=LenName);
  331. end;
  332. else
  333. Found:=false;
  334. end;
  335. end;
  336. {Now, find in name the character which i points to, if the * or ?
  337. wasn't the last character in the pattern, else, use up all the
  338. chars in name}
  339. Found:=true;
  340. if (i<=LenPat) then
  341. begin
  342. repeat
  343. {find a letter (not only first !) which maches pattern[i]}
  344. while (j<=LenName) and (name[j]<>pattern[i]) do
  345. inc (j);
  346. if (j<LenName) then
  347. begin
  348. if DoFnMatch(i+1,j+1) then
  349. begin
  350. i:=LenPat;
  351. j:=LenName;{we can stop}
  352. Found:=true;
  353. end
  354. else
  355. inc(j);{We didn't find one, need to look further}
  356. end;
  357. until (j>=LenName);
  358. end
  359. else
  360. j:=LenName;{we can stop}
  361. end;
  362. else {not a wildcard character in pattern}
  363. Found:=(j<=LenName) and (pattern[i]=name[j]);
  364. end;
  365. inc(i);
  366. inc(j);
  367. end;
  368. DoFnMatch:=Found and (j>LenName);
  369. end;
  370. Begin {start FNMatch}
  371. LenPat:=Length(Pattern);
  372. LenName:=Length(Name);
  373. FNMatch:=DoFNMatch(1,1);
  374. End;
  375. Procedure FindClose(Var f: SearchRec);
  376. {
  377. Closes dirptr if it is open
  378. }
  379. Begin
  380. { could already have been closed }
  381. if assigned(f.dirptr) then
  382. sys_closedir(pdir(f.dirptr));
  383. f.dirptr := nil;
  384. End;
  385. { Returns a filled in searchRec structure }
  386. { and TRUE if the specified file in s is }
  387. { found. }
  388. Function FindGetFileInfo(s:string;var f:SearchRec):boolean;
  389. var
  390. DT : DateTime;
  391. st : stat;
  392. Fmode : byte;
  393. res: string; { overlaid variable }
  394. Dir : DirsTr;
  395. Name : NameStr;
  396. Ext: ExtStr;
  397. begin
  398. FindGetFileInfo:=false;
  399. res := s + #0;
  400. if sys_stat(@res[1],st)<>0 then
  401. exit;
  402. if S_ISDIR(st.st_mode) then
  403. fmode:=directory
  404. else
  405. fmode:=0;
  406. if (st.st_mode and S_IWUSR)=0 then
  407. fmode:=fmode or readonly;
  408. FSplit(s,Dir,Name,Ext);
  409. if Name[1]='.' then
  410. fmode:=fmode or hidden;
  411. If ((FMode and Not(f.searchattr))=0) Then
  412. Begin
  413. if Ext <> '' then
  414. res := Name + Ext
  415. else
  416. res := Name;
  417. f.Name:=res;
  418. f.Attr:=FMode;
  419. f.Size:=longint(st.st_size);
  420. UnixDateToDT(st.st_mtime, DT);
  421. PackTime(DT,f.Time);
  422. FindGetFileInfo:=true;
  423. End;
  424. end;
  425. Procedure FindNext(Var f: SearchRec);
  426. {
  427. re-opens dir if not already in array and calls FindWorkProc
  428. }
  429. Var
  430. FName,
  431. SName : string;
  432. Found,
  433. Finished : boolean;
  434. p : PDirEnt;
  435. Begin
  436. {Main loop}
  437. SName:=f.SearchSpec;
  438. Found:=False;
  439. Finished:=(f.dirptr=nil);
  440. While Not Finished Do
  441. Begin
  442. p:=sys_readdir(pdir(f.dirptr));
  443. if p=nil then
  444. begin
  445. FName:=''
  446. end
  447. else
  448. FName:=Strpas(@p^.d_name);
  449. If FName='' Then
  450. Finished:=True
  451. Else
  452. Begin
  453. If FNMatch(SName,FName) Then
  454. Begin
  455. Found:=FindGetFileInfo(f.SearchDir+FName,f);
  456. if Found then
  457. begin
  458. Finished:=true;
  459. end;
  460. End;
  461. End;
  462. End;
  463. {Shutdown}
  464. If Found Then
  465. Begin
  466. DosError:=0;
  467. End
  468. Else
  469. Begin
  470. FindClose(f);
  471. { FindClose() might be called thereafter also... }
  472. f.dirptr := nil;
  473. DosError:=18;
  474. End;
  475. End;
  476. Procedure FindFirst(Const Path: PathStr; Attr: Word; Var f: SearchRec);
  477. {
  478. opens dir
  479. }
  480. var
  481. res: string;
  482. Dir : DirsTr;
  483. Name : NameStr;
  484. Ext: ExtStr;
  485. Begin
  486. { initialize f.dirptr because it is used }
  487. { to see if we need to close the dir stream }
  488. f.dirptr := nil;
  489. if Path='' then
  490. begin
  491. DosError:=3;
  492. exit;
  493. end;
  494. {We always also search for readonly and archive, regardless of Attr:}
  495. f.SearchAttr := Attr or archive or readonly;
  496. {Wildcards?}
  497. if (Pos('?',Path)=0) and (Pos('*',Path)=0) then
  498. begin
  499. if FindGetFileInfo(Path,f) then
  500. DosError:=0
  501. else
  502. begin
  503. if ErrNo=Sys_ENOENT then
  504. DosError:=3
  505. else
  506. DosError:=18;
  507. end;
  508. f.DirPtr:=nil;
  509. end
  510. else
  511. {Find Entry}
  512. begin
  513. FSplit(Path,Dir,Name,Ext);
  514. if Ext <> '' then
  515. res := Name + Ext
  516. else
  517. res := Name;
  518. f.SearchSpec := res;
  519. { if dir is an empty string }
  520. { then this indicates that }
  521. { use the current working }
  522. { directory. }
  523. if dir = '' then
  524. dir := './';
  525. f.SearchDir := Dir;
  526. { add terminating null character }
  527. Dir := Dir + #0;
  528. f.dirptr := sys_opendir(@Dir[1]);
  529. if not assigned(f.dirptr) then
  530. begin
  531. DosError := 8;
  532. exit;
  533. end;
  534. FindNext(f);
  535. end;
  536. End;
  537. {******************************************************************************
  538. --- File ---
  539. ******************************************************************************}
  540. Function FSearch(const path:pathstr;dirlist:string):pathstr;
  541. {
  542. Searches for a file 'path' in the list of direcories in 'dirlist'.
  543. returns an empty string if not found. Wildcards are NOT allowed.
  544. If dirlist is empty, it is set to '.'
  545. }
  546. Var
  547. NewDir : PathStr;
  548. p1 : Longint;
  549. Info : Stat;
  550. buffer : array[0..FileNameLen+1] of char;
  551. Begin
  552. Move(path[1], Buffer, Length(path));
  553. Buffer[Length(path)]:=#0;
  554. if (length(Path)>0) and (path[1]='/') and (sys_stat(pchar(@Buffer),info)=0) then
  555. begin
  556. FSearch:=path;
  557. exit;
  558. end;
  559. {Replace ':' with ';'}
  560. for p1:=1to length(dirlist) do
  561. if dirlist[p1]=':' then
  562. dirlist[p1]:=';';
  563. {Check for WildCards}
  564. If (Pos('?',Path) <> 0) or (Pos('*',Path) <> 0) Then
  565. FSearch:='' {No wildcards allowed in these things.}
  566. Else
  567. Begin
  568. Dirlist:='.;'+dirlist;{Make sure current dir is first to be searched.}
  569. Repeat
  570. p1:=Pos(';',DirList);
  571. If p1=0 Then
  572. p1:=255;
  573. NewDir:=Copy(DirList,1,P1 - 1);
  574. if NewDir[Length(NewDir)]<>'/' then
  575. NewDir:=NewDir+'/';
  576. NewDir:=NewDir+Path;
  577. Delete(DirList,1,p1);
  578. Move(NewDir[1], Buffer, Length(NewDir));
  579. Buffer[Length(NewDir)]:=#0;
  580. if sys_stat(pchar(@Buffer),Info)=0 then
  581. Begin
  582. If Pos('./',NewDir)=1 Then
  583. Delete(NewDir,1,2);
  584. {DOS strips off an initial .\}
  585. End
  586. Else
  587. NewDir:='';
  588. Until (DirList='') or (Length(NewDir) > 0);
  589. FSearch:=NewDir;
  590. End;
  591. End;
  592. Procedure GetFAttr(var f; var attr : word);
  593. Var
  594. info : stat;
  595. LinAttr : mode_t;
  596. Begin
  597. DosError:=0;
  598. if sys_stat(@textrec(f).name,info)<>0 then
  599. begin
  600. Attr:=0;
  601. DosError:=3;
  602. exit;
  603. end
  604. else
  605. LinAttr:=Info.st_Mode;
  606. if S_ISDIR(LinAttr) then
  607. Attr:=directory
  608. else
  609. Attr:=0;
  610. if sys_Access(@textrec(f).name,W_OK)<>0 then
  611. Attr:=Attr or readonly;
  612. if (filerec(f).name[0]='.') then
  613. Attr:=Attr or hidden;
  614. end;
  615. Procedure getftime (var f; var time : longint);
  616. Var
  617. Info: stat;
  618. DT: DateTime;
  619. Begin
  620. doserror:=0;
  621. if sys_fstat(filerec(f).handle,info)<>0 then
  622. begin
  623. Time:=0;
  624. doserror:=3;
  625. exit
  626. end
  627. else
  628. UnixDateToDT(Info.st_mtime,DT);
  629. PackTime(DT,Time);
  630. End;
  631. {******************************************************************************
  632. --- Environment ---
  633. ******************************************************************************}
  634. Function EnvCount: Longint;
  635. var
  636. envcnt : longint;
  637. p : ppchar;
  638. Begin
  639. envcnt:=0;
  640. p:=envp; {defined in syslinux}
  641. while (p^<>nil) do
  642. begin
  643. inc(envcnt);
  644. inc(p);
  645. end;
  646. EnvCount := envcnt
  647. End;
  648. Function EnvStr (Index: longint): String;
  649. Var
  650. i : longint;
  651. p : ppchar;
  652. Begin
  653. p:=envp; {defined in syslinux}
  654. i:=1;
  655. envstr:='';
  656. if (index < 1) or (index > EnvCount) then
  657. exit;
  658. while (i<Index) and (p^<>nil) do
  659. begin
  660. inc(i);
  661. inc(p);
  662. end;
  663. if p<>nil then
  664. envstr:=strpas(p^)
  665. End;
  666. Function GetEnv(EnvVar:string):string;
  667. {
  668. Searches the environment for a string with name p and
  669. returns a pchar to it's value.
  670. A pchar is used to accomodate for strings of length > 255
  671. }
  672. var
  673. ep : ppchar;
  674. found : boolean;
  675. p1 : pchar;
  676. Begin
  677. EnvVar:=EnvVar+'='; {Else HOST will also find HOSTNAME, etc}
  678. ep:=envp;
  679. found:=false;
  680. if ep<>nil then
  681. begin
  682. while (not found) and (ep^<>nil) do
  683. begin
  684. if strlcomp(@EnvVar[1],(ep^),length(EnvVar))=0 then
  685. found:=true
  686. else
  687. inc(ep);
  688. end;
  689. end;
  690. if found then
  691. p1:=ep^+length(EnvVar)
  692. else
  693. p1:=nil;
  694. if p1 = nil then
  695. GetEnv := ''
  696. else
  697. GetEnv := StrPas(p1);
  698. end;
  699. Procedure setftime(var f; time : longint);
  700. Begin
  701. {! No POSIX equivalent !}
  702. End;
  703. Procedure setfattr (var f;attr : word);
  704. Begin
  705. {! No POSIX equivalent !}
  706. End;
  707. { Include timezone routines }
  708. {$i timezone.inc}
  709. {******************************************************************************
  710. --- Initialization ---
  711. ******************************************************************************}
  712. Initialization
  713. InitLocalTime;
  714. finalization
  715. DoneLocalTime;
  716. end.