LINUX.ORG.RU

Возврат строки из программы, использующей ncurses


0

0

Никак не придумаю, как просто осуществить сабж.
Есть простая программа на ncurses. Весь результат её работы - строка символов, которая должна стать доступна запустившему программу скрипту для bash'а.

Если надо возвращать целое - то в программе return i,
в скрипте беру $?.
А со строкой - непонятно. Попробовал выдать её printf'ом и поймать в скрипте, запуская программу так:
XXX=$(prog_name)
Но такой запуск скрывает весь вывод ncurses.
Можно, конечно, просто записывать строку в файл, но не хочется.

Какие могут быть решения?

временный файл или пайп.

MikeDM ★★★★★
()

Почему бы тебе так же как и в случае с возвратом целого, не использовать переменную окружения?

man setenv ;)

Cy6erBr4in ★★★
()
Ответ на: комментарий от Cy6erBr4in

> временный файл
Не хочу зря теребить винт :-)

> или пайп
перенаправить вывод проги в другую, которая установит переменную окружения?
Не совсем понял.

> Почему бы тебе так же как и в случае с возвратом целого, не 
> использовать переменную окружения?
Наверное, так и надо, но почему-то не выходит:

--- test.c ---
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  if(setenv("X", "qwerty", 1) != 0 ) {
    fprintf(stderr, "error");
  }

  return 0;
}

--- run ---
!/bin/bash

declare X="unchanged"
gcc -Wall -o ./test.elf ./test.c && ./test.elf && echo $X

--- результат ---
$ ./run
unchanged

sergey_feo
() автор топика
Ответ на: комментарий от Cy6erBr4in

>> Почему бы тебе так же как и в случае с возвратом целого, не использовать переменную окружения?

Переменную окружения родительского процесса изменить насколько я знаю невозможно.

Deleted
()
Ответ на: комментарий от Deleted

Судя по-всему очень похоже на то :( бяда прям тогда... чёб такого придумать...

Cy6erBr4in ★★★
()

у тебя два потока- stdout и stderr. Можешь один для отрисовки, второй строку возвращать, но это криво :). fifo (или как оно там называется, забыл уж всё) тебя спасёт. или shared memory. Или пайп. много способов и они не такие уж сложные.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

FIFO, разделяемая память и каналы - все они вроде бы предназначены
для обмена между двумя программами, когда обе работают. А надо, чтобы
информация была доступна после работы программы.

Вроде бы dialog делает что-то похожее на то, что надо. И у него есть опция

--output-fd fd
  Direct output to the given file descriptor. Most  dialog scripts
  write to the standard error, but error messages may also be written 
  there, depending on your script.

И такая:

--stdout
  Direct  output to the standard output.  This option is provided for 
  compatibility with Xdialog, however using it in portable scripts is 
  not recommended, since curses normally writes its screen updates
  to the standard output.

Т.е. надо просто вывести строку в stderr, и проследить, чтобы больше
ничего туда не попало?
Вообще, это тоже не совсем правильно. Ламерский вопрос: можно ли 
создать аналог stdout чтобы вывести строку в него и подхватить
результат в скрипте, не попортив ncurses'овский stdout? Точнее,
как в программе создать такой поток?

sergey_feo
() автор топика
Ответ на: комментарий от sergey_feo

>> FIFO, разделяемая память и каналы - все они вроде бы предназначены для обмена между двумя программами, когда обе работают. А надо, чтобы информация была доступна после работы программы.

AFAIK разделяемая память доступна пока работает хотя-бы один процесс который её "разделяет". С fifo/пайпами сложнее - их никак (почти) не передать из дочернего процесса в родительский.

>> Ламерский вопрос: можно ли создать аналог stdout чтобы вывести строку в него и подхватить результат в скрипте, не попортив ncurses'овский stdout? Точнее, как в программе создать такой поток?

Можно создать пайп в родительском процессе и передать дескриптор дочернему процессу. Так например можно передать пароль в pppd через плагин passwordfd, чтобы не светить его в выводе ps. В bash'е есть такая возможность - с помощью перенаправления в /dev/fd/ (этого пути реально нет, перенаправление туда только баш понимает), но например в debian'е это возможность обрезана мейнтейнерами (зачем кстати?). Так что лучше написать этот скрипт на perl'е например.

И вообще, зачем нужен этот скрипт и что это всё будет делать? Подозреваю что задачу можно решить без таких мощных костылей со скриптами.

Deleted
()

Писать в другой дескриптор и читать из него же?

#include <unistd.h>
#include <string.h>

int main(int argc, char** argv)
{
    const char* m1 = "to stdout\n";
    const char* m2 = "to stderr\n";
    const char* m3 = "to another fd\n";

    write(1, m1, strlen(m1));
    write(2, m2, strlen(m2));
    write(10, m3, strlen(m3));

    return 0;
}


