diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-05-07 15:17:34 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-05-07 15:17:34 +0300 |
commit | 05a8bb0ca988f41f016420ffc7dde427e423c187 (patch) | |
tree | fff58297f073bec8148c2d5468a45d592eab0379 /gacopyz | |
parent | 9f8f65324491b4186f4fd3c2580a8e0b14a248d9 (diff) | |
download | mailfromd-05a8bb0ca988f41f016420ffc7dde427e423c187.tar.gz mailfromd-05a8bb0ca988f41f016420ffc7dde427e423c187.tar.bz2 |
Implement v6 negotiation on the server side.
* gacopyz/stagenames.c: New file.
* gacopyz/Makefile.am (libgacopyz_a_SOURCES): Add stagenames.c.
* gacopyz/gacopyz.c (gacopyz_context_loop): Free req_macros.
(gacopyz_addrcpt_par): rename to gacopyz_add_rcpt_par.
* gacopyz/gacopyz.h (SM_LM_VRS_MAJOR, SM_LM_VRS_MAJOR)
(SM_LM_VRS_PLVL, GACOPYZ_SM_MKVER): New macros.
(macro_index): Rename to gacopyz_stage. All uses updated.
(smfi_version): New proto.
(gacopyz_addrcpt_par): rename to gacopyz_add_rcpt_par.
(gacopyz_stage_name): New declaration.
(gacopyz_srv_get_required_macros): New proto.
(gacopyz_srv_set_version, gacopyz_srv_set_protocol)
(gacopyz_srv_set_actions): 2nd argument is unsigned long.
* gacopyz/server.c (struct gacopyz_srv): New member req_macros.
(gacopyz_srv_get_required_macros): New function.
(gacopyz_srv_destroy): Free req_macros.
(gacopyz_srv_negotiate): Read macros.
* mfd/gram.y (milter_state_name): Removed. Use gacopyz_stage_name instead.
* mtasim/mtasim.c: New options: --gacopyz-log, --milter-proto, --milter-acts.
* doc/mtasim.texi, doc/mailfromd.texi: Update.
Diffstat (limited to 'gacopyz')
-rw-r--r-- | gacopyz/Makefile.am | 1 | ||||
-rw-r--r-- | gacopyz/context.c | 4 | ||||
-rw-r--r-- | gacopyz/gacopyz.c | 71 | ||||
-rw-r--r-- | gacopyz/gacopyz.h | 58 | ||||
-rw-r--r-- | gacopyz/gacopyz_priv.h | 4 | ||||
-rw-r--r-- | gacopyz/server.c | 121 | ||||
-rw-r--r-- | gacopyz/smfi.c | 17 | ||||
-rw-r--r-- | gacopyz/stagenames.c | 27 |
8 files changed, 237 insertions, 66 deletions
diff --git a/gacopyz/Makefile.am b/gacopyz/Makefile.am index 7d8c012b..d658b3e7 100644 --- a/gacopyz/Makefile.am +++ b/gacopyz/Makefile.am @@ -27,6 +27,7 @@ libgacopyz_a_SOURCES = \ mfapi.h\ proc.c\ server.c\ + stagenames.c\ trans.h EXTRA_DIST=trans.tab trans.awk diff --git a/gacopyz/context.c b/gacopyz/context.c index 41d64c44..12094fdf 100644 --- a/gacopyz/context.c +++ b/gacopyz/context.c @@ -1,5 +1,5 @@ /* This file is part of gacopyz. - Copyright (C) 2006, 2007 Sergey Poznyakoff + Copyright (C) 2006, 2007, 2009 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,7 +50,7 @@ gacopyz_getsymval(SMFICTX *ctx, const char *name) if (name[len-1] == '}') len--; - for (i = maci_max - 1; i >= 0; i--) { + for (i = gacopyz_stage_max - 1; i >= 0; i--) { if (ctx->macros[i].argv) { char **p; diff --git a/gacopyz/gacopyz.c b/gacopyz/gacopyz.c index f29681be..e26f7e2e 100644 --- a/gacopyz/gacopyz.c +++ b/gacopyz/gacopyz.c @@ -764,7 +764,7 @@ make_optneg_buf(SMFICTX *ctx, gacopyz_uint32_t *vbuf, size_t bufsize = 0; int i; - for (i = 0; i < maci_max; i++) { + for (i = 0; i < gacopyz_stage_max; i++) { if (ctx->req_macros[i]) bufsize += strlen(ctx->req_macros[i]) + 1 + sizeof(gacopyz_uint32_t); @@ -789,7 +789,7 @@ make_optneg_buf(SMFICTX *ctx, gacopyz_uint32_t *vbuf, *pbuf = buf; buf += OPTLEN; - for (i = 0; i < maci_max; i++) { + for (i = 0; i < gacopyz_stage_max; i++) { if (ctx->req_macros[i]) { gacopyz_uint32_t v; size_t len; @@ -901,7 +901,7 @@ macro_assoc_free(macro_assoc_t *p) static void clear_macros(SMFICTX *ctx, int i) { - for (; i < maci_max; i++) + for (; i < gacopyz_stage_max; i++) macro_assoc_free(&ctx->macros[i]); } @@ -962,7 +962,7 @@ shan_abort(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) static state_ret_type shan_macro(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { - enum macro_index ind; + enum gacopyz_stage ind; char **p; if (!arg->argv.v) @@ -970,31 +970,31 @@ shan_macro(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) switch (arg->argv.cmd) { case SMFIC_CONNECT: - ind = maci_conn; + ind = gacopyz_stage_conn; break; case SMFIC_HELO: - ind = maci_helo; + ind = gacopyz_stage_helo; break; case SMFIC_MAIL: - ind = maci_mail; + ind = gacopyz_stage_mail; break; case SMFIC_RCPT: - ind = maci_rcpt; + ind = gacopyz_stage_rcpt; break; case SMFIC_DATA: - ind = maci_data; + ind = gacopyz_stage_data; break; case SMFIC_BODYEOB: - ind = maci_eom; + ind = gacopyz_stage_eom; break; case SMFIC_EOH: - ind = maci_eoh; + ind = gacopyz_stage_eoh; break; default: @@ -1346,33 +1346,33 @@ shan_unkn(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) static struct state_disp disp[] = { { SMFIC_ABORT, "abort", - arg_no_args, shan_abort, st_abrt, CT_CNT, maci_none }, + arg_no_args, shan_abort, st_abrt, CT_CNT, gacopyz_stage_none }, { SMFIC_MACRO, "macro", - arg_argvc, shan_macro, st_none, CT_CNT, maci_none }, + arg_argvc, shan_macro, st_none, CT_CNT, gacopyz_stage_none }, { SMFIC_BODY, "body", - arg_one_string, shan_body, st_body, CT_CNT, maci_none }, + arg_one_string, shan_body, st_body, CT_CNT, gacopyz_stage_none }, { SMFIC_CONNECT, "connect", - arg_two_strings, shan_connect, st_conn, CT_CLR, maci_conn }, + arg_two_strings, shan_connect, st_conn, CT_CLR, gacopyz_stage_conn }, { SMFIC_BODYEOB, "endm", - arg_one_string, shan_endm, st_endm, CT_CNT, maci_eom }, + arg_one_string, shan_endm, st_endm, CT_CNT, gacopyz_stage_eom }, { SMFIC_HELO, "helo", - arg_one_string, shan_helo, st_helo, CT_CLR, maci_helo }, + arg_one_string, shan_helo, st_helo, CT_CLR, gacopyz_stage_helo }, { SMFIC_HEADER, "header", - arg_two_strings, shan_header, st_hdrs, CT_CNT, maci_none }, + arg_two_strings, shan_header, st_hdrs, CT_CNT, gacopyz_stage_none }, { SMFIC_MAIL, "mail", - arg_argv, shan_mail, st_mail, CT_CLR, maci_mail }, + arg_argv, shan_mail, st_mail, CT_CLR, gacopyz_stage_mail }, { SMFIC_OPTNEG, "optneg", - arg_ints, shan_optneg, st_opts, CT_CNT, maci_none }, + arg_ints, shan_optneg, st_opts, CT_CNT, gacopyz_stage_none }, { SMFIC_EOH, "eoh", - arg_no_args, shan_eoh, st_eohs, CT_CNT, maci_none }, + arg_no_args, shan_eoh, st_eohs, CT_CNT, gacopyz_stage_none }, { SMFIC_QUIT, "quit", - arg_no_args, shan_quit, st_quit, CT_END, maci_none }, + arg_no_args, shan_quit, st_quit, CT_END, gacopyz_stage_none }, { SMFIC_DATA, "data", - arg_no_args, shan_data, st_data, CT_CNT, maci_none }, + arg_no_args, shan_data, st_data, CT_CNT, gacopyz_stage_none }, { SMFIC_RCPT, "rcpt", - arg_argv, shan_rcpt, st_rcpt, CT_IGN|CT_CLR, maci_rcpt }, + arg_argv, shan_rcpt, st_rcpt, CT_IGN|CT_CLR, gacopyz_stage_rcpt }, { SMFIC_UNKNOWN, "unknown", - arg_one_string, shan_unkn, st_unkn, CT_IGN|CT_CLR, maci_none } + arg_one_string, shan_unkn, st_unkn, CT_IGN|CT_CLR, gacopyz_stage_none } }; struct state_disp * @@ -1488,6 +1488,17 @@ report_command(enum state state, enum state next_state, gacopyz_logdump(SMI_LOG_WARN, _("buffer"), buffer, size); } +static int +ctx_free(SMFICTX *ctx) +{ + int i; + + free(ctx->reply); + clear_macros(&ctx, 0); + for (i = 0; i < gacopyz_stage_max; i++) + free(ctx->req_macros[i]); +} + int gacopyz_context_loop(int fd, struct smfiDesc *desc) { @@ -1648,9 +1659,9 @@ gacopyz_context_loop(int fd, struct smfiDesc *desc) free(buffer); if (desc->xxfi_close) desc->xxfi_close(&ctx); - free(ctx.reply); - clear_macros(&ctx, 0); + ctx_free(&ctx); + if (desc->xxfi_finish) desc->xxfi_finish(); @@ -2026,7 +2037,7 @@ gacopyz_quarantine(SMFICTX *ctx, const char *reason) } int -gacopyz_addrcpt_par(SMFICTX *ctx, const char *rcpt, const char *args) +gacopyz_add_rcpt_par(SMFICTX *ctx, const char *rcpt, const char *args) { if (!rcpt || !*rcpt) return MI_FAILURE; @@ -2046,9 +2057,9 @@ gacopyz_chgfrom(SMFICTX *ctx, const char *from, const char *args) } int -gacopyz_setsymlist(SMFICTX *ctx, enum macro_index ind, const char *macros) +gacopyz_setsymlist(SMFICTX *ctx, enum gacopyz_stage ind, const char *macros) { - if (ind < 0 || ind >= maci_max) + if (ind < 0 || ind >= gacopyz_stage_max) return MI_FAILURE; if (ctx->req_macros[ind]) free(ctx->req_macros[ind]); diff --git a/gacopyz/gacopyz.h b/gacopyz/gacopyz.h index f0b5bff2..f7d547a7 100644 --- a/gacopyz/gacopyz.h +++ b/gacopyz/gacopyz.h @@ -48,6 +48,13 @@ extern "C" { /* Implementation version number */ #define SMFI_VERSION 0x01000000 +#define SM_LM_VRS_MAJOR(v) (((v) & 0x7f000000) >> 24) +#define SM_LM_VRS_MINOR(v) (((v) & 0x007fff00) >> 8) +#define SM_LM_VRS_PLVL(v) ((v) & 0x0000007f) + +#define GACOPYZ_SM_MKVER(maj,min,pat) \ + ((((maj) & 0x7f)<<24) | (((min) & 0x7ffff) << 8) | ((pat) & 0x7f)) + /* Milter protocol version */ #define SMFI_PROT_VERSION 6 @@ -199,26 +206,26 @@ typedef union { struct sockaddr_un sunix; } milter_sockaddr_t; -enum macro_index { - maci_conn, - maci_helo, - maci_mail, - maci_rcpt, - maci_data, - maci_eom, - maci_eoh, +enum gacopyz_stage { + gacopyz_stage_conn, + gacopyz_stage_helo, + gacopyz_stage_mail, + gacopyz_stage_rcpt, + gacopyz_stage_data, + gacopyz_stage_eom, + gacopyz_stage_eoh, - maci_max, - maci_none = maci_max + gacopyz_stage_max, + gacopyz_stage_none = gacopyz_stage_max }; -#define SMFIM_CONNECT maci_conn -#define SMFIM_HELO maci_helo -#define SMFIM_ENVFROM maci_mail -#define SMFIM_ENVRCPT maci_rcpt -#define SMFIM_DATA maci_data -#define SMFIM_EOM maci_eom -#define SMFIM_EOH maci_eoh +#define SMFIM_CONNECT gacopyz_stage_conn +#define SMFIM_HELO gacopyz_stage_helo +#define SMFIM_ENVFROM gacopyz_stage_mail +#define SMFIM_ENVRCPT gacopyz_stage_rcpt +#define SMFIM_DATA gacopyz_stage_data +#define SMFIM_EOM gacopyz_stage_eom +#define SMFIM_EOH gacopyz_stage_eoh #define _SOCK_ADDR milter_sockaddr_t #define smfiDesc gacopyz_milter_descr @@ -275,6 +282,7 @@ struct gacopyz_milter_descr }; /* Standard API calls */ +extern int smfi_version (unsigned int *, unsigned int *, unsigned int *); extern int smfi_opensocket (int); extern int smfi_register (struct smfiDesc); extern int smfi_main (void); @@ -365,15 +373,17 @@ int gacopyz_replace_body(SMFICTX *ctx, const unsigned char *bodyp, size_t bodylen); int gacopyz_progress(SMFICTX *ctx); int gacopyz_quarantine(SMFICTX *ctx, const char *reason); -int gacopyz_addrcpt_par(SMFICTX *ctx, const char *rcpt, const char *args); +int gacopyz_add_rcpt_par(SMFICTX *ctx, const char *rcpt, const char *args); int gacopyz_chgfrom(SMFICTX *ctx, const char *from, const char *args); -int gacopyz_setsymlist(SMFICTX *ctx, enum macro_index ind, const char *macros); +int gacopyz_setsymlist(SMFICTX *ctx, enum gacopyz_stage ind, const char *macros); int gacopyz_setpriv (SMFICTX *ctx, void *data); void *gacopyz_getpriv (SMFICTX *ctx); /* Logging (extensions) */ +extern const char *gacopyz_stage_name[gacopyz_stage_max]; + #define GACOPYZ_VBUFSIZE 69 size_t gacopyz_format_vbuf(char vbuf[GACOPYZ_VBUFSIZE], const char *buf, size_t size); @@ -411,6 +421,10 @@ void gacopyz_srv_iterate_macros (gacopyz_srv_t srv, void *data), void *data); void gacopyz_srv_count_macros (gacopyz_srv_t srv, size_t *count); + +const char **gacopyz_srv_get_required_macros(gacopyz_srv_t srv, + enum gacopyz_stage stage); + int gacopyz_srv_connect (gacopyz_srv_t srv); int gacopyz_srv_init(gacopyz_srv_t srv); int gacopyz_srv_negotiate(gacopyz_srv_t srv); @@ -440,9 +454,9 @@ void gacopyz_srv_set_callback(gacopyz_srv_t srv, void gacopyz_srv_set_callback_data(gacopyz_srv_t, void *); int gacopyz_srv_set_source(gacopyz_srv_t srv, unsigned long addr); -int gacopyz_srv_set_version(gacopyz_srv_t srv, int version); -int gacopyz_srv_set_protocol(gacopyz_srv_t srv, int proto); -int gacopyz_srv_set_actions(gacopyz_srv_t srv, int acts); +int gacopyz_srv_set_version(gacopyz_srv_t srv, unsigned long version); +int gacopyz_srv_set_protocol(gacopyz_srv_t srv, unsigned long proto); +int gacopyz_srv_set_actions(gacopyz_srv_t srv, unsigned long acts); #define GACOPYZ_WRITE_TIMEOUT 10 #define GACOPYZ_READ_TIMEOUT 10 diff --git a/gacopyz/gacopyz_priv.h b/gacopyz/gacopyz_priv.h index 76be1611..d7e1ffe9 100644 --- a/gacopyz/gacopyz_priv.h +++ b/gacopyz/gacopyz_priv.h @@ -34,8 +34,8 @@ struct smfi_str { unsigned long mta_pflags; /* pflags supported by MTA */ unsigned long aflags; /* milter action flags (from xxfi_flags) */ int nmacros; /* Number of entries in macros */ - macro_assoc_t macros[maci_max]; /* Macro tables */ - char *req_macros[maci_max]; /* Required macros */ + macro_assoc_t macros[gacopyz_stage_max]; /* Macro tables */ + char *req_macros[gacopyz_stage_max]; /* Required macros */ char *reply; /* reply code */ void *privdata; /* private data */ }; diff --git a/gacopyz/server.c b/gacopyz/server.c index a61836e8..e7cfa643 100644 --- a/gacopyz/server.c +++ b/gacopyz/server.c @@ -1,5 +1,5 @@ /* This file is part of gacopyz. - Copyright (C) 2007, 2008 Sergey Poznyakoff + Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -49,6 +49,7 @@ struct gacopyz_srv { unsigned long version; unsigned long acts; unsigned long proto; + char **req_macros[gacopyz_stage_max]; /* Required macros */ int (*cb_reply) (gacopyz_srv_t srv, int cmd, int rcmd, void *data); void *cb_data; @@ -279,6 +280,13 @@ gacopyz_srv_count_macros(gacopyz_srv_t srv, size_t *count) } +const char ** +gacopyz_srv_get_required_macros(gacopyz_srv_t srv, enum gacopyz_stage stage) +{ + return (const char **) srv->req_macros[stage]; +} + + struct timeval default_gacopyz_timeout[GACOPYZ_TO_COUNT] = { { GACOPYZ_WRITE_TIMEOUT, 0 }, @@ -612,7 +620,7 @@ gacopyz_srv_set_source(gacopyz_srv_t srv, unsigned long addr) } int -gacopyz_srv_set_version(gacopyz_srv_t srv, int version) +gacopyz_srv_set_version(gacopyz_srv_t srv, unsigned long version) { GACOPYZ_ASSERT(srv); @@ -621,7 +629,7 @@ gacopyz_srv_set_version(gacopyz_srv_t srv, int version) } int -gacopyz_srv_set_protocol(gacopyz_srv_t srv, int proto) +gacopyz_srv_set_protocol(gacopyz_srv_t srv, unsigned long proto) { GACOPYZ_ASSERT(srv); @@ -630,7 +638,7 @@ gacopyz_srv_set_protocol(gacopyz_srv_t srv, int proto) } int -gacopyz_srv_set_actions(gacopyz_srv_t srv, int acts) +gacopyz_srv_set_actions(gacopyz_srv_t srv, unsigned long acts) { GACOPYZ_ASSERT(srv); @@ -638,15 +646,24 @@ gacopyz_srv_set_actions(gacopyz_srv_t srv, int acts) return MI_SUCCESS; } - void gacopyz_srv_destroy(gacopyz_srv_t *p) { + int i; + gacopyz_srv_t srv = *p; gacopyz_srv_clear_macros(srv); free(srv->portspec); free(srv->id); free(srv->def); + for (i = 0; i < gacopyz_stage_max; i++) + if (srv->req_macros[i]) { + int j; + + for (j = 0; srv->req_macros[i][j]; j++) + free(srv->req_macros[i][j]); + free(srv->req_macros[i]); + } free(srv->buf); free(srv); *p = 0; @@ -860,6 +877,94 @@ gacopyz_srv_connect(gacopyz_srv_t srv) return MI_SUCCESS; } +#define ISWS(c) ((c) == ' ' || (c) == '\t') + +static void +parse_macros(gacopyz_srv_t srv, enum gacopyz_stage stage, char *buf) +{ + char *p; + char **argv; + size_t count; + + count = 0; + for (p = buf; *p;) { + while (*p && ISWS(*p)) + p++; + if (*p) { + count++; + while (*p && !ISWS(*p)) + p++; + } + } + if (count == 0) + return; + GACOPYZ_ALLOC(srv, argv = calloc(count + 1, sizeof(argv[0]))); + count = 0; + for (p = buf; *p;) { + while (*p && ISWS(*p)) + p++; + if (*p) { + size_t i; + char *str = p; + + for (i = 0; *p && !ISWS(*p); p++, i++) + ; + if (i > 0) { + char *newstr; + + if (*str == '{' && str[i-1] == '}') { + str++; + i -= 2; + } + GACOPYZ_ALLOC(srv, newstr = malloc(i + 1)); + memcpy(newstr, str, i); + newstr[i] = 0; + argv[count++] = newstr; + } + } + } + argv[count] = NULL; + srv->req_macros[stage] = argv; +} + + +static void +read_macros(gacopyz_srv_t srv) +{ + char *buf = srv->buf + 3 * sizeof(gacopyz_uint32_t); + size_t size = srv->bufsize - 3 * sizeof(gacopyz_uint32_t); + + while (size > sizeof(gacopyz_uint32_t)) { + gacopyz_uint32_t v; + unsigned n; + size_t len; + + memcpy (&v, buf, sizeof(gacopyz_uint32_t)); + n = ntohl(v); + if (n >= gacopyz_stage_max) { + gacopyz_io_log(&srv->iod, SMI_LOG_ERR, + _("received invalid stage number")); + break; + } + buf += sizeof(gacopyz_uint32_t); + size -= sizeof(gacopyz_uint32_t); + if (size == 0) + break; + len = strlen(buf) + 1; + if (len > size) { + gacopyz_io_log(&srv->iod, SMI_LOG_ERR, + _("invalid macro list")); + break; + } + gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG, + _("macros for stage \"%s\" (%d): %s"), + gacopyz_stage_name[n], n, buf); + parse_macros(srv, n, buf); + buf += len; + size -= len; + } +} + int gacopyz_srv_negotiate(gacopyz_srv_t srv) { @@ -927,6 +1032,10 @@ gacopyz_srv_negotiate(gacopyz_srv_t srv) return MI_FAILURE; } + if (milter_version > 3 + && srv->bufsize > 3 * sizeof(gacopyz_uint32_t)) + read_macros(srv); + srv->version = milter_version; srv->acts = milter_acts; srv->proto = milter_proto; @@ -1209,8 +1318,6 @@ gacopyz_srv_conn(gacopyz_srv_t srv, const char *hostname, struct sockaddr *sa) int gacopyz_srv_helo(gacopyz_srv_t srv, const char *domain) { - int rc; - GACOPYZ_ASSERT(srv); if (srv->state == srv_msgproc) gacopyz_srv_abort(srv); diff --git a/gacopyz/smfi.c b/gacopyz/smfi.c index 721b3460..4f8628d4 100644 --- a/gacopyz/smfi.c +++ b/gacopyz/smfi.c @@ -197,7 +197,7 @@ smfi_quarantine(SMFICTX *ctx, char *reason) int smfi_addrcpt_par(SMFICTX *ctx, char *rcpt, char *args) { - return gacopyz_addrcpt_par(ctx, rcpt, args); + return gacopyz_add_rcpt_par(ctx, rcpt, args); } int @@ -209,12 +209,23 @@ smfi_chgfrom(SMFICTX *ctx, char *from, char *args) int smfi_setsymlist(SMFICTX *ctx, int n, char *macros) { - if (n < 0 || n >= maci_max) + if (n < 0 || n >= gacopyz_stage_max) return MI_FAILURE; if (!macros || !*macros || ctx->req_macros[n]) return MI_FAILURE; return gacopyz_setsymlist(ctx, n, macros); } - +int +smfi_version(unsigned int *maj, unsigned int *min, unsigned int *pat) +{ + if (maj) + *maj = SM_LM_VRS_MAJOR(SMFI_VERSION); + if (min) + *min = SM_LM_VRS_MINOR(SMFI_VERSION); + if (pat) + *pat = SM_LM_VRS_MINOR(SMFI_VERSION); + return MI_SUCCESS; +} + diff --git a/gacopyz/stagenames.c b/gacopyz/stagenames.c new file mode 100644 index 00000000..0be67617 --- /dev/null +++ b/gacopyz/stagenames.c @@ -0,0 +1,27 @@ +/* This file is part of gacopyz. + Copyright (C) 2009 Sergey Poznyakoff + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <gacopyz_priv.h> + +const char *gacopyz_stage_name[gacopyz_stage_max] = { + "connect", + "helo", + "envfrom", + "envrcpt", + "data", + "eom", + "eoh" +}; |