Introduzione a PERL E.Mumolo mumolo@units.it. Prima parte. Introduzione al linguaggio Practical...

Post on 01-May-2015

217 views 3 download

Transcript of Introduzione a PERL E.Mumolo mumolo@units.it. Prima parte. Introduzione al linguaggio Practical...

Introduzione a PERL

E.Mumolomumolo@units.it

Prima parte.Introduzione al linguaggio

Practical Extraction and Report Languageor

Pathological Eclectic Rubbish Lister?

Introduzione a PERL

• Nato per assistere l’utente Unix per le comuni operazioni, troppo pesanti, troppo dipendenti dalla shell ma troppo complesse da codificare in C ...

• Compattezza (sinteticità) e potenza

• Ambiente più naturale: Unix. Integra comandi sed awk grep mail IPC …

• Finalizzato principalmente per elaborare stringhe e file di testo

 • Correntemente molto usato per operazioni di amministrazione di sistema e per

CGI/HTTP

 • Linguaggio Interpretato

• Riferimenti classici:

- Programming PERL, L.Wall. R.L.Schwartz

- Learning PERL, R.L.Schwartz

Istruzioni di base

• Come si presenta uno script PERL (primo.pl)#!/user/bin/perl#esempio inizialeprint “scrivi una stringa terminata da return”;$nome=<STDIN>;print “ciao $nome\n”;

• Esplicitamente: prompt> perl primo.pl

• Simboli:{} rappresenta un blocco di istruzioni# commenti$ precede nomi variabili e elementi scalari di array@ precede nomi di array normali o di raggruppamenti di elementi di

array% precede i nomi di array associativi& precede i nomi delle funzioni<STDIN>, <STDOUT> descrittori di standard input, output

• Redirezione: prompt> primo.pl < filein > fileout

Tipi di dati in PERL• Stringhe – Numeri – Riferimenti - Liste. Non esiste il tipo logico, ma solo condizioni.

Oppure: variabili non dichiarate, stringhe nulle, stringa “0” e il numero 0 Falso

• Tipo definito con l’inizializzazione. Es: $a=“stringa di prova”; $a=‘0xFF’, $a=‘037’

• Numeri : rappresentazione interna solo doppia precisione

• Delimitatori delle stringhe : – accento singolo : tutti i caratteri tranne tranne ‘ e \ (usare ‘\ e \\)– accento doppio : interpolazione e caratteri di controllo

• Caratteri di controllo :\n newline \cC un carattere di controllo (qui: control-C)\r return \\ backslash\t tab \” doppio accento\f linefeed \l il prossimo carattere e’ minuscolo\b backspace \L tutte i prossimi caratteri sono minuscoli\v tab verticale \u il prox carattere e’ maiuscolo\a bell \U tutti I prox caratteri sono maiuscoli\e esc \E termina \L o \U\007 il valore ottale 07 \x7f il valore hex 7f

Operatori• Operatori aritmetici :+ - * / ** % post/pre-decremento, incrementoNB:Calcoli internamente in virgola mobile • Operatori logici  :

– AND (&&) Se il primo e’ falso, non valuta il secondo Es. $a>10&&print “$a maggiore di 10”– OR (||) Se il primo è vero non valuta il secondo. Es. $a>10||print “$a minore di 10”– NOT (!) Inverte il risultato logico– di confronto tra numeri: < <= > >= == !=– di confronto tra stringhe: lt le gt ge eq ne

 • NB : il confronto tra stringhe e’ diverso dal confronto tra numeri • Operatori per stringhe :

– concatenazione: . (es. “aaa”.”bbb” = aaabbb $a . $b)– ripetizione: x (es. ‘a’x3 = aaa $a x $b)– sottostringa substr($a,$n,%m) a partire da n per m caratteri– Indice index($a,$b) posizione del primo carattere di $b

• Casting delle variabili a seconda dell’operatore Esempio: “F” . (“ 43” + 6) = “F49” “Y“ . (4*5) = “Y20“

Variabili scalari

• Case sensitive

• Il valore di una variabile ‘nomevar’ e’ sempre identificato con $nomevar

• Operatori di assegnazione binaria : += *= .= • Autoincremento, autodecremento: ++$a $a++ • Operatore chomp(argomento): trasforma stringhe DOS in Unix

• Operatore chop(argomento) : elimina l’ultimo carattere dell’argomento. Ritorna il carattere eliminato Es. chop($a=<STDIN>) ;

 • Interpolazione di variabili scalari in stringhe delimitate da “”Es. $a=”bla bla $b bla bla” ; • Se la variabile inserita viene seguita subito da testo, si puo’ usare il delimitatore {}Es. $a=”blabla${b}bla” ; stesso risultato di $a=”blabla$b”.”bla” ; 

Variabili predefinite

• $$ PID del programma

• $< UID reale dell’utente che esegue il programma

• $> UID effettivo dell’utente

• $? stato dell’ultima chiamata

• $_ argomento predefinito

• $0 nome del programma

• $” separatore di lista

• $/ separatore di righe per l’input

Array e liste in PERL

• Liste: sequenze di scalari separati da virgole tra parentesi tonde. Usate per inizializzare array.

• Variabili di tipo Array : individuate con il carattere @@a=(1,2,3) ;@a=1 ; # array di un solo elemento@b=@a ;@a=(“uno”, “due”, “tre”) ;@b=(1,2,@a,3) ; # @b contiene (1,2,”uno”,”due”,”tre”,3)

 • Uso di variabili nell’array.

($a, $b, $c) = (1,2,3) ; #inizializza le variabili $a $b $c($a, $b) = ($b, $a) ; #inverte($d, @z) = ($a, $b, $c) ; #risultato : $d=$a, @z=($b, $c)($e, @z)=@z ; #risultato : $e=$b, @z=($c)

  • Assegnazione scalare=array : la var scalare contiene il numero di elementi

@a=(1,2,3) ;$b=@a ; #risultato : la var b contiene 3($b) = @a ; # la var b contiene il primo elemento di @a

• Accedere ad un elemento non definito ritorna undef ; assegnare un elemento non definito estende l’array

Accesso agli elementi di un array• Array predefinito @ARGV argomenti dello script PERL

• Gli elementi di un array sono indicizzati da 0@a=(1, 2, 3) ;$b=$a[0] ; # $b contiene 1$a[0]=4 ; # @a = (4,2,3)$a[1]++; $a[2] += 4;

 • L’array puo’ essere raggruppato in parti:

@b=@a[0,1] ; # equivale a @b=($a[0], $a[1]) ;@a[0,1]=(x,y) ; # come @a=(x,y)@b=(1,2,3)[2,3]; # come @c=(1,2,3) @b=@c[2,3] $x=0 ; $y=1 ; @b=(1,2,3)[$x,$y] ;@z=($x,$y) ; @b=(1,2,3)[@z] ;

 • Interpolazione di elementi di array in variabili:

