system.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 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. **********************************************************************}
  11. { no stack check in system }
  12. {$S-}
  13. unit system;
  14. interface
  15. {$define StdErrToConsole}
  16. {$ifdef SYSTEMDEBUG}
  17. {$define SYSTEMEXCEPTIONDEBUG}
  18. {$endif SYSTEMDEBUG}
  19. {$ifdef i386}
  20. {$define Set_i386_Exception_handler}
  21. {$endif i386}
  22. { include system-independent routine headers }
  23. {$I systemh.inc}
  24. {Platform specific information}
  25. const
  26. LineEnding = #13#10;
  27. LFNSupport = false; { ??? - that's how it was declared in dos.pp! }
  28. DirectorySeparator = '\';
  29. DriveSeparator = ':';
  30. PathSeparator = ';';
  31. { FileNameCaseSensitive is defined separately below!!! }
  32. type
  33. { the fields of this record are os dependent }
  34. { and they shouldn't be used in a program }
  35. { only the type TCriticalSection is important }
  36. TRTLCriticalSection = packed record
  37. SemaHandle : LONGINT;
  38. SemaIsOpen : BOOLEAN;
  39. end;
  40. { include threading stuff }
  41. { i threadh.inc}
  42. { include heap support headers }
  43. {$I heaph.inc}
  44. CONST
  45. { Default filehandles }
  46. UnusedHandle : longint = -1;
  47. StdInputHandle : longint = 0;
  48. StdOutputHandle : longint = 0;
  49. StdErrorHandle : longint = 0;
  50. FileNameCaseSensitive : boolean = false;
  51. sLineBreak = LineEnding;
  52. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  53. TYPE
  54. TNWCheckFunction = procedure (var code : longint);
  55. VAR
  56. ArgC : INTEGER;
  57. ArgV : ppchar;
  58. NetwareCheckFunction : TNWCheckFunction;
  59. NetwareMainThreadGroupID: longint;
  60. CONST
  61. envp : ppchar = nil; {dummy to make heaptrc happy}
  62. PROCEDURE ConsolePrintf (FormatStr : PCHAR; Param : LONGINT); CDecl;
  63. PROCEDURE ConsolePrintf3 (FormatStr : PCHAR; P1,P2,P3 : LONGINT); CDecl;
  64. PROCEDURE ConsolePrintf (FormatStr : PCHAR); CDecl;
  65. type
  66. TSysCloseAllRemainingSemaphores = procedure;
  67. TSysReleaseThreadVars = procedure;
  68. TSysSetThreadDataAreaPtr = function (newPtr:pointer):pointer;
  69. procedure NWSysSetThreadFunctions (crs:TSysCloseAllRemainingSemaphores;
  70. rtv:TSysReleaseThreadVars;
  71. stdata:TSysSetThreadDataAreaPtr);
  72. implementation
  73. { Indicate that stack checking is taken care by OS}
  74. {$DEFINE NO_GENERIC_STACK_CHECK}
  75. { include system independent routines }
  76. {$I system.inc}
  77. { some declarations for Netware API calls }
  78. {$I nwsys.inc}
  79. {$I errno.inc}
  80. {procedure setup_arguments;
  81. begin
  82. end;
  83. }
  84. {procedure setup_environment;
  85. begin
  86. end;
  87. }
  88. var
  89. CloseAllRemainingSemaphores : TSysCloseAllRemainingSemaphores = nil;
  90. ReleaseThreadVars : TSysReleaseThreadVars = nil;
  91. SetThreadDataAreaPtr : TSysSetThreadDataAreaPtr = nil;
  92. procedure NWSysSetThreadFunctions (crs:TSysCloseAllRemainingSemaphores;
  93. rtv:TSysReleaseThreadVars;
  94. stdata:TSysSetThreadDataAreaPtr);
  95. begin
  96. CloseAllRemainingSemaphores := crs;
  97. ReleaseThreadVars := rtv;
  98. SetThreadDataAreaPtr := stdata;
  99. end;
  100. procedure PASCALMAIN;external name 'PASCALMAIN';
  101. procedure fpc_do_exit;external name 'FPC_DO_EXIT';
  102. {*****************************************************************************
  103. Startup
  104. *****************************************************************************}
  105. PROCEDURE nlm_main (_ArgC : LONGINT; _ArgV : ppchar); CDECL; [public,alias: '_nlm_main'];
  106. BEGIN
  107. ArgC := _ArgC;
  108. ArgV := _ArgV;
  109. fpc_threadvar_relocate_proc := nil;
  110. PASCALMAIN;
  111. END;
  112. {*****************************************************************************
  113. System Dependent Exit code
  114. *****************************************************************************}
  115. procedure FreeSbrkMem; forward;
  116. var SigTermHandlerActive : boolean;
  117. Procedure system_exit;
  118. begin
  119. if assigned (CloseAllRemainingSemaphores) then CloseAllRemainingSemaphores;
  120. if assigned (ReleaseThreadVars) then ReleaseThreadVars;
  121. FreeSbrkMem; { free memory allocated by heapmanager }
  122. if not SigTermHandlerActive then
  123. begin
  124. if ExitCode <> 0 Then { otherwise we dont see runtime-errors }
  125. PressAnyKeyToContinue;
  126. _exit (ExitCode);
  127. end;
  128. end;
  129. {*****************************************************************************
  130. Stack check code
  131. *****************************************************************************}
  132. procedure int_stackcheck(stack_size:longint);[public,alias:'FPC_STACKCHECK'];
  133. {
  134. called when trying to get local stack if the compiler directive $S
  135. is set this function must preserve esi !!!! because esi is set by
  136. the calling proc for methods it must preserve all registers !!
  137. With a 2048 byte safe area used to write to StdIo without crossing
  138. the stack boundary
  139. }
  140. begin
  141. IF _stackavail > stack_size + 2048 THEN EXIT;
  142. HandleError (202);
  143. end;
  144. {*****************************************************************************
  145. ParamStr/Randomize
  146. *****************************************************************************}
  147. { number of args }
  148. function paramcount : longint;
  149. begin
  150. paramcount := argc - 1;
  151. end;
  152. { argument number l }
  153. function paramstr(l : longint) : string;
  154. begin
  155. if (l>=0) and (l+1<=argc) then
  156. paramstr:=strpas(argv[l])
  157. else
  158. paramstr:='';
  159. end;
  160. { set randseed to a new pseudo random value }
  161. procedure randomize;
  162. begin
  163. randseed := _time (NIL);
  164. end;
  165. {*****************************************************************************
  166. Heap Management
  167. *****************************************************************************}
  168. var
  169. heap : longint;external name 'HEAP';
  170. intern_heapsize : longint;external name 'HEAPSIZE';
  171. { first address of heap }
  172. function getheapstart:pointer;
  173. assembler;
  174. asm
  175. leal HEAP,%eax
  176. end ['EAX'];
  177. { current length of heap }
  178. function getheapsize:longint;
  179. assembler;
  180. asm
  181. movl intern_HEAPSIZE,%eax
  182. end ['EAX'];
  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. { function to allocate size bytes more for the program }
  189. { must return the first address of new data space or -1 if fail }
  190. { for netware all allocated blocks are saved to free them at }
  191. { exit (to avoid message "Module did not release xx resources") }
  192. Function Sbrk(size : longint):longint;
  193. var P,P2 : POINTER;
  194. begin
  195. P := _malloc (size);
  196. if P = nil then
  197. Sbrk := -1
  198. else begin
  199. Sbrk := LONGINT (P);
  200. if HeapSbrkBlockList = nil then
  201. begin
  202. Pointer (HeapSbrkBlockList) := _malloc (sizeof (HeapSbrkBlockList^));
  203. if HeapSbrkBlockList = nil then
  204. begin
  205. _free (P);
  206. Sbrk := -1;
  207. exit;
  208. end;
  209. fillchar (HeapSbrkBlockList^,sizeof(HeapSbrkBlockList^),0);
  210. HeapSbrkAllocated := HeapInitialMaxBlocks;
  211. end;
  212. if (HeapSbrkLastUsed = HeapSbrkAllocated) then
  213. begin { grow }
  214. p2 := _realloc (HeapSbrkBlockList, HeapSbrkAllocated + HeapInitialMaxBlocks);
  215. if p2 = nil then
  216. begin
  217. _free (P);
  218. Sbrk := -1;
  219. exit;
  220. end;
  221. inc (HeapSbrkAllocated, HeapInitialMaxBlocks);
  222. end;
  223. inc (HeapSbrkLastUsed);
  224. HeapSbrkBlockList^[HeapSbrkLastUsed] := P;
  225. end;
  226. end;
  227. procedure FreeSbrkMem;
  228. var i : longint;
  229. begin
  230. if HeapSbrkBlockList <> nil then
  231. begin
  232. for i := 1 to HeapSbrkLastUsed do
  233. _free (HeapSbrkBlockList^[i]);
  234. _free (HeapSbrkBlockList);
  235. HeapSbrkAllocated := 0;
  236. HeapSbrkLastUsed := 0;
  237. HeapSbrkBlockList := nil;
  238. end;
  239. end;
  240. { include standard heap management }
  241. {$I heap.inc}
  242. {****************************************************************************
  243. Low level File Routines
  244. All these functions can set InOutRes on errors
  245. ****************************************************************************}
  246. PROCEDURE NW2PASErr (Err : LONGINT);
  247. BEGIN
  248. if Err = 0 then { Else it will go through all the cases }
  249. exit;
  250. case Err of
  251. Sys_ENFILE,
  252. Sys_EMFILE : Inoutres:=4;
  253. Sys_ENOENT : Inoutres:=2;
  254. Sys_EBADF : Inoutres:=6;
  255. Sys_ENOMEM,
  256. Sys_EFAULT : Inoutres:=217;
  257. Sys_EINVAL : Inoutres:=218;
  258. Sys_EPIPE,
  259. Sys_EINTR,
  260. Sys_EIO,
  261. Sys_EAGAIN,
  262. Sys_ENOSPC : Inoutres:=101;
  263. Sys_ENAMETOOLONG,
  264. Sys_ELOOP,
  265. Sys_ENOTDIR : Inoutres:=3;
  266. Sys_EROFS,
  267. Sys_EEXIST,
  268. Sys_EACCES : Inoutres:=5;
  269. Sys_EBUSY : Inoutres:=162;
  270. end;
  271. END;
  272. FUNCTION errno : LONGINT;
  273. BEGIN
  274. errno := __get_errno_ptr^;
  275. END;
  276. PROCEDURE Errno2Inoutres;
  277. BEGIN
  278. NW2PASErr (errno);
  279. END;
  280. PROCEDURE SetFileError (VAR Err : LONGINT);
  281. BEGIN
  282. IF Err >= 0 THEN
  283. InOutRes := 0
  284. ELSE
  285. BEGIN
  286. Err := errno;
  287. NW2PASErr (Err);
  288. Err := 0;
  289. END;
  290. END;
  291. { close a file from the handle value }
  292. procedure do_close(handle : longint);
  293. VAR res : LONGINT;
  294. begin
  295. res := _close (handle);
  296. IF res <> 0 THEN
  297. SetFileError (res)
  298. ELSE
  299. InOutRes := 0;
  300. end;
  301. procedure do_erase(p : pchar);
  302. VAR res : LONGINT;
  303. begin
  304. res := _unlink (p);
  305. IF Res < 0 THEN
  306. SetFileError (res)
  307. ELSE
  308. InOutRes := 0;
  309. end;
  310. procedure do_rename(p1,p2 : pchar);
  311. VAR res : LONGINT;
  312. begin
  313. res := _rename (p1,p2);
  314. IF Res < 0 THEN
  315. SetFileError (res)
  316. ELSE
  317. InOutRes := 0
  318. end;
  319. function do_write(h,addr,len : longint) : longint;
  320. VAR res : LONGINT;
  321. begin
  322. res := _write (h,POINTER(addr),len);
  323. IF res > 0 THEN
  324. InOutRes := 0
  325. ELSE
  326. SetFileError (res);
  327. do_write := res;
  328. end;
  329. function do_read(h,addr,len : longint) : longint;
  330. VAR res : LONGINT;
  331. begin
  332. res := _read (h,POINTER(addr),len);
  333. IF res > 0 THEN
  334. InOutRes := 0
  335. ELSE
  336. SetFileError (res);
  337. do_read := res;
  338. end;
  339. function do_filepos(handle : longint) : longint;
  340. VAR res : LONGINT;
  341. begin
  342. InOutRes:=1;
  343. res := _tell (handle);
  344. IF res < 0 THEN
  345. SetFileError (res)
  346. ELSE
  347. InOutRes := 0;
  348. do_filepos := res;
  349. end;
  350. CONST SEEK_SET = 0; // Seek from beginning of file.
  351. SEEK_CUR = 1; // Seek from current position.
  352. SEEK_END = 2; // Seek from end of file.
  353. procedure do_seek(handle,pos : longint);
  354. VAR res : LONGINT;
  355. begin
  356. res := _lseek (handle,pos, SEEK_SET);
  357. IF res >= 0 THEN
  358. InOutRes := 0
  359. ELSE
  360. SetFileError (res);
  361. end;
  362. function do_seekend(handle:longint):longint;
  363. VAR res : LONGINT;
  364. begin
  365. res := _lseek (handle,0, SEEK_END);
  366. IF res >= 0 THEN
  367. InOutRes := 0
  368. ELSE
  369. SetFileError (res);
  370. do_seekend := res;
  371. end;
  372. function do_filesize(handle : longint) : longint;
  373. VAR res : LONGINT;
  374. begin
  375. res := _filelength (handle);
  376. IF res < 0 THEN
  377. BEGIN
  378. SetFileError (Res);
  379. do_filesize := -1;
  380. END ELSE
  381. BEGIN
  382. InOutRes := 0;
  383. do_filesize := res;
  384. END;
  385. end;
  386. { truncate at a given position }
  387. procedure do_truncate (handle,pos:longint);
  388. VAR res : LONGINT;
  389. begin
  390. res := _chsize (handle,pos);
  391. IF res <> 0 THEN
  392. SetFileError (res)
  393. ELSE
  394. InOutRes := 0;
  395. end;
  396. // mostly stolen from syslinux
  397. procedure do_open(var f;p:pchar;flags:longint);
  398. {
  399. filerec and textrec have both handle and mode as the first items so
  400. they could use the same routine for opening/creating.
  401. when (flags and $10) the file will be append
  402. when (flags and $100) the file will be truncate/rewritten
  403. when (flags and $1000) there is no check for close (needed for textfiles)
  404. }
  405. var
  406. oflags : longint;
  407. Begin
  408. { close first if opened }
  409. if ((flags and $10000)=0) then
  410. begin
  411. case FileRec(f).mode of
  412. fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
  413. fmclosed : ;
  414. else
  415. begin
  416. inoutres:=102; {not assigned}
  417. exit;
  418. end;
  419. end;
  420. end;
  421. { reset file Handle }
  422. FileRec(f).Handle:=UnusedHandle;
  423. { We do the conversion of filemodes here, concentrated on 1 place }
  424. case (flags and 3) of
  425. 0 : begin
  426. oflags := O_RDONLY;
  427. filerec(f).mode := fminput;
  428. end;
  429. 1 : begin
  430. oflags := O_WRONLY;
  431. filerec(f).mode := fmoutput;
  432. end;
  433. 2 : begin
  434. oflags := O_RDWR;
  435. filerec(f).mode := fminout;
  436. end;
  437. end;
  438. if (flags and $1000)=$1000 then
  439. oflags:=oflags or (O_CREAT or O_TRUNC)
  440. else
  441. if (flags and $100)=$100 then
  442. oflags:=oflags or (O_APPEND);
  443. { empty name is special }
  444. if p[0]=#0 then
  445. begin
  446. case FileRec(f).mode of
  447. fminput :
  448. FileRec(f).Handle:=StdInputHandle;
  449. fminout, { this is set by rewrite }
  450. fmoutput :
  451. FileRec(f).Handle:=StdOutputHandle;
  452. fmappend :
  453. begin
  454. FileRec(f).Handle:=StdOutputHandle;
  455. FileRec(f).mode:=fmoutput; {fool fmappend}
  456. end;
  457. end;
  458. exit;
  459. end;
  460. { real open call }
  461. FileRec(f).Handle := _open(p,oflags,438);
  462. //WriteLn ('_open (',p,') liefert ',ErrNo, 'Handle: ',FileRec(f).Handle);
  463. // errno does not seem to be set on succsess ??
  464. IF FileRec(f).Handle < 0 THEN
  465. if (ErrNo=Sys_EROFS) and ((OFlags and O_RDWR)<>0) then
  466. begin // i.e. for cd-rom
  467. Oflags:=Oflags and not(O_RDWR);
  468. FileRec(f).Handle := _open(p,oflags,438);
  469. end;
  470. IF FileRec(f).Handle < 0 THEN
  471. Errno2Inoutres
  472. ELSE
  473. InOutRes := 0;
  474. End;
  475. function do_isdevice(handle:longint):boolean;
  476. begin
  477. do_isdevice := (_isatty (handle) > 0);
  478. end;
  479. {*****************************************************************************
  480. UnTyped File Handling
  481. *****************************************************************************}
  482. {$i file.inc}
  483. {*****************************************************************************
  484. Typed File Handling
  485. *****************************************************************************}
  486. {$i typefile.inc}
  487. {*****************************************************************************
  488. Text File Handling
  489. *****************************************************************************}
  490. { should we consider #26 as the end of a file ? }
  491. {?? $DEFINE EOF_CTRLZ}
  492. {$i text.inc}
  493. {*****************************************************************************
  494. Directory Handling
  495. *****************************************************************************}
  496. procedure mkdir(const s : string);[IOCheck];
  497. VAR S2 : STRING;
  498. Res: LONGINT;
  499. BEGIN
  500. S2 := S;
  501. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  502. S2 := S2 + #0;
  503. Res := _mkdir (@S2[1]);
  504. IF Res = 0 THEN
  505. InOutRes:=0
  506. ELSE
  507. SetFileError (Res);
  508. END;
  509. procedure rmdir(const s : string);[IOCheck];
  510. VAR S2 : STRING;
  511. Res: LONGINT;
  512. BEGIN
  513. S2 := S;
  514. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  515. S2 := S2 + #0;
  516. Res := _rmdir (@S2[1]);
  517. IF Res = 0 THEN
  518. InOutRes:=0
  519. ELSE
  520. SetFileError (Res);
  521. end;
  522. procedure chdir(const s : string);[IOCheck];
  523. VAR S2 : STRING;
  524. Res: LONGINT;
  525. begin
  526. S2 := S;
  527. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  528. S2 := S2 + #0;
  529. Res := _chdir (@S2[1]);
  530. IF Res = 0 THEN
  531. InOutRes:=0
  532. ELSE
  533. SetFileError (Res);
  534. end;
  535. procedure getdir(drivenr : byte;var dir : shortstring);
  536. VAR P : ARRAY [0..255] OF CHAR;
  537. Len: LONGINT;
  538. begin
  539. P[0] := #0;
  540. _getcwd (@P, SIZEOF (P));
  541. Len := _strlen (P);
  542. IF Len > 0 THEN
  543. BEGIN
  544. Move (P, dir[1], Len);
  545. BYTE(dir[0]) := Len;
  546. END ELSE
  547. InOutRes := 1;
  548. end;
  549. {*****************************************************************************
  550. Thread Handling
  551. *****************************************************************************}
  552. procedure InitFPU;assembler;
  553. asm
  554. fninit
  555. fldcw fpucw
  556. end;
  557. { if return-value is <> 0, netware shows the message
  558. Unload Anyway ?
  559. To Disable unload at all, SetNLMDontUnloadFlag can be used on
  560. Netware >= 4.0 }
  561. function CheckFunction : longint; CDECL; [public,alias: 'FPC_NW_CHECKFUNCTION'];
  562. var oldTG:longint;
  563. oldPtr: pointer;
  564. begin
  565. if assigned (NetwareCheckFunction) then
  566. begin
  567. { this function is called without clib context, to allow clib
  568. calls, we set the thread group id before calling the
  569. user-function }
  570. oldTG := _SetThreadGroupID (NetwareMainThreadGroupID);
  571. { to allow use of threadvars, we simply set the threadvar-memory
  572. from the main thread }
  573. if assigned (SetThreadDataAreaPtr) then
  574. oldPtr := SetThreadDataAreaPtr (NIL); { nil means main threadvars }
  575. result := 0;
  576. NetwareCheckFunction (result);
  577. if assigned (SetThreadDataAreaPtr) then
  578. SetThreadDataAreaPtr (oldPtr);
  579. _SetThreadGroupID (oldTG);
  580. end else
  581. result := 0;
  582. end;
  583. {$ifdef StdErrToConsole}
  584. var ConsoleBuff : array [0..512] of char;
  585. Function ConsoleWrite(Var F: TextRec): Integer;
  586. var
  587. i : longint;
  588. Begin
  589. if F.BufPos>0 then
  590. begin
  591. if F.BufPos>sizeof(ConsoleBuff)-1 then
  592. i:=sizeof(ConsoleBuff)-1
  593. else
  594. i:=F.BufPos;
  595. Move(F.BufPtr^,ConsoleBuff,i);
  596. ConsoleBuff[i] := #0;
  597. ConsolePrintf(@ConsoleBuff[0]);
  598. end;
  599. F.BufPos:=0;
  600. ConsoleWrite := 0;
  601. End;
  602. Function ConsoleClose(Var F: TextRec): Integer;
  603. begin
  604. ConsoleClose:=0;
  605. end;
  606. Function ConsoleOpen(Var F: TextRec): Integer;
  607. Begin
  608. TextRec(F).InOutFunc:=@ConsoleWrite;
  609. TextRec(F).FlushFunc:=@ConsoleWrite;
  610. TextRec(F).CloseFunc:=@ConsoleClose;
  611. ConsoleOpen:=0;
  612. End;
  613. procedure AssignStdErrConsole(Var T: Text);
  614. begin
  615. Assign(T,'');
  616. TextRec(T).OpenFunc:=@ConsoleOpen;
  617. Rewrite(T);
  618. end;
  619. {$endif}
  620. { this will be called if the nlm is unloaded. It will NOT be
  621. called if the program exits i.e. with halt.
  622. Halt (or _exit) can not be called from this callback procedure }
  623. procedure TermSigHandler (Sig:longint); CDecl;
  624. var oldTG : longint;
  625. oldPtr: pointer;
  626. begin
  627. oldTG := _SetThreadGroupID (NetwareMainThreadGroupID); { this is only needed for nw 3.11 }
  628. { _GetThreadDataAreaPtr will not be valid because the signal
  629. handler is called by netware with a differnt thread. To avoid
  630. problems in the exit routines, we set the data of the main thread
  631. here }
  632. if assigned (SetThreadDataAreaPtr) then
  633. oldPtr := SetThreadDataAreaPtr (NIL); { nil means main thread }
  634. SigTermHandlerActive := true; { to avoid that system_exit calls _exit }
  635. do_exit; { calls finalize units }
  636. if assigned (SetThreadDataAreaPtr) then
  637. SetThreadDataAreaPtr (oldPtr);
  638. _SetThreadGroupID (oldTG);
  639. end;
  640. procedure SysInitStdIO;
  641. begin
  642. { Setup stdin, stdout and stderr }
  643. StdInputHandle := _fileno (LONGINT (_GetStdIn^)); // GetStd** returns **FILE !
  644. StdOutputHandle:= _fileno (LONGINT (_GetStdOut^));
  645. StdErrorHandle := _fileno (LONGINT (_GetStdErr^));
  646. OpenStdIO(Input,fmInput,StdInputHandle);
  647. OpenStdIO(Output,fmOutput,StdOutputHandle);
  648. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  649. {$ifdef StdErrToConsole}
  650. AssignStdErrConsole(StdErr);
  651. {$else}
  652. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  653. {$endif}
  654. end;
  655. {*****************************************************************************
  656. SystemUnit Initialization
  657. *****************************************************************************}
  658. Begin
  659. StackBottom := SPtr - StackLength;
  660. SigTermHandlerActive := false;
  661. NetwareCheckFunction := nil;
  662. NetwareMainThreadGroupID := _GetThreadGroupID;
  663. _Signal (_SIGTERM, @TermSigHandler);
  664. { Setup heap }
  665. InitHeap;
  666. SysInitExceptions;
  667. SysInitStdIO;
  668. { Reset IO Error }
  669. InOutRes:=0;
  670. {Delphi Compatible}
  671. IsLibrary := FALSE;
  672. IsConsole := TRUE;
  673. ExitCode := 0;
  674. {$ifdef HASVARIANT}
  675. initvariantmanager;
  676. {$endif HASVARIANT}
  677. End.
  678. {
  679. $Log$
  680. Revision 1.16 2003-02-15 19:12:54 armin
  681. * changes for new threadvar support
  682. Revision 1.15 2002/10/13 09:28:45 florian
  683. + call to initvariantmanager inserted
  684. Revision 1.14 2002/09/07 16:01:21 peter
  685. * old logs removed and tabs fixed
  686. Revision 1.13 2002/07/01 16:29:05 peter
  687. * sLineBreak changed to normal constant like Kylix
  688. Revision 1.12 2002/04/15 18:47:34 carl
  689. + reinstate novell stack checking
  690. Revision 1.11 2002/04/12 17:40:11 carl
  691. + generic stack checking
  692. Revision 1.10 2002/04/01 15:20:08 armin
  693. + unload module no longer shows: Module did not release...
  694. + check-function will no longer be removed when smartlink is on
  695. Revision 1.9 2002/04/01 10:47:31 armin
  696. makefile.fpc for netware
  697. stderr to netware console
  698. free all memory (threadvars and heap) to avoid error message while unloading nlm
  699. Revision 1.8 2002/03/30 09:09:47 armin
  700. + support check-function for netware
  701. Revision 1.7 2002/03/17 17:57:33 armin
  702. + threads and winsock2 implemented
  703. }