URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 2971
[ Назад ]

Исходное сообщение
"ввод-вывод в языке С"

Отправлено Naiv , 26-Май-04 15:40 
Как из программы на C (именно на C) запустить какую-либо стандартную утилиту и результат ее работы направить не в консоль, а в буфер памяти программы?

Содержание

Сообщения в этом обсуждении
"ввод-вывод в языке С"
Отправлено robmeister , 30-Май-04 20:38 
>Как из программы на 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.


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

"ввод-вывод в языке С"
Отправлено jd , 31-Май-04 03:55 
С помощью примерно такой функции:

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 , 31-Май-04 07:22 
>
>Писалось это немного под другую задачу и было чуть-чуть переделано, но вроде
>работает. Разумеется понадобятся соответствующие заголовочники.

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


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

// wbr


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

и потом:

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

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

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


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

man popen(3)
man dup2(2)

// wbr


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

++man pipe(2)

// wbr


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

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

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


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


"ввод-вывод в языке С"
Отправлено Naiv , 31-Май-04 14:41 
я эту задачу реализовал так:

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

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