PDA

View Full Version : [C++]Shell Linux


giovessj
06-07-2006, 21:56
Salve a tutti mi servirebbe qlkuno ke abbia realizzato in c++ una shell di Linux...se qlkuno è così gentile da potermi aiutare..pleaseeeeeeee!!!!
Xkè ho provato ma nn ci riesco proprio :muro:

Andlea
06-07-2006, 22:25
posta quello che hai fatto e di cui hai dubbi e ti si da una mano

71104
06-07-2006, 22:40
com'è che proprio in questi momenti scema la passione degli opensourcisti...? :asd:

leggiti il codice di bash visto che è open, no? :asd:

giovessj
07-07-2006, 09:38
Scusa mika mi potrsti dare il link dove trovare il codice di bash??

Andlea
07-07-2006, 10:02
http://www.google.it/search?hl=it&q=bash+source&btnG=Cerca+con+Google&meta=lr%3Dlang_en%7Clang_it

giovessj
07-07-2006, 11:02
Grazie mille Andrea molto gentile ma sapevo cercare anke io su google :D
io chiedevo se c'era qlkuno molto gentile da darmi il link dove c'è già scritto il codice in c++.....è quello ke a me serve xkè come funzione una shell, cm funzionano le fork ecc.. lo so e anke molto bene...ma me servirebbe il codice sorgente della shell!!! :mbe:

trallallero
07-07-2006, 11:31
Grazie mille Andrea molto gentile ma sapevo cercare anke io su google :D
io chiedevo se c'era qlkuno molto gentile da darmi il link dove c'è già scritto il codice in c++.....è quello ke a me serve xkè come funzione una shell, cm funzionano le fork ecc.. lo so e anke molto bene...ma me servirebbe il codice sorgente della shell!!! :mbe:
io ho il codice della bash (me lo sono personalizzato, la history :D )
ma é in C, non C++. Se non sbaglio é su sourceforge.net

giovessj
07-07-2006, 11:47
A me va bene anke in c...mika potresti postarlo o al max darmi il link dove si trova su sourceforge.net xkè io ho visto ma nn sono riuscito a trovarlo...te ne sarei molto grato....

Andlea
07-07-2006, 12:01
il link con google non era uno scherzo :D
prendi il primo risultato, trovi il tar con i sorgenti

trallallero
07-07-2006, 12:04
A me va bene anke in c...mika potresti postarlo o al max darmi il link dove si trova su sourceforge.net xkè io ho visto ma nn sono riuscito a trovarlo...te ne sarei molto grato....
uhm ... chissá dove l'ho trovato ...
ho un tar gzippato ma é di 3.5 Mega. Se mi dai una mail dove mandartelo
perché qui il limite é di 24.4 Kb :eek:

giovessj
07-07-2006, 12:06
Ho visto quello ke dicevi tu Andlea ma sai qual è il fatto ke a me serve scrivere un codice di una shell semplice:
cioè una shell simile a quella di linux ke funzioni sotto linux e ke prenda un comando tipo ls e mi stampi il contenuto della cartella o ce vada avanti e indietro tra le cartelle o ke compili un file c o c++ ecc....

giovessj
07-07-2006, 14:30
ok trallallero ti ho mandato un mex privato cn la mia mail...poi inviarlo li tnx..

trallallero
07-07-2006, 14:37
ok trallallero se x favore potresti mandarmelo a [email protected] te ne sarei grato....
fatto :)

giovessj
07-07-2006, 14:44
ok grazie mille sei stato gentilissimo anke se vedrò di prendere spunto da questa visto ke quello ke devo fare io è a livello molto + basso....
Alla fine io nn devo far altro ke realizzare una semplicissima lettura di stringa di comando in linux con fork e exec...vabbè dai io ora ci provo poi se nn va il codice te lo posto qui e al max mi aiuti...xkè pensavo ke la shell l'avessi fatta te mentre quello ke mi hai mandato è il codice sorgente della bash....cmq di nuovo mille grazie!!

trallallero
07-07-2006, 14:52
ok grazie mille sei stato gentilissimo anke se vedrò di prendere spunto da questa visto ke quello ke devo fare io è a livello molto + basso....
Alla fine io nn devo far altro ke realizzare una semplicissima lettura di stringa di comando in linux con fork e exec...vabbè dai io ora ci provo poi se nn va il codice te lo posto qui e al max mi aiuti...xkè pensavo ke la shell l'avessi fatta te mentre quello ke mi hai mandato è il codice sorgente della bash....cmq di nuovo mille grazie!!
pensavo fosse chiaro che era la bash-shell ... :doh:
io l'ho solo modificata per personalizzarla, piccole modifiche per uso personale.
no no aspetta! 3.5 Mega di sorgente non ti passa piú :eek:
manda la traccia del problema e il codice che hai scritto dai ;)

