int32_t write_clusters(char* outname, char* outname_end, uintptr_t unfiltered_indiv_ct, uintptr_t* indiv_exclude, uintptr_t indiv_ct, char* person_ids, uintptr_t max_person_id_len, uint32_t omit_unassigned, uintptr_t cluster_ct, uint32_t* cluster_map, uint32_t* cluster_starts, char* cluster_ids, uintptr_t max_cluster_id_len) { unsigned char* wkspace_mark = wkspace_base; FILE* outfile = NULL; uintptr_t indiv_uidx = 0; int32_t retval = 0; uint32_t* indiv_to_cluster; char* person_id_ptr; char* bufptr; uintptr_t indiv_idx; uint32_t cluster_idx; uint32_t slen; if (wkspace_alloc_ui_checked(&indiv_to_cluster, unfiltered_indiv_ct * sizeof(int32_t))) { goto write_cluster_ret_NOMEM; } fill_unfiltered_indiv_to_cluster(unfiltered_indiv_ct, cluster_ct, cluster_map, cluster_starts, indiv_to_cluster); memcpy(outname_end, ".clst", 6); if (fopen_checked(&outfile, outname, "w")) { goto write_cluster_ret_OPEN_FAIL; } for (indiv_idx = 0; indiv_idx < indiv_ct; indiv_idx++) { indiv_uidx = next_non_set_unsafe(indiv_exclude, indiv_uidx); cluster_idx = indiv_to_cluster[indiv_uidx]; if ((!omit_unassigned) || (cluster_idx != 0xffffffffU)) { person_id_ptr = &(person_ids[indiv_uidx * max_person_id_len]); slen = strlen_se(person_id_ptr); bufptr = memcpyax(tbuf, person_id_ptr, slen, ' '); bufptr = strcpyax(bufptr, &(person_id_ptr[slen + 1]), ' '); if (cluster_idx != 0xffffffffU) { bufptr = strcpyax(bufptr, &(cluster_ids[cluster_idx * max_cluster_id_len]), '\n'); } else { bufptr = memcpyl3a(bufptr, "NA\n"); } if (fwrite_checked(tbuf, bufptr - tbuf, outfile)) { goto write_cluster_ret_WRITE_FAIL; } } indiv_uidx++; } if (fclose_null(&outfile)) { goto write_cluster_ret_WRITE_FAIL; } sprintf(logbuf, "Pruned cluster assignments written to %s.\n", outname); logprintb(); while (0) { write_cluster_ret_NOMEM: retval = RET_NOMEM; break; write_cluster_ret_OPEN_FAIL: retval = RET_OPEN_FAIL; break; write_cluster_ret_WRITE_FAIL: retval = RET_WRITE_FAIL; break; } fclose_cond(outfile); wkspace_reset(wkspace_mark); return retval; }
/* * Get the responses back from the server, taking appropriate action on each * one depending on its type. Sets the errorcode parameter to the exit status * of the remote command, or to 1 if the remote command failed with an error. * Returns true on success, false if some protocol-level error occurred when * reading the responses. */ static bool process_response(struct remctl *r, int *errorcode) { struct remctl_output *out; *errorcode = 0; out = remctl_output(r); while (out != NULL && out->type != REMCTL_OUT_DONE) { switch (out->type) { case REMCTL_OUT_OUTPUT: if (out->stream == 1) fwrite_checked(out->data, out->length, 1, stdout); else if (out->stream == 2) fwrite_checked(out->data, out->length, 1, stderr); else { warn("unknown output stream %d", out->stream); fwrite_checked(out->data, out->length, 1, stderr); } break; case REMCTL_OUT_ERROR: *errorcode = 255; fwrite_checked(out->data, out->length, 1, stderr); fputc('\n', stderr); return true; case REMCTL_OUT_STATUS: *errorcode = out->status; return true; case REMCTL_OUT_DONE: break; } out = remctl_output(r); } if (out == NULL) { die("error reading from server: %s", remctl_error(r)); return false; } else return true; }