system.pp 24 KB

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