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