int read_word_wops(struct wops_state *w, char *name, uint32_t *value) { int result[4], status, i; int expect[4] = { 6, 0, 2, 2 }; char *ptr; uint32_t tmp; if(maintain_wops(w) < 0){ return -1; } result[0] = append_string_katcl(w->w_line, KATCP_FLAG_FIRST | KATCP_FLAG_STRING, "?read"); result[1] = append_string_katcl(w->w_line, KATCP_FLAG_STRING, name); result[2] = append_unsigned_long_katcl(w->w_line, KATCP_FLAG_ULONG, 0); result[3] = append_unsigned_long_katcl(w->w_line, KATCP_FLAG_LAST | KATCP_FLAG_ULONG, 4); expect[1] = strlen(name) + 1; for(i = 0; i < 4; i++){ if(result[i] != expect[i]){ #ifdef DEBUG fprintf(stderr, "read: append[%d]=%d != %d\n", i, result[i], expect[i]); #endif return -1; } } while((status = complete_rpc_katcl(w->w_line, 0, &(w->w_when))) == 0); #ifdef DEBUG fprintf(stderr, "read: status is %d\n", status); #endif if(status < 0){ if(w->w_line){ destroy_rpc_katcl(w->w_line); w->w_line = NULL; } return -1; } ptr = arg_string_katcl(w->w_line, 1); if(ptr == NULL){ return -1; } if(strcmp(ptr, KATCP_OK)){ return 1; } status = arg_buffer_katcl(w->w_line, 2, &tmp, 4); if(status != 4){ return -1; } *value = ntohl(tmp); return 0; }
int main() { struct katcl_line *l; struct katcl_parse *p; int count, seed, i, k, fds[2], result, al, bl; char alpha[MAX_ARG_LEN], beta[MAX_ARG_LEN]; pid_t pid; seed = getpid(); printf("line test: seed is %d\n", seed); srand(seed); if(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0){ fprintf(stderr, "line: unable to create socketpair\n"); return 1; } pid = fork(); if(pid < 0){ fprintf(stderr, "line: unable to fork\n"); return 1; } if(pid == 0){ close(fds[0]); echobuffer(fds[1]); return 0; } close(fds[1]); l = create_katcl(fds[0]); if(l == NULL){ fprintf(stderr, "main: unable to create katcl\n"); return 1; } for(i = 0; i < TEST_RUNS; i++){ #ifdef DEBUG fprintf(stderr, "line test: iteration %d\n", i); #endif p = create_referenced_parse_katcl(); if(p == NULL){ fprintf(stderr, "unable to create parse instance %d\n", i); return 1; } #ifdef DEBUG fprintf(stderr, "test: ref before submission %d\n", p->p_refs); #endif fill_random_test(p); dump_parse_katcl(p, "random", stderr); if(append_parse_katcl(l, p) < 0){ fprintf(stderr, "unable to add parse %d\n", i); return 1; } #ifdef DEBUG fprintf(stderr, "test: ref after submission %d\n", p->p_refs); #endif while((result = write_katcl(l)) == 0); #ifdef DEBUG fprintf(stderr, "test: ref after write %d\n", p->p_refs); #endif if(result < 0){ fprintf(stderr, "unable to write data\n"); return 1; } do{ result = read_katcl(l); if(result){ fprintf(stderr, "read result is %d\n", result); return 1; } } while(have_katcl(l) == 0); count = arg_count_katcl(l); for(k = 0; k < count; k++){ al = arg_buffer_katcl(l, k, alpha, MAX_ARG_LEN); bl = get_buffer_parse_katcl(p, k, beta, MAX_ARG_LEN); if((bl < 0) || (al < 0)){ fprintf(stderr, "al=%d, bl=%d\n", al, bl); return 1; } if(al != bl){ fprintf(stderr, "al=%d != bl=%d\n", al, bl); return 1; } if(memcmp(alpha, beta, al)){ fprintf(stderr, "mismatch: round=%d, arg=%d\n", i, k); return 1; } } fprintf(stderr, "parsed a line with %d words\n", count); destroy_parse_katcl(p); } destroy_katcl(l, 1); printf("line test: ok\n"); return 0; }
int print_arg(struct katcl_line *l, int index, int fmt) { char *ptr, *tmp; unsigned int want, have, safe, i, dfmt; switch(fmt){ case FMT_TEXT : ptr = arg_string_katcl(l, index); if(ptr == NULL){ #ifdef DEBUG fprintf(stderr, "print: unable to acquire argument %d\n", index); #endif return -1; } fputs(ptr, stdout); return 0; case FMT_HEX : case FMT_BIN : case FMT_AUTO : ptr = NULL; want = BUFFER; have = 0; safe = TIMEOUT; do{ tmp = realloc(ptr, want); if(tmp == NULL){ free(ptr); #ifdef DEBUG fprintf(stderr, "print: unable to reallocate %p to %d\n", ptr, want); #endif return -1; } have = want; ptr = tmp; want = arg_buffer_katcl(l, index, ptr, have); safe--; if(!safe){ #ifdef DEBUG fprintf(stderr, "print: safety threshold exceeded, wanted %d\n", want); #endif free(ptr); return -1; } } while(want > have); if(want <= 0){ free(ptr); #ifdef DEBUG fprintf(stderr, "print: argument %d length is %d\n", index, want); #endif return (want < 0) ? -1 : 0; } if(fmt == FMT_AUTO){ dfmt = FMT_TEXT; for(i = 0; i < want; i++){ if(!isprint(ptr[i])){ dfmt = FMT_HEX; } } } else { dfmt = fmt; } switch(dfmt){ case FMT_BIN : case FMT_TEXT : fwrite(ptr, 1, want, stdout); break; case FMT_HEX : fprintf(stdout, "0x"); for(i = 0; i < want; i++){ fprintf(stdout, "%02x", ((unsigned char *)ptr)[i]); } } free(ptr); return 0; default : #ifdef DEBUG fprintf(stderr, "print: unknown format %d\n", fmt); #endif return -1; } }
int perform_check_wops(struct wops_state *w, char *op) { int j, base, result; uint32_t check, mask, got; base = extract_register_wops(w, op); if(base <= 0){ return base; } mask = 0xffffffff; check = 0; for(j = 0; (j < 32) && (op[base + j] != '\0'); j++){ check = check << 1; mask = mask << 1; switch(op[base + j]){ case 'x' : case 'X' : mask |= 1; break; case '1' : check |= 1; break; case '0' : break; default : return WOPS_ERROR_PERMANENT; } } mask = ~mask; #ifdef DEBUG fprintf(stderr, "check: name=%s, mask=%08x, check=%08x\n", w->w_register, mask, check); #endif for(;;){ result = read_word_wops(w, w->w_register, &got); if(result < 0){ #ifdef DEBUG fprintf(stderr, "check: read returns failure=%d\n", result); #endif return WOPS_ERROR_COMMS; } #if 0 result = send_rpc_katcl(w->w_line, 10000, KATCP_FLAG_FIRST | KATCP_FLAG_STRING, "?read", KATCP_FLAG_STRING, w->w_register, KATCP_FLAG_STRING, "0", KATCP_FLAG_LAST | KATCP_FLAG_STRING, "4"); if(result < 0){ return WOPS_ERROR_COMMS; } if(arg_buffer_katcl(w->w_line, 2, &got, 4) != 4){ return WOPS_ERROR_COMMS; } #endif #ifdef DEBUG fprintf(stderr, "check: got %08x\n", got); #endif if((got & mask) == check){ #ifdef DEBUG fprintf(stderr, "check: tested succeeded (masked got = 0x%0x)\n", got & mask); #endif return WOPS_OK; } /* TODO: something more clever with this */ sleep(1); } return 0; }