/* * extract.c - Part of AFD, an automatic file distribution program. * Copyright (c) 1997 - 2022 Deutscher Wetterdienst (DWD), * Holger Kiehl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "afddefs.h" DESCR__S_M3 /* ** NAME ** extract - breaks up a file containing bulletins to one file per ** bulletin ** ** SYNOPSIS ** int extract(char *file_name, ** char *dest_dir, ** char *p_filter, ** time_t creation_time, ** unsigned int unique_number, ** unsigned int split_job_counter, ** unsigned int job_id, ** unsigned int dir_id, ** char *full_option, ** int type, ** int options, ** int *files_to_send, ** off_t *file_size) ** ** DESCRIPTION ** The function extract reads a WMO bulletin file, and writes each ** bulletin into a separate file. The bulletin must have the following ** format: ** ** nnn ** WMO headerWMO message ** ** Four length indicators with the following length are currently ** recognised by extract(): ** ** 2 Byte - Vax standard ** 4 Byte - Low byte first ** 4 Byte - High byte first ** 4 Byte - MSS standard ** 8 Byte - WMO standard (plus 2 Bytes type indicator) ** ** It is also possible without a length indicator, it must then ** have the following format: ** ** nnn ** WMO headerWMO message ** ** Or a ZCZC at the beginning and an NNNN at the end as shown in ** the following format: ** ** ZCZCNNNN ** ** The file name of the new file will be the WMO header: ** ** TTAAii_CCCC_YYGGgg[_BBB] ** ** RETURN VALUES ** Returns INCORRECT when it fails to read any valid data from the ** file. On success SUCCESS will be returned and the number of files ** that have been created and the sum of their size. ** ** AUTHOR ** H.Kiehl ** ** HISTORY ** 15.09.1997 H.Kiehl Created ** 05.04.1999 H.Kiehl Added WMO standard. ** 03.10.2004 H.Kiehl Added production log. ** 16.08.2005 H.Kiehl Added ASCII option. ** 13.07.2007 H.Kiehl Added option to filter out only those bulletins ** we really nead. ** 08.04.2008 H.Kiehl Added ZCZC_NNNN option. ** 07.12.2008 H.Kiehl Added option to extract reports. ** 15.02.2011 H.Kiehl Added option to add additional header in report ** indicating the report type. ** 15.02.2013 H.Kiehl Added function wmo_standard_chk() that works ** as wmo_standard() only that it checks if the ** terminating ETX is available and if not tries ** to search for it's end. ** 06.12.2017 H.Kiehl Add function separator_char(). ** */ DESCR__E_M3 #include /* sprintf() */ #include /* strtoul(), malloc(), free() */ #include /* strerror() */ #include /* close() */ #include /* isdigit(), isupper() */ #include #include #ifdef HAVE_MMAP # include /* mmap(), munmap() */ #endif #include #include /* struct tm */ #include /* open() */ #include #include "amgdefs.h" #include "version.h" #ifndef MAP_FILE /* Required for BSD */ #define MAP_FILE 0 /* All others do not need it */ #endif #ifdef _PRODUCTION_LOG #define LOG_ENTRY_STEP_SIZE 25 struct prod_log_db { char file_name[MAX_FILENAME_LENGTH + 1]; off_t size; double production_time; struct timeval cpu_usage; }; #endif /* External global variables. */ extern int no_of_bc_entries, no_of_rc_entries, receive_log_fd; #ifdef HAVE_HW_CRC32 extern int have_hw_crc32; #endif #ifdef _PRODUCTION_LOG extern clock_t clktck; #endif extern struct wmo_bul_list *bcdb; /* Bulletin Configuration Database */ extern struct wmo_rep_list *rcdb; /* Bulletin Configuration Database */ extern struct fileretrieve_status *p_fra; /* Local global variables. */ static int *counter, counter_fd, extract_options, *p_files_to_send; static mode_t file_mode; static off_t *p_file_size; static char *extract_p_filter, *p_full_file_name, *p_file_name, *p_orig_name; #ifdef _PRODUCTION_LOG static struct rusage ru; static clock_t start_time; static struct tms tval; static int no_of_log_entries = 0; static struct prod_log_db *pld = NULL; #endif /* Local function prototypes. */ static void ascii_sohetx(char *, off_t, time_t, char *), ascii_zczc_nnnn(char *, off_t, time_t, char *), binary_sohetx(char *, off_t, time_t, char *), four_byte(char *, off_t, time_t), four_byte_swap(char *, off_t, time_t), four_byte_mss(char *, off_t, time_t), four_byte_mss_swap(char *, off_t, time_t), hex_print(char *, char *, int), separator_char(char *, off_t, time_t, char *, char), show_unknown_report(char *, int, char *, char *, int), two_byte_vax(char *, off_t, time_t), two_byte_vax_swap(char *, off_t, time_t), wmo_standard(char *, off_t, time_t), wmo_standard_chk(char *, off_t, time_t); static int check_report(char *, unsigned int, int *), find_offset(int, char *, int, int *, char *), get_rcdb_position(char *, int), get_station_id(char *, int, int *, char *, int, int, int, char **, int *, int *, char *), write_file(char *, unsigned int, time_t, int); /* Local definitions. */ #define MAX_WMO_HEADER_LENGTH 25 #define MAX_REPORT_LINE_LENGTH 80 #define NIL_MESSAGE -2 #define TEXT_MESSAGE -3 /*############################### extract() #############################*/ int extract(char *file_name, char *dest_dir, char *p_filter, #ifdef _PRODUCTION_LOG time_t creation_time, unsigned int unique_number, unsigned int split_job_counter, unsigned int job_id, unsigned int dir_id, char *full_option, #endif int type, int options, int *files_to_send, off_t *file_size) { int byte_order = 1, from_fd; char *src_ptr, fullname[MAX_PATH_LENGTH]; #ifdef HAVE_STATX struct statx stat_buf; #else struct stat stat_buf; #endif #ifdef _PRODUCTION_LOG (void)getrusage(RUSAGE_SELF, &ru); start_time = times(&tval); #endif (void)snprintf(fullname, MAX_PATH_LENGTH, "%s/%s", dest_dir, file_name); if ((from_fd = open(fullname, O_RDONLY)) == -1) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, #ifdef _PRODUCTION_LOG _("Could not open() `%s' for extracting : %s #%x"), fullname, strerror(errno), job_id); #else _("Could not open() `%s' for extracting : %s"), fullname, strerror(errno)); #endif return(INCORRECT); } /* Need size and mode of input file. */ #ifdef HAVE_STATX if (statx(from_fd, "", AT_STATX_SYNC_AS_STAT | AT_EMPTY_PATH, STATX_SIZE | STATX_MTIME | STATX_MODE, &stat_buf) == -1) #else if (fstat(from_fd, &stat_buf) == -1) #endif { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, #ifdef HAVE_STATX _("statx() error : %s"), #else _("fstat() error : %s"), #endif strerror(errno)); (void)close(from_fd); return(INCORRECT); } /* * If the size of the file is less then 10 forget it. There can't * be a WMO bulletin in it. */ #ifdef HAVE_STATX if (stat_buf.stx_size < 10) #else if (stat_buf.st_size < 10) #endif { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, #ifdef _PRODUCTION_LOG _("Got a file for extracting that is %ld bytes long! #%x"), # ifdef HAVE_STATX stat_buf.stx_size, # else stat_buf.st_size, # endif job_id); #else _("Got a file for extracting that is %ld bytes long!"), # ifdef HAVE_STATX stat_buf.stx_size); # else stat_buf.st_size); # endif #endif (void)close(from_fd); return(INCORRECT); } /* * When creating new files take the permissions from the original * files. This gives the originator the possibility to set the * permissions on the destination site. */ #ifdef HAVE_STATX file_mode = stat_buf.stx_mode; #else file_mode = stat_buf.st_mode; #endif #ifdef HAVE_MMAP if ((src_ptr = mmap(NULL, # ifdef HAVE_STATX stat_buf.stx_size, PROT_READ, (MAP_FILE | MAP_SHARED), # else stat_buf.st_size, PROT_READ, (MAP_FILE | MAP_SHARED), # endif from_fd, 0)) == (caddr_t) -1) #else if ((src_ptr = mmap_emu(NULL, # ifdef HAVE_STATX stat_buf.stx_size, PROT_READ, (MAP_FILE | MAP_SHARED), # else stat_buf.st_size, PROT_READ, (MAP_FILE | MAP_SHARED), # endif fullname, 0)) == (caddr_t) -1) #endif { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("mmap() error : %s"), strerror(errno)); (void)close(from_fd); return(INCORRECT); } /* Remove the file now, since it can happen that when we create */ /* a new file with exactly the same name, ie. overwrite the original */ /* file, we may not do it because we just have permission to read it. */ if (unlink(fullname) < 0) { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, _("Failed to unlink() `%s' : %s"), fullname, strerror(errno)); } else { #ifdef HAVE_STATX *file_size -= stat_buf.stx_size; #else *file_size -= stat_buf.st_size; #endif (*files_to_send)--; } if (options & EXTRACT_ADD_UNIQUE_NUMBER) { /* Open counter file. */ if ((counter_fd = open_counter_file(COUNTER_FILE, &counter)) == -1) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to open counter file!")); (void)close(from_fd); return(INCORRECT); } } extract_options = options; extract_p_filter = p_filter; /* * Prepare file_name pointer for function write_file(), so we * only one simple copy to have the full file name for the * new file. Same goes for the file_size and files_to_send. * Just to lazy to handle these values right down to write_file(). */ p_full_file_name = dest_dir; p_file_name = dest_dir + strlen(dest_dir); *(p_file_name++) = '/'; *p_file_name = '\0'; p_file_size = file_size; p_files_to_send = files_to_send; p_orig_name = file_name; switch (type) { case ASCII_STANDARD: /* No length indicator, just locate SOH + ETX. */ #ifdef HAVE_STATX ascii_sohetx(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec, file_name); #else ascii_sohetx(src_ptr, stat_buf.st_size, stat_buf.st_mtime, file_name); #endif break; case BINARY_STANDARD: /* No length indicator, just cut away header. */ #ifdef HAVE_STATX binary_sohetx(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec, file_name); #else binary_sohetx(src_ptr, stat_buf.st_size, stat_buf.st_mtime, file_name); #endif break; case ZCZC_NNNN: /* No length indicator, just locate ZCZC + NNNN. */ #ifdef HAVE_STATX ascii_zczc_nnnn(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec, file_name); #else ascii_zczc_nnnn(src_ptr, stat_buf.st_size, stat_buf.st_mtime, file_name); #endif break; case TWO_BYTE : /* Vax Standard */ if (*(char *)&byte_order == 1) { /* little-endian */ #ifdef HAVE_STATX two_byte_vax(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec); #else two_byte_vax(src_ptr, stat_buf.st_size, stat_buf.st_mtime); #endif } else { /* big-endian */ #ifdef HAVE_STATX two_byte_vax_swap(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec); #else two_byte_vax_swap(src_ptr, stat_buf.st_size, stat_buf.st_mtime); #endif } break; case FOUR_BYTE_LBF : /* Low byte first */ if (*(char *)&byte_order == 1) { /* little-endian */ #ifdef HAVE_STATX four_byte(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec); #else four_byte(src_ptr, stat_buf.st_size, stat_buf.st_mtime); #endif } else { /* big-endian */ #ifdef HAVE_STATX four_byte_swap(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec); #else four_byte_swap(src_ptr, stat_buf.st_size, stat_buf.st_mtime); #endif } break; case FOUR_BYTE_HBF : /* High byte first */ if (*(char *)&byte_order == 1) { /* little-endian */ #ifdef HAVE_STATX four_byte_swap(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec); #else four_byte_swap(src_ptr, stat_buf.st_size, stat_buf.st_mtime); #endif } else { /* big-endian */ #ifdef HAVE_STATX four_byte(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec); #else four_byte(src_ptr, stat_buf.st_size, stat_buf.st_mtime); #endif } break; case FOUR_BYTE_MSS : /* MSS Standard */ if (*(char *)&byte_order == 1) { /* little-endian */ #ifdef HAVE_STATX four_byte_mss_swap(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec); #else four_byte_mss_swap(src_ptr, stat_buf.st_size, stat_buf.st_mtime); #endif } else { /* big-endian */ #ifdef HAVE_STATX four_byte_mss(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec); #else four_byte_mss(src_ptr, stat_buf.st_size, stat_buf.st_mtime); #endif } break; case WMO_STANDARD : /* WMO Standard */ #ifdef HAVE_STATX wmo_standard(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec); #else wmo_standard(src_ptr, stat_buf.st_size, stat_buf.st_mtime); #endif break; case WMO_STANDARD_CHK : /* WMO Standard with end search. */ #ifdef HAVE_STATX wmo_standard_chk(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec); #else wmo_standard_chk(src_ptr, stat_buf.st_size, stat_buf.st_mtime); #endif break; case SP_CHAR : /* No length indicator, just locate separator */ /* character at end. */ #ifdef HAVE_STATX separator_char(src_ptr, stat_buf.stx_size, stat_buf.stx_mtime.tv_sec, file_name, '='); #else separator_char(src_ptr, stat_buf.st_size, stat_buf.st_mtime, file_name, '='); #endif break; default : /* Impossible! */ receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, #ifdef _PRODUCTION_LOG _("Unknown length type (%d) for extracting bulletins. #%x"), type, job_id); #else _("Unknown length type (%d) for extracting bulletins."), type); #endif #ifdef HAVE_MMAP # ifdef HAVE_STATX (void)munmap((void *)src_ptr, stat_buf.stx_size); # else (void)munmap((void *)src_ptr, stat_buf.st_size); # endif #else (void)munmap_emu((void *)src_ptr); #endif (void)close(from_fd); if (options & EXTRACT_ADD_UNIQUE_NUMBER) { close_counter_file(counter_fd, &counter); } *(p_file_name - 1) = '\0'; return(INCORRECT); } #ifdef HAVE_MMAP # ifdef HAVE_STATX if (munmap((void *)src_ptr, stat_buf.stx_size) == -1) # else if (munmap((void *)src_ptr, stat_buf.st_size) == -1) # endif #else if (munmap_emu((void *)src_ptr) == -1) #endif { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, _("Failed to munmap() `%s' : %s"), fullname, strerror(errno)); } if (options & EXTRACT_ADD_UNIQUE_NUMBER) { close_counter_file(counter_fd, &counter); } if (close(from_fd) == -1) { receive_log(DEBUG_SIGN, __FILE__, __LINE__, 0L, _("close() error : %s"), strerror(errno)); } *(p_file_name - 1) = '\0'; #ifdef _PRODUCTION_LOG if ((pld != NULL) && (no_of_log_entries)) { for (byte_order = 0; byte_order < no_of_log_entries; byte_order++) { production_log(creation_time, 1, no_of_log_entries, unique_number, split_job_counter, job_id, dir_id, pld[byte_order].production_time, pld[byte_order].cpu_usage.tv_sec, pld[byte_order].cpu_usage.tv_usec, # if SIZEOF_OFF_T == 4 "%s%c%lx%c%s%c%lx%c0%c%s", # else "%s%c%llx%c%s%c%llx%c0%c%s", # endif p_orig_name, SEPARATOR_CHAR, # ifdef HAVE_STATX (pri_off_t)stat_buf.stx_size, SEPARATOR_CHAR, # else (pri_off_t)stat_buf.st_size, SEPARATOR_CHAR, # endif pld[byte_order].file_name, SEPARATOR_CHAR, (pri_off_t)pld[byte_order].size, SEPARATOR_CHAR, SEPARATOR_CHAR, full_option); } free(pld); no_of_log_entries = 0; pld = NULL; } #endif return(SUCCESS); } /*+++++++++++++++++++++++++++++ ascii_sohetx() ++++++++++++++++++++++++++*/ static void ascii_sohetx(char *src_ptr, off_t total_length, time_t mtime, char *file_name) { if (*src_ptr == 1) { char *ptr = src_ptr, *ptr_start; do { while ((*ptr != 1) && ((ptr - src_ptr) <= total_length)) { ptr++; } if (*ptr == 1) { ptr_start = ptr; while ((*ptr != 3) && ((ptr - src_ptr) <= total_length)) { ptr++; } if (*ptr == 3) { ptr++; if (write_file(ptr_start, (unsigned int)(ptr - ptr_start), mtime, YES) < 0) { return; } if ((ptr - src_ptr) >= total_length) { return; } } else { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to locate terminating ETX in %s."), file_name); return; } } } while ((ptr - src_ptr) <= total_length); } else { (void)write_file(src_ptr, (unsigned int)(total_length), mtime, NO); } return; } /*++++++++++++++++++++++++++++ binary_sohetx() ++++++++++++++++++++++++++*/ static void binary_sohetx(char *src_ptr, off_t total_length, time_t mtime, char *file_name) { char *ptr = src_ptr, *ptr_start; while ((*ptr != 1) && ((ptr - src_ptr) <= total_length)) { ptr++; } if (*ptr == 1) { ptr_start = ptr; ptr += (total_length - 1); if (*ptr == 3) { ptr++; if (write_file(ptr_start, (unsigned int)(ptr - ptr_start), mtime, YES) < 0) { return; } if ((ptr - src_ptr) >= total_length) { return; } } else { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to locate terminating ETX in %s."), file_name); return; } } return; } /*+++++++++++++++++++++++++++ ascii_zczc_nnnn() +++++++++++++++++++++++++*/ static void ascii_zczc_nnnn(char *src_ptr, off_t total_length, time_t mtime, char *file_name) { char *ptr = src_ptr, *ptr_start; do { ptr_start = ptr; while (((*ptr == 13) || (*ptr == 10)) && ((ptr - src_ptr) <= total_length)) { ptr++; } if (((ptr - src_ptr + 4) <= total_length) && (*ptr == 'Z') && (*(ptr + 1) == 'C') && (*(ptr + 2) == 'Z') && (*(ptr + 3) == 'C')) { ptr += 4; while (((ptr - src_ptr + 5) <= total_length) && (!(((*ptr == 13) || (*ptr == 10)) && (*(ptr + 1) == 'N') && (*(ptr + 2) == 'N') && (*(ptr + 3) == 'N') && (*(ptr + 4) == 'N')))) { ptr++; } if (((*ptr == 13) || (*ptr == 10)) && (*(ptr + 1) == 'N') && (*(ptr + 2) == 'N') && (*(ptr + 3) == 'N') && (*(ptr + 4) == 'N')) { ptr += 5; if (write_file(ptr_start, (unsigned int)(ptr - ptr_start), mtime, NEITHER) < 0) { return; } if ((ptr - src_ptr) >= total_length) { return; } } else { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to locate terminating NNNN in %s."), file_name); return; } } } while ((ptr - src_ptr) <= total_length); return; } /*+++++++++++++++++++++++++++++ two_byte_vax() ++++++++++++++++++++++++++*/ static void two_byte_vax(char *src_ptr, off_t total_length, time_t mtime) { unsigned short length; char *ptr = src_ptr; ((char *)&length)[0] = *ptr; ((char *)&length)[1] = *(ptr + 1); if (((ptr + length) - src_ptr) <= total_length) { for (;;) { if (write_file(ptr + 2, (unsigned int)length, mtime, YES) < 0) { return; } ptr += length + 3; if ((ptr - src_ptr) >= total_length) { return; } ((char *)&length)[0] = *ptr; ((char *)&length)[1] = *(ptr + 1); } } return; } /*++++++++++++++++++++++++++ two_byte_vax_swap() ++++++++++++++++++++++++*/ static void two_byte_vax_swap(char *src_ptr, off_t total_length, time_t mtime) { unsigned short length; char *ptr = src_ptr; ((char *)&length)[0] = *(ptr + 1); ((char *)&length)[1] = *ptr; if (((ptr + length) - src_ptr) <= total_length) { for (;;) { if (write_file(ptr + 2, (unsigned int)length, mtime, YES) < 0) { return; } ptr += length + 3; if ((ptr - src_ptr) >= total_length) { return; } ((char *)&length)[0] = *(ptr + 1); ((char *)&length)[1] = *ptr; } } return; } /*++++++++++++++++++++++++++++++ four_byte() ++++++++++++++++++++++++++++*/ static void four_byte(char *src_ptr, off_t total_length, time_t mtime) { unsigned int length; char *ptr = src_ptr; ((char *)&length)[0] = *ptr; ((char *)&length)[1] = *(ptr + 1); ((char *)&length)[2] = *(ptr + 2); ((char *)&length)[3] = *(ptr + 3); if (((ptr + length) - src_ptr) <= total_length) { for (;;) { if (write_file(ptr + 4, length, mtime, YES) < 0) { return; } ptr += length + 4; if ((ptr - src_ptr) >= total_length) { return; } ((char *)&length)[0] = *ptr; ((char *)&length)[1] = *(ptr + 1); ((char *)&length)[2] = *(ptr + 2); ((char *)&length)[3] = *(ptr + 3); } } return; } /*+++++++++++++++++++++++++++ four_byte_swap() ++++++++++++++++++++++++++*/ static void four_byte_swap(char *src_ptr, off_t total_length, time_t mtime) { unsigned int length; char *ptr = src_ptr; ((char *)&length)[0] = *(ptr + 3); ((char *)&length)[1] = *(ptr + 2); ((char *)&length)[2] = *(ptr + 1); ((char *)&length)[3] = *ptr; if (((ptr + length) - src_ptr) <= total_length) { for (;;) { if (write_file(ptr + 4, length, mtime, YES) < 0) { return; } ptr += length + 4; if ((ptr - src_ptr) >= total_length) { return; } ((char *)&length)[0] = *(ptr + 3); ((char *)&length)[1] = *(ptr + 2); ((char *)&length)[2] = *(ptr + 1); ((char *)&length)[3] = *ptr; } } return; } /*++++++++++++++++++++++++++++ four_byte_mss() ++++++++++++++++++++++++++*/ static void four_byte_mss(char *src_ptr, off_t total_length, time_t mtime) { unsigned int length; char *ptr = src_ptr; ((char *)&length)[0] = 0; ((char *)&length)[1] = *(ptr + 1); ((char *)&length)[2] = *(ptr + 2); ((char *)&length)[3] = *(ptr + 3); if (((ptr + length) - src_ptr) <= total_length) { for (;;) { if (write_file(ptr + 4, length, mtime, YES) < 0) { return; } ptr += length + 4; if ((ptr - src_ptr) >= total_length) { return; } ((char *)&length)[0] = 0; ((char *)&length)[1] = *(ptr + 1); ((char *)&length)[2] = *(ptr + 2); ((char *)&length)[3] = *(ptr + 3); } } return; } /*+++++++++++++++++++++++++ four_byte_mss_swap() ++++++++++++++++++++++++*/ static void four_byte_mss_swap(char *src_ptr, off_t total_length, time_t mtime) { unsigned int length; char *ptr = src_ptr; ((char *)&length)[0] = *(ptr + 3); ((char *)&length)[1] = *(ptr + 2); ((char *)&length)[2] = *(ptr + 1); ((char *)&length)[3] = 0; if (((ptr + length) - src_ptr) <= total_length) { for (;;) { if (write_file(ptr + 4, length, mtime, YES) < 0) { return; } ptr += length + 4; if ((ptr - src_ptr) >= total_length) { return; } ((char *)&length)[0] = *(ptr + 3); ((char *)&length)[1] = *(ptr + 2); ((char *)&length)[2] = *(ptr + 1); ((char *)&length)[3] = 0; } } return; } /*+++++++++++++++++++++++++++ wmo_standard() ++++++++++++++++++++++++++++*/ static void wmo_standard(char *src_ptr, off_t total_length, time_t mtime) { int soh_etx; unsigned int length; char *ptr = src_ptr, str_length[9]; str_length[8] = '\0'; do { str_length[0] = *ptr; str_length[1] = *(ptr + 1); str_length[2] = *(ptr + 2); str_length[3] = *(ptr + 3); str_length[4] = *(ptr + 4); str_length[5] = *(ptr + 5); str_length[6] = *(ptr + 6); str_length[7] = *(ptr + 7); length = (unsigned int)strtoul(str_length, NULL, 10); if (length > 0) { if (*(ptr + 9) == '1') { soh_etx = NO; } else { soh_etx = YES; } if (write_file(ptr + 10, length, mtime, soh_etx) < 0) { return; } } ptr += length + 10; } while ((ptr - src_ptr) < total_length); return; } /*+++++++++++++++++++++++++ wmo_standard_chk() ++++++++++++++++++++++++++*/ static void wmo_standard_chk(char *src_ptr, off_t total_length, time_t mtime) { int soh_etx; unsigned int additional_length, length; char *ptr = src_ptr, str_length[9]; str_length[8] = '\0'; do { additional_length = 0; str_length[0] = *ptr; str_length[1] = *(ptr + 1); str_length[2] = *(ptr + 2); str_length[3] = *(ptr + 3); str_length[4] = *(ptr + 4); str_length[5] = *(ptr + 5); str_length[6] = *(ptr + 6); str_length[7] = *(ptr + 7); length = (unsigned int)strtoul(str_length, NULL, 10); if (length > 0) { if (*(ptr + 9) == '1') { soh_etx = NO; } else { soh_etx = YES; if (*(ptr + length + 10 - 1) != 3) { while ((ptr - src_ptr + 10 - 1 + additional_length) < total_length) { additional_length++; if (*(ptr + length + 10 - 1 + additional_length) == 3) { break; } } if (*(ptr + length + 10 - 1 + additional_length) != 3) { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "Unable to determine terminating ETX in %s.", p_orig_name); additional_length = 0; } } } if (write_file(ptr + 10, length + additional_length, mtime, soh_etx) < 0) { return; } } ptr += length + additional_length + 10; } while ((ptr - src_ptr) < total_length); return; } /*++++++++++++++++++++++++++++ separator_char() +++++++++++++++++++++++++*/ static void separator_char(char *src_ptr, off_t total_length, time_t mtime, char *file_name, char separator) { char *ptr = src_ptr, *ptr_start; do { ptr_start = ptr; while ((*ptr != separator) && ((ptr - src_ptr) <= total_length)) { ptr++; } if (*ptr == separator) { ptr++; if (write_file(ptr_start, (unsigned int)(ptr - ptr_start), mtime, NO) < 0) { return; } if ((ptr - src_ptr) >= total_length) { return; } } else { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to locate terminating character %c in %s."), separator, file_name); return; } } while ((ptr - src_ptr) <= total_length); return; } /*------------------------------ write_file() ---------------------------*/ static int write_file(char *msg, unsigned int length, time_t mtime, int soh_etx) { int bcdb_pos = -1, fd, i; off_t size; char *ptr, *p_start; /* * Build the file name from the bulletin header. */ if ((soh_etx == YES) && (msg[0] != 1)) /* Must start with SOH */ { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, _("Failed to read bulletin header. No SOH at start in %s."), p_orig_name); return(INCORRECT); } /* * Position to start of header ie. after nnn * and then store the heading in heading_str. The end of heading is when * we hit an unprintable character, in most cases this should be the * after the heading. */ ptr = msg; while (((ptr - msg) < length) && (*ptr < 32)) { ptr++; } if ((ptr + 3 - msg) >= length) { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, _("Failed to read bulletin header. No header found in %s (%d >= %u)."), p_orig_name, (int)(ptr + 3 - msg), length); return(INCORRECT); } if (((ptr + 4 - msg) <= length) && (*ptr == 'Z') && (*(ptr + 1) == 'C') && (*(ptr + 2) == 'Z') && (*(ptr + 3) == 'C')) { ptr += 4; while (((ptr - msg) < length) && (*ptr == ' ')) { ptr++; } if ((ptr + 3 - msg) >= length) { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, _("Failed to read bulletin header. No header found in %s."), p_orig_name); return(INCORRECT); } } p_start = ptr; while (((ptr - msg) < length) && (isdigit((int)(*ptr)))) { ptr++; } if ((*ptr != 13) && (*ptr != 10)) { ptr = p_start; } while (((ptr - msg) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } p_start = ptr; i = 0; if (extract_options & EXTRACT_ADD_FULL_DATE) { int space_counter = 0; while (((ptr - msg) < length) && (*ptr > 31) && (i < (MAX_WMO_HEADER_LENGTH + 6))) { if ((*ptr == ' ') || (*ptr == '/') || (*ptr < ' ') || (*ptr > 'z')) { p_file_name[i] = '_'; space_counter++; if ((space_counter == 2) && ((ptr + 2 - msg) < length) && (isdigit(*(ptr + 1))) && (isdigit(*(ptr + 2)))) { int day_of_month, diff_mday; struct tm *bd_time; /* Broken-down time. */ if (*(ptr + 1) == '0') { day_of_month = *(ptr + 2) - '0'; } else { day_of_month = ((*(ptr + 1) - '0') * 10) + (*(ptr + 2) - '0'); } bd_time = gmtime(&mtime); diff_mday = day_of_month - bd_time->tm_mday; if (diff_mday != 0) { if (diff_mday > 26) { bd_time->tm_mday = day_of_month; bd_time->tm_mon--; mtime = mktime(bd_time); bd_time = gmtime(&mtime); } else if (diff_mday < -26) { bd_time->tm_mday = day_of_month; bd_time->tm_mon++; mtime = mktime(bd_time); bd_time = gmtime(&mtime); } } i += snprintf(&p_file_name[i + 1], MAX_PATH_LENGTH - (i + 1), "%04d%02d", (bd_time->tm_year + 1900), (bd_time->tm_mon + 1)); } } else { p_file_name[i] = *ptr; } ptr++; i++; } } else { while (((ptr - msg) < length) && (*ptr > 31) && (i < MAX_WMO_HEADER_LENGTH)) { if ((*ptr == ' ') || (*ptr == '/') || (*ptr < ' ') || (*ptr > 'z')) { p_file_name[i] = '_'; } else { p_file_name[i] = *ptr; } ptr++; i++; } } if (i == 0) { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, _("Length of WMO header is 0 in %s!? Discarding file."), p_orig_name); return(INCORRECT); } else { if (p_file_name[i - 1] == '_') { p_file_name[i - 1] = '\0'; i--; } else { p_file_name[i] = '\0'; } } if (extract_options & USE_EXTERNAL_MSG_RULES) { register int j; #ifdef FIRST_MATCH_IS_HIT for (j = 0; j < no_of_bc_entries; j++) { if (((bcdb[j].TTAAii[0] == '/') || (bcdb[j].TTAAii[0] == p_file_name[0])) && ((bcdb[j].TTAAii[1] == '/') || (bcdb[j].TTAAii[1] == p_file_name[1])) && ((bcdb[j].TTAAii[2] == '/') || (bcdb[j].TTAAii[2] == p_file_name[2])) && ((bcdb[j].TTAAii[3] == '/') || (bcdb[j].TTAAii[3] == p_file_name[3])) && (((bcdb[j].TTAAii[4] == '\0') && (p_file_name[4] == '_') && ((bcdb[j].CCCC[0] == '/') || (bcdb[j].CCCC[0] == p_file_name[5])) && ((bcdb[j].CCCC[1] == '/') || (bcdb[j].CCCC[1] == p_file_name[6])) && ((bcdb[j].CCCC[2] == '/') || (bcdb[j].CCCC[2] == p_file_name[7])) && ((bcdb[j].CCCC[3] == '/') || (bcdb[j].CCCC[3] == p_file_name[8]))) || (((bcdb[j].TTAAii[4] == '/') || (bcdb[j].TTAAii[4] == p_file_name[4])) && ((bcdb[j].TTAAii[5] == '/') || (bcdb[j].TTAAii[5] == p_file_name[5])) && (bcdb[j].TTAAii[6] == '\0') && (p_file_name[6] == '_') && ((bcdb[j].CCCC[0] == '/') || (bcdb[j].CCCC[0] == p_file_name[7])) && ((bcdb[j].CCCC[1] == '/') || (bcdb[j].CCCC[1] == p_file_name[8])) && ((bcdb[j].CCCC[2] == '/') || (bcdb[j].CCCC[2] == p_file_name[9])) && ((bcdb[j].CCCC[3] == '/') || (bcdb[j].CCCC[3] == p_file_name[10]))))) { if (bcdb[j].type == BUL_TYPE_IGN) { /* Ignore this bulletin. */ *p_file_name = '\0'; return(SUCCESS); } else { bcdb_pos = j; } break; } } #else /* Last one that matches counts. */ for (j = 0; j < no_of_bc_entries; j++) { if (((bcdb[j].TTAAii[0] == '/') || (bcdb[j].TTAAii[0] == p_file_name[0])) && ((bcdb[j].TTAAii[1] == '/') || (bcdb[j].TTAAii[1] == p_file_name[1])) && ((bcdb[j].TTAAii[2] == '/') || (bcdb[j].TTAAii[2] == p_file_name[2])) && ((bcdb[j].TTAAii[3] == '/') || (bcdb[j].TTAAii[3] == p_file_name[3])) && (((bcdb[j].TTAAii[4] == '\0') && (p_file_name[4] == '_') && ((bcdb[j].CCCC[0] == '/') || (bcdb[j].CCCC[0] == p_file_name[5])) && ((bcdb[j].CCCC[1] == '/') || (bcdb[j].CCCC[1] == p_file_name[6])) && ((bcdb[j].CCCC[2] == '/') || (bcdb[j].CCCC[2] == p_file_name[7])) && ((bcdb[j].CCCC[3] == '/') || (bcdb[j].CCCC[3] == p_file_name[8]))) || (((bcdb[j].TTAAii[4] == '/') || (bcdb[j].TTAAii[4] == p_file_name[4])) && ((bcdb[j].TTAAii[5] == '/') || (bcdb[j].TTAAii[5] == p_file_name[5])) && (bcdb[j].TTAAii[6] == '\0') && (p_file_name[6] == '_') && ((bcdb[j].CCCC[0] == '/') || (bcdb[j].CCCC[0] == p_file_name[7])) && ((bcdb[j].CCCC[1] == '/') || (bcdb[j].CCCC[1] == p_file_name[8])) && ((bcdb[j].CCCC[2] == '/') || (bcdb[j].CCCC[2] == p_file_name[9])) && ((bcdb[j].CCCC[3] == '/') || (bcdb[j].CCCC[3] == p_file_name[10]))))) { bcdb_pos = j; } } if (bcdb[bcdb_pos].type == BUL_TYPE_IGN) { /* Ignore this bulletin. */ *p_file_name = '\0'; return(SUCCESS); } #endif } if (extract_options & EXTRACT_REPORTS) { int offset = 0; while (((ptr - msg) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' ') || (*ptr == '>'))) { ptr++; } if (extract_options & USE_EXTERNAL_MSG_RULES) { int rcdb_pos, ret = INCORRECT; char wid[2]; rcdb_pos = get_rcdb_position(p_file_name, bcdb_pos); wid[0] = '\0'; if ((bcdb_pos != -1) && (bcdb[bcdb_pos].rss != -1) && (rcdb_pos != -1) && (rcdb[rcdb_pos].rt != RT_NOT_DEFINED) && ((ret = find_offset(rcdb_pos, ptr, length - (ptr - msg), &offset, wid)) == SUCCESS)) { int begin_file_name_offset, bul_name_length = i, end_offset, file_name_offset = i, not_wanted = NO, overwrite_extra_heading; char *p_extra_heading = NULL; if ((extract_options & EXTRACT_SHOW_REPORT_TYPE) && (offset > 0)) { int space_count = 0; char *tmp_ptr = ptr; p_file_name[file_name_offset] = '-'; file_name_offset++; begin_file_name_offset = file_name_offset; while ((tmp_ptr < (ptr + offset)) && (*tmp_ptr != 13) && (*tmp_ptr != 10)) { if (*tmp_ptr == ' ') { if (space_count == 0) { p_file_name[file_name_offset] = '_'; space_count++; } else { break; } } else if (*tmp_ptr == '/') { p_file_name[file_name_offset] = '?'; } else { p_file_name[file_name_offset] = *tmp_ptr; } file_name_offset++; tmp_ptr++; } } else { begin_file_name_offset = -1; } p_file_name[file_name_offset] = '-'; file_name_offset++; if ((extract_options & EXTRACT_EXTRA_REPORT_HEADING) && (offset > 0)) { p_extra_heading = ptr; } ptr += offset; do { p_start = ptr; /* Ignore any spaces at start. */ while (((ptr - msg) < length) && ((*ptr == ' ') || (*ptr == '>'))) { ptr++; } if (get_station_id(p_file_name, file_name_offset, &end_offset, ptr, length - (ptr - msg), rcdb_pos, begin_file_name_offset, &p_extra_heading, &offset, &overwrite_extra_heading, wid) != SUCCESS) { /* Assume that this is a malformed or NIL report. */ while (((ptr - msg) < length) && (*ptr != '=')) { ptr++; } while (((ptr - msg) < length) && (*ptr == '=')) { ptr++; } if ((*ptr != 13) && (*ptr != 10)) { while (((ptr - msg) < length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } } while (((ptr - msg) < length) && ((*ptr == 13) || (*ptr == 10))) { ptr++; } if (((isprint((int)(*ptr))) && ((*(ptr + 1) == 13) || (*(ptr + 1) == 10))) || ((isprint((int)(*ptr))) && (isprint((int)(*(ptr + 1)))) && ((*(ptr + 2) == 13) || (*(ptr + 2) == 10))) || ((isprint((int)(*ptr))) && (isprint((int)(*(ptr + 1)))) && (isprint((int)(*(ptr + 2)))) && ((*(ptr + 3) == 13) || (*(ptr + 3) == 10)))) { ptr++; while (((ptr - msg) < length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } while (((ptr - msg) < length) && ((*ptr == 13) || (*ptr == 10))) { ptr++; } } } else { ptr += end_offset; if (extract_p_filter != NULL) { p_file_name[file_name_offset + end_offset] = '\0'; if (pmatch(extract_p_filter, p_file_name, NULL) != 0) { /* Ignore this report. */ not_wanted = YES; } else { not_wanted = NO; } } while (((ptr - msg) < length) && (*ptr != '=')) { ptr++; } while (((ptr - msg) < length) && (*ptr == '=')) { ptr++; } /* * Do not show any garbage or the last * in the report. */ if (not_wanted == NO) { int additional_offset = 0; if (extract_options & EXTRACT_ADD_ADDITIONAL_INFO) { char bulname[32]; if (bul_name_length < 32) { (void)memcpy(bulname, p_file_name, bul_name_length); bulname[bul_name_length] = '\0'; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, _("bulname to short, should be %d bytes long"), bul_name_length); bulname[0] = '\0'; } additional_offset += snprintf(&p_file_name[file_name_offset + end_offset], MAX_PATH_LENGTH - (file_name_offset + end_offset), "#%s.%s#%s#%s#%s#%s", wid, rcdb[rcdb_pos].wid, rcdb[rcdb_pos].BTIME, rcdb[rcdb_pos].ITIME, bulname, p_orig_name); } size = ptr - (p_start + overwrite_extra_heading); if (extract_options & EXTRACT_ADD_CRC_CHECKSUM) { additional_offset += snprintf(&p_file_name[file_name_offset + end_offset + additional_offset], MAX_PATH_LENGTH - (file_name_offset + end_offset + additional_offset), "-%x", get_checksum_crc32c(INITIAL_CRC, p_start + overwrite_extra_heading, #ifdef HAVE_HW_CRC32 (int)size, have_hw_crc32)); #else (int)size)); #endif } if (extract_options & EXTRACT_ADD_UNIQUE_NUMBER) { (void)next_counter(counter_fd, counter, MAX_MSG_PER_SEC); additional_offset += snprintf(&p_file_name[file_name_offset + end_offset + additional_offset], MAX_PATH_LENGTH - (file_name_offset + end_offset + additional_offset), "-%04x", *counter); } p_file_name[file_name_offset + end_offset + additional_offset] = '\0'; if ((fd = open(p_full_file_name, (O_RDWR | O_CREAT | O_TRUNC), file_mode)) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to open() `%s' while extracting reports : %s"), p_full_file_name, strerror(errno)); *p_file_name = '\0'; return(INCORRECT); } if (extract_options & EXTRACT_ADD_BUL_ORIG_FILE) { size_t length; length = strlen(p_file_name); if (writen(fd, p_file_name, length, 0) != (ssize_t)length) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() file name : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } *p_file_size += length; if (writen(fd, " ", (size_t)1, 0) != (ssize_t)1) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() space after file name : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } *p_file_size += 1; length = strlen(p_orig_name); if (writen(fd, p_orig_name, length, 0) != (ssize_t)length) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() extract file name : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } *p_file_size += length; if (writen(fd, "\r\r\n", 3, 0) != 3) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() carriage return, carriage return + line feed : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } *p_file_size += 2; } if (p_extra_heading != NULL) { if (writen(fd, p_extra_heading, (size_t)offset, 0) != (ssize_t)offset) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() extra header in report : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } *p_file_size += offset; } if (writen(fd, (p_start + overwrite_extra_heading), (size_t)size, 0) != (ssize_t)size) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() report : %s"), strerror(errno)); (void)close(fd); if (p_extra_heading != NULL) { *p_file_size -= offset; } return(INCORRECT); } if (writen(fd, "\r\r\n", 3, 0) != 3) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() carriage return, carriage return + line feed : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } (*p_files_to_send)++; *p_file_size += size + 3; if (close(fd) == -1) { receive_log(DEBUG_SIGN, __FILE__, __LINE__, 0L, _("close() error : %s"), strerror(errno)); } #ifdef _PRODUCTION_LOG if (no_of_log_entries == 0) { if ((pld = malloc((LOG_ENTRY_STEP_SIZE * sizeof(struct prod_log_db)))) == NULL) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("malloc() error : %s"), strerror(errno)); } } else { if ((no_of_log_entries % LOG_ENTRY_STEP_SIZE) == 0) { size_t new_size; struct prod_log_db *tmp_pld; new_size = ((no_of_log_entries / LOG_ENTRY_STEP_SIZE) + 1) * LOG_ENTRY_STEP_SIZE * sizeof(struct prod_log_db); if ((tmp_pld = realloc(pld, new_size)) == NULL) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("realloc() error : %s"), strerror(errno)); free(pld); no_of_log_entries = 0; } pld = tmp_pld; } } if (pld != NULL) { pld[no_of_log_entries].size = size; pld[no_of_log_entries].production_time = (times(&tval) - start_time) / (double)clktck; get_sum_cpu_usage(&ru, &pld[no_of_log_entries].cpu_usage); start_time = times(&tval); (void)strcpy(pld[no_of_log_entries].file_name, p_file_name); no_of_log_entries++; } #endif } /* Lets ignore any garbage behind the end of report. */ if ((*ptr != 13) && (*ptr != 10)) { while (((ptr - msg) < length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } } while (((ptr - msg) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } if (((isprint((int)(*ptr))) && ((*(ptr + 1) == 13) || (*(ptr + 1) == 10))) || ((isprint((int)(*ptr))) && (isprint((int)(*(ptr + 1)))) && ((*(ptr + 2) == 13) || (*(ptr + 2) == 10))) || ((isprint((int)(*ptr))) && (isprint((int)(*(ptr + 1)))) && (isprint((int)(*(ptr + 2)))) && ((*(ptr + 3) == 13) || (*(ptr + 3) == 10)))) { ptr++; while (((ptr - msg) < length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } while (((ptr - msg) < length) && ((*ptr == 13) || (*ptr == 10))) { ptr++; } } } } while ((ptr + 6 - msg) < length); } else { if (ret == INCORRECT) { char reason[64]; if (bcdb_pos == -1) { (void)strcpy(reason, "bcb_pos is -1"); } else if (bcdb[bcdb_pos].rss == -1) { (void)strcpy(reason, "report sub specification (rss) says it is not a report"); } else if (rcdb_pos == -1) { (void)strcpy(reason, "rcb_pos is -1"); } else if (rcdb[rcdb_pos].rt == RT_NOT_DEFINED) { (void)strcpy(reason, "report type is not defined"); } else /* Assume we failed to find offset. */ { (void)strcpy(reason, "failed to determine offset"); } receive_log(INFO_SIGN, __FILE__, __LINE__, 0L, "%s: Not extracting reports from %s because %s (pos bul=%d rep=%d)", p_file_name, p_orig_name, reason, bcdb_pos, rcdb_pos); #ifdef WHEN_READY if (extract_options & EXTRACT_ALSO_WRITE_NO_REPORTS) { int file_name_offset = i; p_file_name[file_name_offset] = '-'; file_name_offset++; if (p_file_name[4] == '_') { p_file_name[file_name_offset] = p_file_name[5]; p_file_name[file_name_offset + 1] = p_file_name[6]; p_file_name[file_name_offset + 2] = p_file_name[7]; p_file_name[file_name_offset + 3] = p_file_name[8]; } else if (p_file_name[6] == '_') { p_file_name[file_name_offset] = p_file_name[7]; p_file_name[file_name_offset + 1] = p_file_name[8]; p_file_name[file_name_offset + 2] = p_file_name[9]; p_file_name[file_name_offset + 3] = p_file_name[10]; } else { p_file_name[file_name_offset] = '?'; p_file_name[file_name_offset + 1] = '?'; p_file_name[file_name_offset + 2] = '?'; p_file_name[file_name_offset + 3] = '?'; } p_file_name[file_name_offset + 4] = '\0'; if ((fd = open(p_full_file_name, (O_RDWR | O_CREAT | O_TRUNC), file_mode)) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to open() `%s' while extracting reports : %s"), p_full_file_name, strerror(errno)); *p_file_name = '\0'; return(INCORRECT); } if (writen(fd, p_start, (size_t)length, 0) != (ssize_t)length) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() report : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } (*p_files_to_send)++; *p_file_size += length; if (close(fd) == -1) { receive_log(DEBUG_SIGN, __FILE__, __LINE__, 0L, _("close() error : %s"), strerror(errno)); } } #endif /* WHEN_READY */ } else if (ret == TEXT_MESSAGE) { receive_log(INFO_SIGN, __FILE__, __LINE__, 0L, "%s: Not extracting reports from %s because report type is TEXT (pos bul=%d rep=%d)", p_file_name, p_orig_name, bcdb_pos, rcdb_pos); } } } else { if ((((p_file_name[0] == 'F') && ((p_file_name[1] == 'T') || (p_file_name[1] == 'C'))) || ((p_file_name[0] == 'S') && ((p_file_name[1] == 'A') || (p_file_name[1] == 'H') || (p_file_name[1] == 'I') || (p_file_name[1] == 'M') || (p_file_name[1] == 'N') || (p_file_name[1] == 'P') || (p_file_name[1] == 'X'))) || ((p_file_name[0] == 'U') && ((p_file_name[1] == 'S') || (p_file_name[1] == 'K') || (p_file_name[1] == 'L') || (p_file_name[1] == 'E') || (p_file_name[1] == 'P') || (p_file_name[1] == 'G') || (p_file_name[1] == 'H') || (p_file_name[1] == 'Q')))) && (check_report(ptr, length - (ptr - msg), &offset) == SUCCESS)) { int bul_name_length = i, end_offset, file_name_offset = i, not_wanted = NO; char *p_extra_heading = NULL; if ((extract_options & EXTRACT_SHOW_REPORT_TYPE) && (offset > 0)) { char *tmp_ptr = ptr; p_file_name[file_name_offset] = '-'; file_name_offset++; while ((tmp_ptr < (ptr + offset)) && (*tmp_ptr != 13) && (*tmp_ptr != 10)) { if (*tmp_ptr == ' ') { p_file_name[file_name_offset] = '_'; } else { p_file_name[file_name_offset] = *tmp_ptr; } file_name_offset++; tmp_ptr++; } } p_file_name[file_name_offset] = '-'; file_name_offset++; if ((extract_options & EXTRACT_EXTRA_REPORT_HEADING) && (offset > 0)) { p_extra_heading = ptr; } ptr += offset; do { p_start = ptr; /* Ignore any spaces at start. */ while (((ptr - msg) < length) && (*ptr == ' ')) { ptr++; } /* TAF */ if (((ptr + 9 - msg) < length) && (*ptr == 'T') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'F') && (*(ptr + 3) == ' ') && (isupper((int)(*(ptr + 4)))) && (isupper((int)(*(ptr + 5)))) && (isupper((int)(*(ptr + 6)))) && (isupper((int)(*(ptr + 7)))) && (*(ptr + 8) == ' ')) { p_file_name[file_name_offset] = *(ptr + 4); p_file_name[file_name_offset + 1] = *(ptr + 5); p_file_name[file_name_offset + 2] = *(ptr + 6); p_file_name[file_name_offset + 3] = *(ptr + 7); end_offset = 4; ptr += 9; } /* TAF AMD or COR */ else if (((ptr + 13 - msg) < length) && (isupper((int)(*ptr))) && (isupper((int)(*(ptr + 1)))) && (isupper((int)(*(ptr + 2)))) && (*(ptr + 3) == ' ') && (isupper((int)(*(ptr + 4)))) && (isupper((int)(*(ptr + 5)))) && (isupper((int)(*(ptr + 6)))) && (*(ptr + 7) == ' ') && (isupper((int)(*(ptr + 8)))) && (isupper((int)(*(ptr + 9)))) && (isupper((int)(*(ptr + 10)))) && (isupper((int)(*(ptr + 11)))) && (*(ptr + 12) == ' ')) { p_file_name[file_name_offset] = *(ptr + 8); p_file_name[file_name_offset + 1] = *(ptr + 9); p_file_name[file_name_offset + 2] = *(ptr + 10); p_file_name[file_name_offset + 3] = *(ptr + 11); end_offset = 4; ptr += 13; } /* METAR or SPECI */ else if (((ptr + 6 - msg) < length) && (((*ptr == 'M') && (*(ptr + 1) == 'E') && (*(ptr + 2) == 'T') && (*(ptr + 3) == 'A') && (*(ptr + 4) == 'R')) || ((*ptr == 'S') && (*(ptr + 1) == 'P') && (*(ptr + 2) == 'E') && (*(ptr + 3) == 'C') && (*(ptr + 4) == 'I'))) && (*(ptr + 5) == ' ')) { while (((ptr + 6 - msg) < length) && (*(ptr + 6) == ' ')) { ptr++; } if (((ptr + 4 - msg) < length) && (*(ptr + 6) == 'C') && (*(ptr + 7) == 'O') && (*(ptr + 8) == 'R') && (*(ptr + 9) == ' ')) { ptr += 4; } if (((ptr + 5 - msg) < length) && ((isupper((int)(*(ptr + 6)))) || (isdigit((int)(*(ptr + 6))))) && ((isupper((int)(*(ptr + 7)))) || (isdigit((int)(*(ptr + 6))))) && ((isupper((int)(*(ptr + 8)))) || (isdigit((int)(*(ptr + 6))))) && ((isupper((int)(*(ptr + 9)))) || (isdigit((int)(*(ptr + 6))))) && (*(ptr + 10) == ' ')) { p_file_name[file_name_offset] = *(ptr + 6); p_file_name[file_name_offset + 1] = *(ptr + 7); p_file_name[file_name_offset + 2] = *(ptr + 8); p_file_name[file_name_offset + 3] = *(ptr + 9); end_offset = 4; ptr += 11; } else if (((ptr + 6 - msg) < length) && ((isupper((int)(*(ptr + 6)))) || (isdigit((int)(*(ptr + 6))))) && ((isupper((int)(*(ptr + 7)))) || (isdigit((int)(*(ptr + 7))))) && ((isupper((int)(*(ptr + 8)))) || (isdigit((int)(*(ptr + 8))))) && ((isupper((int)(*(ptr + 9)))) || (isdigit((int)(*(ptr + 9))))) && ((isupper((int)(*(ptr + 10)))) || (isdigit((int)(*(ptr + 10))))) && (*(ptr + 11) == ' ')) { p_file_name[file_name_offset] = *(ptr + 6); p_file_name[file_name_offset + 1] = *(ptr + 7); p_file_name[file_name_offset + 2] = *(ptr + 8); p_file_name[file_name_offset + 3] = *(ptr + 9); p_file_name[file_name_offset + 4] = *(ptr + 10); end_offset = 5; ptr += 12; } else { show_unknown_report(ptr, length, msg, __FILE__, __LINE__); break; } } /* METAR, SPECI, TAF AMD, AAXX or BBXX (in a group) */ else if (((ptr + 5 - msg) < length) && ((isupper((int)(*ptr))) || (isdigit((int)(*ptr)))) && ((isupper((int)(*(ptr + 1)))) || (isdigit((int)(*(ptr + 1))))) && ((isupper((int)(*(ptr + 2)))) || (isdigit((int)(*(ptr + 2))))) && ((isupper((int)(*(ptr + 3)))) || (isdigit((int)(*(ptr + 3))))) && (*(ptr + 4) == ' ')) { p_file_name[file_name_offset] = *ptr; p_file_name[file_name_offset + 1] = *(ptr + 1); p_file_name[file_name_offset + 2] = *(ptr + 2); p_file_name[file_name_offset + 3] = *(ptr + 3); end_offset = 4; ptr += 5; } /* German METAR */ else if (((ptr + 13 - p_start) < length) && (isupper((int)(*ptr))) && (isupper((int)(*(ptr + 1)))) && (isupper((int)(*(ptr + 2)))) && (isupper((int)(*(ptr + 3)))) && (*(ptr + 4) == ' ') && (isdigit((int)(*(ptr + 5)))) && (isdigit((int)(*(ptr + 6)))) && (isdigit((int)(*(ptr + 7)))) && (isdigit((int)(*(ptr + 8)))) && (isdigit((int)(*(ptr + 9)))) && (isdigit((int)(*(ptr + 10)))) && (*(ptr + 11) == 'Z') && (*(ptr + 12) == ' ')) { p_file_name[file_name_offset] = *ptr; p_file_name[file_name_offset + 1] = *(ptr + 1); p_file_name[file_name_offset + 2] = *(ptr + 2); p_file_name[file_name_offset + 3] = *(ptr + 3); end_offset = 4; ptr += 13; } /* AAXX or BBXX (in a group) */ else if (((ptr + 7 - msg) < length) && ((isupper((int)(*ptr))) || (isdigit((int)(*ptr)))) && ((isupper((int)(*(ptr + 1)))) || (isdigit((int)(*(ptr + 1))))) && ((isupper((int)(*(ptr + 2)))) || (isdigit((int)(*(ptr + 2))))) && ((isupper((int)(*(ptr + 3)))) || (isdigit((int)(*(ptr + 3))))) && ((isupper((int)(*(ptr + 4)))) || (isdigit((int)(*(ptr + 4))))) && ((isupper((int)(*(ptr + 5)))) || (isdigit((int)(*(ptr + 5))))) && (*(ptr + 6) == ' ')) { p_file_name[file_name_offset] = *ptr; p_file_name[file_name_offset + 1] = *(ptr + 1); p_file_name[file_name_offset + 2] = *(ptr + 2); p_file_name[file_name_offset + 3] = *(ptr + 3); p_file_name[file_name_offset + 4] = *(ptr + 4); p_file_name[file_name_offset + 5] = *(ptr + 5); end_offset = 6; ptr += 7; } /* AAXX or BBXX (in a group) */ else if (((ptr + 8 - msg) < length) && ((isupper((int)(*ptr))) || (isdigit((int)(*ptr)))) && ((isupper((int)(*(ptr + 1)))) || (isdigit((int)(*(ptr + 1))))) && ((isupper((int)(*(ptr + 2)))) || (isdigit((int)(*(ptr + 2))))) && ((isupper((int)(*(ptr + 3)))) || (isdigit((int)(*(ptr + 3))))) && ((isupper((int)(*(ptr + 4)))) || (isdigit((int)(*(ptr + 4))))) && ((isupper((int)(*(ptr + 5)))) || (isdigit((int)(*(ptr + 5))))) && ((isupper((int)(*(ptr + 6)))) || (isdigit((int)(*(ptr + 6))))) && (*(ptr + 7) == ' ')) { p_file_name[file_name_offset] = *ptr; p_file_name[file_name_offset + 1] = *(ptr + 1); p_file_name[file_name_offset + 2] = *(ptr + 2); p_file_name[file_name_offset + 3] = *(ptr + 3); p_file_name[file_name_offset + 4] = *(ptr + 4); p_file_name[file_name_offset + 5] = *(ptr + 5); p_file_name[file_name_offset + 6] = *(ptr + 6); end_offset = 7; ptr += 8; } /* SYNOP, AAXX or BBXX (in a group) */ else if (((ptr + 6 - msg) < length) && ((isupper((int)(*ptr))) || (isdigit((int)(*ptr)))) && ((isupper((int)(*(ptr + 1)))) || (isdigit((int)(*(ptr + 1))))) && ((isupper((int)(*(ptr + 2)))) || (isdigit((int)(*(ptr + 2))))) && ((isupper((int)(*(ptr + 3)))) || (isdigit((int)(*(ptr + 3))))) && ((isupper((int)(*(ptr + 4)))) || (isdigit((int)(*(ptr + 4))))) && (*(ptr + 5) == ' ')) { p_file_name[file_name_offset] = *ptr; p_file_name[file_name_offset + 1] = *(ptr + 1); p_file_name[file_name_offset + 2] = *(ptr + 2); p_file_name[file_name_offset + 3] = *(ptr + 3); p_file_name[file_name_offset + 4] = *(ptr + 4); end_offset = 5; ptr += 6; } /* SHDL */ else if (((ptr + 12 - msg) < length) && (isupper((int)(*ptr))) && (isupper((int)(*(ptr + 1)))) && (isupper((int)(*(ptr + 2)))) && (isupper((int)(*(ptr + 3)))) && (*(ptr + 4) == ' ') && (isdigit((int)(*(ptr + 5)))) && (isdigit((int)(*(ptr + 6)))) && (isdigit((int)(*(ptr + 7)))) && (isdigit((int)(*(ptr + 8)))) && (isdigit((int)(*(ptr + 9)))) && (isdigit((int)(*(ptr + 10)))) && (isdigit((int)(*(ptr + 11))))) { ptr += 12; while (((ptr - msg) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } p_start = ptr; p_file_name[file_name_offset] = *ptr; p_file_name[file_name_offset + 1] = *(ptr + 1); p_file_name[file_name_offset + 2] = *(ptr + 2); p_file_name[file_name_offset + 3] = *(ptr + 3); p_file_name[file_name_offset + 4] = *(ptr + 4); end_offset = 5; } /* NIL */ else if (((ptr + 4 - msg) < length) && (*ptr == 'N') && (*(ptr + 1) == 'I') && (*(ptr + 2) == 'L') && ((*(ptr + 3) == 13) || (*(ptr + 3) == 10))) { ptr += 4; while (((ptr - msg) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } continue; } /* NIL= */ else if (((ptr + 5 - msg) < length) && (*ptr == 'N') && (*(ptr + 1) == 'I') && (*(ptr + 2) == 'L') && (*(ptr + 3) == '=') && ((*(ptr + 4) == 13) || (*(ptr + 4) == 10))) { ptr += 5; while (((ptr - msg) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } continue; } /* TAF NIL= */ else if (((ptr + 9 - msg) < length) && (*ptr == 'T') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'F') && (*(ptr + 3) == ' ') && (*(ptr + 4) == 'N') && (*(ptr + 5) == 'I') && (*(ptr + 6) == 'L') && (*(ptr + 7) == '=') && ((*(ptr + 8) == 13) || (*(ptr + 8) == 10))) { ptr += 9; while (((ptr - msg) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } continue; } else { show_unknown_report(ptr, length, msg, __FILE__, __LINE__); break; } if (extract_p_filter != NULL) { p_file_name[file_name_offset + end_offset] = '\0'; if (pmatch(extract_p_filter, p_file_name, NULL) != 0) { /* Ignore this report. */ not_wanted = YES; } else { not_wanted = NO; } } while (((ptr - msg) < length) && (*ptr != '=')) { ptr++; } while (((ptr - msg) < length) && (*ptr == '=')) { ptr++; } while (((ptr - msg) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } if (not_wanted == NO) { int additional_offset = 0; if (extract_options & EXTRACT_ADD_ADDITIONAL_INFO) { char bulname[32]; if (bul_name_length < 32) { (void)memcpy(bulname, p_file_name, bul_name_length); bulname[bul_name_length] = '\0'; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, _("bulname to short, should be %d bytes long"), bul_name_length); bulname[0] = '\0'; } additional_offset += snprintf(&p_file_name[file_name_offset + end_offset], MAX_PATH_LENGTH - (file_name_offset + end_offset), "#%s#%s", bulname, p_orig_name); } size = ptr - p_start; if (extract_options & EXTRACT_ADD_CRC_CHECKSUM) { additional_offset += snprintf(&p_file_name[file_name_offset + end_offset + additional_offset], MAX_PATH_LENGTH - (file_name_offset + end_offset + additional_offset), "-%x", get_checksum_crc32c(INITIAL_CRC, p_start, #ifdef HAVE_HW_CRC32 (int)size, have_hw_crc32)); #else (int)size)); #endif } if (extract_options & EXTRACT_ADD_UNIQUE_NUMBER) { (void)next_counter(counter_fd, counter, MAX_MSG_PER_SEC); additional_offset += snprintf(&p_file_name[file_name_offset + end_offset + additional_offset], MAX_PATH_LENGTH - (file_name_offset + end_offset + additional_offset), "-%04x", *counter); } p_file_name[file_name_offset + end_offset + additional_offset] = '\0'; if ((fd = open(p_full_file_name, (O_RDWR | O_CREAT | O_TRUNC), file_mode)) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to open() `%s' while extracting reports : %s"), p_full_file_name, strerror(errno)); *p_file_name = '\0'; return(INCORRECT); } if (extract_options & EXTRACT_ADD_BUL_ORIG_FILE) { size_t length; length = strlen(p_file_name); if (writen(fd, p_file_name, length, 0) != (ssize_t)length) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() file name : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } *p_file_size += length; if (writen(fd, " ", (size_t)1, 0) != (ssize_t)1) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() space after file name : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } *p_file_size += 1; length = strlen(p_orig_name); if (writen(fd, p_orig_name, length, 0) != (ssize_t)length) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() extract file name : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } *p_file_size += length; if (writen(fd, "\r\r\n", 3, 0) != 3) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() carriage return, carriage return + line feed : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } *p_file_size += 2; } if (p_extra_heading != NULL) { if (writen(fd, p_extra_heading, (size_t)offset, 0) != (ssize_t)offset) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() extra header in report : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } *p_file_size += offset; } if (writen(fd, p_start, (size_t)size, 0) != (ssize_t)size) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() report : %s"), strerror(errno)); (void)close(fd); if (p_extra_heading != NULL) { *p_file_size -= offset; } return(INCORRECT); } (*p_files_to_send)++; *p_file_size += size; if (close(fd) == -1) { receive_log(DEBUG_SIGN, __FILE__, __LINE__, 0L, _("close() error : %s"), strerror(errno)); } #ifdef _PRODUCTION_LOG if (no_of_log_entries == 0) { if ((pld = malloc((LOG_ENTRY_STEP_SIZE * sizeof(struct prod_log_db)))) == NULL) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("malloc() error : %s"), strerror(errno)); } } else { if ((no_of_log_entries % LOG_ENTRY_STEP_SIZE) == 0) { size_t new_size; struct prod_log_db *tmp_pld; new_size = ((no_of_log_entries / LOG_ENTRY_STEP_SIZE) + 1) * LOG_ENTRY_STEP_SIZE * sizeof(struct prod_log_db); if ((tmp_pld = realloc(pld, new_size)) == NULL) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("realloc() error : %s"), strerror(errno)); free(pld); no_of_log_entries = 0; } pld = tmp_pld; } } if (pld != NULL) { pld[no_of_log_entries].size = size; pld[no_of_log_entries].production_time = (times(&tval) - start_time) / (double)clktck; get_sum_cpu_usage(&ru, &pld[no_of_log_entries].cpu_usage); start_time = times(&tval); (void)strcpy(pld[no_of_log_entries].file_name, p_file_name); no_of_log_entries++; } #endif } } while ((ptr + 6 - msg) < length); } else { receive_log(DEBUG_SIGN, __FILE__, __LINE__, 0L, _("%s not marked as a report"), p_file_name); } } } else { if (extract_p_filter != NULL) { p_file_name[i] = '\0'; if (pmatch(extract_p_filter, p_file_name, NULL) != 0) { /* Ignore this bulletin. */ return(SUCCESS); } } if (extract_options & EXTRACT_ADD_CRC_CHECKSUM) { i += snprintf(&p_file_name[i], MAX_PATH_LENGTH - i, "-%x", get_checksum_crc32c(INITIAL_CRC, msg, #ifdef HAVE_HW_CRC32 length, have_hw_crc32)); #else length)); #endif } if (extract_options & EXTRACT_ADD_UNIQUE_NUMBER) { (void)next_counter(counter_fd, counter, MAX_MSG_PER_SEC); i += snprintf(&p_file_name[i], MAX_PATH_LENGTH - i, "-%04x", *counter); } p_file_name[i] = '\0'; if ((fd = open(p_full_file_name, (O_WRONLY | O_CREAT | O_TRUNC), file_mode)) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to open() `%s' (mode=%d) while extracting bulletins from `%s' : %s"), p_full_file_name, file_mode, p_orig_name, strerror(errno)); *p_file_name = '\0'; return(INCORRECT); } if ((extract_options & EXTRACT_ADD_SOH_ETX) && ((extract_options & EXTRACT_REMOVE_WMO_HEADER) == 0)) { if (soh_etx == NO) { if (write(fd, "\001", 1) != 1) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to write() SOH : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } } if (writen(fd, msg, (size_t)length, 0) != (ssize_t)length) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() message : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } if (soh_etx == NO) { if (write(fd, "\003", 1) != 1) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to write() ETX : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } size = length + 2; } else { size = length; } } else { if (extract_options & EXTRACT_REMOVE_WMO_HEADER) { p_start = ptr; while ((*p_start == '\012') || (*p_start == '\015')) { p_start++; } } if (msg[length - 1] == 3) { length--; while ((length > 0) && ((msg[length - 1] == '\015') || (msg[length - 1] == '\012'))) { length--; } } length -= (p_start - msg); if (writen(fd, p_start, (size_t)length, 0) != (ssize_t)length) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to writen() message : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } size = length; } (*p_files_to_send)++; *p_file_size += size; if (close(fd) == -1) { receive_log(DEBUG_SIGN, __FILE__, __LINE__, 0L, _("close() error : %s"), strerror(errno)); } #ifdef _PRODUCTION_LOG if (no_of_log_entries == 0) { if ((pld = malloc((LOG_ENTRY_STEP_SIZE * sizeof(struct prod_log_db)))) == NULL) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("malloc() error : %s"), strerror(errno)); } } else { if ((no_of_log_entries % LOG_ENTRY_STEP_SIZE) == 0) { size_t new_size; struct prod_log_db *tmp_pld; new_size = ((no_of_log_entries / LOG_ENTRY_STEP_SIZE) + 1) * LOG_ENTRY_STEP_SIZE * sizeof(struct prod_log_db); if ((tmp_pld = realloc(pld, new_size)) == NULL) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("realloc() error : %s"), strerror(errno)); free(pld); no_of_log_entries = 0; } pld = tmp_pld; } } if (pld != NULL) { pld[no_of_log_entries].size = size; pld[no_of_log_entries].production_time = (times(&tval) - start_time) / (double)clktck; get_sum_cpu_usage(&ru, &pld[no_of_log_entries].cpu_usage); start_time = times(&tval); (void)strcpy(pld[no_of_log_entries].file_name, p_file_name); no_of_log_entries++; } #endif } *p_file_name = '\0'; return(SUCCESS); } /*------------------------- get_rcdb_position() -------------------------*/ static int get_rcdb_position(char *p_file_name, int bcdb_pos) { int i; for (i = 0; i < no_of_rc_entries; i++) { if ((rcdb[i].TT[0] == p_file_name[0]) && (rcdb[i].TT[1] == p_file_name[1]) && (rcdb[i].rss == bcdb[bcdb_pos].rss)) { return(i); } } return(-1); } /*---------------------------- find_offset() ----------------------------*/ static int find_offset(int rcdb_pos, char *ptr, int length, int *offset, char *p_wid) { char *p_start = ptr; /* Ignore any spaces at start. */ while (((ptr - p_start) < length) && (*ptr == ' ')) { ptr++; } if ((*ptr == 'N') && (*(ptr + 1) == 'I') && (*(ptr + 2) == 'L') && ((*(ptr + 3) == 13) || (*(ptr + 3) == 10) || (*(ptr + 3) == '='))) { return(NIL_MESSAGE); } switch (rcdb[rcdb_pos].rt) { case RT_TEXT : /* TEXT */ return(TEXT_MESSAGE); case RT_CLIMAT : /* CLIMAT */ while (((ptr - p_start) < length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } if (rcdb[rcdb_pos].mimj[0] != '\0') { if (isdigit((int)(*(ptr - 1)))) { *p_wid = *(ptr - 1); *(p_wid + 1) = '\0'; } } while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } break; case RT_TAF : /* TAF */ if ((*ptr == 'T') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'F') && (*(ptr + 3) == ' ') && (isdigit((int)(*(ptr + 4)))) && (isdigit((int)(*(ptr + 5)))) && (isdigit((int)(*(ptr + 6)))) && (isdigit((int)(*(ptr + 7)))) && (isdigit((int)(*(ptr + 8)))) && (isdigit((int)(*(ptr + 9)))) && (*(ptr + 10) == 'Z') && (*(ptr + 11) == 13) && (*(ptr + 12) == 13) && (*(ptr + 13) == 10) && (*(ptr + 14) == 'T') && (*(ptr + 15) == 'A') && (*(ptr + 16) == 'F') && ((*(ptr + 17) == ' ') || (*(ptr + 17) == '\t') || (*(ptr + 17) == 13))) { ptr += 14; } else { while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } } break; case RT_SPECIAL_02 : /* SPECIAL-02 */ while (((ptr - p_start) < length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } break; case RT_METAR : /* METAR */ case RT_SPECIAL_01 : /* SPECIAL-01 */ case RT_SPECIAL_03 : /* SPECIAL-03 */ case RT_SPECIAL_66 : /* SPECIAL-66 */ case RT_ATEXT : /* AIR TEXT */ while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } break; case RT_SYNOP : /* SYNOP */ if ((*ptr == 'A') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'X')) { if (*(ptr + 3) == 'X') { ptr += 4; } else { ptr += 3; } while (((ptr - p_start) < length) && (*ptr == ' ')) { ptr++; } if ((isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && (*(ptr + 5) == ' ')) { *p_wid = *(ptr + 4); *(p_wid + 1) = '\0'; ptr += 6; } else { while (((ptr - p_start) < length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } if (isdigit((int)(*(ptr - 1)))) { *p_wid = *(ptr - 1); *(p_wid + 1) = '\0'; } } } while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } break; case RT_SYNOP_SHIP : /* SYNOP-SHIP */ if (rcdb[rcdb_pos].mimj[1] == 'X') { while (((ptr - p_start) < length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } if (isdigit((int)(*(ptr - 1)))) { *p_wid = *(ptr - 1); *(p_wid + 1) = '\0'; } } while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } break; case RT_SYNOP_MOBIL : /* SYNOP-MOBIL */ while (((ptr - p_start) < length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } break; case RT_UPPER_AIR : /* UPPER-AIR */ while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } break; default : /* Unknown report type */ receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, "Unknown report type %d (%d), unable to extract reports.", rcdb[rcdb_pos].rt, rcdb_pos); return(INCORRECT); } *offset = ptr - p_start; return(SUCCESS); } /*-------------------------- get_station_id() ---------------------------*/ static int get_station_id(char *file_name, int file_name_offset, int *station_id_length, char *ptr, int msg_length, int rcdb_pos, int begin_file_name_offset, char **p_extra_heading, int *offset, int *overwrite_extra_heading, char *p_wid) { char *p_start = ptr, *station_id = &file_name[file_name_offset]; *overwrite_extra_heading = 0; switch (rcdb[rcdb_pos].rt) { case RT_TEXT : /* TEXT */ station_id[0] = '\0'; receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: TEXT in %s still needs to be done!", p_file_name, p_orig_name); hex_print(WARN_SIGN, p_start, msg_length); return(INCORRECT); case RT_ATEXT : /* AIR TEXT */ if ((isupper((int)(*ptr))) && (isupper((int)(*(ptr + 1)))) && (isupper((int)(*(ptr + 2)))) && (isalnum((int)(*(ptr + 3)))) && ((*(ptr + 4) == ' ') || (*(ptr + 4) == '\t'))) { station_id[0] = *ptr; station_id[1] = *(ptr + 1); station_id[2] = *(ptr + 2); station_id[3] = *(ptr + 3); *station_id_length = 4; } else { station_id[0] = '\0'; if ((*ptr == 'N') && (((*(ptr + 1) == 'I') && (*(ptr + 2) == 'L')) || (((*(ptr + 1) == 'N') || (*(ptr + 1) == 'n')) && ((*(ptr + 2) == 'N') || (*(ptr + 2) == 'n')) && ((*(ptr + 3) == 'N') || (*(ptr + 3) == 'n'))))) { /* Do not warn if we find NIL or NNNN. */; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown AIR TEXT in %s. If this is a correct report, contact maintainer %s (pos=%d)", p_file_name, p_orig_name, AFD_MAINTAINER, rcdb_pos); hex_print(WARN_SIGN, p_start, msg_length); } return(INCORRECT); } break; case RT_CLIMAT : /* CLIMAT */ if ((isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && ((*(ptr + 5) == ' ') || (*(ptr + 5) == 13) || (*(ptr + 5) == 10))) { station_id[0] = *ptr; station_id[1] = *(ptr + 1); station_id[2] = *(ptr + 2); station_id[3] = *(ptr + 3); station_id[4] = *(ptr + 4); *station_id_length = 5; } else { station_id[0] = '\0'; if ((*ptr == 'N') && (((*(ptr + 1) == 'I') && (*(ptr + 2) == 'L')) || (((*(ptr + 1) == 'N') || (*(ptr + 1) == 'n')) && ((*(ptr + 2) == 'N') || (*(ptr + 2) == 'n')) && ((*(ptr + 3) == 'N') || (*(ptr + 3) == 'n'))))) { /* Do not warn if we find NIL or NNNN. */; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown CLIMAT in %s. If this is a correct report, contact maintainer %s (pos=%d)", p_file_name, p_orig_name, AFD_MAINTAINER, rcdb_pos); hex_print(WARN_SIGN, p_start, msg_length); } return(INCORRECT); } break; case RT_TAF : /* TAF */ /* * Possible cases: 1) TAF STID ...= * 2) TAF AMD STID ...= * 3) TAF COR STID ...= * 4) TAF * STID ...= * STID ...= */ if ((*ptr == 'T') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'F') && ((*(ptr + 3) == ' ') || (*(ptr + 3) == '\t') || (*(ptr + 3) == 13))) { if ((*(ptr + 3) == 13) && (*(ptr + 4) == 13) && (*(ptr + 5) == 10) && (*(ptr + 6) == 'T') && (*(ptr + 7) == 'A') && (*(ptr + 8) == 'F') && ((*(ptr + 9) == ' ') || (*(ptr + 9) == '\t'))) { ptr += 6; } else if ((*(ptr + 3) == ' ') && (((*(ptr + 4) == 'A') && (*(ptr + 5) == 'M') && (*(ptr + 6) == 'D')) || ((*(ptr + 4) == 'C') && (*(ptr + 5) == 'O') && (*(ptr + 6) == 'R'))) && (*(ptr + 7) == 13) && (*(ptr + 8) == 13) && (*(ptr + 9) == 10) && (*(ptr + 10) == 'T') && (*(ptr + 11) == 'A') && (*(ptr + 12) == 'F')) { ptr += 9; } ptr += 4; while ((*ptr == 13) || (*ptr == 10)) { ptr++; } while ((*ptr == ' ') || (*ptr == '\t')) { ptr++; } if ((((*ptr == 'A') && (*(ptr + 1) == 'M') && (*(ptr + 2) == 'D')) || ((*ptr == 'C') && (*(ptr + 1) == 'O') && (*(ptr + 2) == 'R'))) && ((*(ptr + 3) == ' ') || (*(ptr + 3) == '\t') || (*(ptr + 3) == 13))) { ptr += 4; } while ((*ptr == 13) || (*ptr == 10)) { ptr++; } } else if ((*ptr == 'A') && (*(ptr + 1) == 'M') && (*(ptr + 2) == 'D') && ((*(ptr + 3) == ' ') || (*(ptr + 3) == '\t'))) { ptr += 4; while ((*ptr == ' ') || (*ptr == '\t')) { ptr++; } } if ((isupper((int)(*ptr))) && (isupper((int)(*(ptr + 1)))) && (isupper((int)(*(ptr + 2)))) && (isalnum((int)(*(ptr + 3)))) && ((*(ptr + 4) == ' ') || (*(ptr + 4) == '\t'))) { station_id[0] = *ptr; station_id[1] = *(ptr + 1); station_id[2] = *(ptr + 2); station_id[3] = *(ptr + 3); *station_id_length = 4; } else { station_id[0] = '\0'; if (((*ptr == 'N') && (((*(ptr + 1) == 'I') && (*(ptr + 2) == 'L')) || (((*(ptr + 1) == 'N') || (*(ptr + 1) == 'n')) && ((*(ptr + 2) == 'N') || (*(ptr + 2) == 'n')) && ((*(ptr + 3) == 'N') || (*(ptr + 3) == 'n'))))) || ((*ptr == '/') && (*(ptr + 1) == '/') && ((*(ptr + 2) == ' ') || (*(ptr + 2) == 'E')))) { /* Do not warn if we find NIL or NNNN. */; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown TAF in %s. If this is a correct report, contact maintainer %s (pos=%d)", p_file_name, p_orig_name, AFD_MAINTAINER, rcdb_pos); hex_print(WARN_SIGN, p_start, msg_length); } return(INCORRECT); } break; case RT_METAR : /* METAR or SPECI */ /* * Possible cases: 1) METAR STID ...= * 2) METAR COR STID ...= * 3) METAR RRA STID ...= * 4) METAR * STID ...= * STID ...= */ if ((((*ptr == 'M') && (*(ptr + 1) == 'E') && (*(ptr + 2) == 'T') && (*(ptr + 3) == 'A') && (*(ptr + 4) == 'R')) || ((*ptr == 'S') && (*(ptr + 1) == 'P') && (*(ptr + 2) == 'E') && (*(ptr + 3) == 'C') && (*(ptr + 4) == 'I'))) && ((*(ptr + 5) == ' ') || (*(ptr + 5) == '\t') || (*(ptr + 5) == 13))) { ptr += 6; while ((*ptr == ' ') || (*ptr == '\t')) { ptr++; } if ((((*ptr == 'M') && (*(ptr + 1) == 'E') && (*(ptr + 2) == 'T') && (*(ptr + 3) == 'A') && (*(ptr + 4) == 'R')) || ((*ptr == 'S') && (*(ptr + 1) == 'P') && (*(ptr + 2) == 'E') && (*(ptr + 3) == 'C') && (*(ptr + 4) == 'I'))) && ((*(ptr + 5) == ' ') || (*(ptr + 5) == '\t'))) { ptr += 6; while ((*ptr == ' ') || (*ptr == '\t')) { ptr++; } } if ((isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && (isdigit((int)(*(ptr + 5)))) && (*(ptr + 6) == 'Z') && (*(ptr + 7) == 13) && (*(ptr + 8) == 13) && (*(ptr + 9) == 10) && (((*(ptr + 10) == 'M') && (*(ptr + 11) == 'E') && (*(ptr + 12) == 'T') && (*(ptr + 13) == 'A') && (*(ptr + 14) == 'R')) || ((*(ptr + 10) == 'S') && (*(ptr + 11) == 'P') && (*(ptr + 12) == 'E') && (*(ptr + 13) == 'C') && (*(ptr + 14) == 'I'))) && ((*(ptr + 15) == ' ') || (*(ptr + 15) == '\t') || (*(ptr + 15) == 13))) { ptr += 16; } else if ((isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && (isdigit((int)(*(ptr + 5)))) && (*(ptr + 6) == 'Z') && (*(ptr + 7) == 13) && (*(ptr + 8) == 13) && (*(ptr + 9) == 10) && (*(ptr + 10) == 13) && (*(ptr + 11) == 13) && (*(ptr + 12) == 10) && (((*(ptr + 13) == 'M') && (*(ptr + 14) == 'E') && (*(ptr + 15) == 'T') && (*(ptr + 16) == 'A') && (*(ptr + 17) == 'R')) || ((*(ptr + 13) == 'S') && (*(ptr + 14) == 'P') && (*(ptr + 15) == 'E') && (*(ptr + 16) == 'C') && (*(ptr + 17) == 'I'))) && ((*(ptr + 18) == ' ') || (*(ptr + 18) == '\t') || (*(ptr + 18) == 13))) { ptr += 19; } while ((*ptr == ' ') || (*ptr == '\t')) { ptr++; } if ((((*ptr == 'C') && (*(ptr + 1) == 'O') && (*(ptr + 2) == 'R')) || ((*ptr == 'R') && (*(ptr + 1) == 'R') && (*(ptr + 2) == 'A'))) && ((*(ptr + 3) == ' ') || (*(ptr + 3) == '\t') || (*(ptr + 3) == 13))) { ptr += 4; } while ((*ptr == 13) || (*ptr == 10)) { ptr++; } } if ((rcdb[rcdb_pos].stid == STID_CCCC) && (isupper((int)(*ptr))) && (isalnum((int)(*(ptr + 1)))) && (isalnum((int)(*(ptr + 2)))) && (isalnum((int)(*(ptr + 3)))) && ((*(ptr + 4) == ' ') || (*(ptr + 4) == '\t'))) { station_id[0] = *ptr; station_id[1] = *(ptr + 1); station_id[2] = *(ptr + 2); station_id[3] = *(ptr + 3); *station_id_length = 4; } else if ((rcdb[rcdb_pos].stid == STID_IIiii) && (isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && ((*(ptr + 5) == ' ') || (*(ptr + 5) == '\t'))) { station_id[0] = *ptr; station_id[1] = *(ptr + 1); station_id[2] = *(ptr + 2); station_id[3] = *(ptr + 3); station_id[4] = *(ptr + 4); *station_id_length = 5; } else { station_id[0] = '\0'; if (((*ptr == 'N') && (((*(ptr + 1) == 'I') && (*(ptr + 2) == 'L')) || (((*(ptr + 1) == 'N') || (*(ptr + 1) == 'n')) && ((*(ptr + 2) == 'N') || (*(ptr + 2) == 'n')) && ((*(ptr + 3) == 'N') || (*(ptr + 3) == 'n'))))) || ((*p_start == 'M') && (*(p_start + 1) == 'E') && (*(p_start + 2) == 'T') && (*(p_start + 3) == 'A') && (*(p_start + 4) == 'R') && (*(p_start + 5) == ' ') && (isdigit((int)(*(p_start + 6)))) && (isdigit((int)(*(p_start + 7)))) && (isdigit((int)(*(p_start + 8)))) && (isdigit((int)(*(p_start + 9)))) && (isdigit((int)(*(p_start + 10)))) && (isdigit((int)(*(p_start + 11)))) && (*(p_start + 12) == 'Z') && (*(p_start + 13) == 13))) { /* Do not warn if we find NIL, NNNN or METAR xxxxxxZ. */; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown METAR or SPECI in %s. If this is a correct report, contact maintainer %s (pos=%d)", p_file_name, p_orig_name, AFD_MAINTAINER, rcdb_pos); hex_print(WARN_SIGN, p_start, msg_length); } return(INCORRECT); } break; case RT_SPECIAL_01 : /* SPECIAL-01 */ station_id[0] = '\0'; receive_log(INFO_SIGN, __FILE__, __LINE__, 0L, "%s: SPECIAL-01 in %s still needs to be done!", p_file_name, p_orig_name); hex_print(WARN_SIGN, p_start, msg_length); return(INCORRECT); case RT_SPECIAL_02 : /* SPECIAL-02 */ if ((isalpha((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && ((*(ptr + 4) == ' ') || (*(ptr + 4) == 13) || (*(ptr + 4) == 10))) { station_id[0] = *ptr; station_id[1] = *(ptr + 1); station_id[2] = *(ptr + 2); station_id[3] = *(ptr + 3); *station_id_length = 4; } else { station_id[0] = '\0'; if ((*ptr == 'N') && (((*(ptr + 1) == 'I') && (*(ptr + 2) == 'L')) || (((*(ptr + 1) == 'N') || (*(ptr + 1) == 'n')) && ((*(ptr + 2) == 'N') || (*(ptr + 2) == 'n')) && ((*(ptr + 3) == 'N') || (*(ptr + 3) == 'n'))))) { /* Do not warn if we find NIL or NNNN. */; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown SPECIAL-02 in %s. If this is a correct report, contact maintainer %s (pos=%d)", p_file_name, p_orig_name, AFD_MAINTAINER, rcdb_pos); hex_print(WARN_SIGN, p_start, msg_length); } return(INCORRECT); } break; case RT_SPECIAL_03 : /* SPECIAL-03 */ station_id[0] = '\0'; receive_log(INFO_SIGN, __FILE__, __LINE__, 0L, "%s: SPECIAL-03 in %s still needs to be done!", p_file_name, p_orig_name); hex_print(WARN_SIGN, p_start, msg_length); return(INCORRECT); case RT_SPECIAL_66 : /* SPECIAL-66 */ station_id[0] = '\0'; receive_log(INFO_SIGN, __FILE__, __LINE__, 0L, "%s: SPECIAL-66 in %s still needs to be done!", p_file_name, p_orig_name); hex_print(WARN_SIGN, p_start, msg_length); return(INCORRECT); case RT_SYNOP : /* SYNOP */ /* This check is in case a new heading appears. */ if ((isalnum((int)(*ptr))) && (isalnum((int)(*(ptr + 1)))) && (isalnum((int)(*(ptr + 2)))) && (isalnum((int)(*(ptr + 3)))) && (isalnum((int)(*(ptr + 4)))) && (isalnum((int)(*(ptr + 5)))) && (*(ptr + 6) == ' ') && (isupper((int)(*(ptr + 7)))) && (isupper((int)(*(ptr + 8)))) && (isupper((int)(*(ptr + 9)))) && (isupper((int)(*(ptr + 10)))) && (*(ptr + 11) == ' ') && (isdigit((int)(*(ptr + 12)))) && (isdigit((int)(*(ptr + 13)))) && (isdigit((int)(*(ptr + 14)))) && (isdigit((int)(*(ptr + 15)))) && (isdigit((int)(*(ptr + 16)))) && (isdigit((int)(*(ptr + 17)))) && (*(ptr + 18) == 13) && (*(ptr + 19) == 13) && (*(ptr + 20) == 10)) { int i; /* * FIXME! * In most cases this should work. However if the length * of the filename does differ we have a problem and we * need to handle this! Lets first see how often this happens * in the real world. */ p_file_name[0] = *ptr; p_file_name[1] = *(ptr + 1); p_file_name[2] = *(ptr + 2); p_file_name[3] = *(ptr + 3); p_file_name[4] = *(ptr + 4); p_file_name[5] = *(ptr + 5); p_file_name[6] = '_'; p_file_name[7] = *(ptr + 7); p_file_name[8] = *(ptr + 8); p_file_name[9] = *(ptr + 9); p_file_name[10] = *(ptr + 10); p_file_name[11] = '_'; p_file_name[12] = *(ptr + 12); p_file_name[13] = *(ptr + 13); p_file_name[14] = *(ptr + 14); p_file_name[15] = *(ptr + 15); p_file_name[16] = *(ptr + 16); p_file_name[17] = *(ptr + 17); ptr += 21; if (begin_file_name_offset != -1) { if ((*ptr == 'A') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'X')) { int j; p_file_name[18] = '-'; p_file_name[19] = 'A'; p_file_name[20] = 'A'; p_file_name[21] = 'X'; if (*(ptr + 3) == 'X') { p_file_name[22] = 'X'; i = 23; j = 4; } else { i = 22; j = 3; } if ((*(ptr + j) == ' ') && (isdigit((int)(*(ptr + j + 1)))) && (isdigit((int)(*(ptr + j + 2)))) && (isdigit((int)(*(ptr + j + 3)))) && (isdigit((int)(*(ptr + j + 4)))) && (isdigit((int)(*(ptr + j + 5))))) { p_file_name[i] = '_'; p_file_name[i + 1] = *(ptr + j + 1); p_file_name[i + 2] = *(ptr + j + 2); p_file_name[i + 3] = *(ptr + j + 3); p_file_name[i + 4] = *(ptr + j + 4); p_file_name[i + 5] = *(ptr + j + 5); i += 6; *p_wid = *(ptr + j + 5); *(p_wid + 1) = '\0'; } } else { i = 18; } } else { i = 18; } if ((i + 1) != file_name_offset) { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "File name (%s) will be wrong, we need to fix this! Source file is %s. (%d!=%d)", p_file_name, p_orig_name, i + 1, file_name_offset); hex_print(WARN_SIGN, ptr, msg_length); } } if ((isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && ((*(ptr + 5) == ' ') || (*(ptr + 5) == 13) || (*(ptr + 5) == 10))) { station_id[0] = *ptr; station_id[1] = *(ptr + 1); station_id[2] = *(ptr + 2); station_id[3] = *(ptr + 3); station_id[4] = *(ptr + 4); *station_id_length = 5; } /* Heading apears again. */ else if ((p_file_name[0] == *ptr) && (p_file_name[1] == *(ptr + 1)) && (p_file_name[2] == *(ptr + 2)) && (p_file_name[3] == *(ptr + 3)) && (p_file_name[4] == *(ptr + 4)) && (p_file_name[5] == *(ptr + 5)) && (p_file_name[6] == '_') && (*(ptr + 6) == ' ') && (p_file_name[7] == *(ptr + 7)) && (p_file_name[8] == *(ptr + 8)) && (p_file_name[9] == *(ptr + 9)) && (p_file_name[10] == *(ptr + 10)) && (p_file_name[11] == '_') && (*(ptr + 11) == ' ')) { ptr += 11; while (((ptr - p_start) < msg_length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } while (((ptr - p_start) < msg_length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } if ((*ptr == 'A') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'X')) { char *tmp_ptr = ptr; if (begin_file_name_offset != -1) { int space_count = 0; while (((ptr - p_start) < msg_length) && (*ptr != 13) && (*ptr != 10)) { if (*ptr == ' ') { if (space_count == 0) { p_file_name[begin_file_name_offset] = '_'; space_count++; } else { break; } } else if (*ptr == '/') { p_file_name[begin_file_name_offset] = '?'; } else { p_file_name[begin_file_name_offset] = *ptr; } begin_file_name_offset++; ptr++; } } else { if (*(ptr + 3) == 'X') { ptr += 4; } else { ptr += 3; } while (((ptr - p_start) < msg_length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } } if (isdigit((int)(*(ptr - 1)))) { *p_wid = *(ptr - 1); *(p_wid + 1) = '\0'; } if (offset != NULL) { *p_extra_heading = tmp_ptr; *offset = ptr - *p_extra_heading; if (*ptr == ' ') { *overwrite_extra_heading = *offset; } } } while (((ptr - p_start) < msg_length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } if ((isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && ((*(ptr + 5) == ' ') || (*(ptr + 5) == 13) || (*(ptr + 5) == 10))) { station_id[0] = *ptr; station_id[1] = *(ptr + 1); station_id[2] = *(ptr + 2); station_id[3] = *(ptr + 3); station_id[4] = *(ptr + 4); *station_id_length = 5; } else { station_id[0] = '\0'; if ((*ptr == 'N') && (((*(ptr + 1) == 'I') && (*(ptr + 2) == 'L')) || (((*(ptr + 1) == 'N') || (*(ptr + 1) == 'n')) && ((*(ptr + 2) == 'N') || (*(ptr + 2) == 'n')) && ((*(ptr + 3) == 'N') || (*(ptr + 3) == 'n'))))) { /* Do not warn if we find NIL or NNNN. */; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown SYNOP in %s. If this is a correct report, contact maintainer %s (pos=%d)", p_file_name, p_orig_name, AFD_MAINTAINER, rcdb_pos); hex_print(WARN_SIGN, p_start, msg_length); } return(INCORRECT); } } /* Additional AAXX. */ else if ((*ptr == 'A') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'X') && (*(ptr + 3) == 'X') && (*(ptr + 4) == ' ') && (isdigit((int)(*(ptr + 5)))) && (isdigit((int)(*(ptr + 6)))) && (isdigit((int)(*(ptr + 7)))) && (isdigit((int)(*(ptr + 8)))) && (isdigit((int)(*(ptr + 9)))) && ((*(ptr + 10) == 13) || (*(ptr + 10) == 10) || (*(ptr + 10) == ' '))) { char *tmp_ptr = ptr; if (begin_file_name_offset != -1) { int space_count = 0; while (((ptr - p_start) < msg_length) && (*ptr != 13) && (*ptr != 10)) { if (*ptr == ' ') { if (space_count == 0) { p_file_name[begin_file_name_offset] = '_'; space_count++; } else { break; } } else if (*ptr == '/') { p_file_name[begin_file_name_offset] = '?'; } else { p_file_name[begin_file_name_offset] = *ptr; } begin_file_name_offset++; ptr++; } } else { while (((ptr - p_start) < msg_length) && (*ptr != 13) && (*ptr != 10)) { ptr++; } } if (isdigit((int)(*(ptr - 1)))) { *p_wid = *(ptr - 1); *(p_wid + 1) = '\0'; } while (((ptr - p_start) < msg_length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } if (offset != NULL) { *p_extra_heading = tmp_ptr; *offset = ptr - *p_extra_heading; *overwrite_extra_heading = *offset; } if ((isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && ((*(ptr + 5) == ' ') || (*(ptr + 5) == 13) || (*(ptr + 5) == 10))) { station_id[0] = *ptr; station_id[1] = *(ptr + 1); station_id[2] = *(ptr + 2); station_id[3] = *(ptr + 3); station_id[4] = *(ptr + 4); *station_id_length = 5; } else { station_id[0] = '\0'; if ((*ptr == 'N') && (((*(ptr + 1) == 'I') && (*(ptr + 2) == 'L')) || (((*(ptr + 1) == 'N') || (*(ptr + 1) == 'n')) && ((*(ptr + 2) == 'N') || (*(ptr + 2) == 'n')) && ((*(ptr + 3) == 'N') || (*(ptr + 3) == 'n'))))) { /* Do not warn if we find NIL or NNNN. */; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown SYNOP in %s. If this is a correct report, contact maintainer %s (pos=%d)", p_file_name, p_orig_name, AFD_MAINTAINER, rcdb_pos); hex_print(WARN_SIGN, p_start, msg_length); } return(INCORRECT); } } else { station_id[0] = '\0'; if (((*ptr == 'N') && (((*(ptr + 1) == 'I') && (*(ptr + 2) == 'L')) || (((*(ptr + 1) == 'N') || (*(ptr + 1) == 'n')) && ((*(ptr + 2) == 'N') || (*(ptr + 2) == 'n')) && ((*(ptr + 3) == 'N') || (*(ptr + 3) == 'n'))))) || ((*ptr == '/') && (*(ptr + 1) == '/') && ((*(ptr + 2) == ' ') || (*(ptr + 2) == 'E')))) { /* Do not warn if we find NIL or NNNN or */ /* // END OF ... */; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown SYNOP in %s. If this is a correct report, contact maintainer %s (pos=%d) %c%c%c%c", p_file_name, p_orig_name, AFD_MAINTAINER, rcdb_pos, *ptr, *(ptr+1), *(ptr+2), *(ptr+3)); hex_print(WARN_SIGN, p_start, msg_length); } return(INCORRECT); } break; case RT_SYNOP_SHIP : /* SYNOP-SHIP */ if (rcdb[rcdb_pos].mimj[0] == 'B') { /* First store the ship idendifier (up to 10 characters */ /* starting with characters, numbers + ending with numbers) */ if (isalnum((int)(*ptr))) { int i = 1; station_id[0] = *ptr; ptr++; while ((i < 10) && (isalnum((int)(*ptr)))) { station_id[i] = *ptr; i++; ptr++; } if ((i == 10) && (isalnum((int)(*ptr)))) { station_id[i] = '\0'; receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: SHIP identifier in %s more than 10 characters. Ignoring them.", p_file_name, p_orig_name); while (isalnum((int)(*ptr))) { ptr++; } } while (*ptr == ' ') { ptr++; } /* Now lets try and find the locasion of the ship. */ if ((isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && (*(ptr + 5) == ' ') && (isdigit((int)(*(ptr + 6)))) && (isdigit((int)(*(ptr + 7)))) && (isdigit((int)(*(ptr + 8)))) && (isdigit((int)(*(ptr + 9)))) && (isdigit((int)(*(ptr + 10)))) && (*(ptr + 11) == ' ') && (isdigit((int)(*(ptr + 12)))) && (isdigit((int)(*(ptr + 13)))) && (isdigit((int)(*(ptr + 14)))) && (isdigit((int)(*(ptr + 15)))) && (isdigit((int)(*(ptr + 16)))) && ((*(ptr + 17) == ' ') || (*(ptr + 17) == 13) || (*(ptr + 17) == 10))) { station_id[i] = '_'; station_id[i + 1] = *(ptr + 6); station_id[i + 2] = *(ptr + 7); station_id[i + 3] = *(ptr + 8); station_id[i + 4] = *(ptr + 9); station_id[i + 5] = *(ptr + 10); station_id[i + 6] = '_'; station_id[i + 7] = *(ptr + 12); station_id[i + 8] = *(ptr + 13); station_id[i + 9] = *(ptr + 14); station_id[i + 10] = *(ptr + 15); station_id[i + 11] = *(ptr + 16); *station_id_length = i + 12; } else { *station_id_length = i; station_id[i] = '\0'; receive_log(INFO_SIGN, __FILE__, __LINE__, 0L, "%s: Unable to find location of SHIP in %s, ignoring location.", p_file_name, p_orig_name); hex_print(INFO_SIGN, p_start, msg_length); } } else { station_id[0] = '\0'; if ((*ptr == 'N') && (((*(ptr + 1) == 'I') && (*(ptr + 2) == 'L')) || (((*(ptr + 1) == 'N') || (*(ptr + 1) == 'n')) && ((*(ptr + 2) == 'N') || (*(ptr + 2) == 'n')) && ((*(ptr + 3) == 'N') || (*(ptr + 3) == 'n'))))) { /* Do not warn if we find NIL or NNNN. */; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown SYNOP-SHIP in %s. If this is a correct report, contact maintainer %s (pos=%d)", p_file_name, p_orig_name, AFD_MAINTAINER, rcdb_pos); hex_print(WARN_SIGN, p_start, msg_length); } return(INCORRECT); } } else if (rcdb[rcdb_pos].mimj[0] == 'A') { if ((isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && ((*(ptr + 5) == ' ') || (*(ptr + 5) == 13) || (*(ptr + 5) == 10))) { station_id[0] = *ptr; station_id[1] = *(ptr + 1); station_id[2] = *(ptr + 2); station_id[3] = *(ptr + 3); station_id[4] = *(ptr + 4); *station_id_length = 5; } else { station_id[0] = '\0'; if ((*ptr == 'N') && (((*(ptr + 1) == 'I') && (*(ptr + 2) == 'L')) || (((*(ptr + 1) == 'N') || (*(ptr + 1) == 'n')) && ((*(ptr + 2) == 'N') || (*(ptr + 2) == 'n')) && ((*(ptr + 3) == 'N') || (*(ptr + 3) == 'n'))))) { /* Do not warn if we find NIL or NNNN. */; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown SYNOP in %s. If this is a correct report, contact maintainer %s (pos=%d)", p_file_name, p_orig_name, AFD_MAINTAINER, rcdb_pos); hex_print(WARN_SIGN, p_start, msg_length); } return(INCORRECT); } } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: MIMJ needs still to be done for this. (%s %d)", p_file_name, p_orig_name, rcdb_pos); } break; case RT_SYNOP_MOBIL : /* SYNOP-MOBIL */ if (rcdb[rcdb_pos].mimj[0] == 'O') { /* First store the mobil idendifier (up to 10 characters */ /* starting with characters, numbers + ending with numbers) */ if (isalnum((int)(*ptr))) { int i = 1; station_id[0] = *ptr; ptr++; while ((i < 10) && (isalnum((int)(*ptr)))) { station_id[i] = *ptr; i++; ptr++; } if ((i == 10) && (isalnum((int)(*ptr)))) { station_id[i] = '\0'; receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: MOBIL identifier in %s more than 10 characters. Ignoring them.", p_file_name, p_orig_name); while (isalnum((int)(*ptr))) { ptr++; } } while (*ptr == ' ') { ptr++; } /* Ignore date string. */ while (isdigit((int)(*ptr))) { ptr++; } *p_wid = *(ptr - 1); *(p_wid + 1) = '\0'; while (*ptr == ' ') { ptr++; } /* Now lets try and find the location of the mobile. */ if ((isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && (*(ptr + 5) == ' ') && (isdigit((int)(*(ptr + 6)))) && (isdigit((int)(*(ptr + 7)))) && (isdigit((int)(*(ptr + 8)))) && (isdigit((int)(*(ptr + 9)))) && (isdigit((int)(*(ptr + 10)))) && (*(ptr + 11) == ' ') && ((*(ptr + 12) == '/') || (isdigit((int)(*(ptr + 12))))) && ((*(ptr + 13) == '/') || (isdigit((int)(*(ptr + 13))))) && ((*(ptr + 14) == '/') || (isdigit((int)(*(ptr + 14))))) && ((*(ptr + 15) == '/') || (isdigit((int)(*(ptr + 15))))) && ((*(ptr + 16) == '/') || (isdigit((int)(*(ptr + 16))))) && ((*(ptr + 17) == ' ') || (*(ptr + 17) == 13) || (*(ptr + 17) == 10))) { station_id[i] = '_'; station_id[i + 1] = *(ptr + 6); station_id[i + 2] = *(ptr + 7); station_id[i + 3] = *(ptr + 8); station_id[i + 4] = *(ptr + 9); station_id[i + 5] = *(ptr + 10); station_id[i + 6] = '_'; if (*(ptr + 12) == '/') { station_id[i + 7] = '_'; } else { station_id[i + 7] = *(ptr + 12); } if (*(ptr + 13) == '/') { station_id[i + 8] = '_'; } else { station_id[i + 8] = *(ptr + 13); } if (*(ptr + 14) == '/') { station_id[i + 9] = '_'; } else { station_id[i + 9] = *(ptr + 14); } if (*(ptr + 15) == '/') { station_id[i + 10] = '_'; } else { station_id[i + 10] = *(ptr + 15); } if (*(ptr + 16) == '/') { station_id[i + 11] = '_'; } else { station_id[i + 11] = *(ptr + 16); } *station_id_length = i + 12; } else { *station_id_length = i; station_id[i] = '\0'; receive_log(INFO_SIGN, __FILE__, __LINE__, 0L, "%s: Unable to find location of MOBIL in %s, ignoring location.", p_file_name, p_orig_name); hex_print(INFO_SIGN, p_start, msg_length); } } } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: MIMJ needs still to be done for this. (%s %d)", p_file_name, p_orig_name, rcdb_pos); } break; case RT_UPPER_AIR : /* UPPER-AIR */ if ((isalnum((int)(*ptr))) && (isalnum((int)(*(ptr + 1)))) && (isalnum((int)(*(ptr + 2)))) && (isalnum((int)(*(ptr + 3)))) && (isalnum((int)(*(ptr + 4)))) && (isalnum((int)(*(ptr + 5)))) && (*(ptr + 6) == ' ') && (isupper((int)(*(ptr + 7)))) && (isupper((int)(*(ptr + 8)))) && (isupper((int)(*(ptr + 9)))) && (isupper((int)(*(ptr + 10)))) && (*(ptr + 11) == ' ') && (isdigit((int)(*(ptr + 12)))) && (isdigit((int)(*(ptr + 13)))) && (isdigit((int)(*(ptr + 14)))) && (isdigit((int)(*(ptr + 15)))) && (isdigit((int)(*(ptr + 16)))) && (isdigit((int)(*(ptr + 17)))) && (*(ptr + 18) == 13) && (*(ptr + 19) == 13) && (*(ptr + 20) == 10)) { int i = 0; /* * FIXME! * In most cases this should work. However if the length * of the filename does differ we have a problem and we * need to handle this! Lets first see how often this happens * in the real world. */ while (((ptr - p_start) < msg_length) && (*ptr > 31) && (i < MAX_WMO_HEADER_LENGTH)) { if ((*ptr == ' ') || (*ptr == '/') || (*ptr < ' ') || (*ptr > 'z')) { p_file_name[i] = '_'; } else { p_file_name[i] = *ptr; } ptr++; i++; } while (((ptr - p_start) < msg_length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } if ((i + 1) != file_name_offset) { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "File name (%s) will be wrong, we need to fix this! Source file is %s. (%d!=%d)", p_file_name, p_orig_name, i + 1, file_name_offset); hex_print(WARN_SIGN, ptr, msg_length); } } if ((isalpha((int)(*ptr))) && (isalpha((int)(*(ptr + 1)))) && (isalpha((int)(*(ptr + 2)))) && (isalpha((int)(*(ptr + 3)))) && (*(ptr + 4) == ' ') && ((isdigit((int)(*(ptr + 5)))) || (*(ptr + 5) == '/')) && ((isdigit((int)(*(ptr + 6)))) || (*(ptr + 6) == '/')) && ((isdigit((int)(*(ptr + 7)))) || (*(ptr + 7) == '/')) && ((isdigit((int)(*(ptr + 8)))) || (*(ptr + 8) == '/')) && ((isdigit((int)(*(ptr + 9)))) || (*(ptr + 9) == '/')) && (*(ptr + 10) == ' ') && ((*(ptr + 11) == ' ') || (isdigit((int)(*(ptr + 11))))) && (isdigit((int)(*(ptr + 12)))) && (isdigit((int)(*(ptr + 13)))) && (isdigit((int)(*(ptr + 14)))) && (isdigit((int)(*(ptr + 15)))) && ((*(ptr + 16) == ' ') || (*(ptr + 16) == 13) || ((*(ptr + 11) == ' ') && (isdigit((int)(*(ptr + 16)))) && ((*(ptr + 17) == ' ') || (*(ptr + 17) == 13))))) { station_id[0] = *(ptr + 11); station_id[1] = *(ptr + 12); station_id[2] = *(ptr + 13); station_id[3] = *(ptr + 14); station_id[4] = *(ptr + 15); *station_id_length = 5; } else if ((isalpha((int)(*ptr))) && (isalpha((int)(*(ptr + 1)))) && (isalpha((int)(*(ptr + 2)))) && (isalpha((int)(*(ptr + 3)))) && (*(ptr + 4) == ' ') && (*(ptr + 5) == ' ') && ((isdigit((int)(*(ptr + 6)))) || (*(ptr + 6) == '/')) && ((isdigit((int)(*(ptr + 7)))) || (*(ptr + 7) == '/')) && ((isdigit((int)(*(ptr + 8)))) || (*(ptr + 8) == '/')) && ((isdigit((int)(*(ptr + 9)))) || (*(ptr + 9) == '/')) && ((isdigit((int)(*(ptr + 10)))) || (*(ptr + 10) == '/')) && (*(ptr + 11) == ' ') && (isdigit((int)(*(ptr + 12)))) && (isdigit((int)(*(ptr + 13)))) && (isdigit((int)(*(ptr + 14)))) && (isdigit((int)(*(ptr + 15)))) && (isdigit((int)(*(ptr + 16)))) && ((*(ptr + 17) == ' ') || (*(ptr + 17) == 13))) { station_id[0] = *(ptr + 12); station_id[1] = *(ptr + 13); station_id[2] = *(ptr + 14); station_id[3] = *(ptr + 15); station_id[4] = *(ptr + 16); *station_id_length = 5; } else if ((isalpha((int)(*ptr))) && (isalpha((int)(*(ptr + 1)))) && (isalpha((int)(*(ptr + 2)))) && (isalpha((int)(*(ptr + 3)))) && (*(ptr + 4) == ' ') && (*(ptr + 5) == ' ') && ((isdigit((int)(*(ptr + 6)))) || (*(ptr + 6) == '/')) && ((isdigit((int)(*(ptr + 7)))) || (*(ptr + 7) == '/')) && ((isdigit((int)(*(ptr + 8)))) || (*(ptr + 8) == '/')) && ((isdigit((int)(*(ptr + 9)))) || (*(ptr + 9) == '/')) && ((isdigit((int)(*(ptr + 10)))) || (*(ptr + 10) == '/')) && (*(ptr + 11) == ' ') && (*(ptr + 12) == ' ') && (isdigit((int)(*(ptr + 13)))) && (isdigit((int)(*(ptr + 14)))) && (isdigit((int)(*(ptr + 15)))) && (isdigit((int)(*(ptr + 16)))) && (isdigit((int)(*(ptr + 17)))) && ((*(ptr + 18) == ' ') || (*(ptr + 18) == 13))) { station_id[0] = *(ptr + 13); station_id[1] = *(ptr + 14); station_id[2] = *(ptr + 15); station_id[3] = *(ptr + 16); station_id[4] = *(ptr + 17); *station_id_length = 5; } else if ((isalpha((int)(*ptr))) && (isalpha((int)(*(ptr + 1)))) && (isalpha((int)(*(ptr + 2)))) && (isalpha((int)(*(ptr + 3)))) && (*(ptr + 4) == ' ') && (*(ptr + 5) == ' ') && (*(ptr + 6) == ' ') && ((isdigit((int)(*(ptr + 7)))) || (*(ptr + 7) == '/')) && ((isdigit((int)(*(ptr + 8)))) || (*(ptr + 8) == '/')) && ((isdigit((int)(*(ptr + 9)))) || (*(ptr + 9) == '/')) && ((isdigit((int)(*(ptr + 10)))) || (*(ptr + 10) == '/')) && ((isdigit((int)(*(ptr + 11)))) || (*(ptr + 11) == '/')) && (*(ptr + 12) == ' ') && (isdigit((int)(*(ptr + 13)))) && (isdigit((int)(*(ptr + 14)))) && (isdigit((int)(*(ptr + 15)))) && (isdigit((int)(*(ptr + 16)))) && (isdigit((int)(*(ptr + 17)))) && ((*(ptr + 18) == ' ') || (*(ptr + 18) == 13))) { station_id[0] = *(ptr + 13); station_id[1] = *(ptr + 14); station_id[2] = *(ptr + 15); station_id[3] = *(ptr + 16); station_id[4] = *(ptr + 17); *station_id_length = 5; } else if ((isdigit((int)(*ptr))) && (isdigit((int)(*(ptr + 1)))) && (isdigit((int)(*(ptr + 2)))) && (isdigit((int)(*(ptr + 3)))) && (isdigit((int)(*(ptr + 4)))) && (*(ptr + 5) == ' ') && (*(ptr + 6) == 'N') && (*(ptr + 7) == 'I') && (*(ptr + 8) == 'L')) { station_id[0] = *ptr; station_id[1] = *(ptr + 1); station_id[2] = *(ptr + 2); station_id[3] = *(ptr + 3); station_id[4] = *(ptr + 4); *station_id_length = 5; } else { station_id[0] = '\0'; if ((*ptr == 'N') && (((*(ptr + 1) == 'I') && (*(ptr + 2) == 'L')) || (((*(ptr + 1) == 'N') || (*(ptr + 1) == 'n')) && ((*(ptr + 2) == 'N') || (*(ptr + 2) == 'n')) && ((*(ptr + 3) == 'N') || (*(ptr + 3) == 'n'))))) { /* Do not warn if we find NIL or NNNN. */; } else { receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown UPPER-AIR in %s. If this is a correct report, contact maintainer %s (pos=%d)", p_file_name, p_orig_name, AFD_MAINTAINER, rcdb_pos); hex_print(WARN_SIGN, p_start, msg_length); } return(INCORRECT); } break; default : /* Unknown report type */ station_id[0] = '\0'; receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, "%s: Unknown report type %d (pos=%d) for %s, unable to extract reports.", p_file_name, rcdb[rcdb_pos].rt, rcdb_pos, p_orig_name); hex_print(WARN_SIGN, p_start, msg_length); return(INCORRECT); } return(SUCCESS); } /*---------------------------- check_report() ---------------------------*/ static int check_report(char *ptr, unsigned int length, int *offset) { int xxtype = NO; char *p_start = ptr; /* Ignore any spaces at start. */ while (((ptr - p_start) < length) && (*ptr == ' ')) { ptr++; } /* * Lets first check if this is a SYNOP, SPECI, TAF, 'TAF AMD', AAXX, * BBXX which all have an extra line. */ if (((ptr + 11 - p_start) < length) && (isupper((int)(*ptr))) && (isupper((int)(*(ptr + 1)))) && (isupper((int)(*(ptr + 2)))) && (isupper((int)(*(ptr + 3)))) && (*(ptr + 4) == ' ') && (isdigit((int)(*(ptr + 5)))) && (isdigit((int)(*(ptr + 6)))) && (isdigit((int)(*(ptr + 7)))) && (isdigit((int)(*(ptr + 8)))) && (isdigit((int)(*(ptr + 9)))) && ((*(ptr + 10) == 13) || (*(ptr + 10) == 10))) { ptr += 11; while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } *offset = ptr - p_start; } /* SPECI, METAR */ else if (((ptr + 6 - p_start) < length) && ((*(ptr + 5) == 13) || (*(ptr + 5) == 10)) && (((*ptr == 'S') && (*(ptr + 1) == 'P') && (*(ptr + 2) == 'E') && (*(ptr + 3) == 'C') && (*(ptr + 4) == 'I')) || ((*ptr == 'M') && (*(ptr + 1) == 'E') && (*(ptr + 2) == 'T') && (*(ptr + 3) == 'A') && (*(ptr + 4) == 'R')))) { ptr += 6; while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } *offset = ptr - p_start; } /* METAR YYGGggZ */ else if (((ptr + 14 - p_start) < length) && (*ptr == 'M') && (*(ptr + 1) == 'E') && (*(ptr + 2) == 'T') && (*(ptr + 3) == 'A') && (*(ptr + 4) == 'R') && (*(ptr + 5) == ' ') && (isdigit((int)(*(ptr + 6)))) && (isdigit((int)(*(ptr + 7)))) && (isdigit((int)(*(ptr + 8)))) && (isdigit((int)(*(ptr + 9)))) && (isdigit((int)(*(ptr + 10)))) && (isdigit((int)(*(ptr + 11)))) && (*(ptr + 12) == 'Z') && ((*(ptr + 13) == 13) || (*(ptr + 13) == 10))) { ptr += 14; while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } *offset = ptr - p_start; } /* METAR COR */ else if (((ptr + 10 - p_start) < length) && (*ptr == 'M') && (*(ptr + 1) == 'E') && (*(ptr + 2) == 'T') && (*(ptr + 3) == 'A') && (*(ptr + 4) == 'R') && (*(ptr + 5) == ' ') && (*(ptr + 6) == 'C') && (*(ptr + 7) == 'O') && (*(ptr + 8) == 'R') && ((*(ptr + 9) == 13) || (*(ptr + 9) == 10))) { ptr += 10; while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } *offset = ptr - p_start; } /* SWIS */ else if (((ptr + 13 - p_start) < length) && (*ptr == 'S') && (*(ptr + 1) == 'W') && (*(ptr + 2) == 'I') && (*(ptr + 3) == 'S') && (*(ptr + 4) == ' ') && (isdigit((int)(*(ptr + 5)))) && (isdigit((int)(*(ptr + 6)))) && (isdigit((int)(*(ptr + 7)))) && (isdigit((int)(*(ptr + 8)))) && (isdigit((int)(*(ptr + 9)))) && (isdigit((int)(*(ptr + 10)))) && (isdigit((int)(*(ptr + 11)))) && ((*(ptr + 12) == 13) || (*(ptr + 12) == 10))) { ptr += 13; while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } *offset = ptr - p_start; } /* CLIMAT */ else if (((ptr + 13 - p_start) < length) && (*ptr == 'C') && (*(ptr + 1) == 'L') && (*(ptr + 2) == 'I') && (*(ptr + 3) == 'M') && (*(ptr + 4) == 'A') && (*(ptr + 5) == 'T') && (*(ptr + 6) == ' ') && (isdigit((int)(*(ptr + 7)))) && (isdigit((int)(*(ptr + 8)))) && (isdigit((int)(*(ptr + 9)))) && (isdigit((int)(*(ptr + 10)))) && (isdigit((int)(*(ptr + 11)))) && ((*(ptr + 12) == 13) || (*(ptr + 12) == 10))) { ptr += 13; while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } *offset = ptr - p_start; } /* AUTOTREND */ else if (((ptr + 10 - p_start) < length) && (*ptr == 'A') && (*(ptr + 1) == 'U') && (*(ptr + 2) == 'T') && (*(ptr + 3) == 'O') && (*(ptr + 4) == 'T') && (*(ptr + 5) == 'R') && (*(ptr + 6) == 'E') && (*(ptr + 7) == 'N') && (*(ptr + 8) == 'D') && ((*(ptr + 9) == 13) || (*(ptr + 9) == 10))) { ptr += 10; while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } *offset = ptr - p_start; } /* AAXX or BBXX */ else if (((ptr + 6 - p_start) < length) && (((*ptr == 'A') && (*(ptr + 1) == 'A')) || ((*ptr == 'B') && (*(ptr + 1) == 'B'))) && (*(ptr + 2) == 'X') && (*(ptr + 3) == 'X') && ((*(ptr + 4) == 13) || (*(ptr + 4) == 10))) { ptr += 5; while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } xxtype = YES; *offset = ptr - p_start; } /* TAF */ else if (((ptr + 4 - p_start) < length) && (*ptr == 'T') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'F') && ((*(ptr + 3) == 13) || (*(ptr + 3) == 10))) { ptr += 4; while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } *offset = ptr - p_start; } /* TAF AMD or COR */ else if (((ptr + 8 - p_start) < length) && (*ptr == 'T') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'F') && (*(ptr + 3) == ' ') && (((*(ptr + 4) == 'A') && (*(ptr + 5) == 'M') && (*(ptr + 6) == 'D')) || ((*(ptr + 4) == 'C') && (*(ptr + 5) == 'O') && (*(ptr + 6) == 'R'))) && ((*(ptr + 7) == 13) || (*(ptr + 7) == 10))) { ptr += 8; while (((ptr - p_start) < length) && ((*ptr == 13) || (*ptr == 10) || (*ptr == ' '))) { ptr++; } *offset = ptr - p_start; } /* Identify german TEXT as bulletins. */ else if (((ptr + 5 - p_start) < length) && (*ptr == 'T') && (*(ptr + 1) == 'E') && (*(ptr + 2) == 'X') && (*(ptr + 3) == 'T') && (*(ptr + 4) == ' ')) { return(INCORRECT); } /* GAFOR */ else if (((ptr + 6 - p_start) < length) && (*ptr == 'G') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'F') && (*(ptr + 3) == 'O') && (*(ptr + 4) == 'R') && (*(ptr + 5) == ' ')) { return(INCORRECT); } else { *offset = 0; } /* Ignore any spaces at start. */ while (((ptr - p_start) < length) && (*ptr == ' ')) { ptr++; } /* TAF */ if (((ptr + 9 - p_start) < length) && (*ptr == 'T') && (*(ptr + 1) == 'A') && (*(ptr + 2) == 'F') && (*(ptr + 3) == ' ') && (*(ptr + 8) == ' ') && (isupper((int)(*(ptr + 4)))) && (isupper((int)(*(ptr + 5)))) && (isupper((int)(*(ptr + 6)))) && (isupper((int)(*(ptr + 7))))) { return(SUCCESS); } /* TAF AMD or COR */ else if (((ptr + 13 - p_start) < length) && (isupper((int)(*ptr))) && (isupper((int)(*(ptr + 1)))) && (isupper((int)(*(ptr + 2)))) && (*(ptr + 3) == ' ') && (isupper((int)(*(ptr + 4)))) && (isupper((int)(*(ptr + 5)))) && (isupper((int)(*(ptr + 6)))) && (*(ptr + 7) == ' ') && (isupper((int)(*(ptr + 8)))) && (isupper((int)(*(ptr + 9)))) && (isupper((int)(*(ptr + 10)))) && (isupper((int)(*(ptr + 11)))) && (*(ptr + 12) == ' ')) { return(SUCCESS); } /* METAR or SPECI */ else if (((ptr + 6 - p_start) < length) && (((*ptr == 'M') && (*(ptr + 1) == 'E') && (*(ptr + 2) == 'T') && (*(ptr + 3) == 'A') && (*(ptr + 4) == 'R')) || ((*ptr == 'S') && (*(ptr + 1) == 'P') && (*(ptr + 2) == 'E') && (*(ptr + 3) == 'C') && (*(ptr + 4) == 'I'))) && (*(ptr + 5) == ' ')) { while (((ptr + 6 - p_start) < length) && (*(ptr + 6) == ' ')) { ptr++; } if (((ptr + 4 - p_start) < length) && (*(ptr + 6) == 'C') && (*(ptr + 7) == 'O') && (*(ptr + 8) == 'R') && (*(ptr + 9) == ' ')) { ptr += 4; } if (((ptr + 5 - p_start) < length) && ((isupper((int)(*(ptr + 6)))) || (isdigit((int)(*(ptr + 6))))) && ((isupper((int)(*(ptr + 7)))) || (isdigit((int)(*(ptr + 7))))) && ((isupper((int)(*(ptr + 8)))) || (isdigit((int)(*(ptr + 8))))) && ((isupper((int)(*(ptr + 9)))) || (isdigit((int)(*(ptr + 9))))) && (*(ptr + 10) == ' ')) { return(SUCCESS); } else if (((ptr + 6 - p_start) < length) && ((isupper((int)(*(ptr + 6)))) || (isdigit((int)(*(ptr + 6))))) && ((isupper((int)(*(ptr + 7)))) || (isdigit((int)(*(ptr + 7))))) && ((isupper((int)(*(ptr + 8)))) || (isdigit((int)(*(ptr + 8))))) && ((isupper((int)(*(ptr + 9)))) || (isdigit((int)(*(ptr + 9))))) && ((isupper((int)(*(ptr + 10)))) || (isdigit((int)(*(ptr + 10))))) && (*(ptr + 11) == ' ')) { return(SUCCESS); } } /* METAR, SPECI, TAF AMD, AAXX or BBXX (in a group) */ else if (((ptr + 5 - p_start) < length) && ((isupper((int)(*ptr))) || (isdigit((int)(*ptr)))) && ((isupper((int)(*(ptr + 1)))) || (isdigit((int)(*(ptr + 1))))) && ((isupper((int)(*(ptr + 2)))) || (isdigit((int)(*(ptr + 2))))) && ((isupper((int)(*(ptr + 3)))) || (isdigit((int)(*(ptr + 3))))) && (*(ptr + 4) == ' ')) { return(SUCCESS); } /* AAXX or BBXX (in a group) */ else if ((xxtype == YES) && ((ptr + 7 - p_start) < length) && ((isupper((int)(*ptr))) || (isdigit((int)(*ptr)))) && ((isupper((int)(*(ptr + 1)))) || (isdigit((int)(*(ptr + 1))))) && ((isupper((int)(*(ptr + 2)))) || (isdigit((int)(*(ptr + 2))))) && ((isupper((int)(*(ptr + 3)))) || (isdigit((int)(*(ptr + 3))))) && ((isupper((int)(*(ptr + 4)))) || (isdigit((int)(*(ptr + 4))))) && ((isupper((int)(*(ptr + 5)))) || (isdigit((int)(*(ptr + 5))))) && (*(ptr + 6) == ' ')) { return(SUCCESS); } /* AAXX or BBXX (in a group) */ else if ((xxtype == YES) && ((ptr + 8 - p_start) < length) && ((isupper((int)(*ptr))) || (isdigit((int)(*ptr)))) && ((isupper((int)(*(ptr + 1)))) || (isdigit((int)(*(ptr + 1))))) && ((isupper((int)(*(ptr + 2)))) || (isdigit((int)(*(ptr + 2))))) && ((isupper((int)(*(ptr + 3)))) || (isdigit((int)(*(ptr + 3))))) && ((isupper((int)(*(ptr + 4)))) || (isdigit((int)(*(ptr + 4))))) && ((isupper((int)(*(ptr + 5)))) || (isdigit((int)(*(ptr + 5))))) && ((isupper((int)(*(ptr + 6)))) || (isdigit((int)(*(ptr + 6))))) && (*(ptr + 7) == ' ')) { return(SUCCESS); } /* SYNOP, AAXX or BBXX (in a group) */ else if (((ptr + 6 - p_start) < length) && ((isupper((int)(*ptr))) || (isdigit((int)(*ptr)))) && ((isupper((int)(*(ptr + 1)))) || (isdigit((int)(*(ptr + 1))))) && ((isupper((int)(*(ptr + 2)))) || (isdigit((int)(*(ptr + 2))))) && ((isupper((int)(*(ptr + 3)))) || (isdigit((int)(*(ptr + 3))))) && ((isupper((int)(*(ptr + 4)))) || (isdigit((int)(*(ptr + 4))))) && (*(ptr + 5) == ' ')) { return(SUCCESS); } /* German METAR */ else if (((ptr + 13 - p_start) < length) && (isupper((int)(*ptr))) && (isupper((int)(*(ptr + 1)))) && (isupper((int)(*(ptr + 2)))) && (isupper((int)(*(ptr + 3)))) && (*(ptr + 4) == ' ') && (isdigit((int)(*(ptr + 5)))) && (isdigit((int)(*(ptr + 6)))) && (isdigit((int)(*(ptr + 7)))) && (isdigit((int)(*(ptr + 8)))) && (isdigit((int)(*(ptr + 9)))) && (isdigit((int)(*(ptr + 10)))) && (*(ptr + 11) == 'Z') && (*(ptr + 12) == ' ')) { return(SUCCESS); } return(INCORRECT); } /*------------------------- show_unknown_report() -----------------------*/ static void show_unknown_report(char *ptr, int length, char *msg, char *file, int line) { int i = 0; char unknown_report[MAX_REPORT_LINE_LENGTH + 1]; while (((ptr - msg) < length) && (i < MAX_REPORT_LINE_LENGTH) && (*ptr >= ' ') && (*ptr <= 126)) { unknown_report[i] = *ptr; i++; ptr++; } if (i == 0) { while (((ptr - msg) < length) && (*ptr != 10) && (i < MAX_REPORT_LINE_LENGTH)) { if ((*ptr >= ' ') && (*ptr <= 126)) { unknown_report[i] = *ptr; i++; ptr++; } else { i += snprintf(&unknown_report[i], MAX_REPORT_LINE_LENGTH - i, "<%d>", (int)*ptr); ptr++; } } if ((*ptr == 10) && ((i + 4) < MAX_REPORT_LINE_LENGTH)) { unknown_report[i] = '<'; unknown_report[i + 1] = '1'; unknown_report[i + 2] = '0'; unknown_report[i + 3] = '>'; unknown_report[i + 4] = '\0'; } } else { if ((*ptr == 13) && ((i + 4) < MAX_REPORT_LINE_LENGTH) && ((ptr - msg) < length)) { unknown_report[i] = '<'; unknown_report[i + 1] = '1'; unknown_report[i + 2] = '3'; unknown_report[i + 3] = '>'; unknown_report[i + 4] = '\0'; i += 4; ptr++; } if ((*ptr == 13) && ((i + 4) < MAX_REPORT_LINE_LENGTH) && ((ptr - msg) < length)) { unknown_report[i] = '<'; unknown_report[i + 1] = '1'; unknown_report[i + 2] = '3'; unknown_report[i + 3] = '>'; unknown_report[i + 4] = '\0'; i += 4; ptr++; } if ((*ptr == 10) && ((i + 4) < MAX_REPORT_LINE_LENGTH) && ((ptr - msg) < length)) { unknown_report[i] = '<'; unknown_report[i + 1] = '1'; unknown_report[i + 2] = '0'; unknown_report[i + 3] = '>'; unknown_report[i + 4] = '\0'; i += 4; ptr++; } } unknown_report[i] = '\0'; receive_log(DEBUG_SIGN, file, line, 0L, _("Unknown report type `%s' in %s"), unknown_report, p_orig_name); return; } #define ASCII_OFFSET 54 #define DIR_ALIAS_OFFSET 16 /*++++++++++++++++++++++++++++ hex_print() ++++++++++++++++++++++++++++++*/ static void hex_print(char *sign, char *buffer, int buffer_length) { int ascii_offset, header_length = DIR_ALIAS_OFFSET, i, line_length = 0, offset, wpos; char *hex = "0123456789ABCDEF", *ptr = p_fra->dir_alias, wbuf[MAX_LINE_LENGTH + MAX_LINE_LENGTH + 1]; time_t current_time; struct tm *p_ts; current_time = time(NULL); p_ts = localtime(¤t_time); wbuf[0] = (p_ts->tm_mday / 10) + '0'; wbuf[1] = (p_ts->tm_mday % 10) + '0'; wbuf[2] = ' '; wbuf[3] = (p_ts->tm_hour / 10) + '0'; wbuf[4] = (p_ts->tm_hour % 10) + '0'; wbuf[5] = ':'; wbuf[6] = (p_ts->tm_min / 10) + '0'; wbuf[7] = (p_ts->tm_min % 10) + '0'; wbuf[8] = ':'; wbuf[9] = (p_ts->tm_sec / 10) + '0'; wbuf[10] = (p_ts->tm_sec % 10) + '0'; wbuf[11] = ' '; wbuf[12] = sign[0]; if (((sign[1] == 'E') || (sign[1] == 'W')) && ((p_fra->dir_flag & DIR_ERROR_OFFLINE) || (p_fra->dir_flag & DIR_ERROR_OFFL_T))) { wbuf[13] = 'O'; } else { wbuf[13] = sign[1]; } wbuf[14] = sign[2]; wbuf[15] = ' '; while ((header_length < (MAX_LINE_LENGTH + MAX_LINE_LENGTH)) && (*ptr != '\0')) { wbuf[header_length] = *ptr; ptr++; header_length++; } while ((header_length - DIR_ALIAS_OFFSET) < MAX_DIR_ALIAS_LENGTH) { wbuf[header_length] = ' '; header_length++; } wbuf[header_length] = ':'; wbuf[header_length + 1] = ' '; header_length += 2; ascii_offset = header_length + ASCII_OFFSET, wpos = header_length; for (i = 0; i < buffer_length; i++) { if ((i % 16) == 0) { if (line_length > 0) { offset = ascii_offset + line_length; wbuf[ascii_offset - 1] = ' '; wbuf[offset] = '\n'; if (write(receive_log_fd, wbuf, (offset + 1)) != (offset + 1)) { system_log(ERROR_SIGN, __FILE__, __LINE__, "write() error : %s", strerror(errno)); } wpos = header_length; line_length = 0; } } else { if ((i % 4) == 0) { wbuf[wpos] = '|'; wbuf[wpos + 1] = ' '; wpos += 2; } } if ((unsigned char)buffer[i] > 15) { wbuf[wpos] = hex[((unsigned char)buffer[i]) >> 4]; wbuf[wpos + 1] = hex[((unsigned char)buffer[i]) & 0x0F]; } else { wbuf[wpos] = '0'; wbuf[wpos + 1] = hex[(unsigned char)buffer[i]]; } wbuf[wpos + 2] = ' '; wpos += 3; if (((unsigned char)buffer[i] < 32) || ((unsigned char)buffer[i] > 126)) { wbuf[ascii_offset + line_length] = '.'; } else { wbuf[ascii_offset + line_length] = buffer[i]; } line_length++; } if (line_length > 0) { for (i = line_length; i < 16; i++) { if ((i % 4) == 0) { wbuf[wpos] = '|'; wbuf[wpos + 1] = ' '; wpos += 2; } wbuf[wpos] = ' '; wbuf[wpos + 1] = ' '; wbuf[wpos + 2] = ' '; wpos += 3; } offset = ascii_offset + line_length; wbuf[ascii_offset - 1] = ' '; wbuf[offset] = '\n'; if (write(receive_log_fd, wbuf, (offset + 1)) != (offset + 1)) { system_log(ERROR_SIGN, __FILE__, __LINE__, "write() error : %s", strerror(errno)); } } return; }