/* 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 */