/************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefiting. We hope that you share your changes too. What goes * * around, comes around. * *************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************** * 1stMUD ROM Derivative (c) 2001-2003 by Ryan Jennings * * http://1stmud.dlmud.com/ <r-jenn@shaw.ca> * ***************************************************************************/ #include "merc.h" #include "globals.h" #include "recycle.h" #include "save.h" char *timestr(time_t time, bool fShort) { static char timebuf[3][MSL]; static int pindex; // used to rotate around 3 buffers, so timestr can long dsec, dmin, dhour, dday; long dweek, dmonth, dyear; char working[MSL]; char *trim; // be used up to 3 times in one context without // overwriting a previous buffer ++pindex; pindex %= 3; // rotate the pindex timebuf[pindex][0] = NUL; // clear the previous string // calculate the difference in time, and break it down dsec = abs(time); dday = dsec / (DAY); dsec %= DAY; dyear = dday / 365; dday %= 365; dweek = dday / 7; dday %= 7; dmonth = dweek * 12 / 52; dweek -= dmonth * 52 / 12; dhour = dsec / (HOUR); dsec %= HOUR; dmin = dsec / MINUTE; dsec = dsec % MINUTE; // format the result up working[0] = NUL; if (dyear != 0) { if (!fShort) sprintf(working, "%ld year%s, ", dyear, ((dyear != 1) ? "s" : "")); else sprintf(working, "%ld:", dyear); strcat(timebuf[pindex], working); } if (dmonth != 0) { if (!fShort) sprintf(working, "%ld month%s, ", dmonth, ((dmonth != 1) ? "s" : "")); else sprintf(working, "%ld:", dmonth); strcat(timebuf[pindex], working); } if (dweek != 0) { if (!fShort) sprintf(working, "%ld week%s, ", dweek, ((dweek != 1) ? "s" : "")); else sprintf(working, "%ld:", dweek); strcat(timebuf[pindex], working); } if (dday != 0) { if (!fShort) sprintf(working, "%ld day%s, ", dday, ((dday != 1) ? "s" : "")); else sprintf(working, "%ld:", dday); strcat(timebuf[pindex], working); } if (dhour != 0) { if (!fShort) sprintf(working, "%ld hour%s, ", dhour, ((dhour != 1) ? "s" : "")); else sprintf(working, "%ld:", dhour); strcat(timebuf[pindex], working); } if (dmin != 0) { if (!fShort) sprintf(working, "%ld minute%s, ", dmin, ((dmin != 1) ? "s" : "")); else sprintf(working, "%ld:", dmin); strcat(timebuf[pindex], working); } if (dsec != 0) { if (!fShort) sprintf(working, "%ld second%s", dsec, ((dsec != 1) ? "s" : "")); else sprintf(working, "%ld:", dsec); strcat(timebuf[pindex], working); } // remove a space and comma that could be at the end of the line trim = &timebuf[pindex][strlen(timebuf[pindex]) - 1]; if (*trim == ' ' || *trim == ',' || *trim == ':') { *trim = NUL; trim--; if (*trim == ' ' || *trim == ',' || *trim == ':') *trim = NUL; } return (timebuf[pindex]); } void fwrite_time(FILE * fp, const char *name, time_t time, bool fTime) { if (!IS_NULLSTR(name)) fprintf(fp, "%s%s", name, format_tabs(strlen(name))); else fprintf(fp, " "); fprintf(fp, "%ld", time); fprintf(fp, "(%s)\n", !fTime ? str_time(time, -1, NULL) : timestr(current_time - time, FALSE)); } void fread_time(FILE * fp, time_t * tptr) { *tptr = fread_long(fp); fread_to_eol(fp); } void read_time(READ_DATA * str, time_t * tptr) { *tptr = read_long(str); read_to_eol(str); } WRITE_DATA *open_w_a(const char *file, const char *mode) { WRITE_DATA *fp; static int count = 0; if (IS_NULLSTR(file)) return NULL; alloc_mem(fp, WRITE_DATA, 1); if (!fp) return NULL; if (++count > 999) count = 0; fp->file = str_dup(file); #if !defined(WIN32) fp->temp = str_dup(FORMATF("%s.tmp%03d", file, count)); if ((fp->stream = file_open(fp->temp, mode)) == NULL) #else if ((fp->stream = file_open(fp->file, mode)) == NULL) #endif { file_close(fp->stream); free_string(fp->temp); free_string(fp->file); free_mem(fp); return NULL; } return fp; } WRITE_DATA *open_write(const char *path, ...) { char file[1024]; va_list args; if (IS_NULLSTR(path)) return NULL; va_start(args, path); vsnprintf(file, sizeof(file), path, args); va_end(args); return open_w_a(file, "w+"); } WRITE_DATA *open_append(const char *path, ...) { char file[1024]; va_list args; if (IS_NULLSTR(path)) return NULL; va_start(args, path); vsnprintf(file, sizeof(file), path, args); va_end(args); return open_w_a(file, "a+"); } void close_write(WRITE_DATA * fp) { if (fp) { file_close(fp->stream); #if !defined(WIN32) if (rename(fp->temp, fp->file)) { bugf("error renaming %s -> %s", fp->temp, fp->file); log_error("rename"); } #endif free_string(fp->temp); free_string(fp->file); free_mem(fp); } fp = NULL; } void close_append(WRITE_DATA * fp) { close_write(fp); } #define MLR (MAX_STRING_LENGTH * 25) const char *fread_file(FILE * fp) { char buf[MLR + 2]; /* extra 2 bytes on the end for \0 and 1b slack */ char c; long i = 0; bool sFull = FALSE; /* clearing the buffer means we don't have to append \0 on the end */ memset(buf, 0, sizeof(buf)); for (;;) { if (i >= MLR && !sFull) { bugf("String [%20.20s...] exceeded %db size [MLR]", buf, MLR); sFull = TRUE; } switch (c = getc(fp)) { default: if (!sFull) { buf[i] = c; i++; } break; case '\n': if (!sFull) { buf[i] = '\n'; i++; buf[i] = '\r'; i++; } break; case '\r': break; case EOF: return str_dup(buf); } } } const char *read_file(READ_DATA * str) { char buf[MLR + 2]; /* extra 2 bytes on the end for \0 and 1b slack */ char c; long i = 0; bool sFull = FALSE; /* clearing the buffer means we don't have to append \0 on the end */ memset(buf, 0, sizeof(buf)); for (;;) { if (i >= MLR && !sFull) { bugf("FILE: %s: String [%20.20s...] exceeded %db size [MLR]", str->file, buf, MLR); sFull = TRUE; } switch (c = stgetc(str)) { default: if (!sFull) { buf[i] = c; i++; } break; case '\n': if (!sFull) { buf[i] = '\n'; i++; buf[i] = '\r'; i++; } break; case '\r': break; case NUL: return str_dup(buf); } } } /* Function Name: FILE *file_open (const char *mode, char *fmt,...) * this function closes fpReserve (if open), and opens a stream to the * file specified, with the specified modes. */ FILE *file_open(const char *file, const char *mode) { FILE *fp; if (fpReserve != NULL) { fclose(fpReserve); fpReserve = NULL; } if (!(fp = fopen(file, mode))) { fpReserve = fopen(NULL_FILE, "r"); return NULL; } return fp; } /* Function Name: void file_close (FILE *fp) * this function closes the stream specified, and attempts to re-open * fpReserve, if it's not already open. */ void file_close(FILE * fp) { if (fp != NULL) fclose(fp); fp = NULL; if (fpReserve == NULL) fpReserve = fopen(NULL_FILE, "r"); } READ_DATA *open_read(const char *path, ...) { struct stat buf; READ_DATA *str; va_list args; char file[1024]; FILE *fp; if (IS_NULLSTR(path)) return NULL; va_start(args, path); vsnprintf(file, sizeof(file), path, args); va_end(args); if (stat(file, &buf) == -1 || !S_ISREG(buf.st_mode)) return NULL; if ((fp = file_open(file, "r")) == NULL) { file_close(fp); return NULL; } alloc_mem(str, READ_DATA, 1); str->pos = 0; str->size = buf.st_size; str->file = str_dup(file); alloc_mem(str->str, char, str->size + 1); fread(str->str, str->size + 1, 1, fp); file_close(fp); str->str[str->size] = NUL; return str; } void close_read(READ_DATA * str) { if (str) { free_mem(str->str); free_string(str->file); free_mem(str); } str = NULL; } char fread_letter(FILE * fp) { char c; do { c = getc(fp); } while (isspace(c)); return c; } char read_letter(READ_DATA * str) { char c; do { c = stgetc(str); } while (isspace(c)); return c; } int fread_number(FILE * fp) { int number; bool sign; char c; do { c = getc(fp); } while (isspace(c)); number = 0; sign = FALSE; if (c == '+') { c = getc(fp); } else if (c == '-') { sign = TRUE; c = getc(fp); } if (!isdigit(c)) { bug("bad format."); abort(); } while (isdigit(c)) { number = number * 10 + c - '0'; c = getc(fp); } if (sign) number = 0 - number; if (c == '|') number += fread_number(fp); else if (c != ' ') ungetc(c, fp); return number; } int read_number(READ_DATA * str) { int number; bool sign; char c; do { c = stgetc(str); } while (isspace(c)); number = 0; sign = FALSE; if (c == '+') { c = stgetc(str); } else if (c == '-') { sign = TRUE; c = stgetc(str); } if (!isdigit(c)) { bugf("FILE: %s: bad format.", str->file); abort(); } while (isdigit(c)) { number = number * 10 + c - '0'; c = stgetc(str); } if (sign) number = 0 - number; if (c == '|') number += read_number(str); else if (c != ' ') str->pos--; return number; } long fread_long(FILE * fp) { long number; bool sign; char c; do { c = getc(fp); } while (isspace(c)); number = 0; sign = FALSE; if (c == '+') { c = getc(fp); } else if (c == '-') { sign = TRUE; c = getc(fp); } if (!isdigit(c)) { bug("bad format."); abort(); } while (isdigit(c)) { number = number * 10 + c - '0'; c = getc(fp); } if (sign) number = 0 - number; if (c == '|') number += fread_long(fp); else if (c != ' ') ungetc(c, fp); return number; } long read_long(READ_DATA * str) { long number; bool sign; char c; do { c = stgetc(str); } while (isspace(c)); number = 0; sign = FALSE; if (c == '+') { c = stgetc(str); } else if (c == '-') { sign = TRUE; c = stgetc(str); } if (!isdigit(c)) { bugf("FILE: %s: bad format.", str->file); abort(); } while (isdigit(c)) { number = number * 10 + c - '0'; c = stgetc(str); } if (sign) number = 0 - number; if (c == '|') number += read_long(str); else if (c != ' ') str->pos--; return number; } flag_t fread_flag(FILE * fp) { flag_t number; flag_t flag; flag_t temp = 1; char c; bool negative = FALSE; do { c = getc(fp); } while (isspace(c)); if (c != '+') { if (c == '-') { negative = TRUE; c = getc(fp); } number = 0; if (!isdigit(c)) { while (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) { number += flag_convert(c); c = getc(fp); } } while (isdigit(c)) { number = number * 10 + c - '0'; c = getc(fp); } if (c == '|') number += fread_flag(fp); else if (c != ' ') ungetc(c, fp); if (negative) return -1 * number; return number; } else { number = 0; flag = 0; do { c = getc(fp); flag += (temp << number) * (c == 'Y'); number++; } while (c == 'Y' || c == 'n'); if (c == '\n' || c == '\r') ungetc(c, fp); return flag; } } flag_t read_flag(READ_DATA * str) { flag_t number; flag_t flag; flag_t temp = 1; char c; bool negative = FALSE; do { c = stgetc(str); } while (isspace(c)); if (c != '+') { if (c == '-') { negative = TRUE; c = stgetc(str); } number = 0; if (!isdigit(c)) { while (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) { number += flag_convert(c); c = stgetc(str); } } while (isdigit(c)) { number = number * 10 + c - '0'; c = stgetc(str); } if (c == '|') number += read_flag(str); else if (c != ' ') str->pos--; if (negative) return -1 * number; return number; } else { number = 0; flag = 0; do { c = stgetc(str); flag += (temp << number) * (c == 'Y'); number++; } while (c == 'Y' || c == 'n'); if (c == '\n' || c == '\r') str->pos--; return flag; } } void fread_to_eol(FILE * fp) { char c; do { c = getc(fp); } while (c != '\n' && c != '\r'); do { c = getc(fp); } while (c == '\n' || c == '\r'); ungetc(c, fp); return; } void read_to_eol(READ_DATA * str) { char c; do { c = stgetc(str); } while (c != '\n' && c != '\r'); do { c = stgetc(str); } while (c == '\n' || c == '\r'); str->pos--; return; } char *fread_word(FILE * fp) { static char word[MIL]; char *pword; char cEnd; do { if (feof(fp)) { bug(" EOF encountered on read."); if (run_level == RUNLEVEL_BOOTING) exit(1); word[0] = NUL; return word; } cEnd = getc(fp); } while (isspace(cEnd)); if (cEnd == '\'' || cEnd == '"') { pword = word; } else { word[0] = cEnd; pword = word + 1; cEnd = ' '; } for (; pword < word + MIL; pword++) { *pword = getc(fp); if (cEnd == ' ' ? isspace(*pword) : *pword == cEnd) { if (cEnd == ' ') ungetc(*pword, fp); *pword = NUL; return word; } } bug("word too long."); abort(); return NULL; } char *read_word(READ_DATA * fp) { static char word[MIL]; char *pword; char cEnd; do { if (steof(fp)) { bugf(" EOF encountered on read. %d/%d chars.", fp->pos, fp->size); if (run_level == RUNLEVEL_BOOTING) exit(1); word[0] = NUL; return word; } cEnd = stgetc(fp); } while (isspace(cEnd)); if (cEnd == '\'' || cEnd == '"') { pword = word; } else { word[0] = cEnd; pword = word + 1; cEnd = ' '; } for (; pword < word + MIL; pword++) { *pword = stgetc(fp); if (cEnd == ' ' ? isspace(*pword) : *pword == cEnd) { if (cEnd == ' ') fp->pos--; *pword = NUL; return word; } } bug("word too long."); abort(); return NULL; } const char *fread_string(FILE * fp) { char buf[MLR + 2]; /* extra 2 bytes on the end for \0 and 1b slack */ long i = 0; register char c; bool sFull = FALSE; /* skip blanks */ do { c = getc(fp); } while (isspace(c)); /* empty string */ if (c == '~') return str_dup(""); buf[i++] = c; for (;;) { if (i >= MLR && !sFull) { bugf("String [%20.20s...] exceeded [%d] MLR", buf, MLR); sFull = TRUE; } switch (c = getc(fp)) { default: if (!sFull) { buf[i++] = c; } break; case EOF: /* temp fix */ bugf("String [%20.20s...] EOF", buf); abort(); break; case '\n': if (!sFull) { buf[i++] = '\n'; buf[i++] = '\r'; } break; case '\r': break; case '~': buf[i] = NUL; return str_dup(buf); break; } } } const char *read_string(READ_DATA * str) { static char buf[MLR + 2]; /* extra 2 bytes on the end for \0 and 1b slack */ long i = 0; register char c; bool sFull = FALSE; /* skip blanks */ do { c = stgetc(str); } while (isspace(c)); /* empty string */ if (c == '~') return str_dup(""); buf[i++] = c; for (;;) { if (i >= MLR && !sFull) { bugf("FILE: %s: String [%20.20s...] exceeded [%d] MLR", str->file, buf, MLR); sFull = TRUE; } switch (c = stgetc(str)) { default: if (!sFull) { buf[i++] = c; } break; case NUL: /* temp fix */ bugf("FILE: %s: String [%20.20s...] EOF pos %d", str->file, buf, str->pos); abort(); break; case '\n': if (!sFull) { buf[i++] = '\n'; buf[i++] = '\r'; } break; case '\r': break; case '~': buf[i] = NUL; return str_dup(buf); break; } } } /* * Read to end of line into static buffer */ const char *fread_line(FILE * fp) { static char line[MSL]; char *pline; char c; int ln; pline = line; line[0] = NUL; ln = 0; /* * Skip blanks. * Read first char. */ do { if (feof(fp)) { bug("EOF encountered on read."); strcpy(line, ""); return line; } c = getc(fp); } while (isspace(c)); ungetc(c, fp); do { if (feof(fp)) { bug("EOF encountered on read."); *pline = NUL; return line; } c = getc(fp); *pline++ = c; ln++; if (ln >= (MSL - 1)) { bug("line too long"); break; } } while (c != '\n' && c != '\r'); do { c = getc(fp); } while (c == '\n' || c == '\r'); ungetc(c, fp); *pline = NUL; return line; } const char *read_line(READ_DATA * str) { static char line[MSL]; char *pline; char c; int ln; pline = line; line[0] = NUL; ln = 0; /* * Skip blanks. * Read first char. */ do { if (steof(str)) { bugf("EOF encountered on read. pos %d.", str->pos); strcpy(line, ""); return line; } c = stgetc(str); } while (isspace(c)); str->pos--; do { if (steof(str)) { bug("EOF encountered on read."); *pline = NUL; return line; } c = stgetc(str); *pline++ = c; ln++; if (ln >= (MSL - 1)) { bug("line too long"); break; } } while (c != '\n' && c != '\r'); do { c = stgetc(str); } while (c == '\n' || c == '\r'); str->pos--; *pline = NUL; return line; } bool steof(READ_DATA * fp) { return (fp->pos >= fp->size); } char stgetc(READ_DATA * fp) { char c = fp->str[fp->pos]; if (!steof(fp)) fp->pos++; return c; }