Discussione:
Shell linux
(troppo vecchio per rispondere)
Max
2014-07-15 08:29:17 UTC
Permalink
Altro esercizietto, una semplice shell linux che fa solo una cosa:
accetta 2 comandi e ridireziona l'output del primo come input del secondo.
Ho cercato di indentare un pochino meglio, c'è da dire che col copia e
incolla qualcosa si incasina comunque.




#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
int n,i;
char buff[80]; //stringa da imput
char prompt[10];
char * commands[3]; //array di puntatori alle stringhe di: comando 1,
ridirezione e comando 2 estratti da buff
sprintf(prompt, "Prompt:> ");
write(1,prompt,10);

while((n=read(0,buff,80))!=0){
buff[n-1]='\0';

if ((strcmp(buff,"esci"))==0) {exit(0);}
i=0;
commands[i]=strtok(buff," ");

while(commands[i]!=NULL){
i++;
commands[i]=strtok(NULL," ");

}

if (i!=3) {printf("Uso: comando1 | comando2\n"); exit(1);}
if ((strcmp(commands[1],"|"))!=0) {
printf("Uso: comando1 | comando2\n"); exit(1);
}

int pid;
if ((pid=fork())==-1){ // prima fork
perror("Errore\n"), exit(1);
}
if (pid==0){
int fd[2];
pipe(fd);

if ((pid=fork())==-1) { // seconda fork
perror("Errore\n"), exit(1);
}
if (pid==0){
//comando1
close(1);
dup(fd[1]);
close(fd[1]);
close(fd[0]);
execlp(commands[0],commands[0], (char *) 0);
}
else{ //comando2
close(0);
dup(fd[0]);
close(fd[0]);
close(fd[1]);
execlp(commands[2],commands[2], (char *) 0);
}
}
else
pid=wait(NULL);
write(1,prompt,10);
lseek(0,0,SEEK_SET);
}

return 0;
}
m***@gmail.com
2014-07-15 09:21:09 UTC
Permalink
Post by Max
accetta 2 comandi e ridireziona l'output del primo come input del secondo.
Ho cercato di indentare un pochino meglio, c'� da dire che col copia e
incolla qualcosa si incasina comunque.
Per risolvere questo problema ti consiglio di usare un servizio di paste, dove poter mettere online il codice. In questo modo è più facile da leggere.
Post by Max
[...]
Non ho letto il codice a fondo, ma rinnovo il consiglio che ti ho dato prima: suddividi il codice in unità logiche (funzioni) che facciano una ben determinata operazione.

Questo non solo per evitare ripetizioni (nel tuo caso il codice per eseguire un processo esterno e per riportare un errore di comando invalido), ma anche per avere codice più leggibile dato che la funzione main si potrebbe ridurre a qualcosa del genere (pseudo codice):

int main() {
init_shell();

while ... {
parse_command();
if (<command="esci">) {
....
}
else ... {
spawn_command(command1, ...);
spawn_command(command2, ...);
...
}
else {
invalid_command();
}
}
}


Ciao Manlio
Max
2014-07-15 15:19:08 UTC
Permalink
Post by m***@gmail.com
Non ho letto il codice a fondo, ma rinnovo il consiglio che ti ho dato prima: suddividi il codice in unità logiche (funzioni) che facciano una ben determinata operazione.
int main() {
init_shell();
while ... {
parse_command();
if (<command="esci">) {
....
}
else ... {
spawn_command(command1, ...);
spawn_command(command2, ...);
...
}
else {
invalid_command();
}
}
}
Ciao Manlio
Ovviamente creare funzioni per gestire macro compiti rende molto più
leggibile e pulito il codice, oltre che più semplice da controllare.
Mi rendo conto che i miei esercizi, se tendono a superare le 10 righe di
codice, diventano facilmente un mappazzone (cit.) :-P

In realtà faccio cosi' per far prima, sicuramente se dovessi lavorare
seriamente ad un progetto farei come dici, ma al momento sto facendo
solo pratica con le system call, e voglio impadronirmene quanto prima
risparmiando il più tempo possibile :-)
Ovviamente sarebbe meglio iniziare subito col le buone abitudini, ma il
poco tempo per studiare mi frega.

Grazie per i preziosi consigli cmq, torneranno molto utili quando e se
mi troverò a fare progetti più "seri".

Loading...