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