diff --git a/README b/README index 7399736..86b4c63 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -mini-at http://www.lwithers.me.uk/projects/mini-at/ +mini-at ======================================================================== (c)2006, Laurence Withers, . Released under the GNU GPLv2. See file COPYING or @@ -7,8 +7,6 @@ http://www.gnu.org/copyleft/gpl.html for details. Really Quick Instructions ------------------------- -Install libiso8601 from http://www.lwithers.me.uk/projects/libiso8601/ . - To build: ./make.sh To install: ./make.sh install (you might want to set PREFIX, by default it's /usr/local) diff --git a/src/mini-at/TopSource.c b/src/mini-at/TopSource.c index f7a39eb..f215c82 100644 --- a/src/mini-at/TopSource.c +++ b/src/mini-at/TopSource.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff --git a/src/mini-at/build.app b/src/mini-at/build.app index 5e2be31..064ba34 100644 --- a/src/mini-at/build.app +++ b/src/mini-at/build.app @@ -6,8 +6,7 @@ if [ -z ${mini_at_BUILT} ] then mini_at="obj/mini-at" - [ -z "${LIBISO8601_FLAGS}" ] && LIBISO8601_FLAGS="$(pkg-config libiso8601 --libs --cflags)" - EXTRAS="${LIBISO8601_FLAGS}" + EXTRAS="" # @TODO@ cflags, libs echo "Building application ${mini_at}..." diff --git a/src/mini-at/time.c b/src/mini-at/time.c index 055cd4d..3578abf 100644 --- a/src/mini-at/time.c +++ b/src/mini-at/time.c @@ -7,18 +7,426 @@ +int parse_time_digs(const char* str, int numdigs) +{ + int i = 0; + char ch; + + while(numdigs--) { + switch( (ch = *str++) ) { + case '0' ... '9': + i *= 10; + i += ch - '0'; + break; + + default: + return -1; + } + } + + return i; +} + + + +int parse_time_date_daysinyear(int year) +{ + if(!(year % 400)) return 366; + if(!(year % 100)) return 365; + if(!(year % 4)) return 366; + return 365; +} + + + +struct parse_time_date_dayselapsed_t { + int ndays, elapsed; +}; + +struct parse_time_date_dayselapsed_t parse_time_date_dayselapsed_cal[] = { + { 31, 0 }, + { 28, 31 }, + { 31, 59 }, + { 30, 90 }, + { 31, 120 }, + { 30, 151 }, + { 31, 181 }, + { 31, 212 }, + { 30, 243 }, + { 31, 273 }, + { 30, 304 }, + { 31, 334 } +}; + +struct parse_time_date_dayselapsed_t parse_time_date_dayselapsed_leapcal[] = { + { 31, 0 }, + { 29, 31 }, + { 31, 60 }, + { 30, 91 }, + { 31, 121 }, + { 30, 152 }, + { 31, 182 }, + { 31, 213 }, + { 30, 244 }, + { 31, 274 }, + { 30, 305 }, + { 31, 335 } +}; + +int parse_time_date_dayselapsed(int year, int mon, int day) +{ + struct parse_time_date_dayselapsed_t* t; + + --mon; + if(mon < 0 || mon > 11) return -1; + + if(parse_time_date_daysinyear(year) == 366) t = parse_time_date_dayselapsed_leapcal; + else t = parse_time_date_dayselapsed_cal; + + t += mon; + --day; + if(day < 0 || day > t->ndays) return -1; + + return day + t->elapsed; +} + + + +// number of seconds elapsed between 1970 and start of `year' +time_t parse_time_date_mkyear(int year) +{ + long nd; + + // we have an inverse y2k problem! + // basically, the algorithm needs to operate on a 400-year boundary for leap days + // since this is `at', we don't deal with dates in the past + // time_t can't deal with dates earlier than 1970 + // so 2000 seems a logical place to start + year -= 2000; + if(year < 0) return -1; + + /* Every 4th year is leap + * unless it's a century (not leap) + * unless it's a 4*century (leap) + * + * So there are 97 leap days in 400 years, giving 365 * 400 + 397 = 146097 days + * For each 100 years, there are 24 leaps, giving 365 * 100 + 24 = 36524 days + * For each 4 years, there is 1 leap, giving 365 * 4 + 1 = 1461 days + */ + nd = 146097l * (year / 400); + year %= 400; + if(year) { + nd += 36524 * (year / 100); + year %= 100; + nd += 1461 * (year / 4); + if(year) { + year %= 4; + nd += (year ? 1 : 0) + 365 * year; + } else { + nd++; + } + } + + /* Now add number of days between 1970 and 2000 (7 leap years) + * 30 * 365 + 7 = 10957 */ + nd += 10957; + + // ignoring leap seconds, as time_t does, there are 86400 seconds in a day + nd *= 86400; + + // done! + return (time_t)nd; +} + + + +time_t parse_time_date_mkwk(int year, int wk, int wday) +{ +// time_t t; + + fprintf(stderr, "ISO8601 week dates not supported yet\n"); + return -1; + +/* + t = parse_time_date_mkyear(year); + if(t == (time_t)-1) return -1; +*/ +} + + + +time_t parse_time_date_mkord(int year, int oday) +{ + time_t t; + + if(oday < 1 || oday > parse_time_date_daysinyear(year)) return -1; + t = parse_time_date_mkyear(year); + if(t == (time_t)-1) return -1; + + t += (oday - 1) * 86400; + return t; +} + + + +time_t parse_time_date_mkcal(int year, int mon, int day) +{ + time_t t; + + t = parse_time_date_mkyear(year); + if(t == (time_t)-1) return -1; + + t += parse_time_date_dayselapsed(year, mon, day) * 86400; + return t; +} + + + +time_t parse_time_date(const char* str, const char* end) +{ + int year, mon, day; + const char* pos; + + // we don't deal with negative years -- this is at! + if(*str < '0' || *str > '9') return -1; + + if( (pos = strchr(str, 'W')) ) { + if(strchr(pos, '-')) { + /* Either of: + * yyyy-Www + * yyyy-Www-d + */ + switch(end - pos) { + case 3: + year = parse_time_digs(str, pos - str - 1); + mon = parse_time_digs(pos + 1, 2); + return parse_time_date_mkwk(year, mon, 1); + + case 5: + year = parse_time_digs(str, pos - str - 1); + mon = parse_time_digs(pos + 1, 2); + day = parse_time_digs(pos + 4, 1); + return parse_time_date_mkwk(year, mon, day); + + default: + return -1; + } + + } else { + /* Either of: + * yyyyWww + * yyyyWwwd + */ + switch(end - pos) { + case 3: + year = parse_time_digs(str, pos - str); + mon = parse_time_digs(pos + 1, 2); + return parse_time_date_mkwk(year, mon, 1); + + case 4: + year = parse_time_digs(str, pos - str); + mon = parse_time_digs(pos + 1, 2); + day = parse_time_digs(pos + 3, 2); + return parse_time_date_mkwk(year, mon, day); + + default: + return -1; + } + } + + } else if( (pos = strchr(str, '-')) ) { + /* Valid extended formats are: + * yyyy-mm (year + len 3) + * yyyy-ooo (year + len 4) + * yyyy-mm-dd (year + len 6) + */ + switch(end - pos) { + case 3: + year = parse_time_digs(str, pos - str); + mon = parse_time_digs(pos + 1, 2); + return parse_time_date_mkcal(year, mon, 1); + + case 4: + year = parse_time_digs(str, pos - str); + day = parse_time_digs(pos + 1, 3); + return parse_time_date_mkord(year, day); + + case 6: + year = parse_time_digs(str, pos - str); + mon = parse_time_digs(pos + 1, 2); + day = parse_time_digs(pos + 4, 2); + return parse_time_date_mkcal(year, mon, day); + + default: + return -1; + } + } + + /* Valid basic formats, excluding week formats, are: + * yyyy (len 4) + * yyyymm (len 6) + * yyyyooo (len 7) + * yyyymmdd (len 8) + */ + + switch(end - str) { + case 4: + year = parse_time_digs(str, 4); + return parse_time_date_mkord(year, 1); + + case 6: + year = parse_time_digs(str, 4); + mon = parse_time_digs(str + 4, 2); + return parse_time_date_mkcal(year, mon, 1); + + case 7: + year = parse_time_digs(str, 4); + day = parse_time_digs(str + 4, 3); + return parse_time_date_mkord(year, day); + + case 8: + year = parse_time_digs(str, 4); + mon = parse_time_digs(str + 4, 2); + day = parse_time_digs(str + 6, 2); + return parse_time_date_mkcal(year, mon, day); + + default: + return -1; + } +} + + + +int parse_time_time(const char* str, const char* end) +{ + const char* pos; + double d = 0; + char* endp; + int h = 0, m = 0, s = 0, ret; + + pos = strchr(str, '.'); + if(pos) { + errno = 0; + endp = 0; + d = strtod(pos, &endp); + if(errno || !endp) return -1; + switch(*endp) { + case 'Z': + case '+': + case '-': + case 0: + break; + + default: + return -1; + } + } else { + pos = end; + } + + /* Valid formats, excluding fraction, are: + * + * hh (len 2) + * hhmm (len 4) + * hh:mm (len 5) + * hhmmss (len 6) + * hh:mm:ss (len 8) + */ + switch(pos - str) { + case 2: + h = parse_time_digs(str, 2); + ret = ((h + d) * 3600 + 0.5); + break; + + case 4: + h = parse_time_digs(str, 2); + m = parse_time_digs(str + 2, 2); + ret = h * 3600 + ((m + d) * 60 + 0.5); + break; + + case 5: + h = parse_time_digs(str, 2); + m = parse_time_digs(str + 3, 2); + ret = h * 3600 + ((m + d) * 60 + 0.5); + break; + + case 6: + h = parse_time_digs(str, 2); + m = parse_time_digs(str + 2, 2); + s = parse_time_digs(str + 4, 2); + ret = h * 3600 + m * 60 + s + d + 0.5; + break; + + case 8: + h = parse_time_digs(str, 2); + m = parse_time_digs(str + 3, 2); + s = parse_time_digs(str + 5, 2); + ret = h * 3600 + m * 60 + s + d + 0.5; + break; + + default: + return -1; + } + + // special cases + if(h == 24 && m == 0 && s == 0) return ret; // midnight at end of day + if(h == 23 && m == 59 && s == 60) return ret; // leap second + + if(h < 0 || h > 23) return -1; + if(m < 0 || m > 59) return -1; + if(s < 0 || s > 59) return -1; + + return ret; +} + + + /* parse_time() * - * Parses an ISO-8601 date/time. We support any of the ISO-8601 formats. Uses libiso8601. On error, - * returns (time_t)-1. + * Parses an ISO-8601 date/time. We support any of the ISO-8601 formats. */ time_t parse_time(const char* str) { - struct iso8601_date iso; + const char* p, * tz; time_t t; + int s; + + // parse the date portion + p = strchr(str, 'T'); + t = p ? parse_time_date(str, p) : parse_time_date(str, str + strlen(str)); + if(t == (time_t)-1) return -1; + + // parse the time portion + if(p) { + ++p; + tz = strchr(p, 'Z'); + if(tz) { + if(tz[1]) return -1; + } else { + tz = strchr(p, '+'); + if(!tz) tz = strchr(p, '-'); + if(!tz) tz = p + strlen(p); + } + s = parse_time_time(p, tz); + if(s == -1) return -1; + t += s; + + p = tz + 1; + switch(*tz) { + case '+': + s = parse_time_time(p, p + strlen(p)); + if(s == -1) return -1; + t -= s; + break; + + case '-': + s = parse_time_time(p, p + strlen(p)); + if(s == -1) return -1; + t += s; + break; + } + } - if(iso8601_parse(str, &iso, 0, 0)) return (time_t)-1; - iso8601_to_time_t(&t, &iso); return t; } diff --git a/src/mini-atd/main.c b/src/mini-atd/main.c index 466154a..1ae22cf 100644 --- a/src/mini-atd/main.c +++ b/src/mini-atd/main.c @@ -51,7 +51,7 @@ int main(int argc, char* argv[]) // process commandline options while(1) { - switch(getopt_long(argc, argv, "hVDs:p:", options, 0)) { + switch(getopt_long(argc, argv, "hVs:p:", options, 0)) { case -1: goto done; diff --git a/src/mini-atd/setup.c b/src/mini-atd/setup.c index 612d23f..0f20317 100644 --- a/src/mini-atd/setup.c +++ b/src/mini-atd/setup.c @@ -29,8 +29,9 @@ void do_log(int level, const char* fmt, ...) va_start(va, fmt); - vsyslog(level, fmt, va); - if(!Daemon) { + if(Daemon) { + vsyslog(level, fmt, va); + } else { FILE* out = stdout; switch(level) { @@ -127,7 +128,6 @@ int setup_socket(const char* name, int perms) addr.sun_family = AF_UNIX; strcpy(addr.sun_path, name); // main() ensures it is less than UNIX_PATH_MAX bytes - unlink(name); // unlink any existing socket, but ignore errors if(bind(fd, (struct sockaddr*)&addr, sizeof(addr))) { LOG(LOG_CRIT, "Couldn't bind socket (fd %d) to file ``%s'' - %s (%d).", fd, name, strerror(errno), errno); diff --git a/version b/version index 4705925..fafb486 100644 --- a/version +++ b/version @@ -11,8 +11,8 @@ # expected to be in 'major.minor.micro' format. It can optionally be # suffixed with a string. VERMAJOR=1 -VERMINOR=1 -VERMICRO=1 +VERMINOR=0 +VERMICRO=0 VEREXTRA="" # kate: replace-trailing-space-save true; space-indent true; tab-width 4;