diff options
-rw-r--r-- | lexer.l | 46 | ||||
-rw-r--r-- | local.c | 59 | ||||
-rw-r--r-- | local.h | 4 | ||||
-rw-r--r-- | main.c | 54 | ||||
-rw-r--r-- | message.c | 116 | ||||
-rw-r--r-- | message.h | 6 | ||||
-rw-r--r-- | parser.y | 13 | ||||
-rw-r--r-- | rfc822.c | 21 | ||||
-rw-r--r-- | smtp.c | 18 | ||||
-rw-r--r-- | smtp.h | 4 | ||||
-rw-r--r-- | xmalloc.h | 56 |
11 files changed, 172 insertions, 225 deletions
@@ -1,22 +1,22 @@ %{ -/* - * lexer.l -- lexer for the rcfile +/** + * \file lexer.l + * Lexer for the rcfile. + * + * \author Adapted from fetchmail's rcfile_l.l by José Fonseca */ -/* - * Adapted from fetchmail's rcfile_l.l by José Fonseca - */ - + #include <stdio.h> #include <string.h> #include "parser.h" +#include "xmalloc.h" -#define MSGBUFSIZE 8192 int lineno = 1; -void escapes(const char *tp, char *cp); +void escapes(const char *tp, char *cp, size_t n); %} @@ -25,29 +25,29 @@ void escapes(const char *tp, char *cp); %% \"[^\"]*\" { - char buf[MSGBUFSIZE]; + char buf[BUFSIZ]; yytext[strlen(yytext)-1] = '\0'; - escapes(yytext+1, buf); - yylval.sval = (char *) strdup(buf); + escapes(yytext+1, buf, BUFSIZ); + yylval.sval = xstrdup(buf); BEGIN(0); return STRING; } \'[^\']*\' { - char buf[MSGBUFSIZE]; + char buf[BUFSIZ]; yytext[strlen(yytext)-1] = '\0'; - escapes(yytext+1, buf); - yylval.sval = (char *) strdup(buf); + escapes(yytext+1, buf, BUFSIZ); + yylval.sval = xstrdup(buf); BEGIN(0); return STRING; } <NAME>[^=;, \t\r\n]+ { - char buf[MSGBUFSIZE]; + char buf[BUFSIZ]; - escapes(yytext, buf); - yylval.sval = (char *) strdup(buf); + escapes(yytext, buf, BUFSIZ); + yylval.sval = xstrdup(buf); BEGIN(0); return STRING; } @@ -73,10 +73,10 @@ required { return REQUIRED; } -?[0-9]+/[^a-zA-Z] { yylval.number = atoi(yytext); return NUMBER; } [^=;:, \t\r\n]+ { - char buf[MSGBUFSIZE]; + char buf[BUFSIZ]; - escapes(yytext, buf); - yylval.sval = (char *) strdup(buf); + escapes(yytext, buf, BUFSIZ); + yylval.sval = xstrdup(buf); return STRING; } @@ -87,10 +87,11 @@ required { return REQUIRED; } /* process standard C-style escape sequences in a string */ void escapes( const char *cp, /* source string with escapes */ - char *tp /* target buffer for digested string */ + char *tp, /* target buffer for digested string */ + size_t n ) { - while (*cp) + while (*cp && --n) { int cval = 0; @@ -126,6 +127,7 @@ void escapes( else cval = *cp++; *tp++ = cval; + } *tp = '\0'; } @@ -12,6 +12,7 @@ #include "local.h" #include "main.h" +#include "xmalloc.h" #if 0 @@ -37,29 +38,24 @@ static void sanitize(char *s) *cp = '_'; } -#define xmalloc malloc -#define xstrdup strdup - -#define HAVE_SETEUID /** * Pipe the message to the MDA for local delivery. * * Based on fetchmail's open_mda_sink(). */ -int local_init(message_t *message) +void local_init(message_t *message) { -#ifdef HAVE_SETEUID - uid_t orig_uid, uid; - struct passwd *pw; -#endif /* HAVE_SETEUID */ struct idlist *idp; int length = 0, fromlen = 0, nameslen = 0; char *names = NULL, *before, *after, *from = NULL; char *user = NULL; if (!mda) - return 1; + { + fprintf(stderr, "local delivery not possible without a MDA"); + exit(EX_OSFILE); + } length = strlen(mda); before = xstrdup(mda); @@ -172,46 +168,20 @@ int local_init(message_t *message) before = after; } -#ifdef HAVE_SETEUID - /* - * Arrange to run with user's permissions if we're root. - * This will initialize the ownership of any files the - * MDA creates properly. (The seteuid call is available - * under all BSDs and Linux) - */ - orig_uid = getuid(); - /* if `user' doesn't name a real local user, try to run as root */ - if ((pw = getpwnam(user)) == (struct passwd *)NULL) - uid = 0; - else - uid = pw->pw_uid; /* for local delivery via MDA */ - seteuid(uid); -#endif /* HAVE_SETEUID */ - - mda_fp = popen(before, "w"); - -#ifdef HAVE_SETEUID - /* this will fail quietly if we didn't start as root */ - seteuid(orig_uid); -#endif /* HAVE_SETEUID */ - - if (!mda_fp) + + if(!(mda_fp = popen(before, "w"))) { - free(before); - before = NULL; fprintf(stderr, "MDA open failed\n"); - return 0; + exit(EX_OSERR); } - + if(verbose) fprintf(stdout, "Connected to MDA: %s\n", before); free(before); - before = NULL; - return 1; } -int local_flush(message_t *message) +void local_flush(message_t *message) { char buffer[BUFSIZ]; size_t n; @@ -219,10 +189,11 @@ int local_flush(message_t *message) do { n = message_read(message, buffer, BUFSIZ); if(fwrite(buffer, 1, n, mda_fp) != n) - return 0; + { + perror(NULL); + exit(EX_OSERR); + } } while(n == BUFSIZ); - - return 1; } void local_cleanup(void) @@ -19,9 +19,9 @@ extern FILE *mda_fp; int local_address(const char *address); /** Send a message locally (via a MDA) */ -int local_init(message_t *msg); +void local_init(message_t *msg); -int local_flush(message_t *msg); +void local_flush(message_t *msg); void local_cleanup(void); @@ -23,7 +23,6 @@ FILE *log_fp = NULL; int main (int argc, char **argv) { int c; - int ret; enum notify_flags notify = Notify_NOTSET; char *from = NULL; message_t *message; @@ -298,73 +297,54 @@ int main (int argc, char **argv) exit (EX_USAGE); } - if(!(message = message_new())) - goto error; + message = message_new(); /** Parse the envelope headers */ if(parse_headers) - { if(!message_parse_headers(message)) { - fprintf(stderr, "Failed to parse headers\n"); - exit(EX_DATAERR); - } - - if(!remote && !local) - { fprintf(stderr, "No recipients found\n"); exit(EX_DATAERR); } - } /* Set the reverse path for the mail envelope. */ - if(from && !message_set_reverse_path (message, from)) - goto error; + if(from) + message_set_reverse_path (message, from); /* Add remaining program arguments as message recipients. */ - while (optind < argc) { - if(!message_add_recipient(message, argv[optind++])) - goto error; - } + while (optind < argc) + message_add_recipient(message, argv[optind++]); local = !list_empty(&message->local_recipients); remote = !list_empty(&message->remote_recipients); if(remote && !local) - ret = smtp_send(message); + smtp_send(message); else if(!remote && local) { - if(!local_init(message)) - goto error; - - if(!local_flush(message)) - goto error; - + local_init(message); + local_flush(message); local_cleanup(); - - ret = 0; } else { - if(!local_init(message)) - goto error; + local_init(message); - ret = smtp_send(message); + smtp_send(message); if(ferror(mda_fp)) - goto error; + { + perror(NULL); + exit(EX_OSERR); + } - if(!message_eof(message) && !local_flush(message)) - goto error; + if(!message_eof(message)) + local_flush(message); local_cleanup(); } message_free(message); - return ret; - -error: - perror(NULL); - exit(255); + exit(EX_OK); } @@ -14,14 +14,14 @@ #include "message.h" #include "local.h" #include "rfc822.h" +#include "xmalloc.h" message_t *message_new(void) { message_t *message; - if(!(message = (message_t *)malloc(sizeof(message_t)))) - return NULL; + message = (message_t *)xmalloc(sizeof(message_t)); memset(message, 0, sizeof(message_t)); @@ -71,39 +71,29 @@ void message_free(message_t *message) free(message); } -int message_set_reverse_path(message_t *message, const char *address) +void message_set_reverse_path(message_t *message, const char *address) { if(message->reverse_path) free(message->reverse_path); - if(!(message->reverse_path = strdup(address))) - return 0; - - return 1; + message->reverse_path = xstrdup(address); } -int message_add_recipient(message_t *message, const char *address) +void message_add_recipient(message_t *message, const char *address) { recipient_t *recipient; - if(!(recipient = (recipient_t *)malloc(sizeof(recipient_t)))) - return 0; + recipient = (recipient_t *)xmalloc(sizeof(recipient_t)); - if(!(recipient->address = strdup(address))) - { - free(recipient); - return 0; - } + recipient->address = xstrdup(address); if(local_address(address)) list_add(&recipient->list, &message->local_recipients); else list_add(&recipient->list, &message->remote_recipients); - - return 1; } -static int message_buffer_alloc(message_t *message) +static void message_buffer_alloc(message_t *message) { char *buffer; size_t buffer_size; @@ -113,13 +103,10 @@ static int message_buffer_alloc(message_t *message) else buffer_size = message->buffer_size << 1; - if(!(buffer = (char *)realloc(message->buffer, buffer_size))) - return 0; + buffer = (char *)xrealloc(message->buffer, buffer_size); message->buffer = buffer; message->buffer_size = buffer_size; - - return 1; } static char *message_buffer_readline(message_t *message) @@ -129,8 +116,8 @@ static char *message_buffer_readline(message_t *message) while(1) { - if(message->buffer_stop >= message->buffer_size - 1 && !message_buffer_alloc(message)) - return NULL; + if(message->buffer_stop >= message->buffer_size - 1) + message_buffer_alloc(message); if(!fgets(message->buffer + message->buffer_stop, message->buffer_size - message->buffer_stop, fp)) return NULL; @@ -218,8 +205,8 @@ size_t message_read(message_t *message, char *ptr, size_t size) { size_t count = 0, n; - if(!message->buffer && !message_buffer_alloc(message)) - return 0; + if(!message->buffer) + message_buffer_alloc(message); n = message_buffer_flush(message, ptr, size); count += n; @@ -259,8 +246,9 @@ int message_eof(message_t *message) return feof(fp); } -static int message_parse_header(message_t *message, size_t start, size_t stop) +static unsigned message_parse_header(message_t *message, size_t start, size_t stop) { + unsigned count = 0; const char *address; char *header, *next, c; @@ -273,8 +261,10 @@ static int message_parse_header(message_t *message, size_t start, size_t stop) if(!strncasecmp("From: ", header, 6)) { if((address = next_address(header))) - if(!message_set_reverse_path(message, address)) - return 0; + { + message_set_reverse_path(message, address); + count++; + } } else if(!strncasecmp("To: ", header, 4) || !strncasecmp("Cc: ", header, 4) || @@ -283,8 +273,8 @@ static int message_parse_header(message_t *message, size_t start, size_t stop) address = next_address(header); while(address) { - if(!message_add_recipient(message, address)) - return 0; + message_add_recipient(message, address); + count++; address = next_address(NULL); } @@ -301,19 +291,19 @@ static int message_parse_header(message_t *message, size_t start, size_t stop) message->buffer_stop = start + n; } - return 1; + return count; } -int message_parse_headers(message_t *message) +unsigned message_parse_headers(message_t *message) { FILE *fp = message->fp ? message->fp : stdin; char *line, *header; size_t start, stop; + unsigned count = 0; assert(!message->buffer); - if(!message_buffer_alloc(message)) - return 0; + message_buffer_alloc(message); start = 0; while((line = message_buffer_readline(message))) @@ -325,62 +315,16 @@ int message_parse_headers(message_t *message) else { stop = line - message->buffer; - if(stop && !message_parse_header(message, start, stop)) - return 0; + if(stop) + count += message_parse_header(message, start, stop); start = stop; if(line[0] == '\n') - return 1; + return count; } } - return 0; -} - -#ifdef TEST -int local_address(const char *address) -{ - return !strchr(address, '@'); -} - -int main(int argc, char *argv[]) -{ - message_t *message = message_new(); - const size_t len = 8192; - size_t n; - char buf[len]; - unsigned i; - FILE *fpin, *fpout; - struct list_head *ptr; - int ret; - - fpin = fopen("test.in", "r"); - fpout = fopen("test.out", "w"); - message->fp = fpin; - ret = message_parse_headers(message); - do { - n = message_read(message, buf, len); - fwrite(buf, 1, n, fpout); - } while(n == len); - - printf("%d %s\n", ret, message->reverse_path); - list_for_each(ptr, &message->local_recipients) - { - recipient_t *recipient = list_entry(ptr, recipient_t, list); - - if(recipient->address) - printf("%s\n",recipient->address); - } - list_for_each(ptr, &message->remote_recipients) - { - recipient_t *recipient = list_entry(ptr, recipient_t, list); - - if(recipient->address) - printf("%s\n",recipient->address); - } - - message_free(message); + fprintf(stderr, "Failed to parse headers\n"); + exit(EX_DATAERR); } - -#endif @@ -49,11 +49,11 @@ message_t *message_new(void); /** Free the resources associated with a message. */ void message_free(message_t *m); -int message_set_reverse_path(message_t *message, const char *address); +void message_set_reverse_path(message_t *message, const char *address); -int message_add_recipient(message_t *message, const char *address); +void message_add_recipient(message_t *message, const char *address); -int message_parse_headers(message_t *message); +unsigned message_parse_headers(message_t *message); size_t message_read(message_t *message, char *ptr, size_t size); @@ -17,6 +17,7 @@ #include "main.h" #include "smtp.h" #include "local.h" +#include "xmalloc.h" /* parser reads these */ @@ -69,7 +70,7 @@ identity : IDENTITY map STRING { identity = identity_new(); identity_add(identity); - identity->address = strdup($3); + identity->address = xstrdup($3); } ; @@ -78,14 +79,14 @@ statement_list : statement ; /* future global options should also have the form SET <name> optmap <value> */ -statement : HOSTNAME map STRING { identity->host = strdup($3); } - | USERNAME map STRING { identity->user = strdup($3); } - | PASSWORD map STRING { identity->pass = strdup($3); } +statement : HOSTNAME map STRING { identity->host = xstrdup($3); } + | USERNAME map STRING { identity->user = xstrdup($3); } + | PASSWORD map STRING { identity->pass = xstrdup($3); } | STARTTLS map DISABLED { identity->starttls = Starttls_DISABLED; } | STARTTLS map ENABLED { identity->starttls = Starttls_ENABLED; } | STARTTLS map REQUIRED { identity->starttls = Starttls_REQUIRED; } - | CERTIFICATE_PASSPHRASE map STRING { identity->certificate_passphrase = strdup($3); } - | MDA map STRING { mda = strdup($3); } + | CERTIFICATE_PASSPHRASE map STRING { identity->certificate_passphrase = xstrdup($3); } + | MDA map STRING { mda = xstrdup($3); } ; %% @@ -19,14 +19,17 @@ #include <stdlib.h> -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - #define HEADER_END(p) ((p)[0] == '\n' && ((p)[1] != ' ' && (p)[1] != '\t')) +#define START_HDR 0 /**< before header colon */ +#define SKIP_JUNK 1 /**< skip whitespace, \n, and junk */ +#define BARE_ADDRESS 2 /**< collecting address without delimiters */ +#define INSIDE_DQUOTE 3 /**< inside double quotes */ +#define INSIDE_PARENS 4 /**< inside parentheses */ +#define INSIDE_BRACKETS 5 /**< inside bracketed address */ +#define ENDIT_ALL 6 /**< after last address */ + /** * Parse addresses in succession out of a specified RFC822 header. * @@ -40,14 +43,6 @@ char *next_address(const char *hdr) static int state, oldstate; int parendepth = 0; -#define START_HDR 0 /* before header colon */ -#define SKIP_JUNK 1 /* skip whitespace, \n, and junk */ -#define BARE_ADDRESS 2 /* collecting address without delimiters */ -#define INSIDE_DQUOTE 3 /* inside double quotes */ -#define INSIDE_PARENS 4 /* inside parentheses */ -#define INSIDE_BRACKETS 5 /* inside bracketed address */ -#define ENDIT_ALL 6 /* after last address */ - #define NEXTTP() ((tp < sizeof(address)-1) ? tp++ : tp) if (hdr) @@ -20,6 +20,7 @@ #include "smtp.h" #include "local.h" #include "main.h" +#include "xmalloc.h" /** @@ -35,8 +36,7 @@ identity_t *identity_new(void) { identity_t *identity; - if(!(identity = (identity_t *)malloc(sizeof(identity_t)))) - return NULL; + identity = (identity_t *)xmalloc(sizeof(identity_t)); memset(identity, 0, sizeof(identity_t)); @@ -89,12 +89,9 @@ identity_t *identity_lookup(const char *address) return default_identity; } -int identities_init(void) +void identities_init(void) { - if(!(default_identity = identity_new())) - return 0; - - return 1; + default_identity = identity_new(); } void identities_cleanup(void) @@ -306,7 +303,7 @@ void print_recipient_status (smtp_recipient_t recipient, const char *mailbox, fprintf (stderr, "%s: %d %s\n", mailbox, status->code, status->text); } -int smtp_send(message_t *msg) +void smtp_send(message_t *msg) { smtp_session_t session; smtp_message_t message; @@ -403,7 +400,7 @@ int smtp_send(message_t *msg) char buf[128]; fprintf (stderr, "SMTP server problem %s\n", - smtp_strerror (smtp_errno (), buf, sizeof buf)); + smtp_strerror (smtp_errno (), buf, sizeof(buf))); ret = EX_UNAVAILABLE; } @@ -431,7 +428,8 @@ int smtp_send(message_t *msg) auth_destroy_context (authctx); auth_client_exit (); - return ret; + if (ret != EX_OK) + exit(ret); } /*@}*/ @@ -45,7 +45,7 @@ void identity_add(identity_t *identity); identity_t *identity_lookup(const char *address); /** Initialize the identities resources */ -int identities_init(void); +void identities_init(void); /** Cleanup the resources associated with the identities */ void identities_cleanup(void); @@ -54,6 +54,6 @@ void identities_cleanup(void); /** Send a message via a SMTP server */ -int smtp_send(message_t *msg); +void smtp_send(message_t *msg); #endif diff --git a/xmalloc.h b/xmalloc.h new file mode 100644 index 0000000..881bcad --- /dev/null +++ b/xmalloc.h @@ -0,0 +1,56 @@ +/** + * \file xmalloc.c + * Allocate space or die. + * + * \author Adapted from fetchmail's xmalloc.c by José Fonseca. + */ + +#ifndef _XMALLOC_H +#define _XMALLOC_H + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "main.h" + + +static inline +void *xmalloc(size_t size) +{ + void *ptr; + + ptr = malloc(size); + if (ptr == NULL) + { + perror(NULL); + exit(EX_OSERR); + } + return(ptr); +} + +static inline +void *xrealloc(void *ptr, size_t size) +{ + if (ptr == 0) + return xmalloc(size); + ptr = realloc(ptr, size); + if (ptr == NULL) + { + perror(NULL); + exit(EX_OSERR); + } + return ptr; +} + +static inline +char *xstrdup(const char *s) +{ + char *p; + p = (char *)xmalloc(strlen(s) + 1); + strcpy(p, s); + return p; +} + +#endif |