util-warnings-cleanup-20010705
[openafs.git] / src / util / hostparse.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * ALL RIGHTS RESERVED
12  */
13
14 #include <afs/param.h>
15 #ifdef UKERNEL
16 #include "../afs/sysincludes.h"
17 #include "../afs/afsutil.h"
18 #else /* UKERNEL */
19 #include <stdio.h>
20 #include <sys/types.h>
21 #include <stdlib.h>
22 #ifdef AFS_NT40_ENV
23 #include <winsock2.h>
24 #include <direct.h>
25 #else
26 #include <netinet/in.h>
27 #include <sys/socket.h>
28 #include <arpa/inet.h>
29 #include <netdb.h>
30 #include <ctype.h>
31 #endif
32 #ifdef HAVE_STRINGS_H
33 #include <strings.h>
34 #else
35 #ifdef HAVE_STRING_H
36 #include <string.h>
37 #endif
38 #endif
39 #include <errno.h>
40 #include "afsutil.h"
41 #endif /* UKERNEL */
42
43
44 /* also parse a.b.c.d addresses */
45 struct hostent *hostutil_GetHostByName(ahost)
46 register char *ahost; {
47     register int tc;
48     static struct hostent thostent;
49     static char *addrp[2];
50     static char addr[4];
51     register char *ptr = ahost;
52     afs_uint32 tval, numeric=0;
53     int dots=0;
54
55     tc = *ahost;    /* look at the first char */
56     if (tc >= '0' && tc <= '9') {
57         numeric = 1;
58         while ((tc = *ptr++)) {
59             if (tc == '.') {
60                 if (dots >= 3) {
61                     numeric = 0;
62                     break;
63                 }
64                 dots++;
65             } else if (tc > '9' || tc < '0') {
66                 numeric = 0;
67                 break;
68             } 
69         }
70     }
71     if (numeric) {
72         tc = *ahost;    /* look at the first char */
73         /* decimal address, return fake hostent with only hostaddr field good */
74         tval = 0;
75         dots = 0;
76         bzero(addr, sizeof(addr));
77         while ((tc = *ahost++)) {
78             if (tc == '.') {
79                 if (dots >= 3) return (struct hostent *) 0; /* too many dots */
80                 addr[dots++] = tval;
81                 tval = 0;
82             }
83             else if (tc > '9' || tc < '0') return (struct hostent *) 0;
84             else {
85                 tval *= 10;
86                 tval += tc - '0';
87             }
88         }
89         addr[dots] = tval;
90 #ifdef h_addr
91         /* 4.3 system */
92         addrp[0] = addr;
93         addrp[1] = (char *) 0;
94         thostent.h_addr_list = &addrp[0];
95 #else /* h_addr */
96         /* 4.2 and older systems */
97         thostent.h_addr = addr;
98 #endif /* h_addr */
99         return &thostent;
100     }
101     else {
102 #ifdef AFS_NT40_ENV
103         if (afs_winsockInit()<0) 
104             return (struct hostent *)0;
105 #endif
106         return gethostbyname(ahost);
107     }
108 }
109
110 /* Translate an internet address into a nice printable string. The
111  * variable addr is in network byte order.
112  */
113 char *hostutil_GetNameByINet(addr)
114   afs_uint32 addr;
115 {
116   struct hostent *th;
117   static char    tbuffer[256];
118
119 #ifdef AFS_NT40_ENV
120         if (afs_winsockInit()<0) 
121             return (char *)0;
122 #endif
123   th = gethostbyaddr((void *)&addr, sizeof(addr), AF_INET);
124   if (th) {
125      strcpy(tbuffer, th->h_name);
126   } else {
127      addr = ntohl(addr);
128      sprintf(tbuffer, "%d.%d.%d.%d", 
129              (int)((addr>>24) & 0xff), (int)((addr>>16) & 0xff),
130              (int)((addr>>8)  & 0xff), (int)( addr      & 0xff));
131   }
132   
133     return tbuffer;
134 }
135
136 /* the parameter is a pointer to a buffer containing a string of 
137 ** bytes of the form 
138 ** w.x.y.z      # machineName
139 ** returns the network interface in network byte order 
140 */
141 afs_uint32
142 extractAddr(line, maxSize)
143 char* line;
144 int maxSize;
145 {
146         char byte1[32], byte2[32], byte3[32], byte4[32];
147         int i=0;
148         char*   endPtr;
149         afs_uint32 val1, val2, val3, val4;
150         afs_uint32 val=0;
151
152         /* skip empty spaces */
153         while ( isspace(*line) && maxSize ) 
154         {
155                 line++;
156                 maxSize--;
157         }
158         
159         /* skip empty lines */
160         if ( !maxSize || !*line ) return  AFS_IPINVALIDIGNORE;
161         
162         while ( ( *line != '.' ) && maxSize) /* extract first byte */
163         {
164                 if ( !isdigit(*line) ) return AFS_IPINVALID;
165                 if ( i > 31 ) return AFS_IPINVALID; /* no space */
166                 byte1[i++] = *line++;
167                 maxSize--;
168         }
169         if ( !maxSize ) return AFS_IPINVALID;
170         byte1[i] = 0;
171         
172         i=0, line++;
173         while ( ( *line != '.' ) && maxSize) /* extract second byte */
174         {
175                 if ( !isdigit(*line) ) return AFS_IPINVALID;
176                 if ( i > 31 ) return AFS_IPINVALID; /* no space */
177                 byte2[i++] = *line++;
178                 maxSize--;
179         }
180         if ( !maxSize ) return AFS_IPINVALID;
181         byte2[i] = 0;
182
183         i=0, line++;
184         while ( ( *line != '.' ) && maxSize)
185         {
186                 if ( !isdigit(*line) ) return AFS_IPINVALID;
187                 if ( i > 31 ) return AFS_IPINVALID; /* no space */
188                 byte3[i++] = *line++;
189                 maxSize--;
190         }
191         if ( !maxSize ) return AFS_IPINVALID;
192         byte3[i] = 0;
193
194         i=0, line++;
195         while ( *line && !isspace(*line) && maxSize)
196         {
197                 if ( !isdigit(*line) ) return AFS_IPINVALID;
198                 if ( i > 31 ) return AFS_IPINVALID; /* no space */
199                 byte4[i++] = *line++;
200                 maxSize--;
201         }
202         if ( !maxSize ) return AFS_IPINVALID;
203         byte4[i] = 0;
204         
205         errno=0;
206         val1 = strtol(byte1, &endPtr, 10);
207         if (( val1== 0 ) && ( errno != 0 || byte1 == endPtr)) 
208                 return AFS_IPINVALID;
209         
210         errno=0;
211         val2 = strtol(byte2, &endPtr, 10);
212         if (( val2== 0 ) && ( errno !=0 || byte2 == endPtr))/* no conversion */
213                 return AFS_IPINVALID;
214
215         errno=0;
216         val3 = strtol(byte3, &endPtr, 10);
217         if (( val3== 0 ) && ( errno !=0 || byte3 == endPtr))/* no conversion */
218                 return AFS_IPINVALID;
219
220         errno=0;
221         val4 = strtol(byte4, &endPtr, 10);
222         if (( val4== 0 ) && ( errno !=0 || byte4 == endPtr))/* no conversion */
223                 return AFS_IPINVALID;
224
225         val = ( val1 << 24 ) | ( val2 << 16 ) | ( val3 << 8 ) | val4;
226         val = htonl(val);
227         return val;
228 }
229
230 /* 
231 ** converts a 4byte IP address into a static string (e.g. w.x.y.z) 
232 ** On Solaris, if we pass a 4 byte integer directly into inet_ntoa(), it
233 ** causes a memory fault. 
234 */
235 char* afs_inet_ntoa(afs_uint32 addr)
236 {
237     struct in_addr temp;
238     temp.s_addr = addr;
239     return (char *) inet_ntoa(temp);
240 }
241
242 /* same as above, but to a non-static buffer, must be freed by called */
243 char* afs_inet_ntoa_r(afs_uint32 addr, char *buf)
244 {
245     int temp;
246
247     temp = ntohl(addr);
248     sprintf(buf, "%d.%d.%d.%d", 
249             (temp >> 24 ) & 0xff,
250             (temp >> 16 ) & 0xff, 
251             (temp >> 8  ) & 0xff,
252             (temp       ) & 0xff);
253     return buf;
254 }
255
256 /*
257  * gettmpdir() -- Returns pointer to global temporary directory string.
258  *     Always succeeds.  Never attempt to deallocate directory string.
259  */
260
261 char *gettmpdir(void)
262 {
263     char *tmpdirp = NULL;
264     
265 #ifdef AFS_NT40_ENV
266     static char *saveTmpDir = NULL;
267
268     if (saveTmpDir == NULL) {
269         /* initialize global temporary directory string */
270         char *dirp = (char *)malloc(MAX_PATH);
271         int freeDirp = 1;
272
273         if (dirp != NULL) {
274             DWORD pathLen = GetTempPath(MAX_PATH, dirp);
275
276             if (pathLen == 0 || pathLen > MAX_PATH) {
277                 /* can't get tmp path; get cur work dir */
278                 pathLen = GetCurrentDirectory(MAX_PATH, dirp);
279                 if (pathLen == 0 || pathLen > MAX_PATH) {
280                     free(dirp);
281                     dirp = NULL;
282                 }
283             }
284
285             if (dirp != NULL) {
286                 /* Have a valid dir path; check that actually exists. */
287                 DWORD fileAttr = GetFileAttributes(dirp);
288
289                 if ((fileAttr == 0xFFFFFFFF) ||
290                     ((fileAttr & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
291                     free(dirp);
292                     dirp = NULL;
293                 }
294             }
295         } /* dirp != NULL */
296         
297         if (dirp != NULL) {
298             FilepathNormalize(dirp);
299         } else {
300             /* most likely TMP or TEMP env vars specify a non-existent dir */
301             dirp = "/";
302             freeDirp = 0;
303         }
304
305         /* atomically initialize shared buffer pointer IF still null */
306
307 #if 0
308         if (InterlockedCompareExchange(&saveTmpDir, dirp, NULL) != NULL) {
309             /* shared buffer pointer already initialized by another thread */
310             if (freeDirp) {
311                 free(dirp);
312             }
313         } /* interlock xchng */
314 #endif
315
316         /* Above is what we really want to do, but Windows 95 does not have
317          * InterlockedCompareExchange().  So we just atomically swap
318          * the buffer pointer values but we do NOT deallocate the
319          * previously installed buffer, if any, in case it is in use.
320          */
321         InterlockedExchange((LPLONG)&saveTmpDir, (LONG)dirp);
322
323     } /* if (!saveTmpDir) */
324     
325     tmpdirp = saveTmpDir;
326 #else
327     tmpdirp = "/tmp";
328 #endif /* AFS_NT40_ENV */
329     
330     return tmpdirp;
331 }
332
333