mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 02:51:37 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			385 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			385 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| unit beos;
 | |
| 
 | |
| interface
 | |
| 
 | |
| type
 | |
|     Stat = packed record
 | |
|       dev:longint;     {"device" that this file resides on}
 | |
|       ino:int64;       {this file's inode #, unique per device}
 | |
|       mode:dword;      {mode bits (rwx for user, group, etc)}
 | |
|       nlink:longint;   {number of hard links to this file}
 | |
|       uid:dword;       {user id of the owner of this file}
 | |
|       gid:dword;       {group id of the owner of this file}
 | |
|       size:int64;      {size of this file (in bytes)}
 | |
|       rdev:longint;    {device type (not used)}
 | |
|       blksize:longint; {preferref block size for i/o}
 | |
|       atime:longint;   {last access time}
 | |
|       mtime:longint;   {last modification time}
 | |
|       ctime:longint;   {last change time, not creation time}
 | |
|       crtime:longint;  {creation time}
 | |
|     end;
 | |
|     PStat=^Stat;
 | |
|     TStat=Stat;
 | |
| 
 | |
|                 ComStr  = String[255];
 | |
|                   PathStr = String[255];
 | |
|                     DirStr  = String[255];
 | |
|                       NameStr = String[255];
 | |
|         ExtStr  = String[255];
 | |
| 
 | |
| function FStat(Path:String;Var Info:stat):Boolean;
 | |
| function FStat(var f:File;Var Info:stat):Boolean;
 | |
| function GetEnv(P: string): pchar;
 | |
| 
 | |
| function  FExpand(Const Path: PathStr):PathStr;
 | |
| function  FSearch(const path:pathstr;dirlist:string):pathstr;
 | |
| procedure FSplit(const Path:PathStr;Var Dir:DirStr;Var Name:NameStr;Var Ext:ExtStr);
 | |
| function  Dirname(Const path:pathstr):pathstr;
 | |
| function  Basename(Const path:pathstr;Const suf:pathstr):pathstr;
 | |
| function  FNMatch(const Pattern,Name:string):Boolean;
 | |
| {function  StringToPPChar(Var S:STring):ppchar;}
 | |
| 
 | |
| function PExists(path:string):boolean;
 | |
| function FExists(path:string):boolean;
 | |
| 
 | |
| Function Shell(const Command:String):Longint;
 | |
| 
 | |
| implementation
 | |
| 
 | |
| uses strings;
 | |
| 
 | |
| {$i filerec.inc}
 | |
| {$i textrec.inc}
 | |
| 
 | |
| function sys_stat (a:cardinal;path:pchar;info:pstat;n:longint):longint; cdecl; external name 'sys_stat';
 | |
| 
 | |
| function FStat(Path:String;Var Info:stat):Boolean;
 | |
| {
 | |
|   Get all information on a file, and return it in Info.
 | |
| }
 | |
| var tmp:string;
 | |
| var p:pchar;
 | |
| begin
 | |
|   tmp:=path+#0;
 | |
|   p:=@tmp[1];
 | |
|   FStat:=(sys_stat($FF000000,p,@Info,0)=0);
 | |
| end;
 | |
| 
 | |
| function FStat(var f:File;Var Info:stat):Boolean;
 | |
| {
 | |
|   Get all information on a file, and return it in Info.
 | |
| }
 | |
| begin
 | |
|   FStat:=(sys_stat($FF000000,PChar(@FileRec(f).Name),@Info,0)=0);
 | |
| end;
 | |
| 
 | |
| 
 | |
| 
 | |
| Function GetEnv(P:string):Pchar;
 | |
| {
 | |
|   Searches the environment for a string with name p and
 | |
|   returns a pchar to it's value.
 | |
|   A pchar is used to accomodate for strings of length > 255
 | |
| }
 | |
| var
 | |
|   ep    : ppchar;
 | |
|   found : boolean;
 | |
| Begin
 | |
|   p:=p+'=';            {Else HOST will also find HOSTNAME, etc}
 | |
|   ep:=envp;
 | |
|   found:=false;
 | |
|   if ep<>nil then
 | |
|    begin
 | |
|      while (not found) and (ep^<>nil) do
 | |
|       begin
 | |
|         if strlcomp(@p[1],(ep^),length(p))=0 then
 | |
|          found:=true
 | |
|         else
 | |
|          inc(ep);
 | |
|       end;
 | |
|    end;
 | |
|   if found then
 | |
|    getenv:=ep^+length(p)
 | |
|   else
 | |
|    getenv:=nil;
 | |
| {  writeln ('GETENV (',P,') =',getenv);}
 | |
| end;
 | |
| 
 | |
| 
 | |
| 
 | |
| Function StringToPPChar(Var S:String; Var nr:longint):ppchar;
 | |
| {
 | |
|   Create a PPChar to structure of pchars which are the arguments specified
 | |
|   in the string S. Especially usefull for creating an ArgV for Exec-calls
 | |
| }
 | |
| var
 | |
|   Buf : ^char;
 | |
|   p   : ppchar;
 | |
| begin
 | |
|   s:=s+#0;
 | |
|   buf:=@s[1];
 | |
|   nr:=0;
 | |
|   while(buf^<>#0) do
 | |
|    begin
 | |
|      while (buf^ in [' ',#8,#10]) do
 | |
|       inc(buf);
 | |
|      inc(nr);
 | |
|      while not (buf^ in [' ',#0,#8,#10]) do
 | |
|       inc(buf);
 | |
|    end;
 | |
|   getmem(p,nr*4);
 | |
|   StringToPPChar:=p;
 | |
|   if p=nil then
 | |
|    begin
 | |
| {     LinuxError:=sys_enomem;}
 | |
|      exit;
 | |
|    end;
 | |
|   buf:=@s[1];
 | |
|   while (buf^<>#0) do
 | |
|    begin
 | |
|      while (buf^ in [' ',#8,#10]) do
 | |
|       begin
 | |
|         buf^:=#0;
 | |
|         inc(buf);
 | |
|       end;
 | |
|      p^:=buf;
 | |
|      inc(p);
 | |
|      p^:=nil;
 | |
|      while not (buf^ in [' ',#0,#8,#10]) do
 | |
|       inc(buf);
 | |
|    end;
 | |
| end;
 | |
| 
 | |
| 
 | |
| 
 | |
| {
 | |
| function FExpand (const Path: PathStr): PathStr;
 | |
| - declared in fexpand.inc
 | |
| }
 | |
| 
 | |
| {$DEFINE FPC_FEXPAND_TILDE} { Tilde is expanded to home }
 | |
| {$DEFINE FPC_FEXPAND_GETENVPCHAR} { GetEnv result is a PChar }
 | |
| 
 | |
| {$I fexpand.inc}
 | |
| 
 | |
| {$UNDEF FPC_FEXPAND_GETENVPCHAR}
 | |
| {$UNDEF FPC_FEXPAND_TILDE}
 | |
| 
 | |
| 
 | |
| 
 | |
| Function FSearch(const path:pathstr;dirlist:string):pathstr;
 | |
| {
 | |
|   Searches for a file 'path' in the list of direcories in 'dirlist'.
 | |
|   returns an empty string if not found. Wildcards are NOT allowed.
 | |
|   If dirlist is empty, it is set to '.'
 | |
| }
 | |
| Var
 | |
|   NewDir : PathStr;
 | |
|   p1     : Longint;
 | |
|   Info   : Stat;
 | |
| Begin
 | |
| {Replace ':' with ';'}
 | |
|   for p1:=1to length(dirlist) do
 | |
|    if dirlist[p1]=':' then
 | |
|     dirlist[p1]:=';';
 | |
| {Check for WildCards}
 | |
|   If (Pos('?',Path) <> 0) or (Pos('*',Path) <> 0) Then
 | |
|    FSearch:='' {No wildcards allowed in these things.}
 | |
|   Else
 | |
|    Begin
 | |
|      Dirlist:='.;'+dirlist;{Make sure current dir is first to be searched.}
 | |
|      Repeat
 | |
|        p1:=Pos(';',DirList);
 | |
|        If p1=0 Then
 | |
|         p1:=255;
 | |
|        NewDir:=Copy(DirList,1,P1 - 1);
 | |
|        if NewDir[Length(NewDir)]<>'/' then
 | |
|         NewDir:=NewDir+'/';
 | |
|        NewDir:=NewDir+Path;
 | |
|        Delete(DirList,1,p1);
 | |
|        if FStat(NewDir,Info) then
 | |
|         Begin
 | |
|           If Pos('./',NewDir)=1 Then
 | |
|            Delete(NewDir,1,2);
 | |
|         {DOS strips off an initial .\}
 | |
|         End
 | |
|        Else
 | |
|         NewDir:='';
 | |
|      Until (DirList='') or (Length(NewDir) > 0);
 | |
|      FSearch:=NewDir;
 | |
|    End;
 | |
| End;
 | |
| 
 | |
| 
 | |
| 
 | |
| Procedure FSplit(const Path:PathStr;Var Dir:DirStr;Var Name:NameStr;Var Ext:ExtStr);
 | |
| Var
 | |
|   DotPos,SlashPos,i : longint;
 | |
| Begin
 | |
|   SlashPos:=0;
 | |
|   DotPos:=256;
 | |
|   i:=Length(Path);
 | |
|   While (i>0) and (SlashPos=0) Do
 | |
|    Begin
 | |
|      If (DotPos=256) and (Path[i]='.') Then
 | |
|       DotPos:=i;
 | |
|      If (Path[i]='/') Then
 | |
|       SlashPos:=i;
 | |
|      Dec(i);
 | |
|    End;
 | |
|   Ext:=Copy(Path,DotPos,255);
 | |
|   Dir:=Copy(Path,1,SlashPos);
 | |
|   Name:=Copy(Path,SlashPos + 1,DotPos - SlashPos - 1);
 | |
| End;
 | |
| 
 | |
| 
 | |
| 
 | |
| Function Dirname(Const path:pathstr):pathstr;
 | |
| {
 | |
|   This function returns the directory part of a complete path.
 | |
|   Unless the directory is root '/', The last character is not
 | |
|   a slash.
 | |
| }
 | |
| var
 | |
|   Dir  : PathStr;
 | |
|   Name : NameStr;
 | |
|   Ext  : ExtStr;
 | |
| begin
 | |
|   FSplit(Path,Dir,Name,Ext);
 | |
|   if length(Dir)>1 then
 | |
|    Delete(Dir,length(Dir),1);
 | |
|   DirName:=Dir;
 | |
| end;
 | |
| 
 | |
| 
 | |
| 
 | |
| Function Basename(Const path:pathstr;Const suf:pathstr):pathstr;
 | |
| {
 | |
|   This function returns the filename part of a complete path. If suf is
 | |
|   supplied, it is cut off the filename.
 | |
| }
 | |
| var
 | |
|   Dir  : PathStr;
 | |
|   Name : NameStr;
 | |
|   Ext  : ExtStr;
 | |
| begin
 | |
|   FSplit(Path,Dir,Name,Ext);
 | |
|   if Suf<>Ext then
 | |
|    Name:=Name+Ext;
 | |
|   BaseName:=Name;
 | |
| end;
 | |
| 
 | |
| 
 | |
| 
 | |
| Function FNMatch(const Pattern,Name:string):Boolean;
 | |
| Var
 | |
|   LenPat,LenName : longint;
 | |
| 
 | |
|   Function DoFNMatch(i,j:longint):Boolean;
 | |
|   Var
 | |
|     Found : boolean;
 | |
|   Begin
 | |
|   Found:=true;
 | |
|   While Found and (i<=LenPat) Do
 | |
|    Begin
 | |
|      Case Pattern[i] of
 | |
|       '?' : Found:=(j<=LenName);
 | |
|       '*' : Begin
 | |
|             {find the next character in pattern, different of ? and *}
 | |
|               while Found and (i<LenPat) do
 | |
|                 begin
 | |
|                 inc(i);
 | |
|                 case Pattern[i] of
 | |
|                   '*' : ;
 | |
|                   '?' : begin
 | |
|                           inc(j);
 | |
|                           Found:=(j<=LenName);
 | |
|                         end;
 | |
|                 else
 | |
|                   Found:=false;
 | |
|                 end;
 | |
|                end;
 | |
|             {Now, find in name the character which i points to, if the * or ?
 | |
|              wasn't the last character in the pattern, else, use up all the
 | |
|              chars in name}
 | |
|               Found:=true;
 | |
|               if (i<=LenPat) then
 | |
|                 begin
 | |
|                 repeat
 | |
|                 {find a letter (not only first !) which maches pattern[i]}
 | |
|                 while (j<=LenName) and (name[j]<>pattern[i]) do
 | |
|                   inc (j);
 | |
|                  if (j<LenName) then
 | |
|                   begin
 | |
|                     if DoFnMatch(i+1,j+1) then
 | |
|                      begin
 | |
|                        i:=LenPat;
 | |
|                        j:=LenName;{we can stop}
 | |
|                        Found:=true;
 | |
|                      end
 | |
|                     else
 | |
|                      inc(j);{We didn't find one, need to look further}
 | |
|                   end;
 | |
|                until (j>=LenName);
 | |
|                 end
 | |
|               else
 | |
|                 j:=LenName;{we can stop}
 | |
|             end;
 | |
|      else {not a wildcard character in pattern}
 | |
|        Found:=(j<=LenName) and (pattern[i]=name[j]);
 | |
|      end;
 | |
|      inc(i);
 | |
|      inc(j);
 | |
|    end;
 | |
|   DoFnMatch:=Found and (j>LenName);
 | |
|   end;
 | |
| 
 | |
| Begin {start FNMatch}
 | |
|   LenPat:=Length(Pattern);
 | |
|   LenName:=Length(Name);
 | |
|   FNMatch:=DoFNMatch(1,1);
 | |
| End;
 | |
| 
 | |
| 
 | |
| function PExists(path:string):boolean;
 | |
| begin
 | |
|   PExists:=FExists(path);
 | |
| end;
 | |
| 
 | |
| function FExists(path:string):boolean;
 | |
| var
 | |
|     info:stat;
 | |
| begin
 | |
|   FExists:=Fstat(path,info);
 | |
| end;
 | |
| 
 | |
| function sys_load_image(a:cardinal; argp:ppchar; envp:ppchar):longint; cdecl; external name 'sys_load_image';
 | |
| function sys_wait_for_thread (th:longint; var exitcode:longint):longint; cdecl; external name 'sys_wait_for_thread';
 | |
| 
 | |
| Function Shell(const Command:String):Longint;
 | |
| var s:string;
 | |
|     argv:ppchar;
 | |
|     argc:longint;
 | |
|     th:longint;
 | |
| begin
 | |
|   s:=Command;
 | |
|   argv:=StringToPPChar(s,argc);
 | |
|   th:=0;
 | |
| {  writeln ('argc = ',argc);
 | |
|   while argv[th]<>Nil do begin
 | |
|     writeln ('argv[',th,'] = ',argv[th]);
 | |
|     th:=th+1;
 | |
|   end;
 | |
| }
 | |
|   th:=sys_load_image(argc,argv,system.envp);
 | |
|   if th<0 then begin
 | |
|     shell:=0;
 | |
|     exit;
 | |
|   end;
 | |
|   sys_wait_for_thread(th,Shell);
 | |
| end;
 | |
| 
 | |
| 
 | |
| 
 | |
| end.
 | 
