Per poter automatizzare completamente il brute force e evitare che la fork fallisca è necessario:
aggiungere una wait per attendere la terminazione
controllare il valore della exit (con le opportune macro viste in classe) e fermarsi quando il PIN corretto è stato trovato (checkPIN fa exit(0))
Lo scopo è di analizzare il valore di ritorno e stampare solo il PIN corretto.
(Provare da soli prima di guardare la soluzione)
Se non siete ancora appagati 😅 provate a usare tutta la potenza del multi-core con il task extra!
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#define PINLEN "5" // lunghezza PIN come stringa per snprintf
#define CHECK "./checkPIN" // il programma da eseguire
int main(int argc) {
int pid, status;
int pin; // il pin da provare come numero intero
int maxbuf = atoi(PINLEN)+1; // PINLEN+1, convertito in intero
char pinstring[maxbuf]; // il buffer per la stringa contenente il pin
// (serve un byte in più per il terminatore di stringa)
/* il processo genitore sta in questo loop */
for (pin=0;;pin++) {
/*
* converte pin in pinstring mettendo un padding di zeri
* fino a raggiungere PINLEN (5 nel nostro caso)
*/
if (snprintf(pinstring, maxbuf, "%0"PINLEN"d", pin) >= maxbuf) {
/*
* superata la PINLEN ==> nessun pin trovato, quindi esce
* notare che snprintf ritorna >= maxbuf quando ha troncato la stringa
* per farla stare nel buffer (vedere la manpage)
*/
exit(EXIT_FAILURE);
}
pid = fork(); // Crea il processo figlio
if ( pid < 0 ) {
perror("errore fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
/*
* processo figlio, esegue il check lanciando CHECK
* con pinstring come argv[1]
*/
execl(CHECK, CHECK, pinstring, NULL);
/* qui non deve arrivarci mai */
perror("Errore exec!");
exit(EXIT_FAILURE);
}
/* solo il genitore continua e attende il figlio */
if ((pid=wait(&status)) >= 0) {
if (WIFEXITED(status) && WEXITSTATUS(status)==0) {
printf("PIN trovato: Yeah!!\n");
exit(EXIT_SUCCESS);
}
} else {
perror("errore wait");
exit(EXIT_FAILURE);
}
}
}