2
0

dos.pp 13 KB

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