#include <stdio.h> #include <sys/types.h> #include <time.h> #include <ctype.h> #include <string.h> #include "externs.h" #include "db.h" #include "config.h" #include "gametime.h" static long get_timezone() { struct timeval tv; struct timezone tz; gettimeofday(&tv, &tz); return(tz.tz_minuteswest*60); } static void get_tz(char *tz, char **tzp, int *lyp) { char *s; *lyp = 0; *tzp = tz; if(*tzp != NULL) if(**tzp != '\0') if((s = strchr(*tzp, ':')) != NULL) { ++s; if(*s == 'Y' || *s == 'y') *lyp = 1; } } static void get_thing_tz(OBJ *thing, char **tzp, int *lyp) { char *s; *tzp = atr_get(thing, "TZ"); if(**tzp == '\0') *tzp = atr_get(thing->owner, "TZ"); if(**tzp == '\0') *lyp = 0; else { if((s = strchr(*tzp, ':')) == NULL) *lyp = 0; else { ++s; if(*s == 'Y' || *s == 'y') *lyp = 1; } } } char *mktm(time_t cl, char *tz, OBJ *thing) { int ly; char *s; struct tm *tmp; long adjust, utcdiff; if(tz == NULL) tz = ""; if(*tz == 'D' || *tz == '\0') get_thing_tz(thing, &tz, &ly); else if(*tz != 'N') get_tz(tz, &tz, &ly); /* Determine time diff between gmt and local standard time */ utcdiff = get_timezone(); tmp = localtime(&cl); if(tmp) if(tmp->tm_isdst) utcdiff -= 3600L; /* Get or calculate timezone adjustment */ if(*tz == '\0') adjust = utcdiff; else { adjust = 0L - atol(tz) * 3600L; if(ly && tmp->tm_isdst > 0) adjust -= 3600L; } /* Adjust for timezone */ cl += (utcdiff - adjust); /* Generate ascii string */ s = ctime(&cl); *(s+strlen(s)-1) = '\0'; return(s); } /* this routine is designed to interpret a wide variety of time string formats converting them all to a longint x-value time representation */ long mkxtime(char *s, OBJ *thing, char *tz) { int i, j, ly; long cl, adjust, utcdiff; char *p, *q = s, *dayp, *yearp = NULL; int seconds, minutes, hours, day, month, year; struct tm tmbuf; static int tadjust[] = { 0, -4, -5, -5, -6, -6, -7, -7, -8 }; static char *tname[] = { "gmt", "edt", "est", "cdt", "cst", "mdt", "mst", "pdt", "pst", NULL }; static char *mname[] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec", NULL }; /* Locate month if present */ month = -1; for(p = s;month < 0 && *p;p++) { if(isalpha(*p)) for(i = 0;mname[i];i++) { j = 0, q = p; while(mname[i][j] && mname[i][j] == tolower(*q)) ++j, ++q; if(!mname[i][j]) { month = i; break; } } } if(month < 0) return(-1L); /* Skip remaining string and whitespace */ for(p = q;isalpha(*p);p++); for(;isspace(*p);p++); /* Get day */ day = -1; if(isdigit(*p)) day = atoi(p); if(day < 1 || day > 31) return(-1L); dayp = p; /* Get year */ year = -1; for(p = s;*p;p++) if(isdigit(*p)) { year = atoi(p); if(year < 1900) { year = -1; for(;isdigit(*p);p++); continue; } yearp = p; break; } if(year < 0) return(-1L); /* Get hours */ hours = -1; for(p = s;*p;p++) if(isdigit(*p)) { hours = atoi(p); if(p == dayp || p == yearp || hours < 0 || hours > 59) { hours = -1; for(;isdigit(*p);p++); continue; } break; } if(hours < 0) return(-1L); for(;isdigit(*p);p++); /* Get minutes */ minutes = -1; if(*p == ':') minutes = atoi(++p); if(minutes < 0 || minutes > 59) return(-1L); for(;isdigit(*p);p++); /* Get seconds */ seconds = -1; if(*p == ':') seconds = atoi(++p); if(seconds < 0 || seconds > 59) return(-1L); tmbuf.tm_sec = seconds; tmbuf.tm_min = minutes; tmbuf.tm_hour = hours; tmbuf.tm_mday = day; tmbuf.tm_mon = month; tmbuf.tm_year = year - 1900; tmbuf.tm_isdst = -1; cl = mktime(&tmbuf); /* Determine time diff between gmt and local standard time */ /* (for the time calculated) */ utcdiff = (tmbuf.tm_isdst > 0)?get_timezone() - 3600L:get_timezone(); /* Calculate timezone adjustment */ if(!tz) tz = ""; if(*tz == 'D' || !*tz) get_thing_tz(thing, &tz, &ly); else get_tz(tz, &tz, &ly); if(!*tz) adjust = utcdiff; else { adjust = 0L - atol(tz) * 3600L; if(ly && tmbuf.tm_isdst > 0) adjust -= 3600L; } /* Check for timezone override in string specification */ for(p = s;*p;p++) if(isalpha(*p)) { for(i = 0;tname[i];i++) { j = 0; q = p; while(tname[i][j] && tname[i][j] == tolower(*q)) ++j, ++q; if(!tname[i][j]) { adjust = 0L - (3600L * (long) (tadjust[i])); goto OUT; } } } OUT: cl += (adjust - utcdiff); return(cl); } char *make_human_time(int seconds) { char buf[4096]; const long sec_per_year = 31104000L; const long sec_per_month = 2592000L; const long sec_per_day = 86400L; if(seconds >= sec_per_year) sprintf(buf, "%ld year%s", seconds/sec_per_year, check_plural(seconds/sec_per_year, "", "s")); else if(seconds >= sec_per_month) sprintf(buf, "%ld month%s", seconds/sec_per_month, check_plural(seconds/sec_per_month, "", "s")); else sprintf(buf, "%ld day%s", seconds/sec_per_day, check_plural(seconds/sec_per_day, "", "s")); return(stack_string_alloc(buf, 0)); } char *time_format(time_t ticks, int num_fields) { struct { char suffix; time_t length; int amount; } data[6] = { { 'y', SEC_PER_YEAR, 0 }, { 'w', SEC_PER_WEEK, 0 }, { 'd', SEC_PER_DAY, 0 }, { 'h', SEC_PER_HOUR, 0 }, { 'm', SEC_PER_MINUTE, 0 }, { 's', 1, 0 }, }; char buf[4096] = ""; int i, j, first = 0; for(i = 0;i < 6;++i) { data[i].amount = ticks / data[i].length; ticks -= data[i].amount * data[i].length; } for(i = 0;i < 5;++i) /* Don't pass seconds up */ if(data[i].amount) break; for(j = 0;j < num_fields && i < 6;++j, ++i) { if(!first++) sprintf(buf+strlen(buf), "%d%c", data[i].amount, data[i].suffix); else sprintf(buf+strlen(buf), " %2d%c", data[i].amount, data[i].suffix); } return(stack_string_alloc(buf, 0)); } unsigned int my_rand(void) { #ifdef USE_DEV_URANDOM static unsigned int num_list[URANDOM_BURST], offset = -1; static int disable = 0; extern int rand_fd; #endif /* USE_DEV_URANDOM */ #ifndef USE_DEV_URANDOM return(rand()); #else if(disable) return(rand()); if(offset < 0 || offset >= URANDOM_BURST) { if(read(rand_fd, num_list, sizeof(int)*URANDOM_BURST) == -1) { log_error("Couldn't read from /dev/urandom. Disabling."); disable = 1; return(rand()); } offset = 0; } return(num_list[offset++]); #endif /* USE_DEV_URANDOM */ }