dos.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team.
  4. Dos unit for BP7 compatible RTL (novell netware)
  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. Type
  14. searchrec = packed record
  15. DirP : POINTER; { used for opendir }
  16. EntryP: POINTER; { and readdir }
  17. Magic : WORD;
  18. fill : array[1..11] of byte;
  19. attr : byte;
  20. time : longint;
  21. { reserved : word; not in DJGPP V2 }
  22. size : longint;
  23. name : string[255]; { NW uses only [12] but more can't hurt }
  24. end;
  25. {$i dosh.inc}
  26. implementation
  27. uses
  28. strings, nwserv;
  29. {$DEFINE HAS_GETMSCOUNT}
  30. {$DEFINE HAS_GETCBREAK}
  31. {$DEFINE HAS_SETCBREAK}
  32. {$DEFINE HAS_KEEP}
  33. {$define FPC_FEXPAND_DRIVES}
  34. {$define FPC_FEXPAND_VOLUMES}
  35. {$define FPC_FEXPAND_NO_DEFAULT_PATHS}
  36. {$I dos.inc}
  37. {$ASMMODE ATT}
  38. {$I nwsys.inc }
  39. {*****************************************************************************
  40. --- Info / Date / Time ---
  41. ******************************************************************************}
  42. {$PACKRECORDS 4}
  43. function dosversion : word;
  44. VAR F : FILE_SERV_INFO;
  45. begin
  46. IF GetServerInformation(SIZEOF(F),@F) = 0 THEN
  47. dosversion := WORD (F.netwareVersion) SHL 8 + F.netwareSubVersion;
  48. end;
  49. procedure getdate(var year,month,mday,wday : word);
  50. VAR N : NWdateAndTime;
  51. begin
  52. GetFileServerDateAndTime (N);
  53. wday:=N.DayOfWeek;
  54. year:=1900 + N.Year;
  55. month:=N.Month;
  56. mday:=N.Day;
  57. end;
  58. procedure setdate(year,month,day : word);
  59. VAR N : NWdateAndTime;
  60. begin
  61. GetFileServerDateAndTime (N);
  62. SetFileServerDateAndTime(year,month,day,N.Hour,N.Minute,N.Second);
  63. end;
  64. procedure gettime(var hour,minute,second,sec100 : word);
  65. VAR N : NWdateAndTime;
  66. begin
  67. GetFileServerDateAndTime (N);
  68. hour := N.Hour;
  69. Minute:= N.Minute;
  70. Second := N.Second;
  71. sec100 := 0;
  72. end;
  73. procedure settime(hour,minute,second,sec100 : word);
  74. VAR N : NWdateAndTime;
  75. begin
  76. GetFileServerDateAndTime (N);
  77. SetFileServerDateAndTime(N.year,N.month,N.day,hour,minute,second);
  78. end;
  79. function GetMsCount: int64;
  80. begin
  81. GetMsCount := int64 (Nwserv.GetCurrentTicks) * 55;
  82. end;
  83. {******************************************************************************
  84. --- Exec ---
  85. ******************************************************************************}
  86. const maxargs=256;
  87. procedure exec(const path : pathstr;const comline : comstr);
  88. var c : comstr;
  89. i : integer;
  90. args : array[0..maxargs] of pchar;
  91. arg0 : pathstr;
  92. numargs : integer;
  93. begin
  94. //writeln ('dos.exec (',path,',',comline,')');
  95. arg0 := fexpand (path)+#0;
  96. args[0] := @arg0[1];
  97. numargs := 0;
  98. c:=comline;
  99. i:=1;
  100. while i<=length(c) do
  101. begin
  102. if c[i]<>' ' then
  103. begin
  104. {Commandline argument found. append #0 and set pointer in args }
  105. inc(numargs);
  106. args[numargs]:=@c[i];
  107. while (i<=length(c)) and (c[i]<>' ') do
  108. inc(i);
  109. c[i] := #0;
  110. end;
  111. inc(i);
  112. end;
  113. args[numargs+1] := nil;
  114. i := spawnvp (P_WAIT,args[0],@args);
  115. if i >= 0 then
  116. begin
  117. doserror := 0;
  118. lastdosexitcode := i;
  119. end else
  120. begin
  121. doserror := 8; // for now, what about errno ?
  122. end;
  123. end;
  124. procedure getcbreak(var breakvalue : boolean);
  125. begin
  126. breakvalue := _SetCtrlCharCheckMode (false); { get current setting }
  127. if breakvalue then
  128. _SetCtrlCharCheckMode (breakvalue); { and restore old setting }
  129. end;
  130. procedure setcbreak(breakvalue : boolean);
  131. begin
  132. _SetCtrlCharCheckMode (breakvalue);
  133. end;
  134. {******************************************************************************
  135. --- Disk ---
  136. ******************************************************************************}
  137. function getvolnum (drive : byte) : longint;
  138. var dir : STRING[255];
  139. P,PS,
  140. V : LONGINT;
  141. begin
  142. if drive = 0 then
  143. begin // get volume name from current directory (i.e. SERVER-NAME/VOL2:TEST)
  144. getdir (0,dir);
  145. p := pos (':', dir);
  146. if p = 0 then
  147. begin
  148. getvolnum := -1;
  149. exit;
  150. end;
  151. byte (dir[0]) := p-1;
  152. dir[p] := #0;
  153. PS := pos ('/', dir);
  154. INC (PS);
  155. if _GetVolumeNumber (@dir[PS], V) <> 0 then
  156. getvolnum := -1
  157. else
  158. getvolnum := V;
  159. end else
  160. getvolnum := drive-1;
  161. end;
  162. function diskfree(drive : byte) : int64;
  163. VAR Buf : ARRAY [0..255] OF CHAR;
  164. TotalBlocks : WORD;
  165. SectorsPerBlock : WORD;
  166. availableBlocks : WORD;
  167. totalDirectorySlots : WORD;
  168. availableDirSlots : WORD;
  169. volumeisRemovable : WORD;
  170. volumeNumber : LONGINT;
  171. begin
  172. volumeNumber := getvolnum (drive);
  173. if volumeNumber >= 0 then
  174. begin
  175. {i think thats not the right function but for others i need a connection handle}
  176. if _GetVolumeInfoWithNumber (byte(volumeNumber),@Buf,
  177. TotalBlocks,
  178. SectorsPerBlock,
  179. availableBlocks,
  180. totalDirectorySlots,
  181. availableDirSlots,
  182. volumeisRemovable) = 0 THEN
  183. begin
  184. diskfree := int64 (availableBlocks) * int64 (SectorsPerBlock) * 512;
  185. end else
  186. diskfree := 0;
  187. end else
  188. diskfree := 0;
  189. end;
  190. function disksize(drive : byte) : int64;
  191. VAR Buf : ARRAY [0..255] OF CHAR;
  192. TotalBlocks : WORD;
  193. SectorsPerBlock : WORD;
  194. availableBlocks : WORD;
  195. totalDirectorySlots : WORD;
  196. availableDirSlots : WORD;
  197. volumeisRemovable : WORD;
  198. volumeNumber : LONGINT;
  199. begin
  200. volumeNumber := getvolnum (drive);
  201. if volumeNumber >= 0 then
  202. begin
  203. {i think thats not the right function but for others i need a connection handle}
  204. if _GetVolumeInfoWithNumber (byte(volumeNumber),@Buf,
  205. TotalBlocks,
  206. SectorsPerBlock,
  207. availableBlocks,
  208. totalDirectorySlots,
  209. availableDirSlots,
  210. volumeisRemovable) = 0 THEN
  211. begin
  212. disksize := int64 (TotalBlocks) * int64 (SectorsPerBlock) * 512;
  213. end else
  214. disksize := 0;
  215. end else
  216. disksize := 0;
  217. end;
  218. {******************************************************************************
  219. --- Findfirst FindNext ---
  220. ******************************************************************************}
  221. PROCEDURE find_setfields (VAR f : searchRec);
  222. BEGIN
  223. WITH F DO
  224. BEGIN
  225. IF Magic = $AD01 THEN
  226. BEGIN
  227. attr := WORD (PNWDirEnt(EntryP)^.d_attr); // lowest 16 bit -> same as dos
  228. time := PNWDirEnt(EntryP)^.d_time + (LONGINT (PNWDirEnt(EntryP)^.d_date) SHL 16);
  229. size := PNWDirEnt(EntryP)^.d_size;
  230. name := strpas (PNWDirEnt(EntryP)^.d_name);
  231. if name = '' then
  232. name := strpas (PNWDirEnt(EntryP)^.d_nameDOS);
  233. doserror := 0;
  234. END ELSE
  235. BEGIN
  236. FillChar (f,SIZEOF(f),0);
  237. doserror := 18;
  238. END;
  239. END;
  240. END;
  241. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  242. var
  243. path0 : array[0..256] of char;
  244. begin
  245. IF path = '' then
  246. begin
  247. doserror := 18;
  248. exit;
  249. end;
  250. strpcopy(path0,path);
  251. PNWDirEnt(f.DirP) := _opendir (path0);
  252. IF f.DirP = NIL THEN
  253. doserror := 18
  254. ELSE
  255. BEGIN
  256. IF attr <> anyfile THEN
  257. _SetReaddirAttribute (PNWDirEnt(f.DirP), attr);
  258. F.Magic := $AD01;
  259. PNWDirEnt(f.EntryP) := _readdir (PNWDirEnt(f.DirP));
  260. IF F.EntryP = NIL THEN
  261. BEGIN
  262. _closedir (PNWDirEnt(f.DirP));
  263. f.Magic := 0;
  264. doserror := 18;
  265. END ELSE
  266. find_setfields (f);
  267. END;
  268. end;
  269. procedure findnext(var f : searchRec);
  270. begin
  271. IF F.Magic <> $AD01 THEN
  272. BEGIN
  273. doserror := 18;
  274. EXIT;
  275. END;
  276. doserror:=0;
  277. PNWDirEnt(f.EntryP) := _readdir (PNWDirEnt(f.DirP));
  278. IF F.EntryP = NIL THEN
  279. doserror := 18
  280. ELSE
  281. find_setfields (f);
  282. end;
  283. Procedure FindClose(Var f: SearchRec);
  284. begin
  285. IF F.Magic <> $AD01 THEN
  286. BEGIN
  287. doserror := 18;
  288. EXIT;
  289. END;
  290. doserror:=0;
  291. _closedir (PNWDirEnt(f.DirP));
  292. f.Magic := 0;
  293. f.DirP := NIL;
  294. f.EntryP := NIL;
  295. end;
  296. {******************************************************************************
  297. --- File ---
  298. ******************************************************************************}
  299. Function FSearch(path: pathstr; dirlist: string): pathstr;
  300. var
  301. p1 : longint;
  302. s : searchrec;
  303. newdir : pathstr;
  304. begin
  305. { No wildcards allowed in these things }
  306. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  307. begin
  308. fsearch:='';
  309. exit;
  310. end;
  311. { check if the file specified exists }
  312. findfirst(path,anyfile and not(directory),s);
  313. if doserror=0 then
  314. begin
  315. findclose(s);
  316. fsearch:=path;
  317. exit;
  318. end;
  319. findclose(s);
  320. { allow backslash as slash }
  321. DoDirSeparators(dirlist);
  322. repeat
  323. p1:=pos(';',dirlist);
  324. if p1<>0 then
  325. begin
  326. newdir:=copy(dirlist,1,p1-1);
  327. delete(dirlist,1,p1);
  328. end
  329. else
  330. begin
  331. newdir:=dirlist;
  332. dirlist:='';
  333. end;
  334. if (newdir<>'') and (not (newdir[length(newdir)] in [DirectorySeparator,DriveSeparator])) then
  335. newdir:=newdir+DirectorySeparator;
  336. findfirst(newdir+path,anyfile and not(directory),s);
  337. if doserror=0 then
  338. newdir:=newdir+path
  339. else
  340. newdir:='';
  341. findclose(s);
  342. until (dirlist='') or (newdir<>'');
  343. fsearch:=newdir;
  344. end;
  345. {******************************************************************************
  346. --- Get/Set File Time,Attr ---
  347. ******************************************************************************}
  348. procedure getftime(var f;var time : longint);
  349. VAR StatBuf : NWStatBufT;
  350. T : DateTime;
  351. DosDate,
  352. DosTime : WORD;
  353. begin
  354. IF _fstat (FileRec (f).Handle, StatBuf) = 0 THEN
  355. BEGIN
  356. _ConvertTimeToDos (StatBuf.st_mtime, DosDate, DosTime);
  357. time := DosTime + (LONGINT (DosDate) SHL 16);
  358. END ELSE
  359. time := 0;
  360. end;
  361. procedure setftime(var f;time : longint);
  362. begin
  363. {is there a netware function to do that ?????}
  364. ConsolePrintf ('warning: fpc dos.setftime not implemented'#13#10);
  365. end;
  366. procedure getfattr(var f;var attr : word);
  367. VAR StatBuf : NWStatBufT;
  368. begin
  369. IF _fstat (FileRec (f).Handle, StatBuf) = 0 THEN
  370. BEGIN
  371. attr := word (StatBuf.st_attr);
  372. END ELSE
  373. attr := 0;
  374. end;
  375. procedure setfattr(var f;attr : word);
  376. begin
  377. {is there a netware function to do that ?????}
  378. ConsolePrintf ('warning: fpc dos.setfattr not implemented'#13#10);
  379. end;
  380. {******************************************************************************
  381. --- Environment ---
  382. ******************************************************************************}
  383. function envcount : longint;
  384. begin
  385. envcount := 0; {is there a netware function to do that ?????}
  386. ConsolePrintf ('warning: fpc dos.envcount not implemented'#13#10);
  387. end;
  388. function envstr (index: longint) : string;
  389. begin
  390. envstr := ''; {is there a netware function to do that ?????}
  391. ConsolePrintf ('warning: fpc dos.envstr not implemented'#13#10);
  392. end;
  393. { works fine (at least with netware 6.5) }
  394. Function GetEnv(envvar: string): string;
  395. var envvar0 : array[0..512] of char;
  396. p : pchar;
  397. i,isDosPath,res : longint;
  398. begin
  399. if upcase(envvar) = 'PATH' then
  400. begin // netware does not have search paths in the environment var PATH
  401. // return it here (needed for the compiler)
  402. GetEnv := '';
  403. i := 1;
  404. res := _NWGetSearchPathElement (i, isdosPath, @envvar0[0]);
  405. while res = 0 do
  406. begin
  407. if GetEnv <> '' then GetEnv := GetEnv + ';';
  408. GetEnv := GetEnv + strpas(envvar0);
  409. inc (i);
  410. res := _NWGetSearchPathElement (i, isdosPath, @envvar0[0]);
  411. end;
  412. DoDirSeparators(getenv);
  413. end else
  414. begin
  415. strpcopy(envvar0,envvar);
  416. p := _getenv (envvar0);
  417. if p = NIL then
  418. GetEnv := ''
  419. else
  420. GetEnv := strpas (p);
  421. end;
  422. end;
  423. {******************************************************************************
  424. --- Not Supported ---
  425. ******************************************************************************}
  426. Procedure keep(exitcode : word);
  427. Begin
  428. { simply wait until nlm will be unloaded }
  429. while true do _delay (60000);
  430. End;
  431. end.