+
+static void
+amindexd_response(
+ void *datap,
+ pkt_t *pkt,
+ security_handle_t *sech)
+{
+ int ports[NSTREAMS], *response_error = datap, i;
+ char *p;
+ char *tok;
+ char *extra = NULL;
+
+ assert(response_error != NULL);
+ assert(sech != NULL);
+
+ if (pkt == NULL) {
+ errstr = newvstrallocf(errstr, _("[request failed: %s]"),
+ security_geterror(sech));
+ *response_error = 1;
+ return;
+ }
+
+ if (pkt->type == P_NAK) {
+#if defined(PACKET_DEBUG)
+ dbprintf(_("got nak response:\n----\n%s\n----\n\n"), pkt->body);
+#endif
+
+ tok = strtok(pkt->body, " ");
+ if (tok == NULL || strcmp(tok, "ERROR") != 0)
+ goto bad_nak;
+
+ tok = strtok(NULL, "\n");
+ if (tok != NULL) {
+ errstr = newvstrallocf(errstr, "NAK: %s", tok);
+ *response_error = 1;
+ } else {
+bad_nak:
+ errstr = newvstrallocf(errstr, _("request NAK"));
+ *response_error = 2;
+ }
+ return;
+ }
+
+ if (pkt->type != P_REP) {
+ errstr = newvstrallocf(errstr, _("received strange packet type %s: %s"),
+ pkt_type2str(pkt->type), pkt->body);
+ *response_error = 1;
+ return;
+ }
+
+#if defined(PACKET_DEBUG)
+ g_fprintf(stderr, _("got response:\n----\n%s\n----\n\n"), pkt->body);
+#endif
+
+ for(i = 0; i < NSTREAMS; i++) {
+ ports[i] = -1;
+ streams[i].fd = NULL;
+ }
+
+ p = pkt->body;
+ while((tok = strtok(p, " \n")) != NULL) {
+ p = NULL;
+
+ /*
+ * Error response packets have "ERROR" followed by the error message
+ * followed by a newline.
+ */
+ if (strcmp(tok, "ERROR") == 0) {
+ tok = strtok(NULL, "\n");
+ if (tok == NULL) {
+ errstr = newvstrallocf(errstr, _("[bogus error packet]"));
+ } else {
+ errstr = newvstrallocf(errstr, "%s", tok);
+ }
+ *response_error = 2;
+ return;
+ }
+
+
+ /*
+ * Regular packets have CONNECT followed by three streams
+ */
+ if (strcmp(tok, "CONNECT") == 0) {
+
+ /*
+ * Parse the three stream specifiers out of the packet.
+ */
+ for (i = 0; i < NSTREAMS; i++) {
+ tok = strtok(NULL, " ");
+ if (tok == NULL || strcmp(tok, streams[i].name) != 0) {
+ extra = vstrallocf(
+ _("CONNECT token is \"%s\": expected \"%s\""),
+ tok ? tok : _("(null)"), streams[i].name);
+ goto parse_error;
+ }
+ tok = strtok(NULL, " \n");
+ if (tok == NULL || sscanf(tok, "%d", &ports[i]) != 1) {
+ extra = vstrallocf(
+ _("CONNECT %s token is \"%s\" expected a port number"),
+ streams[i].name, tok ? tok : _("(null)"));
+ goto parse_error;
+ }
+ }
+ continue;
+ }
+
+ /*
+ * OPTIONS [options string] '\n'
+ */
+ if (strcmp(tok, "OPTIONS") == 0) {
+ tok = strtok(NULL, "\n");
+ if (tok == NULL) {
+ extra = vstrallocf(_("OPTIONS token is missing"));
+ goto parse_error;
+ }
+#if 0
+ tok_end = tok + strlen(tok);
+ while((p = strchr(tok, ';')) != NULL) {
+ *p++ = '\0';
+ if(strncmp_const(tok, "features=") == 0) {
+ tok += SIZEOF("features=") - 1;
+ am_release_feature_set(their_features);
+ if((their_features = am_string_to_feature(tok)) == NULL) {
+ errstr = newvstrallocf(errstr,
+ _("OPTIONS: bad features value: %s"),
+ tok);
+ goto parse_error;
+ }
+ }
+ tok = p;
+ }
+#endif
+ continue;
+ }
+#if 0
+ extra = vstrallocf(_("next token is \"%s\": expected \"CONNECT\", \"ERROR\" or \"OPTIONS\""), tok ? tok : _("(null)"));
+ goto parse_error;
+#endif
+ }
+
+ /*
+ * Connect the streams to their remote ports
+ */
+ for (i = 0; i < NSTREAMS; i++) {
+/*@i@*/ if (ports[i] == -1)
+ continue;
+ streams[i].fd = security_stream_client(sech, ports[i]);
+ if (streams[i].fd == NULL) {
+ errstr = newvstrallocf(errstr,
+ _("[could not connect %s stream: %s]"),
+ streams[i].name, security_geterror(sech));
+ goto connect_error;
+ }
+ }
+ /*
+ * Authenticate the streams
+ */
+ for (i = 0; i < NSTREAMS; i++) {
+ if (streams[i].fd == NULL)
+ continue;
+ if (security_stream_auth(streams[i].fd) < 0) {
+ errstr = newvstrallocf(errstr,
+ _("[could not authenticate %s stream: %s]"),
+ streams[i].name, security_stream_geterror(streams[i].fd));
+ goto connect_error;
+ }
+ }
+
+ /*
+ * The MESGFD and DATAFD streams are mandatory. If we didn't get
+ * them, complain.
+ */
+ if (streams[MESGFD].fd == NULL) {
+ errstr = newvstrallocf(errstr, _("[couldn't open MESG streams]"));
+ goto connect_error;
+ }
+
+ /* everything worked */
+ *response_error = 0;
+ amindexd_alive = 1;
+ return;
+
+parse_error:
+ errstr = newvstrallocf(errstr,
+ _("[parse of reply message failed: %s]"),
+ extra ? extra : _("(no additional information)"));
+ amfree(extra);
+ *response_error = 2;
+ return;
+
+connect_error:
+ stop_amindexd();
+ *response_error = 1;
+}
+
+/*
+ * This is called when everything needs to shut down so event_loop()
+ * will exit.
+ */
+void
+stop_amindexd(void)
+{
+ int i;
+
+ amindexd_alive = 0;
+ for (i = 0; i < NSTREAMS; i++) {
+ if (streams[i].fd != NULL) {
+ security_stream_close(streams[i].fd);
+ streams[i].fd = NULL;
+ }
+ }
+}