Difference between revisions of "Prova pratica 2014.09.25"
Jump to navigation
Jump to search
m |
m (Aggiunte soluzioni di altri studenti) |
||
(2 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
Testo: [http://www.cs.unibo.it/~renzo/so/pratiche/2014.09.25.pdf] | Testo: [http://www.cs.unibo.it/~renzo/so/pratiche/2014.09.25.pdf] | ||
− | Esercizio | + | ==Esercizio 1== |
+ | <source lang ="text"> | ||
+ | Scrivere un programma che preso come parametro un file contenente un elenco di comandi (con I relativi parametri) | ||
+ | li attivi tutti in esecuzione concorrente e rimanga in attesa. Quando il primo termina, vengono terminati (con segnale SIGTERM) tutti gli altri. | ||
+ | (consiglio: puo' essere utile usare la mia libreria s2argv-execs) | ||
+ | esempio: | ||
+ | wta commands | ||
+ | il file commands contiene: | ||
+ | ./ttest 40 | ||
+ | ./ttest 10 | ||
+ | ./ttest 20 | ||
+ | lo script ./ttest contiene: | ||
+ | #!/bin/bash | ||
+ | echo waiting for $1 seconds | ||
+ | sleep $1 | ||
+ | echo done $i | ||
+ | l'ouptut sara': | ||
+ | waiting for 40 seconds | ||
+ | waiting for 10 seconds | ||
+ | waiting for 20 seconds | ||
+ | done 10 | ||
+ | e poi basta perche' gli altri processi verranno terminati. | ||
+ | </source> | ||
+ | ===Soluzione di Stefano Zaniboni=== | ||
+ | <source lang ="c"> | ||
+ | #include <stdio.h> | ||
+ | #include <s2argv.h> | ||
+ | #include <unistd.h> | ||
+ | #include <string.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <error.h> | ||
+ | #include <sys/wait.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <poll.h> | ||
+ | |||
+ | int main(int argc, char *argv[]){ | ||
+ | FILE *stream; | ||
+ | char *line=NULL; | ||
+ | size_t len=0; | ||
+ | ssize_t read; | ||
+ | int i=0; | ||
+ | int status; | ||
+ | pid_t fineFirst; /*memorizzo il pid del primo processo terminato*/ | ||
+ | pid_t all[i]; | ||
+ | int pipefd[2]; | ||
+ | struct pollfd pipe_read_poll; | ||
+ | |||
+ | if(argc!=2){ | ||
+ | fprintf(stderr,"Argomento Mancante!\n"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | stream=fopen(argv[1], "r"); | ||
+ | if(stream == NULL) | ||
+ | exit(EXIT_FAILURE); | ||
+ | |||
+ | /*aprire una pipe, dentro al while dove ho la fork fare poll che aspetta un carattere dalla pipe. Lo mando finito il while*/ | ||
+ | pipe(pipefd); | ||
+ | pipe_read_poll.fd = pipefd[0]; | ||
+ | pipe_read_poll.events = POLLIN; | ||
+ | |||
+ | while((read = getline(&line, &len, stream)) != -1) { | ||
+ | if(fork()==0){ | ||
+ | i++; | ||
+ | char **lines=s2argv(line, NULL); | ||
+ | poll(&pipe_read_poll,1,-1); | ||
+ | execvp(lines[0], lines); | ||
+ | all[i]=getpid(); /**/ | ||
+ | s2argv_free(lines); | ||
+ | perror("execvp fail!"); | ||
+ | exit(1); | ||
+ | } | ||
+ | else | ||
+ | exit(2); | ||
+ | } | ||
+ | |||
+ | /*inviare carattere alla pipe*/ | ||
+ | char buf='g'; | ||
+ | write(pipefd[1], &buf, 1); | ||
+ | fineFirst=wait(&status); | ||
+ | /*kill the rest of process*/ | ||
+ | while(i > 0){ | ||
+ | if(all[i] != fineFirst){ | ||
+ | kill(all[i], SIGTERM); | ||
+ | } | ||
+ | --i; | ||
+ | } | ||
+ | fclose(stream); | ||
+ | exit(0); | ||
+ | } | ||
+ | |||
+ | </source> | ||
+ | |||
+ | ===Soluzione di Blisset=== | ||
+ | <source lang="c"> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <errno.h> | ||
+ | #include <unistd.h> | ||
+ | #include <s2argv.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <signal.h> | ||
+ | |||
+ | #define MAX 20 | ||
+ | |||
+ | int contaRighe (FILE *A){ | ||
+ | char *a; | ||
+ | int i=0; | ||
+ | a= malloc (MAX*sizeof(char)); | ||
+ | |||
+ | if (a==NULL) { | ||
+ | perror ("malloc"); | ||
+ | return -1; | ||
+ | } | ||
+ | |||
+ | while (fgets(a, MAX, A)){ | ||
+ | if (*a==EOF || *a=='\n') break; | ||
+ | i++; | ||
+ | } | ||
+ | |||
+ | return i; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main (int argc, char *argv []){ | ||
+ | int status; | ||
+ | int i=0; | ||
+ | int j=0; | ||
+ | int z=0; /*indice per ampiezza "pid_t ID" e "char *comando"*/ | ||
+ | char *comando[z]; | ||
+ | pid_t ID [z]; /* memorizza i pid di tutti i processi attivati */ | ||
+ | pid_t terminato; /* memorizza il pid del primo processo che termina*/ | ||
+ | |||
+ | FILE *fd = fopen (argv[1], "r"); | ||
+ | |||
+ | if( fd==NULL ) { | ||
+ | perror("Errore in apertura del file"); | ||
+ | return -1; | ||
+ | } | ||
+ | |||
+ | j=contaRighe (fd); /*ritorna il numero di righe del file dato in input*/ | ||
+ | z=j; /* setto gli array con il numero di righe del file contenente i comandi */ | ||
+ | |||
+ | rewind(fd); /*ritorno all'inizio del file*/ | ||
+ | |||
+ | /* riempie "comando[z]" con tutti i comandi presenti nel file passato, i comando sono contati da 1 a z. */ | ||
+ | while (j!=0){ | ||
+ | comando [i] = malloc (MAX*sizeof(char)); | ||
+ | fgets(comando [i], MAX, fd); | ||
+ | i++; | ||
+ | j--; | ||
+ | } | ||
+ | |||
+ | i--; /* diminuisco "i" di uno perchè prima di uscire dall'ultimo ciclo è aumentata di uno, "j" è uguale a 0 */ | ||
+ | |||
+ | /*ESEGUE TUTTI I COMANDI */ | ||
+ | while (i>=0){ | ||
+ | switch (ID[j]=fork()) { | ||
+ | case 0: | ||
+ | execsp(comando[j]); | ||
+ | perror("exec"); | ||
+ | case -1: | ||
+ | perror ("fork"); | ||
+ | return -1; | ||
+ | } | ||
+ | i--; | ||
+ | j++; | ||
+ | } | ||
+ | |||
+ | i=0; /*setto "i" a 0 per il prossimo while */ | ||
+ | |||
+ | terminato=wait(&status); | ||
+ | |||
+ | /* TERMINA TUTTI I PROCESSI */ | ||
+ | while(i<j){ /* "i" strettamente minore di "j" poichè nell'ultimo ciclo del precedente while viene incrementata di uno */ | ||
+ | if (ID[i]!=terminato) { | ||
+ | printf ("Termina processo %d\n",ID[i]); | ||
+ | kill(ID[i], SIGTERM); /* mando segnale di terminazione a tutti i PID che non sono ancora terminati */ | ||
+ | } | ||
+ | else printf ("Processo completato %d\n",ID[i]); | ||
+ | i++; | ||
+ | } | ||
+ | |||
+ | fclose (fd); | ||
+ | return 0; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | --[[User:Blissett|Blissett]] ([[User talk:Blissett|talk]]) 14:12, 11 March 2015 (CET) | ||
+ | ===Soluzione di Luca=== | ||
+ | <source lang="c"> | ||
+ | #include <stdio.h> | ||
+ | #include <unistd.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/wait.h> | ||
+ | #include <s2argv.h> | ||
+ | #include <signal.h> | ||
+ | |||
+ | |||
+ | int main(int argc, char *argv[]){ | ||
+ | char buff[256]; | ||
+ | int num_cmd=0, tmp=0, i=0, pfd[2]; | ||
+ | FILE *file=fopen(argv[1], "r"); | ||
+ | while(fgets(buff, sizeof(buff), file)!=NULL){//ottengo numero comandi | ||
+ | num_cmd++; | ||
+ | } | ||
+ | rewind(file); | ||
+ | char cmd[num_cmd][256]; | ||
+ | int pid[num_cmd]; | ||
+ | pipe(pfd); | ||
+ | |||
+ | for(i=0; i<num_cmd; i++){ | ||
+ | fgets(cmd[i], sizeof(cmd[i]), file); | ||
+ | //printf("Comando %d: %s", i, cmd[i]); | ||
+ | switch(pid[i]=fork()){ | ||
+ | case 0: | ||
+ | close(pfd[0]); | ||
+ | close(pfd[1]); | ||
+ | execsp(cmd[i]); | ||
+ | exit(1); | ||
+ | case -1: exit(1); | ||
+ | } | ||
+ | } | ||
+ | int status; | ||
+ | close(pfd[0]); | ||
+ | close(pfd[1]); | ||
+ | tmp=wait(&status); | ||
+ | for(i=0; i<num_cmd; i++){ | ||
+ | if(tmp==pid[i]) | ||
+ | continue; | ||
+ | kill(pid[i], SIGTERM); | ||
+ | printf("terminato il processo: pid[%d]=%d\n", i, pid[i]); | ||
+ | } | ||
+ | fclose(file); | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | ==Esercizio 2== | ||
+ | ===Soluzione di LeonardoF=== | ||
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
//ESERCIZIO 2 | //ESERCIZIO 2 | ||
Line 13: | Line 253: | ||
#define AOI_LENSTEP 8 | #define AOI_LENSTEP 8 | ||
− | |||
#define BUFFLEN 256 | #define BUFFLEN 256 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ||
− | |||
struct array_of_integers { | struct array_of_integers { | ||
int **integers; | int **integers; | ||
Line 88: | Line 291: | ||
int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||
/*opening and reading the file*/ | /*opening and reading the file*/ | ||
− | |||
char* line = NULL; | char* line = NULL; | ||
size_t lineLength = 0; | size_t lineLength = 0; | ||
ssize_t numberOfCharactersRead; | ssize_t numberOfCharactersRead; | ||
− | + | ||
− | + | ||
FILE* fd1 = fopen(argv[1],"r"); | FILE* fd1 = fopen(argv[1],"r"); | ||
+ | |||
+ | static array_of_integers arrayOfPid; | ||
+ | static array_of_integers arrayOfFd; | ||
+ | int fd; //file descriptor | ||
+ | int i = 0; //iterator | ||
+ | char concat[BUFFLEN]; | ||
while ((numberOfCharactersRead = getline(&line, &lineLength, fd1)) >= 0) { | while ((numberOfCharactersRead = getline(&line, &lineLength, fd1)) >= 0) { | ||
if (line[numberOfCharactersRead - 1] == '\n') | if (line[numberOfCharactersRead - 1] == '\n') | ||
line[numberOfCharactersRead - 1] = 0; | line[numberOfCharactersRead - 1] = 0; | ||
− | + | ||
− | + | /// | |
− | |||
− | |||
− | |||
/*done*/ | /*done*/ | ||
/* opening output files, forking , saving pids and file descriptors*/ | /* opening output files, forking , saving pids and file descriptors*/ | ||
− | + | sprintf(concat,"./temp%d",i); | |
− | + | fd = open(concat,O_RDWR | O_CREAT | O_TRUNC , 0666); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | int pid = fork(); | |
− | + | switch(pid){ | |
− | + | case 0: //children | |
− | + | //children stdio = file fd | |
− | + | dup2(fd,STDOUT_FILENO); | |
− | + | //execution of the command | |
− | + | execsp(line); | |
− | + | exit(-1); // in case of execsp failure | |
− | + | default: //parent | |
− | + | //must save all the pids | |
− | + | array_of_integers_add(&arrayOfPid,pid); | |
− | + | //must save all the fds. ( they will have the same order of the pids); | |
− | + | array_of_integers_add(&arrayOfFd,fd); | |
− | + | ||
− | + | i ++; | |
− | + | break; | |
} | } | ||
} | } | ||
− | + | free(line); | |
− | |||
/*done*/ | /*done*/ | ||
+ | |||
/*waiting first process and killing the others*/ | /*waiting first process and killing the others*/ | ||
− | + | int firstpid; | |
− | + | size_t j; //iterator | |
size_t firstpid_pos; //position of the first pid in the array | size_t firstpid_pos; //position of the first pid in the array | ||
//wait the first process | //wait the first process | ||
− | + | firstpid = wait(NULL); | |
− | + | ||
− | / | + | /*sigterm the other processes iterating the pids vector*/ |
for (j = 0; j < (&arrayOfPid)->currentlength; j++){ | for (j = 0; j < (&arrayOfPid)->currentlength; j++){ | ||
int temp = *((&arrayOfPid)->integers[j]); | int temp = *((&arrayOfPid)->integers[j]); | ||
Line 157: | Line 354: | ||
/*done*/ | /*done*/ | ||
− | + | /*printing the file of the "fisrt pid" process , unlinking the file and closing them*/ | |
− | /* | ||
for (j = 0; j < (&arrayOfFd)->currentlength; j++){ | for (j = 0; j < (&arrayOfFd)->currentlength; j++){ | ||
fd = *((&arrayOfFd)->integers[j]); | fd = *((&arrayOfFd)->integers[j]); | ||
sprintf(concat,"./temp%lu",j); | sprintf(concat,"./temp%lu",j); | ||
+ | |||
if (j == firstpid_pos){ | if (j == firstpid_pos){ | ||
int c; | int c; | ||
Line 169: | Line 366: | ||
FILE *fdp = fdopen(fd,"r"); | FILE *fdp = fdopen(fd,"r"); | ||
− | + | while ((c = getc(fdp)) != EOF) | |
− | + | putchar(c); | |
− | + | } | |
− | |||
− | |||
− | |||
− | |||
− | } | ||
− | |||
//unlink file fd | //unlink file fd | ||
unlink(concat); | unlink(concat); | ||
//close file fd | //close file fd | ||
close(fd); | close(fd); | ||
− | |||
} | } | ||
/*done*/ | /*done*/ | ||
− | |||
return 0; | return 0; | ||
} | } | ||
Line 191: | Line 380: | ||
--[[User:LeonardoF|LeonardoF]] ([[User talk:LeonardoF|talk]]) 11:33, 26 April 2017 (CEST)LeonardoF | --[[User:LeonardoF|LeonardoF]] ([[User talk:LeonardoF|talk]]) 11:33, 26 April 2017 (CEST)LeonardoF | ||
+ | |||
+ | ===Soluzione di Maldus=== | ||
+ | <source lang="c"> | ||
+ | #include <s2argv.h> | ||
+ | #include <poll.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <unistd.h> | ||
+ | #include <stdio.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <signal.h> | ||
+ | |||
+ | int main(int argc, char* argv[]){ | ||
+ | int i=0, status, out; | ||
+ | FILE *fd, *output; | ||
+ | pid_t *idents, winner; | ||
+ | char *line=NULL, *string; | ||
+ | size_t n=1; | ||
+ | int pipefd[2]; | ||
+ | pipe(pipefd); | ||
+ | struct pollfd pipepoll; | ||
+ | pipepoll.fd = pipefd[0]; | ||
+ | pipepoll.events = POLLIN; | ||
+ | if( !(fd = fopen(argv[1], "r"))){ | ||
+ | perror("fopen:"); | ||
+ | exit(1); | ||
+ | } | ||
+ | while( getline(&line, &n, fd) > 0){ | ||
+ | i++; | ||
+ | free(line); | ||
+ | line=NULL; | ||
+ | } | ||
+ | idents = malloc(sizeof(pid_t)*i); | ||
+ | rewind(fd); | ||
+ | i = 0; | ||
+ | while( getline(&line, &n, fd) >0 ){ | ||
+ | switch( idents[i]=fork()){ | ||
+ | case 0: | ||
+ | asprintf( &string, "out%i" ,getpid()); | ||
+ | if( (out=open(string, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR)) <0){ | ||
+ | perror("open"); | ||
+ | exit(1); | ||
+ | } | ||
+ | free(string); | ||
+ | dup2(out, 1); | ||
+ | close(out); | ||
+ | poll(&pipepoll, 1, -1); | ||
+ | execsp(line); | ||
+ | exit(0); | ||
+ | default: | ||
+ | free(line); | ||
+ | line=NULL; | ||
+ | i++; | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | write(pipefd[1], "g", 1); | ||
+ | winner = wait(&status); | ||
+ | i--; | ||
+ | for( ; i >= 0 ; i--){ | ||
+ | if(idents[i]!=winner){ | ||
+ | kill(idents[i], SIGTERM); | ||
+ | asprintf( &string, "out%i", idents[i]); | ||
+ | unlink(string); | ||
+ | free(string); | ||
+ | } | ||
+ | } | ||
+ | asprintf( &string, "out%i" , winner); | ||
+ | if( !(output = fopen(string, "r"))){ | ||
+ | perror("fopen"); | ||
+ | exit(1); | ||
+ | } | ||
+ | while( getline(&line, &n, output)>0){ | ||
+ | printf("%s", line); | ||
+ | free(line); | ||
+ | line=NULL; | ||
+ | } | ||
+ | unlink(string); | ||
+ | fclose(fd); | ||
+ | fclose(output); | ||
+ | return 0 ; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Per stampare solo l'output del processo vincente salvo quello di ciascun processo in un file di testo ( che poi cancello ). Mi viene però da pensare che debba esistere un modo migliore per farlo... | ||
+ | |||
+ | ==Esercizio 3== | ||
+ | <source lang="text"> | ||
+ | Scrivere un programma python o uno scrip bash che faccia un backup storico di un file. | ||
+ | backn file n | ||
+ | deve mantenere n versioni del file specificato. n>2 | ||
+ | Esempio: | ||
+ | backn miofile 10 | ||
+ | se esiste miofile.9 deve essere rinominato in miofile.10 | ||
+ | se esiste miofile 8 deve essere rinominato in miofile 9 | ||
+ | e cosi' via fino a miofile.2, rinominato miofile 3. | ||
+ | ora se miofile.1 ha lo stesso contenuto di miofile.3, miofile diventa un link fisico a miofile.2 | ||
+ | miofile viene copiato in miofile.1 | ||
+ | </source> | ||
+ | |||
+ | === Soluzione di Blissett === | ||
+ | <source lang="bash"> | ||
+ | #! /bin/bash | ||
+ | |||
+ | if [[ $# != 2 || ! -f $1 ]] | ||
+ | then | ||
+ | echo "Usage: $0 file n_backup" | ||
+ | exit -48 | ||
+ | fi | ||
+ | |||
+ | file=$1 | ||
+ | n_backup=$2 | ||
+ | cartella="cartellaBackup" | ||
+ | true=0 | ||
+ | |||
+ | if [[ ! -d $cartella ]] | ||
+ | then | ||
+ | mkdir $cartella | ||
+ | fi | ||
+ | cd ./$cartella | ||
+ | |||
+ | for i in `find ./ -name "$file*" | sort -n -r -t. -k3 | cut -d. -f3` | ||
+ | do | ||
+ | true=1 | ||
+ | tmp=`find ./ -name "$file.$i"` | ||
+ | num=$(($i+1)) | ||
+ | mv $tmp "$file.$num" | ||
+ | if [[ $num -gt n_backup ]] | ||
+ | then | ||
+ | rm "$file.$num" | ||
+ | fi | ||
+ | done | ||
+ | |||
+ | if [[ $true -eq 1 ]] | ||
+ | then | ||
+ | cmp -s "$file.2" "../$file" | ||
+ | if [[ $? -eq 0 ]] | ||
+ | then | ||
+ | echo creo link fisico. | ||
+ | ln "$file.2" "$file.1" | ||
+ | else | ||
+ | cp ../$file ./ | ||
+ | mv $file "$file.1" | ||
+ | fi | ||
+ | else | ||
+ | cp ../$file ./ | ||
+ | mv $file "$file.1" | ||
+ | fi | ||
+ | </source> | ||
+ | --[[User:Blissett|Blissett]] ([[User talk:Blissett|talk]]) 13:14, 11 May 2015 (CEST) | ||
+ | |||
+ | ===Soluzione di Maldus=== | ||
+ | <source lang="python"> | ||
+ | import argparse | ||
+ | import sys | ||
+ | import os | ||
+ | import shutil | ||
+ | import filecmp | ||
+ | |||
+ | def olderVersion( new, old ): | ||
+ | new = new + '.' | ||
+ | l = len(new) | ||
+ | if new in old: | ||
+ | try: | ||
+ | num=int(old[l:]) | ||
+ | if num < args.version and num!=1 : os.rename(old, old[:l]+str(num+1)) | ||
+ | except ValueError: | ||
+ | return | ||
+ | |||
+ | |||
+ | parser = argparse.ArgumentParser(description='backup storico') | ||
+ | parser.add_argument('file', metavar='file', type=str, help='file di cui fare backup') | ||
+ | parser.add_argument('version', metavar='versione', type=int, help='numero di versione') | ||
+ | args = parser.parse_args() | ||
+ | new = args.file | ||
+ | |||
+ | if args.version < 2: | ||
+ | print("la versione deve essere > 2") | ||
+ | sys.exit(1) | ||
+ | |||
+ | entries = [ x for x in os.listdir('.') if os.path.isfile(x)] | ||
+ | if not new in entries: | ||
+ | print("Nessun file con quel nome") | ||
+ | sys.exit(1) | ||
+ | |||
+ | for file in entries: olderVersion( new, file ) | ||
+ | |||
+ | if new+'.2' in entries: | ||
+ | if filecmp.cmp(new+'.3', new+'.1'): os.link(new, new+'.2') | ||
+ | else: os.rename(new+'.1', new+'.2') | ||
+ | elif new+'.1' in entries: os.rename(new+'.1', new+'.2') | ||
+ | |||
+ | shutil.copyfile(new, new+'.1') | ||
+ | </source> |
Latest revision as of 08:35, 10 May 2017
Testo: [1]
Esercizio 1
Scrivere un programma che preso come parametro un file contenente un elenco di comandi (con I relativi parametri)
li attivi tutti in esecuzione concorrente e rimanga in attesa. Quando il primo termina, vengono terminati (con segnale SIGTERM) tutti gli altri.
(consiglio: puo' essere utile usare la mia libreria s2argv-execs)
esempio:
wta commands
il file commands contiene:
./ttest 40
./ttest 10
./ttest 20
lo script ./ttest contiene:
#!/bin/bash
echo waiting for $1 seconds
sleep $1
echo done $i
l'ouptut sara':
waiting for 40 seconds
waiting for 10 seconds
waiting for 20 seconds
done 10
e poi basta perche' gli altri processi verranno terminati.
Soluzione di Stefano Zaniboni
#include <stdio.h>
#include <s2argv.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <error.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <poll.h>
int main(int argc, char *argv[]){
FILE *stream;
char *line=NULL;
size_t len=0;
ssize_t read;
int i=0;
int status;
pid_t fineFirst; /*memorizzo il pid del primo processo terminato*/
pid_t all[i];
int pipefd[2];
struct pollfd pipe_read_poll;
if(argc!=2){
fprintf(stderr,"Argomento Mancante!\n");
exit(1);
}
stream=fopen(argv[1], "r");
if(stream == NULL)
exit(EXIT_FAILURE);
/*aprire una pipe, dentro al while dove ho la fork fare poll che aspetta un carattere dalla pipe. Lo mando finito il while*/
pipe(pipefd);
pipe_read_poll.fd = pipefd[0];
pipe_read_poll.events = POLLIN;
while((read = getline(&line, &len, stream)) != -1) {
if(fork()==0){
i++;
char **lines=s2argv(line, NULL);
poll(&pipe_read_poll,1,-1);
execvp(lines[0], lines);
all[i]=getpid(); /**/
s2argv_free(lines);
perror("execvp fail!");
exit(1);
}
else
exit(2);
}
/*inviare carattere alla pipe*/
char buf='g';
write(pipefd[1], &buf, 1);
fineFirst=wait(&status);
/*kill the rest of process*/
while(i > 0){
if(all[i] != fineFirst){
kill(all[i], SIGTERM);
}
--i;
}
fclose(stream);
exit(0);
}
Soluzione di Blisset
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <s2argv.h>
#include <sys/types.h>
#include <signal.h>
#define MAX 20
int contaRighe (FILE *A){
char *a;
int i=0;
a= malloc (MAX*sizeof(char));
if (a==NULL) {
perror ("malloc");
return -1;
}
while (fgets(a, MAX, A)){
if (*a==EOF || *a=='\n') break;
i++;
}
return i;
}
int main (int argc, char *argv []){
int status;
int i=0;
int j=0;
int z=0; /*indice per ampiezza "pid_t ID" e "char *comando"*/
char *comando[z];
pid_t ID [z]; /* memorizza i pid di tutti i processi attivati */
pid_t terminato; /* memorizza il pid del primo processo che termina*/
FILE *fd = fopen (argv[1], "r");
if( fd==NULL ) {
perror("Errore in apertura del file");
return -1;
}
j=contaRighe (fd); /*ritorna il numero di righe del file dato in input*/
z=j; /* setto gli array con il numero di righe del file contenente i comandi */
rewind(fd); /*ritorno all'inizio del file*/
/* riempie "comando[z]" con tutti i comandi presenti nel file passato, i comando sono contati da 1 a z. */
while (j!=0){
comando [i] = malloc (MAX*sizeof(char));
fgets(comando [i], MAX, fd);
i++;
j--;
}
i--; /* diminuisco "i" di uno perchè prima di uscire dall'ultimo ciclo è aumentata di uno, "j" è uguale a 0 */
/*ESEGUE TUTTI I COMANDI */
while (i>=0){
switch (ID[j]=fork()) {
case 0:
execsp(comando[j]);
perror("exec");
case -1:
perror ("fork");
return -1;
}
i--;
j++;
}
i=0; /*setto "i" a 0 per il prossimo while */
terminato=wait(&status);
/* TERMINA TUTTI I PROCESSI */
while(i<j){ /* "i" strettamente minore di "j" poichè nell'ultimo ciclo del precedente while viene incrementata di uno */
if (ID[i]!=terminato) {
printf ("Termina processo %d\n",ID[i]);
kill(ID[i], SIGTERM); /* mando segnale di terminazione a tutti i PID che non sono ancora terminati */
}
else printf ("Processo completato %d\n",ID[i]);
i++;
}
fclose (fd);
return 0;
}
--Blissett (talk) 14:12, 11 March 2015 (CET)
Soluzione di Luca
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <s2argv.h>
#include <signal.h>
int main(int argc, char *argv[]){
char buff[256];
int num_cmd=0, tmp=0, i=0, pfd[2];
FILE *file=fopen(argv[1], "r");
while(fgets(buff, sizeof(buff), file)!=NULL){//ottengo numero comandi
num_cmd++;
}
rewind(file);
char cmd[num_cmd][256];
int pid[num_cmd];
pipe(pfd);
for(i=0; i<num_cmd; i++){
fgets(cmd[i], sizeof(cmd[i]), file);
//printf("Comando %d: %s", i, cmd[i]);
switch(pid[i]=fork()){
case 0:
close(pfd[0]);
close(pfd[1]);
execsp(cmd[i]);
exit(1);
case -1: exit(1);
}
}
int status;
close(pfd[0]);
close(pfd[1]);
tmp=wait(&status);
for(i=0; i<num_cmd; i++){
if(tmp==pid[i])
continue;
kill(pid[i], SIGTERM);
printf("terminato il processo: pid[%d]=%d\n", i, pid[i]);
}
fclose(file);
}
Esercizio 2
Soluzione di LeonardoF
//ESERCIZIO 2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "execs.h" //https://github.com/rd235/s2argv-execs
#include <fcntl.h>
#define AOI_LENSTEP 8
#define BUFFLEN 256
struct array_of_integers {
int **integers;
size_t currentlength; //the length of number of integers in memory
size_t arraylength; //the length of memory allocated
};
typedef struct array_of_integers array_of_integers;
void array_of_integers_add(array_of_integers *arrayOfIntegers, int val) {
if (arrayOfIntegers->currentlength >= arrayOfIntegers->arraylength) {
size_t newlength = arrayOfIntegers->arraylength + AOI_LENSTEP;
int **new_vec = realloc(arrayOfIntegers->integers, newlength * sizeof(arrayOfIntegers->integers[0]));
if (new_vec != NULL) {
arrayOfIntegers->arraylength = newlength;
arrayOfIntegers->integers = new_vec;
}
}
if (arrayOfIntegers->currentlength < arrayOfIntegers->arraylength)
arrayOfIntegers->integers[arrayOfIntegers->currentlength] = malloc(sizeof(int));
*(arrayOfIntegers->integers[arrayOfIntegers->currentlength++]) = val;
}
void array_of_integers_print(array_of_integers *v) {
size_t i;
for (i = 0; i < v->currentlength; i++)
printf("[%3lu]: %d\n", i, *(v->integers[i]));
}
int main(int argc, char *argv[]) {
/*opening and reading the file*/
char* line = NULL;
size_t lineLength = 0;
ssize_t numberOfCharactersRead;
FILE* fd1 = fopen(argv[1],"r");
static array_of_integers arrayOfPid;
static array_of_integers arrayOfFd;
int fd; //file descriptor
int i = 0; //iterator
char concat[BUFFLEN];
while ((numberOfCharactersRead = getline(&line, &lineLength, fd1)) >= 0) {
if (line[numberOfCharactersRead - 1] == '\n')
line[numberOfCharactersRead - 1] = 0;
///
/*done*/
/* opening output files, forking , saving pids and file descriptors*/
sprintf(concat,"./temp%d",i);
fd = open(concat,O_RDWR | O_CREAT | O_TRUNC , 0666);
int pid = fork();
switch(pid){
case 0: //children
//children stdio = file fd
dup2(fd,STDOUT_FILENO);
//execution of the command
execsp(line);
exit(-1); // in case of execsp failure
default: //parent
//must save all the pids
array_of_integers_add(&arrayOfPid,pid);
//must save all the fds. ( they will have the same order of the pids);
array_of_integers_add(&arrayOfFd,fd);
i ++;
break;
}
}
free(line);
/*done*/
/*waiting first process and killing the others*/
int firstpid;
size_t j; //iterator
size_t firstpid_pos; //position of the first pid in the array
//wait the first process
firstpid = wait(NULL);
/*sigterm the other processes iterating the pids vector*/
for (j = 0; j < (&arrayOfPid)->currentlength; j++){
int temp = *((&arrayOfPid)->integers[j]);
if(temp != firstpid)
kill( temp,SIGTERM);
else
firstpid_pos = j ;
}
/*done*/
/*printing the file of the "fisrt pid" process , unlinking the file and closing them*/
for (j = 0; j < (&arrayOfFd)->currentlength; j++){
fd = *((&arrayOfFd)->integers[j]);
sprintf(concat,"./temp%lu",j);
if (j == firstpid_pos){
int c;
//lseek is needed because the file is inherited
lseek(fd,0,SEEK_SET);
FILE *fdp = fdopen(fd,"r");
while ((c = getc(fdp)) != EOF)
putchar(c);
}
//unlink file fd
unlink(concat);
//close file fd
close(fd);
}
/*done*/
return 0;
}
--LeonardoF (talk) 11:33, 26 April 2017 (CEST)LeonardoF
Soluzione di Maldus
#include <s2argv.h>
#include <poll.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
int main(int argc, char* argv[]){
int i=0, status, out;
FILE *fd, *output;
pid_t *idents, winner;
char *line=NULL, *string;
size_t n=1;
int pipefd[2];
pipe(pipefd);
struct pollfd pipepoll;
pipepoll.fd = pipefd[0];
pipepoll.events = POLLIN;
if( !(fd = fopen(argv[1], "r"))){
perror("fopen:");
exit(1);
}
while( getline(&line, &n, fd) > 0){
i++;
free(line);
line=NULL;
}
idents = malloc(sizeof(pid_t)*i);
rewind(fd);
i = 0;
while( getline(&line, &n, fd) >0 ){
switch( idents[i]=fork()){
case 0:
asprintf( &string, "out%i" ,getpid());
if( (out=open(string, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR)) <0){
perror("open");
exit(1);
}
free(string);
dup2(out, 1);
close(out);
poll(&pipepoll, 1, -1);
execsp(line);
exit(0);
default:
free(line);
line=NULL;
i++;
break;
}
}
write(pipefd[1], "g", 1);
winner = wait(&status);
i--;
for( ; i >= 0 ; i--){
if(idents[i]!=winner){
kill(idents[i], SIGTERM);
asprintf( &string, "out%i", idents[i]);
unlink(string);
free(string);
}
}
asprintf( &string, "out%i" , winner);
if( !(output = fopen(string, "r"))){
perror("fopen");
exit(1);
}
while( getline(&line, &n, output)>0){
printf("%s", line);
free(line);
line=NULL;
}
unlink(string);
fclose(fd);
fclose(output);
return 0 ;
}
Per stampare solo l'output del processo vincente salvo quello di ciascun processo in un file di testo ( che poi cancello ). Mi viene però da pensare che debba esistere un modo migliore per farlo...
Esercizio 3
Scrivere un programma python o uno scrip bash che faccia un backup storico di un file.
backn file n
deve mantenere n versioni del file specificato. n>2
Esempio:
backn miofile 10
se esiste miofile.9 deve essere rinominato in miofile.10
se esiste miofile 8 deve essere rinominato in miofile 9
e cosi' via fino a miofile.2, rinominato miofile 3.
ora se miofile.1 ha lo stesso contenuto di miofile.3, miofile diventa un link fisico a miofile.2
miofile viene copiato in miofile.1
Soluzione di Blissett
#! /bin/bash
if [[ $# != 2 || ! -f $1 ]]
then
echo "Usage: $0 file n_backup"
exit -48
fi
file=$1
n_backup=$2
cartella="cartellaBackup"
true=0
if [[ ! -d $cartella ]]
then
mkdir $cartella
fi
cd ./$cartella
for i in `find ./ -name "$file*" | sort -n -r -t. -k3 | cut -d. -f3`
do
true=1
tmp=`find ./ -name "$file.$i"`
num=$(($i+1))
mv $tmp "$file.$num"
if [[ $num -gt n_backup ]]
then
rm "$file.$num"
fi
done
if [[ $true -eq 1 ]]
then
cmp -s "$file.2" "../$file"
if [[ $? -eq 0 ]]
then
echo creo link fisico.
ln "$file.2" "$file.1"
else
cp ../$file ./
mv $file "$file.1"
fi
else
cp ../$file ./
mv $file "$file.1"
fi
--Blissett (talk) 13:14, 11 May 2015 (CEST)
Soluzione di Maldus
import argparse
import sys
import os
import shutil
import filecmp
def olderVersion( new, old ):
new = new + '.'
l = len(new)
if new in old:
try:
num=int(old[l:])
if num < args.version and num!=1 : os.rename(old, old[:l]+str(num+1))
except ValueError:
return
parser = argparse.ArgumentParser(description='backup storico')
parser.add_argument('file', metavar='file', type=str, help='file di cui fare backup')
parser.add_argument('version', metavar='versione', type=int, help='numero di versione')
args = parser.parse_args()
new = args.file
if args.version < 2:
print("la versione deve essere > 2")
sys.exit(1)
entries = [ x for x in os.listdir('.') if os.path.isfile(x)]
if not new in entries:
print("Nessun file con quel nome")
sys.exit(1)
for file in entries: olderVersion( new, file )
if new+'.2' in entries:
if filecmp.cmp(new+'.3', new+'.1'): os.link(new, new+'.2')
else: os.rename(new+'.1', new+'.2')
elif new+'.1' in entries: os.rename(new+'.1', new+'.2')
shutil.copyfile(new, new+'.1')