uniroma1.*_main.c.cognome.nome. Sulle postazioni del laboratorio sarà /home/biar/Desktop/cognome.nome/.cognome.nome.zip (zip -r cognome.nome.zip cognome.nome/).cognome.nome.zip.rm -rf cognome.nome).Per maggiori informazioni fate riferimento al regolamento delle esercitazioni.
stdin in C)Questo è un esercizio di mera conoscenza del linguaggio C. Il canale stdin (di tipo FILE*) modella in C la sorgente di caratteri ASCII che proviene come input, salvo diversamente specificato, dal terminale. Si chiede di scrivere nel file E1-get-cmd-line/e1.c una funzione void get_cmd_line(char* argv[]); che legge la prossima linea di testo da stdin, estrae ciascun token (sequenza consecutiva di caratteri, esclusi spazi, tab \t e ritorni a capo \n) e produce un array di al più n<=MAX_TOKENS=64 stringhe come segue:
malloc;NULL, fungendo da “terminatore”.Assumere che la linea di testo letta da stdin contenga al più 1024 caratteri compreso il ritorno a capo \n.
Esempio: se la linea letta da stdin è rm -f .DS_store, la chiamata get_cmd_line(argv) restituisce in argv l’array di stringhe {"rm", "-f". ".DS_Store", NULL}.
Suggerimenti. Basandosi sul comando man (oppure la documentazione online cercando funzione opengroup) usare:
fgets per leggere una linea da stdio di al più MAX_LINE=1024 caratteri terminata dal ritorno a capo \n;strtok per tokenizzare la linea una volta letta da stdio.L’array di stringhe prodotto deve essere deallocabile con la semplice funzione:
void free_args(char* argv[]) {
while (*argv) free(argv++);
}
Usare il main di prova nella directory di lavoro E1-parse-line compilando con `gcc e1_main.c e1.c -o e1´.
[Svolgere questo esercizio solo dopo aver svolto l’Esercizio 1]
Una shell è un programma che chiede all’utente di eseguire altri programmmi sotto forma di nuovi processi, passandogli eventuali argomenti specificati dall’utente. Una shell fornisce normalmente un prompt, vale a dire un breve testo (es. $, >, ecc.) che segnala all’utente che la shell è in attesa di ricevere comandi.
Si chiede di scrivere nel file E2-shell/e2.c una semplice shell sotto forma di una funzione int do_shell(const char* prompt); che prende come parametro la stringa di prompt e si comporta come segue;
stdin un comando seguito dai suoi eventuali argomenti (es: ls -l, dove ls è il comando e -l è il suo unico argomento). Per ottenere comando e argomenti da stdin usare il risultato dell’esercizio 2;quit terminare con successo la shell;fork un nuovo processo che esegua il comando con gli argomenti dati usando execvp;unknown command seguito dal nome del comando e tornare al punto 1;wait la terminazione del processo e tornare al punto 1.Per valutare il corretto funzionamento della shell, effettuare i seguenti quattro test:
ls -l e verificare che listi la directory correnteecho hello e verificare che venga stampato hellosergente hartman e verificare che venga stampato un messaggio di errorequit e verificare la terminazione della shellIl risultatao di ogni system call deve essere controllato e in caso di errore segnalato con perror e terminazione EXIT_FAILURE.
Rispondi alle seguenti domande, tenendo conto che una risposta corretta vale 1 punti, mentre una risposta errata vale 0 punti.
Domanda 1 Relativamente al seguente codice C (supponendo che la fork non generi un errore), quale tra le seguenti affermazioni è VERA?

Padre: 1” e poi “Figlio: 2”Figlio: 2” e poi “Padre: 1”Figlio: 1” e poi “Padre: 1”Figlio: 1” e poi “Padre: 2”Figlio: 2” e poi “Padre: 2”Domanda 2 Relativamente al seguente codice C (supponendo che la fork non generi un errore), qual è l’output atteso?

Figlio 1: x=10”, “Figlio 2: x=20”, “Figlio 3: x=30”, “Padre: x=40”Figlio 1: x=10”, “Figlio 2: x=10”, “Figlio 3: x=10”, “Padre: x=30”Figlio 1: x=10”, “Figlio 2: x=10”, “Figlio 3: x=10”, “Padre: x=40”Figlio 1: x=10”, “Figlio 2: x=20”, “Figlio 3: x=30”, “Padre: x=30”Figlio 1: x=10”, “Figlio 2: x=30”, “Figlio 3: x=60”, “Padre: x=100”Domanda 3 Relativamente al seguente codice C (supponendo che la execv non generi un errore), qual è l’output atteso?

--- started ---”, “Hello”, “NULL, “--- finished ---”--- started ---”, “Hello”, “--- finished ---”--- started ---”, “Hello”--- started ---”, “--- finished ---”stdin in C)e1.c
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "e1.h"
char* dup_string(const char* in) {
size_t n = strlen(in);
char* out = malloc(n + 1);
strcpy(out, in);
return out;
}
void get_cmd_line(char* argv[MAX_TOKENS]) {
int argc = 0;
char line[MAX_LINE];
fgets(line, MAX_LINE, stdin);
char* token = strtok(line, " \t\n");
argc = 0;
while (argc < MAX_TOKENS && token != NULL) {
argv[argc++] = dup_string(token);
token = strtok(NULL, " \t\n");
}
argv[argc] = NULL;
}
e2.c
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "e2.h"
#define MAX_LINE 1024
#define MAX_TOKENS 64
void do_cmd(char* argv[MAX_TOKENS]) {
int res;
pid_t pid = fork();
if (pid == -1) {
perror("fork error");
exit(EXIT_FAILURE);
}
if (pid == 0) {
res = execvp(argv[0], argv);
if (res == -1) {
printf("unkwnown command %s\n", argv[0]);
_exit(EXIT_FAILURE);
}
}
res = wait(NULL);
if (pid == -1) {
perror("wait error");
exit(EXIT_FAILURE);
}
}
void deallocate_cmd(char* argv[MAX_TOKENS]) {
while (*argv != NULL)
free(*argv++);
}
char* dup_string(const char* in) {
size_t n = strlen(in);
char* out = malloc(n + 1);
strcpy(out, in);
return out;
}
void get_cmd_line(char* argv[MAX_TOKENS]) {
int argc = 0;
char line[MAX_LINE];
fgets(line, MAX_LINE, stdin);
char* token = strtok(line, " \t\n");
argc = 0;
while (argc < MAX_TOKENS && token != NULL) {
argv[argc++] = dup_string(token);
token = strtok(NULL, " \t\n");
}
argv[argc] = NULL;
}
int do_shell(const char* prompt){
for (;;) {
printf("%s", prompt);
char* argv[MAX_TOKENS];
get_cmd_line(argv);
if (argv[0] == NULL) continue;
if (strcmp(argv[0], "quit") == 0) break;
do_cmd(argv);
deallocate_cmd(argv);
}
return EXIT_SUCCESS;
}
Figlio: 1” e poi “Padre: 1”Figlio 1: x=10”, “Figlio 2: x=20”, “Figlio 3: x=30”, “Padre: x=40”--- started ---”, “Hello”