home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
b
/
bmh02src.zip
/
SEND.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-16
|
12KB
|
495 lines
/*
send.c : Taken from bm.
Copyright 1986 Bdale Garbee, All Rights Reserved.
Permission granted for non-commercial copying and use, provided
this notice is retained.
Copyright 1987 1988 Dave Trulli NN2Z, All Rights Reserved.
Permission granted for non-commercial copying and use, provided
this notice is retained.
920801 : Added dosend.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <sys/types.h>
#include <dir.h>
#include "rc.h"
#include "smtp.h"
#include "lock.h"
#include "misc.h"
#include "send.h"
#include "header.h"
#include "mailer.h"
/* address structure */
struct addr {
struct addr *next;
char *user;
char *host;
int sent;
};
static struct addr *addrecip(struct addr **head, char *user, char *host);
static void del_addrlist(struct addr *list);
static struct addr *expandalias(struct addr **head, char *user);
static struct addr *make_tolist(int argc, char *argv[]);
static int queuejob(FILE *dfile, struct addr *tolist, long position);
static int recordmsg(FILE *dfile, char *to);
/*
* send a message
* return -1 on error, 0 otherwise
* calls dosend
*/
int
dosmtpsend(FILE *fpin, char *to, char *cc, char *subj)
{
char msgid[255], from[255];
sprintf(msgid, "%ld@%s", get_msgid(getrc(mqueue)), getrc(hostname));
if ( getrc(fullname) != NULL )
sprintf(from, "%s@%s (%s)", getrc(username),
getrc(hostname), getrc(fullname) );
else
sprintf(from, "%s@%s", getrc(username), getrc(hostname) );
return dosend(fpin, to, cc, subj, from, msgid);
}
static int
writes(FILE *fp, struct addr *tp)
{
int len = 0;
if (tp->next != NULL) {
len = writes(fp, tp->next); /* recurse */
if (len > 50) {
fputs(",\n\t", fp);
len = 0;
}
else
fputs(", ", fp);
}
fputs(tp->user, fp);
len += strlen(tp->user);
if ( (tp->host != NULL) || (*tp->host != '\0') ) {
fprintf(fp, "@%s", tp->host);
len += strlen(tp->host) + 1;
}
/*
fprintf(stderr, "send: mailing %s@%s\n", tp->user,
tp->host == NULL ? getrc(hostname) : tp->host);
*/
return len;
}
static int
write2s(FILE *fp, char *header, struct addr *tolist)
{
fputs(header, fp);
(void) writes(fp, tolist);
putc('\n', fp);
return ferror(fp);
}
int
dosend(FILE *fp, char *to, char *cc, char *subj, char *from, char *msgid)
{
char tf[256];
FILE *tfile;
int c, argc, ret = -1;
struct addr *tolist, *cclist = NULL;
char *argv[MAXARGS];
if ( (to == NULL) || ((argc = parse(to, argv, MAXARGS)) < 1) ||
((tolist = make_tolist(argc, argv)) == NULL) ) {
fprintf(stderr, "bmh: no recpients, send aborted\n");
return -1;
}
if ( (tfile = tempfile("bmh", tf, "w+")) == NULL) {
del_addrlist(tolist);
return -1;
}
/*
* write RFC822-compatible headers
*/
fprintf(tfile, "Date: %s", ptime(time(NULL)));
fprintf(tfile, "Message-Id: <%s>\n", msgid);
fprintf(tfile, "From: %s\n", from);
if (getrc(replyto) != NULL)
fprintf(tfile, "Reply-To: %s\n", getrc(replyto));
write2s(tfile, "To: ", tolist);
if (cc != NULL)
if ( (argc = parse(cc, argv, MAXARGS)) > 0)
cclist = make_tolist(argc, argv);
if (cclist != NULL)
write2s(tfile, "Cc: ", cclist);
fprintf(tfile, "Subject: %s\n", subj == NULL ? "" : subj);
/*
* Hack to allow misc headers be sent
*/
{
char line[256];
int done1 = 0;
while (fgets(line, sizeof(line), fp) != NULL)
if ( (htype(line) != NOHEADER) ||
(done1 && ((line[0] == ' ') || (line[0] == '\t')))
) {
done1 = 1;
if (fputs(line, tfile) == EOF)
goto cleanup;
}
else {
if ( (fputc('\n', tfile) == EOF) || /* End of message headers */
(fputs(line, tfile) == EOF) ) /* first line of message */
goto cleanup;
break;
}
}
while ( (c = getc(fp)) != EOF)
if ( putc(c, tfile) == EOF )
goto cleanup;
queuejob(tfile, tolist, 0L);
recordmsg(tfile, from); /* save copy for sender */
ret = 0;
cleanup:
if (ret == -1)
perror("bmh: smtp dosend,");
del_addrlist(tolist);
if (cclist != NULL) {
queuejob(tfile, cclist, 0L);
del_addrlist(cclist);
}
(void) fclose(tfile);
unlink(tf);
return ret;
}
/*
* Print out the time and date field as
* "DAY day MONTH year hh:mm:ss ZONE"
*/
char *
ptime(long t)
{
static char str[40];
struct tm *ltm;
char tz[4];
char *p;
static char *days[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
static char *months[12] = {
"Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec" };
ltm = localtime(&t); /* Read the system time */
if ((p = getenv("TZ")) == NULL)
strcpy(tz, "GMT");
else
strncpy(tz, p, 3);
/* rfc 822 format */
sprintf(str,"%s, %.2d %s %02d %02d:%02d:%02d %.3s\n",
days[ltm->tm_wday],
ltm->tm_mday,
months[ltm->tm_mon],
ltm->tm_year,
ltm->tm_hour,
ltm->tm_min,
ltm->tm_sec,
tz);
return(str);
}
/*
* save copy in the record file
*/
static int
recordmsg(FILE *dfile, char *from)
{
FILE *fp;
if (getrc(record) == NULL)
return -1;
if ( (fp = fopen(getrc(record), "a")) == NULL)
fprintf(stderr, "bm: unable to append to %s\n", getrc(record));
else {
int c;
time_t t = time(NULL);
fprintf(fp, "From %s %s", from, ctime(&t));
fseek(dfile, 0L, 0);
while((c = getc(dfile)) != EOF)
if( putc(c, fp) == EOF) {
(void) fclose(fp);
return -1;
}
(void) fclose(fp);
}
return 0;
}
/*
* place a mail job in the outbound queue
*/
static int
queuejob(FILE *dfile, struct addr *tolist, long position)
{
FILE *fp;
char tmpstring[50];
struct addr *tp, *sp;
char prefix[255];
int c;
long id;
for (tp = tolist; tp != NULL; tp = tp->next) {
if (tp->sent)
continue;
fseek(dfile, position, SEEK_SET);
id = get_msgid(getrc(mqueue));
sprintf(prefix, "%s/%ld", getrc(mqueue), id);
(void) lockit(prefix);
sprintf(tmpstring,"%s/%ld%s", getrc(mqueue), id, EXT);
if((fp = fopen(tmpstring,"w")) == NULL) {
printf("unable to open %s\n", tmpstring);
(void) bm_unlock(prefix);
return -1;
}
while((c = getc(dfile)) != EOF)
if(putc(c,fp) == EOF) {
(void) fclose(fp);
(void) bm_unlock(prefix);
return -1;
}
(void) fclose(fp);
sprintf(tmpstring, "%s/%ld.wrk", getrc(mqueue), id);
if((fp = fopen(tmpstring, "w")) == NULL) {
(void) bm_unlock(prefix);
return -1;
}
fprintf(fp, "%s\n%s@%s\n", tp->host, getrc(username), getrc(hostname));
fprintf(fp,"%s@%s\n",tp->user,tp->host);
tp->sent++;
/* find and other addresses to the same host */
for (sp = tp->next; sp != NULL; sp = sp->next) {
if (sp->sent)
continue;
if (strcmp(tp->host,sp->host) == 0) {
fprintf(fp,"%s@%s\n", sp->user, sp->host);
sp->sent++;
}
}
(void) fclose(fp);
(void) bm_unlock(prefix);
}
return 0;
}
#define SKIPWORD(X) while(*X && *X!=' ' && *X!='\t' && *X!='\n' && *X!= ',') X++;
#define SKIPSPACE(X) while(*X ==' ' || *X =='\t' || *X =='\n' || *X == ',') X++;
/*
* check for and alias and expand alias into a address list
*/
static struct addr *
expandalias(struct addr **head, char *user)
{
FILE *fp;
char *s, *p, *h;
int inalias;
struct addr *tp;
char buf[LINELEN];
if ( (fp= fopen(getrc(alias), "r")) == NULL)
return addrecip(head, user, getrc(hostname) );
inalias = 0;
while (fgets(buf, LINELEN, fp) != NULL) {
p = buf;
if ( *p == '#' || *p == '\0')
continue;
rip(p);
/* if not in an matching entry skip continuation lines */
if (!inalias && isspace(*p))
continue;
/* when processing an active alias check for a continuation */
if (inalias) {
if (!isspace(*p))
break; /* done */
} else {
s = p;
SKIPWORD(p);
*p++ = '\0'; /* end the alias name */
if (strcmp(s,user) != 0)
continue; /* no match go on */
inalias = 1;
}
/* process the recipients on the alias line */
SKIPSPACE(p);
while(*p != '\0' && *p != '#') {
s = p;
SKIPWORD(p);
if (*p != '\0')
*p++ = '\0';
/* find hostname */
if ((h = strchr(s,'@')) != NULL)
*h++ = '\0';
else
h = getrc(hostname);
tp = addrecip(head,s,h);
SKIPSPACE(p);
}
}
(void) fclose(fp);
if (inalias) /* found and processed and alias. */
return tp;
/* no alias found treat as a local address */
return addrecip(head, user, getrc(hostname));
}
/*
* convert a arg list to an list of address structures
*/
static struct addr *
make_tolist(int argc, char *argv[])
{
struct addr *tolist = NULL, *tp;
int i;
for (i = 0; i < argc; i++) {
char *user = argv[i],
*host = strchr(argv[i], '@');
if (host != NULL) {
*host++ = '\0';
if (stricmp(host, getrc(hostname)) == 0)
host = NULL;
}
if (host == NULL) /* a local address */
tp = expandalias(&tolist, user);
else /* a remote address */
tp = addrecip(&tolist, user, host);
if (tp == NULL) {
fprintf(stderr, "bm: out of memory\n");
del_addrlist(tolist);
return NULL;
}
}
return tolist;
}
/*
* delete a list of mail addresses
*/
static void
del_addrlist(struct addr *list)
{
struct addr *tp, *tp1;
for (tp = list; tp != NULL; tp = tp1) {
tp1 = tp->next;
if (tp->user != NULL);
free(tp->user);
if (tp->host != NULL);
free(tp->host);
free(tp);
}
}
/* add an address to the from of the list pointed to by head
** return NULL if out of memory.
*/
static struct addr *
addrecip(struct addr **head, char *user, char *host)
{
struct addr *tp;
if ( (tp = (struct addr *)calloc(1,sizeof(struct addr))) == NULL)
return NULL;
tp->next = NULL;
/* allocate storage for the user's login */
if ((tp->user = malloc((unsigned)strlen(user)+1)) == NULL) {
(void) free((char *)tp);
return NULL;
}
strcpy(tp->user,user);
/* allocate storage for the host name */
if (host != NULL)
if ((tp->host = malloc((unsigned)strlen(host)+1)) == NULL) {
(void) free(tp->user);
(void) free((char *)tp);
return NULL;
}
strcpy(tp->host,host);
/* add entry to front of existing list */
if (*head == NULL)
*head = tp;
else {
tp->next = *head;
*head = tp;
}
return tp;
}
/*
* forward a message in its orginal form
*/
int
bouncemsg(FILE *fp, char *to)
{
struct addr *list;
int argc;
char *argv[MAXARGS];
if ( ((argc = parse(to, argv, MAXARGS)) < 1) ||
((list = make_tolist(argc, argv)) == NULL) ) {
fprintf(stderr, "bmh: no recpients, send aborted\n");
return -1;
}
else {
queuejob(fp, list, ftell(fp)); /* ftell = hack.. */
del_addrlist(list);
return 0;
}
}