giovessj
07-07-2006, 14:58
La traccia è la seguente:

-Realizzare in c++ la shell i linux..cioè la gestione dell'input e dell'output...
-Il probelma consiste nel realizzare in un file .cpp un codice il quale riceva in ingresso una stringa del tipo (ls) e dia in output il comando linux...tt qui....

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>


char **crea_vettore(char *stringa);
void dealloca(char **array_di_stringhe);

int main (int argc, char *argv[]){

int pid,i;
int status;
char *stringa;//stringa dove memorizzo la stringa dei comandi
char **stringhe; //array di stringhe



stringa=(char *)calloc(20,sizeof(char));

if ((stringa=fgets(stringa,20,stdin)) == NULL) exit(1);
while ( strncmp(stringa,"stop",4) != 0){

stringhe=crea_vettore(stringa);
if ( (pid = fork()) < 0){
perror("fork");
exit(1);
}else{
if (pid == 0){//figlio
if ( execvp(stringhe[0],stringhe) < 0 )
perror("execvp"),exit(1);
}else{//padre
//aspetto la terminazione di mio figlio
wait(&status);
//dealloca(stringhe);//libero memoria
}//fine else padre
}//fine else

if ((stringa=fgets(stringa,20,stdin)) == NULL) exit(1);
}//fine while


exit (0);
}

char **crea_vettore(char *stringa){

char **stringhe;
char *parola=NULL;
int i=0,
size=1,
j=0;

if ((stringhe=(char **)malloc(size*sizeof(char *))) == NULL)
perror("malloc"),exit(1);//errore allocazione

while ( stringa[i] != '\0' ){//scandisco tutta la stringa e la divido in tante parole

while ( (stringa[i] != ' ') && (stringa[i] != '\0') && (stringa[i] != '\n')){
//costruisco la parola
parola=(char *)realloc(parola,(j+1)*sizeof(char *));
parola[j]=stringa[i];
j=j+1;
i=i+1;
}
if ( ( stringa[i] == ' ') || (stringa[i] == '\n') )
i=i+1;
printf("parola= %s\n",parola);
if (parola != NULL){//parola trovata
stringhe=(char **)realloc(stringhe,(size+1)*sizeof(char *));
if ( (stringhe[size-1]=(char *)malloc(strlen(parola)+1)) == NULL)
perror("malloc"),exit(1);//errore allocazione
strcpy(stringhe[size-1],parola);
size=size+1;
}
parola=NULL;
j=0;
}
stringhe[size-1]=NULL;//fine dell array di stringhe

return (stringhe);
}


void dealloca(char **array_di_stringhe){

int i=0;

while ( array_di_stringhe[i] != NULL ){
free(array_di_stringhe[i]);
i=i+1;
}
free(array_di_stringhe[i]);
free(array_di_stringhe);
return;

}

questo è quello ke ho fatto.... dovrebbe funzionare + o - in questo modo e poi dovrei realizzare in visualc++ un'interfaccia grafica!!

trallallero
07-07-2006, 15:08
-Il probelma consiste nel realizzare in un file .cpp un codice il quale riceva in ingresso una stringa del tipo (ls) e dia in output il comando linux...tt qui....

se il problema é solo questo ti basta questo codice ;)

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char **argv )
{
system( argv[1] );
}

ma mi sembra strano ...

giovessj
07-07-2006, 15:10
No io devo scrivere il codice della shell...devo farla io la gestione della stringa in ingresso e la gestione dei processi padre e figlio...il codice ke mi hai scritto a ke serve????

trallallero
07-07-2006, 15:24
No io devo scrivere il codice della shell...devo farla io la gestione della stringa in ingresso e la gestione dei processi padre e figlio...il codice ke mi hai scritto a ke serve????
la system esegue un comando di sistema.
argv[1] é il primo parametro che passi all'eseguibile.
se passi ls all'eseguibile "lui" fa ls ;)
Adesso peró devo fare un lavoro su Oracle per un pó ...

giovessj
07-07-2006, 15:29
ok ti kiedo solo un favore...qndo hai tempo potresti modificarmi il codice e aggiustarmelo in maniera corretta?...anke se è in c nn fa nulla al max poi lo modifico in c++...cmq ora ti lascio al tuo lavoro...se e qndo puoi riesci a farmi sto piacere te ne sarei grato...cmq grazie mille di tt :)

trallallero
07-07-2006, 15:44
ok ti kiedo solo un favore...qndo hai tempo potresti modificarmi il codice e aggiustarmelo in maniera corretta?...anke se è in c nn fa nulla al max poi lo modifico in c++...cmq ora ti lascio al tuo lavoro...se e qndo puoi riesci a farmi sto piacere te ne sarei grato...cmq grazie mille di tt :)


