View Full Version : [C] Alcuni problemi riguardo la exec()
Ciao.
Sto creando una piccola shell in C. Ho alcuni problemi:
1 - Eseguendo la execvp ad esempio con ls, ho l'output di ls normalmente; se invece aggiungo un argomento ad esempio per eseguire ls -l non mi fa vedere l'output come dovrebbe essere con l'opzione -l ma me lo fa vedere come se non ci fosse tale opzione. E' come se ignorasse gli argomenti, non capisco perché.
2 - Nella gestione del segnale (fatta da me) di SIGQUIT quando premo la combinazione di tasti CTRL-\ mi scrive Quit (core dumped) ed esce dalla shell. E' normale come comportamento?
3 - Per quanto riguarda i comandi builtin della mia shell, ho creato un file txt con una lista di comandi interni (tipo alias, cd, pwd ecc.). Il problema è che qualsiasi comando faccia partire di questi, la execvp mi ritorna sempre con un errore dicendo "No such file or directory".
Ditemi se devo postarvi qualche pezzo di codice, perché è molto lungo. Grazie.
1 - Eseguendo la execvp ad esempio con ls, ho l'output di ls normalmente; se invece aggiungo un argomento ad esempio per eseguire ls -l non mi fa vedere l'output come dovrebbe essere con l'opzione -l ma me lo fa vedere come se non ci fosse tale opzione. E' come se ignorasse gli argomenti, non capisco perché.Ecco un banale esempio (senza fork per cui sostituisce il processo e basta).
#include <stdio.h>
#include <unistd.h>
int main (void)
{
char *args[4];
args[0] = "ls";
args[1] = "-laA";
args[2] = "/tmp";
args[3] = NULL;
execvp (args[0], args); /* Lancia: ls -laA /tmp */
return 0;
}
3 - Per quanto riguarda i comandi builtin della mia shell, ho creato un file txt con una lista di comandi interni (tipo alias, cd, pwd ecc.). Il problema è che qualsiasi comando faccia partire di questi, la execvp mi ritorna sempre con un errore dicendo "No such file or directory".Beh, certo è normale! Se sono comandi "built-in" vuol dire che non sono degli eseguibili esterni presenti in qualche punto del file-system!!
Quando la shell riceve un comando "built-in" dal prompt (o leggendo uno script), ad esempio il comando 'cd', non avvia nulla di esterno. Per il comando 'cd', esso fa nient'altro che chiamare la funzione di sistema int chdir(const char *path);, in modo da cambiare la directory corrente dentro il processo della shell.
Spero cioè di essermi spiegato: molti dei comandi built-in operano sullo stato interno della shell e spesso chiamano semplicemente delle funzioni di sistema. Così, se nella "tua" shell vuoi implementare in comando "pwd", quando lo ricevi (da prompt) devi fare semplicemente così: chiamare la funzione getcwd() e stampare il path ottenuto.
Nota: poi se vai a vedere la documentazione della bash, vedi che pwd ha 2 opzioni: -L e -P. Dipende se devi "replicare" fedelmente la bash oppure no, ma questo tocca a te decidere in base a cosa vuoi/devi fare.
Devil_Dante
30-12-2006, 20:02
Ciao manugal..per caso stai svolgendo questo progetto per l'esame di laboratorio di sistemi della sapienza a roma? perchè anche io devo svolgere lo stesso progetto proprio per questa materia!! Se possibile avrei bisogno di qualche consiglio a riguardo; sono a metà progetto ma ci sono dei punti poco chiari. Fammi sapere :p
Ciao a presto!
Ah quindi per i comandi interni devo ogni volta chiamare la funzione appropriata? Questo significa che ogni comando ha la sua funzione (cioè fg ha la sua funzione, bg anche, echo anche ecc.) giusto? Saranno almeno una trentina i comandi builtin. Dove le trovo tutte le funzioni associate a ciascun comando?
Per quanto riguarda la prima domanda ad args[0] gli passo direttamente tutto il path del comando, mentre gli altri argomenti li passo tali e quali come mi hai fatto vedere tu. Ma lui si ostina a farmi vedere ls come se lo passassi senza ulteriori argomenti. Non capisco perché. Dimmi se ti serve qualche pezzo di codice.
Grazie.
P.S. Devil_Dante hai un PM ;)
beppegrillo
30-12-2006, 20:16
Ah quindi per i comandi interni devo ogni volta chiamare la funzione appropriata? Questo significa che ogni comando ha la sua funzione (cioè fg ha la sua funzione, bg anche, echo anche ecc.) giusto? Saranno almeno una trentina i comandi builtin. Dove le trovo tutte le funzioni associate a ciascun comando?
Per quanto riguarda la prima domanda ad args[0] gli passo direttamente tutto il path del comando, mentre gli altri argomenti li passo tali e quali come mi hai fatto vedere tu. Ma lui si ostina a farmi vedere ls come se lo passassi senza ulteriori argomenti. Non capisco perché. Dimmi se ti serve qualche pezzo di codice.
Grazie.
P.S. Devil_Dante hai un PM ;)
controlla bene che non fai cosi
execve("ls","-l"), ma bisogna fare come andbin giustamente ti mostra :)
Guarda controllando con il debugger gdb vedo proprio che gli passa ls e poi -l seguito da NULL. Non capisco perché non mi interpreta il -l.
Finalmente ci sono riuscito. Grazie mille a tutti. :)
beppegrillo
31-12-2006, 15:25
Finalmente ci sono riuscito. Grazie mille a tutti. :)
ps.
Regola fondamentale, quando si risolve un problema va detto anche come lo si è risolto, per due motivi :
1) Altri potrebbero avere lo stesso tuo problema, cercando trovano pure la soluzione
2) Per curiosità di chi ti ha aiutato, per vedere se ha beccato il problema
Buon anno
Ok. Praticamente ho risolto chiamando execvp("ls", "ls -l",NULL); cioè vale a dire che "ls -l" è un argomento unico e così lo riesce ad interpretare correttamente.
Ciao e buon anno. :)
Ok. Praticamente ho risolto chiamando execvp("ls", "ls -l",NULL);Assolutamente sbagliato!! execvp ha il seguente prototipo:
int execvp(const char *file, char *const argv[]);
Il secondo parametro deve essere un array di puntatori a char, non un puntatore a char!!! E il compilatore dovrebbe pure arrabbiarsi.
Se vuoi proprio passare direttamente i parametri nella chiamata, potresti al massimo usare la funzione execlp (nota la 'l' invece della 'v'). Il mio esempio che ho postato prima lo potrei riscrivere con execlp così:
execlp ("ls", "ls", "-laA", "/tmp", NULL);
Ma ripeto, usare execvp come hai appena detto tu, è sbagliato. ;)
Scusa io gli passo un array di puntatori a char (cioè args che è la variabile che ho creato appositamente). Faccio una chiamata così execvp(name,args); (con name che è essenzialmente "ls") solamente che args[0]="ls -l" e args[1]=NULL. Non gli passo infatti un puntatore a char. Se invece args[0]="ls", args[1]="-l" e args[2]=NULL allora così non funziona.
Scusa io gli passo un array di puntatori a charAh ... volevo dire! Dal tuo precedente post si capiva tutta un'altra cosa .... ;)
(cioè args che è la variabile che ho creato appositamente). Faccio una chiamata così execvp(name,args); (con name che è essenzialmente "ls") solamente che args[0]="ls -l" e args[1]=NULL.Così è sbagliato e infatti non dovrebbe funzionare (a me non funziona)
Se invece args[0]="ls", args[1]="-l" e args[2]=NULL allora così non funziona.No, così è corretto e dovrebbe funzionare (e a me funziona). ;)
Ti costa molto verificare che:
char *args[2];
args[0] = "ls -l";
args[1] = NULL;
execvp ("ls", args);
così non funziona
e che invece:
char *args[3];
args[0] = "ls";
args[1] = "-l";
args[2] = NULL;
execvp ("ls", args);
così funziona.
?
Boh strano. Adesso l'ho provato su un sorgente nuovo e funziona come dici tu :) . Però a me sul programma che sto facendo funziona. Forse mi sono sbagliato a dirti che gli passo gli argomenti in quel modo, mentre in realtà li passo con il tuo sistema. Perché se funziona e fa quello che deve fare è corretto no?
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.