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