Пример #1
0
static kernel_symbol_t *
do_lookup (kernel_symbol_t *symbols,
	   gulong        address,
	   int           first,
	   int           last)
{
    if (address >= symbols[last].address)
    {
	return &(symbols[last]);
    }
    else if (last - first < 3)
    {
	while (last >= first)
	{
	    if (address >= symbols[last].address)
		return &(symbols[last]);

	    last--;
	}

	return NULL;
    }
    else
    {
	int mid = (first + last) / 2;

	if (symbols[mid].address > address)
	    return do_lookup (symbols, address, first, mid);
	else
	    return do_lookup (symbols, address, mid, last);
    }
}
Пример #2
0
int
handle_transfer_command(struct thread_data_t * datum, char * args)
{
  long amount, balance;
  char * user, buffer[MAX_COMMAND_LENGTH];

  #ifndef NDEBUG
  if (*args == '\0') {
    fprintf(stderr,
            "[thread %lu] WARNING: [%s] arguments empty\n",
            datum->id, "transfer");
  } else {
    fprintf(stderr,
            "[thread %lu] INFO: [%s] '%s' (arguments)\n",
            datum->id, "transfer", args);
  }
  #endif
  amount = strtol(args, &args, 10);
  user = ++args;

  if (amount <= 0 || amount > MAX_TRANSACTION) {
    snprintf(buffer, MAX_COMMAND_LENGTH, "Invalid transfer amount.");
  } else if (datum->credentials.userlength
   && do_lookup(session_data.db_conn, NULL,
                datum->credentials.username,
                datum->credentials.userlength,
                &balance) == BANKING_SUCCESS) {
    if (balance < amount) {
      snprintf(buffer, MAX_COMMAND_LENGTH, "Insufficient funds.");
    } else if (do_update(session_data.db_conn, NULL,
               datum->credentials.username,
               datum->credentials.userlength,
               balance - amount)
            || do_lookup(session_data.db_conn, NULL,
               user, strnlen(user, MAX_COMMAND_LENGTH),
               &balance)
            || do_update(session_data.db_conn, NULL,
               user, strnlen(user, MAX_COMMAND_LENGTH),
               balance + amount)) {
      /* TODO atomic operation? */
      snprintf(buffer, MAX_COMMAND_LENGTH, "Cannot complete transfer.");
    } else {
      snprintf(buffer, MAX_COMMAND_LENGTH, "Transfered $%li to %s",
                                           amount, user);
    }
  } else {
    snprintf(buffer, MAX_COMMAND_LENGTH, "TRANSFER ERROR");
  }
  salt_and_pepper(buffer, NULL, &datum->buffet);
  encrypt_message(&datum->buffet, datum->credentials.key);
  send_message(&datum->buffet, datum->sock);

  return BANKING_SUCCESS;
}
void __attribute__((constructor)) construct() {
    /* test if we can do a dlsym() lookup in the constructor */
    if(do_lookup("time") == NULL) {
        fprintf(stdout, "failed to load time() in constructor\n");
    } else {
        fprintf(stdout, "succeeded loading time() in constructor\n");
    }
    if(do_lookup("malloc") == NULL) {
        fprintf(stdout, "failed to load malloc() in constructor\n");
    } else {
        fprintf(stdout, "succeeded loading malloc() in constructor\n");
    }
}
Пример #4
0
/**
 *  Look up the codeword for a given 8 bit value. If the value does not
 *  appear in the tree, this function will provide the codeword for not
 *  seen, and return 0.
 */
    PUBLIC int
lookup_codeword (const node_t *tree, int ch, char *buffer, int length)
{
    if (seen_symbol (ch) != 1 && ch != END_OF_STREAM)
    {
        // look up the codeword for NOT_SEEN
        do_lookup (tree, NOT_SEEN, buffer, length);
        return 0;
    }
    else
    {
        do_lookup (tree, ch, buffer, length);
        return 1;
    }
}
Пример #5
0
static void dns_test(void)
{
	do_lookup("os.inf.tu-dresden.de");
	do_lookup("www.heise.de");
	do_lookup("www.twitter.com");
	do_lookup("www.tudos.org");
	do_lookup("www.ifsr.de");
	do_lookup("www.dynamo-dresden.de");
	do_lookup("www.spiegel.de");
	do_lookup("www.smoking-gnu.de");
	do_lookup("www.fail.fx");
}
Пример #6
0
/**
 * g_resource_open_stream:
 * @resource: A #GResource
 * @path: A pathname inside the resource
 * @lookup_flags: A #GResourceLookupFlags
 * @error: return location for a #GError, or %NULL
 *
 * Looks for a file at the specified @path in the resource and
 * returns a #GInputStream that lets you read the data.
 *
 * @lookup_flags controls the behaviour of the lookup.
 *
 * Returns: (transfer full): #GInputStream or %NULL on error.
 *     Free the returned object with g_object_unref()
 *
 * Since: 2.32
 **/
