head 1.13;
access;
symbols
L2_0_9_13:1.13
FSL_1_7_0:1.13
L2_0_9_12:1.13
LMTP2NNTP_1_4_1:1.13
LMTP2NNTP_1_4_0:1.13
FSL_1_6_1:1.13
L2_0_9_11:1.13
FSL_1_6_0:1.12
FSL_1_6b2:1.12
L2_0_9_10:1.12
FSL_1_6b1:1.12
L2_0_9_9:1.12
LMTP2NNTP_1_3_0:1.11
LMTP2NNTP_1_3b2:1.11
LMTP2NNTP_1_3b1:1.11
LMTP2NNTP_1_3a3:1.11
FSL_1_5_0:1.11
LMTP2NNTP_1_3a2:1.11
FSL_1_5a3:1.11
LMTP2NNTP_1_3a1:1.11
FSL_1_5a2:1.11
L2_0_9_8:1.11
FSL_1_5a1:1.11
L2_0_9_7:1.11
L2_0_9_6:1.11
FSL_1_4_0:1.11
FSL_1_4b1:1.11
L2_0_9_5:1.11
FSL_1_4a1:1.11
FSL_1_3_0:1.11
FSL_1_3b1:1.11
L2_0_9_4:1.11
FSL_1_2_1:1.11
L2_0_9_3:1.11
FSL_1_2_0:1.11
L2_0_9_2:1.11
FSL_1_1_0:1.11
FSL_1_1b1:1.11
WORKOFF:1.11.0.2
WORKOFF_BP:1.11
FSL_1_0_8:1.11
LMTP2NNTP_1_2_0:1.11
LMTP2NNTP_1_2b4:1.11
LMTP2NNTP_1_2b3:1.11
LMTP2NNTP_1_2b2:1.11
LMTP2NNTP_1_2b1:1.11
LMTP2NNTP_1_2a8:1.11
LMTP2NNTP_1_2a7:1.11
FSL_1_0_7:1.11
FSL_1_0_6:1.10
FSL_1_0_5:1.10
FSL_1_0_4:1.10
L2_0_9_1:1.10
FSL_1_0_3:1.10
LMTP2NNTP_1_2a6:1.10
FSL_1_0_2:1.10
FSL_1_0_1:1.10
FSL_1_0_0:1.10
FSL_0_9_0:1.10
L2_0_9_0:1.10
FSL_0_1_12:1.9
FSL_0_1_11:1.9
FSL_0_1_10:1.9
FSL_0_1_9:1.9
FSL_0_1_8:1.9
FSL_0_1_7:1.9
FSL_0_1_6:1.9
FSL_0_1_5:1.9
FSL_0_1_1:1.9
LMTP2NNTP_1_2a5:1.9
LMTP2NNTP_1_2a4:1.9
LMTP2NNTP_1_2a3:1.9
LMTP2NNTP_1_2a1:1.8
LMTP2NNTP_1_1_1:1.5
LMTP2NNTP_1_1_0:1.5
LMTP2NNTP_1_1b4:1.5
LMTP2NNTP_1_1b3:1.5
L2_CHANNEL_ONLY_REVAMPING_BEFORE:1.6
LMTP2NNTP_1_1b2:1.5
LMTP2NNTP_1_1b1:1.5
L2_0_1_0:1.2;
locks; strict;
comment @ * @;
1.13
date 2005.10.03.08.08.11; author rse; state Exp;
branches;
next 1.12;
1.12
date 2005.01.24.15.03.17; author rse; state Exp;
branches;
next 1.11;
1.11
date 2003.01.06.11.41.51; author rse; state Exp;
branches;
next 1.10;
1.10
date 2002.07.30.19.08.24; author rse; state Exp;
branches;
next 1.9;
1.9
date 2002.01.02.17.07.38; author rse; state Exp;
branches;
next 1.8;
1.8
date 2001.11.07.13.05.20; author rse; state Exp;
branches;
next 1.7;
1.7
date 2001.11.07.11.37.18; author rse; state Exp;
branches;
next 1.6;
1.6
date 2001.10.19.11.55.00; author rse; state Exp;
branches;
next 1.5;
1.5
date 2001.10.10.15.58.27; author rse; state Exp;
branches;
next 1.4;
1.4
date 2001.10.06.14.33.09; author rse; state Exp;
branches;
next 1.3;
1.3
date 2001.09.14.12.55.20; author rse; state Exp;
branches;
next 1.2;
1.2
date 2001.09.12.09.42.34; author ms; state Exp;
branches;
next 1.1;
1.1
date 2001.09.09.15.57.10; author rse; state Exp;
branches;
next ;
desc
@@
1.13
log
@Adjust copyright messages for new year 2005.
@
text
@/*
** OSSP l2 - Flexible Logging
** Copyright (c) 2001-2005 Cable & Wireless
** Copyright (c) 2001-2005 The OSSP Project
** Copyright (c) 2001-2005 Ralf S. Engelschall
**
** This file is part of OSSP l2, a flexible logging library which
** can be found at http://www.ossp.org/pkg/lib/l2/.
**
** Permission to use, copy, modify, and distribute this software for
** any purpose with or without fee is hereby granted, provided that
** the above copyright notice and this permission notice appear in all
** copies.
**
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
**
** l2_ch_smtp.c: SMTP channel implementation
*/
#include "l2.h"
#include "l2_p.h" /* for l2_version */
#include
#include
#include
#include
#include
/* declare private channel configuration */
typedef struct {
char *cpFrom;
char *cpRcpt;
char *cpSubject;
char *cpHost;
char *cpPort;
char *cpLocalProg;
char *cpLocalUser;
char *cpLocalHost;
long nTimeout;
sa_addr_t *saaServer;
sa_t *saServer;
} l2_ch_smtp_t;
/* create channel */
static l2_result_t hook_create(l2_context_t *ctx, l2_channel_t *ch)
{
l2_ch_smtp_t *cfg;
struct utsname uts;
struct passwd *pw;
/* allocate private channel configuration */
if ((cfg = (l2_ch_smtp_t *)malloc(sizeof(l2_ch_smtp_t))) == NULL)
return L2_ERR_ARG;
/* initialize configuration with reasonable defaults */
cfg->cpLocalProg = NULL;
if ((pw = getpwuid(getuid())) != NULL)
cfg->cpLocalUser = strdup(pw->pw_name);
else
cfg->cpLocalUser = l2_util_asprintf("uid#%d", getuid());
if (uname(&uts) == 0)
cfg->cpLocalHost = strdup(uts.nodename);
else
cfg->cpLocalHost = strdup("localhost");
cfg->cpFrom = l2_util_asprintf("%s@@%s", cfg->cpLocalUser, cfg->cpLocalHost);
cfg->cpRcpt = NULL;
cfg->cpSubject = l2_util_asprintf("[L2] log channel output on %s", cfg->cpLocalHost);
cfg->cpHost = NULL;
cfg->cpPort = strdup("smtp");
cfg->nTimeout = 30;
cfg->saaServer = NULL;
cfg->saServer = NULL;
/* link private channel configuration into channel context */
ctx->vp = cfg;
return L2_OK;
}
/* configure channel */
static l2_result_t hook_configure(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap)
{
l2_ch_smtp_t *cfg = (l2_ch_smtp_t *)ctx->vp;
l2_param_t pa[10];
l2_result_t rv;
l2_env_t *env;
/* feed and call generic parameter parsing engine */
L2_PARAM_SET(pa[0], progname, STR, &cfg->cpLocalProg);
L2_PARAM_SET(pa[1], localhost, STR, &cfg->cpLocalHost);
L2_PARAM_SET(pa[2], localuser, STR, &cfg->cpLocalUser);
L2_PARAM_SET(pa[3], from, STR, &cfg->cpFrom);
L2_PARAM_SET(pa[4], rcpt, STR, &cfg->cpRcpt);
L2_PARAM_SET(pa[5], subject, STR, &cfg->cpSubject);
L2_PARAM_SET(pa[6], host, STR, &cfg->cpHost);
L2_PARAM_SET(pa[7], port, STR, &cfg->cpPort);
L2_PARAM_SET(pa[8], timeout, INT, &cfg->nTimeout);
L2_PARAM_END(pa[9]);
l2_channel_env(ch, &env);
rv = l2_util_setparams(env, pa, fmt, ap);
return rv;
}
/* open channel */
static l2_result_t hook_open(l2_context_t *ctx, l2_channel_t *ch)
{
l2_ch_smtp_t *cfg = (l2_ch_smtp_t *)ctx->vp;
sa_rc_t rc;
/* make sure a path was set */
if (cfg->cpHost == NULL || cfg->cpRcpt == NULL)
return L2_ERR_USE;
/* create socket address */
if ((rc = sa_addr_create(&cfg->saaServer)) != SA_OK)
return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
if ((rc = sa_addr_u2a(cfg->saaServer, "inet://%s:%s",
cfg->cpHost, cfg->cpPort)) != SA_OK)
return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
/* create socket */
if ((rc = sa_create(&cfg->saServer)) != SA_OK)
return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
/* configure socket parameters */
sa_timeout(cfg->saServer, SA_TIMEOUT_ALL, cfg->nTimeout, 0);
sa_buffer(cfg->saServer, SA_BUFFER_READ, 4096);
sa_buffer(cfg->saServer, SA_BUFFER_WRITE, 4096);
return L2_OK;
}
/* write to channel */
static l2_result_t hook_write(l2_context_t *ctx, l2_channel_t *ch,
l2_level_t level, const char *buf, size_t buf_size)
{
l2_ch_smtp_t *cfg = (l2_ch_smtp_t *)ctx->vp;
char caLine[1024];
sa_t *sa;
sa_addr_t *saa;
l2_result_t rv = L2_OK;
sa_rc_t sa_rv;
size_t n;
const char *cpB;
const char *cpE;
const char *cpL;
struct tm *tm;
time_t t;
char caDate[80];
/*
* Sample SMTP transaction for reference:
*
* | 220 en1.engelschall.com ESMTP SMTP Sendmail 8.11.0+ ready
* | HELO l2
* | 250 en1.engelschall.com Hello en1.engelschall.com [141.1.129.1], pleased to meet you
* | MAIL From:
* | 250 2.1.0 ... Sender ok
* | RCPT To:
* | 250 2.1.5 ... Recipient ok
* | DATA
* | 354 Enter mail, end with "." on a line by itself
* | Date: Fri, 14 Sep 2001 14:50:51 CEST
* | From: rse@@en1.engelschall.com
* | To: rse@@engelschall.com
* | Subject: [L2] log channel output on en1.engelschall.com
* | User-Agent: L2/0.1.0
* |
* | A program of user rse on host en1.engelschall.com logged:
* | [2001-09-10/01:02:03] sample logging message
* | .
* | 250 2.0.0 f88Aev847031 Message accepted for delivery
* | QUIT
* | 221 2.0.0 en1.engelschall.com closing connection
*
* For more details read:
* RFC 2821: Simple Mail Transfer Protocol; J. Klensin; April 2001.
* RFC 2822: Internet Message Format; P. Resnick; April 2001.
*/
/* establish connection to server */
saa = cfg->saaServer;
sa = cfg->saServer;
if ((sa_rv = sa_connect(sa, saa)) != SA_OK)
cu(sa_rv == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
/* | 220 en1.engelschall.com ESMTP SMTP Sendmail 8.11.0+ ready */
sa_rv = sa_readln(sa, caLine, sizeof(caLine), &n);
cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 220), L2_ERR_IO);
/* | HELO l2
* | 250 en1.engelschall.com Hello en1.engelschall.com [141.1.129.1], pleased to meet you */
sa_writef(sa, "HELO %s\r\n", cfg->cpLocalHost);
sa_rv = sa_readln(sa, caLine, sizeof(caLine), &n);
cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 250), L2_ERR_IO);
/* | MAIL From:
* | 250 2.1.0 ... Sender ok */
sa_writef(sa, "MAIL FROM:<%s>\r\n", cfg->cpFrom);
sa_rv = sa_readln(sa, caLine, sizeof(caLine), &n);
cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 250), L2_ERR_IO);
/* | RCPT To:
* | 250 2.1.5 ... Recipient ok */
sa_writef(sa, "RCPT TO:<%s>\r\n", cfg->cpRcpt);
sa_rv = sa_readln(sa, caLine, sizeof(caLine), &n);
cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 250), L2_ERR_IO);
/* | DATA
* | 354 Enter mail, end with "." on a line by itself */
sa_writef(sa, "DATA\r\n");
sa_rv = sa_readln(sa, caLine, sizeof(caLine), &n);
cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 354), L2_ERR_IO);
/* | Date: Fri, 14 Sep 2001 14:50:51 CEST
* | From: rse@@en1.engelschall.com
* | To: rse@@engelschall.com
* | Subject: [L2] log channel output on en1.engelschall.com
* | User-Agent: L2/0.1.0
* | */
t = time(NULL);
tm = localtime(&t);
strftime(caDate, sizeof(caDate), "%a, %d %b %Y %H:%M:%S %Z", tm);
sa_writef(sa, "Date: %s\r\n", caDate);
sa_writef(sa, "From: %s\r\n", cfg->cpFrom);
sa_writef(sa, "To: %s\r\n", cfg->cpRcpt);
sa_writef(sa, "Subject: %s\r\n", cfg->cpSubject);
if (cfg->cpLocalProg != NULL)
sa_writef(sa, "User-Agent: %s (%s)\r\n",
l2_version.v_web, cfg->cpLocalProg);
else
sa_writef(sa, "User-Agent: %s\r\n", l2_version.v_web);
sa_write(sa, "\r\n", 2, NULL);
/* | A program of user rse on host en1.engelschall.com logged:
* | [2001-09-10/01:02:03] sample logging message */
if (cfg->cpLocalProg != NULL)
sa_writef(sa, "Program %s of user %s on host %s logged:\r\n",
cfg->cpLocalProg, cfg->cpLocalUser, cfg->cpLocalHost);
else
sa_writef(sa, "A program of user %s on host %s logged:\r\n",
cfg->cpLocalUser, cfg->cpLocalHost);
cpB = buf;
cpE = buf;
cpL = buf+buf_size;
while (cpB < cpL) {
for (cpE = cpB; cpE < cpL && (*cpE != '\r' && *cpE != '\n'); cpE++)
;
if (*cpB == '.')
sa_write(sa, ".", 1, NULL);
sa_write(sa, cpB, cpE-cpB, NULL);
sa_write(sa, "\r\n", 2, NULL);
for (; cpE < cpL && (*cpE == '\r' || *cpE == '\n'); cpE++)
;
cpB = cpE;
}
/* | .
* | 250 2.0.0 f88Aev847031 Message accepted for delivery */
sa_write(sa, ".\r\n", 3, NULL);
sa_readln(sa, caLine, sizeof(caLine), &n);
cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 250), L2_ERR_IO);
/* | QUIT
* | 221 2.0.0 en1.engelschall.com closing connection */
sa_writef(sa, "QUIT\r\n");
sa_readln(sa, caLine, sizeof(caLine), &n);
cus:
/* shutdown connection to server */
sa_shutdown(sa, "rw");
return rv;
}
/* close channel */
static l2_result_t hook_close(l2_context_t *ctx, l2_channel_t *ch)
{
l2_ch_smtp_t *cfg = (l2_ch_smtp_t *)ctx->vp;
/* destroy remote address */
if (cfg->saServer != NULL) {
sa_destroy(cfg->saServer);
cfg->saServer = NULL;
}
if (cfg->saaServer != NULL) {
sa_addr_destroy(cfg->saaServer);
cfg->saaServer = NULL;
}
return L2_OK;
}
/* destroy channel */
static l2_result_t hook_destroy(l2_context_t *ctx, l2_channel_t *ch)
{
l2_ch_smtp_t *cfg = (l2_ch_smtp_t *)ctx->vp;
/* destroy channel configuration */
if (cfg->cpFrom != NULL)
free(cfg->cpFrom);
if (cfg->cpRcpt != NULL)
free(cfg->cpRcpt);
if (cfg->cpSubject != NULL)
free(cfg->cpSubject);
if (cfg->cpHost != NULL)
free(cfg->cpHost);
if (cfg->cpPort != NULL)
free(cfg->cpPort);
if (cfg->cpLocalHost != NULL)
free(cfg->cpLocalHost);
if (cfg->cpLocalUser != NULL)
free(cfg->cpLocalUser);
if (cfg->cpLocalProg != NULL)
free(cfg->cpLocalProg);
free(cfg);
return L2_OK;
}
/* exported channel handler structure */
l2_handler_t l2_handler_smtp = {
"smtp",
L2_CHANNEL_OUTPUT,
hook_create,
hook_configure,
hook_open,
hook_write,
NULL,
hook_close,
hook_destroy
};
@
1.12
log
@Adjust copyright messages for new year 2005.
@
text
@d3 3
a5 3
** Copyright (c) 2001-2004 Cable & Wireless
** Copyright (c) 2001-2004 The OSSP Project
** Copyright (c) 2001-2004 Ralf S. Engelschall
@
1.11
log
@- remove trailing whitespaces
- adjust copyright messages
- consistently use "OSSP l2"
- consistently talk about "Flexible Logging"
- use standard OSSP ASCII-art
@
text
@d3 3
a5 3
** Copyright (c) 2001-2003 Cable & Wireless Deutschland GmbH
** Copyright (c) 2001-2003 The OSSP Project (http://www.ossp.org/)
** Copyright (c) 2001-2003 Ralf S. Engelschall
@
1.10
log
@polish for release
@
text
@d2 4
a5 3
** OSSP l2 - Logging Library
** Copyright (c) 2001-2002 The OSSP Project (http://www.ossp.org/)
** Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/)
d7 1
a7 1
** This file is part of OSSP L2, a flexible logging library which
d50 1
a50 1
long nTimeout;
d95 1
a95 1
l2_param_t pa[10];
d129 1
a129 1
if ((rc = sa_addr_u2a(cfg->saaServer, "inet://%s:%s",
d162 2
a163 2
/*
d179 1
a179 1
* | User-Agent: L2/0.1.0
d202 1
a202 1
d231 1
a231 1
* | User-Agent: L2/0.1.0
d241 1
a241 1
sa_writef(sa, "User-Agent: %s (%s)\r\n",
d250 1
a250 1
sa_writef(sa, "Program %s of user %s on host %s logged:\r\n",
d253 1
a253 1
sa_writef(sa, "A program of user %s on host %s logged:\r\n",
@
1.9
log
@bump copyright year
@
text
@d2 1
a2 1
** L2 - OSSP Logging Library
d7 1
a7 1
** can be found at http://www.ossp.org/pkg/l2/.
@
1.8
log
@Hell, I've seldom seen that it is needed to prepare and adjust such a
lot of subtle details of existing code in order to make a new feature
implementable in a straight-forward way. Anyway, here comes one more
preparation change for the forthcoming channel tree specification
parser:
- change l2_util_setparam() to take an l2_env_t parameter
which allows the function to report better error messages.
- completely rewrite l2_util_setparam() to support calls
l2_channel_configure(ch, "n1=v1,n2=v2,n3=v3")
and/or
l2_channel_configure(ch, "n1=%x,n2=%x,n3=%x", v1, v2, v3)
instead of
l2_channel_configure(ch, "n1,n2,n3", v1, v2, v3)
This is both a step forward to make the interface of
l2_channel_configure() more flexible (because one now can directly
inline values instead of having them to be passed explicitly) and
allows the spec parser not having to know the type (integer, floating
point or string) of a parameter (which is important if one wants the
parser to be independent of the implementing channel handlers).
@
text
@d3 2
a4 2
** Copyright (c) 2001 The OSSP Project (http://www.ossp.org/)
** Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/)
@
1.7
log
@More preparations for forthcoming channel tree specification parser
(especially to allow the parser to determine the handler structure
from a handler name without introducing another and this way redundant
sub-API):
- add "char *name" to l2_handler_t in order to tag each
handler structure with the corresponding channel name
- add l2_env_handler() function to add handler to
l2_env_t objects. All l2_handler_xxxx are automatically
pre-configured there after l2_env_create().
- change l2_channel_create() to take a "const char *name"
(handler name) instead of the "l2_handler_t *h" (handler
pointer) to make the stuff consistent and more clear.
- adjust l2_test.c to reflect the changes.
@
text
@d96 1
d99 9
a107 9
L2_PARAM_SET(pa[0], progname, STRING, &cfg->cpLocalProg);
L2_PARAM_SET(pa[1], localhost, STRING, &cfg->cpLocalHost);
L2_PARAM_SET(pa[2], localuser, STRING, &cfg->cpLocalUser);
L2_PARAM_SET(pa[3], from, STRING, &cfg->cpFrom);
L2_PARAM_SET(pa[4], rcpt, STRING, &cfg->cpRcpt);
L2_PARAM_SET(pa[5], subject, STRING, &cfg->cpSubject);
L2_PARAM_SET(pa[6], host, STRING, &cfg->cpHost);
L2_PARAM_SET(pa[7], port, STRING, &cfg->cpPort);
L2_PARAM_SET(pa[8], timeout, INT, &cfg->nTimeout);
d109 2
a110 1
rv = l2_util_setparams(pa, fmt, ap);
@
1.6
log
@fix memory leak
@
text
@d333 1
@
1.5
log
@Upgrade to the latest and greatest OSSP SA.
@
text
@d324 2
@
1.4
log
@Upgrade to latest OSSP SA snapshot.
This time by using SA_PREFIX to hide SA inside the l2_util_ namespace prefix.
@
text
@d135 3
a137 2
sa_timeout(cfg->saServer, cfg->nTimeout, 0);
sa_buffers(cfg->saServer, 4096, 4096);
@
1.3
log
@Finish and enhance the SMTP channel implementation.
- use 4KB buffers, because a single SMTP line is
already allowed to be up to 1KB in size.
- use the cleanup macros to get rid of the deep if-cascade.
- add support for correct RFC2821/RFC2822 dot escaping
- add RFC2822-compliant Date header
- reduce User-Agent header to just "L2/V.R.L"
@
text
@d124 4
a127 1
if ((rc = sa_u2a(&cfg->saaServer, "tcp://%s:%s", cfg->cpHost, cfg->cpPort)) != SA_OK)
d196 1
a196 1
sa_rv = sa_readline(sa, caLine, sizeof(caLine), &n);
d201 2
a202 2
sa_printf(sa, "HELO %s\r\n", cfg->cpLocalHost);
sa_rv = sa_readline(sa, caLine, sizeof(caLine), &n);
d207 2
a208 2
sa_printf(sa, "MAIL FROM:<%s>\r\n", cfg->cpFrom);
sa_rv = sa_readline(sa, caLine, sizeof(caLine), &n);
d213 2
a214 2
sa_printf(sa, "RCPT TO:<%s>\r\n", cfg->cpRcpt);
sa_rv = sa_readline(sa, caLine, sizeof(caLine), &n);
d219 2
a220 2
sa_printf(sa, "DATA\r\n");
sa_rv = sa_readline(sa, caLine, sizeof(caLine), &n);
d232 4
a235 4
sa_printf(sa, "Date: %s\r\n", caDate);
sa_printf(sa, "From: %s\r\n", cfg->cpFrom);
sa_printf(sa, "To: %s\r\n", cfg->cpRcpt);
sa_printf(sa, "Subject: %s\r\n", cfg->cpSubject);
d237 1
a237 1
sa_printf(sa, "User-Agent: %s (%s)\r\n",
d240 1
a240 1
sa_printf(sa, "User-Agent: %s\r\n", l2_version.v_web);
d246 1
a246 1
sa_printf(sa, "Program %s of user %s on host %s logged:\r\n",
d249 1
a249 1
sa_printf(sa, "A program of user %s on host %s logged:\r\n",
d269 1
a269 1
sa_readline(sa, caLine, sizeof(caLine), &n);
d274 2
a275 2
sa_printf(sa, "QUIT\r\n");
sa_readline(sa, caLine, sizeof(caLine), &n);
d296 1
a296 1
free(cfg->saaServer);
@
1.2
log
@Upgraded both stream and channel-level APIs to include new L2_LEVEL parameter design.
@
text
@d37 1
d133 1
a133 1
sa_buffers(cfg->saServer, 1024, 1024);
a143 1
int bSent;
d146 2
a147 1
sa_rc_t rc;
d149 6
a155 6
/* establish connection to server */
saa = cfg->saaServer;
sa = cfg->saServer;
if ((rc = sa_connect(sa, saa)) != SA_OK)
return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
d168 2
a169 1
* | From: l2@@localhost
d171 2
a172 1
* | Subject: [L2] SMTP channel output
d174 2
a175 1
* | test log entry
d181 3
a183 2
* For more details about SMTP, see RFC 2821:
* Simple Mail Transfer Protocol; J. Klensin; April 2001.
d186 75
a260 44
bSent = FALSE;
if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
&& n > 3 && atoi(caLine) == 220) {
sa_printf(sa, "HELO %s\r\n", cfg->cpLocalHost);
if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
&& n > 3 && atoi(caLine) == 250) {
sa_printf(sa, "MAIL FROM:<%s>\r\n", cfg->cpFrom);
if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
&& n > 3 && atoi(caLine) == 250) {
sa_printf(sa, "RCPT TO:<%s>\r\n", cfg->cpRcpt);
if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
&& n > 3 && atoi(caLine) == 250) {
sa_printf(sa, "DATA\r\n");
if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
&& n > 3 && atoi(caLine) == 354) {
sa_printf(sa, "From: %s\r\n", cfg->cpFrom);
sa_printf(sa, "To: %s\r\n", cfg->cpRcpt);
sa_printf(sa, "Subject: %s\r\n", cfg->cpSubject);
if (cfg->cpLocalProg != NULL)
sa_printf(sa, "User-Agent: %s, %s\r\n",
cfg->cpLocalProg, l2_version.v_gnu);
else
sa_printf(sa, "User-Agent: %s\r\n", l2_version.v_gnu);
sa_printf(sa, "\r\n");
if (cfg->cpLocalProg != NULL)
sa_printf(sa, "Program %s of user %s on host %s logged:\r\n",
cfg->cpLocalProg, cfg->cpLocalUser, cfg->cpLocalHost);
else
sa_printf(sa, "A program of user %s on host %s logged:\r\n",
cfg->cpLocalUser, cfg->cpLocalHost);
/* FIXME: dot-escaping and remove doubled newline */
sa_write(sa, buf, buf_size, &n);
sa_printf(sa, "\r\n");
sa_printf(sa, ".\r\n");
if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
&& n > 3 && atoi(caLine) == 250) {
sa_printf(sa, "QUIT\r\n");
sa_readline(sa, caLine, sizeof(caLine), &n);
bSent = TRUE;
}
}
}
}
}
d263 13
d279 1
a279 1
return (bSent ? L2_OK : L2_ERR_IO);
@
1.1
log
@First cut for an SMTP output channel. This is very useful for
(additionally) logging L2_LEVEL_PANIC messages in real-time to a mailbox
via direct SMTP connection to a mail server. Internally it is very
simple, because it is based on our new Socket Abstraction (SA) library
(l2_ut_sa.[ch])...
@
text
@d138 2
a139 2
static l2_result_t hook_write(l2_context_t *ctx, l2_channel_t *ch,
const char *buf, size_t buf_size)
@