🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.perl
2 messages
2 total messages Started by Qrczak Tue, 14 Apr 1998 11:15
system "aaa|bbb|ccc" bez szela
#1221
Author: Qrczak
Date: Tue, 14 Apr 1998 11:15
121 lines
6068 bytes
Jeśli masz coś lepszego do roboty, to pomiń ten post, jako że nie jestem
w sytuacji bez wyjścia :-)

Mój skrypt na podstawie argumentów wywołania buduje sobie ciąg
połączonych rurkami programów do uruchomienia. Zastanawiałem się, czy by
nie spróbować samemu uruchomić te programy z odpowiednio przekierowanymi
stdin i stdout, zamiast zlecać to szelowi.

Założenia: W praktyce większość tych programów jest wołana z pełną
ścieżką i bez argumentów. Każdemu programowi przekazuję pewne dane
w zmiennej środowiskowej ARG. Tylko nieliczne programy będą dowolnymi
poleceniami szela (to te w nawiasach z poprzedniego mojego problemu).

Na razie buduję z tego jedną komendę szela. Argumenty dodaję mniej
więcej w taki sposób (do każdego członu pipelina (rurociągu?) osobno):
    $arg =~ s/(?=\W)/\\/g;
    $_ = "ARG=$arg $_";
(jeśli każemy bashowi uruchomić "ARG=wartość program argumenty",
to program ów dostanie zmienioną zmienną ARG w środowisku).

A gdyby tak samemu uruchomić każdy program, łącząc odpowiednio ich
wejścia i wyjścia, przekazując argumenty przez $ENV{ARG}...

Najpierw, co taka zmiana IMHO powinna dać:

Być może działałoby nieco szybciej. Ciąg ów jest uruchamiany dla każdego
przetwarzanego pliku, których może być więcej niż jeden. Szel byłby
odpalany tylko dla niektórych programów (dla tych w nawiasach, a i to
nie zawsze) - potencjalnie więcej razy, ale w praktyce najczęściej ani
razu.

Mniej byłoby eskejpowania i interpretowania symboli specjalnych.
Prawdopodobnie można by się postarać, żeby nigdzie nie były
interpretowane żadne symbole - mianowicie gdyby uruchamiać to przez:
    exec $program $program
Teraz trzeba eskejpować różne rzeczy w ARG. W praktyce zapewne nie
będzie żadnych niebezpiecznych znaków w ścieżce do programu, ale po co
niepotrzebnie ograniczać...

Ogólniej, ów szczególny przypadek odpalenia procesów (większość z pełną
ścieżką i bez argumentów, z ustawioną tylko zmienną ARG i odpowiednio
połączonymi stdin i stdout) byłby od razu implementowany tak jak wygląda
naprawdę, zamiast opisywać go tekstowo i kazać interpretować ten tekst
szelowi.

Może i to jest bardzo złośliwy przypadek, ale nie znalazłem lepszego:
W tym drugim podejściu zostałby wykryty błąd polegający na przekazaniu
programowi czegoś w stylu:
   (echo ")+cośtam+(echo ")
Obecnie jest to zamieniane na coś takiego:
   (echo ")|ARG= /ścieżka/cośtam|(echo ")
i w wyniku otrzymujemy jedną komendę wypisującą
')|ARG= /ścieżka/cośtam|(echo '. W drugim podejściu samemu
próbowalibyśmy odpalić wszystkie trzy programy i słusznie wyskoczyłby
błąd, taki jak przy próbie odpalenia /bin/sh -c '(echo ")'.

Ceną za to wszystko byłoby większe skomplikowanie skryptu. Nie wiem, czy
warto.

Dobra, tylko jak to zrobić? Próbowałem poczarować z otwieraniem
niby-pliku "-|", ale nie wyszły mi podłączenia stdin i stdout bez
ręcznego przepychania. To znaczy prawdopodobnie by to zadziałało, gdybym
pododawał coś w stylu print while <RURKA>, czego z oczywistych powodów
nie chcę robić. Czytałem w manie o niby-plikach ">&numer" i "<&=numer",
ale się zaplątałem, nic z tego nie wyszło i się poddałem...

