Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  mail_copy.c

  Sprache: C
 

/*++
/* NAME
/* mail_copy 3
/* SUMMARY
/* copy message with extreme prejudice
/* SYNOPSIS
/* #include <mail_copy.h>
/*
/* int mail_copy(sender, orig_to, delivered, src, dst, flags, eol, why)
/* const char *sender;
/* const char *orig_to;
/* const char *delivered;
/* VSTREAM *src;
/* VSTREAM *dst;
/* int flags;
/* const char *eol;
/* DSN_BUF *why;
/* DESCRIPTION
/* mail_copy() copies a mail message from record stream to stream-lf
/* stream, and attempts to detect all possible I/O errors.
/*
/* Arguments:
/* .IP sender
/* The sender envelope address.
/* .IP delivered
/* Null pointer or delivered-to: header address.
/* .IP src
/* The source record stream, positioned at the beginning of the
/* message contents.
/* .IP dst
/* The destination byte stream (in stream-lf format). If the message
/* ends in an incomplete line, a newline character is appended to
/* the output.
/* .IP flags
/* The binary OR of zero or more of the following:
/* .RS
/* .IP MAIL_COPY_QUOTE
/* Prepend a `>' character to lines beginning with `From '.
/* .IP MAIL_COPY_DOT
/* Prepend a `.' character to lines beginning with `.'.
/* .IP MAIL_COPY_TOFILE
/* On systems that support this, use fsync() to flush the
/* data to stable storage, and truncate the destination
/* file to its original length in case of problems.
/* .IP MAIL_COPY_FROM
/* Prepend a UNIX-style From_ line to the message.
/* .IP MAIL_COPY_BLANK
/* Append an empty line to the end of the message.
/* .IP MAIL_COPY_DELIVERED
/* Prepend a Delivered-To: header with the name of the
/* \fIdelivered\fR attribute.
/* The address is quoted according to RFC822 rules.
/* .IP MAIL_COPY_ORIG_RCPT
/* Prepend an X-Original-To: header with the original
/* envelope recipient address. This is a NOOP with
/* var_enable_orcpt === 0.
/* .IP MAIL_COPY_RETURN_PATH
/* Prepend a Return-Path: header with the value of the
/* \fIsender\fR attribute.
/* .RE
/* The manifest constant MAIL_COPY_MBOX is a convenient shorthand for
/* all MAIL_COPY_XXX options that are appropriate for mailbox delivery.
/* Use MAIL_COPY_NONE to copy a message without any options enabled.
/* .IP eol
/* Record delimiter, for example, LF or CF LF.
/* .IP why
/* A null pointer, or storage for the reason of failure in
/* the form of a DSN detail code plus free text.
/* DIAGNOSTICS
/* A non-zero result means the operation failed. Warnings: corrupt
/* message file. A corrupt message is marked as corrupt.
/*
/* The result is the bit-wise OR of zero or more of the following:
/* .IP MAIL_COPY_STAT_CORRUPT
/* The queue file is marked as corrupt.
/* .IP MAIL_COPY_STAT_READ
/* A read error was detected; errno specifies the nature of the problem.
/* .IP MAIL_COPY_STAT_WRITE
/* A write error was detected; errno specifies the nature of the problem.
/* SEE ALSO
/* mark_corrupt(3), mark queue file as corrupted.
/* 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
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/


/* System library. */

#include <sys_defs.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>

/* Utility library. */

#include <msg.h>
#include <htable.h>
#include <vstream.h>
#include <vstring.h>
#include <vstring_vstream.h>
#include <stringops.h>
#include <iostuff.h>
#include <warn_stat.h>

/* Global library. */

#include "quote_822_local.h"
#include "record.h"
#include "rec_type.h"
#include "mail_queue.h"
#include "mail_addr.h"
#include "mark_corrupt.h"
#include "mail_params.h"
#include "mail_copy.h"
#include "mbox_open.h"
#include "dsn_buf.h"
#include "sys_exits.h"

/* mail_copy - copy message with extreme prejudice */

