0

工作控制中的 tcgetattr 和 tcsetattr

大家好。我目前正在用 C 语言重新创建一个 shell,其中包括作业控制。

我现在正在重新编码内置的 fg。

根据thisthis 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 应保持在前台本身并继续从终端读取命令。

图片

我错过了什么?

4

0 回答 0