home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************/
- /* sendmail.c */
- /* ---------- */
- /* */
- /* Copyright (C) 1990, 1991 Ingo Feulner, Magic Soft Developments */
- /* -- all rights reserved -- */
- /* */
- /* This program may be copied for non-comercial use. */
- /* */
- /**********************************************************************/
-
- /*
- Note: This Programm has been written for the SAS/C compiler.
- So I have used sometimes C++ - style comments (//).
-
- Revision history:
-
- 29-Jul-90 first version created.
- 19-Aug-90 new parser. seems to work
- 20-Aug-90 first mail read-in routine written. works well.
- version is now 0.10
- 21-Aug-90 Mail is now copied into a mail structure.
- 22-Aug-90 First save routine written. It works!
- 28-Aug-90 Last known bugs corrected. Looks well.
- 30-Aug-90 First send_mailerdaemon() routine written.
- 1-Sep-90 Now sendmail can be used without the need of a maps database
- 14-Sep-90 UULIB:Domain file has now the same format than the output
- of 'pathalias'. There can be now domain and system path
- entries. version is now 0.90
- 18-Sep-90 Some bug-fixes. version is now 0.91
- 2-Oct-90 Fixed a bug in the rfctime() routine. version is 0.92
- The "From " line is now RFC976 compatible.
- 1-Nov-90 Corrected clean_address(). Now a address in the form
- "Realname <user@node.domain>" is passed correctly.
- Version is now 0.93
- 2-Mar-91 Changed parse() in parse.c so, that now site.domain will be used
- for database searching. This is the correct way.
- Version is now 0.94
- 7-Mar-91 parse() returned wrong path if the address had the dummy ".UUCP"
- domain. This is now corrected.
- Version is again 0.94
- 17-Apr-91 Changed rfctime() and messageid() to be to RFC1123-conform.
- Corrected some bugs in strltok() and readin_mail() which
- caused Enforcer hits.
- Added support for multiline header entries.
- 20-Apr-91 Rewritten the address parser. Now there should be no more problems.
- Version is now 0.95.
- 24-Apr-91 Now the "Reply-To:" entry will not be deleted, if given.
- Version is now 0.96.
- 29-Apr-91 The address in the form "@gateway.dom.ain:user@system.dom.ain"
- will now be parsed correctly.
- Version is now 0.97
- 3-May-91 'Bcc:' thing works now.
- Version is now 0.98
- 8-May-91 Now every address is parsed very carefully for comments and
- things like this.
- Version is now 1.00 - released to the public.
- 19-May-91 clean_address_line() completely rewritten. Has now no more problems
- with commas in comments. Corrected some other bugs and an enforcer
- hit in compare_address().
- Version is now 1.01
- 11-Jun-91 Now there will ever be a "remote" entry in the frompath...
- Version is now 1.02
- */
-
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <time.h>
- #include "config.h"
- #include "log.h"
- #include "support.h"
-
- #define MAINVERSION "//\\\\migaUUCP Plus 1.02b"
- #define VERDATE " 1.02 (11 Jun 91) "
-
- #define PALIAS "palias" /* Name of the database relative to UULIB */
- #define MYBUFLEN 4096 /* Must be enough in any case */
-
- #define ADDRSEPCHAR '\x08' /* Defines End of a single address */
- #define ADDRSEP "\x08"
-
-
-
- /********************/
- /* data structures: */
- /********************/
-
- /* linked address list */
- struct Address
- {
- struct Address *a_next; /* Pointer to next address. NULL if only one addr. */
- char *a_original; /* Original address (smart, bang, etc) */
- char *a_address; /* Address without the node we will sent the mail to */
- char *a_system; /* node we will sent the mail to. NULL if local */
- short a_type; /* Type of Address (Bcc or normal) */
- };
-
- #define NRM_ADDR 0
- #define BCC_ADDR 10
-
- /* our mail structure */
- struct Mail
- {
- /* struct mail *m_next; Pointer to next mail. Yet unused */
- struct Address m_address; /* linked address list */
- short m_rmail; /* if m_rmail != 0, than act as rmail */
- char *m_rmailaddr; /* rmail address, if m_rmail != 0 */
- char *m_frompath; /* 'From ' line. The way the mail came */
- char *m_fromsystem; /* The system name we got the mail from */
- char *m_messageid; /* The messageid of the mail, if given */
- char *m_date; /* Date when the mail was written */
- char *m_from; /* User sent the mail */
- char *m_replyto; /* If given, it must be used instead of From: */
- char *m_to; /* Address where the mail should go */
- char *m_subject; /* mail subject */
- char *m_cc; /* Copies to the following addresses */
- char *m_bcc; /* Blind carbon copy */
- char *m_receivedbuf; /* contains all old 'received: ' lines */
- long m_rbuflen; /* lenght of receivedbuf in bytes */
- char *m_headerbuf; /* contains the uninteresting rest of the header */
- long m_hbuflen; /* length of headerbuf in bytes */
- char *m_mailbuf; /* contains the pure mail */
- long m_mbuflen; /* length of mailbuf in bytes */
- };
-
-
- /***************/
- /* Prototypes: */
- /***************/
-
- /* Imports: */
-
- /* Local: */
- void version(void);
- void init(void);
- struct Mail *init_mailstruct(void);
- int readin_mail(struct Mail *, FILE *);
- void set_mailparams(struct Mail *);
- int sendmail(struct Mail *);
- int local_sendmail(struct Mail *, struct Address *);
- int forward_sendmail(struct Mail *, struct Address *);
- int check_addressline(struct Address *, struct Mail *, char *, short);
- char *get_header_entry(char *, long, FILE *);
- void test_parsing(void);
-
- /* Support routines: */
- char *__regargs strltok(char *, char *, char **);
- char *__regargs clean_address_line(char *);
- char *__regargs clean_address(char *, char *);
- int __regargs compare_nodes(char *, char *);
- char *get_sender(char *);
- char *messageid(int);
- int check_local_address(char *, char **);
-
-
- /************/
- /* Globals: */
- /************/
-
- static char *version20 = "$VER: sendmail" VERDATE "\n\r";
- static char *NULL_String = "\x00";
-
- char *_TZ;
- char *Progname;
- char *UserName;
- char *RealName;
- char *NodeName;
- char *DomainName;
- char *DefaultNode;
- int Seq; /* Global Sequence number. Used for messagid, if new mail,
- and for first Received - line entry */
-
- int sendmailcalls = 1; /* How often have we send a mail?
- This is used for the right sequence number; */
-
- short DataBase = 1; /* Used by parse() */
-
- void version(void)
- {
- fprintf(stderr, "AmigaUUCP Plus: %s%s\n", Progname, VERDATE);
- fprintf(stderr, "Copyright (C) 1990, 1991 Ingo Feulner\n\n");
- fprintf(stderr, "Usage: %s [-f from] [-t to] [-s subject]\n", Progname);
- fprintf(stderr, "\t\t[-c cc] [-b bcc] [-r] [-?] [-V]\n");
- }
-
- int mybreak(void)
- {
- return 0;
- }
-
- int main(int argc, char *argv[])
- {
- extern char *optarg;
- extern int optind;
-
- struct Mail *mail;
- struct Address *addr;
- char *buf;
- signed char c;
- int returncode = 0;
-
-
- LogProgram = "sendmail";
-
- onbreak(mybreak);
-
- /* Get pure program name */
- {
- char *ptr = argv[0] + strlen(argv[0]);
-
- while(ptr >= argv[0] && *ptr != '/' && *ptr != ':')
- ptr--;
- ++ptr;
-
- Progname = ptr;
- }
-
- init();
- mail = init_mailstruct(); /* allocate and init mail structure */
-
- while((c = getopt(argc, argv, "f:t:s:c:b:r:T?V")) > 0)
- {
- switch(c)
- {
- case 'f':
- buf = xmalloc(256);
- if(strchr(optarg, ATSIGN) == NULL) /* Only Username, without node */
- {
- if((strcmp(optarg, UserName)) == 0)
- sprintf(buf, "%s@%s%s (%s)", optarg, NodeName, DomainName, RealName);
- else
- sprintf(buf, "%s@%s%s", optarg, NodeName, DomainName);
-
- mail->m_from = strsave(buf);
- }
- else /* Address contains node */
- {
- mail->m_from = strsave(optarg);
- }
- free(buf);
- break;
- case 't':
- mail->m_to = strsave(optarg);
- break;
- case 's':
- mail->m_subject = strsave(optarg);
- break;
- case 'c':
- mail->m_cc = strsave(optarg);
- break;
- case 'b':
- mail->m_bcc = strsave(optarg);
- break;
- case 'r':
- mail->m_rmail = 1;
- mail->m_rmailaddr = strsave(optarg);
- break;
- case '?':
- version();
- exit(20);
- break;
- case 'V':
- version();
- break;
-
- case 'T':
- test_parsing();
- exit(0);
- break;
- }
- }
-
- LockFile("sendmail");
-
- if(readin_mail(mail, stdin) != SUCCEED)
- {
- fprintf(stderr, "This is no mail\n");
- exit(20);
- }
-
- set_mailparams(mail);
-
- #ifdef MYDEBUG
- printf("From System: %s\n", mail->m_fromsystem);
- printf("Frompath: %s\n\n", mail->m_frompath);
- printf("Receivedbuf: (Size %ld bytes)\n%s\n\n", mail->m_rbuflen,
- mail->m_receivedbuf);
- printf("Message-Id: %s\n", mail->m_messageid);
- printf("Date: %s\n", mail->m_date);
- printf("From: %s\n", mail->m_from);
- printf("To: %s\n", mail->m_to);
- printf("Cc: %s\n", mail->m_cc);
- printf("Bcc: %s\n", mail->m_bcc);
- printf("Subject: %s\n\n", mail->m_subject);
- printf("Rest of header: (Size %ld bytes)\n%s\n\n", mail->m_hbuflen,
- mail->m_headerbuf);
- printf("Mail: (Size %ld bytes)\n%s\n\n", mail->m_mbuflen, mail->m_mailbuf);
-
- printf("This mail will be sent to:\n");
- for(addr = mail->m_address.a_next; addr != NULL; addr = addr->a_next)
- {
- printf("Spoolsystem: %s\n", addr->a_system);
- printf("Address : %s\n\n", addr->a_address);
- }
-
- exit(0);
- #endif /* MYDEBUG */
-
-
- if(sendmail(mail) != SUCCEED)
- {
- ulog(-1, "All addresses were unknown");
- }
-
- UnLockFile("sendmail");
- return returncode;
- }
-
- static char *funnytext = "This is a binary and not a textfile, you idiot!";
-
- int sendmail(struct Mail *mail)
- {
- struct Address *addr;
- char *buf = xmalloc(256);
-
- int returncode;
- int successful = 0;
-
- for(addr = mail->m_address.a_next; addr != NULL; addr = addr->a_next)
- {
- if(*addr->a_system != '\0') /* Forward Mail */
- {
- returncode = forward_sendmail(mail, addr);
- }
- else /* Local mail */
- {
- returncode = local_sendmail(mail, addr);
- }
-
- sendmailcalls++;
-
- if(returncode != SUCCEED)
- {
- sprintf(buf, "sending mail to '%s' failed", addr->a_original);
- }
- else
- {
- sprintf(buf, "sending mail to '%s' succeeded", addr->a_original);
- successful++;
- }
- ulog(-1, buf);
- }
- free(buf);
-
- if(successful > 0)
- return SUCCEED;
- else
- return FAIL;
- }
-
- int forward_sendmail(struct Mail *mail, struct Address *addr)
- {
- FILE *cfp;
- FILE *dfp;
- FILE *xfp;
-
- static char comfile[50];
- static char datfile[50];
- static char exefile[50];
- static char xfile[50];
-
- char *user;
- int seq;
-
- seq = (sendmailcalls == 1) ? Seq : GetSequence(1);
-
- if(mail->m_rmail == 0)
- user = get_sender(mail->m_from);
- else
- user = "uucp";
-
- sprintf(comfile, "C.%.6sA%04lx", addr->a_system, seq);
- sprintf(datfile, "D.%.6sB%04lx", addr->a_system, seq);
- sprintf(exefile, "D.%.6sX%04lx", addr->a_system, seq);
- sprintf(xfile, "X.%.6sX%04lx", addr->a_system, seq);
-
- cfp = fopen(MakeConfigPath(UUSPOOL, comfile), "w");
- dfp = fopen(MakeConfigPath(UUSPOOL, datfile), "w");
- xfp = fopen(MakeConfigPath(UUSPOOL, exefile), "w");
-
- if(cfp == NULL || dfp == NULL || xfp == NULL)
- return FAIL;
-
- /* First, write the mail */
-
- fprintf(dfp, "From %s\n", mail->m_frompath);
-
- if(mail->m_rmail != 0)
- {
- fprintf(dfp,
- "Received: from %s by %s%s (" MAINVERSION ")\n"
- "\tid AA%05ld; %s\n",
- mail->m_fromsystem, NodeName, DomainName, seq, rfctime());
- }
- else
- {
- fprintf(dfp,
- "Received: by %s%s (" MAINVERSION ")\n"
- "\tid AA%05ld; %s\n", NodeName, DomainName, seq, rfctime());
- }
-
- if(mail->m_rbuflen > 0)
- (void)fwrite(mail->m_receivedbuf, mail->m_rbuflen, 1, dfp);
-
- if(mail->m_hbuflen > 0)
- (void)fwrite(mail->m_headerbuf, mail->m_hbuflen, 1, dfp);
-
- fprintf(dfp, "Message-Id: %s\n", mail->m_messageid);
- fprintf(dfp, "Date: %s\n", mail->m_date);
- fprintf(dfp, "From: %s\n", mail->m_from);
-
- if(mail->m_replyto != NULL && *mail->m_replyto != '\0')
- fprintf(dfp, "Reply-To: %s\n", mail->m_replyto);
-
- fprintf(dfp, "To: %s\n", mail->m_to);
-
- if(mail->m_cc != NULL && *mail->m_cc != '\0')
- fprintf(dfp, "Cc: %s\n", mail->m_cc);
-
- if(mail->m_bcc != NULL && *mail->m_bcc != '\0' && addr->a_type == BCC_ADDR)
- fprintf(dfp, "Bcc: %s\n", mail->m_bcc);
-
- fprintf(dfp, "Subject: %s\n\n", mail->m_subject);
- /* double newline indicates end of header */
-
- /* So lets write the pure mail */
- if(mail->m_mbuflen > 0)
- (void)fwrite(mail->m_mailbuf, mail->m_mbuflen, 1, dfp);
-
- if(ferror(dfp))
- return FAIL;
-
- fclose(dfp);
-
- /* Second, write the exefile */
-
- fprintf(xfp, "U %s %s\n", user, NodeName);
- fprintf(xfp, "F %s\n", datfile);
- fprintf(xfp, "I %s\n", datfile);
- fprintf(xfp, "C rmail %s\n", addr->a_address);
-
- if(ferror(xfp))
- return FAIL;
-
- fclose(xfp);
-
- /* Last, write the commandfile */
-
- fprintf(cfp, "S %s %s %s - %s 0666\n", datfile, datfile, user, datfile);
- fprintf(cfp, "S %s %s %s - %s 0666\n", exefile, xfile, user, exefile);
-
- if(ferror(cfp))
- return FAIL;
-
- fclose(cfp);
-
- return SUCCEED;
- }
-
- int local_sendmail(struct Mail *mail, struct Address *addr)
- {
- FILE *output;
-
- int seq = (sendmailcalls == 1) ? Seq : GetSequence(1);
-
- if((output = fopen(MakeConfigPath(UUMAIL, addr->a_address), "a")) == NULL)
- return FAIL;
-
-
- fprintf(output, "From %s\n", mail->m_frompath);
-
- if(mail->m_rmail != 0)
- {
- fprintf(output,
- "Received: from %s by %s%s (" MAINVERSION ")\n"
- "\tid AA%05ld; %s\n",
- mail->m_fromsystem, NodeName, DomainName, seq, rfctime());
- }
- else
- {
- fprintf(output,
- "Received: by %s%s (" MAINVERSION ")\n"
- "\tid AA%05ld; %s\n", NodeName, DomainName, seq, rfctime());
- }
-
- if(mail->m_rbuflen > 0)
- (void)fwrite(mail->m_receivedbuf, mail->m_rbuflen, 1, output);
-
- if(mail->m_hbuflen > 0)
- (void)fwrite(mail->m_headerbuf, mail->m_hbuflen, 1, output);
-
- fprintf(output, "Message-Id: %s\n", mail->m_messageid);
- fprintf(output, "Date: %s\n", mail->m_date);
- fprintf(output, "From: %s\n", mail->m_from);
-
- if(mail->m_replyto != NULL && *mail->m_replyto != '\0')
- fprintf(output, "Reply-To: %s\n", mail->m_replyto);
-
- fprintf(output, "To: %s\n", mail->m_to);
-
- if(mail->m_cc != NULL && *mail->m_cc != '\0')
- fprintf(output, "Cc: %s\n", mail->m_cc);
-
- if(mail->m_bcc != NULL && *mail->m_bcc != '\0' && addr->a_type == BCC_ADDR)
- fprintf(output, "Bcc: %s\n", mail->m_bcc);
-
- fprintf(output, "Subject: %s\n\n", mail->m_subject);
- /* double newline indicates end of header */
-
- /* So lets write now the pure mail */
- if(mail->m_mbuflen > 0)
- (void)fwrite(mail->m_mailbuf, mail->m_mbuflen, 1, output);
-
- if(ferror(output))
- return FAIL;
-
- fclose(output);
-
- return SUCCEED;
- }
-
- static char *addr_error_banner = "\
- |------------------------- Failed address follows -----------------------|\n";
- static char *text_banner ="\
- |------------------------- Message text follows -------------------------|\n";
- static char *textend_banner ="\
- |------------------------- End of message -------------------------------|\n";
-
- void send_mailerdaemon(struct Mail *mail, char *address)
- {
- #define ENDOFBUF(ptr) ((ptr += strlen(ptr)))
-
- struct Mail *dmail;
- struct Address *faddress;
-
- char *sender;
- char *buf = xmalloc(512); /* Used as a temporary buffer */
-
- dmail = xcalloc(sizeof(struct Mail));
- faddress = xcalloc(sizeof(struct Address));
-
- sender = clean_address_line(mail->m_from); /* Cut off Realname */
-
- if((check_addressline(faddress, NULL, sender, NRM_ADDR)) == 1)
- {
- char *tmpbuf;
- char *ptr;
-
- ulog(-1, "mailerguru: sending mail back to sender '%s'", sender);
-
-
- tmpbuf = xmalloc(mail->m_rbuflen + mail->m_hbuflen
- + mail->m_mbuflen + 8192);
- ptr = tmpbuf;
-
- /* Initialize new daemon mail structure */
- sprintf(buf, "mailerguru@%s%s (Guru Mailer)", NodeName, DomainName);
-
- /* Mail header */
- dmail->m_from = strsave(buf);
- dmail->m_to = strsave(mail->m_from);
- dmail->m_subject = strsave("Failed mail");
-
- /* Mail */
- sprintf(ptr, "%s\n%s\n\n%s\n", addr_error_banner, address, text_banner);
- ENDOFBUF(ptr); /* Jump to end of buf */
-
- sprintf(ptr, ">From %s\n", mail->m_frompath);
- ENDOFBUF(ptr);
-
- /*
- if(mail->m_rmail != 0)
- {
- sprintf(ptr,
- "Received: from %s by %s%s (" MAINVERSION ")\n"
- "\tid AA%05ld; %s\n",
- mail->m_fromsystem, NodeName, DomainName, seq, rfctime());
- }
- else
- {
- sprintf(ptr,
- "Received: by %s%s (" MAINVERSION ")\n"
- "\tid AA%05ld; %s\n", NodeName, DomainName, seq, rfctime());
- }
- ENDOFBUF(ptr);
- */
-
- if(mail->m_rbuflen > 0)
- {
- (void)stccpy(ptr, mail->m_receivedbuf, mail->m_rbuflen);
- ENDOFBUF(ptr);
- }
-
- if(mail->m_hbuflen > 0)
- {
- (void)stccpy(ptr, mail->m_headerbuf, mail->m_hbuflen);
- ENDOFBUF(ptr);
- }
-
- sprintf(ptr, "Message-Id: %s\n", mail->m_messageid);
- ENDOFBUF(ptr);
- sprintf(ptr, "Date: %s\n", mail->m_date);
- ENDOFBUF(ptr);
- sprintf(ptr, "From: %s\n", mail->m_from);
- ENDOFBUF(ptr);
- sprintf(ptr, "To: %s\n", mail->m_to);
- ENDOFBUF(ptr);
-
- if(mail->m_cc != NULL && *mail->m_cc != '\0')
- {
- sprintf(ptr, "Cc: %s\n", mail->m_cc);
- ENDOFBUF(ptr);
- }
-
- if(mail->m_bcc != NULL && *mail->m_bcc != '\0')
- {
- sprintf(ptr, "Bcc: %s\n", mail->m_bcc);
- ENDOFBUF(ptr);
- }
-
- sprintf(ptr, "Subject: %s\n\n", mail->m_subject);
- /* double newline indicates end of header */
- ENDOFBUF(ptr);
-
- /* So lets write now the pure mail */
- if(mail->m_mbuflen > 0)
- {
- (void)stccpy(ptr, mail->m_mailbuf, mail->m_mbuflen);
- ENDOFBUF(ptr);
- }
-
- sprintf(ptr, "\n\n%s", textend_banner);
-
- dmail->m_mailbuf = tmpbuf;
- dmail->m_mbuflen = strlen(tmpbuf); /* Hope that works always */
-
- /* Set the other mail parameters */
- set_mailparams(dmail);
-
- /* Lets send it! */
- if((sendmail(dmail)) != SUCCEED)
- {
- ulog(-1, "mailerguru: failed.");
- fprintf(stderr, "%s: Fatal Error! Sending mailerdaemon message failed\n", Progname);
- fprintf(stderr, "ABORTING!\n");
- exit(20);
- }
- }
- else
- {
- fprintf(stderr, "Sender unknown\n");
- }
- }
-
- int readin_mail(struct Mail *mail, FILE *input)
- {
- char *buf = xmalloc(MYBUFLEN);
- char *tmphdr = NULL;
-
- /*
- if mail->m_rmail != 0, act as rmail. So the first line must be
- the "From ..." line
- */
- if(mail->m_rmail != 0)
- {
- if((fgets(buf, MYBUFLEN - 1, input)) != NULL)
- {
- if((strncmp(buf, "From ", 5)) == 0) /* Found it */
- {
- char *tmpbuf = strsave(strclean(&buf[5]));
- *(strchr(tmpbuf, ' ')) = '\0'; /* Cut away old time & date */
-
- mail->m_frompath = strsave(tmpbuf);
- free(tmpbuf);
- }
- else /* Ugh, no mail! */
- {
- fprintf(stderr, "%s: no mail.\n", Progname);
- return FAIL;
- }
- }
- else
- {
- fprintf(stderr, "%s: null file\n", Progname);
- return FAIL;
- }
- }
-
-
- while((get_header_entry(buf, MYBUFLEN - 1, input)) != NULL)
- {
- if(mail->m_rmail != 0) /* Check only for 'Received' if acting as rmail */
- {
- if((strncmp(buf, "Received: ", 10)) == 0)
- {
- char *tmpbuf;
- char *destbuf;
- char *rptr;
- char *dest;
-
- destbuf = xmalloc(strlen(buf) + 1);
- dest = destbuf;
-
- rptr = &buf[10];
- if((strncmp(rptr, "by ", 3)) == 0)
- {
- char *ptr = &rptr[3];
-
- while(*ptr != ' ' && *ptr != '.' && *ptr != '\0')
- *dest++ = *ptr++;
- *dest = '\0';
- }
- else if((strncmp(rptr, "from ", 5)) == 0)
- {
- char *ptr = &rptr[5];
-
- while(*ptr != '\0' && *ptr != ' ')
- ptr++;
-
- if(*ptr != '\0')
- ptr++;
-
- if((strncmp(ptr, "by ", 3)) == 0)
- {
- ptr += 3;
-
- while(*ptr != ' ' && *ptr != '.' && *ptr != '\0')
- *dest++ = *ptr++;
- *dest = '\0';
- }
- }
-
- if(*destbuf != '\0')
- {
- mail->m_fromsystem = xmalloc(strlen(destbuf) + 1);
- strcpy(mail->m_fromsystem, destbuf);
- }
- else
- {
- fprintf(stderr, "%s: warning: unknown received line format:\n%s\n",
- Progname, buf);
- }
- free(destbuf);
-
- tmpbuf = strsave(buf);
-
- while((fgets(buf, MYBUFLEN - 1, input)) != NULL)
- {
- if(((strncmp(buf, "Received: ", 10)) == 0)
- || (*buf == '\t') || (*buf == ' '))
- {
- tmpbuf = xrealloc(tmpbuf, strlen(tmpbuf) + strlen(buf) + 1);
- strcat(tmpbuf, buf);
- }
- else
- break;
- }
- mail->m_receivedbuf = tmpbuf;
- mail->m_rbuflen = strlen(tmpbuf);
- }
- } /* end of rmail part */
-
- if((strncmp(buf, "From:", 5)) == 0)
- {
- if(mail->m_from == NULL)
- mail->m_from = strsave(strclean(&buf[5]));
- }
- else if((strncmp(buf, "Reply-To:", 9)) == 0)
- {
- mail->m_replyto = strsave(strclean(&buf[9]));
- }
- else if((strncmp(buf, "To:", 3)) == 0)
- {
- if(mail->m_to == NULL)
- mail->m_to = strsave(strclean(&buf[3]));
- }
- else if((strncmp(buf, "Subject:", 8)) == 0)
- {
- if(mail->m_subject == NULL)
- mail->m_subject = strsave(strclean(&buf[8]));
- }
- else if((strncmp(buf, "Date:", 5)) == 0)
- {
- mail->m_date = strsave(strclean(&buf[5]));
- }
- else if((strncmp(buf, "Message-Id:", 11)) == 0)
- {
- mail->m_messageid = strsave(strclean(&buf[11]));
- }
- else if((strncmp(buf, "Cc:", 3)) == 0)
- {
- if(mail->m_cc == NULL)
- mail->m_cc = strsave(strclean(&buf[3]));
- }
- else if((strncmp(buf, "Bcc:", 4)) == 0)
- {
- if(mail->m_bcc == NULL)
- mail->m_bcc = strsave(strclean(&buf[4]));
- }
- else if(*buf == '\n') /* Newline indicates end of header */
- {
- break;
- }
- else /* Other header entries, not specially scanned */
- {
- if(tmphdr == NULL)
- tmphdr = strsave(buf);
- else
- {
- tmphdr = xrealloc(tmphdr, strlen(tmphdr) + strlen(buf) + 1);
- strcat(tmphdr, buf);
- }
- }
- }
-
- if(tmphdr != NULL)
- {
- mail->m_headerbuf = tmphdr;
- mail->m_hbuflen = strlen(tmphdr);
- }
- else
- {
- mail->m_headerbuf = NULL;
- mail->m_hbuflen = 0;
- }
-
-
- if(!feof(input)) /* Now lets read in the 'real' mail */
- {
- char *tmpmail;
- long i = 0;
-
- tmpmail = xmalloc(MYBUFLEN);
-
- (void)memset(buf, 0, MYBUFLEN);
-
- while((fread(buf, MYBUFLEN, 1, input)) == 1)
- {
- (void)memcpy(tmpmail + (i * MYBUFLEN), buf, MYBUFLEN);
- tmpmail = xrealloc(tmpmail, (i + 2) * MYBUFLEN); /* allocate next block */
-
- (void)memset(buf, 0, MYBUFLEN);
- i++;
- }
- /* And finally, copy the rest until 0 is reached */
- (void)strcpy(tmpmail + (i * MYBUFLEN), buf);
-
- mail->m_mailbuf = tmpmail;
- mail->m_mbuflen = (i * MYBUFLEN) + strlen(buf);
- }
- else
- {
- return FAIL;
- }
-
- free(buf);
-
- return SUCCEED;
- }
-
- /*
- get_header_entry()
-
- Returns a header entry. Checks for multiple-line entries.
- */
- char *get_header_entry(char *buffer, long length, FILE *fp)
- {
- char buf[512];
- char *destbuf;
- char *p;
-
- int c;
-
- p = destbuf = xmalloc(length + 1);
-
-
- if((fgets(buf, sizeof(buf), fp)) != NULL)
- {
- if( ((strncmp(buf, "Received: ", 10)) == 0) || (*buf == '\n') )
- {
- strcpy(buffer, buf);
- free(destbuf);
-
- return buffer;
- }
-
- // strcpy(p, strclean(buf));
- strcpy(p, buf);
- p += strlen(buf);
-
- for(;;)
- {
- if((c = getc(fp)) != EOF && (c == ' ' || c == '\t'))
- {
- fgets(buf, sizeof(buf), fp);
- *p++ = ' ';
-
- // strcpy(p, strclean(buf));
- strcpy(p, buf);
- p += strlen(buf);
- }
- else
- {
- ungetc(c, fp);
- break;
- }
- }
-
- strcpy(buffer, destbuf);
- free(destbuf);
- return buffer;
- }
- return NULL;
- }
-
-
- void set_mailparams(struct Mail *mail)
- {
- if(mail->m_rmail != 0) /* act as rmail */
- {
- char *fromsystem;
-
- fromsystem = strsave(mail->m_fromsystem);
-
- /* First, make the new 'From' Line. */
- {
- char *tmpbuf;
-
- if(*fromsystem != '\0')
- {
- char *currtime = rfctime();
-
- tmpbuf = xmalloc(strlen(fromsystem) + strlen(mail->m_frompath) +
- strlen(currtime) + 100);
-
- /* First let's see if the node is already in the from - line */
- if((compare_nodes(fromsystem, mail->m_frompath)) != SUCCEED)
- { /* no */
- strcpy(tmpbuf, fromsystem);
- strcat(tmpbuf, "!");
- }
- strcat(tmpbuf, mail->m_frompath);
- strcat(tmpbuf, " ");
- strcat(tmpbuf, currtime);
- strcat(tmpbuf, " remote from ");
- strcat(tmpbuf, NodeName);
- }
- else /* we can't get a system name out of the last 'received' line, */
- { /* so change only time & date */
- char *currtime = rfctime();
-
- tmpbuf = xmalloc(strlen(mail->m_frompath) + strlen(currtime) + 100);
-
- strcpy(tmpbuf, mail->m_frompath);
- strcat(tmpbuf, " ");
- strcat(tmpbuf, currtime);
- strcat(tmpbuf, " remote from ");
- strcat(tmpbuf, NodeName);
- }
-
- free(mail->m_frompath);
- mail->m_frompath = strsave(tmpbuf);
- free(tmpbuf);
- }
-
- /* So, now lets look what we have to do with the mail */
- (void)check_addressline(&mail->m_address, mail, mail->m_rmailaddr, NRM_ADDR);
- }
- else /* act as sendmail - new mail */
- {
- char *fromname;
- char *buf = xmalloc(512);
-
- if(mail->m_from == NULL || *mail->m_from == '\0')
- {
- fromname = UserName;
-
- sprintf(buf, "%s@%s%s (%s)", UserName, NodeName, DomainName, RealName);
- mail->m_from = strsave(buf);
- }
- else
- {
- fromname = get_sender(mail->m_from);
- }
-
- /* Let's make the from - path */
- /* RFC976
- sprintf(buf, "%s%s!%s %s remote from %s", NodeName, DomainName,
- fromname, rfctime(), NodeName);
- */
-
- /* Normal */
- sprintf(buf, "%s %s remote from %s", fromname, rfctime(), NodeName);
-
- mail->m_frompath = strsave(buf);
-
- /* And check the other entries */
- if(mail->m_date == NULL || *mail->m_date == '\0')
- {
- mail->m_date = strsave(rfctime());
- }
-
- if(mail->m_messageid == NULL || *mail->m_messageid == '\0')
- {
- mail->m_messageid = messageid(0);
- }
-
- /* No subject? */
- if(mail->m_subject == NULL || *mail->m_subject == '\0')
- mail->m_subject = strsave("(none)");
-
- free(buf); /* Finally, free the buf */
-
- /* now let's check the dest. address */
- {
- /* First, the 'To: ' line */
- (void)check_addressline(&mail->m_address, mail,
- clean_address_line(mail->m_to), NRM_ADDR);
-
- /* And then, the 'Cc:' line */
- if(mail->m_cc != NULL && *mail->m_cc != '\0')
- (void)check_addressline(&mail->m_address, mail,
- clean_address_line(mail->m_cc), NRM_ADDR);
-
- /* And finally the 'Bcc' line */
- if(mail->m_bcc != NULL && *mail->m_bcc != '\0')
- (void)check_addressline(&mail->m_address, mail,
- clean_address_line(mail->m_bcc), BCC_ADDR);
- }
- }
- }
-
- int __regargs compare_nodes(char *node, char *fromline)
- {
- char *a, *b;
-
- for(a = node, b = fromline; *b != '.' && *b != '!' && *b != '\0'; a++, b++)
- if(*a != *b)
- break;
-
- if((*b == '!' || *b == '.' || *b == '\0') && *a == '\0') /* equal */
- return SUCCEED;
- else
- return FAIL;
- }
-
- int check_addressline(struct Address *address,
- struct Mail *mail, char *addressline, short addr_type)
- {
- struct Address *q, *p;
- char *addrline = strsave(addressline);
- char *lastpos; /* last position in token string. for strltok() */
- char *token;
- char *path;
- int type;
-
- int noad = 0; /* Number of addresses found */
-
- for(q = address; ; q = q->a_next)
- if(q == NULL || q->a_next == NULL) /* end of address structure */
- break;
-
- token = strltok(addrline, ADDRSEP, &lastpos);
- while(token != NULL)
- {
- type = parse(token, &path); /* Parse the address */
-
- if(type == LOCALMAIL)
- {
- char *forwardbuf;
-
- type = check_local_address(path, &forwardbuf);
- if(type == LOCALMAIL)
- {
- if((compare_address(address->a_next, path)) != SUCCEED)
- {
- p = xmalloc(sizeof(struct Address));
-
- p->a_original = strsave(token); /* Save the original address */
- p->a_address = strsave(path);
- p->a_system = NULL_String;
- p->a_type = addr_type;
-
- q->a_next = p;
- p->a_next = NULL;
- q = p;
- noad++;
- }
- }
- else /* type == FORWARDMAIL */
- {
- int no;
-
- no = check_addressline(address, mail, forwardbuf, addr_type);
- if(no < 1)
- {
- ulog(-1, "All addresses in %s are illegal",
- MakeConfigPath(UUMAIL, path));
- }
- else
- {
- noad += no;
- for(q = address; ; q = q->a_next) /* search for new end */
- if(q == NULL || q->a_next == NULL)
- break;
- }
- }
- }
- else if(type == FORWARDMAIL)
- {
- if((compare_address(address->a_next, path)) != SUCCEED)
- {
- char *ptr = strchr(path, '!');
-
- p = xmalloc(sizeof(struct Address));
-
- p->a_original = strsave(token); /* Save the original address */
- p->a_address = correct_address(ptr + 1);
- *ptr = '\0';
- p->a_system = strsave(path);
- p->a_type = addr_type;
-
- q->a_next = p;
- p->a_next = NULL;
- q = p;
- noad++;
- }
- }
- else /* type == UNKNOWNMAIL */
- {
- ulog(-1, "Unknown address '%s' - calling mailerguru", token);
- if(mail != NULL)
- send_mailerdaemon(mail, token);
- }
-
- free(path);
- token = strltok(NULL, ADDRSEP, &lastpos);
- }
- return noad;
- }
-
- int compare_address(struct Address *address, char *path)
- {
- struct Address *q;
- char *pathline;
- char *ptr;
-
- pathline = strsave(path);
-
- if((ptr = strchr(pathline, '!')) != NULL) /* Forward mail */
- {
- char *addr;
- char *sys;
-
- addr = strsave(ptr + 1);
- *ptr = '\0';
- sys = strsave(pathline);
-
- for(q = address; q != NULL; q = q->a_next)
- {
- if((strcmp(q->a_system, sys)) == 0)
- {
- if((strcmp(q->a_address, addr)) == 0)
- {
- free(pathline);
- free(sys);
- free(addr);
- return SUCCEED;
- }
- }
- }
- free(sys);
- free(addr);
- }
- else /* Local mail, a_system is NULL */
- {
- for(q = address; q != NULL; q = q->a_next)
- {
- if(*q->a_system == '\0')
- {
- if((strcmp(q->a_address, pathline)) == 0)
- {
- free(pathline);
- return SUCCEED;
- }
- }
- }
- }
- free(pathline);
- return FAIL;
- }
-
- int check_local_address(char *address, char **forwardbuf)
- {
- FILE *fp;
-
- char *mailpath = MakeConfigPath(UUMAIL, address);
- char *buf = xmalloc(512);
-
- if((fp = fopen(mailpath, "r")) != NULL)
- {
- if((fgets(buf, 511, fp)) != NULL)
- {
- if((strncmp(buf, "forward to ", 11)) == 0)
- {
- *forwardbuf = xmalloc(strlen(buf) - 10);
- strcpy(*forwardbuf, strclean(&buf[11]));
- free(buf);
- return FORWARDMAIL;
- }
- }
- fclose(fp);
- }
- free(buf);
-
- *forwardbuf = NULL;
- return LOCALMAIL;
- }
-
- void init(void)
- {
- char *paliasdat;
-
- /* Read out config file */
-
- /* Set local time */
- _TZ = FindConfig("TimeZone");
- tzset();
-
- UserName = FindConfig("UserName");
- RealName = FindConfig("RealName");
- NodeName = FindConfig("NodeName");
- DomainName = FindConfig("DomainName");
-
- DefaultNode = FindConfig("DefaultNode");
- *(strchr(DefaultNode, DOT)) = '\0'; /* Pure Node, without domain */
-
- if(!is_in_L_sys_file(DefaultNode))
- {
- ulog(-1, "fatal error - DefaultNode '%s' not in L.sys file!", DefaultNode);
- exit(20);
- }
-
- paliasdat = MakeConfigPath(UULIB, PALIAS);
-
- if(dbminit(paliasdat) != 0)
- {
- ulog(-1, "warning: maps database not available.");
- DataBase = 0;
- }
-
- Seq = GetSequence(1);
- }
-
-
- /*********************/
- /* Support functions */
- /*********************/
-
- struct Mail *init_mailstruct(void)
- {
- struct Mail *mail;
-
- mail = xcalloc(sizeof(struct Mail));
-
- return mail;
- }
-
- char *__regargs strsave(char *string)
- {
- char *buf;
-
- buf = xmalloc(strlen(string) + 1);
- strcpy(buf, string);
- return buf;
- }
-
- char *__regargs strclean(char *string)
- {
- char *ptr;
-
- ptr = string + strlen(string) - 1; /* end of string. */
-
- while(ptr >= string &&
- (*ptr == ' ' || *ptr == '\n' || *ptr == '\r' || *ptr == '\t'))
- --ptr;
- *++ptr = '\0';
-
- ptr = string;
-
- while(*ptr != '\0' &&
- (*ptr == ' ' || *ptr == '\n' || *ptr == '\r' || *ptr == '\t'))
- ++ptr;
-
- return ptr;
- }
-
- /* Delete Realnames (in brackets) out of a given address and return it */
- /* 1/11/90: New: Does now understand 'Realname <user@node.domain>' */
-
- char *__regargs clean_address_line(char *addr)
- {
- char *new_addr = xcalloc(strlen(addr) + 1);
- char *ptr;
- char *dest;
- short blev = 0;
- long addr_pos = 0; // Begin of an address
- long cur_pos = 0; // Position in this address
-
-
- ptr = addr;
- dest = new_addr;
-
- for(; *ptr != '\0'; ptr++)
- {
- switch(*ptr)
- {
- case '(':
- blev++;
-
- while(blev > 0 && *ptr != '\0')
- {
- ptr++;
-
- if(*ptr == ')')
- blev--;
- else if(*ptr == '(')
- blev++;
- }
- break;
-
- case '"':
- *dest++ = *ptr++;
- cur_pos++;
-
- while(*ptr != '\0' && *ptr != '"')
- {
- *dest++ = *ptr++;
- cur_pos++;
- }
-
- if(*ptr != '\0')
- {
- *dest++ = *ptr;
- cur_pos++;
- }
-
- break;
-
- case '<':
- dest = new_addr + addr_pos;
- cur_pos = 0;
- ptr++;
-
- while(*ptr != '\0' && *ptr != '>')
- {
- *dest++ = *ptr++;
- cur_pos++;
- }
- break;
-
- case ',':
- *dest++ = ADDRSEPCHAR; /* Defines next address */
- addr_pos += cur_pos + 1;
- cur_pos = 0;
- break;
-
- case ' ':
- case '\t':
- case '\f':
- case '\n':
- break;
-
- default:
- *dest++ = *ptr;
- cur_pos++;
- break;
- }
- }
- *dest = '\0';
-
- return new_addr;
- }
-
- /* strtok without the need of a static variable */
- char *__regargs strltok(char *buf, char *separators, char **lastpos)
- {
- #define STRING_END '\0'
-
- char *token, *end; /* Start and end of token. */
-
- if(token = (buf != NULL) ? buf : *lastpos)
- {
- token += strspn(token, separators); /* Find token! */
- if(*token == STRING_END)
- return(NULL);
-
- *lastpos = ((end = strpbrk(token, separators)) ? &end[1] : NULL);
- if(end != NULL)
- *end = STRING_END; /* Cut it short! */
- }
- return(token);
- }
-
- /* malloc with error checking */
- void *xmalloc(unsigned int size)
- {
- void *buf;
-
- if((buf = malloc(size)) != NULL)
- {
- return buf;
- }
- else
- {
- fprintf(stderr, "%s: Insufficient free store!\n", Progname);
- exit(20);
- }
- }
-
- void *xcalloc(unsigned int size)
- {
- void *buf;
-
- if((buf = malloc(size)) != NULL)
- {
- (void)memset(buf, 0, size);
- return buf;
- }
- else
- {
- fprintf(stderr, "%s: Insufficient free store!\n", Progname);
- exit(20);
- }
- }
-
- void *xrealloc(void *oldbuf, unsigned int size)
- {
- void *buf;
-
- if((buf = realloc(oldbuf, size)) != NULL)
- {
- return buf;
- }
- else
- {
- fprintf(stderr, "%s: Insufficient free store!\n", Progname);
- exit(20);
- }
- }
-
- /*
- rfctime() - return time & date in the official RFC format
-
- 17-Apr-91: Uses now a 4-digit year. (RFC 1123)
- */
-
- static char *wdays[] =
- {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- };
-
- static char *mdays[] =
- {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
- "Aug", "Sep", "Oct", "Nov", "Dec"
- };
-
- char *rfctime(void)
- {
- static char timestr[40];
- struct tm *tm;
- long t;
-
-
- (void)time(&t);
- tm = gmtime(&t);
-
- sprintf(timestr, "%s, %ld %s %ld %02ld:%02ld:%02ld GMT",
- wdays[tm->tm_wday],
- tm->tm_mday,
- mdays[tm->tm_mon],
- tm->tm_year + 1900,
- tm->tm_hour,
- tm->tm_min,
- tm->tm_sec);
-
- return timestr;
- }
-
- /*
- messageid()
-
- Returns an unique messageid.
-
- 17 Apr 91: Made it RFC1123-conform. (4-digit year)
- */
-
- char *messageid(int seq)
- {
- static char messageid[100];
-
- struct tm *tm;
- long t;
-
- (void)time(&t);
- tm = gmtime(&t);
-
- sprintf(messageid, "<%ld%s%ld%02ld%02ld.AA%05ld@%s%s>",
- tm->tm_mday, mdays[tm->tm_mon], tm->tm_year + 1900,
- tm->tm_hour, tm->tm_min, (seq == 0) ? Seq : seq,
- NodeName, DomainName);
-
- return messageid;
- }
-
- char *get_sender(char *fromline)
- {
- char *ptr;
- char *fromname;
- char *tmpbuf = strsave(fromline);
-
- /* From: Line MUST contain an ATSIGN */
- if((ptr = strchr(tmpbuf, ATSIGN)) != NULL)
- {
- char *ptre = ptr;
-
- while(ptr >= tmpbuf && *ptr != '<')
- --ptr;
- ++ptr;
-
- ptre = fromname = xmalloc((ptre - ptr) + 1);
-
- while(*ptr != ATSIGN)
- *ptre++ = *ptr++;
- *ptre = '\0';
- }
- else
- fromname = NULL;
-
- return fromname;
- }
-
- static void test_parsing(void)
- {
- struct Address *faddress, *fa;
- char buf[256];
-
-
- fprintf(stdout, "Entering interactive mode... please type in your test address\n\n");
-
- while((fgets(buf, sizeof(buf), stdin)) != NULL)
- {
- if(buf[0] == '\n')
- break;
-
- *(strchr(buf, '\n')) = '\0';
-
- faddress = xcalloc(sizeof(struct Address));
-
- if((check_addressline(faddress, NULL, clean_address_line(buf), NRM_ADDR)) >= 1)
- {
- for(fa = faddress->a_next; fa != NULL; fa = fa->a_next)
- {
- fprintf(stdout, "Spool mail to system: %s\n",
- (*fa->a_system != '\0') ? fa->a_system : "<local>");
- fprintf(stdout, "With this path : %s\n\n",
- fa->a_address);
- }
- }
- else
- {
- fprintf(stdout, "'%s' is not a valid address!\n\n", buf);
- }
- free(faddress);
- }
- }
-