Tak się składa, że niedawno na zajęciach (ten program jest akurat
mój prywatny) robiliśmy pierścień procesów połączonych rurkami w C
i napisałem to bez większych kłopotów, jednak wyszły z tego dość
skomplikowane akrobacje z pipami, forkami, closami i dupami (bez
skojarzeń). Myślałem teraz, że w perlu uda się bardzo podobną rzecz
zrobić prościej, a tu dupa, nie wyszło.

Jeśli komuś się chce i ma jakieś pomysły, jak by to w miarę prosto
zrobić, to proszę o wskazówki. Jeśli się uda to przerobić, to potestuję
szybkość i pewnie pozostanę przy szybszym rozwiązaniu. Powtarzam
w skrócie (pomijając $ENV{ARG}): Należy stworzyć ciąg procesów
połączonych rurkami. Każdy proces odpali coś np. execem, więc muszą być
połączone akurat przez STDIN i STDOUT.

Próbowałem mniej więcej w tym duchu:

sub wykonaj
{
    $program = shift;
    if (@_ && open RURKA, "-|")
    {
        # Tutaj trzeba by jakoś połączyć RURKĘ ze STDIN...
        wykonaj @_;
    }
    else { exec $program }
}

Niestety open RURKA, "-|" tworzy nowy deskryptor, więc pewnie nie tędy
droga. Ale którędy?

BTW: Wcześniejsza wersja tego wszystkiego była w bashu. Bez budowania
pojedynczej komendy do odpalenia - rekurencyjne funkcje basha połączone
|'ami, analiza napisów w stylu:

    while ! mamy "$FILTR1" && ! case "$FILTR1" in (*-*-*) false;; esac
    do
        : "${FILTR2:=${FILTR1##*-}}"
        FILTR1=${FILTR1%-*}
        FILTR2=${FILTR1##*-}-$FILTR2
    done

Przy każdym przetwarzanym pliku interpretowało to cały napis połączony
+'ami i -'ami od nowa. Ale działało (nie licząc drobnych błędów, które
później zauważyłem). Wtedy prawie nie znałem perla. Teraz to na niego
przetłumaczyłem - trochę krócej wyszło, też działa, ale zachciało mi się
sprytniej...

Skrypt ten i kilka innych można obejrzeć pod
http://qrczak.home.ml.org/programy/linux/konwert/konwert-1.2.tar.gz

-- 
                                 QRCZAK
    __("<              Marcin Kowalczyk
    \__/              qrczak@knm.org.pl
     ^^      http://qrczak.home.ml.org/
Re: system "aaa|bbb|ccc" bez szela
#1222
Author: Michal Mosiewicz
Date: Tue, 14 Apr 1998 13:36
17 lines
1370 bytes
Qrczak wrote:

> Tak się składa, że niedawno na zajęciach (ten program jest akurat
> mój prywatny) robiliśmy pierścień procesów połączonych rurkami w C
> i napisałem to bez większych kłopotów, jednak wyszły z tego dość
> skomplikowane akrobacje z pipami, forkami, closami i dupami (bez
> skojarzeń). Myślałem teraz, że w perlu uda się bardzo podobną rzecz
> zrobić prościej, a tu dupa, nie wyszło.

Jeśli chcesz zrobić to w Perlu, to używasz IPC::Open(2|3) i łączysz
strumienie tak jak w C przy pomocy pipe. 

Michał

-- 
WWW: http://www.lodz.pdi.net/~mimo  tel: Int. Acc. Code + 48 42 148340
add: Michal Mosiewicz  *  Bugaj 66 m.54 *  95-200 Pabianice  *  POLAND
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads