go로 브라우저에서 움직이는 터미널 에뮬레이터를 만든 이야기

7431 단어 터미널

만든 것



브라우저에서 움직이는 터미널 에뮬레이터를 만들었습니다.



구성



서버 측은 go로 구현되었고 클라이언트 측은 typescript로 구현되었습니다.
입출력은 websocket으로 교환합니다.

구현 개요



pty를 만들고 bash와 연결합니다.



터미널 에뮬레이터가 단말기에서 움직이는 프로그램과 입출력을 주고받는 경우에는 pty(가상 단말기)라고 하는 것을 사용합니다. 1
pty는 openpty() 함수를 사용하여 작성합니다.
go는 openpty에 해당하는 함수를 찾을 수 없으므로 cgo를 사용하여 호출합니다.
openpty를 호출하면 amaster와 aslave이라는 두 가지 값을 얻을 수 있으므로,
aslave 쪽을 단말상에서 움직이는 프로그램의 표준 입출력에 할당해, amaster 쪽에 브라우저로부터 받은 입력을 넣습니다.

var amaster C.int
var aslave C.int
if errno := C.openpty((*C.int)(unsafe.Pointer(&amaster)), (*C.int)(unsafe.Pointer(&aslave)), nil, nil, nil); errno != 0 {
    panic(fmt.Sprintf("errorno: %d\n", errno))
}
sysattr := syscall.SysProcAttr{Setsid: true}
attr := syscall.ProcAttr{
    Files: []uintptr{uintptr(aslave), uintptr(aslave), uintptr(aslave)},
    Env:   []string{"TERM=vt100"},
    Sys:   &sysattr,
}
pid, err := syscall.ForkExec("/usr/bin/bash", []string{}, &attr)
if err != nil {
    panic(err)
}

이 상태에서 amaster에게 쓰면 쉘에 값이 보내지고,
또한 쉘 결과를 amaster에서 읽을 수 있습니다.

amaster에 읽고 쓰려면 os.NewFile을 사용할 수 있습니다.
file := os.NewFile(uintptr(amaster), "ptymaster")
file.Write([]byte("ls"))

다양한 키를 쉘로 보내기



각종 키로 알파벳 등은 그대로 대응하는 ASCII 코드를 amaster에 입력하면 됩니다.
브라우저 측에서
Backspace 키를 누르면 BS(0x08),
Enter 키를 누르면 CR(0x13)을 두면 됩니다.

Ctrl 키에 해당



Ctrl+아무것도 키의 경우는 해당 ASCII 코드에서 0x40을 뺀 값을 보냅니다.
(예: Ctrl+C라면 0x03이 된다)
실제로 시그널을 보내는 부분은 pty가 좋은 느낌으로 해주고 있는 것 같고, 이것을 구현하는 것만으로 Ctrl+C를 누르면 현재 실행중의 프로그램이 종료하게 됩니다.

특수 문자와 이스케이프 시퀀스 처리



단지 이것만으로는, 단지 문자는 추기되는 것만으로, BS로 문자를 삭제하는 것조차 할 수 없습니다.
이미 입력한 문자를 삭제하는 경우, 다른 장소에 문자를 표시하고 싶은 경우 등은, 특별한 문자가 보내져 오므로 클라이언트측에서 잘 취급해 해야 합니다.

우선 이하의 특수 문자를 구현하면(자) 그렇게 됩니다.
  • CR (0x13) 커서를 줄 머리로 되돌립니다.
  • LF (0x10) 커서를 다음 행으로 이동합니다.
  • BS (0x08) 커서를 한 글자 왼쪽으로 이동합니다.

    우선 여기까지 구현하면 탭 보완 상하 키에 의한 이력 표시당은 움직일 것입니다.

    좀 더 정교한 것을 움직이고 싶다면 이스케이프 시퀀스를 구현해야합니다.
    이스케이프 시퀀스는 여러 문자 조합으로 터미널을 제어하는 ​​것입니다.
    필자는 다음 사이트를 참고로 좋은 느낌으로 구현했습니다.

    htp://bkcぁs. 웨 b. FC2. 작은 m/do c_vt100. html
    htps //w w. vt100. 네 t/도 cs/vt510-rm/짱 p r4. HTML
    htps // 엔.ぃきぺぢ아. 오 rg / uuki / anshi _ s s ぺ _ 여기

    끝에



    코드는 공개하고 있으므로 흥미있는 분은 부디.
    htps : // 기주 b. 코 m / sd 카와타 /
    (보안 안전 확인은 하지 않으므로, 글로벌에서 액세스할 수 없는 장소에서 이동해 주세요)



    pty란 무엇인가라고 하면 설명이 어렵다(라고 할까 필자도 잘 모르는)입니다만, 여러가지 기능이 붙은 파이프와 같은 것이라고 생각해 두는 것이 좋다고 생각합니다. 구체적으로 어떤 기능이 붙어 있는지에 대해서는 htps : // 이 m / 펑크 l_p_57 / ms / f1c0d054714b7982 또는 50 가 참고가 됩니다.
  • 좋은 웹페이지 즐겨찾기