154359Sroberto/* machines.c - provide special support for peculiar architectures 254359Sroberto * 354359Sroberto * Real bummers unite ! 454359Sroberto * 554359Sroberto */ 654359Sroberto 754359Sroberto#ifdef HAVE_CONFIG_H 854359Sroberto#include "config.h" 954359Sroberto#endif 1054359Sroberto 11290001Sglebius#include "ntp.h" 1254359Sroberto#include "ntp_machine.h" 1354359Sroberto#include "ntp_syslog.h" 1454359Sroberto#include "ntp_stdlib.h" 1554359Sroberto#include "ntp_unixtime.h" 16290001Sglebius#include "lib_strbuf.h" 17290001Sglebius#include "ntp_debug.h" 1854359Sroberto 1954359Sroberto#ifdef HAVE_UNISTD_H 2054359Sroberto#include <unistd.h> 2154359Sroberto#endif 2254359Sroberto 2354359Sroberto#ifdef SYS_WINNT 24132451Srobertoint _getch(void); /* Declare the one function rather than include conio.h */ 2554359Sroberto#else 2654359Sroberto 2754359Sroberto#ifdef SYS_VXWORKS 2854359Sroberto#include "taskLib.h" 2954359Sroberto#include "sysLib.h" 3054359Sroberto#include "time.h" 3154359Sroberto#include "ntp_syslog.h" 3254359Sroberto 3354359Sroberto/* some translations to the world of vxWorkings -casey */ 3454359Sroberto/* first some netdb type things */ 3554359Sroberto#include "ioLib.h" 3654359Sroberto#include <socket.h> 3754359Srobertoint h_errno; 3854359Sroberto 3954359Srobertostruct hostent *gethostbyname(char *name) 4054359Sroberto { 4154359Sroberto struct hostent *host1; 4254359Sroberto h_errno = 0; /* we are always successful!!! */ 43290001Sglebius host1 = (struct hostent *) emalloc (sizeof(struct hostent)); 4454359Sroberto host1->h_name = name; 4554359Sroberto host1->h_addrtype = AF_INET; 4654359Sroberto host1->h_aliases = name; 4754359Sroberto host1->h_length = 4; 4854359Sroberto host1->h_addr_list[0] = (char *)hostGetByName (name); 4954359Sroberto host1->h_addr_list[1] = NULL; 5054359Sroberto return host1; 5154359Sroberto } 5254359Sroberto 5354359Srobertostruct hostent *gethostbyaddr(char *name, int size, int addr_type) 5454359Sroberto { 5554359Sroberto struct hostent *host1; 5654359Sroberto h_errno = 0; /* we are always successful!!! */ 57290001Sglebius host1 = (struct hostent *) emalloc (sizeof(struct hostent)); 5854359Sroberto host1->h_name = name; 5954359Sroberto host1->h_addrtype = AF_INET; 6054359Sroberto host1->h_aliases = name; 6154359Sroberto host1->h_length = 4; 6254359Sroberto host1->h_addr_list = NULL; 6354359Sroberto return host1; 6454359Sroberto } 6554359Sroberto 6654359Srobertostruct servent *getservbyname (char *name, char *type) 6754359Sroberto { 6854359Sroberto struct servent *serv1; 69290001Sglebius serv1 = (struct servent *) emalloc (sizeof(struct servent)); 7054359Sroberto serv1->s_name = "ntp"; /* official service name */ 7154359Sroberto serv1->s_aliases = NULL; /* alias list */ 7254359Sroberto serv1->s_port = 123; /* port # */ 7354359Sroberto serv1->s_proto = "udp"; /* protocol to use */ 7454359Sroberto return serv1; 7554359Sroberto } 7654359Sroberto 7754359Sroberto/* second 7854359Sroberto * vxworks thinks it has insomnia 7954359Sroberto * we have to sleep for number of seconds 8054359Sroberto */ 8154359Sroberto 8254359Sroberto#define CLKRATE sysClkRateGet() 8354359Sroberto 8454359Sroberto/* I am not sure how valid the granularity is - it is from G. Eger's port */ 8554359Sroberto#define CLK_GRANULARITY 1 /* Granularity of system clock in usec */ 8654359Sroberto /* Used to round down # usecs/tick */ 8754359Sroberto /* On a VCOM-100, PIT gets 8 MHz clk, */ 8854359Sroberto /* & it prescales by 32, thus 4 usec */ 8954359Sroberto /* on mv167, granularity is 1usec anyway*/ 9054359Sroberto /* To defeat rounding, set to 1 */ 9154359Sroberto#define USECS_PER_SEC MILLION /* Microseconds per second */ 9254359Sroberto#define TICK (((USECS_PER_SEC / CLKRATE) / CLK_GRANULARITY) * CLK_GRANULARITY) 9354359Sroberto 9454359Sroberto/* emulate unix sleep 9554359Sroberto * casey 9654359Sroberto */ 9754359Srobertovoid sleep(int seconds) 9854359Sroberto { 9954359Sroberto taskDelay(seconds*TICK); 10054359Sroberto } 10154359Sroberto/* emulate unix alarm 10254359Sroberto * that pauses and calls SIGALRM after the seconds are up... 10354359Sroberto * so ... taskDelay() fudged for seconds should amount to the same thing. 10454359Sroberto * casey 10554359Sroberto */ 10654359Srobertovoid alarm (int seconds) 10754359Sroberto { 10854359Sroberto sleep(seconds); 10954359Sroberto } 11054359Sroberto 11154359Sroberto#endif /* SYS_VXWORKS */ 11254359Sroberto 11354359Sroberto#ifdef SYS_PTX /* Does PTX still need this? */ 11454359Sroberto/*#include <sys/types.h> */ 11554359Sroberto#include <sys/procstats.h> 11654359Sroberto 11754359Srobertoint 11854359Srobertogettimeofday( 11954359Sroberto struct timeval *tvp 12054359Sroberto ) 12154359Sroberto{ 12254359Sroberto /* 12354359Sroberto * hi, this is Sequents sneak path to get to a clock 12454359Sroberto * this is also the most logical syscall for such a function 12554359Sroberto */ 12654359Sroberto return (get_process_stats(tvp, PS_SELF, (struct procstats *) 0, 12754359Sroberto (struct procstats *) 0)); 12854359Sroberto} 12954359Sroberto#endif /* SYS_PTX */ 13054359Sroberto 131106163Sroberto#ifdef MPE 132106163Sroberto/* This is a substitute for bind() that if called for an AF_INET socket 133106163Srobertoport less than 1024, GETPRIVMODE() and GETUSERMODE() calls will be done. */ 134106163Sroberto 135106163Sroberto#undef bind 136106163Sroberto#include <sys/types.h> 137106163Sroberto#include <sys/socket.h> 138106163Sroberto#include <netinet/in.h> 139106163Sroberto#include <sys/un.h> 140106163Sroberto 141106163Srobertoextern void GETPRIVMODE(void); 142106163Srobertoextern void GETUSERMODE(void); 143106163Sroberto 144106163Srobertoint __ntp_mpe_bind(int s, void *addr, int addrlen); 145106163Sroberto 146106163Srobertoint __ntp_mpe_bind(int s, void *addr, int addrlen) { 147106163Sroberto int priv = 0; 148106163Sroberto int result; 149106163Sroberto 150106163Srobertoif (addrlen == sizeof(struct sockaddr_in)) { /* AF_INET */ 151106163Sroberto if (((struct sockaddr_in *)addr)->sin_port > 0 && 152106163Sroberto ((struct sockaddr_in *)addr)->sin_port < 1024) { 153106163Sroberto priv = 1; 154106163Sroberto GETPRIVMODE(); 155106163Sroberto } 156106163Sroberto/* ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0; */ 157106163Sroberto result = bind(s,addr,addrlen); 158106163Sroberto if (priv == 1) GETUSERMODE(); 159106163Sroberto} else /* AF_UNIX */ 160106163Sroberto result = bind(s,addr,addrlen); 161106163Sroberto 162106163Srobertoreturn result; 163106163Sroberto} 164106163Sroberto 165106163Sroberto/* 166106163Sroberto * MPE stupidly requires sfcntl() to be used on sockets instead of fcntl(), 167106163Sroberto * so we define a wrapper to analyze the file descriptor and call the correct 168106163Sroberto * function. 169106163Sroberto */ 170106163Sroberto 171106163Sroberto#undef fcntl 172106163Sroberto#include <errno.h> 173106163Sroberto#include <fcntl.h> 174106163Sroberto 175106163Srobertoint __ntp_mpe_fcntl(int fd, int cmd, int arg); 176106163Sroberto 177106163Srobertoint __ntp_mpe_fcntl(int fd, int cmd, int arg) { 178106163Sroberto int len; 179106163Sroberto struct sockaddr sa; 180106163Sroberto 181106163Sroberto extern int sfcntl(int, int, int); 182106163Sroberto 183106163Sroberto len = sizeof sa; 184106163Sroberto if (getsockname(fd, &sa, &len) == -1) { 185106163Sroberto if (errno == EAFNOSUPPORT) /* AF_UNIX socket */ 186106163Sroberto return sfcntl(fd, cmd, arg); 187106163Sroberto if (errno == ENOTSOCK) /* file or pipe */ 188106163Sroberto return fcntl(fd, cmd, arg); 189106163Sroberto return (-1); /* unknown getsockname() failure */ 190106163Sroberto } else /* AF_INET socket */ 191106163Sroberto return sfcntl(fd, cmd, arg); 192106163Sroberto} 193106163Sroberto 194106163Sroberto/* 195106163Sroberto * Setitimer emulation support. Note that we implement this using alarm(), 196106163Sroberto * and since alarm() only delivers one signal, we must re-enable the alarm 197106163Sroberto * by enabling our own SIGALRM setitimer_mpe_handler routine to be called 198106163Sroberto * before the real handler routine and re-enable the alarm at that time. 199106163Sroberto * 200106163Sroberto * Note that this solution assumes that sigaction(SIGALRM) is called before 201106163Sroberto * calling setitimer(). If it should ever to become necessary to support 202106163Sroberto * sigaction(SIGALRM) after calling setitimer(), it will be necessary to trap 203106163Sroberto * those sigaction() calls. 204106163Sroberto */ 205106163Sroberto 206106163Sroberto#include <limits.h> 207106163Sroberto#include <signal.h> 208106163Sroberto 209106163Sroberto/* 210106163Sroberto * Some global data that needs to be shared between setitimer() and 211106163Sroberto * setitimer_mpe_handler(). 212106163Sroberto */ 213106163Sroberto 214106163Srobertostruct { 215106163Sroberto unsigned long current_msec; /* current alarm() value in effect */ 216106163Sroberto unsigned long interval_msec; /* next alarm() value from setitimer */ 217106163Sroberto unsigned long value_msec; /* first alarm() value from setitimer */ 218106163Sroberto struct itimerval current_itimerval; /* current itimerval in effect */ 219106163Sroberto struct sigaction oldact; /* SIGALRM state saved by setitimer */ 220106163Sroberto} setitimer_mpe_ctx = { 0, 0, 0 }; 221106163Sroberto 222106163Sroberto/* 223106163Sroberto * Undocumented, unsupported function to do alarm() in milliseconds. 224106163Sroberto */ 225106163Sroberto 226106163Srobertoextern unsigned int px_alarm(unsigned long, int *); 227106163Sroberto 228106163Sroberto/* 229106163Sroberto * The SIGALRM handler routine enabled by setitimer(). Re-enable the alarm or 230106163Sroberto * restore the original SIGALRM setting if no more alarms are needed. Then 231106163Sroberto * call the original SIGALRM handler (if any). 232106163Sroberto */ 233106163Sroberto 234106163Srobertostatic RETSIGTYPE setitimer_mpe_handler(int sig) 235106163Sroberto{ 236106163Srobertoint alarm_hpe_status; 237106163Sroberto 238106163Sroberto/* Update the new current alarm value */ 239106163Sroberto 240106163Srobertosetitimer_mpe_ctx.current_msec = setitimer_mpe_ctx.interval_msec; 241106163Sroberto 242106163Srobertoif (setitimer_mpe_ctx.interval_msec > 0) { 243106163Sroberto /* Additional intervals needed; re-arm the alarm timer */ 244106163Sroberto px_alarm(setitimer_mpe_ctx.interval_msec,&alarm_hpe_status); 245106163Sroberto} else { 246106163Sroberto /* No more intervals, so restore previous original SIGALRM handler */ 247106163Sroberto sigaction(SIGALRM, &setitimer_mpe_ctx.oldact, NULL); 248106163Sroberto} 249106163Sroberto 250106163Sroberto/* Call the original SIGALRM handler if it is a function and not just a flag */ 251106163Sroberto 252106163Srobertoif (setitimer_mpe_ctx.oldact.sa_handler != SIG_DFL && 253106163Sroberto setitimer_mpe_ctx.oldact.sa_handler != SIG_ERR && 254106163Sroberto setitimer_mpe_ctx.oldact.sa_handler != SIG_IGN) 255106163Sroberto (*setitimer_mpe_ctx.oldact.sa_handler)(SIGALRM); 256106163Sroberto 257106163Sroberto} 258106163Sroberto 259106163Sroberto/* 260106163Sroberto * Our implementation of setitimer(). 261106163Sroberto */ 262106163Sroberto 263106163Srobertoint 264106163Srobertosetitimer(int which, struct itimerval *value, 265106163Sroberto struct itimerval *ovalue) 266106163Sroberto{ 267106163Sroberto 268106163Srobertoint alarm_hpe_status; 269106163Srobertounsigned long remaining_msec, value_msec, interval_msec; 270106163Srobertostruct sigaction newact; 271106163Sroberto 272106163Sroberto/* 273106163Sroberto * Convert the initial interval to milliseconds 274106163Sroberto */ 275106163Sroberto 276106163Srobertoif (value->it_value.tv_sec > (UINT_MAX / 1000)) 277106163Sroberto value_msec = UINT_MAX; 278106163Srobertoelse 279106163Sroberto value_msec = value->it_value.tv_sec * 1000; 280106163Sroberto 281106163Srobertovalue_msec += value->it_value.tv_usec / 1000; 282106163Sroberto 283106163Sroberto/* 284106163Sroberto * Convert the reset interval to milliseconds 285106163Sroberto */ 286106163Sroberto 287106163Srobertoif (value->it_interval.tv_sec > (UINT_MAX / 1000)) 288106163Sroberto interval_msec = UINT_MAX; 289106163Srobertoelse 290106163Sroberto interval_msec = value->it_interval.tv_sec * 1000; 291106163Sroberto 292106163Srobertointerval_msec += value->it_interval.tv_usec / 1000; 293106163Sroberto 294106163Srobertoif (value_msec > 0 && interval_msec > 0) { 295106163Sroberto /* 296106163Sroberto * We'll be starting an interval timer that will be repeating, so we need to 297106163Sroberto * insert our own SIGALRM signal handler to schedule the repeats. 298106163Sroberto */ 299106163Sroberto 300106163Sroberto /* Read the current SIGALRM action */ 301106163Sroberto 302106163Sroberto if (sigaction(SIGALRM, NULL, &setitimer_mpe_ctx.oldact) < 0) { 303106163Sroberto fprintf(stderr,"MPE setitimer old handler failed, errno=%d\n",errno); 304106163Sroberto return -1; 305106163Sroberto } 306106163Sroberto 307106163Sroberto /* Initialize the new action to call our SIGALRM handler instead */ 308106163Sroberto 309106163Sroberto newact.sa_handler = &setitimer_mpe_handler; 310106163Sroberto newact.sa_mask = setitimer_mpe_ctx.oldact.sa_mask; 311106163Sroberto newact.sa_flags = setitimer_mpe_ctx.oldact.sa_flags; 312106163Sroberto 313106163Sroberto if (sigaction(SIGALRM, &newact, NULL) < 0) { 314106163Sroberto fprintf(stderr,"MPE setitimer new handler failed, errno=%d\n",errno); 315106163Sroberto return -1; 316106163Sroberto } 317106163Sroberto} 318106163Sroberto 319106163Sroberto/* 320106163Sroberto * Return previous itimerval if desired 321106163Sroberto */ 322106163Sroberto 323106163Srobertoif (ovalue != NULL) *ovalue = setitimer_mpe_ctx.current_itimerval; 324106163Sroberto 325106163Sroberto/* 326106163Sroberto * Save current parameters for later usage 327106163Sroberto */ 328106163Sroberto 329106163Srobertosetitimer_mpe_ctx.current_itimerval = *value; 330106163Srobertosetitimer_mpe_ctx.current_msec = value_msec; 331106163Srobertosetitimer_mpe_ctx.value_msec = value_msec; 332106163Srobertosetitimer_mpe_ctx.interval_msec = interval_msec; 333106163Sroberto 334106163Sroberto/* 335106163Sroberto * Schedule the first alarm 336106163Sroberto */ 337106163Sroberto 338106163Srobertoremaining_msec = px_alarm(value_msec, &alarm_hpe_status); 339106163Srobertoif (alarm_hpe_status == 0) 340106163Sroberto return (0); 341106163Srobertoelse 342106163Sroberto return (-1); 343106163Sroberto} 344106163Sroberto 345106163Sroberto/* 346106163Sroberto * MPE lacks gettimeofday(), so we define our own. 347106163Sroberto */ 348106163Sroberto 349106163Srobertoint gettimeofday(struct timeval *tvp) 350106163Sroberto 351106163Sroberto{ 352106163Sroberto/* Documented, supported MPE functions. */ 353106163Srobertoextern void GETPRIVMODE(void); 354106163Srobertoextern void GETUSERMODE(void); 355106163Sroberto 356106163Sroberto/* Undocumented, unsupported MPE functions. */ 357106163Srobertoextern long long get_time(void); 358106163Srobertoextern void get_time_change_info(long long *, char *, char *); 359106163Srobertoextern long long ticks_to_micro(long long); 360106163Sroberto 361106163Srobertochar pwf_since_boot, recover_pwf_time; 362106163Srobertolong long mpetime, offset_ticks, offset_usec; 363106163Sroberto 364106163SrobertoGETPRIVMODE(); 365106163Srobertompetime = get_time(); /* MPE local time usecs since Jan 1 1970 */ 366106163Srobertoget_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time); 367106163Srobertooffset_usec = ticks_to_micro(offset_ticks); /* UTC offset usecs */ 368106163SrobertoGETUSERMODE(); 369106163Sroberto 370106163Srobertompetime = mpetime - offset_usec; /* Convert from local time to UTC */ 371106163Srobertotvp->tv_sec = mpetime / 1000000LL; 372106163Srobertotvp->tv_usec = mpetime % 1000000LL; 373106163Sroberto 374106163Srobertoreturn 0; 375106163Sroberto} 376106163Sroberto 377106163Sroberto/* 378106163Sroberto * MPE lacks settimeofday(), so we define our own. 379106163Sroberto */ 380106163Sroberto 381106163Sroberto#define HAVE_SETTIMEOFDAY 382106163Sroberto 383106163Srobertoint settimeofday(struct timeval *tvp) 384106163Sroberto 385106163Sroberto{ 386106163Sroberto/* Documented, supported MPE functions. */ 387106163Srobertoextern void GETPRIVMODE(void); 388106163Srobertoextern void GETUSERMODE(void); 389106163Sroberto 390106163Sroberto/* Undocumented, unsupported MPE functions. */ 391106163Srobertoextern void get_time_change_info(long long *, char *, char *); 392106163Srobertoextern void initialize_system_time(long long, int); 393106163Srobertoextern void set_time_correction(long long, int, int); 394106163Srobertoextern long long ticks_to_micro(long long); 395106163Sroberto 396106163Srobertochar pwf_since_boot, recover_pwf_time; 397106163Srobertolong long big_sec, big_usec, mpetime, offset_ticks, offset_usec; 398106163Sroberto 399106163Srobertobig_sec = tvp->tv_sec; 400106163Srobertobig_usec = tvp->tv_usec; 401106163Srobertompetime = (big_sec * 1000000LL) + big_usec; /* Desired UTC microseconds */ 402106163Sroberto 403106163SrobertoGETPRIVMODE(); 404106163Srobertoset_time_correction(0LL,0,0); /* Cancel previous time correction, if any */ 405106163Srobertoget_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time); 406106163Srobertooffset_usec = ticks_to_micro(offset_ticks); /* UTC offset microseconds */ 407106163Srobertompetime = mpetime + offset_usec; /* Convert from UTC to local time */ 408106163Srobertoinitialize_system_time(mpetime,1); 409106163SrobertoGETUSERMODE(); 410106163Sroberto 411106163Srobertoreturn 0; 412106163Sroberto} 413106163Sroberto#endif /* MPE */ 414106163Sroberto 415290001Sglebius#define SET_TOD_UNDETERMINED 0 416290001Sglebius#define SET_TOD_CLOCK_SETTIME 1 417290001Sglebius#define SET_TOD_SETTIMEOFDAY 2 418290001Sglebius#define SET_TOD_STIME 3 41954359Sroberto 420290001Sglebiusconst char * const set_tod_used[] = { 421290001Sglebius "undetermined", 422290001Sglebius "clock_settime", 423290001Sglebius "settimeofday", 424290001Sglebius "stime" 425290001Sglebius}; 426290001Sglebius 427290001Sglebiuspset_tod_using set_tod_using = NULL; 428290001Sglebius 429290001Sglebius 43054359Srobertoint 43154359Srobertontp_set_tod( 43254359Sroberto struct timeval *tvp, 43354359Sroberto void *tzp 43454359Sroberto ) 43554359Sroberto{ 436290001Sglebius static int tod; 437290001Sglebius int rc; 438290001Sglebius int saved_errno; 43954359Sroberto 440290001Sglebius TRACE(1, ("In ntp_set_tod\n")); 441290001Sglebius rc = -1; 442290001Sglebius saved_errno = 0; 443106163Sroberto 44454359Sroberto#ifdef HAVE_CLOCK_SETTIME 445290001Sglebius if (rc && (SET_TOD_CLOCK_SETTIME == tod || !tod)) { 44654359Sroberto struct timespec ts; 44754359Sroberto 44854359Sroberto /* Convert timeval to timespec */ 44954359Sroberto ts.tv_sec = tvp->tv_sec; 45054359Sroberto ts.tv_nsec = 1000 * tvp->tv_usec; 45154359Sroberto 452106163Sroberto errno = 0; 45354359Sroberto rc = clock_settime(CLOCK_REALTIME, &ts); 454290001Sglebius saved_errno = errno; 455290001Sglebius TRACE(1, ("ntp_set_tod: clock_settime: %d %m\n", rc)); 456290001Sglebius if (!tod && !rc) 457290001Sglebius tod = SET_TOD_CLOCK_SETTIME; 458290001Sglebius 45954359Sroberto } 46054359Sroberto#endif /* HAVE_CLOCK_SETTIME */ 46154359Sroberto#ifdef HAVE_SETTIMEOFDAY 462290001Sglebius if (rc && (SET_TOD_SETTIMEOFDAY == tod || !tod)) { 463132451Sroberto struct timeval adjtv; 464132451Sroberto 465132451Sroberto /* 466132451Sroberto * Some broken systems don't reset adjtime() when the 467132451Sroberto * clock is stepped. 468132451Sroberto */ 469132451Sroberto adjtv.tv_sec = adjtv.tv_usec = 0; 470132451Sroberto adjtime(&adjtv, NULL); 471182007Sroberto errno = 0; 47254359Sroberto rc = SETTIMEOFDAY(tvp, tzp); 473290001Sglebius saved_errno = errno; 474290001Sglebius TRACE(1, ("ntp_set_tod: settimeofday: %d %m\n", rc)); 475290001Sglebius if (!tod && !rc) 476290001Sglebius tod = SET_TOD_SETTIMEOFDAY; 47754359Sroberto } 47854359Sroberto#endif /* HAVE_SETTIMEOFDAY */ 47954359Sroberto#ifdef HAVE_STIME 480290001Sglebius if (rc && (SET_TOD_STIME == tod || !tod)) { 48154359Sroberto long tp = tvp->tv_sec; 48254359Sroberto 483182007Sroberto errno = 0; 48454359Sroberto rc = stime(&tp); /* lie as bad as SysVR4 */ 485290001Sglebius saved_errno = errno; 486290001Sglebius TRACE(1, ("ntp_set_tod: stime: %d %m\n", rc)); 487290001Sglebius if (!tod && !rc) 488290001Sglebius tod = SET_TOD_STIME; 48954359Sroberto } 49054359Sroberto#endif /* HAVE_STIME */ 491290001Sglebius 492290001Sglebius errno = saved_errno; /* for %m below */ 493290001Sglebius TRACE(1, ("ntp_set_tod: Final result: %s: %d %m\n", 494290001Sglebius set_tod_used[tod], rc)); 495290001Sglebius /* 496290001Sglebius * Say how we're setting the time of day 497290001Sglebius */ 498290001Sglebius if (!rc && NULL != set_tod_using) { 499290001Sglebius (*set_tod_using)(set_tod_used[tod]); 500290001Sglebius set_tod_using = NULL; 501290001Sglebius } 502290001Sglebius 503106163Sroberto if (rc) 504290001Sglebius errno = saved_errno; 505290001Sglebius 506106163Sroberto return rc; 50754359Sroberto} 50854359Sroberto 50954359Sroberto#endif /* not SYS_WINNT */ 51054359Sroberto 511106163Sroberto#if defined (SYS_WINNT) || defined (SYS_VXWORKS) || defined(MPE) 51254359Sroberto/* getpass is used in ntpq.c and ntpdc.c */ 51354359Sroberto 51454359Srobertochar * 51554359Srobertogetpass(const char * prompt) 51654359Sroberto{ 51754359Sroberto int c, i; 51854359Sroberto static char password[32]; 519182007Sroberto 52054359Sroberto fprintf(stderr, "%s", prompt); 52154359Sroberto fflush(stderr); 522182007Sroberto 52382498Sroberto for (i=0; i<sizeof(password)-1 && ((c=_getch())!='\n' && c!='\r'); i++) { 52454359Sroberto password[i] = (char) c; 52554359Sroberto } 52654359Sroberto password[i] = '\0'; 52754359Sroberto 528290001Sglebius fputc('\n', stderr); 529290001Sglebius fflush(stderr); 530290001Sglebius 53154359Sroberto return password; 53254359Sroberto} 53354359Sroberto#endif /* SYS_WINNT */ 534