int call_alloc(struct call **callp, struct flowmgr *fm, const char *convid) { struct call *call; int err; if (!callp || !fm) return EINVAL; call = mem_zalloc(sizeof(*call), call_destructor); if (call == NULL) { return ENOMEM; } info("flowmgr(%p): call(%p) alloc\n", fm, call); call->fm = fm; err = dict_add(fm->calls, convid, call); if (err) { warning("flowmgr: call_alloc: failed to add to calls: %m\n", err); goto out; } err = str_dup(&call->convid, convid); if (err) { goto out; } err = dict_alloc(&call->flows); if (err) { goto out; } err = dict_alloc(&call->users); if (err) { goto out; } list_init(&call->conf_parts); list_init(&call->rrl); list_init(&call->ghostl); /* Call is now owned by the dictionary */ mem_deref(call); out: if (err) { /* If no one received the call object, * it is referenced by the dictionary */ mem_deref(call); } else if (callp) { *callp = call; } return err; }
DICT * dict_erlang_open(const char *key, int open_flags, int dict_flags) { DICT_ERLANG *dict_erlang; if (open_flags != O_RDONLY) msg_fatal("%s:%s map requires O_RDONLY access mode", DICT_TYPE_ERLANG, key); erl_init(NULL, 0); dict_erlang = (DICT_ERLANG *)dict_alloc(DICT_TYPE_ERLANG, key, sizeof(DICT_ERLANG)); dict_erlang->dict.lookup = dict_erlang_lookup; dict_erlang->dict.close = dict_erlang_close; dict_erlang->dict.flags = dict_flags; erlang_parse_config(dict_erlang, key); if (dict_erlang->nodes->argc == 0) msg_fatal("no erlang nodes specified"); dict_erlang->active_node = 0; if (dict_erlang->cookie == NULL) msg_fatal("no erlang cookie specified"); if (dict_erlang->mod == NULL) msg_fatal("no erlang module specified"); if (dict_erlang->fun == NULL) msg_fatal("no erlang function specified"); return (DICT_DEBUG(&dict_erlang->dict)); }
DICT *dict_tcp_open(const char *map, int open_flags, int dict_flags) { DICT_TCP *dict_tcp; dict_errno = 0; /* * Sanity checks. */ if (dict_flags & DICT_FLAG_NO_UNAUTH) msg_fatal("%s:%s map is not allowed for security sensitive data", DICT_TYPE_TCP, map); if (open_flags != O_RDONLY) msg_fatal("%s:%s map requires O_RDONLY access mode", DICT_TYPE_TCP, map); /* * Create the dictionary handle. Do not open the connection until the * first request is made. */ dict_tcp = (DICT_TCP *) dict_alloc(DICT_TYPE_TCP, map, sizeof(*dict_tcp)); dict_tcp->fp = 0; dict_tcp->raw_buf = dict_tcp->hex_buf = 0; dict_tcp->dict.lookup = dict_tcp_lookup; dict_tcp->dict.close = dict_tcp_close; dict_tcp->dict.flags = dict_flags | DICT_FLAG_PATTERN; if (dict_flags & DICT_FLAG_FOLD_MUL) dict_tcp->dict.fold_buf = vstring_alloc(10); return (DICT_DEBUG (&dict_tcp->dict)); }
/* Create an initial dictionary if necessary. */ static ref * make_initial_dict(i_ctx_t *i_ctx_p, const char *iname, ref idicts[]) { int i; /* systemdict was created specially. */ if (!strcmp(iname, "systemdict")) return systemdict; for (i = 0; i < countof(initial_dictionaries); i++) { const char *dname = initial_dictionaries[i].name; const int dsize = initial_dictionaries[i].size; if (!strcmp(iname, dname)) { ref *dref = &idicts[i]; if (r_has_type(dref, t_null)) { gs_ref_memory_t *mem = (initial_dictionaries[i].local ? iimemory_local : iimemory_global); int code = dict_alloc(mem, dsize, dref); if (code < 0) return 0; /* disaster */ } return dref; } } /* * Name mentioned in some op_def, but not in initial_dictionaries. * Punt. */ return 0; }
DICT *dict_pgsql_open(const char *name, int open_flags, int dict_flags) { DICT_PGSQL *dict_pgsql; CFG_PARSER *parser; /* * Sanity check. */ if (open_flags != O_RDONLY) return (dict_surrogate(DICT_TYPE_PGSQL, name, open_flags, dict_flags, "%s:%s map requires O_RDONLY access mode", DICT_TYPE_PGSQL, name)); /* * Open the configuration file. */ if ((parser = cfg_parser_alloc(name)) == 0) return (dict_surrogate(DICT_TYPE_PGSQL, name, open_flags, dict_flags, "open %s: %m", name)); dict_pgsql = (DICT_PGSQL *) dict_alloc(DICT_TYPE_PGSQL, name, sizeof(DICT_PGSQL)); dict_pgsql->dict.lookup = dict_pgsql_lookup; dict_pgsql->dict.close = dict_pgsql_close; dict_pgsql->dict.flags = dict_flags; dict_pgsql->parser = parser; pgsql_parse_config(dict_pgsql, name); dict_pgsql->active_host = 0; dict_pgsql->pldb = plpgsql_init(dict_pgsql->hosts); if (dict_pgsql->pldb == NULL) msg_fatal("couldn't intialize pldb!\n"); dict_pgsql->dict.owner = cfg_get_owner(dict_pgsql->parser); return (DICT_DEBUG (&dict_pgsql->dict)); }
/* * Make a copy of dict "d". Shallow if "deep" is FALSE. * The refcount of the new dict is set to 1. * See item_copy() for "copyID". * Returns NULL when out of memory. */ dict_T * dict_copy(dict_T *orig, int deep, int copyID) { dict_T *copy; dictitem_T *di; int todo; hashitem_T *hi; if (orig == NULL) return NULL; copy = dict_alloc(); if (copy != NULL) { if (copyID != 0) { orig->dv_copyID = copyID; orig->dv_copydict = copy; } todo = (int)orig->dv_hashtab.ht_used; for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi) { if (!HASHITEM_EMPTY(hi)) { --todo; di = dictitem_alloc(hi->hi_key); if (di == NULL) break; if (deep) { if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep, copyID) == FAIL) { vim_free(di); break; } } else copy_tv(&HI2DI(hi)->di_tv, &di->di_tv); if (dict_add(copy, di) == FAIL) { dictitem_free(di); break; } } } ++copy->dv_refcount; if (todo > 0) { dict_unref(copy); copy = NULL; } } return copy; }
DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags) { DICT_CIDR *dict_cidr; VSTREAM *map_fp; VSTRING *line_buffer = vstring_alloc(100); VSTRING *why = vstring_alloc(100); DICT_CIDR_ENTRY *rule; DICT_CIDR_ENTRY *last_rule = 0; int lineno = 0; /* * Sanity checks. */ if (open_flags != O_RDONLY) msg_fatal("%s:%s map requires O_RDONLY access mode", DICT_TYPE_CIDR, mapname); /* * XXX Eliminate unnecessary queries by setting a flag that says "this * map matches network addresses only". */ dict_cidr = (DICT_CIDR *) dict_alloc(DICT_TYPE_CIDR, mapname, sizeof(*dict_cidr)); dict_cidr->dict.lookup = dict_cidr_lookup; dict_cidr->dict.close = dict_cidr_close; dict_cidr->dict.flags = dict_flags | DICT_FLAG_PATTERN; dict_cidr->head = 0; if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0) msg_fatal("open %s: %m", mapname); while (readlline(line_buffer, map_fp, &lineno)) { rule = dict_cidr_parse_rule(vstring_str(line_buffer), why); if (rule == 0) { msg_warn("cidr map %s, line %d: %s: skipping this rule", mapname, lineno, vstring_str(why)); continue; } if (last_rule == 0) dict_cidr->head = rule; else last_rule->cidr_info.next = &(rule->cidr_info); last_rule = rule; } /* * Clean up. */ if (vstream_fclose(map_fp)) msg_fatal("cidr map %s: read error: %m", mapname); vstring_free(line_buffer); vstring_free(why); return (DICT_DEBUG (&dict_cidr->dict)); }
DICT *dict_static_open(const char *name, int unused_flags, int dict_flags) { DICT *dict; dict = dict_alloc(DICT_TYPE_STATIC, name, sizeof(*dict)); dict->lookup = dict_static_lookup; dict->close = dict_static_close; dict->flags = dict_flags | DICT_FLAG_FIXED; dict->owner.status = DICT_OWNER_TRUSTED; return (DICT_DEBUG (dict)); }
void dict_xset(struct dict *d, const char * k, void *data) { struct dictentry *entry; if ((entry = dict_alloc(k, data)) == NULL) err(1, "dict_xset: malloc"); if (SPLAY_INSERT(_dict, &d->dict, entry)) errx(1, "dict_xset(%p, %s)", d, k); d->count += 1; }
static DICT *dict_cdbq_open(const char *path, int dict_flags) { DICT_CDBQ *dict_cdbq; struct stat st; char *cdb_path; int fd; cdb_path = concatenate(path, CDB_SUFFIX, (char *) 0); if ((fd = open(cdb_path, O_RDONLY)) < 0) return (dict_surrogate(DICT_TYPE_CDB, path, O_RDONLY, dict_flags, "open database %s: %m", cdb_path)); dict_cdbq = (DICT_CDBQ *) dict_alloc(DICT_TYPE_CDB, cdb_path, sizeof(*dict_cdbq)); #if defined(TINYCDB_VERSION) if (cdb_init(&(dict_cdbq->cdb), fd) != 0) msg_fatal("dict_cdbq_open: unable to init %s: %m", cdb_path); #else cdb_init(&(dict_cdbq->cdb), fd); #endif dict_cdbq->dict.lookup = dict_cdbq_lookup; dict_cdbq->dict.close = dict_cdbq_close; dict_cdbq->dict.stat_fd = fd; if (fstat(fd, &st) < 0) msg_fatal("dict_dbq_open: fstat: %m"); dict_cdbq->dict.mtime = st.st_mtime; dict_cdbq->dict.owner.uid = st.st_uid; dict_cdbq->dict.owner.status = (st.st_uid != 0); close_on_exec(fd, CLOSE_ON_EXEC); /* * Warn if the source file is newer than the indexed file, except when * the source file changed only seconds ago. */ if (stat(path, &st) == 0 && st.st_mtime > dict_cdbq->dict.mtime && st.st_mtime < time((time_t *) 0) - 100) msg_warn("database %s is older than source file %s", cdb_path, path); /* * If undecided about appending a null byte to key and value, choose to * try both in query mode. */ if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) dict_flags |= DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL; dict_cdbq->dict.flags = dict_flags | DICT_FLAG_FIXED; if (dict_flags & DICT_FLAG_FOLD_FIX) dict_cdbq->dict.fold_buf = vstring_alloc(10); myfree(cdb_path); return (&dict_cdbq->dict); }
DICT *dict_random_open(const char *name, int open_flags, int dict_flags) { DICT_RANDOM *dict_random; char *saved_name = 0; size_t len; /* * Clarity first. Let the optimizer worry about redundant code. */ #define DICT_RANDOM_RETURN(x) do { \ if (saved_name != 0) \ myfree(saved_name); \ return (x); \ } while (0) /* * Sanity checks. */ if (open_flags != O_RDONLY) DICT_RANDOM_RETURN(dict_surrogate(DICT_TYPE_RANDOM, name, open_flags, dict_flags, "%s:%s map requires O_RDONLY access mode", DICT_TYPE_RANDOM, name)); /* * Split the name name into its constituent parts. */ if ((len = balpar(name, "{}")) == 0 || name[len] != 0 || *(saved_name = mystrndup(name + 1, len - 2)) == 0) DICT_RANDOM_RETURN(dict_surrogate(DICT_TYPE_RANDOM, name, open_flags, dict_flags, "bad syntax: \"%s:%s\"; " "need \"%s:{type:name...}\"", DICT_TYPE_RANDOM, name, DICT_TYPE_RANDOM)); /* * Bundle up the result. */ dict_random = (DICT_RANDOM *) dict_alloc(DICT_TYPE_RANDOM, name, sizeof(*dict_random)); dict_random->dict.lookup = dict_random_lookup; dict_random->dict.close = dict_random_close; dict_random->dict.flags = dict_flags | DICT_FLAG_PATTERN; dict_random->replies = argv_splitq(saved_name, ", \t\r\n", "{}"); dict_random->dict.owner.status = DICT_OWNER_TRUSTED; dict_random->dict.owner.uid = 0; DICT_RANDOM_RETURN(DICT_DEBUG (&dict_random->dict)); }
/* * Allocate an empty dict for a return value. * Returns OK or FAIL. */ int rettv_dict_alloc(typval_T *rettv) { dict_T *d = dict_alloc(); if (d == NULL) return FAIL; rettv->vval.v_dict = d; rettv->v_type = VAR_DICT; rettv->v_lock = 0; ++d->dv_refcount; return OK; }
DICT *dict_env_open(const char *name, int unused_flags, int dict_flags) { DICT *dict; dict = dict_alloc(DICT_TYPE_ENVIRON, name, sizeof(*dict)); dict->lookup = dict_env_lookup; dict->update = dict_env_update; dict->close = dict_env_close; dict->flags = dict_flags | DICT_FLAG_FIXED; if (dict_flags & DICT_FLAG_FOLD_FIX) dict->fold_buf = vstring_alloc(10); dict->owner.status = DICT_OWNER_TRUSTED; return (DICT_DEBUG (dict)); }
DICT *dict_ht_open(const char *name, int unused_open_flags, int dict_flags) { DICT_HT *dict_ht; dict_ht = (DICT_HT *) dict_alloc(DICT_TYPE_HT, name, sizeof(*dict_ht)); dict_ht->dict.lookup = dict_ht_lookup; dict_ht->dict.update = dict_ht_update; dict_ht->dict.sequence = dict_ht_sequence; dict_ht->dict.close = dict_ht_close; dict_ht->dict.flags = dict_flags | DICT_FLAG_FIXED; if (dict_flags & DICT_FLAG_FOLD_FIX) dict_ht->dict.fold_buf = vstring_alloc(10); dict_ht->table = htable_create(0); dict_ht->dict.owner.status = DICT_OWNER_TRUSTED; return (&dict_ht->dict); }
void * dict_set(struct dict *d, const char *k, void *data) { struct dictentry *entry, key; char *old; key.key = k; if ((entry = SPLAY_FIND(_dict, &d->dict, &key)) == NULL) { if ((entry = dict_alloc(k, data)) == NULL) err(1, "dict_set: malloc"); SPLAY_INSERT(_dict, &d->dict, entry); old = NULL; d->count += 1; } else { old = entry->data; entry->data = data; } return (old); }
DICT *dict_nis_open(const char *map, int open_flags, int dict_flags) { DICT_NIS *dict_nis; if (open_flags != O_RDONLY) msg_fatal("%s:%s map requires O_RDONLY access mode", DICT_TYPE_NIS, map); dict_nis = (DICT_NIS *) dict_alloc(DICT_TYPE_NIS, map, sizeof(*dict_nis)); dict_nis->dict.lookup = dict_nis_lookup; dict_nis->dict.close = dict_nis_close; dict_nis->dict.flags = dict_flags | DICT_FLAG_FIXED; if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) dict_nis->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL); if (dict_flags & DICT_FLAG_FOLD_FIX) dict_nis->dict.fold_buf = vstring_alloc(10); if (dict_nis_domain == 0) dict_nis_init(); return (DICT_DEBUG (&dict_nis->dict)); }
/********************************************************************** * public interface dict_mysql_open * create association with database with appropriate values * parse the map's config file * allocate memory **********************************************************************/ DICT *dict_mysql_open(const char *name, int open_flags, int dict_flags) { DICT_MYSQL *dict_mysql; /* * Sanity checks. */ if (open_flags != O_RDONLY) msg_fatal("%s:%s map requires O_RDONLY access mode", DICT_TYPE_MYSQL, name); dict_mysql = (DICT_MYSQL *) dict_alloc(DICT_TYPE_MYSQL, name, sizeof(DICT_MYSQL)); dict_mysql->dict.lookup = dict_mysql_lookup; dict_mysql->dict.close = dict_mysql_close; dict_mysql->dict.flags = dict_flags | DICT_FLAG_FIXED; dict_mysql->name = mysqlname_parse(name); dict_mysql->pldb = plmysql_init(dict_mysql->name->hostnames, dict_mysql->name->len_hosts); if (dict_mysql->pldb == NULL) msg_fatal("couldn't intialize pldb!\n"); return (DICT_DEBUG (&dict_mysql->dict)); }
DICT *dict_sqlite_open(const char *name, int open_flags, int dict_flags) { DICT_SQLITE *dict_sqlite; CFG_PARSER *parser; /* * Sanity checks. */ if (open_flags != O_RDONLY) return (dict_surrogate(DICT_TYPE_SQLITE, name, open_flags, dict_flags, "%s:%s map requires O_RDONLY access mode", DICT_TYPE_SQLITE, name)); /* * Open the configuration file. */ if ((parser = cfg_parser_alloc(name)) == 0) return (dict_surrogate(DICT_TYPE_SQLITE, name, open_flags, dict_flags, "open %s: %m", name)); dict_sqlite = (DICT_SQLITE *) dict_alloc(DICT_TYPE_SQLITE, name, sizeof(DICT_SQLITE)); dict_sqlite->dict.lookup = dict_sqlite_lookup; dict_sqlite->dict.close = dict_sqlite_close; dict_sqlite->dict.flags = dict_flags; dict_sqlite->parser = parser; sqlite_parse_config(dict_sqlite, name); if (sqlite3_open(dict_sqlite->dbpath, &dict_sqlite->db)) msg_fatal("%s:%s: Can't open database: %s\n", DICT_TYPE_SQLITE, name, sqlite3_errmsg(dict_sqlite->db)); dict_sqlite->dict.owner = cfg_get_owner(dict_sqlite->parser); return (DICT_DEBUG (&dict_sqlite->dict)); }
static int ref_param_begin_write_collection(gs_param_list * plist, gs_param_name pkey, gs_param_dict * pvalue, gs_param_collection_type_t coll_type) { iparam_list *const iplist = (iparam_list *) plist; gs_ref_memory_t *imem = iplist->ref_memory; dict_param_list *dlist = (dict_param_list *) gs_alloc_bytes(plist->memory, size_of(dict_param_list), "ref_param_begin_write_collection"); int code; if (dlist == 0) return_error(e_VMerror); if (coll_type != gs_param_collection_array) { ref dref; code = dict_alloc(imem, pvalue->size, &dref); if (code >= 0) { code = dict_param_list_write(dlist, &dref, NULL, imem); dlist->int_keys = coll_type == gs_param_collection_dict_int_keys; } } else { ref aref; code = gs_alloc_ref_array(imem, &aref, a_all, pvalue->size, "ref_param_begin_write_collection"); if (code >= 0) code = array_new_indexed_plist_write(dlist, &aref, NULL, imem); } if (code < 0) gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection"); else pvalue->list = (gs_param_list *) dlist; return code; }
DICT *dict_thash_open(const char *path, int open_flags, int dict_flags) { DICT_THASH *dict_thash; VSTREAM *fp = 0; struct stat st; time_t before; time_t after; VSTRING *line_buffer = 0; int lineno; char *key; char *value; HTABLE *table; HTABLE_INFO *ht; /* * Let the optimizer worry about eliminating redundant code. */ #define DICT_THASH_OPEN_RETURN(d) { \ DICT *__d = (d); \ if (fp != 0) \ vstream_fclose(fp); \ if (line_buffer != 0) \ vstring_free(line_buffer); \ return (__d); \ } while (0) /* * Sanity checks. */ if (open_flags != O_RDONLY) DICT_THASH_OPEN_RETURN(dict_surrogate(DICT_TYPE_THASH, path, open_flags, dict_flags, "%s:%s map requires O_RDONLY access mode", DICT_TYPE_THASH, path)); /* * Read the flat text file into in-memory hash. Read the file again if it * may have changed while we were reading. */ for (before = time((time_t *) 0); /* see below */ ; before = after) { if ((fp = vstream_fopen(path, open_flags, 0644)) == 0) { DICT_THASH_OPEN_RETURN(dict_surrogate(DICT_TYPE_THASH, path, open_flags, dict_flags, "open database %s: %m", path)); } if (line_buffer == 0) line_buffer = vstring_alloc(100); lineno = 0; table = htable_create(13); while (readlline(line_buffer, fp, &lineno)) { /* * Split on the first whitespace character, then trim leading and * trailing whitespace from key and value. */ key = STR(line_buffer); value = key + strcspn(key, " \t\r\n"); if (*value) *value++ = 0; while (ISSPACE(*value)) value++; trimblanks(key, 0)[0] = 0; trimblanks(value, 0)[0] = 0; /* * Enforce the "key whitespace value" format. Disallow missing * keys or missing values. */ if (*key == 0 || *value == 0) { msg_warn("%s, line %d: expected format: key whitespace value" " -- ignoring this line", path, lineno); continue; } if (key[strlen(key) - 1] == ':') msg_warn("%s, line %d: record is in \"key: value\" format;" " is this an alias file?", path, lineno); /* * Optionally fold the key. */ if (dict_flags & DICT_FLAG_FOLD_FIX) lowercase(key); /* * Store the value under the key. Handle duplicates * appropriately. */ if ((ht = htable_locate(table, key)) != 0) { if (dict_flags & DICT_FLAG_DUP_IGNORE) { /* void */ ; } else if (dict_flags & DICT_FLAG_DUP_REPLACE) { myfree(ht->value); ht->value = mystrdup(value); } else if (dict_flags & DICT_FLAG_DUP_WARN) { msg_warn("%s, line %d: duplicate entry: \"%s\"", path, lineno, key); } else { msg_fatal("%s, line %d: duplicate entry: \"%s\"", path, lineno, key); } } else { htable_enter(table, key, mystrdup(value)); } } /* * See if the source file is hot. */ if (fstat(vstream_fileno(fp), &st) < 0) msg_fatal("fstat %s: %m", path); if (vstream_fclose(fp)) msg_fatal("read %s: %m", path); fp = 0; /* DICT_THASH_OPEN_RETURN() */ after = time((time_t *) 0); if (st.st_mtime < before - 1 || st.st_mtime > after) break; /* * Yes, it is hot. Discard the result and read the file again. */ htable_free(table, myfree); if (msg_verbose > 1) msg_info("pausing to let file %s cool down", path); doze(300000); } /* * Create the in-memory table. */ dict_thash = (DICT_THASH *) dict_alloc(DICT_TYPE_THASH, path, sizeof(*dict_thash)); dict_thash->dict.lookup = dict_thash_lookup; dict_thash->dict.sequence = dict_thash_sequence; dict_thash->dict.close = dict_thash_close; dict_thash->dict.flags = dict_flags | DICT_FLAG_DUP_WARN | DICT_FLAG_FIXED; if (dict_flags & DICT_FLAG_FOLD_FIX) dict_thash->dict.fold_buf = vstring_alloc(10); dict_thash->info = 0; dict_thash->table = table; dict_thash->dict.owner.uid = st.st_uid; dict_thash->dict.owner.status = (st.st_uid != 0); DICT_THASH_OPEN_RETURN(DICT_DEBUG (&dict_thash->dict)); }
/* initialize the dictionaries that hold operator definitions. */ int obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem) { int level = gs_op_language_level(); ref system_dict; i_ctx_t *i_ctx_p; int code; /* * Create systemdict. The context machinery requires that * we do this before initializing the interpreter. */ code = dict_alloc(idmem->space_global, (level >= 3 ? SYSTEMDICT_LL3_SIZE : level >= 2 ? SYSTEMDICT_LEVEL2_SIZE : SYSTEMDICT_SIZE), &system_dict); if (code < 0) return code; /* Initialize the interpreter. */ code = gs_interp_init(pi_ctx_p, &system_dict, idmem); if (code < 0) return code; i_ctx_p = *pi_ctx_p; { #define icount countof(initial_dictionaries) ref idicts[icount]; int i; const op_def *const *tptr; min_dstack_size = MIN_DSTACK_SIZE; refset_null(idicts, icount); /* Put systemdict on the dictionary stack. */ if (level >= 2) { dsp += 2; /* * For the moment, let globaldict be an alias for systemdict. */ dsp[-1] = system_dict; min_dstack_size++; } else { ++dsp; } *dsp = system_dict; /* Create dictionaries which are to be homes for operators. */ for (tptr = op_defs_all; *tptr != 0; tptr++) { const op_def *def; for (def = *tptr; def->oname != 0; def++) if (op_def_is_begin_dict(def)) { if (make_initial_dict(i_ctx_p, def->oname, idicts) == 0) return_error(e_VMerror); } } /* Set up the initial dstack. */ for (i = 0; i < countof(initial_dstack); i++) { const char *dname = initial_dstack[i]; ++dsp; if (!strcmp(dname, "userdict")) dstack_userdict_index = dsp - dsbot; ref_assign(dsp, make_initial_dict(i_ctx_p, dname, idicts)); } /* Enter names of referenced initial dictionaries into systemdict. */ initial_enter_name("systemdict", systemdict); for (i = 0; i < icount; i++) { ref *idict = &idicts[i]; if (!r_has_type(idict, t_null)) { /* * Note that we enter the dictionary in systemdict * even if it is in local VM. There is a special * provision in the garbage collector for this: * see ivmspace.h for more information. * In order to do this, we must temporarily * identify systemdict as local, so that the * store check in dict_put won't fail. */ uint save_space = r_space(systemdict); r_set_space(systemdict, avm_local); code = initial_enter_name(initial_dictionaries[i].name, idict); r_set_space(systemdict, save_space); if (code < 0) return code; } } #undef icount } gs_interp_reset(i_ctx_p); { ref vnull, vtrue, vfalse; make_null(&vnull); make_true(&vtrue); make_false(&vfalse); if ((code = initial_enter_name("null", &vnull)) < 0 || (code = initial_enter_name("true", &vtrue)) < 0 || (code = initial_enter_name("false", &vfalse)) < 0 ) return code; } /* Create the error name table */ { int n = countof(gs_error_names) - 1; int i; ref era; code = ialloc_ref_array(&era, a_readonly, n, "ErrorNames"); if (code < 0) return code; for (i = 0; i < n; i++) if ((code = name_enter_string(imemory, (const char *)gs_error_names[i], era.value.refs + i)) < 0) return code; return initial_enter_name("ErrorNames", &era); } }
DICT *dict_union_open(const char *name, int open_flags, int dict_flags) { static const char myname[] = "dict_union_open"; DICT_UNION *dict_union; char *saved_name = 0; char *dict_type_name; ARGV *argv = 0; char **cpp; DICT *dict; int match_flags = 0; struct DICT_OWNER aggr_owner; size_t len; /* * Clarity first. Let the optimizer worry about redundant code. */ #define DICT_UNION_RETURN(x) do { \ if (saved_name != 0) \ myfree(saved_name); \ if (argv != 0) \ argv_free(argv); \ return (x); \ } while (0) /* * Sanity checks. */ if (open_flags != O_RDONLY) DICT_UNION_RETURN(dict_surrogate(DICT_TYPE_UNION, name, open_flags, dict_flags, "%s:%s map requires O_RDONLY access mode", DICT_TYPE_UNION, name)); /* * Split the table name into its constituent parts. */ if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0 || *(saved_name = mystrndup(name + 1, len - 2)) == 0 || ((argv = argv_splitq(saved_name, CHARS_COMMA_SP, CHARS_BRACE)), (argv->argc == 0))) DICT_UNION_RETURN(dict_surrogate(DICT_TYPE_UNION, name, open_flags, dict_flags, "bad syntax: \"%s:%s\"; " "need \"%s:{type:name...}\"", DICT_TYPE_UNION, name, DICT_TYPE_UNION)); /* * The least-trusted table in the set determines the over-all trust * level. The first table determines the pattern-matching flags. */ DICT_OWNER_AGGREGATE_INIT(aggr_owner); for (cpp = argv->argv; (dict_type_name = *cpp) != 0; cpp++) { if (msg_verbose) msg_info("%s: %s", myname, dict_type_name); if (strchr(dict_type_name, ':') == 0) DICT_UNION_RETURN(dict_surrogate(DICT_TYPE_UNION, name, open_flags, dict_flags, "bad syntax: \"%s:%s\"; " "need \"%s:{type:name...}\"", DICT_TYPE_UNION, name, DICT_TYPE_UNION)); if ((dict = dict_handle(dict_type_name)) == 0) dict = dict_open(dict_type_name, open_flags, dict_flags); dict_register(dict_type_name, dict); DICT_OWNER_AGGREGATE_UPDATE(aggr_owner, dict->owner); if (cpp == argv->argv) match_flags = dict->flags & (DICT_FLAG_FIXED | DICT_FLAG_PATTERN); } /* * Bundle up the result. */ dict_union = (DICT_UNION *) dict_alloc(DICT_TYPE_UNION, name, sizeof(*dict_union)); dict_union->dict.lookup = dict_union_lookup; dict_union->dict.close = dict_union_close; dict_union->dict.flags = dict_flags | match_flags; dict_union->dict.owner = aggr_owner; dict_union->re_buf = vstring_alloc(100); dict_union->map_union = argv; argv = 0; DICT_UNION_RETURN(DICT_DEBUG (&dict_union->dict)); }
/// Copies a C string into a String (binary safe string, characters + length). /// The resulting string is also NUL-terminated, to facilitate interoperating /// with code using C strings. /// /// @param str the C string to copy /// @return the resulting String, if the input string was NULL, an /// empty String is returned String cstr_to_string(const char *str) { if (str == NULL) { return (String) STRING_INIT; } size_t len = strlen(str); return (String) { .data = xmemdupz(str, len), .size = len }; } static bool object_to_vim(Object obj, typval_T *tv, Error *err) { tv->v_type = VAR_UNKNOWN; tv->v_lock = 0; switch (obj.type) { case kObjectTypeNil: tv->v_type = VAR_NUMBER; tv->vval.v_number = 0; break; case kObjectTypeBoolean: tv->v_type = VAR_NUMBER; tv->vval.v_number = obj.data.boolean; break; case kObjectTypeInteger: if (obj.data.integer > INT_MAX || obj.data.integer < INT_MIN) { set_api_error("Integer value outside range", err); return false; } tv->v_type = VAR_NUMBER; tv->vval.v_number = (int)obj.data.integer; break; case kObjectTypeFloat: tv->v_type = VAR_FLOAT; tv->vval.v_float = obj.data.floating; break; case kObjectTypeString: tv->v_type = VAR_STRING; tv->vval.v_string = xmemdupz(obj.data.string.data, obj.data.string.size); break; case kObjectTypeArray: tv->v_type = VAR_LIST; tv->vval.v_list = list_alloc(); for (uint32_t i = 0; i < obj.data.array.size; i++) { Object item = obj.data.array.items[i]; listitem_T *li = listitem_alloc(); if (!object_to_vim(item, &li->li_tv, err)) { // cleanup listitem_free(li); list_free(tv->vval.v_list, true); return false; } list_append(tv->vval.v_list, li); } tv->vval.v_list->lv_refcount++; break; case kObjectTypeDictionary: tv->v_type = VAR_DICT; tv->vval.v_dict = dict_alloc(); for (uint32_t i = 0; i < obj.data.dictionary.size; i++) { KeyValuePair item = obj.data.dictionary.items[i]; String key = item.key; if (key.size == 0) { set_api_error("Empty dictionary keys aren't allowed", err); // cleanup dict_free(tv->vval.v_dict, true); return false; } dictitem_T *di = dictitem_alloc((uint8_t *) key.data); if (!object_to_vim(item.value, &di->di_tv, err)) { // cleanup dictitem_free(di); dict_free(tv->vval.v_dict, true); return false; } dict_add(tv->vval.v_dict, di); } tv->vval.v_dict->dv_refcount++; break; } return true; }
int zdefault_make_font(gs_font_dir * pdir, const gs_font * oldfont, const gs_matrix * pmat, gs_font ** ppfont) { gs_font *newfont = *ppfont; gs_memory_t *mem = newfont->memory; /* HACK: we know this font was allocated by the interpreter. */ gs_ref_memory_t *imem = (gs_ref_memory_t *)mem; ref *fp = pfont_dict(oldfont); font_data *pdata; ref newdict, newmat, scalemat; uint dlen = dict_maxlength(fp); uint mlen = dict_length(fp) + 3; /* FontID, OrigFont, ScaleMatrix */ int code; if (dlen < mlen) dlen = mlen; if ((pdata = gs_alloc_struct(mem, font_data, &st_font_data, "make_font(font_data)")) == 0 ) return_error(e_VMerror); /* * This dictionary is newly created: it's safe to pass NULL as the * dstack pointer to dict_copy and dict_put_string. */ if ((code = dict_alloc(imem, dlen, &newdict)) < 0 || (code = dict_copy(fp, &newdict, NULL)) < 0 || (code = gs_alloc_ref_array(imem, &newmat, a_all, 12, "make_font(matrices)")) < 0 ) return code; refset_null_new(newmat.value.refs, 12, imemory_new_mask(imem)); ref_assign(&scalemat, &newmat); r_set_size(&scalemat, 6); scalemat.value.refs += 6; /* * Create the scaling matrix. We could do this several different * ways: by "dividing" the new FontMatrix by the base FontMatrix, by * multiplying the current scaling matrix by a ScaleMatrix kept in * the gs_font, or by multiplying the current scaling matrix by the * ScaleMatrix from the font dictionary. We opt for the last of * these. */ { gs_matrix scale, prev_scale; ref *ppsm; if (!(dict_find_string(fp, "ScaleMatrix", &ppsm) > 0 && read_matrix(mem, ppsm, &prev_scale) >= 0 && gs_matrix_multiply(pmat, &prev_scale, &scale) >= 0) ) scale = *pmat; write_matrix_new(&scalemat, &scale, imem); } r_clear_attrs(&scalemat, a_write); r_set_size(&newmat, 6); write_matrix_new(&newmat, &newfont->FontMatrix, imem); r_clear_attrs(&newmat, a_write); if ((code = dict_put_string(&newdict, "FontMatrix", &newmat, NULL)) < 0 || (code = dict_put_string(&newdict, "OrigFont", pfont_dict(oldfont->base), NULL)) < 0 || (code = dict_put_string(&newdict, "ScaleMatrix", &scalemat, NULL)) < 0 || (code = add_FID(NULL, &newdict, newfont, imem)) < 0 ) return code; newfont->client_data = pdata; *pdata = *pfont_data(oldfont); pdata->dict = newdict; r_clear_attrs(dict_access_ref(&newdict), a_write); return 0; }
static DICT *dict_cdbm_open(const char *path, int dict_flags) { DICT_CDBM *dict_cdbm; char *cdb_path; char *tmp_path; int fd; struct stat st0, st1; cdb_path = concatenate(path, CDB_SUFFIX, (char *) 0); tmp_path = concatenate(path, CDB_TMP_SUFFIX, (char *) 0); /* * Repeat until we have opened *and* locked *existing* file. Since the * new (tmp) file will be renamed to be .cdb file, locking here is * somewhat funny to work around possible race conditions. Note that we * can't open a file with O_TRUNC as we can't know if another process * isn't creating it at the same time. */ for (;;) { if ((fd = open(tmp_path, O_RDWR | O_CREAT, 0644)) < 0) return (dict_surrogate(DICT_TYPE_CDB, path, O_RDWR, dict_flags, "open database %s: %m", tmp_path)); if (fstat(fd, &st0) < 0) msg_fatal("fstat(%s): %m", tmp_path); /* * Get an exclusive lock - we're going to change the database so we * can't have any spectators. */ if (myflock(fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0) msg_fatal("lock %s: %m", tmp_path); if (stat(tmp_path, &st1) < 0) msg_fatal("stat(%s): %m", tmp_path); /* * Compare file's state before and after lock: should be the same, * and nlinks should be >0, or else we opened non-existing file... */ if (st0.st_ino == st1.st_ino && st0.st_dev == st1.st_dev && st0.st_rdev == st1.st_rdev && st0.st_nlink == st1.st_nlink && st0.st_nlink > 0) break; /* successefully opened */ close(fd); } #ifndef NO_FTRUNCATE if (st0.st_size) ftruncate(fd, 0); #endif dict_cdbm = (DICT_CDBM *) dict_alloc(DICT_TYPE_CDB, path, sizeof(*dict_cdbm)); if (cdb_make_start(&dict_cdbm->cdbm, fd) < 0) msg_fatal("initialize database %s: %m", tmp_path); dict_cdbm->dict.close = dict_cdbm_close; dict_cdbm->dict.update = dict_cdbm_update; dict_cdbm->cdb_path = cdb_path; dict_cdbm->tmp_path = tmp_path; dict_cdbm->dict.owner.uid = st1.st_uid; dict_cdbm->dict.owner.status = (st1.st_uid != 0); close_on_exec(fd, CLOSE_ON_EXEC); /* * If undecided about appending a null byte to key and value, choose a * default to not append a null byte when creating a cdb. */ if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) dict_flags |= DICT_FLAG_TRY0NULL; else if ((dict_flags & DICT_FLAG_TRY1NULL) && (dict_flags & DICT_FLAG_TRY0NULL)) dict_flags &= ~DICT_FLAG_TRY0NULL; dict_cdbm->dict.flags = dict_flags | DICT_FLAG_FIXED; if (dict_flags & DICT_FLAG_FOLD_FIX) dict_cdbm->dict.fold_buf = vstring_alloc(10); return (&dict_cdbm->dict); }
DICT *dict_sockmap_open(const char *mapname, int open_flags, int dict_flags) { DICT_SOCKMAP *dp; char *saved_name = 0; char *sockmap; DICT_SOCKMAP_REFC_HANDLE *ref_handle; HTABLE_INFO *client_info; /* * Let the optimizer worry about eliminating redundant code. */ #define DICT_SOCKMAP_OPEN_RETURN(d) { \ DICT *__d = (d); \ if (saved_name != 0) \ myfree(saved_name); \ return (__d); \ } while (0) /* * Sanity checks. */ if (open_flags != O_RDONLY) DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname, open_flags, dict_flags, "%s:%s map requires O_RDONLY access mode", DICT_TYPE_SOCKMAP, mapname)); if (dict_flags & DICT_FLAG_NO_UNAUTH) DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname, open_flags, dict_flags, "%s:%s map is not allowed for security-sensitive data", DICT_TYPE_SOCKMAP, mapname)); /* * Separate the socketmap name from the socketmap server name. */ saved_name = mystrdup(mapname); if ((sockmap = split_at_right(saved_name, ':')) == 0) DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname, open_flags, dict_flags, "%s requires server:socketmap argument", DICT_TYPE_SOCKMAP)); /* * Use one reference-counted client handle for all socketmaps with the * same inet:host:port or unix:pathname information. * * XXX Todo: graceful degradation after endpoint syntax error. */ if (dict_sockmap_handles == 0) dict_sockmap_handles = htable_create(1); if ((client_info = htable_locate(dict_sockmap_handles, saved_name)) == 0) { ref_handle = (DICT_SOCKMAP_REFC_HANDLE *) mymalloc(sizeof(*ref_handle)); client_info = htable_enter(dict_sockmap_handles, saved_name, (char *) ref_handle); /* XXX Late initialization, so we can reuse macros for consistency. */ DICT_SOCKMAP_RH_REFCOUNT(client_info) = 1; DICT_SOCKMAP_RH_HANDLE(client_info) = auto_clnt_create(saved_name, dict_sockmap_timeout, dict_sockmap_max_idle, dict_sockmap_max_ttl); } else DICT_SOCKMAP_RH_REFCOUNT(client_info) += 1; /* * Instantiate a socket map handle. */ dp = (DICT_SOCKMAP *) dict_alloc(DICT_TYPE_SOCKMAP, mapname, sizeof(*dp)); dp->rdwr_buf = vstring_alloc(100); dp->sockmap_name = mystrdup(sockmap); dp->client_info = client_info; dp->dict.lookup = dict_sockmap_lookup; dp->dict.close = dict_sockmap_close; /* Don't look up parent domains or network superblocks. */ dp->dict.flags = dict_flags | DICT_FLAG_PATTERN; DICT_SOCKMAP_OPEN_RETURN(DICT_DEBUG (&dp->dict)); }
/* * Allocate a variable for a Dictionary and fill it from "*arg". * Return OK or FAIL. Returns NOTDONE for {expr}. */ int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) { dict_T *d = NULL; typval_T tvkey; typval_T tv; char_u *key = NULL; dictitem_T *item; char_u *start = skipwhite(*arg + 1); char_u buf[NUMBUFLEN]; /* * First check if it's not a curly-braces thing: {expr}. * Must do this without evaluating, otherwise a function may be called * twice. Unfortunately this means we need to call eval1() twice for the * first item. * But {} is an empty Dictionary. */ if (*start != '}') { if (eval1(&start, &tv, FALSE) == FAIL) /* recursive! */ return FAIL; if (*start == '}') return NOTDONE; } if (evaluate) { d = dict_alloc(); if (d == NULL) return FAIL; } tvkey.v_type = VAR_UNKNOWN; tv.v_type = VAR_UNKNOWN; *arg = skipwhite(*arg + 1); while (**arg != '}' && **arg != NUL) { if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */ goto failret; if (**arg != ':') { EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg); clear_tv(&tvkey); goto failret; } if (evaluate) { key = get_tv_string_buf_chk(&tvkey, buf); if (key == NULL) { /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */ clear_tv(&tvkey); goto failret; } } *arg = skipwhite(*arg + 1); if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */ { if (evaluate) clear_tv(&tvkey); goto failret; } if (evaluate) { item = dict_find(d, key, -1); if (item != NULL) { EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key); clear_tv(&tvkey); clear_tv(&tv); goto failret; } item = dictitem_alloc(key); clear_tv(&tvkey); if (item != NULL) { item->di_tv = tv; item->di_tv.v_lock = 0; if (dict_add(d, item) == FAIL) dictitem_free(item); } } if (**arg == '}') break; if (**arg != ',') { EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg); goto failret; } *arg = skipwhite(*arg + 1); } if (**arg != '}') { EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg); failret: if (evaluate) dict_free(d); return FAIL; } *arg = skipwhite(*arg + 1); if (evaluate) { rettv->v_type = VAR_DICT; rettv->vval.v_dict = d; ++d->dv_refcount; } return OK; }
DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags) { DICT_PCRE *dict_pcre; VSTREAM *map_fp; struct stat st; VSTRING *line_buffer; DICT_PCRE_RULE *last_rule = 0; DICT_PCRE_RULE *rule; int lineno = 0; int nesting = 0; char *p; /* * Sanity checks. */ if (open_flags != O_RDONLY) return (dict_surrogate(DICT_TYPE_PCRE, mapname, open_flags, dict_flags, "%s:%s map requires O_RDONLY access mode", DICT_TYPE_PCRE, mapname)); /* * Open the configuration file. */ if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0) return (dict_surrogate(DICT_TYPE_PCRE, mapname, open_flags, dict_flags, "open %s: %m", mapname)); if (fstat(vstream_fileno(map_fp), &st) < 0) msg_fatal("fstat %s: %m", mapname); line_buffer = vstring_alloc(100); dict_pcre = (DICT_PCRE *) dict_alloc(DICT_TYPE_PCRE, mapname, sizeof(*dict_pcre)); dict_pcre->dict.lookup = dict_pcre_lookup; dict_pcre->dict.close = dict_pcre_close; dict_pcre->dict.flags = dict_flags | DICT_FLAG_PATTERN; if (dict_flags & DICT_FLAG_FOLD_MUL) dict_pcre->dict.fold_buf = vstring_alloc(10); dict_pcre->head = 0; dict_pcre->expansion_buf = 0; if (dict_pcre_init == 0) { pcre_malloc = (void *(*) (size_t)) mymalloc; pcre_free = (void (*) (void *)) myfree; dict_pcre_init = 1; } dict_pcre->dict.owner.uid = st.st_uid; dict_pcre->dict.owner.status = (st.st_uid != 0); /* * Parse the pcre table. */ while (readlline(line_buffer, map_fp, &lineno)) { p = vstring_str(line_buffer); trimblanks(p, 0)[0] = 0; /* Trim space at end */ if (*p == 0) continue; rule = dict_pcre_parse_rule(mapname, lineno, p, nesting, dict_flags); if (rule == 0) continue; if (rule->op == DICT_PCRE_OP_IF) { nesting++; } else if (rule->op == DICT_PCRE_OP_ENDIF) { nesting--; } if (last_rule == 0) dict_pcre->head = rule; else last_rule->next = rule; last_rule = rule; } if (nesting) msg_warn("pcre map %s, line %d: more IFs than ENDIFs", mapname, lineno); vstring_free(line_buffer); vstream_fclose(map_fp); return (DICT_DEBUG (&dict_pcre->dict)); }
int megahal_keywords(brain_t brain, const list_t *words, dict_t **keywords) { dict_t *keywords_p; uint_fast32_t i; uint32_t size; int ret; WARN_IF(words == NULL); WARN_IF(keywords == NULL); *keywords = dict_alloc(); if (*keywords == NULL) return -ENOMEM; keywords_p = *keywords; ret = list_size(words, &size); if (ret) return ret; for (i = 0; i < size; i++) { word_t word; ret = list_get(words, i, &word); if (ret) return ret; ret = db_map_get(brain, MAP_SWAP, word, &word); if (ret != OK && ret != -ENOTFOUND) return ret; ret = db_list_contains(brain, LIST_BAN, word); if (ret == OK) continue; if (ret != -ENOTFOUND) return ret; ret = db_list_contains(brain, LIST_AUX, word); if (ret == OK) continue; if (ret != -ENOTFOUND) return ret; ret = db_model_contains(brain, word); if (ret == -ENOTFOUND) continue; if (ret != OK) return ret; ret = add_keyword(keywords_p, word); if (ret) return ret; } ret = dict_size(keywords_p, &size); if (ret) return ret; if (size == 0) return OK; ret = list_size(words, &size); if (ret) return ret; for (i = 0; i < size; i++) { word_t word; ret = list_get(words, i, &word); if (ret) return ret; ret = db_map_get(brain, MAP_SWAP, word, &word); if (ret != OK && ret != -ENOTFOUND) return ret; ret = db_list_contains(brain, LIST_AUX, word); if (ret == -ENOTFOUND) continue; if (ret != OK) return ret; ret = db_model_contains(brain, word); if (ret == -ENOTFOUND) continue; if (ret != OK) return ret; ret = add_keyword(keywords_p, word); if (ret) return ret; } return OK; }
DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags) { char *myname = "dict_ldap_open"; DICT_LDAP *dict_ldap; VSTRING *url_list; char *s; char *h; char *server_host; char *domainlist; char *scope; char *attr; int tmp; if (msg_verbose) msg_info("%s: Using LDAP source %s", myname, ldapsource); dict_ldap = (DICT_LDAP *) dict_alloc(DICT_TYPE_LDAP, ldapsource, sizeof(*dict_ldap)); dict_ldap->dict.lookup = dict_ldap_lookup; dict_ldap->dict.close = dict_ldap_close; dict_ldap->dict.flags = dict_flags | DICT_FLAG_FIXED; dict_ldap->ld = NULL; dict_ldap->parser = cfg_parser_alloc(ldapsource); dict_ldap->ldapsource = mystrdup(ldapsource); server_host = cfg_get_str(dict_ldap->parser, "server_host", "localhost", 1, 0); /* * get configured value of "server_port"; default to LDAP_PORT (389) */ dict_ldap->server_port = cfg_get_int(dict_ldap->parser, "server_port", LDAP_PORT, 0, 0); /* * Define LDAP Version. */ dict_ldap->version = cfg_get_int(dict_ldap->parser, "version", 2, 2, 0); switch (dict_ldap->version) { case 2: dict_ldap->version = LDAP_VERSION2; break; case 3: dict_ldap->version = LDAP_VERSION3; break; default: msg_warn("%s: %s Unknown version %d.", myname, ldapsource, dict_ldap->version); dict_ldap->version = LDAP_VERSION2; } #if defined(LDAP_API_FEATURE_X_OPENLDAP) dict_ldap->ldap_ssl = 0; #endif url_list = vstring_alloc(32); s = server_host; while ((h = mystrtok(&s, " \t\n\r,")) != NULL) { #if defined(LDAP_API_FEATURE_X_OPENLDAP) /* * Convert (host, port) pairs to LDAP URLs */ if (ldap_is_ldap_url(h)) { LDAPURLDesc *url_desc; int rc; if ((rc = ldap_url_parse(h, &url_desc)) != 0) { msg_error("%s: error parsing URL %s: %d: %s; skipping", myname, h, rc, ldap_err2string(rc)); continue; } if (strcasecmp(url_desc->lud_scheme, "ldap") != 0 && dict_ldap->version != LDAP_VERSION3) { msg_warn("%s: URL scheme %s requires protocol version 3", myname, url_desc->lud_scheme); dict_ldap->version = LDAP_VERSION3; } if (strcasecmp(url_desc->lud_scheme, "ldaps") == 0) dict_ldap->ldap_ssl = 1; ldap_free_urldesc(url_desc); vstring_sprintf_append(url_list, " %s", h); } else { if (strrchr(h, ':')) vstring_sprintf_append(url_list, " ldap://%s", h); else vstring_sprintf_append(url_list, " ldap://%s:%d", h, dict_ldap->server_port); } #else vstring_sprintf_append(url_list, " %s", h); #endif } dict_ldap->server_host = mystrdup(VSTRING_LEN(url_list) > 0 ? vstring_str(url_list) + 1 : ""); #if defined(LDAP_API_FEATURE_X_OPENLDAP) /* * With URL scheme, clear port to normalize connection cache key */ dict_ldap->server_port = LDAP_PORT; if (msg_verbose) msg_info("%s: %s server_host URL is %s", myname, ldapsource, dict_ldap->server_host); #endif myfree(server_host); vstring_free(url_list); /* * Scope handling thanks to Carsten Hoeger of SuSE. */ scope = cfg_get_str(dict_ldap->parser, "scope", "sub", 1, 0); if (strcasecmp(scope, "one") == 0) { dict_ldap->scope = LDAP_SCOPE_ONELEVEL; } else if (strcasecmp(scope, "base") == 0) { dict_ldap->scope = LDAP_SCOPE_BASE; } else if (strcasecmp(scope, "sub") == 0) { dict_ldap->scope = LDAP_SCOPE_SUBTREE; } else { msg_warn("%s: %s: Unrecognized value %s specified for scope; using sub", myname, ldapsource, scope); dict_ldap->scope = LDAP_SCOPE_SUBTREE; } myfree(scope); dict_ldap->search_base = cfg_get_str(dict_ldap->parser, "search_base", "", 0, 0); domainlist = cfg_get_str(dict_ldap->parser, "domain", "", 0, 0); if (*domainlist) { #ifdef MATCH_FLAG_NONE dict_ldap->domain = match_list_init(MATCH_FLAG_NONE, domainlist, 1, match_string); #else dict_ldap->domain = match_list_init(domainlist, 1, match_string); #endif if (dict_ldap->domain == NULL) msg_warn("%s: domain match list creation using \"%s\" failed, will continue without it", myname, domainlist); if (msg_verbose) msg_info("%s: domain list created using \"%s\"", myname, domainlist); } else { dict_ldap->domain = NULL; } myfree(domainlist); /* * get configured value of "timeout"; default to 10 seconds * * Thanks to Manuel Guesdon for spotting that this wasn't really getting * set. */ dict_ldap->timeout = cfg_get_int(dict_ldap->parser, "timeout", 10, 0, 0); dict_ldap->query_filter = cfg_get_str(dict_ldap->parser, "query_filter", "(mailacceptinggeneralid=%s)", 0, 0); dict_ldap->result_filter = cfg_get_str(dict_ldap->parser, "result_filter", "%s", 0, 0); if (strcmp(dict_ldap->result_filter, "%s") == 0) { myfree(dict_ldap->result_filter); dict_ldap->result_filter = NULL; } attr = cfg_get_str(dict_ldap->parser, "result_attribute", "maildrop", 0, 0); dict_ldap->result_attributes = argv_split(attr, " ,\t\r\n"); dict_ldap->num_attributes = dict_ldap->result_attributes->argc; myfree(attr); attr = cfg_get_str(dict_ldap->parser, "special_result_attribute", "", 0, 0); if (*attr) { argv_split_append(dict_ldap->result_attributes, attr, " ,\t\r\n"); } myfree(attr); /* * get configured value of "bind"; default to true */ dict_ldap->bind = cfg_get_bool(dict_ldap->parser, "bind", 1); /* * get configured value of "bind_dn"; default to "" */ dict_ldap->bind_dn = cfg_get_str(dict_ldap->parser, "bind_dn", "", 0, 0); /* * get configured value of "bind_pw"; default to "" */ dict_ldap->bind_pw = cfg_get_str(dict_ldap->parser, "bind_pw", "", 0, 0); /* * get configured value of "cache"; default to false */ tmp = cfg_get_bool(dict_ldap->parser, "cache", 0); if (tmp) msg_warn("%s: %s ignoring cache", myname, ldapsource); /* * get configured value of "cache_expiry"; default to 30 seconds */ tmp = cfg_get_int(dict_ldap->parser, "cache_expiry", -1, 0, 0); if (tmp >= 0) msg_warn("%s: %s ignoring cache_expiry", myname, ldapsource); /* * get configured value of "cache_size"; default to 32k */ tmp = cfg_get_int(dict_ldap->parser, "cache_size", -1, 0, 0); if (tmp >= 0) msg_warn("%s: %s ignoring cache_size", myname, ldapsource); /* * get configured value of "recursion_limit"; default to 1000 */ dict_ldap->recursion_limit = cfg_get_int(dict_ldap->parser, "recursion_limit", 1000, 1, 0); /* * get configured value of "expansion_limit"; default to 0 */ dict_ldap->expansion_limit = cfg_get_int(dict_ldap->parser, "expansion_limit", 0, 0, 0); /* * get configured value of "size_limit"; default to expansion_limit */ dict_ldap->size_limit = cfg_get_int(dict_ldap->parser, "size_limit", dict_ldap->expansion_limit, 0, 0); /* * Alias dereferencing suggested by Mike Mattice. */ dict_ldap->dereference = cfg_get_int(dict_ldap->parser, "dereference", 0, 0, 0); if (dict_ldap->dereference < 0 || dict_ldap->dereference > 3) { msg_warn("%s: %s Unrecognized value %d specified for dereference; using 0", myname, ldapsource, dict_ldap->dereference); dict_ldap->dereference = 0; } /* Referral chasing */ dict_ldap->chase_referrals = cfg_get_bool(dict_ldap->parser, "chase_referrals", 0); #ifdef LDAP_API_FEATURE_X_OPENLDAP /* * TLS options */ /* get configured value of "start_tls"; default to no */ dict_ldap->start_tls = cfg_get_bool(dict_ldap->parser, "start_tls", 0); if (dict_ldap->start_tls && dict_ldap->version < LDAP_VERSION3) { msg_warn("%s: %s start_tls requires protocol version 3", myname, ldapsource); dict_ldap->version = LDAP_VERSION3; } /* get configured value of "tls_require_cert"; default to no */ dict_ldap->tls_require_cert = cfg_get_bool(dict_ldap->parser, "tls_require_cert", 0); /* get configured value of "tls_ca_cert_file"; default "" */ dict_ldap->tls_ca_cert_file = cfg_get_str(dict_ldap->parser, "tls_ca_cert_file", "", 0, 0); /* get configured value of "tls_ca_cert_dir"; default "" */ dict_ldap->tls_ca_cert_dir = cfg_get_str(dict_ldap->parser, "tls_ca_cert_dir", "", 0, 0); /* get configured value of "tls_cert"; default "" */ dict_ldap->tls_cert = cfg_get_str(dict_ldap->parser, "tls_cert", "", 0, 0); /* get configured value of "tls_key"; default "" */ dict_ldap->tls_key = cfg_get_str(dict_ldap->parser, "tls_key", "", 0, 0); /* get configured value of "tls_random_file"; default "" */ dict_ldap->tls_random_file = cfg_get_str(dict_ldap->parser, "tls_random_file", "", 0, 0); /* get configured value of "tls_cipher_suite"; default "" */ dict_ldap->tls_cipher_suite = cfg_get_str(dict_ldap->parser, "tls_cipher_suite", "", 0, 0); #endif /* * Debug level. */ #if defined(LDAP_OPT_DEBUG_LEVEL) && defined(LBER_OPT_LOG_PRINT_FN) dict_ldap->debuglevel = cfg_get_int(dict_ldap->parser, "debuglevel", 0, 0, 0); #endif /* * Find or allocate shared LDAP connection container. */ dict_ldap_conn_find(dict_ldap); /* * Return the new dict_ldap structure. */ return (DICT_DEBUG (&dict_ldap->dict)); }