dos.pp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team.
  5. Dos unit for BP7 compatible RTL
  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. Uses
  15. Go32;
  16. Const
  17. {Bitmasks for CPU Flags}
  18. fcarry = $0001;
  19. fparity = $0004;
  20. fauxiliary = $0010;
  21. fzero = $0040;
  22. fsign = $0080;
  23. foverflow = $0800;
  24. {Bitmasks for file attribute}
  25. readonly = $01;
  26. hidden = $02;
  27. sysfile = $04;
  28. volumeid = $08;
  29. directory = $10;
  30. archive = $20;
  31. anyfile = $3F;
  32. {File Status}
  33. fmclosed = $D7B0;
  34. fminput = $D7B1;
  35. fmoutput = $D7B2;
  36. fminout = $D7B3;
  37. Type
  38. comstr = string[127]; { command line string }
  39. pathstr = string[79]; { string for a file path }
  40. dirstr = string[67]; { string for a directory }
  41. namestr = string[8]; { string for a file name }
  42. extstr = string[4]; { string for an extension }
  43. {
  44. filerec.inc contains the definition of the filerec.
  45. textrec.inc contains the definition of the textrec.
  46. It is in a separate file to make it available in other units without
  47. having to use the DOS unit for it.
  48. }
  49. {$i filerec.inc}
  50. {$i textrec.inc}
  51. DateTime = packed record
  52. Year,
  53. Month,
  54. Day,
  55. Hour,
  56. Min,
  57. Sec : word;
  58. End;
  59. searchrec = packed record
  60. fill : array[1..21] of byte;
  61. attr : byte;
  62. time : longint;
  63. reserved : word; { requires the DOS extender (DJ GNU-C) }
  64. size : longint;
  65. name : string[15]; { the same size as declared by (DJ GNU C) }
  66. end;
  67. registers = packed record
  68. case i : integer of
  69. 0 : (ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,f8,flags,fs,gs : word);
  70. 1 : (al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh : byte);
  71. 2 : (eax, ebx, ecx, edx, ebp, esi, edi : longint);
  72. end;
  73. Var
  74. DosError : integer;
  75. {Interrupt}
  76. Procedure Intr(intno: byte; var regs: registers);
  77. Procedure MSDos(var regs: registers);
  78. {Info/Date/Time}
  79. Function DosVersion: Word;
  80. Procedure GetDate(var year, month, mday, wday: word);
  81. Procedure GetTime(var hour, minute, second, sec100: word);
  82. procedure SetDate(year,month,day: word);
  83. Procedure SetTime(hour,minute,second,sec100: word);
  84. Procedure UnpackTime(p: longint; var t: datetime);
  85. Procedure PackTime(var t: datetime; var p: longint);
  86. {Exec}
  87. Procedure Exec(const path: pathstr; const comline: comstr);
  88. Function DosExitCode: word;
  89. {Disk}
  90. Function DiskFree(drive: byte) : longint;
  91. Function DiskSize(drive: byte) : longint;
  92. Procedure FindFirst(const path: pathstr; attr: word; var f: searchRec);
  93. Procedure FindNext(var f: searchRec);
  94. Procedure FindClose(Var f: SearchRec);
  95. {File}
  96. Procedure GetFAttr(var f; var attr: word);
  97. Procedure GetFTime(var f; var time: longint);
  98. Function FSearch(path: pathstr; dirlist: string): pathstr;
  99. Function FExpand(const path: pathstr): pathstr;
  100. Procedure FSplit(path: pathstr; var dir: dirstr; var name: namestr; var ext: extstr);
  101. {Environment}
  102. Function EnvCount: longint;
  103. Function EnvStr(index: integer): string;
  104. Function GetEnv(envvar: string): string;
  105. {Misc}
  106. Procedure SetFAttr(var f; attr: word);
  107. Procedure SetFTime(var f; time: longint);
  108. Procedure GetCBreak(var breakvalue: boolean);
  109. Procedure SetCBreak(breakvalue: boolean);
  110. Procedure GetVerify(var verify: boolean);
  111. Procedure SetVerify(verify: boolean);
  112. {Do Nothing Functions}
  113. Procedure SwapVectors;
  114. Procedure GetIntVec(intno: byte; var vector: pointer);
  115. Procedure SetIntVec(intno: byte; vector: pointer);
  116. Procedure Keep(exitcode: word);
  117. implementation
  118. uses
  119. strings;
  120. {$ASMMODE ATT}
  121. {******************************************************************************
  122. --- Dos Interrupt ---
  123. ******************************************************************************}
  124. var
  125. dosregs : registers;
  126. procedure LoadDosError;
  127. begin
  128. if (dosregs.flags and carryflag) <> 0 then
  129. { conversion from word to integer !!
  130. gave a Bound check error if ax is $FFFF !! PM }
  131. doserror:=integer(dosregs.ax)
  132. else
  133. doserror:=0;
  134. end;
  135. {$ASMMODE DIRECT}
  136. procedure intr(intno : byte;var regs : registers);
  137. begin
  138. asm
  139. .data
  140. int86:
  141. .byte 0xcd
  142. int86_vec:
  143. .byte 0x03
  144. jmp int86_retjmp
  145. .text
  146. movl 8(%ebp),%eax
  147. movb %al,int86_vec
  148. movl 10(%ebp),%eax
  149. // do not use first int
  150. addl $2,%eax
  151. movl 4(%eax),%ebx
  152. movl 8(%eax),%ecx
  153. movl 12(%eax),%edx
  154. movl 16(%eax),%ebp
  155. movl 20(%eax),%esi
  156. movl 24(%eax),%edi
  157. movl (%eax),%eax
  158. jmp int86
  159. int86_retjmp:
  160. pushf
  161. pushl %ebp
  162. pushl %eax
  163. movl %esp,%ebp
  164. // calc EBP new
  165. addl $12,%ebp
  166. movl 10(%ebp),%eax
  167. // do not use first int
  168. addl $2,%eax
  169. popl (%eax)
  170. movl %ebx,4(%eax)
  171. movl %ecx,8(%eax)
  172. movl %edx,12(%eax)
  173. // restore EBP
  174. popl %edx
  175. movl %edx,16(%eax)
  176. movl %esi,20(%eax)
  177. movl %edi,24(%eax)
  178. // ignore ES and DS
  179. popl %ebx /* flags */
  180. movl %ebx,32(%eax)
  181. // FS and GS too
  182. end;
  183. end;
  184. {$ASMMODE ATT}
  185. procedure msdos(var regs : registers);
  186. begin
  187. intr($21,regs);
  188. end;
  189. {******************************************************************************
  190. --- Info / Date / Time ---
  191. ******************************************************************************}
  192. function dosversion : word;
  193. begin
  194. dosregs.ax:=$3000;
  195. msdos(dosregs);
  196. dosversion:=dosregs.ax;
  197. end;
  198. procedure getdate(var year,month,mday,wday : word);
  199. begin
  200. dosregs.ax:=$2a00;
  201. msdos(dosregs);
  202. wday:=dosregs.al;
  203. year:=dosregs.cx;
  204. month:=dosregs.dh;
  205. mday:=dosregs.dl;
  206. end;
  207. procedure setdate(year,month,day : word);
  208. begin
  209. dosregs.cx:=year;
  210. dosregs.dh:=month;
  211. dosregs.dl:=day;
  212. dosregs.ah:=$2b;
  213. msdos(dosregs);
  214. DosError:=0;
  215. end;
  216. procedure gettime(var hour,minute,second,sec100 : word);
  217. begin
  218. dosregs.ah:=$2c;
  219. msdos(dosregs);
  220. hour:=dosregs.ch;
  221. minute:=dosregs.cl;
  222. second:=dosregs.dh;
  223. sec100:=dosregs.dl;
  224. DosError:=0;
  225. end;
  226. procedure settime(hour,minute,second,sec100 : word);
  227. begin
  228. dosregs.ch:=hour;
  229. dosregs.cl:=minute;
  230. dosregs.dh:=second;
  231. dosregs.dl:=sec100;
  232. dosregs.ah:=$2d;
  233. msdos(dosregs);
  234. DosError:=0;
  235. end;
  236. Procedure packtime(var t : datetime;var p : longint);
  237. Begin
  238. p:=(t.sec shr 1)+(t.min shl 5)+(t.hour shl 11)+(t.day shl 16)+(t.month shl 21)+((t.year-1980) shl 25);
  239. End;
  240. Procedure unpacktime(p : longint;var t : datetime);
  241. Begin
  242. with t do
  243. begin
  244. sec:=(p and 31) shl 1;
  245. min:=(p shr 5) and 63;
  246. hour:=(p shr 11) and 31;
  247. day:=(p shr 16) and 31;
  248. month:=(p shr 21) and 15;
  249. year:=(p shr 25)+1980;
  250. end;
  251. End;
  252. {******************************************************************************
  253. --- Exec ---
  254. ******************************************************************************}
  255. var
  256. lastdosexitcode : word;
  257. procedure exec(const path : pathstr;const comline : comstr);
  258. var
  259. i : longint;
  260. b : array[0..255] of char;
  261. begin
  262. doserror:=0;
  263. for i:=1to length(path) do
  264. if path[i]='/' then
  265. b[i-1]:='\'
  266. else
  267. b[i-1]:=path[i];
  268. b[i]:=' ';
  269. inc(i);
  270. move(comline[1],b[i],length(comline));
  271. inc(i,length(comline));
  272. b[i]:=#0;
  273. asm
  274. leal b,%ebx
  275. movw $0xff07,%ax
  276. int $0x21
  277. movw %ax,LastDosExitCode
  278. end;
  279. end;
  280. function dosexitcode : word;
  281. begin
  282. dosexitcode:=lastdosexitcode;
  283. end;
  284. procedure getcbreak(var breakvalue : boolean);
  285. begin
  286. DosError:=0;
  287. dosregs.ax:=$3300;
  288. msdos(dosregs);
  289. breakvalue:=dosregs.dl<>0;
  290. end;
  291. procedure setcbreak(breakvalue : boolean);
  292. begin
  293. DosError:=0;
  294. dosregs.ax:=$3301;
  295. dosregs.dl:=ord(breakvalue);
  296. msdos(dosregs);
  297. end;
  298. procedure getverify(var verify : boolean);
  299. begin
  300. DosError:=0;
  301. dosregs.ah:=$54;
  302. msdos(dosregs);
  303. verify:=dosregs.al<>0;
  304. end;
  305. procedure setverify(verify : boolean);
  306. begin
  307. DosError:=0;
  308. dosregs.ah:=$2e;
  309. dosregs.al:=ord(verify);
  310. msdos(dosregs);
  311. end;
  312. {******************************************************************************
  313. --- Disk ---
  314. ******************************************************************************}
  315. function diskfree(drive : byte) : longint;
  316. begin
  317. DosError:=0;
  318. dosregs.dl:=drive;
  319. dosregs.ah:=$36;
  320. msdos(dosregs);
  321. if dosregs.ax<>$FFFF then
  322. diskfree:=dosregs.ax*dosregs.bx*dosregs.cx
  323. else
  324. diskfree:=-1;
  325. end;
  326. function disksize(drive : byte) : longint;
  327. begin
  328. DosError:=0;
  329. dosregs.dl:=drive;
  330. dosregs.ah:=$36;
  331. msdos(dosregs);
  332. if dosregs.ax<>$FFFF then
  333. disksize:=dosregs.ax*dosregs.cx*dosregs.dx
  334. else
  335. disksize:=-1;
  336. end;
  337. {******************************************************************************
  338. --- DosFindfirst DosFindNext ---
  339. ******************************************************************************}
  340. procedure dossearchrec2searchrec(var f : searchrec);
  341. var
  342. len : longint;
  343. begin
  344. len:=StrLen(@f.Name);
  345. Move(f.Name[0],f.Name[1],Len);
  346. f.Name[0]:=chr(len);
  347. end;
  348. procedure Dosfindfirst(path : pchar;attr : word;var f : searchrec);
  349. var
  350. i : longint;
  351. begin
  352. { allow slash as backslash }
  353. for i:=0 to strlen(path) do
  354. if path[i]='/' then path[i]:='\';
  355. asm
  356. movl f,%edx
  357. movb $0x1a,%ah
  358. int $0x21
  359. movl path,%edx
  360. movzwl attr,%ecx
  361. movb $0x4e,%ah
  362. int $0x21
  363. jnc .LFF
  364. movw %ax,DosError
  365. .LFF:
  366. end;
  367. dossearchrec2searchrec(f);
  368. end;
  369. procedure Dosfindnext(var f : searchrec);
  370. begin
  371. asm
  372. movl 12(%ebp),%edx
  373. movb $0x1a,%ah
  374. int $0x21
  375. movb $0x4f,%ah
  376. int $0x21
  377. jnc .LFN
  378. movw %ax,DosError
  379. .LFN:
  380. end;
  381. dossearchrec2searchrec(f);
  382. end;
  383. {******************************************************************************
  384. --- Findfirst FindNext ---
  385. ******************************************************************************}
  386. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  387. var
  388. path0 : array[0..256] of char;
  389. begin
  390. doserror:=0;
  391. strpcopy(path0,path);
  392. Dosfindfirst(path0,attr,f);
  393. end;
  394. procedure findnext(var f : searchRec);
  395. begin
  396. doserror:=0;
  397. Dosfindnext(f);
  398. end;
  399. Procedure FindClose(Var f: SearchRec);
  400. begin
  401. DosError:=0;
  402. end;
  403. procedure swapvectors;
  404. begin
  405. DosError:=0;
  406. end;
  407. {******************************************************************************
  408. --- File ---
  409. ******************************************************************************}
  410. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  411. var
  412. p1,i : longint;
  413. begin
  414. { allow slash as backslash }
  415. for i:=1 to length(path) do
  416. if path[i]='/' then path[i]:='\';
  417. { get drive name }
  418. p1:=pos(':',path);
  419. if p1>0 then
  420. begin
  421. dir:=path[1]+':';
  422. delete(path,1,p1);
  423. end
  424. else
  425. dir:='';
  426. { split the path and the name, there are no more path informtions }
  427. { if path contains no backslashes }
  428. while true do
  429. begin
  430. p1:=pos('\',path);
  431. if p1=0 then
  432. break;
  433. dir:=dir+copy(path,1,p1);
  434. delete(path,1,p1);
  435. end;
  436. { try to find out a extension }
  437. begin
  438. p1:=pos('.',path);
  439. if p1>0 then
  440. begin
  441. ext:=copy(path,p1,4);
  442. delete(path,p1,length(path)-p1+1);
  443. end
  444. else
  445. ext:='';
  446. name:=path;
  447. end;
  448. end;
  449. (*
  450. function FExpand (const Path: PathStr): PathStr;
  451. - declared in fexpand.inc
  452. *)
  453. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  454. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  455. {$I fexpand.inc}
  456. {$UNDEF FPC_FEXPAND_DRIVES}
  457. {$UNDEF FPC_FEXPAND_UNC}
  458. Function FSearch(path: pathstr; dirlist: string): pathstr;
  459. var
  460. i,p1 : longint;
  461. s : searchrec;
  462. newdir : pathstr;
  463. begin
  464. { No wildcards allowed in these things }
  465. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  466. fsearch:=''
  467. else
  468. begin
  469. { allow slash as backslash }
  470. for i:=1 to length(dirlist) do
  471. if dirlist[i]='/' then dirlist[i]:='\';
  472. repeat
  473. p1:=pos(';',dirlist);
  474. if p1<>0 then
  475. begin
  476. newdir:=copy(dirlist,1,p1-1);
  477. delete(dirlist,1,p1);
  478. end
  479. else
  480. begin
  481. newdir:=dirlist;
  482. dirlist:='';
  483. end;
  484. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  485. newdir:=newdir+'\';
  486. findfirst(newdir+path,anyfile,s);
  487. if doserror=0 then
  488. newdir:=newdir+path
  489. else
  490. newdir:='';
  491. until (dirlist='') or (newdir<>'');
  492. fsearch:=newdir;
  493. end;
  494. end;
  495. {******************************************************************************
  496. --- Get/Set File Time,Attr ---
  497. ******************************************************************************}
  498. procedure getftime(var f;var time : longint);
  499. begin
  500. dosregs.bx:=textrec(f).handle;
  501. dosregs.ax:=$5700;
  502. msdos(dosregs);
  503. loaddoserror;
  504. time:=(dosregs.dx shl 16)+dosregs.cx;
  505. end;
  506. procedure setftime(var f;time : longint);
  507. begin
  508. dosregs.bx:=textrec(f).handle;
  509. dosregs.cx:=time and $ffff;
  510. dosregs.dx:=time shr 16;
  511. dosregs.ax:=$5701;
  512. msdos(dosregs);
  513. loaddoserror;
  514. end;
  515. procedure getfattr(var f;var attr : word);
  516. begin
  517. dosregs.edx:=longint(@filerec(f).name);
  518. dosregs.ax:=$4300;
  519. msdos(dosregs);
  520. LoadDosError;
  521. Attr:=dosregs.cx;
  522. end;
  523. procedure setfattr(var f;attr : word);
  524. begin
  525. dosregs.edx:=longint(@filerec(f).name);
  526. dosregs.ax:=$4301;
  527. dosregs.cx:=attr;
  528. msdos(dosregs);
  529. LoadDosError;
  530. end;
  531. {******************************************************************************
  532. --- Environment ---
  533. ******************************************************************************}
  534. function envcount : longint;
  535. var
  536. hp : ppchar;
  537. begin
  538. hp:=envp;
  539. envcount:=0;
  540. while assigned(hp^) do
  541. begin
  542. inc(envcount);
  543. hp:=hp+4;
  544. end;
  545. end;
  546. function envstr(index : integer) : string;
  547. begin
  548. if (index<=0) or (index>envcount) then
  549. begin
  550. envstr:='';
  551. exit;
  552. end;
  553. envstr:=strpas(ppchar(envp+4*(index-1))^);
  554. end;
  555. Function GetEnv(envvar: string): string;
  556. var
  557. hp : ppchar;
  558. hs : string;
  559. eqpos : longint;
  560. begin
  561. envvar:=upcase(envvar);
  562. hp:=envp;
  563. getenv:='';
  564. while assigned(hp^) do
  565. begin
  566. hs:=strpas(hp^);
  567. eqpos:=pos('=',hs);
  568. if copy(hs,1,eqpos-1)=envvar then
  569. begin
  570. getenv:=copy(hs,eqpos+1,255);
  571. exit;
  572. end;
  573. hp:=hp+4;
  574. end;
  575. end;
  576. {******************************************************************************
  577. --- Not Supported ---
  578. ******************************************************************************}
  579. Procedure keep(exitcode : word);
  580. Begin
  581. End;
  582. Procedure getintvec(intno : byte;var vector : pointer);
  583. Begin
  584. End;
  585. Procedure setintvec(intno : byte;vector : pointer);
  586. Begin
  587. End;
  588. end.
  589. {
  590. $Log$
  591. Revision 1.3 2001-03-10 09:57:51 hajny
  592. * FExpand without IOResult change, remaining direct asm removed
  593. Revision 1.2 2000/07/13 11:33:38 michael
  594. + removed logs
  595. }