Comportamento de codificação de caracteres do Konsole Estranho

1

Eu configurei a codificação de caracteres do Konsole no Lubuntu para UTF-16 (não sei se o Konsole usa UTF-16 little endian ou UTF-16 big endian).

Em seguida, eu corro o seguinte comando na janela Executar:

Emseguida,pressioneiobotão"a" no meu teclado (o layout do teclado selecionado em Lubuntu é o inglês), o que suponho que os bytes 61 00 (se o Konsole usar little endian UTF-16) sejam enviados para o disciplina de linha , e a disciplina de linha por sua vez fará eco desses bytes de volta ao Konsole, e o Konsole exibirá o caractere "a". Mas em vez disso eu peguei o seguinte:

Novamente,pressioneiobotão"a" e obtive o seguinte:

Alémdisso,pressioneinovamenteobotão"a" e obtive o seguinte:

Alémdisso,pressioneinovamenteobotão"a" e obtive o seguinte:

Porqueestourecebendoessescaracteresestranhosemvezdesimplesmentepegaroscaracteres"aaaa"?

Editar:

Estes são os caracteres exibidos no Konsole:

幡`懾䁞幡`懾䁞

    
por rony_t 09.06.2018 / 06:46

1 resposta

1

Vamos ainda mais enfatizar que xxd -p é irrelevante, estamos não falando sobre a saída its . Ele nem viu a entrada devido ao buffer de linha no lado do kernel e, portanto, não produziu nenhuma saída. Por que vale a pena, também pode ser um cat ou um sleep 100000 ou o que for. Estamos falando sobre como o kernel (a disciplina de linha) ecoa de volta a entrada.

Se você voltar para UTF-8 e pressionar Enter para xxd -p , sua saída será igual a fffe6100fffe6100 . Então little endian é confirmado (ou provavelmente é a ordem de bytes nativa da arquitetura), mas, surpreendentemente, há uma BOM antes de cada caractere. Faz-me suspeitar que não foi devidamente pensado pelos desenvolvedores do Konsole, eles apenas invocam cegamente o iconv com UTF-16 (sem BE ou LE especificado) como o conjunto de caracteres de destino, para cada pedaço de entrada à medida que se torna disponível e iconv places lá.

Vamos strace konsole para ver o que ele faz no descritor de arquivo conectado a /dev/ptmx :

write(..., "76a
write(..., "76a%pre%", 4)             = 4
[...]
read(..., "76a^@", 5)              = 5
", 4) = 4 [...] read(..., "76a^@", 5) = 5

O byte NUL (0x00) retorna como literal ^@ , ou seja, 0x5e seguido por 0x40.

Juntamente com a (0x61), isso dá a você U + 5e61, que é exatamente o primeiro glifo que você vê aparecendo. Além disso, você estará desligado por um byte, ou seja, o próximo byte supostamente baixo será interpretado como alto byte e vice-versa.

Para o byte 0x00 , o kernel simplesmente manipula como é ecoado de volta. Para alguns outros bytes, também executa outras ações. Por exemplo, o byte 0x03 ( ^C ) geralmente aciona uma interrupção para ser enviada ao processo em primeiro plano, 0x15 ( ^U ) apaga os dados que você inseriu até o momento, 0x0a e / ou 0x0d (isto é, nova linha) libera os dados para seu aplicativo, etc. Todos esses bytes podem (e realmente) ocorrem legalmente dentro da representação de caracteres UTF-16, e você certamente não quer que nenhum deles aconteça enquanto digita sua entrada .

Para usar o UTF-16 na linha discipular, o kernel precisaria fornecer suporte explícito para isso e precisaria ser informado de que esta codificação está sendo usada (algo nos moldes de um stty utf16 ). Para o meu melhor conhecimento, isso não é implementado (felizmente - seria um desperdício total de recursos do desenvolvedor). O kernel espera que uma codificação compatível com ASCII seja usada, o que não é o UTF-16.

Mesmo se o UTF-16 fosse implementado no kernel para a linha tty, todo o ecossistema seria necessariamente bastante frágil. O terminal pode receber dados de várias fontes simultaneamente, e não há como garantir que todos os produtores de dados e todos os transportadores (por exemplo, ssh) possam sempre manter os bytes acoplados em pares. Uma vez que se apaga um byte (como visto acima), o resto é inutilizável.

Agora estou mais certo de que o desenvolvedor do Konsole não pensou corretamente sobre isso. Na minha opinião, o UTF-16 deve ser removido de sua lista de codificações oferecidas, ou pelo menos uma advertência deve ser mostrada. Eu enviei o erro do Konsole 395171 .

    
por 09.06.2018 / 11:24