Difference between revisions of "Prova pratica 2014.09.25"

From Sistemi Operativi
Jump to navigation Jump to search
(Created page with "Testo: [http://http://www.cs.unibo.it/~renzo/so/pratiche/2014.09.25.pdf] Esercizio 2 <syntaxhighlight lang="C"> //ESERCIZIO 2 #include <stdio.h> #include <stdlib.h> #include...")
 
m (Aggiunte soluzioni di altri studenti)
 
(4 intermediate revisions by 2 users not shown)
Line 1: Line 1:
Testo: [http://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 2
+
==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 AOS_LENSTEP 8
 
 
#define BUFFLEN  256
 
#define BUFFLEN  256
/*
 
* Define a struct for managing and array of pointer to strings.
 
*/
 
struct array_of_strings {
 
    char **strings;
 
    size_t currentlength; //the length of number of string in memory
 
    size_t arraylength; //the length of memory allocated
 
};
 
 
typedef struct array_of_strings array_of_strings;
 
 
void array_of_strings_add(array_of_strings *arrayOfStrings, char *string) {
 
    //if there is not enough space for the string increase it
 
    if (arrayOfStrings->currentlength >= arrayOfStrings->arraylength) {
 
        //increase the array length by the size of a string pointer
 
        size_t newlength = arrayOfStrings->arraylength + AOS_LENSTEP;
 
        //reallocate the arrayOfString with the new size
 
        char **new_string = realloc(arrayOfStrings->strings, newlength * sizeof(arrayOfStrings->strings[0]));
 
        //if the reallocation is successful
 
        if (new_string != NULL) {
 
            arrayOfStrings->arraylength = newlength;
 
            arrayOfStrings->strings = new_string;
 
        }
 
    }
 
    //if there is enough space for the string insert it
 
    if (arrayOfStrings->currentlength < arrayOfStrings->arraylength)
 
        //strdup return a pointer to a duplicate of the string
 
        arrayOfStrings->strings[arrayOfStrings->currentlength++] = strdup(string);
 
}
 
 
void array_of_strings_print(array_of_strings *v) {
 
    size_t i;
 
    for (i = 0; i < v->currentlength; i++)
 
        printf("[%3lu]: %s\n", i, v->strings[i]);
 
}
 
  
//readapting the struct and the functions above to manage integers
+
 
//polymorphism?
 
 
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*/
int commandNumber= 0;
 
 
     char* line = NULL;
 
     char* line = NULL;
 
     size_t lineLength = 0;
 
     size_t lineLength = 0;
 
ssize_t numberOfCharactersRead;
 
ssize_t numberOfCharactersRead;
    static array_of_strings arrayOfStrings;
+
 
   
+
 
 
     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;
        array_of_strings_add(&arrayOfStrings, line);
+
     
        commandNumber ++;
+
  ///
    }
 
 
  free(line);
 
 
  /*done*/
 
  /*done*/
 
  /* opening output files, forking , saving pids and file descriptors*/
 
  /* opening output files, forking , saving pids and file descriptors*/
int pid;
+
     sprintf(concat,"./temp%d",i);
int i = 0; //iterator
+
    fd = open(concat,O_RDWR | O_CREAT | O_TRUNC , 0666);
int fd; //file descriptor
 
char concat[BUFFLEN];
 
    static array_of_integers arrayOfPid;
 
    static array_of_integers arrayOfFd;
 
      
 
while(commandNumber > 0 ){
 
            sprintf(concat,"./temp%d",i);
 
            fd = open(concat,O_RDWR | O_CREAT | O_TRUNC , 0666);
 
  
pid = fork();
+
int pid = fork();
switch(pid){
+
switch(pid){
case 0: //children
+
case 0: //children
 
                         //children stdio = file fd
 
                         //children stdio = file fd
 
                         dup2(fd,STDOUT_FILENO);
 
                         dup2(fd,STDOUT_FILENO);
//execution of the command
+
//execution of the command
        execsp(arrayOfStrings.strings[i]);
+
execsp(line);
break;
+
        exit(-1); // in case of execsp failure
default: //parent  
+
default: //parent  
                        //must save all the pids
+
                        //must save all the pids
                        array_of_integers_add(&arrayOfPid,pid);
+
                        array_of_integers_add(&arrayOfPid,pid);
                        //must save all the fds. ( they will have the same order of the pids);
+
                        //must save all the fds. ( they will have the same order of the pids);
                        array_of_integers_add(&arrayOfFd,fd); /*this statement needs to be discussed*/
+
                        array_of_integers_add(&arrayOfFd,fd);  
commandNumber --;
+
i ++;
+
                        i ++;
break;
+
break;
 
  }
 
  }
 
 
 
 
 
  }
 
  }
     printf("arrayofFd\n");
+
     free(line);
    array_of_integers_print(&arrayOfFd);
 
 
     /*done*/
 
     /*done*/
 +
   
 
     /*waiting first process and killing the others*/
 
     /*waiting first process and killing the others*/
int firstpid;
+
    int firstpid;
size_t j; //iterator
+
    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);
+
    firstpid = wait(NULL);
//printf("%d\n",firstpid );
+
     //sigterm the other processes iterating the pids vector
+
     /*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*/
  
     /*this part needs to be discussed*/
+
     /*printing the file of the "fisrt pid" process , unlinking the file and closing them*/
    /*printign 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;
     //FILE *fdp = fdopen(fd,"r");
+
     //lseek is needed because the file is inherited
    FILE *fdp = fopen(concat,"r");
+
    lseek(fd,0,SEEK_SET);
   
 
      while ((c = getc(fdp)) != EOF)
 
        putchar(c);
 
 
 
 
    
 
    
 
+
    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 188: 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')