2013-04-18 19 views
9

Ecco il codice che implementa la chiamata di sistema cd utilizzando C. Il problema con questo codice è che non sta entrando nella condizione ifif(strcmp(buffer,"cd") == 0) e non riesco a capire perché.implementazione chiamata di sistema cd usando C- condizione if

#include<sys/stat.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 
#include<dirent.h> 
#include<error.h> 

#define BUFFERSIZE 20 
int main(){ 

char *args[80]; 
char buffer[BUFFERSIZE]; 
char *prompt = "OS"; 
char *a = ">"; 
printf("%s%s",prompt,a); 
fgets(buffer, BUFFERSIZE, stdin); 

char *tok; 
tok = strtok (buffer," "); 


while(buffer != NULL){ 
    buffer[strlen(buffer)-1] = '\0'; 
    pid_t pid; 
    pid = fork(); 
    if(pid < 0){ 
     fprintf(stderr, "Fork failed"); 
     return 1; 
    } 
    else if(pid == 0){ 

     if(strcmp(buffer,"cd") == 0){ 
     tok = strtok(NULL,"\n"); 
     cd(tok); 
     } 
     printf("%s%s",prompt,a); 
     fgets(buffer, BUFFERSIZE, stdin); 
    } 
    else{ 
    wait(NULL); 
    } 
} 
return 0; 
} 


int cd(char *pth){ 
    char path[1000]; 
    strcpy(path,pth); 

    static char *prompt = "OS"; 
    static char *a = ">"; 
    char *token; 

    char cwd[256]; 
    getcwd(cwd,sizeof(cwd)); 

    strcat(cwd,"/"); 
    strcat(cwd,path); 
    chdir(cwd);  

    printf("%s-%s%s",prompt,path,a); 
    return 0; 
    } 
+1

D: Hai guardato il valore di "temp" nel tuo debugger di scelta? È infatti uguale a "cd"? Ecco un buon tutorial per "gdb": http://www.cs.cmu.edu/~gilpin/tutorial/ – paulsm4

+4

1) 'buffer [strlen (buffer) -1] = '\ 0';' Cattiva abitudine, IMHO . strlen() * potrebbe * restituire zero. 2) 'tok = strtok (temp," ");' tok shadows un altro 'tok' – wildplasser

+2

' cd' * non può * essere un programma standalone, deve essere un built-in di shell. Cosa stai cercando di fare esattamente? –

risposta

6

Hanno aggiornato la logica dopo i suggerimenti degli altri.

C'è non c'è bisogno di un processo figlio qui. Se si desidera il multitasking, utilizzare i thread. Child process may be required for process running in background.

Il seguente programma sta lavorando per me:

#include <stdio.h> 

#include <sys/stat.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 
#include <dirent.h> 
//#include <error.h> 

int hasPrefix(char const *, char const *); 
int cd(char *pth); 

#define BUFFERSIZE 200 
int main(){ 

    char buffer[BUFFERSIZE]; 
    char *prompt = "OS"; 
    char *a = ">"; 

    char *tok; 
    tok = strtok (buffer," "); 


    while(buffer != NULL){ 
     bzero(buffer, BUFFERSIZE); 
     printf("%s%s",prompt,a); 
     fgets(buffer, BUFFERSIZE, stdin); 
     if(hasPrefix(buffer,"cd") == 0){ 
      tok = strchr(buffer,' '); //use something more powerful 
      if(tok) { 
       char *tempTok = tok + 1; 
       tok = tempTok; 
       char *locationOfNewLine = strchr(tok, '\n'); 
       if(locationOfNewLine) { 
        *locationOfNewLine = '\0'; 
       } 
       cd(tok); 
      } 
     }else{ 
      system("ls"); //for testing the CWD/PWD 
     } 
    } 
    return 0; 
} 

int hasPrefix(char const *p, char const *q) 
{ 
    int i = 0; 
    for(i = 0;q[i];i++) 
    { 
     if(p[i] != q[i]) 
      return -1; 
    } 
    return 0; 
} 

int cd(char *pth){ 
    char path[BUFFERSIZE]; 
    strcpy(path,pth); 

    char cwd[BUFFERSIZE]; 
    if(pth[0] != '/') 
    {// true for the dir in cwd 
     getcwd(cwd,sizeof(cwd)); 
     strcat(cwd,"/"); 
     strcat(cwd,path); 
     chdir(cwd); 
    }else{//true for dir w.r.t./
     chdir(pth); 
    } 

    return 0; 
} 
+0

grazie mille .. è stato molto utile ... – urwaCFC

+3

Cosa c'è di sbagliato nello standard 'strcmp()' che richiede di scriverne uno proprio. – Barmar

+0

Non avresti dovuto suggerire di usare un 'mystrcmp 'in homebrew, e hai inavvertitamente dimostrato il perché. Lo standard 'strcmp' non ha nulla di sbagliato qui, mentre il tuo lo fa. Ha due bug: 1. Se 'q' è una stringa vuota (' "" "), riferirai sempre l'uguaglianza e 2. Se la stringa' p' ha la stringa 'q' come prefisso ma ha un finale di caratteri aggiuntivi riferirà l'uguaglianza Sarebbe stato meglio [tagliare la linea di nuova da 'fgets()' con questa copertina singola (http://stackoverflow.com/a/28462221/2809095). –

1

Credo che il problema è a causa di questa linea:

buffer[strlen(buffer)-1] = '\0'; 

Questo sostituisce l'ultimo carattere di buffer con un carattere null. Quindi se buffer contiene "cd", ora contiene solo "c" (poiché il carattere null è il terminatore di stringa in C).

Non sembra esserci alcuna necessità per questa affermazione, basta rimuoverlo.

+0

Appena inciampato su questo, e questa è davvero l'unica risposta corretta. –

2

Usa

... 
if(strncmp(buffer,"cd",2) == 0){ 
... 

invece. È buono per confrontare prefissi di lunghezza arbitraria. Mette anche un limite alle dimensioni delle stringhe. Non c'è bisogno di costruire la propria routine di confronto.

Hai altri problemi altrove nel codice, ma questi possono essere indirizzati separatamente.

Problemi correlati