示例#1
0
VSTRING *vstring_sprintf_prepend(VSTRING *vp, const char *format,...)
{
    va_list ap;
    ssize_t old_len = VSTRING_LEN(vp);
    ssize_t result_len;

    /* Construct: old|new|free */
    va_start(ap, format);
    vp = vstring_vsprintf_append(vp, format, ap);
    va_end(ap);
    result_len = VSTRING_LEN(vp);

    /* Construct: old|new|old|free */
    VSTRING_SPACE(vp, old_len);
    vstring_memcat(vp, vstring_str(vp), old_len);

    /* Construct: new|old|free */
    memmove(vstring_str(vp), vstring_str(vp) + old_len, result_len);
    VSTRING_AT_OFFSET(vp, result_len);
    VSTRING_TERMINATE(vp);
    return (vp);
}
示例#2
0
int     main(int argc, char **argv)
{
    SESSION *session;
    char   *host;
    char   *port;
    char   *path;
    int     path_len;
    int     sessions = 1;
    int     ch;
    int     i;
    char   *buf;
    const char *parse_err;
    struct addrinfo *res;
    int     aierr;
    const char *protocols = INET_PROTO_NAME_ALL;
    INET_PROTO_INFO *proto_info;
    char   *message_file = 0;

    /*
     * Fingerprint executables and core dumps.
     */
    MAIL_VERSION_STAMP_ALLOCATE;

    signal(SIGPIPE, SIG_IGN);
    msg_vstream_init(argv[0], VSTREAM_ERR);

    /*
     * Parse JCL.
     */
    while ((ch = GETOPT(argc, argv, "46AcC:df:F:l:Lm:M:Nor:R:s:S:t:T:vw:")) > 0) {
        switch (ch) {
        case '4':
            protocols = INET_PROTO_NAME_IPV4;
            break;
        case '6':
            protocols = INET_PROTO_NAME_IPV6;
            break;
        case 'A':
            allow_reject = 1;
            break;
        case 'c':
            count++;
            break;
        case 'C':
            if ((connect_count = atoi(optarg)) <= 0)
                msg_fatal("bad connection count: %s", optarg);
            break;
        case 'd':
            disconnect = 0;
            break;
        case 'f':
            sender = optarg;
            break;
        case 'F':
            if (message_file == 0 && message_length > 0)
                msg_fatal("-l option cannot be used with -F");
            message_file = optarg;
            break;
        case 'l':
            if (message_file != 0)
                msg_fatal("-l option cannot be used with -F");
            if ((message_length = atoi(optarg)) <= 0)
                msg_fatal("bad message length: %s", optarg);
            break;
        case 'L':
            talk_lmtp = 1;
            break;
        case 'm':
            if ((message_count = atoi(optarg)) <= 0)
                msg_fatal("bad message count: %s", optarg);
            break;
        case 'M':
            if (*optarg == '[') {
                if (!valid_mailhost_literal(optarg, DO_GRIPE))
                    msg_fatal("bad address literal: %s", optarg);
            } else {
                if (!valid_hostname(optarg, DO_GRIPE))
                    msg_fatal("bad hostname: %s", optarg);
            }
            var_myhostname = optarg;
            break;
        case 'N':
            number_rcpts = 1;
            break;
        case 'o':
            send_helo_first = 0;
            send_headers = 0;
            break;
        case 'r':
            if ((recipients = atoi(optarg)) <= 0)
                msg_fatal("bad recipient count: %s", optarg);
            break;
        case 'R':
            if (fixed_delay > 0)
                msg_fatal("do not use -w and -R options at the same time");
            if ((random_delay = atoi(optarg)) <= 0)
                msg_fatal("bad random delay: %s", optarg);
            break;
        case 's':
            if ((sessions = atoi(optarg)) <= 0)
                msg_fatal("bad session count: %s", optarg);
            break;
        case 'S':
            subject = optarg;
            break;
        case 't':
            recipient = optarg;
            break;
        case 'T':
            if ((inet_windowsize = atoi(optarg)) <= 0)
                msg_fatal("bad TCP window size: %s", optarg);
            break;
        case 'v':
            msg_verbose++;
            break;
        case 'w':
            if (random_delay > 0)
                msg_fatal("do not use -w and -R options at the same time");
            if ((fixed_delay = atoi(optarg)) <= 0)
                msg_fatal("bad fixed delay: %s", optarg);
            break;
        default:
            usage(argv[0]);
        }
    }
    if (argc - optind != 1)
        usage(argv[0]);

    if (random_delay > 0)
        srand(getpid());

    /*
     * Initialize the message content, SMTP encoded. smtp_fputs() will append
     * another \r\n but we don't care.
     */
    if (message_file != 0) {
        VSTREAM *fp;
        VSTRING *buf = vstring_alloc(100);
        VSTRING *msg = vstring_alloc(100);

        if ((fp = vstream_fopen(message_file, O_RDONLY, 0)) == 0)
            msg_fatal("open %s: %m", message_file);
        while (vstring_get_nonl(buf, fp) != VSTREAM_EOF) {
            if (*vstring_str(buf) == '.')
                VSTRING_ADDCH(msg, '.');
            vstring_memcat(msg, vstring_str(buf), VSTRING_LEN(buf));
            vstring_memcat(msg, "\r\n", 2);
        }
        if (vstream_ferror(fp))
            msg_fatal("read %s: %m", message_file);
        vstream_fclose(fp);
        vstring_free(buf);
        message_length = VSTRING_LEN(msg);
        message_data = vstring_export(msg);
        send_headers = 0;
    } else if (message_length > 0) {
        message_data = mymalloc(message_length);
        memset(message_data, 'X', message_length);
        for (i = 80; i < message_length; i += 80) {
            message_data[i - 80] = "0123456789"[(i / 80) % 10];
            message_data[i - 2] = '\r';
            message_data[i - 1] = '\n';
        }
    }

    /*
     * Translate endpoint address to internal form.
     */
    proto_info = inet_proto_init("protocols", protocols);
    if (strncmp(argv[optind], "unix:", 5) == 0) {
        path = argv[optind] + 5;
        path_len = strlen(path);
        if (path_len >= (int) sizeof(sun.sun_path))
            msg_fatal("unix-domain name too long: %s", path);
        memset((char *) &sun, 0, sizeof(sun));
        sun.sun_family = AF_UNIX;
#ifdef HAS_SUN_LEN
        sun.sun_len = path_len + 1;
#endif
        memcpy(sun.sun_path, path, path_len);
        sa = (struct sockaddr *) & sun;
        sa_length = sizeof(sun);
    } else {
        if (strncmp(argv[optind], "inet:", 5) == 0)
            argv[optind] += 5;
        buf = mystrdup(argv[optind]);
        if ((parse_err = host_port(buf, &host, (char *) 0, &port, "smtp")) != 0)
            msg_fatal("%s: %s", argv[optind], parse_err);
        if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res)) != 0)
            msg_fatal("%s: %s", argv[optind], MAI_STRERROR(aierr));
        myfree(buf);
        sa = (struct sockaddr *) & ss;
        if (res->ai_addrlen > sizeof(ss))
            msg_fatal("address length %d > buffer length %d",
                      (int) res->ai_addrlen, (int) sizeof(ss));
        memcpy((char *) sa, res->ai_addr, res->ai_addrlen);
        sa_length = res->ai_addrlen;
