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
1154359Sroberto#include "ntp_machine.h"
1254359Sroberto#include "ntp_syslog.h"
1354359Sroberto#include "ntp_stdlib.h"
1454359Sroberto#include "ntp_unixtime.h"
1554359Sroberto
1654359Sroberto#ifdef HAVE_UNISTD_H
1754359Sroberto#include <unistd.h>
1854359Sroberto#endif
1954359Sroberto
2054359Sroberto#ifdef SYS_WINNT
21132451Srobertoint _getch(void);	/* Declare the one function rather than include conio.h */
2254359Sroberto#else
2354359Sroberto
2454359Sroberto#ifdef SYS_VXWORKS
2554359Sroberto#include "taskLib.h"
2654359Sroberto#include "sysLib.h"
2754359Sroberto#include "time.h"
2854359Sroberto#include "ntp_syslog.h"
2954359Sroberto
3054359Sroberto/*	some translations to the world of vxWorkings -casey */
3154359Sroberto/* first some netdb type things */
3254359Sroberto#include "ioLib.h"
3354359Sroberto#include <socket.h>
3454359Srobertoint h_errno;
3554359Sroberto
3654359Srobertostruct hostent *gethostbyname(char *name)
3754359Sroberto	{
3854359Sroberto	struct hostent *host1;
3954359Sroberto	h_errno = 0;					/* we are always successful!!! */
4054359Sroberto	host1 = (struct hostent *) malloc (sizeof(struct hostent));
4154359Sroberto	host1->h_name = name;
4254359Sroberto	host1->h_addrtype = AF_INET;
4354359Sroberto	host1->h_aliases = name;
4454359Sroberto	host1->h_length = 4;
4554359Sroberto	host1->h_addr_list[0] = (char *)hostGetByName (name);
4654359Sroberto	host1->h_addr_list[1] = NULL;
4754359Sroberto	return host1;
4854359Sroberto	}
4954359Sroberto
5054359Srobertostruct hostent *gethostbyaddr(char *name, int size, int addr_type)
5154359Sroberto	{
5254359Sroberto	struct hostent *host1;
5354359Sroberto	h_errno = 0;  /* we are always successful!!! */
5454359Sroberto	host1 = (struct hostent *) malloc (sizeof(struct hostent));
5554359Sroberto	host1->h_name = name;
5654359Sroberto	host1->h_addrtype = AF_INET;
5754359Sroberto	host1->h_aliases = name;
5854359Sroberto	host1->h_length = 4;
5954359Sroberto	host1->h_addr_list = NULL;
6054359Sroberto	return host1;
6154359Sroberto	}
6254359Sroberto
6354359Srobertostruct servent *getservbyname (char *name, char *type)
6454359Sroberto	{
6554359Sroberto	struct servent *serv1;
6654359Sroberto	serv1 = (struct servent *) malloc (sizeof(struct servent));
6754359Sroberto	serv1->s_name = "ntp";      /* official service name */
6854359Sroberto	serv1->s_aliases = NULL;	/* alias list */
6954359Sroberto	serv1->s_port = 123;		/* port # */
7054359Sroberto	serv1->s_proto = "udp";     /* protocol to use */
7154359Sroberto	return serv1;
7254359Sroberto	}
7354359Sroberto
7454359Sroberto/* second
7554359Sroberto * vxworks thinks it has insomnia
7654359Sroberto * we have to sleep for number of seconds
7754359Sroberto */
7854359Sroberto
7954359Sroberto#define CLKRATE 	sysClkRateGet()
8054359Sroberto
8154359Sroberto/* I am not sure how valid the granularity is - it is from G. Eger's port */
8254359Sroberto#define CLK_GRANULARITY  1		/* Granularity of system clock in usec	*/
8354359Sroberto								/* Used to round down # usecs/tick		*/
8454359Sroberto								/* On a VCOM-100, PIT gets 8 MHz clk,	*/
8554359Sroberto								/*	& it prescales by 32, thus 4 usec	*/
8654359Sroberto								/* on mv167, granularity is 1usec anyway*/
8754359Sroberto								/* To defeat rounding, set to 1 		*/
8854359Sroberto#define USECS_PER_SEC		MILLION		/* Microseconds per second	*/
8954359Sroberto#define TICK (((USECS_PER_SEC / CLKRATE) / CLK_GRANULARITY) * CLK_GRANULARITY)
9054359Sroberto
9154359Sroberto/* emulate unix sleep
9254359Sroberto * casey
9354359Sroberto */
9454359Srobertovoid sleep(int seconds)
9554359Sroberto	{
9654359Sroberto	taskDelay(seconds*TICK);
9754359Sroberto	}
9854359Sroberto/* emulate unix alarm
9954359Sroberto * that pauses and calls SIGALRM after the seconds are up...
10054359Sroberto * so ... taskDelay() fudged for seconds should amount to the same thing.
10154359Sroberto * casey
10254359Sroberto */
10354359Srobertovoid alarm (int seconds)
10454359Sroberto	{
10554359Sroberto	sleep(seconds);
10654359Sroberto	}
10754359Sroberto
10854359Sroberto#endif /* SYS_VXWORKS */
10954359Sroberto
11054359Sroberto#ifdef SYS_PTX			/* Does PTX still need this? */
11154359Sroberto/*#include <sys/types.h>	*/
11254359Sroberto#include <sys/procstats.h>
11354359Sroberto
11454359Srobertoint
11554359Srobertogettimeofday(
11654359Sroberto	struct timeval *tvp
11754359Sroberto	)
11854359Sroberto{
11954359Sroberto	/*
12054359Sroberto	 * hi, this is Sequents sneak path to get to a clock
12154359Sroberto	 * this is also the most logical syscall for such a function
12254359Sroberto	 */
12354359Sroberto	return (get_process_stats(tvp, PS_SELF, (struct procstats *) 0,
12454359Sroberto				  (struct procstats *) 0));
12554359Sroberto}
12654359Sroberto#endif /* SYS_PTX */
12754359Sroberto
128106163Sroberto#ifdef MPE
129106163Sroberto/* This is a substitute for bind() that if called for an AF_INET socket
130106163Srobertoport less than 1024, GETPRIVMODE() and GETUSERMODE() calls will be done. */
131106163Sroberto
132106163Sroberto#undef bind
133106163Sroberto#include <sys/types.h>
134106163Sroberto#include <sys/socket.h>
135106163Sroberto#include <netinet/in.h>
136106163Sroberto#include <sys/un.h>
137106163Sroberto
138106163Srobertoextern void GETPRIVMODE(void);
139106163Srobertoextern void GETUSERMODE(void);
140106163Sroberto
141106163Srobertoint __ntp_mpe_bind(int s, void *addr, int addrlen);
142106163Sroberto
143106163Srobertoint __ntp_mpe_bind(int s, void *addr, int addrlen) {
144106163Sroberto	int priv = 0;
145106163Sroberto	int result;
146106163Sroberto
147106163Srobertoif (addrlen == sizeof(struct sockaddr_in)) { /* AF_INET */
148106163Sroberto	if (((struct sockaddr_in *)addr)->sin_port > 0 &&
149106163Sroberto	    ((struct sockaddr_in *)addr)->sin_port < 1024) {
150106163Sroberto		priv = 1;
151106163Sroberto		GETPRIVMODE();
152106163Sroberto	}
153106163Sroberto/*	((struct sockaddr_in *)addr)->sin_addr.s_addr = 0; */
154106163Sroberto	result = bind(s,addr,addrlen);
155106163Sroberto	if (priv == 1) GETUSERMODE();
156106163Sroberto} else /* AF_UNIX */
157106163Sroberto	result = bind(s,addr,addrlen);
158106163Sroberto
159106163Srobertoreturn result;
160106163Sroberto}
161106163Sroberto
162106163Sroberto/*
163106163Sroberto * MPE stupidly requires sfcntl() to be used on sockets instead of fcntl(),
164106163Sroberto * so we define a wrapper to analyze the file descriptor and call the correct
165106163Sroberto * function.
166106163Sroberto */
167106163Sroberto
168106163Sroberto#undef fcntl
169106163Sroberto#include <errno.h>
170106163Sroberto#include <fcntl.h>
171106163Sroberto
172106163Srobertoint __ntp_mpe_fcntl(int fd, int cmd, int arg);
173106163Sroberto
174106163Srobertoint __ntp_mpe_fcntl(int fd, int cmd, int arg) {
175106163Sroberto	int len;
176106163Sroberto	struct sockaddr sa;
177106163Sroberto
178106163Sroberto	extern int sfcntl(int, int, int);
179106163Sroberto
180106163Sroberto	len = sizeof sa;
181106163Sroberto	if (getsockname(fd, &sa, &len) == -1) {
182106163Sroberto		if (errno == EAFNOSUPPORT) /* AF_UNIX socket */
183106163Sroberto			return sfcntl(fd, cmd, arg);
184106163Sroberto		if (errno == ENOTSOCK) /* file or pipe */
185106163Sroberto			return fcntl(fd, cmd, arg);
186106163Sroberto		return (-1); /* unknown getsockname() failure */
187106163Sroberto	} else /* AF_INET socket */
188106163Sroberto		return sfcntl(fd, cmd, arg);
189106163Sroberto}
190106163Sroberto
191106163Sroberto/*
192106163Sroberto * Setitimer emulation support.  Note that we implement this using alarm(),
193106163Sroberto * and since alarm() only delivers one signal, we must re-enable the alarm
194106163Sroberto * by enabling our own SIGALRM setitimer_mpe_handler routine to be called
195106163Sroberto * before the real handler routine and re-enable the alarm at that time.
196106163Sroberto *
197106163Sroberto * Note that this solution assumes that sigaction(SIGALRM) is called before
198106163Sroberto * calling setitimer().  If it should ever to become necessary to support
199106163Sroberto * sigaction(SIGALRM) after calling setitimer(), it will be necessary to trap
200106163Sroberto * those sigaction() calls.
201106163Sroberto */
202106163Sroberto
203106163Sroberto#include <limits.h>
204106163Sroberto#include <signal.h>
205106163Sroberto
206106163Sroberto/*
207106163Sroberto * Some global data that needs to be shared between setitimer() and
208106163Sroberto * setitimer_mpe_handler().
209106163Sroberto */
210106163Sroberto
211106163Srobertostruct {
212106163Sroberto	unsigned long current_msec;	/* current alarm() value in effect */
213106163Sroberto	unsigned long interval_msec;	/* next alarm() value from setitimer */
214106163Sroberto	unsigned long value_msec;	/* first alarm() value from setitimer */
215106163Sroberto	struct itimerval current_itimerval; /* current itimerval in effect */
216106163Sroberto	struct sigaction oldact;	/* SIGALRM state saved by setitimer */
217106163Sroberto} setitimer_mpe_ctx = { 0, 0, 0 };
218106163Sroberto
219106163Sroberto/*
220106163Sroberto * Undocumented, unsupported function to do alarm() in milliseconds.
221106163Sroberto */
222106163Sroberto
223106163Srobertoextern unsigned int px_alarm(unsigned long, int *);
224106163Sroberto
225106163Sroberto/*
226106163Sroberto * The SIGALRM handler routine enabled by setitimer().  Re-enable the alarm or
227106163Sroberto * restore the original SIGALRM setting if no more alarms are needed.  Then
228106163Sroberto * call the original SIGALRM handler (if any).
229106163Sroberto */
230106163Sroberto
231106163Srobertostatic RETSIGTYPE setitimer_mpe_handler(int sig)
232106163Sroberto{
233106163Srobertoint alarm_hpe_status;
234106163Sroberto
235106163Sroberto/* Update the new current alarm value */
236106163Sroberto
237106163Srobertosetitimer_mpe_ctx.current_msec = setitimer_mpe_ctx.interval_msec;
238106163Sroberto
239106163Srobertoif (setitimer_mpe_ctx.interval_msec > 0) {
240106163Sroberto  /* Additional intervals needed; re-arm the alarm timer */
241106163Sroberto  px_alarm(setitimer_mpe_ctx.interval_msec,&alarm_hpe_status);
242106163Sroberto} else {
243106163Sroberto  /* No more intervals, so restore previous original SIGALRM handler */
244106163Sroberto  sigaction(SIGALRM, &setitimer_mpe_ctx.oldact, NULL);
245106163Sroberto}
246106163Sroberto
247106163Sroberto/* Call the original SIGALRM handler if it is a function and not just a flag */
248106163Sroberto
249106163Srobertoif (setitimer_mpe_ctx.oldact.sa_handler != SIG_DFL &&
250106163Sroberto    setitimer_mpe_ctx.oldact.sa_handler != SIG_ERR &&
251106163Sroberto    setitimer_mpe_ctx.oldact.sa_handler != SIG_IGN)
252106163Sroberto  (*setitimer_mpe_ctx.oldact.sa_handler)(SIGALRM);
253106163Sroberto
254106163Sroberto}
255106163Sroberto
256106163Sroberto/*
257106163Sroberto * Our implementation of setitimer().
258106163Sroberto */
259106163Sroberto
260106163Srobertoint
261106163Srobertosetitimer(int which, struct itimerval *value,
262106163Sroberto	    struct itimerval *ovalue)
263106163Sroberto{
264106163Sroberto
265106163Srobertoint alarm_hpe_status;
266106163Srobertounsigned long remaining_msec, value_msec, interval_msec;
267106163Srobertostruct sigaction newact;
268106163Sroberto
269106163Sroberto/*
270106163Sroberto * Convert the initial interval to milliseconds
271106163Sroberto */
272106163Sroberto
273106163Srobertoif (value->it_value.tv_sec > (UINT_MAX / 1000))
274106163Sroberto  value_msec = UINT_MAX;
275106163Srobertoelse
276106163Sroberto  value_msec = value->it_value.tv_sec * 1000;
277106163Sroberto
278106163Srobertovalue_msec += value->it_value.tv_usec / 1000;
279106163Sroberto
280106163Sroberto/*
281106163Sroberto * Convert the reset interval to milliseconds
282106163Sroberto */
283106163Sroberto
284106163Srobertoif (value->it_interval.tv_sec > (UINT_MAX / 1000))
285106163Sroberto  interval_msec = UINT_MAX;
286106163Srobertoelse
287106163Sroberto  interval_msec = value->it_interval.tv_sec * 1000;
288106163Sroberto
289106163Srobertointerval_msec += value->it_interval.tv_usec / 1000;
290106163Sroberto
291106163Srobertoif (value_msec > 0 && interval_msec > 0) {
292106163Sroberto  /*
293106163Sroberto   * We'll be starting an interval timer that will be repeating, so we need to
294106163Sroberto   * insert our own SIGALRM signal handler to schedule the repeats.
295106163Sroberto   */
296106163Sroberto
297106163Sroberto  /* Read the current SIGALRM action */
298106163Sroberto
299106163Sroberto  if (sigaction(SIGALRM, NULL, &setitimer_mpe_ctx.oldact) < 0) {
300106163Sroberto    fprintf(stderr,"MPE setitimer old handler failed, errno=%d\n",errno);
301106163Sroberto    return -1;
302106163Sroberto  }
303106163Sroberto
304106163Sroberto  /* Initialize the new action to call our SIGALRM handler instead */
305106163Sroberto
306106163Sroberto  newact.sa_handler = &setitimer_mpe_handler;
307106163Sroberto  newact.sa_mask = setitimer_mpe_ctx.oldact.sa_mask;
308106163Sroberto  newact.sa_flags = setitimer_mpe_ctx.oldact.sa_flags;
309106163Sroberto
310106163Sroberto  if (sigaction(SIGALRM, &newact, NULL) < 0) {
311106163Sroberto    fprintf(stderr,"MPE setitimer new handler failed, errno=%d\n",errno);
312106163Sroberto    return -1;
313106163Sroberto  }
314106163Sroberto}
315106163Sroberto
316106163Sroberto/*
317106163Sroberto * Return previous itimerval if desired
318106163Sroberto */
319106163Sroberto
320106163Srobertoif (ovalue != NULL) *ovalue = setitimer_mpe_ctx.current_itimerval;
321106163Sroberto
322106163Sroberto/*
323106163Sroberto * Save current parameters for later usage
324106163Sroberto */
325106163Sroberto
326106163Srobertosetitimer_mpe_ctx.current_itimerval = *value;
327106163Srobertosetitimer_mpe_ctx.current_msec = value_msec;
328106163Srobertosetitimer_mpe_ctx.value_msec = value_msec;
329106163Srobertosetitimer_mpe_ctx.interval_msec = interval_msec;
330106163Sroberto
331106163Sroberto/*
332106163Sroberto * Schedule the first alarm
333106163Sroberto */
334106163Sroberto
335106163Srobertoremaining_msec = px_alarm(value_msec, &alarm_hpe_status);
336106163Srobertoif (alarm_hpe_status == 0)
337106163Sroberto  return (0);
338106163Srobertoelse
339106163Sroberto  return (-1);
340106163Sroberto}
341106163Sroberto
342106163Sroberto/*
343106163Sroberto * MPE lacks gettimeofday(), so we define our own.
344106163Sroberto */
345106163Sroberto
346106163Srobertoint gettimeofday(struct timeval *tvp)
347106163Sroberto
348106163Sroberto{
349106163Sroberto/* Documented, supported MPE functions. */
350106163Srobertoextern void GETPRIVMODE(void);
351106163Srobertoextern void GETUSERMODE(void);
352106163Sroberto
353106163Sroberto/* Undocumented, unsupported MPE functions. */
354106163Srobertoextern long long get_time(void);
355106163Srobertoextern void get_time_change_info(long long *, char *, char *);
356106163Srobertoextern long long ticks_to_micro(long long);
357106163Sroberto
358106163Srobertochar pwf_since_boot, recover_pwf_time;
359106163Srobertolong long mpetime, offset_ticks, offset_usec;
360106163Sroberto
361106163SrobertoGETPRIVMODE();
362106163Srobertompetime = get_time(); /* MPE local time usecs since Jan 1 1970 */
363106163Srobertoget_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time);
364106163Srobertooffset_usec = ticks_to_micro(offset_ticks);  /* UTC offset usecs */
365106163SrobertoGETUSERMODE();
366106163Sroberto
367106163Srobertompetime = mpetime - offset_usec;  /* Convert from local time to UTC */
368106163Srobertotvp->tv_sec = mpetime / 1000000LL;
369106163Srobertotvp->tv_usec = mpetime % 1000000LL;
370106163Sroberto
371106163Srobertoreturn 0;
372106163Sroberto}
373106163Sroberto
374106163Sroberto/*
375106163Sroberto * MPE lacks settimeofday(), so we define our own.
376106163Sroberto */
377106163Sroberto
378106163Sroberto#define HAVE_SETTIMEOFDAY
379106163Sroberto
380106163Srobertoint settimeofday(struct timeval *tvp)
381106163Sroberto
382106163Sroberto{
383106163Sroberto/* Documented, supported MPE functions. */
384106163Srobertoextern void GETPRIVMODE(void);
385106163Srobertoextern void GETUSERMODE(void);
386106163Sroberto
387106163Sroberto/* Undocumented, unsupported MPE functions. */
388106163Srobertoextern void get_time_change_info(long long *, char *, char *);
389106163Srobertoextern void initialize_system_time(long long, int);
390106163Srobertoextern void set_time_correction(long long, int, int);
391106163Srobertoextern long long ticks_to_micro(long long);
392106163Sroberto
393106163Srobertochar pwf_since_boot, recover_pwf_time;
394106163Srobertolong long big_sec, big_usec, mpetime, offset_ticks, offset_usec;
395106163Sroberto
396106163Srobertobig_sec = tvp->tv_sec;
397106163Srobertobig_usec = tvp->tv_usec;
398106163Srobertompetime = (big_sec * 1000000LL) + big_usec;  /* Desired UTC microseconds */
399106163Sroberto
400106163SrobertoGETPRIVMODE();
401106163Srobertoset_time_correction(0LL,0,0); /* Cancel previous time correction, if any */
402106163Srobertoget_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time);
403106163Srobertooffset_usec = ticks_to_micro(offset_ticks); /* UTC offset microseconds */
404106163Srobertompetime = mpetime + offset_usec; /* Convert from UTC to local time */
405106163Srobertoinitialize_system_time(mpetime,1);
406106163SrobertoGETUSERMODE();
407106163Sroberto
408106163Srobertoreturn 0;
409106163Sroberto}
410106163Sroberto#endif /* MPE */
411106163Sroberto
41254359Srobertoconst char *set_tod_using = "UNKNOWN";
41354359Sroberto
41454359Srobertoint
41554359Srobertontp_set_tod(
41654359Sroberto	struct timeval *tvp,
41754359Sroberto	void *tzp
41854359Sroberto	)
41954359Sroberto{
420106163Sroberto	int rc = -1;
42154359Sroberto
422106163Sroberto#ifdef DEBUG
423106163Sroberto	if (debug)
424106163Sroberto	    printf("In ntp_set_tod\n");
425106163Sroberto#endif
426106163Sroberto
42754359Sroberto#ifdef HAVE_CLOCK_SETTIME
428106163Sroberto	if (rc) {
42954359Sroberto		struct timespec ts;
43054359Sroberto
431106163Sroberto		set_tod_using = "clock_settime";
43254359Sroberto		/* Convert timeval to timespec */
43354359Sroberto		ts.tv_sec = tvp->tv_sec;
43454359Sroberto		ts.tv_nsec = 1000 *  tvp->tv_usec;
43554359Sroberto
436106163Sroberto		errno = 0;
43754359Sroberto		rc = clock_settime(CLOCK_REALTIME, &ts);
438106163Sroberto#ifdef DEBUG
439106163Sroberto		if (debug) {
440106163Sroberto			printf("ntp_set_tod: %s: %d: %s\n",
441106163Sroberto			       set_tod_using, rc, strerror(errno));
44254359Sroberto		}
443106163Sroberto#endif
44454359Sroberto	}
44554359Sroberto#endif /* HAVE_CLOCK_SETTIME */
44654359Sroberto#ifdef HAVE_SETTIMEOFDAY
447106163Sroberto	if (rc) {
448132451Sroberto		struct timeval adjtv;
449132451Sroberto
450106163Sroberto		set_tod_using = "settimeofday";
451132451Sroberto		/*
452132451Sroberto		 * Some broken systems don't reset adjtime() when the
453132451Sroberto		 * clock is stepped.
454132451Sroberto		 */
455132451Sroberto		adjtv.tv_sec = adjtv.tv_usec = 0;
456132451Sroberto		adjtime(&adjtv, NULL);
457182007Sroberto		errno = 0;
45854359Sroberto		rc = SETTIMEOFDAY(tvp, tzp);
459106163Sroberto#ifdef DEBUG
460106163Sroberto		if (debug) {
461106163Sroberto			printf("ntp_set_tod: %s: %d: %s\n",
462106163Sroberto			       set_tod_using, rc, strerror(errno));
46354359Sroberto		}
464106163Sroberto#endif
46554359Sroberto	}
46654359Sroberto#endif /* HAVE_SETTIMEOFDAY */
46754359Sroberto#ifdef HAVE_STIME
468106163Sroberto	if (rc) {
46954359Sroberto		long tp = tvp->tv_sec;
47054359Sroberto
471106163Sroberto		set_tod_using = "stime";
472182007Sroberto		errno = 0;
47354359Sroberto		rc = stime(&tp); /* lie as bad as SysVR4 */
474106163Sroberto#ifdef DEBUG
475106163Sroberto		if (debug) {
476106163Sroberto			printf("ntp_set_tod: %s: %d: %s\n",
477106163Sroberto			       set_tod_using, rc, strerror(errno));
47854359Sroberto		}
479106163Sroberto#endif
48054359Sroberto	}
48154359Sroberto#endif /* HAVE_STIME */
482106163Sroberto	if (rc)
483106163Sroberto	    set_tod_using = "Failed!";
484106163Sroberto#ifdef DEBUG
485106163Sroberto	if (debug) {
486106163Sroberto		printf("ntp_set_tod: Final result: %s: %d: %s\n",
487106163Sroberto			set_tod_using, rc, strerror(errno));
488106163Sroberto	}
489106163Sroberto#endif
490106163Sroberto	return rc;
49154359Sroberto}
49254359Sroberto
49354359Sroberto#endif /* not SYS_WINNT */
49454359Sroberto
495106163Sroberto#if defined (SYS_WINNT) || defined (SYS_VXWORKS) || defined(MPE)
49654359Sroberto/* getpass is used in ntpq.c and ntpdc.c */
49754359Sroberto
49854359Srobertochar *
49954359Srobertogetpass(const char * prompt)
50054359Sroberto{
50154359Sroberto	int c, i;
50254359Sroberto	static char password[32];
503182007Sroberto
50454359Sroberto	fprintf(stderr, "%s", prompt);
50554359Sroberto	fflush(stderr);
506182007Sroberto
50782498Sroberto	for (i=0; i<sizeof(password)-1 && ((c=_getch())!='\n' && c!='\r'); i++) {
50854359Sroberto		password[i] = (char) c;
50954359Sroberto	}
51054359Sroberto	password[i] = '\0';
51154359Sroberto
51254359Sroberto	return password;
51354359Sroberto}
51454359Sroberto#endif /* SYS_WINNT */
51554359Sroberto
51654359Sroberto#if !defined(HAVE_MEMSET)
51754359Srobertovoid
51854359Srobertontp_memset(
51954359Sroberto	char *a,
52054359Sroberto	int x,
52154359Sroberto	int c
52254359Sroberto	)
52354359Sroberto{
52454359Sroberto	while (c-- > 0)
52554359Sroberto		*a++ = (char) x;
52654359Sroberto}
52754359Sroberto#endif /*POSIX*/
528