1{ 2 3 This file is part of the Free Pascal run time library. 4 Copyright (c) 2004-2005 by Olle Raab 5 6 Sysutils unit for Mac OS. 7 8 NOTE !!! THIS FILE IS UNDER CONSTRUCTION AND DOES NOT WORK CURRENLY. 9 10 THUS IT IS NOT BUILT BY THE MAKEFILES 11 12 See the file COPYING.FPC, included in this distribution, 13 for details about the copyright. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 18 19 **********************************************************************} 20unit sysutils; 21interface 22 23{$MODE objfpc} 24{$modeswitch out} 25{ force ansistrings } 26{$H+} 27{$modeswitch typehelpers} 28{$modeswitch advancedrecords} 29 30{OS has only 1 byte version for ExecuteProcess} 31{$define executeprocuni} 32 33uses 34 MacOSTP; 35 36{$DEFINE HAS_SLEEP} {Dummy implementation: TODO } 37//{$DEFINE HAS_OSERROR} TODO 38//{$DEFINE HAS_OSCONFIG} TODO 39 40type 41//TODO Check pad and size 42//TODO unify with Dos.SearchRec 43 PMacOSFindData = ^TMacOSFindData; 44 TMacOSFindData = record 45 {MacOS specific params, private, do not use:} 46 paramBlock: CInfoPBRec; 47 searchFSSpec: FSSpec; 48 searchAttr: Byte; {attribute we are searching for} 49 exactMatch: Boolean; 50 end; 51 52{ used OS file system APIs use ansistring } 53{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL} 54{ OS has an ansistring/single byte environment variable API } 55{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL} 56 57{ Include platform independent interface part } 58{$i sysutilh.inc} 59 60implementation 61 62uses 63 Dos, Sysconst, macutils; // For some included files. 64 65{$DEFINE FPC_FEXPAND_VOLUMES} 66{$DEFINE FPC_FEXPAND_NO_DEFAULT_PATHS} 67{$DEFINE FPC_FEXPAND_DRIVESEP_IS_ROOT} 68{$DEFINE FPC_FEXPAND_NO_DOTS_UPDIR} 69{$DEFINE FPC_FEXPAND_NO_CURDIR} 70 71{ Include platform independent implementation part } 72{$i sysutils.inc} 73 74 75{**************************************************************************** 76 File Functions 77****************************************************************************} 78 79Function FileOpen (Const FileName : rawbytestring; Mode : Integer) : Longint; 80 81Var LinuxFlags : longint; 82 SystemFileName: RawByteString; 83begin 84 (* TODO fix 85 SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName); 86 LinuxFlags:=0; 87 Case (Mode and 3) of 88 0 : LinuxFlags:=LinuxFlags or Open_RdOnly; 89 1 : LinuxFlags:=LinuxFlags or Open_WrOnly; 90 2 : LinuxFlags:=LinuxFlags or Open_RdWr; 91 end; 92 FileOpen:=fdOpen (FileName,LinuxFlags); 93 //!! We need to set locking based on Mode !! 94 *) 95end; 96 97 98Function FileCreate (Const FileName : RawByteString) : Longint; 99 100begin 101 (* TODO fix 102 FileCreate:=fdOpen(FileName,Open_RdWr or Open_Creat or Open_Trunc); 103 *) 104end; 105 106 107Function FileCreate (Const FileName : RawByteString;Rights : Longint) : Longint; 108 109Var LinuxFlags : longint; 110 111BEGIN 112 (* TODO fix 113 LinuxFlags:=0; 114 Case (Mode and 3) of 115 0 : LinuxFlags:=LinuxFlags or Open_RdOnly; 116 1 : LinuxFlags:=LinuxFlags or Open_WrOnly; 117 2 : LinuxFlags:=LinuxFlags or Open_RdWr; 118 end; 119 FileCreate:=fdOpen(FileName,LinuxFlags or Open_Creat or Open_Trunc); 120 *) 121end; 122 123Function FileCreate (Const FileName : RawByteString;ShareMode : Longint; Rights : Longint) : Longint; 124 125Var LinuxFlags : longint; 126 127BEGIN 128 (* TODO fix 129 LinuxFlags:=0; 130 Case (Mode and 3) of 131 0 : LinuxFlags:=LinuxFlags or Open_RdOnly; 132 1 : LinuxFlags:=LinuxFlags or Open_WrOnly; 133 2 : LinuxFlags:=LinuxFlags or Open_RdWr; 134 end; 135 FileCreate:=fdOpen(FileName,LinuxFlags or Open_Creat or Open_Trunc); 136 *) 137end; 138 139 140Function FileRead (Handle : Longint; out Buffer; Count : longint) : Longint; 141 142begin 143 (* TODO fix 144 FileRead:=fdRead (Handle,Buffer,Count); 145 *) 146end; 147 148 149Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint; 150 151begin 152 (* TODO fix 153 FileWrite:=fdWrite (Handle,Buffer,Count); 154 *) 155end; 156 157 158Function FileSeek (Handle,FOffset,Origin : Longint) : Longint; 159 160begin 161 (* TODO fix 162 FileSeek:=fdSeek (Handle,FOffset,Origin); 163 *) 164end; 165 166 167Function FileSeek (Handle : Longint; FOffset: Int64; Origin : Longint) : Int64; 168 169begin 170 (* TODO fix 171 {$warning need to add 64bit call } 172 FileSeek:=fdSeek (Handle,FOffset,Origin); 173 *) 174end; 175 176 177Procedure FileClose (Handle : Longint); 178 179begin 180 (* TODO fix 181 fdclose(Handle); 182 *) 183end; 184 185Function FileTruncate (Handle: THandle; Size: Int64) : boolean; 186 187begin 188 (* TODO fix 189 FileTruncate:=fdtruncate(Handle,Size); 190 *) 191end; 192 193Function FileAge (Const FileName : RawByteString): Longint; 194 195 (* 196Var Info : Stat; 197 Y,M,D,hh,mm,ss : word; 198 *) 199 200begin 201 (* TODO fix 202 If not fstat (FileName,Info) then 203 exit(-1) 204 else 205 begin 206 EpochToLocal(info.mtime,y,m,d,hh,mm,ss); 207 Result:=DateTimeToFileDate(EncodeDate(y,m,d)+EncodeTime(hh,mm,ss,0)); 208 end; 209 *) 210end; 211 212 213function FileGetSymLinkTarget(const FileName: RawByteString; out SymLinkRec: TRawbyteSymLinkRec): Boolean; 214begin 215 Result := False; 216end; 217 218 219Function FileExists (Const FileName : RawByteString; FollowLink : Boolean) : Boolean; 220 221 (* 222Var Info : Stat; 223 *) 224 225begin 226 (* TODO fix 227 FileExists:=fstat(filename,Info); 228 *) 229end; 230 231 232Function DirectoryExists (Const Directory : RawByteString; FollowLink : Boolean) : Boolean; 233 234 (* 235Var Info : Stat; 236 *) 237 238begin 239 (* TODO fix 240 DirectoryExists:=fstat(Directory,Info) and 241 ((info.mode and STAT_IFMT)=STAT_IFDIR); 242 *) 243end; 244 245(* 246Function LinuxToWinAttr (FN : Pchar; Const Info : Stat) : Longint; 247 248begin 249 Result:=faArchive; 250 If (Info.Mode and STAT_IFDIR)=STAT_IFDIR then 251 Result:=Result or faDirectory; 252 If (FN[0]='.') and (not (FN[1] in [#0,'.'])) then 253 Result:=Result or faHidden; 254 If (Info.Mode and STAT_IWUSR)=0 Then 255 Result:=Result or faReadOnly; 256 If (Info.Mode and 257 (STAT_IFSOCK or STAT_IFBLK or STAT_IFCHR or STAT_IFIFO))<>0 then 258 Result:=Result or faSysFile; 259end; 260 261{ 262 GlobToSearch takes a glob entry, stats the file. 263 The glob entry is removed. 264 If FileAttributes match, the entry is reused 265} 266 267Type 268 TGlobSearchRec = Record 269 Path : String; 270 GlobHandle : PGlob; 271 end; 272 PGlobSearchRec = ^TGlobSearchRec; 273 274Function GlobToTSearchRec (Var Info : TSearchRec) : Boolean; 275 276Var SInfo : Stat; 277 p : Pglob; 278 GlobSearchRec : PGlobSearchrec; 279 280begin 281 GlobSearchRec:=PGlobSearchrec(Info.FindHandle); 282 P:=GlobSearchRec^.GlobHandle; 283 Result:=P<>Nil; 284 If Result then 285 begin 286 GlobSearchRec^.GlobHandle:=P^.Next; 287 Result:=Fstat(GlobSearchRec^.Path+StrPas(p^.name),SInfo); 288 If Result then 289 begin 290 Info.Attr:=LinuxToWinAttr(p^.name,SInfo); 291 Result:=(Info.ExcludeAttr and Info.Attr)=0; 292 If Result Then 293 With Info do 294 begin 295 Attr:=Info.Attr; 296 If P^.Name<>Nil then 297 Name:=strpas(p^.name); 298 Time:=Sinfo.mtime; 299 Size:=Sinfo.Size; 300 end; 301 end; 302 P^.Next:=Nil; 303 GlobFree(P); 304 end; 305end; 306*) 307 308 309procedure DoFind (var F: TSearchRec; var retname: RawByteString; firstTime: Boolean); 310 311 var 312 err: OSErr; 313 s: Str255; 314 315begin 316(* TODO fix 317 with Rslt, findData, paramBlock do 318 begin 319 ioVRefNum := searchFSSpec.vRefNum; 320 if firstTime then 321 ioFDirIndex := 0; 322 323 while true do 324 begin 325 s := ''; 326 ioDirID := searchFSSpec.parID; 327 ioFDirIndex := ioFDirIndex + 1; 328 ioNamePtr := @s; 329 330 err := PBGetCatInfoSync(@paramBlock); 331 332 if err <> noErr then 333 begin 334 if err = fnfErr then 335 DosError := 18 336 else 337 DosError := MacOSErr2RTEerr(err); 338 break; 339 end; 340 341 attr := GetFileAttrFromPB(Rslt.paramBlock); 342 if ((Attr and not(searchAttr)) = 0) then 343 begin 344 retname := s; 345 SetCodePage(retname, DefaultFileSystemCodePage, false); 346 UpperString(s, true); 347 348 if FNMatch(Rslt.searchFSSpec.name, s) then 349 begin 350 size := GetFileSizeFromPB(paramBlock); 351 time := MacTimeToDosPackedTime(ioFlMdDat); 352 Result := 0; 353 break; 354 end; 355 end; 356 end; 357 end; 358*) 359end; 360 361 362Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint; 363 var 364 s: Str255; 365 366begin 367(* TODO fix 368 if path = '' then 369 begin 370 Result := 3; 371 Exit; 372 end; 373 374 {We always also search for readonly and archive, regardless of Attr.} 375 Rslt.searchAttr := (Attr or (archive or readonly)); 376 377 { TODO: convert PathArgToFSSpec (and the routines it calls) to rawbytestring } 378 Result := PathArgToFSSpec(path, Rslt.searchFSSpec); 379 with Rslt do 380 if (Result = 0) or (Result = 2) then 381 begin 382 { FIXME: SearchSpec is a shortstring -> ignores encoding } 383 SearchSpec := path; 384 NamePos := Length(path) - Length(searchFSSpec.name); 385 386 if (Pos('?', searchFSSpec.name) = 0) and (Pos('*', searchFSSpec.name) = 0) then {No wildcards} 387 begin {If exact match, we don't have to scan the directory} 388 exactMatch := true; 389 Result := DoFindOne(searchFSSpec, paramBlock); 390 if Result = 0 then 391 begin 392 Attr := GetFileAttrFromPB(paramBlock); 393 if ((Attr and not(searchAttr)) = 0) then 394 begin 395 name := searchFSSpec.name; 396 SetCodePage(name, DefaultFileSystemCodePage, false); 397 size := GetFileSizeFromPB(paramBlock); 398 time := MacTimeToDosPackedTime(paramBlock.ioFlMdDat); 399 end 400 else 401 Result := 18; 402 end 403 else if Result = 2 then 404 Result := 18; 405 end 406 else 407 begin 408 exactMatch := false; 409 410 s := searchFSSpec.name; 411 UpperString(s, true); 412 Rslt.searchFSSpec.name := s; 413 414 DoFind(Rslt, name, true); 415 end; 416 end; 417*) 418end; 419 420 421Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint; 422 423begin 424(* TODO fix 425 if F.exactMatch then 426 Result := 18 427 else 428 Result:=DoFind (Rslt, Name, false); 429*) 430end; 431 432 433Procedure InternalFindClose (var Handle: THandle; var FindData: TFindData); 434 435 (* 436Var 437 GlobSearchRec : PGlobSearchRec; 438 *) 439 440begin 441 (* TODO fix 442 GlobSearchRec:=PGlobSearchRec(Handle); 443 GlobFree (GlobSearchRec^.GlobHandle); 444 Dispose(GlobSearchRec); 445 *) 446end; 447 448 449Function FileGetDate (Handle : Longint) : Longint; 450 451 (* 452Var Info : Stat; 453 *) 454 455begin 456 (* TODO fix 457 If Not(FStat(Handle,Info)) then 458 Result:=-1 459 else 460 Result:=Info.Mtime; 461 *) 462end; 463 464 465Function FileSetDate (Handle,Age : Longint) : Longint; 466 467begin 468 // TODO fix 469 // Impossible under Linux from FileHandle !! 470 FileSetDate:=-1; 471end; 472 473 474Function FileGetAttr (Const FileName : RawByteString) : Longint; 475 476 (* 477Var Info : Stat; 478 *) 479 480begin 481 (* TODO fix 482 If Not FStat (FileName,Info) then 483 Result:=-1 484 Else 485 Result:=LinuxToWinAttr(Pchar(FileName),Info); 486 *) 487end; 488 489 490Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint; 491 492begin 493 Result:=-1; 494end; 495 496 497Function DeleteFile (Const FileName : RawByteString) : Boolean; 498 499begin 500 (* TODO fix 501 Result:=UnLink (FileName); 502 *) 503end; 504 505 506Function RenameFile (Const OldName, NewName : RawByteString) : Boolean; 507 508begin 509 (* TODO fix 510 RenameFile:=Unix.FRename(OldNAme,NewName); 511 *) 512end; 513 514 515{**************************************************************************** 516 Disk Functions 517****************************************************************************} 518 519{ 520 The Diskfree and Disksize functions need a file on the specified drive, since this 521 is required for the statfs system call. 522 These filenames are set in drivestr[0..26], and have been preset to : 523 0 - '.' (default drive - hence current dir is ok.) 524 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system ) 525 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system ) 526 3 - '/' (C: equivalent of dos is the root partition) 527 4..26 (can be set by you're own applications) 528 ! Use AddDisk() to Add new drives ! 529 They both return -1 when a failure occurs. 530} 531Const 532 FixDriveStr : array[0..3] of pchar=( 533 '.', 534 '/fd0/.', 535 '/fd1/.', 536 '/.' 537 ); 538var 539 Drives : byte; 540 DriveStr : array[4..26] of pchar; 541 542Procedure AddDisk(const path:string); 543begin 544 if not (DriveStr[Drives]=nil) then 545 FreeMem(DriveStr[Drives],StrLen(DriveStr[Drives])+1); 546 GetMem(DriveStr[Drives],length(Path)+1); 547 StrPCopy(DriveStr[Drives],path); 548 inc(Drives); 549 if Drives>26 then 550 Drives:=4; 551end; 552 553 554Function DiskFree(Drive: Byte): int64; 555 (* 556var 557 fs : tstatfs; 558 *) 559Begin 560 (* TODO fix 561 if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and statfs(StrPas(fixdrivestr[drive]),fs)) or 562 ((not (drivestr[Drive]=nil)) and statfs(StrPas(drivestr[drive]),fs)) then 563 Diskfree:=int64(fs.bavail)*int64(fs.bsize) 564 else 565 Diskfree:=-1; 566 *) 567End; 568 569 570 571Function DiskSize(Drive: Byte): int64; 572 (* 573var 574 fs : tstatfs; 575 *) 576Begin 577 (* TODO fix 578 if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and statfs(StrPas(fixdrivestr[drive]),fs)) or 579 ((not (drivestr[Drive]=nil)) and statfs(StrPas(drivestr[drive]),fs)) then 580 DiskSize:=int64(fs.blocks)*int64(fs.bsize) 581 else 582 DiskSize:=-1; 583 *) 584End; 585 586 587{**************************************************************************** 588 Locale Functions 589****************************************************************************} 590 591Procedure GetLocalTime(var SystemTime: TSystemTime); 592begin 593 (* TODO fix 594 Unix.GetTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second); 595 Unix.GetDate(SystemTime.Year, SystemTime.Month, SystemTime.Day); 596 SystemTime.MilliSecond := 0; 597 *) 598end ; 599 600 601Procedure InitAnsi; 602Var 603 i : longint; 604begin 605 { Fill table entries 0 to 127 } 606 for i := 0 to 96 do 607 UpperCaseTable[i] := chr(i); 608 for i := 97 to 122 do 609 UpperCaseTable[i] := chr(i - 32); 610 for i := 123 to 191 do 611 UpperCaseTable[i] := chr(i); 612 Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT)); 613 614 for i := 0 to 64 do 615 LowerCaseTable[i] := chr(i); 616 for i := 65 to 90 do 617 LowerCaseTable[i] := chr(i + 32); 618 for i := 91 to 191 do 619 LowerCaseTable[i] := chr(i); 620 Move (CPISO88591LCT,UpperCaseTable[192],SizeOf(CPISO88591UCT)); 621end; 622 623 624Procedure InitInternational; 625begin 626 InitInternationalGeneric; 627 InitAnsi; 628end; 629 630function SysErrorMessage(ErrorCode: Integer): String; 631 632begin 633 (* TODO fix 634 Result:=StrError(ErrorCode); 635 *) 636end; 637 638{**************************************************************************** 639 OS utility functions 640****************************************************************************} 641 642Function GetEnvironmentVariable(Const EnvVar : String) : String; 643 644begin 645 (* TODO fix 646 Result:=Unix.Getenv(PChar(EnvVar)); 647 *) 648end; 649 650Function GetEnvironmentVariableCount : Integer; 651 652begin 653 // Result:=FPCCountEnvVar(EnvP); 654 Result:=0; 655end; 656 657Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif}; 658 659begin 660 // Result:=FPCGetEnvStrFromP(Envp,Index); 661 Result:=''; 662end; 663 664{ Create a DoScript AppleEvent that targets the given application with text as the direct object. } 665function CreateDoScriptEvent (applCreator: OSType; scriptText: PChar; var theEvent: AppleEvent): OSErr; 666 667 var 668 err: OSErr; 669 targetAddress: AEDesc; 670 s: signedByte; 671 672begin 673 err := AECreateDesc(FourCharCodeToLongword(typeApplSignature), @applCreator, sizeof(applCreator), targetAddress); 674 if err = noErr then 675 begin 676 err := AECreateAppleEvent(FourCharCodeToLongword('misc'), FourCharCodeToLongword('dosc'), 677 targetAddress, kAutoGenerateReturnID, kAnyTransactionID, theEvent); 678 679 if err = noErr then 680 { Add script text as the direct object parameter. } 681 err := AEPutParamPtr(theEvent, FourCharCodeToLongword('----'), 682 FourCharCodeToLongword('TEXT'), scriptText, Length(scriptText)); 683 684 if err <> noErr then 685 AEDisposeDesc(theEvent); 686 AEDisposeDesc(targetAddress); 687 end; 688 689 CreateDoScriptEvent := err; 690end; 691 692Procedure Fpc_WriteBuffer(var f:Text;const b;len:longint);[external name 'FPC_WRITEBUFFER']; 693{declared in text.inc} 694 695procedure WriteAEDescTypeCharToFile(desc: AEDesc; var f: Text); 696 697begin 698 if desc.descriptorType = FourCharCodeToLongword(typeChar) then 699 begin 700 HLock(desc.dataHandle); 701 Fpc_WriteBuffer(f, PChar(desc.dataHandle^)^, GetHandleSize(desc.dataHandle)); 702 Flush(f); 703 HUnLock(desc.dataHandle); 704 end; 705end; 706 707function ExecuteToolserverScript(scriptText: PChar; var statusCode: Longint): OSErr; 708 709 var 710 err: OSErr; 711 err2: OSErr; {Non serious error} 712 theEvent: AppleEvent; 713 reply: AppleEvent; 714 aresult: AEDesc; 715 applFileSpec: FSSpec; 716 p: SignedByte; 717 718 const 719 applCreator = 'MPSX'; {Toolserver} 720 721begin 722 statusCode:= 3; //3 according to MPW. 723 err:= CreateDoScriptEvent (FourCharCodeToLongword(applCreator), scriptText, theEvent); 724 if err = noErr then 725 begin 726 err := AESend(theEvent, reply, kAEWaitReply, kAENormalPriority, kAEDefaultTimeOut, nil, nil); 727 728 if err = connectionInvalid then { Toolserver not available } 729 begin 730 err := FindApplication(FourCharCodeToLongword(applCreator), applFileSpec); 731 if err = noErr then 732 err := LaunchFSSpec(false, applFileSpec); 733 if err = noErr then 734 err := AESend(theEvent, reply, kAEWaitReply, kAENormalPriority, kAEDefaultTimeOut, nil, nil); 735 end; 736 737 if err = noErr then 738 begin 739 err:= AEGetParamDesc(reply, FourCharCodeToLongword('stat'), 740 FourCharCodeToLongword(typeLongInteger), aresult); 741 742 if err = noErr then 743 if aresult.descriptorType = FourCharCodeToLongword(typeLongInteger) then 744 statusCode:= LongintPtr(aresult.dataHandle^)^; 745 746 {If there is no output below, we get a non zero error code} 747 748 err2:= AEGetParamDesc(reply, FourCharCodeToLongword('----'), 749 FourCharCodeToLongword(typeChar), aresult); 750 if err2 = noErr then 751 WriteAEDescTypeCharToFile(aresult, stdout); 752 753 err2:= AEGetParamDesc(reply, FourCharCodeToLongword('diag'), 754 FourCharCodeToLongword(typeChar), aresult); 755 if err2 = noErr then 756 WriteAEDescTypeCharToFile(aresult, stderr); 757 758 AEDisposeDesc(reply); 759 760 {$IFDEF TARGET_API_MAC_CARBON } 761 {$ERROR FIXME AEDesc data is not allowed to be directly accessed} 762 {$ENDIF} 763 end; 764 765 AEDisposeDesc(theEvent); 766 end; 767 768 ExecuteToolserverScript:= err; 769end; 770 771 772function ExecuteProcess (const Path: RawByteString; const ComLine: RawByteString;Flags:TExecuteFlags=[]): 773 integer; 774var 775 s: AnsiString; 776 wdpath: RawByteString; 777 laststatuscode : longint; 778 E: EOSError; 779Begin 780 {Make ToolServers working directory in sync with our working directory} 781 PathArgToFullPath(':', wdpath); 782 wdpath:= 'Directory ' + wdpath; 783 Result := ExecuteToolserverScript(PChar(wdpath), laststatuscode); 784 {TODO Only change path when actually needed. But this requires some 785 change counter to be incremented each time wd is changed. } 786 787 s:= path + ' ' + comline; 788 789 Result := ExecuteToolserverScript(PChar(s), laststatuscode); 790 if Result = afpItemNotFound then 791 Result := 900 792 else 793 Result := MacOSErr2RTEerr(Result); 794 if Result <> 0 then 795 begin 796 E := EOSError.CreateFmt (SExecuteProcessFailed, [Comline, DosError]); 797 E.ErrorCode := DosError; 798 raise E; 799 end; 800 //TODO Better dos error codes 801 if laststatuscode <> 0 then 802 begin 803 {MPW status might be 24 bits} 804 Result := laststatuscode and $ffff; 805 if Result = 0 then 806 Result := 1; 807 end 808 else 809 Result := 0; 810End; 811 812 813function ExecuteProcess (const Path: RawByteString; 814 const ComLine: array of RawByteString;Flags:TExecuteFlags=[]): integer; 815var 816 CommandLine: RawByteString; 817 I: integer; 818 819begin 820 Commandline := ''; 821 for I := 0 to High (ComLine) do 822 if Pos (' ', ComLine [I]) <> 0 then 823 CommandLine := CommandLine + ' ' + '"' + ToSingleByteFileSystemEncodedFileName(ComLine [I]) + '"' 824 else 825 CommandLine := CommandLine + ' ' + ToSingleByteFileSystemEncodedFileName(Comline [I]); 826 ExecuteProcess := ExecuteProcess (Path, CommandLine); 827end; 828 829 830procedure C_usleep(val : uint32); external 'StdCLib' name 'usleep'; 831 832procedure Sleep(milliseconds: Cardinal); 833begin 834 C_usleep(milliseconds*1000); 835end; 836 837(* 838Function GetLastOSError : Integer; 839 840begin 841end; 842*) 843 844{**************************************************************************** 845 Initialization code 846****************************************************************************} 847 848Initialization 849 InitExceptions; { Initialize exceptions. OS independent } 850 InitInternational; { Initialize internationalization settings } 851Finalization 852 FreeTerminateProcs; 853 DoneExceptions; 854end. 855