@a=(1,2,3) ;$b=”bla bla $a[1] bla” ;$b=”bla bla @a bla” ;$b=”blabla @a[1,2] bla” ;

Operatori per array• Minimo e Massimo indice di un array : $[a $#a

• push() e pop() :aggiungono e tolgono elementi dal lato destro dell’array.push(@a,$x) ; # come @a = (@a, $x)$old=pop(@a) ;push(@a,$x,$y,$z) ;

 • shift() e unshift() : tolgono e aggiungono elementi dal lato sinistro dell’array

unshift(@a, $x) ; #come @a=($x,@a)$x=shift(@a) ; #come ($x,@a)=@a

 • reverse() : inverte l’ordine degli elemeti di un array • sort() : ordina un array in senso ascendente.

@a=sort(@a) ;

 • Accesso ad un elemento: $a[$b]

• chop() : se applicato ad un array, elimina l’ultimo elemento.  • Lettura da tastiera con <STDIN>

@a=<STDIN> ; #legge dallo standard input ogni riga in un elemento dell’array. 

Il ciclo for

• Sintassi: 

for(condizione iniziale; condizione finale; incremento) {istruzioni;

} • Esempio : stampa di un array

#!/user/local/bin/perl@v = (“lun”, “mar”, “mer”, “gio”, “ven”, “sab”);for($i=0; $i<=$#v; $i++){ print “$v[$i]\n”; }

• Struttura foreach $varloop: la variabile di loop e’ un riferimento ad ogni elemento dell’array. L’array puo’ essere modificato. Se non indico la variabile variabile implicita $_Esempio : stampa di un array#!/user/local/bin/perl@v = (“lun”, “mar”, “mer”, “gio”, “ven”, “sab”);foreach $a(@v){ print “$a\n”; }

Array associativi

• Collezione di dati scalari, individuati dal valore delle chiavi.

Coppie (chiave-dato) indirizzata per chiave

%a=(“a”, dato_a, “b”, dato_b, “c”, dato_c);

•  Accesso agli elementi di %a: $b=$a{$chiave};print $a{“a”};

print $a{“b”};

•  Inizializzazione elemento per elemento:$a{“a”} = “dato_a”;

$a{“b”} = “dato_b”;

•  Principali operatori per gli array associativi– keys() ritorna la lista di tutte le chiavi

@lista = keys(%a); # ritorna (“a”, “b”, “c”);

foreach $key (keys(%a)){

print “alla chiave $key corrisponde $a{$key}” # stampa la coppia chiave/valore

}

–  each() ritorna la coppia (chiave, dato)

while( ($x,$y) = each(%a)) { print “$x $y”; }

–  delete cancella un elemento dell’array associativo tramite la chiave

delete $a{“a”};

Struttura condizionata• Struttura if-else

if(condizione){ if(condizione) {primo blocco di istruzioni ; istruzioni ;

}else { } elsif (condizione) {secondo blocco di istruzioni ; istruzioni ;

} } elsif(condizione) {…..}

• Struttura postfissa (singola istruzione): istruzione if condizione;• Se l’espressione e’ una stringa di singoli caratteri, l’espressione e’ valutata così :

se “0” => falso . Se non “0” => vero. 0, “0” falso

“0” falso1-1 falso0 “0” falso“00” vero

1 vero“” falso

 • unless : realizza la parte else dell’if :

 unless(condizione){secondo blocco di istruzioni ;

}

Struttura condizionata

• Le istruzioni ritornano un valore vero se sono andati a buon fine istruzioni come condizioni.

– Struttura if(PrimaIstruzione) {SecondaIstruzione;}– Realizzazione in PERL PrimaIstruzione && SecondaIstruzione;

– Struttura if( ! PrimaIstruzione) {SecondaIstruzione;}– Realizzazione in PERL PrimaIstruzione || SecondaIstruzione;

• Precedenze degli operatori

• Uso di ‘die’: istruzione || die “errore”

Strutture while/until• Sintassi

while(espression){ until(espressione){istruzioni ; istruzioni ;

} } • Esempi: lettura di un file.

#!/user/local/bin/perlopen(f, “< nomefile”) || die “errore di apertura file”;while($r = <f>) { print $r; }close(f);

• Stampa di un array.#!/user/local/bin/perl@v = (“lun”, “mar”, “mer”, “gio”, “ven”, “sab”);while(@v) {

$giorno = shift @v;print “$giorno\n”;

}

Input/Output• Lettura da <STDIN>

$a = <STDIN> #legge una linea

@a = <STDIN> #legge tutte le linee fino a ^d

while(<STDIN>){ #legge in $_

chop; #agisce su $_

print “$_” # … elabora $_

}

 • Operatore diamante < > : legge una riga alla volta dai file forniti come argomenti dello

script. NB: i nomi vengono prelevati dall’array @ARGV

script ‘prova’#!/usr/local/bin/perl

while(<>) {

print $_

}

  prova file1 file2 …

 • Uscita su STDOUT con print.

$a = print(“blabla \n ») ; #ritorna vero o falso

print(“%s %d %f\n”, $a, $b, $c); #print formattato

Gestione dei file in PERL

• Gestione dei file attraverso i file handle • Apertura di un file handle: open(nome file handle, “nome file”);

– open ritorna vero o falso– per aprire in scrittura: open(OUT, “>nome file”);– aggiungere al file: open(OUT,”>>nome file”);– apertura in lettura: open(IN,”nome file”);

• Spostamento del puntatore al file: seek(puntatore, posizione, partenza)

• Operatore die(“…”): scrive il messaggio e poi esce dal processounless(open(OUT,”>file”)){

die(“errore\n”);} else{

print(“ok\n”); #resto del programma;

}

oppure: open(OUT,”>file”) || die(“errore\n”);

Gestione dei file in PERL• Lettura file:

open(IN, “file”);while(<IN>){

chop; print “linea letta= $_ \n”:}close(IN);

 • Copia file:

open(IN, “file_in”);open(OUT, “>file_out”);while(<IN>){

chop; print(OUT, $_);}close(IN); close(OUT);

 • Test sui file:

-r file leggibile -w file eseguibile-x file o directory eseguibile -o appartiene all’utente-R leggibile dall’utente reale, non effettivo -W scrivibile dall’utente reale-X eseguibile dall’utente reale -O appartiene all’utente reale-e il file esiste

Gestione dei file in PERL

• Test sui file-z il file esiste ma ha dimensione nulla -s esiste ed ha dimensione

non nulla

-f file regolare -d direttorio

-l link simbolico -s socket

-p pipe con nome (fifo) -b file speciale a blocchi

-c file speciale a caratteri -uil file o directory ha setuid settato

