我的shell无法阻止ctrl + c杀死自己

时间:2019-03-15 09:35:25

标签: c linux

我编写了自己的外壳程序(下面列出了源代码),并将用户的默认外壳程序设置为该外壳程序。

我用该用户登录并键入ctrl-C,即使捕获了此信号,该外壳也被杀死。但是,我直接从bash运行此shell,它按预期运行。有什么区别。

结果

使用默认外壳程序设置为我自己的外壳程序的用户登录:

BMC login:
BMC login: naroot
Password:
BMC > signal = 2
BMC login:

直接在bash下运行它:

~# /tmp/systemshell
BMC > signal = 2
BMC > signal = 2
BMC > signal = 2
BMC >

源代码

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <readline/readline.h>
#include <readline/history.h>

#include <signal.h> // sigaction(), sigsuspend(), sig*()

void signalHandler(int signum) {
    signal(SIGINT, signalHandler);
    signal(SIGTSTP, signalHandler);
    signal(SIGQUIT, SIG_IGN);
    signal(SIGTTIN, SIG_IGN);
    signal(SIGTTOU, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);

    printf("signal = %d\n", signum);
}

int main()
{
    signal(SIGINT, signalHandler);
    signal(SIGTSTP, signalHandler);
    signal(SIGQUIT, SIG_IGN);
    signal(SIGTTIN, SIG_IGN);
    signal(SIGTTOU, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);

    char *input;

    while (1) {
        input = readline("BMC > ");
        if (input) {
            printf("%s\n", input);
            free(input);
        }
    }
    return 0;
}

1 个答案:

答案 0 :(得分:0)

我想知道ash或其他bash为何可以工作,所以请深入研究ash的源代码。我尝试了这个snippets

有效

    int ofd;
    ofd = fd = open(_PATH_TTY, O_RDWR);
    if (fd < 0) {
/* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
 * That sometimes helps to acquire controlling tty.
 * Obviously, a workaround for bugs when someone
 * failed to provide a controlling tty to bash! :) */
        fd = 2;
        while (!isatty(fd))
            if (--fd < 0)
                goto out;
    }
    /* fd is a tty at this point */
    fd = fcntl(fd, F_DUPFD, 10);
    if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, dont */
        close(ofd);
    if (fd < 0)
        goto out; /* F_DUPFD failed */
    close_on_exec_on(fd);
    while (1) { /* while we are in the background */
        pgrp = tcgetpgrp(fd);
        if (pgrp < 0) {
out:
            ash_msg("can't access tty; job control turned off");
            mflag = on = 0;
            goto close;
        }
        if (pgrp == getpgrp())
            break;
        killpg(0, SIGTTIN);
    }
    initialpgrp = pgrp;

    setsignal(SIGTSTP);
    setsignal(SIGTTOU);
    setsignal(SIGTTIN);
    pgrp = rootpid;
    setpgid(0, pgrp);
    xtcsetpgrp(fd, pgrp);