Аргументы C и execve (3)

Я работаю над проектом, который в основном делает то же самое, что и strace(1), используя ptrace(). В основном у нас есть программа controller.c, которая принимает исполняемый файл в качестве аргумента и выводит любые системные вызовы, сделанные исполняемым файлом (например, % controller ls -l). Мы используем execve() для запуска исполняемого файла, но у нас есть небольшие проблемы . execve принимает следующие аргументы

 execve( const char *filename, char *const argv[], char *const envp[] )

где filename в этом случае будет "ls", а argv[] - это список аргументов для данного имени файла. Итак, у нас есть что-то похожее на это (в файле C)

int main(int argc, char *argv[],char *envp[]){
  pid_t child;
  child = fork;

  if(/* CHILD */){
    ptrace(PTRACE_TRACEME,0, NULL, NULL);

    if(argc == 2) {
      execve(argv[1],NULL,envp);
    }
    else {
      execve( argv[1], /* ARGUMENT LIST */, envp);
    }

  } else /* PARENT */ {
    //PARENT CODE 
  }
}

Итак, если мы получим исполняемый файл, например controller ls -l, where argv[0] = "controller", argv[1] = "ls" и argv[2] = "-l", как мы можем передать правильный параметр в «СПИСОК АРГУМЕНТОВ» (где аргументы в этом случае просто "-l", но их может быть больше)?

В принципе, как нам инициализировать массив типа const char *, чтобы в массиве были значения аргументов для исполняемого файла? Нужно ли нам вообще беспокоиться о наличии дополнительных значений в массиве и только после argv для СПИСОК АРГУМЕНТОВ?

Спасибо за вашу помощь!


person user1348913    schedule 16.09.2012    source источник
comment
Я мало работаю с Си. Работает ли этот синтаксис для получения подмассива некоторого массива? (Я собираюсь попробовать)   -  person user1348913    schedule 17.09.2012
comment
Во-первых, вам вообще не нужен этот внутренний if/else, и во-вторых, почему бы просто не &argv[1] в качестве среднего аргумента для execve?   -  person Carl Norum    schedule 17.09.2012
comment
argv + n - это просто массив / указатель, который указывает на n-й элемент argv. Это эквивалент &argv[n].   -  person epsalon    schedule 17.09.2012


Ответы (1)


Вы можете просто передать argv + 1 (чтобы пропустить имя вашей программы). argv + 1 - указатель на массив, начиная со второго элемента argv, который является именем исполняемой программы. argv + 1 эквивалентно &argv[1], и вы можете использовать любой стиль, который вам больше нравится.

Как упоминалось в комментариях, в разделе 5.1.2.2.1 стандарта указано, что argv действительно заканчивается нулем. Приведенный ниже раздел сохранен для полноты.

В случае, если C не гарантирует, что argv завершается нулевым символом (и мне неясно, имеет это значение или нет), вы можете сделать:

char **new_argv = malloc((argc-1) * sizeof(char*));
for (int i = 0; i < argc - 1) new_argv[i] = argv[i+1];

и используйте new_argv для списка аргументов.

person epsalon    schedule 16.09.2012
comment
Я думаю, вы обнаружите, что C действительно гарантирует, что массивы argv и envp завершаются нулем. - person Neil; 17.09.2012
comment
@Neil - ты где-то нашел доказательства этого? Я просто взглянул на спецификацию, но ничего такого не бросилось мне в глаза. - person Carl Norum; 17.09.2012
comment
@CarlNorum: в ответе на этот вопрос упоминается, что в 5.1.2.2.1 стандарта указано, что argv имеет нулевое завершение, что это то, что я всегда считал правдой. envp должен заканчиваться NULL, чтобы можно было определить его конец. - person AusCBloke; 17.09.2012
comment
@AusCBloke, я сейчас смотрю на это и вижу строчку. Не знаю, как я это пропустил раньше - он смотрит мне прямо в лицо: argv[argc] должен быть нулевым указателем .. envp на самом деле не входит в него, так как это все равно не стандартный Си. - person Carl Norum; 17.09.2012