1 /*
2 * $Id: util.c,v 1.10 2010/02/04 10:31:41 aland Exp $
3 *
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 *
6 * Copyright (C) 1995,1996,1997 Lars Fenneberg
7 *
8 * Copyright 1992 Livingston Enterprises, Inc.
9 *
10 * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
11 * and Merit Network, Inc. All Rights Reserved
12 *
13 * See the file COPYRIGHT for the respective terms and conditions.
14 * If the file is missing contact me at lf@elemental.net
15 * and I'll send you a copy.
16 *
17 */
18
19 #include <sys/time.h>
20
21 #include <config.h>
22 #include <includes.h>
23 #include <freeradius-client.h>
24
25 #define RC_BUFSIZ 1024
26
27 /*
28 * Function: rc_str2tm
29 *
30 * Purpose: Turns printable string into correct tm struct entries.
31 *
32 */
33
34 static char const * months[] =
35 {
36 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
37 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
38 };
39
rc_str2tm(char const * valstr,struct tm * tm)40 void rc_str2tm (char const *valstr, struct tm *tm)
41 {
42 int i;
43
44 /* Get the month */
45 for (i = 0; i < 12; i++)
46 {
47 if (strncmp (months[i], valstr, 3) == 0)
48 {
49 tm->tm_mon = i;
50 i = 13;
51 }
52 }
53
54 /* Get the Day */
55 tm->tm_mday = atoi (&valstr[4]);
56
57 /* Now the year */
58 tm->tm_year = atoi (&valstr[7]) - 1900;
59 }
60
61 /*
62 * Function: rc_getifname
63 *
64 * Purpose: get the network interface name associated with this tty
65 *
66 */
67
rc_getifname(rc_handle * rh,char const * tty)68 char *rc_getifname(rc_handle *rh, char const *tty)
69 {
70 #if defined(BSD4_4) || defined(linux)
71 int fd;
72
73 if ((fd = open(tty, O_RDWR|O_NDELAY)) < 0) {
74 rc_log(LOG_ERR, "rc_getifname: can't open %s: %s", tty, strerror(errno));
75 return NULL;
76 }
77 #endif
78
79 #ifdef BSD4_4
80 strcpy(rh->ifname,ttyname(fd));
81 if (strlen(rh->ifname) < 1) {
82 rc_log(LOG_ERR, "rc_getifname: can't get attached interface of %s: %s", tty, strerror(errno));
83 close(fd);
84 return NULL;
85 }
86 #elif linux
87 if (ioctl(fd, SIOCGIFNAME, rh->ifname) < 0) {
88 rc_log(LOG_ERR, "rc_getifname: can't ioctl %s: %s", tty, strerror(errno));
89 close(fd);
90 return NULL;
91 }
92 #else
93 return NULL;
94 #endif
95
96 #if defined(BSD4_4) || defined(linux)
97 close(fd);
98 return rh->ifname;
99 #endif
100 }
101
102 /*
103 * Function: rc_getstr
104 *
105 * Purpose: Reads in a string from the user (with or witout echo)
106 *
107 */
108 #ifndef _MSC_VER
rc_getstr(rc_handle * rh,char const * prompt,int do_echo)109 char *rc_getstr (rc_handle *rh, char const *prompt, int do_echo)
110 {
111 int in, out;
112 char *p;
113 struct termios term_old, term_new;
114 int is_term, flags, old_flags;
115 char c;
116 int flushed = 0;
117 sigset_t newset;
118 sigset_t oldset;
119
120 in = fileno(stdin);
121 out = fileno(stdout);
122
123 (void) sigemptyset (&newset);
124 (void) sigaddset (&newset, SIGINT);
125 (void) sigaddset (&newset, SIGTSTP);
126 (void) sigaddset (&newset, SIGQUIT);
127
128 (void) sigprocmask (SIG_BLOCK, &newset, &oldset);
129
130 if ((is_term = isatty(in)))
131 {
132
133 (void) tcgetattr (in, &term_old);
134 term_new = term_old;
135 if (do_echo)
136 term_new.c_lflag |= ECHO;
137 else
138 term_new.c_lflag &= ~ECHO;
139
140 if (tcsetattr (in, TCSAFLUSH, &term_new) == 0)
141 flushed = 1;
142
143 }
144 else
145 {
146 is_term = 0;
147 if ((flags = fcntl(in, F_GETFL, 0)) >= 0) {
148 old_flags = flags;
149 flags |= O_NONBLOCK;
150
151 fcntl(in, F_SETFL, flags);
152
153 while (read(in, &c, 1) > 0)
154 /* nothing */;
155
156 fcntl(in, F_SETFL, old_flags);
157
158 flushed = 1;
159 }
160 }
161
162 (void)write(out, prompt, strlen(prompt));
163
164 /* well, this looks ugly, but it handles the following end of line
165 markers: \r \r\0 \r\n \n \n\r, at least at a second pass */
166
167 p = rh->buf;
168 for (;;)
169 {
170 if (read(in, &c, 1) <= 0)
171 return NULL;
172
173 if (!flushed && ((c == '\0') || (c == '\r') || (c == '\n'))) {
174 flushed = 1;
175 continue;
176 }
177
178 if ((c == '\r') || (c == '\n'))
179 break;
180
181 flushed = 1;
182
183 if (p < rh->buf + GETSTR_LENGTH)
184 {
185 if (do_echo && !is_term)
186 (void)write(out, &c, 1);
187 *p++ = c;
188 }
189 }
190
191 *p = '\0';
192
193 if (!do_echo || !is_term) (void)write(out, "\r\n", 2);
194
195 if (is_term)
196 tcsetattr (in, TCSAFLUSH, &term_old);
197 else {
198 if ((flags = fcntl(in, F_GETFL, 0)) >= 0) {
199 old_flags = flags;
200 flags |= O_NONBLOCK;
201
202 fcntl(in, F_SETFL, flags);
203
204 while (read(in, &c, 1) > 0)
205 /* nothing */;
206
207 fcntl(in, F_SETFL, old_flags);
208 }
209 }
210
211 (void) sigprocmask (SIG_SETMASK, &oldset, NULL);
212
213 return rh->buf;
214 }
215 #endif
rc_mdelay(int msecs)216 void rc_mdelay(int msecs)
217 {
218 struct timeval tv;
219
220 tv.tv_sec = (int) msecs / 1000;
221 tv.tv_usec = (msecs % 1000) * 1000;
222
223 select(0, NULL, NULL, NULL, &tv);
224 }
225
226 /*
227 * Function: rc_mksid
228 *
229 * Purpose: generate a quite unique string
230 *
231 * Remarks: not that unique at all...
232 *
233 */
234
235 char *
rc_mksid(rc_handle * rh)236 rc_mksid (rc_handle *rh)
237 {
238 snprintf (rh->buf1, sizeof(rh->buf1), "%08lX%04X", (unsigned long int) time (NULL), (unsigned int) getpid ());
239 return rh->buf1;
240 }
241
242 /*
243 * Function: rc_new
244 *
245 * Purpose: Initialises new Radius Client handle
246 *
247 */
248
249 rc_handle *
rc_new(void)250 rc_new(void)
251 {
252 rc_handle *rh;
253
254 rh = malloc(sizeof(*rh));
255 if (rh == NULL) {
256 rc_log(LOG_CRIT, "rc_new: out of memory");
257 return NULL;
258 }
259 memset(rh, 0, sizeof(*rh));
260 return rh;
261 }
262
263 /*
264 * Function: rc_destroy
265 *
266 * Purpose: Destroys Radius Client handle reclaiming all memory
267 *
268 */
269
270 void
rc_destroy(rc_handle * rh)271 rc_destroy(rc_handle *rh)
272 {
273
274 rc_map2id_free(rh);
275 rc_dict_free(rh);
276 rc_config_free(rh);
277 if (rh->this_host_bind_ipaddr != NULL)
278 free(rh->this_host_bind_ipaddr);
279 free(rh);
280 }
281
282 /*
283 * Function: rc_fgetln
284 *
285 * Purpose: Get next line from the stream.
286 *
287 */
288
289 char *
rc_fgetln(FILE * fp,size_t * len)290 rc_fgetln(FILE *fp, size_t *len)
291 {
292 static char *buf = NULL;
293 static size_t bufsiz = 0;
294 char *ptr;
295
296 if (buf == NULL) {
297 bufsiz = RC_BUFSIZ;
298 if ((buf = malloc(bufsiz)) == NULL)
299 return NULL;
300 }
301
302 if (fgets(buf, (int)bufsiz, fp) == NULL)
303 return NULL;
304 *len = 0;
305
306 while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
307 size_t nbufsiz = bufsiz + RC_BUFSIZ;
308 char *nbuf = realloc(buf, nbufsiz);
309
310 if (nbuf == NULL) {
311 int oerrno = errno;
312 free(buf);
313 errno = oerrno;
314 buf = NULL;
315 return NULL;
316 } else
317 buf = nbuf;
318
319 *len = bufsiz;
320 if (fgets(&buf[bufsiz], RC_BUFSIZ, fp) == NULL)
321 return buf;
322
323 bufsiz = nbufsiz;
324 }
325
326 *len = (ptr - buf) + 1;
327 return buf;
328 }
329
330 /*
331 * Function: rc_getctime
332 *
333 * Purpose: Get current time (seconds since epoch) expressed as
334 * double-precision floating point number.
335 *
336 */
337
338 double
rc_getctime(void)339 rc_getctime(void)
340 {
341 struct timeval timev;
342
343 if (gettimeofday(&timev, NULL) == -1)
344 return -1;
345
346 return timev.tv_sec + ((double)timev.tv_usec) / 1000000.0;
347 }
348