Por que o ed não pode ser encerrado com o Cc?

20

O programa ed, um editor de texto mínimo, não pode ser encerrado enviando uma interrupção usando Ctrl- C, imprimindo a mensagem de erro "?" para o console. Por que edsimplesmente não sai quando recebe a interrupção? Certamente não há razão para que uma mensagem de erro enigmática seja mais útil aqui do que apenas sair. Esse comportamento leva muitos novos usuários ao seguinte tipo de interação:

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

Um desperdício tão trágico - facilmente evitável se edsimplesmente concordar em ser interrompido.

Outro programa teimoso que exibe comportamento semelhante é o lessque também parece não ter muitos motivos para ignorar C-c. Por que esses programas não dão apenas uma dica?

Lily Chung
fonte
4
Aplicativos interativos não são os mesmos que não interativos. O comportamento Ctrl-C ao qual você está acostumado é o padrão para os não-interativos. Os interativos podem substituir o comportamento do Ctrl-C para seus próprios propósitos.
jw013
4
Além disso, não tenho certeza se piada
jw013
@ jw013 Sim, a "sessão típica" foi uma piada (não consegui encontrar essa por algum motivo), mas minha pergunta é séria. O que não entendo é por que esses aplicativos optam por substituir o comportamento do Ctrl-C, se ele realmente não fornece nada útil.
Lily Chung
1
Como essa pergunta surge como a principal resposta de pesquisa do Google para "como sair do ed", gostaria de adicionar aqui que é apenas 'q' seguido de um retorno. Muitos botânicos morreram para nos trazer essas informações.
Dmitri

Respostas:

19

Ctrl+ Cenvia SIGINT . A ação convencional do SIGINT é retornar ao loop de nível superior de um programa, cancelando o comando atual e entrando no modo em que o programa aguarda o próximo comando. Apenas programas não interativos devem morrer do SIGINT.

Portanto, é natural que o Ctrl+ Cnão mate, mas faça com que ele retorne ao seu loop de nível superior. Ctrl+ Cinterrompe a linha de entrada atual e retorna ao prompt ed.

O mesmo vale menos: Ctrl+ Cinterrompe o comando atual e retorna ao prompt de comando.

Por razões históricas, ed ignora SIGQUIT ( Ctrl+ \). Os aplicativos normais não devem captar esse sinal e permitir que sejam finalizados, com um dump principal, se ativado.

Gilles 'SO- parar de ser mau'
fonte
@Kzqai Não, aplicativos normais não devem pegar o SIGQUIT, é uma saída de emergência.
Gilles 'SO- stop be evil'
Ah, entendi. Tudo bem, retraído.
Kzqai
18

O código fonte do Unix V7ed(1) é um programa C primitivo de 1.762 linhas com apenas alguns comentários, um dos quais é este comentário de cabeçalho altamente esclarecedor:

/*
 * Editor
 */

Dado que o código fonte em si não fornece nenhuma justificativa, você o receberá apenas pelo autor do programa.

edfoi originalmente escrito por Ken Thompson na montagem do PDP-11 , mas você realmente precisa conversar com quem o transportou para C. Esse poderia ter sido Dennis Ritchie , desde que ele criou C para Unix, e foi um dos muitos que usaram C para torne o Unix portátil para máquinas que não sejam PDP. O Dr. Ritchie não está mais por perto para responder a essas perguntas.

Minha leitura do código sugere que foi feito para tentar preservar o conteúdo da cópia dentro do núcleo do documento editado. Você notará que outros editores de texto também não morrem Ctrl-C.

Aqui está o que edacontece em Ctrl-C:

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

(Sim, K&R C. Não precisamos de nenhum especificador de tipo de retorno ou declaração de parâmetro.)

Traduzido para o inglês ed:

  1. Registra novamente o manipulador de sinal.

    (O Unix não recebeu sinais de redefinição automática até 4,3BSD , em meados da década de 1980).

  2. Escreve uma nova linha e lembra que fez isso, através da variável global lastc.

    ( ed.cpossui cerca de sessenta variáveis ​​globais.)

  3. Chama a error()função, que famosa faz pouco mais que imprimir ?, da perspectiva do usuário.

