; Arquivo: pipe_ls_cat.asm
; Montar com: nasm -felf64 pipe_ls_cat.asm && ld -o pipe_ls_cat pipe_ls_cat.o

%define SYS_READ    0
%define SYS_WRITE   1
%define SYS_CLOSE   3
%define SYS_PIPE    22
%define SYS_DUP2    33
%define SYS_FORK    57
%define SYS_EXECVE  59
%define SYS_EXIT    60
%define SYS_WAITPID 61

%define STDIN_FD    0
%define STDOUT_FD   1
%define STDERR_FD   2

%define EXIT_SUCCESS 0
%define EXIT_FAILURE 1

section .rodata
    cmd_ls     db "/bin/ls", 0
    arg0_ls    dq cmd_ls
    arg1_ls    db "-l", 0
    arg2_ls    db "/proc/self/fd", 0
    argv_ls    dq arg0_ls, arg1_ls, arg2_ls, 0

    cmd_cat    db "/bin/cat", 0
    arg0_cat   dq cmd_cat
    argv_cat   dq arg0_cat, 0

    envp_null  dq 0

section .bss
    pipefds resq 2   ; 2 x 8 bytes (r/w)

section .text
global _start

_start:
    ; Cria pipe
    mov     rax, SYS_PIPE
    mov     rdi, pipefds
    syscall

    mov     r12, [pipefds]       ; leitura (pipefds[0])
    mov     r13, [pipefds + 8]   ; escrita (pipefds[1])

    ; Fork para ls
    mov     rax, SYS_FORK
    syscall
    test    rax, rax
    jz      .ls_child

    ; Fork para cat
    mov     rax, SYS_FORK
    syscall
    test    rax, rax
    jz      .cat_child

    ; Pai: fecha descritores do pipe
    mov     rax, SYS_CLOSE
    mov     rdi, r12
    syscall

    mov     rax, SYS_CLOSE
    mov     rdi, r13
    syscall

    ; Espera dois filhos
    xor     rdi, rdi
    xor     rsi, rsi
    xor     rdx, rdx
    mov     rax, SYS_WAITPID
    syscall

    xor     rdi, rdi
    xor     rsi, rsi
    xor     rdx, rdx
    mov     rax, SYS_WAITPID
    syscall

    ; Finaliza
    mov     rax, SYS_EXIT
    xor     rdi, rdi
    syscall

; -----------------------------------------
; Processo filho: ls -l /proc/self/fd
; -----------------------------------------
.ls_child:
    ; Redireciona stdout → pipe[1]
    mov     rax, SYS_DUP2
    mov     rdi, r13         ; escrita
    mov     rsi, STDOUT_FD
    syscall

    ; Fecha descritores
    mov     rax, SYS_CLOSE
    mov     rdi, r12
    syscall
    mov     rax, SYS_CLOSE
    mov     rdi, r13
    syscall

    ; execve("/bin/ls", ["ls", "-l", "/proc/self/fd"], NULL)
    mov     rax, SYS_EXECVE
    mov     rdi, cmd_ls
    mov     rsi, argv_ls
    mov     rdx, envp_null
    syscall

    ; Se execve falhar
    mov     rax, SYS_EXIT
    mov     rdi, EXIT_FAILURE
    syscall

; -----------------------------------------
; Processo filho: cat
; -----------------------------------------
.cat_child:
    ; Redireciona stdin ← pipe[0]
    mov     rax, SYS_DUP2
    mov     rdi, r12         ; leitura
    mov     rsi, STDIN_FD
    syscall

    ; Fecha descritores
    mov     rax, SYS_CLOSE
    mov     rdi, r12
    syscall
    mov     rax, SYS_CLOSE
    mov     rdi, r13
    syscall

    ; execve("/bin/cat", ["cat"], NULL)
    mov     rax, SYS_EXECVE
    mov     rdi, cmd_cat
    mov     rsi, argv_cat
    mov     rdx, envp_null
    syscall

    ; Se execve falhar
    mov     rax, SYS_EXIT
    mov     rdi, EXIT_FAILURE
    syscall
