static int Unix_cf_pclose(FILE *pp) { int fd; pid_t pid; CfDebug("Unix_cf_pclose(pp)\n"); if (!ThreadLock(cft_count)) { return -1; } if (CHILDREN == NULL) /* popen hasn't been called */ { ThreadUnlock(cft_count); return -1; } ThreadUnlock(cft_count); ALARM_PID = -1; fd = fileno(pp); if (fd >= MAX_FD) { CfOut(cf_error, "", "File descriptor %d of child higher than MAX_FD in Unix_cf_pclose, check for defunct children", fd); pid = -1; } else { if ((pid = CHILDREN[fd]) == 0) { return -1; } ThreadLock(cft_count); CHILDREN[fd] = 0; ThreadUnlock(cft_count); } if (fclose(pp) == EOF) { return -1; } return cf_pwait(pid); }
int cf_pclose(FILE *pp) { int fd = fileno(pp); pid_t pid; if (!ThreadLock(cft_count)) { fclose(pp); return -1; } if (CHILDREN == NULL) /* popen hasn't been called */ { ThreadUnlock(cft_count); fclose(pp); return -1; } ALARM_PID = -1; if (fd >= MAX_FD) { ThreadUnlock(cft_count); Log(LOG_LEVEL_ERR, "File descriptor %d of child higher than MAX_FD in cf_pclose!", fd); pid = 0; } else { pid = CHILDREN[fd]; CHILDREN[fd] = 0; ThreadUnlock(cft_count); } if (fclose(pp) == EOF || pid == 0) { return -1; } return cf_pwait(pid); }
static FILE *Unix_cf_popen_shsetuid(char *command, char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv) { int i, pd[2]; pid_t pid; FILE *pp = NULL; CfDebug("Unix_cf_popen_shsetuid(%s,%s,%d,%d)\n", command, type, uid, gid); if ((*type != 'r' && *type != 'w') || (type[1] != '\0')) { errno = EINVAL; return NULL; } if (!ThreadLock(cft_count)) { return NULL; } if (CHILDREN == NULL) /* first time */ { CHILDREN = xcalloc(MAX_FD, sizeof(pid_t)); } ThreadUnlock(cft_count); if (pipe(pd) < 0) /* Create a pair of descriptors to this process */ { return NULL; } if ((pid = fork()) == -1) { close(pd[0]); close(pd[1]); return NULL; } signal(SIGCHLD, SIG_DFL); ALARM_PID = (pid != 0 ? pid : -1); if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } for (i = 0; i < MAX_FD; i++) { if (CHILDREN[i] > 0) { close(i); } } if (chrootv && strlen(chrootv) != 0) { if (chroot(chrootv) == -1) { CfOut(cf_error, "chroot", "Couldn't chroot to %s\n", chrootv); return NULL; } } if (chdirv && strlen(chdirv) != 0) { if (chdir(chdirv) == -1) { CfOut(cf_error, "chdir", "Couldn't chdir to %s\n", chdirv); return NULL; } } if (!CfSetuid(uid, gid)) { _exit(1); } execl(SHELL_PATH, "sh", "-c", command, NULL); _exit(1); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } if (fileno(pp) >= MAX_FD) { CfOut(cf_error, "", "File descriptor %d of child %d higher than MAX_FD in Unix_cf_popen_shsetuid, check for defunct children", fileno(pp), pid); cf_pwait(pid); return NULL; } else { ThreadLock(cft_count); CHILDREN[fileno(pp)] = pid; ThreadUnlock(cft_count); } return pp; } return NULL; }
static FILE *Unix_cf_popen(char *command, char *type) { int i, pd[2]; char **argv; pid_t pid; FILE *pp = NULL; CfDebug("Unix_cf_popen(%s)\n", command); if ((*type != 'r' && *type != 'w') || (type[1] != '\0')) { errno = EINVAL; return NULL; } if (!ThreadLock(cft_count)) { return NULL; } if (CHILDREN == NULL) /* first time */ { CHILDREN = xcalloc(MAX_FD, sizeof(pid_t)); } ThreadUnlock(cft_count); if (pipe(pd) < 0) /* Create a pair of descriptors to this process */ { return NULL; } if ((pid = fork()) == -1) { close(pd[0]); close(pd[1]); return NULL; } signal(SIGCHLD, SIG_DFL); ALARM_PID = (pid != 0 ? pid : -1); if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } for (i = 0; i < MAX_FD; i++) { if (CHILDREN[i] > 0) { close(i); } } argv = ArgSplitCommand(command); if (execv(argv[0], argv) == -1) { CfOut(cf_error, "execv", "Couldn't run %s", argv[0]); } _exit(1); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } if (fileno(pp) >= MAX_FD) { CfOut(cf_error, "", "File descriptor %d of child %d higher than MAX_FD in Unix_cf_popen, check for defunct children", fileno(pp), pid); } else { ThreadLock(cft_count); CHILDREN[fileno(pp)] = pid; ThreadUnlock(cft_count); } return pp; } return NULL; /* Cannot reach here */ }
FILE *cf_popen_shsetuid(const char *command, char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv, int background) { int pd[2]; pid_t pid; FILE *pp = NULL; CfDebug("cf_popen_shsetuid(%s,%s,%" PRIuMAX ",%" PRIuMAX ")\n", command, type, (uintmax_t)uid, (uintmax_t)gid); pid = CreatePipeAndFork(type, pd); if (pid == -1) { return NULL; } if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } CloseChildrenFD(); if (chrootv && (strlen(chrootv) != 0)) { if (chroot(chrootv) == -1) { CfOut(cf_error, "chroot", "Couldn't chroot to %s\n", chrootv); return NULL; } } if (chdirv && (strlen(chdirv) != 0)) { if (chdir(chdirv) == -1) { CfOut(cf_error, "chdir", "Couldn't chdir to %s\n", chdirv); return NULL; } } if (!CfSetuid(uid, gid)) { _exit(1); } execl(SHELL_PATH, "sh", "-c", command, NULL); _exit(1); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } SetChildFD(fileno(pp), pid); return pp; } return NULL; }
FILE *cf_popen_sh(const char *command, char *type) { int pd[2]; pid_t pid; FILE *pp = NULL; CfDebug("cf_popen_sh(%s)\n", command); pid = CreatePipeAndFork(type, pd); if (pid == -1) { return NULL; } if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } CloseChildrenFD(); execl(SHELL_PATH, "sh", "-c", command, NULL); _exit(1); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } SetChildFD(fileno(pp), pid); return pp; } return NULL; }
FILE *cf_popen(const char *command, char *type) { int pd[2]; char **argv; pid_t pid; FILE *pp = NULL; CfDebug("cf_popen(%s)\n", command); pid = CreatePipeAndFork(type, pd); if (pid == -1) { return NULL; } if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } CloseChildrenFD(); argv = ArgSplitCommand(command); if (execv(argv[0], argv) == -1) { CfOut(cf_error, "execv", "Couldn't run %s", argv[0]); } _exit(1); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } SetChildFD(fileno(pp), pid); return pp; } return NULL; /* Cannot reach here */ }
FILE *cf_popensetuid(const char *command, char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv, int background) { int i, pd[2]; char **argv; pid_t pid; FILE *pp = NULL; CfDebug("cf_popensetuid(%s,%s,%" PRIuMAX ",%" PRIuMAX ")\n", command, type, (uintmax_t)uid, (uintmax_t)gid); if (((*type != 'r') && (*type != 'w')) || (type[1] != '\0')) { errno = EINVAL; return NULL; } if (!ThreadLock(cft_count)) { return NULL; } if (CHILDREN == NULL) /* first time */ { CHILDREN = xcalloc(MAX_FD, sizeof(pid_t)); } ThreadUnlock(cft_count); if (pipe(pd) < 0) /* Create a pair of descriptors to this process */ { return NULL; } if ((pid = fork()) == -1) { close(pd[0]); close(pd[1]); return NULL; } signal(SIGCHLD, SIG_DFL); ALARM_PID = (pid != 0 ? pid : -1); if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } for (i = 0; i < MAX_FD; i++) { if (CHILDREN[i] > 0) { close(i); } } argv = ArgSplitCommand(command); if (chrootv && (strlen(chrootv) != 0)) { if (chroot(chrootv) == -1) { CfOut(cf_error, "chroot", "Couldn't chroot to %s\n", chrootv); ArgFree(argv); return NULL; } } if (chdirv && (strlen(chdirv) != 0)) { if (chdir(chdirv) == -1) { CfOut(cf_error, "chdir", "Couldn't chdir to %s\n", chdirv); ArgFree(argv); return NULL; } } if (!CfSetuid(uid, gid)) { _exit(1); } if (execv(argv[0], argv) == -1) { CfOut(cf_error, "execv", "Couldn't run %s", argv[0]); } _exit(1); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } if (fileno(pp) >= MAX_FD) { CfOut(cf_error, "", "File descriptor %d of child %jd higher than MAX_FD in cf_popensetuid, check for defunct children", fileno(pp), (intmax_t)pid); } else { ThreadLock(cft_count); CHILDREN[fileno(pp)] = pid; ThreadUnlock(cft_count); } return pp; } return NULL; /* cannot reach here */ }
FILE *cf_popensetuid(const char *command, char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv, int background) { int pd[2]; char **argv; pid_t pid; FILE *pp = NULL; CfDebug("cf_popensetuid(%s,%s,%" PRIuMAX ",%" PRIuMAX ")\n", command, type, (uintmax_t)uid, (uintmax_t)gid); pid = CreatePipeAndFork(type, pd); if (pid == -1) { return NULL; } if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } CloseChildrenFD(); argv = ArgSplitCommand(command); if (chrootv && (strlen(chrootv) != 0)) { if (chroot(chrootv) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "chroot", "Couldn't chroot to %s\n", chrootv); ArgFree(argv); return NULL; } } if (chdirv && (strlen(chdirv) != 0)) { if (chdir(chdirv) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "chdir", "Couldn't chdir to %s\n", chdirv); ArgFree(argv); return NULL; } } if (!CfSetuid(uid, gid)) { _exit(1); } if (execv(argv[0], argv) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "execv", "Couldn't run %s", argv[0]); } _exit(1); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } SetChildFD(fileno(pp), pid); return pp; } return NULL; /* cannot reach here */ }
FILE *cf_popen_shsetuid(const char *command, const char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv, ARG_UNUSED int background) { int pd[2]; pid_t pid; FILE *pp = NULL; pid = CreatePipeAndFork(type, pd); if (pid == -1) { return NULL; } if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } CloseChildrenFD(); if (chrootv && (strlen(chrootv) != 0)) { if (chroot(chrootv) == -1) { Log(LOG_LEVEL_ERR, "Couldn't chroot to '%s'. (chroot: %s)", chrootv, GetErrorStr()); return NULL; } } if (chdirv && (strlen(chdirv) != 0)) { if (safe_chdir(chdirv) == -1) { Log(LOG_LEVEL_ERR, "Couldn't chdir to '%s'. (chdir: %s)", chdirv, GetErrorStr()); return NULL; } } if (!CfSetuid(uid, gid)) { _exit(EXIT_FAILURE); } execl(SHELL_PATH, "sh", "-c", command, NULL); _exit(EXIT_FAILURE); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } SetChildFD(fileno(pp), pid); return pp; } return NULL; }
FILE *cf_popen(const char *command, const char *type, bool capture_stderr) { int pd[2]; char **argv; pid_t pid; FILE *pp = NULL; pid = CreatePipeAndFork(type, pd); if (pid == -1) { return NULL; } if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ if (capture_stderr) { dup2(pd[1], 2); /* Merge stdout/stderr */ } else { int nullfd = open(NULLFILE, O_WRONLY); dup2(nullfd, 2); close(nullfd); } close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } CloseChildrenFD(); argv = ArgSplitCommand(command); if (execv(argv[0], argv) == -1) { Log(LOG_LEVEL_ERR, "Couldn't run '%s'. (execv: %s)", argv[0], GetErrorStr()); } _exit(EXIT_FAILURE); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } SetChildFD(fileno(pp), pid); return pp; } return NULL; /* Cannot reach here */ }