khri81
03-05-2005, 18:18
dopo il precedente andato a buon fine x fortuna, anche grazie ai vostri consigli mi serve di nuovo un aiutino, ovviamente nn chiedo che lo facciate voi ma che mi possiate dare qualche dritta su come poter fare il prog, questo è ciò che il prof vuole:
Scrivete un programma C che agisca da interprete di comandi per il kernel Linux. La shell dovrebbe usare lo stesso stile della Bourne shell per eseguire i comandi.
I passi che devono essere compiuti dalla shell sono:
1. stampare il prompt – quando la shell parte dovrebbe cercare il nome della
macchina sulla quale è in esecuzione in modo che il prompt abbia il seguente
formato nome_macchina:directory_corrente>. Inoltre ogni volta che viene
utilizzato il comando cd per spostarsi nel file system, il prompt venga modificato
di conseguenza.
2. prelevare la riga di comando – la shell deve eseguire una operazione di lettura
del comando terminato da un carattere di NEWLINE (‘\n’).
3. analisi del comando – analisi della riga di comando a partire da sinistra verso
destra. La sintassi del comando è la seguente identificatore [identificatore
[identificatore]] dove il primo identificatore indica il comando mentre i restanti
sono i parametri del comando stesso. Ogni identificatore è separato dagli altri da
caratteri tipo: space, tab, oppure NEWLINE.
4. ricerca del file del comando – la shell fornisce un insieme di variabili di
ambiente. Tra queste la variabile di ambiente PATH contiene una lista ordinata di
pathname dove la shell dovrebbe ricercare il comando.
5. preparazione dei parametri – la shella prepara i parametri per il comando
inserendoli in un vettore di stringhe tipo char *argv[].
6. esecuzione del comando – la shell esegue il comando utilizzando un processo
figlio creato tramite una fork(), il quale chiama ad esempio execve() mentre il
processo padre invoca una wait().
Conviene svolgere il compito nei seguenti passi:
- Strutturate la shell in modo che inizi le variabili necessarie ed esegua un loop
senza fine a meno di non rivelare una condizione di EOF sullo stdin (esempio il
carattere Ctrl-D). Scrivete una versione che presenti un prompt, attenda un
comando dall’utente, legga il comando e lo stampi a schermo.
- Successivamente analizzate la riga di comando in modo da separare il comando e i parametri che dovreste porre in un vettore char *argv[]. Inoltre dovreste
calcolare il valore di int argc. Stampate a schermo il contenuto di argc e argv[].
Dovreste individuare un comando di exit per terminare la shell.
Un possibile schema per la shell potrebbe essere il seguente:
int main(){
struct command_struct {
char *name;
char *argv[];
…
} *command;
//inizializzazione della shell
..
//Loop principale
while (stdin non è EOF){
print_to_stdout(prompt_string);
command_line=read_from_stdin();
// determinate il nome del comando ed i parametri
…
// eseguite il comando con i parametri specificati
…
}
// terminate la shell
….
}
- Utilizzate argv[0] per localizzare il file eseguibile. In questa versione semplificata di shell, stampiamo il nome del file.
• Costruiamo una versione che ricerchi il comando tra i file presenti nella
directory corrente.
• Miglioriamo il programma in modo che trovi il comando tra i file
specificati con un pathname assoluto.
• Rendiamo possibile la ricerca nell’elenco delle directory presenti nella
variabile di ambiente PATH.
- Creiamo un processo figlio che esegua il comando (utilizzate la chiamata
execve()).
if( fork() == 0) {
// processo figlio
// viene eseguito nello stesso ambiente del padre
execvp(full_pathname,command->argv,0);
}
else {
// processo genitore
wait(&status);
}
- Implementiamo la possibilità che il comando venga eseguito in background dalla
shell: il processo padre (shell) non esegue una wait(), ma ripresenta il prompt. In
questo caso è possibile la presenza di processi zombie che vanno eliminati con
una gestione del segnale SIGCHLD.
- Prevediamo la possibilità di gestire la redirezione dello standard input (<
input_file), dello standard output (> output_file), della pipeline (cmd1 | cmd2)
raga aiuto nn so da dove cominciare e nemmeno cosa fare. :(
Scrivete un programma C che agisca da interprete di comandi per il kernel Linux. La shell dovrebbe usare lo stesso stile della Bourne shell per eseguire i comandi.
I passi che devono essere compiuti dalla shell sono:
1. stampare il prompt – quando la shell parte dovrebbe cercare il nome della
macchina sulla quale è in esecuzione in modo che il prompt abbia il seguente
formato nome_macchina:directory_corrente>. Inoltre ogni volta che viene
utilizzato il comando cd per spostarsi nel file system, il prompt venga modificato
di conseguenza.
2. prelevare la riga di comando – la shell deve eseguire una operazione di lettura
del comando terminato da un carattere di NEWLINE (‘\n’).
3. analisi del comando – analisi della riga di comando a partire da sinistra verso
destra. La sintassi del comando è la seguente identificatore [identificatore
[identificatore]] dove il primo identificatore indica il comando mentre i restanti
sono i parametri del comando stesso. Ogni identificatore è separato dagli altri da
caratteri tipo: space, tab, oppure NEWLINE.
4. ricerca del file del comando – la shell fornisce un insieme di variabili di
ambiente. Tra queste la variabile di ambiente PATH contiene una lista ordinata di
pathname dove la shell dovrebbe ricercare il comando.
5. preparazione dei parametri – la shella prepara i parametri per il comando
inserendoli in un vettore di stringhe tipo char *argv[].
6. esecuzione del comando – la shell esegue il comando utilizzando un processo
figlio creato tramite una fork(), il quale chiama ad esempio execve() mentre il
processo padre invoca una wait().
Conviene svolgere il compito nei seguenti passi:
- Strutturate la shell in modo che inizi le variabili necessarie ed esegua un loop
senza fine a meno di non rivelare una condizione di EOF sullo stdin (esempio il
carattere Ctrl-D). Scrivete una versione che presenti un prompt, attenda un
comando dall’utente, legga il comando e lo stampi a schermo.
- Successivamente analizzate la riga di comando in modo da separare il comando e i parametri che dovreste porre in un vettore char *argv[]. Inoltre dovreste
calcolare il valore di int argc. Stampate a schermo il contenuto di argc e argv[].
Dovreste individuare un comando di exit per terminare la shell.
Un possibile schema per la shell potrebbe essere il seguente:
int main(){
struct command_struct {
char *name;
char *argv[];
…
} *command;
//inizializzazione della shell
..
//Loop principale
while (stdin non è EOF){
print_to_stdout(prompt_string);
command_line=read_from_stdin();
// determinate il nome del comando ed i parametri
…
// eseguite il comando con i parametri specificati
…
}
// terminate la shell
….
}
- Utilizzate argv[0] per localizzare il file eseguibile. In questa versione semplificata di shell, stampiamo il nome del file.
• Costruiamo una versione che ricerchi il comando tra i file presenti nella
directory corrente.
• Miglioriamo il programma in modo che trovi il comando tra i file
specificati con un pathname assoluto.
• Rendiamo possibile la ricerca nell’elenco delle directory presenti nella
variabile di ambiente PATH.
- Creiamo un processo figlio che esegua il comando (utilizzate la chiamata
execve()).
if( fork() == 0) {
// processo figlio
// viene eseguito nello stesso ambiente del padre
execvp(full_pathname,command->argv,0);
}
else {
// processo genitore
wait(&status);
}
- Implementiamo la possibilità che il comando venga eseguito in background dalla
shell: il processo padre (shell) non esegue una wait(), ma ripresenta il prompt. In
questo caso è possibile la presenza di processi zombie che vanno eliminati con
una gestione del segnale SIGCHLD.
- Prevediamo la possibilità di gestire la redirezione dello standard input (<
input_file), dello standard output (> output_file), della pipeline (cmd1 | cmd2)
raga aiuto nn so da dove cominciare e nemmeno cosa fare. :(