Skip to content

c - 系统执行

static pid_t child_pid;

static void kill_child(int sig)
{
    kill(child_pid, SIGKILL);
}

/**
 * @brief 使用fork执行系统命令,返回从stdout读取到长度值
 *
 * @param cmd  需要执行的命令
 * @param buf  读取到数据存在的buf
 * @param count buf参数的最大长度
 * @param wstatus 返回执行状态0才代表成功
 * @return int 读取到的stdout的长度
 */
int fork_with_result(const char *cmd, void *buf, size_t count, int *wstatus)
{
    int status, fds[2];
    if (pipe(fds)) {
        loge("Failed to spawn pipe.\n");
        return -1;
    }

    signal(SIGALRM, (void (*)(int))kill_child);

    switch ((child_pid = fork())) {
        case -1:
            close(fds[0]);
            close(fds[1]);
            loge("Failed to fork process.\n");
            return -1;
        case 0:
            dup2(fds[1], 1);
            dup2(fds[1], 2);
            close(fds[0]);
            close(fds[1]);
            if (execl("/bin/sh", "sh", "-c", cmd, (char *)0) < 0) {
                loge("Failed execl\n");
                exit(-1);
            }
            exit(0);
        default:
            /* 子进程默认最多允许执行60秒钟 */
            alarm(60);
            /* 关闭写入端 */
            close(fds[1]);
            int wpid;
            while ((wpid = wait(&status)) > 0)
                ;
            int len = 0;
            if (buf && count)
                len = read(fds[0], buf, count);
            if (wstatus) {
                /*分析返回值*/
                if (WIFEXITED(status)) {
                    *wstatus = WEXITSTATUS(status);
                    logd("Exited, status=%d.\n", *wstatus);
                } else {
                    loge("Abornaml exited.\n");
                    *wstatus = -1;
                    if (WIFSIGNALED(status)) {
                        logd("Killed by signal %d\n", WTERMSIG(status));
                    } else if (WIFSTOPPED(status)) {
                        logd("Stopped by signal %d\n", WSTOPSIG(status));
                    } else if (WIFCONTINUED(status)) {
                        logd("Continued\n");
                    }
                }
            }
            close(fds[0]);
            return len;
    }
    return 0;
}