2013-02-13 13 views
9

Mam zadanie, nad którym pracuję i mam trudności z jego wykończeniem. Chodzi o to, aby napisać program if.c, który wykonuje jeden program i jeśli mu się to uda, wykonuje drugi program. Powinienem tłumić standardowe wyjście pierwszego programu i wypuścić standardowe wyjście dla drugiego. Otrzymuję komunikat o błędzie podczas wielu testów. Na przykład: "./if echo no, echo yes" zwraca "echo: błąd zapisu: zły deskryptor pliku". Próbowałem znaleźć to, co robię źle online, ale bez powodzenia.W C, w jaki sposób mogę przekierować STDOUT_FILENO do/dev/null przy użyciu dup2, a następnie przekierować ponownie do pierwotnej wartości później?

Oto mój kod:

#include <fcntl.h> 
#include <sys/wait.h> 
#include <stdio.h> 
#include "tlpi_hdr.h" 

int main(int argc, char *argv[]) 
{ 
    if(argc < 4){ 
     fprintf(stderr,"Incorrect number of arguments.\n"); 
     exit(EXIT_FAILURE); 
    } 

    int thenArg = 0; 
    char then[4]; 
    strcpy(then,"then"); 
    for(int x=1; x<argc; x++){ 
     if(strncmp(argv[x], then, 4) == 0) thenArg = x; 
    } 

    if(thenArg == 0){ 
     fprintf(stderr,"No 'then' argument found.\n"); 
     exit(EXIT_FAILURE); 
    } 

    int save_out = dup(STDOUT_FILENO); 
    if(save_out == -1){ 
     fprintf(stderr,"Error in dup(STDOUT_FILENO)\n"); 
     exit(EXIT_FAILURE); 
    } 

    int devNull = open("/dev/null",0); 
    if(devNull == -1){ 
     fprintf(stderr,"Error in open('/dev/null',0)\n"); 
     exit(EXIT_FAILURE); 
    } 

    int dup2Result = dup2(devNull, STDOUT_FILENO); 
    if(dup2Result == -1) { 
     fprintf(stderr,"Error in dup2(devNull, STDOUT_FILENO)\n"); 
     exit(EXIT_FAILURE); 
    } 

    int program1argLocation = 1; 
    int program2argLocation = thenArg + 1; 
    int program1argCount = thenArg-1; 
    int program2argCount = argc-(program2argLocation); 
    char *program1args[program1argCount+1]; 
    char *program2args[program2argCount+1]; 

    for(int i=0; i<program1argCount; i++){ 
     program1args[i]=argv[program1argLocation + i]; 
    } 
    program1args[program1argCount] = NULL; 
    for(int i=0; i<program2argCount; i++){ 
     program2args[i]=argv[program2argLocation + i]; 
    } 
    program2args[program2argCount] = NULL; 

    pid_t pid = fork(); 
    int child_status; 
    switch (pid) { 
    case -1: 
     fprintf(stderr,"Fork failed\n"); 
     exit(EXIT_FAILURE); 

    case 0: //child 
     //child will run program 1 
     if(execvp(program1args[0],&program1args[0]) == -1){ 
      fprintf(stderr,"Program 1 Failed.\n"); 
      exit(EXIT_FAILURE); 
     } 

    default: //parent 
     //parent will run program2 
     pid = wait(&child_status); 

     if(WEXITSTATUS(child_status) == 0){ 
      dup2(save_out, STDOUT_FILENO); 

      int prog2status = execvp(program2args[0],&program2args[0]); 
      if(prog2status == -1) { 
       fprintf(stderr,"Program 2 failed.\n"); 
       exit(EXIT_FAILURE); 
      } 
     } 
    } 

} 
+0

'char następnie [ 4]; strcpy (następnie "wtedy"); 'jest przepełnieniem bufora. Dlaczego po prostu nie użyjesz 'if (0 == strcmp (argv [x]," then ")) lub' if (0 == strncmp (argv [x], "then", 4)) zamiast tego? – nneonneo

+0

Myślę, że próbowałem, że po raz pierwszy zaimplementowałem to i popadłem w jakiś błąd. Zapamiętam to i powrócę do niego następnym razem, gdy natknę się na to samo. Dziękuję Ci! Nie używane do C jeszcze, więc wszelkie dane wejściowe w ten sposób są świetne. – Frank

Odpowiedz

15

Twój błąd jest tutaj:

int devNull = open("/dev/null",0); 

Aby korzystać devNull jako STDOUT_FILENO, musi być otwarty do zapisu:

int devNull = open("/dev/null", O_WRONLY); 
+0

Dziękujemy! Rzeczywiście znalazłem to samo rozwiązanie chwilę przed odpowiedzią. Próbowałem cię upomnieć, ale najwyraźniej nie mogę tego zrobić. Jestem podekscytowany, aby w przyszłości wykorzystać więcej przepełnień stosu! To jest niesamowite źródło informacji. – Frank