1
我正在使用僞終端庫。代碼以C代碼實現,代碼由基於Web的終端使用。只要我不使用sudo或登錄,代碼就可以工作。僞終端問題(Mac/Linux):SIGTTOU&不適當的ioctl
這是我的錯誤,當我運行在Mac上的服務器:
sh-3.2$ sudo ls
Password:
[1]+ Stopped(SIGTTOU)
sh-3.2$
在Linux上面的作品:
$ sudo ls
readme.txt
不過,我得到了在Linux上使用sudo慶典以下:
$ sudo bash
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
]0;[email protected]: /[email protected]:/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));
}
感謝torek,但我有setsid。我已經包含了上面的代碼。 – Will 2013-03-20 20:40:58
啊。嘗試不使用'O_NOCTTY'標誌:這是禁止將新打開的設備設置爲控制終端的標誌。你會認爲這樣可以,因爲'TIOCSCTTY',但是這個ioctl可能現在在OS X上是沒有操作的(我不確定)。 – torek 2013-03-20 21:02:10
各種UNIX發行版並不完全相同,因此在所有UNIX版本中應該兼容的首選方法是使用O_NOCTTY打開PTY,然後設置TIOCSCTTY,因爲ioctl(fd,TIOCSCTTY,NULL)調用在所有版本中都是兼容的。另一種選擇是忽略由ioctl(fd,TIOCSCTTY,NULL)返回的錯誤。 順便說一句,我發現了這個問題,我修改了上面的例子。 – Will 2013-03-27 18:27:45