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;
}
Exemple #2
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;
}
Exemple #3
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;
}