X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/ea97267cea0f7e6054806504b3616f2bf9723bce..190404d75c168ce1e6dbf6ee08bdbbf62b365e4b:/src/src/receive.c diff --git a/src/src/receive.c b/src/src/receive.c index bc5cebaad..ba4767916 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -144,7 +144,7 @@ Returns: available on-root space, in kilobytes All values are -1 if the STATFS functions are not available. */ -int +int_eximarith_t receive_statvfs(BOOL isspool, int *inodeptr) { #ifdef HAVE_STATFS @@ -223,7 +223,7 @@ if (STATVFS(CS path, &statbuf) != 0) /* Disks are getting huge. Take care with computing the size in kilobytes. */ -return (int)(((double)statbuf.F_BAVAIL * (double)statbuf.F_FRSIZE)/1024.0); +return (int_eximarith_t)(((double)statbuf.F_BAVAIL * (double)statbuf.F_FRSIZE)/1024.0); #else /* Unable to find partition sizes in this environment. */ @@ -258,22 +258,23 @@ Returns: FALSE if there isn't enough space, or if the information cannot BOOL receive_check_fs(int msg_size) { -int space, inodes; +int_eximarith_t space; +int inodes; if (check_spool_space > 0 || msg_size > 0 || check_spool_inodes > 0) { space = receive_statvfs(TRUE, &inodes); DEBUG(D_receive) - debug_printf("spool directory space = %dK inodes = %d " - "check_space = %dK inodes = %d msg_size = %d\n", + debug_printf("spool directory space = " PR_EXIM_ARITH "K inodes = %d " + "check_space = " PR_EXIM_ARITH "K inodes = %d msg_size = %d\n", space, inodes, check_spool_space, check_spool_inodes, msg_size); if ((space >= 0 && space < check_spool_space) || (inodes >= 0 && inodes < check_spool_inodes)) { - log_write(0, LOG_MAIN, "spool directory space check failed: space=%d " - "inodes=%d", space, inodes); + log_write(0, LOG_MAIN, "spool directory space check failed: space=" + PR_EXIM_ARITH " inodes=%d", space, inodes); return FALSE; } } @@ -283,15 +284,15 @@ if (check_log_space > 0 || check_log_inodes > 0) space = receive_statvfs(FALSE, &inodes); DEBUG(D_receive) - debug_printf("log directory space = %dK inodes = %d " - "check_space = %dK inodes = %d\n", + debug_printf("log directory space = " PR_EXIM_ARITH "K inodes = %d " + "check_space = " PR_EXIM_ARITH "K inodes = %d\n", space, inodes, check_log_space, check_log_inodes); - if ((space >= 0 && space < check_log_space) || - (inodes >= 0 && inodes < check_log_inodes)) + if ( space >= 0 && space < check_log_space + || inodes >= 0 && inodes < check_log_inodes) { - log_write(0, LOG_MAIN, "log directory space check failed: space=%d " - "inodes=%d", space, inodes); + log_write(0, LOG_MAIN, "log directory space check failed: space=" PR_EXIM_ARITH + " inodes=%d", space, inodes); return FALSE; } } @@ -553,11 +554,9 @@ Returns: TRUE if it did remove something; FALSE otherwise BOOL receive_remove_recipient(uschar *recipient) { -int count; DEBUG(D_receive) debug_printf("receive_remove_recipient(\"%s\") called\n", recipient); -for (count = 0; count < recipients_count; count++) - { +for (int count = 0; count < recipients_count; count++) if (Ustrcmp(recipients_list[count].address, recipient) == 0) { if ((--recipients_count - count) > 0) @@ -565,7 +564,6 @@ for (count = 0; count < recipients_count; count++) (recipients_count - count)*sizeof(recipient_item)); return TRUE; } - } return FALSE; } @@ -1173,7 +1171,6 @@ Returns: nothing static void add_acl_headers(int where, uschar *acl_name) { -header_line *h, *next; header_line *last_received = NULL; switch(where) @@ -1194,7 +1191,7 @@ if (acl_removed_headers) { DEBUG(D_receive|D_acl) debug_printf_indent(">>Headers removed by %s ACL:\n", acl_name); - for (h = header_list; h; h = h->next) if (h->type != htype_old) + for (header_line * h = header_list; h; h = h->next) if (h->type != htype_old) { const uschar * list = acl_removed_headers; int sep = ':'; /* This is specified as a colon-separated list */ @@ -1215,7 +1212,7 @@ if (acl_removed_headers) if (!acl_added_headers) return; DEBUG(D_receive|D_acl) debug_printf_indent(">>Headers added by %s ACL:\n", acl_name); -for (h = acl_added_headers; h; h = next) +for (header_line * h = acl_added_headers, * next; h; h = next) { next = h->next; @@ -1305,15 +1302,12 @@ if (sender_fullhost) if (LOGGING(dnssec) && sender_host_dnssec) /*XXX sender_helo_dnssec? */ g = string_catn(g, US" DS", 3); g = string_append(g, 2, US" H=", sender_fullhost); - if (LOGGING(incoming_interface) && interface_address != NULL) - { - g = string_cat(g, - string_sprintf(" I=[%s]:%d", interface_address, interface_port)); - } + if (LOGGING(incoming_interface) && interface_address) + g = string_fmt_append(g, " I=[%s]:%d", interface_address, interface_port); } if (f.tcp_in_fastopen && !f.tcp_in_fastopen_logged) { - g = string_catn(g, US" TFO", 4); + g = string_catn(g, US" TFO*", f.tcp_in_fastopen_data ? 5 : 4); f.tcp_in_fastopen_logged = TRUE; } if (sender_ident) @@ -1321,7 +1315,17 @@ if (sender_ident) if (received_protocol) g = string_append(g, 2, US" P=", received_protocol); if (LOGGING(pipelining) && f.smtp_in_pipelining_advertised) - g = string_catn(g, US" L-", f.smtp_in_pipelining_used ? 2 : 3); + { + g = string_catn(g, US" L", 2); +#ifdef EXPERIMENTAL_PIPE_CONNECT + if (f.smtp_in_early_pipe_used) + g = string_catn(g, US"*", 1); + else if (f.smtp_in_early_pipe_advertised) + g = string_catn(g, US".", 1); +#endif + if (!f.smtp_in_pipelining_used) + g = string_catn(g, US"-", 1); + } return g; } @@ -1352,7 +1356,6 @@ run_mime_acl(uschar *acl, BOOL *smtp_yield_ptr, uschar **smtp_reply_ptr, FILE *mbox_file; uschar * rfc822_file_path = NULL; unsigned long mbox_size; -header_line *my_headerlist; uschar *user_msg, *log_msg; int mime_part_count_buffer = -1; uschar * mbox_filename; @@ -1360,7 +1363,8 @@ int rc = OK; /* check if it is a MIME message */ -for (my_headerlist = header_list; my_headerlist; my_headerlist = my_headerlist->next) +for (header_line * my_headerlist = header_list; my_headerlist; + my_headerlist = my_headerlist->next) if ( my_headerlist->type != '*' /* skip deleted headers */ && strncmpic(my_headerlist->text, US"Content-Type:", 13) == 0 ) @@ -1615,7 +1619,6 @@ not. */ BOOL receive_msg(BOOL extract_recip) { -int i; int rc = FAIL; int msg_size = 0; int process_info_len = Ustrlen(process_info); @@ -1623,7 +1626,7 @@ int error_rc = error_handling == ERRORS_SENDER ? errors_sender_rc : EXIT_FAILURE; int header_size = 256; int start, end, domain; -int id_resolution; +int id_resolution = 0; int had_zero = 0; int prevlines_length = 0; @@ -1658,7 +1661,7 @@ uschar *user_msg, *log_msg; /* Working header pointers */ -header_line *h, *next; +header_line *next; /* Flags for noting the existence of certain headers (only one left) */ @@ -1764,7 +1767,7 @@ single timeout for the whole message. */ else if (receive_timeout > 0) { os_non_restarting_signal(SIGALRM, data_timeout_handler); - alarm(receive_timeout); + ALARM(receive_timeout); } /* SIGTERM and SIGINT are caught always. */ @@ -2120,7 +2123,8 @@ for (;;) the line, stomp on them here. */ if (had_zero > 0) - for (p = next->text; p < next->text + ptr; p++) if (*p == 0) *p = '?'; + for (uschar * p = next->text; p < next->text + ptr; p++) if (*p == 0) + *p = '?'; /* It is perfectly legal to have an empty continuation line at the end of a header, but it is confusing to humans @@ -2222,7 +2226,7 @@ normal case). */ DEBUG(D_receive) { debug_printf(">>Headers received:\n"); - for (h = header_list->next; h; h = h->next) + for (header_line * h = header_list->next; h; h = h->next) debug_printf("%s", h->text); debug_printf("\n"); } @@ -2249,7 +2253,7 @@ if (filter_test != FTEST_NONE && header_list->next == NULL) /* Scan the headers to identify them. Some are merely marked for later processing; some are dealt with here. */ -for (h = header_list->next; h; h = h->next) +for (header_line * h = header_list->next; h; h = h->next) { BOOL is_resent = strncmpic(h->text, US"resent-", 7) == 0; if (is_resent) contains_resent_headers = TRUE; @@ -2463,7 +2467,7 @@ if (extract_recip) /* Now scan the headers */ - for (h = header_list->next; h; h = h->next) + for (header_line * h = header_list->next; h; h = h->next) { if ((h->type == htype_to || h->type == htype_cc || h->type == htype_bcc) && (!contains_resent_headers || strncmpic(h->text, US"resent-", 7) == 0)) @@ -2476,7 +2480,7 @@ if (extract_recip) while (*s != 0) { uschar *ss = parse_find_address_end(s, FALSE); - uschar *recipient, *errmess, *p, *pp; + uschar *recipient, *errmess, *pp; int start, end, domain; /* Check on maximum */ @@ -2492,7 +2496,7 @@ if (extract_recip) of the header. */ pp = recipient = store_get(ss - s + 1); - for (p = s; p < ss; p++) if (*p != '\n') *pp++ = *p; + for (uschar * p = s; p < ss; p++) if (*p != '\n') *pp++ = *p; *pp = 0; #ifdef SUPPORT_I18N @@ -2625,7 +2629,7 @@ the message, if necessary (we hope it won't be). */ if (host_number_string) { - id_resolution = (BASE_62 == 62)? 5000 : 10000; + id_resolution = BASE_62 == 62 ? 5000 : 10000; sprintf(CS(message_id + MESSAGE_ID_LENGTH - 3), "-%2s", string_base62((long int)( host_number * (1000000/id_resolution) + @@ -2637,7 +2641,7 @@ appropriate resolution. */ else { - id_resolution = (BASE_62 == 62)? 500 : 1000; + id_resolution = BASE_62 == 62 ? 500 : 1000; sprintf(CS(message_id + MESSAGE_ID_LENGTH - 3), "-%2s", string_base62((long int)(message_id_tv.tv_usec/id_resolution)) + 4); } @@ -2662,7 +2666,6 @@ any illegal characters therein. */ if ( !msgid_header && ((!sender_host_address && !f.suppress_local_fixups) || f.submission_mode)) { - uschar *p; uschar *id_text = US""; uschar *id_domain = primary_hostname; @@ -2681,7 +2684,7 @@ if ( !msgid_header else if (*new_id_domain) { id_domain = new_id_domain; - for (p = id_domain; *p; p++) + for (uschar * p = id_domain; *p; p++) if (!isalnum(*p) && *p != '.') *p = '-'; /* No need to test '-' ! */ } } @@ -2702,7 +2705,7 @@ if ( !msgid_header else if (*new_id_text) { id_text = new_id_text; - for (p = id_text; *p; p++) if (mac_iscntrl_or_special(*p)) *p = '-'; + for (uschar * p = id_text; *p; p++) if (mac_iscntrl_or_special(*p)) *p = '-'; } } @@ -2722,7 +2725,7 @@ function may mess with the real recipients. */ if (LOGGING(received_recipients)) { raw_recipients = store_get(recipients_count * sizeof(uschar *)); - for (i = 0; i < recipients_count; i++) + for (int i = 0; i < recipients_count; i++) raw_recipients[i] = string_copy(recipients_list[i].address); raw_recipients_count = recipients_count; } @@ -2731,7 +2734,7 @@ if (LOGGING(received_recipients)) recipients will get here only if the conditions were right (allow_unqualified_ recipient is TRUE). */ -for (i = 0; i < recipients_count; i++) +for (int i = 0; i < recipients_count; i++) recipients_list[i].address = rewrite_address(recipients_list[i].address, TRUE, TRUE, global_rewrite_rules, rewrite_existflags); @@ -2930,7 +2933,7 @@ We start at the second header, skipping our own Received:. This rewriting is documented as happening *after* recipient addresses are taken from the headers by the -t command line option. An added Sender: gets rewritten here. */ -for (h = header_list->next; h; h = h->next) +for (header_line * h = header_list->next; h; h = h->next) { header_line *newh = rewrite_header(h, NULL, NULL, global_rewrite_rules, rewrite_existflags, TRUE); @@ -2969,7 +2972,7 @@ new Received:) has not yet been set. */ DEBUG(D_receive) { debug_printf(">>Headers after rewriting and local additions:\n"); - for (h = header_list->next; h; h = h->next) + for (header_line * h = header_list->next; h; h = h->next) debug_printf("%c %s", h->type, h->text); debug_printf("\n"); } @@ -3236,16 +3239,15 @@ if (extract_recip && (bad_addresses || recipients_count == 0)) if (recipients_count == 0) debug_printf("*** No recipients\n"); if (bad_addresses) { - error_block *eblock = bad_addresses; debug_printf("*** Bad address(es)\n"); - while (eblock != NULL) - { + for (error_block * eblock = bad_addresses; eblock; eblock = eblock->next) debug_printf(" %s: %s\n", eblock->text1, eblock->text2); - eblock = eblock->next; - } } } + log_write(0, LOG_MAIN|LOG_PANIC, "%s %s found in headers", + message_id, bad_addresses ? "bad addresses" : "no recipients"); + fseek(spool_data_file, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET); /* If configured to send errors to the sender, but this fails, force @@ -3257,11 +3259,12 @@ if (extract_recip && (bad_addresses || recipients_count == 0)) if (error_handling == ERRORS_SENDER) { if (!moan_to_sender( - (bad_addresses == NULL)? - (extracted_ignored? ERRMESS_IGADDRESS : ERRMESS_NOADDRESS) : - (recipients_list == NULL)? ERRMESS_BADNOADDRESS : ERRMESS_BADADDRESS, - bad_addresses, header_list, spool_data_file, FALSE)) - error_rc = (bad_addresses == NULL)? EXIT_NORECIPIENTS : EXIT_FAILURE; + bad_addresses + ? recipients_list ? ERRMESS_BADADDRESS : ERRMESS_BADNOADDRESS + : extracted_ignored ? ERRMESS_IGADDRESS : ERRMESS_NOADDRESS, + bad_addresses, header_list, spool_data_file, FALSE + ) ) + error_rc = bad_addresses ? EXIT_FAILURE : EXIT_NORECIPIENTS; } else { @@ -3456,13 +3459,12 @@ else #ifndef DISABLE_PRDR if (prdr_requested && recipients_count > 1 && acl_smtp_data_prdr) { - unsigned int c; int all_pass = OK; int all_fail = FAIL; smtp_printf("353 PRDR content analysis beginning\r\n", TRUE); /* Loop through recipients, responses must be in same order received */ - for (c = 0; recipients_count > c; c++) + for (unsigned int c = 0; recipients_count > c; c++) { uschar * addr= recipients_list[c].address; uschar * msg= US"PRDR R=<%s> %s"; @@ -3657,9 +3659,9 @@ if (sigsetjmp(local_scan_env, 1) == 0) had_local_scan_timeout = 0; os_non_restarting_signal(SIGALRM, local_scan_timeout_handler); - if (local_scan_timeout > 0) alarm(local_scan_timeout); + if (local_scan_timeout > 0) ALARM(local_scan_timeout); rc = local_scan(data_fd, &local_scan_data); - alarm(0); + ALARM_CLR(0); os_non_restarting_signal(SIGALRM, sigalrm_handler); f.enable_dollar_recipients = FALSE; @@ -3728,18 +3730,15 @@ the spool file gets corrupted. Ensure that all recipients are qualified. */ if (rc == LOCAL_SCAN_ACCEPT) { if (local_scan_data) - { - uschar *s; - for (s = local_scan_data; *s != 0; s++) if (*s == '\n') *s = ' '; - } - for (i = 0; i < recipients_count; i++) + for (uschar * s = local_scan_data; *s != 0; s++) if (*s == '\n') *s = ' '; + for (int i = 0; i < recipients_count; i++) { recipient_item *r = recipients_list + i; r->address = rewrite_address_qualify(r->address, TRUE); - if (r->errors_to != NULL) + if (r->errors_to) r->errors_to = rewrite_address_qualify(r->errors_to, TRUE); } - if (recipients_count == 0 && blackholed_by == NULL) + if (recipients_count == 0 && !blackholed_by) blackholed_by = US"local_scan"; } @@ -3858,10 +3857,9 @@ file fails, we have failed to accept this message. */ if (host_checking || blackholed_by) { - header_line *h; Uunlink(spool_name); msg_size = 0; /* Compute size for log line */ - for (h = header_list; h; h = h->next) + for (header_line * h = header_list; h; h = h->next) if (h->type != '*') msg_size += h->slen; } @@ -3893,16 +3891,6 @@ else receive_messagecount++; -/* In SMTP sessions we may receive several in one connection. After each one, -we wait for the clock to tick at the level of message-id granularity. This is -so that the combination of time+pid is unique, even on systems where the pid -can be re-used within our time interval. We can't shorten the interval without -re-designing the message-id. See comments above where the message id is -created. This is Something For The Future. */ - -message_id_tv.tv_usec = (message_id_tv.tv_usec/id_resolution) * id_resolution; -exim_wait_tick(&message_id_tv, id_resolution); - /* Add data size to written header size. We do not count the initial file name that is in the file, but we do add one extra for the notional blank line that precedes the data. This total differs from message_size in that it include the @@ -4034,7 +4022,6 @@ text. By expanding $h_subject: we make use of the MIME decoding. */ if (LOGGING(subject) && subject_header) { - int i; uschar *p = big_buffer; uschar *ss = expand_string(US"$h_subject:"); @@ -4042,7 +4029,7 @@ if (LOGGING(subject) && subject_header) a C-like string, and turn any non-printers into escape sequences. */ *p++ = '\"'; - if (*ss != 0) for (i = 0; i < 100 && ss[i] != 0; i++) + if (*ss != 0) for (int i = 0; i < 100 && ss[i] != 0; i++) { if (ss[i] == '\"' || ss[i] == '\\') *p++ = '\\'; *p++ = ss[i]; @@ -4261,6 +4248,23 @@ then we can think about properly declaring the message not-received. */ TIDYUP: +/* In SMTP sessions we may receive several messages in one connection. After +each one, we wait for the clock to tick at the level of message-id granularity. +This is so that the combination of time+pid is unique, even on systems where the +pid can be re-used within our time interval. We can't shorten the interval +without re-designing the message-id. See comments above where the message id is +created. This is Something For The Future. +Do this wait any time we have created a message-id, even if we rejected the +message. This gives unique IDs for logging done by ACLs. */ + +if (id_resolution != 0) + { + message_id_tv.tv_usec = (message_id_tv.tv_usec/id_resolution) * id_resolution; + exim_wait_tick(&message_id_tv, id_resolution); + id_resolution = 0; + } + + process_info[process_info_len] = 0; /* Remove message id */ if (spool_data_file && cutthrough_done == NOT_TRIED) {