Отправляет email-рассылки с помощью сервиса Sendsay

Трубопровод в Linux

Привет всем.
С наступившим 2006.
С Рождеством.

Вопрос банальный.

Как в своей программе организовать прием из pipe.
Есть программа my_prog
Нужно что бы при 'cat filename | my_prog' она принимала данные.

Пытаюсь так:
int fd[2];
pipe(fd);
dup2(fd[0], 0);
close(fd[0]);
close(fd[1]);
read(0, .....);
В результате совсем не то, что ожидалось.
Если без примудростей:
read(0, .....);
то при 'my_prog' читает строку до Enter'а
А из трубы то же самое - не то, чего хочу.

Если можно, пример простой программки.
Рылся по исходникам. Ни .... не понял.
Всяк на свой лад.

Заранее спасибо.

Ответить   Fri, 6 Jan 2006 21:00:08 +0600 (#497927)

 

Ответы:

On Fri, 6 Jan 2006 21:00:08 +0600
Владимир Ковалев wrote:

Забудь про пайп и считай, что у тебя пользователь вводит даные в
программу, строчка за строчкой.

Фактически это означает открытие файла /dev/stdin и чтение его пока не
коничтся.

Ответить   Fri, 6 Jan 2006 18:36:30 +0300 (#497953)

 

On Fri, 6 Jan 2006 18:36:30 +0300
Vladimir Rusinov <vladim***@l*****.ru> wrote:

Спасибо за напоминание что в *nix все есть файл. Попробую и это.

Ответить   Sat, 7 Jan 2006 01:40:09 +0600 (#498061)

 

On Sat, 7 Jan 2006 01:40:09 +0600
Владимир Ковалев wrote:

Только открывать его не надо - при старте программы он и так открыт. И
если вы специально не укажете какой-либо указатель файла в функции
ввода/вывода, то будут использованы файлы stdin или stdout.

Кстати, также не стоит забывать, что в unix файл - это не просто
именованная запись данных на каком-либо носителе, это пожалуй
есдинственный способ ввода/вывода информации (если только вы не пишете
драйвер): любое устройство - файл, любое сетевое подключение - файл
(если только это не на низком уровне, что позволено только суперюзеру) и
т.д.

Ответить   Fri, 6 Jan 2006 23:27:34 +0300 (#498116)

 

On Fri, 6 Jan 2006 21:00:08 +0600
Владимир Ковалев <beaver***@n*****.ru> wrote:

Это вообще создает НОВЫЙ пайп, который вам, как я понимаю, совершенно не нужен.
'|' - символ, сигнализирующий башу о том что, необходимо создать такой вот пайп
и
перенаправить выходной поток первой программы во входной поток второй.

Ну, во такое точно работает:

//test1.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
int f;
char buf[1]={0};

f = open("./output", O_CREAT|O_WRONLY, S_IREAD|S_IWRITE);
while(read(0, buf, 1))
write(f, buf, 1);
}

$ gcc test1.c
$cat test1.c | ./a.out

Смотрим файлик ./output

Ответить   Matvey Fri, 6 Jan 2006 18:34:25 +0200 (#497963)

 

On Fri, 6 Jan 2006 18:34:25 +0200
Matvey <mathw***@l*****.ru> wrote:

Действительно, полез куда то не туда.

Почему до этого сам не додумался, не знаю.
Большое спасибо за наставление на путь праведный (ишь как завернул
в ночь под Рождество).

Еще раз спасибо. Тема закрыта.

Ответить   Sat, 7 Jan 2006 01:37:59 +0600 (#498059)

 

On Fri, 6 Jan 2006 21:00:08 +0600
Владимир Ковалев <beaver***@n*****.ru> wrote:

Просто читаем из stdin

#include <stdio.h>
int main()
{
char line[512];
while (fgets(line,512,stdin))
fputs(line,stdout);
}

Функция fgets используется для большей безопасности, в буфер не
запишется больше 512 символов.

Ответить   Dark Coder Fri, 6 Jan 2006 21:35:42 +0300 (#498092)

 

Привет всем.

Позволю себе возобновить тему.

А как определить: передают в программу данные из трубопровода (pipe) или
программа просто запущена из коммандной строки.

Навыки программирования в M$ системах не позволили узнать принципы
перенаправления ввода/вывода.

Решение естественно нужно на C (C++).

Заранее спасибо.

Ответить   Sun, 8 Jan 2006 19:59:43 +0600 (#498798)

 

On Sun, 8 Jan 2006 19:59:43 +0600
Владимир Ковалев <beaver***@n*****.ru> wrote:

А разница? Данные все равно принимаются из stdin.

Ответить   Dark Coder Sun, 8 Jan 2006 19:15:21 +0300 (#498838)

 

On Sun, 8 Jan 2006 19:15:21 +0300
Dark Coder <dcod***@k*****.ru> wrote:

Это понятно. Но в программе предусмотренна возможность чтения данных из файла
при указании имени файла в параметрах коммандной строки. При запуске программы
без имени файла предусмотрен прием данных из pipe. Но он имеет смысл только при
приеме потока. Ручной ввод данных в моем случае - вещь не нужная и бесполезная.

Кроме того обрабатываются некоторые параметры типа --version и --help, при
которых подразумевается вывод соответствущего сообщения и завершение программы.
Так же, при неправильных параметрах, происходит завершение программы с выдачей
сообщения в stderr.
При возможном (по закону Мерфи) неправильном вводе параметров вывод при
потоковой обработке будет совсем не тот, который ожидался.

Так вот, в случае my_prog | other_prog я допускаю обработку ключей типа
--version и --help. Однако при other_prog | my_prog, по моему мнению, более
приемлемым будет игнорирование некоторых ключей и использование значений по
умолчанию.

Для этого и надо определить: в потоке работает программа или нет (хотя бы для
второго случая).

Совсем забыл: программа анализирует файл и выдает результат анализа в виде
сообщения (зависящего от ключей коммандной строки) от одной строки до всего
файла.

Прошу меня извинить, что начинаю тему здесь-же, но кто нибудь подскажет аналоги
функций (не надо бросать в меня тухлых яиц и гнилых помидоров) M$ WinAPI
GetPrivateProfileString, GetPrivateProfileSection. Пол-года назад
помоему где то встречал, но не могу вспомнить и поиски результата не дали.
Подскажите хотя-бы название функции.

Ответить   Sun, 8 Jan 2006 23:29:29 +0600 (#498862)

 

Владимир Ковалев пишет:

Может быть это?

#include <unistd.h>

if (isatty(0)) {
// stdin - терминал
} else {
// stdin - файл или пайп
}

Ответить   Sun, 08 Jan 2006 19:40:56 +0200 (#498867)

 

On Sun, 08 Jan 2006 19:40:56 +0200
"Yuri N. Glibovetz" <inetbo***@g*****.com> wrote:

Спасибо. Понял. Работает.

Ответить   Mon, 9 Jan 2006 00:16:52 +0600 (#498879)

 

On Sun, 8 Jan 2006 23:29:29 +0600
Владимир Ковалев <beaver***@n*****.ru> wrote:

при

Не логично ли, если в строке аргументов есть имена файлов, обрабатываем
их; иначе обрабатываем данные из потока?
Попутно смотрим исходники more

Ответить   Dark Coder Sun, 8 Jan 2006 21:04:53 +0300 (#498870)

 

On Sun, 8 Jan 2006 21:04:53 +0300
Dark Coder <dcod***@k*****.ru> wrote:

Вариант первый: программа запущена без параметров.
Выдаем сообщение об использовании. Отслеживается по отсутствию параметров.
Вариант второй: программа запущена без параметров, но таким вот образом:
other_prog | my_prog.
Необходимо обработать входной поток при значениях по умолчанию.
Вообще, если указан файл и его можно открыть, то обрабатываем файл, иначе поток,
несмотря на наличие прерывающих работу ключей (номер версии, помощь). Однако
если мы не в потоке, то обработать соответствующие ключи.

PS. Как я забыл про more?

Ответить   Mon, 9 Jan 2006 00:33:31 +0600 (#498889)

 

В сообщении от 1136755769 секунд после начала Эпохи Владимир Ковалев написал(а):

Его вообще не должно быть, так как сообщение об ошибке идет на stderr.

А вот это лишнее. По моему это мусор, который никому не нужен и только
загрязняет код программы. Ладно, вывод usage при отсутствии аргументов
и канала на stdin, еще приносит небольшую пользу пользователю.

Ответить   Konstantin Korikov Mon, 9 Jan 2006 00:36:33 +0200 (#498993)

 

On Mon, 9 Jan 2006 00:36:33 +0200
Konstantin Korikov <lostcl***@i*****.ua> wrote:

по

Тем не менее, наличие обработки этих ключей - требование GNU к софту.

Ответить   Matvey Mon, 9 Jan 2006 13:22:41 +0200 (#499151)

 

В сообщении от 1136805761 секунд после начала Эпохи Matvey написал(а):

Так я и имел введу игнорирование опций `--help' и `--version'. Если
быть более точным: я считаю излишним игнорирование опций `--help' и
`--version' когда на стандартном вводе программный канал (pipe). Какой
идиот будет использовать вызов:

$ other_prog |my_prog --version

?

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

Ответить   Konstantin Korikov Mon, 9 Jan 2006 16:26:20 +0200 (#499251)

 

Привет всем.
Приношу свои извинения за самоволное изменение следования цитат в письме
Константина. Просто таким образом мне проще будет высказать свою мысль.

Первая цитата:

^^^^
ведь
Здесь ни чего личного. В данном случае все поняли, что подразумевалось.
Но глупые программы, воспринимающие входные данные буквально (внимание:
неологизм - "байтально" ;) ), этого не поймут. А с учетом стандарта кодирования
GNU, применение для разбора параметров коммандной строки функции getopt_long
подразумевает некоторую реакцию на неправильно введенные параметры. И если
программа запущена следующим образом:
$ my_prog --(что-то неправильное) --(что-то правильное)
то можно смело отругать пользователя за неверно введенные параметры и завершить
программу.
А если программа запущена так:
$ other_prog | my_prog --(что-то неправильное) --(что-то правильное)
или (еще веселее) так:
$ other_prog1 | my_prog --(что-то неправильное) --(что-то правильное) |
other_prog2
то в этом случае имеет смысл проигнорировать неправильно введенные параметры,
принимая во внимание только правильные и параметры по умолчанию.

Вторая цитата:

Здесь я согласен полностью. Для указанных ключей можно и отказаться от их
игнорирования, но их дополнительная обработка у меня лично добавила менее 10
строк в код программы.

Вод здесь переходим к последней цитате:

Добавление большого количество параметров ведь тоже раздует программу, причем,
скорее всего, гораздо значительнее, чем обработка некоторых (специфических)
парметров. Кроме того, насколько я понимаю, утилиты в *nix системах тем и
отличаются, что, по возможности, делают что-то одно, но качественно. При грубом
приближении можно сказать примерно так: "Одна задача - одна программа".

Впрочем весь этот разговор уже значительно отклонился от правил листа
comp.soft.linux.discuss. При желании можно перенести тему в discuss или
попробовать оживить comp.soft.prog.linux где для этой темы самое подходящее
место.

С искренним уважением.

Ответить   Mon, 9 Jan 2006 22:05:14 +0600 (#499298)

 

Прошу прощения:

конечно же в debate.

Ответить   Mon, 9 Jan 2006 22:26:06 +0600 (#499310)

 

В сообщении от 1136838366 секунд после начала Эпохи Владимир Ковалев написал(а):

Перенесено в дебаты.

Ответить   Konstantin Korikov Tue, 10 Jan 2006 11:06:59 +0200 (#499541)

 

Ответить   Konstantin Korikov (#499540)

 

Ответить   Konstantin Korikov (#499930)

 

Ответить   Konstantin Korikov (#500264)

 

Ответить   Konstantin Korikov (#501384)

 

Ответить   Matvey (#501374)

 

Ответить   Konstantin Korikov (#501383)

 

Ответить   Dark Coder (#499830)

 

Ответить   Konstantin Korikov (#499928)

 

Ответить   Konstantin Korikov (#499929)