#ifdef HAS_SA_LEN
        sa->sa_len = sa_length;
#endif
        freeaddrinfo(res);
    }

    /*
     * Make sure the SMTP server cannot run us out of memory by sending
     * never-ending lines of text.
     */
    if (buffer == 0) {
        buffer = vstring_alloc(100);
        vstring_ctl(buffer, VSTRING_CTL_MAXLEN, (ssize_t) var_line_limit, 0);
    }

    /*
     * Make sure we have sender and recipient addresses.
     */
    if (var_myhostname == 0)
        var_myhostname = get_hostname();
    if (sender == 0 || recipient == 0) {
        vstring_sprintf(buffer, "foo@%s", var_myhostname);
        defaddr = mystrdup(vstring_str(buffer));
        if (sender == 0)
            sender = defaddr;
        if (recipient == 0)
            recipient = defaddr;
    }

    /*
     * Start sessions.
     */
    while (sessions-- > 0) {
        session = (SESSION *) mymalloc(sizeof(*session));
        session->stream = 0;
        session->xfer_count = 0;
        session->connect_count = connect_count;
        session->next = 0;
        session_count++;
        startup(session);
    }
    for (;;) {
        event_loop(-1);
        if (session_count <= 0 && message_count <= 0) {
            if (count) {
                VSTREAM_PUTC('\n', VSTREAM_OUT);
                vstream_fflush(VSTREAM_OUT);
            }
            exit(0);
        }
    }
}