static int doit(char *q,char qtype[2],char ip[4]) { int r; uint32 dlen; unsigned int qlen; qlen = dns_domain_length(q); if (qlen > 255) return 0; /* impossible */ if (byte_diff(qtype,2,DNS_T_A) && byte_diff(qtype,2,DNS_T_ANY)) goto REFUSE; key[0] = '%'; byte_copy(key + 1,4,ip); r = cdb_find(&c,key,5); if (!r) r = cdb_find(&c,key,4); if (!r) r = cdb_find(&c,key,3); if (!r) r = cdb_find(&c,key,2); if (r == -1) return 0; key[0] = '+'; byte_zero(key + 1,2); if (r && (cdb_datalen(&c) == 2)) if (cdb_read(&c,key + 1,2,cdb_datapos(&c)) == -1) return 0; byte_copy(key + 3,qlen,q); case_lowerb(key + 3,qlen + 3); r = cdb_find(&c,key,qlen + 3); if (!r) { byte_zero(key + 1,2); r = cdb_find(&c,key,qlen + 3); } if (!r) goto REFUSE; if (r == -1) return 0; dlen = cdb_datalen(&c); if (dlen > 512) dlen = 512; if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) return 0; dns_sortip(data,dlen); if (dlen > 12) dlen = 12; while (dlen >= 4) { dlen -= 4; if (!response_rstart(q,DNS_T_A,"\0\0\0\5")) return 0; if (!response_addbytes(data + dlen,4)) return 0; response_rfinish(RESPONSE_ANSWER); } return 1; REFUSE: response[2] &= ~4; response[3] &= ~15; response[3] |= 5; return 1; }
int respond(char *q,char qtype[2],char ip[4]) { int fd; int r; char key[6]; tai_now(&now); fd = open_read("data.cdb"); if (fd == -1) return 0; cdb_init(&c,fd); byte_zero(clientloc,2); key[0] = 0; key[1] = '%'; byte_copy(key + 2,4,ip); r = cdb_find(&c,key,6); if (!r) r = cdb_find(&c,key,5); if (!r) r = cdb_find(&c,key,4); if (!r) r = cdb_find(&c,key,3); if (!r) r = cdb_find(&c,key,2); if (r == -1) return 0; if (r && (cdb_datalen(&c) == 2)) if (cdb_read(&c,clientloc,2,cdb_datapos(&c)) == -1) return 0; r = doit(q,qtype); cdb_free(&c); close(fd); return r; }
// This is going to be slow since it is a search by value. I.e. it // walks through the entire CDB sequentially trying to map a value // back to its key. Therefore it should only be used in debug or // error scenarios. static CCS _shop_find_cmdline(shopping_state_s *ssp, CCS cmdix) { unsigned loc = 0; cdb_seqinit(&loc, ssp->cdbp); while (cdb_seqnext(&loc, ssp->cdbp) > 0) { unsigned len; CS cmdstate, ix; len = cdb_datalen(ssp->cdbp); cmdstate = (CS)alloca(len + 1); cdb_read(ssp->cdbp, cmdstate, len, cdb_datapos(ssp->cdbp)); cmdstate[len] = '\0'; if ((ix = util_strsep(&cmdstate, FS1)) && !strcmp(cmdix, ix)) { CS line; len = cdb_keylen(ssp->cdbp); line = (CS)putil_malloc(len + 1); cdb_read(ssp->cdbp, line, len, cdb_keypos(ssp->cdbp)); line[len] = '\0'; return line; } } return NULL; }
static int __cdbb_findnext(struct cdbb *a, const char *needle, struct nentry *n, int ignorecase) { uint32 kp, dp, ks, vs; unsigned char *k, *v; if (cdb_nextkey(a->r, &a->kfindpos) != 1) return -1; kp = cdb_keypos(a->r); ks = cdb_keylen(a->r); k = alloca(ks); cdb_read(a->r, k, ks, kp); dp = cdb_datapos(a->r); vs = cdb_datalen(a->r); /* in some cases we do not need to read e.g. when deleting * or filtering but for simplicity we just do it anyways */ v = alloca(vs); cdb_read(a->r, v, vs, dp); /* search value */ if (ignorecase) { if (strcasestr((char *)v, needle) == NULL) return 0; } else { if (strstr((char *)v, needle) == NULL) return 0; } array_catb(&n->k, (char *)k, ks); array_catb(&n->e, (char *)v, vs); return 1; }
static int __cdbb_copy(struct cdbb *a, size_t ks, size_t vs) { unsigned char k[ks]; unsigned char v[vs]; uint32 kp, dp; int found, filter; found = 0; kp = cdb_keypos(a->r); cdb_read(a->r, k, ks, kp); dp = cdb_datapos(a->r); /* in some cases we do not need to read e.g. when deleting * or filtering but for simplicity we just do it anyways */ cdb_read(a->r, v, vs, dp); found = cdbb_check_ops(a, k, ks, v, vs); filter = cdbb_check_filter(a, k, ks, v, vs); /* if an operation applied or a filter, don't copy */ if (!found && !filter && kp) { cdb_make_add(a->w, k, ks, v, vs); return 1; } return 0; }
int main(int argc, char* argv[]) { int fd; static struct cdb c; errmsg_iam("cdbget"); if(argc < 3) die(1, "usage: cdbget data.cdb key"); fd = open(argv[1], O_RDONLY | O_BINARY); if(fd == -1) diesys(1, "open"); cdb_init(&c, fd); if(cdb_find(&c, argv[2], str_len(argv[2])) > 0) { do { char* x = malloc(cdb_datalen(&c)); if(!x) die(1, "out of memory"); if(cdb_read(&c, x, cdb_datalen(&c), cdb_datapos(&c)) == -1) diesys(1, "cdb_read"); buffer_put(buffer_1, x, cdb_datalen(&c)); buffer_put(buffer_1, "\n", 1); free(x); } while(cdb_findnext(&c, argv[2], str_len(argv[2])) > 0); } buffer_flush(buffer_1); }
static int do_regex_checks(struct _info *info, char *rr_type, char *key, char *rr_rdata) { char *pattern; unsigned keylen = strlen(key), patlen, vpos; int nchecks = 0; if (cdb_findinit(&info->cdbf, &info->cdb, key, keylen) <= 0) { return (-1); } while (cdb_findnext(&info->cdbf) > 0) { int m; vpos = cdb_datapos(&info->cdb); patlen = cdb_datalen(&info->cdb); pattern = malloc(patlen + 1); cdb_read(&info->cdb, pattern, patlen, vpos); pattern[patlen] = '\0'; if (*pattern == '@') { /* * Handle special function for data check */ if (!strcmp(pattern, "@IP")) { m = func_ip(info, rr_type, rr_rdata); if (m) { ++nchecks; } else { return (0); } } else if (!strcmp(pattern, "@SOA")) { m = func_soa(info, rr_type, rr_rdata); if (m) { ++nchecks; } else { return (0); } } } else { m = match(pattern, rr_rdata); // fprintf(stderr, "*** match %s ", m ? "TRUE " : "false"); // fprintf(stderr, "%s\n", pattern); if (m) { ++nchecks; // FIXME: can return now } else { sprintf(info->reason, "%s [%s] fails regexp [%s]", rr_type, rr_rdata, pattern); } } free(pattern); } return (nchecks); }
int OS_DBSearchKeyAddressValue(ListRule *lrule, char *key) { int result=-1; char *val; unsigned vlen, vpos; if (lrule->db!= NULL) { if(_OS_CDBOpen(lrule->db) == -1) return 0; // First lookup for a single IP address if(cdb_find(&lrule->db->cdb, key, strlen(key)) > 0 ) { vpos = cdb_datapos(&lrule->db->cdb); vlen = cdb_datalen(&lrule->db->cdb); val = malloc(vlen); cdb_read(&lrule->db->cdb, val, vlen, vpos); result = OSMatch_Execute(val, vlen, lrule->matcher); free(val); return result; } else { // IP address not found, look for matching subnets char *tmpkey; os_strdup(key, tmpkey); while(strlen(tmpkey) > 0) { if(tmpkey[strlen(tmpkey) - 1] == '.') { if( cdb_find(&lrule->db->cdb, tmpkey, strlen(tmpkey)) > 0 ) { vpos = cdb_datapos(&lrule->db->cdb); vlen = cdb_datalen(&lrule->db->cdb); val = malloc(vlen); cdb_read(&lrule->db->cdb, val, vlen, vpos); result = OSMatch_Execute(val, vlen, lrule->matcher); free(val); free(tmpkey); return result; } } tmpkey[strlen(tmpkey) - 1] = '\0'; } free(tmpkey); return 0; } } return 0; }
int find_client_loc(char loc[2],const char ip[16]) { int r, fd; char key[32+3]; static struct cdb c; fd = open_read("data.cdb"); if (fd == -1) return 0; cdb_init(&c,fd); byte_zero(loc,2); key[0] = 0; key[1] = '%'; if (byte_equal(ip,12,V4mappedprefix)) { key[2] = 'f'; byte_copy(key + 3,4,ip+12); r = cdb_find(&c,key,7); if (!r) r = cdb_find(&c,key,6); if (!r) r = cdb_find(&c,key,5); if (!r) r = cdb_find(&c,key,4); if (!r) r = cdb_find(&c,key,3); if (r == -1) return 0; if (r && (cdb_datalen(&c) == 2)) if (cdb_read(&c,loc,2,cdb_datapos(&c)) == -1) return 0; } else { unsigned int n; key[2] = 's'; ip6_fmt_flat(key+3,ip); for (n=19; n>3; --n) { r = cdb_find(&c,key,n); if (r) break; } if (r == -1) return 0; if (r && (cdb_datalen(&c) == 2)) if (cdb_read(&c,loc,2,cdb_datapos(&c)) == -1) return 0; } cdb_free(&c); close(fd); return r; }
static PyObject * _cdbo_keyiter(CdbObject *self) { PyObject *key; char buf[8]; uint32 klen, dlen; if (! self->eod) _cdbo_init_eod(self); while (self->iter_pos < self->eod) { if (cdb_read(&self->c, buf, 8, self->iter_pos) == -1) return CDBerr; uint32_unpack(buf, &klen); uint32_unpack(buf+4, &dlen); key = cdb_pyread(self, klen, self->iter_pos + 8); if (key == NULL) return NULL; switch(cdb_find(&self->c,PyString_AsString(key),PyString_Size(key))) { case -1: Py_DECREF(key); key = NULL; return CDBerr; case 0: /* bizarre, impossible? PyExc_RuntimeError? */ PyErr_SetString(PyExc_KeyError, PyString_AS_STRING((PyStringObject *) key)); Py_DECREF(key); key = NULL; default: if (key == NULL) /* already raised error */ return NULL; if (cdb_datapos(&self->c) == self->iter_pos + klen + 8) { /** first occurrence of key in the cdb **/ self->iter_pos += 8 + klen + dlen; return key; } Py_DECREF(key); /* better luck next time around */ self->iter_pos += 8 + klen + dlen; } } return Py_BuildValue(""); /* iter_pos >= eod; we're done */ }
static enum nss_status __nss_cdb_dobyid(struct nss_cdb *dbp, unsigned long id, void *result, char *buf, size_t bufl, int *errnop) { int r; unsigned len; const char *data; if ((r = cdb_find(&dbp->cdb, buf, sprintf(buf, ":%lu", id))) < 0) return *errnop = errno, NSS_STATUS_UNAVAIL; len = cdb_datalen(&dbp->cdb); if (!r || len < 2) return *errnop = ENOENT, NSS_STATUS_NOTFOUND; if (!(data = (const char*)cdb_get(&dbp->cdb, len, cdb_datapos(&dbp->cdb)))) return *errnop = errno, NSS_STATUS_UNAVAIL; return __nss_cdb_dobyname(dbp, data, len, result, buf, bufl, errnop); }
VALUE mCDB_Reader_get(VALUE self, VALUE key) { struct cdb db; VALUE value; StringValue(key); int fd = open_cdb_fd(self); size_t vlen; cdb_init(&db,fd); if(cdb_find(&db,RSTRING_PTR(key),RSTRING_LEN(key)) > 0) { vlen = cdb_datalen(&db); value = rb_str_buf_new(vlen); cdb_read(&db,RSTRING_PTR(value),vlen,cdb_datapos(&db)); rb_str_set_len(value,vlen); return value; } close(fd); return Qnil; }
int cdbb_readn(struct cdbb *a, char *k, size_t ks, char *v, size_t n) { int dlen; if (cdb_find(a->r, (unsigned char *)k, ks) <= 0) return -1; dlen = cdb_datalen(a->r); if (dlen > n) return -2; if (cdb_read(a->r, (unsigned char *)v, dlen, cdb_datapos(a->r)) < 0) return -3; return 1; }
SDB_VISIBLE int sdb_exists (Sdb* s, const char *key) { char ch; SdbKv *kv; int klen = strlen (key); ut32 pos, hash = sdb_hash (key, klen); kv = (SdbKv*)ht_lookup (s->ht, hash); if (kv) return (*kv->value)? 1: 0; if (s->fd == -1) return 0; cdb_findstart (&s->db); if (cdb_findnext (&s->db, hash, key, klen)) { pos = cdb_datapos (&s->db); cdb_read (&s->db, &ch, 1, pos); return ch != 0; } return 0; }
SDB_VISIBLE char *sdb_get (Sdb* s, const char *key, ut32 *cas) { char *buf; ut32 hash, pos, len, keylen; SdbKv *kv; ut64 now = 0LL; if (cas) *cas = 0; if (!s || !key) return NULL; keylen = strlen (key)+1; hash = sdb_hash (key, keylen); /* search in memory */ kv = (SdbKv*)ht_lookup (s->ht, hash); if (kv) { if (*kv->value) { if (kv->expire) { if (!now) now = sdb_now (); if (now > kv->expire) { sdb_remove (s, key, 0); return NULL; } } if (cas) *cas = kv->cas; return strdup (kv->value); // XXX too many mallocs } return NULL; } /* search in disk */ if (s->fd == -1) return NULL; cdb_findstart (&s->db); if (!cdb_findnext (&s->db, hash, key, keylen)) return NULL; len = cdb_datalen (&s->db); if (len == 0) return NULL; pos = cdb_datapos (&s->db); if (!(buf = malloc (len+1))) // XXX too many mallocs return NULL; cdb_read (&s->db, buf, len, pos); buf[len] = 0; return buf; }
/* read data from a constant database file */ uint64_t readcontentsfromcdb (void *hint,bstring key,char *data,uint64_t dsize) { cdb_t *cdb = (cdb_t *)hint; uint32_t vlen = 0, vpos = 0; if (cdb_find(cdb,btocstr(key),blength(key)) > 0) { vpos = cdb_datapos(cdb); vlen = cdb_datalen(cdb); cdb_read (cdb,data,(vlen < dsize) ? vlen : dsize,vpos); uint64_t Kb = (vlen < 1024) ? vlen : vlen / 1024; return (vlen < dsize) ? vlen : dsize; } return 0; }
VALUE mCDB_Reader_each_for_key(VALUE self,VALUE key) { struct cdb db; VALUE value; struct cdb_find find; StringValue(key); int fd = open_cdb_fd(self); size_t vlen; cdb_init(&db,fd); cdb_findinit(&find,&db,RSTRING_PTR(key),RSTRING_LEN(key)); while(cdb_findnext(&find) > 0) { vlen = cdb_datalen(&db); value = rb_str_buf_new(vlen); cdb_read(&db,RSTRING_PTR(value),vlen,cdb_datapos(&db)); rb_str_set_len(value,vlen); rb_yield(value); } close(fd); return Qnil; }
static int find(char *d,int flagwild) { int r; char ch; struct tai cutoff; char ttd[8]; char ttlstr[4]; char recordloc[2]; double newttl; for (;;) { r = cdb_findnext(&c,d,dns_domain_length(d)); if (r <= 0) return r; dlen = cdb_datalen(&c); if (dlen > sizeof data) return -1; if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) return -1; dpos = dns_packet_copy(data,dlen,0,type,2); if (!dpos) return -1; dpos = dns_packet_copy(data,dlen,dpos,&ch,1); if (!dpos) return -1; if ((ch == '=' + 1) || (ch == '*' + 1)) { --ch; dpos = dns_packet_copy(data,dlen,dpos,recordloc,2); if (!dpos) return -1; if (byte_diff(recordloc,2,clientloc)) continue; } if (flagwild != (ch == '*')) continue; dpos = dns_packet_copy(data,dlen,dpos,ttlstr,4); if (!dpos) return -1; uint32_unpack_big(ttlstr,&ttl); dpos = dns_packet_copy(data,dlen,dpos,ttd,8); if (!dpos) return -1; if (byte_diff(ttd,8,"\0\0\0\0\0\0\0\0")) { tai_unpack(ttd,&cutoff); if (ttl == 0) { if (tai_less(&cutoff,&now)) continue; tai_sub(&cutoff,&cutoff,&now); newttl = tai_approx(&cutoff); if (newttl <= 2.0) newttl = 2.0; if (newttl >= 3600.0) newttl = 3600.0; ttl = newttl; } else if (!tai_less(&cutoff,&now)) continue; } return 1; } }
main(int argc,char **argv) { char *key; int r; uint32 pos; uint32 len; unsigned long u = 0; if (!*argv) die_usage(); if (!*++argv) die_usage(); key = *argv; if (*++argv) { scan_ulong(*argv,&u); } cdb_init(&c,0); cdb_findstart(&c); for (;;) { r = cdb_findnext(&c,key,str_len(key)); if (r == -1) die_read(); if (!r) _exit(100); if (!u) break; --u; } pos = cdb_datapos(&c); len = cdb_datalen(&c); while (len > 0) { r = sizeof buf; if (r > len) r = len; if (cdb_read(&c,buf,r,pos) == -1) die_read(); if (buffer_put(buffer_1small,buf,r) == -1) die_write(); pos += r; len -= r; } if (buffer_flush(buffer_1small) == -1) die_write(); _exit(0); }
int checks(char *key, char *buf) { struct cdb cdb; struct cdb_find cdbf; int fd; char *data; unsigned keylen = strlen(key), datalen, vpos; if (((fd = open(DB, O_RDONLY)) == -1) || (cdb_init(&cdb, fd) != 0)) { printf("Can't open database: %s\n", strerror(errno)); return (-1); } if (cdb_findinit(&cdbf, &cdb, key, keylen) <= 0) { return (-1); } while (cdb_findnext(&cdbf) > 0) { char *pattern, *subject; int m; vpos = cdb_datapos(&cdb); datalen = cdb_datalen(&cdb); data = malloc(datalen + 1); cdb_read(&cdb, data, datalen, vpos); data[datalen] = '\0'; pattern = data; subject = buf; m = match(pattern, subject); printf("*** match %s ", m ? "TRUE " : "false"); printf("%s\n", data); free(data); } cdb_free(&cdb); close(fd); return (0); }
static long cdb_getval(struct _info *info, char *keyname) { unsigned keylen = strlen(keyname), vlen, vpos; long nval; char *val; if (cdb_find(&info->cdb, keyname, keylen) > 0) { vpos = cdb_datapos(&info->cdb); vlen = cdb_datalen(&info->cdb); val = malloc(vlen); cdb_read(&info->cdb, val, vlen, vpos); nval = atol(val); free(val); return (nval); } return (-1L); }
SDB_VISIBLE const char *sdb_getc (Sdb* s, const char *key, ut32 *cas) { ut32 hash, pos, len, keylen; SdbKv *kv; ut64 now = 0LL; if (cas) *cas = 0; if (!s||!key) return NULL; keylen = strlen (key)+1; hash = sdb_hash (key, keylen); /* search in memory */ kv = (SdbKv*)ht_lookup (s->ht, hash); if (kv) { if (*kv->value) { if (kv->expire) { if (!now) now = sdb_now (); if (now > kv->expire) { sdb_remove (s, key, 0); return NULL; } } if (cas) *cas = kv->cas; return kv->value; } return NULL; } /* search in disk */ if (s->fd == -1) return NULL; cdb_findstart (&s->db); if (!cdb_findnext (&s->db, hash, key, keylen)) return NULL; len = cdb_datalen (&s->db); if (len == 0) return NULL; pos = cdb_datapos (&s->db); return s->db.map+pos; }
int OS_DBSearchKeyValue(ListRule *lrule, char *key) { int result=-1; char *val; unsigned vlen, vpos; if (lrule->db!= NULL) { if(_OS_CDBOpen(lrule->db) == -1) return 0; if(cdb_find(&lrule->db->cdb, key, strlen(key)) > 0 ) { vpos = cdb_datapos(&lrule->db->cdb); vlen = cdb_datalen(&lrule->db->cdb); val = malloc(vlen); cdb_read(&lrule->db->cdb, val, vlen, vpos); result = OSMatch_Execute(val, vlen, lrule->matcher); free(val); return result; } else { return 0; } } return 0; }
static enum nss_status __nss_cdb_dobyname(struct nss_cdb *dbp, const char *key, unsigned len, void *result, char *buf, size_t bufl, int *errnop) { int r; if ((r = cdb_find(&dbp->cdb, key, len)) < 0) return *errnop = errno, NSS_STATUS_UNAVAIL; len = cdb_datalen(&dbp->cdb); if (!r || len < 2) return *errnop = ENOENT, NSS_STATUS_NOTFOUND; if (len >= bufl) return *errnop = ERANGE, NSS_STATUS_TRYAGAIN; if (cdb_read(&dbp->cdb, buf, len, cdb_datapos(&dbp->cdb)) != 0) return *errnop = errno, NSS_STATUS_UNAVAIL; buf[len] = '\0'; if ((r = dbp->parsefn(result, buf, bufl)) < 0) return *errnop = ENOENT, NSS_STATUS_NOTFOUND; if (!r) return *errnop = ERANGE, NSS_STATUS_TRYAGAIN; return NSS_STATUS_SUCCESS; }
static int dorule(void (*callback)(char *,unsigned int)) { char *data; unsigned int datalen; switch(cdb_find(&c,rules_name.s,rules_name.len)) { case -1: return -1; case 0: return 0; } datalen = cdb_datalen(&c); data = alloc(datalen); if (!data) return -1; if (cdb_read(&c,data,datalen,cdb_datapos(&c)) == -1) { alloc_free(data); return -1; } callback(data,datalen); alloc_free(data); return 1; }
int respond(char *q,char qtype[2],char ip[4]) { static struct tai cdb_valid = { 0 }; static int fd = -1; struct tai one_second; int r; char key[6]; tai_now(&now); if (tai_less(&cdb_valid, &now)) { if (fd != -1) { cdb_free(&c); close(fd); } fd = open_read("data.cdb"); if (fd == -1) return 0; cdb_init(&c,fd); tai_uint(&one_second, 1); tai_add(&cdb_valid, &now, &one_second); } byte_zero(clientloc,2); key[0] = 0; key[1] = '%'; byte_copy(key + 2,4,ip); r = cdb_find(&c,key,6); if (!r) r = cdb_find(&c,key,5); if (!r) r = cdb_find(&c,key,4); if (!r) r = cdb_find(&c,key,3); if (!r) r = cdb_find(&c,key,2); if (r == -1) return 0; if (r && (cdb_datalen(&c) == 2)) if (cdb_read(&c,clientloc,2,cdb_datapos(&c)) == -1) return 0; r = doit(q,qtype); return r; }
int ipsvd_check_cdbentry(stralloc *d, stralloc *m, char *ip, int *rc) { switch(cdb_find(&c, m->s, m->len -1)) { case -1: return(-1); case 1: dlen =cdb_datalen(&c); if (! stralloc_ready(d, dlen)) return(-1); if (cdb_read(&c, d->s, dlen, cdb_datapos(&c)) == -1) return(-1); if (! dlen) return(-1); switch(d->s[dlen -1]) { case 'D': *rc =IPSVD_DENY; return(1); case 'X': d->s[dlen -1] =0; d->len =dlen; *rc =IPSVD_EXEC; return(1); case 'I': d->s[dlen -1] =0; d->len =dlen; if ((*rc =ipsvd_instruct(d, m, ip)) == -1) return(-1); return(1); } } return(0); }
int cdbb_read_nentry(struct cdbb *a, char *k, size_t ks, struct nentry *n) { int err, dlen; unsigned char *buf; array_catb(&n->k, k, ks); err = cdb_find(a->r, (unsigned char *)k, ks); if (err <= 0) return err; err = 0; /* num */ do { dlen = cdb_datalen(a->r); buf = alloca(dlen); if (cdb_read(a->r, buf, dlen, cdb_datapos(a->r)) < 0) return -2; array_catb(&n->e, (char *)buf, dlen); err++; } while (cdb_findnext(a->r, (unsigned char *)k, ks) > 0); return err; }
static void search_dictionaries(int out, Dlist *dic_list, char *rbuf) { Dlist_data *dd; Hash *word_hash; char word[SKKSERV_WORD_SIZE]; char result[SKKSERV_RESULT_SIZE]; char tmpresult[SKKSERV_RESULT_SIZE]; char *end; int i, p, r, len, rlen, ncandidates; if ((end = strchr(rbuf + 1, ' ')) == NULL) { rbuf[0] = SKKSERV_S_ERROR; write(out, rbuf, strlen(rbuf)); return; } len = end - (rbuf + 1); memcpy(word, rbuf + 1, len); word[len] = '\0'; word_hash = hash_create(HASH_SIZE); rlen = 1; ncandidates = 0; result[0] = SKKSERV_S_FOUND; dlist_iter(dic_list, dd) { Dictionary *dic = dlist_data(dd); pthread_mutex_lock(&dic->mutex); __cdb_findstart(dic); if ((r = __cdb_findnext(dic, word, len)) == -1) { err_message_fnc("cdb_findnext() failed.\n"); if (!ncandidates) { rbuf[0] = SKKSERV_S_ERROR; write(out, rbuf, strlen(rbuf)); } pthread_mutex_unlock(&dic->mutex); hash_destroy(word_hash); return; } debug_message_fnc("word %s, len %d, r = %d\n", word, len, r); if (r) { int dpos = cdb_datapos(&dic->cdb); int dlen = cdb_datalen(&dic->cdb); debug_message_fnc("%s found, r = %d, dpos = %d, dlen = %d.\n", word, r, dpos, dlen); if (rlen + dlen + 2 > SKKSERV_RESULT_SIZE) { err_message_fnc("Truncated: %s\n", word); r = SKKSERV_RESULT_SIZE - rlen - 2; } else { r = dlen; } debug_message_fnc("read %d bytes\n", r); if (cdb_read(&dic->cdb, tmpresult, r, dpos) == -1) { if (!ncandidates) { err_message_fnc("cdb_read() failed.\n"); rbuf[0] = SKKSERV_S_ERROR; write(out, rbuf, strlen(rbuf)); pthread_mutex_unlock(&dic->mutex); hash_destroy(word_hash); return; } else { result[rlen] = '\0'; continue; } } /* Merge */ p = 0; i = 1; while (i < r) { if (tmpresult[i] == '/') { if (i - p - 1 > 0 && hash_define_value(word_hash, tmpresult + p + 1, i - p - 1, (void *)1) == 1) { memcpy(result + rlen, tmpresult + p, i - p); rlen += i - p; ncandidates++; } p = i; } i++; } } pthread_mutex_unlock(&dic->mutex); }
/* main program */ int main(int argc, char *argv[]) { char combuf[BUFSIZE], data[DATASIZE]; char *pbuf, *key, *p; struct cdb diccdb; int dicfd, ex, length; unsigned int keylen, datalen; /* open dictionary cdb file */ if ((dicfd = open(JISYO_FILE, O_RDONLY, S_IRUSR)) < 0) { exit(EX_CONFIG); } /* init cdb */ cdb_init(&diccdb, dicfd); /* To exit, set ex to non-zero */ ex = 0; /* command loop */ while (!ex) { /* Read from stdin */ length = read(STDIN, &combuf[0], BUFSIZE - 1); if (length < 0) { exit(EX_NOINPUT); } else if (length == 0) { /* EOF detected */ /* exit from the while loop */ ex = 1; break; } /* parse request code */ switch (combuf[0]) { case CLIENT_END: /* End of conversion requested*/ /* exit from the while loop */ ex = 1; break; case CLIENT_VERSION: if (write(STDOUT, VERSION, sizeof(VERSION) - 1) < 0) { exit(EX_IOERR); } break; case CLIENT_HOST: if (write(STDOUT, DUMMYHOSTNAME, sizeof(DUMMYHOSTNAME) - 1) < 0) { exit(EX_IOERR); } break; case CLIENT_REQUEST: /* get size of key */ key = &combuf[1]; for (pbuf = &combuf[1]; *pbuf != ' ' && pbuf != &combuf[length - 1]; pbuf++) { } keylen = pbuf - &combuf[1]; if (keylen <= 0) { /* invalid keysize */ exit(EX_PROTOCOL); } /* lookup the cdb database */ switch (cdb_find(&diccdb, key, keylen)) { case -1: /* fatal error on cdb_find() */ exit(EX_SOFTWARE); break; case 1: /* found */ if ((datalen = cdb_datalen(&diccdb)) >= DATASIZE - 2) { exit(EX_PROTOCOL); } /* generate the answer string */ p = data; *p++ = SERVER_FOUND; if (cdb_read(&diccdb, p, datalen, cdb_datapos(&diccdb)) < 0) { exit(EX_SOFTWARE); } p += datalen; *p = '\n'; /* sending found code and the result data string with LF */ if (write(STDOUT, data, datalen + 2) < 0) { exit(EX_IOERR); } break; case 0: /* NOT found */ /* generate the answer string */ combuf[0] = SERVER_NOT_FOUND; *pbuf = '\n'; /* sending error code and the key string with LF */ /* this action is required by skkinput */ if (write(STDOUT, combuf, keylen + 2) < 0) { exit(EX_IOERR); } break; default: /* unknown cdb return value */ exit(EX_SOFTWARE); break; } break; /* end CLIENT_REQUEST switch clause */ /* unknown request code */ default: exit(EX_PROTOCOL); } /* end request code parsing */ } /* end while loop */ /* close dictionary db file */ cdb_free(&diccdb); if (close(dicfd) != 0) { exit(EX_IOERR); } /* normal exit, finally */ exit(EX_OK); }