-g bit setgid settato -k sticky bit settato

-T file testo

-B file binario -M tempo dall’ultima modifica in giorni

-A tempo dall’ultimo accesso in giorni

-C tempo dall’ultima modifica dell’inode in giorni

 • Operatore stat(file name) : ritorna informazioni dettagliate sui file.

($dev, $ino, $mode, $nlink, $UID, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat(“nome”);

 • Per selezionare le informazioni: ($uid, $gid) = (stat(“nome”))[4,5];

 • Operatore lstat(nome): ritorna informazioni dettagliate su un link

simbolico (stat su un link simbolico fornisce informazioni sul file puntato)

Gestione delle directories• Operatore chdir:

chdir(“directory”) || die

 • Espansione degli argomenti (globbing): lista dei file corrispondenti alla

espansione di *:@a = <*>;@a = <path*>;

  while($b = <*>) {print “$b”;

}

 • Operatori opendir/closedir: gestione delle directory handle:

opendir(ETC,”/etc”) || die(“errore\n”);

 • Operatore readdir(handle) : ritorna un nome file ($a=readdir) o tutti i nomi file

(@a=readdir) contenuti nella directory 

opendir(ETC,”/etc”) || die; #nomi in ordine alfabetico.foreach $a (sort readdir(ETC)){

print “$a\n”;}closedir(ETC);

Gestione file in PERL• Cancellazione: unlink(nome). Ritorna il nr di file cancellati

unlink(“nomefile”);unlink(“file1”, “file2”, “file3”);unlink(<*.txt>);

  foreach $a (<*.txt>) {unlink($a) || die;

}  foreach (<*.txt>){

unlink || die(“errore $_ \n”);}

 • Operatore rename($old, $new); rinomina file. • Operatore link, symlink: introduce un link ad un file

Link(“old”,”new”)||die; #hard linkSymlink(“old”, “new”) || die; #link simbolico

 • Operatore mkdir(): crea subdirectories

Mkdir(“nomedir”, 0777);

 • Operatore rmdir: cancella subdirectories

Rmdir(“nomedir”);

Gestione file in PERL• Operatore chmod() modifica i permessi del file; ritorna il nr di file modificati con successo

$a=chmod(0666,”nomefile”);Foreach $file (“nome1”, “nome2”){

Unless (chmod(0666, $file)) {Print “errore nella modifica dei permessi!!\n”

}}

 • Operatore chown: modifica proprietario/gruppo

chown(UID, GID, “file”);

 • Operatore utime(ultimo accesso, ultima modifica, files): modifica I tempi

Tempi associati ad un file: data ultimo accesso, data ultima modifica, data ultima modifica dell’inode

 • Operatore time (ritorna il tempo corrente):

$a=time - 20*60; # 20 minuti da orautime($a, $a, “nome_file1”, “nome_file2”, …); # i file indicati sono aggiornati a 20 minuti fa

Gestione processi in PERL

• Creazione processi con istruzioni fork/exec/wait: crea un clone del processo corrente. Fork ritorna 0 al figlio !0 al padre

If(fork){ Print “sono il padre”; }else{ print “sono il figlio”; exec(“date”); }

unless (fork) {exec(“date”); # sono qui perche’ fork ritorna 0

}wait;

 • Exi : uscita da un processo • Variabile d’ambiente: l’ambiente viene messo nell’array associativo %ENV

forach $a (sort keys %ENV){ # elenca le variabili d’ambientePrint “$a = $ENV{$a}\n”;

} $oldpath=$ENV(“PATH”); # modifica le variabili d’ambiente$ENV(“PATH”) = “ bla nuovo PATH bla”;

…$ENV(“PATH”) = $oldpath;

Espressioni regolari in PERL• ER: espressione costruita secondo una sintassi che ci permette di descrivere

una stringa• Pattern matching: verifica se una stringa o una sua sottostringa corrisponde ad

una ER.• In PERL con variabile implicita: m/ER/ (m può essere omesso.)• Esempio: funzione grep #!/usr/local/bin/perl

while(<>){ if(/er/){ Print”$_”; } }

• In PERL con variabile esplicita: operatore di match =~ Applica una espressione regolare ad una variabile che non sia $_

$a=”blablabla”;

if($a =~ /^b/){

print $a #stampa $a se la stringa inizia con b

}

  print “continuare? (S/s o N/n)”

if(<STDIN> =~ /^[Ss]/) {

print “hai risposto si!”

}

 

• Caratteri maiuscoli o minuscoli (ignora il case) con l’opzione i: /er/i

Espressioni regolari in PERL

• Esempio: stampare tutte le righe di un file che contengono una stringa fornita dall’utente.

#!/user/local/bin/perl

print “dare il nome del file: “;

$nome=<STDIN>;

chop/$nome);

-e $nome || die “file non esistente\n”;

-T $nome || die “file non e’ di testo\n”;

print “dare la stringa: “;

$str = <STDIN>;

chop($str);

open(f, “< $nome”) || “impossibile aprire il file\n”;

while ($r = <f>){

$r = ~/$str/ && print$r;

}

close(f):

Espressioni regolari in PERL• Una ER puo’ contenere variabili. Le variabili vengono espanse prima di considerare

eventuali caratteri speciali.

$a=”abc def ghi”;print “scrivi una parola di 3 caratteri”;$b=<STDIN>;chop($b);if($a =~ /z$b/){

print “trovato z$b in $a\n”;} else {

print “non trovato\n”;}

 • Sostituzione in PERL: s/old-ER/new-ER/

$_=”abc def ghi”;s/abc/xyz/g; #tutte le stringhe /abc/ vengono

sostituite 

$a=”abc def ghi”; #caso in cui ho una variabile esplicita

$a =~ s/abc/xyz/g; 

Espressioni regolari in PERL

• Operatore split(espressione regolare , stringa) : ritorna un vettore formato dalle parti della stringa che NON corrispondono alla ER

$a=”a:b:c:d”;

@b=split(/:/, $a);# @b contiene (a, b, c ,d)

@b=split(/er/);# in questo caso la stringa e’ $_

 • Operatore join($glue, @lista): riunisce gli elementi della lista attraverso

$glue in una stringa

$a = join(“:”, @b); #ricostruisce la stringa precedente

Funzioni in PERL• Il programmatore puo’ definire delle subroutine nella forma

sub nome{ #i parametri passati si trovano in @_, quindi $_[0], $_[1] …

istruzioni;return (valore);

}

• Chiamata della subroutine: &nome• Visibilità:

– Le variabili locali definite con local(lista_variabili) le variabili sono visibili nella subroutine e nelle subroutine chiamate

– Le variabili definite con my(lista variabili) sono visibili solo dove sono dichiarate.

• Le funzioni sono ricorsive:#!/user/local/bin/perl#script fattoriale.plSub fattoriale{

