Pourquoi ne peut-on pas quitter ed avec Cc?

20

Le programme ed, un éditeur de texte minimal, ne peut pas être quitté en lui envoyant une interruption en utilisant Ctrl- C, en affichant à la place le message d'erreur "?" à la console. Pourquoi ne quitte-t-il pas edsimplement lorsqu'il reçoit l'interruption? Il n'y a sûrement aucune raison pour laquelle un message d'erreur cryptique est plus utile ici que de simplement quitter. Ce comportement conduit de nombreux nouveaux utilisateurs au type d'interaction suivant:

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

Un tel gaspillage tragique - facilement évitable s'il est edsimplement accepté d'être interrompu.

Un autre programme tenace présentant un comportement similaire est celui lessqui ne semble pas non plus avoir beaucoup de raisons d'ignorer C-c. Pourquoi ces programmes ne prennent-ils pas simplement un indice?

Lily Chung
la source
4
Les applications interactives ne sont pas les mêmes que les applications non interactives. Le comportement Ctrl-C auquel vous êtes habitué est celui par défaut pour les comportements non interactifs. Les interactifs peuvent remplacer le comportement de Ctrl-C à leurs propres fins.
jw013
4
Aussi,
je
@ jw013 Oui, la "session typique" était une blague (je n'ai pas pu trouver celle-là pour une raison quelconque) mais ma question est sérieuse. Ce que je ne comprends pas, c'est pourquoi ces applications choisissent de remplacer le comportement de Ctrl-C s'il ne fournit rien d'utile.
Lily Chung
1
Étant donné que cette question apparaît comme une réponse de recherche Google de premier plan à «comment quitter ed», je voudrais ajouter ici que c'est juste «q» suivi d'un retour. Beaucoup de Bothans sont morts pour nous apporter ces informations.
Dmitri

Réponses:

19

Ctrl+ Cenvoie SIGINT . L'action conventionnelle pour SIGINT consiste à revenir à la boucle de niveau supérieur d'un programme, à annuler la commande en cours et à entrer dans un mode où le programme attend la commande suivante. Seuls les programmes non interactifs sont censés mourir de SIGINT.

Il est donc naturel que Ctrl+ Cne tue pas ed, mais le fasse revenir à sa boucle de niveau supérieur. Ctrl+ Cabandonne la ligne d'entrée actuelle et revient à l'invite ed.

Il en va de même pour moins: Ctrl+ Cinterrompt la commande en cours et vous ramène à son invite de commande.

Pour des raisons historiques, ed ignore SIGQUIT ( Ctrl+ \). Les applications normales ne devraient pas capter ce signal et se permettre d'être interrompues, avec un vidage de mémoire s'il est activé.

Gilles 'SO- arrête d'être méchant'
la source
@Kzqai Non, les applications normales ne devraient pas intercepter SIGQUIT, elles sont conçues comme une issue de secours.
Gilles 'SO- arrête d'être méchant'
Ah, gotcha. D'accord, rétracté.
Kzqai
18

Le code source d' Unix V7ed(1) est un programme C primitif de 1762 lignes avec seulement quelques commentaires, dont l'un est ce commentaire d'en-tête très instructif:

/*
 * Editor
 */

Étant donné que le code source lui-même ne fournit aucune justification, vous ne l'obtiendrez que de l'auteur du programme.

eda été initialement écrit par Ken Thompson dans l'assemblage PDP-11 , mais vous auriez en fait besoin de parler à celui qui l'a porté sur C. Cela pourrait être Dennis Ritchie , puisqu'il a créé C pour Unix, et était l'un des nombreux à utiliser C pour rendre Unix portable sur des machines non PDP. Le Dr Ritchie n'est plus là pour répondre à de telles questions.

Ma lecture du code suggère qu'il a été fait pour essayer de conserver le contenu de la copie in-core du document édité. Vous remarquerez que d'autres éditeurs de texte ne meurent pas non plus Ctrl-C.

Voici ce que edça fait Ctrl-C:

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

(Oui, K&R C. Nous n'avons pas besoin de spécificateurs de type de retour steenkin ou de déclarations de paramètres.)

Traduit en anglais ed,:

  1. Réenregistre le gestionnaire de signaux.

    (Unix n'a pas reçu de signaux de réinitialisation automatique avant 4.3BSD , au milieu des années 1980.)

  2. Écrit une nouvelle ligne, et se souvient qu'elle l'a fait, via la variable globale lastc.

    ( ed.cpossède une soixantaine de variables globales.)

  3. Appelle la error()fonction, qui célèbre ne fait guère plus que la presse écrite ?, du point de vue de l'utilisateur.

En d'autres termes, il dit: "Vous ne vouliez pas vraiment faire ça, n'est-ce pas?"

Warren Young
la source
2
Il convient également de noter que de nombreux éditeurs de texte ne quittent pas Control-C. Vim non plus. Nano non plus. Je ne pense pas qu'emacs le fasse non plus, mais je ne l'ai pas installé pour le tester.
derobert
3
@derobert Vi traite Ctrl + C à la manière Unix: retournez au niveau supérieur. Emacs a ses propres raccourcis clavier, en raison de ses origines non Unix; l'équivalent Emacs du Ctrl + C d'Unix est Ctrl + G (le caractère de la cloche - sonner la cloche à l'ordinateur pour l'interrompre)
Gilles 'SO- arrête d'être méchant'
@derobert: Juste point. J'ai ajouté ceci à la réponse.
Warren Young
2
@Gilles: L' un des effets secondaires de l' appel error(s)en ed.cest de revenir à la boucle principale de traitement. Il le fait avec un longjmp()appel. frisson
Warren Young
1
Merci pour les détails et la leçon d'histoire. Ce fut une excellente lecture!
alichaudry
7

ed, comme d'autres programmes interactifs, utilisez Ctrl+ Cpour interrompre les tâches du programme lui-même.
Ceci est très similaire au cas normal, où il interrompt une tâche en cours d'exécution dans le shell - une commande.

Du point de vue de l'utilisateur, les deux variantes sont très similaires. Le traitement du signal est différent: dans le cas habituel, le signal SIGINTest envoyé au processus de premier plan, une commande en cours, et la commande le gère en quittant.
Dans le cas de ed, le signal est envoyé au processus de premier plan, l' edinstance. Si une tâche est en cours d'exécution ed, elle est interrompue et l'invite s'affiche. Si aucune tâche n'est en cours d'exécution, rien n'est modifié.

Notez comment un shell ne sort pas non plus sur Ctrl+ C, tout comme ed. Et qu'il sort sur Ctrl+ D. Encore une fois, tout commeed

Volker Siegel
la source
3

Il y a trois signaux qui edimportent:

  1. INT
  2. HUP
  3. QUIT

La spécification POSIX deed dit ce qui suit à propos de ces éléments:

SIGINT

L' edutilitaire doit interrompre son activité actuelle, écrire la chaîne ?\ndans la sortie standard et revenir en mode commande (voir la section DESCRIPTION ÉTENDUE).

SIGHUP

Si le tampon n'est pas vide et a changé depuis la dernière écriture, l' edutilitaire doit tenter d'écrire une copie du tampon dans un fichier. Tout d'abord, le fichier nommé ed.hupdans le répertoire courant doit être utilisé; en cas d'échec, le fichier nommé ed.hupdans le répertoire nommé par la HOMEvariable d'environnement doit être utilisé. Dans tous les cas, l' edutilitaire doit quitter sans écrire le fichier dans le chemin d'accès actuellement mémorisé et sans revenir en mode commande.

SIGQUIT

L' edutilitaire doit ignorer cet événement.

Quelle que soit l'implémentation que edvous utilisez, elle est conforme à la spécification POSIX en ce qui concerne le INTsignal (qui est ce qui Ctrl+Cenvoie).

À cet égard, l'éditeur se comporte comme un shell interactif, qui ne se termine pas non plus lors de la réception du INTsignal. D'autres éditeurs, comme viet nanofont la même chose.

Kusalananda
la source
1
Certaines implémentations de programme contredisent délibérément POSIX, il pourrait donc être utile d'expliquer la justification de la norme / le coût de sa rupture dans ce cas. stackoverflow.com/questions/38605463/…
sourcejedi
1
@sourcejedi La norme ne dit rien sur les signaux dans sa justification. Je n'ai trouvé aucune justification expliquant pourquoi la norme est suivie dans les sources eddont je dispose. Il se comporte de manière similaire à la coque, qui ne se termine pas non plus lors de la réception du INTsignal.
Kusalananda