Как мне получить этот pty и что я могу с ним сделать?

Как мне получить этот pty и что я могу с ним сделать?

Похоже, что простое перенаправление оболочки с /dev/ptmxдаёт мне новый псевдотерминал.

$ ls /dev/pts; ls /dev/pts </dev/ptmx
0  1  2  ptmx
0  1  2  3  ptmx

Он исчезает, как только процесс, которому принадлежит претензия fd, завершается /dev/ptmx, но его достаточно просто сохранить:

$ PS1='<$(ls -1 "$@" /dev/pts/*|uniq -u)> $ ' \
  exec 3<>/dev/ptmx "$0" -si -- /dev/pts/*
</dev/pts/3> $ ls /dev/pts; exec 3>&-
0  1  2  3  ptmx
<> $ ls /dev/pts; exec 3<>/dev/ptmx
0  1  2  ptmx
</dev/pts/3> $ exit

Так что, похоже, простого open()on /dev/ptmxдостаточно, чтобы получить псевдотерминал. Я думаю, это сделало бы оболочку -(или процесс, для которого выполняется перенаправление)- владелец основной стороны объекта недвижимости.

Но как мне назначить сторону раба - илиможетЯ назначаю подчиненную сторону? И если могу - что я могу с ней сделать? Могу ли я повлиять на ее время чтения/записи/очистки с помощью stty? Будет ли подчиненный процесс ссылаться на мой новый pty при обращении к /dev/tty?

решение1

Итак, как @muru указывает в комментариях, похоже, нет простого способа связать созданный для вас pty только с оболочкой. Я справился со всем, кроме части unlockpt(). Согласно тому, что я читалздесьможет быть, в ядре есть какие-то опции компиляции для отключения блокировки вновь созданных pty, но я не хотел этого делать. Поэтому я сделал кое-что другое.

Мне на самом деле не нужно grantpt(). Согласно найденному описаниюздесьвсе, что он делает, это меняет UID/GID для /dev/pts/[num]файла устройства. Но, согласно man mountесть более простые способы справиться с этим. Вот некоторые devptsпараметры монтирования:

  • uid=valueиgid=value
    • Это устанавливает владельца или группу вновь созданных PTY на указанные значения. Если ничего не указано, они будут установлены на UID и GID процесса создания. Например, если есть телетайп группа с GID 5, то gid=5вновь созданные PTY будут принадлежатьтелетайпгруппа.

Это уже было по умолчанию в моей системе. Но после прочтения я понял, что, возможно, мне все-таки захочется внести изменения. В следующем разделе говорится:

  • ptmxmode=value
    • Установите режим для нового узла устройства ptmx в devptsфайловой системе.
    • Благодаря поддержке нескольких экземпляров devpts(см. newinstanceопцию выше) каждый экземпляр имеет частный узел ptmx в корне файловой devptsсистемы.(обычно /dev/pts/ptmx).
    • Для совместимости со старыми версиями ядра режимом по умолчанию нового узла ptmx является 0000. ptmxmode=value определяет более полезный режим для узла ptmx и настоятельно рекомендуется, если newinstanceуказана эта опция.

Хотя это работало бы и без этого, мне понравилась эта идея, и я установил значение, 0640рекомендованное вдокументация ядра. Кстати, ссылка на документацию ядра подробно описывает newinstanceопцию монтирования, которая довольно крута и, по сути, позволяет вам получить отдельную группу пространств имен pty для каждого /dev/ptmxмонтирования.

В любом случае, так чточто-то другоев основном составили:

mount -o remount,newinstance,gid=5,ptmxmode=0640 /dev/pts
mount --bind /dev/pts/ptmx /dev/ptmx

...как рекомендует документация ядра - см. ссылку, почему. Я также сделал эффект вышеприведенных команд постоянным, добавив пару строк в свой /etc/fstab.

И...

<<\C cc -xc - -o pts
#include <stdio.h>
int main(int argc, char *argv[]) {
        if(unlockpt(0)) return 2;
        char *ptsname(int fd);
        printf("%s\n",ptsname(0));
        return argc - 1;
}
C

Которая просто компилирует маленькую программу на языке C, которая пытается вызвать unlockpt()свой stdin и в случае успеха выводит имя недавно созданного и разблокированного pty stdoutили молча возвращает 2.

Как только это будет сделано, я смогу создать свой собственныйэкранированныйтакие процессы как:

exec 3<>/dev/ptmx

...чтобы получить главный файловый дескриптор в текущей оболочке, то...

(setsid -c "$0" -i 2>&1|tee log) <>"$(./pts <&3)" 3>&- >&0 &

Это запускает интерактивную оболочку на другом конце псевдотерминала в фоновом режиме. Она будет интерпретировать все, что выводится на печать, >&3как пользовательский ввод.

mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$
mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$ hey
$ 

Что по сути дает мне фонового, зарегистрированного, интерактивного переводчика.(или что-нибудь еще, что я захочу запустить на этих устройствах)ala screenбез особых накладных расходов и с любым выбранным мной файловым дескриптором.

Файловый дескриптор на стороне мастера, принадлежащий моей текущей оболочке, является единственным средством обслуживания ввода на стороне подчинённого устройства и доступен для записи только моему текущему процессу оболочки.(и его дети)Я могу общаться с другим концом, отправляя ему сообщения >&3, и могу читать оттуда же или из файла журнала по своему усмотрению.

И sttyработает ли это на терминале в конце концов:

mikeserv@localhost$ echo stty -a ">$(tty)" >&3
speed 38400 baud; rows 0; columns 0; line = 0;                                      
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc
-ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl
echoke

Связанный контент