1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) University of Cambridge 1995 - 2016 */
6 /* See the file NOTICE for conditions of use and distribution. */
8 /* Functions for reading spool files. When compiling for a utility (eximon),
9 not all are needed, and some functionality can be cut out. */
16 #ifndef COMPILE_UTILITY
17 /*************************************************
18 * Open and lock data file *
19 *************************************************/
21 /* The data file is the one that is used for locking, because the header file
22 can get replaced during delivery because of header rewriting. The file has
23 to opened with write access so that we can get an exclusive lock, but in
24 fact it won't be written to. Just in case there's a major disaster (e.g.
25 overwriting some other file descriptor with the value of this one), open it
28 Argument: the id of the message
29 Returns: fd if file successfully opened and locked, else -1
31 Side effect: message_subdir is set for the (possibly split) spool directory
35 spool_open_datafile(uschar *id)
42 /* If split_spool_directory is set, first look for the file in the appropriate
43 sub-directory of the input directory. If it is not found there, try the input
44 directory itself, to pick up leftovers from before the splitting. If split_
45 spool_directory is not set, first look in the main input directory. If it is
46 not found there, try the split sub-directory, in case it is left over from a
49 for (i = 0; i < 2; i++)
54 message_subdir[0] = split_spool_directory == i ? '\0' : id[5];
55 fname = spool_fname(US"input", message_subdir, id, US"-D");
56 DEBUG(D_deliver) debug_printf("Trying spool file %s\n", fname);
58 if ((fd = Uopen(fname, O_RDWR | O_APPEND, 0)) >= 0)
65 log_write(0, LOG_MAIN, "Spool%s%s file %s-D not found",
66 *queue_name ? US" Q=" : US"",
67 *queue_name ? queue_name : US"",
71 log_write(0, LOG_MAIN, "Spool error for %s: %s", fname, strerror(errno));
76 /* File is open and message_subdir is set. Set the close-on-exec flag, and lock
77 the file. We lock only the first line of the file (containing the message ID)
78 because this apparently is needed for running Exim under Cygwin. If the entire
79 file is locked in one process, a sub-process cannot access it, even when passed
80 an open file descriptor (at least, I think that's the Cygwin story). On real
81 Unix systems it doesn't make any difference as long as Exim is consistent in
84 (void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) |
87 lock_data.l_type = F_WRLCK;
88 lock_data.l_whence = SEEK_SET;
89 lock_data.l_start = 0;
90 lock_data.l_len = SPOOL_DATA_START_OFFSET;
92 if (fcntl(fd, F_SETLK, &lock_data) < 0)
94 log_write(L_skip_delivery,
96 "Spool file is locked (another process is handling this message)");
102 /* Get the size of the data; don't include the leading filename line
103 in the count, but add one for the newline before the data. */
105 if (fstat(fd, &statbuf) == 0)
107 message_body_size = statbuf.st_size - SPOOL_DATA_START_OFFSET;
108 message_size = message_body_size + 1;
113 #endif /* COMPILE_UTILITY */
117 /*************************************************
118 * Read non-recipients tree from spool file *
119 *************************************************/
121 /* The tree of non-recipients is written to the spool file in a form that
122 makes it easy to read back into a tree. The format is as follows:
124 . Each node is preceded by two letter(Y/N) indicating whether it has left
125 or right children. There's one space after the two flags, before the name.
127 . The left subtree (if any) then follows, then the right subtree (if any).
129 This function is entered with the next input line in the buffer. Note we must
130 save the right flag before recursing with the same buffer.
132 Once the tree is read, we re-construct the balance fields by scanning the tree.
133 I forgot to write them out originally, and the compatible fix is to do it this
134 way. This initial local recursing function does the necessary.
139 Returns: maximum depth below the node, including the node itself
143 count_below(tree_node *node)
146 if (node == NULL) return 0;
147 nleft = count_below(node->left);
148 nright = count_below(node->right);
149 node->balance = (nleft > nright)? 1 : ((nright > nleft)? 2 : 0);
150 return 1 + ((nleft > nright)? nleft : nright);
153 /* This is the real function...
156 connect pointer to the root of the tree
157 f FILE to read data from
158 buffer contains next input line; further lines read into it
159 buffer_size size of the buffer
161 Returns: FALSE on format error
165 read_nonrecipients_tree(tree_node **connect, FILE *f, uschar *buffer,
169 int n = Ustrlen(buffer);
170 BOOL right = buffer[1] == 'Y';
172 if (n < 5) return FALSE; /* malformed line */
173 buffer[n-1] = 0; /* Remove \n */
174 node = store_get(sizeof(tree_node) + n - 3);
176 Ustrcpy(node->name, buffer + 3);
177 node->data.ptr = NULL;
179 if (buffer[0] == 'Y')
181 if (Ufgets(buffer, buffer_size, f) == NULL ||
182 !read_nonrecipients_tree(&node->left, f, buffer, buffer_size))
185 else node->left = NULL;
189 if (Ufgets(buffer, buffer_size, f) == NULL ||
190 !read_nonrecipients_tree(&node->right, f, buffer, buffer_size))
193 else node->right = NULL;
195 (void) count_below(*connect);
202 /*************************************************
203 * Read spool header file *
204 *************************************************/
206 /* This function reads a spool header file and places the data into the
207 appropriate global variables. The header portion is always read, but header
208 structures are built only if read_headers is set true. It isn't, for example,
209 while generating -bp output.
211 It may be possible for blocks of nulls (binary zeroes) to get written on the
212 end of a file if there is a system crash during writing. It was observed on an
213 earlier version of Exim that omitted to fsync() the files - this is thought to
214 have been the cause of that incident, but in any case, this code must be robust
215 against such an event, and if such a file is encountered, it must be treated as
219 name name of the header file, including the -H
220 read_headers TRUE if in-store header structures are to be built
221 subdir_set TRUE is message_subdir is already set
223 Returns: spool_read_OK success
224 spool_read_notopen open failed
225 spool_read_enverror error in the envelope portion
226 spool_read_hdrdrror error in the header portion
230 spool_read_header(uschar *name, BOOL read_headers, BOOL subdir_set)
236 BOOL inheader = FALSE;
239 /* Reset all the global variables to their default values. However, there is
240 one exception. DO NOT change the default value of dont_deliver, because it may
241 be forced by an external setting. */
243 acl_var_c = acl_var_m = NULL;
244 authenticated_id = NULL;
245 authenticated_sender = NULL;
246 allow_unqualified_recipient = FALSE;
247 allow_unqualified_sender = FALSE;
250 deliver_firsttime = FALSE;
251 deliver_freeze = FALSE;
252 deliver_frozen_at = 0;
253 deliver_manual_thaw = FALSE;
254 /* dont_deliver must NOT be reset */
255 header_list = header_last = NULL;
256 host_lookup_deferred = FALSE;
257 host_lookup_failed = FALSE;
258 interface_address = NULL;
260 local_error_message = FALSE;
261 local_scan_data = NULL;
262 max_received_linelength = 0;
263 message_linecount = 0;
264 received_protocol = NULL;
266 recipients_list = NULL;
267 sender_address = NULL;
268 sender_fullhost = NULL;
269 sender_helo_name = NULL;
270 sender_host_address = NULL;
271 sender_host_name = NULL;
272 sender_host_port = 0;
273 sender_host_authenticated = NULL;
275 sender_local = FALSE;
276 sender_set_untrusted = FALSE;
277 smtp_active_hostname = primary_hostname;
278 tree_nonrecipients = NULL;
280 #ifdef EXPERIMENTAL_BRIGHTMAIL
287 dkim_disable_verify = FALSE;
288 dkim_collect_input = FALSE;
292 tls_in.certificate_verified = FALSE;
293 # ifdef EXPERIMENTAL_DANE
294 tls_in.dane_verified = FALSE;
296 tls_in.cipher = NULL;
297 # ifndef COMPILE_UTILITY /* tls support fns not built in */
298 tls_free_cert(&tls_in.ourcert);
299 tls_free_cert(&tls_in.peercert);
301 tls_in.peerdn = NULL;
303 tls_in.ocsp = OCSP_NOT_REQ;
306 #ifdef WITH_CONTENT_SCAN
309 spam_score_int = NULL;
312 #if defined(SUPPORT_I18N) && !defined(COMPILE_UTILITY)
313 message_smtputf8 = FALSE;
314 message_utf8_downconvert = 0;
320 /* Generate the full name and open the file. If message_subdir is already
321 set, just look in the given directory. Otherwise, look in both the split
322 and unsplit directories, as for the data file above. */
324 for (n = 0; n < 2; n++)
327 message_subdir[0] = split_spool_directory == (n == 0) ? name[5] : 0;
329 if ((f = Ufopen(spool_fname(US"input", message_subdir, name, US""), "rb")))
331 if (n != 0 || subdir_set || errno != ENOENT)
332 return spool_read_notopen;
337 #ifndef COMPILE_UTILITY
338 DEBUG(D_deliver) debug_printf("reading spool file %s\n", name);
339 #endif /* COMPILE_UTILITY */
341 /* The first line of a spool file contains the message id followed by -H (i.e.
342 the file name), in order to make the file self-identifying. */
344 if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
345 if (Ustrlen(big_buffer) != MESSAGE_ID_LENGTH + 3 ||
346 Ustrncmp(big_buffer, name, MESSAGE_ID_LENGTH + 2) != 0)
347 goto SPOOL_FORMAT_ERROR;
349 /* The next three lines in the header file are in a fixed format. The first
350 contains the login, uid, and gid of the user who caused the file to be written.
351 There are known cases where a negative gid is used, so we allow for both
352 negative uids and gids. The second contains the mail address of the message's
353 sender, enclosed in <>. The third contains the time the message was received,
354 and the number of warning messages for delivery delays that have been sent. */
356 if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
358 p = big_buffer + Ustrlen(big_buffer);
359 while (p > big_buffer && isspace(p[-1])) p--;
361 if (!isdigit(p[-1])) goto SPOOL_FORMAT_ERROR;
362 while (p > big_buffer && (isdigit(p[-1]) || '-' == p[-1])) p--;
364 if (p <= big_buffer || *(--p) != ' ') goto SPOOL_FORMAT_ERROR;
366 if (!isdigit(p[-1])) goto SPOOL_FORMAT_ERROR;
367 while (p > big_buffer && (isdigit(p[-1]) || '-' == p[-1])) p--;
369 if (p <= big_buffer || *(--p) != ' ') goto SPOOL_FORMAT_ERROR;
372 originator_login = string_copy(big_buffer);
373 originator_uid = (uid_t)uid;
374 originator_gid = (gid_t)gid;
377 if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
378 n = Ustrlen(big_buffer);
379 if (n < 3 || big_buffer[0] != '<' || big_buffer[n-2] != '>')
380 goto SPOOL_FORMAT_ERROR;
382 sender_address = store_get(n-2);
383 Ustrncpy(sender_address, big_buffer+1, n-3);
384 sender_address[n-3] = 0;
387 if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
388 if (sscanf(CS big_buffer, "%d %d", &received_time, &warning_count) != 2)
389 goto SPOOL_FORMAT_ERROR;
391 message_age = time(NULL) - received_time;
393 #ifndef COMPILE_UTILITY
394 DEBUG(D_deliver) debug_printf("user=%s uid=%ld gid=%ld sender=%s\n",
395 originator_login, (long int)originator_uid, (long int)originator_gid,
397 #endif /* COMPILE_UTILITY */
399 /* Now there may be a number of optional lines, each starting with "-". If you
400 add a new setting here, make sure you set the default above.
402 Because there are now quite a number of different possibilities, we use a
403 switch on the first character to avoid too many failing tests. Thanks to Nico
404 Erfurth for the patch that implemented this. I have made it even more efficient
405 by not re-scanning the first two characters.
407 To allow new versions of Exim that add additional flags to interwork with older
408 versions that do not understand them, just ignore any lines starting with "-"
409 that we don't recognize. Otherwise it wouldn't be possible to back off a new
410 version that left new-style flags written on the spool. */
416 if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
417 if (big_buffer[0] != '-') break;
418 while ( (len = Ustrlen(big_buffer)) == big_buffer_size-1
419 && big_buffer[len-1] != '\n'
421 { /* buffer not big enough for line; certs make this possible */
423 if (big_buffer_size >= BIG_BUFFER_SIZE*4) goto SPOOL_READ_ERROR;
424 buf = store_get_perm(big_buffer_size *= 2);
425 memcpy(buf, big_buffer, --len);
427 if (Ufgets(big_buffer+len, big_buffer_size-len, f) == NULL)
428 goto SPOOL_READ_ERROR;
430 big_buffer[len-1] = 0;
432 switch(big_buffer[1])
436 /* Nowadays we use "-aclc" and "-aclm" for the different types of ACL
437 variable, because Exim allows any number of them, with arbitrary names.
438 The line in the spool file is "-acl[cm] <name> <length>". The name excludes
441 if (Ustrncmp(p, "clc ", 4) == 0 ||
442 Ustrncmp(p, "clm ", 4) == 0)
444 uschar *name, *endptr;
447 endptr = Ustrchr(big_buffer + 6, ' ');
448 if (endptr == NULL) goto SPOOL_FORMAT_ERROR;
449 name = string_sprintf("%c%.*s", big_buffer[4], endptr - big_buffer - 6,
451 if (sscanf(CS endptr, " %d", &count) != 1) goto SPOOL_FORMAT_ERROR;
452 node = acl_var_create(name);
453 node->data.ptr = store_get(count + 1);
454 if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR;
455 ((uschar*)node->data.ptr)[count] = 0;
458 else if (Ustrcmp(p, "llow_unqualified_recipient") == 0)
459 allow_unqualified_recipient = TRUE;
460 else if (Ustrcmp(p, "llow_unqualified_sender") == 0)
461 allow_unqualified_sender = TRUE;
463 else if (Ustrncmp(p, "uth_id", 6) == 0)
464 authenticated_id = string_copy(big_buffer + 9);
465 else if (Ustrncmp(p, "uth_sender", 10) == 0)
466 authenticated_sender = string_copy(big_buffer + 13);
467 else if (Ustrncmp(p, "ctive_hostname", 14) == 0)
468 smtp_active_hostname = string_copy(big_buffer + 17);
470 /* For long-term backward compatibility, we recognize "-acl", which was
471 used before the number of ACL variables changed from 10 to 20. This was
472 before the subsequent change to an arbitrary number of named variables.
473 This code is retained so that upgrades from very old versions can still
474 handle old-format spool files. The value given after "-acl" is a number
475 that is 0-9 for connection variables, and 10-19 for message variables. */
477 else if (Ustrncmp(p, "cl ", 3) == 0)
479 unsigned index, count;
480 uschar name[20]; /* Need plenty of space for %u format */
482 if ( sscanf(CS big_buffer + 5, "%u %u", &index, &count) != 2
485 goto SPOOL_FORMAT_ERROR;
487 (void) string_format(name, sizeof(name), "%c%u", 'c', index);
489 (void) string_format(name, sizeof(name), "%c%u", 'm', index - 10);
490 node = acl_var_create(name);
491 node->data.ptr = store_get(count + 1);
492 if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR;
493 (US node->data.ptr)[count] = '\0';
498 if (Ustrncmp(p, "ody_linecount", 13) == 0)
499 body_linecount = Uatoi(big_buffer + 15);
500 else if (Ustrncmp(p, "ody_zerocount", 13) == 0)
501 body_zerocount = Uatoi(big_buffer + 15);
502 #ifdef EXPERIMENTAL_BRIGHTMAIL
503 else if (Ustrncmp(p, "mi_verdicts ", 12) == 0)
504 bmi_verdicts = string_copy(big_buffer + 14);
509 if (Ustrcmp(p, "eliver_firsttime") == 0)
510 deliver_firsttime = TRUE;
511 /* Check if the dsn flags have been set in the header file */
512 else if (Ustrncmp(p, "sn_ret", 6) == 0)
513 dsn_ret= atoi(CS big_buffer + 8);
514 else if (Ustrncmp(p, "sn_envid", 8) == 0)
515 dsn_envid = string_copy(big_buffer + 11);
519 if (Ustrncmp(p, "rozen", 5) == 0)
521 deliver_freeze = TRUE;
522 if (sscanf(CS big_buffer+7, TIME_T_FMT, &deliver_frozen_at) != 1)
523 goto SPOOL_READ_ERROR;
528 if (Ustrcmp(p, "ost_lookup_deferred") == 0)
529 host_lookup_deferred = TRUE;
530 else if (Ustrcmp(p, "ost_lookup_failed") == 0)
531 host_lookup_failed = TRUE;
532 else if (Ustrncmp(p, "ost_auth", 8) == 0)
533 sender_host_authenticated = string_copy(big_buffer + 11);
534 else if (Ustrncmp(p, "ost_name", 8) == 0)
535 sender_host_name = string_copy(big_buffer + 11);
536 else if (Ustrncmp(p, "elo_name", 8) == 0)
537 sender_helo_name = string_copy(big_buffer + 11);
539 /* We now record the port number after the address, separated by a
540 dot. For compatibility during upgrading, do nothing if there
541 isn't a value (it gets left at zero). */
543 else if (Ustrncmp(p, "ost_address", 11) == 0)
545 sender_host_port = host_address_extract_port(big_buffer + 14);
546 sender_host_address = string_copy(big_buffer + 14);
551 if (Ustrncmp(p, "nterface_address", 16) == 0)
553 interface_port = host_address_extract_port(big_buffer + 19);
554 interface_address = string_copy(big_buffer + 19);
556 else if (Ustrncmp(p, "dent", 4) == 0)
557 sender_ident = string_copy(big_buffer + 7);
561 if (Ustrcmp(p, "ocal") == 0) sender_local = TRUE;
562 else if (Ustrcmp(big_buffer, "-localerror") == 0)
563 local_error_message = TRUE;
564 else if (Ustrncmp(p, "ocal_scan ", 10) == 0)
565 local_scan_data = string_copy(big_buffer + 12);
569 if (Ustrcmp(p, "anual_thaw") == 0) deliver_manual_thaw = TRUE;
570 else if (Ustrncmp(p, "ax_received_linelength", 22) == 0)
571 max_received_linelength = Uatoi(big_buffer + 24);
575 if (*p == 0) dont_deliver = TRUE; /* -N */
579 if (Ustrncmp(p, "eceived_protocol", 16) == 0)
580 received_protocol = string_copy(big_buffer + 19);
584 if (Ustrncmp(p, "ender_set_untrusted", 19) == 0)
585 sender_set_untrusted = TRUE;
586 #ifdef WITH_CONTENT_SCAN
587 else if (Ustrncmp(p, "pam_bar ", 8) == 0)
588 spam_bar = string_copy(big_buffer + 10);
589 else if (Ustrncmp(p, "pam_score ", 10) == 0)
590 spam_score = string_copy(big_buffer + 12);
591 else if (Ustrncmp(p, "pam_score_int ", 14) == 0)
592 spam_score_int = string_copy(big_buffer + 16);
594 #if defined(SUPPORT_I18N) && !defined(COMPILE_UTILITY)
595 else if (Ustrncmp(p, "mtputf8", 7) == 0)
596 message_smtputf8 = TRUE;
602 if (Ustrncmp(p, "ls_certificate_verified", 23) == 0)
603 tls_in.certificate_verified = TRUE;
604 else if (Ustrncmp(p, "ls_cipher", 9) == 0)
605 tls_in.cipher = string_copy(big_buffer + 12);
606 # ifndef COMPILE_UTILITY /* tls support fns not built in */
607 else if (Ustrncmp(p, "ls_ourcert", 10) == 0)
608 (void) tls_import_cert(big_buffer + 13, &tls_in.ourcert);
609 else if (Ustrncmp(p, "ls_peercert", 11) == 0)
610 (void) tls_import_cert(big_buffer + 14, &tls_in.peercert);
612 else if (Ustrncmp(p, "ls_peerdn", 9) == 0)
613 tls_in.peerdn = string_unprinting(string_copy(big_buffer + 12));
614 else if (Ustrncmp(p, "ls_sni", 6) == 0)
615 tls_in.sni = string_unprinting(string_copy(big_buffer + 9));
616 else if (Ustrncmp(p, "ls_ocsp", 7) == 0)
617 tls_in.ocsp = big_buffer[10] - '0';
621 #if defined(SUPPORT_I18N) && !defined(COMPILE_UTILITY)
623 if (Ustrncmp(p, "tf8_downcvt", 11) == 0)
624 message_utf8_downconvert = 1;
625 else if (Ustrncmp(p, "tf8_optdowncvt", 15) == 0)
626 message_utf8_downconvert = -1;
630 default: /* Present because some compilers complain if all */
631 break; /* possibilities are not covered. */
635 /* Build sender_fullhost if required */
637 #ifndef COMPILE_UTILITY
638 host_build_sender_fullhost();
639 #endif /* COMPILE_UTILITY */
641 #ifndef COMPILE_UTILITY
643 debug_printf("sender_local=%d ident=%s\n", sender_local,
644 (sender_ident == NULL)? US"unset" : sender_ident);
645 #endif /* COMPILE_UTILITY */
647 /* We now have the tree of addresses NOT to deliver to, or a line
648 containing "XX", indicating no tree. */
650 if (Ustrncmp(big_buffer, "XX\n", 3) != 0 &&
651 !read_nonrecipients_tree(&tree_nonrecipients, f, big_buffer, big_buffer_size))
652 goto SPOOL_FORMAT_ERROR;
654 #ifndef COMPILE_UTILITY
657 debug_printf("Non-recipients:\n");
658 debug_print_tree(tree_nonrecipients);
660 #endif /* COMPILE_UTILITY */
662 /* After reading the tree, the next line has not yet been read into the
663 buffer. It contains the count of recipients which follow on separate lines. */
665 if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
666 if (sscanf(CS big_buffer, "%d", &rcount) != 1) goto SPOOL_FORMAT_ERROR;
668 #ifndef COMPILE_UTILITY
669 DEBUG(D_deliver) debug_printf("recipients_count=%d\n", rcount);
670 #endif /* COMPILE_UTILITY */
672 recipients_list_max = rcount;
673 recipients_list = store_get(rcount * sizeof(recipient_item));
675 for (recipients_count = 0; recipients_count < rcount; recipients_count++)
680 uschar *orcpt = NULL;
681 uschar *errors_to = NULL;
684 if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
685 nn = Ustrlen(big_buffer);
686 if (nn < 2) goto SPOOL_FORMAT_ERROR;
688 /* Remove the newline; this terminates the address if there is no additional
691 p = big_buffer + nn - 1;
694 /* Look back from the end of the line for digits and special terminators.
695 Since an address must end with a domain, we can tell that extra data is
696 present by the presence of the terminator, which is always some character
697 that cannot exist in a domain. (If I'd thought of the need for additional
698 data early on, I'd have put it at the start, with the address at the end. As
699 it is, we have to operate backwards. Addresses are permitted to contain
702 This code has to cope with various versions of this data that have evolved
703 over time. In all cases, the line might just contain an address, with no
704 additional data. Otherwise, the possibilities are as follows:
706 Exim 3 type: <address><space><digits>,<digits>,<digits>
708 The second set of digits is the parent number for one_time addresses. The
709 other values were remnants of earlier experiments that were abandoned.
711 Exim 4 first type: <address><space><digits>
713 The digits are the parent number for one_time addresses.
715 Exim 4 new type: <address><space><data>#<type bits>
717 The type bits indicate what the contents of the data are.
719 Bit 01 indicates that, reading from right to left, the data
720 ends with <errors_to address><space><len>,<pno> where pno is
721 the parent number for one_time addresses, and len is the length
722 of the errors_to address (zero meaning none).
724 Bit 02 indicates that, again reading from right to left, the data continues
725 with orcpt len(orcpt),dsn_flags
728 while (isdigit(*p)) p--;
730 /* Handle Exim 3 spool files */
735 while (isdigit(*(--p)) || *p == ',');
739 (void)sscanf(CS p, "%d,%d", &dummy, &pno);
743 /* Handle early Exim 4 spool files */
748 (void)sscanf(CS p, "%d", &pno);
751 /* Handle current format Exim 4 spool files */
757 #if !defined (COMPILE_UTILITY)
758 DEBUG(D_deliver) debug_printf("**** SPOOL_IN - Exim 4 standard format spoolfile\n");
761 (void)sscanf(CS p+1, "%d", &flags);
763 if ((flags & 0x01) != 0) /* one_time data exists */
766 while (isdigit(*(--p)) || *p == ',' || *p == '-');
767 (void)sscanf(CS p+1, "%d,%d", &len, &pno);
772 errors_to = string_copy(p);
776 *(--p) = 0; /* Terminate address */
777 if ((flags & 0x02) != 0) /* one_time data exists */
780 while (isdigit(*(--p)) || *p == ',' || *p == '-');
781 (void)sscanf(CS p+1, "%d,%d", &len, &dsn_flags);
786 orcpt = string_copy(p);
790 *(--p) = 0; /* Terminate address */
792 #if !defined(COMPILE_UTILITY)
794 { DEBUG(D_deliver) debug_printf("**** SPOOL_IN - No additional fields\n"); }
796 if ((orcpt != NULL) || (dsn_flags != 0))
798 DEBUG(D_deliver) debug_printf("**** SPOOL_IN - address: |%s| orcpt: |%s| dsn_flags: %d\n",
799 big_buffer, orcpt, dsn_flags);
801 if (errors_to != NULL)
803 DEBUG(D_deliver) debug_printf("**** SPOOL_IN - address: |%s| errorsto: |%s|\n",
804 big_buffer, errors_to);
808 recipients_list[recipients_count].address = string_copy(big_buffer);
809 recipients_list[recipients_count].pno = pno;
810 recipients_list[recipients_count].errors_to = errors_to;
811 recipients_list[recipients_count].orcpt = orcpt;
812 recipients_list[recipients_count].dsn_flags = dsn_flags;
815 /* The remainder of the spool header file contains the headers for the message,
816 separated off from the previous data by a blank line. Each header is preceded
817 by a count of its length and either a certain letter (for various identified
818 headers), space (for a miscellaneous live header) or an asterisk (for a header
819 that has been rewritten). Count the Received: headers. We read the headers
820 always, in order to check on the format of the file, but only create a header
821 list if requested to do so. */
824 if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
825 if (big_buffer[0] != '\n') goto SPOOL_FORMAT_ERROR;
827 while ((n = fgetc(f)) != EOF)
833 if (!isdigit(n)) goto SPOOL_FORMAT_ERROR;
834 if(ungetc(n, f) == EOF || fscanf(f, "%d%c ", &n, flag) == EOF)
835 goto SPOOL_READ_ERROR;
836 if (flag[0] != '*') message_size += n; /* Omit non-transmitted headers */
840 h = store_get(sizeof(header_line));
844 h->text = store_get(n+1);
846 if (h->type == htype_received) received_count++;
848 if (header_list == NULL) header_list = h;
849 else header_last->next = h;
852 for (i = 0; i < n; i++)
855 if (c == 0 || c == EOF) goto SPOOL_FORMAT_ERROR;
856 if (c == '\n' && h->type != htype_old) message_linecount++;
862 /* Not requiring header data, just skip through the bytes */
864 else for (i = 0; i < n; i++)
867 if (c == 0 || c == EOF) goto SPOOL_FORMAT_ERROR;
871 /* We have successfully read the data in the header file. Update the message
872 line count by adding the body linecount to the header linecount. Close the file
873 and give a positive response. */
875 #ifndef COMPILE_UTILITY
876 DEBUG(D_deliver) debug_printf("body_linecount=%d message_linecount=%d\n",
877 body_linecount, message_linecount);
878 #endif /* COMPILE_UTILITY */
880 message_linecount += body_linecount;
883 return spool_read_OK;
886 /* There was an error reading the spool or there was missing data,
887 or there was a format error. A "read error" with no errno means an
888 unexpected EOF, which we treat as a format error. */
895 #ifndef COMPILE_UTILITY
896 DEBUG(D_any) debug_printf("Error while reading spool file %s\n", name);
897 #endif /* COMPILE_UTILITY */
901 return inheader? spool_read_hdrerror : spool_read_enverror;
906 #ifndef COMPILE_UTILITY
907 DEBUG(D_any) debug_printf("Format error in spool file %s\n", name);
908 #endif /* COMPILE_UTILITY */
911 errno = ERRNO_SPOOLFORMAT;
912 return inheader? spool_read_hdrerror : spool_read_enverror;
917 /* End of spool_in.c */