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