dstr dstr_cat(dstr ds, const char *str) { size_t length = str ? strlen(str) : 0; return dstr_cat_len(ds, str, length); }
dstr *dstr_split_args(const char *line, int *argc) { const char *p = line; dstr current = NULL; dstr *argv = NULL; *argc = 0; for (;;) { while (*p && isspace(*p)) ++p; if (*p) { int inq = 0; /* 1 if in quotes */ int insq = 0; /* 1 if in single quotes */ int done = 0; if (current == NULL) current = dstr_new_len("", 0); while (!done) { /* FIXME */ if (inq) { if (*p == '\\' && *(p + 1) == 'x' && is_hex_digit(*(p + 2)) && is_hex_digit(*(p + 3))) { unsigned char byte = 16 * hex_digit_to_int(*(p + 2)) + hex_digit_to_int(*(p + 3)); p += 3; current = dstr_cat_len(current, (char *)&byte, 1); } else if (*p == '\\' && *(p + 1)) { char c; ++p; switch (*p) { case 'a': c = '\a'; break; case 'b': c = '\b'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; default: c = *p; break; } current = dstr_cat_len(current, &c, 1); } else if (*p == '"') { /* closing quote must be followed by a space or not at all */ if (*(p + 1) && !isspace(*(p + 1))) goto err; done = 1; /* unterminated quotes */ } else if (*p == '\0') goto err; else current = dstr_cat_len(current, p, 1); } else if (insq) { if (*p == '\\' && *(p + 1) == '\'') { ++p; current = dstr_cat_len(current, "'", 1); } else if (*p == '\'') { /* closing quote must be followed by a space or not at all */ if (*(p + 1) && !isspace(*(p + 1))) goto err; done = 1; /* unterminated quotes */ } else if (*p == '\0') goto err; else current = dstr_cat_len(current, p, 1); } else switch (*p) { case ' ': case '\0': case '\n': case '\r': case '\t': done = 1; break; case '"': inq = 1; break; case '\'': insq = 1; break; default: current = dstr_cat_len(current, p, 1); break; } if (*p) ++p; } if (RESIZE(argv, (*argc + 1) * sizeof (char *)) == NULL) goto err; argv[*argc] = current; ++*argc; current = NULL; } else return argv; } err: { int i; for (i = 0; i < *argc; ++i) dstr_free(argv[i]); FREE(argv); if (current) dstr_free(current); return NULL; } }
/* FIXME */ static void *q_thread(void *data) { struct crss *crss = (struct crss *)data; char buf[64]; dstr rid, res = NULL; db_iterator_t *it; const char *key, *value; size_t klen, vlen; snprintf(buf, sizeof buf, "%p,", crss->c); rid = dstr_new(buf); rid = dstr_cat(rid, crss->rid); it = db_iterator_create(db, db_ro); db_iterator_seek(it, crss->start, dstr_length(crss->start)); /* seek failed */ if (!db_iterator_valid(it)) { res = dstr_new(crss->rid); res = dstr_cat(res, ",1\r\n\r\n"); pthread_spin_lock(&crss->c->lock); if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", crss->c, strerror(errno)); pthread_spin_unlock(&crss->c->lock); goto end; } key = db_iterator_key(it, &klen); while (memcmp(key, crss->stop, dstr_length(crss->stop)) <= 0) { if (crss->cancel) break; if (!strcmp(crss->match, "") || strstr(key, crss->match)) { value = db_iterator_value(it, &vlen); res = dstr_new(crss->rid); res = dstr_cat(res, ",0,"); res = dstr_cat_len(res, key, klen); res = dstr_cat(res, ","); res = dstr_cat_len(res, value, vlen); res = dstr_cat(res, "\r\n"); pthread_spin_lock(&crss->c->lock); if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) { xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", crss->c, strerror(errno)); pthread_spin_unlock(&crss->c->lock); goto end; } pthread_spin_unlock(&crss->c->lock); dstr_free(res); } db_iterator_next(it); if (!db_iterator_valid(it) || crss->cancel) break; key = db_iterator_key(it, &klen); } res = dstr_new(crss->rid); res = dstr_cat(res, ",1\r\n\r\n"); pthread_spin_lock(&crss->c->lock); if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", crss->c, strerror(errno)); pthread_spin_unlock(&crss->c->lock); end: db_iterator_destroy(&it); dstr_free(res); table_lock(rids); table_remove(rids, rid); table_unlock(rids); dstr_free(rid); client_decr(crss->c); dstr_free(crss->rid); dstr_free(crss->match); dstr_free(crss->start); dstr_free(crss->stop); FREE(crss); return NULL; }