Commit 9d604ec6 authored by Nick Mathewson's avatar Nick Mathewson 🦀
Browse files

Add code to read configuration lines from a string as well as a file


svn:r2676
parent 831c988e
Loading
Loading
Loading
Loading
+79 −1
Original line number Diff line number Diff line
@@ -875,7 +875,7 @@ char *read_file_to_str(const char *filename, int bin) {
int
parse_line_from_file(char *line, size_t maxlen, FILE *f,
                     char **key_out, char **value_out) {
  char *s, *key, *end, *value;
  char *s;

try_next_line:
  if(!fgets(line, maxlen, f)) {
@@ -883,6 +883,17 @@ try_next_line:
      return 0;
    return -1; /* real error */
  }
  line[maxlen-1] = '\0';

  s = parse_line_from_str(line, key_out, value_out);
  if (!s)
    return -1;
  if (!*key_out)
    goto try_next_line;

  return 1;

#if 0

  if((s = strchr(line,'#'))) /* strip comments */
    *s = 0; /* stop the line there */
@@ -920,6 +931,73 @@ try_next_line:
  log_fn(LOG_DEBUG,"got keyword '%s', value '%s'", key, value);
  *key_out = key, *value_out = value;
  return 1;
#endif
}


/** DOCDOC.
 *
 * Return next line or end of string on success, NULL on failure.
 */
char *
parse_line_from_str(char *line, char **key_out, char **value_out)
{
  char *key, *val, *cp;

  tor_assert(key_out);
  tor_assert(value_out);

  *key_out = *value_out = key = val = NULL;
  /* Skip until the first keyword. */
  while (1) {
    while (isspace(*line))
      ++line;
    if (*line == '#') {
      while (*line && *line != '\n')
        ++line;
    } else {
      break;
    }
  }

  if (!*line) { /* End of string? */
    *key_out = *value_out = NULL;
    return line;
  }

  /* Skip until the next space. */
  key = line;
  while (*line && !isspace(*line) && *line != '#')
    ++line;

  /* Skip until the value */
  while (*line == ' ' || *line == '\t')
    *line++ = '\0';
  val = line;

  /* Find the end of the line. */
  while (*line && *line != '\n' && *line != '#')
    ++line;
  if (*line == '\n')
    cp = line++;
  else {
    cp = line-1;
  }
  while (cp>=val && isspace(*cp))
    *cp-- = '\0';

  if (*line == '#') {
    do {
      *line++ = '\0';
    } while (*line && *line != '\n');
    if (*line == '\n')
      ++line;
  }

  *key_out = key;
  *value_out = val;

  return line;
}

/** Expand any homedir prefix on 'filename'; return a newly allocated
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ int write_bytes_to_file(const char *fname, const char *str, size_t len,
                        int bin);
char *read_file_to_str(const char *filename, int bin);
int parse_line_from_file(char *line, size_t maxlen, FILE *f, char **key_out, char **value_out);
char *parse_line_from_str(char *line, char **key_out, char **value_out);
char *expand_filename(const char *filename);

/* Net helpers */
+48 −1
Original line number Diff line number Diff line
@@ -489,7 +489,7 @@ test_util(void) {
  int i;
  uint32_t u32;
  uint16_t u16;
  char *cp;
  char *cp, *k, *v;

  start.tv_sec = 5;
  start.tv_usec = 5000;
@@ -674,6 +674,53 @@ test_util(void) {
  test_eq(10L, tor_parse_long("10",10,0,100,NULL,NULL));
  test_eq(0L, tor_parse_long("10",10,50,100,NULL,NULL));

  /* Test parse_line_from_str */
  strlcpy(buf, "k v\n" " key    value with spaces   \n"  "keykey val\n"
          "k2\n"
          "k3 \n"  "\n" "   \n" "#comment\n"
          "k4#a\n" "k5#abc\n" "k6 val #with comment\n", sizeof(buf));
  cp = buf;

  cp = parse_line_from_str(cp, &k, &v);
  test_streq(k, "k");
  test_streq(v, "v");
  test_assert(!strcmpstart(cp, " key    value with"));

  cp = parse_line_from_str(cp, &k, &v);
  test_streq(k, "key");
  test_streq(v, "value with spaces");
  test_assert(!strcmpstart(cp, "keykey"));

  cp = parse_line_from_str(cp, &k, &v);
  test_streq(k, "keykey");
  test_streq(v, "val");
  test_assert(!strcmpstart(cp, "k2\n"));

  cp = parse_line_from_str(cp, &k, &v);
  test_streq(k, "k2");
  test_streq(v, "");
  test_assert(!strcmpstart(cp, "k3 \n"));

  cp = parse_line_from_str(cp, &k, &v);
  test_streq(k, "k3");
  test_streq(v, "");
  test_assert(!strcmpstart(cp, "\n   \n"));

  cp = parse_line_from_str(cp, &k, &v);
  test_streq(k, "k4");
  test_streq(v, "");
  test_assert(!strcmpstart(cp, "k5#abc"));

  cp = parse_line_from_str(cp, &k, &v);
  test_streq(k, "k5");
  test_streq(v, "");
  test_assert(!strcmpstart(cp, "k6"));

  cp = parse_line_from_str(cp, &k, &v);
  test_streq(k, "k6");
  test_streq(v, "val");
  test_streq(cp, "");

  /* XXXX test older functions. */
  smartlist_free(sl);
}