/* The Open DNS Update Daemon (dnsd) Copyright (C) 1998 Aaron Sethman The read_line() function was borrowed from Eric S. Raymond's fetchmail program. Fetchmail is Copyright (C) Eric S. Raymond. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* File status: finished..... Last modified: April 16, 1999 asethman@mandate-inc.com */ #include #include #include #include #include #include #include #include #include #include // #include #include #include #include #include "client.h" void do_select2(int socket, int tv_sec); char *getip(int s) { char *ptr; struct sockaddr_in *sin; int len; len = sizeof(struct sockaddr_in); sin = malloc(len); if (getpeername(s, (struct sockaddr *)sin, &len) >= 0 && (sin != NULL)) { ptr = strdup(inet_ntoa(sin->sin_addr)); free(sin); return(ptr); } return NULL; } int mydprintf(int s, char *fmt,...) { int x; char *ptr; va_list ap; va_start(ap, fmt); myvasprintf(&ptr, fmt, ap); x = write(s, ptr, strlen(ptr)); free(ptr); return(x); } void do_select2(int socket, int tv_sec) { fd_set rfds; struct timeval tv; struct timeval *t; FD_ZERO(&rfds); FD_SET(socket, &rfds); tv.tv_sec = tv_sec; tv.tv_usec = 0; t = &tv; if(tv_sec == -1) t = NULL; select(socket + 1, &rfds, NULL, NULL, t); } void do_select(int socket) { do_select2(socket, -1); } int read_line(int sock, char **buf) { /* Rewritten to do something mildly intelliegent.... */ int len = 8192; int x; int flags = MSG_PEEK, broken = 0; char *ptr, *r, *p, *q; ptr = malloc(len); if (sock < 0) return -1; do_select(sock); start: while ((x = recv(sock, ptr, len, flags)) > 0) { q = memchr(ptr, '\n', x); p = memchr(ptr, '\r', x); if(p != NULL && q != NULL) break; if((p == NULL) && (q == NULL)) { if(x == len) { len = len * 2; ptr = realloc(ptr, len); } else if(x == 1) { if(broken == 1) return -1; broken = 1; } goto start; } if((p == NULL) || (q == NULL)) { if(x == len) { len = len * 2; ptr = realloc(ptr, len); } else break; } } if ((r = mymemmem(ptr, x, "\n\r", 2)) != NULL) x = (r - ptr) + 2; else if ((r = mymemmem(ptr, x, "\r\n", 2)) != NULL) x = (r - ptr) + 2; else if ((r = mymemmem(ptr, x, "\r", 1)) != NULL) x = (r - ptr) + 1; else if ((r = mymemmem(ptr, x, "\n", 1)) != NULL) x = (r - ptr) + 1; ptr = realloc(ptr, x); x = recv(sock, ptr, x, 0); *buf = malloc(x); memcpy(*buf, ptr, x); free(ptr); if(broken) fcntl(sock, F_SETFL, O_NONBLOCK); return x; } int do_tcpconnect(char *hostname, int port) { struct hostent *host; struct sockaddr_in in; int s; if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) return -1; if ((host = gethostbyname(hostname)) == NULL) { return -1; } in.sin_family = AF_INET; in.sin_port = htons(port); in.sin_addr.s_addr = *(unsigned long *) host->h_addr; if (connect(s, (struct sockaddr *) &in, sizeof(struct sockaddr_in))) { return -1; } return (s); }