GInputStream *
g_resource_open_stream (GResource             *resource,
                        const gchar           *path,
                        GResourceLookupFlags   lookup_flags,
                        GError               **error)
{
  const void *data;
  gsize data_size;
  guint32 flags;
  GInputStream *stream, *stream2;

  if (!do_lookup (resource, path, lookup_flags, NULL, &flags, &data, &data_size, error))
    return NULL;

  stream = g_memory_input_stream_new_from_data (data, data_size, NULL);
  g_object_set_data_full (G_OBJECT (stream), "g-resource",
                          g_resource_ref (resource),
                          (GDestroyNotify)g_resource_unref);

  if (flags & G_RESOURCE_FLAGS_COMPRESSED)
    {
      GZlibDecompressor *decompressor =
        g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_ZLIB);

      stream2 = g_converter_input_stream_new (stream, G_CONVERTER (decompressor));
      g_object_unref (decompressor);
      g_object_unref (stream);
      stream = stream2;
    }

  return stream;
}
Пример #7
0
int
handle_balance_command(struct thread_data_t * datum, char * args)
{
  long int balance;
  char buffer[MAX_COMMAND_LENGTH];

  /* Balance command takes no arguments */
  #ifndef NDEBUG
  if (*args != '\0') {
    fprintf(stderr,
            "[thread %lu] WARNING: ignoring '%s' (argument residue)\n",
            datum->id, args);
  }
  #endif

  /* Formulate a response */
  memset(buffer, '\0', MAX_COMMAND_LENGTH);
  /* If we have a username, try to do a lookup */
  if (datum->credentials.userlength
   && do_lookup(session_data.db_conn, NULL,
                datum->credentials.username,
                datum->credentials.userlength,
                &balance) == BANKING_SUCCESS) {
    snprintf(buffer, MAX_COMMAND_LENGTH,
             "%s, your balance is $%li.",
             datum->credentials.username, balance);
  } else {
    snprintf(buffer, MAX_COMMAND_LENGTH, "BALANCE ERROR");
  }
  /* Send the results */
  salt_and_pepper(buffer, NULL, &datum->buffet);
  encrypt_message(&datum->buffet, datum->credentials.key);
  send_message(&datum->buffet, datum->sock);
  return BANKING_SUCCESS;
}
Пример #8
0
struct bstree_node *bstree_insert(struct bstree_node *node, struct bstree *tree)
{
	struct bstree_node *key, *parent;
	int is_left;

	key = do_lookup(node, tree, &parent, &is_left);
	if (key)
		return key;

	if (!parent) {
		INIT_NODE(node);
		tree->root = tree->first = tree->last = node;
		return NULL;
	}
	if (is_left) {
		if (parent == tree->first)
			tree->first = node;
		set_prev(get_prev(parent), node);
		set_next(parent, node);
		set_left(node, parent);
	} else {
		if (parent == tree->last)
			tree->last = node;
		set_prev(parent, node);
		set_next(get_next(parent), node);
		set_right(node, parent);
	}
	return NULL;
}
Пример #9
0
void*  rbtree_lookup(struct rbtree* tree,void* key)
{
    assert(tree != NULL) ;
    struct rbtree_node* node;
    node = do_lookup(key,tree,NULL);
    return node == NULL ?NULL:node->data;
}
Пример #10
0
F_NONNULL
static void do_repl(gdmaps_t* gdmaps) {
    dmn_assert(gdmaps);

    char linebuf[256];
    char map_name[128];
    char ip_addr[128];
    const bool have_tty = isatty(fileno(stdin)) && isatty(fileno(stdout));
    while(1) {
        if(have_tty) {
            fputs("> ", stdout);
            fflush(stdout);
        }
        if(!fgets(linebuf, 255, stdin)) {
            if(!feof(stdin))
                log_err("fgets(stdin) failed: %s", dmn_logf_strerror(ferror(stdin)));
            if(have_tty)
                fputs("\n", stdout);
            return;
        }

        if(2 != sscanf(linebuf, "%127[^ \t\n] %127[^ \t\n]\n", map_name, ip_addr)) {
            log_err("Invalid input.  Please enter a map name followed by an IP address");
            continue;
        }

        do_lookup(gdmaps, map_name, ip_addr);
    }
}
Пример #11
0
struct avltree_node *avltree_lookup(const struct avltree_node *key,
				    const struct avltree *tree)
{
	struct avltree_node *parent, *unbalanced;
	int is_left;

	return do_lookup(key, tree, &parent, &unbalanced, &is_left);
}
 rpi_version_mapped_pin_id::rpi_version_mapped_pin_id
 ( pin_id_int_t pin
 , pin_id_int_t const * map
 , std::size_t n_pins
 , std::size_t n_versions
 )
 : pin_id(do_lookup(pin, rpi_info().index_version(), map, n_pins, n_versions))
 {}
