Возникли проблемы с пониманием формата аргументов execvp()

#c #exec

Вопрос:

В настоящее время я работаю над проектом, в котором мне нужно использовать execvp. У меня возникли проблемы с использованием этого, потому что я не могу заставить его работать, так что, возможно, это как-то связано с тем, как я передаю аргументы.
Мне нужно выполнить программу, предоставленную нам нашими профессорами.
Аргументами для выполнения этой программы являются:
$ ./bin/aurrasd-filters/aurrasd-gain-double < samples/sample-1-so.m4a > output.m4a
Вот как я пытался привести аргументы, чтобы это сработало:

 int main () {
    char *agr2[] = {"./bin/aurrasd-filters/aurrasd-gain-double", "<", "samples/sample-1-so.m4a", ">", "output.m4a", NULL};
    if (!fork()) {
        execvp(*agr2, agr2);
    }
    else {
        wait(NULL);
        printf("Terminated"n);
    }
    return 0;
}
 

Поместило бы это все аргументы в правильное место? Кажется, я не могу понять, в чем ошибка.

Комментарии:

1. Я думаю, что ваша проблема в том, что execvp не реализовано перенаправление ввода-вывода, поэтому аргументы < и > и их аргументы передаются непосредственно программе как часть ее аргументов, а это не то, что она ожидает. Измените ./bin/aurrasd-filters/aurrasd-gain-double /bin/echo , чтобы увидеть это своими глазами. Это не ответ, потому что исправление зависит от более подробной информации о том, что вас просят сделать для вашего задания; Я больше не могу вам помочь без полной расшифровки инструкций, которые вам были даны.

2. Привет, сработало бы, если бы я использовал execv() вместо этого? Из того, что я понимаю, это позволило бы мне сделать это правильно?

3.Нет, ни одна из функций, имя которой начинается с exec , не реализует перенаправление ввода-вывода. system делает (вроде того), но для этого требуется одна строка аргумента, а не вектор аргументов, и он сам разветвляется, так что вполне вероятно, что вы не должны его использовать. Я на самом деле держу пари, что цель задания-научить вас вручную выполнять перенаправление ввода-вывода, что слишком большой вопрос для этого сайта. Опять же, мне нужно увидеть полную расшифровку инструкций, которые вам дали, чтобы помочь еще больше.

4. Если вы хотите самостоятельно обработать перенаправление ввода/вывода, вам нужно будет использовать pipe в сочетании с одним из dup системных вызовов, чтобы stdin и stdout ссылались на нужные файлы. Т. Е. вам нужно будет сделать то же самое, что делает оболочка.

5. @zwol Большое вам спасибо, я ничего не знал о перенаправлении ввода-вывода.. потратив некоторое время на чтение, я наконец-то смог сделать то, что хотел.

Ответ №1:

Что мне нужно было сделать, так это перенаправить stdout и stdin. < и > не были аргументами в пользу исполняемого файла, как я думал.
Это выглядело бы примерно так:

 int main () {
    char *arg[] = {"./bin/aurrasd-filters/aurrasd-gain-double", NULL};
    char *input = "samples/sample-1-so.m4a";
    char *output = "output.m4a";
    if (!fork()) {
        int input_f;
        if ((input_f = open(input, O_RDONLY)) < 0) {
            perror("Error opening input file");
            return -1;
        }
        dup2(input_f, 0);
        close(input_f);
       
        int output_f;
        if ((output = open(output, O_CREAT | O_TRUNC | O_WRONLY)) < 0) {
            perror("Error creating output file");
            return -1;
        }
        dup2(output_f, 1);
        close(output_f);
        execvp(*arg, arg);
        _exit(0);
    }
    else {
        wait(NULL);
    }
    return 0;
}
 

Как упоминалось выше @zwol, нам нужно обработать перенаправление ввода-вывода, я делаю это с помощью dup2() функции, устанавливая входной файл как stdin и создавая выходной файл и устанавливая его как stdout.
Это сработало для меня, может быть, это поможет кому-то в будущем..