Enchaîner des commandes systèmes (processus parents/enfants)


Scénario No.1

- Afficher 'Je vais executer la commande 'ls''
- Exécuter la commande 'ls'

Ecrire le programme 2cmds.asm suivant

section .data
 message db 'Je vais exécuter la commande 'ls'', 10, 0 ; Message à afficher
 message_len equ $-message
 command db '/bin/ls', 0 ; Commande à exécuter
 argv dq command, 0 ; Tableau d'arguments pour ls
 envp dq 0 ; Tableau d'environnement vide

section .text
 global _start

_start:
 ; Afficher le message
 mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
 mov rdi, 1 ; Écrire sur la sortie standard (1 = stdout)
 lea rsi, [message] ; Adresse du message à afficher
 mov rdx, message_len ; Longueur du message
 syscall ; Appeler le système pour afficher le message

 ; Exécuter la commande 'ls'
 mov rax, 59 ; Le numéro de système pour sys_execve sur FreeBSD
 lea rdi, [command] ; Le premier argument de sys_execve, le chemin du programme
 lea rsi, [argv] ; Le deuxième argument, le tableau d'arguments
 lea rdx, [envp] ; Le troisième argument, le tableau d'environnement
 syscall ; Appeler le système pour exécuter la commande 'ls'

 ; Terminer le programme proprement
 mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
 xor rdi, rdi ; Code de sortie 0
 syscall ; Appeler le système pour terminer le programme

Assembler

nasm -f elf64 2cmds.asm

Linker

ld 2cmds.o -o 2cmds

Lancer le programme

./2cmds

Scénario No.2

- Afficher 'Je vais executer la commande 'ls''
- Exécuter la commande 'ls'
- Afficher 'J'ai terminé!'

Le processus n'est pas simple : c'est là qu'on voit apparaître les processus parents/enfants.
Il faut créer un processus enfant et le surveiller pour savoir quand il a fini, afin de pouvoir exécuter une nouvelle commande.

Ecrire le programme 2cmds.asm suivant

section .data
 message1 db 10
 db 'Je vais exécuter la commande 'ls' :', 10, 0 ; Message 1 à afficher
 db 10
 message1_len equ $-message1
 message2 db 10
 db 'J'ai terminé !', 10, 0 ; Message 2 à afficher
 db 10
 message2_len equ $-message2
 command db '/bin/ls', 0 ; Commande à exécuter
 argv dq command, 0 ; Tableau d'arguments pour ls
 envp dq 0 ; Tableau d'environnement vide

section .text
 global _start

_start:
 ; Afficher le premier message
 mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
 mov rdi, 1 ; Écrire sur la sortie standard (1 = stdout)
 lea rsi, [message1] ; Adresse du message 1 à afficher
 mov rdx, message1_len ; Longueur du message 1
 syscall ; Appeler le système pour afficher le message

 ; Créer un nouveau processus
 mov rax, 2 ; Le numéro de système pour sys_fork sur FreeBSD
 syscall ; Appeler le système pour créer un processus enfant

 ; Vérifier si nous sommes dans le processus parent ou enfant
 test rax, rax
 jz execute_command ; Si RAX est 0, nous sommes dans le processus enfant

 ; Nous sommes dans le processus parent, attendre que le processus enfant termine
wait_child:
 mov rax, 7 ; Le numéro de système pour sys_wait4 sur FreeBSD
 xor rdi, rdi ; Attendre n'importe quel enfant
 xor rsi, rsi ; Pas de statut
 xor rdx, rdx ; Pas d'options
 syscall ; Appeler le système

 ; Afficher le deuxième message
 mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
 mov rdi, 1 ; Écrire sur la sortie standard (1 = stdout)
 lea rsi, [message2] ; Adresse du message 2 à afficher
 mov rdx, message2_len ; Longueur du message 2
 syscall ; Appeler le système pour afficher le message

 ; Terminer le programme proprement
 mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
 xor rdi, rdi ; Code de sortie 0
 syscall ; Appeler le système pour terminer le programme

execute_command:
 ; Exécuter la commande 'ls' dans le processus enfant
 mov rax, 59 ; Le numéro de système pour sys_execve sur FreeBSD
 lea rdi, [command] ; Le premier argument de sys_execve, le chemin du programme
 lea rsi, [argv] ; Le deuxième argument, le tableau d'arguments
 lea rdx, [envp] ; Le troisième argument, le tableau d'environnement
 syscall ; Appeler le système

Scénario No.3

- Exécuter la commande 'ls' une première fois
- Exécuter la commande 'ls' une seconde fois, lorsque l'exécution de la première commande est terminé.

Idem, il faut créer un processus enfant et le surveiller pour savoir quand il a fini, afin de pouvoir exécuter une nouvelle commande.

Ecrire le programme 2cmds.asm suivant

section .data
 command db '/bin/ls', 0 ; Commande à exécuter avec un caractère nul à la fin
 argv dq command, 0 ; Tableau d'arguments pour ls (seulement le nom du programme)
 envp dq 0 ; Tableau d'environnement vide

