/* System-specific functions */
#include "config.h"
#include "machine.h"
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#include "common.h"
#include "comm.h"
#ifdef sun
time_t time PROT((time_t *));
#endif
/*
* Return a random number in the range 0 .. n-1
*/
int random_number(n)
int n;
{
#ifdef RANDOM
return random() % n;
#else /* RANDOM */
#ifdef DRAND48
return (int)(drand48() * n);
#else /* DRAND48 */
#ifdef RAND
return rand() % n;
#else
extern int current_time;
return current_time % n; /* Suit yourself :-) */
#endif /* RAND */
#endif /* DRAND48 */
#endif /* RANDOM */
}
/* On a SUN Sparc I, a negative time offset of 22 seconds between two
* sucessive calls to time() has been observed. Negative time offsets
* can mess up the call_out tables. Since they also could mess up the
* mudlib, completely hide them by forcing the visible time to continue
* to run in positive direction.
*/
mp_int get_current_time() {
/* Don't write ever to total_alarms outside the interrupt, to avoid
* race conditions.
*/
extern volatile mp_int total_alarms;
static mp_int last_time = 0;
static mp_int noted_alarms = 0;
mp_int offset;
mp_int now;
offset = total_alarms - noted_alarms >> 1;
/* allow one alarm to happen without force-incrementing the time, so
* that no time anomaly due to race conditions occurs.
*/
noted_alarms += offset;
last_time += offset;
now = (mp_int)time((time_t *)NULL); /* Just use the old time() for now */
if (now >= last_time) {
last_time = now;
return now;
}
debug_message("Time anomaly, %ld seconds.\n", (long)(last_time - now));
return last_time;
}
/*
* high-speed processing of select() output. Consider searching a single
* descriptor in a sea of 2000...
*/
void walk_fdset(fd_set *set, int n) {
int *p, mask;
int offset, s;
p = (int*)set;
offset = 0;
do {
mask = *p++;
if (mask) {
s = ffs(mask);
do {
struct fd_entry *fpe;
s--;
mask &= ~(1 << s);
s += offset;
fpe = &fd_table[s];
(*fpe->f)(fpe, s);
} while (s = ffs(mask));
}
offset += 8*sizeof(*p);
} while (--n);
}
/*
* The functions below fix up some deficiencies of various platforms
*/
#ifdef STRTOL_BROKEN
#define DIGIT(x) (isdigit(x) ? (x) - '0' : \
islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
#define MBASE ('z' - 'a' + 1 + 10)
long
strtol(str, ptr, base)
#ifdef STRTOL_CONST_CHARP
const
#endif
register char *str;
char **ptr;
register int base;
{
register long val;
register int c;
int xx, neg = 0;
if (ptr != (char **)0)
*ptr = (char*)str; /* in case no number is formed */
if (base < 0 || base > MBASE)
return (0); /* base is invalid -- should be a fatal error */
if (!isalnum(c = *str)) {
while (isspace(c))
c = *++str;
switch (c) {
case '-':
neg++;
case '+': /* fall-through */
c = *++str;
}
}
if (base == 0)
if (c != '0')
base = 10;
else if (str[1] == 'x' || str[1] == 'X')
base = 16;
else
base = 8;
/*
* for any base > 10, the digits incrementally following
* 9 are assumed to be "abc...z" or "ABC...Z"
*/
if (!isalnum(c) || (xx = DIGIT(c)) >= base)
return (0); /* no number formed */
if (base == 10) {
/* accumulate neg avoids surprises near MAXLONG */
for (val = '0'-c; isdigit(c = *++str); )
/* multiplication with a constant can be optimized */
val = 10 * val +'0'-c;
} else if (base == 16) {
/* str[1] might be '0', thus we must not access str[2] without check. */
if (c == '0' && (str[1] == 'x' || str[1] == 'X') && isxdigit(str[2]))
c = *(str += 2); /* skip over leading "0x" or "0X" */
for (val = -DIGIT(c); isalnum(c = *++str) && (xx = DIGIT(c)) < 16; )
val = (val << 4) - xx;
} else {
for (val = -DIGIT(c); isalnum(c = *++str) && (xx = DIGIT(c)) < base; )
val = base * val - xx;
}
if (ptr != (char **)0)
*ptr = (char *)str;
return (neg ? val : -val);
}
#endif /* STRTOL_BROKEN */
#ifndef HAVE_MEMSET
char *memset (s, c, n)
char *s;
int c, n;
{
#ifdef HAVE_BZERO
if(c == 0)
bzero(s, n);
else
#endif
{
while(--n >= 0)
*s++ = c;
}
}
#endif /* !HAVE_MEMSET */
#if !defined(HAVE_CRYPT) && !defined(HAVE__CRYPT)
#include "hosts/crypt.c"
#endif
#if 0 /* If you can't get crypt to compile, you can use this dummy */
char * crypt(pass,salt)
char *pass, *salt;
{
return pass;
}
#endif
#ifndef HAVE_MEMMEM
/* This implementation is not very efficient, but still better than the old
* match_string() .
*/
char *memmem(needle, needlelen, haystack, haystacklen)
const void *needle, *haystack;
size_t needlelen, haystacklen;
{
mp_int i;
i = haystacklen - needlelen;
if (i >= 0) do {
if ( !memcmp(needle, haystack, needlelen) )
return haystack;
haystack = (char*)haystack + 1;
} while (--i >= 0);
return 0;
}
#endif /* !HAVE_MEMMEM */
#if !defined(HAVE_MEMMOVE) && !defined(OVERLAPPING_BCOPY)
void move_memory(dest, src, n)
char *dest, *src;
size_t n; /* might be unsigned */
{
if (!n)
return;
if (dest > src) {
dest += n;
src += n;
do
*--dest = *--src;
while (--n);
} else {
do
*dest++ = *src++;
while (--n);
}
}
#endif /* !HAVE_MEMMOVE */