/src/ntp-dev/libntp/machines.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* machines.c - provide special support for peculiar architectures |
2 | | * |
3 | | * Real bummers unite ! |
4 | | * |
5 | | */ |
6 | | |
7 | | #ifdef HAVE_CONFIG_H |
8 | | #include "config.h" |
9 | | #endif |
10 | | |
11 | | #include "ntp.h" |
12 | | #include "ntp_machine.h" |
13 | | #include "ntp_syslog.h" |
14 | | #include "ntp_stdlib.h" |
15 | | #include "ntp_unixtime.h" |
16 | | #include "lib_strbuf.h" |
17 | | #include "ntp_debug.h" |
18 | | |
19 | | #ifdef HAVE_UNISTD_H |
20 | | #include <unistd.h> |
21 | | #endif |
22 | | |
23 | | #ifdef SYS_WINNT |
24 | | int _getch(void); /* Declare the one function rather than include conio.h */ |
25 | | #else |
26 | | |
27 | | #ifdef SYS_VXWORKS |
28 | | #include "taskLib.h" |
29 | | #include "sysLib.h" |
30 | | #include "time.h" |
31 | | #include "ntp_syslog.h" |
32 | | |
33 | | /* some translations to the world of vxWorkings -casey */ |
34 | | /* first some netdb type things */ |
35 | | #include "ioLib.h" |
36 | | #include <socket.h> |
37 | | int h_errno; |
38 | | |
39 | | struct hostent *gethostbyname(char *name) |
40 | | { |
41 | | struct hostent *host1; |
42 | | h_errno = 0; /* we are always successful!!! */ |
43 | | host1 = (struct hostent *) emalloc (sizeof(struct hostent)); |
44 | | host1->h_name = name; |
45 | | host1->h_addrtype = AF_INET; |
46 | | host1->h_aliases = name; |
47 | | host1->h_length = 4; |
48 | | host1->h_addr_list[0] = (char *)hostGetByName (name); |
49 | | host1->h_addr_list[1] = NULL; |
50 | | return host1; |
51 | | } |
52 | | |
53 | | struct hostent *gethostbyaddr(char *name, int size, int addr_type) |
54 | | { |
55 | | struct hostent *host1; |
56 | | h_errno = 0; /* we are always successful!!! */ |
57 | | host1 = (struct hostent *) emalloc (sizeof(struct hostent)); |
58 | | host1->h_name = name; |
59 | | host1->h_addrtype = AF_INET; |
60 | | host1->h_aliases = name; |
61 | | host1->h_length = 4; |
62 | | host1->h_addr_list = NULL; |
63 | | return host1; |
64 | | } |
65 | | |
66 | | struct servent *getservbyname (char *name, char *type) |
67 | | { |
68 | | struct servent *serv1; |
69 | | serv1 = (struct servent *) emalloc (sizeof(struct servent)); |
70 | | serv1->s_name = "ntp"; /* official service name */ |
71 | | serv1->s_aliases = NULL; /* alias list */ |
72 | | serv1->s_port = 123; /* port # */ |
73 | | serv1->s_proto = "udp"; /* protocol to use */ |
74 | | return serv1; |
75 | | } |
76 | | |
77 | | /* second |
78 | | * vxworks thinks it has insomnia |
79 | | * we have to sleep for number of seconds |
80 | | */ |
81 | | |
82 | | #define CLKRATE sysClkRateGet() |
83 | | |
84 | | /* I am not sure how valid the granularity is - it is from G. Eger's port */ |
85 | | #define CLK_GRANULARITY 1 /* Granularity of system clock in usec */ |
86 | | /* Used to round down # usecs/tick */ |
87 | | /* On a VCOM-100, PIT gets 8 MHz clk, */ |
88 | | /* & it prescales by 32, thus 4 usec */ |
89 | | /* on mv167, granularity is 1usec anyway*/ |
90 | | /* To defeat rounding, set to 1 */ |
91 | | #define USECS_PER_SEC MILLION /* Microseconds per second */ |
92 | | #define TICK (((USECS_PER_SEC / CLKRATE) / CLK_GRANULARITY) * CLK_GRANULARITY) |
93 | | |
94 | | /* emulate unix sleep |
95 | | * casey |
96 | | */ |
97 | | void sleep(int seconds) |
98 | | { |
99 | | taskDelay(seconds*TICK); |
100 | | } |
101 | | /* emulate unix alarm |
102 | | * that pauses and calls SIGALRM after the seconds are up... |
103 | | * so ... taskDelay() fudged for seconds should amount to the same thing. |
104 | | * casey |
105 | | */ |
106 | | void alarm (int seconds) |
107 | | { |
108 | | sleep(seconds); |
109 | | } |
110 | | |
111 | | #endif /* SYS_VXWORKS */ |
112 | | |
113 | | #ifdef SYS_PTX /* Does PTX still need this? */ |
114 | | /*#include <sys/types.h> */ |
115 | | #include <sys/procstats.h> |
116 | | |
117 | | int |
118 | | gettimeofday( |
119 | | struct timeval *tvp |
120 | | ) |
121 | | { |
122 | | /* |
123 | | * hi, this is Sequents sneak path to get to a clock |
124 | | * this is also the most logical syscall for such a function |
125 | | */ |
126 | | return (get_process_stats(tvp, PS_SELF, (struct procstats *) 0, |
127 | | (struct procstats *) 0)); |
128 | | } |
129 | | #endif /* SYS_PTX */ |
130 | | |
131 | | #ifdef MPE |
132 | | /* This is a substitute for bind() that if called for an AF_INET socket |
133 | | port less than 1024, GETPRIVMODE() and GETUSERMODE() calls will be done. */ |
134 | | |
135 | | #undef bind |
136 | | #include <sys/types.h> |
137 | | #include <sys/socket.h> |
138 | | #include <netinet/in.h> |
139 | | #include <sys/un.h> |
140 | | |
141 | | extern void GETPRIVMODE(void); |
142 | | extern void GETUSERMODE(void); |
143 | | |
144 | | int __ntp_mpe_bind(int s, void *addr, int addrlen); |
145 | | |
146 | | int __ntp_mpe_bind(int s, void *addr, int addrlen) { |
147 | | int priv = 0; |
148 | | int result; |
149 | | |
150 | | if (addrlen == sizeof(struct sockaddr_in)) { /* AF_INET */ |
151 | | if (((struct sockaddr_in *)addr)->sin_port > 0 && |
152 | | ((struct sockaddr_in *)addr)->sin_port < 1024) { |
153 | | priv = 1; |
154 | | GETPRIVMODE(); |
155 | | } |
156 | | /* ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0; */ |
157 | | result = bind(s,addr,addrlen); |
158 | | if (priv == 1) GETUSERMODE(); |
159 | | } else /* AF_UNIX */ |
160 | | result = bind(s,addr,addrlen); |
161 | | |
162 | | return result; |
163 | | } |
164 | | |
165 | | /* |
166 | | * MPE stupidly requires sfcntl() to be used on sockets instead of fcntl(), |
167 | | * so we define a wrapper to analyze the file descriptor and call the correct |
168 | | * function. |
169 | | */ |
170 | | |
171 | | #undef fcntl |
172 | | #include <errno.h> |
173 | | #include <fcntl.h> |
174 | | |
175 | | int __ntp_mpe_fcntl(int fd, int cmd, int arg); |
176 | | |
177 | | int __ntp_mpe_fcntl(int fd, int cmd, int arg) { |
178 | | int len; |
179 | | struct sockaddr sa; |
180 | | |
181 | | extern int sfcntl(int, int, int); |
182 | | |
183 | | len = sizeof sa; |
184 | | if (getsockname(fd, &sa, &len) == -1) { |
185 | | if (errno == EAFNOSUPPORT) /* AF_UNIX socket */ |
186 | | return sfcntl(fd, cmd, arg); |
187 | | if (errno == ENOTSOCK) /* file or pipe */ |
188 | | return fcntl(fd, cmd, arg); |
189 | | return (-1); /* unknown getsockname() failure */ |
190 | | } else /* AF_INET socket */ |
191 | | return sfcntl(fd, cmd, arg); |
192 | | } |
193 | | |
194 | | /* |
195 | | * Setitimer emulation support. Note that we implement this using alarm(), |
196 | | * and since alarm() only delivers one signal, we must re-enable the alarm |
197 | | * by enabling our own SIGALRM setitimer_mpe_handler routine to be called |
198 | | * before the real handler routine and re-enable the alarm at that time. |
199 | | * |
200 | | * Note that this solution assumes that sigaction(SIGALRM) is called before |
201 | | * calling setitimer(). If it should ever to become necessary to support |
202 | | * sigaction(SIGALRM) after calling setitimer(), it will be necessary to trap |
203 | | * those sigaction() calls. |
204 | | */ |
205 | | |
206 | | #include <limits.h> |
207 | | #include <signal.h> |
208 | | |
209 | | /* |
210 | | * Some global data that needs to be shared between setitimer() and |
211 | | * setitimer_mpe_handler(). |
212 | | */ |
213 | | |
214 | | struct { |
215 | | unsigned long current_msec; /* current alarm() value in effect */ |
216 | | unsigned long interval_msec; /* next alarm() value from setitimer */ |
217 | | unsigned long value_msec; /* first alarm() value from setitimer */ |
218 | | struct itimerval current_itimerval; /* current itimerval in effect */ |
219 | | struct sigaction oldact; /* SIGALRM state saved by setitimer */ |
220 | | } setitimer_mpe_ctx = { 0, 0, 0 }; |
221 | | |
222 | | /* |
223 | | * Undocumented, unsupported function to do alarm() in milliseconds. |
224 | | */ |
225 | | |
226 | | extern unsigned int px_alarm(unsigned long, int *); |
227 | | |
228 | | /* |
229 | | * The SIGALRM handler routine enabled by setitimer(). Re-enable the alarm or |
230 | | * restore the original SIGALRM setting if no more alarms are needed. Then |
231 | | * call the original SIGALRM handler (if any). |
232 | | */ |
233 | | |
234 | | static RETSIGTYPE setitimer_mpe_handler(int sig) |
235 | | { |
236 | | int alarm_hpe_status; |
237 | | |
238 | | /* Update the new current alarm value */ |
239 | | |
240 | | setitimer_mpe_ctx.current_msec = setitimer_mpe_ctx.interval_msec; |
241 | | |
242 | | if (setitimer_mpe_ctx.interval_msec > 0) { |
243 | | /* Additional intervals needed; re-arm the alarm timer */ |
244 | | px_alarm(setitimer_mpe_ctx.interval_msec,&alarm_hpe_status); |
245 | | } else { |
246 | | /* No more intervals, so restore previous original SIGALRM handler */ |
247 | | sigaction(SIGALRM, &setitimer_mpe_ctx.oldact, NULL); |
248 | | } |
249 | | |
250 | | /* Call the original SIGALRM handler if it is a function and not just a flag */ |
251 | | |
252 | | if (setitimer_mpe_ctx.oldact.sa_handler != SIG_DFL && |
253 | | setitimer_mpe_ctx.oldact.sa_handler != SIG_ERR && |
254 | | setitimer_mpe_ctx.oldact.sa_handler != SIG_IGN) |
255 | | (*setitimer_mpe_ctx.oldact.sa_handler)(SIGALRM); |
256 | | |
257 | | } |
258 | | |
259 | | /* |
260 | | * Our implementation of setitimer(). |
261 | | */ |
262 | | |
263 | | int |
264 | | setitimer(int which, struct itimerval *value, |
265 | | struct itimerval *ovalue) |
266 | | { |
267 | | |
268 | | int alarm_hpe_status; |
269 | | unsigned long remaining_msec, value_msec, interval_msec; |
270 | | struct sigaction newact; |
271 | | |
272 | | /* |
273 | | * Convert the initial interval to milliseconds |
274 | | */ |
275 | | |
276 | | if (value->it_value.tv_sec > (UINT_MAX / 1000)) |
277 | | value_msec = UINT_MAX; |
278 | | else |
279 | | value_msec = value->it_value.tv_sec * 1000; |
280 | | |
281 | | value_msec += value->it_value.tv_usec / 1000; |
282 | | |
283 | | /* |
284 | | * Convert the reset interval to milliseconds |
285 | | */ |
286 | | |
287 | | if (value->it_interval.tv_sec > (UINT_MAX / 1000)) |
288 | | interval_msec = UINT_MAX; |
289 | | else |
290 | | interval_msec = value->it_interval.tv_sec * 1000; |
291 | | |
292 | | interval_msec += value->it_interval.tv_usec / 1000; |
293 | | |
294 | | if (value_msec > 0 && interval_msec > 0) { |
295 | | /* |
296 | | * We'll be starting an interval timer that will be repeating, so we need to |
297 | | * insert our own SIGALRM signal handler to schedule the repeats. |
298 | | */ |
299 | | |
300 | | /* Read the current SIGALRM action */ |
301 | | |
302 | | if (sigaction(SIGALRM, NULL, &setitimer_mpe_ctx.oldact) < 0) { |
303 | | fprintf(stderr,"MPE setitimer old handler failed, errno=%d\n",errno); |
304 | | return -1; |
305 | | } |
306 | | |
307 | | /* Initialize the new action to call our SIGALRM handler instead */ |
308 | | |
309 | | newact.sa_handler = &setitimer_mpe_handler; |
310 | | newact.sa_mask = setitimer_mpe_ctx.oldact.sa_mask; |
311 | | newact.sa_flags = setitimer_mpe_ctx.oldact.sa_flags; |
312 | | |
313 | | if (sigaction(SIGALRM, &newact, NULL) < 0) { |
314 | | fprintf(stderr,"MPE setitimer new handler failed, errno=%d\n",errno); |
315 | | return -1; |
316 | | } |
317 | | } |
318 | | |
319 | | /* |
320 | | * Return previous itimerval if desired |
321 | | */ |
322 | | |
323 | | if (ovalue != NULL) *ovalue = setitimer_mpe_ctx.current_itimerval; |
324 | | |
325 | | /* |
326 | | * Save current parameters for later usage |
327 | | */ |
328 | | |
329 | | setitimer_mpe_ctx.current_itimerval = *value; |
330 | | setitimer_mpe_ctx.current_msec = value_msec; |
331 | | setitimer_mpe_ctx.value_msec = value_msec; |
332 | | setitimer_mpe_ctx.interval_msec = interval_msec; |
333 | | |
334 | | /* |
335 | | * Schedule the first alarm |
336 | | */ |
337 | | |
338 | | remaining_msec = px_alarm(value_msec, &alarm_hpe_status); |
339 | | if (alarm_hpe_status == 0) |
340 | | return (0); |
341 | | else |
342 | | return (-1); |
343 | | } |
344 | | |
345 | | /* |
346 | | * MPE lacks gettimeofday(), so we define our own. |
347 | | */ |
348 | | |
349 | | int gettimeofday(struct timeval *tvp) |
350 | | |
351 | | { |
352 | | /* Documented, supported MPE functions. */ |
353 | | extern void GETPRIVMODE(void); |
354 | | extern void GETUSERMODE(void); |
355 | | |
356 | | /* Undocumented, unsupported MPE functions. */ |
357 | | extern long long get_time(void); |
358 | | extern void get_time_change_info(long long *, char *, char *); |
359 | | extern long long ticks_to_micro(long long); |
360 | | |
361 | | char pwf_since_boot, recover_pwf_time; |
362 | | long long mpetime, offset_ticks, offset_usec; |
363 | | |
364 | | GETPRIVMODE(); |
365 | | mpetime = get_time(); /* MPE local time usecs since Jan 1 1970 */ |
366 | | get_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time); |
367 | | offset_usec = ticks_to_micro(offset_ticks); /* UTC offset usecs */ |
368 | | GETUSERMODE(); |
369 | | |
370 | | mpetime = mpetime - offset_usec; /* Convert from local time to UTC */ |
371 | | tvp->tv_sec = mpetime / 1000000LL; |
372 | | tvp->tv_usec = mpetime % 1000000LL; |
373 | | |
374 | | return 0; |
375 | | } |
376 | | |
377 | | /* |
378 | | * MPE lacks settimeofday(), so we define our own. |
379 | | */ |
380 | | |
381 | | #define HAVE_SETTIMEOFDAY |
382 | | |
383 | | int settimeofday(struct timeval *tvp) |
384 | | |
385 | | { |
386 | | /* Documented, supported MPE functions. */ |
387 | | extern void GETPRIVMODE(void); |
388 | | extern void GETUSERMODE(void); |
389 | | |
390 | | /* Undocumented, unsupported MPE functions. */ |
391 | | extern void get_time_change_info(long long *, char *, char *); |
392 | | extern void initialize_system_time(long long, int); |
393 | | extern void set_time_correction(long long, int, int); |
394 | | extern long long ticks_to_micro(long long); |
395 | | |
396 | | char pwf_since_boot, recover_pwf_time; |
397 | | long long big_sec, big_usec, mpetime, offset_ticks, offset_usec; |
398 | | |
399 | | big_sec = tvp->tv_sec; |
400 | | big_usec = tvp->tv_usec; |
401 | | mpetime = (big_sec * 1000000LL) + big_usec; /* Desired UTC microseconds */ |
402 | | |
403 | | GETPRIVMODE(); |
404 | | set_time_correction(0LL,0,0); /* Cancel previous time correction, if any */ |
405 | | get_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time); |
406 | | offset_usec = ticks_to_micro(offset_ticks); /* UTC offset microseconds */ |
407 | | mpetime = mpetime + offset_usec; /* Convert from UTC to local time */ |
408 | | initialize_system_time(mpetime,1); |
409 | | GETUSERMODE(); |
410 | | |
411 | | return 0; |
412 | | } |
413 | | #endif /* MPE */ |
414 | | |
415 | | #define SET_TOD_UNDETERMINED 0 |
416 | 0 | #define SET_TOD_CLOCK_SETTIME 1 |
417 | 0 | #define SET_TOD_SETTIMEOFDAY 2 |
418 | | #define SET_TOD_STIME 3 |
419 | | |
420 | | const char * const set_tod_used[] = { |
421 | | "undetermined", |
422 | | "clock_settime", |
423 | | "settimeofday", |
424 | | "stime" |
425 | | }; |
426 | | |
427 | | pset_tod_using set_tod_using = NULL; |
428 | | |
429 | | |
430 | | int |
431 | | ntp_set_tod( |
432 | | struct timeval *tvp, |
433 | | void *tzp |
434 | | ) |
435 | 0 | { |
436 | 0 | static int tod; |
437 | 0 | int rc; |
438 | 0 | int saved_errno; |
439 | |
|
440 | 0 | TRACE(1, ("In ntp_set_tod\n")); |
441 | 0 | rc = -1; |
442 | 0 | saved_errno = 0; |
443 | |
|
444 | 0 | #ifdef HAVE_CLOCK_SETTIME |
445 | 0 | if (rc && (SET_TOD_CLOCK_SETTIME == tod || !tod)) { |
446 | 0 | struct timespec ts; |
447 | | |
448 | | /* Convert timeval to timespec */ |
449 | 0 | ts.tv_sec = tvp->tv_sec; |
450 | 0 | ts.tv_nsec = 1000 * tvp->tv_usec; |
451 | |
|
452 | 0 | errno = 0; |
453 | 0 | rc = clock_settime(CLOCK_REALTIME, &ts); |
454 | 0 | saved_errno = errno; |
455 | 0 | TRACE(1, ("ntp_set_tod: clock_settime: %d %m\n", rc)); |
456 | 0 | if (!tod && !rc) |
457 | 0 | tod = SET_TOD_CLOCK_SETTIME; |
458 | |
|
459 | 0 | } |
460 | 0 | #endif /* HAVE_CLOCK_SETTIME */ |
461 | 0 | #ifdef HAVE_SETTIMEOFDAY |
462 | 0 | if (rc && (SET_TOD_SETTIMEOFDAY == tod || !tod)) { |
463 | 0 | struct timeval adjtv; |
464 | | |
465 | | /* |
466 | | * Some broken systems don't reset adjtime() when the |
467 | | * clock is stepped. |
468 | | */ |
469 | 0 | adjtv.tv_sec = adjtv.tv_usec = 0; |
470 | 0 | adjtime(&adjtv, NULL); |
471 | 0 | errno = 0; |
472 | 0 | rc = SETTIMEOFDAY(tvp, tzp); |
473 | 0 | saved_errno = errno; |
474 | 0 | TRACE(1, ("ntp_set_tod: settimeofday: %d %m\n", rc)); |
475 | 0 | if (!tod && !rc) |
476 | 0 | tod = SET_TOD_SETTIMEOFDAY; |
477 | 0 | } |
478 | 0 | #endif /* HAVE_SETTIMEOFDAY */ |
479 | | #ifdef HAVE_STIME |
480 | | if (rc && (SET_TOD_STIME == tod || !tod)) { |
481 | | long tp = tvp->tv_sec; |
482 | | |
483 | | errno = 0; |
484 | | rc = stime(&tp); /* lie as bad as SysVR4 */ |
485 | | saved_errno = errno; |
486 | | TRACE(1, ("ntp_set_tod: stime: %d %m\n", rc)); |
487 | | if (!tod && !rc) |
488 | | tod = SET_TOD_STIME; |
489 | | } |
490 | | #endif /* HAVE_STIME */ |
491 | |
|
492 | 0 | errno = saved_errno; /* for %m below */ |
493 | 0 | TRACE(1, ("ntp_set_tod: Final result: %s: %d %m\n", |
494 | 0 | set_tod_used[tod], rc)); |
495 | | /* |
496 | | * Say how we're setting the time of day |
497 | | */ |
498 | 0 | if (!rc && NULL != set_tod_using) { |
499 | 0 | (*set_tod_using)(set_tod_used[tod]); |
500 | 0 | set_tod_using = NULL; |
501 | 0 | } |
502 | |
|
503 | 0 | if (rc) |
504 | 0 | errno = saved_errno; |
505 | |
|
506 | 0 | return rc; |
507 | 0 | } |
508 | | |
509 | | #endif /* not SYS_WINNT */ |
510 | | |
511 | | #if defined (SYS_WINNT) || defined (SYS_VXWORKS) || defined(MPE) |
512 | | /* getpass is used in ntpq.c and ntpdc.c */ |
513 | | |
514 | | char * |
515 | | getpass(const char * prompt) |
516 | | { |
517 | | int c, i; |
518 | | static char password[32]; |
519 | | |
520 | | fprintf(stderr, "%s", prompt); |
521 | | fflush(stderr); |
522 | | |
523 | | for (i=0; i<sizeof(password)-1 && ((c=_getch())!='\n' && c!='\r'); i++) { |
524 | | password[i] = (char) c; |
525 | | } |
526 | | password[i] = '\0'; |
527 | | |
528 | | fputc('\n', stderr); |
529 | | fflush(stderr); |
530 | | |
531 | | return password; |
532 | | } |
533 | | #endif /* SYS_WINNT */ |