Пример #13
0
struct bstree_node *bstree_lookup(const struct bstree_node *key,
				  const struct bstree *tree)
{
	struct bstree_node *parent;
	int is_left;

	return do_lookup(key, tree, &parent, &is_left);
}
Пример #14
0
/* 取得key用于遍历 */
const h_rb_cursor_st *h_rbtree_get_cursor(const h_rbtree_st *tree,
        const void *key, uint32_t ksize)
{
    rbtree_node_st *parent;
    int is_left;

    rbtree_node_st *result = do_lookup(tree, key, ksize, &parent, &is_left);
    return result == NULL ? NULL : &(result->cs);
}
Пример #15
0
int  rbtree_remove(struct rbtree* tree,void *key)
{
    struct rbtree_node* node = do_lookup(key,tree,NULL);
    if(node == NULL)
        return -1;
    else
        __rbtree_remove(node,tree);
    return 0;
}
Пример #16
0
/**
 * g_resource_get_info:
 * @resource: A #GResource
 * @path: A pathname inside the resource
 * @lookup_flags: A #GResourceLookupFlags
 * @size:  (out) (allow-none): a location to place the length of the contents of the file,
 *    or %NULL if the length is not needed
 * @flags:  (out) (allow-none): a location to place the flags about the file,
 *    or %NULL if the length is not needed
 * @error: return location for a #GError, or %NULL
 *
 * Looks for a file at the specified @path in the resource and
 * if found returns information about it.
 *
 * @lookup_flags controls the behaviour of the lookup.
 *
 * Returns: %TRUE if the file was found. %FALSE if there were errors
 *
 * Since: 2.32
 **/
gboolean
g_resource_get_info (GResource             *resource,
                     const gchar           *path,
                     GResourceLookupFlags   lookup_flags,
                     gsize                 *size,
                     guint32               *flags,
                     GError               **error)
{
  return do_lookup (resource, path, lookup_flags, size, flags, NULL, NULL, error);
}
Пример #17
0
int
deposit_command(char * args)
{
  size_t len, i;
  char * username;
  const char * residue;
  long int amount, balance;

  /* Advance args to the first token, this is the username */
  len = strnlen(args, MAX_COMMAND_LENGTH);
  for (i = 0; *args == ' ' && i < len; ++i, ++args);
  for (username = args; *args != '\0' && i < len; ++i, ++args) {
    if (*args == ' ') { *args = '\0'; i = len; }
  }
  len = strnlen(username, (size_t)(args - username));

  /* We should now be at the addition amount */
  amount = strtol(args, (char **)(&residue), 10);
  #ifndef NDEBUG
  if (*residue != '\0') {
    fprintf(stderr,
            "WARNING: ignoring '%s' (argument residue)\n",
            residue);
  }
  #endif

  /* Ensure the transaction amount is sane, TODO better solution? */
  if (amount < -MAX_TRANSACTION || amount > MAX_TRANSACTION) {
    fprintf(stderr,
            "ERROR: amount (%li) exceeds maximum transaction (%i)\n",
            amount, MAX_TRANSACTION);
    return BANKING_SUCCESS;
  }

  /* Prepare and run actual queries */
  if (do_lookup(session_data.db_conn, &residue,
                username, len, &balance)) {
    fprintf(stderr, "ERROR: no account found for '%s'\n", username);
  } else if (do_update(session_data.db_conn, &residue,
                       username, len, balance + amount)) {
    fprintf(stderr,
            "ERROR: unable to complete request on ('%s', %li)\n",
            username, balance);
  } else {
    printf("A transaction of $%li brings %s's balance from $%li to $%li\n",
           amount, username, balance, balance + amount);
  }
  #ifndef NDEBUG
  if (*residue != '\0') {
    fprintf(stderr, "WARNING: ignoring '%s' (query residue)\n", residue);
  }
  #endif

  return BANKING_SUCCESS;
}
Пример #18
0
/**
 *  Traverse the Huffman tree searching for the node corresponding to
 *  the given 8 bit value.
 *
 *  Return value is 1 if ch was found, 0 if not found.
 */
    PRIVATE int