Em outras palavras, está dizendo: "Você realmente não quis fazer isso, não é?"

Warren Young
fonte
2
Também é importante notar que muitos editores de texto não saem no Control-C. Vim também não. Nem o nano. Também não acho que o emacs o faça, mas não o instale para testar.
precisa saber é
3
@derobert Vi trata Ctrl + C da maneira Unix: volte para o nível superior. O Emacs possui suas próprias combinações de teclas, devido às suas origens não-Unix; o equivalente do Emacs ao Ctrl + C do Unix é Ctrl + G (o caractere sino - toque o sino no computador para interrompê-lo)
Gilles 'SO- stop be evil'
@derobert: ponto justo. Eu adicionei isso à resposta.
Warren Young
2
@Gilles: Um dos efeitos laterais de chamada error(s)em ed.cé para voltar ao ciclo de processamento principal. Faz isso com uma longjmp()chamada. shudder #
Warren Young
1
Obrigado pelos detalhes e pela lição de história. Esta foi uma ótima leitura!
Alichaudry 17/11/16
7

ed, como outros programas interativos, use Ctrl+ Cpara interromper as tarefas do próprio programa.
Isso é muito semelhante ao caso normal, onde interrompe uma tarefa em execução no shell - um comando.

Da perspectiva do usuário, as duas variantes são muito semelhantes. A manipulação do sinal é diferente: no caso usual, o sinalSIGINT é enviado para o processo em primeiro plano, um comando em execução, e o comando lida com isso saindo.
No caso de ed, o sinal é enviado para o processo em primeiro plano, a edinstância. Se houver uma tarefa em execução ed, ela será interrompida e o prompt será mostrado. Se não houver nenhuma tarefa em execução, nada será alterado.

Observe como um shell também não sai no Ctrl+ C, assim como ed. E que sai no Ctrl+ D. Mais uma vez, assim comoed

Volker Siegel
fonte
3

Existem três sinais importantes ed:

  1. INT
  2. HUP
  3. QUIT

A especificação POSIX deed diz o seguinte sobre estes:

SIGINT

O edutilitário interrompe sua atividade atual, grava a string ?\nna saída padrão e retorna ao modo de comando (consulte a seção DESCRIÇÃO ESTENDIDA).

SIGHUP

Se o buffer não estiver vazio e tiver sido alterado desde a última gravação, o edutilitário tentará escrever uma cópia do buffer em um arquivo. Primeiro, o arquivo nomeado ed.hupno diretório atual deve ser usado; se isso falhar, o arquivo nomeado ed.hupno diretório nomeado pela HOMEvariável de ambiente deve ser usado. Em qualquer caso, o edutilitário deve sair sem gravar o arquivo no nome do caminho atualmente lembrado e sem retornar ao modo de comando.

SIGQUIT

O edutilitário deve ignorar esse evento.

Portanto, qualquer que seja sua implementação ed, ela está em conformidade com a especificação POSIX em relação ao INTsinal (que é o que é enviado Ctrl+C).

Nesse sentido, o editor se comporta como um shell interativo, que também não termina ao receber o INTsinal. Outros editores, como vie nanofazem a mesma coisa.

Kusalananda
fonte
1
Algumas implementações de programa contradizem deliberadamente o POSIX, portanto, pode ser útil explicar a lógica do padrão / custo de quebrá-lo nesse caso. stackoverflow.com/questions/38605463/…
sourcejedi
1
@sourcejedi O padrão não diz nada sobre os sinais em sua lógica. Não encontrei nenhuma justificativa dizendo nada sobre por que o padrão é seguido nas fontes edque tenho disponíveis. Ele se comporta de maneira semelhante ao shell, que também não termina ao receber o INTsinal.
Kusalananda