local($n) = shift(@_);($n==1) && return (1);return($n * &fattoriale($n-1);

}$n=<STDIN>;$r=&fattoriale($n);Print “fattoriale di $n = $r\n”;

Funzioni in PERL• Uno script PERL può richiamare programmi esterni o comandi Unix.

– Mediante apici inversi@r=`cat $file | grep $s | sort`

– Mediante system o execsystem() lo script aspetta la terminazione del programma esternosystem(“comando di shell”) && die;system(“comando1; comando2 > filek&”) && die;system(“comando > file”) && die;

exec() lo script termina e continua il programma esterno

– Mediante apertura di canali di pipe:open(OUT, “| more”) || die “errore\n”;foreach $r(@array) {

print OUT $r;}close(OUT);

……open(HANDLE, “who|”); #lettura@a = <HANDLE>; close(HANDLE);

 ........open(HANDLE, “|cat”); #scritturaprint(HANDLE,”stringa da stampare con cat”); close(HANDLE);

Funzioni in PERL• Attenzione: oltre a return, esiste un altro metodo di passaggio parametri: il/i

valori di ritorno sono gli ultimi valutati!

• Lista di tutti gli elementi maggiori di A:  sub somma{

local($n,@a); ($n,@a) = @_; local(@b);for($i=1;$i<$n; $i++){

if($a[$i]> A)push(@b, $a[$i]);

}@b;

}@a=&somma(100,@lista);

 • Lista di tutti gli elementi maggiori di A:

sub somma{local($n,@a); ($n,@a) = @_; local(@b);foreach $_ (@a){

if($_ > A)push(@b, $_);

}@b;

}@a=&somma(100,@lista);

Seconda parte.Esempi di programmazione

#!/usr/local/bin/perl

#

# legge dallo standard input delle parole e conta le occorrenze

@words = <STDIN>; # leggi le parole dallo standard in

foreach $word (@words) {

chop($word); # rimuove il newline

$count{$word}++ ;

}

foreach $word (keys %count) {

print "$word appare $count{$word} volte\n";

}

#!/usr/local/bin/perl# conta le occorrenze dallo standard inwhile(<STDIN>){ chop; $a{$_}++; }foreach $b (keys(%a)){ print "La parola $b appare $a{$b} volte\n"};

#!/usr/local/bin/perl# legge parole da filewhile(<>){ chop; $a{$_}++; }foreach $b (keys(%a)){ print "La parola $b \t appare $a{$b}\t volte\n"};

#!/usr/local/bin/perl#Legge una lista di stringhe e le stampa con formato desideratoprint "Field width: ";chop($width = <STDIN>);print "List of strings:\n";chop(@strings = <STDIN>);foreach (@strings) { printf "%${width}s\n", $_;}

#!/usr/local/bin/perl

#

while (<STDIN>) {

($user, $pass, $uid, $gid, $gcos) = split(/:/);

($real) = split(/,/, $gcos);

($first) = split(/\s+/, $real);

$seen{$first}++;

}

foreach (keys %seen) {

if ($seen{$_} > 1) {

print "$_ visto $seen{$_} volte\n";

}

}

#!/usr/local/bin/perl# questo script sostituisce stringhe in un file#print "Input file name: ";chop($infilename = <STDIN>);print "Output file name: ";chop($outfilename = <STDIN>);print “Stringa da cercare: ";chop($search = <STDIN>);print “Stringa da rimpiazzare: ";chop($replace = <STDIN>);open(IN,$infilename) || die “non posso aprire $infilename in lettura";## test opzionale per sovrascrivere...die “non sovrascrivo $outfilename" if -e $outfilename;open(OUT,">$outfilename") || die “non posso creare $outfilename";while (<IN>) { # leggi una linea dal file $a in $_

s/$search/$replace/g; # cambia le lineeprint OUT $_; # scrivi quella linea nel file $b

}close(IN);close(OUT);

#!/usr/local/bin/perl

#

while (<>) {

chop;

($age) = (stat("$_"))[8];

# $age= -M; # l'operatore -M ritorna la data dell'ultima modifica

print "file $_ age $age\n";

if ($newest_age < $age) {

$newest_name = $_;

$newest_age = $age;

}

}

print “Il file piu’ recente e’$newest_name ",

“e ha $newest_age giorni.\n";

#!/usr/local/bin/perl#print “quale directory? ";chop($newdir = <STDIN>);chdir($newdir) ||

die “Non posso spostarmi in $newdir";opendir(DOT,".") || die “non posso aprire la directory";foreach (sort readdir(DOT)) { print "$_\n"; }closedir(DOT);

#!/usr/local/bin/perl@a = <*>;foreach $nomefile(sort(@a)){ print "$nomefile\n";}

#!/usr/local/bin/perl#open(PW,"/etc/passwd");while (<PW>) { chop; ($user,$pw,$uid,$gid,$gcos) = split(/:/); ($real) = split(/,/, $gcos); $real{$user} = $real;}close(PW);

open(WHO,"who|") || die “non posso aprire la pipe";while (<WHO>) { ($login, $rest) = /^(\S+)\s+(.*)/; $login = $real{$login} if $real{$login}; printf "%-30s %s\n",$login,$rest;}

#!/usr/local/bin/perl

&init;

print “Nome utente? "; $name = <STDIN>; chop($name);

print "Password? "; $pass = <STDIN>; chop($pass);

while ($pass ne $words{$name}) {

print "password errata! riprova: "; $pass=<STDIN>; chop($pass);

}

print "ok\n";

exit;

sub init{

open(WORDLIST, "wordlist");

while($name=<WORDLIST>){

chop($name); $word= <WORDLIST>; chop($word); $words{$name} = $word;

}

close(WORDLIST);

}

#!/usr/local/bin/perlsub test{if ($#ARGV<0) {print "Specifica il file... \n";exit; }}&test;print "N. parametri: ", $#ARGV+1," Pid:$$ \n";$i=1;foreach $a (@ARGV) {

print "parametro n. $i:$a \n";$i++;

}open (IN,"$ARGV[0]");print "Contenuto del file:\n";while ($a=<IN>) {

print $a;};

close (IN);

#!/usr/local/bin/perlsub test{if ($#ARGV<0) {print "Manca il nome del file. \n";exit; }}&test;print "N. parametri: ",$#ARGV+1," Pid:$$ \n";

for ($i=0;$i<=$#ARGV;$i++) {print "parametro n. ",$i+1,": $ARGV[$i] \n";

}

open (IN,"$ARGV[0]");print "Contenuto del file:\n";while (@a=<IN>) {

foreach $b(@a) {print $b; }

};

close (IN);

#!/usr/local/bin/perlsub test{if ($#ARGV<0) {print "Inserisci il nome del file... \n";exit; }}

