Beispiel #1
0
int load_arg(struct katcl_line *l, char *arg, int fmt, int flags)
{
  unsigned char *tmp;
  int len, i, j, v, result;

  switch(fmt){
    case FMT_BIN  :
    case FMT_TEXT :
      return append_string_katcl(l, flags, arg);
    case FMT_AUTO : 
    case FMT_HEX  : 
      if(strncmp(arg, "0x", 2)){
        return append_string_katcl(l, flags, arg);
      } else {
        len = strlen(arg + 2);
        if(len % 2){
          fprintf(stderr, "warning: argument %s contains an odd number of hex characters, ignoring the trailing one\n", arg);
          len--;
        }

        len = len / 2;

        if(len == 0){
          /* NULL parameters are really bad form */
          return append_buffer_katcl(l, flags, NULL, 0);
        }

        tmp = malloc(len);
        if(tmp == NULL){
          fprintf(stderr, "warning: argument %s contains an odd number of hex characters, ignoring the trailing one\n", arg);
          return -1;
        }
  
        j = 2; 
        for(i = 0; i < len; i++){
          v = h2n(arg[j++]);
          if(v < 0){
            free(tmp);
            return -1;
          }
          tmp[i] = 0xf0 & (v << 4);
          v = h2n(arg[j++]);
          if(v < 0){
            free(tmp);
            return -1;
          }
          tmp[i] |= 0x0f & v;
        }

        result = append_buffer_katcl(l, flags, tmp, len);
        free(tmp);

        return result;
      }
      break;
    default :
      fprintf(stderr, "error: unhandled format %d\n", fmt);
      return -1;
  }
}
Beispiel #2
0
int vextra_response_katcl(struct katcl_line *cl, int code, char *fmt, va_list args)
{
  int result[3];
  char *name, *status;

  if(code > KATCP_RESULT_OK){
    return -1;
  }

  name = arg_copy_string_katcl(cl, 0);
  if(name == NULL){
    return -1;
  }
  name[0] = KATCP_REPLY;

  status = code_to_name_katcm(code);
  if(status == NULL){
    return -1;
  }

  result[0] = append_string_katcl(cl, KATCP_FLAG_FIRST, name);
  result[1] = append_string_katcl(cl, 0, status);
  result[2] = append_vargs_katcl(cl, KATCP_FLAG_LAST, fmt, args);

  return vector_sum(result, 3);
}
Beispiel #3
0
int write_word_wops(struct wops_state *w, char *name, uint32_t value)
{
  int result[4], status, i;
  int expect[4] = { 7, 0, 2, 5 };
  char *ptr;
  uint32_t tmp;

  if(maintain_wops(w) < 0){
    return -1;
  }

  tmp = htonl(value);

  result[0] = append_string_katcl(w->w_line,       KATCP_FLAG_FIRST | KATCP_FLAG_STRING, "?write");
  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_buffer_katcl(w->w_line,        KATCP_FLAG_LAST | KATCP_FLAG_BUFFER, &tmp, 4);

  expect[1] = strlen(name) + 1;
  for(i = 0; i < 4; i++){
    if(result[i] != expect[i]){
#ifdef DEBUG
      fprintf(stderr, "write: result[%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);
  if(status < 0){
    if(w->w_line){
      destroy_rpc_katcl(w->w_line);
      w->w_line = NULL;
    }
#ifdef DEBUG
    fprintf(stderr, "write: complete call failed\n");
#endif
    return -1;
  }

  ptr = arg_string_katcl(w->w_line, 1);
  if(ptr == NULL){
#ifdef DEBUG
    fprintf(stderr, "write: unable to acquire first parameter\n");
#endif
    return -1;
  }

  if(strcmp(ptr, KATCP_OK)){
#ifdef DEBUG
    fprintf(stderr, "write: problematic return code %s\n", ptr);
#endif
    return 1;
  }

  return 0;
}
Beispiel #4
0
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;
}
Beispiel #5
0
int basic_inform_katcl(struct katcl_line *cl, char *name, char *arg)
{
  int result[2];

  if(arg){
    result[0] = append_string_katcl(cl, KATCP_FLAG_FIRST, name);
    result[1] = append_string_katcl(cl, KATCP_FLAG_LAST, arg);
    return vector_sum(result, 2);
  } else {
    return append_string_katcl(cl, KATCP_FLAG_FIRST | KATCP_FLAG_LAST, name);
  }
}
Beispiel #6
0
int reg_req_wordread(struct katcl_line *l, char *reg)
{
    int ret = 0;

    if (l == NULL) {
        fprintf(stderr, "NULL katcl_line pointer");
        return -1;
    }

    ret += append_string_katcl(l, KATCP_FLAG_FIRST | KATCP_FLAG_STRING, REG_KATCP_WORDREAD);
    ret += append_string_katcl(l, KATCP_FLAG_LAST | KATCP_FLAG_STRING, reg);

    return ret;
}
Beispiel #7
0
int vlog_message_katcl(struct katcl_line *cl, int level, char *name, char *fmt, va_list args)
{
  int result[5];
  struct timeval now;
  unsigned int milli;
  char *subsystem, *logstring;

#ifdef DEBUG
  if(level >= KATCP_LEVEL_OFF){
    fprintf(stderr, "log: bad form to a message of level off or worse\n");
    return -1;
  }
#endif

  logstring = log_to_string_katcl(level);
  if(logstring == NULL){
#ifdef DEBUG
    fprintf(stderr, "log: bad log level\n");
    abort();
#endif
    return -1;
  }

  subsystem = name ? name : "unknown" ;

  gettimeofday(&now, NULL);
  milli = now.tv_usec / 1000;

  result[0] = append_string_katcl(cl, KATCP_FLAG_FIRST, KATCP_LOG_INFORM);
  result[1] = append_string_katcl(cl, 0, logstring);
  result[2] = append_args_katcl(cl, 0, "%lu%03d", now.tv_sec, milli);
  result[3] = append_string_katcl(cl, 0, subsystem);

#if DEBUG > 1
  fprintf(stderr, "log: my fmt string is <%s>, milli=%u\n", fmt, milli);
#endif

  result[4] = append_vargs_katcl(cl, KATCP_FLAG_LAST, fmt, args);

  /* do the right thing, collect error codes */
  return vector_sum(result, 5);
}
Beispiel #8
0
int upload_tbs(struct katcl_line *l, void *data)
{ 
  struct tbs_port_data *pd;
  int run, lfd, nfd, rr, wr, have;
  unsigned char buf[MTU];

  if (data == NULL)
    return -1;

  pd = data;
  if (pd == NULL)
    return -1;

  lfd = net_listen(NULL, pd->t_port, NETC_VERBOSE_ERRORS | NETC_VERBOSE_STATS);
  if (lfd < 0){
    return -1;
  }

  signal(SIGALRM, SIG_DFL);
  alarm(UPLOAD_TIMEOUT);

  nfd = accept(lfd, NULL, 0);
  close(lfd);

  if (nfd < 0){
    return -1;
  }
  
  for (run = 1; run > 0; ){

    rr = read(nfd, buf, MTU);

    if (rr == 0){
      run = rr;
      break;
    } else if (rr < 0){
      sync_message_katcl(l, KATCP_LEVEL_INFO, NULL, "%s: read failed while receiving bof file: %s", __func__, strerror(errno));
      append_string_katcl(l, KATCP_FLAG_FIRST | KATCP_FLAG_STRING | KATCP_FLAG_LAST, UPLOADFAIL);
      while(write_katcl(l) == 0);
      close(nfd);
      return -1;
    }

    have = 0;
    do {
      wr = write(pd->t_fd, buf+have, rr-have);
      switch(wr){
        case -1:
          switch(errno){
            case EAGAIN:
            case EINTR:
              break;
            default:
              sync_message_katcl(l, KATCP_LEVEL_INFO, NULL, "%s: WRITE FAILED %s", __func__, strerror(errno));
              append_string_katcl(l, KATCP_FLAG_FIRST | KATCP_FLAG_STRING | KATCP_FLAG_LAST, UPLOADFAIL);
              while(write_katcl(l) == 0);
              close(nfd);
              return-1;
          }
        case 0:
          sync_message_katcl(l, KATCP_LEVEL_INFO, NULL, "%s: WRITE FAILED %s", __func__, strerror(errno));
          append_string_katcl(l, KATCP_FLAG_FIRST | KATCP_FLAG_STRING | KATCP_FLAG_LAST, UPLOADFAIL);
          while(write_katcl(l) == 0);
          close(nfd);
          return-1;
        default:
          have += wr;
          sync_message_katcl(l, KATCP_LEVEL_DEBUG, NULL, "%s: wrote %d bytes to parent", __func__, wr);
          break;
      }
    } while(have < rr);

    pd->t_rsize += rr;

    sync_message_katcl(l, KATCP_LEVEL_INFO, NULL, "uploaded %d bytes", pd->t_rsize);
    alarm(UPLOAD_TIMEOUT);
  }
  
  append_string_katcl(l, KATCP_FLAG_FIRST | KATCP_FLAG_STRING | KATCP_FLAG_LAST, UPLOADCOMPLETE);
  while(write_katcl(l) == 0);
  close(nfd);

  alarm(0);

  return 0;
}
Beispiel #9
0
int vsend_katcl(struct katcl_line *l, va_list args)
{
  int flags, result, check;
  char *string;
  void *buffer;
  unsigned long value;
  int len;
#ifdef KATCP_USE_FLOATS
  double dvalue;
#endif

  check = KATCP_FLAG_FIRST;
  
  do{
    flags = va_arg(args, int);
    if((check & flags) != check){
      /* WARNING: tests first arg for FLAG_FIRST */
#ifdef DEBUG
      fprintf(stderr, "vsend: flag check failed 0x%x\n", flags);
#endif
      return -1;
    }
    check = 0;

    switch(flags & KATCP_TYPE_FLAGS){
      case KATCP_FLAG_STRING :
        string = va_arg(args, char *);
        result = append_string_katcl(l, flags & KATCP_ORDER_FLAGS, string);
        break;
      case KATCP_FLAG_SLONG :
        value = va_arg(args, unsigned long);
        result = append_signed_long_katcl(l, flags & KATCP_ORDER_FLAGS, value);
        break;
      case KATCP_FLAG_ULONG :
        value = va_arg(args, unsigned long);
        result = append_unsigned_long_katcl(l, flags & KATCP_ORDER_FLAGS, value);
        break;
      case KATCP_FLAG_XLONG :
        value = va_arg(args, unsigned long);
        result = append_hex_long_katcl(l, flags & KATCP_ORDER_FLAGS, value);
        break;
      case KATCP_FLAG_BUFFER :
        buffer = va_arg(args, void *);
        len = va_arg(args, int);
        result = append_buffer_katcl(l, flags & KATCP_ORDER_FLAGS, buffer, len);
        break;
#ifdef KATCP_USE_FLOATS
        case KATCP_FLAG_DOUBLE :
        dvalue = va_arg(args, double);
        result = append_double_katcl(l, flags & KATCP_ORDER_FLAGS, dvalue);
        break;
#endif
      default :
#ifdef DEBUG
        fprintf(stderr, "vsend: bad type flag 0x%x\n", flags);
#endif
        result = (-1);
        break;
    }
#if DEBUG > 1
    fprintf(stderr, "vsend: appended: flags=0x%02x, result=%d\n", flags, result);
#endif
    if(result <= 0){
#ifdef DEBUG
      fprintf(stderr, "vsend: bad result for type 0x%x\n", flags);
#endif
      return -1;
    }
  } while(!(flags & KATCP_FLAG_LAST));

  return 0;
}
Beispiel #10
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;
}