+ /* --- Go for it --- */
+
+ while (state != st_done) {
+ switch (state) {
+
+ /* --- Initial whitespace before hostname --- */
+
+ case st_start:
+ if (ch == EOF)
+ state = st_done;
+ else if (isspace((unsigned char)ch))
+ ch = getc(fp);
+ else
+ state = st_host;
+ break;
+
+ /* --- Read a host name --- */
+
+ case st_host:
+ if (p == l)
+ die(1, "string too long in `" file_SERVER "'");
+ if (ch != EOF && !isspace((unsigned char)ch) && ch != ':') {
+ *p++ = ch;
+ ch = getc(fp);
+ } else {
+ struct hostent *h;
+
+ *p++ = 0;
+ if ((h = gethostbyname(buff)) == 0)
+ die(1, "unknown host `%s' in `" file_SERVER "'", buff);
+ memcpy(&t_host, h->h_addr, sizeof(t_host));
+ state = st_colon;
+ }
+ break;
+
+ /* --- Waiting for a colon coming up --- */
+
+ case st_colon:
+ if (ch == EOF)
+ state = st_commit;
+ else if (isspace((unsigned char)ch))
+ ch = getc(fp);
+ else if (ch == ':') {
+ state = st_preport;
+ ch = getc(fp);
+ }
+ else
+ state = st_commit;
+ break;
+
+ /* --- Clearing whitespace before a port number --- */
+
+ case st_preport:
+ if (ch == EOF)
+ state = st_commit;
+ else if (isspace((unsigned char)ch))
+ ch = getc(fp);
+ else {
+ state = st_port;
+ p = buff;
+ }
+ break;
+
+ /* --- Read a port number --- */
+
+ case st_port:
+ if (p == l)
+ die(1, "string too long in `" file_SERVER "'");
+ if (ch != EOF && !isspace((unsigned char)ch) && ch != ':') {
+ *p++ = ch;
+ ch = getc(fp);
+ } else {
+ struct servent *s;
+
+ *p++ = 0;
+ s = getservbyname(buff, "udp");
+ if (!s && isdigit((unsigned char)buff[0]))
+ t_port = htons(atoi(buff));
+ else if (!s)
+ die(1, "unknown service `%s' in `" file_SERVER "'", buff);
+ else
+ t_port = s->s_port;
+ state = st_commit;
+ }
+ break;
+
+ /* --- A server has been read successfully --- */
+
+ case st_commit:
+ if (n_serv == max_serv) {
+ max_serv *= 2;
+ serv = xrealloc(serv, n_serv * sizeof(*serv),
+ max_serv * sizeof(*serv));
+ }
+ serv[n_serv].sin_family = AF_INET;
+ serv[n_serv].sin_addr = t_host;
+ serv[n_serv].sin_port = t_port;
+ n_serv++;
+ state = st_start;
+ p = buff;
+ t_port = port;
+ break;
+
+ /* --- A safety net for a broken parser --- */
+
+ default:
+ die(1, "internal error: can't get here in check__client");
+ break;
+ }
+ }
+ }