2015-04-08 3 views
0

Я написал программу (с кодом из SO), которая делает printenv | sort | less, и теперь я должен реализовать обработку ошибок. Как это можно сделать? Программа должна потерпеть неудачу изящно, например, когда переданы неправильные аргументы.Как должна моя программа вести обработку ошибок?

#include <sys/types.h> 
#include <errno.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
struct command 
{ 
    const char **argv; 
}; 
/* Helper function that spawns processes */ 
int spawn_proc (int in, int out, struct command *cmd) { 
    pid_t pid; 
    if ((pid = fork()) == 0) { 
     if (in != 0) { 
      dup2 (in, 0); 
      close (in); 
     } 
     if (out != 1) { 
      dup2 (out, 1); 
      close (out); 
     } 
     return execvp (cmd->argv [0], (char * const *)cmd->argv); 
    } 
    return pid; 
} 
/* Helper function that forks pipes */ 
int fork_pipes (int n, struct command *cmd) { 
    int i; 
    int in, fd [2]; 
    for (i = 0; i < n - 1; ++i) { 
     pipe (fd); 
     spawn_proc (in, fd [1], cmd + i); 
     close (fd [1]); 
     in = fd [0]; 
    } 
    dup2 (in, 0); 
    return execvp (cmd [i].argv [0], (char * const *)cmd [i].argv); 
} 

int main (int argc, char ** argv) { 
    int i; 
    if (argc == 1) { /* There were no arguments */ 
     const char *printenv[] = { "printenv", 0}; 
     const char *sort[] = { "sort", 0 }; 
     const char *less[] = { "less", 0 }; 
     struct command cmd [] = { {printenv}, {sort}, {less} }; 
     return fork_pipes (3, cmd); 
    } 
    if (argc > 1) { /* I'd like an argument */ 

     if (strncmp(argv[1], "cd", 2) && strncmp(argv[1], "exit", 2)) { 
      char *tmp; 
      int len = 1; 
      for(i=1; i<argc; i++) 
      { 
       len += strlen(argv[i]) + 2; 
      } 
      tmp = (char*) malloc(len); 
      tmp[0] = '\0'; 
      int pos = 0; 
      for(i=1; i<argc; i++) 
      { 
       pos += sprintf(tmp+pos, "%s%s", (i==1?"":"|"), argv[i]); 
      } 
      const char *printenv[] = { "printenv", 0}; 
      const char *grep[] = { "grep", "-E", tmp, NULL}; 
      const char *sort[] = { "sort", 0 }; 
      const char *less[] = { "less", 0 }; 
      struct command cmd [] = { {printenv}, {grep}, {sort}, {less} }; 
      return fork_pipes (4, cmd); 
      free(tmp); 
     } else if (! strncmp(argv[1], "cd", 2)) { /* change directory */ 
      printf("change directory to %s\n" , argv[2]); 
      chdir(argv[2]); 
     } else if (! strncmp(argv[1], "exit", 2)) { /* change directory */ 
      printf("exit\n"); 
      exit(0); 
     } 
    } 
    exit(0); 
} 
+2

заменил [тег: ubuntu] на [tag: linux], поскольку в вашем вопросе не было ничего конкретного Ubuntu. – 0xC0000022L

+2

Определите возможные случаи ошибок, спроектируйте полезные тесты для них внутри вашей программы в соответствующее время, а затем выйдите с разными кодами выхода. Может быть сообщение об ошибке для stderr. Что-нибудь более конкретное? – Minix

ответ

2

Это будет откровенно немного больно, чтобы пройти через вашу программу и исправить все эти недостающей обработки ошибок ошибок постфактум. Гораздо лучше было бы написать правильный код с самого начала! Более того, у вас больше ошибок, чем просто отсутствие обработки ошибок. Я не просматривал весь ваш код, но на первый взгляд я уже видел одно использование неинициализированной локальной переменной (in в fork_pipes используется до его установки). Любой достойный компилятор с включенными предупреждениями поймал бы это.

Как прямой ответ на ваш вопрос, вам просто нужно пройти через каждый вызов системного вызова или функции библиотеки, который способен возвращать ошибки, видеть, проверяете ли вы их и добавляете проверки, если они уже нет. fork, malloc, dup2 - все.

Смежные вопросы