Intercettazione dei segnali - assembly, Linux & fun
Pubblicato da syscalo il 08/12/2000
Livello intermedio
Introduzione
Intercettare i segnali inviati al nostro programma e' una delle cose da imparare se vogliamo gestire in modo intelligente le varie problematiche che si potrebbero verificare durante l'esecuzione.
Per non farne una trattazione noiosa, ho pensato di creare un piccolo programmino che potreste usare per fare uno scherzo ad un vostro amico poco esperto di Linux, molto poco esperto (capirete poi perche' specifico questo).
Come tutti sapete per inviare segnali ad un programma in esecuzione sul nostro pc si possono usare le combinazioni di tasti ^C (segnale di interrupt), ^Z (segnale di stop) e ^\ (segnale di uscita).
Lo scherzo consiste nell'intercettare questi segnali e far rispondere con frasi simpatiche (forse) invece che eseguire le operazioni di default assegnate ad ogni segnale.
Programmi usati
Iniziamo
Un po' di teoria:
Per intercettare i segnali e' necessario effettuare le seguenti operazioni:
void nome(void);
Per registrare la funzione dobbiamo chiamare la funzione signal che ha il seguente prototipo:
void (*signal(int signum, void (*handler)(int)))(int);
in cui i parametri rappresentano:
Passiamo al codice:
Pur essendo semplice, ho aggiunto qualche commento al programma.
##
## file funsig.S
## gcc -o funsig funsig.S
## ./funsig
##
##
## sezione dati
##
.data
##
## valore numerico dei segnali
## reperibile in "man 7 signal"
##
.equ SIGINT, 2
.equ SIGQUIT, 3
.equ SIGTSTP, 20
## valore usato per il tloop
## ritardo di 3 secondi
.equ ritardo, 3
## le stringhe sono create per una lunghezza di 80 caratteri
presentazione:
.asciz "\n\033[36m\033[1m\033[33GFun & other...\033[m\n"
m_int:
.asciz "\033[44m\033[1m Lasciami girare ancora un po' ;-D \
\033[m"
m_tstp:
.asciz "\033[47m\033[1m Non ho voglia di dormire!! ;-P \
\033[m"
m_quit:
.asciz "\033[42m\033[1m Ok, ok, adesso termino... che palle!! :-\\ \
\\n Terminazione processo in corso... \
\033[m"
m_fun:
.asciz "\033[41m\033[1m hehe scherzetto ;-pp \
\033[m"
##
## sezione codice
##
.text
.global main
## implementazione delle funzioni
sig_int:
pushl $m_int
call puts
addl $4, %esp
ret
sig_tstp:
pushl $m_tstp
call puts
addl $4, %esp
ret
sig_quit:
pushl $m_quit
call puts
addl $4, %esp
## ritardo di 3 secondi
pushl $ritardo
call sleep
addl $4, %esp
pushl $m_fun
call puts
addl $4, %esp
ret
##
## funzione main
##
## setta la corrispondenza segnale <--> funzione
## visualizza la frase di intestazione del programma
## entra in un ciclo infinito
##
main:
pushl %ebp
movl %esp, %ebp
pushl %ebx
pushl %esi
pushl %edi
pushl $sig_int
pushl $SIGINT
call signal
addl $8, %esp
pushl $sig_tstp
pushl $SIGTSTP
call signal
addl $8, %esp
pushl $sig_quit
pushl $SIGQUIT
call signal
addl $8, %esp
pushl $presentazione
call puts
addl $4, %esp
## ciclo infinito
loop:
jmp loop
popl %edi
popl %esi
popl %ebx
movl %ebp, %esp
popl %ebp
xorl %eax, %eax
ret
Ed ora ecco la spiegazione del perche' ho sottolineato che questo "scherzetto" puo' essere fatto solo ad un amico che ne sa molto poco di Linux: per terminare il programma e' sufficiente loggarsi su un'altra console e dare il comando "killall funsig".
Conclusioni
Per la funzione signal fate riferimento a "man 2 signal".
Per una lista dei segnali e delle loro caratteristiche "man 7 signal".