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 #define SET_TOD_CLOCK_SETTIME 1 416 #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 { 435 static int tod; 436 int rc; 437 int saved_errno; 438 439 TRACE(1, ("In ntp_set_tod\n")); 440 rc = -1; 441 saved_errno = 0; 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 TRACE(1, ("ntp_set_tod: clock_settime: %d %m\n", rc)); 455 if (!tod && !rc) 456 tod = SET_TOD_CLOCK_SETTIME; 457 458 } 459 #endif /* HAVE_CLOCK_SETTIME */ 460 #ifdef HAVE_SETTIMEOFDAY 461 if (rc && (SET_TOD_SETTIMEOFDAY == tod || !tod)) { 462 struct timeval adjtv; 463 464 /* 465 * Some broken systems don't reset adjtime() when the 466 * clock is stepped. 467 */ 468 adjtv.tv_sec = adjtv.tv_usec = 0; 469 adjtime(&adjtv, NULL); 470 errno = 0; 471 rc = SETTIMEOFDAY(tvp, tzp); 472 saved_errno = errno; 473 TRACE(1, ("ntp_set_tod: settimeofday: %d %m\n", rc)); 474 if (!tod && !rc) 475 tod = SET_TOD_SETTIMEOFDAY; 476 } 477 #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 errno = saved_errno; /* for %m below */ 492 TRACE(1, ("ntp_set_tod: Final result: %s: %d %m\n", 493 set_tod_used[tod], rc)); 494 /* 495 * Say how we're setting the time of day 496 */ 497 if (!rc && NULL != set_tod_using) { 498 (*set_tod_using)(set_tod_used[tod]); 499 set_tod_using = NULL; 500 } 501 502 if (rc) 503 errno = saved_errno; 504 505 return rc; 506 } 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 { 564 int i; 565 566 for (i = 0; baudTable[i][1] >= 0; ++i) { 567 if (baudTable[i][0] == symBaud) { 568 break; 569 } 570 } 571 return baudTable[i][1]; 572 } 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 */ 588