&test;open (IN,"$ARGV[0]");while ($a=<IN>) {

chop($a);@b=split(/,?\s+/,$a);foreach $c (@b) {

$occor{$c}++;};

};close (IN);

foreach $a (keys (%occor)) {print "Parola [$a] -> occorrenze: $occor{$a}\n";};

#!/usr/local/bin/perl

sub test{if ($#ARGV<0) {print "Inserire il nome del file. \n";exit; }}

&test;

while (<>) {chop;@b=split(/,?\s+/);foreach $c (@b) {

$occor{$c}++;};

};

foreach $a (keys (%occor)) {print "Parola [$a] -> occorrenze: $occor{$a}\n";};

#!/usr/local/bin/perlsub test{if ($#ARGV<0) {print "Inserire il nome del file... \n";exit; }}&test;open (IN,"$ARGV[0]");while (@a=<IN>) {

foreach $b (@a) {chop($b);@c=split(/,?\s+/,$b);foreach $d (@c) {

$occor{$d}++;};

};};

close (IN);foreach $a (keys (%occor)) {

print "Parola [$a] -> occorrenze: $occor{$a}\n";};

#!/usr/local/bin/perlsub test{ if($#ARGV<2){ print"Errore! \n";

print"Sintassi : perlex3 file vecchia_stringa nuova_stringa\n";

exit; }}&test;unless(open(FILE,"$ARGV[0]")){ print"errore nell'apertura del file\n"; exit;}@testo=<FILE>;close(FILE);$i=0;@temp;foreach $riga(@testo){

$riga =~ s/$ARGV[1]/$ARGV[2]/g;$temp[$i]=$riga;$i++;

}print "Risultato:\n"; print @temp; print "\n";

#!/usr/local/bin/perlprint "Nome file di input: ";$file = <STDIN>;chop($file);-e $file || die "Il file non esiste!\n\n";-T $file || die "Il file non e' un file di testo!\n\n";print "Stringa da cercare: ";$stringa = <STDIN>;chop($stringa);print "Stringa da sostituire: ";$sost = <STDIN>;chop($sost);open (IN, "< $file") || die "Impossibile aprire $file.\n\n";$i=0;@temp;while ($r = <IN>) { $r =~ s/$stringa/$sost/g; $temp[$i]=$r; $i++;}close(IN);print "Risultato: \n";print "@temp";

#!/usr/local/bin/perlsub test{ if($#ARGV<1){ print"Mancano parametri\n"; exit; }}&test;unless(open(FILE,"$ARGV[0]")){ print"Errore in apertura di $ARGV[0]\n"; exit;}@testo=<FILE>;close(FILE);$i=0;foreach $riga(@testo){

chop($riga);@campo=split(/\s+/,$riga);if($campo[0]=~/$ARGV[1]/) { $i++ };

}print "Righe di $ARGV[0] contenenti nel primo campo $ARGV[1] :

$i\n";

#!/usr/local/bin/perlsub load {

open (F,"PASS");while (<F>) {

chop;@a = split(/\s/);$PASS{$a[1]} = $a[0];

}}&load; print "username: ";$user = <STDIN>;chop ($user);print "chiave: ";$chiave = <STDIN>;chop ($chiave);# cancello eco?????????????if ($PASS{$chiave} eq $user) {

print "\nChiave esatta!";print "\nOra puoi accedere alle risorse protette!\n";}

else {print "\nSpiacente: non puoi entrare!\n"};

#!/usr/local/bin/perl@d = <*>;foreach $nomefile(@d){ $size = (stat($nomefile))[7]; $dim{$size} = $nomefile;#print "$nomefile -> $size\n";}@s = sort(keys(%dim));$numtot = @s;$medium=int(${numtot}/2);$medio = @s[$medium];$grande = pop(@s);$piccolo = shift(@s);print "\nIl file piu' grande e': $dim{$grande}

($grande bytes)";print "\nIl file piu' piccolo e': $dim{$piccolo}

($piccolo bytes)";print "\nIl file medio e': $dim{$medio} ($medio bytes)\

n";

#!/usr/local/bin/perl

@d = <*>;print "\n # = 100 bytes\n";

foreach $nomefile(@d){ @a = stat ($nomefile); $size = $a[7]; $quad = $size/100; printf("%-15s %+10s ", $nomefile, $size); for($i=0;$i<$quad;$i++) {

printf( "#"); } printf("\n");}

#!/usr/bin/perl#argomento: nomefile -opzione

