Quine создать и выполнить файл

Я создаю Quine на C, и мне нужно создать новый файл c а затем скомпилируйте его и выполните.

Я сделал простой фрагмент, чтобы понять, почему он не работает.

Я предполагаю, что execv запускает команду до того, как fprintf закончит писать, но я положил сон, и он тоже не работал.

(Все мои извинения за этот самый уродливый код, но это не цель)

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
    char *cmd[100]= {"sh", "-c", "\"gcc tmp.c && ./a.out\""};

    fprintf(fopen("tmp.c", "w"), "#include <stdio.h>\nint main(){puts(\"Hello World\");}");
    execv("/bin/sh", cmd);
    return (0);
}

Вывод

sh: gcc tmp.c && ./a.out: No such file or directory

Любая идея ?


person albttx    schedule 04.11.2016    source источник
comment
Разве цель программы quine не воссоздавать свой собственный исходный код в качестве вывода при запуске? См. Программа, которая выводит собственный исходный код и Программа, которая печатает себя, даже если исходный файл удален в качестве примера; в списке «Похожие вопросы» на RHS есть еще.   -  person Jonathan Leffler    schedule 05.11.2016


Ответы (2)


Ваш массив аргументов cmd не заканчивается указателем NULL. Кроме того, у него есть проблема с цитатой.

Вы также должны закрыть файл перед вызовом execv(). Причина, по которой вы ничего не видите в файле, заключается в буферизации fprintf(). Пока все открытые файлы закрываются при выходе из процесса, вы выполняете до этого.

int main(void)
{

   char *cmd[]= {"sh", "-c", "gcc tmp.c && ./a.out", (char*)0};

    FILE *fp = fopen("tmp.c", "w");
    if (!fp) {
       perror("fopen");
       exit(1);
    }

    fprintf(fp, "#include <stdio.h>\nint main(){puts(\"Hello World\");}");
    fclose(fp);
    execv("/bin/sh", cmd);
    perror("execv");
    return (0);
}
person P.P    schedule 04.11.2016

когда вы вызываете свою оболочку в обычной оболочке, вы делаете:

sh -c "gcc tmp.c && ./a.out"

(sh -c gcc tmp.c && ./a.out работает в моей оболочке, но не в вашей, как указано в ваших комментариях)

Таким образом, это означает, что вы должны передавать аргументы не так часто, как execv, или они интерпретируются как один аргумент, как если бы вы это сделали:

sh -c \""gcc tmp.c && ./a.out\""

предлагаемое исправление:

char *cmd[100]= {"sh", "-c", "gcc tmp.c && ./a.out", NULL};

Кстати: не забудьте поставить fclose файл, иначе tmp.c может быть равно нулю. BTW2: благодаря usr, NULL отсутствовал: отредактировано.

Полностью исправленное предложение кода:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
    char *cmd[100]= {"sh", "-c", "gcc tmp.c && ./a.out", NULL};
    FILE *outfile = fopen("tmp.c", "w");
    if (!outfile) {printf("cannot open output file\n");exit(1);}

    fprintf(outfile, "#include <stdio.h>\nint main(){puts(\"Hello World\");}");
    fclose(outfile);  // required else file remains open
    execv("/bin/sh", cmd);
    return (0);
}
person Jean-François Fabre    schedule 04.11.2016
comment
sh -c gcc tmp.c && ./a.out не работает в моей оболочке - person albttx; 05.11.2016
comment
Я просто подумал, что должен использовать system() ! - person albttx; 05.11.2016
comment
да, system тоже хорош. Но цитата будет действовать так же. Смотрите и тестируйте мое редактирование. Цитирую ад!!! - person Jean-François Fabre; 05.11.2016
comment
с вашим вариантом файл не заполняется - person albttx; 05.11.2016
comment
не моя вина: проверьте мое редактирование. вы не закрываете свой выходной файл. - person Jean-François Fabre; 05.11.2016
comment
@Jean-FrançoisFabre Массив cmd также должен заканчиваться нулевым указателем. - person P.P; 05.11.2016