int main(int argc, char **argv) { struct katcl_line *l; int result, total, i; char *ptr; if(argc <= 2){ fprintf(stderr, "usage: %s server-ip[:server-port] command\n", argv[0]); fprintf(stderr, "example: %s localhost:7147 ?watchdog\n", argv[0]); return 1; } /* connect to a remote machine, arg is "server:port" where ":port is optional" */ l = create_name_rpc_katcl(argv[1]); if(l == NULL){ fprintf(stderr, "unable to create client connection to server %s: %s\n", argv[1], strerror(errno)); return 1; } /* send the request, with 5000ms timeout. Here we don't pass any parameters */ result = send_rpc_katcl(l, 5000, KATCP_FLAG_FIRST | KATCP_FLAG_LAST | KATCP_FLAG_STRING, argv[2], NULL); /* result is 0 if the reply returns "ok", 1 if it failed and -1 if things went wrong doing IO or otherwise */ printf("result of %s request is %d\n", argv[2], result); /* you can examine the content of the reply with the following functions */ total = arg_count_katcl(l); printf("have %d arguments in reply\n", total); for(i = 0; i < total; i++){ /* for binary data use the arg_buffer_katcl, string will stop at the first occurrence of a \0 */ ptr = arg_string_katcl(l, i); printf("reply[%d] is <%s>\n", i, ptr); } destroy_rpc_katcl(l); 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 main(int argc, char **argv) { char *app, *server, *match, *parm, *tmp, *cmd, *extra; int i, j, c, fd; int verbose, result, status, base, run, info, reply, display, max, prefix, timeout, fmt, pos, flags, munge, show; struct katcl_line *l, *k; fd_set fsr, fsw; struct timeval tv; server = getenv("KATCP_SERVER"); if(server == NULL){ server = "localhost"; } info = 1; reply = 1; verbose = 1; i = j = 1; app = argv[0]; base = (-1); timeout = 5; fmt = FMT_TEXT; pos = (-1); k = NULL; munge = 0; show = 1; while (i < argc) { if (argv[i][0] == '-') { c = argv[i][j]; switch (c) { case 'h' : usage(app); return 0; case 'v' : verbose++; j++; break; case 'q' : verbose = 0; info = 0; reply = 0; j++; break; case 'i' : info = 1 - info; j++; break; case 'r' : reply = 1 - reply; j++; break; case 'n' : show = 0; j++; break; case 'k' : k = create_katcl(STDOUT_FILENO); if(k == NULL){ fprintf(stderr, "%s: unable to create katcp message logic\n", app); return 2; } j++; break; case 'a' : fmt = FMT_AUTO; j++; break; case 'x' : fmt = FMT_HEX; j++; break; case 'b' : fmt = FMT_BIN; j++; break; case 'm' : munge = 1; j++; break; case 's' : case 't' : case 'p' : j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fprintf(stderr, "%s: argument needs a parameter\n", app); return 2; } switch(c){ case 's' : server = argv[i] + j; break; case 't' : timeout = atoi(argv[i] + j); break; case 'p' : pos = atoi(argv[i] + j); if(pos < 0){ fprintf(stderr, "%s: position needs to be nonnegative, not %d\n", app, pos); return 2; } break; } i++; j = 1; break; case '-' : j++; break; case '\0': j = 1; i++; break; default: fprintf(stderr, "%s: unknown option -%c\n", app, argv[i][j]); return 2; } } else { base = i; i = argc; } } if(munge){ if(k){ reply = 1; } } if(base < 0){ if(k){ sync_message_katcl(k, KATCP_LEVEL_ERROR, KCPCMD_NAME, "no command given"); } fprintf(stderr, "%s: need a command to send (use -h for help)\n", app); return 2; } status = 1; flags = 0; if(verbose > 0){ flags = NETC_VERBOSE_ERRORS; if(verbose > 1){ flags = NETC_VERBOSE_STATS; } } fd = net_connect(server, 0, flags); if(fd < 0){ if(k){ sync_message_katcl(k, KATCP_LEVEL_ERROR, KCPCMD_NAME, "unable to connect to %s", server); } return 2; } l = create_katcl(fd); if(l == NULL){ if(k){ sync_message_katcl(k, KATCP_LEVEL_ERROR, KCPCMD_NAME, "unable to create katcp parser"); } fprintf(stderr, "%s: unable to create katcp parser\n", app); return 2; } i = base; match = NULL; flags = ((i + 1) < argc) ? KATCP_FLAG_FIRST : (KATCP_FLAG_FIRST | KATCP_FLAG_LAST); switch(argv[i][0]){ case KATCP_REQUEST : match = argv[i] + 1; /* FALL */ case KATCP_INFORM : case KATCP_REPLY : append_string_katcl(l, flags, argv[i]); break; default : match = argv[i]; append_args_katcl(l, flags, "%c%s", KATCP_REQUEST, argv[i]); break; } i++; while(i < argc){ tmp = argv[i]; i++; flags = (i < argc) ? 0 : KATCP_FLAG_LAST; if(load_arg(l, tmp, fmt, flags) < 0){ if(k){ sync_message_katcl(k, KATCP_LEVEL_ERROR, KCPCMD_NAME, "unable to load argument %d", i); } fprintf(stderr, "%s: unable to load argument %d\n", app, i); return 2; } } if(match){ for(prefix = 0; (match[prefix] != '\0') && (match[prefix] != ' '); prefix++); #ifdef DEBUG fprintf(stderr, "debug: checking prefix %d of %s\n", prefix, match); #endif } else { prefix = 0; /* pacify -Wall, prefix only used if match is set */ } /* WARNING: logic a bit intricate */ for(run = 1; run;){ FD_ZERO(&fsr); FD_ZERO(&fsw); if(match){ /* only look for data if we need it */ FD_SET(fd, &fsr); } if(flushing_katcl(l)){ /* only write data if we have some */ FD_SET(fd, &fsw); } tv.tv_sec = timeout; tv.tv_usec = 0; result = select(fd + 1, &fsr, &fsw, NULL, &tv); switch(result){ case -1 : switch(errno){ case EAGAIN : case EINTR : continue; /* WARNING */ default : if(k){ sync_message_katcl(k, KATCP_LEVEL_ERROR, KCPCMD_NAME, "select failed: %s", strerror(errno)); } return 2; } break; case 0 : if(k){ sync_message_katcl(k, KATCP_LEVEL_ERROR, KCPCMD_NAME, "request timed out after %d seconds", timeout); } if(verbose){ fprintf(stderr, "%s: no io activity within %d seconds\n", app, timeout); } /* could terminate cleanly here, but ... */ return 2; } if(FD_ISSET(fd, &fsw)){ result = write_katcl(l); if(result < 0){ if(k){ sync_message_katcl(k, KATCP_LEVEL_ERROR, KCPCMD_NAME, "write failed: %s", strerror(errno)); } fprintf(stderr, "%s: write failed: %s\n", app, strerror(error_katcl(l))); return 2; } if((result > 0) && (match == NULL)){ /* if we finished writing and don't expect a match then quit */ run = 0; } } if(FD_ISSET(fd, &fsr)){ result = read_katcl(l); if(result){ if(k){ sync_message_katcl(k, KATCP_LEVEL_ERROR, KCPCMD_NAME, "read failed: %s", (result < 0) ? strerror(error_katcl(l)) : "connection terminated"); } fprintf(stderr, "%s: read failed: %s\n", app, (result < 0) ? strerror(error_katcl(l)) : "connection terminated"); return 2; } } while(have_katcl(l) > 0){ cmd = arg_string_katcl(l, 0); if(cmd){ display = 0; switch(cmd[0]){ case KATCP_INFORM : display = info; if(show == 0){ if(!strcmp(KATCP_VERSION_CONNECT_INFORM, cmd)){ display = 0; } } break; case KATCP_REPLY : display = reply; parm = arg_string_katcl(l, 1); if(match){ if(strncmp(match, cmd + 1, prefix) || ((cmd[prefix + 1] != '\0') && (cmd[prefix + 1] != ' '))){ if(k){ sync_message_katcl(k, KATCP_LEVEL_WARN, KCPCMD_NAME, "encountered unexpected reply %s", cmd); } fprintf(stderr, "%s: warning: encountered unexpected reply <%s>\n", app, cmd); } else { if(parm && !strcmp(parm, KATCP_OK)){ status = 0; } run = 0; } } break; case KATCP_REQUEST : if(k){ sync_message_katcl(k, KATCP_LEVEL_WARN, KCPCMD_NAME, "encountered unanswerable request %s", cmd); } fprintf(stderr, "%s: warning: encountered an unanswerable request <%s>\n", app, cmd); break; default : if(k){ sync_message_katcl(k, KATCP_LEVEL_WARN, KCPCMD_NAME, "read malformed message %s", cmd); } fprintf(stderr, "%s: read malformed message <%s>\n", app, cmd); break; } if(display){ #ifdef DEBUG fprintf(stderr, "need to display\n"); #endif if(k){ if(munge && parm && (cmd[0] == KATCP_REPLY)){ if(!strcmp(parm, KATCP_OK)){ sync_message_katcl(k, KATCP_LEVEL_DEBUG, cmd + 1, KATCP_OK); } else { extra = arg_string_katcl(l, 2); sync_message_katcl(k, KATCP_LEVEL_WARN, cmd + 1, "%s (%s)", parm, extra ? extra : "no extra information"); } } else { relay_katcl(l, k); } } else { max = arg_count_katcl(l); if(pos < 0){ for(i = 0; i < max; i++){ if(print_arg(l, i, fmt) < 0){ fprintf(stderr, "%s: failed to print argument %d\n", app, i); return 2; } fputc(((i + 1) == max) ? '\n' : ' ' , stdout); } } else { if(pos < max){ i = pos; if(print_arg(l, i, fmt) < 0){ fprintf(stderr, "%s: failed to print argument %d\n", app, i); return 2; } } } } } } } } destroy_katcl(l, 1); if(k){ while(write_katcl(k) == 0); destroy_katcl(k, 0); } return status; }