#define _LARGEFILE64_SOURCE /* required for GLIBC to enable stat64 and friends */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mt.h" #include "mem.h" #include "error.h" #include "utils.h" #include "exec.h" #include "globals.h" int cv_offsets_compare(const void *a, const void *b) { cv_off *pa = (cv_off *)a, *pb = (cv_off *)b; if (pa -> start > pb -> start) return -1; else if (pa -> start == pb -> start) { if (pa -> end > pb -> end) return -1; } return 0; } char * epoch_to_str(time_t epoch) { char *new_string; struct tm *ptm = localtime(&epoch); if (!ptm) return NULL; new_string = mymalloc(4096, __FILE__, __PRETTY_FUNCTION__, __LINE__); if (!strftime(new_string, 4096, cnv_ts_format, ptm)) error_exit(__FILE__, __PRETTY_FUNCTION__, __LINE__, "An error occured whilte converting timestamp format '%s'.\n", cnv_ts_format); return new_string; } char *do_convert(char *what, int what_len, int type, script *pscript) { switch(type) { case CONVTYPE_SIGNRTOSTRING: { int signr = atoi(what); if (signr > n_known_sigs || signr < 1) return mystrdup("unknown signal", __FILE__, __PRETTY_FUNCTION__, __LINE__); return mystrdup(sigs[signr], __FILE__, __PRETTY_FUNCTION__, __LINE__); } case CONVTYPE_TAI64NTODATE: { long long int v2_62 = (long long int)1 << (long long int)62; long long int val = 0; int loop; if (what[0] == '@') what++; /* http://cr.yp.to/libtai/tai64.html#tai64n */ /* convert to 64 bit integer */ for(loop=0; loop<(8 * 2); loop++) { int c = tolower(what[loop]); val <<= (long long int)4; if (c >= 'a') val += 10 + c - 'a'; else val += c - '0'; } if (val >= v2_62) /* FIXME: 2^63 are reserved, not checking for that, sorry */ { char *new_str = epoch_to_str((time_t)(val - v2_62)); if (new_str) return new_str; else return mystrdup("cannot convert current 'TAI64N'-date to string", __FILE__, __PRETTY_FUNCTION__, __LINE__); } else { /* before 1970/1/1 now what should I do with that? */ return mystrdup("cannot convert 'TAI64N'-dates before the epoch", __FILE__, __PRETTY_FUNCTION__, __LINE__); } } case CONVTYPE_IP4TOHOST: { struct hostent *ht; in_addr_t addr = inet_addr(what); if ((int)addr == -1) return mystrdup(what, __FILE__, __PRETTY_FUNCTION__, __LINE__); if ((ht = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET)) == NULL) return mystrdup(what, __FILE__, __PRETTY_FUNCTION__, __LINE__); return mystrdup(ht -> h_name, __FILE__, __PRETTY_FUNCTION__, __LINE__); } break; /* this redundant break-statement is what we call "defensive programming" */ case CONVTYPE_EPOCHTODATE: { char *new_str = epoch_to_str((time_t)atoll(what)); if (new_str) return new_str; else return mystrdup("cannot convert current epoch value", __FILE__, __PRETTY_FUNCTION__, __LINE__); } break; case CONVTYPE_ERRNO: { return mystrdup(strerror(atoi(what)), __FILE__, __PRETTY_FUNCTION__, __LINE__); } case CONVTYPE_HEXTODEC: { long long int result = strtoll(what, NULL, 16); char result_str[128]; snprintf(result_str, sizeof(result_str), "%lld", result); return mystrdup(result_str, __FILE__, __PRETTY_FUNCTION__, __LINE__); } case CONVTYPE_DECTOHEX: { long long int result = atoll(what); char result_str[128]; snprintf(result_str, sizeof(result_str), "%llx", result); return mystrdup(result_str, __FILE__, __PRETTY_FUNCTION__, __LINE__); } case CONVTYPE_SCRIPT: { int rc; char *send_buffer = mymalloc(what_len + 1 + 1, __FILE__, __PRETTY_FUNCTION__, __LINE__); char *result_str = mymalloc(SCRIPT_IO_BUFFER_SIZE, __FILE__, __PRETTY_FUNCTION__, __LINE__); exec_script(pscript); memcpy(send_buffer, what, what_len); send_buffer[what_len] = '\n'; send_buffer[what_len + 1] = 0x00; WRITE(pscript -> fd_w, send_buffer, what_len + 1, "conversion script (is it still running?)"); myfree(send_buffer); rc = READ(pscript -> fd_r, result_str, SCRIPT_IO_BUFFER_SIZE - 1, pscript -> script); result_str[rc > 0?rc - 1:rc] = 0x00; return result_str; } case CONVTYPE_ABBRTOK: return amount_to_str(atoll(what)); default: error_exit(__FILE__, __PRETTY_FUNCTION__, __LINE__, "Internal error: unknown conversion type %d.\n", type); } return "do_convert: INTERNAL ERROR"; } char *convert(int_array_t *pconversions, char *line) { conversion *cur_conv = NULL; cv_off *cv_offsets = NULL; int conv_index; int conv_req; int new_len = 0; int max_n_cv_matches = 0, cur_n_cv_matches = 0; char *new_string = NULL; int offset_old = 0, offset_new = 0; int old_len = strlen(line); int n_conversions = get_iat_size(pconversions); if (n_conversions == 0) return line; for(conv_req=0; conv_req < n_conversions; conv_req++) { cur_conv = &conversions[get_iat_element(pconversions, conv_req)]; max_n_cv_matches = cur_conv -> n * MAX_N_RE_MATCHES; cv_offsets = (cv_off *)mymalloc(sizeof(cv_off) * max_n_cv_matches, __FILE__, __PRETTY_FUNCTION__, __LINE__); /* find where they match */ for(conv_index=0; conv_index n && cur_n_cv_matches < max_n_cv_matches; conv_index++) { int offset = 0; do { int cur_match_index; int cur_offset = offset; regmatch_t matches[MAX_N_RE_MATCHES]; /* FIXME: what to do with regexp errors? */ if (regexec(&(cur_conv -> pcb)[conv_index].regex, &line[offset], MAX_N_RE_MATCHES, matches, offset?REG_NOTBOL:0) != 0) break; for(cur_match_index=1; cur_match_index pcb)[conv_index].match_count++; cv_offsets[cur_n_cv_matches].start = match_start; cv_offsets[cur_n_cv_matches].end = match_end; dummylen = match_end - match_start; dummy = mymalloc(dummylen + 1, __FILE__, __PRETTY_FUNCTION__, __LINE__); memcpy(dummy, &line[match_start], dummylen); dummy[dummylen] = 0x00; cv_offsets[cur_n_cv_matches].newstr = do_convert(dummy, dummylen, (cur_conv -> pcb)[conv_index].type, &(cur_conv -> pcs)[conv_index]); myfree(dummy); cur_n_cv_matches++; } } while (offset < old_len); } } if (cur_n_cv_matches) { int n_copy; /* sort */ if (cur_n_cv_matches > 1) qsort(cv_offsets, cur_n_cv_matches, sizeof(cv_off), cv_offsets_compare); /* create new string */ for(conv_index=0; conv_index < cur_n_cv_matches; conv_index++) { n_copy = cv_offsets[conv_index].start - offset_old; if (n_copy > 0) { new_string = myrealloc(new_string, new_len + n_copy + 1, __FILE__, __PRETTY_FUNCTION__, __LINE__); memcpy(&new_string[offset_new], &line[offset_old], n_copy); new_string[offset_new + n_copy] = 0x00; new_len += n_copy; offset_new += n_copy; } offset_old = cv_offsets[conv_index].end; n_copy = strlen(cv_offsets[conv_index].newstr); new_string = myrealloc(new_string, new_len + n_copy + 1, __FILE__, __PRETTY_FUNCTION__, __LINE__); memcpy(&new_string[offset_new], cv_offsets[conv_index].newstr, n_copy); new_string[offset_new + n_copy] = 0x00; myfree(cv_offsets[conv_index].newstr); new_len += n_copy; offset_new += n_copy; } n_copy = old_len - offset_old; if (n_copy) { new_string = myrealloc(new_string, new_len + n_copy + 1, __FILE__, __PRETTY_FUNCTION__, __LINE__); memcpy(&new_string[offset_new], &line[offset_old], n_copy); new_string[offset_new + n_copy] = 0x00; } } else { new_string = line; } myfree(cv_offsets); return new_string; } int find_conversion_scheme(char *name) { int loop; for(loop=0; loop