123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782 |
- {
- $Id$
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2000 by Michael Van Canneyt,
- member of the Free Pascal development team.
- This is the core of the system unit *nix systems (now FreeBSD
- and Unix).
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- { These things are set in the makefile, }
- { But you can override them here.}
- { If you use an aout system, set the conditional AOUT}
- { $Define AOUT}
- {$I system.inc}
- { used in syscall to report errors.}
- var
- Errno : longint;
- { Include constant and type definitions }
- {$i errno.inc } { Error numbers }
- {$i sysnr.inc } { System call numbers }
- {$i sysconst.inc } { Miscellaneous constants }
- {$i systypes.inc } { Types needed for system calls }
- { Read actual system call definitions. }
- {$i signal.inc}
- {$i syscalls.inc }
- {*****************************************************************************
- Misc. System Dependent Functions
- *****************************************************************************}
- procedure prthaltproc;external name '_haltproc';
- procedure System_exit;
- {$undef fpc_system_exit_ok}
- begin
- {$ifdef i386}
- {$define fpc_system_exit_ok}
- asm
- jmp prthaltproc
- end;
- {$endif i386}
- {$ifdef m68k}
- {$undef fpc_system_exit_ok}
- asm
- bra prthaltproc
- end;
- {$endif m68k}
- {$ifndef fpc_system_exit_ok}
- {$error System_exit code is not implemented }
- {$endif not fpc_system_exit_ok}
- End;
- Function ParamCount: Longint;
- Begin
- Paramcount:=argc-1
- End;
- Function ParamStr(l: Longint): String;
- var
- link,
- hs : string;
- i : longint;
- begin
- if l=0 then
- begin
- str(sys_getpid,hs);
- hs:='/proc/'+hs+'/exe'#0;
- i:=Sys_readlink(@hs[1],@link[1],high(link));
- { it must also be an absolute filename, linux 2.0 points to a memory
- location so this will skip that }
- if (i>0) and (link[1]='/') then
- begin
- link[0]:=chr(i);
- paramstr:=link;
- end
- else
- paramstr:=strpas(argv[0]);
- end
- else
- if (l>0) and (l<argc) then
- paramstr:=strpas(argv[l])
- else
- paramstr:='';
- end;
- Procedure Randomize;
- Begin
- randseed:=sys_time;
- End;
- {*****************************************************************************
- Heap Management
- *****************************************************************************}
- var
- _HEAP : longint;external name 'HEAP';
- _HEAPSIZE : longint;external name 'HEAPSIZE';
- function getheapstart:pointer;assembler;
- {$undef fpc_getheapstart_ok}
- {$ifdef i386}
- {$define fpc_getheapstart_ok}
- asm
- leal _HEAP,%eax
- end ['EAX'];
- {$endif i386}
- {$ifdef m68k}
- {$define fpc_getheapstart_ok}
- asm
- lea.l _HEAP,a0
- move.l a0,d0
- end['A0','D0'];
- {$endif m68k}
- {$ifndef fpc_getheapstart_ok}
- {$error Getheapstart code is not implemented }
- {$endif not fpc_getheapstart_ok}
- function getheapsize:longint;assembler;
- {$undef fpc_getheapsize_ok}
- {$ifdef i386}
- {$define fpc_getheapsize_ok}
- asm
- movl _HEAPSIZE,%eax
- end ['EAX'];
- {$endif i386}
- {$ifdef m68k}
- {$define fpc_getheapsize_ok}
- asm
- move.l _HEAPSIZE,d0
- end ['D0'];
- {$endif m68k}
- {$ifndef fpc_getheapsize_ok}
- {$error Getheapsize code is not implemented }
- {$endif not fpc_getheapsize_ok}
- Function sbrk(size : longint) : Longint;
- begin
- sbrk:=Sys_mmap(0,Size,3,MAP_PRIVATE+MAP_ANONYMOUS,-1,0);
- if sbrk<>-1 then
- errno:=0;
- {! It must be -1, not 0 as before, see heap.inc. Should be in sysmmap?}
- end;
- { include standard heap management }
- {$I heap.inc}
- {*****************************************************************************
- Low Level File Routines
- *****************************************************************************}
- {
- The lowlevel file functions should take care of setting the InOutRes to the
- correct value if an error has occured, else leave it untouched
- }
- Procedure Errno2Inoutres;
- {
- Convert ErrNo error to the correct Inoutres value
- }
- begin
- if ErrNo=0 then { Else it will go through all the cases }
- exit;
- If errno<0 then Errno:=-errno;
- case ErrNo of
- Sys_ENFILE,
- Sys_EMFILE : Inoutres:=4;
- Sys_ENOENT : Inoutres:=2;
- Sys_EBADF : Inoutres:=6;
- Sys_ENOMEM,
- Sys_EFAULT : Inoutres:=217;
- Sys_EINVAL : Inoutres:=218;
- Sys_EPIPE,
- Sys_EINTR,
- Sys_EIO,
- Sys_EAGAIN,
- Sys_ENOSPC : Inoutres:=101;
- Sys_ENAMETOOLONG,
- Sys_ELOOP,
- Sys_ENOTDIR : Inoutres:=3;
- Sys_EROFS,
- Sys_EEXIST,
- Sys_EACCES : Inoutres:=5;
- Sys_ETXTBSY : Inoutres:=162;
- end;
- end;
- Procedure Do_Close(Handle:Longint);
- Begin
- sys_close(Handle);
- End;
- Procedure Do_Erase(p:pchar);
- Begin
- sys_unlink(p);
- Errno2Inoutres;
- End;
- Procedure Do_Rename(p1,p2:pchar);
- Begin
- sys_rename(p1,p2);
- Errno2Inoutres;
- End;
- Function Do_Write(Handle,Addr,Len:Longint):longint;
- Begin
- repeat
- Do_Write:=sys_write(Handle,pchar(addr),len);
- until ErrNo<>Sys_EINTR;
- Errno2Inoutres;
- if Do_Write<0 then
- Do_Write:=0;
- End;
- Function Do_Read(Handle,Addr,Len:Longint):Longint;
- Begin
- repeat
- Do_Read:=sys_read(Handle,pchar(addr),len);
- until ErrNo<>Sys_EINTR;
- Errno2Inoutres;
- if Do_Read<0 then
- Do_Read:=0;
- End;
- Function Do_FilePos(Handle: Longint): Longint;
- Begin
- Do_FilePos:=sys_lseek(Handle, 0, Seek_Cur);
- Errno2Inoutres;
- End;
- Procedure Do_Seek(Handle,Pos:Longint);
- Begin
- sys_lseek(Handle, pos, Seek_set);
- errno2inoutres;
- End;
- Function Do_SeekEnd(Handle:Longint): Longint;
- begin
- Do_SeekEnd:=sys_lseek(Handle,0,Seek_End);
- errno2inoutres;
- end;
- Function Do_FileSize(Handle:Longint): Longint;
- var
- Info : Stat;
- Begin
- if sys_fstat(handle,info)=0 then
- Do_FileSize:=Info.Size
- else
- Do_FileSize:=0;
- Errno2Inoutres;
- End;
- Procedure Do_Truncate(Handle,fPos:longint);
- begin
- sys_ftruncate(handle,fpos);
- Errno2Inoutres;
- end;
- Procedure Do_Open(var f;p:pchar;flags:longint);
- {
- FileRec and textrec have both Handle and mode as the first items so
- they could use the same routine for opening/creating.
- when (flags and $100) the file will be append
- when (flags and $1000) the file will be truncate/rewritten
- when (flags and $10000) there is no check for close (needed for textfiles)
- }
- var
- oflags : longint;
- Begin
- { close first if opened }
- if ((flags and $10000)=0) then
- begin
- case FileRec(f).mode of
- fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
- fmclosed : ;
- else
- begin
- inoutres:=102; {not assigned}
- exit;
- end;
- end;
- end;
- { reset file Handle }
- FileRec(f).Handle:=UnusedHandle;
- { We do the conversion of filemodes here, concentrated on 1 place }
- case (flags and 3) of
- 0 : begin
- oflags :=Open_RDONLY;
- FileRec(f).mode:=fminput;
- end;
- 1 : begin
- oflags :=Open_WRONLY;
- FileRec(f).mode:=fmoutput;
- end;
- 2 : begin
- oflags :=Open_RDWR;
- FileRec(f).mode:=fminout;
- end;
- end;
- if (flags and $1000)=$1000 then
- oflags:=oflags or (Open_CREAT or Open_TRUNC)
- else
- if (flags and $100)=$100 then
- oflags:=oflags or (Open_APPEND);
- { empty name is special }
- if p[0]=#0 then
- begin
- case FileRec(f).mode of
- fminput :
- FileRec(f).Handle:=StdInputHandle;
- fminout, { this is set by rewrite }
- fmoutput :
- FileRec(f).Handle:=StdOutputHandle;
- fmappend :
- begin
- FileRec(f).Handle:=StdOutputHandle;
- FileRec(f).mode:=fmoutput; {fool fmappend}
- end;
- end;
- exit;
- end;
- { real open call }
- FileRec(f).Handle:=sys_open(p,oflags,438);
- if (ErrNo=Sys_EROFS) and ((OFlags and Open_RDWR)<>0) then
- begin
- Oflags:=Oflags and not(Open_RDWR);
- FileRec(f).Handle:=sys_open(p,oflags,438);
- end;
- Errno2Inoutres;
- End;
- Function Do_IsDevice(Handle:Longint):boolean;
- {
- Interface to Unix ioctl call.
- Performs various operations on the filedescriptor Handle.
- Ndx describes the operation to perform.
- Data points to data needed for the Ndx function. The structure of this
- data is function-dependent.
- }
- var
- Data : array[0..255] of byte; {Large enough for termios info}
- begin
- Do_IsDevice:=(sys_ioctl(handle,IOCTL_TCGETS,@data)<>-1);
- end;
- {*****************************************************************************
- UnTyped File Handling
- *****************************************************************************}
- {$i file.inc}
- {*****************************************************************************
- Typed File Handling
- *****************************************************************************}
- {$i typefile.inc}
- {*****************************************************************************
- Text File Handling
- *****************************************************************************}
- {$DEFINE SHORT_LINEBREAK}
- {$DEFINE EXTENDED_EOF}
- {$i text.inc}
- {*****************************************************************************
- Directory Handling
- *****************************************************************************}
- Procedure MkDir(Const s: String);[IOCheck];
- Var
- Buffer: Array[0..255] of Char;
- Begin
- If (s='') or (InOutRes <> 0) then
- exit;
- Move(s[1], Buffer, Length(s));
- Buffer[Length(s)] := #0;
- sys_mkdir(@buffer, 511);
- Errno2Inoutres;
- End;
- Procedure RmDir(Const s: String);[IOCheck];
- Var
- Buffer: Array[0..255] of Char;
- Begin
- If (s='') or (InOutRes <> 0) then
- exit;
- Move(s[1], Buffer, Length(s));
- Buffer[Length(s)] := #0;
- sys_rmdir(@buffer);
- Errno2Inoutres;
- End;
- Procedure ChDir(Const s: String);[IOCheck];
- Var
- Buffer: Array[0..255] of Char;
- Begin
- If (s='') or (InOutRes <> 0) then
- exit;
- Move(s[1], Buffer, Length(s));
- Buffer[Length(s)] := #0;
- sys_chdir(@buffer);
- Errno2Inoutres;
- { file not exists is path not found under tp7 }
- if InOutRes=2 then
- InOutRes:=3;
- End;
- procedure GetDir (DriveNr: byte; var Dir: ShortString);
- var
- thisdir : stat;
- rootino,
- thisino,
- dotdotino : longint;
- rootdev,
- thisdev,
- dotdotdev : dev_t;
- thedir,dummy : string[255];
- dirstream : pdir;
- d : pdirent;
- mountpoint,validdir : boolean;
- predot : string[255];
- begin
- drivenr:=0;
- dir:='';
- thedir:='/'#0;
- if sys_stat(@thedir[1],thisdir)<0 then
- exit;
- rootino:=thisdir.ino;
- rootdev:=thisdir.dev;
- thedir:='.'#0;
- if sys_stat(@thedir[1],thisdir)<0 then
- exit;
- thisino:=thisdir.ino;
- thisdev:=thisdir.dev;
- { Now we can uniquely identify the current and root dir }
- thedir:='';
- predot:='';
- while not ((thisino=rootino) and (thisdev=rootdev)) do
- begin
- { Are we on a mount point ? }
- dummy:=predot+'..'#0;
- if sys_stat(@dummy[1],thisdir)<0 then
- exit;
- dotdotino:=thisdir.ino;
- dotdotdev:=thisdir.dev;
- mountpoint:=(thisdev<>dotdotdev);
- { Now, Try to find the name of this dir in the previous one }
- dirstream:=opendir (@dummy[1]);
- if dirstream=nil then
- exit;
- repeat
- d:=sys_readdir (dirstream);
- validdir:=false;
- if (d<>nil) and
- (not ((d^.name[0]='.') and ((d^.name[1]=#0) or ((d^.name[1]='.')
- and (d^.name[2]=#0))))) and
- (mountpoint or (d^.ino=thisino)) then
- begin
- dummy:=predot+'../'+strpas(@(d^.name[0]))+#0;
- validdir:=not (sys_stat (@(dummy[1]),thisdir)<0);
- end
- else
- validdir:=false;
- until (d=nil) or
- ((validdir) and (thisdir.dev=thisdev) and (thisdir.ino=thisino) );
- { At this point, d.name contains the name of the current dir}
- if (d<>nil) then
- thedir:='/'+strpas(@(d^.name[0]))+thedir;
- { closedir also makes d invalid }
- if (closedir(dirstream)<0) or (d=nil) then
- exit;
- thisdev:=dotdotdev;
- thisino:=dotdotino;
- predot:=predot+'../';
- end;
- { Now rootino=thisino and rootdev=thisdev so we've reached / }
- dir:=thedir
- end;
- {*****************************************************************************
- SystemUnit Initialization
- *****************************************************************************}
- {$ifdef I386}
- { this should be defined in i386 directory !! PM }
- const
- fpucw : word = $1332;
- FPU_Invalid = 1;
- FPU_Denormal = 2;
- FPU_DivisionByZero = 4;
- FPU_Overflow = 8;
- FPU_Underflow = $10;
- FPU_StackUnderflow = $20;
- FPU_StackOverflow = $40;
- {$endif I386}
- Procedure ResetFPU;
- begin
- {$ifdef I386}
- asm
- fninit
- fldcw fpucw
- end;
- {$endif I386}
- end;
- {$ifdef BSD}
- procedure SignalToRunerror(Sig: longint; SigContext: SigContextRec;someptr:pointer); cdecl;
- {$else}
- {$ifdef Solaris}
- procedure SignalToRunerror(Sig: longint; SigContext: SigContextRec;someptr:pointer); cdecl;
- {$else}
- procedure SignalToRunerror(Sig: longint; SigContext: SigContextRec); cdecl;
- {$endif}
- {$ENDIF}
- var
- res,fpustate : word;
- begin
- res:=0;
- case sig of
- SIGFPE :
- begin
- { this is not allways necessary but I don't know yet
- how to tell if it is or not PM }
- {$ifdef I386}
- fpustate:=0;
- res:=200;
- {$ifndef BSD}
- if assigned(SigContext.fpstate) then
- fpuState:=SigContext.fpstate^.sw;
- {$else}
- fpustate:=SigContext.en_sw;
- {$ifdef SYSTEM_DEBUG}
- writeln('xx:',sigcontext.en_tw,' ',sigcontext.en_cw);
- {$endif SYSTEM_DEBUG}
- {$endif}
- {$ifdef SYSTEM_DEBUG}
- Writeln(stderr,'FpuState = ',FpuState);
- {$endif SYSTEM_DEBUG}
- if (FpuState and $7f) <> 0 then
- begin
- { first check te more precise options }
- if (FpuState and FPU_DivisionByZero)<>0 then
- res:=200
- else if (FpuState and FPU_Overflow)<>0 then
- res:=205
- else if (FpuState and FPU_Underflow)<>0 then
- res:=206
- else if (FpuState and FPU_Denormal)<>0 then
- res:=216
- else if (FpuState and (FPU_StackOverflow or FPU_StackUnderflow))<>0 then
- res:=207
- else if (FpuState and FPU_Invalid)<>0 then
- res:=216
- else
- res:=207; {'Coprocessor Error'}
- end;
- {$endif I386}
- ResetFPU;
- end;
- SIGILL,
- SIGBUS,
- SIGSEGV :
- res:=216;
- end;
- { give runtime error at the position where the signal was raised }
- if res<>0 then
- begin
- {$ifdef I386}
- {$ifdef BSD}
- HandleErrorAddrFrame(res,SigContext.sc_eip,SigContext.sc_ebp);
- {$else}
- HandleErrorAddrFrame(res,SigContext.eip,SigContext.ebp);
- {$endif}
- {$else}
- HandleError(res);
- {$endif}
- end;
- end;
- Procedure InstallSignals;
- const
- {$Ifndef BSD}
- {$ifdef solaris}
- act: SigActionRec =(sa_flags:SA_SIGINFO;Handler:(sa:@signaltorunerror;sa_mask:0);
- {$else}
- act: SigActionRec = (handler:(Sa:@SignalToRunError);sa_mask:0;sa_flags:0;
- Sa_restorer: NIL);
- {$endif}
- {$ELSE}
- act: SigActionRec = (handler:(Sa:@SignalToRunError);sa_flags:SA_SIGINFO;
- sa_mask:0);
- {$endif}
- oldact: PSigActionRec = Nil; {Probably not necessary anymore, now
- VAR is removed}
- begin
- ResetFPU;
- SigAction(SIGFPE,@act,oldact);
- {$ifndef Solaris}
- SigAction(SIGSEGV,@act,oldact);
- SigAction(SIGBUS,@act,oldact);
- SigAction(SIGILL,@act,oldact);
- {$endif}
- end;
- procedure SetupCmdLine;
- var
- bufsize,
- len,j,
- size,i : longint;
- found : boolean;
- buf : array[0..1026] of char;
- procedure AddBuf;
- begin
- reallocmem(cmdline,size+bufsize);
- move(buf,cmdline[size],bufsize);
- inc(size,bufsize);
- bufsize:=0;
- end;
- begin
- size:=0;
- bufsize:=0;
- i:=0;
- while (i<argc) do
- begin
- len:=strlen(argv[i]);
- if len>sizeof(buf)-2 then
- len:=sizeof(buf)-2;
- found:=false;
- for j:=1 to len do
- if argv[i][j]=' ' then
- begin
- found:=true;
- break;
- end;
- if bufsize+len>=sizeof(buf)-2 then
- AddBuf;
- if found then
- begin
- buf[bufsize]:='"';
- inc(bufsize);
- end;
- move(argv[i]^,buf[bufsize],len);
- inc(bufsize,len);
- if found then
- begin
- buf[bufsize]:='"';
- inc(bufsize);
- end;
- if i<argc then
- buf[bufsize]:=' '
- else
- buf[bufsize]:=#0;
- inc(bufsize);
- inc(i);
- end;
- AddBuf;
- end;
- Begin
- { Set up signals handlers }
- InstallSignals;
- { Setup heap }
- InitHeap;
- InitExceptions;
- { Arguments }
- SetupCmdLine;
- { Setup stdin, stdout and stderr }
- OpenStdIO(Input,fmInput,StdInputHandle);
- OpenStdIO(Output,fmOutput,StdOutputHandle);
- OpenStdIO(StdOut,fmOutput,StdOutputHandle);
- OpenStdIO(StdErr,fmOutput,StdErrorHandle);
- { Reset IO Error }
- InOutRes:=0;
- End.
- {
- $Log$
- Revision 1.13 2001-07-13 22:05:09 peter
- * cygwin updates
- Revision 1.12 2001/06/02 19:24:49 peter
- * chdir rte 2 mapped to 3
- Revision 1.11 2001/06/02 00:31:31 peter
- * merge unix updates from the 1.0 branch, mostly related to the
- solaris target
- Revision 1.10 2001/04/23 20:33:31 peter
- * also install sig handlers for sigill,sigbus
- Revision 1.9 2001/04/13 22:39:05 peter
- * removed warning
- Revision 1.8 2001/04/12 17:53:43 peter
- * fixed usage of already release memory in getdir
- Revision 1.7 2001/03/21 21:08:20 hajny
- * GetDir fixed
- Revision 1.6 2001/03/16 20:09:58 hajny
- * universal FExpand
- Revision 1.5 2001/02/20 21:31:12 peter
- * chdir,mkdir,rmdir with empty string fixed
- Revision 1.4 2000/12/17 14:00:57 peter
- * removed debug writelns
- Revision 1.3 2000/10/09 16:35:51 marco
- * Fixed the first (of many) ioctls that make building the IDE hard.
- Revision 1.2 2000/09/18 13:14:51 marco
- * Global Linux +bsd to (rtl/freebsd rtl/unix rtl/linux structure)
- Revision 1.6 2000/09/11 13:48:08 marco
- * FreeBSD support and removal of old sighandler
- Revision 1.5 2000/08/13 08:43:45 peter
- * don't check for directory in do_open (merged)
- Revision 1.4 2000/08/05 18:33:51 peter
- * paramstr(0) fix for linux 2.0 kernels (merged)
- Revision 1.3 2000/07/14 10:33:10 michael
- + Conditionals fixed
- Revision 1.2 2000/07/13 11:33:49 michael
- + removed logs
- }
|