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