dos.pp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  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. end;
  215. procedure gettime(var hour,minute,second,sec100 : word);
  216. begin
  217. dosregs.ah:=$2c;
  218. msdos(dosregs);
  219. hour:=dosregs.ch;
  220. minute:=dosregs.cl;
  221. second:=dosregs.dh;
  222. sec100:=dosregs.dl;
  223. end;
  224. procedure settime(hour,minute,second,sec100 : word);
  225. begin
  226. dosregs.ch:=hour;
  227. dosregs.cl:=minute;
  228. dosregs.dh:=second;
  229. dosregs.dl:=sec100;
  230. dosregs.ah:=$2d;
  231. msdos(dosregs);
  232. DosError:=0;
  233. end;
  234. Procedure packtime(var t : datetime;var p : longint);
  235. Begin
  236. 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);
  237. End;
  238. Procedure unpacktime(p : longint;var t : datetime);
  239. Begin
  240. with t do
  241. begin
  242. sec:=(p and 31) shl 1;
  243. min:=(p shr 5) and 63;
  244. hour:=(p shr 11) and 31;
  245. day:=(p shr 16) and 31;
  246. month:=(p shr 21) and 15;
  247. year:=(p shr 25)+1980;
  248. end;
  249. End;
  250. {******************************************************************************
  251. --- Exec ---
  252. ******************************************************************************}
  253. var
  254. lastdosexitcode : word;
  255. procedure exec(const path : pathstr;const comline : comstr);
  256. var
  257. i : longint;
  258. b : array[0..255] of char;
  259. begin
  260. doserror:=0;
  261. for i:=1to length(path) do
  262. if path[i]='/' then
  263. b[i-1]:='\'
  264. else
  265. b[i-1]:=path[i];
  266. b[i]:=' ';
  267. inc(i);
  268. move(comline[1],b[i],length(comline));
  269. inc(i,length(comline));
  270. b[i]:=#0;
  271. asm
  272. leal b,%ebx
  273. movw $0xff07,%ax
  274. int $0x21
  275. movw %ax,LastDosExitCode
  276. end;
  277. end;
  278. function dosexitcode : word;
  279. begin
  280. dosexitcode:=lastdosexitcode;
  281. end;
  282. procedure getcbreak(var breakvalue : boolean);
  283. begin
  284. dosregs.ax:=$3300;
  285. msdos(dosregs);
  286. breakvalue:=dosregs.dl<>0;
  287. end;
  288. procedure setcbreak(breakvalue : boolean);
  289. begin
  290. dosregs.ax:=$3301;
  291. dosregs.dl:=ord(breakvalue);
  292. msdos(dosregs);
  293. end;
  294. procedure getverify(var verify : boolean);
  295. begin
  296. dosregs.ah:=$54;
  297. msdos(dosregs);
  298. verify:=dosregs.al<>0;
  299. end;
  300. procedure setverify(verify : boolean);
  301. begin
  302. dosregs.ah:=$2e;
  303. dosregs.al:=ord(verify);
  304. msdos(dosregs);
  305. end;
  306. {******************************************************************************
  307. --- Disk ---
  308. ******************************************************************************}
  309. function diskfree(drive : byte) : longint;
  310. begin
  311. dosregs.dl:=drive;
  312. dosregs.ah:=$36;
  313. msdos(dosregs);
  314. if dosregs.ax<>$FFFF then
  315. diskfree:=dosregs.ax*dosregs.bx*dosregs.cx
  316. else
  317. diskfree:=-1;
  318. end;
  319. function disksize(drive : byte) : longint;
  320. begin
  321. dosregs.dl:=drive;
  322. dosregs.ah:=$36;
  323. msdos(dosregs);
  324. if dosregs.ax<>$FFFF then
  325. disksize:=dosregs.ax*dosregs.cx*dosregs.dx
  326. else
  327. disksize:=-1;
  328. end;
  329. {******************************************************************************
  330. --- DosFindfirst DosFindNext ---
  331. ******************************************************************************}
  332. procedure dossearchrec2searchrec(var f : searchrec);
  333. var
  334. len : longint;
  335. begin
  336. len:=StrLen(@f.Name);
  337. Move(f.Name[0],f.Name[1],Len);
  338. f.Name[0]:=chr(len);
  339. end;
  340. procedure Dosfindfirst(path : pchar;attr : word;var f : searchrec);
  341. var
  342. i : longint;
  343. begin
  344. { allow slash as backslash }
  345. for i:=0 to strlen(path) do
  346. if path[i]='/' then path[i]:='\';
  347. asm
  348. movl f,%edx
  349. movb $0x1a,%ah
  350. int $0x21
  351. movl path,%edx
  352. movzwl attr,%ecx
  353. movb $0x4e,%ah
  354. int $0x21
  355. jnc .LFF
  356. movw %ax,DosError
  357. .LFF:
  358. end;
  359. dossearchrec2searchrec(f);
  360. end;
  361. procedure Dosfindnext(var f : searchrec);
  362. begin
  363. asm
  364. movl 12(%ebp),%edx
  365. movb $0x1a,%ah
  366. int $0x21
  367. movb $0x4f,%ah
  368. int $0x21
  369. jnc .LFN
  370. movw %ax,DosError
  371. .LFN:
  372. end;
  373. dossearchrec2searchrec(f);
  374. end;
  375. {******************************************************************************
  376. --- Findfirst FindNext ---
  377. ******************************************************************************}
  378. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  379. var
  380. path0 : array[0..256] of char;
  381. begin
  382. doserror:=0;
  383. strpcopy(path0,path);
  384. Dosfindfirst(path0,attr,f);
  385. end;
  386. procedure findnext(var f : searchRec);
  387. begin
  388. doserror:=0;
  389. Dosfindnext(f);
  390. end;
  391. Procedure FindClose(Var f: SearchRec);
  392. begin
  393. DosError:=0;
  394. end;
  395. procedure swapvectors;
  396. begin
  397. DosError:=0;
  398. end;
  399. {******************************************************************************
  400. --- File ---
  401. ******************************************************************************}
  402. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  403. var
  404. p1,i : longint;
  405. begin
  406. { allow slash as backslash }
  407. for i:=1 to length(path) do
  408. if path[i]='/' then path[i]:='\';
  409. { get drive name }
  410. p1:=pos(':',path);
  411. if p1>0 then
  412. begin
  413. dir:=path[1]+':';
  414. delete(path,1,p1);
  415. end
  416. else
  417. dir:='';
  418. { split the path and the name, there are no more path informtions }
  419. { if path contains no backslashes }
  420. while true do
  421. begin
  422. p1:=pos('\',path);
  423. if p1=0 then
  424. break;
  425. dir:=dir+copy(path,1,p1);
  426. delete(path,1,p1);
  427. end;
  428. { try to find out a extension }
  429. begin
  430. p1:=pos('.',path);
  431. if p1>0 then
  432. begin
  433. ext:=copy(path,p1,4);
  434. delete(path,p1,length(path)-p1+1);
  435. end
  436. else
  437. ext:='';
  438. name:=path;
  439. end;
  440. end;
  441. (*
  442. function FExpand (const Path: PathStr): PathStr;
  443. - declared in fexpand.inc
  444. *)
  445. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  446. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  447. {$I fexpand.inc}
  448. {$UNDEF FPC_FEXPAND_DRIVES}
  449. {$UNDEF FPC_FEXPAND_UNC}
  450. Function FSearch(path: pathstr; dirlist: string): pathstr;
  451. var
  452. i,p1 : longint;
  453. s : searchrec;
  454. newdir : pathstr;
  455. begin
  456. { No wildcards allowed in these things }
  457. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  458. fsearch:=''
  459. else
  460. begin
  461. { allow slash as backslash }
  462. for i:=1 to length(dirlist) do
  463. if dirlist[i]='/' then dirlist[i]:='\';
  464. repeat
  465. p1:=pos(';',dirlist);
  466. if p1<>0 then
  467. begin
  468. newdir:=copy(dirlist,1,p1-1);
  469. delete(dirlist,1,p1);
  470. end
  471. else
  472. begin
  473. newdir:=dirlist;
  474. dirlist:='';
  475. end;
  476. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  477. newdir:=newdir+'\';
  478. findfirst(newdir+path,anyfile,s);
  479. if doserror=0 then
  480. newdir:=newdir+path
  481. else
  482. newdir:='';
  483. until (dirlist='') or (newdir<>'');
  484. fsearch:=newdir;
  485. end;
  486. end;
  487. {******************************************************************************
  488. --- Get/Set File Time,Attr ---
  489. ******************************************************************************}
  490. procedure getftime(var f;var time : longint);
  491. begin
  492. dosregs.bx:=textrec(f).handle;
  493. dosregs.ax:=$5700;
  494. msdos(dosregs);
  495. loaddoserror;
  496. time:=(dosregs.dx shl 16)+dosregs.cx;
  497. end;
  498. procedure setftime(var f;time : longint);
  499. begin
  500. dosregs.bx:=textrec(f).handle;
  501. dosregs.cx:=time and $ffff;
  502. dosregs.dx:=time shr 16;
  503. dosregs.ax:=$5701;
  504. msdos(dosregs);
  505. loaddoserror;
  506. end;
  507. procedure getfattr(var f;var attr : word);
  508. begin
  509. dosregs.edx:=longint(@filerec(f).name);
  510. dosregs.ax:=$4300;
  511. msdos(dosregs);
  512. LoadDosError;
  513. Attr:=dosregs.cx;
  514. end;
  515. procedure setfattr(var f;attr : word);
  516. begin
  517. dosregs.edx:=longint(@filerec(f).name);
  518. dosregs.ax:=$4301;
  519. dosregs.cx:=attr;
  520. msdos(dosregs);
  521. LoadDosError;
  522. end;
  523. {******************************************************************************
  524. --- Environment ---
  525. ******************************************************************************}
  526. function envcount : longint;
  527. var
  528. hp : ppchar;
  529. begin
  530. hp:=envp;
  531. envcount:=0;
  532. while assigned(hp^) do
  533. begin
  534. inc(envcount);
  535. hp:=hp+4;
  536. end;
  537. end;
  538. function envstr(index : integer) : string;
  539. begin
  540. if (index<=0) or (index>envcount) then
  541. begin
  542. envstr:='';
  543. exit;
  544. end;
  545. envstr:=strpas(ppchar(envp+4*(index-1))^);
  546. end;
  547. Function GetEnv(envvar: string): string;
  548. var
  549. hp : ppchar;
  550. hs : string;
  551. eqpos : longint;
  552. begin
  553. envvar:=upcase(envvar);
  554. hp:=envp;
  555. getenv:='';
  556. while assigned(hp^) do
  557. begin
  558. hs:=strpas(hp^);
  559. eqpos:=pos('=',hs);
  560. if copy(hs,1,eqpos-1)=envvar then
  561. begin
  562. getenv:=copy(hs,eqpos+1,255);
  563. exit;
  564. end;
  565. hp:=hp+4;
  566. end;
  567. end;
  568. {******************************************************************************
  569. --- Not Supported ---
  570. ******************************************************************************}
  571. Procedure keep(exitcode : word);
  572. Begin
  573. End;
  574. Procedure getintvec(intno : byte;var vector : pointer);
  575. Begin
  576. End;
  577. Procedure setintvec(intno : byte;vector : pointer);
  578. Begin
  579. End;
  580. end.
  581. {
  582. $Log$
  583. Revision 1.4 2001-11-23 00:27:22 carl
  584. * updated behavior of some routines to conform to docs
  585. Revision 1.3 2001/03/10 09:57:51 hajny
  586. * FExpand without IOResult change, remaining direct asm removed
  587. Revision 1.2 2000/07/13 11:33:38 michael
  588. + removed logs
  589. }