The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
ввод-вывод в языке С, !*! Naiv, 26-Май-04, 15:40  [смотреть все]
Как из программы на C (именно на C) запустить какую-либо стандартную утилиту и результат ее работы направить не в консоль, а в буфер памяти программы?
  • ввод-вывод в языке С, !*! robmeister, 20:38 , 30-Май-04 (1)
    >Как из программы на C (именно на C) запустить какую-либо стандартную утилиту
    >и результат ее работы направить не в консоль, а в буфер
    >памяти программы?


    nu zapustit' ochen' prosto: vizovami funkcii klassa 'exec...' ili 'system' (esli est' u tebia takovie)
    a perenapravit' toje mojno standartnimi stredstvami... na freebsd ne znaiu a vot na windows eto bilo sdelat' prosto s pomoshiu api.

    • ввод-вывод в языке С, !*! Мартовский заец, 23:11 , 30-Май-04 (2)
      >>Как из программы на C (именно на C) запустить какую-либо стандартную утилиту
      >>и результат ее работы направить не в консоль, а в буфер
      >>памяти программы?
      >
      >
      Можно выложить во временный файл (типа > /tmp/tmp), потоv его читать
      Мона функцией popen() - запускает программу и возвращает FILE* дял интерфейса к ней
  • ввод-вывод в языке С, !*! jd, 03:55 , 31-Май-04 (3)
    С помощью примерно такой функции:

    int my_exec(char* const cmd, char* out, int bufsize)
    { pid_t pid;
      char* argv[4];  /* for child/execv() */
      int len;        /* for child/write() */
      int stat;       /* for parent/waitpid() */
      int ret=-1;     /* for parent return status */
      int p[2];       /* pipe */
      int tmp;

      if(!cmd)
        return -1;
      if(pipe(p)==-1)
        return -1;
      switch(pid=fork())
      { case -1:
          tmp=errno;
          close(p[0]);
          close(p[1]);
          errno=tmp;
          break;
        case 0:  /* Child */
          close(p[0]);
          close(0);
          close(2);
          open("/dev/null", O_RDONLY);
          open("/dev/null", O_WRONLY);
          dup2(p[1], 1);
          close(p[1]);
          argv[0]="sh";
          argv[1]="-c";
          argv[2]=cmd;
          argv[3]=NULL;
          execv("/bin/sh", argv);
          exit(1); /* execv() fails */
        default: /* Parent */
          close(p[1]);
          *out='\0';
          if(waitpid(pid, &stat, WUNTRACED)==pid)
          { if(WIFEXITED(stat))
            { ret=WEXITSTATUS(stat);
              if(out && bufsize)
              { int len=read(p[0], out, bufsize-1);
                if(len>=0)
                  out[len]='\0';
              }
            }
            else if(WIFSIGNALED(stat))
              ret=-2;
            else if(WIFSTOPPED(stat))
            { kill(pid, SIGKILL); /* or wait more??? */
              ret=-3;
            }
          }
          close(p[0]);
      }
      return ret;
    }

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

    • ввод-вывод в языке С, !*! klalafuda, 07:22 , 31-Май-04 (5)
      >
      >Писалось это немного под другую задачу и было чуть-чуть переделано, но вроде
      >работает. Разумеется понадобятся соответствующие заголовочники.

      идея верная, но реализация несколько ограничена :)


      1. нет проверки ошибочных ситуаций -> в случае чего, застрелитесь отслеживать ошибочные ситуации.
      2. жестко заданная последовательность "waitpid - read" -> может быть переполнение пайпа и потеря данных от клиента, равно как и просто блокировка клиента на заполненном пайпе -> deadlock.
      3. waitpid может вернуть не только pid (допустим, по приходу сигнала) -> потенциальная потеря дочернего процесса в виде зомби и потеря всех данных из пайпа.
      4. на stderr то-же бывает что сыплется интересная информация, а вы ее просто выкидываете в /dev/null. если уж не обрабатываете, то лучше хотя бы вообще не трогать.
      5. может быть еще что-то по мелочам.

      // wbr

      • ввод-вывод в языке С, !*! jd, 13:42 , 31-Май-04 (8)
        >идея верная, но реализация несколько ограничена :)
        Ну я же говорю, что писалось под другую задачу и что примерно такая функция. То есть это скорее информация для размышления. :)

        и потом:

        >1. нет проверки ошибочных ситуаций -> в случае чего, застрелитесь отслеживать ошибочные ситуации.
        если ошибка произойдёт именно где-то в функции, то errno добавит информации. Конечно неплохо бы добавить пару !разных! кодов возврата...

        >4. на stderr то-же бывает что сыплется интересная информация, а вы ее
        >просто выкидываете в /dev/null. если уж не обрабатываете, то лучше хотя
        >бы вообще не трогать.
        Добавить это при необходимости совсем не сложно. К тому же мне сначала показалось, что требовался только стандартный поток вывода. Sorry.

        А в остальном, выше я уже сказал, это просто пример вместо обычных man popen(3), man dup2(2), man pipe(2), которые разумеется тоже нужно изучить, но идея реализации бывает весьма кстати...

  • ввод-вывод в языке С, !*! klalafuda, 07:13 , 31-Май-04 (4)
    >Как из программы на C (именно на C) запустить какую-либо стандартную утилиту
    >и результат ее работы направить не в консоль, а в буфер
    >памяти программы?

    man popen(3)
    man dup2(2)

    // wbr

    • ввод-вывод в языке С, !*! klalafuda, 07:24 , 31-Май-04 (6)
      >>Как из программы на C (именно на C) запустить какую-либо стандартную утилиту
      >>и результат ее работы направить не в консоль, а в буфер
      >>памяти программы?
      >
      >man popen(3)
      >man dup2(2)

      ++man pipe(2)

      // wbr

  • ввод-вывод в языке С, !*! ACCA, 09:26 , 31-Май-04 (7)
    >Как из программы на C (именно на C) запустить какую-либо стандартную утилиту
    >и результат ее работы направить не в консоль, а в буфер памяти программы?

    Попробуй подумать над задачей. Зачем запускать из C стандартную утилиту, если для этого существует sh? Твоя главная программа должна быть на sh и организовывать взаимодействе между процессами.

    Каждая программа должен заниматься только своим участком работы, процессы очень посто и удобно взаимодействуют через stdin/stdout. В последний раз я делал exec из C в MS-Windows 3.0.

    • ввод-вывод в языке С, !*! Naiv, 14:47 , 31-Май-04 (10)
      это я не понял. мне в программе надо реализовать довольно большой алгоритм, который на sh не написать. в том числе проводить сложный поиск по текстовому файлу. я и планирую не писать подпрограммы для обработки текста на С, а вызывать стандартные утилиты типа grep или sed.

  • ввод-вывод в языке С, !*! Naiv, 14:41 , 31-Май-04 (9)
    я эту задачу реализовал так:

    FILE *f;
    char *command;
    char buffer[1024];

    f = popen (command,"r");
    while (1) {
      if ( fgets (buffer, 1024, f) == NULL )
                break;
    }
    pclose (f);





Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру