Dlaczego ed nie można wyjść z Cc?

20

Program ed, minimalny edytor tekstu, nie może zostać zamknięty, wysyłając mu przerwanie za pomocą Ctrl- C, zamiast tego drukując komunikat o błędzie „?” do konsoli. Dlaczego nie edkończy się po otrzymaniu przerwania? Z pewnością nie ma powodu, dla którego tajemniczy komunikat o błędzie jest bardziej przydatny niż samo wyjście. Takie zachowanie prowadzi wielu nowych użytkowników do następującego rodzaju interakcji:

$ ed
hello
?
help
?
exit
?
quit
?
^C
?
^C
?
?
?
^D
$ su
# rm -f /bin/ed

Takie tragiczne marnotrawstwo - łatwe do uniknięcia, jeśli edzwyczajnie zgodzi się na przerwanie.

Innym upartym programem wykazującym podobne zachowanie, lessktóry również nie wydaje się mieć zbyt dużego powodu do ignorowania C-c. Dlaczego te programy po prostu nie podpowiedziały?

Lily Chung
źródło
4
Aplikacje interaktywne to nie to samo co nieinteraktywne. Zachowanie Ctrl-C, do którego jesteś przyzwyczajony, jest domyślne dla nieinteraktywnych. Te interaktywne mogą nadpisywać zachowanie Ctrl-C do własnych celów.
jw013,
4
Również nie jestem pewien, czy żart
jw013
@ jw013 Tak, „typowa sesja” była żartem (z jakiegoś powodu nie mogłem jej znaleźć), ale moje pytanie jest poważne. Nie rozumiem, dlaczego te aplikacje zastępują zachowanie Ctrl-C, jeśli tak naprawdę nie zapewnia niczego pożytecznego.
Lily Chung,
1
Ponieważ to pytanie pojawia się jako najlepsza odpowiedź w wyszukiwarce Google na „jak wyjść z edycji”, chciałbym dodać tutaj, że jest to po prostu „q”, po którym następuje powrót. Wielu Bothans zginęło, by dostarczyć nam te informacje.
Dmitri

Odpowiedzi:

19

Ctrl+ Cwysyła SIGINT . Konwencjonalną czynnością dla SIGINT jest powrót do pętli najwyższego poziomu programu, anulowanie bieżącego polecenia i wejście w tryb, w którym program czeka na następne polecenie. Tylko nieinteraktywne programy powinny umrzeć z powodu SIGINT.

Jest więc naturalne, że Ctrl+ Cnie zabija ed, ale powoduje, że powraca do pętli najwyższego poziomu. Ctrl+ Cprzerywa bieżącą linię wprowadzania i wraca do monitu ed.

To samo dotyczy mniej: Ctrl+ Cprzerywa bieżące polecenie i powoduje powrót do wiersza polecenia.

Z przyczyn historycznych ed ignoruje SIGQUIT ( Ctrl+ \). Normalne aplikacje nie powinny wychwytywać tego sygnału i pozwolić sobie na zakończenie, z zrzutem rdzenia, jeśli jest włączony.

Gilles „SO- przestań być zły”
źródło
@Kzqai Nie, normalne aplikacje nie powinny przechwytywać SIGQUIT, jest to wyjście awaryjne.
Gilles „SO- przestań być zły”
Ach, gotcha. W porządku, schowane.
Kzqai,
18

Unix V7 ed(1)kod źródłowy jest prymitywne 1762-linia C Program wystarczy kilka uwag, z których jeden jest to wysoce pouczające komentarz nagłówka:

/*
 * Editor
 */

Biorąc pod uwagę, że sam kod źródłowy nie przedstawia żadnego uzasadnienia, otrzymasz go tylko od autora programu.

edzostał pierwotnie napisany przez Kena Thompsona w zespole PDP-11 , ale tak naprawdę trzeba porozmawiać z kimkolwiek, kto go przetransportował do C. To mógł być Dennis Ritchie , ponieważ stworzył C dla Uniksa i był jednym z wielu, którzy używali C do uczynić Unix przenośnym na maszyny inne niż PDP. Dr Ritchie nie jest już w pobliżu, aby odpowiedzieć na takie pytania.

Moja lektura kodu sugeruje, że zrobiono to, aby zachować zawartość wewnętrznej kopii edytowanego dokumentu. Zauważysz, że inne edytory tekstu również nie umierają Ctrl-C.

Oto, co eddziała na Ctrl-C:

onintr()
{
    signal(SIGINT, onintr);
    putchr('\n');
    lastc = '\n';
    error(Q);
}

(Tak, K&R C .. Nie potrzebujemy żadnych specyfikacji typu powrotu ani deklaracji parametrów steenkin).