do_lookup (const node_t *tree, int ch, char *buffer, int length)
{
    assert (length > 0);

    // have we reached a leaf node? If so, check if it is the
    // one we are looking for.
    if (tree->left == NULL && tree->right == NULL)
    {
        *buffer = '\0';

        if (tree->ch == ch)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }

    // not a leaf node. Continue to search any child of the current node.
    if (tree->left != NULL)
    {
        *buffer = '0';

        if (do_lookup (tree->left, ch, buffer + 1, length - 1) == 1)
            return 1;
    }

    if (tree->right != NULL)
    {
        *buffer = '1';

        if (do_lookup (tree->right, ch, buffer + 1, length - 1) == 1)
            return 1;
    }

    return 0;
}
Пример #19
0
/* 搜索key,从val中返回结果 */
int h_rbtree_search(const h_rbtree_st *tree, const void *key,
        uint32_t ksize, void **val)
{
    rbtree_node_st *parent;
    int is_left;
    rbtree_node_st *nd = do_lookup(tree, key, ksize, &parent, &is_left);

    if (!nd)
        return -1;
    if (val)
        *val = nd->cs.data;
    return 0;
}
Пример #20
0
/**
 * Look up key in the tree, returning the associated node pointer.
 *
 * This interface returns a node and not a key pointer to allow for direct
 * traversal or manipulation of the node (removal from tree for instance).
 * To simply get the key structure, use erbtree_lookup().
 *
 * To get back at the key from the returned node pointer, and assuming items
 * in the tree are defined as:
 *
 *     struct item {
 *         int key;
 *         <other fields>
 *         rbnode_t node;
 *     };
 *
 * use the following method:
 *
 *     struct item *item;
 *     rbnode_t *rn;
 *     struct item key;
 *
 *     key.key = <some value>;
 *     rn = erbtreee_getnode(tree, &key);
 *     item = NULL == rn ? NULL : erbtree_key(rn, struct item, node);
 *
 * Usage of erbtree_key() should be avoided whenever possible by using
 * erbtree_lookup(), and high-level iterators that handle keys directly.
 *
 * @param tree		the red-black tree
 * @param key		pointer to the key structure (NOT a node)
 *
 * @return node associated with key, NULL if not found.
 */
