1 /* $NetBSD: machines.c,v 1.3 2006/06/11 19:34:10 kardel Exp $ */
3 /* machines.c - provide special support for peculiar architectures
13 #include "ntp_machine.h"
14 #include "ntp_syslog.h"
15 #include "ntp_stdlib.h"
16 #include "ntp_unixtime.h"
23 int _getch(void); /* Declare the one function rather than include conio.h */
30 #include "ntp_syslog.h"
32 /* some translations to the world of vxWorkings -casey */
33 /* first some netdb type things */
38 struct hostent
*gethostbyname(char *name
)
40 struct hostent
*host1
;
41 h_errno
= 0; /* we are always successful!!! */
42 host1
= (struct hostent
*) malloc (sizeof(struct hostent
));
44 host1
->h_addrtype
= AF_INET
;
45 host1
->h_aliases
= name
;
47 host1
->h_addr_list
[0] = (char *)hostGetByName (name
);
48 host1
->h_addr_list
[1] = NULL
;
52 struct hostent
*gethostbyaddr(char *name
, int size
, int addr_type
)
54 struct hostent
*host1
;
55 h_errno
= 0; /* we are always successful!!! */
56 host1
= (struct hostent
*) malloc (sizeof(struct hostent
));
58 host1
->h_addrtype
= AF_INET
;
59 host1
->h_aliases
= name
;
61 host1
->h_addr_list
= NULL
;
65 struct servent
*getservbyname (char *name
, char *type
)
67 struct servent
*serv1
;
68 serv1
= (struct servent
*) malloc (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 */
77 * vxworks thinks it has insomnia
78 * we have to sleep for number of seconds
81 #define CLKRATE sysClkRateGet()
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)
96 void sleep(int seconds
)
98 taskDelay(seconds
*TICK
);
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.
105 void alarm (int seconds
)
110 #endif /* SYS_VXWORKS */
112 #ifdef SYS_PTX /* Does PTX still need this? */
113 /*#include <sys/types.h> */
114 #include <sys/procstats.h>
122 * hi, this is Sequents sneak path to get to a clock
123 * this is also the most logical syscall for such a function
125 return (get_process_stats(tvp
, PS_SELF
, (struct procstats
*) 0,
126 (struct procstats
*) 0));
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. */
135 #include <sys/types.h>
136 #include <sys/socket.h>
137 #include <netinet/in.h>
140 extern void GETPRIVMODE(void);
141 extern void GETUSERMODE(void);
143 int __ntp_mpe_bind(int s
, void *addr
, int addrlen
);
145 int __ntp_mpe_bind(int s
, void *addr
, int addrlen
) {
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) {
155 /* ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0; */
156 result
= bind(s
,addr
,addrlen
);
157 if (priv
== 1) GETUSERMODE();
159 result
= bind(s
,addr
,addrlen
);
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
174 int __ntp_mpe_fcntl(int fd
, int cmd
, int arg
);
176 int __ntp_mpe_fcntl(int fd
, int cmd
, int arg
) {
180 extern int sfcntl(int, int, int);
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
);
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.
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.
209 * Some global data that needs to be shared between setitimer() and
210 * setitimer_mpe_handler().
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 };
222 * Undocumented, unsupported function to do alarm() in milliseconds.
225 extern unsigned int px_alarm(unsigned long, int *);
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).
233 static RETSIGTYPE
setitimer_mpe_handler(int sig
)
235 int alarm_hpe_status
;
237 /* Update the new current alarm value */
239 setitimer_mpe_ctx
.current_msec
= setitimer_mpe_ctx
.interval_msec
;
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
);
245 /* No more intervals, so restore previous original SIGALRM handler */
246 sigaction(SIGALRM
, &setitimer_mpe_ctx
.oldact
, NULL
);
249 /* Call the original SIGALRM handler if it is a function and not just a flag */
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
);
259 * Our implementation of setitimer().
263 setitimer(int which
, struct itimerval
*value
,
264 struct itimerval
*ovalue
)
267 int alarm_hpe_status
;
268 unsigned long remaining_msec
, value_msec
, interval_msec
;
269 struct sigaction newact
;
272 * Convert the initial interval to milliseconds
275 if (value
->it_value
.tv_sec
> (UINT_MAX
/ 1000))
276 value_msec
= UINT_MAX
;
278 value_msec
= value
->it_value
.tv_sec
* 1000;
280 value_msec
+= value
->it_value
.tv_usec
/ 1000;
283 * Convert the reset interval to milliseconds
286 if (value
->it_interval
.tv_sec
> (UINT_MAX
/ 1000))
287 interval_msec
= UINT_MAX
;
289 interval_msec
= value
->it_interval
.tv_sec
* 1000;
291 interval_msec
+= value
->it_interval
.tv_usec
/ 1000;
293 if (value_msec
> 0 && interval_msec
> 0) {
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.
299 /* Read the current SIGALRM action */
301 if (sigaction(SIGALRM
, NULL
, &setitimer_mpe_ctx
.oldact
) < 0) {
302 fprintf(stderr
,"MPE setitimer old handler failed, errno=%d\n",errno
);
306 /* Initialize the new action to call our SIGALRM handler instead */
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
;
312 if (sigaction(SIGALRM
, &newact
, NULL
) < 0) {
313 fprintf(stderr
,"MPE setitimer new handler failed, errno=%d\n",errno
);
319 * Return previous itimerval if desired
322 if (ovalue
!= NULL
) *ovalue
= setitimer_mpe_ctx
.current_itimerval
;
325 * Save current parameters for later usage
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
;
334 * Schedule the first alarm
337 remaining_msec
= px_alarm(value_msec
, &alarm_hpe_status
);
338 if (alarm_hpe_status
== 0)
345 * MPE lacks gettimeofday(), so we define our own.
348 int gettimeofday(struct timeval
*tvp
)
351 /* Documented, supported MPE functions. */
352 extern void GETPRIVMODE(void);
353 extern void GETUSERMODE(void);
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);
360 char pwf_since_boot
, recover_pwf_time
;
361 long long mpetime
, offset_ticks
, offset_usec
;
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 */
369 mpetime
= mpetime
- offset_usec
; /* Convert from local time to UTC */
370 tvp
->tv_sec
= mpetime
/ 1000000LL;
371 tvp
->tv_usec
= mpetime
% 1000000LL;
377 * MPE lacks settimeofday(), so we define our own.
380 #define HAVE_SETTIMEOFDAY
382 int settimeofday(struct timeval
*tvp
)
385 /* Documented, supported MPE functions. */
386 extern void GETPRIVMODE(void);
387 extern void GETUSERMODE(void);
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);
395 char pwf_since_boot
, recover_pwf_time
;
396 long long big_sec
, big_usec
, mpetime
, offset_ticks
, offset_usec
;
398 big_sec
= tvp
->tv_sec
;
399 big_usec
= tvp
->tv_usec
;
400 mpetime
= (big_sec
* 1000000LL) + big_usec
; /* Desired UTC microseconds */
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);
414 const char *set_tod_using
= "UNKNOWN";
426 printf("In ntp_set_tod\n");
429 #ifdef HAVE_CLOCK_SETTIME
433 set_tod_using
= "clock_settime";
434 /* Convert timeval to timespec */
435 ts
.tv_sec
= tvp
->tv_sec
;
436 ts
.tv_nsec
= 1000 * tvp
->tv_usec
;
439 rc
= clock_settime(CLOCK_REALTIME
, &ts
);
442 printf("ntp_set_tod: %s: %d: %s\n",
443 set_tod_using
, rc
, strerror(errno
));
447 #endif /* HAVE_CLOCK_SETTIME */
448 #ifdef HAVE_SETTIMEOFDAY
450 struct timeval adjtv
;
452 set_tod_using
= "settimeofday";
454 * Some broken systems don't reset adjtime() when the
457 adjtv
.tv_sec
= adjtv
.tv_usec
= 0;
458 adjtime(&adjtv
, NULL
);
460 rc
= SETTIMEOFDAY(tvp
, tzp
);
463 printf("ntp_set_tod: %s: %d: %s\n",
464 set_tod_using
, rc
, strerror(errno
));
468 #endif /* HAVE_SETTIMEOFDAY */
471 long tp
= tvp
->tv_sec
;
473 set_tod_using
= "stime";
475 rc
= stime(&tp
); /* lie as bad as SysVR4 */
478 printf("ntp_set_tod: %s: %d: %s\n",
479 set_tod_using
, rc
, strerror(errno
));
483 #endif /* HAVE_STIME */
485 set_tod_using
= "Failed!";
488 printf("ntp_set_tod: Final result: %s: %d: %s\n",
489 set_tod_using
, rc
, strerror(errno
));
495 #endif /* not SYS_WINNT */
497 #if defined (SYS_WINNT) || defined (SYS_VXWORKS) || defined(MPE)
498 /* getpass is used in ntpq.c and ntpdc.c */
501 getpass(const char * prompt
)
504 static char password
[32];
506 fprintf(stderr
, "%s", prompt
);
509 for (i
=0; i
<sizeof(password
)-1 && ((c
=_getch())!='\n' && c
!='\r'); i
++) {
510 password
[i
] = (char) c
;
516 #endif /* SYS_WINNT */
518 #if !defined(HAVE_MEMSET)