execvp(): нет такого файла или каталога?

По какой-то причине execvp() не находит команды (например, ls, pwd и т. д.) в моем файле PATH, который включает /bin. Поскольку у меня есть настроенный псевдоним терминала с ls, я использую pwd и т. д. для тестирования (а также новую машину с Linux), но я продолжаю получать это для вывода:

gcc main.c
./a.out

What would you like to do?
ls
arg[0]: ls

arg[1]: (null)
arg[2]: (null)
arg[3]: (null)
arg[4]: (null)
arg[5]: (null)
arg[6]: (null)
arg[7]: (null)
arg[8]: (null)
arg[9]: (null)
before exec
after exec
ERROR: No such file or directory

Вот код:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

/* 
Write a c program that runs a command line program with exactly one command line argument. It should work as follows:
Prompts the user for a program to run via the command line.
Reads in that line (using fgets) and parses it to be used by one of the exec functions.
Runs the command using exec
You do not need to fork off a separate process and wait, the purpose of this assignment is only to parse a single line of input and run a program once.
*/

int main() {
  printf("\nWhat would you like to do?\n");

  char* input = malloc( 100 ); //100 character string for input
  fgets(input, 100, stdin); //reads from stdin (terminal input "file")

  //parses command in input (max of 8 flags)
  int number_of_args = 10;

  char *args[number_of_args];

  //puts cmd && flags in args
  int i = 0;
  for(; i < number_of_args; i++) {
    args[i] = strsep( &input, " ");
    printf("arg[%i]: %s\n", i, args[i]);
  }
  args[number_of_args - 1] = 0; //last element for execvp must be NULL;
  //  printf("nullify final index -> args[%i] = %s\n", number_of_args - 1, args[number_of_args -1]);

  printf("before exec\n");
  int e = execvp( args[0], args);
  printf("after exec\n");
  if(e < 0)
    printf("ERROR: %s\n", strerror(errno));

  return 0;
}

РЕДАКТИРОВАТЬ: Подумал, что было бы неплохо включить и мой PATH:

echo $PATH
/usr/local/bin:/usr/local/bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

person CodeSammich    schedule 14.11.2015    source источник


Ответы (1)


fgets() считывает символ новой строки, если в буфере есть свободное место. Поэтому, когда вы вводите ls, это на самом деле ls\n. Очевидно, что execvp() не может найти такую ​​команду и не работает. Таким образом, решение состоит в том, чтобы удалить завершающую новую строку, если таковая имеется.

char *p = strchr(input, '\n');
if (p)  *p = 0;

Вы также должны использовать argc для обработки аргументов (если вы читаете команды и аргументы через аргумент main()), а не принимать какие-то фиксированные числа. Или просто разорвите цикл, когда strsep() вернет NULL в первый раз. Технически ваш код вызывает неопределенное поведение, когда вы печатаете все эти нулевые строки.

person P.P    schedule 14.11.2015
comment
Это объяснило бы дополнительную новую строку! Я ломал голову, пытаясь понять, почему. Благодарю вас! - person CodeSammich; 14.11.2015