X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Ftransport.c;h=e66e498be1e70f8ed6e2cc17e0d6f281ba7fd66c;hb=da3d9acf6fdb2912fd6ed1abd8296d2726fa9b3b;hp=c388187700d5aa1d55bdc77c0d9f0a9774836e5a;hpb=2e2a30b495b1ef8052259093f9422f57903b1717;p=exim.git diff --git a/src/src/transport.c b/src/src/transport.c index c38818770..e66e498be 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/transport.c,v 1.8 2005/05/03 14:20:01 ph10 Exp $ */ +/* $Cambridge: exim/src/src/transport.c,v 1.13 2005/08/01 14:41:25 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -199,26 +199,42 @@ BOOL transport_write_block(int fd, uschar *block, int len) { int i, rc, save_errno; +int local_timeout = transport_write_timeout; + +/* This loop is for handling incomplete writes and other retries. In most +normal cases, it is only ever executed once. */ for (i = 0; i < 100; i++) { DEBUG(D_transport) debug_printf("writing data block fd=%d size=%d timeout=%d\n", - fd, len, transport_write_timeout); - if (transport_write_timeout > 0) alarm(transport_write_timeout); + fd, len, local_timeout); - #ifdef SUPPORT_TLS - if (tls_active == fd) rc = tls_write(block, len); else - #endif + /* This code makes use of alarm() in order to implement the timeout. This + isn't a very tidy way of doing things. Using non-blocking I/O with select() + provides a neater approach. However, I don't know how to do this when TLS is + in use. */ - rc = write(fd, block, len); - save_errno = errno; + if (transport_write_timeout <= 0) /* No timeout wanted */ + { + #ifdef SUPPORT_TLS + if (tls_active == fd) rc = tls_write(block, len); else + #endif + rc = write(fd, block, len); + save_errno = errno; + } - /* Cancel the alarm and deal with a timeout */ + /* Timeout wanted. */ - if (transport_write_timeout > 0) + else { - alarm(0); + alarm(local_timeout); + #ifdef SUPPORT_TLS + if (tls_active == fd) rc = tls_write(block, len); else + #endif + rc = write(fd, block, len); + save_errno = errno; + local_timeout = alarm(0); if (sigalrm_seen) { errno = ETIMEDOUT; @@ -230,7 +246,8 @@ for (i = 0; i < 100; i++) if (rc == len) { transport_count += len; return TRUE; } - /* A non-negative return code is an incomplete write. Try again. */ + /* A non-negative return code is an incomplete write. Try again for the rest + of the block. If we have exactly hit the timeout, give up. */ if (rc >= 0) { @@ -238,7 +255,7 @@ for (i = 0; i < 100; i++) block += rc; transport_count += rc; DEBUG(D_transport) debug_printf("write incomplete (%d)\n", rc); - continue; + goto CHECK_TIMEOUT; /* A few lines below */ } /* A negative return code with an EINTR error is another form of @@ -248,7 +265,7 @@ for (i = 0; i < 100; i++) { DEBUG(D_transport) debug_printf("write interrupted before anything written\n"); - continue; + goto CHECK_TIMEOUT; /* A few lines below */ } /* A response of EAGAIN from write() is likely only in the case of writing @@ -259,6 +276,16 @@ for (i = 0; i < 100; i++) DEBUG(D_transport) debug_printf("write temporarily locked out, waiting 1 sec\n"); sleep(1); + + /* Before continuing to try another write, check that we haven't run out of + time. */ + + CHECK_TIMEOUT: + if (transport_write_timeout > 0 && local_timeout <= 0) + { + errno = ETIMEDOUT; + return FALSE; + } continue; } @@ -957,7 +984,7 @@ dk_transport_write_message(address_item *addr, int fd, int options, int wwritten = 0; uschar *dk_signature = NULL; - snprintf(CS dk_spool_name, 256, "%s/input/%s/%s-K", + (void)string_format(dk_spool_name, 256, "%s/input/%s/%s-K", spool_directory, message_subdir, message_id); dk_fd = Uopen(dk_spool_name, O_RDWR|O_CREAT|O_EXCL, SPOOL_MODE); if (dk_fd < 0) @@ -1015,8 +1042,8 @@ dk_transport_write_message(address_item *addr, int fd, int options, uschar *dk_strict_result = expand_string(dk_strict); if (dk_strict_result != NULL) { - if ( (strcmpic(dk_strict,"1") == 0) || - (strcmpic(dk_strict,"true") == 0) ) + if ( (strcmpic(dk_strict,US"1") == 0) || + (strcmpic(dk_strict,US"true") == 0) ) { save_errno = errno; rc = FALSE; @@ -1034,7 +1061,7 @@ dk_transport_write_message(address_item *addr, int fd, int options, /* write the chunk */ DK_WRITE: #ifdef SUPPORT_TLS - if (tls_active == fd) wwritten = tls_write(p, sread); else + if (tls_active == fd) wwritten = tls_write(US p, sread); else #endif wwritten = write(fd,p,sread); if (wwritten == -1) @@ -1063,7 +1090,7 @@ dk_transport_write_message(address_item *addr, int fd, int options, CLEANUP: /* unlink -K file */ - close(dk_fd); + (void)close(dk_fd); Uunlink(dk_spool_name); errno = save_errno; return rc; @@ -1137,10 +1164,10 @@ save_errno = 0; yield = FALSE; write_pid = (pid_t)(-1); -fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); +(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); filter_pid = child_open(transport_filter_argv, NULL, 077, &fd_write, &fd_read, FALSE); -fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) & ~FD_CLOEXEC); +(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) & ~FD_CLOEXEC); if (filter_pid < 0) goto TIDY_UP; /* errno set */ DEBUG(D_transport) @@ -1155,25 +1182,25 @@ if (pipe(pfd) != 0) goto TIDY_UP; /* errno set */ if ((write_pid = fork()) == 0) { BOOL rc; - close(fd_read); - close(pfd[pipe_read]); + (void)close(fd_read); + (void)close(pfd[pipe_read]); nl_check_length = nl_escape_length = 0; rc = internal_transport_write_message(addr, fd_write, (options & ~(topt_use_crlf | topt_end_dot)), size_limit, add_headers, remove_headers, NULL, NULL, rewrite_rules, rewrite_existflags); save_errno = errno; - write(pfd[pipe_write], (void *)&rc, sizeof(BOOL)); - write(pfd[pipe_write], (void *)&save_errno, sizeof(int)); - write(pfd[pipe_write], (void *)&(addr->more_errno), sizeof(int)); + (void)write(pfd[pipe_write], (void *)&rc, sizeof(BOOL)); + (void)write(pfd[pipe_write], (void *)&save_errno, sizeof(int)); + (void)write(pfd[pipe_write], (void *)&(addr->more_errno), sizeof(int)); _exit(0); } save_errno = errno; /* Parent process: close our copy of the writing subprocess' pipes. */ -close(pfd[pipe_write]); -close(fd_write); +(void)close(pfd[pipe_write]); +(void)close(fd_write); fd_write = -1; /* Writing process creation failed */ @@ -1243,8 +1270,8 @@ sure. Also apply a paranoia timeout. */ TIDY_UP: save_errno = errno; -close(fd_read); -if (fd_write > 0) close(fd_write); +(void)close(fd_read); +if (fd_write > 0) (void)close(fd_write); if (!yield) { @@ -1276,11 +1303,11 @@ if (write_pid > 0) if (rc == 0) { BOOL ok; - read(pfd[pipe_read], (void *)&ok, sizeof(BOOL)); + (void)read(pfd[pipe_read], (void *)&ok, sizeof(BOOL)); if (!ok) { - read(pfd[pipe_read], (void *)&save_errno, sizeof(int)); - read(pfd[pipe_read], (void *)&(addr->more_errno), sizeof(int)); + (void)read(pfd[pipe_read], (void *)&save_errno, sizeof(int)); + (void)read(pfd[pipe_read], (void *)&(addr->more_errno), sizeof(int)); yield = FALSE; } } @@ -1293,7 +1320,7 @@ if (write_pid > 0) } } } -close(pfd[pipe_read]); +(void)close(pfd[pipe_read]); /* If there have been no problems we can now add the terminating "." if this is SMTP output, turning off escaping beforehand. If the last character from the @@ -1757,8 +1784,8 @@ if ((pid = fork()) == 0) if (socket_fd != 0) { - dup2(socket_fd, 0); - close(socket_fd); + (void)dup2(socket_fd, 0); + (void)close(socket_fd); } DEBUG(D_exec) debug_print_argv(argv);