; _______________________________________________________________________________________
;|                                                                                       |
;| ..::FreshLib::..  Free, open source. Licensed under "BSD 2-clause" license."          |
;|_______________________________________________________________________________________|
;
;  Description: Process management library. Linux part
;
;  Target OS: Linux
;
;  Dependencies:
;
;  Notes:
;_________________________________________________________________________________________


; This procedure switches the program in PER_LINUX32_3GB personality, because of
; some conflicts with StrLib handles that are placed in the number space above
; $c0000000.
;
; It is usually the first of the initialization procedures.

if defined options.Force3GB & options.Force3GB

proc ___SwitchLinuxTo3GB
begin
        OutputValue "Stack top address: $", esp, 16, 8

        cmp     esp, $c0000000
        jb      .finish                 ; the system is 32bit

        mov     eax, sys_personality
        mov     ebx, -1
        int     $80

        OutputValue "Initial personality: $", eax, 16, 8

        test    eax, ADDR_LIMIT_3GB
        jnz     .finish                         ; everything is OK.

; set the needed personality

        DebugMsg "Switch to 3GB address space."

        mov     eax, sys_personality
        mov     ebx, PER_LINUX32_3GB
        int     $80

; and restart the process

        mov     eax, [esp+4]          ; argument count
        mov     ebx, [esp+8]          ; the first argument is the name of the program.
        lea     ecx, [esp+8]          ; the arguments list.
        lea     edx, [ecx+4*eax+4]    ; the environment list.

        mov     eax, sys_execve
        int     $80

   ; !!! THIS PROC EXITS ONLY IF EVERYTHING IS OK !!!
   ; if something gone wrong, it comes here and stops!

        int3

.finish:

        DebugMsg "The program switched to 3GB address space."
        return
endp
end if




; Terminate all process threads
body TerminateAll
begin
        mov     eax, sys_exit_group
        mov     ebx, [.exit_code]
        int     $80
        return
endp




body SetForcedTerminateHandler

  .action lnx_sigaction

begin
        pushad

        mov     eax, [.procHandler]
        mov     [__UserSignalsProc], eax

        mov     [.action.sa_handler], __TerminateSignalsHandler
        mov     [.action.sa_sigaction], 0
        mov     [.action.sa_mask], 0
        mov     [.action.sa_flags], 0
        mov     [.action.sa_restorer], 0

        mov     eax, sys_sigaction
        mov     ebx, SIGTERM
        lea     ecx, [.action]
        xor     edx, edx
        int     $80

        mov     eax, sys_sigaction
        mov     ebx, SIGINT
        lea     ecx, [.action]
        xor     edx, edx
        int     $80

        mov     eax, sys_sigaction
        mov     ebx, SIGQUIT
        lea     ecx, [.action]
        xor     edx, edx
        int     $80

        mov     eax, sys_sigaction
        mov     ebx, SIGHUP
        lea     ecx, [.action]
        xor     edx, edx
        int     $80

        mov     eax, sys_sigaction
        mov     ebx, SIGUSR1
        lea     ecx, [.action]
        xor     edx, edx
        int     $80

        popad
        return
endp


uglobal
  __UserSignalsProc dd ?
  __MemoryFault     dd ?
endg


proc __TerminateSignalsHandler, .signal
begin
        pushad
        DebugMsg "Terminating event received!"

        cmp     [__UserSignalsProc], 0
        je      .finish

        stdcall [__UserSignalsProc], [.signal]

.finish:
        popad
        cret
endp






body GetCmdArguments
begin
        push    ecx edx esi

        mov     esi, [_ptrEnvironment]

        mov     ecx, [esi]
        add     esi, 4

        stdcall CreateArray, 4
        mov     edx, eax
        jecxz   .array_ok

        stdcall AddArrayItems, eax, ecx

.array_ok:
        push    edx
        jecxz   .arg_ok

        lea     edx, [edx+TArray.array]

.loop:
        lodsd
        stdcall StrDupMem, eax
        mov     [edx], eax
        add     edx, 4
        loop    .loop

.arg_ok:
        pop     eax
        pop     esi edx ecx
        return
endp







proc SetSegmentationFaultHandler, .procHandler

  .action lnx_sigaction

begin
        pushad

        mov     eax, [.procHandler]
        mov     [__MemoryFault], eax

        mov     [.action.sa_handler], __ExceptionHandler
        mov     [.action.sa_sigaction], 0
        mov     [.action.sa_mask], 0
        mov     [.action.sa_flags], 0
        mov     [.action.sa_restorer], 0

        mov     eax, sys_sigaction
        mov     ebx, SIGSEGV
        lea     ecx, [.action]
        xor     edx, edx
        int     $80

        popad
        return
endp



if used __ExceptionHandler

__ExceptionHandler:

        lea     esi, [esp+8]    ; the start of sig_context structure.

        stdcall FileOpenAccess, "fault.txt", faCreateAlways or faWriteOnly
        mov     ebx, eax

        mov     eax, [esi+sig_context.eip]

        stdcall NumToStr, eax, ntsHex or ntsUnsigned or ntsFixedWidth + 8
        stdcall FileWriteString, ebx, eax
        stdcall FileWriteString, ebx, <txt 13, 10, 13, 10>

        lea     ebp, [esi+sig_context.ebp]

.loop:
        mov     ebp, [ebp]
        mov     eax, [ebp+4]    ; return address

        stdcall NumToStr, eax, ntsHex or ntsUnsigned or ntsFixedWidth + 8
        stdcall FileWriteString, ebx, eax
        stdcall FileWriteString, ebx, <txt 13, 10>

        cmp     dword [ebp+4], $b0000000
        jb      .loop

.finish:
        stdcall FileClose, ebx

        cmp     [__MemoryFault], 0
        je      .return

        jmp     [__MemoryFault]

.return:
        retn


end if











match =LinuxThreads, LinuxThreads {
  define LinuxThreads posix
}

match =native, LinuxThreads {
  include '_process_native.asm'
}

match =posix, LinuxThreads {
  include '_process_posix.asm'
}