rbnode_t *
erbtree_getnode(const erbtree_t *tree, const void *key)
{
	rbnode_t *parent;
	bool is_left;

	erbtree_check(tree);
	g_assert(key != NULL);

	if (erbtree_is_extended(tree)) {
		return do_lookup_ext(ERBTREE_E(tree), key, &parent, &is_left);
	} else {
		return do_lookup(tree, key, &parent, &is_left);
	}
}
Пример #21
0
duk_hstring *duk_heap_string_intern(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen) {
	duk_hstring *res;
	duk_uint32_t strhash;

	/* caller is responsible for ensuring this */
	DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN);

	res = do_lookup(heap, str, blen, &strhash);
	if (res) {
		return res;
	}

	res = do_intern(heap, str, blen, strhash);
	return res;  /* may be NULL */
}
Пример #22
0
/* 取得<=key的元素 */
const h_rb_cursor_st *h_rbtree_upper_bound(const h_rbtree_st *tree,
        const void *key, uint32_t ksize)
{
    rbtree_node_st *parent;
    int is_left;
    rbtree_node_st *ret = do_lookup(tree, key, ksize, &parent, &is_left);
    if (ret)
        return &(ret->cs);

    while (parent
            && tree->cmp_fn(parent->cs.key, parent->cs.ksize, key, ksize) > 0) {
        parent = rb_prev(parent);
    }

    return parent == NULL ? NULL : &(parent->cs);
}
Пример #23
0
int
handle_withdraw_command(struct thread_data_t * datum, char * args)
{
  long balance, amount;
  char buffer[MAX_COMMAND_LENGTH];

  #ifndef NDEBUG
  if (*args == '\0') {
    fprintf(stderr,
            "[thread %lu] WARNING: [%s] arguments empty\n",
            datum->id, "withdraw");
  } else {
    fprintf(stderr,
            "[thread %lu] INFO: [%s] '%s' (arguments)\n",
            datum->id, "withdraw", args);
  }
  #endif
  amount = strtol(args, &args, 10);

  if (amount <= 0 || amount > MAX_TRANSACTION) {
    snprintf(buffer, MAX_COMMAND_LENGTH, "Invalid withdrawal amount.");
  } else if (datum->credentials.userlength
   && do_lookup(session_data.db_conn, NULL,
                datum->credentials.username,
                datum->credentials.userlength,
                &balance) == BANKING_SUCCESS) {
    if (balance < amount) {
      snprintf(buffer, MAX_COMMAND_LENGTH, "Insufficient funds.");
    } else if (do_update(session_data.db_conn, NULL,
               datum->credentials.username,
               datum->credentials.userlength,
               balance - amount)) {
      snprintf(buffer, MAX_COMMAND_LENGTH, "Cannot complete withdrawal.");
    } else {
      snprintf(buffer, MAX_COMMAND_LENGTH, "Withdrew $%li", amount);
    }
  } else {
    snprintf(buffer, MAX_COMMAND_LENGTH, "WITHDRAW ERROR");
  }
  salt_and_pepper(buffer, NULL, &datum->buffet);
  encrypt_message(&datum->buffet, datum->credentials.key);
  send_message(&datum->buffet, datum->sock);

  return BANKING_SUCCESS;
}
Пример #24
0
int kernel(void)
{
  /* Vacuous terminate */;
  if (_state_1) {
    _s.fun = 0, strcpy(fun_v, "None");;;
    _state_1 = 0;
  } else {
    _state_1 = 0;
    if (_s.ev) {
      _Event(&X, ev_v);
      strcpy(f, do_lookup(X));
      (strcpy(fun_v, f)), (_s.fun = 1);
    }
  }
  if (_s.fun) { kernel_O_fun(fun_v); _s.fun = 0; }
  _s.ev = 0;
  return 1;
}
Пример #25
0
/**
 * Look up key in the tree, returning the associated key item if found.
 *
 * @param tree		the red-black tree
 * @param key		pointer to the key structure (NOT a node)
 *
 * @return found item associated with key, NULL if not found.
 */
