/****************************************************************************/ /* Convert unix binary time to RFC 1123 time format: * Wdy, DD Mon YY HH:MM:SS TIMEZONE * * If DATE_FORMAT_850 defined, use older format. * Weekday, DD-Mon-YY HH:MM:SS TIMEZONE * */ #include #include #include #include extern int lib$emul(), lib$ediv(), lib$addx(), lib$subx(), sys$bintim(); static unsigned long base_time[2], zero_time[2]; static int base_initialized = 0; static void init_base_time() { int status, tdiff, conv, offset; unsigned long diff_time[2]; $DESCRIPTOR ( unix_zero, "1-JAN-1970 00:00:00.0" ); char *tzone; /* * Convert unix base time to VMS format. */ status = sys$bintim ( &unix_zero, zero_time ); /* * Get offset from GMT. and adjust base time. */ tzone = getenv ( "SYS$TIMEZONE_DIFFERENTIAL" ); if ( tzone ) { tdiff = atoi ( tzone ); conv = -10000000; offset = 0; lib$emul ( &tdiff, &conv, &offset, diff_time ); lib$addx ( diff_time, zero_time, base_time ); } else { base_time[0] = zero_time[0]; base_time[1] = zero_time[1]; } base_initialized = 1; } char *tf_format_time ( unsigned long bintim, char *buffer ) { #ifdef DATE_FORMAT_850 static char *weekday[] = {"Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday"}; #define MONTH_DELIMITER '-' #else static char *weekday[] = {"Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed"}; #define MONTH_DELIMITER ' ' #endif static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; unsigned long offset, conv, quad_time[2], final_time[2]; int status, i, wdy, mon, sys$numtim(); unsigned short num_time[7]; /* * Initialize constants used in conversion. */ if ( !base_initialized ) init_base_time(); /* * Convert Unix time (seconds since 1970) to VMS binary time, base * time is adjust to result time in UTC (GMT) timezone. */ offset = 0; conv = 10000000; /* 100 nanosecond ticks to seconds */ lib$emul ( &bintim, &conv, &offset, quad_time ); lib$addx ( quad_time, base_time, final_time ); status = sys$numtim ( num_time, final_time ); /* * Get day of week. */ wdy = bintim / 86400; /* day-number since 1970 */ wdy = wdy % 7; /* Day of week */ for ( i = 0; weekday[wdy][i]; i++ ) buffer[i] = weekday[wdy][i]; buffer[i++] = ','; buffer[i++] = ' '; /* * Add date; */ buffer[i] = (char) (48+(num_time[2]/10)); /* Day of month */ i++; /* always include leading 0 */ buffer[i++] = (char) (48+(num_time[2]%10)); buffer[i++] = MONTH_DELIMITER; mon = num_time[1] - 1; /* Month of year */ buffer[i++] = month[mon][0]; buffer[i++] = month[mon][1]; buffer[i++] = month[mon][2]; buffer[i++] = MONTH_DELIMITER; #ifndef DATE_FORMAT_850 buffer[i++] = (char) (48+(num_time[0]/1000)); /* high order digit */ num_time[0] = num_time[0]%1000; /* Get rid of millenia */ buffer[i++] = (char) (48+(num_time[0]/100)); /* century digit */ #endif num_time[0] = num_time[0]%100; /* Get rid of centuries */ buffer[i++] = (char) (48+(num_time[0]/10)); /* Show last 2 digits of year*/ buffer[i++] = (char) (48+(num_time[0]%10)); buffer[i++] = ' '; /* * add time. */ buffer[i++] = (char) (48+(num_time[3]/10)); /* hours */ buffer[i++] = (char) (48+(num_time[3]%10)); buffer[i++] = ':'; buffer[i++] = (char) (48+(num_time[4]/10)); /* minutes */ buffer[i++] = (char) (48+(num_time[4]%10)); buffer[i++] = ':'; buffer[i++] = (char) (48+(num_time[5]/10)); /* seconds */ buffer[i++] = (char) (48+(num_time[5]%10)); buffer[i++] = ' '; /* * add timezone. */ buffer[i++] = 'G'; buffer[i++] = 'M'; buffer[i++] = 'T'; buffer[i++] = '\0'; return buffer; } /****************************************************************************/ /* Convert text time into binary time. Input format may be 1 of following: * sun,06nov199408:49:37GMT ; RFC 822 (1123) * sunday,6-nov-9408:49:37GMT ; RFC 850 (1036) * sunnov608:49:371994 ; asctime() function. * * Return value is zero on format error. */ unsigned long tf_decode_time ( char *string ) { int i, comma, hyphen1, hyphen2, colon1, colon2, status; struct { long l; char *s; } dx; unsigned long vms_time[2], offset[2], seconds, remainder, conv; char asctim[32]; /* * Scan string for landmarks. */ comma = hyphen1 = hyphen2 = colon1 = colon2 = -1; for ( i = 0; string[i]; i++ ) { char c; c = string[i]; if ( c == ',' ) comma = i; else if ( c == '-' ) { if ( hyphen1 < 0 ) hyphen1 = i; else hyphen2 = i; } else if ( c == ':' ) { if ( colon1 < 0 ) colon1 = i; else colon2 = i; } } /* * Do some sanity checks on landmarks. */ #ifdef DEBUG tlog_putlog(1,"h1: !SL, h2: !SL, c1: !SL, c2: !SL, comma: !SL!/", hyphen1, hyphen2, colon1, colon2, comma ); #endif if ( (hyphen1 > hyphen2) || (colon1 > colon2) || (hyphen2 > colon1) || (comma > colon1) || (colon1+3 != colon2) || (colon2+5 >= i) ) return 0; /* * Rearrange components into VMS absolute time string: * "DD-MMM-YYYY HH:MM:SS" * 012345678901234567890 */ strcpy ( asctim, "01-JAN-1970 00:00:00.00" ); asctim[19] = string[colon2+2]; asctim[18] = string[colon2+1]; asctim[16] = string[colon2-1]; asctim[15] = string[colon2-2]; asctim[13] = string[colon1-1]; asctim[12] = string[colon1-2]; /* Finished HH::MM::SS */ if ( comma >= 0 ) { asctim[10] = string[colon1-3]; asctim[9] = string[colon1-4]; if ( hyphen2 != colon1-5 ) { /* * No hyphens in time string, synthesize them. */ asctim[8] = string[colon1-5]; asctim[7] = string[colon1-6]; /* 4 digit year */ hyphen2 = colon1 - 6; hyphen1 = colon1 - 9; } asctim[5] = string[hyphen2-1]; asctim[4] = string[hyphen2-2]; asctim[3] = string[hyphen2-3]; asctim[1] = string[hyphen1-1]; asctim[0] = string[hyphen1-2]; } else { /* ctime() */ asctim[1] = string[colon1-3]; if ( (string[colon1-4] >= '0') && (string[colon1-4] <= '9') ) { if ( colon1 < 7 ) return 0; asctim[0] = string[colon1-4]; asctim[3] = string[colon1-7]; asctim[4] = string[colon1-6]; asctim[5] = string[colon1-5]; } else { if ( colon1 < 6 ) return 0; asctim[3] = string[colon1-6]; asctim[4] = string[colon1-5]; asctim[5] = string[colon1-4]; } asctim[10] = string[colon2+6]; asctim[9] = string[colon2+5]; asctim[8] = string[colon2+4]; asctim[7] = string[colon2+3]; } /* * Convert string to binary time. Month must be in upper case. */ dx.l = 23; dx.s = asctim; for ( i = 0; asctim[i]; i++ ) asctim[i] = _toupper(asctim[i]); status = sys$bintim ( &dx, vms_time ); if ( (status&1) == 0 ) return 0; /* Invalid time */ /* * Convert to delta seconds since unix base time. */ if ( !base_initialized ) init_base_time(); lib$subx ( vms_time, base_time, offset ); conv = 10000000; /* 100 nanosecond ticks to seconds */ lib$ediv ( &conv, &offset, &seconds, &remainder ); return seconds; }