工作控制中的 tcgetattr 和 tcsetattr
大家好。我目前正在用 C 语言重新创建一个 shell,其中包括作业控制。
我现在正在重新编码内置的 fg。
根据this和this documentation,似乎他们在创建新工作时将termios保存在工作结构中,然后用tcsetattr
.
我正在尝试(几乎)做同样的事情。这是我的代码:
当我在链接列表中创建新工作时:
static t_jobs_lst *new(void)
{
t_jobs_lst *job;
if (!(job = (t_jobs_lst *)malloc(sizeof(t_jobs_lst))))
return (NULL);
job->command = NULL;
job->job_number = g_shell.jobs.index++;
job->pid = 0;
job->childs = NULL;
job->current = '+';
job->state = "Running";
tcgetattr(STDERR_FILENO, &job->tmodes);
job->prev = NULL;
job->next = NULL;
jobs_insert(job);
return (job);
}
当我尝试将其设置在前台时:
int change_grp(t_shell *shell, int converted, int cont)
{
t_jobs_lst *searched;
int wpid;
int status;
signal(SIGTTOU, SIG_IGN);
searched = job_search(shell, converted);
if (tcsetpgrp(STDERR_FILENO, searched->pid) < 0)
return (EXIT_FAILURE);
ft_printf("%s\n", searched->command);
/* Send the job a continue signal, if necessary. */
if (cont)
{
tcsetattr(STDERR_FILENO, TCSADRAIN, &searched->tmodes); //causing bug in termcaps when uncommented
if (kill(-searched->pid, SIGCONT) < 0)
return (EXIT_FAILURE);
}
wpid = 0;
status = 0;
while (!wpid)
{
pause();
wpid = waitpid(searched->pid, &status, WNOHANG);
}
if (tcsetpgrp(0, shell->pid) < 0)
return (EXIT_FAILURE);
/* Restore the shell's terminal modes. */
tcgetattr (STDERR_FILENO, &searched->tmodes);
tcsetattr (STDERR_FILENO, TCSADRAIN, &shell->prev_term);
job_delete(shell, searched->pid);
return (EXIT_SUCCESS);
}
我的问题是:当tcsetattr(STDERR_FILENO, TCSADRAIN, &searched->tmodes); //causing bug in termcaps when uncommented
未注释时,它似乎打破了我的术语上限,如下图所示。
如果这一行被注释,我不能输入任何东西,只有按 CTRL-C 才能让我回到 shell 上。
当我想停止它时,我应该能够键入 AND 以按 CTRL-C,如第一个链接中所述。
如果进程组作为后台作业启动,shell 应保持在前台本身并继续从终端读取命令。
我错过了什么?