/* * MISC.C: * * Miscellaneous string, file and data structure manipulation * routines. * * Copyright (C) 1991, 1992, 1993, 1997 Brooke Paul & Brett Vickers * */ #ifdef IRIX #define _BSD_COMPAT #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #endif /* IRIX */ #include "mstruct.h" #include "mextern.h" #include <stdio.h> #include <sys/types.h> #ifndef WIN32 #include <sys/time.h> #else #include <time.h> #endif #include <ctype.h> #ifdef DMALLOC #include "/usr/local/include/dmalloc.h" #endif /************************************************************************/ /* merror */ /************************************************************************/ /* merror is called whenever an error message should be output to the */ /* log file. If the error is fatal, then the program is aborted */ void merror(str, errtype) char *str; char errtype; { long t; char bugstr[256]; t = time(0); sprintf(bugstr, "Error occured in %s. %s", str, ctime(&t)); loge(bugstr); if(errtype == FATAL) exit(-1); } /************************************************************************/ /* lowercize */ /************************************************************************/ /* This function takes the string passed in as the first parameter and */ /* converts it to lowercase. If the flag in the second parameter has */ /* its first bit set, then the first letter is capitalized. */ void lowercize(str, flag) char *str; int flag; { int i, n; n = (str) ? strlen(str) : 0; for(i=0; i<n; i++) str[i] = (str[i] >= 'A' && str[i] <= 'Z') ? str[i]+32:str[i]; if(flag & 1) str[0] = (str[0] >= 'a' && str[0] <= 'z') ? str[0]-32:str[0]; } /************************************************************************/ /* low */ /************************************************************************/ /* If the character passed in as the first parameter is an uppercase */ /* alphabetic character, then it is converted to lowercase and returned */ /* Otherwise, it is unchanged. */ int low(ch) char ch; { if(ch >= 'A' && ch <= 'Z') return(ch+32); else return(ch); } int up(ch) char ch; { if(ch >= 'a' && ch <= 'z') return(ch-32); else return(ch); } /************************************************************************/ /* zero */ /************************************************************************/ /* This function zeroes a block of bytes at the given pointer and the */ /* given length. */ void zero(ptr, size) void *ptr; int size; { char *chptr; int i; chptr = (char *)ptr; for(i=0; i<size; i++) chptr[i] = 0; } /* Temporary (but static) data for the next several functions */ static char xstr[5][80]; static int xnum=0; /************************************************************************/ /* crt_str */ /************************************************************************/ /* This function takes the creature given it in the first parameter, */ /* and forms the appropriate singularized or pluralized version of the */ /* creature's name using certain flags. */ char *crt_str(crt, num, flag) creature *crt; int num, flag; { char ch; char *str; char pform[80]; char sform[80]; char pfile[80]; int found; FILE *plural; str = xstr[xnum]; xnum = (xnum + 1)%5; if(crt->type != MONSTER) { if((((F_ISSET(crt, PINVIS) || F_ISSET(crt, PDMINV)) && !(flag & 2)) || F_ISSET(crt, PDMINV)) && !F_ISSET(crt, PALIAS)) strcpy(str, "Someone"); else { if(F_ISSET(crt, PALIAS) && F_ISSET(crt, PDMINV)) { if(!F_ISSET(Ply[crt->fd].extr->alias_crt, MNOPRE)) { strcpy(str, "A "); strcat(str, Ply[crt->fd].extr->alias_crt->name); } else strcpy(str, Ply[crt->fd].extr->alias_crt->name); } else strcpy(str, crt->name); if(F_ISSET(crt, PINVIS)) strcat(str, " (*)"); } return(str); } if(num == 0) { if(!F_ISSET(crt, MNOPRE)) { strcpy(str, "the "); strcat(str, crt->name); } else strcpy(str, crt->name); } else if(num == 1) { if(F_ISSET(crt, MNOPRE)) strcpy(str, ""); else { ch = low(crt->name[0]); if(ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') strcpy(str, "an "); else strcpy(str, "a "); } strcat(str, crt->name); } else { if(num < 21) sprintf(str, "%s ", number[num]); else sprintf(str, "%d ", num); strcat(str, crt->name); if(F_ISSET(crt, MTOMEN)) { str[strlen(str)-2] = 'e'; } else if(!F_ISSET(crt, MDROPS)) { str[strlen(str)+1] = 0; str[strlen(str)+2] = 0; if(str[strlen(str)-1] == 's' || str[strlen(str)-1] == 'x') { str[strlen(str)] = 'e'; str[strlen(str)] = 's'; } else str[strlen(str)] = 's'; } } if(F_ISSET(crt, MIREGP) && num > 1) { found = 0; strcpy(pfile, MONPATH); strcat(pfile,"/plurals"); plural = fopen(pfile, "r"); if(plural != NULL) { while (!found && !(feof (plural))) { fflush(plural); /* get singular form */ fgets(sform, sizeof(sform), plural); sform[strlen(sform)-1] = 0; fflush(plural); /* get plural form */ fgets(pform, sizeof(pform), plural); pform[strlen(pform)-1] = 0; if(strcmp(crt->name, sform) == 0) { strcpy(str, ""); if(num < 21) if(num < 21) sprintf(str, "%s ", number[num]); else sprintf(str, "%d ", num); strcat(str, pform); found = 1; } } fclose(plural); } } if(flag & CAP) str[0] = up(str[0]); if((flag & MAG) && (crt->type != PLAYER) && (F_ISSET(crt, MMAGIC))) strcat(str, " (M)"); return(str); } /************************************************************************/ /* obj_str */ /************************************************************************/ /* This function examines an object's flags and its name, and returns */ /* the appropriate pluralized or singularized version of the name. */ /* In some cases it is necessary to drop the s on a plural version of */ /* a word. */ char *obj_str(obj, num, flag) object *obj; int num, flag; { char ch; char str2[10]; char *str; char pform[80]; char sform[80]; char pfile[80]; int found; FILE *plural; str = xstr[xnum]; xnum = (xnum + 1)%5; if(num == 0) { if(!F_ISSET(obj, ONOPRE)) { strcpy(str, "the "); strcat(str, obj->name); } else strcpy(str, obj->name); } else if(num == 1) { if(F_ISSET(obj, ONOPRE) || obj->type == MONEY) strcpy(str, ""); else if(F_ISSET(obj, OSOMEA)) strcpy(str, "some "); else { ch = low(obj->name[0]); if(ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') strcpy(str, "an "); else strcpy(str, "a "); } strcat(str, obj->name); } else { if(num < 21) sprintf(str, "%s ", number[num]); else sprintf(str, "%d ", num); if(F_ISSET(obj, OSOMEA)) strcat(str, "sets of "); strcat(str, obj->name); if(!F_ISSET(obj, ODROPS) && !F_ISSET(obj, OSOMEA)) { str[strlen(str)+1] = 0; str[strlen(str)+2] = 0; if(str[strlen(str)-1] == 's' || str[strlen(str)-1] == 'x') { str[strlen(str)] = 'e'; str[strlen(str)] = 's'; } else str[strlen(str)] = 's'; } } if(F_ISSET(obj, OIREGP) && num > 1) { found = 0; strcpy(pfile, OBJPATH); strcat(pfile,"/plurals"); plural = fopen(pfile, "r"); if(plural != NULL) { while (!found && !(feof (plural))) { fflush(plural); /* get singular form */ fgets(sform, sizeof(sform), plural); sform[strlen(sform)-1] = 0; fflush(plural); /* get plural form */ fgets(pform, sizeof(pform), plural); pform[strlen(pform)-1] = 0; if(strcmp(obj->name, sform) == 0) { strcpy(str, ""); if(num < 21) sprintf(str, "%s ", number[num]); else sprintf(str, "%d ", num); strcat(str, pform); found = 1; } } fclose(plural); } } if(flag & CAP) str[0] = up(str[0]); if((flag & MAG) && obj->adjustment) { sprintf(str2, " (%s%d)", obj->adjustment >= 0 ? "+":"", obj->adjustment); strcat(str, str2); } else if((flag & MAG) && obj->magicpower) strcat(str, " (M)"); return(str); } /************************************************************************/ /* delimit */ /************************************************************************/ /* This function takes a given string, and if it is greater than a given*/ /* number of characters, then it is split up into several lines. This */ /* is done by replacing spaces with carriage returns before the end of */ /* the line. */ #define MAXLINE 77 void delimit(str) char *str; { int i, j, l, len, lastspace; char str2[4096]; str2[0] = 0; j = (str) ? strlen(str) : 0; if(j < MAXLINE) return; len = 0; lastspace = -1; l = 0; for(i=0; i<j; i++) { if(str[i] == ' ') lastspace = i; if(str[i] == '\n') { len = 0; lastspace = -1; } len++; if(len > MAXLINE && lastspace > -1) { str[lastspace] = 0; strcat(str2, &str[l]); strcat(str2, "\n "); l = lastspace + 1; len = i - lastspace + 3; lastspace = -1; } } strcat(str2, &str[l]); strcpy(str, str2); } /************************************************************************/ /* view_file */ /************************************************************************/ /* This function views a file whose name is given by the third */ /* parameter. If the file is longer than 20 lines, then the user is */ /* prompted to hit return to continue, thus dividing the output into */ /* several pages. */ #define FBUF 800 void view_file(fd, param, str) int fd, param; char *str; { char buf[FBUF+1]; int i, l, n, ff, line; long offset; buf[FBUF] = 0; switch(param) { case 1: offset = 0L; strcpy(Ply[fd].extr->tempstr[1], str); ff = open(str, O_RDONLY, 0); if(ff < 0) { print(fd, "File could not be opened.\n"); RETURN(fd, command, 1); } line = 0; while(1) { n = read(ff, buf, FBUF); l = 0; for(i=0; i<n; i++) { if(buf[i] == '\n') { buf[i] = 0; line++; print(fd, "%s\n", &buf[l]); offset += (i-l+1); l = i+1; } if(line > 20) break; } if(line > 20) { sprintf(Ply[fd].extr->tempstr[0], "%lu", offset); break; } else if(l != n) { print(fd, "%s", &buf[l]); offset += (i-l); } if(n<FBUF) break; } if(n==FBUF || line>20) { F_SET(Ply[fd].ply, PREADI); print(fd, "[Hit Return, Q to Quit]: "); output_buf(); Ply[fd].io->intrpt &= ~1; } if(n<FBUF && line <= 20) { close(ff); RETURN(fd, command, 1); } else { close(ff); F_SET(Ply[fd].ply, PREADI); RETURN(fd, view_file, 2); } case 2: if(str[0] != 0) { print(fd, "Aborted.\n"); F_CLR(Ply[fd].ply, PREADI); RETURN(fd, command, 1); } offset = atol(Ply[fd].extr->tempstr[0]); ff = open(Ply[fd].extr->tempstr[1], O_RDONLY, 0); if(ff < 0) { print(fd, "File could not be opened.\n"); F_CLR(Ply[fd].ply, PREADI); RETURN(fd, command, 1); } lseek(ff, offset, 0); line = 0; while(1) { n = read(ff, buf, FBUF); l = 0; for(i=0; i<n; i++) { if(buf[i] == '\n') { buf[i] = 0; line++; print(fd, "%s\n", &buf[l]); offset += (i-l+1); l = i+1; } if(line > 20) break; } if(line > 20) { sprintf(Ply[fd].extr->tempstr[0], "%lu", offset); break; } else if(l != n) { print(fd, "%s", &buf[l]); offset += (i-l); } if(n<FBUF) break; } if(n==FBUF || line > 20) { F_SET(Ply[fd].ply, PREADI); print(fd, "[Hit Return, Q to Quit]: "); output_buf(); Ply[fd].io->intrpt &= ~1; } if(n<FBUF && line <= 20) { close(ff); F_CLR(Ply[fd].ply, PREADI); RETURN(fd, command, 1); } else { close(ff); RETURN(fd, view_file, 2); } } } /************************************************************************/ /* dice */ /************************************************************************/ /* This function rolls n s-sided dice and adds p to the total. */ int dice(n, s, p) int n, s, p; { int i; for(i=0; i<n; i++) p += mrand(1,s); return(p); } /************************************************************************/ /* exp_to_lev */ /************************************************************************/ /* This function takes a given amount of experience as its first */ /* argument returns the level that the experience reflects. */ int exp_to_lev(exp) long exp; { int level = 1; while (exp >= needed_exp[level-1] && level < MAXALVL) level++; if (level == MAXALVL) { level = exp/(needed_exp[MAXALVL-1]); level++; level= MAX(25,level); } return(MAX(1,level)); } /************************************************************************/ /* dec_daily */ /************************************************************************/ /* This function is called whenever a daily-use item or operation is */ /* used or performed. If the number of daily uses are used, up then */ /* a 0 is returned. Otherwise, the number of uses is decremented and */ /* a 1 is returned. */ int dec_daily(dly_ptr) struct daily *dly_ptr; { long t; struct tm *tm, time1, time2; t = time(0); tm = localtime(&t); time1 = *tm; tm = localtime(&dly_ptr->ltime); time2 = *tm; if(time1.tm_yday != time2.tm_yday) { dly_ptr->cur = dly_ptr->max; dly_ptr->ltime = t; } if(dly_ptr->cur == 0) return(0); dly_ptr->cur--; return(1); } /************************************************************************/ /* loge */ /************************************************************************/ /* This function writes a formatted printf string to a logfile called */ /* "log" in the player directory. */ void loge(fmt, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10) char *fmt; int i1, i2, i3, i4, i5, i6, i7, i8, i9, i10; { char file[80]; char str[1024]; int fd; sprintf(file, "%s/log", LOGPATH); fd = open(file, O_RDWR, 0); if(fd < 0) { fd = open(file, O_RDWR | O_CREAT, ACC); if(fd < 0) return; } lseek(fd, 0L, 2); sprintf(str, fmt, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10); write(fd, str, strlen(str)); close(fd); } /************************************************************************/ /* sort_cmds */ /************************************************************************/ /* This function sorts the global cmdlist structure array so that the */ /* command list is sorted by how often each command is used. The most- */ /* used commands will end up at the top of the list. */ void sort_cmds() { Cmdnum = 0; while(cmdlist[Cmdnum].cmdno != 0) Cmdnum++; qsort((void *)cmdlist, Cmdnum, sizeof(struct cmdstruct), sort_cmp); } /************************************************************************/ /* sort_cmp */ /************************************************************************/ /* This function is used by the quicksort routine to sort the command */ /* list according to how often each command has been used. */ int sort_cmp(arg1, arg2) struct cmdstruct *arg1, *arg2; { return(strcmp(arg1->cmdstr, arg2->cmdstr)); } /************************************************************************/ /* file_exists */ /************************************************************************/ /* This function returns 1 if the filename specified by the first par- */ /* ameter exists, 0 if it doesn't. */ int file_exists(filename) char *filename; { int ff; ff = open(filename, O_RDONLY); if(ff > -1) { close(ff); return(1); } else return(0); } /************************************************************************/ /* load_lockouts */ /************************************************************************/ /* This function opens the lockout file and reads in all locked out */ /* sites. */ void load_lockouts() { FILE *fp; char str[80]; int i; if(Lockout) free(Lockout); Numlockedout = 0; sprintf(str, "%s/lockout", LOGPATH); fp = fopen(str, "r"); if(!fp) return; while(1) { if(fscanf(fp, "%s", str) == EOF) break; if(fscanf(fp, "%s", str) == EOF) break; if(fscanf(fp, "%s", str) == EOF) break; Numlockedout++; } if(!Numlockedout) { fclose(fp); return; } Lockout = (lockout *)malloc(Numlockedout * sizeof(lockout)); fseek(fp, 0L, 0); for(i=0; i<Numlockedout; i++) { fscanf(fp, "%s", Lockout[i].userid); fscanf(fp, "%s", Lockout[i].address); fscanf(fp, "%s", Lockout[i].password); if(Lockout[i].password[0] == '-' && !Lockout[i].password[1]) Lockout[i].password[0] = 0; } fclose(fp); } /************************************************************************/ /* please_wait */ /************************************************************************/ void please_wait(fd, duration) int fd; int duration; { if(duration == 1) print(fd, "Please wait 1 more second.\n"); else print(fd, "Please wait %d more seconds.\n", duration); } /************************************************************************/ /* logn */ /************************************************************************/ /* This function writes a formatted printf string to a logfile called */ /* "name" in the log directory. */ void logn(name,fmt, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10) char *name; char *fmt; int i1, i2, i3, i4, i5, i6, i7, i8, i9, i10; { char file[80]; char str[1024]; int fd; sprintf(file, "%s/%s", LOGPATH,name); fd = open(file, O_RDWR | O_APPEND, 0); if(fd < 0) { fd = open(file, O_RDWR | O_CREAT, ACC); if(fd < 0) return; } lseek(fd, 0L, 2); sprintf(str, fmt, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10); write(fd, str, strlen(str)); close(fd); } /*====================================================================*/ #ifdef FREEBSD int is_num(str) #else int isnumber(str) #endif char *str; /* checks if the given str contains all digits */ { int len, i; len = strlen(str); for (i=0;i < len; i++) if(!isdigit(str[i])) return (0); return (1); }