void *
erbtree_lookup(const erbtree_t *tree, const void *key)
{
	rbnode_t *parent;
	bool is_left;
	rbnode_t *rn;

	erbtree_check(tree);
	g_assert(key != NULL);

	if (erbtree_is_extended(tree)) {
		rn = do_lookup_ext(ERBTREE_E(tree), key, &parent, &is_left);
	} else {
		rn = do_lookup(tree, key, &parent, &is_left);
	}

	return NULL == rn ? NULL : ptr_add_offset(rn, -tree->offset);
}
Пример #26
0
int main(int argc, char* argv[]) {
    const char* input_cfgdir = NULL;
    const char* map_name = NULL;
    const char* ip_arg = NULL;

    switch(argc) {
        // gdnsd_geoip_test -c x map_name ip
        case 5:
            if(strcmp(argv[1], "-c")) usage(argv[0]);
            input_cfgdir = argv[2];
            map_name = argv[3];
            ip_arg = argv[4];
            break;
        // gdnsd_geoip_test map_name ip
        //   -or-
        // gdnsd_geoip_test -c x
        case 3:
            if(!strcmp(argv[1], "-c")) {
                input_cfgdir = argv[2];
            }
            else {
                map_name = argv[1];
                ip_arg = argv[2];
            }
            break;
        // no args at all
        case 1:
            break;
        default:
            usage(argv[0]);
    }

    gdmaps_t* gdmaps = gdmaps_test_init(input_cfgdir);

    if(map_name) {
        dmn_assert(ip_arg);
        do_lookup(gdmaps, map_name, ip_arg);
    }
    else {
        do_repl(gdmaps);
    }

    return 0;
}
Пример #27
0
static int do_queued_lookup(struct dnsquery *q)
{
#ifndef THREAD_SAFE_LOOKUP
	q->next_in_queue = NULL;
	if (!dns_queue) {
		dns_queue = q;
		/*debug("direct lookup");*/
#endif
		return do_lookup(q, 0);
#ifndef THREAD_SAFE_LOOKUP
	} else {
		/*debug("queuing lookup for %s", q->name);*/
		if (dns_queue->next_in_queue) internal("DNS queue corrupted");
		dns_queue->next_in_queue = q;
		dns_queue = q;
		return 1;
	}
#endif
}
Пример #28
0
const char *
lookup_kernel_symbol (gulong address)
{
    kernel_symbol_t *result;
    GArray *ksyms = get_kernel_symbols ();
    const char *sym;
    int i;

    if (ksyms->len == 0)
	return NULL;

    result = do_lookup ((kernel_symbol_t *)ksyms->data,
			address, 0, ksyms->len - 1);

    sym = result? result->name : NULL;


    /* This is a workaround for a kernel bug, where it reports not
     * only the kernel stack, but also the IRQ stack for the
     * timer interrupt that generated the stack.
     *
     * The stack as reported by the kernel looks like this:
     *
     * [ip] [irq stack] [real kernel stack]
     *
     * Below we filter out the [irq stack]
     */
    i = 0;
    while (sym && skip_kernel_symbols[i][0] != '\0')
    {
	if (strcmp (sym, skip_kernel_symbols[i]) == 0)
	{
	    sym = NULL;
	    break;
	}
	i++;
    }

    return sym;
}
Пример #29
0
int
balance_command(char * args)
{
  size_t len, i;
  char * username;
  long int balance;
  const char * residue;

  /* Advance to the first token, this is the username */
  len = strnlen(args, MAX_COMMAND_LENGTH);
  for (i = 0; *args == ' ' && i < len; ++i, ++args);
  for (username = args; *args != '\0' && i < len; ++i, ++args) {
    if (*args == ' ') { *args = '\0'; i = len; }
  }
  len = strnlen(username, (size_t)(args - username));

  /* The remainder is residue */
  residue = (const char *)(args);
  #ifndef NDEBUG
  if (*residue != '\0') {
    fprintf(stderr,
            "WARNING: ignoring '%s' (argument residue)\n",
            residue);
  }
  #endif

  /* Prepare the statement and run the query */
  if (do_lookup(session_data.db_conn, &residue, username, len, &balance)) {
    fprintf(stderr, "ERROR: no account found for '%s'\n", username);
  } else {
    printf("%s's balance is $%li\n", username, balance);
  }
  #ifndef NDEBUG
  if (*residue != '\0') {
    fprintf(stderr, "WARNING: ignoring '%s' (query residue)\n", residue);
  }
  #endif

  return BANKING_SUCCESS;
}
Пример #30
0
static void end_dns_lookup(struct dnsquery *q, int a)
{
	struct dnsentry *dnsentry;
	void (*fn)(void *, int);
	void *data;
	/*debug("end lookup %s", q->name);*/
#ifndef THREAD_SAFE_LOOKUP
	if (q->next_in_queue) {
		/*debug("processing next in queue: %s", q->next_in_queue->name);*/
		do_lookup(q->next_in_queue, 1);
	} else dns_queue = NULL;
#endif
	if (!q->fn || !q->addr) {
		free(q);
		return;
	}
	if (!find_in_dns_cache(q->name, &dnsentry)) {
		if (a) {
			memcpy(q->addr, &dnsentry->addr, sizeof(ip__address));
			a = 0;
			goto e;
		}
		del_from_list(dnsentry);
		mem_free(dnsentry);
	}
	if (a) goto e;
	dnsentry = mem_alloc(sizeof(struct dnsentry) + strlen(q->name) + 1);
	strcpy(dnsentry->name, q->name);
	memcpy(&dnsentry->addr, q->addr, sizeof(ip__address));
	dnsentry->get_time = get_time();
	add_to_list(dns_cache, dnsentry);
	e:
	if (q->s) *q->s = NULL;
	fn = q->fn;
	data = q->data;
	free(q);
	fn(data, a);
}