system.pp 20 KB

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