Перенаправление stdin и stdout? - PullRequest
0 голосов
/ 07 ноября 2018

Поэтому я пытаюсь перенаправить ввод-вывод для чтения команды из файла, а затем, когда пользователь запускает команду вывода, он выводит скомпилированную команду в выходной файл.

Например на терминале:

./run 2 < test.txt // This would take file using dup and take the input

Затем, когда вы хотите вывести компиляцию:

./run 1 > output.txt // and it would put into an output file

Пока я знаю, как выводить в файл, но моя проблема с вводом. как получить команду из файла с помощью функции dup2()? Я пытался исследовать это, но безуспешно.

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

char inputForOutput[100];

void functionOutput(int argc, char **argv){

    int ofd; //Init of file desc.

    ofd = open(argv[1], O_CREAT|O_TRUNC|O_WRONLY);

    dup2(ofd, 1);//Duplicates to stdout

    system("ls");//Copies commnd given to output_file
}

//Function is called when argument number is == 1
void functionInput(int argc, char **argv){
    FILE *ifd;
        printf("\n %s \n ", argv[2]);
    ifd = fopen(argv[2] , "r");
    if (ifd == NULL){
        perror("No file found");
        exit(1);
    }
    fscanf(ifd,"%s",inputForOutput);
    printf("\n**%s**\n",inputForOutput);
}

int main(int argc, char **argv)
{
    int output;
    int input;
    output = strcmp("1", argv[1]);
    input = strcmp("2" ,argv[1]);
    if (output == 0 ) { //Fail safe for number of arguments
        functionOutput(argc, argv);
    }
    else if ( input == 0){
        functionInput(argc, argv);
    }
    else{
        fprintf(stderr, "How to use: %s function output_file\n", argv[0]); // FAIL SAFE IF INPUT DOES NOT MATCH BOTH FUNCTIONS
    }
    return 0;
}

Ответы [ 3 ]

0 голосов
/ 08 ноября 2018

Чтобы перенаправить ввод и вывод, используйте этот формат

myprogram > out.txt < in.txt //read from in.txt, write to out.txt
myprogram < in.txt > out.txt //read from in.txt, write to out.txt
myprogram < in.txt //redirect stdin only
myprogram > out.txt //redirect stdout only
myprogram //no redirection
...

Это должно работать с любой программой. Пример:

int main(void)
{
    char buf[1000];
    if(fgets(buf, sizeof(buf), stdin))
        printf("write: %s\n", buf);
    return 0;
}

Для перенаправления стандартного ввода / вывода в программе используйте стандартный метод

freopen("output.txt", "w", stdout);
printf("Testing...");
fclose(stdout);

freopen("input.txt", "r", stdin);
char buf[100];
fgets(buf, sizeof(buf), stdin);
fclose(stdin);

В качестве альтернативы, установите FILE *fin = stdin; FILE* fout = stdout; для перенаправления в обратном направлении.

Далее, чтобы написать программу с использованием элементов argv, всегда сначала проверяйте argc. Код ниже показывает пример.

#include <stdio.h>
#include <string.h>

int redirect(int argc, char **argv, int *index)
{
    //no more redirection!
    if(*index >= argc)
        return 1;

    //not enough parameters
    if(*index + 1 >= argc)
    {
        printf("wrong usage\n");
        return 0;
    }

    if(strcmp(argv[*index], "<") == 0)
    {
        *index++; //next parameter is to redirect input
        if(!freopen(argv[*index], "r", stdin))
            printf("error, redirect input failed");
    }
    else if(strcmp(argv[*index], ">") == 0)
    {
        *index++; //next parameter is to redirect output
        if(!freopen(argv[*index], "w", stdout))
            printf("error, redirect output failed");
    }
    else
    {
        printf("wrong usage\n");
        return 0;
    }

    return 1;
}

int main(int argc, char **argv)
{
    int index = 1;
    if(!redirect(argc, argv, &index))
        return 1;

    if(!redirect(argc, argv, &index))
        return 1;

    //read
    char buf[1000];
    if(fgets(buf, sizeof(buf), stdin))
    {
        //write
        printf("write: %s\n", buf);
    }

    fclose(stdin);
    fclose(stdout);

    return 0;
}
0 голосов
/ 08 ноября 2018

Если я понимаю ваш вопрос, и вы хотите запустить свою программу по существу в двух разных режимах, (1) вы хотите получить ввод, если есть входные данные, которые должны быть приняты для stdin; и (2) если нет ожидающего ввода, вы хотите сделать вывод, тогда select/pselect или poll - это то, что вы ищете.

Например, select позволяет вам проверить, есть ли ввод, готовый для чтения в дескрипторе файла (или наборе дескрипторов), и вернет количество дескрипторов с ожиданием ввода (или -1 и установкой * 1008). * по ошибке). Вы можете просто использовать STDIN_FILENO (a / k / a fd 0), чтобы проверить, есть ли ввод на stdin, например,

#include <stdio.h>
#include <unistd.h>         /* for STDIN_FILENO */
#include <sys/select.h>     /* for pselect   */

int input (int filedes)
{
    fd_set set;

    /* declare/initialize zero timeout */
    struct timespec timeout = { .tv_sec = 0 };

    /* Initialize the file descriptor set. */
    FD_ZERO (&set);
    FD_SET (filedes, &set);

    /* check whether input is ready on filedes */
    return pselect (filedes + 1, &set, NULL, NULL, &timeout, NULL);
}

int main (void)
{
    if (input (STDIN_FILENO))
        puts ("doing input routine");
    else
        puts ("doing output routine");

    return 0;
}

( примечание: со страницы руководства "select() использует время ожидания, равное struct timeval (с секундами и микросекундами), в то время как pselect() использует struct timespec (с секундами и наносекундами) ). ")

Пример использования / Вывод

$ ./bin/select_peekstdin < file
doing input routine

$ ./bin/select_peekstdin
doing output routine
0 голосов
/ 07 ноября 2018

С functionOutput() у вас есть хорошая первая попытка записать вывод системной команды в файл.На самом деле, , что - это функция, вызываемая, когда первый аргумент равен 1, поэтому вы можете обновить свой комментарий.Кроме того, вы создаете файл с именем, хранящимся в argv[1], который мы уже знаем как 1, поэтому он, вероятно, не выполняет то, что вы ожидаете, и вы, вероятно, хотите:

ofd = open(argv[2], O_CREAT|O_TRUNC|O_WRONLY);

С functionInput() вы читаете первую запись без пробелов из файла.Если вы говорите ему прочитать файл, который вы выводите с помощью функции functionOutput(), это, вероятно, будет (частично) имя первого файла, который был указан как ls.

Iмне неясно, что ты хочешь делать, а это не так.Если вы хотите узнать, какой командой вы управляли, чтобы сгенерировать вывод, эта информация не доступна из самого файла, потому что вы ее там не записали.Если это то, что вам нужно, вы можете рассмотреть возможность записи команды в качестве первой строки файла с последующим выводом.Затем, когда вы прочитаете его, вы можете предположить, что первая строка - это команда run, за которой следует вывод этой команды.

...