section .text
 global _start

_start:
 ; Créer un nouveau processus
 mov rax, 2 ; Le numéro de système pour sys_fork sur FreeBSD
 syscall ; Appeler le système pour créer un processus enfant

 ; Vérifier si nous sommes dans le processus parent ou enfant
 test rax, rax
 jz execute_command ; Si RAX est 0, nous sommes dans le processus enfant

 ; Nous sommes dans le processus parent, attendre que le processus enfant termine
wait_child:
 mov rax, 7 ; Le numéro de système pour sys_wait4 sur FreeBSD
 xor rdi, rdi ; Attendre n'importe quel enfant
 xor rsi, rsi ; Pas de statut
 xor rdx, rdx ; Pas d'options
 syscall ; Appeler le système

 ; Exécuter la commande une seconde fois dans le processus parent
execute_command:
 mov rax, 59 ; Le numéro de système pour sys_execve sur FreeBSD
 lea rdi, [command] ; Le premier argument de sys_execve, le chemin du programme
 lea rsi, [argv] ; Le deuxième argument, le tableau d'arguments
 lea rdx, [envp] ; Le troisième argument, le tableau d'environnement
 syscall ; Appeler le système

 ; Terminer le programme proprement
 mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
 xor rdi, rdi ; Code de sortie 0
 syscall ; Appeler le système

Scénario No.4

- Afficher 'Je vais exécuter la commande 'ls' 2 fois : '
- Exécuter la commande 'ls' une première fois
- Exécuter la commande 'ls' une seconde fois, lorsque l'exécution de la première commande est terminé.
- Afficher 'J'ai terminé'

Ecrire le programme 2cmds.asm suivant

section .data
 message1 db 10
 db 'Je vais exécuter la commande 'ls' 2 fois : ', 10 ; Message 1 à afficher
 db 10
 message1_len equ $-message1
 message2 db 10
 db 'J'ai terminé !', 10, 0 ; Message 2 à afficher
 db 10
 message2_len equ $-message2
 command db '/bin/ls', 0 ; Commande à exécuter
 argv dq command, 0 ; Tableau d'arguments pour ls
 envp dq 0 ; Tableau d'environnement vide

section .text
 global _start

_start:
 ; Afficher le premier message
 mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
 mov rdi, 1 ; Écrire sur la sortie standard (1 = stdout)
 lea rsi, [message1] ; Adresse du message 1 à afficher
 mov rdx, message1_len ; Longueur du message 1
 syscall ; Appeler le système pour afficher le message

 ; Créer un premier processus enfant
 mov rax, 2 ; Le numéro de système pour sys_fork sur FreeBSD
 syscall ; Appeler le système pour créer un premier processus enfant

 ; Vérifier si nous sommes dans le processus parent ou enfant
 test rax, rax
 jz execute_second_ls ; Si RAX est 0, nous sommes dans le premier processus enfant

 ; Nous sommes dans le processus parent, attendre que le premier processus enfant termine
wait_first_child:
 mov rax, 7 ; Le numéro de système pour sys_wait4 sur FreeBSD
 xor rdi, rdi ; Attendre n'importe quel enfant
 xor rsi, rsi ; Pas de statut
 xor rdx, rdx ; Pas d'options
 syscall ; Appeler le système

 ; Créer un deuxième processus enfant
 mov rax, 2 ; Le numéro de système pour sys_fork sur FreeBSD
 syscall ; Appeler le système pour créer un deuxième processus enfant

 ; Vérifier si nous sommes dans le processus parent ou deuxième enfant
 test rax, rax
 jz execute_second_ls ; Si RAX est 0, nous sommes dans le deuxième processus enfant

 ; Nous sommes dans le processus parent, attendre que le deuxième processus enfant termine
wait_second_child:
 mov rax, 7 ; Le numéro de système pour sys_wait4 sur FreeBSD
 xor rdi, rdi ; Attendre n'importe quel enfant
 xor rsi, rsi ; Pas de statut
 xor rdx, rdx ; Pas d'options
 syscall ; Appeler le système

 ; Afficher le deuxième message
 mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
 mov rdi, 1 ; Écrire sur la sortie standard (1 = stdout)
 lea rsi, [message2] ; Adresse du message 2 à afficher
 mov rdx, message2_len ; Longueur du message 2
 syscall ; Appeler le système pour afficher le message

 ; Terminer le programme proprement
 mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
 xor rdi, rdi ; Code de sortie 0
 syscall ; Appeler le système

execute_second_ls:
 ; Exécuter la commande 'ls' dans le processus enfant
 mov rax, 59 ; Le numéro de système pour sys_execve sur FreeBSD
 lea rdi, [command] ; Le premier argument de sys_execve, le chemin du programme
 lea rsi, [argv] ; Le deuxième argument, le tableau d'arguments
 lea rdx, [envp] ; Le troisième argument, le tableau d'environnement
 syscall ; Appeler le système

