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