int ni_process_run_and_capture_output(ni_process_t *pi, ni_buffer_t *out_buffer) { int pfd[2], rv; if (pipe(pfd) < 0) { ni_error("%s: unable to create pipe: %m", __func__); return -1; } rv = __ni_process_run(pi, pfd); if (rv < 0) { close(pfd[0]); close(pfd[1]); return rv; } close(pfd[1]); while (1) { int cnt; if (ni_buffer_tailroom(out_buffer) < 256) ni_buffer_ensure_tailroom(out_buffer, 4096); cnt = read(pfd[0], ni_buffer_tail(out_buffer), ni_buffer_tailroom(out_buffer)); if (cnt == 0) { break; } else if (cnt > 0) { out_buffer->tail += cnt; } else if (errno != EINTR) { ni_error("read error on subprocess pipe: %m"); return -1; } } while (waitpid(pi->pid, &pi->status, 0) < 0) { if (errno == EINTR) continue; ni_error("%s: waitpid returns error (%m)", __func__); return -1; } pi->pid = 0; if (pi->notify_callback) pi->notify_callback(pi); if (!ni_process_exit_status_okay(pi)) { ni_error("subprocesses exited with error"); return -1; } return rv; }
ni_buffer_t * ni_file_read(FILE *fp) { struct stat stb; unsigned int count, done, size; ni_buffer_t *result; if (fstat(fileno(fp), &stb) < 0) return NULL; if (S_ISREG(stb.st_mode)) { size = stb.st_size; result = ni_buffer_new_dynamic(size); if (result == NULL) return NULL; for (done = 0; done < size; done += count) { void *buffer = ni_buffer_tail(result); count = fread(buffer, 1, size - done, fp); if (count == 0) break; ni_buffer_push_tail(result, count); } } else { /* Could be a pipe or tty or socket */ result = ni_buffer_new_dynamic(4096); if (result == NULL) return NULL; while (TRUE) { void *buffer; ni_buffer_ensure_tailroom(result, 4096); buffer = ni_buffer_tail(result); count = fread(buffer, 1, ni_buffer_tailroom(result), fp); if (count == 0) break; ni_buffer_push_tail(result, count); } } if (ferror(fp)) { ni_error("%s: read error on file", __func__); ni_buffer_free(result); return NULL; } return result; }
int ni_process_run_and_capture_output(ni_process_t *pi, ni_buffer_t *out_buffer) { int pfd[2], rv; if (pipe(pfd) < 0) { ni_error("%s: unable to create pipe: %m", __func__); return NI_PROCESS_FAILURE; } rv = __ni_process_run(pi, pfd); if (rv < NI_PROCESS_SUCCESS) { close(pfd[0]); close(pfd[1]); return rv; } rv = NI_PROCESS_SUCCESS; close(pfd[1]); while (1) { int cnt; if (ni_buffer_tailroom(out_buffer) < 256) ni_buffer_ensure_tailroom(out_buffer, 4096); cnt = read(pfd[0], ni_buffer_tail(out_buffer), ni_buffer_tailroom(out_buffer)); if (cnt == 0) { break; } else if (cnt > 0) { out_buffer->tail += cnt; } else if (errno != EINTR) { ni_error("read error on subprocess pipe: %m"); rv = NI_PROCESS_IOERROR; break; } } close(pfd[0]); while (waitpid(pi->pid, &pi->status, 0) < 0) { if (errno == EINTR) continue; ni_error("%s: waitpid returns error (%m)", __func__); rv = NI_PROCESS_WAITPID; } if (pi->notify_callback) pi->notify_callback(pi); if (rv != NI_PROCESS_SUCCESS) return rv; return __ni_process_run_info(pi); }
/* * Connect the subprocess output to our I/O handling loop */ static void __ni_process_output_recv(ni_socket_t *sock) { ni_process_t *pi = sock->user_data; ni_buffer_t *rbuf = &sock->rbuf; int cnt; ni_assert(pi); if (ni_buffer_tailroom(rbuf) < 256) ni_buffer_ensure_tailroom(rbuf, 4096); cnt = recv(sock->__fd, ni_buffer_tail(rbuf), ni_buffer_tailroom(rbuf), MSG_DONTWAIT); if (cnt >= 0) { rbuf->tail += cnt; } else if (errno != EWOULDBLOCK) { ni_error("read error on subprocess pipe: %m"); ni_socket_deactivate(sock); } }
/* * Connect the subprocess output to our I/O handling loop */ static void __ni_process_output_recv(ni_socket_t *sock) { ni_process_t *pi = sock->user_data; ni_buffer_t *rbuf = &sock->rbuf; int cnt; ni_assert(pi); /* Grow socket input buffer as needed. * NB: we may put an upper limit on how much process output we capture. * Anything beyond a few MB is insane... */ if (ni_buffer_tailroom(rbuf) < 256) ni_buffer_ensure_tailroom(rbuf, 4096); cnt = recv(sock->__fd, ni_buffer_tail(rbuf), ni_buffer_tailroom(rbuf), MSG_DONTWAIT); if (cnt >= 0) { rbuf->tail += cnt; } else if (errno != EWOULDBLOCK) { ni_error("read error on subprocess pipe: %m"); ni_socket_deactivate(sock); } }
ni_iaid_map_t * ni_iaid_map_load(const char *filename) { ni_iaid_map_t *map; const char *type; ni_buffer_t buff; struct stat stb; ssize_t len; if (!(map = ni_iaid_map_new())) { ni_error("unable to allocate memory for iaid map: %m"); return NULL; } if (filename) { type = "given"; if (!ni_string_dup(&map->file, filename)) { ni_error("unable to copy %s iaid map file name (%s): %m", type, filename); goto failure; } if (!ni_iaid_map_open(map)) { ni_error("unable to open %s iaid map file name (%s): %m", type, map->file); goto failure; } } else { type = "default"; if (!ni_iaid_map_set_default_file(&map->file)) { ni_error("unable to construct %s iaid map file name: %m", type); goto failure; } if (!ni_iaid_map_open(map)) { ni_debug_readwrite("unable to open %s iaid map file name (%s): %m", type, map->file); type = "fallback"; if (!ni_iaid_map_set_fallback_file(&map->file)) { ni_error("unable to construct %s iaid map file name: %m", type); goto failure; } if (!ni_iaid_map_open(map)) { ni_error("unable to open iaid map file name (%s): %m", map->file); goto failure; } } } if (!ni_iaid_map_lock(map)) { ni_error("unable to lock %s iaid map file name (%s): %m", type, map->file); goto failure; } if (fstat(map->fd, &stb) < 0) stb.st_size = BUFSIZ; ni_buffer_init_dynamic(&buff, stb.st_size + 1); do { if (!ni_buffer_tailroom(&buff)) ni_buffer_ensure_tailroom(&buff, BUFSIZ); do { len = read(map->fd, ni_buffer_tail(&buff), ni_buffer_tailroom(&buff)); if (len > 0) ni_buffer_push_tail(&buff, len); } while (len < 0 && errno == EINTR); } while (len > 0); if (len < 0) { ni_error("unable to read %s iaid map file name (%s): %m", type, map->file); } else { map->doc = xml_document_from_buffer(&buff, map->file); ni_buffer_destroy(&buff); if (!map->doc) { map->doc = xml_document_new(); ni_warn("unable to parse %s iaid map file name (%s): %m", type, map->file); } return map; } failure: ni_iaid_map_free(map); return NULL; }