system.pp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2004 by the Free Pascal development team.
  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. System.pp for Netware libc environment
  11. **********************************************************************}
  12. { no stack check in system }
  13. {$S-}
  14. unit system;
  15. interface
  16. {$define netware}
  17. {$define netware_libc}
  18. {$define StdErrToConsole}
  19. {$define autoHeapRelease}
  20. {$define IOpossix}
  21. {$define DisableArrayOfConst}
  22. {$ifdef SYSTEMDEBUG}
  23. {$define SYSTEMEXCEPTIONDEBUG}
  24. {$endif SYSTEMDEBUG}
  25. {$ifdef cpui386}
  26. {$define Set_i386_Exception_handler}
  27. {$endif cpui386}
  28. { include system-independent routine headers }
  29. {$I systemh.inc}
  30. type THandle = DWord;
  31. {Platform specific information}
  32. const
  33. LineEnding = #13#10;
  34. LFNSupport : boolean = false;
  35. DirectorySeparator = '/';
  36. DriveSeparator = ':';
  37. PathSeparator = ';';
  38. { FileNameCaseSensitive is defined separately below!!! }
  39. maxExitCode = $ffff;
  40. { include heap support headers }
  41. {$I heaph.inc}
  42. CONST
  43. { Default filehandles }
  44. UnusedHandle : THandle = -1;
  45. StdInputHandle : THandle = 0;
  46. StdOutputHandle : THandle = 0;
  47. StdErrorHandle : THandle = 0;
  48. FileNameCaseSensitive : boolean = false;
  49. sLineBreak = LineEnding;
  50. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  51. TYPE
  52. TNWCheckFunction = procedure (var code : longint);
  53. VAR
  54. ArgC : INTEGER;
  55. ArgV : ppchar;
  56. NetwareCheckFunction : TNWCheckFunction;
  57. NetwareMainThreadGroupID: longint;
  58. NetwareCodeStartAddress : dword;
  59. CONST
  60. envp : ppchar = nil;
  61. {type
  62. TSysCloseAllRemainingSemaphores = procedure;
  63. TSysReleaseThreadVars = procedure;
  64. TSysSetThreadDataAreaPtr = function (newPtr:pointer):pointer;
  65. procedure NWSysSetThreadFunctions (crs:TSysCloseAllRemainingSemaphores;
  66. rtv:TSysReleaseThreadVars;
  67. stdata:TSysSetThreadDataAreaPtr);
  68. }
  69. procedure __ConsolePrintf (s :string);
  70. implementation
  71. { Indicate that stack checking is taken care by OS}
  72. {$DEFINE NO_GENERIC_STACK_CHECK}
  73. { include system independent routines }
  74. {$I system.inc}
  75. { some declarations for Netware API calls }
  76. { I nwlibc.inc}
  77. {$I errno.inc}
  78. {$define INCLUDED_FROM_SYSTEM}
  79. {$I libc.pp}
  80. var
  81. HeapAllocResourceTag,HeapListAllocResourceTag : rtag_t;
  82. NLMHandle : pointer;
  83. {$ifdef StdErrToConsole}
  84. NWLoggerScreen : Tscr;
  85. {$endif}
  86. {CloseAllRemainingSemaphores : TSysCloseAllRemainingSemaphores = nil;
  87. ReleaseThreadVars : TSysReleaseThreadVars = nil;
  88. SetThreadDataAreaPtr : TSysSetThreadDataAreaPtr = nil;
  89. procedure NWSysSetThreadFunctions (crs:TSysCloseAllRemainingSemaphores;
  90. rtv:TSysReleaseThreadVars;
  91. stdata:TSysSetThreadDataAreaPtr);
  92. begin
  93. CloseAllRemainingSemaphores := crs;
  94. ReleaseThreadVars := rtv;
  95. SetThreadDataAreaPtr := stdata;
  96. end;}
  97. procedure PASCALMAIN;external name 'PASCALMAIN';
  98. procedure fpc_do_exit;external name 'FPC_DO_EXIT';
  99. {*****************************************************************************
  100. System Dependent Exit code
  101. *****************************************************************************}
  102. {$ifdef autoHeapRelease}
  103. procedure FreeSbrkMem; forward;
  104. {$endif}
  105. var SigTermHandlerActive : boolean;
  106. Procedure system_exit;
  107. begin
  108. __ConsolePrintf ('system_exit');
  109. //if assigned (CloseAllRemainingSemaphores) then CloseAllRemainingSemaphores;
  110. //if assigned (ReleaseThreadVars) then ReleaseThreadVars;
  111. {$ifdef autoHeapRelease}
  112. FreeSbrkMem; { free memory allocated by heapmanager }
  113. {$endif}
  114. __ConsolePrintf ('Heap mem released');
  115. if not SigTermHandlerActive then
  116. begin
  117. //if ExitCode <> 0 Then { otherwise we dont see runtime-errors }
  118. // _SetAutoScreenDestructionMode (false);
  119. _exit (ExitCode);
  120. end;
  121. end;
  122. {*****************************************************************************
  123. Stack check code
  124. *****************************************************************************}
  125. const StackErr : boolean = false;
  126. procedure int_stackcheck(stack_size:Cardinal);[saveregisters,public,alias:'FPC_STACKCHECK'];
  127. {
  128. called when trying to get local stack if the compiler directive $S
  129. is set this function must preserve all registers
  130. With a 2048 byte safe area used to write to StdIo without crossing
  131. the stack boundary
  132. }
  133. begin
  134. if StackErr then exit; // avoid recursive calls
  135. if stackavail > stack_size + 2048 THEN EXIT;
  136. StackErr := true;
  137. HandleError (202);
  138. end;
  139. {*****************************************************************************
  140. ParamStr/Randomize
  141. *****************************************************************************}
  142. { number of args }
  143. function paramcount : longint;
  144. begin
  145. paramcount := argc - 1;
  146. end;
  147. { argument number l }
  148. function paramstr(l : longint) : string;
  149. begin
  150. if (l>=0) and (l+1<=argc) then
  151. begin
  152. paramstr:=strpas(argv[l]);
  153. if l = 0 then // fix nlm path
  154. begin
  155. for l := 1 to length (paramstr) do
  156. if paramstr[l] = '\' then paramstr[l] := '/';
  157. end;
  158. end else
  159. paramstr:='';
  160. end;
  161. { set randseed to a new pseudo random value }
  162. procedure randomize;
  163. begin
  164. randseed := time (NIL);
  165. end;
  166. {*****************************************************************************
  167. Heap Management
  168. *****************************************************************************}
  169. var
  170. int_heap : pointer;external name 'HEAP';
  171. int_heapsize : longint;external name 'HEAPSIZE';
  172. { first address of heap }
  173. function getheapstart:pointer;
  174. begin
  175. getheapstart := int_heap;
  176. end;
  177. { current length of heap }
  178. function getheapsize:longint;
  179. begin
  180. getheapsize := int_heapsize;
  181. end;
  182. {$ifdef autoHeapRelease}
  183. const HeapInitialMaxBlocks = 32;
  184. type THeapSbrkBlockList = array [1.. HeapInitialMaxBlocks] of pointer;
  185. var HeapSbrkBlockList : ^THeapSbrkBlockList = nil;
  186. HeapSbrkLastUsed : dword = 0;
  187. HeapSbrkAllocated : dword = 0;
  188. HeapSbrkReleased : boolean = false;
  189. { function to allocate size bytes more for the program }
  190. { must return the first address of new data space or nil if fail }
  191. { for netware all allocated blocks are saved to free them at }
  192. { exit (to avoid message "Module did not release xx resources") }
  193. Function SysOSAlloc(size : longint):pointer;
  194. var P2 : POINTER;
  195. i : longint;
  196. Slept : longint;
  197. begin
  198. if HeapSbrkReleased then
  199. begin
  200. __ConsolePrintf ('Error: SysOSFree called after all heap memory was released');
  201. exit(nil);
  202. end;
  203. SysOSAlloc := _Alloc (size,HeapAllocResourceTag);
  204. if SysOSAlloc <> nil then begin
  205. if HeapSbrkBlockList = nil then
  206. begin
  207. Pointer (HeapSbrkBlockList) := _Alloc (sizeof (HeapSbrkBlockList^),HeapListAllocResourceTag);
  208. if HeapSbrkBlockList = nil then
  209. begin
  210. _free (SysOSAlloc);
  211. SysOSAlloc := nil;
  212. exit;
  213. end;
  214. fillchar (HeapSbrkBlockList^,sizeof(HeapSbrkBlockList^),0);
  215. HeapSbrkAllocated := HeapInitialMaxBlocks;
  216. end;
  217. if (HeapSbrkLastUsed > 0) then
  218. for i := 1 to HeapSbrkLastUsed do
  219. if (HeapSbrkBlockList^[i] = nil) then
  220. begin // reuse free slot
  221. HeapSbrkBlockList^[i] := SysOSAlloc;
  222. exit;
  223. end;
  224. if (HeapSbrkLastUsed = HeapSbrkAllocated) then
  225. begin { grow }
  226. slept := 0;
  227. p2 := _ReallocSleepOK (HeapSbrkBlockList, (HeapSbrkAllocated + HeapInitialMaxBlocks) * sizeof(pointer),HeapListAllocResourceTag,Slept);
  228. if p2 = nil then // should we better terminate with error ?
  229. begin
  230. _free (SysOSAlloc);
  231. SysOSAlloc := nil;
  232. exit;
  233. end;
  234. HeapSbrkBlockList := p2;
  235. inc (HeapSbrkAllocated, HeapInitialMaxBlocks);
  236. end;
  237. inc (HeapSbrkLastUsed);
  238. HeapSbrkBlockList^[HeapSbrkLastUsed] := SysOSAlloc;
  239. end;
  240. end;
  241. procedure FreeSbrkMem;
  242. var i : longint;
  243. begin
  244. if HeapSbrkBlockList <> nil then
  245. begin
  246. for i := 1 to HeapSbrkLastUsed do
  247. if (HeapSbrkBlockList^[i] <> nil) then
  248. _free (HeapSbrkBlockList^[i]);
  249. _free (HeapSbrkBlockList);
  250. HeapSbrkAllocated := 0;
  251. HeapSbrkLastUsed := 0;
  252. HeapSbrkBlockList := nil;
  253. end;
  254. HeapSbrkReleased := true;
  255. {ReturnResourceTag(HeapAllocResourceTag,1);
  256. ReturnResourceTag(HeapListAllocResourceTag,1); not in netware.imp, seems to be not needed}
  257. end;
  258. {*****************************************************************************
  259. OS Memory allocation / deallocation
  260. ****************************************************************************}
  261. {$define HAS_SYSOSFREE}
  262. procedure SysOSFree(p: pointer; size: ptrint);
  263. var i : longint;
  264. begin
  265. if HeapSbrkReleased then
  266. begin
  267. __ConsolePrintf ('Error: SysOSFree called after all heap memory was released');
  268. end else
  269. if (HeapSbrkLastUsed > 0) then
  270. for i := 1 to HeapSbrkLastUsed do
  271. if (HeapSbrkBlockList^[i] = p) then
  272. begin
  273. _free (p);
  274. HeapSbrkBlockList^[i] := nil;
  275. exit;
  276. end;
  277. HandleError (204); // invalid pointer operation
  278. end;
  279. {$else autoHeapRelease}
  280. {$define HAS_SYSOSFREE}
  281. procedure SysOSFree(p: pointer; size: ptrint);
  282. begin
  283. _free (p);
  284. end;
  285. function SysOSAlloc(size: ptrint): pointer;
  286. begin
  287. writeln ('Alloc ',size,' bytes');
  288. SysOSAlloc := _Alloc(size,HeapAllocResourceTag);
  289. end;
  290. {$endif autoHeapRelease}
  291. { include standard heap management }
  292. {$I heap.inc}
  293. {****************************************************************************
  294. Low level File Routines
  295. All these functions can set InOutRes on errors
  296. ****************************************************************************}
  297. PROCEDURE NW2PASErr (Err : LONGINT);
  298. BEGIN
  299. if Err = 0 then { Else it will go through all the cases }
  300. exit;
  301. case Err of
  302. Sys_ENFILE,
  303. Sys_EMFILE : Inoutres:=4;
  304. Sys_ENOENT : Inoutres:=2;
  305. Sys_EBADF : Inoutres:=6;
  306. Sys_ENOMEM,
  307. Sys_EFAULT : Inoutres:=217;
  308. Sys_EINVAL : Inoutres:=218;
  309. Sys_EPIPE,
  310. Sys_EINTR,
  311. Sys_EIO,
  312. Sys_EAGAIN,
  313. Sys_ENOSPC : Inoutres:=101;
  314. Sys_ENAMETOOLONG,
  315. Sys_ELOOP,
  316. Sys_ENOTDIR : Inoutres:=3;
  317. Sys_EROFS,
  318. Sys_EEXIST,
  319. Sys_EACCES : Inoutres:=5;
  320. Sys_EBUSY : Inoutres:=162;
  321. end;
  322. END;
  323. {FUNCTION errno : LONGINT;
  324. BEGIN
  325. errno := ___errno^;
  326. END;}
  327. procedure Errno2Inoutres;
  328. begin
  329. NW2PASErr (___errno^);
  330. end;
  331. procedure SetFileError (VAR Err : LONGINT);
  332. begin
  333. if Err >= 0 then
  334. InOutRes := 0
  335. else begin
  336. // libc_perror ('SetFileError');
  337. Err := ___errno^;
  338. NW2PASErr (Err);
  339. Err := 0;
  340. end;
  341. end;
  342. { close a file from the handle value }
  343. procedure do_close(handle : thandle);
  344. VAR res : LONGINT;
  345. begin
  346. {$ifdef IOpossix}
  347. res := FpClose (handle);
  348. {$else}
  349. res := _fclose (_TFILE(handle));
  350. {$endif}
  351. IF res <> 0 THEN
  352. SetFileError (res)
  353. ELSE
  354. InOutRes := 0;
  355. end;
  356. procedure do_erase(p : pchar);
  357. VAR res : LONGINT;
  358. begin
  359. res := unlink (p);
  360. IF Res < 0 THEN
  361. SetFileError (res)
  362. ELSE
  363. InOutRes := 0;
  364. end;
  365. procedure do_rename(p1,p2 : pchar);
  366. VAR res : LONGINT;
  367. begin
  368. res := rename (p1,p2);
  369. IF Res < 0 THEN
  370. SetFileError (res)
  371. ELSE
  372. InOutRes := 0
  373. end;
  374. function do_write(h:thandle;addr:pointer;len : longint) : longint;
  375. var res : LONGINT;
  376. begin
  377. {$ifdef IOpossix}
  378. res := Fpwrite (h,addr,len);
  379. {$else}
  380. res := _fwrite (addr,1,len,_TFILE(h));
  381. {$endif}
  382. if res > 0 then
  383. InOutRes := 0
  384. else
  385. SetFileError (res);
  386. do_write := res;
  387. end;
  388. function do_read(h:thandle;addr:pointer;len : longint) : longint;
  389. VAR res : LONGINT;
  390. begin
  391. {$ifdef IOpossix}
  392. res := Fpread (h,addr,len);
  393. {$else}
  394. res := _fread (addr,1,len,_TFILE(h));
  395. {$endif}
  396. IF res > 0 THEN
  397. InOutRes := 0
  398. ELSE
  399. SetFileError (res);
  400. do_read := res;
  401. end;
  402. function do_filepos(handle : thandle) : longint;
  403. var res : LONGINT;
  404. begin
  405. InOutRes:=1;
  406. {$ifdef IOpossix}
  407. res := Fptell (handle);
  408. {$else}
  409. res := _ftell (_TFILE(handle));
  410. {$endif}
  411. if res < 0 THEN
  412. SetFileError (res)
  413. else
  414. InOutRes := 0;
  415. do_filepos := res;
  416. end;
  417. procedure do_seek(handle:thandle;pos : longint);
  418. VAR res : LONGINT;
  419. begin
  420. {$ifdef IOpossix}
  421. res := Fplseek (handle,pos, SEEK_SET);
  422. {$else}
  423. res := _fseek (_TFILE(handle),pos, SEEK_SET);
  424. {$endif}
  425. IF res >= 0 THEN
  426. InOutRes := 0
  427. ELSE
  428. SetFileError (res);
  429. end;
  430. function do_seekend(handle:thandle):longint;
  431. VAR res : LONGINT;
  432. begin
  433. {$ifdef IOpossix}
  434. res := Fplseek (handle,0, SEEK_END);
  435. {$else}
  436. res := _fseek (_TFILE(handle),0, SEEK_END);
  437. {$endif}
  438. IF res >= 0 THEN
  439. InOutRes := 0
  440. ELSE
  441. SetFileError (res);
  442. do_seekend := res;
  443. end;
  444. function do_filesize(handle : thandle) : longint;
  445. VAR res : LONGINT;
  446. statbuf : TStat;
  447. begin
  448. {$ifdef IOpossix}
  449. res := fstat (handle, statbuf);
  450. {$else}
  451. res := _fstat (_fileno (_TFILE(handle)), statbuf); // was _filelength for clib
  452. {$endif}
  453. if res <> 0 then
  454. begin
  455. SetFileError (Res);
  456. do_filesize := -1;
  457. end else
  458. begin
  459. InOutRes := 0;
  460. do_filesize := statbuf.st_size;
  461. end;
  462. end;
  463. { truncate at a given position }
  464. procedure do_truncate (handle:thandle;pos:longint);
  465. VAR res : LONGINT;
  466. begin
  467. {$ifdef IOpossix}
  468. res := ftruncate (handle,pos);
  469. {$else}
  470. res := _ftruncate (_fileno (_TFILE(handle)),pos);
  471. {$endif}
  472. IF res <> 0 THEN
  473. SetFileError (res)
  474. ELSE
  475. InOutRes := 0;
  476. end;
  477. {$ifdef IOpossix}
  478. // mostly stolen from syslinux
  479. procedure do_open(var f;p:pchar;flags:longint);
  480. {
  481. filerec and textrec have both handle and mode as the first items so
  482. they could use the same routine for opening/creating.
  483. when (flags and $10) the file will be append
  484. when (flags and $100) the file will be truncate/rewritten
  485. when (flags and $1000) there is no check for close (needed for textfiles)
  486. }
  487. var
  488. oflags : longint;
  489. Begin
  490. { close first if opened }
  491. if ((flags and $10000)=0) then
  492. begin
  493. case FileRec(f).mode of
  494. fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
  495. fmclosed : ;
  496. else
  497. begin
  498. inoutres:=102; {not assigned}
  499. exit;
  500. end;
  501. end;
  502. end;
  503. { reset file Handle }
  504. FileRec(f).Handle:=UnusedHandle;
  505. { We do the conversion of filemodes here, concentrated on 1 place }
  506. case (flags and 3) of
  507. 0 : begin
  508. oflags := O_RDONLY;
  509. filerec(f).mode := fminput;
  510. end;
  511. 1 : begin
  512. oflags := O_WRONLY;
  513. filerec(f).mode := fmoutput;
  514. end;
  515. 2 : begin
  516. oflags := O_RDWR;
  517. filerec(f).mode := fminout;
  518. end;
  519. end;
  520. if (flags and $1000)=$1000 then
  521. oflags:=oflags or (O_CREAT or O_TRUNC)
  522. else
  523. if (flags and $100)=$100 then
  524. oflags:=oflags or (O_APPEND);
  525. { empty name is special }
  526. if p[0]=#0 then
  527. begin
  528. case FileRec(f).mode of
  529. fminput :
  530. FileRec(f).Handle:=StdInputHandle;
  531. fminout, { this is set by rewrite }
  532. fmoutput :
  533. FileRec(f).Handle:=StdOutputHandle;
  534. fmappend :
  535. begin
  536. FileRec(f).Handle:=StdOutputHandle;
  537. FileRec(f).mode:=fmoutput; {fool fmappend}
  538. end;
  539. end;
  540. exit;
  541. end;
  542. { real open call }
  543. FileRec(f).Handle := open(p,oflags,438);
  544. if FileRec(f).Handle < 0 then
  545. if (___errno^=Sys_EROFS) and ((OFlags and O_RDWR)<>0) then
  546. begin // i.e. for cd-rom
  547. Oflags:=Oflags and not(O_RDWR);
  548. FileRec(f).Handle := open(p,oflags,438);
  549. end;
  550. if FileRec(f).Handle < 0 then
  551. Errno2Inoutres
  552. else
  553. InOutRes := 0;
  554. end;
  555. {$else}
  556. procedure do_open(var f;p:pchar;flags:longint);
  557. {
  558. filerec and textrec have both handle and mode as the first items so
  559. they could use the same routine for opening/creating.
  560. when (flags and $10) the file will be append
  561. when (flags and $100) the file will be truncate/rewritten
  562. when (flags and $1000) there is no check for close (needed for textfiles)
  563. }
  564. var
  565. oflags : string[10];
  566. Begin
  567. { close first if opened }
  568. if ((flags and $10000)=0) then
  569. begin
  570. case FileRec(f).mode of
  571. fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
  572. fmclosed : ;
  573. else
  574. begin
  575. inoutres:=102; {not assigned}
  576. exit;
  577. end;
  578. end;
  579. end;
  580. { reset file Handle }
  581. FileRec(f).Handle:=UnusedHandle;
  582. { We do the conversion of filemodes here, concentrated on 1 place }
  583. case (flags and 3) of
  584. 0 : begin
  585. oflags := 'rb'#0;
  586. filerec(f).mode := fminput;
  587. end;
  588. 1 : begin
  589. if (flags and $1000)=$1000 then
  590. oflags := 'w+b' else
  591. oflags := 'wb';
  592. filerec(f).mode := fmoutput;
  593. end;
  594. 2 : begin
  595. if (flags and $1000)=$1000 then
  596. oflags := 'w+' else
  597. oflags := 'r+';
  598. filerec(f).mode := fminout;
  599. end;
  600. end;
  601. {if (flags and $1000)=$1000 then
  602. oflags:=oflags or (O_CREAT or O_TRUNC)
  603. else
  604. if (flags and $100)=$100 then
  605. oflags:=oflags or (O_APPEND);}
  606. { empty name is special }
  607. if p[0]=#0 then
  608. begin
  609. case FileRec(f).mode of
  610. fminput :
  611. FileRec(f).Handle:=StdInputHandle;
  612. fminout, { this is set by rewrite }
  613. fmoutput :
  614. FileRec(f).Handle:=StdOutputHandle;
  615. fmappend :
  616. begin
  617. FileRec(f).Handle:=StdOutputHandle;
  618. FileRec(f).mode:=fmoutput; {fool fmappend}
  619. end;
  620. end;
  621. exit;
  622. end;
  623. { real open call }
  624. FileRec(f).Handle := THandle (_fopen (p,@oflags[1]));//_open(p,oflags,438);
  625. //WriteLn ('_open (',p,') returned ',ErrNo, 'Handle: ',FileRec(f).Handle);
  626. // errno does not seem to be set on succsess ??
  627. {IF FileRec(f).Handle < 0 THEN
  628. if (ErrNo=Sys_EROFS) and ((OFlags and O_RDWR)<>0) then
  629. begin // i.e. for cd-rom
  630. Oflags:=Oflags and not(O_RDWR);
  631. FileRec(f).Handle := _open(p,oflags,438);
  632. end;}
  633. if FileRec(f).Handle = 0 then
  634. Errno2Inoutres
  635. else
  636. InOutRes := 0;
  637. End;
  638. {$endif}
  639. function do_isdevice(handle:THandle):boolean;
  640. begin
  641. {$ifdef IOpossix}
  642. do_isdevice := (Fpisatty (handle) > 0);
  643. {$else}
  644. do_isdevice := (isatty (_fileno(_TFILE(handle))) > 0);
  645. {$endif}
  646. end;
  647. {*****************************************************************************
  648. UnTyped File Handling
  649. *****************************************************************************}
  650. {$i file.inc}
  651. {*****************************************************************************
  652. Typed File Handling
  653. *****************************************************************************}
  654. {$i typefile.inc}
  655. {*****************************************************************************
  656. Text File Handling
  657. *****************************************************************************}
  658. { should we consider #26 as the end of a file ? }
  659. {?? $DEFINE EOF_CTRLZ}
  660. {$i text.inc}
  661. {*****************************************************************************
  662. Directory Handling
  663. *****************************************************************************}
  664. procedure mkdir(const s : string);[IOCheck];
  665. var S2 : STRING;
  666. Res: LONGINT;
  667. BEGIN
  668. S2 := S;
  669. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  670. S2 := S2 + #0;
  671. Res := FpMkdir (@S2[1],S_IRWXU);
  672. if Res = 0 then
  673. InOutRes:=0
  674. else
  675. SetFileError (Res);
  676. end;
  677. procedure rmdir(const s : string);[IOCheck];
  678. VAR S2 : STRING;
  679. Res: LONGINT;
  680. BEGIN
  681. S2 := S;
  682. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  683. S2 := S2 + #0;
  684. Res := FpRmdir (@S2[1]);
  685. IF Res = 0 THEN
  686. InOutRes:=0
  687. ELSE
  688. SetFileError (Res);
  689. end;
  690. procedure chdir(const s : string);[IOCheck];
  691. VAR S2 : STRING;
  692. Res: LONGINT;
  693. begin
  694. S2 := S;
  695. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  696. S2 := S2 + #0;
  697. Res := FpChdir (@S2[1]);
  698. IF Res = 0 THEN
  699. InOutRes:=0
  700. ELSE
  701. SetFileError (Res);
  702. end;
  703. procedure getdir(drivenr : byte;var dir : shortstring);
  704. VAR P : ARRAY [0..255] OF CHAR;
  705. i : LONGINT;
  706. begin
  707. P[0] := #0;
  708. //getcwd (@P, SIZEOF (P));
  709. getcwdpath(@P,nil,0);
  710. i := libc_strlen (P);
  711. if i > 0 then
  712. begin
  713. Move (P, dir[1], i);
  714. BYTE(dir[0]) := i;
  715. For i := 1 to length (dir) do
  716. if dir[i] = '\' then dir [i] := '/';
  717. // fix / after volume, the compiler needs that
  718. // normaly root of a volumes is SERVERNAME/SYS:, change that
  719. // to SERVERNAME/SYS:/
  720. i := pos (':',dir);
  721. if (i > 0) then
  722. if i = Length (dir) then dir := dir + '/' else
  723. if dir [i+1] <> '/' then insert ('/',dir,i+1);
  724. END ELSE
  725. InOutRes := 1;
  726. end;
  727. {*****************************************************************************
  728. Thread Handling
  729. *****************************************************************************}
  730. procedure InitFPU;assembler;
  731. asm
  732. fninit
  733. fldcw fpucw
  734. end;
  735. { if return-value is <> 0, netware shows the message
  736. Unload Anyway ?
  737. To Disable unload at all, SetNLMDontUnloadFlag can be used on
  738. Netware >= 4.0 }
  739. function CheckFunction : longint; CDECL; [public,alias: '_NonAppCheckUnload'];
  740. begin
  741. __ConsolePrintf ('CheckFunction');
  742. if assigned (NetwareCheckFunction) then
  743. begin
  744. { this function is called without clib context, to allow clib
  745. calls, we set the thread group id before calling the
  746. user-function }
  747. //oldTG := _SetThreadGroupID (NetwareMainThreadGroupID);
  748. { to allow use of threadvars, we simply set the threadvar-memory
  749. from the main thread }
  750. //if assigned (SetThreadDataAreaPtr) then
  751. // oldPtr := SetThreadDataAreaPtr (NIL); { nil means main threadvars }
  752. result := 0;
  753. NetwareCheckFunction (result);
  754. // if assigned (SetThreadDataAreaPtr) then
  755. // SetThreadDataAreaPtr (oldPtr);
  756. // _SetThreadGroupID (oldTG);
  757. end else
  758. result := 0;
  759. end;
  760. procedure __ConsolePrintf (s : string);
  761. begin
  762. if length(s) > 252 then
  763. byte(s[0]) := 252;
  764. s := s + #13#10#0;
  765. screenprintf (NWLoggerScreen,@s[1]);
  766. end;
  767. {$ifdef StdErrToConsole}
  768. var ConsoleBuff : array [0..512] of char;
  769. Function ConsoleWrite(Var F: TextRec): Integer;
  770. var
  771. i : longint;
  772. Begin
  773. if F.BufPos>0 then
  774. begin
  775. if F.BufPos>sizeof(ConsoleBuff)-1 then
  776. i:=sizeof(ConsoleBuff)-1
  777. else
  778. i:=F.BufPos;
  779. Move(F.BufPtr^,ConsoleBuff,i);
  780. ConsoleBuff[i] := #0;
  781. screenprintf (NWLoggerScreen,@ConsoleBuff);
  782. end;
  783. F.BufPos:=0;
  784. ConsoleWrite := 0;
  785. End;
  786. Function ConsoleClose(Var F: TextRec): Integer;
  787. begin
  788. ConsoleClose:=0;
  789. end;
  790. Function ConsoleOpen(Var F: TextRec): Integer;
  791. Begin
  792. TextRec(F).InOutFunc:=@ConsoleWrite;
  793. TextRec(F).FlushFunc:=@ConsoleWrite;
  794. TextRec(F).CloseFunc:=@ConsoleClose;
  795. ConsoleOpen:=0;
  796. End;
  797. procedure AssignStdErrConsole(Var T: Text);
  798. begin
  799. Assign(T,'');
  800. TextRec(T).OpenFunc:=@ConsoleOpen;
  801. Rewrite(T);
  802. end;
  803. {$endif}
  804. { this will be called if the nlm is unloaded. It will NOT be
  805. called if the program exits i.e. with halt.
  806. Halt (or _exit) can not be called from this callback procedure }
  807. procedure TermSigHandler (Sig:longint); CDecl;
  808. begin
  809. SigTermHandlerActive := true; { to avoid that system_exit calls _exit }
  810. do_exit; { calls finalize units }
  811. end;
  812. procedure SysInitStdIO;
  813. begin
  814. { Setup stdin, stdout and stderr }
  815. {$ifdef IOpossix}
  816. StdInputHandle := THandle (fileno (___stdin^)); // GetStd** returns **FILE !
  817. StdOutputHandle:= THandle (fileno (___stdout^));
  818. StdErrorHandle := THandle (fileno (___stderr^));
  819. {$else}
  820. StdInputHandle := THandle (___stdin^); // GetStd** returns **FILE !
  821. StdOutputHandle:= THandle (___stdout^);
  822. StdErrorHandle := THandle (___stderr^);
  823. {$endif}
  824. OpenStdIO(Input,fmInput,StdInputHandle);
  825. OpenStdIO(Output,fmOutput,StdOutputHandle);
  826. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  827. {$ifdef StdErrToConsole}
  828. AssignStdErrConsole(StdErr);
  829. {$else}
  830. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  831. {$endif}
  832. end;
  833. procedure nlm_main (_ArgC : LONGINT; _ArgV : ppchar); cdecl; [public,alias: 'main'];
  834. BEGIN
  835. ArgC := _ArgC;
  836. ArgV := _ArgV;
  837. PASCALMAIN;
  838. END;
  839. {*****************************************************************************
  840. SystemUnit Initialization
  841. *****************************************************************************}
  842. Begin
  843. StackBottom := SPtr - StackLength;
  844. SigTermHandlerActive := false;
  845. NetwareCheckFunction := nil;
  846. {$ifdef StdErrToConsole}
  847. NWLoggerScreen := getnetwarelogger;
  848. {$endif}
  849. CheckFunction; // avoid check function to be removed by the linker
  850. envp := ____environ^; // nxGetEnviron;
  851. NLMHandle := getnlmhandle;
  852. HeapAllocResourceTag :=
  853. AllocateResourceTag(NLMHandle,'Heap Memory',AllocSignature);
  854. HeapListAllocResourceTag :=
  855. AllocateResourceTag(NLMHandle,'Heap Memory List',AllocSignature);
  856. Signal (SIGTERM, @TermSigHandler);
  857. { Setup heap }
  858. InitHeap;
  859. SysInitExceptions;
  860. { Reset IO Error }
  861. InOutRes:=0;
  862. (* This should be changed to a real value during *)
  863. (* thread driver initialization if appropriate. *)
  864. ThreadID := 1;
  865. SysInitStdIO;
  866. {Delphi Compatible}
  867. IsLibrary := FALSE;
  868. IsConsole := TRUE;
  869. ExitCode := 0;
  870. {$ifdef HASVARIANT}
  871. initvariantmanager;
  872. {$endif HASVARIANT}
  873. End.
  874. {
  875. $Log$
  876. Revision 1.2 2004-09-12 20:51:22 armin
  877. * added keyboard and video
  878. * a lot of fixes
  879. Revision 1.1 2004/09/05 20:58:47 armin
  880. * first rtl version for netwlibc
  881. }