• Patch: Elm ME+ 2.5 PLalpha46 -> Elm ME+ 2.5 PLalpha47 [5/7] (4/7)

    From Kari Hurtta@21:1/5 to All on Sat Feb 10 14:46:35 2018
    [continued from previous message]

    + }
    +
    + qitem->valid_answer = 1;
    +
    + if (qitem->cache_answer_in) {
    + int have_error = 0;
    +
    + qitem->cache_answer_ret =
    + fill_resolv_cache(qitem->cache_answer_in,
    + &(qitem->answer_buffer->parsed_message),
    + &(qitem->query_time),
    + &(qitem->answer_search_name), + &(qitem->looking_up),
    + &have_error);
    +
    + if (have_error) {
    + DPRINT(Debug,14,(&Debug,
    + "process_answer: [pid %d] %lu %s: fill_resolv_cache have error\n",
    + pid,
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>"));
    + qitem->fill_have_error = 1;
    + }
    +
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "process_answer: [pid %d] %lu %s: no answer record for fill_resolv_cache\n",
    + pid,
    + (unsigned long)(qitem->querynum), + qitem->name ? qitem->name : "<NO NAME>"));
    + qitem->fill_have_error = 1;
    + }
    +
    + } else
    + qitem->failed_answer = 1;
    +
    + } else {
    + DPRINT(Debug,14,(&Debug, "process_answer: [pid %d] %lu %s: will not store answer\n",
    + pid,
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>")); + qitem->invalid_answer = 1;
    + }
    +
    + if (refname) {
    + DPRINT(Debug,14,(&Debug, "process_answer: [pid %d] %lu %s: query name %s\n",
    + pid,
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>",
    + refname));
    + free(refname);
    + refname = NULL;
    + }
    +
    + } else {
    + DPRINT(Debug,14,(&Debug, "process_answer: [pid %d] %lu %s: query not stored\n",
    + pid,
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>"));
    +
    + qitem->invalid_answer = 1;
    + }
    +
    + if (!ok) {
    + DPRINT(Debug,14,(&Debug, "process_answer: [pid %d] %lu %s: clearing answer\n",
    + pid,
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>"));
    +
    + qitem->answer_buffer->message_len = 0;
    + qitem->answer_buffer->message_parsed = 0;
    +
    + if (qitem->answer_hdr)
    + *(qitem->answer_hdr) = NULL_resolv_query_hdr;
    +
    + /* bzero is defined on hdrs/defs.h */
    + if (qitem->answer_buffer->message && qitem->answer_buffer->message_size)
    + bzero(qitem->answer_buffer->message,qitem->answer_buffer->message_size);
    + }
    +
    +
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "process_answer: [pid %d] %lu %s: no answer buffer\n",
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>"));
    + qitem->invalid_answer = 1;
    + }
    + } else {
    + DPRINT(Debug,14,(&Debug, "process_answer: [pid %d] no query item\n",
    + pid));
    +
    + }
    + }
    +
    + S_(free_action_data_f resolv_free_state)
    + static void resolv_free_state P_((union action_routine_data * data));
    + static void resolv_free_state(data)
    + union action_routine_data * data;
    + {
    + free_resolv_message_state(&(data->resolv));
    + }
    +
    + S_(inc_action_data_refcount_f resolv_inc_state_refcount)
    + static void resolv_inc_state_refcount P_((union action_routine_data data));
    + static void resolv_inc_state_refcount(data)
    + union action_routine_data data;
    + {
    + inc_resolv_message_state_refcount(data.resolv);
    + }
    +
    +
    + S_(action_routine resolv_read_message)
    + enum action_status resolv_read_message P_((int fd,
    + union action_routine_data data,
    + const struct schedule_timelimit * now));
    + enum action_status resolv_read_message(fd,data,now)
    + int fd;
    + union action_routine_data data;
    + const struct schedule_timelimit * now;
    + {
    + struct resolv_message_state * state = data.resolv;
    + int pid = getpid();
    + int err = 0;
    + enum action_status st = action_continue;
    +
    + enum read_status rs;
    +
    + DPRINT(Debug,14,(&Debug, "resolv_read_message: [pid %d] socket %d readable\n",
    + pid,fd));
    +
    + if (RESOLV_MESSAGE_STATE_magic != state->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,"resolv_read_message",
    + "Bad magic number (resolv_message_state)",0);
    +
    + rs = read_message(fd,
    + &(state->read_hdr),
    + state->read_buffer,
    + state->read_buffer_size,
    + &(state->read_buffer_len),
    + &err,pid,
    + &(state->read_pos));
    +
    + DPRINT(Debug,14,(&Debug, "resolv_read_message: [pid %d] fd %d: got %d",
    + pid,fd,rs));
    + switch(rs) {
    + case rs_read_error: SIGDPRINT(Debug,14,(&Debug, " (read error, error=%d) ",err));
    + if (err != EINTR && err != EAGAIN && err != EWOULDBLOCK)
    + st = action_disable;
    + break;
    + case rs_parse_error: SIGDPRINT(Debug,14,(&Debug, " (parse error) ")); break;
    + case rs_EOF: SIGDPRINT(Debug,14,(&Debug, " (EOF) "));
    + if (! state->broken_pipe) {
    + SIGDPRINT(Debug,14,(&Debug, ", marking broken pipe"));
    + state->broken_pipe = 1; /* Writing will cause EPIPE error */
    + }
    + st = action_disable;
    + break;
    + case rs_none: SIGDPRINT(Debug,14,(&Debug, " (none) ")); break;
    + case rs_got_message: SIGDPRINT(Debug,14,(&Debug, " (got message) ")); break;
    + case rs_incomplete: SIGDPRINT(Debug,14,(&Debug, " (incomplete) ")); break;
    + case rs_continue: SIGDPRINT(Debug,14,(&Debug, " (continue) ")); break;
    + }
    + SIGDPRINT(Debug,14,(&Debug, "\n"));
    +
    + if (state->query_in_progress) {
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: resetting 'query in progress' (querynum %lu)\n",
    + pid,fd,(unsigned long)(state->querynum)));
    + state->query_in_progress = 0;
    + }
    +
    + if (rs_got_message == rs) {
    + struct resolv_query_hdr * hdr = &(state->read_hdr);
    + struct resolv_process * proc = NULL;
    + struct resolv_query_item * qitem = NULL;
    +
    + DPRINT(Debug,14,(&Debug, "resolv_read_message: [pid %d] fd %d: got message %d",
    + pid,fd,hdr->msg));
    + switch(hdr->msg) {
    + case qm_none: SIGDPRINT(Debug,14,(&Debug, " (none)")); break;
    + case qm_query: SIGDPRINT(Debug,14,(&Debug, " (query)")); break;
    + case qm_answer: SIGDPRINT(Debug,14,(&Debug, " (answer)")); break;
    + case qm_res_send_fail: SIGDPRINT(Debug,14,(&Debug, " (res_send fail)")); break;
    + case qm_running: SIGDPRINT(Debug,14,(&Debug, " (running)")); break;
    + case qm_shutdown: SIGDPRINT(Debug,14,(&Debug, " (shutdown)")); break;
    + case qm_sizeupdate: SIGDPRINT(Debug,14,(&Debug, " (sizeupdate)")); break;
    + }
    + if (hdr->senderpid > 0) {
    + size_t i;
    +
    + SIGDPRINT(Debug,14,(&Debug, ", sender pid %d",hdr->senderpid));
    +
    + for (i = 0; i < process_list_len; i++) {
    + if (process_list[i]) {
    + if (RESOLV_PROCESS_magic != process_list[i]->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,"resolv_read_message",
    + "Bad magic number (resolv_process)",0);
    +
    + if (hdr->senderpid == process_list[i]->pid) {
    + SIGDPRINT(Debug,14,(&Debug, "; found #%lu: state=%d",
    + (unsigned long)i,
    + process_list[i]->state));
    +
    + switch(process_list[i]->state) {
    + case ps_none: SIGDPRINT(Debug,14,(&Debug, " (none) ")); break;
    + case ps_forked: SIGDPRINT(Debug,14,(&Debug, " (forked) ")); break;
    + case ps_running: SIGDPRINT(Debug,14,(&Debug, " (running) ")); break;
    + case ps_shutdown: SIGDPRINT(Debug,14,(&Debug, " (shutdown)")); break;
    + case ps_exited: SIGDPRINT(Debug,14,(&Debug, " (exited) ")); break;
    + case ps_died: SIGDPRINT(Debug,14,(&Debug, " (died) ")); break;
    + }
    +
    + if (state == process_list[i]->message) {
    + proc = process_list[i];
    + break;
    +
    + } else {
    + SIGDPRINT(Debug,14,(&Debug, " <- not current"));
    + }
    + }
    + }
    + }
    + }
    +
    + if (hdr->querynum > 0) {
    + SIGDPRINT(Debug,14,(&Debug, ", querynum=%lu", (unsigned long)(hdr->querynum)));
    +
    + if (hdr->querynum < query_list_len &&
    + query_list[hdr->querynum]) {
    +
    + if (RESOLV_QUERY_ITEM_magic != query_list[hdr->querynum]->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,"resolv_read_message",
    + "Bad magic number (resolv_query_item)",0);
    + qitem = query_list[hdr->querynum];
    + } else {
    + SIGDPRINT(Debug,14,(&Debug, " (invalid)"));
    + }
    + }
    + SIGDPRINT(Debug,14,(&Debug, "\n"));
    +
    + switch(hdr->msg) {
    + union resolv_sizeupdate_p size_update;
    +
    + case qm_none: break;
    + case qm_query: break;
    + case qm_answer:
    + if (state->read_buffer_len) {
    + process_answer(pid,
    + hdr,
    + state->read_buffer,
    + state->read_buffer_len,
    + qitem);
    + } else if (qitem) {
    + DPRINT(Debug,14,(&Debug, "process_answer: [pid %d] %lu %s: no answer",
    + pid,
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>"));
    +
    + if (hdr->errno_val) {
    + DPRINT(Debug,14,(&Debug,"copying error %d (%s)",
    + hdr->errno_val,strerror(hdr->errno_val))); + qitem->last_errno = hdr->errno_val;
    + }
    + DPRINT(Debug,14,(&Debug,"\n"));
    +
    + qitem->invalid_answer = 1;
    + }
    +
    + break;
    +
    + case qm_res_send_fail:
    + if (qitem) {
    + int have_already_answer = 1;
    +
    + if (qitem->answer_hdr) {
    + if (RESOLV_QUERY_HDR_magic != qitem->answer_hdr->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,
    + "resolv_read_message",
    + "Bad magic number ( resolv_query_hdr)",0);
    +
    + if (qm_none != qitem->answer_hdr->msg) {
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: lu% %s: have already valid answer header\n",
    + pid,fd,
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>"));
    + } else
    + have_already_answer = 0;
    +
    +
    + } else
    + have_already_answer = 0;
    +
    + if (qitem->answer_buffer) {
    + if (RESOLV_MESSAGE_magic != qitem->answer_buffer->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,
    + "resolv_read_message",
    + "Bad magic number (resolv_message)",0);
    +
    + if (qitem->answer_buffer->message &&
    + qitem->answer_buffer->message_len &&
    + qitem->answer_buffer->message_parsed) {
    +
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: %lu %s: have already valid answer message\n",
    + pid,fd,
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>"));
    +
    + } else
    + have_already_answer = 0;
    +
    + } else
    + have_already_answer = 0;
    +
    +
    + if (have_already_answer &&
    + qitem->valid_answer) {
    +
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: lu% %s: ignoring res_send failing, seems already got valid answer\n",
    + pid,fd,
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>")); + } else {
    + /* Store error message */
    +
    + qitem->failed_answer = 1;
    +
    + if (!qitem->answer_hdr)
    + qitem->answer_hdr = safe_malloc(sizeof (* (qitem->answer_hdr)));
    + * (qitem->answer_hdr) = *hdr;
    +
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: %lu %s: res_send failed\n",
    + pid,fd,
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>")); + }
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: res_send failed, no query item\n",
    + pid,fd));
    +
    + }
    + break;
    +
    + case qm_running:
    +
    + if (proc) {
    + if (ps_forked == proc->state) {
    +
    + proc->state = ps_running;
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: marking pid %d running\n",
    + pid,fd,proc->pid));
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: pid %d have unexpected state %d (got running)\n",
    + pid,fd,proc->pid,proc->state));
    + }
    + }
    + break;
    +
    + case qm_shutdown:
    + if (proc) {
    + if (ps_forked == proc->state ||
    + ps_running == proc->state) {
    + proc->state = ps_shutdown;
    +
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: marking pid %d shutdown\n",
    + pid,fd,proc->pid));
    + } else if (ps_exited == proc->state) {
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: pid %d already exited (got shutdown)\n",
    + pid,fd,proc->pid));
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: pid %d have unexpected state %d (got shutdown)\n",
    + pid,fd,proc->pid,proc->state));
    + }
    + }
    +
    + if (qitem) {
    + DPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: lu% %s: query got shutdown?\n",
    + pid,fd,
    + (unsigned long)(qitem->querynum),
    + qitem->name ? qitem->name : "<NO NAME>"));
    + qitem->shutdown = 1;
    + }
    +
    + break;
    + case qm_sizeupdate:
    + size_update.buffer = state->read_buffer;
    +
    + if (state->read_buffer_len == sizeof (struct resolv_sizeupdate) && + RESOLV_SIZEUPDATE_magic == size_update.update->magic) {
    +
    + if (size_update.update->querysize >= sizeof (struct resolv_sizeupdate)) {
    +
    + if (state->write_prepared &&
    + size_update.update->querysize < state->write_buffer_len) {
    + SIGDPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: Ignoring querysize %lu => %d (write buffer size) -- write buffer len = %lu\n",
    + pid,fd,(unsigned long)(state->write_buffer_size),
    + size_update.update->querysize,
    + (unsigned long)(state->write_buffer_len)));
    +
    + } else if (size_update.update->querysize != state->write_buffer_size) {
    + SIGDPRINT(Debug,14,(&Debug,
    + "resolv_read_message: [pid %d] fd %d: Changing querysize %lu => %d (write buffer size)\n",
    + pid,fd,(unsigned long)(state->write_buffer_size),size_update.update->querysize));
    + state->write_buffer_size = size_update.update->querysize;
    + state->write_buffer = safe_realloc(state->write_buffer,state->write_buffer_size);
    +
    + }
    +
    + } else {
    + SIGDPRINT(Debug,14,(&Debug, "resolv_read_message: [pid %d] fd %d: Bad size update message, querysize %d\n",
    + pid,fd,size_update.update->querysize)); + }
    +
    + if (size_update.update->anssize >= sizeof (struct resolv_sizeupdate)) {
    +
    + if (size_update.update->anssize != state->read_buffer_size) {
    + SIGDPRINT(Debug,14,(&Debug, "resolv_read_message: [pid %d] fd %d: Changing anssize %lu => %d (read buffer size)\n",
    + pid,fd,(unsigned long)(state->read_buffer_size),
    + size_update.update->anssize));
    +
    + state->read_buffer_size = size_update.update->anssize; + state->read_buffer = safe_realloc(state->read_buffer,state->read_buffer_size);
    + }
    +
    + } else {
    + SIGDPRINT(Debug,14,(&Debug, "resolv_read_message: [pid %d] fd %d: Bad size update message, anssize %d\n",
    + pid,fd,size_update.update->anssize));
    + }
    +
    + } else {
    + SIGDPRINT(Debug,14,(&Debug, "resolv_read_message: [pid %d] fd %d: Bad size update message\n",
    + pid,fd));
    + }
    +
    + break;
    + }
    + }
    +
    + DPRINT(Debug,14,(&Debug, "resolv_read_message: [pid %d] result %d",pid,st));
    + switch(st) {
    + case action_disable: DPRINT(Debug,14,(&Debug, " (disable)")); break;
    + case action_continue: DPRINT(Debug,14,(&Debug, " (continue)")); break;
    + }
    + DPRINT(Debug,14,(&Debug, "\n"));
    + return st;
    + }
    +
    + S_(action_routine resolv_write_message)
    + enum action_status resolv_write_message P_((int fd,
    + union action_routine_data data,
    + const struct schedule_timelimit * now));
    + enum action_status resolv_write_message(fd,data,now)
    + int fd;
    + union action_routine_data data;
    + const struct schedule_timelimit * now;
    + {
    + struct resolv_message_state * state = data.resolv;
    + int pid = getpid();
    + int err = 0;
    + enum action_status st = action_continue;
    +
    + enum write_status ws;
    +
    + DPRINT(Debug,14,(&Debug, "resolv_write_message: [pid %d] socket %d writable\n",
    + pid,fd));
    +
    + if (RESOLV_MESSAGE_STATE_magic != state->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,"resolv_write_message",
    + "Bad magic number (resolv_message_state)",0);
    +
    + if (!state->write_prepared) {
    + size_t previous = state->querynum;
    +
    + if (previous >= query_list_len) {
    + previous = 0;
    + state->querynum = 0;
    + DPRINT(Debug,14,(&Debug,
    + "resolv_write_message: [pid %d] socket %d -- resetting search of query to %lu\n",
    + pid,fd,(unsigned long)previous));
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "resolv_write_message: [pid %d] socket %d -- starting search of query from %lu\n",
    + pid,fd,(unsigned long)previous));
    + }
    +
    + do {
    +
    +
    + if (state->querynum < query_list_len && query_list[state->querynum]) {
    + if (RESOLV_QUERY_ITEM_magic != query_list[state->querynum]->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,"resolv_read_message",
    + "Bad magic number (resolv_query_item)",0);
    +
    + if (! query_list[state->querynum]->query_sent &&
    + query_list[state->querynum]->query_buffer &&
    + query_list[state->querynum]->answer_buffer &&
    + query_list[state->querynum]->query_hdr) {
    + DPRINT(Debug,14,(&Debug, "resolv_write_message: [pid %d] socket %d -- selected query %lu\n",
    + pid,fd,(unsigned long)(state->querynum))); + break;
    + }
    + }
    +
    + state->querynum++;
    + if (state->querynum >= query_list_len) {
    + size_t X UNUSED_VAROK = state->querynum;
    + state->querynum = 0;
    +
    + DPRINT(Debug,14,(&Debug, "resolv_write_message: [pid %d] socket %d -- reached query number %lu -- wrapping to %lu\n",
    + pid,fd,(unsigned long)X,(unsigned long)(state->querynum)));
    +
    + }
    +
    + } while (state->querynum != previous);
    +
    + if (state->querynum < query_list_len && query_list[state->querynum]) { +
    + if (RESOLV_QUERY_ITEM_magic != query_list[state->querynum]->magic) + panic("RESOLV PANIC",__FILE__,__LINE__,"resolv_read_message",
    + "Bad magic number (resolv_query_item)",0);
    +
    + if (! query_list[state->querynum]->query_sent &&
    + query_list[state->querynum]->query_buffer &&
    + query_list[state->querynum]->answer_buffer &&
    + query_list[state->querynum]->query_hdr) {
    + size_t querysize = RESOLV_BUFSIZE;
    + size_t anssize = RESOLV_BUFSIZE;
    + int queryupdate, ansupdate;
    +
    + if (RESOLV_MESSAGE_magic != query_list[state->querynum]->query_buffer->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,
    + "resolv_write_message",
    + "Bad magic number (resolv_message) of query_buffer",0);
    +
    + if (RESOLV_MESSAGE_magic != query_list[state->querynum]->answer_buffer->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,
    + "resolv_write_message",
    + "Bad magic number (resolv_message) of answer_buffer",0);
    +
    + if (RESOLV_QUERY_HDR_magic != query_list[state->querynum]->query_hdr->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,
    + "resolv_write_message",
    + "Bad magic number (resolv_query_hdr)",0);
    +
    + querysize = query_list[state->querynum]->query_buffer->message_size;
    + anssize = query_list[state->querynum]->answer_buffer->message_size;
    +
    + queryupdate = ( querysize >= sizeof (struct resolv_sizeupdate) &&
    + querysize != state->write_buffer_size );
    + ansupdate = ( anssize >= sizeof (struct resolv_sizeupdate) && + anssize != state->read_buffer_size );
    +
    + if (queryupdate || ansupdate) {
    + struct resolv_query_hdr Z = NULL_resolv_query_hdr;
    + struct resolv_sizeupdate U = NULL_resolv_sizeupdate;
    + union resolv_sizeupdate_p update_buffer;
    + size_t wsize,rsize;
    +
    + DPRINT(Debug,14,(&Debug,
    + "resolv_write_message: [pid %d] socket %d: need update sizes: write buffer size %lu %s query buffer size %lu, read buffer size %lu %s answer buffer size %lu\n",
    + pid,fd,
    + (unsigned long)(state->write_buffer_size), + queryupdate ? "=>" : "~",
    + (unsigned long)querysize,
    + (unsigned long)state->read_buffer_size,
    + ansupdate ? "=>" : "~",
    + (unsigned long)anssize));
    +
    + wsize = queryupdate ? querysize : state->write_buffer_size; + rsize = ansupdate ? anssize : state->read_buffer_size; +
    + if (wsize < sizeof U)
    + wsize = sizeof U;
    + if (rsize < sizeof U)
    + rsize = sizeof U;
    +
    + if (wsize != state->write_buffer_size) {
    + DPRINT(Debug,14,(&Debug,
    + "resolv_write_message: [pid %d] socket %d: changing write buffer size %lu => %lu\n",
    + pid,fd,
    + (unsigned long)(state->write_buffer_size),
    + (unsigned long)wsize));
    +
    + state->write_buffer_size = wsize;
    + state->write_buffer = safe_realloc(state->write_buffer,
    + state->write_buffer_size);
    + }
    + U.querysize = state->write_buffer_size;
    +
    + if (rsize != state->read_buffer_size) {
    + DPRINT(Debug,14,(&Debug,
    + "resolv_write_message: [pid %d] socket %d: changing read buffer size %lu => %lu\n",
    + pid,fd,
    + (unsigned long)(state->read_buffer_size),
    + (unsigned long)rsize));
    +
    + state->read_buffer_size = rsize;
    + state->read_buffer = safe_realloc(state->read_buffer,state->read_buffer_size);
    + }
    + U.anssize = state->read_buffer_size;
    +
    + update_buffer.update = &U;
    + Z.buflen = sizeof U;
    + Z.senderpid = pid;
    + Z.msg = qm_sizeupdate;
    +
    + state->write_hdr = Z;
    + memcpy(state->write_buffer, update_buffer.buffer,sizeof U); + state->write_buffer_len = sizeof U;
    + state->write_pos = 0;
    + state->write_prepared = 1;
    +
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "resolv_write_message: [pid %d] socket %d: writing query\n",
    + pid,fd));
    +
    + if (state->write_buffer_size < query_list[state->querynum]->query_buffer->message_len ||
    + query_list[state->querynum]->query_buffer->message_len !=
    + query_list[state->querynum]->query_hdr->buflen)
    + panic("RESOLV PANIC",__FILE__,__LINE__,
    + "resolv_write_message",
    + "Bad message_len",0);
    +
    + state->write_hdr = * (query_list[state->querynum]->query_hdr);
    + if (query_list[state->querynum]->query_buffer->message_len &&
    + query_list[state->querynum]->query_buffer->message) {
    + memcpy(state->write_buffer,query_list[state->querynum]->query_buffer->message,
    + query_list[state->querynum]->query_buffer->message_len);
    + state->write_buffer_len = query_list[state->querynum]->query_buffer->message_len;
    + } else
    + state->write_buffer_len = 0;
    +
    + state->write_pos = 0;
    + state->write_prepared = 1;
    + query_list[state->querynum]->query_sent = 1;
    + }
    + }
    + }
    + }
    +
    + if (state->write_prepared) {
    +
    + ws = write_message(fd,&(state->write_hdr),state->write_buffer,state->write_buffer_len,
    + &err,pid,&(state->write_pos));
    +
    + DPRINT(Debug,14,(&Debug, "resolv_write_message: [pid %d] socket %d, got %d",
    + pid,fd,ws));
    + switch (ws) {
    + case ws_write_error: SIGDPRINT(Debug,14,(&Debug, " (write error, error=%d) ",err));
    + if (err != EINTR && err != EAGAIN && err != EWOULDBLOCK)
    + st = action_disable;
    +
    + if (EPIPE == err) {
    + if (! state->broken_pipe) {
    + SIGDPRINT(Debug,14,(&Debug, ", marking broken pipe"));
    + state->broken_pipe = 1;
    + }
    + }
    + if (state->querynum < query_list_len && query_list[state->querynum]) {
    +
    + if (RESOLV_QUERY_ITEM_magic != query_list[state->querynum]->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,"resolv_read_message",
    + "Bad magic number (resolv_query_item)",0);
    +
    + if (query_list[state->querynum]->query_sent) {
    + query_list[state->querynum]->last_errno = err;
    + SIGDPRINT(Debug,14,(&Debug, " -- query %lu errno %d set",
    + (unsigned long)(state->querynum),
    + err));
    + }
    + }
    + break;
    + case ws_none: SIGDPRINT(Debug,14,(&Debug, " (none) ")); break;
    + case ws_sent_message: SIGDPRINT(Debug,14,(&Debug, " (sent message) "));
    +
    + if (state->querynum < query_list_len && query_list[state->querynum]) {
    +
    + if (RESOLV_QUERY_ITEM_magic != query_list[state->querynum]->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,"resolv_read_message",
    + "Bad magic number (resolv_query_item)",0);
    +
    + if (query_list[state->querynum]->query_sent) {
    + SIGDPRINT(Debug,14,(&Debug, " -- query %lu done",
    + (unsigned long)(state->querynum)));
    + st = action_disable;
    +
    + if (!state->query_in_progress) {
    + SIGDPRINT(Debug,14,(&Debug, ", setting 'query in progress'"));
    + state->query_in_progress = 1;
    + }
    + }
    + }
    + state->write_prepared = 0;
    + break;
    + case ws_incomplete: SIGDPRINT(Debug,14,(&Debug, " (incomplete) ")); break;
    + case ws_continue: SIGDPRINT(Debug,14,(&Debug, " (continue) ")); break;
    + }
    + DPRINT(Debug,14,(&Debug, "\n"));
    + } else {
    + st = action_disable;
    + DPRINT(Debug,14,(&Debug, "resolv_write_message: [pid %d] socket %d: No query available\n",
    + pid,fd));
    + }
    +
    +
    + DPRINT(Debug,14,(&Debug, "resolv_write_message: [pid %d] socket %d: result %d",pid,fd,st));
    + switch(st) {
    + case action_disable: DPRINT(Debug,14,(&Debug, " (disable)")); break;
    + case action_continue: DPRINT(Debug,14,(&Debug, " (continue)")); break;
    + }
    + DPRINT(Debug,14,(&Debug, "\n"));
    + return st;
    + }
    + #endif
    +
    + /* -------------------------------------------------------------------------------------
    + http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_10.html quote:
    +
    + The SOCK_SEQPACKET socket type is similar to the SOCK_STREAM type,
    + and is also connection-oriented. The only difference between these
    + types is that record boundaries are maintained using the
    + SOCK_SEQPACKET type. A record can be sent using one or more output
    + operations and received using one or more input operations, but a
    + single operation never transfers parts of more than one
    + record. Record boundaries are visible to the receiver via the
    + MSG_EOR flag in the received message flags returned by the
    + recvmsg() function. It is protocol-specific whether a maximum
    + record size is imposed.
    +
    + -------------------------------------------------------------------------------------- */
    +
    + S_(end_handler end_send_process)
    + static void end_send_process P_((union any_fd fd, char * title,
    + struct run_state *rs, int ret, int exit_stat));
    + static void end_send_process(fd,title,rs,ret,exit_stat)
    + union any_fd fd;
    + char * title;
    + struct run_state *rs;
    + int ret;
    + int exit_stat;
    + {
    + struct resolv_process *proc = fd.resolv_process;
    +
    + if (RESOLV_PROCESS_magic != proc->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,"end_send_process",
    + "Bad magic number (resolv_process)",0);
    +
    + if (proc->state >= ps_forked && proc->state <= ps_shutdown) {
    + if (ret < 0) {
    + proc->state = ps_died;
    + DPRINT(Debug,12,(&Debug,
    + "end_send_process: marking pid %d died\n",
    + proc->pid));
    + } else {
    + proc->state = ps_exited;
    + DPRINT(Debug,12,(&Debug,
    + "end_send_process: marking pid %d exited\n",
    + proc->pid));
    +
    + }
    + } else {
    + DPRINT(Debug,12,(&Debug,
    + "end_send_process: pid %d have unexpected state %d\n", + proc->pid,proc->state));
    + }
    + }
    +
    + S_(free_any_fd_f free_send_process)
    + static void free_send_process P_((union any_fd *fd));
    + static void free_send_process(fd)
    + union any_fd *fd;
    + {
    + free_resolv_process(& (fd->resolv_process));
    + }
    +
    + S_(inc_any_fd_refcount_f inc_send_process_refount)
    + static void inc_send_process_refount P_((union any_fd fd));
    + static void inc_send_process_refount(fd)
    + union any_fd fd;
    + {
    + inc_resolv_process_refcount(fd.resolv_process);
    + }
    +
    + static int resolv_process_ok P_((struct resolv_process *pr));
    + static int resolv_process_ok(pr)
    + struct resolv_process *pr;
    + {
    + int XX = 0;
    +
    + if (RESOLV_PROCESS_magic != pr->magic)
    + panic("RESOLV PANIC",__FILE__,__LINE__,"resolv_process_ok",
    + "Bad magic number (resolv_process)",0);
    +
    + DPRINT(Debug,14,(&Debug, "resolv_process_ok: "));
    +
    + if (-1 != pr->pid) {
    + DPRINT(Debug,14,(&Debug, "pid %d, ",pr->pid));
    + }
    +
    + DPRINT(Debug,14,(&Debug, "state %d",pr->state));
    + switch (pr->state) {
    + case ps_none: DPRINT(Debug,14,(&Debug, " (none)")); break;
    + case ps_forked: DPRINT(Debug,14,(&Debug, " (forked)")); break;
    + case ps_running: DPRINT(Debug,14,(&Debug, " (running)"));
    + if (-1 != pr->pid) {
    + XX = 1;
    + }
    + break;
    + case ps_shutdown: DPRINT(Debug,14,(&Debug, " (shutdown)")); break;
    + case ps_exited: DPRINT(Debug,14,(&Debug, " (exited)")); break;
    + case ps_died: DPRINT(Debug,14,(&Debug, " (died)")); break;
    + }
    +
    + if (-1 != pr->socket) {
    + DPRINT(Debug,14,(&Debug, ", socket %d",
    + pr->socket));
    +
    + } else
    + XX = 0;
    +
    + DPRINT(Debug,14,(&Debug, " => result %d%s\n",
    + XX,XX ? " OK ": ""));
    +
    + return XX;
    + }
    +
    + #if defined(RESOLV_SENDOK) && defined(RESOLV_SEQPACKET) && defined(BACKGROUD_PROCESSES)
    + static struct resolv_process * give_resolv_process P_((int pid0));
    + static struct resolv_process * give_resolv_process(pid0)
    + int pid0;
    + {
    + struct resolv_process * ret = NULL;
    +
    + int com_socket_pair[2];
    + int r = socketpair(AF_UNIX,SOCK_SEQPACKET,0,com_socket_pair);
    +
    + if (0 == r) {
    + struct resolv_message_state * st;
    + char title[80];
    + union any_fd FD;
    + int pid;
    +
    + union action_routine_data data;
    +
    + DPRINT(Debug,12,(&Debug, "give_resolv_process: Got socket %d <-> %d\n", + com_socket_pair[0],com_socket_pair[1]));
    +
    + pid = fork();
    + /* Add one worker process */
    +
    + if (0 == pid) { /* Child */
    +
    + close(com_socket_pair[0]);
    + resolv_send_process(com_socket_pair[1]);
    +
    + exit(0);
    +
    + } else if (-1 == pid) {
    + int err = errno;
    +
    + lib_error(CATGETS(elm_msg_cat,
    + ResolvSet,
    + ResolvFailedChildResSend,
    + "Failed to create child prosess for res_send: %s"),
    + strerror(err));
    + goto fail;
    + }
    +
    + DPRINT(Debug,12,(&Debug,
    + "give_resolv_process: #%lu, pid %d created\n",
    + (unsigned long)process_list_len,
    + pid));
    +
    + close(com_socket_pair[1]);
    + st = new_resolv_message_state(pid0);
    + data.resolv = st;
    +
    + if (-1 == fcntl(com_socket_pair[0],F_SETFL,O_NONBLOCK)) {
    + int err UNUSED_VAROK = errno;
    + DPRINT(Debug,12,(&Debug,
    + "give_resolv_process: fcntl [O_NONBLOCK] failed: %s\n",
    + strerror(err)));
    + }
    +
    + change_action(com_socket_pair[0],-1,resolv_read_message,
    + no_action_routine,no_action_routine,
    + resolv_free_state,resolv_inc_state_refcount,data);
    +
    +
    + ret = new_resolv_process(pid);
    + ret->state = ps_forked;
    + ret->message = st;
    + ret->socket = com_socket_pair[0];
    +
    + process_list = safe_array_realloc(process_list,
    + process_list_len+1,
    + sizeof (process_list[0]));
    +
    + process_list[process_list_len++] = ret;
    +
    + elm_sfprintf(title, sizeof title,
    + CATGETS(elm_msg_cat,
    + ResolvSet,
    + ResolvLookupHelper,
    + "Lookup (res_send) helper (pid %d)"),
    + pid);
    + FD.resolv_process = ret;
    + add_foreign_background(pid,FD,title,end_send_process,
    + free_send_process,inc_send_process_refount);
    +
    + inc_resolv_process_refcount(ret);
    + } else if (-1 == r) {

    [continued in next message]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)