int     mail_copy(const char *sender,
            const char *orig_rcpt,
            const char *delivered,
            VSTREAM *src, VSTREAM *dst,
            int flags, const char *eol, DSN_BUF *why)
{
    const char *myname = "mail_copy";
    VSTRING *buf;
    char   *bp;
    off_t   orig_length;
    int     read_error;
    int     write_error;
    int     corrupt_error = 0;
    time_t  now;
    int     type;
    int     prev_type;
    struct stat st;
    off_t   size_limit;

    /*
     * Workaround 20090114. This will hopefully get someone's attention. The
     * problem with file_size_limit < message_size_limit is that mail will be
     * delivered again and again until someone removes it from the queue by
     * hand, because Postfix cannot mark a recipient record as "completed".
     */

    if (fstat(vstream_fileno(src), &st) < 0)
 msg_fatal("fstat: %m");
    if ((size_limit = get_file_limit()) < st.st_size)
 msg_panic("file size limit %lu < message size %lu. This "
    "causes large messages to be delivered repeatedly "
    "after they were submitted with \"sendmail -t\" "
    "or after recipients were added with the Milter "
    "SMFIR_ADDRCPT request",
    (unsigned long) size_limit,
    (unsigned long) st.st_size);

    /*
     * Initialize.
     */

#ifndef NO_TRUNCATE
    if ((flags & MAIL_COPY_TOFILE) != 0)
 if ((orig_length = vstream_fseek(dst, (off_t) 0, SEEK_END)) < 0)
     msg_fatal("seek file %s: %m", VSTREAM_PATH(dst));
#endif
    buf = vstring_alloc(100);

    /*
     * Prepend a bunch of headers to the message.
     */

    if (flags & (MAIL_COPY_FROM | MAIL_COPY_RETURN_PATH)) {
 if (sender == 0)
     msg_panic("%s: null sender", myname);
 quote_822_local(buf, sender);
 if (flags & MAIL_COPY_FROM) {
     time(&now);
     vstream_fprintf(dst, "From %s  %.24s%s", *sender == 0 ?
       MAIL_ADDR_MAIL_DAEMON : vstring_str(buf),
       asctime(localtime(&now)), eol);
 }
 if (flags & MAIL_COPY_RETURN_PATH) {
     vstream_fprintf(dst, "Return-Path: <%s>%s",
       *sender ? vstring_str(buf) : "", eol);
 }
    }
    if (flags & MAIL_COPY_ORIG_RCPT) {
 if (orig_rcpt == 0)
     msg_panic("%s: null orig_rcpt", myname);

 /*
  * An empty original recipient record almost certainly means that
  * original recipient processing was disabled.
 */

 if (var_enable_orcpt && *orig_rcpt) {
     quote_822_local(buf, orig_rcpt);
     vstream_fprintf(dst, "X-Original-To: %s%s", vstring_str(buf), eol);
 }
    }
    if (flags & MAIL_COPY_DELIVERED) {
 if (delivered == 0)
     msg_panic("%s: null delivered", myname);
 quote_822_local(buf, delivered);
 vstream_fprintf(dst, "Delivered-To: %s%s", vstring_str(buf), eol);
    }

    /*
     * Copy the message. Escape lines that could be confused with the ugly
     * From_ line. Make sure that there is a blank line at the end of the
     * message so that the next ugly From_ can be found by mail reading
     * software.
     * 
     * XXX Rely on the front-end services to enforce record size limits.
     */

#define VSTREAM_FWRITE_BUF(s,b) \
 vstream_fwrite((s),vstring_str(b),VSTRING_LEN(b))

    prev_type = REC_TYPE_NORM;
    while ((type = rec_get(src, buf, 0)) > 0) {
 if (type != REC_TYPE_NORM && type != REC_TYPE_CONT)
     break;
 bp = vstring_str(buf);
 if (prev_type == REC_TYPE_NORM) {
     if ((flags & MAIL_COPY_QUOTE) && *bp == 'F' && !strncmp(bp, "From "5))
  VSTREAM_PUTC('>', dst);
     if ((flags & MAIL_COPY_DOT) && *bp == '.')
  VSTREAM_PUTC('.', dst);
 }
 if (VSTRING_LEN(buf) && VSTREAM_FWRITE_BUF(dst, buf) != VSTRING_LEN(buf))
     break;
 if (type == REC_TYPE_NORM && vstream_fputs(eol, dst) == VSTREAM_EOF)
     break;
 prev_type = type;
    }
    if (vstream_ferror(dst) == 0) {
 if (var_fault_inj_code == 1)
     type = 0;
 if (type != REC_TYPE_XTRA) {
     /* XXX Where is the queue ID? */
     msg_warn("bad record type: %d in message content", type);
     corrupt_error = mark_corrupt(src);
 }
 if (prev_type != REC_TYPE_NORM)
     vstream_fputs(eol, dst);
 if (flags & MAIL_COPY_BLANK)
     vstream_fputs(eol, dst);
    }
    vstring_free(buf);

    /*
     * Make sure we read and wrote all. Truncate the file to its original
     * length when the delivery failed. POSIX does not require ftruncate(),
     * so we may have a portability problem. Note that fclose() may fail even
     * while fflush and fsync() succeed. Think of remote file systems such as
     * AFS that copy the file back to the server upon close. Oh well, no
     * point optimizing the error case. XXX On systems that use flock()
     * locking, we must truncate the file before closing it (and losing the
     * exclusive lock).
     */

    read_error = vstream_ferror(src);
    write_error = vstream_fflush(dst);
#ifdef HAS_FSYNC
    if ((flags & MAIL_COPY_TOFILE) != 0)
 write_error |= fsync(vstream_fileno(dst));
#endif
    if (var_fault_inj_code == 2) {
 read_error = 1;
 errno = ENOENT;
    }
    if (var_fault_inj_code == 3) {
 write_error = 1;
 errno = ENOENT;
    }
#ifndef NO_TRUNCATE
    if ((flags & MAIL_COPY_TOFILE) != 0)
 if (corrupt_error || read_error || write_error)
     /* Complain about ignored "undo" errors? So sue me. */
     (void) ftruncate(vstream_fileno(dst), orig_length);
#endif
    write_error |= vstream_fclose(dst);

    /*
     * Return the optional verbose error description.
     */

#define TRY_AGAIN_ERROR(errno) \
 (errno == EAGAIN || errno == ESTALE)

    if (why && read_error)
 dsb_unix(why, TRY_AGAIN_ERROR(errno) ? "4.3.0" : "5.3.0",
   sys_exits_detail(EX_IOERR)->text,
   "error reading message: %m");
    if (why && write_error)
 dsb_unix(why, mbox_dsn(errno, "5.3.0"),
   sys_exits_detail(EX_IOERR)->text,
   "error writing message: %m");

    /*
     * Use flag+errno description when the optional verbose description is
     * not desired.
     */

    return ((corrupt_error ? MAIL_COPY_STAT_CORRUPT : 0)
     | (read_error ? MAIL_COPY_STAT_READ : 0)
     | (write_error ? MAIL_COPY_STAT_WRITE : 0));
}

Messung V0.5 in Prozent
C=72 H=100 G=86

¤ Dauer der Verarbeitung: 0.9 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002