Хочу сделать так:с помощью функции popen() открыть /bin/bash на запись,записать туда допустим "uname -r " но вывод uname -r произвести не на stdout ,а на другой ф.дескриптор с помощью dup2():
printf(">>>> Opening stream popen <<<<\n"); FILE *fp,*lp; lp=fopen("output","w+"); char ch[20]; fp=popen("/bin/bash","w"); printf("Enter command\n"); scanf("%s",&ch); dup2(0,lp); dup2(1,lp); fprintf(fp,"%s",ch); pclose(fp); Но все равно выводится на экран а не в файл output! * |
Если я правильно понял логику Вашей программы, то ошибка в том, что dup2 вызывается после popen. Поскольку popen по сути fork, дескрипторы будут унаследованы нормальные (на stdout), а не переопределенные (в файл). И зачем Вы перенаправляете stdin (id=0)? Наверное, надо 1 и 2.
|
Я последовал вашему совету,но результат тот же!
Даже не работает такой код: FILE *fp; fp=fopen("output","w"); dup2(1,fp) dup2(2,fp); printf("HEllo"); почему так?Все равно на экран выводит! |
Неправильно указаны аргументы у dup2
Код:
#include <stdio.h> |
Вроде работает!
Скорее всего из-за dup2() - но ведь в мане сказано что первый параметр - это старый дескриптор,а второй - новый,на который надо все перенаправлять! И лучше использовать int lp=open()? |
В мане немного по-дургому написано. dup2 делает newfd копией oldfd, закрывая newfd, если это необходимо. Недопонимание возникает, если не знать, как работает просто dup(), а не dup2(). Так исторически сложилось...
Насчёт open и fopen - трудно сказть, что лучше. open универсальнее, но с ней немного труднее работать. |
Теперь у меня такая трабла:Я хочу ессно это с сетью связать,т.е типа telnet'a
сделать: Сервак: #define PORT1 1234 #define PORT2 4321 int main (void) { int acc; char buf[64]; int from_len; FILE *fp; fp=popen("/bin/sh","w");//открываем /bin/sh struct sockaddr_in serv,client; int s; s=socket(AF_INET,SOCK_STREAM,0); serv.sin_family=AF_INET; serv.sin_addr.s_addr=INADDR_ANY; serv.sin_port=htons(PORT1); bind(s,&serv,sizeof(serv)); int lis=listen(s,10); while(1) { from_len=sizeof(client); acc=accept(s,&client,sizeof(client));//принимаем коннект dup2(acc,1);//перенаправляем i/o dup2(acc,2);// while(1) { from_len=read(acc,buf,64);//принимаем команды и записываем в buf if(buf=="killbill") {//если получаем команду "killbill" то выходим break; } fprintf(fp,"%s",buf);//записываем команду в /bin/sh perror("Status"); } break; exit(0); } "stream.c" 44L, 791C written Клиент выглядит так же - цикл с посылкой и отправкой команды - но ничего не происходит!Как будто обе проги виснут!Иногда вылезает еррор Broken pipe |
0. Пользуйтесь тегом {{code}}
1. Приведите код клиента 2. Дескриптор 1 - stdout. В него только пишут. Вы из него читаете. То же касается и 2 - stderr. 3. Эффект зависания, кстати, будет всегда, поскольку Вы используете синхронную передачу данных. В результате, Ваша программа сервер будет жрать 100% CPU, если я ничего не путаю. Я пользуюсь select в таких случаях. 4. Брокен пип вылезает, очевидно, поле Ctrll+C? Если да, то так и должно быть, имхо. |
Это клиент;
Код:
#define PORT1 1234 Я немного переделал сервер,но все равно глючит: Код:
while(1) { |
Зачем bind в клиенте?
... Что-то я начинаю терять мысль. Вы мне даёте всё больше и больше кода, но какими-то кусками.Я по обрывкам кода не могу догадаться "а где тут глючит?" Давайте поконкретнее. У Вас проблема с сокетами или с пайпами? Это хоть и из одной оперы, но разные вещи. |
Я сам запутался.....
Прежде я решил сделать все сначала(ну в смысле не переделать) Сперва я сделал клиент - сервер,клиент просто передает одно сообщение(строку) серверу.Дальше я решил сделать цикл отправки и приема сообщений .Вроде получается. Но вот пара вопросов: Почему на код Код:
if(strcmp(s,"kill")==0) { Мне тогда выход из кллиента не сделать! И еще один вопрос - если я скажем сервер запустил,потом послал ему строку "kill",сервер выключился,то если сразу его врубить то он пишет "BIND() :Address already in use" и приходится просто немного ждать!Я ведь делаю в конце программы close(s) close(s_new) shutdown(....); в чем дело? Сейчас я постараюсь сам решить вопрос чтобы не сбивать с толко вас и себя.... Добавлено: так проблемму решил,т.е теперь клиент - сервак свободно обмениваются сообщениями. |
2hasherfrog: Ура почти получилось!
Теперь если я скажем посылаю серверу команду "uname" он обратно посылает "Linux" Но теперь вот что.Я максимум могу принимать одну строку,поэтому команда df вернет мне всего лишь одну строчку.Это происходит потому что я вызываю recv() только один раз - мне как я понял нужно сделать цикл с приемом сообщения....только вот не получается! Вот сервер в "кратком содержании": Код:
..... Теперь клиент Код:
while(1) { |
Насчёт получения только одной строки из ожидаемого множества. Тут уже немного зыбкая почва. Не пробовал. Точнее, не пробовал именно так. По-другому я делал. у меня тоже была проблема - приходила только одна строка, потом был длительный таймаут, потом я просил ещё рез и тут приходила куча - и задержавшиеся сообщения, и новые. Но это потому программа основывалась на QProcess и там странно организована работа с пайпами. Поскольку в данном случае всё "своё", надо подумать... Может дело в самих пайпах, а может, в неправильной работе в ними.
Как вариант 1: может, надо добавить флаг MSG_WAITALL в recv()? Как вариант 2: Работайте с select. Вот кусок моего старого кода от логгера: Код:
do { ЗЫ. Нда-с, не совсем понятно. fd[1] - конец трубы, из которой должна идти инфа. logger - класс логгера, не обращайте внимания. [s]Исправлено: hasherfrog, 10:13 10-06-2004[/s] |
ок,попробую разобратся......
|
У меня еще такой вопрос(надеюсь последний=))
После того как popen запускает прогу ,то после завершения проги посылается какой-нибудь флаг типа EOF или еще что-то?Так было бы очень удобно,ведь я б знал до какого места считывать строки из сокета... |
Вообще-то, хм... popen - это по сути, fork. Какая программа должна завершиться первой? Та, которая отпочковалась или та, которая слушает процесс?
В приведённом мной последнем куске кода строка if (retval == -1) break прекращает слушание, потому что программа-потомок судя по всему, окончила работу. feof для FILE* при этом вернёт true, кстати. Но лучше не рассчитывать на FILE*, а работать с select'ом Ей можно после этого выходить. Если же основная программа хочет выйти первой, то она просто должна посиснуть на проводе с помощью pclose. как pclose вернёт управление - потомка нет, можно и самой уходить. Надеюсь, мысль понятна... |
Так popen у меня запускается,и он я запускаю /bin/sh,которая вырубится если я пошлю скажем команду killpopen.А та утилита,которую я запускаю с помощью sh и должна что то вернуть в конце!Вот к чему я клоню!
У меня же такая схема: Сервак получает команду,записывает ее в fp,там /bin/sh форкает прогу какую-нибудь,прога все выводит на сокет - я со стороны клиента должен все что она вывела принять....... только я не знаю СКОЛЬКО раз мне нужно вызвать функцию recv,ведь мне данные приходят по строкам! а если бы в конце прога что-то посылала,то я мог бы сделать что-то вроде while(recved!=EOF) { recv(s,recved,sizeof(recved),0); printf("%s",recved); } Вот! p.s. ваша мысль плохо понятна(в смысле я плохо понимаю....) Добавлено: Это похоже примерно на это: сервак: char first[20]="aaaaaaaa"; char second[20]="bbbbbbb"; char third[20]="EOF"; send(first); send(second); send(third); клиент: while(recved!="EOF") { recv(&recved); printf(recved); } |
Всё ходим вокруг одного и того же.
Код:
do { |
Я вас начинаю понимать!
Возможно я просто использую неудобный механизм передачи - мысль с завершением самой /bin/sh понятна.т.е после записи команды в /bin/sh,я вырубаю коннект(pclose(fp)),соответственно на клиенте вырубается дескриптор сокета(select) а что бы послать следующую команду,нужно просто заново присоединится с серваком,и повторить цикл.......только бы это щас реализовать......... (p.s. надо бы зарегистрироватся...=)) |
Время: 17:03. |
Время: 17:03.
© OSzone.net 2001-