dos.pas 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. {****************************************************************************
  2. $Id$
  3. Free Pascal Runtime-Library
  4. DOS unit for OS/2
  5. Copyright (c) 1997,1998 by Dani‰l Mantione,
  6. member of the Free Pascal development team
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. ****************************************************************************}
  13. unit dos;
  14. {$I os.inc}
  15. {$ASMMODE ATT}
  16. {***************************************************************************}
  17. interface
  18. {***************************************************************************}
  19. {$PACKRECORDS 1}
  20. uses strings;
  21. const {Bit masks for CPU flags.}
  22. fcarry = $0001;
  23. fparity = $0004;
  24. fauxiliary = $0010;
  25. fzero = $0040;
  26. fsign = $0080;
  27. foverflow = $0800;
  28. {Bit masks for file attributes.}
  29. readonly = $01;
  30. hidden = $02;
  31. sysfile = $04;
  32. volumeid = $08;
  33. directory = $10;
  34. archive = $20;
  35. anyfile = $3F;
  36. fmclosed = $D7B0;
  37. fminput = $D7B1;
  38. fmoutput = $D7B2;
  39. fminout = $D7B3;
  40. type {Some string types:}
  41. comstr=string; {Filenames can be long in OS/2.}
  42. pathstr=string; {String for pathnames.}
  43. dirstr=string; {String for a directory}
  44. namestr=string; {String for a filename.}
  45. extstr=string[40]; {String for an extension. Can be 253
  46. characters long, in theory, but let's
  47. say fourty will be enough.}
  48. {Search record which is used by findfirst and findnext:}
  49. searchrec=record
  50. fill:array[1..21] of byte;
  51. attr:byte;
  52. time:longint;
  53. size:longint;
  54. name:string; {Filenames can be long in OS/2!}
  55. end;
  56. {$i filerec.inc}
  57. {$i textrec.inc}
  58. {Data structure for the registers needed by msdos and intr:}
  59. registers=record
  60. case i:integer of
  61. 0:(ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,
  62. f8,flags,fs,gs:word);
  63. 1:(al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh:byte);
  64. 2:(eax,ebx,ecx,edx,ebp,esi,edi:longint);
  65. end;
  66. {Record for date and time:}
  67. datetime=record
  68. year,month,day,hour,min,sec:word;
  69. end;
  70. {Flags for the exec procedure:
  71. Starting the program:
  72. efwait: Wait until program terminates.
  73. efno_wait: Don't wait until the program terminates. Does not work
  74. in dos, as DOS cannot multitask.
  75. efoverlay: Terminate this program, then execute the requested
  76. program. WARNING: Exit-procedures are not called!
  77. efdebug: Debug program. Details are unknown.
  78. efsession: Do not execute as child of this program. Use a seperate
  79. session instead.
  80. efdetach: Detached. Function unknown. Info wanted!
  81. efpm: Run as presentation manager program.
  82. Determining the window state of the program:
  83. efdefault: Run the pm program in it's default situation.
  84. efminimize: Run the pm program minimized.
  85. efmaximize: Run the pm program maximized.
  86. effullscreen: Run the non-pm program fullscreen.
  87. efwindowed: Run the non-pm program in a window.
  88. Other options are not implemented defined because lack of
  89. knowledge abou what they do.}
  90. type execrunflags=(efwait,efno_wait,efoverlay,efdebug,efsession,
  91. efdetach,efpm);
  92. execwinflags=(efdefault,efminimize,efmaximize,effullscreen,
  93. efwindowed);
  94. var doserror:integer;
  95. dosexitcode:word;
  96. procedure getdate(var year,month,day,dayofweek:word);
  97. procedure gettime(var hour,minute,second,sec100:word);
  98. function dosversion:word;
  99. procedure setdate(year,month,day:word);
  100. procedure settime(hour,minute,second,sec100:word);
  101. procedure getcbreak(var breakvalue:boolean);
  102. procedure setcbreak(breakvalue:boolean);
  103. procedure getverify(var verify:boolean);
  104. procedure setverify(verify : boolean);
  105. function diskfree(drive:byte):longint;
  106. function disksize(drive:byte):longint;
  107. procedure findfirst(const path:pathstr;attr:word;var f:searchRec);
  108. procedure findnext(var f:searchRec);
  109. procedure findclose(var f:searchRec);
  110. {Is a dummy:}
  111. procedure swapvectors;
  112. {Not supported:
  113. procedure getintvec(intno:byte;var vector:pointer);
  114. procedure setintvec(intno:byte;vector:pointer);
  115. procedure keep(exitcode:word);
  116. }
  117. procedure msdos(var regs:registers);
  118. procedure intr(intno : byte;var regs:registers);
  119. procedure getfattr(var f;var attr:word);
  120. procedure setfattr(var f;attr:word);
  121. function fsearch(path:pathstr;dirlist:string):pathstr;
  122. procedure getftime(var f;var time:longint);
  123. procedure setftime(var f;time:longint);
  124. procedure packtime (var d:datetime; var time:longint);
  125. procedure unpacktime (time:longint; var d:datetime);
  126. function fexpand(const path:pathstr):pathstr;
  127. procedure fsplit(path:pathstr;var dir:dirstr;var name:namestr;
  128. var ext:extstr);
  129. procedure exec(const path:pathstr;const comline:comstr);
  130. function exec(path:pathstr;runflags:execrunflags;winflags:execwinflags;
  131. const comline:comstr):longint;
  132. function envcount:longint;
  133. function envstr(index:longint) : string;
  134. function getenv(const envvar:string): string;
  135. implementation
  136. uses doscalls;
  137. {Import syscall to call it nicely from assembler procedures.}
  138. procedure syscall;external name '___SYSCALL';
  139. function fsearch(path:pathstr;dirlist:string):pathstr;
  140. var i,p1:longint;
  141. s:searchrec;
  142. newdir:pathstr;
  143. begin
  144. {No wildcards allowed in these things:}
  145. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  146. fsearch:=''
  147. else
  148. begin
  149. { allow slash as backslash }
  150. for i:=1 to length(dirlist) do
  151. if dirlist[i]='/' then dirlist[i]:='\';
  152. repeat
  153. p1:=pos(';',dirlist);
  154. if p1<>0 then
  155. begin
  156. newdir:=copy(dirlist,1,p1-1);
  157. delete(dirlist,1,p1);
  158. end
  159. else
  160. begin
  161. newdir:=dirlist;
  162. dirlist:='';
  163. end;
  164. if (newdir<>'') and
  165. not (newdir[length(newdir)] in ['\',':']) then
  166. newdir:=newdir+'\';
  167. findfirst(newdir+path,anyfile,s);
  168. if doserror=0 then
  169. newdir:=newdir+path
  170. else
  171. newdir:='';
  172. until (dirlist='') or (newdir<>'');
  173. fsearch:=newdir;
  174. end;
  175. end;
  176. procedure getftime(var f;var time:longint);
  177. begin
  178. asm
  179. {Load handle}
  180. movl f,%ebx
  181. movw (%ebx),%bx
  182. {Get date}
  183. movw $0x5700,%ax
  184. call syscall
  185. shll $16,%edx
  186. movw %cx,%dx
  187. movl time,%ebx
  188. movl %edx,(%ebx)
  189. xorb %ah,%ah
  190. movw %ax,doserror
  191. end;
  192. end;
  193. procedure setftime(var f;time : longint);
  194. begin
  195. asm
  196. {Load handle}
  197. movl f,%ebx
  198. movw (%ebx),%bx
  199. movl time,%ecx
  200. shldl $16,%ecx,%edx
  201. {Set date}
  202. movw $0x5701,%ax
  203. call syscall
  204. xorb %ah,%ah
  205. movw %ax,doserror
  206. end;
  207. end;
  208. procedure msdos(var regs:registers);
  209. {Not recommended for EMX. Only works in DOS mode, not in OS/2 mode.}
  210. begin
  211. intr($21,regs);
  212. end;
  213. {$ASMMODE DIRECT}
  214. procedure intr(intno:byte;var regs:registers);
  215. {Not recommended for EMX. Only works in DOS mode, not in OS/2 mode.}
  216. begin
  217. asm
  218. .data
  219. int86:
  220. .byte 0xcd
  221. int86_vec:
  222. .byte 0x03
  223. jmp int86_retjmp
  224. .text
  225. movl 8(%ebp),%eax
  226. movb %al,int86_vec
  227. movl 10(%ebp),%eax
  228. {Do not use first int}
  229. incl %eax
  230. incl %eax
  231. movl 4(%eax),%ebx
  232. movl 8(%eax),%ecx
  233. movl 12(%eax),%edx
  234. movl 16(%eax),%ebp
  235. movl 20(%eax),%esi
  236. movl 24(%eax),%edi
  237. movl (%eax),%eax
  238. jmp int86
  239. int86_retjmp:
  240. pushf
  241. pushl %ebp
  242. pushl %eax
  243. movl %esp,%ebp
  244. {Calc EBP new}
  245. addl $12,%ebp
  246. movl 10(%ebp),%eax
  247. {Do not use first int}
  248. incl %eax
  249. incl %eax
  250. popl (%eax)
  251. movl %ebx,4(%eax)
  252. movl %ecx,8(%eax)
  253. movl %edx,12(%eax)
  254. {Restore EBP}
  255. popl %edx
  256. movl %edx,16(%eax)
  257. movl %esi,20(%eax)
  258. movl %edi,24(%eax)
  259. {Ignore ES and DS}
  260. popl %ebx {Flags.}
  261. movl %ebx,32(%eax)
  262. {FS and GS too}
  263. end;
  264. end;
  265. {$ASMMODE ATT}
  266. procedure exec(const path:pathstr;const comline:comstr);
  267. {Execute a program.}
  268. begin
  269. dosexitcode:=exec(path,efwait,efdefault,comline);
  270. end;
  271. function exec(path:pathstr;runflags:execrunflags;winflags:execwinflags;
  272. const comline:comstr):longint;
  273. {Execute a program. More suitable for OS/2 than the exec above.}
  274. {512 bytes should be enough to contain the command-line.}
  275. type bytearray=array[0..8191] of byte;
  276. Pbytearray=^bytearray;
  277. execstruc=record
  278. argofs,envofs,nameofs:pointer;
  279. argseg,envseg,nameseg:word;
  280. numarg,sizearg,
  281. numenv,sizeenv:word;
  282. mode1,mode2:byte;
  283. end;
  284. var args:Pbytearray;
  285. env:Pbytearray;
  286. i,j:word;
  287. es:execstruc;
  288. esadr:pointer;
  289. d:dirstr;
  290. n:namestr;
  291. e:extstr;
  292. begin
  293. getmem(args,512);
  294. getmem(env,8192);
  295. j:=1;
  296. {Now setup the arguments. The first argument should be the program
  297. name without directory and extension.}
  298. fsplit(path,d,n,e);
  299. es.numarg:=1;
  300. args^[0]:=$80;
  301. for i:=1 to length(n) do
  302. begin
  303. args^[j]:=byte(n[i]);
  304. inc(j);
  305. end;
  306. args^[j]:=0;
  307. inc(j);
  308. {Now do the real arguments.}
  309. i:=1;
  310. while i<=length(comline) do
  311. begin
  312. if comline[i]<>' ' then
  313. begin
  314. {Commandline argument found. Copy it.}
  315. inc(es.numarg);
  316. args^[j]:=$80;
  317. inc(j);
  318. while (i<=length(comline)) and (comline[i]<>' ') do
  319. begin
  320. args^[j]:=byte(comline[i]);
  321. inc(j);
  322. inc(i);
  323. end;
  324. args^[j]:=0;
  325. inc(j);
  326. end;
  327. inc(i);
  328. end;
  329. args^[j]:=0;
  330. inc(j);
  331. {Commandline ready, now build the environment.
  332. Oh boy, I always had the opinion that executing a program under Dos
  333. was a hard job!}
  334. {$ASMMODE DIRECT}
  335. asm
  336. movl env,%edi {Setup destination pointer.}
  337. movl _envc,%ecx {Load number of arguments in edx.}
  338. movl _environ,%esi {Load env. strings.}
  339. xorl %edx,%edx {Count environment size.}
  340. exa1:
  341. lodsl {Load a Pchar.}
  342. xchgl %eax,%ebx
  343. exa2:
  344. movb (%ebx),%al {Load a byte.}
  345. incl %ebx {Point to next byte.}
  346. stosb {Store it.}
  347. incl %edx {Increase counter.}
  348. cmpb $0,%al {Ready ?.}
  349. jne exa2
  350. loop exa1 {Next argument.}
  351. stosb {Store an extra 0 to finish. (AL is now 0).}
  352. incl %edx
  353. movl %edx,(24)es {Store environment size.}
  354. end;
  355. {$ASMMODE ATT}
  356. {Environtment ready, now set-up exec structure.}
  357. es.argofs:=args;
  358. es.envofs:=env;
  359. asm
  360. leal path,%esi
  361. lodsb
  362. movzbl %al,%eax
  363. addl %eax,%esi
  364. movb $0,(%esi)
  365. end;
  366. es.nameofs:=pointer(longint(@path)+1);
  367. asm
  368. movw %ss,es.argseg
  369. movw %ss,es.envseg
  370. movw %ss,es.nameseg
  371. end;
  372. es.sizearg:=j;
  373. es.numenv:=0;
  374. {Typecasting of sets in FPK is a bit hard.}
  375. es.mode1:=byte(runflags);
  376. es.mode2:=byte(winflags);
  377. {Now exec the program.}
  378. asm
  379. leal es,%edx
  380. mov $0x7f06,%ax
  381. call syscall
  382. xorl %edi,%edi
  383. jnc .Lexprg1
  384. xchgl %eax,%edi
  385. xorl %eax,%eax
  386. decl %eax
  387. .Lexprg1:
  388. movw %di,doserror
  389. movl %eax,__RESULT
  390. end;
  391. freemem(args,512);
  392. freemem(env,8192);
  393. {Phew! That's it. This was the most sophisticated procedure to call
  394. a system function I ever wrote!}
  395. end;
  396. function dosversion:word;assembler;
  397. {Returns DOS version in DOS and OS/2 version in OS/2}
  398. asm
  399. movb $0x30,%ah
  400. call syscall
  401. end;
  402. procedure getdate(var year,month,day,dayofweek:word);
  403. begin
  404. asm
  405. movb $0x2a,%ah
  406. call syscall
  407. xorb %ah,%ah
  408. movl 20(%ebp),%edi
  409. stosw
  410. movl 16(%ebp),%edi
  411. movb %dl,%al
  412. stosw
  413. movl 12(%ebp),%edi
  414. movb %dh,%al
  415. stosw
  416. movl 8(%ebp),%edi
  417. xchgw %ecx,%eax
  418. stosw
  419. end;
  420. end;
  421. procedure setdate(year,month,day : word);
  422. begin
  423. {DOS only! You cannot change the system date in OS/2!}
  424. asm
  425. movw 8(%ebp),%cx
  426. movb 10(%ebp),%dh
  427. movb 12(%ebp),%dl
  428. movb $0x2b,%ah
  429. call syscall
  430. xorb %ah,%ah
  431. movw %ax,doserror
  432. end;
  433. end;
  434. procedure gettime(var hour,minute,second,sec100:word);
  435. begin
  436. asm
  437. movb $0x2c,%ah
  438. call syscall
  439. xorb %ah,%ah
  440. movl 20(%ebp),%edi
  441. movb %dl,%al
  442. stosw
  443. movl 16(%ebp),%edi
  444. movb %dh,%al
  445. stosw
  446. movl 12(%ebp),%edi
  447. movb %cl,%al
  448. stosw
  449. movl 8(%ebp),%edi
  450. movb %ch,%al
  451. stosw
  452. end;
  453. end;
  454. procedure settime(hour,minute,second,sec100:word);
  455. begin
  456. asm
  457. movb 8(%ebp),%ch
  458. movb 10(%ebp),%cl
  459. movb 12(%ebp),%dh
  460. movb 14(%ebp),%dl
  461. movb $0x2d,%ah
  462. call syscall
  463. xorb %ah,%ah
  464. movw %ax,doserror
  465. end;
  466. end;
  467. procedure getcbreak(var breakvalue:boolean);
  468. begin
  469. {! Do not use in OS/2. Also not recommended in DOS. Use
  470. signal handling instead.}
  471. asm
  472. movw $0x3300,%ax
  473. call syscall
  474. movl 8(%ebp),%eax
  475. movb %dl,(%eax)
  476. end;
  477. end;
  478. procedure setcbreak(breakvalue:boolean);
  479. begin
  480. {! Do not use in OS/2. Also not recommended in DOS. Use
  481. signal handling instead.}
  482. asm
  483. movb 8(%ebp),%dl
  484. movw $0x3301,%ax
  485. call syscall
  486. end;
  487. end;
  488. procedure getverify(var verify:boolean);
  489. begin
  490. {! Do not use in OS/2.}
  491. asm
  492. movb $0x54,%ah
  493. call syscall
  494. movl 8(%ebp),%edi
  495. stosb
  496. end;
  497. end;
  498. procedure setverify(verify:boolean);
  499. begin
  500. {! Do not use in OS/2.}
  501. asm
  502. movb 8(%ebp),%al
  503. movb $0x2e,%ah
  504. call syscall
  505. end;
  506. end;
  507. function diskfree(drive:byte):longint;
  508. var fi:TFSinfo;
  509. begin
  510. if os_mode=osDOS then
  511. {Function 36 is not supported in OS/2.}
  512. asm
  513. movb 8(%ebp),%dl
  514. movb $0x36,%ah
  515. call syscall
  516. cmpw $-1,%ax
  517. je .LDISKFREE1
  518. mulw %cx
  519. mulw %bx
  520. shll $16,%edx
  521. movw %ax,%dx
  522. xchgl %edx,%eax
  523. leave
  524. ret
  525. .LDISKFREE1:
  526. cltd
  527. leave
  528. ret
  529. end
  530. else
  531. {In OS/2, we use the filesystem information.}
  532. begin
  533. doserror:=dosqueryFSinfo(drive,1,FI,sizeof(FI));
  534. if doserror=0 then
  535. diskfree:=FI.free_clusters*FI.sectors_per_cluster*
  536. FI.bytes_per_sector
  537. else
  538. diskfree:=-1;
  539. end;
  540. end;
  541. function disksize(drive:byte):longint;
  542. var fi:TFSinfo;
  543. begin
  544. if os_mode=osDOS then
  545. {Function 36 is not supported in OS/2.}
  546. asm
  547. movb 8(%ebp),%dl
  548. movb $0x36,%ah
  549. call syscall
  550. movw %dx,%bx
  551. cmpw $-1,%ax
  552. je .LDISKSIZE1
  553. mulw %cx
  554. mulw %bx
  555. shll $16,%edx
  556. movw %ax,%dx
  557. xchgl %edx,%eax
  558. leave
  559. ret
  560. .LDISKSIZE1:
  561. cltd
  562. leave
  563. ret
  564. end
  565. else
  566. {In OS/2, we use the filesystem information.}
  567. begin
  568. doserror:=dosqueryFSinfo(drive,1,FI,sizeof(FI));
  569. if doserror=0 then
  570. disksize:=FI.total_clusters*FI.sectors_per_cluster*
  571. FI.bytes_per_sector
  572. else
  573. disksize:=-1;
  574. end;
  575. end;
  576. procedure searchrec2dossearchrec(var f:searchrec);
  577. const namesize=255;
  578. var l,i:longint;
  579. begin
  580. l:=length(f.name);
  581. for i:=1 to namesize do
  582. f.name[i-1]:=f.name[i];
  583. f.name[l]:=#0;
  584. end;
  585. procedure dossearchrec2searchrec(var f : searchrec);
  586. const namesize=255;
  587. var l,i : longint;
  588. begin
  589. for i:=0 to namesize do
  590. if f.name[i]=#0 then
  591. begin
  592. l:=i;
  593. break;
  594. end;
  595. for i:=namesize-1 downto 0 do
  596. f.name[i+1]:=f.name[i];
  597. f.name[0]:=char(l);
  598. end;
  599. procedure findfirst(const path:pathstr;attr:word;var f:searchRec);
  600. procedure _findfirst(path:pchar;attr:word;var f:searchrec);
  601. begin
  602. asm
  603. movl 12(%esp),%edx
  604. movw 16(%esp),%cx
  605. {No need to set DTA in EMX. Just give a pointer in ESI.}
  606. movl 18(%ebp),%esi
  607. movb $0x4e,%ah
  608. call syscall
  609. jnc .LFF
  610. movw %ax,doserror
  611. .LFF:
  612. end;
  613. end;
  614. var path0:array[0..255] of char;
  615. begin
  616. {No error.}
  617. doserror:=0;
  618. strPcopy(path0,path);
  619. _findfirst(path0,attr,f);
  620. dossearchrec2searchrec(f);
  621. end;
  622. procedure findnext(var f:searchRec);
  623. procedure _findnext(var f : searchrec);
  624. begin
  625. asm
  626. movl 12(%ebp),%esi
  627. movb $0x4f,%ah
  628. call syscall
  629. jnc .LFN
  630. movw %ax,doserror
  631. .LFN:
  632. end;
  633. end;
  634. begin
  635. {No error}
  636. doserror:=0;
  637. searchrec2dossearchrec(f);
  638. _findnext(f);
  639. dossearchrec2searchrec(f);
  640. end;
  641. procedure findclose(var f:searchRec);
  642. begin
  643. end;
  644. procedure swapvectors;
  645. {For TP compatibility, this exists.}
  646. begin
  647. end;
  648. type PPchar=^Pchar;
  649. {$ASMMODE DIRECT}
  650. function envs:PPchar;assembler;
  651. asm
  652. movl _environ,%eax
  653. end ['EAX'];
  654. function envcount:longint;assembler;
  655. var hp : ppchar;
  656. asm
  657. movl _envc,%eax
  658. end ['EAX'];
  659. {$ASMMODE ATT}
  660. function envstr(index : longint) : string;
  661. var hp:PPchar;
  662. begin
  663. if (index<=0) or (index>envcount) then
  664. begin
  665. envstr:='';
  666. exit;
  667. end;
  668. hp:=envs+4*(index-1);
  669. envstr:=strpas(hp^);
  670. end;
  671. function getenv(const envvar : string) : string;
  672. var hs,_envvar : string;
  673. eqpos,i : longint;
  674. begin
  675. _envvar:=upcase(envvar);
  676. getenv:='';
  677. for i:=1 to envcount do
  678. begin
  679. hs:=envstr(i);
  680. eqpos:=pos('=',hs);
  681. if copy(hs,1,eqpos-1)=_envvar then
  682. begin
  683. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  684. exit;
  685. end;
  686. end;
  687. end;
  688. procedure fsplit(path:pathstr;var dir:dirstr;var name:namestr;
  689. var ext:extstr);
  690. var p1,i : longint;
  691. begin
  692. {Get drive name}
  693. p1:=pos(':',path);
  694. if p1>0 then
  695. begin
  696. dir:=path[1]+':';
  697. delete(path,1,p1);
  698. end
  699. else
  700. dir:='';
  701. { split the path and the name, there are no more path informtions }
  702. { if path contains no backslashes }
  703. while true do
  704. begin
  705. p1:=pos('\',path);
  706. if p1=0 then
  707. p1:=pos('/',path);
  708. if p1=0 then
  709. break;
  710. dir:=dir+copy(path,1,p1);
  711. delete(path,1,p1);
  712. end;
  713. {Try to find an extension.}
  714. ext:='';
  715. for i:=length(path) downto 1 do
  716. if path[i]='.' then
  717. begin
  718. ext:=copy(path,i,high(extstr));
  719. delete(path,i,length(path)-i+1);
  720. break;
  721. end;
  722. name:=path;
  723. end;
  724. function fexpand(const path:pathstr):pathstr;
  725. function get_current_drive:byte;assembler;
  726. asm
  727. movb $0x19,%ah
  728. call syscall
  729. end;
  730. var s,pa:string;
  731. i,j:longint;
  732. begin
  733. getdir(0,s);
  734. pa:=upcase(path);
  735. {Allow slash as backslash}
  736. for i:=1 to length(pa) do
  737. if pa[i]='/' then
  738. pa[i]:='\';
  739. if (length(pa)>1) and (pa[1] in ['A'..'Z']) and (pa[2]=':') then
  740. begin
  741. {We must get the right directory}
  742. getdir(byte(pa[1])-byte('A')+1,s);
  743. if (byte(pa[0])>2) and (pa[3]<>'\') then
  744. if pa[1]=s[1] then
  745. pa:=s+'\'+copy (pa,3,length(pa))
  746. else
  747. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  748. end
  749. else
  750. if pa[1]='\' then
  751. pa:=s[1]+':'+pa
  752. else if s[0]=#3 then
  753. pa:=s+pa
  754. else
  755. pa:=s+'\'+pa;
  756. {First remove all references to '\.\'}
  757. i:=pos('\.\',pa);
  758. while i<>0 do
  759. begin
  760. delete(pa,i,2);
  761. i:=pos('\.\',pa);
  762. end;
  763. {Now remove also all references to '\..\' + of course previous dirs..}
  764. repeat
  765. i:=pos('\..\',pa);
  766. if i<>0 then
  767. begin
  768. j:=i-1;
  769. while (j>1) and (pa[j]<>'\') do
  770. dec(j);
  771. delete (pa,j,i-j+3);
  772. end;
  773. until i=0;
  774. {Remove End . and \}
  775. if (length(pa)>0) and (pa[length(pa)]='.') then
  776. dec(byte(pa[0]));
  777. if (length(pa)>0) and (pa[length(pa)]='\') then
  778. dec(byte(pa[0]));
  779. fexpand:=pa;
  780. end;
  781. procedure packtime(var d:datetime;var time:longint);
  782. var zs:longint;
  783. begin
  784. time:=-1980;
  785. time:=time+d.year and 127;
  786. time:=time shl 4;
  787. time:=time+d.month;
  788. time:=time shl 5;
  789. time:=time+d.day;
  790. time:=time shl 16;
  791. zs:=d.hour;
  792. zs:=zs shl 6;
  793. zs:=zs+d.min;
  794. zs:=zs shl 5;
  795. zs:=zs+d.sec div 2;
  796. time:=time+(zs and $ffff);
  797. end;
  798. procedure unpacktime (time:longint;var d:datetime);
  799. begin
  800. d.sec:=(time and 31) * 2;
  801. time:=time shr 5;
  802. d.min:=time and 63;
  803. time:=time shr 6;
  804. d.hour:=time and 31;
  805. time:=time shr 5;
  806. d.day:=time and 31;
  807. time:=time shr 5;
  808. d.month:=time and 15;
  809. time:=time shr 4;
  810. d.year:=time+1980;
  811. end;
  812. procedure getfattr(var f;var attr : word);assembler;
  813. asm
  814. movw $0x4300,%ax
  815. movl f,%edx
  816. {addl $filerec.name,%edx Doesn't work!!}
  817. addl $60,%edx
  818. call syscall
  819. movl attr,%ebx
  820. movw %cx,(%ebx)
  821. end;
  822. procedure setfattr(var f;attr : word);assembler;
  823. asm
  824. movw $0x4301,%ax
  825. movl f,%edx
  826. {addl $filerec.name,%edx Doesn't work!!}
  827. addl $60,%edx
  828. movw attr,%cx
  829. call syscall
  830. end;
  831. end.
  832. {
  833. $Log$
  834. Revision 1.12 1999-01-22 16:25:58 pierre
  835. + findclose added
  836. Revision 1.11 1999/01/18 16:22:51 jonas
  837. - removed "noattcdq" define
  838. Revision 1.10 1998/12/10 16:05:39 daniel
  839. * Fsearch bug fixed
  840. Revision 1.9 1998/12/07 18:55:41 jonas
  841. * fixed bug reported in the mailing list by Frank McCormick (fsearch: changed
  842. "if p1 = 0" to "if p1 <> 0"
  843. Revision 1.8 1998/10/16 14:18:02 daniel
  844. * Updates
  845. Revision 1.7 1998/07/08 14:44:11 daniel
  846. + Added moucalls and viocalls written by Tomas Hajny.
  847. + Final routines in doscalls implemented.
  848. * Fixed bugs in dos.pas.
  849. * Changed some old $ifdef FPK into $ifdef FPC.
  850. - Removed go32 stuff from dos.pas.
  851. - Removed '/' to '\' translation from system unit - EMX does this
  852. automatically.
  853. }