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