Я работаю над псевдотерминальной библиотекой. Код реализован в коде C, и код используется веб-терминалом. Код работает, пока я не использую sudo или логин.
Это ошибка, которую я получаю, когда запускаю сервер на Mac:
sh-3.2$ sudo ls
Password:
[1]+ Stopped(SIGTTOU)
sh-3.2$
Вышеупомянутое работает в Linux:
$ sudo ls
readme.txt
Однако в Linux с помощью sudo bash я получаю следующее:
$ sudo bash
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
]0;root@ubuntu: /tmproot@ubuntu:/tmp#
Примечание: вышеизложенное работает, но у меня нет контроля над заданиями.
Я, вероятно, забыл установить некоторые управляющие биты на терминале, но Google не очень помог в поиске этого. Кроме того, знаете ли вы какие-нибудь хорошие книги, в которых очень подробно объясняется управление псевдотерминалом.
У меня есть вызов setsid, но я не использую openpty. Я использую следующий код при открытии pty:
static int createPty(lua_State* L, char* ttyName, int* pty)
{
*pty = getpt();
if (*pty < 0 || grantpt(*pty) < 0 || unlockpt(*pty) < 0)
return lDoErr(L,"Cannot open PTY: %s",strerror(errno));
if(ptsname_r(*pty, ttyName, PTY_NAME_SIZE-1))
return lDoErr(L,"ptsname_r: %s",strerror(errno));
return 0;
}
Я отредактировал приведенный ниже код, и этот код работает. Причина, по которой моя первая версия не работала, заключалась в том, что я пытался создать два канала PTY. Я хотел иметь возможность различать stdout и stderr, но ядро Linux не допускает многократных вызовов TIOCSCTTY.
static int
childOpenTTY(const char* ttyName)
{
struct termios termbuf;
int fd=open(ttyName, O_RDWR);
if(fd < 0)
doClientError("open %s: %s",ttyName, strerror(errno));
tcsetpgrp(fd, getpid());
ioctl(fd,TIOCSCTTY,NULL);
tcgetattr(fd, &termbuf);
cfmakeraw(&termbuf); /* turn off NL to CR/NL mapping on output. */
tcsetattr(fd, TCSANOW, &termbuf);
return fd;
}
if( (ret = createPty(L, ttyName, &te->pty)) != 0)
return ret;
if ((te->pid = zzbafork()) < 0)
return lDoErr(L,"fork: %s",strerror(errno));
if(te->pid == 0)
{ /* Child process */
static const char efmt[]={"Cannot set '%s' (dup2 err)"};
int fd;
if(setsid() < 0) /* make new process group */
doClientError("setsid: %s",strerror(errno));
fd=childOpenTTY(ttyName);
if(dup2(fd, STDIN_FILENO) != STDIN_FILENO)
doClientError(efmt,"stdin");
if(dup2(fd, STDOUT_FILENO) != STDOUT_FILENO)
doClientError(efmt,"stdout");
if(dup2(fd, STDERR_FILENO) != STDERR_FILENO)
doClientError(efmt,"stderr");
if(fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
close(fd);
execve(cmd, (char**)cmdArgv, environ);
/* execve should not return, unless error exec cmd */
doClientError("Executing %s failed: %s",cmd,strerror(errno));
}