mirror of
https://github.com/NLnetLabs/unbound.git
synced 2024-09-21 06:37:08 +00:00
forwarder mode options for library.
git-svn-id: file:///svn/unbound/trunk@895 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
452b7cc069
commit
2e28288b1d
@ -5,6 +5,8 @@
|
||||
- make pipe nonblocking at start.
|
||||
- update plane for retry mode with caution to limit bandwidth.
|
||||
- fix Makefile for concurrent make of unbound-host.
|
||||
- renamed ub_val_ctx_wait/poll/process/fd to ub_val*.
|
||||
- new calls to set forwarding added to header and docs.
|
||||
|
||||
23 January 2008: Wouter
|
||||
- removed debug prints from if-auto, verb-algo enables some.
|
||||
|
@ -17,15 +17,17 @@
|
||||
.B ub_val_ctx_create,
|
||||
.B ub_val_ctx_delete,
|
||||
.B ub_val_ctx_config,
|
||||
.B ub_val_ctx_set_fwd,
|
||||
.B ub_val_ctx_resolvconf,
|
||||
.B ub_val_ctx_add_ta,
|
||||
.B ub_val_ctx_add_ta_file,
|
||||
.B ub_val_ctx_trustedkeys,
|
||||
.B ub_val_ctx_debuglevel,
|
||||
.B ub_val_ctx_async,
|
||||
.B ub_val_ctx_poll,
|
||||
.B ub_val_ctx_wait,
|
||||
.B ub_val_ctx_fd,
|
||||
.B ub_val_ctx_process,
|
||||
.B ub_val_poll,
|
||||
.B ub_val_wait,
|
||||
.B ub_val_fd,
|
||||
.B ub_val_process,
|
||||
.B ub_val_resolve,
|
||||
.B ub_val_resolve_async,
|
||||
.B ub_val_cancel,
|
||||
@ -46,6 +48,12 @@
|
||||
\fBub_val_ctx_config\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_set_fwd\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR addr);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_resolvconf\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_add_ta\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR ta);
|
||||
.LP
|
||||
\fIint\fR
|
||||
@ -65,16 +73,16 @@
|
||||
\fBub_val_ctx_async\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR dothread);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_poll\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
\fBub_val_poll\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_wait\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
\fBub_val_wait\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_fd\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
\fBub_val_fd\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_process\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
\fBub_val_process\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_resolve\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR name,
|
||||
@ -138,6 +146,25 @@ A power\-user interface that lets you specify an unbound config file, see
|
||||
relevant. For some specific options, such as adding trust anchors, special
|
||||
routines exist.
|
||||
.TP
|
||||
.B ub_val_ctx_set_fwd
|
||||
Set machine to forward DNS queries to, the caching resolver to use.
|
||||
IP4 or IP6 address. Forwards all DNS requests to that machine, which
|
||||
is expected to run a recursive resolver. If the proxy is not
|
||||
DNSSEC capable, validation may fail. Can be called several times, in
|
||||
that case the addresses are used as backup servers.
|
||||
At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
.B ub_val_ctx_resolvconf
|
||||
Read list of nameservers to use from the filename given.
|
||||
Usually "/etc/resolv.conf". Uses those nameservers as caching proxies.
|
||||
If they do not support DNSSEC, validation may fail.
|
||||
Only nameservers are picked up, the searchdomain, ndots and other
|
||||
settings from \fIresolv.conf\fR(5) are ignored.
|
||||
If fname NULL is passed, "/etc/resolv.conf" is used.
|
||||
At this time it is only possible to set configuration before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
.B
|
||||
ub_val_ctx_add_ta
|
||||
Add a trust anchor to the given context.
|
||||
@ -173,27 +200,27 @@ Changes to this setting after
|
||||
calls have been made have no effect (delete and re\-create the context
|
||||
to change).
|
||||
.TP
|
||||
.B ub_val_ctx_poll
|
||||
.B ub_val_poll
|
||||
Poll a context to see if it has any new results.
|
||||
Do not poll in a loop, instead extract the fd below to poll for readiness,
|
||||
and then check, or wait using the wait routine.
|
||||
Returns 0 if nothing to read, or nonzero if a result is available.
|
||||
If nonzero, call
|
||||
.B ub_val_ctx_process
|
||||
.B ub_val_process
|
||||
to do callbacks.
|
||||
.TP
|
||||
.B ub_val_ctx_wait
|
||||
.B ub_val_wait
|
||||
Wait for a context to finish with results. Calls
|
||||
.B ub_val_ctx_process
|
||||
.B ub_val_process
|
||||
after the wait for you. After the wait, there are no more outstanding
|
||||
asynchronous queries.
|
||||
.TP
|
||||
.B ub_val_ctx_fd
|
||||
.B ub_val_fd
|
||||
Get file descriptor. Wait for it to become readable, at this point
|
||||
answers are returned from the asynchronous validating resolver.
|
||||
Then call the \fBub_val_ctx_process\fR to continue processing.
|
||||
Then call the \fBub_val_process\fR to continue processing.
|
||||
.TP
|
||||
.B ub_val_ctx_process
|
||||
.B ub_val_process
|
||||
Call this routine to continue processing results from the validating
|
||||
resolver (when the fd becomes readable).
|
||||
Will perform necessary callbacks.
|
||||
@ -264,9 +291,9 @@ to obtain a readable error string.
|
||||
returns a zero terminated string.
|
||||
.B ub_val_ctx_create
|
||||
returns NULL on an error (a malloc failure).
|
||||
.B ub_val_ctx_poll
|
||||
.B ub_val_poll
|
||||
returns true if some information may be available, false otherwise.
|
||||
.B ub_val_ctx_fd
|
||||
.B ub_val_fd
|
||||
returns a file descriptor or -1 on error.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
|
@ -175,7 +175,9 @@ enum ub_ctx_err {
|
||||
/** initialization failed (bad settings) */
|
||||
UB_INITFAIL = -7,
|
||||
/** error in pipe communication with async bg worker */
|
||||
UB_PIPE = -8
|
||||
UB_PIPE = -8,
|
||||
/** error reading from file (resolv.conf) */
|
||||
UB_READFILE = -9
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,15 +1,17 @@
|
||||
ub_val_ctx_create
|
||||
ub_val_ctx_delete
|
||||
ub_val_ctx_config
|
||||
ub_val_ctx_set_fwd
|
||||
ub_val_ctx_resolvconf
|
||||
ub_val_ctx_add_ta
|
||||
ub_val_ctx_add_ta_file
|
||||
ub_val_ctx_trustedkeys
|
||||
ub_val_ctx_debuglevel
|
||||
ub_val_ctx_async
|
||||
ub_val_ctx_poll
|
||||
ub_val_ctx_wait
|
||||
ub_val_ctx_fd
|
||||
ub_val_ctx_process
|
||||
ub_val_poll
|
||||
ub_val_wait
|
||||
ub_val_fd
|
||||
ub_val_process
|
||||
ub_val_resolve
|
||||
ub_val_resolve_async
|
||||
ub_val_cancel
|
||||
|
@ -319,7 +319,7 @@ pollit(struct ub_val_ctx* ctx, struct timeval* t)
|
||||
}
|
||||
|
||||
int
|
||||
ub_val_ctx_poll(struct ub_val_ctx* ctx)
|
||||
ub_val_poll(struct ub_val_ctx* ctx)
|
||||
{
|
||||
struct timeval t;
|
||||
int r;
|
||||
@ -331,7 +331,7 @@ ub_val_ctx_poll(struct ub_val_ctx* ctx)
|
||||
}
|
||||
|
||||
int
|
||||
ub_val_ctx_wait(struct ub_val_ctx* ctx)
|
||||
ub_val_wait(struct ub_val_ctx* ctx)
|
||||
{
|
||||
int r;
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
@ -341,7 +341,7 @@ ub_val_ctx_wait(struct ub_val_ctx* ctx)
|
||||
r = pollit(ctx, NULL);
|
||||
lock_basic_unlock(&ctx->rrpipe_lock);
|
||||
if(r)
|
||||
ub_val_ctx_process(ctx);
|
||||
ub_val_process(ctx);
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
@ -349,7 +349,7 @@ ub_val_ctx_wait(struct ub_val_ctx* ctx)
|
||||
}
|
||||
|
||||
int
|
||||
ub_val_ctx_fd(struct ub_val_ctx* ctx)
|
||||
ub_val_fd(struct ub_val_ctx* ctx)
|
||||
{
|
||||
int fd;
|
||||
lock_basic_lock(&ctx->rrpipe_lock);
|
||||
@ -418,7 +418,7 @@ process_answer(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len)
|
||||
}
|
||||
|
||||
int
|
||||
ub_val_ctx_process(struct ub_val_ctx* ctx)
|
||||
ub_val_process(struct ub_val_ctx* ctx)
|
||||
{
|
||||
int r;
|
||||
uint8_t* msg = NULL;
|
||||
@ -601,6 +601,127 @@ ub_val_strerror(int err)
|
||||
case UB_INITFAIL: return "initialization failure";
|
||||
case UB_AFTERFINAL: return "setting change after finalize";
|
||||
case UB_PIPE: return "error in pipe communication with async";
|
||||
case UB_READFILE: return "error reading file";
|
||||
default: return "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ub_val_ctx_set_fwd(struct ub_val_ctx* ctx, char* addr)
|
||||
{
|
||||
struct sockaddr_storage storage;
|
||||
socklen_t stlen;
|
||||
struct config_stub* s;
|
||||
char* dupl;
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(ctx->finalized) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
errno=EINVAL;
|
||||
return UB_AFTERFINAL;
|
||||
}
|
||||
if(!addr) {
|
||||
/* disable fwd mode - the root stub should be first. */
|
||||
if(ctx->env->cfg->forwards &&
|
||||
strcmp(ctx->env->cfg->forwards->name, ".") == 0) {
|
||||
s = ctx->env->cfg->forwards;
|
||||
ctx->env->cfg->forwards = s->next;
|
||||
s->next = NULL;
|
||||
config_delstubs(s);
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
|
||||
/* check syntax for addr */
|
||||
if(!extstrtoaddr(addr, &storage, &stlen)) {
|
||||
errno=EINVAL;
|
||||
return UB_SYNTAX;
|
||||
}
|
||||
|
||||
/* it parses, add root stub in front of list */
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(!ctx->env->cfg->forwards ||
|
||||
strcmp(ctx->env->cfg->forwards->name, ".") != 0) {
|
||||
s = calloc(1, sizeof(*s));
|
||||
if(!s) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
errno=ENOMEM;
|
||||
return UB_NOMEM;
|
||||
}
|
||||
s->name = strdup(".");
|
||||
if(!s->name) {
|
||||
free(s);
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
errno=ENOMEM;
|
||||
return UB_NOMEM;
|
||||
}
|
||||
s->next = ctx->env->cfg->forwards;
|
||||
ctx->env->cfg->forwards = s;
|
||||
} else {
|
||||
log_assert(ctx->env->cfg->forwards);
|
||||
s = ctx->env->cfg->forwards;
|
||||
}
|
||||
dupl = strdup(addr);
|
||||
if(!dupl) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
errno=ENOMEM;
|
||||
return UB_NOMEM;
|
||||
}
|
||||
if(!cfg_strlist_insert(&s->addrs, dupl)) {
|
||||
free(dupl);
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
errno=ENOMEM;
|
||||
return UB_NOMEM;
|
||||
}
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
int
|
||||
ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname)
|
||||
{
|
||||
FILE* in;
|
||||
int numserv = 0;
|
||||
char buf[1024];
|
||||
char* parse, *addr;
|
||||
int r;
|
||||
if(fname == NULL)
|
||||
fname = "/etc/resolv.conf";
|
||||
in = fopen(fname, "r");
|
||||
if(!in) {
|
||||
/* error in errno! perror(fname) */
|
||||
return UB_READFILE;
|
||||
}
|
||||
while(fgets(buf, (int)sizeof(buf), in)) {
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
parse=buf;
|
||||
while(*parse == ' ' || *parse == '\t')
|
||||
parse++;
|
||||
if(strncmp(parse, "nameserver", 10) == 0) {
|
||||
numserv++;
|
||||
parse += 10; /* skip 'nameserver' */
|
||||
/* skip whitespace */
|
||||
while(*parse == ' ' || *parse == '\t')
|
||||
parse++;
|
||||
addr = parse;
|
||||
/* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */
|
||||
while(isxdigit(*parse) || *parse=='.' || *parse==':')
|
||||
parse++;
|
||||
/* terminate after the address, remove newline */
|
||||
*parse = 0;
|
||||
|
||||
if((r = ub_val_ctx_set_fwd(ctx, addr)) != UB_NOERROR) {
|
||||
fclose(in);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(in);
|
||||
if(numserv == 0) {
|
||||
/* from resolv.conf(5) if none given, use localhost */
|
||||
log_info("resconf: no nameservers, using localhost");
|
||||
return ub_val_ctx_set_fwd(ctx, "127.0.0.1");
|
||||
}
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
@ -57,15 +57,15 @@
|
||||
* Application not threaded. Non-blocking ('asynchronous').
|
||||
* err = ub_val_resolve_async(ctx, "www.example.com", ... my_callback);
|
||||
* ... application resumes processing ...
|
||||
* ... and when either ub_val_ctx_poll(ctx) is true
|
||||
* ... or when the file descriptor ub_val_ctx_fd(ctx) is readable,
|
||||
* ... and when either ub_val_poll(ctx) is true
|
||||
* ... or when the file descriptor ub_val_fd(ctx) is readable,
|
||||
* ... or whenever, the app calls ...
|
||||
* ub_val_ctx_process(ctx);
|
||||
* ub_val_process(ctx);
|
||||
* ... if no result is ready, the app resumes processing above,
|
||||
* ... or process() calls my_callback() with results.
|
||||
*
|
||||
* ... if the application has nothing more to do, wait for answer
|
||||
* ub_val_ctx_wait(ctx);
|
||||
* ub_val_wait(ctx);
|
||||
*
|
||||
* Application threaded. Blocking.
|
||||
* Blocking, same as above. The current thread does the work.
|
||||
@ -84,7 +84,7 @@
|
||||
* Otherwise, for asynchronous with threading, a worker thread is created.
|
||||
*
|
||||
* The blocking calls use shared ctx-cache when threaded. Thus
|
||||
* ub_val_resolve() and ub_val_resolve_async() && ub_val_ctx_wait() are
|
||||
* ub_val_resolve() and ub_val_resolve_async() && ub_val_wait() are
|
||||
* not the same. The first makes the current thread do the work, setting
|
||||
* up buffers, etc, to perform the work (but using shared cache data).
|
||||
* The second calls another worker thread (or process) to perform the work.
|
||||
@ -217,6 +217,41 @@ void ub_val_ctx_delete(struct ub_val_ctx* ctx);
|
||||
*/
|
||||
int ub_val_ctx_config(struct ub_val_ctx* ctx, char* fname);
|
||||
|
||||
/**
|
||||
* Set machine to forward DNS queries to, the caching resolver to use.
|
||||
* IP4 or IP6 address. Forwards all DNS requests to that machine, which
|
||||
* is expected to run a recursive resolver. If the proxy is not
|
||||
* DNSSEC-capable, validation may fail. Can be called several times, in
|
||||
* that case the addresses are used as backup servers.
|
||||
*
|
||||
* To read the list of nameservers from /etc/resolv.conf (from DHCP or so),
|
||||
* use the call ub_val_ctx_resolvconf.
|
||||
*
|
||||
* @param ctx: context.
|
||||
* At this time it is only possible to set configuration before the
|
||||
* first resolve is done.
|
||||
* @param addr: address, IP4 or IP6 in string format.
|
||||
* If the addr is NULL, forwarding is disabled.
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
int ub_val_ctx_set_fwd(struct ub_val_ctx* ctx, char* addr);
|
||||
|
||||
/**
|
||||
* Read list of nameservers to use from the filename given.
|
||||
* Usually "/etc/resolv.conf". Uses those nameservers as caching proxies.
|
||||
* If they do not support DNSSEC, validation may fail.
|
||||
*
|
||||
* Only nameservers are picked up, the searchdomain, ndots and other
|
||||
* settings from resolv.conf(5) are ignored.
|
||||
*
|
||||
* @param ctx: context.
|
||||
* At this time it is only possible to set configuration before the
|
||||
* first resolve is done.
|
||||
* @param fname: file name string. If NULL "/etc/resolv.conf" is used.
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
int ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname);
|
||||
|
||||
/**
|
||||
* Add a trust anchor to the given context.
|
||||
* The trust anchor is a string, on one line, that holds a valid DNSKEY or
|
||||
@ -283,27 +318,27 @@ int ub_val_ctx_async(struct ub_val_ctx* ctx, int dothread);
|
||||
* @return: 0 if nothing to read, or nonzero if a result is available.
|
||||
* If nonzero, call ctx_process() to do callbacks.
|
||||
*/
|
||||
int ub_val_ctx_poll(struct ub_val_ctx* ctx);
|
||||
int ub_val_poll(struct ub_val_ctx* ctx);
|
||||
|
||||
/**
|
||||
* Wait for a context to finish with results. Calls ctx_process() after
|
||||
* Wait for a context to finish with results. Calls ub_val_process() after
|
||||
* the wait for you. After the wait, there are no more outstanding
|
||||
* asynchronous queries.
|
||||
* @param ctx: context.
|
||||
* @return: 0 if OK, else error.
|
||||
*/
|
||||
int ub_val_ctx_wait(struct ub_val_ctx* ctx);
|
||||
int ub_val_wait(struct ub_val_ctx* ctx);
|
||||
|
||||
/**
|
||||
* Get file descriptor. Wait for it to become readable, at this point
|
||||
* answers are returned from the asynchronous validating resolver.
|
||||
* Then call the ub_val_ctx_process to continue processing.
|
||||
* Then call the ub_val_process to continue processing.
|
||||
* This routine works immediately after context creation, the fd
|
||||
* does not change.
|
||||
* @param ctx: context.
|
||||
* @return: -1 on error, or file descriptor to use select(2) with.
|
||||
*/
|
||||
int ub_val_ctx_fd(struct ub_val_ctx* ctx);
|
||||
int ub_val_fd(struct ub_val_ctx* ctx);
|
||||
|
||||
/**
|
||||
* Call this routine to continue processing results from the validating
|
||||
@ -312,7 +347,7 @@ int ub_val_ctx_fd(struct ub_val_ctx* ctx);
|
||||
* @param ctx: context
|
||||
* @return: 0 if OK, else error.
|
||||
*/
|
||||
int ub_val_ctx_process(struct ub_val_ctx* ctx);
|
||||
int ub_val_process(struct ub_val_ctx* ctx);
|
||||
|
||||
/**
|
||||
* Perform resolution and validation of the target name.
|
||||
|
@ -69,6 +69,8 @@ void usage(char* argv[])
|
||||
printf("-d : enable debug output\n");
|
||||
printf("-t : use a resolver thread instead of forking a process\n");
|
||||
printf("-c : cancel the requests\n");
|
||||
printf("-r fname : read resolv.conf from fname\n");
|
||||
printf("-f addr : use addr, forward to that server\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -119,6 +121,26 @@ int main(int argc, char** argv)
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
if(argc > 1 && strcmp(argv[0], "-r") == 0) {
|
||||
r = ub_val_ctx_resolvconf(ctx, argv[1]);
|
||||
if(r != 0) {
|
||||
printf("ub_val_ctx_resolvconf error: %s : %s\n",
|
||||
ub_val_strerror(r), strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
argc-=2;
|
||||
argv+=2;
|
||||
}
|
||||
if(argc > 1 && strcmp(argv[0], "-f") == 0) {
|
||||
r = ub_val_ctx_set_fwd(ctx, argv[1]);
|
||||
if(r != 0) {
|
||||
printf("ub_val_ctx_set_fwd error: %s\n",
|
||||
ub_val_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
argc-=2;
|
||||
argv+=2;
|
||||
}
|
||||
|
||||
/* allocate array for results. */
|
||||
lookups = (struct lookinfo*)calloc((size_t)argc,
|
||||
@ -136,6 +158,11 @@ int main(int argc, char** argv)
|
||||
r = ub_val_resolve_async(ctx, argv[i], LDNS_RR_TYPE_A,
|
||||
LDNS_RR_CLASS_IN, &lookups[i], &lookup_is_done,
|
||||
&lookups[i].async_id);
|
||||
if(r != 0) {
|
||||
printf("ub_val_resolve_async error: %s\n",
|
||||
ub_val_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(cancel) {
|
||||
for(i=0; i<argc; i++) {
|
||||
@ -149,9 +176,9 @@ int main(int argc, char** argv)
|
||||
for(i=0; i<1000; i++) {
|
||||
usleep(100000);
|
||||
fprintf(stderr, "%g seconds passed\n", 0.1*(double)i);
|
||||
r = ub_val_ctx_process(ctx);
|
||||
r = ub_val_process(ctx);
|
||||
if(r != 0) {
|
||||
printf("ub_val_ctx_process error: %s\n",
|
||||
printf("ub_val_process error: %s\n",
|
||||
ub_val_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
|
@ -220,8 +220,7 @@ config_deldblstrlist(struct config_str2list* p)
|
||||
}
|
||||
}
|
||||
|
||||
/** delete config stublist */
|
||||
static void
|
||||
void
|
||||
config_delstubs(struct config_stub* p)
|
||||
{
|
||||
struct config_stub* np;
|
||||
|
@ -298,6 +298,12 @@ void config_delstrlist(struct config_strlist* list);
|
||||
*/
|
||||
void config_deldblstrlist(struct config_str2list* list);
|
||||
|
||||
/**
|
||||
* Delete items in config stub list.
|
||||
* @param list: list.
|
||||
*/
|
||||
void config_delstubs(struct config_stub* list);
|
||||
|
||||
/**
|
||||
* Convert 14digit to time value
|
||||
* @param str: string of 14 digits
|
||||
|
Loading…
Reference in New Issue
Block a user