[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)