#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>

#define MAX_CHILDREN 1024
#define MAX_LINE     256

static pid_t child_pids[MAX_CHILDREN];
static int   child_count = 0;

static void sigchld_handler(int sig){
    int saved_errno = errno;
    pid_t pid;
    int   status;

    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
        printf("[SIGCHLD] 子进程 %d 已终止", pid);
        if (WIFEXITED(status))
            printf(", 退出码=%d", WEXITSTATUS(status));
        if (WIFSIGNALED(status))
            printf(", 被信号 %d (%s) 终止", WTERMSIG(status),
                   (WTERMSIG(status) == SIGTERM) ? "SIGTERM" : "");
        printf("\n");

        for (int i = 0; i < child_count; i++) {
            if (child_pids[i] == pid) {
                child_pids[i] = child_pids[child_count - 1];
                child_count--;
                break;
            }
        }
    }
    errno = saved_errno;
}

static void child_main(void)
{
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = SIG_DFL;
    sigemptyset(&sa.sa_mask);

    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGTERM);
    sigprocmask(SIG_BLOCK, &mask, NULL);

    printf("子进程 %d 启动\n", getpid());

    /* 等待 SIGTERM 信号 */
    int sig;
    sigwait(&mask, &sig);

    printf("killed by parent\n");
    exit(100);
}

static void cmd_create(int n)
{
    sigset_t block_mask, old_mask;

    sigemptyset(&block_mask);
    sigaddset(&block_mask, SIGCHLD);
    sigprocmask(SIG_BLOCK, &block_mask, &old_mask);

    int created = 0;
    for (int i = 0; i < n; i++) {
        if (child_count >= MAX_CHILDREN) {
            printf("子进程数已达上限 %d\n", MAX_CHILDREN);
            break;
        }
        pid_t pid = fork();
        if (pid < 0) {
            perror("fork");
            break;
        }
        if (pid == 0) {
            sigprocmask(SIG_SETMASK, &old_mask, NULL);
            child_main();
        }
        child_pids[child_count++] = pid;
        created++;
    }

    sigprocmask(SIG_SETMASK, &old_mask, NULL);

    if (created > 0) {
        printf("已创建 %d 个子进程:", created);
        for (int i = child_count - created; i < child_count; i++)
            printf(" %d", child_pids[i]);
        printf("\n");
    }
}

static void cmd_kill(int n, pid_t *pids)
{
    for (int i = 0; i < n; i++) {
        int found = 0;
        for (int j = 0; j < child_count; j++) {
            if (child_pids[j] == pids[i]) {
                found = 1;
                break;
            }
        }
        if (!found) {
            printf("PID %d 不是当前管理的子进程, 跳过\n", pids[i]);
            continue;
        }
        if (kill(pids[i], SIGTERM) == 0) {
            printf("已向子进程 %d 发送终止信号\n", pids[i]);
        } else {
            perror("kill");
        }
    }
}

static void cmd_ps(void)
{
    sigset_t block_mask, old_mask;

    sigemptyset(&block_mask);
    sigaddset(&block_mask, SIGCHLD);
    sigprocmask(SIG_BLOCK, &block_mask, &old_mask);

    if (child_count == 0) {
        printf("当前无子进程\n");
    } else {
        printf("当前子进程 (%d 个):", child_count);
        for (int i = 0; i < child_count; i++)
            printf(" %d", child_pids[i]);
        printf("\n");
    }

    sigprocmask(SIG_SETMASK, &old_mask, NULL);
}

static void process_command(char *line)
{
    size_t len = strlen(line);
    if (len > 0 && line[len - 1] == '\n')
    {
        line[len - 1] = '\0';
    }
    if (len == 0)
    {
        return;
    }

    char *cmd = strtok(line, " ");
    if (!cmd)
    {
        return;
    }
    
    if (strcmp(cmd, "create") == 0) {
        char *arg = strtok(NULL, " ");
        if (!arg) {
            printf("用法: create <n>\n");
            return;
        }
        int n = atoi(arg);
        if (n <= 0) {
            printf("无效的子进程数量: %s\n", arg);
            return;
        }
        cmd_create(n);

    }
    else if (strcmp(cmd, "kill") == 0) {
        pid_t pids[256];
        int n = 0;
        char *arg;
        while ((arg = strtok(NULL, " ")) && n < 256) {
            pids[n++] = atoi(arg);
        }
        if (n == 0) {
            printf("用法: kill <P1> <P2> ...\n");
            return;
        }
        cmd_kill(n, pids);

    } else if (strcmp(cmd, "ps") == 0) {
        char *arg = strtok(NULL, " ");
        if (!arg || strcmp(arg, "-u") != 0) {
            printf("用法: ps -u\n");
            return;
        }
        cmd_ps();

    } else if (strcmp(cmd, "exit") == 0) {
        sigset_t block_mask, old_mask;
        sigemptyset(&block_mask);
        sigaddset(&block_mask, SIGCHLD);
        sigprocmask(SIG_BLOCK, &block_mask, &old_mask);
        int remaining = child_count;
        sigprocmask(SIG_SETMASK, &old_mask, NULL);

        if (remaining > 0) {
            printf("还有 %d 个子进程未终止, 请先 kill 或等待其结束\n", remaining);
            return;
        }
        printf("所有子进程已结束, 父进程退出\n");
        exit(0);

    } else {
        printf("未知命令: %s\n", cmd);
        printf("支持: create <n> | kill <P1> ... | ps -u | exit\n");
    }
}

int main(void)
{
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = sigchld_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
        sigaction(SIGCHLD, &sa, NULL);

    /* 忽略 SIGTERM, 父进程不会被意外终止 */
    signal(SIGTERM, SIG_IGN);

    printf("=== 子进程管理程序 ===\n");
    printf("命令: create <n> | kill <P1> <P2> ... | ps -u | exit\n");

    char line[MAX_LINE];
    while (1) {
        printf("> ");
        fflush(stdout);
        if (!fgets(line, sizeof(line), stdin)) 
        {
            break;  /* EOF */
        }
        process_command(line);
    }

    printf("父进程退出\n");
    return 0;
}