#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>


char **crea_vettore(char *stringa);
void dealloca (char **array_di_stringhe);

int main(int argc, char *argv[])
{
int pid, i;
int status;
char *stringa;
//stringa dove memorizzo la stringa dei comandi
char **stringhe;
//array di stringhe

stringa = (char *) calloc(20, sizeof(char));

if ((stringa = fgets(stringa, 20, stdin)) == NULL)
exit(1);
while (strncmp(stringa, "stop", 4) != 0)
{
stringhe = crea_vettore(stringa);

if ((pid = fork()) < 0)
{
perror("fork");
exit(1);
}
else
{
if (pid == 0)
{
//figlio
if (execvp(stringhe[0], stringhe) < 0)
perror("execvp"), exit(1);
}
else
{
//padre
// aspetto la terminazione di mio figlio
wait(&status);
//dealloca(stringhe);
//libero memoria
} //fine
} //fine
} //fine while

return 0; // CI VUOLE UN RITORNO
}

char **crea_vettore(char *stringa)
{

char **stringhe;
char *parola = NULL;
int i = 0, size = 1, j = 0;

if ((stringhe = (char **) malloc(size * sizeof(char *))) == NULL)
perror("malloc"), exit(1);
//errore allocazione

while (stringa[i] != '\0')
{
//scandisco tutta la stringa e la divido in tante parole
while ((stringa[i] != ' ') && (stringa[i] != '\0') && (stringa[i] != '\n'))
{
//costruisco la parola
parola = (char *) realloc(parola, (j + 1) * sizeof(char *));
parola[j] = stringa[i];
j = j + 1;
i = i + 1;
}
if ((stringa[i] == ' ') || (stringa[i] == '\n'))
i = i + 1;

printf("parola= %s\n", parola);

if (parola != NULL)
{
//parola trovata
stringhe = (char **) realloc(stringhe, (size + 1) * sizeof(char *));

if ((stringhe[size - 1] = (char *) malloc(strlen(parola) + 1)) == NULL)
perror("malloc"), exit(1); //errore allocazione

strcpy(stringhe[size - 1], parola);
size = size + 1;
}
parola = NULL;
j = 0;
}
stringhe[size - 1] = NULL;
//fine dell array di stringhe

return (stringhe);
}


void dealloca(char **array_di_stringhe)
{
int i = 0;

while (array_di_stringhe[i] != NULL)
{
free(array_di_stringhe[i]);
i = i + 1;
}
free(array_di_stringhe[i]);
free(array_di_stringhe);
}

ti ho corretto gli errori (non quelli logici) e adesso compila
ma non mi sembra corretta la "crea_vettore".
Solo che é un pó lungo ... devo solo fare una cosa poi
se entro le 17 la finisco lo leggo meglio

ps: scusa ma ho reindentato piú o meno a modo mio per capire meglio

Andlea
07-07-2006, 15:47
No io devo scrivere il codice della shell...devo farla io la gestione della stringa in ingresso e la gestione dei processi padre e figlio...il codice ke mi hai scritto a ke serve????
Se ho capito bene ti basta fare una pipe, fare la fork, chiudere scrittura al padre, chiudere stdin, dupare la pipe in lettura, nel figlio chiudere estremo di lettura della pipe, chiudere stdout, dupare la pipe di scrittura e lanciare l'exec con l'argomento passato a parametro

giovessj
07-07-2006, 15:59
Andlea è da dire ke io sn alle prime armi e quindi sinceramente nn ho capito quello ke vuoi dire...se potresti essere + gentile da spiegarti cn qlke esempio....

Andlea
07-07-2006, 16:19
Ogni volta che ricevi un comando, crei una nuova pipe
int piped[2];
...
pipe(piped);
dopodichè fai la fork()
Nel padre farai così

close(piped[1]); // chiudi estremo di scrittura della pipe
while((nread=read(piped[0], buff, MAX_BUFF))>0)
printf("%s", buff);

buff è un char*, MAX_BUFF una costante che puoi impostare ad esempio a 20
Questa parte di codice non fa altro che leggere quello che esce dalla pipe e visualizzarlo a schermo

Il figlio dovrà scrivere sulla pipe, per farlo fa così

close(piped[0]);
close(1);
dup(piped[1]);
close(piped[1]);
exec(.....);

In questo modo chiude l'estremo di lettura della pipe, chiude lo standard output, e rimpiazza il descrittore dello stdout con l'estremo di scrittura della pipe
nell'exec farai la chiamata al comando impartito dall'utente, e il risultato verrà mandato nella pipe, ricvuta e visualizzata dal padre.

