/* * PROGRAM: JRD Journal Server * MODULE: misc.c * DESCRIPTION: * * The contents of this file are subject to the Interbase Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy * of the License at http://www.Inprise.com/IPL.html * * Software distributed under the License is distributed on an * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express * or implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code was created by Inprise Corporation * and its predecessors. Portions created by Inprise Corporation are * Copyright (C) Inprise Corporation. * * All Rights Reserved. * Contributor(s): ______________________________________. * * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "M88K" port * */ #include "firebird.h" #include "../jrd/ib_stdio.h" #include #include "../jrd/time.h" #include "../jrd/common.h" #ifdef WIN_NT #include #include #define TEXT SCHAR #endif #include "../jrd/ods.h" #include "../jrd/gds.h" #include "../jrd/license.h" #include "../journal/journal.h" #ifndef INCLUDE_FB_BLK #include "../include/old_fb_blk.h" #endif #include "../jrd/jrn.h" #include "../journal/gjrn_proto.h" #include "../journal/misc_proto.h" #include "../jrd/gds_proto.h" #define LETTER(c) (c >= 'A' && c <= 'Z') #define DIGIT(c) (c >= '0' && c <= '9') #define DECIMAL_LIMIT (1 << 30) / 5 #define TODAY "TODAY" #define NOW "NOW" #define TOMORROW "TOMORROW" #define YESTERDAY "YESTERDAY" static void now_to_date(struct tm *, SLONG[2]); static TEXT *months[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER", 0 }; UCHAR *MISC_alloc_jrnl(size) SLONG size; { /************************************** * * M I S C _ a l l o c _ j r n l * ************************************** * * Functional description * Allocate block of memory. * Zero it out. * **************************************/ UCHAR *p, *block; if (!(block = (UCHAR *) gds__alloc((SLONG) size))) { GJRN_printf(109, NULL, NULL, NULL, NULL); /* msg 109: malloc failed??? */ return NULL; } p = block; do *p++ = 0; while (--size); return block; } void MISC_down_case( UCHAR * in, UCHAR * out) { /************************************** * * M I S C _ d o w n _ c a s e * ************************************** * * Functional description * Copy a string, down casing as we go. * **************************************/ UCHAR c; while (c = *in++) *out++ = (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; *out = 0; } void MISC_free_jrnl( int *block) { /************************************** * * M I S C _ f r e e _ j r n l * ************************************** * * Functional description * Release an unwanted block. * **************************************/ gds__free(block); } int MISC_get_line( TEXT * prompt, TEXT * buffer, SSHORT size) { /************************************** * * M I S C _ g e t _ l i n e * ************************************** * * Functional description * Eat a command line throwing away extra bytes. Return FALSE * if end of file. * **************************************/ TEXT *end; SSHORT c; SSHORT count; GJRN_output("%s", prompt); end = buffer + size - 1; count = 0; if (sw_service_gjrn) GJRN_output("\001"); fflush(stdout); while ((c = getchar()) != '\n') { count++; if (c == EOF) { *buffer = 0; GJRN_output("%s", "\n"); return FALSE; } if (buffer < end) *buffer++ = c; } *buffer = 0; if (!count) return FALSE; return TRUE; } void MISC_get_new_value( SCHAR * string1, SCHAR * buffer, int size) { /************************************** * * M I S C _ g e t _ n e w _ v a l u e * ************************************** * * Functional description * **************************************/ SCHAR temp[25]; SCHAR buff[MSG_LENGTH]; GJRN_output("%s is: %s\n", string1, buffer); GJRN_get_msg(84, buff, NULL, NULL, NULL); MISC_get_line(buff, temp, sizeof(temp)); MISC_down_case(temp, temp); if (temp[0] != 'y') return; GJRN_get_msg(85, buff, NULL, NULL, NULL); MISC_get_line(buff, buffer, size); } void MISC_get_time( struct timeval *current) { /************************************** * * M I S C _ g e t _ t i m e * ************************************** * * Functional description * Get the current time of day. * **************************************/ #ifdef HAVE_GETTIMEOFDAY #ifdef GETTIMEOFDAY_RETURNS_TIMEZONE (void)gettimeofday(current, (struct timezone *)0); #else (void)gettimeofday(current); #endif #else struct timeb buffer; ftime(&buffer); current->tv_sec = buffer.time; current->tv_usec = (SLONG) buffer.millitm * 1000L; #endif } void MISC_get_wal_info( LTJC * msg, SCHAR * db_name, SCHAR * dir_name) { /************************************** * * M I S C _ g e t _ w a l _ i n f o * ************************************** * * Functional description * get wal info from message * **************************************/ SCHAR *p, *q, *b; SSHORT l; db_name[0] = 0; dir_name[0] = 0; for (p = msg->ltjc_data; p[0] != JRNW_END; p += 2 + p[1]) { switch (*p) { case gds__dpb_wal_backup_dir: b = dir_name; q = &p[2]; l = p[1]; if (l) do *b++ = *q++; while (--l); *b++ = 0; break; case JRNW_DB_NAME: b = db_name; q = &p[2]; l = p[1]; if (l) do *b++ = *q++; while (--l); *b++ = 0; break; default:; } } } void MISC_print_journal_syntax(void) { /************************************** * * M I S C _ p r i n t _ j o u r n a l _ s y n t a x * ************************************** * * Functional description * print possible options * **************************************/ GJRN_print_syntax(); GJRN_printf(7, NULL, NULL, NULL, NULL); /* msg 7: : -enable | -disable | -online_dump | -server | -console | -restore */ /* server options */ GJRN_printf(75, NULL, NULL, NULL, NULL); /* msg 75: */ GJRN_printf(8, NULL, NULL, NULL, NULL); /* msg 8: -j */ /* console options */ GJRN_printf(76, NULL, NULL, NULL, NULL); /* msg 76: */ GJRN_printf(8, NULL, NULL, NULL, NULL); /* msg 8: -j */ GJRN_printf(77, NULL, NULL, NULL, NULL); /* msg 77: -s */ /* enable options */ GJRN_printf(78, NULL, NULL, NULL, NULL); /* msg 78: */ GJRN_printf(8, NULL, NULL, NULL, NULL); /* msg 8: -j */ GJRN_printf(9, NULL, NULL, NULL, NULL); /* msg 9: -a */ /* disable options */ GJRN_printf(79, NULL, NULL, NULL, NULL); /* msg 79: */ /* restore options */ GJRN_printf(80, NULL, NULL, NULL, NULL); /* msg 80: */ GJRN_printf(8, NULL, NULL, NULL, NULL); /* msg 8: -j */ GJRN_printf(11, NULL, NULL, NULL, NULL); /* msg 11: -u */ GJRN_printf(10, NULL, NULL, NULL, NULL); /* msg 10: -i -interactive mode */ GJRN_printf(142, NULL, NULL, NULL, NULL); /* msg 142: -m */ GJRN_printf(196, NULL, NULL, NULL, NULL); /* msg 196: -a\t\t-activate partially recovered database */ GJRN_printf(197, NULL, NULL, NULL, NULL); /* msg 197: \t\t-p */ /* online dump options */ GJRN_printf(81, NULL, NULL, NULL, NULL); /* msg 81: */ GJRN_printf(10, NULL, NULL, NULL, NULL); /* msg 10: -i -interactive mode */ GJRN_printf(82, NULL, NULL, NULL, NULL); /* msg 82: -f */ GJRN_printf(83, NULL, NULL, NULL, NULL); /* msg 83: -s */ GJRN_abort(0); } int MISC_time_convert( TEXT * string, USHORT length, SLONG date[2]) { /************************************** * * M I S C _ t i m e _ c o n v e r t * ************************************** * * Functional description * Convert an arbitrary string to a date. Return SUCCESS if successful, * otherwise FAILURE. * **************************************/ TEXT c, *p, temp[15], *t, *end, **month_ptr, *m; USHORT n, month_position, i, components[7]; SLONG xclock; struct tm times, times2; p = string; end = p + length; month_position = 0; xclock = time(0); times2 = *localtime(&xclock); for (i = 0; i < 7; i++) components[i] = 0; /* Parse components */ for (i = 0; i < 7; i++) { /* Skip leading blanks. If we run out of characters, we're done with parse. */ while (p < end && (*p == ' ' || *p == '\t')) p++; if (p == end) break; /* Handle digit or character strings */ c = UPPER(*p); if (DIGIT(c)) { n = 0; while (p < end && DIGIT(*p)) n = n * 10 + *p++ - '0'; } else if (LETTER(c)) { t = temp; while (p < end && LETTER(c)) { c = UPPER(*p); if (!LETTER(c)) break; *t++ = c; p++; } *t = 0; month_ptr = months; while (TRUE) { if (!*month_ptr) { /* it's not a month name, so it's either a magic word or a non-date string. If there are more characters, it's bad */ while (++p < end) if (*p != ' ' && *p != '\t' && *p != 0) return FAILURE; if (strcmp(temp, NOW) == 0) { now_to_date(×2, date); return SUCCESS; } times2.tm_hour = times2.tm_min = times2.tm_sec = 0; gds__encode_date(×2, date); if (strcmp(temp, TODAY) == 0) return SUCCESS; if (strcmp(temp, TOMORROW) == 0) { ++date[0]; return SUCCESS; } if (strcmp(temp, YESTERDAY) == 0) { --date[0]; return SUCCESS; } return FAILURE; } for (t = temp, m = *month_ptr++; *t && *t == *m; t++, m++); if (!*t) break; } n = month_ptr - months; month_position = i; } else return FAILURE; components[i] = n; while (p < end && (*p == ' ' || *p == '\t')) p++; if (*p == '/' || *p == '-' || *p == ',' || *p == ':') { p++; continue; } if (*p == '.') { if (!month_position && i < 2) month_position = 1; p++; continue; } } /* Slide things into day, month, year form */ if (!components[0] && !components[1] && !components[2]) { date[0] = date[1] = 0; return SUCCESS; } if (month_position) { times.tm_mon = components[1]; times.tm_mday = components[0]; } else { times.tm_mon = components[0]; times.tm_mday = components[1]; } /* Handle defaulting of year */ if ((times.tm_year = components[2]) == 0) times.tm_year = times2.tm_year + 1900; else if (times.tm_year < 100) { if (times.tm_year < (times2.tm_year - 50) % 100) times.tm_year += 2000; else times.tm_year += 1900; } times.tm_year -= 1900; times.tm_mon -= 1; times.tm_hour = components[3]; times.tm_min = components[4]; times.tm_sec = components[5]; /* convert day/month/year to Julian and validate result */ gds__encode_date(×, date); gds__decode_date(date, ×2); if (times.tm_year != times2.tm_year || times.tm_mon != times2.tm_mon || times.tm_mday != times2.tm_mday) return FAILURE; return SUCCESS; } static void now_to_date( struct tm *xtime, SLONG date[2]) { /************************************** * * n o w _ t o _ d a t e * ************************************** * * Functional description * Convert "now" (or best guess) to * a date attempting to get millisecond * precision. This unfortunately means * that we use one routine for VAX, and * another for Unix. * **************************************/ gds__encode_date(xtime, date); }