Przetłumaczone na angielski ed:

  1. Ponownie rejestruje procedurę obsługi sygnału.

    (Unix nie otrzymał sygnałów automatycznego resetowania aż do 4.3BSD , w połowie lat 80.)

  2. Zapisuje nowy wiersz i pamięta, że ​​to zrobił, za pomocą zmiennej globalnej lastc.

    ( ed.cma około sześćdziesięciu zmiennych globalnych).

  3. Wywołuje error()funkcję, która słynie niewiele więcej niż drukowanie ?, z perspektywy użytkownika.

Innymi słowy, mówi: „Tak naprawdę nie chciałeś tego zrobić, prawda?”

Warren Young
źródło
2
Warto również zauważyć, że wiele edytorów tekstu nie wychodzi z Control-C. Vim też nie. Nano też nie. Nie sądzę, że emacs też tak robi, ale nie mam go zainstalowanego do testowania.
derobert,
3
@derobert Vi traktuje Ctrl + C w sposób uniksowy: wróć do najwyższego poziomu. Emacs ma własne skróty klawiszowe ze względu na swoje pochodzenie inne niż Unix; odpowiednikiem Ctrl + C w Uniksie jest Ctrl + G (postać dzwonka - zadzwoń do komputera, aby go przerwać)
SO Gillesa - przestań być zły ”
@derobert: Sprawiedliwy punkt. Dodałem to do odpowiedzi.
Warren Young,
2
@Gilles: Jednym z efektów ubocznych wywołanie error(s)w ed.cjest powrót do głównej pętli procesu obróbki. Robi to za pomocą longjmp()połączenia. wzdrygam się
Warren Young,
1
Dziękuję za szczegóły i lekcję historii. To była świetna lektura!
alichaudry
7

ed, podobnie jak inne programy interaktywne, użyj Ctrl+, Caby przerwać zadania samego programu.
Jest to bardzo podobne do normalnego przypadku, w którym przerywa zadanie uruchomione w powłoce - polecenie.

Z perspektywy użytkownika oba warianty są bardzo podobne. Obsługa sygnału jest inna: w zwykłym przypadku sygnał SIGINTjest wysyłany do procesu pierwszoplanowego, do uruchomionego polecenia, a polecenie obsługuje je, wychodząc.
W przypadku ed, sygnał jest wysyłany do procesu pierwszego planu, edinstancji. Jeśli uruchomione jest zadanie ed, zostanie ono przerwane i wyświetlony zostanie monit. Jeśli nie ma uruchomionego zadania, nic się nie zmienia.

Zauważ, że powłoka również nie wychodzi z Ctrl+ C, tak jak ed. I że wychodzi na Ctrl+ D. Znowu tak jaked

Volker Siegel
źródło
3

Istnieją trzy sygnały, na których edzależy:

  1. INT
  2. HUP
  3. QUIT

Specyfikacja POSIXed mówi o nich:

SIGINT

edNarzędzie musi przerwać swoją bieżącą działalność, pisać ciąg ?\nna standardowe wyjście i powrót do trybu poleceń (patrz sekcja rozszerzonego opisu).

SIGHUP

Jeśli bufor nie jest pusty i zmienił się od ostatniego zapisu, ednarzędzie podejmie próbę zapisania kopii bufora w pliku. Najpierw ed.hupnależy użyć pliku wymienionego w bieżącym katalogu; jeśli to się nie powiedzie, należy użyć pliku wymienionego ed.hupw katalogu o nazwie HOMEzmiennej środowiskowej. W każdym przypadku ednarzędzie zakończy pracę bez zapisywania pliku do aktualnie zapamiętanej nazwy ścieżki i bez powrotu do trybu poleceń.

SIGQUIT

edNarzędzie musi zignorować to wydarzenie.

Niezależnie od tego, edjakiej implementacji używasz, jest ona zgodna ze specyfikacją POSIX w odniesieniu do INTsygnału (który Ctrl+Cwysyła).

Pod tym względem edytor zachowuje się jak interaktywna powłoka, która również nie kończy się po odebraniu INTsygnału. Inne edytory, takie jak vii nanorobi to samo.

Kusalananda
źródło
1
Niektóre implementacje programu celowo zaprzeczają POSIX, więc może być przydatne wyjaśnienie uzasadnienia standardu / kosztu złamania go w tym przypadku. stackoverflow.com/questions/38605463/…
sourcejedi
1
@sourcejedi Standard nie mówi nic o sygnałach w uzasadnieniu. Nie znalazłem żadnego uzasadnienia mówiącego o tym, dlaczego standard jest przestrzegany w dostępnych źródłach ed. Zachowuje się podobnie jak powłoka, która również nie kończy się po otrzymaniu INTsygnału.
Kusalananda