Una volta finito fai la wait(&status); e ricomincerai chiedendo il comando, ecc..

trallallero
07-07-2006, 16:25
problema oracle rimandato a mercoledi :)

per adesso vedo un errore

sbagliato:
parola = (char *) realloc(parola, (j + 1) * sizeof(char *));
corretto
parola = (char *) realloc(parola, (j + 1) * sizeof(char));
stai allocando una stringa non una matrice

poi non ho capito il problema ...
il programma chiede una serie di comandi e tu per ogni comando lanci un figlio che lo esegue ?

trallallero
07-07-2006, 16:27
while (strncmp(stringa, "stop", 4) != 0)

ciclo infinito ;)

se stringa é "ciao pippo pluto stop" la strncmp
punterá sempre a ciao quindi condizione sempre falsa

giovessj
07-07-2006, 16:28
si esattamente...cioè nn fa altro ke ad ogni fork lanciare un figlio....

giovessj
07-07-2006, 16:31
quindi il ciclo while così fatto nn va bene??

trallallero
07-07-2006, 16:36
no, penso di aver capito ;)

tu devi creare 1 figlio con la fork.
La execvp ha una lista di argomenti e serve per trasformare il figlio
nel programma che vuoi tu.
Il primo argomento é infatti il nome del programma (per ex. ls)
poi gli argomenti per i programma (per ex. -ltr pippo ...)
l'ultimo argomento é NULL per far capire che é finita la lista.
Il figlio quindi si trasforma nel programma specificato e gli passa gli argomenti restanti.

giovessj
07-07-2006, 16:40
si xkè tipo puo' accadere ke cm riga di comando ci possa essere:
g++ -o shell.cpp e la mia shell cmq deve rilevare tt le parole presenti nela riga...

trallallero
07-07-2006, 16:46
si xkè tipo puo' accadere ke cm riga di comando ci possa essere:
g++ -o shell.cpp e la mia shell cmq deve rilevare tt le parole presenti nela riga...

Appunto, non é un figlio per parola ma un solo figlio che fa tutto.

Devi fare cosí:

- ottieni stringa (senza stop, non serve)
- crei vettore
- chiami la fork
- chiami la execvp passando il vettore terminato da NULL

io fra un pó devo andare. Ti posto il codice di un client
di un sistema client/server che ho fatto qualche anno fa.
Il sistema é lo stesso.
Il server si clona, chiama la execvp e si trasforma in child
passando gli argomenti.
Ovviamente io ho fatto anche child.c che gestisce il client
ma a te non serve perché chiami i comandi di sistema.
Spero ti torni utile, é molto commentato.


/* -----------------------------------------*\
AVVIA UN PROCESSO FIGLIO.
\* -----------------------------------------*/
static void ChildBorning( int ThisSocket )
{
int pid;

if ( ThisSocket <= (stderr - stdin) ) return;

pid = fork(); // SDOPPIA IL PROCESSO ATTUALE.

if ( pid < 0 ) // ERRORE
DiagMsg(__LINE__ ,"'fork': %s" ,strerror(errno));
else if ( pid > 0 ) // PARENT
DiagMsg(__LINE__ ,"Connection signal received from PPSERVER; child starting...");
else // CHILD
{ // RILASCIA IL FILE_DESCRIPTOR DEL SOCKET DEL GENITORE.
// --- SOSTITUISCE L'IMMAGINE DEL PROGRAMMA ATTUALE ---
int parm = 0;
char buff[16];
char *arglist[7];

// ID DELLA CODA_MESSAGGI PASSATO COME PARAMETRO AL PROGRAMMA CHE SUBENTRA AL CLONE DEL GENITORE.
sprintf( buff, "%05.5d", ThisSocket );

close(sockfd);
// ACCATASTA I PARAMETRI PER IL PROGRAMMA 'CHILD'.
arglist[parm++] = "child"; // NOME PROCESSO
arglist[parm++] = buff; // NUMERO CODA MESSAGGI
if (Diagnostic) arglist[parm++] = Diagnostic; // EVENTUALE FLAG DI DIAGNOSTICA ( -d, -D )
arglist[parm++] = NULL; // FINE ARGOMENTI


// STAMPA IL COMANDO COMPLETO PER L'ESECUZIONE DI 'CHILD'.
ArgListing( arglist, "Executed", "execvp" );
execvp( arglist[0], arglist );

// SE SIAMO QUI NON RIUSCITA 'exec'
// STAMPA IL COMANDO COMPLETO PER L'ESECUZIONE DI 'CHILD'.
ArgListing(arglist ,"Failed" ,"execvp");
}
}
/* -----------------------------------------------------------------------------------*/

giovessj
07-07-2006, 16:49
Ok grazie mille x la tua disponibilità sei stato gentilissimo....