2013-04-18 10 views
9

Oto kod, który implementuje wywołanie systemowe cd za pomocą C. Problem z tym kodem polega na tym, że nie wchodzi on w stan if stanu if(strcmp(buffer,"cd") == 0) i nie mogę zrozumieć, dlaczego.implementowanie wywołania systemowego cd przy użyciu C- jeśli warunek

#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

Pytanie: Czy sprawdziłeś wartość "temp" w swoim wybranym debugerze? Czy w rzeczywistości jest równa "cd"? Oto dobry samouczek dla "gdb": http://www.cs.cmu.edu/~gilpin/tutorial/ – paulsm4

+4

1) 'buffer [strlen (buffer) -1] = '\ 0';" Bad habit, IMHO . strlen() * może * zwrócić zero. 2) 'tok = strtok (temp," ");' tok cienie innego 'tok' – wildplasser

+2

' cd' * nie może * być samodzielnym programem, musi to być wbudowana powłoka. Co dokładnie próbujesz zrobić? –

Odpowiedz

6

Zaktualizowałem logikę po sugestiach innych osób.

Istnieje nie ma potrzeby, aby proces potomny tutaj. Jeśli chcesz wielozadaniowości, użyj wątków. Child process may be required for process running in background.

Poniższy program pracuje dla mnie:

#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

dziękuję milionowi .. to było bardzo pomocne ... – urwaCFC

+3

Co jest nie tak ze standardowym 'strcmp()', które wymaga napisania własnego. – Barmar

+0

Nie powinieneś sugerować używania "tajemniczego" homebrew i nieumyślnie zademonstrowałeś dlaczego. Standardowy "strcmp" nie ma tu nic złego, podczas gdy twój robi. Ma dwa błędy: 1. Jeśli 'q' jest pustym ciągiem znaków (' "" '), zawsze zgłaszasz równość i 2. Jeśli ciąg' p' ma ciąg 'q' jako przedrostek, ale zawiera dodatkowe znaki , zgłosi równość. Byłoby lepiej [odciąć znak nowej linii od 'fgets()' z tą jedną linią] (http://stackoverflow.com/a/28462221/2809095). –

1

Myślę, że problem jest z powodu tej linii:

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

ten zastępuje ostatni znak buffer z pustym znakiem. Więc jeśli buffer zawierał "cd", zawiera teraz tylko "c" (ponieważ znak null jest terminatorem ciągu w C).

Wydaje się, że to stwierdzenie nie jest potrzebne, po prostu je usuń.

+0

Natknąłem się na to, a to naprawdę jedyna poprawna odpowiedź. –

2

Zastosowanie

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

zamiast. Dobrze jest porównywać przedrostki o dowolnej długości. Ustawia także limit rozmiaru łańcucha. Nie ma potrzeby tworzenia własnej procedury porównywania.

Masz inne problemy w innym miejscu kodu, ale można je rozwiązać osobno.

Powiązane problemy