dos.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2004 by the Free Pascal development team.
  4. Dos unit for BP7 compatible RTL (novell netware libc)
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit dos;
  12. interface
  13. uses libc;
  14. Type
  15. searchrec = packed record
  16. DirP : POINTER; { used for opendir }
  17. EntryP: POINTER; { and readdir }
  18. Magic : WORD;
  19. fill : array[1..11] of byte;
  20. attr : byte;
  21. time : longint;
  22. size : longint;
  23. name : string[255];
  24. { Internals used by netware port only: }
  25. _mask : string[255];
  26. _dir : string[255];
  27. _attr : word;
  28. end;
  29. {$i dosh.inc}
  30. {Extra Utils}
  31. function weekday(y,m,d : longint) : longint;
  32. implementation
  33. uses
  34. strings;
  35. {$DEFINE HAS_GETMSCOUNT}
  36. {$DEFINE HAS_KEEP}
  37. {$DEFINE FPC_FEXPAND_DRIVES}
  38. {$DEFINE FPC_FEXPAND_VOLUMES}
  39. {$DEFINE FPC_FEXPAND_NO_DEFAULT_PATHS}
  40. {$i dos.inc}
  41. {$ASMMODE ATT}
  42. {*****************************************************************************
  43. --- Info / Date / Time ---
  44. ******************************************************************************}
  45. {$PACKRECORDS 4}
  46. function dosversion : word;
  47. var i : Tutsname;
  48. begin
  49. if Fpuname (i) >= 0 then
  50. dosversion := WORD (i.netware_minor) SHL 8 + i.netware_major
  51. else dosversion := $0005;
  52. end;
  53. function WeekDay (y,m,d:longint):longint;
  54. {
  55. Calculates th day of the week. returns -1 on error
  56. }
  57. var
  58. u,v : longint;
  59. begin
  60. if (m<1) or (m>12) or (y<1600) or (y>4000) or
  61. (d<1) or (d>30+((m+ord(m>7)) and 1)-ord(m=2)) or
  62. ((m*d=58) and (((y mod 4>0) or (y mod 100=0)) and (y mod 400>0))) then
  63. WeekDay:=-1
  64. else
  65. begin
  66. u:=m;
  67. v:=y;
  68. if m<3 then
  69. begin
  70. inc(u,12);
  71. dec(v);
  72. end;
  73. WeekDay:=(d+2*u+((3*(u+1)) div 5)+v+(v div 4)-(v div 100)+(v div 400)+1) mod 7;
  74. end;
  75. end;
  76. procedure getdate(var year,month,mday,wday : word);
  77. var
  78. t : TTime_t;
  79. tm : Ttm;
  80. begin
  81. time(t); localtime_r(t,tm);
  82. with tm do
  83. begin
  84. year := tm_year+1900;
  85. month := tm_mon+1;
  86. mday := tm_mday;
  87. wday := tm_wday;
  88. end;
  89. end;
  90. procedure setdate(year,month,day : word);
  91. begin
  92. end;
  93. procedure gettime(var hour,minute,second,sec100 : word);
  94. var
  95. t : TTime_t;
  96. tm : Ttm;
  97. begin
  98. time(t); localtime_r(t,tm);
  99. with tm do
  100. begin
  101. hour := tm_hour;
  102. minute := tm_min;
  103. second := tm_sec;
  104. sec100 := 0;
  105. end;
  106. end;
  107. procedure settime(hour,minute,second,sec100 : word);
  108. begin
  109. end;
  110. function GetMsCount: int64;
  111. var
  112. tv : TimeVal;
  113. tz : TimeZone;
  114. begin
  115. FPGetTimeOfDay (tv, tz);
  116. GetMsCount := int64 (tv.tv_Sec) * 1000 + tv.tv_uSec div 1000;
  117. end;
  118. {******************************************************************************
  119. --- Exec ---
  120. ******************************************************************************}
  121. const maxargs=256;
  122. procedure exec(const path : pathstr;const comline : comstr);
  123. var c : comstr;
  124. i : integer;
  125. args : array[0..maxargs] of pchar;
  126. arg0 : pathstr;
  127. numargs,wstat : integer;
  128. Wiring : TWiring;
  129. begin
  130. if pos ('.',path) = 0 then
  131. arg0 := fexpand(path+'.nlm'#0) else
  132. arg0 := fexpand (path)+#0;
  133. //writeln (stderr,'dos.exec (',path,',',comline,') arg0:"',copy(arg0,1,length(arg0)-1),'"');
  134. args[0] := @arg0[1];
  135. numargs := 0;
  136. c:=comline;
  137. i:=1;
  138. while i<=length(c) do
  139. begin
  140. if c[i]<>' ' then
  141. begin
  142. {Commandline argument found. append #0 and set pointer in args }
  143. inc(numargs);
  144. args[numargs]:=@c[i];
  145. while (i<=length(c)) and (c[i]<>' ') do
  146. inc(i);
  147. c[i] := #0;
  148. end;
  149. inc(i);
  150. end;
  151. args[numargs+1] := nil;
  152. // i := spawnvp (P_WAIT,args[0],@args);
  153. Wiring.infd := StdInputHandle; //textrec(Stdin).Handle;
  154. Wiring.outfd:= textrec(stdout).Handle;
  155. Wiring.errfd:= textrec(stderr).Handle;
  156. //writeln (stderr,'calling procve');
  157. i := procve(args[0],
  158. PROC_CURRENT_SPACE+PROC_INHERIT_CWD,
  159. envP, // const char * env[] If passed as NULL, the child process inherits the parent.s environment at the time of the call.
  160. @Wiring, // wiring_t *wiring, Pass NULL to inherit system defaults for wiring.
  161. nil, // struct fd_set *fds, Not currently implemented. Pass in NULL.
  162. nil, // void *appdata, Not currently implemented. Pass in NULL.
  163. 0, // size_t appdata_size, Not currently implemented. Pass in 0
  164. nil, // void *reserved, Reserved. Pass NULL.
  165. @args); // const char *argv[]
  166. //writeln (stderr,'Ok');
  167. if i <> -1 then
  168. begin
  169. Fpwaitpid(i,@wstat,0);
  170. doserror := 0;
  171. lastdosexitcode := wstat;
  172. end else
  173. begin
  174. doserror := 8; // for now, what about errno ?
  175. end;
  176. end;
  177. {******************************************************************************
  178. --- Disk ---
  179. ******************************************************************************}
  180. function getvolnum (drive : byte) : longint;
  181. {var dir : STRING[255];
  182. P,PS,
  183. V : LONGINT;}
  184. begin
  185. {if drive = 0 then
  186. begin // get volume name from current directory (i.e. SERVER-NAME/VOL2:TEST)
  187. getdir (0,dir);
  188. p := pos (':', dir);
  189. if p = 0 then
  190. begin
  191. getvolnum := -1;
  192. exit;
  193. end;
  194. byte (dir[0]) := p-1;
  195. dir[p] := #0;
  196. PS := pos ('/', dir);
  197. INC (PS);
  198. if _GetVolumeNumber (@dir[PS], V) <> 0 then
  199. getvolnum := -1
  200. else
  201. getvolnum := V;
  202. end else
  203. getvolnum := drive-1;}
  204. getvolnum := -1;
  205. end;
  206. function diskfree(drive : byte) : int64;
  207. {VAR Buf : ARRAY [0..255] OF CHAR;
  208. TotalBlocks : WORD;
  209. SectorsPerBlock : WORD;
  210. availableBlocks : WORD;
  211. totalDirectorySlots : WORD;
  212. availableDirSlots : WORD;
  213. volumeisRemovable : WORD;
  214. volumeNumber : LONGINT;}
  215. begin
  216. // volumeNumber := getvolnum (drive);
  217. (*
  218. if volumeNumber >= 0 then
  219. begin
  220. {i think thats not the right function but for others i need a connection handle}
  221. if _GetVolumeInfoWithNumber (byte(volumeNumber),@Buf,
  222. TotalBlocks,
  223. SectorsPerBlock,
  224. availableBlocks,
  225. totalDirectorySlots,
  226. availableDirSlots,
  227. volumeisRemovable) = 0 THEN
  228. begin
  229. diskfree := int64 (availableBlocks) * int64 (SectorsPerBlock) * 512;
  230. end else
  231. diskfree := 0;
  232. end else*)
  233. diskfree := 0;
  234. end;
  235. function disksize(drive : byte) : int64;
  236. {VAR Buf : ARRAY [0..255] OF CHAR;
  237. TotalBlocks : WORD;
  238. SectorsPerBlock : WORD;
  239. availableBlocks : WORD;
  240. totalDirectorySlots : WORD;
  241. availableDirSlots : WORD;
  242. volumeisRemovable : WORD;
  243. volumeNumber : LONGINT;}
  244. begin
  245. (*
  246. volumeNumber := getvolnum (drive);
  247. if volumeNumber >= 0 then
  248. begin
  249. {i think thats not the right function but for others i need a connection handle}
  250. if _GetVolumeInfoWithNumber (byte(volumeNumber),@Buf,
  251. TotalBlocks,
  252. SectorsPerBlock,
  253. availableBlocks,
  254. totalDirectorySlots,
  255. availableDirSlots,
  256. volumeisRemovable) = 0 THEN
  257. begin
  258. disksize := int64 (TotalBlocks) * int64 (SectorsPerBlock) * 512;
  259. end else
  260. disksize := 0;
  261. end else*)
  262. disksize := 0;
  263. end;
  264. {******************************************************************************
  265. --- Utils ---
  266. ******************************************************************************}
  267. procedure timet2dostime (timet:longint; var dostime : longint);
  268. var tm : Ttm;
  269. begin
  270. localtime_r(timet,tm);
  271. dostime:=(tm.tm_sec shr 1)+(tm.tm_min shl 5)+(tm.tm_hour shl 11)+(tm.tm_mday shl 16)+((tm.tm_mon+1) shl 21)+((tm.tm_year+1900-1980) shl 25);
  272. end;
  273. function nwattr2dosattr (nwattr : longint) : word;
  274. begin
  275. nwattr2dosattr := 0;
  276. if nwattr and M_A_RDONLY > 0 then nwattr2dosattr := nwattr2dosattr + readonly;
  277. if nwattr and M_A_HIDDEN > 0 then nwattr2dosattr := nwattr2dosattr + hidden;
  278. if nwattr and M_A_SYSTEM > 0 then nwattr2dosattr := nwattr2dosattr + sysfile;
  279. if nwattr and M_A_SUBDIR > 0 then nwattr2dosattr := nwattr2dosattr + directory;
  280. if nwattr and M_A_ARCH > 0 then nwattr2dosattr := nwattr2dosattr + archive;
  281. end;
  282. {******************************************************************************
  283. --- Findfirst FindNext ---
  284. ******************************************************************************}
  285. {returns true if attributes match}
  286. function find_setfields (var f : searchRec) : boolean;
  287. var
  288. StatBuf : TStat;
  289. fname : string[255];
  290. begin
  291. find_setfields := false;
  292. with F do
  293. begin
  294. if Magic = $AD01 then
  295. begin
  296. attr := nwattr2dosattr (Pdirent(EntryP)^.d_mode);
  297. size := Pdirent(EntryP)^.d_size;
  298. name := strpas (Pdirent(EntryP)^.d_name);
  299. doserror := 0;
  300. fname := f._dir + f.name;
  301. if length (fname) = 255 then dec (byte(fname[0]));
  302. fname := fname + #0;
  303. if Fpstat (@fname[1],StatBuf) = 0 then
  304. timet2dostime (StatBuf.st_mtim.tv_sec, time)
  305. else
  306. time := 0;
  307. if (f._attr and hidden) = 0 then
  308. if attr and hidden > 0 then exit;
  309. if (f._attr and Directory) = 0 then
  310. if attr and Directory > 0 then exit;
  311. if (f._attr and SysFile) = 0 then
  312. if attr and SysFile > 0 then exit;
  313. find_setfields := true;
  314. end else
  315. begin
  316. FillChar (f,sizeof(f),0);
  317. doserror := 18;
  318. end;
  319. end;
  320. end;
  321. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  322. var
  323. path0 : array[0..256] of char;
  324. p : longint;
  325. begin
  326. IF path = '' then
  327. begin
  328. doserror := 18;
  329. exit;
  330. end;
  331. f._attr := attr;
  332. p := length (path);
  333. while (p > 0) and (not (path[p] in AllowDirectorySeparators)) do
  334. dec (p);
  335. if p > 0 then
  336. begin
  337. f._mask := copy (path,p+1,255);
  338. f._dir := copy (path,1,p);
  339. strpcopy(path0,f._dir);
  340. end else
  341. begin
  342. f._mask := path;
  343. getdir (0,f._dir);
  344. if (f._dir[length(f._dir)] <> '/') and
  345. (f._dir[length(f._dir)] <> '\') then
  346. f._dir := f._dir + '/';
  347. strpcopy(path0,f._dir);
  348. end;
  349. if f._mask = '*' then f._mask := '';
  350. if f._mask = '*.*' then f._mask := '';
  351. //writeln (stderr,'mask: "',f._mask,'" dir:"',path0,'"');
  352. f._mask := f._mask + #0;
  353. Pdirent(f.DirP) := opendir (path0);
  354. if f.DirP = nil then
  355. doserror := 18
  356. else begin
  357. F.Magic := $AD01;
  358. findnext (f);
  359. end;
  360. end;
  361. procedure findnext(var f : searchRec);
  362. begin
  363. if F.Magic <> $AD01 then
  364. begin
  365. doserror := 18;
  366. exit;
  367. end;
  368. doserror:=0;
  369. repeat
  370. Pdirent(f.EntryP) := readdir (Pdirent(f.DirP));
  371. if F.EntryP = nil then
  372. doserror := 18
  373. else
  374. if find_setfields (f) then
  375. begin
  376. if f._mask = #0 then exit;
  377. if fnmatch(@f._mask[1],Pdirent(f.EntryP)^.d_name,FNM_CASEFOLD) = 0 then
  378. exit;
  379. end;
  380. until doserror <> 0;
  381. end;
  382. Procedure FindClose(Var f: SearchRec);
  383. begin
  384. if F.Magic <> $AD01 then
  385. begin
  386. doserror := 18;
  387. EXIT;
  388. end;
  389. doserror:=0;
  390. closedir (Pdirent(f.DirP));
  391. f.Magic := 0;
  392. f.DirP := NIL;
  393. f.EntryP := NIL;
  394. end;
  395. {******************************************************************************
  396. --- File ---
  397. ******************************************************************************}
  398. Function FSearch(path: pathstr; dirlist: string): pathstr;
  399. var
  400. i,p1 : longint;
  401. s : searchrec;
  402. newdir : pathstr;
  403. begin
  404. { check if the file specified exists }
  405. findfirst(path,anyfile,s);
  406. if doserror=0 then
  407. begin
  408. findclose(s);
  409. fsearch:=path;
  410. exit;
  411. end;
  412. { No wildcards allowed in these things }
  413. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  414. fsearch:=''
  415. else
  416. begin
  417. { allow backslash as slash }
  418. DoDirSeparators(dirlist);
  419. repeat
  420. p1:=pos(';',dirlist);
  421. if p1<>0 then
  422. begin
  423. newdir:=copy(dirlist,1,p1-1);
  424. delete(dirlist,1,p1);
  425. end
  426. else
  427. begin
  428. newdir:=dirlist;
  429. dirlist:='';
  430. end;
  431. if (newdir<>'') and (not (newdir[length(newdir)] in ['/',':'])) then
  432. newdir:=newdir+'/';
  433. findfirst(newdir+path,anyfile,s);
  434. if doserror=0 then
  435. newdir:=newdir+path
  436. else
  437. newdir:='';
  438. until (dirlist='') or (newdir<>'');
  439. fsearch:=newdir;
  440. end;
  441. findclose(s);
  442. end;
  443. {******************************************************************************
  444. --- Get/Set File Time,Attr ---
  445. ******************************************************************************}
  446. procedure getftime(var f;var time : longint);
  447. var
  448. StatBuf : TStat;
  449. begin
  450. doserror := 0;
  451. if Fpfstat (filerec (f).handle, StatBuf) = 0 then
  452. timet2dostime (StatBuf.st_mtim.tv_sec,time)
  453. else begin
  454. time := 0;
  455. doserror := ___errno^;
  456. end;
  457. end;
  458. procedure setftime(var f;time : longint);
  459. Var
  460. utim: utimbuf;
  461. DT: DateTime;
  462. path: pathstr;
  463. tm : TTm;
  464. Begin
  465. doserror:=0;
  466. with utim do
  467. begin
  468. actime:=libc.time(nil); // getepochtime;
  469. UnPackTime(Time,DT);
  470. with tm do
  471. begin
  472. tm_sec := DT.Sec; // seconds after the minute [0..59]
  473. tm_min := DT.Min; // minutes after the hour [0..59]
  474. tm_hour := DT.hour; // hours since midnight [0..23]
  475. tm_mday := DT.Day; // days of the month [1..31]
  476. tm_mon := DT.month-1; // months since January [0..11]
  477. tm_year := DT.year-1900;
  478. tm_wday := -1;
  479. tm_yday := -1;
  480. tm_isdst := -1;
  481. end;
  482. modtime:=mktime(tm);
  483. end;
  484. if utime(@filerec(f).name,utim)<0 then
  485. begin
  486. Time:=0;
  487. doserror:=3;
  488. end;
  489. end;
  490. procedure getfattr(var f;var attr : word);
  491. VAR StatBuf : TStat;
  492. begin
  493. doserror := 0;
  494. if Fpstat (@textrec(f).name, StatBuf) = 0 then
  495. attr := nwattr2dosattr (StatBuf.st_mode)
  496. else
  497. begin
  498. attr := 0;
  499. doserror := ___errno^;
  500. end;
  501. end;
  502. procedure setfattr(var f;attr : word);
  503. var
  504. StatBuf : TStat;
  505. newMode : longint;
  506. begin
  507. if Fpstat (@textrec(f).name,StatBuf) = 0 then
  508. begin
  509. newmode := StatBuf.st_mode and ($FFFF0000 - M_A_RDONLY-M_A_HIDDEN-M_A_SYSTEM-M_A_ARCH); {only this can be set by dos unit}
  510. newmode := newmode or M_A_BITS_SIGNIFICANT; {set netware attributes}
  511. if attr and readonly > 0 then
  512. newmode := newmode or M_A_RDONLY;
  513. if attr and hidden > 0 then
  514. newmode := newmode or M_A_HIDDEN;
  515. if attr and sysfile > 0 then
  516. newmode := newmode or M_A_SYSTEM;
  517. if attr and archive > 0 then
  518. newmode := newmode or M_A_ARCH;
  519. if Fpchmod (@textrec(f).name,newMode) < 0 then
  520. doserror := ___errno^ else
  521. doserror := 0;
  522. end else
  523. doserror := ___errno^;
  524. end;
  525. {******************************************************************************
  526. --- Environment ---
  527. ******************************************************************************}
  528. Function EnvCount: Longint;
  529. var
  530. envcnt : longint;
  531. p : ppchar;
  532. Begin
  533. envcnt:=0;
  534. p:=envp; {defined in system}
  535. while (p^<>nil) do
  536. begin
  537. inc(envcnt);
  538. inc(p);
  539. end;
  540. EnvCount := envcnt
  541. End;
  542. Function EnvStr (Index: longint): String;
  543. Var
  544. i : longint;
  545. p : ppchar;
  546. Begin
  547. if Index <= 0 then
  548. envstr:=''
  549. else
  550. begin
  551. p:=envp; {defined in system}
  552. i:=1;
  553. while (i<Index) and (p^<>nil) do
  554. begin
  555. inc(i);
  556. inc(p);
  557. end;
  558. if p=nil then
  559. envstr:=''
  560. else
  561. envstr:=strpas(p^)
  562. end;
  563. end;
  564. { works fine (at least with netware 6.5) }
  565. Function GetEnv(envvar: string): string;
  566. var envvar0 : array[0..512] of char;
  567. p : pchar;
  568. SearchElement : string[255];
  569. i,isDosPath,res : longint;
  570. begin
  571. if upcase(envvar) = 'PATH' then
  572. begin // netware does not have search paths in the environment var PATH
  573. // return it here (needed for the compiler)
  574. GetEnv := '';
  575. i := 1;
  576. res := GetSearchPathElement (i, isdosPath, @SearchElement[0]);
  577. while res = 0 do
  578. begin
  579. if isDosPath = 0 then
  580. begin
  581. if GetEnv <> '' then GetEnv := GetEnv + ';';
  582. GetEnv := GetEnv + SearchElement;
  583. end;
  584. inc (i);
  585. res := GetSearchPathElement (i, isdosPath, @SearchElement[0]);
  586. end;
  587. DoDirSeparators(getenv);
  588. end else
  589. begin
  590. strpcopy(envvar0,envvar);
  591. p := libc.getenv (envvar0);
  592. if p = NIL then
  593. GetEnv := ''
  594. else
  595. GetEnv := strpas (p);
  596. end;
  597. end;
  598. {******************************************************************************
  599. --- Not Supported ---
  600. ******************************************************************************}
  601. Procedure keep(exitcode : word);
  602. Begin
  603. { simply wait until nlm will be unloaded }
  604. while true do delay (60000);
  605. End;
  606. end.