Открытие нового файла псевдотерминального устройства в macOS с помощью swift - PullRequest
2 голосов
/ 18 марта 2019

Я пытаюсь поддерживать работу оболочки (bash / zsh / etc) с помощью Process из библиотеки Foundation.

Я знаю, как использовать Pipe для стандартного ввода / вывода /ошибка для других исполняемых файлов командной строки, но кажется, что программы оболочки требуют, чтобы стандартный файл ввода / вывода / ошибки был файлом терминального устройства.

Похоже, это файлы с именем /dev/ttys<3 digit number>, которые созданы длякаждый новый экземпляр оболочки.Как я могу создать эти файлы сам и использовать их в Swift?

1 Ответ

2 голосов
/ 19 марта 2019

РЕШЕНИЕ:

Так что все оказалось намного проще, чем я думал.Вот шаги, необходимые для создания пары главных и подчиненных псевдотерминалов FileHandle объектов:

  1. Импорт модуля Darwin.
  2. Позвоните на posix_openpt(int oflag), чтобы получитьдескриптор файла для доступного главного псевдо-терминального устройства.
  3. Позвоните на grantpt(int filedes), чтобы установить право собственности на соответствующее подчиненное псевдо-терминальное устройство.
  4. Позвоните на unlockpt(int filedes), чтобы разблокировать подчиненное псевдо-терминальное устройство.-терминальное устройство.
  5. Вызовите ptsname(int filedes), чтобы получить путь к подчиненному псевдотерминальному устройству.
  6. Создание FileHandle объектов с использованием файлового дескриптора из шага 2 и пути из шага 5.

На шагах 3 - 5 filedes - дескриптор файла, возвращаемый вызовом posix_openpt(int oflag) с шага 1. Используйте O_RDRW для параметра oflag на шаге 1 для разрешений на чтение и записьв главном файле устройства псевдотерминала.

Пример кода, в котором мы поддерживаем сеанс bash и запускаем команду tty:

import Foundation
import Darwin

class A: NSObject {
    var task: Process?
    var slaveFile: FileHandle?
    var masterFile: FileHandle?

    override init() {
        self.task = Process()
        var masterFD: Int32 = 0
        masterFD = posix_openpt(O_RDWR)
        grantpt(masterFD)
        unlockpt(masterFD)
        self.masterFile = FileHandle.init(fileDescriptor: masterFD)
        let slavePath = String.init(cString: ptsname(masterFD))
        self.slaveFile = FileHandle.init(forUpdatingAtPath: slavePath)
        self.task!.executableURL = URL(fileURLWithPath: "/bin/bash")
        self.task!.arguments = ["-i"]
        self.task!.standardOutput = slaveFile
        self.task!.standardInput = slaveFile
        self.task!.standardError = slaveFile
    }

    func run() {
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            guard let self = self else {
                return
            }
            do {
                try self.task!.run()
            } catch {
                print("Something went wrong.\n")
            }
        }
        let data = self.masterFile!.availableData
        let strData = String(data: data, encoding: String.Encoding.utf8)!
        print("Output: "+strData)
        self.masterFile!.write("tty\u{0D}".data(using: String.Encoding.utf8)!)
        sleep(1)
        let data1 = self.masterFile!.availableData
        let strData1 = String(data: data1, encoding: String.Encoding.utf8)!
        print("Output: "+strData1)
    }
}

let a = A()
a.run()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...