Почему нельзя выйти с помощью Cc?

20

Программа ed, минимальный текстовый редактор, не может быть закрыта, посылая ей прерывание через использование Ctrl- Cвместо того, чтобы печатать сообщение об ошибке «?» на консоль. Почему edпросто не выйти, когда получит прерывание? Конечно, нет никаких причин, почему загадочное сообщение об ошибке здесь более полезно, чем просто выход. Такое поведение приводит многих новых пользователей к следующему виду взаимодействия:

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

Такие трагические отходы - их легко избежать, если edсогласиться на прерывание.

Другая упрямая программа, демонстрирующая подобное поведение, lessтакже не имеет особых причин для игнорирования C-c. Почему эти программы не принимают подсказки?

Лили Чунг
источник
4
Интерактивные приложения - это не то же самое, что неинтерактивные приложения. Поведение Ctrl-C, к которому вы привыкли, используется по умолчанию для неинтерактивных. Интерактивные могут переопределять поведение Ctrl-C для своих собственных целей.
jw013
4
Кроме того, не уверен, если шутка
jw013
@ jw013 Да, «типичная сессия» была шуткой (я почему-то не смог ее найти), но мой вопрос серьезный. Чего я не понимаю, так это того, почему эти приложения предпочитают переопределять поведение Ctrl-C, если оно не дает ничего полезного.
Лили Чунг
1
Так как этот вопрос является главным поисковым ответом Google на вопрос «как выйти из ed», я хотел бы добавить, что это просто «q», за которым следует возврат. Многие ботаны умерли, чтобы принести нам эту информацию.
Дмитрий

Ответы:

19

Ctrl+ Cотправляет SIGINT . Обычное действие для SIGINT - возврат к циклу верхнего уровня программы, отмена текущей команды и переход в режим, в котором программа ожидает следующую команду. Только неинтерактивные программы должны умереть от SIGINT.

Поэтому естественно, что Ctrl+ Cне убивает ed, но заставляет его возвращаться в цикл верхнего уровня. Ctrl+ Cпрерывает текущую строку ввода и возвращает к приглашению ed.

То же самое касается меньшего: Ctrl+ Cпрерывает текущую команду и возвращает вас к ее командной строке.

По историческим причинам Эд игнорирует SIGQUIT ( Ctrl+ \). Обычные приложения не должны перехватывать этот сигнал и позволять завершать себя, с дампом ядра, если он включен.

Жиль "ТАК - прекрати быть злым"
источник
@ Kzqai Нет, обычные приложения не должны ловить SIGQUIT, это означает аварийный выход.
Жиль "ТАК - перестань быть злым"
Ах, понял. Хорошо, отрекся.
Kzqai
18

Unix V7 ed(1)исходный код является примитивной 1762-линией C программой всего лишь несколько замечаний, один из которых это высоко поучительного заголовка комментарий:

/*
 * Editor
 */

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

edПервоначально он был написан Кеном Томпсоном в сборке PDP-11 , но вам действительно нужно было поговорить с тем, кто перенес его на C. Это мог быть Деннис Ритчи , так как он создал C для Unix и был одним из многих, кто использовал C для сделать Unix переносимым на машины без PDP. Доктора Ритчи больше нет рядом, чтобы отвечать на такие вопросы.

Мое чтение кода предполагает, что это было сделано для того, чтобы попытаться сохранить содержимое основной копии отредактированного документа. Вы заметите, что другие текстовые редакторы также не умирают Ctrl-C.

Вот что edделает на Ctrl-C:

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

(Да, K & R C. Нам не нужны никакие идентификаторы возвращаемых типов или объявления параметров).

Переведено на английский ed:

  1. Перерегистрирует обработчик сигнала.

    (Unix не получал сигналы автоматического сброса до 4.3BSD , в середине 1980-х.)

  2. Записывает новую строку и запоминает, что это так, через глобальную переменную lastc.

    ( ed.cимеет около шестидесяти глобальных переменных.)

  3. Вызывает error()функцию, которая классно делает немного больше, чем печать ?, с точки зрения пользователя.

Другими словами, он говорит: «Вы действительно не хотели этого делать?»

Уоррен Янг
источник
2
Также стоит отметить, что многие текстовые редакторы не выходят на Control-C. Вим тоже нет. Ни один не делает нано. Я не думаю, что emacs тоже, но не установил его для тестирования.
Дероберт
3
@derobert Vi обрабатывает Ctrl + C по Unix: вернитесь на верхний уровень. Emacs имеет свои собственные сочетания клавиш из-за не-Unix-происхождения; Emacs-эквивалент Unix's Ctrl + C - это Ctrl + G (символ колокольчика - звонить в колокольчик на компьютере, чтобы прервать его)
Жиль "ТАК - перестать быть злым"
@derobert: Честная точка зрения. Я добавил это к ответу.
Уоррен Янг
2
@Gilles: Одним из побочных эффектов вызова error(s)в ed.c, чтобы вернуться в основной цикл обработки. Это делается с помощью longjmp()звонка. дрожь
Уоррен Янг
1
Спасибо за детали и урок истории. Это было отличное чтение!
alichaudry
7

edКак и другие интерактивные программы, используйте Ctrl+ Cдля прерывания задач самой программы.
Это очень похоже на обычный случай, когда он прерывает задачу, выполняемую в оболочке, - команду.

С точки зрения пользователя, оба варианта очень похожи. Обработка сигнала отличается: в обычном случае сигнал SIGINTотправляется процессу переднего плана, выполняющейся команде, и команда обрабатывает его, завершаясь.
В случае ed, сигнал отправляется на передний план процесса, edэкземпляр. Если задание выполняется ed, оно прерывается и отображается приглашение. Если задание не выполняется, ничего не меняется.

Обратите внимание, что оболочка также не выходит на Ctrl+ C, как ed. И что это действительно выход на Ctrl+ D. Опять какed

Volker Siegel
источник
3

Есть три сигнала, которые edзаботятся о:

  1. INT
  2. HUP
  3. QUIT

В спецификации POSIXed говорится следующее:

SIGINT

edУтилита прерывает свою текущую деятельность, записать строку ?\nна стандартный вывод, и вернуться в командный режим (см ОПИСАНИЕ раздел Extended).

SIGHUP

Если буфер не пустой и изменился с момента последней записи, edутилита должна попытаться записать копию буфера в файл. Во-первых, должен использоваться файл, названный ed.hupв текущем каталоге; если это не удается, следует использовать файл, указанный ed.hupв каталоге, указанном HOMEпеременной среды. В любом случае, edутилита должна выйти без записи файла в текущий запомненный путь и без возврата в командный режим.

SIGQUIT

edУтилита будет игнорировать это событие.

Поэтому, какую бы реализацию edвы ни использовали, она соответствует спецификации POSIX в отношении INTсигнала (который и Ctrl+Cотправляет).

В этом отношении редактор ведет себя как интерактивная оболочка, которая также не завершается при получении INTсигнала. Другие редакторы, такие как viи nanoделает то же самое.

Кусалананда
источник
1
Некоторые реализации программ намеренно противоречат POSIX, поэтому может быть полезно объяснить обоснование стандарта / стоимость его нарушения в этом случае. stackoverflow.com/questions/38605463/…
sourcejedi
1
@sourcejedi Стандарт ничего не говорит о сигналах в своем обосновании. Я не нашел никакого объяснения, говорящего о том, почему этот стандарт соблюдается в edдоступных мне источниках . Он ведет себя так же, как и оболочка, которая также не заканчивается при получении INTсигнала.
Кусалананда