version 0.9.6
[rofl0r-htun.git] / src / util.c
blob4d96ba63af25d3273e024887945c183e19a2065d
1 /* -------------------------------------------------------------------------
2 * util.c - htun miscellaneous utility functions
3 * Copyright (C) 2002 Moshe Jacobson <moshe@runslinux.net>,
4 * Ola Nordström <ola@triblock.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * -------------------------------------------------------------------------
21 /* $Id: util.c,v 2.18 2002/09/11 20:57:26 jehsom Exp $ */
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <unistd.h>
27 #include <ctype.h>
28 #include <errno.h>
29 #include <netdb.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
34 #undef __EI
35 #include "util.h"
36 #include "log.h"
37 #include "common.h"
39 int xstrncasecmp( const char *s1, const char *s2, int n ){
40 const char *p1=s1, *p2=s2;
41 int ctr=0;
43 if( s1 == s2 ) return 0;
45 while( *p1 && tolower(*p1) == tolower(*p2) ) {
46 if( n ) {
47 ctr++;
48 if( ctr >= n ) return 0;
50 p1++; p2++;
52 if( !*p1 && *p2 ) return -1;
53 else if( !*p2 && *p1 ) return 1;
54 else return tolower(*p1)-tolower(*p2);
57 int fdprintf(int fd, char *fmt, ...) {
58 FILE *fp = fdopen(dup(fd), "w");
59 int rc;
60 va_list ap;
62 va_start(ap, fmt);
63 rc=vfprintf(fp, fmt, ap);
64 fflush(fp);
65 fclose(fp);
66 va_end(ap);
67 return rc;
70 char *recvline( char *buf, int len, int fd ){
71 char c=0;
72 int ctr=0;
74 while( ctr < len-2 ){
75 if( c != '\n' && read(fd,&c,1) == 1 ){
76 buf[ctr]=c;
77 ctr++;
78 } else {
79 break;
82 if( ctr == len-2 ){
83 while( c != '\n' && read(fd,&c,1) == 1 ) ctr++;
84 lprintf( log, WARN,
85 "line exceeded buffer space by %d bytes.",
86 ctr-len);
88 buf[ctr]='\0';
90 if( *buf == '\0' ) return NULL;
91 else return buf;
94 int recvflush( int s ) {
95 fd_set fds;
96 char c=0;
97 int rc, cnt=0;
98 struct timeval tv;
100 FD_ZERO(&fds);
101 FD_SET(s, &fds);
102 tv.tv_sec = 0;
103 tv.tv_usec = 0;
105 while( (rc=select(s+1, &fds, NULL, NULL, &tv)) ) {
106 if( rc == -1 ) {
107 lprintf(log, WARN, "select() failed: %s",
108 strerror(errno));
109 break;
111 if( (rc=read(s, &c, 1)) < 1 ) {
112 if( rc == 0 ) {
113 lprintf(log, WARN, "connection reset by peer");
114 } else {
115 lprintf(log, WARN, "read() failed: %s",
116 strerror(errno));
118 break;
120 cnt++;
121 tv.tv_sec = 0;
122 tv.tv_usec = 0;
125 dprintf(log, DEBUG, "returning %d.", cnt);
126 return cnt;
130 * Reads exactly len bytes from fd and returns the data in a dynamically
131 * allocated buffer
133 char *readloop( int fd, size_t len ) {
134 size_t cnt=0;
135 int rc;
136 char *buf = malloc(len+1);
138 if(!buf) return NULL;
140 dprintf(log, DEBUG, "attempting to read %d bytes from fd #%d",
141 len, fd);
142 while( cnt < len ) {
143 if( (rc=read(fd,buf+cnt,len-cnt)) <= 0 ) {
144 if( rc < 0 ) {
145 if( errno == EINTR ) continue;
146 lprintf(log, WARN, "Reading from sock fd %d: %s.", fd,
147 strerror(errno));
148 } else {
149 lprintf(log, WARN,
150 "Reading from sock fd %d: Read %d bytes, expected %d",
151 fd, cnt, len);
153 free(buf);
154 return NULL;
156 dprintf(log, DEBUG, "read() returned %d.", rc);
157 cnt += rc;
159 buf[len] = '\0';
161 return buf;
164 char **splitlines( char *buf ) {
165 int cnt = 1;
166 char **tmp, **ret = NULL;
167 char *cp;
169 if( !buf || !*buf ) return NULL;
170 if( (ret=malloc(1 + cnt * sizeof(char**))) == NULL ) return NULL;
171 ret[0] = buf;
173 for( cp=buf; *cp; cp++ ) {
174 if( *cp != '\n' ) continue;
175 if( (tmp=realloc(ret, (++cnt + 1) * sizeof(char**))) == NULL ) {
176 free(ret);
177 return NULL;
179 ret=tmp;
181 *cp = '\0';
182 ret[cnt-1] = cp + 1;
185 ret[cnt] = NULL;
186 return ret;
189 /* Thread-safe resolve */
190 struct hostent *
191 resolve( const char *name, struct hostent *hostbuf, char *buf, size_t len )
193 struct hostent *hp;
194 int herr, rc=0, i;
196 for( i=0; i<3; i++ ){
197 rc=gethostbyname_r(name, hostbuf, buf, len, &hp, &herr);
198 if( !rc ){
199 return hp;
200 } else if( herr == TRY_AGAIN ){
201 continue;
202 } else {
203 break;
206 errno=rc;
207 return NULL;
210 long base64_encode( char *to, const char *from, unsigned int len ) {
211 char b64string[] =
212 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
213 const char *fromp = from;
214 char end[3], *top = to;
215 unsigned char cbyte, obyte;
217 for (; len >= 3; len -= 3) {
218 cbyte = *fromp++;
219 *top++ = b64string[(int)(cbyte >> 2)];
220 obyte = (cbyte << 4) & 0x30; /* 0011 0000 */
222 cbyte = *fromp++;
223 obyte |= (cbyte >> 4); /* 0000 1111 */
224 *top++ = b64string[(int)obyte];
225 obyte = (cbyte << 2) & 0x3C; /* 0011 1100 */
227 cbyte = *fromp++;
228 obyte |= (cbyte >> 6); /* 0000 0011 */
229 *top++ = b64string[(int)obyte];
230 *top++ = b64string[(int)(cbyte & 0x3F)];/* 0011 1111 */
233 if (len) {
234 end[0] = *fromp++;
235 if (--len) end[1] = *fromp++; else end[1] = 0;
236 end[2] = 0;
238 cbyte = end[0];
239 *top++ = b64string[(int)(cbyte >> 2)];
240 obyte = (cbyte << 4) & 0x30; /* 0011 0000 */
242 cbyte = end[1];
243 obyte |= (cbyte >> 4);
244 *top++ = b64string[(int)obyte];
245 obyte = (cbyte << 2) & 0x3C; /* 0011 1100 */
247 if (len) *top++ = b64string[(int)obyte];
248 else *top++ = '=';
249 *top++ = '=';
251 *top = 0;
252 return top - to;