$ ./a.out
to stdout
to stderr

$./a.out 10>&1
to stdout
to stderr
to another fd

kondor ★★★
()
Ответ на: комментарий от kondor

>> Писать в другой дескриптор и читать из него же?

Этот пайп (10) умрёт при завершении программы и прочитать его убедт невозможно. Чтобы этого не произошло - нужно открыть его в родительском процессе.

Deleted
()
Ответ на: комментарий от kondor

> write(10, m3, strlen(m3));

А теперь используем эту программу (допустим, называется test.elf) вот
так:

--- скрипт ---
#!/bin/bash

declare X="unchanged"

exec 3>&1; X="`./test.elf 10>&1 1>&3`"; exec 3>&-;
echo ==$X==

И вуаля:

--- результат ---

to stdout
to stderr
==to another fd==

Хитроумная конструкция с exec'ом позаимствована с
http://www.opennet.ru/openforum/vsluhforumID1/47070.html.
Похоже, что тут:
- первый exec делает доступным дескриптор 3,
перенаправленный на экран;
- выходная строка программы (ради чего всё и затевается)
направляется в stdout, чтобы захватилось в X;
- stdout программы при этом прячется в поток 3,
направленный на экран
- дескриптор 3 прибивается.
Причём stdout для дескриптора 3 и для программы вроде
разные.
Так я понимаю то, что получилось? :-)


> И вообще, зачем нужен этот скрипт и что это всё будет
> делать? Подозреваю что задачу можно решить без таких
> мощных костылей со скриптами.

Это всё сюда: http://www.linux.org.ru/view-message.jsp?msgid=2810424
Хочется 3 программки:

1) автоматическая определялка профиля.
2) выводилка менюшки.
3) переключалка профилей.

Изучаю ncurses, делая себе менюшку. Задача - передача строки с именем профиля из меню в переключалку. Можно было взять dialog, но его внешний вид мне не нравится и захотелось построить небольшой
учебный велосипед :-)

И ещё: а насколько законно вот так брать - и писать по дескриптору 10?
Не надо его как-то перед этим попросить у системы - вдруг он ей нужен?
sergey_feo * (*) (01.07.2008 21:59:26)

sergey_feo
() автор топика
Ответ на: комментарий от sergey_feo

> FIFO, разделяемая память и каналы - все они вроде бы предназначены для обмена между двумя программами, когда обе работают. А надо, чтобы информация была доступна после работы программы.

Есть еще один из способов IPC, называется queue. Он примечателен тем свойством, которое тебе и нужно.

smh ★★★
()
Ответ на: комментарий от sergey_feo

> FIFO, разделяемая память и каналы - все они вроде бы предназначены для обмена между двумя программами, когда обе работают. А надо, чтобы информация была доступна после работы программы.

так ты считай и сохрани, естественно fifo это не persistent storage. Задача-то данные получить а не сохранить.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

>И ещё: а насколько законно вот так брать - и писать по дескриптору 10? >Не надо его как-то перед этим попросить у системы - вдруг он ей нужен?

Мануалов чтение тебе поможет, падаван.

anonymous
()
Ответ на: комментарий от anonymous

Красноглазие свое победить ты должен.

anonymous
()
Ответ на: комментарий от anonymous

>>И ещё: а насколько законно вот так брать - и писать по дескриптору
>>10? Не надо его как-то перед этим попросить у системы - вдруг он ей
>>нужен?

> Мануалов чтение тебе поможет, падаван.

Разные мануалы смотрел я, но ответа на вопрос этот не нашёл пока.

sergey_feo
() автор топика
Ответ на: комментарий от sergey_feo

> FIFO, разделяемая память и каналы - все они вроде бы предназначены
для обмена между двумя программами, когда обе работают. А надо, чтобы
информация была доступна после работы программы.

Для разделяемой памяти это не так. Выделенный блок может существовать в системе даже в том случае, если нет ни одного процесса, который его использует. NB: при использовании разделяемой памяти любой вменяемый программист должен помнить о Race condition.

В данном же конкретном случае можно написать очень простой демон-диспетчер, который по запросу будет принимать нужные данные через FIFO и по запросу отдавать. Типа кладовщика :) Он может жить независимо от процесса создающего контент и процессов, этот контент потребляющих.

А еще проще не парить мозги и писать в файл, предварительно залочив его (опять таки - Race condition!). Кода минимум, но в ущерб быстродействию.

bon
()
Ответ на: комментарий от bon

Интересно, а D-BUS - это не почти такой демон? Или он не умеет работать кладовщиком?

sergey_feo
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.