Esercitazione 1 - 9 ottobre 2014 (90 min)
Questionario
Prima di iniziare l'esercitazione, si prega di riempire il
questionario anonimo sul primo anno del corso di laurea in Ingegneria Informatica e Automatica.
Preliminari
Aprire un terminale, creare una
directory di lavoro sc1415 e posizionarsi nella directory creata come segue:
$ mkdir /home/studente/Desktop/sc1415
$ cd /home/studente/Desktop/sc1415
$ mkdir /home/studente16/Scrivania/sc1415
$ cd /home/studente16/Scrivania/sc1415
Per questa esercitazione, si faccia riferimento alla appendici A, B, e C della
dispensa del corso.
Esercizio 1 (file e directory)
Il primo esercizio è volto a familiarizzare con i comandi dei sistemi *nix per navigare e manipolare il file system.
A) Usando i comandi
cd,
mkdir e
touch, si crei nella directory di lavoro (
sc1415) la seguente struttura di directory e file (
d1,
d2 e
d3 sono nomi di directory, mentre
f1,
f2,
f3 sono nomi di file vuoti):
|
d1/d2/f1
d1/d2/f2
d1/d3/f3
d1/f1
|
B) Usando il comando
cp una sola volta, si modifichi poi la struttura come segue:
|
d1/d2/f1
d1/d2/f2
d1/d3/f3
d1/d3/d3/f1
d1/d3/d3/f2
d1/f1
|
C) Usando il comando
rm non più di due volte si trasformi infine la struttura nella seguente:
|
d1/d3/f3
d1/d3/d3/f2
d1/f1
|
Esercizio 2 (argc/argv, programmi C su più moduli)
1. Scaricare il seguente programma in un file
main.c:
#include <stdio.h>
#include <stdlib.h>
int max
(int a,
int b
) { return a > b ? a : b;
}
int main
(int argc,
char* argv
[]) {
// argc contiene il numero di parametri passati al programma + 1
// argv[0] è il nome del programma
// argv[1] è il primo parametro passato al programma
// argv[2] è il secondo parametro passato al programma
// ecc.
// verifica che il numero di parametri passati sia sufficiente
if (argc <
3) {
printf("uso: %s a b\n", argv
[0]);
return -1;
// restituisce codice di terminazione con insuccesso
}
int a = atoi
(argv
[1]);
// prende primo parametro dalla riga di comando e lo converte a int
int b = atoi
(argv
[2]);
// prende secondo parametro dalla riga di comando e lo converte a int
int m = max
(a, b
);
// ne calcola il massimo
printf("a=%d, b=%d, max(a,b)=%d\n", a, b, m
);
// stampa il risultato
return 0;
// restituisce codice di terminazione con successo
}
2. Compilare il programma nella directory di lavoro generando un file eseguibile chiamato
max. Testarne il funzionamento come segue:
$ ./max
uso: ./max a b
$ ./max 5 3
a=5, b=3, max(a,b)=5
$
3. Modificare ora il programma in modo che la definizione della funzione
max sia in un file separato
max.c.
4. Compilare separatamente i moduli
main.c e
max.c generando i file oggetto
main.o e
max.o.
5. Linkare i due file oggetto producendo un file eseguibile
max equivalente a quello di partenza.
Esercizio 3 (analisi del tipo di file)
Si scarichino i due file compressi
mistero1.gz e
mistero2.gz nella directory di lavoro e li si decomprima usando il comando
gunzip nome-file. Usando il comando
file nome-file, si identifichi se sono file di testo o binari e di che tipo sono.
Esercizio 4 (hacker in erba!)
1. Si scarichi e si compili il seguente programma hello world generando un file eseguibile
hello:
#include <stdio.h>
int main
() {
printf("Hello world\n");
return 0;
}
2. Si usi poi il comando
xxd -g 1 hello > hello.hex per ottenere un dump esadecimale in formato testo del file eseguibile
hello.
3. Si apra il file
hello.hex con un editor di testo (es.
geany) e si modifichino i byte della stringa
Hello world che compare nell'eseguibile in modo che diventi
Hackato! (si faccia riferimento alla tabella dei codici ASCII nell'
appendice A della dispensa del corso). Fare attenzione a mantenere il terminatore di stringa (carattere
\0).
4. Convertire il file
hello.hex da testo a binario usando il comando
xxd -r hello.hex > hello
5. Vedere se l'hacking ha funzionato: eseguendo il programma
hello dovrebbe stampare
Hackato! invece di
Hello world
Esercizio 5 (valgrind)
Usando il tool
valgrind si identifichino e si correggano gli errori nel seguente programma C (per interpretare i messaggi di errore di valgrind, si faccia riferimento agli appunti della lezione del 30 settembre oppure alla documentazione
qui):
// =====================================================================
// errato.c
// =====================================================================
// Author: (c) 2014 Camil Demetrescu
// Created: October 8, 2014
// Last changed: $Date: 2014/10/08 15:00:07 $
// Changed by: $Author: demetres $
// Revision: $Revision: 1.00 $
#include <stdio.h>
#include <stdlib.h>
typedef struct array array;
struct array {
int* v;
int n;
};
// ---------------------------------------------------------------------
// array_new
// ---------------------------------------------------------------------
// alloca un nuovo array di n numeri interi
array* array_new(int n) {
array* a = malloc(4);
a->n = n;
a->v = calloc(n, 2);
return a;
}
// ---------------------------------------------------------------------
// array_delete
// ---------------------------------------------------------------------
// dealloca l'array
void array_delete(array* a) {
free(a->v);
}
// ---------------------------------------------------------------------
// array_sum
// ---------------------------------------------------------------------
int array_sum(array* a) {
int i, sum = 0;
for (i=0; i<a->n; i++)
sum += a->v[i];
return sum;
}
// ---------------------------------------------------------------------
// main
// ---------------------------------------------------------------------
int main() {
array* a = array_new(10);
int sum = array_sum(a);
array_delete(a);
return sum;
}