dos.pas 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  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. {Is a dummy:}
  110. procedure swapvectors;
  111. {Not supported:
  112. procedure getintvec(intno:byte;var vector:pointer);
  113. procedure setintvec(intno:byte;vector:pointer);
  114. procedure keep(exitcode:word);
  115. }
  116. procedure msdos(var regs:registers);
  117. procedure intr(intno : byte;var regs:registers);
  118. procedure getfattr(var f;var attr:word);
  119. procedure setfattr(var f;attr:word);
  120. function fsearch(path:pathstr;dirlist:string):pathstr;
  121. procedure getftime(var f;var time:longint);
  122. procedure setftime(var f;time:longint);
  123. procedure packtime (var d:datetime; var time:longint);
  124. procedure unpacktime (time:longint; var d:datetime);
  125. function fexpand(const path:pathstr):pathstr;
  126. procedure fsplit(path:pathstr;var dir:dirstr;var name:namestr;
  127. var ext:extstr);
  128. procedure exec(const path:pathstr;const comline:comstr);
  129. function exec(path:pathstr;runflags:execrunflags;winflags:execwinflags;
  130. const comline:comstr):longint;
  131. function envcount:longint;
  132. function envstr(index:longint) : string;
  133. function getenv(const envvar:string): string;
  134. implementation
  135. uses doscalls;
  136. {Import syscall to call it nicely from assembler procedures.}
  137. procedure syscall;external name '___SYSCALL';
  138. function fsearch(path:pathstr;dirlist:string):pathstr;
  139. var i,p1:longint;
  140. s:searchrec;
  141. newdir:pathstr;
  142. begin
  143. {No wildcards allowed in these things:}
  144. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  145. fsearch:=''
  146. else
  147. begin
  148. { allow slash as backslash }
  149. for i:=1 to length(dirlist) do
  150. if dirlist[i]='/' then dirlist[i]:='\';
  151. repeat
  152. p1:=pos(';',dirlist);
  153. if p1<>0 then
  154. begin
  155. newdir:=copy(dirlist,1,p1-1);
  156. delete(dirlist,1,p1);
  157. end
  158. else
  159. begin
  160. newdir:=dirlist;
  161. dirlist:='';
  162. end;
  163. if (newdir<>'') and
  164. not (newdir[length(newdir)] in ['\',':']) then
  165. newdir:=newdir+'\';
  166. findfirst(newdir+path,anyfile,s);
  167. if doserror=0 then
  168. newdir:=newdir+path
  169. else
  170. newdir:='';
  171. until (dirlist='') or (newdir<>'');
  172. fsearch:=newdir;
  173. end;
  174. end;
  175. procedure getftime(var f;var time:longint);
  176. begin
  177. asm
  178. {Load handle}
  179. movl f,%ebx
  180. movw (%ebx),%bx
  181. {Get date}
  182. movw $0x5700,%ax
  183. call syscall
  184. shll $16,%edx
  185. movw %cx,%dx
  186. movl time,%ebx
  187. movl %edx,(%ebx)
  188. xorb %ah,%ah
  189. movw %ax,doserror
  190. end;
  191. end;
  192. procedure setftime(var f;time : longint);
  193. begin
  194. asm
  195. {Load handle}
  196. movl f,%ebx
  197. movw (%ebx),%bx
  198. movl time,%ecx
  199. shldl $16,%ecx,%edx
  200. {Set date}
  201. movw $0x5701,%ax
  202. call syscall
  203. xorb %ah,%ah
  204. movw %ax,doserror
  205. end;
  206. end;
  207. procedure msdos(var regs:registers);
  208. {Not recommended for EMX. Only works in DOS mode, not in OS/2 mode.}
  209. begin
  210. intr($21,regs);
  211. end;
  212. {$ASMMODE DIRECT}
  213. procedure intr(intno:byte;var regs:registers);
  214. {Not recommended for EMX. Only works in DOS mode, not in OS/2 mode.}
  215. begin
  216. asm
  217. .data
  218. int86:
  219. .byte 0xcd
  220. int86_vec:
  221. .byte 0x03
  222. jmp int86_retjmp
  223. .text
  224. movl 8(%ebp),%eax
  225. movb %al,int86_vec
  226. movl 10(%ebp),%eax
  227. {Do not use first int}
  228. incl %eax
  229. incl %eax
  230. movl 4(%eax),%ebx
  231. movl 8(%eax),%ecx
  232. movl 12(%eax),%edx
  233. movl 16(%eax),%ebp
  234. movl 20(%eax),%esi
  235. movl 24(%eax),%edi
  236. movl (%eax),%eax
  237. jmp int86
  238. int86_retjmp:
  239. pushf
  240. pushl %ebp
  241. pushl %eax
  242. movl %esp,%ebp
  243. {Calc EBP new}
  244. addl $12,%ebp
  245. movl 10(%ebp),%eax
  246. {Do not use first int}
  247. incl %eax
  248. incl %eax
  249. popl (%eax)
  250. movl %ebx,4(%eax)
  251. movl %ecx,8(%eax)
  252. movl %edx,12(%eax)
  253. {Restore EBP}
  254. popl %edx
  255. movl %edx,16(%eax)
  256. movl %esi,20(%eax)
  257. movl %edi,24(%eax)
  258. {Ignore ES and DS}
  259. popl %ebx {Flags.}
  260. movl %ebx,32(%eax)
  261. {FS and GS too}
  262. end;
  263. end;
  264. {$ASMMODE ATT}
  265. procedure exec(const path:pathstr;const comline:comstr);
  266. {Execute a program.}
  267. begin
  268. dosexitcode:=exec(path,efwait,efdefault,comline);
  269. end;
  270. function exec(path:pathstr;runflags:execrunflags;winflags:execwinflags;
  271. const comline:comstr):longint;
  272. {Execute a program. More suitable for OS/2 than the exec above.}
  273. {512 bytes should be enough to contain the command-line.}
  274. type bytearray=array[0..8191] of byte;
  275. Pbytearray=^bytearray;
  276. execstruc=record
  277. argofs,envofs,nameofs:pointer;
  278. argseg,envseg,nameseg:word;
  279. numarg,sizearg,
  280. numenv,sizeenv:word;
  281. mode1,mode2:byte;
  282. end;
  283. var args:Pbytearray;
  284. env:Pbytearray;
  285. i,j:word;
  286. es:execstruc;
  287. esadr:pointer;
  288. d:dirstr;
  289. n:namestr;
  290. e:extstr;
  291. begin
  292. getmem(args,512);
  293. getmem(env,8192);
  294. j:=1;
  295. {Now setup the arguments. The first argument should be the program
  296. name without directory and extension.}
  297. fsplit(path,d,n,e);
  298. es.numarg:=1;
  299. args^[0]:=$80;
  300. for i:=1 to length(n) do
  301. begin
  302. args^[j]:=byte(n[i]);
  303. inc(j);
  304. end;
  305. args^[j]:=0;
  306. inc(j);
  307. {Now do the real arguments.}
  308. i:=1;
  309. while i<=length(comline) do
  310. begin
  311. if comline[i]<>' ' then
  312. begin
  313. {Commandline argument found. Copy it.}
  314. inc(es.numarg);
  315. args^[j]:=$80;
  316. inc(j);
  317. while (i<=length(comline)) and (comline[i]<>' ') do
  318. begin
  319. args^[j]:=byte(comline[i]);
  320. inc(j);
  321. inc(i);
  322. end;
  323. args^[j]:=0;
  324. inc(j);
  325. end;
  326. inc(i);
  327. end;
  328. args^[j]:=0;
  329. inc(j);
  330. {Commandline ready, now build the environment.
  331. Oh boy, I always had the opinion that executing a program under Dos
  332. was a hard job!}
  333. {$ASMMODE DIRECT}
  334. asm
  335. movl env,%edi {Setup destination pointer.}
  336. movl _envc,%ecx {Load number of arguments in edx.}
  337. movl _environ,%esi {Load env. strings.}
  338. xorl %edx,%edx {Count environment size.}
  339. exa1:
  340. lodsl {Load a Pchar.}
  341. xchgl %eax,%ebx
  342. exa2:
  343. movb (%ebx),%al {Load a byte.}
  344. incl %ebx {Point to next byte.}
  345. stosb {Store it.}
  346. incl %edx {Increase counter.}
  347. cmpb $0,%al {Ready ?.}
  348. jne exa2
  349. loop exa1 {Next argument.}
  350. stosb {Store an extra 0 to finish. (AL is now 0).}
  351. incl %edx
  352. movl %edx,(24)es {Store environment size.}
  353. end;
  354. {$ASMMODE ATT}
  355. {Environtment ready, now set-up exec structure.}
  356. es.argofs:=args;
  357. es.envofs:=env;
  358. asm
  359. leal path,%esi
  360. lodsb
  361. movzbl %al,%eax
  362. addl %eax,%esi
  363. movb $0,(%esi)
  364. end;
  365. es.nameofs:=pointer(longint(@path)+1);
  366. asm
  367. movw %ss,es.argseg
  368. movw %ss,es.envseg
  369. movw %ss,es.nameseg
  370. end;
  371. es.sizearg:=j;
  372. es.numenv:=0;
  373. {Typecasting of sets in FPK is a bit hard.}
  374. es.mode1:=byte(runflags);
  375. es.mode2:=byte(winflags);
  376. {Now exec the program.}
  377. asm
  378. leal es,%edx
  379. mov $0x7f06,%ax
  380. call syscall
  381. xorl %edi,%edi
  382. jnc .Lexprg1
  383. xchgl %eax,%edi
  384. xorl %eax,%eax
  385. decl %eax
  386. .Lexprg1:
  387. movw %di,doserror
  388. movl %eax,__RESULT
  389. end;
  390. freemem(args,512);
  391. freemem(env,8192);
  392. {Phew! That's it. This was the most sophisticated procedure to call
  393. a system function I ever wrote!}
  394. end;
  395. function dosversion:word;assembler;
  396. {Returns DOS version in DOS and OS/2 version in OS/2}
  397. asm
  398. movb $0x30,%ah
  399. call syscall
  400. end;
  401. procedure getdate(var year,month,day,dayofweek:word);
  402. begin
  403. asm
  404. movb $0x2a,%ah
  405. call syscall
  406. xorb %ah,%ah
  407. movl 20(%ebp),%edi
  408. stosw
  409. movl 16(%ebp),%edi
  410. movb %dl,%al
  411. stosw
  412. movl 12(%ebp),%edi
  413. movb %dh,%al
  414. stosw
  415. movl 8(%ebp),%edi
  416. xchgw %ecx,%eax
  417. stosw
  418. end;
  419. end;
  420. procedure setdate(year,month,day : word);
  421. begin
  422. {DOS only! You cannot change the system date in OS/2!}
  423. asm
  424. movw 8(%ebp),%cx
  425. movb 10(%ebp),%dh
  426. movb 12(%ebp),%dl
  427. movb $0x2b,%ah
  428. call syscall
  429. xorb %ah,%ah
  430. movw %ax,doserror
  431. end;
  432. end;
  433. procedure gettime(var hour,minute,second,sec100:word);
  434. begin
  435. asm
  436. movb $0x2c,%ah
  437. call syscall
  438. xorb %ah,%ah
  439. movl 20(%ebp),%edi
  440. movb %dl,%al
  441. stosw
  442. movl 16(%ebp),%edi
  443. movb %dh,%al
  444. stosw
  445. movl 12(%ebp),%edi
  446. movb %cl,%al
  447. stosw
  448. movl 8(%ebp),%edi
  449. movb %ch,%al
  450. stosw
  451. end;
  452. end;
  453. procedure settime(hour,minute,second,sec100:word);
  454. begin
  455. asm
  456. movb 8(%ebp),%ch
  457. movb 10(%ebp),%cl
  458. movb 12(%ebp),%dh
  459. movb 14(%ebp),%dl
  460. movb $0x2d,%ah
  461. call syscall
  462. xorb %ah,%ah
  463. movw %ax,doserror
  464. end;
  465. end;
  466. procedure getcbreak(var breakvalue:boolean);
  467. begin
  468. {! Do not use in OS/2. Also not recommended in DOS. Use
  469. signal handling instead.}
  470. asm
  471. movw $0x3300,%ax
  472. call syscall
  473. movl 8(%ebp),%eax
  474. movb %dl,(%eax)
  475. end;
  476. end;
  477. procedure setcbreak(breakvalue:boolean);
  478. begin
  479. {! Do not use in OS/2. Also not recommended in DOS. Use
  480. signal handling instead.}
  481. asm
  482. movb 8(%ebp),%dl
  483. movw $0x3301,%ax
  484. call syscall
  485. end;
  486. end;
  487. procedure getverify(var verify:boolean);
  488. begin
  489. {! Do not use in OS/2.}
  490. asm
  491. movb $0x54,%ah
  492. call syscall
  493. movl 8(%ebp),%edi
  494. stosb
  495. end;
  496. end;
  497. procedure setverify(verify:boolean);
  498. begin
  499. {! Do not use in OS/2.}
  500. asm
  501. movb 8(%ebp),%al
  502. movb $0x2e,%ah
  503. call syscall
  504. end;
  505. end;
  506. function diskfree(drive:byte):longint;
  507. var fi:TFSinfo;
  508. begin
  509. if os_mode=osDOS then
  510. {Function 36 is not supported in OS/2.}
  511. asm
  512. movb 8(%ebp),%dl
  513. movb $0x36,%ah
  514. call syscall
  515. cmpw $-1,%ax
  516. je .LDISKFREE1
  517. mulw %cx
  518. mulw %bx
  519. shll $16,%edx
  520. movw %ax,%dx
  521. xchgl %edx,%eax
  522. leave
  523. ret
  524. .LDISKFREE1:
  525. {$ifdef NOATTCDQ}
  526. cltd
  527. {$else}
  528. cwde
  529. {$endif}
  530. leave
  531. ret
  532. end
  533. else
  534. {In OS/2, we use the filesystem information.}
  535. begin
  536. doserror:=dosqueryFSinfo(drive,1,FI,sizeof(FI));
  537. if doserror=0 then
  538. diskfree:=FI.free_clusters*FI.sectors_per_cluster*
  539. FI.bytes_per_sector
  540. else
  541. diskfree:=-1;
  542. end;
  543. end;
  544. function disksize(drive:byte):longint;
  545. var fi:TFSinfo;
  546. begin
  547. if os_mode=osDOS then
  548. {Function 36 is not supported in OS/2.}
  549. asm
  550. movb 8(%ebp),%dl
  551. movb $0x36,%ah
  552. call syscall
  553. movw %dx,%bx
  554. cmpw $-1,%ax
  555. je .LDISKSIZE1
  556. mulw %cx
  557. mulw %bx
  558. shll $16,%edx
  559. movw %ax,%dx
  560. xchgl %edx,%eax
  561. leave
  562. ret
  563. .LDISKSIZE1:
  564. {$ifdef NOATTCDQ}
  565. cltd
  566. {$else}
  567. cwde
  568. {$endif}
  569. leave
  570. ret
  571. end
  572. else
  573. {In OS/2, we use the filesystem information.}
  574. begin
  575. doserror:=dosqueryFSinfo(drive,1,FI,sizeof(FI));
  576. if doserror=0 then
  577. disksize:=FI.total_clusters*FI.sectors_per_cluster*
  578. FI.bytes_per_sector
  579. else
  580. disksize:=-1;
  581. end;
  582. end;
  583. procedure searchrec2dossearchrec(var f:searchrec);
  584. const namesize=255;
  585. var l,i:longint;
  586. begin
  587. l:=length(f.name);
  588. for i:=1 to namesize do
  589. f.name[i-1]:=f.name[i];
  590. f.name[l]:=#0;
  591. end;
  592. procedure dossearchrec2searchrec(var f : searchrec);
  593. const namesize=255;
  594. var l,i : longint;
  595. begin
  596. for i:=0 to namesize do
  597. if f.name[i]=#0 then
  598. begin
  599. l:=i;
  600. break;
  601. end;
  602. for i:=namesize-1 downto 0 do
  603. f.name[i+1]:=f.name[i];
  604. f.name[0]:=char(l);
  605. end;
  606. procedure findfirst(const path:pathstr;attr:word;var f:searchRec);
  607. procedure _findfirst(path:pchar;attr:word;var f:searchrec);
  608. begin
  609. asm
  610. movl 12(%esp),%edx
  611. movw 16(%esp),%cx
  612. {No need to set DTA in EMX. Just give a pointer in ESI.}
  613. movl 18(%ebp),%esi
  614. movb $0x4e,%ah
  615. call syscall
  616. jnc .LFF
  617. movw %ax,doserror
  618. .LFF:
  619. end;
  620. end;
  621. var path0:array[0..255] of char;
  622. begin
  623. {No error.}
  624. doserror:=0;
  625. strPcopy(path0,path);
  626. _findfirst(path0,attr,f);
  627. dossearchrec2searchrec(f);
  628. end;
  629. procedure findnext(var f:searchRec);
  630. procedure _findnext(var f : searchrec);
  631. begin
  632. asm
  633. movl 12(%ebp),%esi
  634. movb $0x4f,%ah
  635. call syscall
  636. jnc .LFN
  637. movw %ax,doserror
  638. .LFN:
  639. end;
  640. end;
  641. begin
  642. {No error}
  643. doserror:=0;
  644. searchrec2dossearchrec(f);
  645. _findnext(f);
  646. dossearchrec2searchrec(f);
  647. end;
  648. procedure swapvectors;
  649. {For TP compatibility, this exists.}
  650. begin
  651. end;
  652. type PPchar=^Pchar;
  653. {$ASMMODE DIRECT}
  654. function envs:PPchar;assembler;
  655. asm
  656. movl _environ,%eax
  657. end ['EAX'];
  658. function envcount:longint;assembler;
  659. var hp : ppchar;
  660. asm
  661. movl _envc,%eax
  662. end ['EAX'];
  663. {$ASMMODE ATT}
  664. function envstr(index : longint) : string;
  665. var hp:PPchar;
  666. begin
  667. if (index<=0) or (index>envcount) then
  668. begin
  669. envstr:='';
  670. exit;
  671. end;
  672. hp:=envs+4*(index-1);
  673. envstr:=strpas(hp^);
  674. end;
  675. function getenv(const envvar : string) : string;
  676. var hs,_envvar : string;
  677. eqpos,i : longint;
  678. begin
  679. _envvar:=upcase(envvar);
  680. getenv:='';
  681. for i:=1 to envcount do
  682. begin
  683. hs:=envstr(i);
  684. eqpos:=pos('=',hs);
  685. if copy(hs,1,eqpos-1)=_envvar then
  686. begin
  687. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  688. exit;
  689. end;
  690. end;
  691. end;
  692. procedure fsplit(path:pathstr;var dir:dirstr;var name:namestr;
  693. var ext:extstr);
  694. var p1,i : longint;
  695. begin
  696. {Get drive name}
  697. p1:=pos(':',path);
  698. if p1>0 then
  699. begin
  700. dir:=path[1]+':';
  701. delete(path,1,p1);
  702. end
  703. else
  704. dir:='';
  705. { split the path and the name, there are no more path informtions }
  706. { if path contains no backslashes }
  707. while true do
  708. begin
  709. p1:=pos('\',path);
  710. if p1=0 then
  711. p1:=pos('/',path);
  712. if p1=0 then
  713. break;
  714. dir:=dir+copy(path,1,p1);
  715. delete(path,1,p1);
  716. end;
  717. {Try to find an extension.}
  718. ext:='';
  719. for i:=length(path) downto 1 do
  720. if path[i]='.' then
  721. begin
  722. ext:=copy(path,i,high(extstr));
  723. delete(path,i,length(path)-i+1);
  724. break;
  725. end;
  726. name:=path;
  727. end;
  728. function fexpand(const path:pathstr):pathstr;
  729. function get_current_drive:byte;assembler;
  730. asm
  731. movb $0x19,%ah
  732. call syscall
  733. end;
  734. var s,pa:string;
  735. i,j:longint;
  736. begin
  737. getdir(0,s);
  738. pa:=upcase(path);
  739. {Allow slash as backslash}
  740. for i:=1 to length(pa) do
  741. if pa[i]='/' then
  742. pa[i]:='\';
  743. if (length(pa)>1) and (pa[1] in ['A'..'Z']) and (pa[2]=':') then
  744. begin
  745. {We must get the right directory}
  746. getdir(byte(pa[1])-byte('A')+1,s);
  747. if (byte(pa[0])>2) and (pa[3]<>'\') then
  748. if pa[1]=s[1] then
  749. pa:=s+'\'+copy (pa,3,length(pa))
  750. else
  751. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  752. end
  753. else
  754. if pa[1]='\' then
  755. pa:=s[1]+':'+pa
  756. else if s[0]=#3 then
  757. pa:=s+pa
  758. else
  759. pa:=s+'\'+pa;
  760. {First remove all references to '\.\'}
  761. i:=pos('\.\',pa);
  762. while i<>0 do
  763. begin
  764. delete(pa,i,2);
  765. i:=pos('\.\',pa);
  766. end;
  767. {Now remove also all references to '\..\' + of course previous dirs..}
  768. repeat
  769. i:=pos('\..\',pa);
  770. if i<>0 then
  771. begin
  772. j:=i-1;
  773. while (j>1) and (pa[j]<>'\') do
  774. dec(j);
  775. delete (pa,j,i-j+3);
  776. end;
  777. until i=0;
  778. {Remove End . and \}
  779. if (length(pa)>0) and (pa[length(pa)]='.') then
  780. dec(byte(pa[0]));
  781. if (length(pa)>0) and (pa[length(pa)]='\') then
  782. dec(byte(pa[0]));
  783. fexpand:=pa;
  784. end;
  785. procedure packtime(var d:datetime;var time:longint);
  786. var zs:longint;
  787. begin
  788. time:=-1980;
  789. time:=time+d.year and 127;
  790. time:=time shl 4;
  791. time:=time+d.month;
  792. time:=time shl 5;
  793. time:=time+d.day;
  794. time:=time shl 16;
  795. zs:=d.hour;
  796. zs:=zs shl 6;
  797. zs:=zs+d.min;
  798. zs:=zs shl 5;
  799. zs:=zs+d.sec div 2;
  800. time:=time+(zs and $ffff);
  801. end;
  802. procedure unpacktime (time:longint;var d:datetime);
  803. begin
  804. d.sec:=(time and 31) * 2;
  805. time:=time shr 5;
  806. d.min:=time and 63;
  807. time:=time shr 6;
  808. d.hour:=time and 31;
  809. time:=time shr 5;
  810. d.day:=time and 31;
  811. time:=time shr 5;
  812. d.month:=time and 15;
  813. time:=time shr 4;
  814. d.year:=time+1980;
  815. end;
  816. procedure getfattr(var f;var attr : word);assembler;
  817. asm
  818. movw $0x4300,%ax
  819. movl f,%edx
  820. {addl $filerec.name,%edx Doesn't work!!}
  821. addl $60,%edx
  822. call syscall
  823. movl attr,%ebx
  824. movw %cx,(%ebx)
  825. end;
  826. procedure setfattr(var f;attr : word);assembler;
  827. asm
  828. movw $0x4301,%ax
  829. movl f,%edx
  830. {addl $filerec.name,%edx Doesn't work!!}
  831. addl $60,%edx
  832. movw attr,%cx
  833. call syscall
  834. end;
  835. end.
  836. {
  837. $Log$
  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. }