COMPITO DI SISTEMI OPERATIVI (A.A. 93-94) 5 Ottobre 1994 Si progetti, utilizzando il linguaggio C e le primitive di basso livello che operano sui file, un filtro filtro che prevede tre argomenti di invocazione. Il primo parametro deve essere considerato come un numero intero (N), mentre gli altri due rappresentano due nomi di file (f1 e f2). Il filtro deve riportare sullo standard output una "fusione" del contenuto dei due file f1 e f2. Piu' precisamente si deve riportare in uscita N caratteri del file f1, poi N caratteri del file f2 e cosi' via. Inoltre, utilizzando il Bourne Shell di UNIX, si progetti un algoritmo che preveda tre parametri: il primo parametro sia il nome assoluto di un direttorio, il secondo parametro sia il nome assoluto di un file, mentre il terzo sia una stringa. Il primo parametro determina una gerarchia del file system che ha origine da tale direttorio. In tale gerarchia, si cerchino tutti i file il cui nome contiene la stringa passata come terzo parametro (in una qualunque posizione). Per ognuno dei file trovati, si deve scriverne il nome assoluto sullo standard output e si deve richiedere interattivamente all'utente un numero intero N. Quindi si applichi il filtro filtro di cui sopra, passandogli come parametri : 1) il valore di N, 2) il nome del file trovato, 3) il secondo parametro del file comandi. #5ott94.sh dir file stringa case $# in 3) # controllo sul primo parametro: direttorio assoluto case $1 in /*) if test ! -d $1 -o ! -x $1 then echo Direttorio $1 inesistente o inaccessibile exit 2 fi;; *) echo $1 non assoluto exit 3;; esac # controllo sul secondo parametro = file con percorso assoluto case $2 in /*) if test ! -f $2 then echo File $2 inesistente exit 4 fi;; *) echo $2 non assoluto exit 3;; esac;; # non c'e' bisogno del controllo sulla stringa terzo parametro perche' se fosse vuota avrei solo 2 parametri sulla # riga di comando *) echo Errore: Usage is $0 dir file stringa exit 1;; esac PATH=$PATH:`pwd` export PATH #chiamata al file comandi ricorsivo che effettua la ricerca scan $1 $2 $3 # --------------------------------------------------------------------------------- # scan dir nomefile stringa # prima versione: uso di case per pattern cd $1 for i in * do if test -f $i -a -r $i then case $i in *$3*) echo Trovato file `pwd`/$i echo Inserisci valore intero read N expr $N + 0 >/dev/null 2>&1 if test $? -ne 0 then echo errore argomento numerico $N exit 1 fi echo filtro $i $2 $N;; esac else if test -d $i -a -x $i then scan `pwd`/$i $2 $3 fi fi done #-------------------------------------------------------------------------------- #scan nomefile stringa # seconda versione: uso di for con pattern cd $1 #andiamo nel direttorio for i in *$3* do if test -f $i -a -r $i then echo Trovato file `pwd`/$i echo Inserisci valore intero read N expr $N + 0 >/dev/null 2>&1 if test $? -ne 0 then echo errore argomento numerico $N exit 1 fi echo filtro $i $2 $N fi done for i in * do if test -d $i -a -x $i then scan `pwd`/$i $2 $3 # chiamata ricorsiva fi done # ------------------------------------------------------------------------------- /* questo è il filtro */ #include #include main (argc, argv) int argc; char **argv; { int fd1, fd2, N, nread1, nread2; char *buff1, *buff2; if (argc != 4) { puts("Errore nel numero di parametri"); exit(-1);} N = atoi(argv[1]); if ((fd1 = open(argv[2], O_RDONLY)) < 0) { puts("Errore nell'apertura primo file"); exit(-2);} if ((fd2 = open(argv[3], O_RDONLY)) < 0) { puts("Errore nell'apertura secondo file"); exit(-2);} buff1 = (char *) malloc(N); buff2 = (char *) malloc(N); while (((nread1 = read(fd1, buff1, N)) > 0) && ((nread2 = read(fd2, buff2, N)) > 0) ) { write (1, buff1, nread1); write (1, buff2, nread2); } if (nread1 > 0) write (1, buff1, nread1); while ((nread1 = read(fd1, buff1, N)) > 0) write (1, buff1, nread1); while ((nread2 = read(fd2, buff2, N)) > 0) write (1, buff2, nread2); close(fd1); close(fd2); free(buff1); free(buff2); } 5ott94 - 5