#include <sys/time.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include "kernel.h" #include "global.h" #include "utils.h" #include "crypt.h" /************************************************************************ * Functions to use with qsort(). * ************************************************************************/ /* Compare players by their level, finding the higher level. */ int cmp_player (const void *a, const void *b) { return plev (*(int *) b) - plev (*(int *) a); } /* Compare strings and return which one comes first alphabetically. */ int cmp_alpha (const void *a, const void *b) { return (strcasecmp (a, b)); } /************************************************************************ * Functions to handle random number generation. * ************************************************************************/ void init_rand (void) { #ifndef SYS_NO_RANDOM srandom (9876); #else srand (9876); #endif } int randperc (void) { return my_random () % 100; } /************************************************************************ * Functions to handle string comparisions and to operate string * * comparing tables. * ************************************************************************/ /* Searches a string using a table using a case-sensitive substring * search method. The position of the beginning and the end of the * substring is stored in the *begin and *end variables. * (1996, Illusion) */ int strtlookup (char *elem, char **table, int *begin, int *end) { char **t, *ptr; int x; for (t = table, x = 0; *t != TABLE_END; ++t, ++x) { if (*t == NULL) continue; if ((ptr = strstr (elem, *t)) != NULL) { *begin = ptr - elem; *end = (ptr - elem) + strlen (*t); return x; } } return (-1); } Boolean match (char *p, char *q) { register char *s = p; register char *t = q; register char c; register char d; for (;;) { if ((c = *s++) == 0) return (*t == 0); if ((d = *t++) == 0) break; if (isupper (c)) c = tolower (c); if (isupper (d)) d = tolower (d); if (c == d) continue; if (d != '*') break; if ((d = *t++) == 0) return True; while (*s++ != d) { if (*(s - 1) == 0) return False; } } return False; } Boolean infile (char *file, char *line) { register char *p; register char *q; FILE *fl; Boolean invert; char a[80]; char b[80]; if ((fl = fopen (file, "r")) == 0) return False; invert = False; if (!fgets (a, sizeof a, fl)) { fclose (fl); return False; } if (*a == '!') { invert = True; if (!fgets (a, sizeof a, fl)) { fclose (fl); return False; } } for (p = line; isspace (*p); ++p) ; for (q = b; !isspace (*p) && *p != 0; ++p) *q++ = *p; *q = 0; do { for (p = a; isspace (*p); ++p) ; for (q = p; !isspace (*q) && *q != 0; ++q) ; *q = 0; if (match (b, p)) { fclose (fl); return !invert; } } while (fgets (a, sizeof a, fl)); fclose (fl); return invert; } #ifdef SYS_EQBUG /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific written prior permission. This software * is provided ``as is'' without express or implied warranty. */ /* * This array is designed for mapping upper and lower case letter * together for a case independent comparison. The mappings are * based upon ascii character sequences. */ static u_char charmap[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', }; int strcasecmp (char *s1, char *s2) { register u_char *cm = charmap, *us1 = (u_char *) s1, *us2 = (u_char *) s2; while (cm[*us1] == cm[*us2++]) if (*us1++ == '\0') return (0); return (cm[*us1] - cm[*--us2]); } int strncasecmp (const char *s1, const char *s2, register size_t n) { register u_char *cm = charmap, *us1 = (u_char *) s1, *us2 = (u_char *) s2; while (--n >= 0 && cm[*us1] == cm[*us2++]) if (*us1++ == '\0') return (0); return (n < 0 ? 0 : cm[*us1] - cm[*--us2]); } #endif int glookup (char *elem, int n, char **table, int (*strcmpfun) (const char *s1, const char *s2, size_t n)) { char **t; int x; for (t = table, x = 0; *t != TABLE_END; ++t, ++x) { if (*t == NULL) continue; if (strcmpfun (elem, *t, n) == 0) return x; } return (-1); } int tlookup (char *elem, char **table) { return glookup (elem, strlen (elem), table, strncasecmp); } /* the function used for xlookup */ static int xstrcasecmp (const char *s1, const char *s2, size_t n) { /* n is ignored */ return strcasecmp (s1, s2); } /* Like tlookup but uses strcasecmp (actually xstrcasecmp) instead of * strncasecmp. */ int xlookup (char *elem, char **table) { return glookup (elem, 0, table, xstrcasecmp); } /* Convert a string to lowercase */ char * lowercase (char *str) { char *p; for (p = str; *p; p++) if (isupper (*p)) *p = tolower (*p); return str; } /* Convert a string to uppercase. */ char * uppercase (char *str) { char *p; for (p = str; *p; p++) if (islower (*p)) *p = toupper (*p); return str; } /************************************************************************ * Memory Handling Functions * ************************************************************************/ void xfree (void *ptr) { free ((void *) ptr); } void * xmalloc (int nelem, int elem_size) { void *p; if ((p = calloc (nelem, elem_size)) == NULL) { write_date_stderr (); fprintf (stderr, "ERROR: xmalloc(); No room to allocate bytes.\n"); abort (); } return p; } void * resize_array (void *start, int elem_size, int oldlen, int newlen) { void *p = NULL; if (newlen != 0) p = xmalloc (newlen, elem_size); if (start != NULL) { if (newlen != 0) { memcpy (p, start, min (oldlen, newlen) * elem_size); } FREE (start); } return p; } /************************************************************************ * Miscellaneous Functions * ************************************************************************/ void write_date_stderr (void) { time_t t; char *z; time (&t); z = ctime (&t); z[19] = '\0'; fprintf (stderr, "%s: ", z); } char * x_strcpy (char *d, char *s) { /* Like strcpy except it returns the pointer just past last char in d */ while ((*d++ = *s++) != '\0') ; return d - 1; } char * my_crypt (char *buf, char *pw, int len) { char *s = crypt (pw, "Mu"); s[len - 1] = 0; return strcpy (buf, s); } char * mk_string (char *b, char *str, int k, int stopch) { unsigned char *s = (unsigned char *) str; char *t = b; int c; while ((c = 0377 & *s++) != stopch && --k >= 0) { switch (c) { case '\\': *t++ = '\\'; *t++ = '\\'; break; case '\n': *t++ = '\\'; *t++ = 'n'; break; case '\t': *t++ = '\\'; *t++ = 't'; break; case '\b': *t++ = '\\'; *t++ = 'b'; break; case '\f': *t++ = '\\'; *t++ = 'f'; break; case '\r': *t++ = '\\'; *t++ = 'r'; break; case '\"': *t++ = '\\'; *t++ = '\"'; break; default: if (isprint (c)) *t++ = c; else { *t++ = '\\'; *t++ = '0' + ((c >> 6) & 3); *t++ = '0' + ((c >> 3) & 7); *t++ = '0' + (c & 7); } break; } } *t = 0; return b; } /************************************************************************ * A package for handling sets of integers. * * 1993, Nicknack * ************************************************************************/ static Boolean check_for_possible_resize (int_set * p); void init_intset (int_set * p, int len) { p->len = p->current = 0; p->list = resize_array (NULL, sizeof (int), 0, p->maxlen = len); } void free_intset (int_set * p) { if (p->list != NULL) FREE (p->list); } Boolean add_int (int n, int_set * p) { int i; check_for_possible_resize (p); for (i = 0; i < p->len; i++) { if (p->list[i] == n) return False; } p->list[p->len++] = n; return True; } Boolean remove_int (int n, int_set * p) { int i; if (p->list == NULL) return False; for (i = 0; i < p->len && p->list[i] != n; i++) ; if (i == p->len) return False; if (i < p->current) { if (i < p->current - 1) p->list[i] = p->list[p->current - 1]; i = --p->current; } p->list[i] = p->list[--p->len]; check_for_possible_resize (p); return True; } int find_int (int n, int_set * p) { int i; if (p->list == NULL) return -1; for (i = 0; i < p->len && p->list[i] != n; i++) ; return i < p->len ? i + 1 : 0; } int find_int_number (int n, int_set * p) { return (n < 0 || n >= p->len) ? SET_END : p->list[n]; } int foreach_int (int_set * p, int (*func) (int)) { int i; int n = 0; for (i = 0; i < p->len; i++) { if (func (p->list[i])) n++; } return n; } void remove_current (int_set * p) { p->list[--p->current] = p->list[--p->len]; check_for_possible_resize (p); } int get_set_mem_usage (int_set * p) { return p->len * sizeof (int); } static Boolean check_for_possible_resize (int_set * p) { int oldlen = p->maxlen; if (p->len == p->maxlen) { p->maxlen = p->len < 20 ? 2 * (p->len + 1) : p->len + 25; } else if (p->maxlen > 0 && p->len < p->maxlen / 5) { p->maxlen /= 2; } else { return False; } p->list = resize_array (p->list, sizeof (int), oldlen, p->maxlen); return True; } /************************************************************************ * A table package for handling long integer [key + match]'es. * * 1993, Nicknack * ************************************************************************/ static int hash (long int value, int tbl_size) { return value % tbl_size; } void init_inttable (int_table * p, int size) { p->table = NEW (table_entry *, p->len = size); while (--size >= 0) p->table[size] = NULL; } void free_inttable (int_table * p) { FREE (p->table); } static table_entry * new_entry (long int key, long int value, table_entry * next) { table_entry *p = NEW (table_entry, 1); p->key = key; p->value = value; p->next = next; return p; } static void unlink_entry (table_entry ** entry) { table_entry *p = *entry; *entry = (*entry)->next; FREE (p); } /* Return a pointer to the pointer to the entry that represents 'key', * starting the search at the entry to which *p points. * If it does not exist, return a pointer to the pointer to the entry that * would succede 'key', had it existed. */ static table_entry ** find_position (long int key, table_entry ** p) { while (*p != NULL && (*p)->key > key) p = &(*p)->next; return p; } static table_entry * find_entry (long int key, int_table * p) { table_entry **r = find_position (key, &p->table[hash (key, p->len)]); return (*r != NULL && (*r)->key == key) ? *r : NULL; } Boolean insert_entry (long int key, long int value, int_table * p) { table_entry **q = find_position (key, &p->table[hash (key, p->len)]); if ((*q) == NULL) { *q = new_entry (key, value, NULL); } else if ((*q)->key < key) { *q = new_entry (key, value, *q); } else return False; return True; } Boolean remove_entry (long int key, int_table * p) { table_entry **q = find_position (key, &p->table[hash (key, p->len)]); if ((*q) != NULL && (*q)->key == key) { unlink_entry (q); return True; } else { return False; } } long int lookup_entry (long int key, int_table * p) { table_entry *q = find_entry (key, p); return (q != NULL) ? (q)->value : NOT_IN_TABLE; } long int change_entry (long int key, long int new_value, int_table * p) { table_entry *q = find_entry (key, p); if (q != NULL) { long int v = q->value; q->value = new_value; return v; } else { return NOT_IN_TABLE; } } int get_table_mem_usage (int_table * p) { return p->len * sizeof (table_entry *); } /************************************************************************ * Bit Manipulation Functions * ************************************************************************/ /* Test if all of the bits set in M is also set in W */ Boolean tstbits (int w, int m) { return (bits (w, m) == m); } Boolean tst_bit (LongInt * f, int b) { if (b >= 32) return xtstbit (f->h, (b - 32)); return xtstbit (f->l, b); } Boolean dtst_bit (DLongInt * f, int b) { if (b >= 64) return xtstbit (f->u, (b - 64)); if (b >= 32) return xtstbit (f->h, (b - 32)); return xtstbit (f->l, b); } void set_bit (LongInt * f, int b) { if (b >= 32) xsetbit (f->h, (b - 32)); else xsetbit (f->l, b); } void dset_bit (DLongInt * f, int b) { if (b >= 64) xsetbit (f->u, (b - 64)); else if (b >= 32) xsetbit (f->h, (b - 32)); else xsetbit (f->l, b); } void clr_bit (LongInt * f, int b) { if (b >= 32) xclrbit (f->h, (b - 32)); else xclrbit (f->l, b); } void dclr_bit (DLongInt * f, int b) { if (b >= 64) xclrbit (f->u, (b - 64)); else if (b >= 32) xclrbit (f->h, (b - 32)); else xclrbit (f->l, b); } /************************************************************************ * Ban File Utilities * ************************************************************************/ int addordel (char file_name[80], char check[80]) { FILE *fl; if ((fl = fopen (file_name, "r")) != NULL) if (infile (file_name, check)) { fclose (fl); return delname (file_name, check); } else { fclose (fl); return addname (file_name, check); } else return 0; } int addname (char file_name[80], char name[80]) { FILE *fl; if ((fl = (fopen (file_name, "a"))) == NULL) { return 0; } fprintf (fl, name); fprintf (fl, "\n"); fclose (fl); return ADDED; } int delname (char file_name[80], char name[80]) { FILE *a, *b; char name_in_file[80]; if ((a = fopen (file_name, "r")) == NULL) return 0; if ((b = fopen ("TMP_FILE", "w")) == NULL) { fclose (a); return 0; } strcat (name, "\n"); while (fgets (name_in_file, sizeof name_in_file, a)) if (!EQ (name, name_in_file)) fprintf (b, "%s", name_in_file); fclose (a); fclose (b); unlink (file_name); rename ("TMP_FILE", file_name); return DELETED; } /************************************************************************ * Text File Seeking Utilities * * 1996, Illusion * ************************************************************************/ int fnumlines (char file[200]) { FILE *fp; char tmp[300]; int num = 0; if ((fp = fopen (file, "rt")) == NULL) return -1; while (fgets (tmp, sizeof (tmp), fp)) num++; fclose (fp); return num; } void fileseek (FILE * file, int lines) { char tmp[300]; int loc; fseek (file, 0L, SEEK_SET); for (loc = 0; loc < lines; loc++) fgets (tmp, sizeof (tmp), file); } /************************************************************************ * bcopy() and bzero() replacement functions. * * 1996, Illusion * ************************************************************************/ #ifdef NO_BCOPY void bcopy (const void *src, void *dest, int n) { memcpy (dest, src, n); } void bzero (void *s, int n) { memset (s, 0, n); } #endif /************************************************************************ * Compressed File Handling Utilities * * 1996, Illusion * ************************************************************************/ int check_file_magic (char *filename) { char magic[3]; FILE *fp; if ((fp = fopen (filename, "rb")) == NULL) { write_date_stderr (); fprintf (stderr, "ERROR: Cannot find file %s.\n", filename); return -1; } fgets (magic, sizeof (magic), fp); if (magic[0] != MAGIC_ZHEADER) return 0; if (magic[1] == MAGIC_GZIP) return IS_GZIP; if (magic[1] == MAGIC_COMPRESS) return IS_COMPRESS; return 0; } FILE * zopen (char *filename) { char pipecom[100]; FILE *fp; int type; if ((type = check_file_magic (filename)) == -1) { write_date_stderr (); fprintf (stderr, "ERROR: Call to check_file_magic() failed.\n"); return NULL; } if (type != 0) { write_date_stderr (); fprintf (stderr, "ZOPEN: Compressed file access (Type=%s)\n", IS_GZIP ? "GZIP" : "COMPRESS"); sprintf (pipecom, "zcat %s", filename); if ((fp = popen (pipecom, "r")) == NULL) { write_date_stderr (); fprintf (stderr, "ZOPEN: Error, popen() failed.\n"); return NULL; } } else { if ((fp = fopen (filename, "r")) == NULL) { write_date_stderr (); fprintf (stderr, "ZOPEN: Error, fopen() failed.\n"); return NULL; } } return (fp); } void zclose (FILE * fp) { struct stat zstat; if (fstat (fileno (fp), &zstat) < 0) { write_date_stderr (); fprintf (stderr, "ZCLOSE: Error, fstat() failed.\n"); return; } if (S_ISFIFO (zstat.st_mode)) pclose (fp); else fclose (fp); }