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