sub test{ if ($#ARGV < 1) {print "errore\n"; exit 1;} } &test;foreach $a(@ARGV){print "parametri: $a\n";}print "Il PID del processo e' $$\n";

open(FILE, "$ARGV[0]");while ($a=<FILE>) { chop ($a) ; print "$a\n"; }close(FILE);

#!/usr/bin/perl# argomento: nomefile -opzione

sub test{ if ($#ARGV < 1) {print "errore\n"; exit 1;} } &test;for ($i=0;$i<=$#ARGV;$i++){print "parametri: $ARGV[$i]\

n";}print "Il PID del processo e' $$\n";

open(FILE, "$ARGV[0]");while ($a=<FILE>) { chop ($a) ; print "$a\n"; }close(FILE);

#!/usr/bin/perl

# argomento: nomefile -opzione

sub test{

if ($#ARGV < 1) {print "errore\n";

exit 1;}

}

&test;

foreach $a(@ARGV){print "parametri: $a\n";}

print "Il PID del processo e' $$\n";

open(FILE, "$ARGV[0]");

@a=<FILE>;

foreach $b(@a) {

chop ($b) ;

print "$b\n";

}

close(FILE);

#!/usr/bin/perl#argomento: nomefile

sub test{ if ($#ARGV !=0) {

print "errore\n"; exit 1;} } &test;print "Nome File: $ARGV[0]\n";open(FILE, "$ARGV[0]");while ($a=<FILE>) { chop ($a) ; @b=split(/,?\s+/,$a); foreach $c(@b){ $occor{$c}++; }

}foreach $c(keys %occor){ print "$c $occor{$c}\n"; }close(FILE);

#!/usr/bin/perl# argomento: nomefile

sub test{ if ($#ARGV !=0) {print "errore\n"; exit 1;} } &test;print "Nome File: $ARGV[0]\n";open("$ARGV[0]");while (<>) { chop ; @b=split(/,?\s+/); foreach $c(@b){ $occor{$c}++; } }foreach $c(keys %occor){ print "$c $occor{$c}\n"; }close(FILE);

#!/usr/bin/perl# argomento: nomefilesub test{ if ($#ARGV !=0) {print "errore\n"; exit 1;} }&test;print "Nome File: $ARGV[0]\n";open(FILE, "$ARGV[0]");@a=<FILE>;foreach $d(@a){ chop ($d) ; @b=split(/,?\s+/,$d); foreach $c(@b){ $occor{$c}++; }

}foreach $c(keys %occor){ print "$c $occor{$c}\n"; }close(FILE);

#!/usr/bin/perl#argomento: nomefile "er_old" "er_new"

sub test{ if ($#ARGV <2) {print "errore\n"; exit 1;} } &test;print "Nome File: $ARGV[0]\n";open(IN,"$ARGV[0]");open(OUT, ">$ARGV[0]new");while (<IN>) { s/$er_old/$er_new/g; print OUT $_; }close(IN); close(OUT);

#!/usr/bin/perl#print "Nome File Input:\n";chop ($infile=<STDIN>);print "Nome file Output:\n";chop ($outfile=<STDIN>);print "Espressione Regolare da sostituire:\n";chop ($er_old=<STDIN>);print "Espressione Regolare sostituta:\n";chop ($er_new=<STDIN>);

open (IN, $infile) || die "Non posso aprire il File $infile\n";open (OUT, ">$outfile") || die "Non posso creare il File $outfile\n";while (<IN>){ s/$er_old/$er_new/g; print OUT $_; }close(IN); close(OUT);

#!/usr/bin/perl#argomenti: nomefile "separatore_campi" "primo_campo"

sub test{ if ($#ARGV < 2) {print "errore\n"; exit 1;} }&test;print "nome file: $ARGV[0]\n";print "numero di righe in cui il primo campo è $ARGV[2] :\n";open (FILE, $ARGV[0]) || die "Non posso aprire il file\n";$i=0;while (<FILE>){ chop; @b=split(/$ARGV[1]/); if ($b[0] eq $ARGV[2]){ $i=$i+1} }print "$i\n";

#!/usr/bin/perl#

open (F, "passwd");while ($l=<F>) { chop($l); @a=split(/\s+/,"$l"); $pass{$a[1]}=$a[0]; } print "User Name:\n";chop($user=<STDIN>);print "Password:\n";chop($p=<STDIN>);

if ($pass{$p} eq $user) { print "Utente autorizzato\n"; #lista istruzioni }

else { print "Utente non autorizzato\n"; }

#!/usr/bin/perl

#

#elenca in ordine alfabetico i file regolari contenuti nella directory

@a=<*>;

@a=sort(@a);

foreach $b(@a){ if ( -f "$b"){ print "$b\n"}

}

#!/usr/local/bin/perl$i=0;while ($b=<*>){ if ( -f "$b" ){ @a=stat($b); $elenco{$b}=$a[7]; $dim[$i]=$a[7]; $i++; } }@dim=sort {$a<=>$b} @dim; $m=($#dim/2);foreach $b(keys(%elenco)){ if($elenco{$b}==$dim[-1]) {push(@max,$b)} if($elenco{$b}==$dim[0]) {push(@min,$b)} if($elenco{$b}==$dim[$m]) {push(@med,$b)} }if ($#max==0) { print "Il File piu'grande e': $max[0] $dim[-1] bytes\n"} else { print "I Files piu' grandi sono :\n"; foreach $b(@max){ print "$b $dim[-1] bytes\n"} }if ($#med==0) { print "Il File mediano e': $med[0] $dim[$m] bytes\n"} else{ print "I Files mediani sono :\n"; foreach $b(@med){ print "$b $dim[$m] bytes\n"} }if ($#min==0){print "Il File piu' piccolo e': $min[0] $dim[0] bytes\n"} else{ print "I Files piu' piccoli sono :\n"; foreach $b(@min){ print "$b $dim[0] bytes\n"} }

#!/usr/bin/perl

#visualizza un istogramma delle dimensioni dei file regolari

$i=0;

$max=0;

while ($b=<*>) { if ( -f "$b"){ @a=stat($b);

$size=$a[7];

$nomi[$i]=$b;

$dim[$i]=$size;

$i=$i+1;

if($size>$max){ $max=$size }

}

}

$scala=($max/60);

print "ISTOGRAMMA DIMENSIONE FILES\n";

print "Ogni \"o\" corrisponde a $scala bytes\n";

$i=0;

foreach $n(@nomi){ $simboli[$i]=("o"x($dim[$i]/$scala));

$spazio="-"x(15-length($n));

print "$n $spazio |$simboli[$i]\n";

$i=$i+1;

}

Terza parte.Argomenti avanzati.

• Moduli e packages

• Oop

• Processi e IPC

• Socket

Moduli

I moduli sono scritti per portare a termine dei compiti che non sono implementati dalle funzioni integrate del PERL o che potrebbero essere implementati in modo diverso (migliore).

I moduli sono composti da package.

Finalità:

• produzione di codice riutilizzabile

• utilizzo di moduli standard (o core) distribuiti con PERL

Spazi dei nomiSpazi dei nomiMemorizza nomi di: variabili, subroutine, filehandle, formati.Lo spazio dei nomi predefinito dei programmi è main.

In PERL uno spazio dei nomi contenuto in un package.

Da un package è possibile fare riferimento alle variabili di un altro, qualificandole con

il nome del pacchetto.

$Package::varname

$::var$main::var

Moduli

Per utilizzare i moduli si usano le parola chiave require o use.

require Module;

use Module;

use Module qw(const1 const2 func1);

use carica il modulo in fase di compilazione

require richiede di qualificare in modo esplicito le sue routine con il nome del pacchetto

OOP

Definizione di classi e oggettiUn modulo descrive una classe e deve contenere una subroutine specialeper la creazione di un oggetto (costruttore).

Il costruttore crea un nuovo oggetto e restituisce un riferimento.

All’interno dei programmi, il riferimento è usato per manipolare l’oggetto.

I metodi sono delle subroutine che si aspettano come primo argomento un riferimento a un oggetto:

sub in_class { my $class = shift; #riferimento a un oggetto my ($this, $that) = @_; #parametri}

OOP

I metodi possono essere invocati nei seguenti modi:

$PackageName->constructor(args)->method_name(args);

$object = PackageName->Constructor(args);

$object->method_name(args);

I costruttori degli oggetti si invocano con new.

Un oggetto è distrutto quando scompare anche il suo ultimo riferimento.

Creazione Processi

Nel corso dell’esecuzione di un processo, ci sono vari modi per lanciare

in esecuzione un altro processo:

exec lancia l’esecuzione di un nuovo processo e termina definitivamente

l’esecuzione del programma chiamante

system avvia l’esecuzione di un nuovo processo e riprende

l’esecuzione del processo originario solo al termine dell’esecuzione

del nuovo processo

fork genera un clone del processo padre

Creazione Processi

#!/usr/bin/perl -w# programma che esegue la chiamata di sistema fork

print "Nome: exfork1\n";$pid=fork();if ($pid) { # $pid=0, sono il PADRE print "p->\$pid=$pid\n"; print "Sono il padre!\n"; exit(0);} else { # $pid=0, sono il FIGLIO print "c->\$pid=$pid\n"; print "Sono il figlio!\n"; exit(0);}

Sincronizzazione

La sincronizzazione tra processi può essere fatta in vari modi:

• invio di segnali

• semafori

• pipe e fifo

• scambio di messaggi

• memoria condivisa

• socket

In Linux sono implementate le chiamate di sistema

IPC System V (standard UNIX).

Semafori

Principio base: si controlla lo stato di una variabile (semaforo) che viene aggiornato con operazioni atomiche (non interrompibili).In realtà i semafori delle IPC System V sono dei semafori con contatore.

semget definisce un semaforo e ne restituisce l’ID

semop operazione sul semaforo OCCUPAZIONE RISORSA

se la risorsa libera, e incremento del contatore semaforo (pone il semaforo a ROSSO)

RILASCIO RISORSAdecremento contatore semaforo (pone il Semaforo a VERDE)

semctl controllo semaforo

Semafori

Creazione del semaforo

use IPC::SysV qw(IPC_CREAT);$IPC_KEY = 1234;$id = semget($IPC_KEY, 10, 0666 | IPC_CREAT ) || die "$!";print "sem key $id\n";# crea il semaforo e visualizza l’id a schermo

Utilizzo di semaforo già creato

$IPC_KEY = 1234;$id = semget($IPC_KEY, 0 , 0 );die if !defined($id);

Semafori

Blocco del semaforo

# aspetta che il semaforo diventi zero

$semop = 0;

$opstring1 = pack("s!s!s!", $semnum, $semop, $semflag);

# ...e incrementa il contatore del semaforo

$semop = 1;

$opstring2 = pack("s!s!s!", $semnum, $semop, $semflag);

$opstring = $opstring1 . $opstring2;

semop($id,$opstring) || die "$!";

Semafori

Rilascio del semaforo

$semnum = 0;

$semflag = 0;

# Decrementa il contatore del semaforo

$semop = -1;

$opstring = pack("s!s!s!", $semnum, $semop, $semflag);

semop($id,$opstring) || die "$!";

Memoria Condivisa

è la tecnica di comunicazione tra processi più veloce, viene predisposta dal sistema operativo una zona di memoria che puòessere utilizzata da tutti i processi che lo richiedono con la chiamata shmget().

Gli accessi ai dati devono essere regolati, in modo che più processinon accedano contemporaneamente alla stessa zona dati, causandoproblemi di consistenza dei dati (ad es. più processi che scrivonocontemporaneamente sulla zona dati) utilizzando per es. semafori.

ID=shmget(KEY,SIZE,FLAGS) definisce una zona di memoria condivisashmread(ID, VAR, POS, SIZE) legge dal segmento ID di memoria

condivisa, dalla posizione POS per SIZE byte. Azioni: attach, legge, detach

shmwrite scrive sulla memoria condivisashmctl controllo memoria condivisa

#!/usr/bin/perl –w# shared memoryuse IPC::SysV qw(IPC_PRIVATE IPC_RMID S_IRWXU);

$size = 2000;$id = shmget(IPC_PRIVATE, $size, S_IRWXU) || die "$!";print "shm key $id\n";

$message = "Messaggio #1";shmwrite($id, $messaggio, 0, 60) || die "$!";print “scritto: '$messaggio'\n";

shmread($id, $buff, 0, 60) || die "$!";print “letto : '$buff'\n";

# the buffer of shmread is zero-character end-padded.substr($buff, index($buff, "\0")) = '';print "un" unless $buff eq $message;print "swell\n";

print “cancello shm $id\n";shmctl($id, IPC_RMID, 0) || die "$!";

Pack - Unpack

• Pack: codifica secondo il formato richiesto numeri o stringhe.– Es.: formato ‘C’ un char, ‘CCCC’ 4 char,

‘l’ intero con segno di 4 byte, ‘ll’ 8 byte– $a=pack(“CCCC”,140,105,50,61);

• Unpack: decodifica stringhe secondo il formato richiesto– Es: ($a,$b)=unpack(“ll”, “abcdefgh”);

Scambio di messaggiSimile alle FIFO (pipe con nome), solo i dati possono essere dei record

contenenti variabili di tipi diversi.

msgget(KEY,FLAG) definisce una coda di messaggi e ne restituisce l’ID

msgrcv(ID,VAR,SIZE,TYPE,FLAGS) riceve un messaggio dalla coda ID in VAR con lunghezza massima SIZE. VAR

inizia con il tipo di messaggio ($type,$msg)=unpack(‘ll’,$rcv);

msgsnd(ID,MSG,FLAGS) manda il messaggio MSG alla coda ID. MSG deve iniziare con un long che rappresenta il tipo di messaggio

pack(“l”,$type);

msgctl(ID,CMD,ARG) controllo coda di messaggi

Tipo di messaggio: 0 primo messaggio sulla lista

>0 primo messaggio di quel tipo

<0 primo messaggio con il minimo tipo

Messaggi

use IPC::SysV qw(IPC_PRIVATE IPC_RMID IPC_CREAT S_IRWXU);

my $id = msgget(IPC_PRIVATE, IPC_CREAT | S_IRWXU);

my $sent = "message";

my $type = 1234;

my $rcvd;

my $type_rcvd;

Messaggi

if (defined $id) { if (msgsnd($id, pack("l", $type_sent), $sent, 0)) { if (msgrcv($id, $rcvd, 60, 0, 0)) {

($type_rcvd, $rcvd) = unpack("ll", $rcvd); if ($rcvd eq $sent) { print "okay\n"; }

else { print "not okay\n"; } } else { die "# msgrcv failed\n"; } }

else { die "# msgsnd failed\n"; }

msgctl($id, IPC_RMID, 0) || die "msgctl failed\n"; } else { die "# msgget failed\n"; }

Socket in Perl

Programmazione Client-Server

Si utilizzano i socket di Internet per far comunicare due processi

Server ascolta sul socket in attesa di un collegamento

da parte di un client

Client chiama il server, il server risponde e

i processi possono comunicare

Socket in Perl

Inizializzazione di un socket (CLIENT e SERVER)Sia il client che il server usano la chiamata socket per creare un socket e associarlo a un filehandle.

use Socket;

socket(SH, PF_INET, SOCK_STREAM, getprotobyname(’tcp’)) || die $!;

socket(SH2, PF_INET, SOCK_DGRAM, getprotobyname(’udp’)) || die $!;

I socket con un indirizzo del dominio Unix usano PF_UNIX anziché PF_INET.

Socket in Perl

CLIENT

Dal lato client, dopo l’inizializzazione (con la chiamata di sistema socket)

bisogna realizzare la connessione con un server su una porta e un

host particolare, usando la chiamata connect.

Una volta stabilita la connessione, possiamo leggere dal socket o scrivere

sul socket.

Al termine il socket va chiuso con shutdown o close.

Socket in Perl

my $dest = sockaddr_in(80, inet_aton(’www.units.it’));

connect (SH, $dest) || die $!;

$data="Ciao";

send(FH, $data);

select(FH);

print "$data";

recv(FH, $buffer);

$input=<FH>;

close(FH);

Socket in Perl

Dopo aver creato un socket con socket, è necessario che

un’applicazione server passi attraverso le seguenti operazioni

per ricevere la connessione di rete:

1) associa il socket a un numero di porta e indirizzo della macchina;

2) mettersi in ascolto di connessioni di client entranti sulla porta;

3) accettare una richiesta di client e assegnare la connessione al filehandle specificato.

Socket in Perl

my $proto=getprotobyname(’tcp’);

socket(FH, PF_INET, SOCK_STREAM, $proto) || die $!;

my $sin = sockaddr_in(80, INADDR_ANY);

bind(FH, $sin) || die $!;

listen(FH, $length);

accept(NEW_FH, FH) || die $!;

# Ora il server comunica col client usando NEW_FH

#!/usr/bin/perl# file server.pl#use Socket;use Carp;#$EOL = "\015\012";sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }my $port = shift || 2345;my $proto = getprotobyname('tcp');$port = $1 if $port =~ /(\d+)/;socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) || die ;bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";listen(Server,SOMAXCONN) || die "listen: $!";logmsg "server avviato alla porta $port";my $paddr;$SIG{CHLD} = \&REAPER;for ( ; $paddr = accept(Client,Server); close Client) { my($port,$iaddr) = sockaddr_in($paddr); my $name = gethostbyaddr($iaddr,AF_INET); logmsg "Connessione da $name [", inet_ntoa($iaddr), "], porta

$port"; print Client "Salve $name, sono le ", scalar localtime, "\n";}

#!/usr/bin/perl –w# file client.pl#use Socket;my ($remote,$port, $iaddr, $paddr, $proto, $line);$remote = shift || 'localhost';$port = shift || 2345; # random portif ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }die "No port" unless $port;$iaddr = inet_aton($remote) || die "no host: $remote";$paddr = sockaddr_in($port, $iaddr);$proto = getprotobyname('tcp');socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket:$!";connect(SOCK, $paddr) || die "connect: $!";while (defined($line = <SOCK>)) { print $line;}close (SOCK) || die "close: $!";exit;

#!/usr/bin/perl# file webserver.pl#use Socket;my ($port, $proto, $paddr, $name, $iaddr);$port = 80;$proto = getprotobyname('tcp');socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, 1) || die "setsockopt: $!";bind(SOCK, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";listen(SOCK, SOMAXCONN) || die "listen: $!";while(1) { $paddr = accept(CLIENT, SOCK); ($port, $iaddr) = sockaddr_in($paddr); $name = gethostbyaddr($iaddr, AF_INET); print STDERR "Chiamata da [", inet_ntoa($iaddr), "]\n"; $messaggio = <CLIENT>; ($richiesta, $filename) = split(/\s+/, $messaggio); if ($richiesta =~ /^GET/) { open(INP, $filename) || print CLIENT "Errore\n"; while($line = <INP>) { print CLIENT $line; } } close(CLIENT);}

#!/usr/bin/perl –w# file: webclient.pluse Socket;my ($remote, $port, $proto, $iaddr, $paddr, $line, $richiesta, $len,

$written);if ($#ARGV != 1) { print STDERR "USO: $0 host file\n"; exit(1);}$remote = $ARGV[0];$port = "www"; # porta standard per il WWWif ($port =~ /\D/) { $port = getservbyname($port, 'tcp'); } die

"No port" unless $port;$iaddr = inet_aton($remote) or die "no host: $remote\n";$paddr = sockaddr_in($port, $iaddr);$proto = getprotobyname('tcp');socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket $!";connect(SOCK, $paddr) || die "connect: $!";$richiesta = "GET /" . $ARGV[1] . "\n";$written = syswrite(SOCK, $richiesta, length($richiesta));die "System write error: $!\n“ unless defined $written; while($line = <SOCK>) { print $line; } close(SOCK) or die "close: $!";exit;

Quarta parte.

Elenco delle funzioni principali.

• Elaborazione di array• pop, push, shift, splice, unshift

• Elaborazione di liste• grep, join, map, qw//, reverse, sort, unpack

• Elaborazione di hash• delete, each, exists, keys, values

• Input e output• binmode, close, closedir, dbmclose, dbmopen, die,• eof, fileno, flock, format, getc, print, printf,• read, readdir, rewinddir, seek, seekdir, select,• syscall, sysread, sysseek, syswrite, tell, relldir,• truncate, warn, write

• Dati a lunghezza fissa e record• pack, read, syscall, sysread, syswrite, unpack, vec

• Filehandle, file e directory• chdir,chmod, chown, chroot, fcntl, glob,ioctl, link,• lstat,mkdir, open,opendir, readlink, rename, rmdir,• stat, symlink, sysopen, umask, unlink, utime

• Controllo del flusso di programma• caller, continue, die, do, dump, eval, exit, goto,• last, next, redo, return, sub, wantarray

• Visibilità• caller, import, local, my, package, use

• Varie• defined, dump, eval, formline, local, my, prototype,• reset, scalar, undef, wantarray

• Processi e gruppi di processi• alarm, exec, fork, getprrp, getpid, getpriority,• kill, pipe, qx//, setpgrp, setpriority, sleep, system,• times, wait, waitpid

• Moduli di libreria• do, import, no, package, require, use

• Classi e oggetti• bless, dbmclose, dbmopen, package, ref, tie, tied,• untied, use

• Accesso di basso livello ai socket• accept, bind, connect, getpeername, getsockname,• getsockopt, listen, recv, send, setsockopt, shutdown,• socket, socketpair

• Comunicazione interprocesso System V• msgctl, msgget, msgrcv, msgsnd, semctl, semget,• semop, shmctl, shmget, shmread, shmwrite

• Prelievo delle informazioni di utente e di gruppo• endgrent, endhostent, endnetent, endpwent, getgrent,• getgrgid, getgrnam, getlogin, getpwent, getpwnam,• getpwuid, setgrent, setpwent

• Prelievo delle informazioni di rete• endprotoent, endservent, gethostbyaddr, gethostbyname,• gethostent, getnetbyaddr, getnetbyname,• getnetent, getprotobyname, getprotobynumber, getprotoent,• getservbyname, getservbyport, getservent,• sethostent, setetent, setprotoent, setservent

• Data e ora• gmtime, localtime, time, times