dos.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team.
  4. Dos unit for BP7 compatible RTL
  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. {$inline on}
  12. unit dos;
  13. interface
  14. Type
  15. searchrec = packed record
  16. fill : array[1..21] of byte;
  17. attr : byte;
  18. time : longint;
  19. { reserved : word; not in DJGPP V2 }
  20. size : longint;
  21. name : string[255]; { LFN Name, DJGPP uses only [12] but more can't hurt (PFV) }
  22. end;
  23. {$DEFINE HAS_REGISTERS}
  24. {$I registers.inc}
  25. {$i dosh.inc}
  26. {$IfDef SYSTEM_DEBUG_STARTUP}
  27. {$DEFINE FORCE_PROXY}
  28. {$endif SYSTEM_DEBUG_STARTUP}
  29. Const
  30. { This variable can be set to true
  31. to force use of !proxy command lines even for short
  32. strings, for debugging purposes mainly, as
  33. this might have negative impact if trying to
  34. call non-go32v2 programs }
  35. force_go32v2_proxy : boolean =
  36. {$ifdef FORCE_PROXY}
  37. true;
  38. {$DEFINE DEBUG_PROXY}
  39. {$else not FORCE_PROXY}
  40. false;
  41. {$endif not FORCE_PROXY}
  42. { This variable allows to use !proxy if command line is
  43. longer than 126 characters.
  44. This will only work if the called program knows how to handle
  45. those command lines.
  46. Luckily this is the case for Free Pascal compiled
  47. programs (even old versions)
  48. and go32v2 DJGPP programs.
  49. You can set this to false to get a warning to stderr
  50. if command line is too long. }
  51. Use_go32v2_proxy : boolean = true;
  52. { Added to interface so that there is no need to implement it
  53. both in dos and sysutils units }
  54. procedure exec_ansistring(path : string;comline : ansistring);
  55. procedure Intr(IntNo: Byte; var Regs: Registers); external name 'FPC_INTR';
  56. procedure MsDos(var Regs: Registers); external name 'FPC_MSDOS';
  57. implementation
  58. uses
  59. strings;
  60. type
  61. PFarByte = ^Byte;far;
  62. PFarChar = ^Char;far;
  63. PFarWord = ^Word;far;
  64. {$DEFINE HAS_GETMSCOUNT}
  65. {$DEFINE HAS_INTR}
  66. {$DEFINE HAS_SETCBREAK}
  67. {$DEFINE HAS_GETCBREAK}
  68. {$DEFINE HAS_SETVERIFY}
  69. {$DEFINE HAS_GETVERIFY}
  70. {$DEFINE HAS_SWAPVECTORS}
  71. {$DEFINE HAS_GETSHORTNAME}
  72. {$DEFINE HAS_GETLONGNAME}
  73. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  74. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  75. {$I dos.inc}
  76. {******************************************************************************
  77. --- Dos Interrupt ---
  78. ******************************************************************************}
  79. var
  80. dosregs : registers;
  81. procedure LoadDosError;
  82. var
  83. r : registers;
  84. SimpleDosError : word;
  85. begin
  86. if (dosregs.flags and fcarry) <> 0 then
  87. begin
  88. { I got a extended error = 0
  89. while CarryFlag was set from Exec function }
  90. SimpleDosError:=dosregs.ax;
  91. r.ax:=$5900;
  92. r.bx:=$0;
  93. intr($21,r);
  94. { conversion from word to integer !!
  95. gave a Bound check error if ax is $FFFF !! PM }
  96. doserror:=integer(r.ax);
  97. case doserror of
  98. 0 : DosError:=integer(SimpleDosError);
  99. 19 : DosError:=150;
  100. 21 : DosError:=152;
  101. end;
  102. end
  103. else
  104. doserror:=0;
  105. end;
  106. {******************************************************************************
  107. --- Info / Date / Time ---
  108. ******************************************************************************}
  109. function dosversion : word;
  110. begin
  111. dosregs.ax:=$3000;
  112. msdos(dosregs);
  113. dosversion:=dosregs.ax;
  114. end;
  115. procedure getdate(var year,month,mday,wday : word);
  116. begin
  117. dosregs.ax:=$2a00;
  118. msdos(dosregs);
  119. wday:=dosregs.al;
  120. year:=dosregs.cx;
  121. month:=dosregs.dh;
  122. mday:=dosregs.dl;
  123. end;
  124. procedure setdate(year,month,day : word);
  125. begin
  126. dosregs.cx:=year;
  127. dosregs.dh:=month;
  128. dosregs.dl:=day;
  129. dosregs.ah:=$2b;
  130. msdos(dosregs);
  131. end;
  132. procedure gettime(var hour,minute,second,sec100 : word);
  133. begin
  134. dosregs.ah:=$2c;
  135. msdos(dosregs);
  136. hour:=dosregs.ch;
  137. minute:=dosregs.cl;
  138. second:=dosregs.dh;
  139. sec100:=dosregs.dl;
  140. end;
  141. procedure settime(hour,minute,second,sec100 : word);
  142. begin
  143. dosregs.ch:=hour;
  144. dosregs.cl:=minute;
  145. dosregs.dh:=second;
  146. dosregs.dl:=sec100;
  147. dosregs.ah:=$2d;
  148. msdos(dosregs);
  149. end;
  150. function GetMsCount: int64;
  151. begin
  152. GetMsCount := int64 (MemL [$40:$6c]) * 55;
  153. end;
  154. {******************************************************************************
  155. --- Exec ---
  156. ******************************************************************************}
  157. const
  158. DOS_MAX_COMMAND_LINE_LENGTH = 126;
  159. procedure exec_ansistring(path : string;comline : ansistring);
  160. begin
  161. {TODO: implement}
  162. runerror(304);
  163. end;
  164. procedure exec(const path : pathstr;const comline : comstr);
  165. begin
  166. exec_ansistring(path, comline);
  167. end;
  168. procedure getcbreak(var breakvalue : boolean);
  169. begin
  170. dosregs.ax:=$3300;
  171. msdos(dosregs);
  172. breakvalue:=dosregs.dl<>0;
  173. end;
  174. procedure setcbreak(breakvalue : boolean);
  175. begin
  176. dosregs.ax:=$3301;
  177. dosregs.dl:=ord(breakvalue);
  178. msdos(dosregs);
  179. end;
  180. procedure getverify(var verify : boolean);
  181. begin
  182. dosregs.ah:=$54;
  183. msdos(dosregs);
  184. verify:=dosregs.al<>0;
  185. end;
  186. procedure setverify(verify : boolean);
  187. begin
  188. dosregs.ah:=$2e;
  189. dosregs.al:=ord(verify);
  190. msdos(dosregs);
  191. end;
  192. {******************************************************************************
  193. --- Disk ---
  194. ******************************************************************************}
  195. type
  196. ExtendedFat32FreeSpaceRec = packed record
  197. RetSize : word; { $00 }
  198. Strucversion : word; { $02 }
  199. SecPerClus, { $04 }
  200. BytePerSec, { $08 }
  201. AvailClusters, { $0C }
  202. TotalClusters, { $10 }
  203. AvailPhysSect, { $14 }
  204. TotalPhysSect, { $18 }
  205. AvailAllocUnits, { $1C }
  206. TotalAllocUnits : longword; { $20 }
  207. Dummy, { $24 }
  208. Dummy2 : longword; { $28 }
  209. end; { $2C }
  210. const
  211. IOCTL_INPUT = 3; //For request header command field
  212. CDFUNC_SECTSIZE = 7; //For cdrom control block func field
  213. CDFUNC_VOLSIZE = 8; //For cdrom control block func field
  214. type
  215. TRequestHeader = packed record
  216. length : byte; { $00 }
  217. subunit : byte; { $01 }
  218. command : byte; { $02 }
  219. status : word; { $03 }
  220. reserved1 : longword; { $05 }
  221. reserved2 : longword; { $09 }
  222. media_desc : byte; { $0D }
  223. transf_ofs : word; { $0E }
  224. transf_seg : word; { $10 }
  225. numbytes : word; { $12 }
  226. end; { $14 }
  227. TCDSectSizeReq = packed record
  228. func : byte; { $00 }
  229. mode : byte; { $01 }
  230. secsize : word; { $02 }
  231. end; { $04 }
  232. TCDVolSizeReq = packed record
  233. func : byte; { $00 }
  234. size : longword; { $01 }
  235. end; { $05 }
  236. function do_diskdata(drive : byte; Free : boolean) : Int64;
  237. begin
  238. {TODO: implement}
  239. runerror(304);
  240. end;
  241. function diskfree(drive : byte) : int64;
  242. begin
  243. diskfree:=Do_DiskData(drive,TRUE);
  244. end;
  245. function disksize(drive : byte) : int64;
  246. begin
  247. disksize:=Do_DiskData(drive,false);
  248. end;
  249. {******************************************************************************
  250. --- LFNFindfirst LFNFindNext ---
  251. ******************************************************************************}
  252. type
  253. LFNSearchRec=packed record
  254. attr,
  255. crtime,
  256. crtimehi,
  257. actime,
  258. actimehi,
  259. lmtime,
  260. lmtimehi,
  261. sizehi,
  262. size : longint;
  263. reserved : array[0..7] of byte;
  264. name : array[0..259] of byte;
  265. shortname : array[0..13] of byte;
  266. end;
  267. procedure LFNSearchRec2Dos(const w:LFNSearchRec;hdl:longint;var d:Searchrec;from_findfirst : boolean);
  268. var
  269. Len : longint;
  270. begin
  271. With w do
  272. begin
  273. FillChar(d,sizeof(SearchRec),0);
  274. if DosError=0 then
  275. len:=StrLen(@Name)
  276. else
  277. len:=0;
  278. d.Name[0]:=chr(len);
  279. Move(Name[0],d.Name[1],Len);
  280. d.Time:=lmTime;
  281. d.Size:=Size;
  282. d.Attr:=Attr and $FF;
  283. if (DosError<>0) and from_findfirst then
  284. hdl:=-1;
  285. Move(hdl,d.Fill,4);
  286. end;
  287. end;
  288. {$ifdef DEBUG_LFN}
  289. const
  290. LFNFileName : string = 'LFN.log';
  291. LFNOpenNb : longint = 0;
  292. LogLFN : boolean = false;
  293. var
  294. lfnfile : text;
  295. {$endif DEBUG_LFN}
  296. procedure LFNFindFirst(path:pchar;attr:longint;var s:searchrec);
  297. var
  298. i : longint;
  299. w : LFNSearchRec;
  300. begin
  301. { allow slash as backslash }
  302. DoDirSeparators(path);
  303. dosregs.si:=1; { use ms-dos time }
  304. { don't include the label if not asked for it, needed for network drives }
  305. if attr=$8 then
  306. dosregs.cx:=8
  307. else
  308. dosregs.cx:=attr and (not 8);
  309. dosregs.dx:=Ofs(path^);
  310. dosregs.ds:=Seg(path^);
  311. dosregs.di:=Ofs(w);
  312. dosregs.es:=Seg(w);
  313. dosregs.ax:=$714e;
  314. msdos(dosregs);
  315. LoadDosError;
  316. if DosError=2 then
  317. DosError:=18;
  318. {$ifdef DEBUG_LFN}
  319. if (DosError=0) and LogLFN then
  320. begin
  321. Append(lfnfile);
  322. inc(LFNOpenNb);
  323. Writeln(lfnfile,LFNOpenNb,' LFNFindFirst called ',path);
  324. close(lfnfile);
  325. end;
  326. {$endif DEBUG_LFN}
  327. LFNSearchRec2Dos(w,dosregs.ax,s,true);
  328. end;
  329. procedure LFNFindNext(var s:searchrec);
  330. var
  331. hdl : longint;
  332. w : LFNSearchRec;
  333. begin
  334. Move(s.Fill,hdl,4);
  335. dosregs.si:=1; { use ms-dos time }
  336. dosregs.di:=Ofs(w);
  337. dosregs.es:=Seg(w);
  338. dosregs.bx:=hdl;
  339. dosregs.ax:=$714f;
  340. msdos(dosregs);
  341. LoadDosError;
  342. LFNSearchRec2Dos(w,hdl,s,false);
  343. end;
  344. procedure LFNFindClose(var s:searchrec);
  345. var
  346. hdl : longint;
  347. begin
  348. Move(s.Fill,hdl,4);
  349. { Do not call MsDos if FindFirst returned with an error }
  350. if hdl=-1 then
  351. begin
  352. DosError:=0;
  353. exit;
  354. end;
  355. dosregs.bx:=hdl;
  356. dosregs.ax:=$71a1;
  357. msdos(dosregs);
  358. LoadDosError;
  359. {$ifdef DEBUG_LFN}
  360. if (DosError=0) and LogLFN then
  361. begin
  362. Append(lfnfile);
  363. Writeln(lfnfile,LFNOpenNb,' LFNFindClose called ');
  364. close(lfnfile);
  365. if LFNOpenNb>0 then
  366. dec(LFNOpenNb);
  367. end;
  368. {$endif DEBUG_LFN}
  369. end;
  370. {******************************************************************************
  371. --- DosFindfirst DosFindNext ---
  372. ******************************************************************************}
  373. procedure dossearchrec2searchrec(var f : searchrec);
  374. var
  375. len : longint;
  376. begin
  377. { Check is necessary!! OS/2's VDM doesn't clear the name with #0 if the }
  378. { file doesn't exist! (JM) }
  379. if dosError = 0 then
  380. len:=StrLen(@f.Name)
  381. else len := 0;
  382. Move(f.Name[0],f.Name[1],Len);
  383. f.Name[0]:=chr(len);
  384. end;
  385. procedure DosFindfirst(path : pchar;attr : word;var f : searchrec);
  386. begin
  387. { allow slash as backslash }
  388. DoDirSeparators(path);
  389. dosregs.dx:=Ofs(f);
  390. dosregs.ds:=Seg(f);
  391. dosregs.ah:=$1a;
  392. msdos(dosregs);
  393. dosregs.cx:=attr;
  394. dosregs.dx:=Ofs(path^);
  395. dosregs.ds:=Seg(path^);
  396. dosregs.ah:=$4e;
  397. msdos(dosregs);
  398. LoadDosError;
  399. dossearchrec2searchrec(f);
  400. end;
  401. procedure Dosfindnext(var f : searchrec);
  402. begin
  403. dosregs.dx:=Ofs(f);
  404. dosregs.ds:=Seg(f);
  405. dosregs.ah:=$1a;
  406. msdos(dosregs);
  407. dosregs.ah:=$4f;
  408. msdos(dosregs);
  409. LoadDosError;
  410. dossearchrec2searchrec(f);
  411. end;
  412. {******************************************************************************
  413. --- Findfirst FindNext ---
  414. ******************************************************************************}
  415. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  416. var
  417. path0 : array[0..255] of char;
  418. begin
  419. doserror:=0;
  420. strpcopy(path0,path);
  421. if LFNSupport then
  422. LFNFindFirst(path0,attr,f)
  423. else
  424. Dosfindfirst(path0,attr,f);
  425. end;
  426. procedure findnext(var f : searchRec);
  427. begin
  428. doserror:=0;
  429. if LFNSupport then
  430. LFNFindnext(f)
  431. else
  432. Dosfindnext(f);
  433. end;
  434. Procedure FindClose(Var f: SearchRec);
  435. begin
  436. DosError:=0;
  437. if LFNSupport then
  438. LFNFindClose(f);
  439. end;
  440. type swap_proc = procedure;
  441. var
  442. _swap_in : swap_proc;external name '_swap_in';
  443. _swap_out : swap_proc;external name '_swap_out';
  444. _exception_exit : pointer;external name '_exception_exit';
  445. _v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  446. procedure swapvectors;
  447. begin
  448. if _exception_exit<>nil then
  449. if _v2prt0_exceptions_on then
  450. _swap_out()
  451. else
  452. _swap_in();
  453. end;
  454. {******************************************************************************
  455. --- File ---
  456. ******************************************************************************}
  457. Function FSearch(path: pathstr; dirlist: string): pathstr;
  458. var
  459. i,p1 : longint;
  460. s : searchrec;
  461. newdir : pathstr;
  462. begin
  463. { check if the file specified exists }
  464. findfirst(path,anyfile and not(directory),s);
  465. if doserror=0 then
  466. begin
  467. findclose(s);
  468. fsearch:=path;
  469. exit;
  470. end;
  471. { No wildcards allowed in these things }
  472. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  473. fsearch:=''
  474. else
  475. begin
  476. { allow slash as backslash }
  477. DoDirSeparators(dirlist);
  478. repeat
  479. p1:=pos(';',dirlist);
  480. if p1<>0 then
  481. begin
  482. newdir:=copy(dirlist,1,p1-1);
  483. delete(dirlist,1,p1);
  484. end
  485. else
  486. begin
  487. newdir:=dirlist;
  488. dirlist:='';
  489. end;
  490. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  491. newdir:=newdir+'\';
  492. findfirst(newdir+path,anyfile and not(directory),s);
  493. if doserror=0 then
  494. newdir:=newdir+path
  495. else
  496. newdir:='';
  497. until (dirlist='') or (newdir<>'');
  498. fsearch:=newdir;
  499. end;
  500. findclose(s);
  501. end;
  502. { change to short filename if successful DOS call PM }
  503. function GetShortName(var p : String) : boolean;
  504. var
  505. c : array[0..255] of char;
  506. begin
  507. move(p[1],c[0],length(p));
  508. c[length(p)]:=#0;
  509. dosregs.ax:=$7160;
  510. dosregs.cx:=1;
  511. dosregs.ds:=Seg(c);
  512. dosregs.si:=Ofs(c);
  513. dosregs.es:=Seg(c);
  514. dosregs.di:=Ofs(c);
  515. msdos(dosregs);
  516. LoadDosError;
  517. if DosError=0 then
  518. begin
  519. move(c[0],p[1],strlen(c));
  520. p[0]:=char(strlen(c));
  521. GetShortName:=true;
  522. end
  523. else
  524. GetShortName:=false;
  525. end;
  526. { change to long filename if successful DOS call PM }
  527. function GetLongName(var p : String) : boolean;
  528. var
  529. c : array[0..260] of char;
  530. begin
  531. move(p[1],c[0],length(p));
  532. c[length(p)]:=#0;
  533. dosregs.ax:=$7160;
  534. dosregs.cx:=2;
  535. dosregs.ds:=Seg(c);
  536. dosregs.si:=Ofs(c);
  537. dosregs.es:=Seg(c);
  538. dosregs.di:=Ofs(c);
  539. msdos(dosregs);
  540. LoadDosError;
  541. if DosError=0 then
  542. begin
  543. c[255]:=#0;
  544. move(c[0],p[1],strlen(c));
  545. p[0]:=char(strlen(c));
  546. GetLongName:=true;
  547. end
  548. else
  549. GetLongName:=false;
  550. end;
  551. {******************************************************************************
  552. --- Get/Set File Time,Attr ---
  553. ******************************************************************************}
  554. procedure getftime(var f;var time : longint);
  555. begin
  556. dosregs.bx:=textrec(f).handle;
  557. dosregs.ax:=$5700;
  558. msdos(dosregs);
  559. loaddoserror;
  560. time:=(dosregs.dx shl 16)+dosregs.cx;
  561. end;
  562. procedure setftime(var f;time : longint);
  563. begin
  564. dosregs.bx:=textrec(f).handle;
  565. dosregs.cx:=time and $ffff;
  566. dosregs.dx:=time shr 16;
  567. dosregs.ax:=$5701;
  568. msdos(dosregs);
  569. loaddoserror;
  570. end;
  571. procedure getfattr(var f;var attr : word);
  572. begin
  573. dosregs.dx:=Ofs(filerec(f).name);
  574. dosregs.ds:=Seg(filerec(f).name);
  575. if LFNSupport then
  576. begin
  577. dosregs.ax:=$7143;
  578. dosregs.bx:=0;
  579. end
  580. else
  581. dosregs.ax:=$4300;
  582. msdos(dosregs);
  583. LoadDosError;
  584. Attr:=dosregs.cx;
  585. end;
  586. procedure setfattr(var f;attr : word);
  587. begin
  588. { Fail for setting VolumeId. }
  589. if ((attr and VolumeID)<>0) then
  590. begin
  591. doserror:=5;
  592. exit;
  593. end;
  594. dosregs.dx:=Ofs(filerec(f).name);
  595. dosregs.ds:=Seg(filerec(f).name);
  596. if LFNSupport then
  597. begin
  598. dosregs.ax:=$7143;
  599. dosregs.bx:=1;
  600. end
  601. else
  602. dosregs.ax:=$4301;
  603. dosregs.cx:=attr;
  604. msdos(dosregs);
  605. LoadDosError;
  606. end;
  607. {******************************************************************************
  608. --- Environment ---
  609. ******************************************************************************}
  610. function GetEnvStr(EnvNo: Integer; var OutEnvStr: string): integer;
  611. var
  612. dos_env_seg: Word;
  613. ofs: Word;
  614. Ch, Ch2: Char;
  615. begin
  616. dos_env_seg := PFarWord(Ptr(dos_psp, $2C))^;
  617. GetEnvStr := 1;
  618. OutEnvStr := '';
  619. ofs := 0;
  620. repeat
  621. Ch := PFarChar(Ptr(dos_env_seg,ofs))^;
  622. Ch2 := PFarChar(Ptr(dos_env_seg,ofs + 1))^;
  623. if (Ch = #0) and (Ch2 = #0) then
  624. exit;
  625. if Ch = #0 then
  626. Inc(GetEnvStr);
  627. if (Ch <> #0) and (GetEnvStr = EnvNo) then
  628. OutEnvStr := OutEnvStr + Ch;
  629. Inc(ofs);
  630. if ofs = 0 then
  631. exit;
  632. until false;
  633. end;
  634. function envcount : longint;
  635. var
  636. tmpstr: string;
  637. begin
  638. envcount := GetEnvStr(-1, tmpstr);
  639. end;
  640. function envstr (Index: longint): string;
  641. begin
  642. GetEnvStr(Index, envstr);
  643. end;
  644. Function GetEnv(envvar: string): string;
  645. var
  646. hs : string;
  647. eqpos : longint;
  648. I : integer;
  649. begin
  650. envvar:=upcase(envvar);
  651. getenv:='';
  652. for I := 1 to envcount do
  653. begin
  654. hs:=envstr(I);
  655. eqpos:=pos('=',hs);
  656. if upcase(copy(hs,1,eqpos-1))=envvar then
  657. begin
  658. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  659. break;
  660. end;
  661. end;
  662. end;
  663. {$ifdef DEBUG_LFN}
  664. begin
  665. LogLFN:=(GetEnv('LOGLFN')<>'');
  666. assign(lfnfile,LFNFileName);
  667. {$I-}
  668. Reset(lfnfile);
  669. if IOResult<>0 then
  670. begin
  671. Rewrite(lfnfile);
  672. Writeln(lfnfile,'New lfn.log');
  673. end;
  674. close(lfnfile);
  675. {$endif DEBUG_LFN}
  676. end.