dos.pp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  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. i,p1 : longint;
  302. s : searchrec;
  303. newdir : pathstr;
  304. begin
  305. write ('FSearch ("',path,'","',dirlist,'"');
  306. { check if the file specified exists }
  307. findfirst(path,anyfile,s);
  308. if doserror=0 then
  309. begin
  310. findclose(s);
  311. fsearch:=path;
  312. exit;
  313. end;
  314. { No wildcards allowed in these things }
  315. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  316. fsearch:=''
  317. else
  318. begin
  319. { allow backslash as slash }
  320. for i:=1 to length(dirlist) do
  321. if dirlist[i]='\' then dirlist[i]:='/';
  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 ['/',':'])) then
  335. newdir:=newdir+'/';
  336. findfirst(newdir+path,anyfile,s);
  337. if doserror=0 then
  338. newdir:=newdir+path
  339. else
  340. newdir:='';
  341. until (dirlist='') or (newdir<>'');
  342. fsearch:=newdir;
  343. end;
  344. findclose(s);
  345. end;
  346. {******************************************************************************
  347. --- Get/Set File Time,Attr ---
  348. ******************************************************************************}
  349. procedure getftime(var f;var time : longint);
  350. VAR StatBuf : NWStatBufT;
  351. T : DateTime;
  352. DosDate,
  353. DosTime : WORD;
  354. begin
  355. IF _fstat (FileRec (f).Handle, StatBuf) = 0 THEN
  356. BEGIN
  357. _ConvertTimeToDos (StatBuf.st_mtime, DosDate, DosTime);
  358. time := DosTime + (LONGINT (DosDate) SHL 16);
  359. END ELSE
  360. time := 0;
  361. end;
  362. procedure setftime(var f;time : longint);
  363. begin
  364. {is there a netware function to do that ?????}
  365. ConsolePrintf ('warning: fpc dos.setftime not implemented'#13#10);
  366. end;
  367. procedure getfattr(var f;var attr : word);
  368. VAR StatBuf : NWStatBufT;
  369. begin
  370. IF _fstat (FileRec (f).Handle, StatBuf) = 0 THEN
  371. BEGIN
  372. attr := word (StatBuf.st_attr);
  373. END ELSE
  374. attr := 0;
  375. end;
  376. procedure setfattr(var f;attr : word);
  377. begin
  378. {is there a netware function to do that ?????}
  379. ConsolePrintf ('warning: fpc dos.setfattr not implemented'#13#10);
  380. end;
  381. {******************************************************************************
  382. --- Environment ---
  383. ******************************************************************************}
  384. function envcount : longint;
  385. begin
  386. envcount := 0; {is there a netware function to do that ?????}
  387. ConsolePrintf ('warning: fpc dos.envcount not implemented'#13#10);
  388. end;
  389. function envstr (index: longint) : string;
  390. begin
  391. envstr := ''; {is there a netware function to do that ?????}
  392. ConsolePrintf ('warning: fpc dos.envstr not implemented'#13#10);
  393. end;
  394. { works fine (at least with netware 6.5) }
  395. Function GetEnv(envvar: string): string;
  396. var envvar0 : array[0..512] of char;
  397. p : pchar;
  398. i,isDosPath,res : longint;
  399. begin
  400. if upcase(envvar) = 'PATH' then
  401. begin // netware does not have search paths in the environment var PATH
  402. // return it here (needed for the compiler)
  403. GetEnv := '';
  404. i := 1;
  405. res := _NWGetSearchPathElement (i, isdosPath, @envvar0[0]);
  406. while res = 0 do
  407. begin
  408. if GetEnv <> '' then GetEnv := GetEnv + ';';
  409. GetEnv := GetEnv + strpas(envvar0);
  410. inc (i);
  411. res := _NWGetSearchPathElement (i, isdosPath, @envvar0[0]);
  412. end;
  413. for i := 1 to length(GetEnv) do
  414. if GetEnv[i] = '\' then
  415. GetEnv[i] := '/';
  416. end else
  417. begin
  418. strpcopy(envvar0,envvar);
  419. p := _getenv (envvar0);
  420. if p = NIL then
  421. GetEnv := ''
  422. else
  423. GetEnv := strpas (p);
  424. end;
  425. end;
  426. {******************************************************************************
  427. --- Not Supported ---
  428. ******************************************************************************}
  429. Procedure keep(exitcode : word);
  430. Begin
  431. { simply wait until nlm will be unloaded }
  432. while true do _delay (60000);
  433. End;
  434. end.