#include <NetInfo/nilib2.h>
#include <stdlib.h>
#include <rpc/rpc.h>
enum ni_parse_status
ni_parse_server_tag(char *str, struct sockaddr_in *server, char **t)
{
int len, i;
char *host, *tag, *slash;
struct hostent *hent;
len = strlen(str);
slash = index(str, '/');
if (slash == NULL) return NI_PARSE_BADFORMAT;
i = slash - str;
if (i == 0) return NI_PARSE_NOHOST;
if (i == (len - 1)) return NI_PARSE_NOTAG;
host = (char *)malloc(i + 1);
*t = (char *)malloc(len - i);
tag = *t;
strncpy(host, str, i);
host[i] = '\0';
strcpy(tag, slash + 1);
server->sin_addr.s_addr = inet_addr(host);
if (server->sin_addr.s_addr == -1)
{
hent = gethostbyname(host);
if (hent != NULL)
{
bcopy(hent->h_addr, &server->sin_addr, hent->h_length);
}
else
{
fprintf(stderr, "Can't find address for %s\n", host);
free(host);
free(tag);
return NI_PARSE_HOSTNOTFOUND;
}
}
free(host);
return NI_PARSE_OK;
}
const char *
ni_parse_error_string(enum ni_parse_status status)
{
switch (status)
{
case NI_PARSE_OK: return("Operation succeeded");
case NI_PARSE_BADFORMAT: return("Bad format");
case NI_PARSE_NOHOST: return("No host");
case NI_PARSE_NOTAG: return("No tag");
case NI_PARSE_BADADDR: return("Bad address");
case NI_PARSE_HOSTNOTFOUND: return("Host not found");
}
return NULL;
}
int
do_open(char *tool, char *name, void **domain, bool bytag, int timeout, char *user, char *passwd)
{
char *tag;
enum ni_parse_status pstatus;
ni_status status;
struct sockaddr_in server;
ni_id rootdir;
void *localni;
if (bytag) {
pstatus = ni_parse_server_tag(name, &server, &tag);
if (pstatus != NI_PARSE_OK)
{
fprintf(stderr, "%s: incorrect format for domain %s (%s)\n",
tool, name, ni_parse_error_string(pstatus));
fprintf(stderr, "usage: -t <host>/<tag>\n");
fprintf(stderr, "<host> can be a host name or IP address\n");
return NI_FAILED + 1 + pstatus;
}
*domain = ni_connect(&server, tag);
free(tag);
if (*domain == NULL) {
fprintf(stderr, "%s: can't connect to server %s\n", tool, name);
return NI_FAILED + 1;
}
}
else {
ni_open(NULL, ".", &localni);
ni_setabort(localni, 1);
ni_setreadtimeout(localni, timeout);
ni_setwritetimeout(localni, timeout);
status = ni_open(localni, name, domain);
ni_free(localni);
if (status != NI_OK) {
fprintf(stderr, "%s: can't connect to server for domain %s\n",
tool, name);
return status;
}
}
ni_setabort(*domain, 1);
ni_setreadtimeout(*domain, timeout);
ni_setwritetimeout(*domain, timeout);
if (user != NULL) {
ni_setuser(*domain, user);
if (passwd != NULL) ni_setpassword(*domain, passwd);
}
status = ni_root(*domain, &rootdir);
if (status != NI_OK) {
if (bytag)
fprintf(stderr, "%s: can't connect to server %s: %s\n",
tool, name, ni_error(status));
else
fprintf(stderr, "%s: can't connect to server for domain %s: %s\n",
tool, name, ni_error(status));
return status;
}
return 0;
}
ni_status ni2_create(void *domain, char *pathname)
{
ni_status ret;
ni_id dir;
ni_needwrite(domain, 1);
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret == NI_OK) return NI_OK;
ret = ni_root(domain, &dir);
if (ret != NI_OK) return ret;
if (pathname[0] == '/') ret = ni2_createpath(domain, &dir, pathname+1);
else ret = ni2_createpath(domain, &dir, pathname);
return ret;
}
ni_status ni2_createprop(void *domain, char *pathname, const ni_name key, ni_namelist values)
{
ni_status ret;
ni_id dir;
ni_needwrite(domain, 1);
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
return ni2_createdirprop(domain, &dir, key, values);
}
ni_status ni2_createdirprop(void *domain, ni_id *dir, const ni_name key, ni_namelist values)
{
ni_status ret;
ni_property p;
ni_namelist nl;
ni_index where;
ni_needwrite(domain, 1);
NI_INIT(&nl);
ret = ni_listprops(domain, dir, &nl);
if (ret != NI_OK) {
return ret;
}
where = ni_namelist_match(nl, key);
ni_namelist_free(&nl);
if (where == NI_INDEX_NULL) {
NI_INIT(&p);
p.nip_name = ni_name_dup(key);
p.nip_val = ni_namelist_dup(values);
ret = ni_createprop(domain, dir, p, NI_INDEX_NULL);
ni_prop_free(&p);
return ret;
}
ret = ni_writeprop(domain, dir, where, values);
return ret;
}
ni_status ni2_appendprop(void *domain, char *pathname, const ni_name key, ni_namelist values)
{
ni_status ret;
ni_id dir;
ni_needwrite(domain, 1);
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
return ni2_appenddirprop(domain, &dir, key, values);
}
ni_status ni2_appenddirprop(void *domain, ni_id *dir, const ni_name key, ni_namelist values)
{
ni_status ret;
ni_property p;
ni_namelist nl;
ni_index where;
int i;
ni_needwrite(domain, 1);
NI_INIT(&nl);
ret = ni_listprops(domain, dir, &nl);
if (ret != NI_OK) {
return ret;
}
where = ni_namelist_match(nl, key);
ni_namelist_free(&nl);
if (where == NI_INDEX_NULL) {
NI_INIT(&p);
p.nip_name = ni_name_dup(key);
p.nip_val = ni_namelist_dup(values);
ret = ni_createprop(domain, dir, p, NI_INDEX_NULL);
ni_prop_free(&p);
return ret;
}
NI_INIT(&nl);
ret = ni_readprop(domain, dir, where, &nl);
if (ret != NI_OK) {
return ret;
}
for (i = 0; i < values.ni_namelist_len; i++) {
ni_namelist_insert(&nl, values.ni_namelist_val[i], NI_INDEX_NULL);
}
ret = ni_writeprop(domain, dir, where, nl);
ni_namelist_free(&nl);
return ret;
}
ni_status ni2_insertval(void *domain, char *pathname, const ni_name key, const ni_name value, ni_index where)
{
ni_status ret;
ni_id dir;
ni_needwrite(domain, 1);
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
return ni2_insertdirval(domain, &dir, key, value, where);
}
ni_status ni2_insertdirval(void *domain, ni_id *dir, const ni_name key, const ni_name value, ni_index whereval)
{
ni_status ret;
ni_property p;
ni_namelist nl;
ni_index where;
ni_needwrite(domain, 1);
NI_INIT(&nl);
ret = ni_listprops(domain, dir, &nl);
if (ret != NI_OK) {
return ret;
}
where = ni_namelist_match(nl, key);
ni_namelist_free(&nl);
if (where == NI_INDEX_NULL) {
NI_INIT(&nl);
ni_namelist_insert(&nl, value, NI_INDEX_NULL);
NI_INIT(&p);
p.nip_name = ni_name_dup(key);
p.nip_val = ni_namelist_dup(nl);
ret = ni_createprop(domain, dir, p, NI_INDEX_NULL);
ni_namelist_free(&nl);
ni_prop_free(&p);
return ret;
}
NI_INIT(&nl);
ret = ni_readprop(domain, dir, where, &nl);
if (ret != NI_OK) {
return ret;
}
ni_namelist_insert(&nl, value, whereval);
ret = ni_writeprop(domain, dir, where, nl);
ni_namelist_free(&nl);
return ret;
}
ni_status ni2_mergeprop(void *domain, char *pathname, const ni_name key, ni_namelist values)
{
ni_status ret;
ni_id dir;
ni_needwrite(domain, 1);
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
return ni2_mergedirprop(domain, &dir, key, values);
}
ni_status ni2_mergedirprop(void *domain, ni_id *dir, const ni_name key, ni_namelist values)
{
ni_status ret;
ni_property p;
ni_namelist nl;
ni_index where, whereval;
int i;
ni_needwrite(domain, 1);
NI_INIT(&nl);
ret = ni_listprops(domain, dir, &nl);
if (ret != NI_OK) {
return ret;
}
where = ni_namelist_match(nl, key);
ni_namelist_free(&nl);
if (where == NI_INDEX_NULL) {
NI_INIT(&p);
p.nip_name = ni_name_dup(key);
p.nip_val = ni_namelist_dup(values);
ret = ni_createprop(domain, dir, p, NI_INDEX_NULL);
ni_prop_free(&p);
return ret;
}
NI_INIT(&nl);
ret = ni_readprop(domain, dir, where, &nl);
if (ret != NI_OK) {
return ret;
}
for (i = 0; i < values.ni_namelist_len; i++) {
whereval = ni_namelist_match(nl, values.ni_namelist_val[i]);
if (whereval == NI_INDEX_NULL) {
ni_namelist_insert(&nl, values.ni_namelist_val[i], NI_INDEX_NULL);
}
}
ret = ni_writeprop(domain, dir, where, nl);
ni_namelist_free(&nl);
return ret;
}
ni_status ni2_destroy(void *domain, char *pathname)
{
ni_status ret;
ni_id dir, parent;
ni_index pi;
ni_needwrite(domain, 1);
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
ret = ni_parent(domain, &dir, &pi);
if (ret != NI_OK) return ret;
parent.nii_object = pi;
ret = ni_self(domain, &parent);
if (ret != NI_OK) return ret;
return ni2_destroydir(domain, &dir, &parent);
}
ni_status ni2_destroydir(void *domain, ni_id *dir, ni_id *parent)
{
ni_status ret;
int i;
ni_idlist children;
ni_id child;
ni_needwrite(domain, 1);
NI_INIT(&children);
ret = ni_children(domain, dir, &children);
if (ret != NI_OK) return ret;
for (i = 0; i < children.ni_idlist_len; i++) {
child.nii_object = children.ni_idlist_val[i];
ret = ni_self(domain, &child);
if (ret != NI_OK) return ret;
ret = ni2_destroydir(domain, &child, dir);
if (ret != NI_OK) return ret;
}
ni_idlist_free(&children);
return ni_destroy(domain, parent, *dir);
}
ni_status ni2_destroyprop(void *domain, char *pathname, ni_namelist keys)
{
ni_status ret;
ni_id dir;
ni_needwrite(domain, 1);
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
return ni2_destroydirprop(domain, &dir, keys);
}
ni_status ni2_destroydirprop(void *domain, ni_id *dir, ni_namelist keys)
{
ni_status ret;
ni_index where;
ni_namelist nl;
int i;
ni_needwrite(domain, 1);
NI_INIT(&nl);
ret = ni_listprops(domain, dir, &nl);
if (ret != NI_OK) {
return ret;
}
for (i = 0; i < keys.ni_namelist_len; i++) {
where = ni_namelist_match(nl, keys.ni_namelist_val[i]);
while (where != NI_INDEX_NULL) {
ret = ni_destroyprop(domain, dir, where);
if (ret != NI_OK) {
ni_namelist_free(&nl);
return ret;
}
ni_namelist_delete(&nl, where);
where = ni_namelist_match(nl, keys.ni_namelist_val[i]);
}
}
ni_namelist_free(&nl);
return NI_OK;
}
ni_status ni2_destroyval(void *domain, char *pathname, const ni_name key, ni_namelist values)
{
ni_status ret;
ni_id dir;
ni_needwrite(domain, 1);
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
return ni2_destroydirval(domain, &dir, key, values);
}
ni_status ni2_destroydirval(void *domain, ni_id *dir, const ni_name key, ni_namelist values)
{
ni_status ret;
ni_namelist nl;
ni_index where, whereval;
int i;
ni_needwrite(domain, 1);
NI_INIT(&nl);
ret = ni_listprops(domain, dir, &nl);
if (ret != NI_OK) {
return ret;
}
where = ni_namelist_match(nl, key);
ni_namelist_free(&nl);
if (where == NI_INDEX_NULL) {
return NI_OK;
}
NI_INIT(&nl);
ret = ni_readprop(domain, dir, where, &nl);
if (ret != NI_OK) {
return ret;
}
for (i = 0; i < values.ni_namelist_len; i++) {
whereval = ni_namelist_match(nl, values.ni_namelist_val[i]);
while (whereval != NI_INDEX_NULL) {
ni_namelist_delete(&nl, whereval);
whereval = ni_namelist_match(nl, values.ni_namelist_val[i]);
}
}
ret = ni_writeprop(domain, dir, where, nl);
ni_namelist_free(&nl);
return ret;
}
ni_status ni2_renameprop(void *domain, char *pathname, const ni_name oldname, const ni_name newname)
{
ni_status ret;
ni_id dir;
ni_needwrite(domain, 1);
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
return ni2_renamedirprop(domain, &dir, oldname, newname);
}
ni_status ni2_renamedirprop(void *domain, ni_id *dir, const ni_name oldname, const ni_name newname)
{
ni_status ret;
ni_index where;
ni_namelist nl;
ni_needwrite(domain, 1);
NI_INIT(&nl);
ret = ni_listprops(domain, dir, &nl);
if (ret != NI_OK) {
return ret;
}
where = ni_namelist_match(nl, oldname);
ni_namelist_free(&nl);
if (where == NI_INDEX_NULL) {
return NI_NOPROP;
}
return ni_renameprop(domain, dir, where, newname);
}
ni_status ni2_pathsearch(void *domain, ni_id *dir, char *pathname)
{
int i, len;
bool is_id;
len = strlen(pathname);
is_id = true;
for (i = 0; i < len && is_id; i++)
if (!isdigit(pathname[i])) is_id = false;
if (is_id) {
dir->nii_object = (unsigned long)atoi(pathname);
return ni_self(domain, dir);
}
else {
return ni_pathsearch(domain, dir, pathname);
}
}
ni_status ni2_createpath(void *domain, ni_id *dir, char *pathname)
{
ni_status ret;
ni_id checkdir;
int i, j, len;
char *dirname = NULL;
bool simple;
i = 0;
while (pathname[i] != '\0') {
simple = true;
for (j = i; pathname[j] != '\0' && simple; j++) {
if (pathname[j] == '\\' && pathname[j+1] == '/') j+=2;
if (pathname[j] == '/') simple = false;
}
len = j - i;
if (!simple) len--;
dirname = malloc(len + 1);
strncpy(dirname, pathname+i, len);
dirname[len] = '\0';
i = j;
checkdir = *dir;
ret = ni_pathsearch(domain, dir, dirname);
if (ret == NI_NODIR) {
*dir = checkdir;
ret = ni2_createchild(domain, dir, dirname);
if (ret != NI_OK) return ret;
}
free(dirname);
}
return NI_OK;
}
ni_status ni2_createchild(void *domain, ni_id *dir, const ni_name dirname)
{
ni_status ret;
ni_proplist p;
ni_id child;
int i, j, k, len;
char *key = NULL;
char *value = NULL;
len = 0;
for (i = 0; dirname[i] != '\0' && dirname[i] != '='; i++);
if (dirname[i] == '=') len = i;
if (len > 0) {
key = malloc(len + 1);
for (i = 0, j = 0; i < len; i++, j++) {
if (dirname[i] == '\\' && dirname[i+1] == '/') i++;
key[j] = dirname[i];
}
key[j] = '\0';
i = len + 1;
}
else {
key = malloc(5);
strcpy(key, "name");
i = 0;
}
j = strlen(dirname);
len = j - i;
value = malloc(len + 1);
for (k = 0; i < j; k++, i++) {
if (dirname[i] == '\\' && dirname[i+1] == '/') i++;
value[k] = dirname[i];
}
value[k] = '\0';
NI_INIT(&p);
nipl_createprop(&p, key);
nipl_appendprop(&p, key, value);
ret = ni_create(domain, dir, p, &child, NI_INDEX_NULL);
if (ret != NI_OK) {
ni_proplist_free(&p);
return ret;
}
ni_proplist_free(&p);
free(key);
free(value);
*dir = child;
return NI_OK;
}
void nipl_createprop(ni_proplist *l, const ni_name n)
{
ni_property p;
NI_INIT(&p);
p.nip_name = ni_name_dup(n);
p.nip_val.ninl_len = 0;
p.nip_val.ninl_val = NULL;
ni_proplist_insert(l, p, NI_INDEX_NULL);
ni_prop_free(&p);
}
void nipl_appendprop(ni_proplist *l, const ni_name n, const ni_name v)
{
ni_index where;
where = ni_proplist_match(*l, n, NULL);
if (where == NI_INDEX_NULL) {
nipl_createprop(l, n);
where = ni_proplist_match(*l, n, NULL);
}
ni_namelist_insert(&(l->nipl_val[where].nip_val), v, NI_INDEX_NULL);
}
void nipl_mergeprop(ni_proplist *l, const ni_name n, const ni_name v)
{
ni_index where;
where = ni_proplist_match(*l, n, NULL);
if (where == NI_INDEX_NULL) {
nipl_createprop(l, n);
where = ni_proplist_match(*l, n, NULL);
}
where = ni_namelist_match(l->nipl_val[where].nip_val, v);
if (where == NI_INDEX_NULL) {
ni_namelist_insert(&(l->nipl_val[where].nip_val), v, NI_INDEX_NULL);
}
}
ni_status ni2_statprop(void *domain, char *pathname, const ni_name key, ni_index *where)
{
ni_status ret;
ni_id dir;
*where = NI_INDEX_NULL;
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
return ni2_statpropdir(domain, &dir, key, where);
}
ni_status ni2_statpropdir(void *domain, ni_id *dir, const ni_name key, ni_index *where)
{
ni_status ret;
ni_namelist nl;
*where = NI_INDEX_NULL;
NI_INIT(&nl);
ret = ni_listprops(domain, dir, &nl);
if (ret != NI_OK) {
return ret;
}
*where = ni_namelist_match(nl, key);
ni_namelist_free(&nl);
if (*where == NI_INDEX_NULL) {
return NI_NOPROP;
}
return NI_OK;
}
ni_status ni2_statval(void *domain, char *pathname, const ni_name key, const ni_name value, ni_index *where)
{
ni_status ret;
ni_id dir;
*where = NI_INDEX_NULL;
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
return ni2_statvaldir(domain, &dir, key, value, where);
}
ni_status ni2_statvaldir(void *domain, ni_id *dir, const ni_name key, const ni_name value, ni_index *where)
{
ni_status ret;
ni_namelist nl;
ni_index wh;
*where = NI_INDEX_NULL;
NI_INIT(&nl);
ret = ni_listprops(domain, dir, &nl);
if (ret != NI_OK) {
return ret;
}
wh = ni_namelist_match(nl, key);
ni_namelist_free(&nl);
if (wh == NI_INDEX_NULL) {
return NI_NOPROP;
}
NI_INIT(&nl);
ret = ni_readprop(domain, dir, wh, &nl);
if (ret != NI_OK) {
return ret;
}
wh = ni_namelist_match(nl, value);
ni_namelist_free(&nl);
if (wh == NI_INDEX_NULL) {
return NI_NONAME;
}
*where = wh;
return NI_OK;
}
ni_status ni2_reapprop(void *domain, char *pathname, const ni_name key)
{
ni_status ret;
ni_id dir;
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
return ni2_reappropdir(domain, &dir, key);
}
ni_status ni2_reappropdir(void *domain, ni_id *dir, const ni_name key)
{
ni_status ret;
ni_namelist nl;
ni_index where;
NI_INIT(&nl);
ret = ni_listprops(domain, dir, &nl);
if (ret != NI_OK) {
return ret;
}
where = ni_namelist_match(nl, key);
ni_namelist_free(&nl);
if (where == NI_INDEX_NULL) {
return NI_OK;
}
NI_INIT(&nl);
ret = ni_readprop(domain, dir, where, &nl);
if (ret != NI_OK) {
return ret;
}
if (nl.ni_namelist_len > 0) {
ni_namelist_free(&nl);
return NI_OK;
}
ni_namelist_free(&nl);
return ni_destroyprop(domain, dir, where);
}
ni_status ni2_reapdir(void *domain, char *pathname)
{
ni_status ret;
ni_id dir;
ni_namelist nl;
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
NI_INIT(&nl);
ret = ni_listprops(domain, &dir, &nl);
if (ret != NI_OK) {
return ret;
}
if (nl.ni_namelist_len > 1) {
ni_namelist_free(&nl);
return NI_OK;
}
ni_namelist_free(&nl);
return ni2_destroy(domain, pathname);
}
ni_status ni2_copy(void *srcdomain, char *path, void*dstdomain, bool recursive)
{
ni_status ret;
ni_id srcdir, dstdir;
ret = ni2_pathsearch(srcdomain, &srcdir, path);
if (ret != NI_OK) return ret;
ret = ni2_create(dstdomain, path);
if (ret != NI_OK) return ret;
ret = ni2_pathsearch(dstdomain, &dstdir, path);
if (ret != NI_OK) return ret;
return ni2_copydir(srcdomain, &srcdir, dstdomain, &dstdir, recursive);
}
ni_status ni2_copydir(void *srcdomain, ni_id *srcdir, void*dstdomain, ni_id *dstdir , bool recursive)
{
ni_status ret;
ni_idlist children;
int i, len;
ni_proplist p;
ni_id dir;
NI_INIT(&p);
ret = ni_read(srcdomain, srcdir, &p);
if (ret != NI_OK) {
return ret;
}
ret = ni_write(dstdomain, dstdir, p);
if (ret != NI_OK) {
ni_proplist_free(&p);
return ret;
}
ni_proplist_free(&p);
if (recursive) {
NI_INIT(&children);
ret = ni_children(srcdomain, srcdir, &children);
if (ret != NI_OK) {
return ret;
}
len = children.ni_idlist_len;
for (i = 0; i < len; i++) {
dir.nii_object = children.ni_idlist_val[i];
ret = ni_self(srcdomain, &dir);
if (ret != NI_OK) {
ni_idlist_free(&children);
return ret;
}
ret = ni2_copydirtoparentdir(srcdomain,&dir,dstdomain,dstdir,recursive);
}
ni_idlist_free(&children);
}
return NI_OK;
}
ni_status ni2_copydirtoparentdir(void *srcdomain, ni_id *srcdir, void*dstdomain, ni_id *dstdir , bool recursive)
{
ni_status ret;
ni_idlist children;
int i, len;
ni_proplist p;
ni_id dir, newdstdir;
NI_INIT(&p);
ret = ni_read(srcdomain, srcdir, &p);
if (ret != NI_OK) {
return ret;
}
ret = ni_create(dstdomain, dstdir, p, &newdstdir, NI_INDEX_NULL);
if (ret != NI_OK) {
ni_proplist_free(&p);
return ret;
}
ni_proplist_free(&p);
if (recursive) {
NI_INIT(&children);
ret = ni_children(srcdomain, srcdir, &children);
if (ret != NI_OK) {
return ret;
}
len = children.ni_idlist_len;
for (i = 0; i < len; i++) {
dir.nii_object = children.ni_idlist_val[i];
ret = ni_self(srcdomain, &dir);
if (ret != NI_OK) {
ni_idlist_free(&children);
return ret;
}
ret = ni2_copydirtoparentdir(srcdomain,&dir,dstdomain, &newdstdir,recursive);
}
ni_idlist_free(&children);
}
return NI_OK;
}
ni_status ni2_lookupprop(void *domain, char *pathname, const ni_name key, ni_namelist *values)
{
ni_status ret;
ni_id dir;
ret = ni2_pathsearch(domain, &dir, pathname);
if (ret != NI_OK) return ret;
return ni_lookupprop(domain, &dir, key, values);
}
ni_index ni_namelist_insert_sorted(ni_namelist *values, const ni_name newvalue)
{
int i, len;
len = values->ni_namelist_len;
for (i = 0; i < len; i++) {
if (strcmp(newvalue, values->ni_namelist_val[i]) <= 0) {
ni_namelist_insert(values, newvalue, (ni_index)i);
return (ni_index)i;
}
}
ni_namelist_insert(values, newvalue, NI_INDEX_NULL);
return NI_INDEX_NULL;
}