Postfix version 19991231 patchlevel 03 fixes low-priority defects and provides workarounds for unusual conditions. - Workaround to prevent one site with a huge backlog from blocking all other deliveries. This is controlled by a new configuration parameter qmgr_site_hog_factor (default: 90 percent) that limits how much in-memory queue manager resources a site can claim. - Workarounds for the most likely problems that will happen when running the Postfix queue on top of NFS. - The SMTP server did not look in the relocated table and would report "User unknown" rather than letting the mail bounce the way it is supposed to be. - When requested to extract recipients from message headers, Postfix now insists that no message header exceeds the header size limit. This prevents Postfix from inadvertently disclosing Bcc: addresses. postfix-19991231-patch03 is about 1500 lines. This is too large for distribution via mail. The patch and a fully-patched version of the source code are being made available via the usual FTP servers, primary site: ftp://ftp.porcupine.org/mirrors/postfix-release/official/ Or, if you use a web browser, ftp://ftp.porcupine.org/mirrors/postfix-release/index.html Wietse diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/global/mail_version.h ./global/mail_version.h *** ../postfix-19991231-pl02/global/mail_version.h Tue Jan 4 08:12:42 2000 --- ./global/mail_version.h Thu Jan 6 11:10:10 2000 *************** *** 15,21 **** * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" ! #define DEF_MAIL_VERSION "Postfix-19991231-pl02" extern char *var_mail_version; /* LICENSE --- 15,21 ---- * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" ! #define DEF_MAIL_VERSION "Postfix-19991231-pl03" extern char *var_mail_version; /* LICENSE diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/HISTORY ./HISTORY *** ../postfix-19991231-pl02/HISTORY Tue Jan 4 08:30:35 2000 --- ./HISTORY Thu Jan 27 21:13:39 2000 *************** *** 3528,3536 **** for this common error and logs a warning instead of refusing the mail. File: smtpd/smtpd_check.c. ! 20000103 Bugfix: a case sensitivity bug had slipped through in the anti-relaying code, causing mail for USER@VIRTUAL.DOMAIN to be rejected with "relay access denied". This was found by Jim Maenpaa @ jmm.com. --- 3528,3603 ---- for this common error and logs a warning instead of refusing the mail. File: smtpd/smtpd_check.c. ! 20000104 Bugfix: a case sensitivity bug had slipped through in the anti-relaying code, causing mail for USER@VIRTUAL.DOMAIN to be rejected with "relay access denied". This was found by Jim Maenpaa @ jmm.com. + + Portability: Ultrix patch from Simon Burge @ thistledown.com.au. + + Portability: Siemens Pyramid (dcosx) patch by Thomas D. + Knox @ vushta.com. + + 20000105 + + Cleanup: the INSTALL.sh script now updates the sample files + in /etc/postfix even when main.cf exists. + + 20000106 + + Bugfix: the SMTP server should consult the relocated map + for virtual destinations (Denis Shaposhnikov). Files: + smtpd/smtpd.c smtpd/smtpd_check.c. + + 20000108 + + Workaround: rename() over NFS can fail with ENOENT even + when the operation succeeds (Graham Orndorff @ WebTV). This + is not news. Any non-idempotent operation can fail over + NFS when the NFS server's acknowledgement is lost and the + NFS client code retries the operation (other examples are: + create, symlink, link, unlink, mkdir, rmdir). Postfix has + workarounds for the cases where this is most likely to + cause trouble. Files: util/sane_{rename,link}.[hc]. If + you want reliable mail system, do not use NFS. + + 20000115 + + Workaround: better detection of bad hardware. Added SIGBUS + to the list of signals that the master will log before + exiting. + + 20000122 + + Portability: preliminary SCO5 port Christopher Wong @ + csports.com. This still needs to a workaround for "find" + not supporting "-type s" (actually, UNIX-domain sockets + have no unique representation in the file system and show + up as FIFOs). + + 20000115-22 + + Bugfix: in case of a too long message header, don't extract + recipients from message headers. With the previous behavior, + Bcc information could be left in the message body, as one + person found out the hard way. Files: cleanup/cleanup.c, + cleanup/cleanup_extracted.c, global/cleanup_user.h. + + 20000124 + + Whatever: RFC 1869 amends RFC 821 and specifies that code + 555 is to be used when a MAIL FROM or RCPT TO parameter is + not implemented or not recognized. Russ Allbery @stanford.edu. + This reply code is added to the list of reply codes that + cause the Postfix SMTP client to mail a transcript to the + postmaster. File: smtp/smtp_trouble.c. + + 20000126 + + Emergency feature: qmgr_site_hog_factor (default: 90 + percent) limits the amount of resources that Postfix will + devote to a single site. With less than 100, Postfix will + defer the excess mail so that one site with a large backlog + does not block other deliveries. diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/INSTALL.sh ./INSTALL.sh *** ../postfix-19991231-pl02/INSTALL.sh Fri Dec 31 10:47:21 1999 --- ./INSTALL.sh Thu Jan 27 21:12:59 2000 *************** *** 255,263 **** compare_or_symlink $SENDMAIL_PATH $MAILQ_PATH } ! compare_or_replace a+r,go-w conf/LICENSE $CONFIG_DIRECTORY/LICENSE || exit 1 ! ! test -f $CONFIG_DIRECTORY/main.cf || { cp conf/* $CONFIG_DIRECTORY || exit 1 chmod a+r,go-w $CONFIG_DIRECTORY/* || exit 1 --- 255,267 ---- compare_or_symlink $SENDMAIL_PATH $MAILQ_PATH } ! if [ -f $CONFIG_DIRECTORY/main.cf ] ! then ! for file in LICENSE `cd conf; echo sample*` main.cf.default ! do ! compare_or_replace a+r,go-w conf/$file $CONFIG_DIRECTORY/$file || exit 1 ! done ! else cp conf/* $CONFIG_DIRECTORY || exit 1 chmod a+r,go-w $CONFIG_DIRECTORY/* || exit 1 *************** *** 269,275 **** echo "BTW: Edit your alias database and be sure to set up aliases" 1>&2 echo "for root and postmaster, then run $NEWALIASES_PATH." 1>&2 } ! } # Save settings. --- 273,279 ---- echo "BTW: Edit your alias database and be sure to set up aliases" 1>&2 echo "for root and postmaster, then run $NEWALIASES_PATH." 1>&2 } ! fi # Save settings. diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/RELEASE_NOTES ./RELEASE_NOTES *** ../postfix-19991231-pl02/RELEASE_NOTES Sun Jan 2 12:41:54 2000 --- ./RELEASE_NOTES Thu Jan 6 09:52:40 2000 *************** *** 77,85 **** domains that are defined by Postfix virtual maps. - The SMTP server can reject mail for unknown local users. Specify ! "local_recipient_maps = $relocated_maps, $alias_maps, unix:passwd.byname" ! if your local mail is delivered by a UNIX-style local delivery ! agent. See example in conf/main.cf. - Use "disable_vrfy_command = yes" to disable the SMTP VRFY command. This prevents some forms of address harvesting. --- 77,85 ---- domains that are defined by Postfix virtual maps. - The SMTP server can reject mail for unknown local users. Specify ! "local_recipient_maps = $alias_maps, unix:passwd.byname" if your ! local mail is delivered by a UNIX-style local delivery agent. See ! example in conf/main.cf. - Use "disable_vrfy_command = yes" to disable the SMTP VRFY command. This prevents some forms of address harvesting. diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/cleanup/cleanup.c ./cleanup/cleanup.c *** ../postfix-19991231-pl02/cleanup/cleanup.c Fri Aug 13 10:16:22 1999 --- ./cleanup/cleanup.c Thu Jan 27 20:17:48 2000 *************** *** 267,280 **** * If the client requests us to do the bouncing in case of problems, * throw away the input only in case of real show-stopper errors, such as * unrecognizable data (which should never happen) or insufficient space ! * for the queue file (which will happen occasionally). Otherwise, throw ! * away the input after any error. See the CLEANUP_OUT_OK() definition. */ if (cleanup_flags & CLEANUP_FLAG_BOUNCE) { cleanup_err_mask = (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE | CLEANUP_STAT_SIZE); } else { ! cleanup_err_mask = ~0; } /* --- 267,281 ---- * If the client requests us to do the bouncing in case of problems, * throw away the input only in case of real show-stopper errors, such as * unrecognizable data (which should never happen) or insufficient space ! * for the queue file (which will happen occasionally). Otherwise, ! * discard input after any lethal error. See the CLEANUP_OUT_OK() ! * definition. */ if (cleanup_flags & CLEANUP_FLAG_BOUNCE) { cleanup_err_mask = (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE | CLEANUP_STAT_SIZE); } else { ! cleanup_err_mask = CLEANUP_STAT_LETHAL; } /* *************** *** 321,338 **** * file in the first place). * * Do not log the arrival of a message that will be bounced by the client. */ #define CAN_BOUNCE() \ ((cleanup_errs & (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE)) == 0 \ && cleanup_sender != 0 \ && (cleanup_flags & CLEANUP_FLAG_BOUNCE) != 0) ! if (cleanup_errs) { if (CAN_BOUNCE()) { if (bounce_append(BOUNCE_FLAG_CLEAN, cleanup_queue_id, cleanup_recip ? cleanup_recip : "", "cleanup", cleanup_time, ! "%s", cleanup_strerror(cleanup_errs)) == 0 && bounce_flush(BOUNCE_FLAG_CLEAN, MAIL_QUEUE_INCOMING, cleanup_queue_id, cleanup_sender) == 0) { --- 322,348 ---- * file in the first place). * * Do not log the arrival of a message that will be bounced by the client. + * + * XXX CLEANUP_STAT_LETHAL masks errors that are not directly fatal (e.g., + * header buffer overflow is normally allowed to happen), but that can + * indirectly become a problem (e.g., no recipients were extracted from + * message headers because we could not process all the message headers). + * However, cleanup_strerror() prioritizes errors so that it can report + * the cause (e.g., header buffer overflow), which is more useful. + * Amazing. */ #define CAN_BOUNCE() \ ((cleanup_errs & (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE)) == 0 \ && cleanup_sender != 0 \ && (cleanup_flags & CLEANUP_FLAG_BOUNCE) != 0) ! if (cleanup_errs & CLEANUP_STAT_LETHAL) { if (CAN_BOUNCE()) { if (bounce_append(BOUNCE_FLAG_CLEAN, cleanup_queue_id, cleanup_recip ? cleanup_recip : "", "cleanup", cleanup_time, ! "Message rejected: %s", ! cleanup_strerror(cleanup_errs)) == 0 && bounce_flush(BOUNCE_FLAG_CLEAN, MAIL_QUEUE_INCOMING, cleanup_queue_id, cleanup_sender) == 0) { *************** *** 354,360 **** */ junk = cleanup_path; cleanup_path = 0; /* don't delete upon error */ ! mail_print(cleanup_src, "%d", cleanup_errs);/* we're committed now */ if (msg_verbose) msg_info("cleanup_service: status %d", cleanup_errs); myfree(junk); --- 364,371 ---- */ junk = cleanup_path; cleanup_path = 0; /* don't delete upon error */ ! mail_print(cleanup_src, "%d", /* we're committed now */ ! cleanup_errs & CLEANUP_STAT_LETHAL); if (msg_verbose) msg_info("cleanup_service: status %d", cleanup_errs); myfree(junk); diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/cleanup/cleanup_extracted.c ./cleanup/cleanup_extracted.c *** ../postfix-19991231-pl02/cleanup/cleanup_extracted.c Wed Aug 18 19:39:26 1999 --- ./cleanup/cleanup_extracted.c Sat Jan 22 15:08:51 2000 *************** *** 119,128 **** /* * Optionally account for missing recipient envelope records. * * XXX Code duplication from cleanup_envelope.c. This should be in one * place. */ ! if (cleanup_recip == 0) { rcpt = (cleanup_resent[0] ? cleanup_resent_recip : cleanup_recipients); if (*var_always_bcc && rcpt->argv[0]) { clean_addr = vstring_alloc(100); --- 119,131 ---- /* * Optionally account for missing recipient envelope records. * + * Don't extract recipients when some header was too long. We have + * incomplete information. + * * XXX Code duplication from cleanup_envelope.c. This should be in one * place. */ ! if (cleanup_recip == 0 && (cleanup_errs & CLEANUP_STAT_HOVFL) == 0) { rcpt = (cleanup_resent[0] ? cleanup_resent_recip : cleanup_recipients); if (*var_always_bcc && rcpt->argv[0]) { clean_addr = vstring_alloc(100); diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/cleanup/cleanup_message.c ./cleanup/cleanup_message.c *** ../postfix-19991231-pl02/cleanup/cleanup_message.c Wed Nov 3 20:09:45 1999 --- ./cleanup/cleanup_message.c Thu Jan 27 20:27:59 2000 *************** *** 408,415 **** * header record does not fit in a REC_TYPE_NORM type record. */ if (VSTRING_LEN(cleanup_header_buf) > 0) { ! if (VSTRING_LEN(cleanup_header_buf) < var_header_limit ! && type == REC_TYPE_NORM && ISSPACE(*start)) { VSTRING_ADDCH(cleanup_header_buf, '\n'); vstring_strcat(cleanup_header_buf, start); continue; --- 408,417 ---- * header record does not fit in a REC_TYPE_NORM type record. */ if (VSTRING_LEN(cleanup_header_buf) > 0) { ! if ((VSTRING_LEN(cleanup_header_buf) >= var_header_limit ! || type != REC_TYPE_NORM)) { ! cleanup_errs |= CLEANUP_STAT_HOVFL; ! } else if (ISSPACE(*start)) { VSTRING_ADDCH(cleanup_header_buf, '\n'); vstring_strcat(cleanup_header_buf, start); continue; *************** *** 431,438 **** * immediately followed by a non-empty message body. */ if (in_header ! && (VSTRING_LEN(cleanup_header_buf) >= var_header_limit ! || type != REC_TYPE_NORM || !is_header(start))) { in_header = 0; cleanup_missing_headers(); --- 433,439 ---- * immediately followed by a non-empty message body. */ if (in_header ! && ((cleanup_errs & CLEANUP_STAT_HOVFL) || !is_header(start))) { in_header = 0; cleanup_missing_headers(); diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/conf/main.cf ./conf/main.cf *** ../postfix-19991231-pl02/conf/main.cf Sun Jan 2 14:19:11 2000 --- ./conf/main.cf Thu Jan 6 09:52:45 2000 *************** *** 128,134 **** # FOR THIS TO WORK, DO NOT SPECIFY VIRTUAL DOMAINS IN MYDESTINATION. # MYDESTINATION MUST LIST NON-VIRTUAL DOMAINS ONLY. # ! #local_recipient_maps = $relocated_maps $alias_maps unix:passwd.byname # ADDRESS REWRITING # --- 128,134 ---- # FOR THIS TO WORK, DO NOT SPECIFY VIRTUAL DOMAINS IN MYDESTINATION. # MYDESTINATION MUST LIST NON-VIRTUAL DOMAINS ONLY. # ! #local_recipient_maps = $alias_maps unix:passwd.byname # ADDRESS REWRITING # diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/global/cleanup_strerror.c ./global/cleanup_strerror.c *** ../postfix-19991231-pl02/global/cleanup_strerror.c Fri Dec 11 13:55:23 1998 --- ./global/cleanup_strerror.c Sat Jan 22 15:15:52 2000 *************** *** 39,45 **** /* * Mapping from status code to printable string. One message may suffer from * multiple errors, to it is important to list the most severe errors first, ! * because the result of lookup can be only one string. */ struct cleanup_stat_map { unsigned status; --- 39,46 ---- /* * Mapping from status code to printable string. One message may suffer from * multiple errors, to it is important to list the most severe errors first, ! * or to list the cause (header overflow) before the effect (no recipients), ! * because cleanup_strerror() can report only one error. */ struct cleanup_stat_map { unsigned status; *************** *** 48,53 **** --- 49,55 ---- static struct cleanup_stat_map cleanup_stat_map[] = { CLEANUP_STAT_BAD, "Internal protocol error", + CLEANUP_STAT_HOVFL, "Message header too long", CLEANUP_STAT_RCPT, "No recipients specified", CLEANUP_STAT_HOPS, "Too many hops", CLEANUP_STAT_SIZE, "Message file too big", diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/global/cleanup_user.h ./global/cleanup_user.h *** ../postfix-19991231-pl02/global/cleanup_user.h Fri Dec 11 13:55:24 1998 --- ./global/cleanup_user.h Mon Jan 24 12:32:01 2000 *************** *** 31,36 **** --- 31,39 ---- #define CLEANUP_STAT_HOPS (1<<4) /* Too many hops */ #define CLEANUP_STAT_SYN (1<<5) /* Bad address syntax */ #define CLEANUP_STAT_RCPT (1<<6) /* No recipients found */ + #define CLEANUP_STAT_HOVFL (1<<7) /* Header overflow */ + + #define CLEANUP_STAT_LETHAL (~CLEANUP_STAT_HOVFL) /* lethal errors */ extern const char *cleanup_strerror(unsigned); diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/global/mail_params.h ./global/mail_params.h *** ../postfix-19991231-pl02/global/mail_params.h Mon Dec 27 14:17:32 1999 --- ./global/mail_params.h Thu Jan 27 21:05:29 2000 *************** *** 420,425 **** --- 420,426 ---- #define VAR_QMGR_ACT_LIMIT "qmgr_message_active_limit" #define DEF_QMGR_ACT_LIMIT 1000 + extern int var_qmgr_active_limit; #define VAR_QMGR_RCPT_LIMIT "qmgr_message_recipient_limit" #define DEF_QMGR_RCPT_LIMIT 10000 *************** *** 429,434 **** --- 430,439 ---- #define DEF_QMGR_FUDGE 100 extern int var_qmgr_fudge; + #define VAR_QMGR_HOG "qmgr_site_hog_factor" + #define DEF_QMGR_HOG 90 + extern int var_qmgr_hog; + /* * Queue manager: default destination concurrency levels. */ *************** *** 437,442 **** --- 442,448 ---- extern int var_init_dest_concurrency; #define VAR_DEST_CON_LIMIT "default_destination_concurrency_limit" + #define _DEST_CON_LIMIT "_destination_concurrency_limit" #define DEF_DEST_CON_LIMIT 10 extern int var_dest_con_limit; *************** *** 444,451 **** --- 450,461 ---- * Queue manager: default number of recipients per transaction. */ #define VAR_DEST_RCPT_LIMIT "default_destination_recipient_limit" + #define _DEST_RCPT_LIMIT "_destination_recipient_limit" #define DEF_DEST_RCPT_LIMIT 50 extern int var_dest_rcpt_limit; + + #define VAR_LOCAL_RCPT_LIMIT "local" _DEST_RCPT_LIMIT /* XXX */ + #define DEF_LOCAL_RCPT_LIMIT 1 /* XXX */ /* * Queue manager: default delay before retrying a dead transport. diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/global/mail_queue.c ./global/mail_queue.c *** ../postfix-19991231-pl02/global/mail_queue.c Tue Feb 16 11:25:22 1999 --- ./global/mail_queue.c Thu Jan 27 20:35:57 2000 *************** *** 299,304 **** --- 299,305 ---- int fd; const char *file_id; VSTREAM *stream; + int count; /* * Initialize. *************** *** 349,358 **** file_id = get_file_id(fd); GETTIMEOFDAY(&tv); ! for (;;) { vstring_sprintf(id_buf, "%05X%s", (int) tv.tv_usec, file_id); mail_queue_path(path_buf, queue_name, STR(id_buf)); ! if (rename(STR(temp_path), STR(path_buf)) == 0) /* success */ break; if (errno == EPERM || errno == EISDIR) {/* collision. weird. */ if ((int) ++tv.tv_usec < 0) --- 350,359 ---- file_id = get_file_id(fd); GETTIMEOFDAY(&tv); ! for (count = 0;; count++) { vstring_sprintf(id_buf, "%05X%s", (int) tv.tv_usec, file_id); mail_queue_path(path_buf, queue_name, STR(id_buf)); ! if (sane_rename(STR(temp_path), STR(path_buf)) == 0) /* success */ break; if (errno == EPERM || errno == EISDIR) {/* collision. weird. */ if ((int) ++tv.tv_usec < 0) *************** *** 362,369 **** if (errno != ENOENT || mail_queue_mkdirs(STR(path_buf)) < 0) { msg_warn("%s: rename %s to %s: %m", myname, STR(temp_path), STR(path_buf)); - sleep(10); } } stream = vstream_fdopen(fd, O_RDWR); --- 363,372 ---- if (errno != ENOENT || mail_queue_mkdirs(STR(path_buf)) < 0) { msg_warn("%s: rename %s to %s: %m", myname, STR(temp_path), STR(path_buf)); } + if (count > 1000) /* XXX whatever */ + msg_fatal("%s: rename %s to %s: giving up", myname, + STR(temp_path), STR(path_buf)); } stream = vstream_fdopen(fd, O_RDWR); diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/html/faq.html ./html/faq.html *** ../postfix-19991231-pl02/html/faq.html Sun Jan 2 17:24:04 2000 --- ./html/faq.html Sat Jan 22 15:59:30 2000 *************** *** 87,92 **** --- 87,94 ----
  • Postfix breaks the majordomo "approve" command +
  • Postfix accepts MAIL FROM/RCPT TO "|command" +

    Mail relaying

    *************** *** 1157,1163 ****
          /etc/postfix/main.cf:
    ! 	local_recipient_maps = $relocated_maps $alias_maps, unix:passwd.byname
      

    --- 1159,1165 ----

          /etc/postfix/main.cf:
    ! 	local_recipient_maps = $alias_maps, unix:passwd.byname
      

    *************** *** 1446,1451 **** --- 1448,1496 ---- when delivering to commands such as majordomo. See the FAQ entry titled "Getting rid of the ugly Delivered-To: header". + +


    + +

    Postfix accepts MAIL FROM and RCPT TO "|command"

    + + With Postfix, | or / has special meaning only when it appears in + aliases, .forward files or in :include: files. It has no special + meaning in mail addresses. + +

    + + If you must receive mail for systems with 10-year old vulnerabilities, + it is prudent to set up a regexp filter that rejects potentially + harmful MAIL FROM or RCPT TO commands. + +

    + +

    +     /etc/postfix/main.cf:
    + 	smtpd_sender_restrictions =
    + 	    regexp:/etc/postfix/envelope-regexp
    + 	    reject_unknown_sender_domain
    + 	smtpd_recipient_restrictions =
    + 	    regexp:/etc/postfix/envelope-regexp
    + 	    permit_mynetworks
    + 	    check_relay_domains
    + 
    +     /etc/postfix/envelope-regexp:
    + 	/[/|]/	REJECT
    + 
    + +

    + + However, rejecting all envelope addresses with / causes trouble + with simple-minded X.400 to Internet address mappings that leave + the X.400 address structure exposed. + +

    + + See also the documentation on header + checks restrictions for message header contents. These restrictions + can be used to protect against attacks with command/file destinations + in, for example, Errors-To: or Return-Receipt_To: message headers.


    diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/html/qmgr.8.html ./html/qmgr.8.html *** ../postfix-19991231-pl02/html/qmgr.8.html Mon Dec 20 21:00:57 1999 --- ./html/qmgr.8.html Thu Jan 27 19:16:12 2000 *************** *** 289,328 **** list receive that same burst of messages a whole day later. initial_destination_concurrency ! Initial per-destination concurrency level for par- allel delivery to the same destination. default_destination_concurrency_limit ! Default limit on the number of parallel deliveries to the same destination. transport_destination_concurrency_limit ! Limit on the number of parallel deliveries to the ! same destination, for delivery via the named mes- sage transport. Recipient controls default_destination_recipient_limit ! Default limit on the number of recipients per mes- sage transfer. transport_destination_recipient_limit ! Limit on the number of recipients per message transfer, for the named message transport. - SEE ALSO - master(8), process manager - relocated(5), format of the "user has moved" table - syslogd(8) system logging - trivial-rewrite(8), address routing - - LICENSE - The Secure Mailer license must be distributed with this - software. - - AUTHOR(S) - Wietse Venema --- 289,328 ---- list receive that same burst of messages a whole day later. + qmgr_site_hog_factor (valid range: 10..100) + The percentage of delivery resources that a busy + mail system will use up for delivery to a single + site. With 100%, mail is delivered in first-in, + first-out order, so that a burst of mail for one + site can block mail for other destinations. With + less than 100%, the excess mail is deferred. The + deferred mail is delivered in little bursts, the + remainder of the backlog being deferred again, with + a lot of I/O activity happening as Postfix searches + the deferred queue for deliverable mail. + initial_destination_concurrency ! Initial per-destination concurrency level for par- allel delivery to the same destination. default_destination_concurrency_limit ! Default limit on the number of parallel deliveries to the same destination. transport_destination_concurrency_limit ! Limit on the number of parallel deliveries to the ! same destination, for delivery via the named mes- sage transport. Recipient controls default_destination_recipient_limit ! Default limit on the number of recipients per mes- sage transfer. transport_destination_recipient_limit ! Limit on the number of recipients per message transfer, for the named message transport. *************** *** 335,355 **** QMGR(8) QMGR(8) IBM T.J. Watson Research P.O. Box 704 Yorktown Heights, NY 10598, USA - - - - - - - - - - - - --- 335,355 ---- QMGR(8) QMGR(8) + SEE ALSO + master(8), process manager + relocated(5), format of the "user has moved" table + syslogd(8) system logging + trivial-rewrite(8), address routing + + LICENSE + The Secure Mailer license must be distributed with this + software. + + AUTHOR(S) + Wietse Venema IBM T.J. Watson Research P.O. Box 704 Yorktown Heights, NY 10598, USA diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/local/maildir.c ./local/maildir.c *** ../postfix-19991231-pl02/local/maildir.c Sun Jun 27 17:14:47 1999 --- ./local/maildir.c Sat Jan 22 16:35:41 2000 *************** *** 53,58 **** --- 53,59 ---- #include #include #include + #include /* Global library. */ *************** *** 136,145 **** vstring_sprintf(why, "create %s: %m", tmpfile); } else { if (mail_copy(COPY_ATTR(state.msg_attr), dst, copy_flags, why) == 0) { ! if (link(tmpfile, newfile) < 0 && (errno != ENOENT || (make_dirs(curdir, 0700), make_dirs(newdir, 0700)) < 0 ! || link(tmpfile, newfile) < 0)) { vstring_sprintf(why, "link to %s: %m", newfile); } else { if (unlink(tmpfile) < 0) --- 137,146 ---- vstring_sprintf(why, "create %s: %m", tmpfile); } else { if (mail_copy(COPY_ATTR(state.msg_attr), dst, copy_flags, why) == 0) { ! if (sane_link(tmpfile, newfile) < 0 && (errno != ENOENT || (make_dirs(curdir, 0700), make_dirs(newdir, 0700)) < 0 ! || sane_link(tmpfile, newfile) < 0)) { vstring_sprintf(why, "link to %s: %m", newfile); } else { if (unlink(tmpfile) < 0) diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/makedefs ./makedefs *** ../postfix-19991231-pl02/makedefs Fri Dec 17 22:57:53 1999 --- ./makedefs Sat Jan 22 14:04:27 2000 *************** *** 51,67 **** SYSTEM=`(uname -s) 2>/dev/null` RELEASE=`(uname -r) 2>/dev/null` case "$SYSTEM.$RELEASE" in UnixWare.5*) SYSTYPE=UW7 ! CC=cc ! DEBUG= RANLIB=echo SYSLIBS="-lresolv -lsocket -lnsl" ;; UNIX_SV.4.2*) case "`uname -v`" in 2.1*) SYSTYPE=UW21 ! CC=/usr/bin/cc RANLIB=echo SYSLIBS="-lresolv -lsocket -lnsl -lc -L/usr/ucblib -lucb" ;; --- 51,81 ---- SYSTEM=`(uname -s) 2>/dev/null` RELEASE=`(uname -r) 2>/dev/null` + VERSION=`(uname -v) 2>/dev/null` + + case "$VERSION" in + dcosx*) SYSTEM=$VERSION;; + esac case "$SYSTEM.$RELEASE" in + SCO_SV.3.2) SYSTYPE=SCO5 + # Use the native compiler by default + : ${CC="/usr/bin/cc -b elf"} + : ${DEBUG=} + SYSLIBS="-lsocket -ldbm" + RANLIB=echo + ;; UnixWare.5*) SYSTYPE=UW7 ! # Use the native compiler by default ! : ${CC=/usr/bin/cc} ! : ${DEBUG=} RANLIB=echo SYSLIBS="-lresolv -lsocket -lnsl" ;; UNIX_SV.4.2*) case "`uname -v`" in 2.1*) SYSTYPE=UW21 ! # Use the native compiler by default ! : ${CC=/usr/bin/cc} RANLIB=echo SYSLIBS="-lresolv -lsocket -lnsl -lc -L/usr/ucblib -lucb" ;; *************** *** 195,200 **** --- 209,219 ---- : ${CC=cc} AWK=gawk ;; + dcosx.1*) SYSTYPE=DCOSX1 + RANLIB=echo + SYSLIBS="-lresolv -lsocket -lnsl -lc -lrpcsvc -L/usr/ucblib -lucb" + ;; + ".") if [ -d /NextApps ]; then SYSTYPE=`hostinfo | sed -n \ 's/^.*NeXT Mach 3.*$/NEXTSTEP3/;/NEXTSTEP3/{p;q;}'` diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/man/man8/qmgr.8 ./man/man8/qmgr.8 *** ../postfix-19991231-pl02/man/man8/qmgr.8 Mon Dec 20 21:00:51 1999 --- ./man/man8/qmgr.8 Thu Jan 27 19:16:03 2000 *************** *** 223,228 **** --- 223,237 ---- case, recipients near the beginning of a large list receive a burst of messages immediately, while recipients near the end of that list receive that same burst of messages a whole day later. + .IP "\fBqmgr_site_hog_factor\fR (valid range: 10..100)" + The percentage of delivery resources that a busy mail system will + use up for delivery to a single site. + With 100%, mail is delivered in first-in, first-out order, so that + a burst of mail for one site can block mail for other destinations. + With less than 100%, the excess mail is deferred. The deferred mail + is delivered in little bursts, the remainder of the backlog being + deferred again, with a lot of I/O activity happening as Postfix + searches the deferred queue for deliverable mail. .IP \fBinitial_destination_concurrency\fR Initial per-destination concurrency level for parallel delivery to the same destination. diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/master/master_sig.c ./master/master_sig.c *** ../postfix-19991231-pl02/master/master_sig.c Thu Feb 4 20:07:40 1999 --- ./master/master_sig.c Sat Jan 15 16:15:03 2000 *************** *** 159,165 **** char *myname = "master_sigsetup"; struct sigaction action; static int sigs[] = { ! SIGINT, SIGQUIT, SIGSEGV, SIGILL, SIGTERM, }; unsigned i; --- 159,165 ---- char *myname = "master_sigsetup"; struct sigaction action; static int sigs[] = { ! SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGSEGV, SIGTERM, }; unsigned i; diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/postconf/local_table.h ./postconf/local_table.h *** ../postfix-19991231-pl02/postconf/local_table.h Mon Dec 7 19:36:05 1998 --- ./postconf/local_table.h Thu Jan 27 20:42:24 2000 *************** *** 1,2 **** "local_destination_concurrency_limit", "$default_destination_concurrency_limit", &var_local_destination_concurrency_limit, 0, 0, - "local_destination_recipient_limit", "$default_destination_recipient_limit", &var_local_destination_recipient_limit, 0, 0, --- 1 ---- diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/postconf/local_vars.h ./postconf/local_vars.h *** ../postfix-19991231-pl02/postconf/local_vars.h Mon Dec 7 19:35:08 1998 --- ./postconf/local_vars.h Thu Jan 27 20:42:36 2000 *************** *** 1,2 **** char *var_local_destination_concurrency_limit; - char *var_local_destination_recipient_limit; --- 1 ---- diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/qmgr/qmgr.c ./qmgr/qmgr.c *** ../postfix-19991231-pl02/qmgr/qmgr.c Sat Dec 11 18:20:08 1999 --- ./qmgr/qmgr.c Thu Jan 27 20:47:53 2000 *************** *** 193,204 **** /* use up for delivery of a large mailing list message. /* With 100%, delivery of one message does not begin before the previous /* message has been delivered. This results in good performance for large ! /* mailing lists, but results in poor response time for one-to-one mail. /* With less than 100%, response time for one-to-one mail improves, /* but large mailing list delivery performance suffers. In the worst /* case, recipients near the beginning of a large list receive a burst /* of messages immediately, while recipients near the end of that list /* receive that same burst of messages a whole day later. /* .IP \fBinitial_destination_concurrency\fR /* Initial per-destination concurrency level for parallel delivery /* to the same destination. --- 193,213 ---- /* use up for delivery of a large mailing list message. /* With 100%, delivery of one message does not begin before the previous /* message has been delivered. This results in good performance for large ! /* mailing lists, but results in poor response time for one-to-one mail. /* With less than 100%, response time for one-to-one mail improves, /* but large mailing list delivery performance suffers. In the worst /* case, recipients near the beginning of a large list receive a burst /* of messages immediately, while recipients near the end of that list /* receive that same burst of messages a whole day later. + /* .IP "\fBqmgr_site_hog_factor\fR (valid range: 10..100)" + /* The percentage of delivery resources that a busy mail system will + /* use up for delivery to a single site. + /* With 100%, mail is delivered in first-in, first-out order, so that + /* a burst of mail for one site can block mail for other destinations. + /* With less than 100%, the excess mail is deferred. The deferred mail + /* is delivered in little bursts, the remainder of the backlog being + /* deferred again, with a lot of I/O activity happening as Postfix + /* searches the deferred queue for deliverable mail. /* .IP \fBinitial_destination_concurrency\fR /* Initial per-destination concurrency level for parallel delivery /* to the same destination. *************** *** 280,286 **** char *var_virtual_maps; char *var_defer_xports; bool var_allow_min_user; ! bool var_qmgr_fudge; static QMGR_SCAN *qmgr_incoming; static QMGR_SCAN *qmgr_deferred; --- 289,297 ---- char *var_virtual_maps; char *var_defer_xports; bool var_allow_min_user; ! int var_qmgr_fudge; ! int var_qmgr_hog; ! int var_local_rcpt_lim; /* XXX */ static QMGR_SCAN *qmgr_incoming; static QMGR_SCAN *qmgr_deferred; *************** *** 474,479 **** --- 485,492 ---- VAR_DEST_CON_LIMIT, DEF_DEST_CON_LIMIT, &var_dest_con_limit, 0, 0, VAR_DEST_RCPT_LIMIT, DEF_DEST_RCPT_LIMIT, &var_dest_rcpt_limit, 0, 0, VAR_QMGR_FUDGE, DEF_QMGR_FUDGE, &var_qmgr_fudge, 10, 100, + VAR_QMGR_HOG, DEF_QMGR_HOG, &var_qmgr_hog, 10, 100, + VAR_LOCAL_RCPT_LIMIT, DEF_LOCAL_RCPT_LIMIT, &var_local_rcpt_lim, 0, 0, 0, }; static CONFIG_BOOL_TABLE bool_table[] = { diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/qmgr/qmgr_message.c ./qmgr/qmgr_message.c *** ../postfix-19991231-pl02/qmgr/qmgr_message.c Thu Dec 23 20:04:42 1999 --- ./qmgr/qmgr_message.c Thu Jan 27 19:14:29 2000 *************** *** 528,535 **** --- 528,537 ---- */ if ((at = strrchr(STR(reply.recipient), '@')) == 0 || resolve_local(at + 1)) { + #if 0 vstring_strcpy(reply.nexthop, STR(reply.recipient)); (void) split_at_right(STR(reply.nexthop), '@'); + #endif #if 0 if (*var_rcpt_delim) (void) split_addr(STR(reply.nexthop), *var_rcpt_delim); *************** *** 541,547 **** * have to configure something for mail directed to the local * postmaster, though, but that is an RFC requirement anyway. */ ! if (strcasecmp(STR(reply.nexthop), var_double_bounce_sender) == 0) { sent(message->queue_id, recipient->address, "none", message->arrival_time, "discarded"); deliver_completed(message->fp, recipient->offset); --- 543,551 ---- * have to configure something for mail directed to the local * postmaster, though, but that is an RFC requirement anyway. */ ! if (strncasecmp(STR(reply.recipient), var_double_bounce_sender, ! at - STR(reply.recipient)) == 0 ! && !var_double_bounce_sender[at - STR(reply.recipient)]) { sent(message->queue_id, recipient->address, "none", message->arrival_time, "discarded"); deliver_completed(message->fp, recipient->offset); *************** *** 609,614 **** --- 613,635 ---- if (queue->window == 0) { qmgr_defer_recipient(message, recipient->address, queue->reason); continue; + } + + /* + * This queue is a hog. Defer this recipient until the queue drains. + * When a site accumulates a large backlog, Postfix will deliver a + * little chunk and hammer the disk as it defers the remainder of the + * backlog and searches the deferred queue for deliverable mail. + */ + if (var_qmgr_hog < 100) { + if (queue->todo_refcount + queue->busy_refcount + > (var_qmgr_hog / 100.0) + * (qmgr_recipient_count > 0.8 * var_qmgr_rcpt_limit ? + qmgr_message_count : var_qmgr_active_limit)) { + qmgr_defer_recipient(message, recipient->address, + "site destination queue overflow"); + continue; + } } /* diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/smtp/smtp_trouble.c ./smtp/smtp_trouble.c *** ../postfix-19991231-pl02/smtp/smtp_trouble.c Wed Jun 23 21:14:24 1999 --- ./smtp/smtp_trouble.c Mon Jan 24 12:22:46 2000 *************** *** 134,139 **** --- 134,140 ---- * anti-UCE systems, by people who aren't aware of RFC details. */ if ((!SMTP_SOFT(code) && !SMTP_HARD(code)) + || code == 555 /* RFC 1869, section 6.1. */ || (code >= 500 && code < 510)) state->error_mask |= MAIL_ERROR_PROTOCOL; } diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/smtpd/smtpd.c ./smtpd/smtpd.c *** ../postfix-19991231-pl02/smtpd/smtpd.c Mon Dec 27 14:19:41 1999 --- ./smtpd/smtpd.c Thu Jan 6 09:55:48 2000 *************** *** 302,307 **** --- 302,308 ---- char *var_canonical_maps; char *var_rcpt_canon_maps; char *var_virtual_maps; + char *var_relocated_maps; char *var_alias_maps; char *var_local_rcpt_maps; bool var_allow_untrust_route; *************** *** 1347,1352 **** --- 1348,1354 ---- VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, 0, 0, VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps, 0, 0, VAR_VIRTUAL_MAPS, DEF_VIRTUAL_MAPS, &var_virtual_maps, 0, 0, + VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocated_maps, 0, 0, VAR_ALIAS_MAPS, DEF_ALIAS_MAPS, &var_alias_maps, 0, 0, VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, 0, 0, 0, diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/smtpd/smtpd_check.c ./smtpd/smtpd_check.c *** ../postfix-19991231-pl02/smtpd/smtpd_check.c Tue Jan 4 08:11:52 2000 --- ./smtpd/smtpd_check.c Thu Jan 6 09:56:16 2000 *************** *** 312,317 **** --- 312,318 ---- static MAPS *rcpt_canon_maps; static MAPS *canonical_maps; static MAPS *virtual_maps; + static MAPS *relocated_maps; /* * Pre-opened access control lists. *************** *** 455,460 **** --- 456,463 ---- DICT_FLAG_LOCK); virtual_maps = maps_create(VAR_VIRTUAL_MAPS, var_virtual_maps, DICT_FLAG_LOCK); + relocated_maps = maps_create(VAR_RELOCATED_MAPS, var_relocated_maps, + DICT_FLAG_LOCK); /* * Reply is used as a cache for resolved addresses, and error_text is *************** *** 1969,1974 **** --- 1972,1978 ---- if (*var_local_rcpt_maps && !mail_addr_find(rcpt_canon_maps, STR(reply.recipient), NOP) && !mail_addr_find(canonical_maps, STR(reply.recipient), NOP) + && !mail_addr_find(relocated_maps, STR(reply.recipient), NOP) && !mail_addr_find(local_rcpt_maps, STR(reply.recipient), NOP)) { (void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE, "550 <%s>: User unknown", recipient); *************** *** 1978,1983 **** --- 1982,1988 ---- if (*var_virtual_maps && !mail_addr_find(rcpt_canon_maps, STR(reply.recipient), NOP) && !mail_addr_find(canonical_maps, STR(reply.recipient), NOP) + && !mail_addr_find(relocated_maps, STR(reply.recipient), NOP) && !mail_addr_find(virtual_maps, STR(reply.recipient), NOP) && maps_find(virtual_maps, domain, 0)) { (void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE, *************** *** 2064,2069 **** --- 2069,2075 ---- char *var_rcpt_canon_maps; char *var_canonical_maps; char *var_virtual_maps; + char *var_relocated_maps; char *var_local_rcpt_maps; typedef struct { *************** *** 2081,2086 **** --- 2087,2093 ---- VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps, VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, VAR_VIRTUAL_MAPS, DEF_VIRTUAL_MAPS, &var_virtual_maps, + VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocated_maps, VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, 0, }; diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/util/Makefile.in ./util/Makefile.in *** ../postfix-19991231-pl02/util/Makefile.in Thu Dec 30 16:54:00 1999 --- ./util/Makefile.in Mon Jan 24 12:32:49 2000 *************** *** 20,26 **** vstream.c vstream_popen.c vstring.c vstring_vstream.c writable.c \ write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \ stream_connect.c stream_trigger.c dict_regexp.c mac_expand.c \ ! clean_env.c watchdog.c spawn_command.c OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \ close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \ dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \ --- 20,26 ---- vstream.c vstream_popen.c vstring.c vstring_vstream.c writable.c \ write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \ stream_connect.c stream_trigger.c dict_regexp.c mac_expand.c \ ! clean_env.c watchdog.c spawn_command.c sane_rename.c sane_link.c OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \ close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \ dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \ *************** *** 42,48 **** vstream.o vstream_popen.o vstring.o vstring_vstream.o writable.o \ write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \ stream_connect.o stream_trigger.o dict_regexp.o mac_expand.o \ ! clean_env.o watchdog.o spawn_command.o HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \ dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \ dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \ --- 42,48 ---- vstream.o vstream_popen.o vstring.o vstring_vstream.o writable.o \ write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \ stream_connect.o stream_trigger.o dict_regexp.o mac_expand.o \ ! clean_env.o watchdog.o spawn_command.o sane_rename.o sane_link.o HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \ dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \ dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \ *************** *** 57,63 **** timed_connect.h timed_wait.h trigger.h username.h valid_hostname.h \ vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \ dict_unix.h dict_pcre.h dict_regexp.h mac_expand.h clean_env.h \ ! watchdog.h spawn_command.h TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \ stream_test.c dup2_pass_on_exec.c WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ --- 57,63 ---- timed_connect.h timed_wait.h trigger.h username.h valid_hostname.h \ vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \ dict_unix.h dict_pcre.h dict_regexp.h mac_expand.h clean_env.h \ ! watchdog.h spawn_command.h sane_fsops.h TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \ stream_test.c dup2_pass_on_exec.c WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ *************** *** 716,721 **** --- 716,729 ---- sane_accept.o: sane_accept.c sane_accept.o: sys_defs.h sane_accept.o: sane_accept.h + sane_link.o: sane_link.c + sane_link.o: sys_defs.h + sane_link.o: msg.h + sane_link.o: sane_fsops.h + sane_rename.o: sane_rename.c + sane_rename.o: sys_defs.h + sane_rename.o: msg.h + sane_rename.o: sane_fsops.h scan_dir.o: scan_dir.c scan_dir.o: sys_defs.h scan_dir.o: msg.h diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/util/make_dirs.c ./util/make_dirs.c *** ../postfix-19991231-pl02/util/make_dirs.c Fri Dec 11 13:55:38 1998 --- ./util/make_dirs.c Sat Jan 15 22:02:04 2000 *************** *** 72,80 **** SKIP_WHILE(*cp != '/', cp); if ((saved_ch = *cp) != 0) *cp = 0; ! if ((ret = stat(saved_path, &st)) < 0) ! if (errno != ENOENT || (ret = mkdir(saved_path, perms)) < 0) break; if (saved_ch != 0) *cp = saved_ch; SKIP_WHILE(*cp == '/', cp); --- 72,85 ---- SKIP_WHILE(*cp != '/', cp); if ((saved_ch = *cp) != 0) *cp = 0; ! if ((ret = stat(saved_path, &st)) >= 0) { ! if (!S_ISDIR(st.st_mode)) { ! errno = ENOTDIR; ! ret = -1; break; + } + } else if (errno != ENOENT || (ret = mkdir(saved_path, perms)) < 0) + break; if (saved_ch != 0) *cp = saved_ch; SKIP_WHILE(*cp == '/', cp); diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/util/sane_fsops.h ./util/sane_fsops.h *** ../postfix-19991231-pl02/util/sane_fsops.h Wed Dec 31 19:00:00 1969 --- ./util/sane_fsops.h Thu Jan 27 20:57:35 2000 *************** *** 0 **** --- 1,30 ---- + #ifndef _SANE_FSOPS_H_ + #define _SANE_FSOPS_H_ + + /*++ + /* NAME + /* sane_rename 3h + /* SUMMARY + /* sanitize rename() error returns + /* SYNOPSIS + /* #include + /* DESCRIPTION + /* .nf + + /* External interface. */ + + extern int sane_rename(const char *, const char *); + extern int sane_link(const char *, const char *); + + /* LICENSE + /* .ad + /* .fi + /* The Secure Mailer license must be distributed with this software. + /* AUTHOR(S) + /* Wietse Venema + /* IBM T.J. Watson Research + /* P.O. Box 704 + /* Yorktown Heights, NY 10598, USA + /*--*/ + + #endif diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/util/sane_link.c ./util/sane_link.c *** ../postfix-19991231-pl02/util/sane_link.c Wed Dec 31 19:00:00 1969 --- ./util/sane_link.c Thu Jan 27 19:39:55 2000 *************** *** 0 **** --- 1,71 ---- + /*++ + /* NAME + /* sane_link 3 + /* SUMMARY + /* sanitize link() error returns + /* SYNOPSIS + /* #include + /* + /* int sane_link(old, new) + /* const char *from; + /* const char *to; + /* DESCRIPTION + /* sane_link() implements the link(2) system call, and works + /* around some errors that are possible with NFS file systems. + /* LICENSE + /* .ad + /* .fi + /* The Secure Mailer license must be distributed with this software. + /* AUTHOR(S) + /* Wietse Venema + /* IBM T.J. Watson Research + /* P.O. Box 704 + /* Yorktown Heights, NY 10598, USA + /*--*/ + + /* System library. */ + + #include "sys_defs.h" + #include + #include + #include + + /* Utility library. */ + + #include "msg.h" + #include "sane_fsops.h" + + /* sane_link - sanitize link() error returns */ + + int sane_link(const char *from, const char *to) + { + char *myname = "sane_link"; + int saved_errno; + struct stat from_st; + struct stat to_st; + + /* + * Normal case: link() succeeds. + */ + if (link(from, to) >= 0) + return (0); + + /* + * Woops. Save errno, and see if the error is an NFS artefact. If it is, + * pretend the error never happened. + */ + saved_errno = errno; + if (stat(from, &from_st) >= 0 && stat(to, &to_st) >= 0 + && from_st.st_dev == to_st.st_dev + && from_st.st_ino == to_st.st_ino) { + msg_info("%s(%s,%s): worked around spurious NFS error", + myname, from, to); + return (0); + } + + /* + * Nope, it didn't. Restore errno and report the error. + */ + errno = saved_errno; + return (-1); + } diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/util/sane_rename.c ./util/sane_rename.c *** ../postfix-19991231-pl02/util/sane_rename.c Wed Dec 31 19:00:00 1969 --- ./util/sane_rename.c Thu Jan 27 19:40:59 2000 *************** *** 0 **** --- 1,68 ---- + /*++ + /* NAME + /* sane_rename 3 + /* SUMMARY + /* sanitize rename() error returns + /* SYNOPSIS + /* #include + /* + /* int sane_rename(old, new) + /* const char *from; + /* const char *to; + /* DESCRIPTION + /* sane_rename() implements the rename(2) system call, and works + /* around some errors that are possible with NFS file systems. + /* LICENSE + /* .ad + /* .fi + /* The Secure Mailer license must be distributed with this software. + /* AUTHOR(S) + /* Wietse Venema + /* IBM T.J. Watson Research + /* P.O. Box 704 + /* Yorktown Heights, NY 10598, USA + /*--*/ + + /* System library. */ + + #include "sys_defs.h" + #include + #include + #include /* rename(2) syscall in stdio.h? */ + + /* Utility library. */ + + #include "msg.h" + #include "sane_fsops.h" + + /* sane_rename - sanitize rename() error returns */ + + int sane_rename(const char *from, const char *to) + { + char *myname = "sane_rename"; + int saved_errno; + struct stat st; + + /* + * Normal case: rename() succeeds. + */ + if (rename(from, to) >= 0) + return (0); + + /* + * Woops. Save errno, and see if the error is an NFS artefact. If it is, + * pretend the error never happened. + */ + saved_errno = errno; + if (stat(from, &st) < 0 && stat(to, &st) >= 0) { + msg_info("%s(%s,%s): worked around spurious NFS error", + myname, from, to); + return (0); + } + + /* + * Nope, it didn't. Restore errno and report the error. + */ + errno = saved_errno; + return (-1); + } diff -cr --exclude-from=/tmp/ignore --new-file ../postfix-19991231-pl02/util/sys_defs.h ./util/sys_defs.h *** ../postfix-19991231-pl02/util/sys_defs.h Wed Nov 17 21:33:35 1999 --- ./util/sys_defs.h Sat Jan 22 16:03:31 2000 *************** *** 62,69 **** #define UNSAFE_CTYPE /* XXX verify */ #define _PATH_MAILDIR "/var/spool/mail" #define _PATH_BSHELL "/bin/sh" ! #define _PATH_DEFPATH "/usr/bin:/usr/ucb" ! #define _PATH_STDPATH "/usr/bin:/usr/etc:/usr/ucb" #define USE_FLOCK_LOCK #define USE_DOT_LOCK #define HAS_FSYNC --- 62,69 ---- #define UNSAFE_CTYPE /* XXX verify */ #define _PATH_MAILDIR "/var/spool/mail" #define _PATH_BSHELL "/bin/sh" ! #define _PATH_DEFPATH "/bin:/usr/bin:/usr/ucb" ! #define _PATH_STDPATH "/bin:/usr/bin:/usr/etc:/usr/ucb" #define USE_FLOCK_LOCK #define USE_DOT_LOCK #define HAS_FSYNC *************** *** 79,84 **** --- 79,85 ---- extern int optind; extern char *optarg; extern int opterr; + extern int h_errno; #define MISSING_STRFTIME_E #define HAS_NIS *************** *** 554,559 **** --- 555,618 ---- #define USE_STATVFS #define STATVFS_IN_SYS_STATVFS_H #define MISSING_USLEEP + #endif + + #ifdef DCOSX1 /* Siemens Pyramid */ + #define SUPPORTED + #include + #define _PATH_MAILDIR "/var/mail" + #define _PATH_BSHELL "/bin/sh" + #define _PATH_DEFPATH "/usr/bin:/usr/ucb" + #define _PATH_STDPATH "/usr/bin:/usr/sbin:/usr/ucb" + #define MISSING_SETENV + #define USE_FCNTL_LOCK + #define USE_DOT_LOCK + #define HAS_FSYNC + #define DEF_DB_TYPE "hash" + #define ALIAS_DB_MAP "hash:/etc/aliases" + /* Uncomment the following line if you have NIS package installed */ + /* #define HAS_NIS */ + #define USE_SYS_SOCKIO_H + #define GETTIMEOFDAY(t) gettimeofday(t,NULL) + #define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb" + #define FIONREAD_IN_SYS_FILIO_H + #define DBM_NO_TRAILING_NULL + #define USE_STATVFS + #define STATVFS_IN_SYS_STATVFS_H + #define UNIX_DOMAIN_CONNECT_BLOCKS_FOR_ACCEPT + #ifndef S_ISSOCK + #define S_ISSOCK(mode) ((mode&0xF000) == 0xC000) + #endif + #endif + + #ifdef SCO5 + #define SUPPORTED + #include + #include + extern int h_errno; + #define _PATH_MAILDIR "/usr/spool/mail" + #define _PATH_BSHELL "/bin/sh" + #define _PATH_DEFPATH "/bin:/usr/bin" + #define USE_PATHS_H + #define USE_FCNTL_LOCK + #define USE_DOT_LOCK + #define HAS_FSYNC + #define HAS_DBM + #define DEF_DB_TYPE "dbm" + #define ALIAS_DB_MAP "dbm:/etc/mail/aliases" + #define DBM_NO_TRAILING_NULL + #define HAS_NIS + #define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0) + #define ROOT_PATH "/bin:/etc:/usr/bin:/tcb/bin" + #define USE_STATVFS + #define STATVFS_IN_SYS_STATVFS_H + #define UNIX_DOMAIN_CONNECT_BLOCKS_FOR_ACCEPT + #define MISSING_SETENV + /* SCO5 misses just S_ISSOCK, the others are there + * Use C_ISSOCK definition from cpio.h. + */ + #include + #define S_ISSOCK(mode) (((mode) & (S_IFMT)) == (C_ISSOCK)) #endif /*