/* 7.1 */ const SWmlNode * lookupElement(SDocData *data) { /* 1. Pick up the name of the current element from event list. * 2. Look into table of tags/elements of SWmlDescriptor for it. * 3. Return the corresponding node, or the node of the unknown element. * * Note: The value of the current XML event must exits. * Assume the calling takes place from the proper context. *--------------------------------------------------------------------------- */ /* Data Structures */ PString _str; /* name of the element */ unsigned _idx; /* the index of element in the table */ const SWmlNode * _node; /* traverses the list */ /* Code */ _str = data->m_eventList.m_head->m_tokenValue; _idx = (!STR_LEN(_str)) ? 0 : (*STR_DATA(_str))&0x7f; _node = FIRST_NODE(data->m_desc->m_elements[_idx]); while(_node && !STR_SAME(_node->m_name, _str)) _node = _node->m_next; return _node ? _node : g_unknownElement; }
void master_config(void) { MASTER_SERV *entry; MASTER_SERV *serv; #define STR_DIFF strcmp #define STR_SAME !strcmp #define SWAP(type,a,b) { type temp = a; a = b; b = temp; } /* * A service is identified by its endpoint name AND by its transport * type, not just by its name alone. The name is unique within its * transport type. XXX Service privacy is encoded in the service name. */ set_master_ent(); while ((entry = get_master_ent()) != 0) { if (msg_verbose) print_master_ent(entry); for (serv = master_head; serv != 0; serv = serv->next) if (STR_SAME(serv->name, entry->name) && serv->type == entry->type) break; /* * Add a new service entry. We do not really care in what order the * service entries are kept in memory. */ if (serv == 0) { entry->next = master_head; master_head = entry; master_start_service(entry); } /* * Update an existing service entry. Make the current generation of * child processes commit suicide whenever it is convenient. The next * generation of child processes will run with the new configuration * settings. */ else { serv->flags &= ~MASTER_FLAG_MARK; if (entry->flags & MASTER_FLAG_CONDWAKE) serv->flags |= MASTER_FLAG_CONDWAKE; else serv->flags &= ~MASTER_FLAG_CONDWAKE; serv->wakeup_time = entry->wakeup_time; serv->max_proc = entry->max_proc; serv->throttle_delay = entry->throttle_delay; SWAP(char *, serv->ext_name, entry->ext_name); SWAP(char *, serv->path, entry->path); SWAP(ARGV *, serv->args, entry->args); SWAP(char *, serv->stress_param_val, entry->stress_param_val); master_restart_service(serv, DO_CONF_RELOAD); free_master_ent(entry); } } end_master_ent(); }
/* 7.2 */ const SWmlNode * lookupAttr(SDocData *data, const SWmlNode *element) { /* 1. Pick up the name of the current current attribute from event list. * 2. If the 'element' had that attribute: return it. * 3. If the attribute was found in the table of attributes of the * SWmlDescriptor: return it. * 4. Otherwise return the 'unknown' attribute. * * Note: The value of the current XML event must exits. * Assume the calling takes place from the proper context. *--------------------------------------------------------------------------- */ /* Data Structures */ PString _str = data->m_eventList.m_head->m_tokenValue; const SWmlNode * _node = FIRST_NODE(element->m_children); unsigned _idx; /* Code */ DBG_LOG2( (DBG_WML, _str, "lookupAttr:") ); while(_node && !STR_SAME(_node->m_name, _str)) { DBG_LOG2( (DBG_WML, _node->m_name, " ?:") ); _node = _node->m_next; } if(!_node) { /* global attributes */ _idx = (!STR_LEN(_str)) ? 0 : (*STR_DATA(_str))&0x7f; _node = FIRST_NODE(data->m_desc->m_attributes[_idx]); while(_node && !STR_SAME(_node->m_name, _str)) _node = _node->m_next; } DBG_LOG( (DBG_WML, "lookupAttr: found: %p",_node ) ); return _node ? _node : g_unknownAttribute; }
/* 7.3 */ SWmlString * lookupString(SDocData *data, PString str) { /* Search for 'str' in 'stringTable' of DocData. * Return the node or NULL. *--------------------------------------------------------------------------- */ /* Data Structures */ unsigned _idx = (!STR_LEN(str)) ? 0 : (*STR_DATA(str))&0x7f; SWmlString * _node = FIRST_NODE(data->m_stringTable[_idx]); /* Code */ while(_node && !STR_SAME(_node->m_string, str)) _node = _node->m_next; return _node; }
MASTER_SERV *get_master_ent() { VSTRING *buf = vstring_alloc(100); VSTRING *junk = vstring_alloc(100); MASTER_SERV *serv; char *cp; char *name; char *host = 0; char *port = 0; char *transport; int private; int unprivileged; /* passed on to child */ int chroot; /* passed on to child */ char *command; int n; char *bufp; char *atmp; const char *parse_err; static char *saved_interfaces = 0; char *err; if (master_fp == 0) msg_panic("get_master_ent: config file not open"); if (master_disable == 0) msg_panic("get_master_ent: no service disable list"); /* * XXX We cannot change the inet_interfaces setting for a running master * process. Listening sockets are inherited by child processes so that * closing and reopening those sockets in the master does not work. * * Another problem is that library routines still cache results that are * based on the old inet_interfaces setting. It is too much trouble to * recompute everything. * * In order to keep our data structures consistent we ignore changes in * inet_interfaces settings, and issue a warning instead. */ if (saved_interfaces == 0) saved_interfaces = mystrdup(var_inet_interfaces); /* * Skip blank lines and comment lines. */ for (;;) { if (readllines(buf, master_fp, &master_line_last, &master_line) == 0) { vstring_free(buf); vstring_free(junk); return (0); } bufp = vstring_str(buf); if ((cp = mystrtok(&bufp, master_blanks)) == 0) continue; name = cp; transport = get_str_ent(&bufp, "transport type", (char *) 0); vstring_sprintf(junk, "%s/%s", name, transport); if (match_service_match(master_disable, vstring_str(junk)) == 0) break; } /* * Parse one logical line from the configuration file. Initialize service * structure members in order. */ serv = (MASTER_SERV *) mymalloc(sizeof(MASTER_SERV)); serv->next = 0; /* * Flags member. */ serv->flags = 0; /* * All servers busy warning timer. */ serv->busy_warn_time = 0; /* * Service name. Syntax is transport-specific. */ serv->ext_name = mystrdup(name); /* * Transport type: inet (wild-card listen or virtual) or unix. */ #define STR_SAME !strcmp if (STR_SAME(transport, MASTER_XPORT_NAME_INET)) { if (!STR_SAME(saved_interfaces, var_inet_interfaces)) { msg_warn("service %s: ignoring %s change", serv->ext_name, VAR_INET_INTERFACES); msg_warn("to change %s, stop and start Postfix", VAR_INET_INTERFACES); } serv->type = MASTER_SERV_TYPE_INET; atmp = mystrdup(name); if ((parse_err = host_port(atmp, &host, "", &port, (char *) 0)) != 0) fatal_with_context("%s in \"%s\"", parse_err, name); if (*host) { serv->flags |= MASTER_FLAG_INETHOST;/* host:port */ MASTER_INET_ADDRLIST(serv) = (INET_ADDR_LIST *) mymalloc(sizeof(*MASTER_INET_ADDRLIST(serv))); inet_addr_list_init(MASTER_INET_ADDRLIST(serv)); if (inet_addr_host(MASTER_INET_ADDRLIST(serv), host) == 0) fatal_with_context("bad hostname or network address: %s", name); inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv)); serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used; } else { MASTER_INET_ADDRLIST(serv) = strcasecmp(saved_interfaces, INET_INTERFACES_ALL) ? own_inet_addr_list() : /* virtual */ wildcard_inet_addr_list(); /* wild-card */ inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv)); serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used; } MASTER_INET_PORT(serv) = mystrdup(port); for (n = 0; /* see below */ ; n++) { if (n >= MASTER_INET_ADDRLIST(serv)->used) { serv->flags |= MASTER_FLAG_LOCAL_ONLY; break; } if (!sock_addr_in_loopback(SOCK_ADDR_PTR(MASTER_INET_ADDRLIST(serv)->addrs + n))) break; } } else if (STR_SAME(transport, MASTER_XPORT_NAME_UNIX)) { serv->type = MASTER_SERV_TYPE_UNIX; serv->listen_fd_count = 1; serv->flags |= MASTER_FLAG_LOCAL_ONLY; } else if (STR_SAME(transport, MASTER_XPORT_NAME_UXDG)) { serv->type = MASTER_SERV_TYPE_UXDG; serv->listen_fd_count = 1; serv->flags |= MASTER_FLAG_LOCAL_ONLY; } else if (STR_SAME(transport, MASTER_XPORT_NAME_FIFO)) { serv->type = MASTER_SERV_TYPE_FIFO; serv->listen_fd_count = 1; serv->flags |= MASTER_FLAG_LOCAL_ONLY; #ifdef MASTER_SERV_TYPE_PASS } else if (STR_SAME(transport, MASTER_XPORT_NAME_PASS)) { serv->type = MASTER_SERV_TYPE_PASS; serv->listen_fd_count = 1; /* If this is a connection screener, remote clients are likely. */ #endif } else { fatal_with_context("bad transport type: %s", transport); } /* * Service class: public or private. */ private = get_bool_ent(&bufp, "private", "y");