2015-09-20 2 views
0

Обратите внимание, что это домашнее задание. Цель состоит в создании интерфейса оболочки.Почему я не вижу результаты execvp() в командной строке?

Вопрос в том, почему я не могу увидеть результаты execvp() на терминале при вводе команды?

Код выглядит следующим образом:

int getcmd(char *prompt, char *args[], int *background) 
{ 
    int length, i = 0; 
    char *token, *loc; 
    char *line; 
    size_t linecap = 0; 

    printf("%s", prompt); 
    length = getline(&line, &linecap, stdin); 



    if (length <= 0) { 
     exit(-1); 
    } 

    // Check if background is specified.. 
    if ((loc = index(line, '&')) != NULL) { 
     *background = 1; 
     *loc = ' '; 
    } else 
     *background = 0; 

while ((token = strsep(&line, " \t\n")) != NULL) { 
    for (int j = 0; j < strlen(token); j++) 
     if (token[j] <= 32) 
      token[j] = '\0'; 
     if (strlen(token) > 0) 
      args[i++] = token; 
     } 

    return i; 
} 

Следующая моя главная функция:

int main() 
{ 
    char *args[20]; 
    int bg; 

    while(1){ 
     bg = 0; 
     int cnt = getcmd("\n>> ", args, &bg); 
     pid_t child_pid = fork(); 
     //for (int i = 0; i < cnt; i++) 
     // printf("\nArg[%d] = %s", i, args[i]); 

     // a negative number will be returned only 
     // if the forking was unsuccessful i.e 
     // no child process is cloned from the original 
     // process 
     if(child_pid < 0){ 
      fprintf(stderr, "Fork Failed"); 
      return 1; 
     } 

     // the return value for a successful fork of a child is 0 
     else if(child_pid == 0){ 
      execvp(args[0], args); 
     } 

     // this is the parent process here 
     else { 
      int status; 
      if (bg == 1){ 
       printf("\nBackground enabled..\n"); 
       getcmd("\n>> ", args, &bg); 
      } 
      else{ 
       printf("\nBackground not enabled \n"); 
       waitpid(child_pid, NULL, 0); 
      } 
     } 
    } 
} 

Когда я запускаю мой код, он компилирует и дает мне подсказку (>>). Когда я запускаю команду, такую ​​как ls, она только печатает фон не включен (так как я не указал &). Однако, если я делаю команду ps на другом терминале, я вижу, что есть новый процесс. Я что-то пропускаю? Почему я не могу увидеть результат ls, когда я даю его в качестве аргумента для системного вызова execvp()?

+2

Does getcmd() '' NULL'-terminate 'args'? – alk

+2

Также вызовы 'perror (« exec failed »); exit (1); 'сразу после вызова' execvp() 'может помочь. – alk

+0

Да getcmd() null terminates and perror ("exec failed") возвращает: exec failed: Плохой адрес – Ralph

ответ

2

getcmd() не хватает инициализации line. Он должен сначала указать на NULL:

char *line = NULL; 

От getline()'s man-page:

Если linep указывает на указатель NULL, новый буфер будет выделен.


Также, пожалуйста, где вы NULL -terminate args. Элемент args, следующий за последним, получающий значение, назначенное getcmd(), должен указывать на NULL.

Вы можете убедиться, что это так на инициализацию всех args элементов NULL в самом начале по

char * args[20]; 
for (size_t i = 0; i < 20; ++i) 
{ 
    args[i] = NULL; 
} 

Для тестирования можно инициализировать args как этого

char * args[] = { 
    "ls", 
    "ls", 
    "-alrt", 
    NULL /* a must */ 
} 

От execvp()s man-page:

T он execv(), execvp() и execvP() функции обеспечивают массив указателей на нуль-терминатором строки , которые представляют собой список параметров, доступных для новой программы. Первый аргумент, по соглашению, должен указывать на имя файла, связанное с исполняемым файлом. Массив указателей должен быть be завершен указателем NULL.

+0

Он по-прежнему дает ту же ошибку, независимо от того, инициализирую ли я линию или нет. – Ralph

+0

@ Ralphyabro: см. Мой обновленный ответ. – alk

+0

Отлично, сейчас он работает. Я до сих пор не понимаю, почему вы сначала должны были инициализировать их до NULL. – Ralph

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