Annotation of embedaddon/ntp/libntp/machines.c, revision 1.1
1.1 ! misho 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 "lib_strbuf.h"
! 17:
! 18: #ifdef HAVE_UNISTD_H
! 19: #include <unistd.h>
! 20: #endif
! 21:
! 22: #ifdef SYS_WINNT
! 23: int _getch(void); /* Declare the one function rather than include conio.h */
! 24: #else
! 25:
! 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 *) malloc (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 *) malloc (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 *) 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 */
! 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 = -1;
! 437: int saved_errno = 0;
! 438:
! 439: #ifdef DEBUG
! 440: if (debug)
! 441: printf("In ntp_set_tod\n");
! 442: #endif
! 443:
! 444: #ifdef HAVE_CLOCK_SETTIME
! 445: if (rc && (SET_TOD_CLOCK_SETTIME == tod || !tod)) {
! 446: struct timespec ts;
! 447:
! 448: /* Convert timeval to timespec */
! 449: ts.tv_sec = tvp->tv_sec;
! 450: ts.tv_nsec = 1000 * tvp->tv_usec;
! 451:
! 452: errno = 0;
! 453: rc = clock_settime(CLOCK_REALTIME, &ts);
! 454: saved_errno = errno;
! 455: #ifdef DEBUG
! 456: if (debug) {
! 457: printf("ntp_set_tod: clock_settime: %d: %s\n",
! 458: rc, strerror(saved_errno));
! 459: }
! 460: #endif
! 461: if (!tod && !rc)
! 462: tod = SET_TOD_CLOCK_SETTIME;
! 463:
! 464: }
! 465: #endif /* HAVE_CLOCK_SETTIME */
! 466: #ifdef HAVE_SETTIMEOFDAY
! 467: if (rc && (SET_TOD_SETTIMEOFDAY == tod || !tod)) {
! 468: struct timeval adjtv;
! 469:
! 470: /*
! 471: * Some broken systems don't reset adjtime() when the
! 472: * clock is stepped.
! 473: */
! 474: adjtv.tv_sec = adjtv.tv_usec = 0;
! 475: adjtime(&adjtv, NULL);
! 476: errno = 0;
! 477: rc = SETTIMEOFDAY(tvp, tzp);
! 478: saved_errno = errno;
! 479: #ifdef DEBUG
! 480: if (debug) {
! 481: printf("ntp_set_tod: settimeofday: %d: %s\n",
! 482: rc, strerror(saved_errno));
! 483: }
! 484: #endif
! 485: if (!tod && !rc)
! 486: tod = SET_TOD_SETTIMEOFDAY;
! 487: }
! 488: #endif /* HAVE_SETTIMEOFDAY */
! 489: #ifdef HAVE_STIME
! 490: if (rc && (SET_TOD_STIME == tod || !tod)) {
! 491: long tp = tvp->tv_sec;
! 492:
! 493: errno = 0;
! 494: rc = stime(&tp); /* lie as bad as SysVR4 */
! 495: saved_errno = errno;
! 496: #ifdef DEBUG
! 497: if (debug) {
! 498: printf("ntp_set_tod: stime: %d: %s\n",
! 499: rc, strerror(saved_errno));
! 500: }
! 501: #endif
! 502: if (!tod && !rc)
! 503: tod = SET_TOD_STIME;
! 504: }
! 505: #endif /* HAVE_STIME */
! 506:
! 507: #ifdef DEBUG
! 508: if (debug) {
! 509: printf("ntp_set_tod: Final result: %s: %d: %s\n",
! 510: set_tod_used[tod], rc, strerror(saved_errno));
! 511: }
! 512: #endif
! 513: /*
! 514: * Say how we're setting the time of day
! 515: */
! 516: if (!rc && NULL != set_tod_using) {
! 517: (*set_tod_using)(set_tod_used[tod]);
! 518: set_tod_using = NULL;
! 519: }
! 520:
! 521: if (rc)
! 522: errno = saved_errno;
! 523:
! 524: return rc;
! 525: }
! 526:
! 527: #endif /* not SYS_WINNT */
! 528:
! 529: #if defined (SYS_WINNT) || defined (SYS_VXWORKS) || defined(MPE)
! 530: /* getpass is used in ntpq.c and ntpdc.c */
! 531:
! 532: char *
! 533: getpass(const char * prompt)
! 534: {
! 535: int c, i;
! 536: static char password[32];
! 537:
! 538: fprintf(stderr, "%s", prompt);
! 539: fflush(stderr);
! 540:
! 541: for (i=0; i<sizeof(password)-1 && ((c=_getch())!='\n' && c!='\r'); i++) {
! 542: password[i] = (char) c;
! 543: }
! 544: password[i] = '\0';
! 545:
! 546: fputc('\n', stderr);
! 547: fflush(stderr);
! 548:
! 549: return password;
! 550: }
! 551: #endif /* SYS_WINNT */
! 552:
! 553: #if !defined(HAVE_MEMSET)
! 554: void
! 555: ntp_memset(
! 556: char *a,
! 557: int x,
! 558: int c
! 559: )
! 560: {
! 561: while (c-- > 0)
! 562: *a++ = (char) x;
! 563: }
! 564: #endif /*POSIX*/
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>