Scénario No.5

- Afficher le message 'Looking for pkg, please wait...'
- Vérifier l'existence de la ressource '/usr/local/sbin/pkg' avec une conditionnelle :
--- Si /usr/local/sbin/pkg n'existe pas, alors installer pkg en exécutant la commande 'pkg install -y pkg && pkg update'
- Afficher un dernier message 'Welcome to this desktop installation script for FreeBSD!'.

Bien entendu, si '/usr/local/sbin/pkg' n'est pas présent (ce qui déclenche alors l'installation de pkg) alors il faut s'assurer que chaque processus est terminé avant de passer au suivant.
(là, ça commence à devenir plus trappu !)

section .data
 path db '/usr/local/sbin/pkg', 0 ; Définir le chemin à vérifier
 command db '/bin/sh', 0 ; Utiliser le shell pour exécuter la commande
 arg1 db '-c', 0 ; Argument pour exécuter une commande
 arg2 db 'pkg install -y pkg && pkg update', 0 ; Commande à exécuter si le chemin n'existe pas
 argv dq command, arg1, arg2, 0 ; Tableau d'arguments pour execve
 envp dq 0 ; Tableau d'environnement vide
 install_msg db 10
 db '------------------------------------------------', 10
 db '| Looking for pkg, please wait...', 10 ; Message d'installation
 db 10
 install_msg_len equ $-install_msg
 welcome_msg db 10
 db '------------------------------------------------', 10
 db '| Welcome to this desktop installation program for FreeBSD!', 10
 db 10
 welcome_msg_len equ $-welcome_msg

section .bss
 statbuf resb 144 ; Buffer pour l'appel système stat

section .text
 global _start

_start:
 ; Afficher le message d'installation
 mov rax, 4 ; Numéro de l'appel système pour sys_write sous FreeBSD
 mov rdi, 1 ; Descripteur de fichier pour la sortie standard (STDOUT)
 mov rsi, install_msg ; Adresse du message à afficher
 mov rdx, install_msg_len ; Longueur du message
 syscall

 ; Vérifier si le chemin existe en utilisant 'stat'
 mov rax, 188 ; Numéro de l'appel système pour 'stat' sous FreeBSD
 lea rdi, [path] ; Adresse du chemin
 lea rsi, [statbuf] ; Adresse du buffer stat
 syscall

 ; Vérifier si stat a réussi
 cmp rax, 0
 je path_exists ; Sauter si le chemin existe

 ; Si stat échoue, le chemin n'existe pas, exécuter la commande dans un processus enfant
 mov rax, 2 ; Le numéro de système pour sys_fork sur FreeBSD
 syscall ; Appeler le système pour créer un processus enfant

 ; Vérifier si nous sommes dans le processus parent ou enfant
 test rax, rax
 jz execute_command ; Si RAX est 0, nous sommes dans le processus enfant

 ; Nous sommes dans le processus parent, attendre que le processus enfant termine
wait_child:
 mov rax, 7 ; Le numéro de système pour sys_wait4 sur FreeBSD
 xor rdi, rdi ; Attendre n'importe quel enfant
 xor rsi, rsi ; Pas de statut
 xor rdx, rdx ; Pas d'options
 syscall ; Appeler le système

 ; Afficher le message de bienvenue
 mov rax, 4 ; Numéro de l'appel système pour sys_write sous FreeBSD
 mov rdi, 1 ; Descripteur de fichier pour la sortie standard (STDOUT)
 mov rsi, welcome_msg ; Adresse du message à afficher
 mov rdx, welcome_msg_len ; Longueur du message
 syscall

 ; Terminer le programme
 mov rax, 1 ; Numéro de l'appel système pour sys_exit sous FreeBSD
 xor rdi, rdi ; Code de sortie 0
 syscall ; Appeler le système

execute_command:
 ; Exécuter la commande 'pkg install -y pkg && pkg update' dans le processus enfant
 mov rax, 59 ; Numéro de l'appel système pour sys_execve sous FreeBSD
 lea rdi, [command] ; Premier argument pour sys_execve, le chemin du programme
 lea rsi, [argv] ; Deuxième argument, le tableau d'arguments
 lea rdx, [envp] ; Troisième argument, le tableau d'environnement
 syscall ; Appeler le système

path_exists:
 ; Afficher le message de bienvenue
 mov rax, 4 ; Numéro de l'appel système pour sys_write sous FreeBSD
 mov rdi, 1 ; Descripteur de fichier pour la sortie standard (STDOUT)
 mov rsi, welcome_msg ; Adresse du message à afficher
 mov rdx, welcome_msg_len ; Longueur du message
 syscall

 ; Terminer le programme
 mov rax, 1 ; Numéro de l'appel système pour sys_exit sous FreeBSD
 xor rdi, rdi ; Code de sortie 0
 syscall ; Appeler le système


↑ Haut de page