Чому не можна вийти з 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 на "як вийти з редакції", я хотів би додати тут, що це просто "q" з подальшим поверненням. Багато ботанів загинули, щоб донести нам цю інформацію.
Дмитро

Відповіді:


19

Ctrl+ Cнадсилає SIGINT . Умовна дія для SIGINT полягає у поверненні до циклу вершин програми, скасування поточної команди та введення режиму, коли програма чекає наступної команди. Тільки неінтерактивні програми повинні померти від SIGINT.

Тож природно, що Ctrl+ Cне вбиває Ед, але змушує повернутися до його циклу топлерів. Ctrl+ Cперериває поточний рядок введення та повертається до рядка редагування.

Те ж саме стосується менше: Ctrl+ Cперериває поточну команду і повертає вас до її командного рядка.

З історичних причин ed ігнорує SIGQUIT ( Ctrl+ \). Звичайні програми не повинні вловлювати цей сигнал і дозволяти їм припиняти роботу, з базовим дамп, якщо це включено.


@Kzqai Ні, звичайні програми не повинні вловлювати SIGQUIT, це означає як аварійний вихід.
Жиль "ТАК - перестань бути злим"

Ах, готча. Добре, втягнуто.
Kzqai

18

Unix V7 ed(1)вихідний код є примітивною тисячі сімсот шістьдесят дві-лінією 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. Нам не потрібні специфікатори типу повернення Steenkin або декларації параметрів.)

Перекладено англійською мовою ed:

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

    ( У середині 1980-х Unix не отримувала сигнали автоматичного скидання до 4.3BSD .)

  2. Виписує новий рядок і пам’ятає, що це робилося через глобальну змінну lastc.

    ( ed.cмає близько шістдесяти глобальних змінних.)

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

Іншими словами, це говорить: "Ви насправді не хотіли цього робити, чи не так?"


2
Також варто зазначити, що багато Text редакторів не виходять з Control-C. Vim також не робить. Ні нано. Я також не думаю, що Emacs це робить, але не встановлюють його для тестування.
дероберт

3
@derobert Vi розглядає Ctrl + C способом Unix: поверніться до верхнього рівня. Emacs має власні зв'язки клавіш, завдяки своїм джерелам не Unix; еквівалент Emacs Ctrl + C від Unix - це Ctrl + G (символ дзвони - дзвоніть у дзвіночок на комп’ютері, щоб перервати його)
Жил "SO - перестаньте бути злим"

@derobert: Справедливий пункт. Я додав це до відповіді.
Warren Young

2
@Gilles: Одним з побічних ефектів виклику error(s)в ed.c, щоб повернутися в основний цикл обробки. Це робиться за допомогою longjmp()дзвінка. здригаються
Warren Young

1
Дякую за деталі та урок історії. Це було чудове прочитання!
alichaudry

7

ed, як і інші інтерактивні програми, використовуйте Ctrl+ Cдля переривання завдань самої програми.
Це дуже схоже на звичайний випадок, коли він перериває завдання, що працює в оболонці - команду.

З точки зору користувача, обидва варіанти дуже схожі. Обробка сигналу різна: у звичайному випадку сигнал SIGINTнадсилається до процесу переднього плану, запущеній команді, і команда обробляє його шляхом виходу.
У випадку з edцим сигнал надсилається в процес переднього плану, edекземпляр. Якщо виконується завдання ed, воно переривається і відображається підказка. Якщо завдання не виконується, нічого не змінюється.

Зверніть увагу, як оболонка також не виходить на Ctrl+ C, так само, як ed. І що він робить вихід на Ctrl+ D. Знову просто такed


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сигналу.
Кусалаланда
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.