home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 2 BBS
/
02-BBS.zip
/
msq31004.zip
/
makemsgn.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-09
|
45KB
|
1,747 lines
/* MakeMsg.c
**
** released into the PUBLIC DOMAIN 30 jul 1990 by jim nutt
** Changes released into the PUBLIC DOMAIN 10 jul 1994 by John Dennis
**
** Routines to create new messages.
*/
#include "msged.h"
#include "date.h"
#include "main.h"
#include "menu.h"
#include "keys.h"
#include "nshow.h"
#include "template.h"
#define TEXTLEN 128
#define INPLEN 60
/* prototypes */
int EditHeader(msg *m);
static void reply_msg(int type);
static void crosspost(msg *m);
void clear_attributes(struct _attributes *);
int editmsg(msg *m, int quote);
LINE * clearbuffer(LINE *buffer);
LINE * InsertLine(LINE *current);
ADDRESS v7lookup(char *);
char * v7lookupnode(ADDRESS *faddr, char *name);
static int externalEditor(msg *m);
extern int msgederr;
extern int savecc;
static msg *EdMsg; /* message header being edited */
static int scan_base; /* force a scan of the msgbase */
int do_lookup = FALSE; /* lookup thru the nodelist? */
static int editRet;
static int sent_msg(void)
{
int ret;
ret = ChoiceBox(" Confirm ", "Message already sent, contine?", "Ok", "Cancel", NULL);
if (ret == ID_ONE)
return 1;
return 0;
}
/*
**
** Creates a duplicate of the passed message header, allocating
** memory for it in the process.
**
*/
#define copystr(d, s) {if (s) d = strdup(s); else d = NULL;}
msg * duplicatemsg(msg *from)
{
msg *to;
if ((to = calloc(1, sizeof(msg))) == NULL)
return NULL;
*to = *from; /* copy all the bits */
copystr(to->isfrom, from->isfrom);
copystr(to->isto, from->isto);
copystr(to->subj, from->subj);
copystr(to->to.domain, from->to.domain);
copystr(to->from.domain, from->from.domain);
copystr(to->msgid, from->msgid);
copystr(to->reply, from->reply);
to->text = NULL;
return to;
}
void newmsg(void)
{
reply_msg(MT_NEW);
}
void reply(void)
{
reply_msg(MT_REP);
}
void quote(void)
{
reply_msg(SW->rquote);
}
void reply_oarea(void)
{
reply_msg(SW->rotharea);
}
void followup(void)
{
reply_msg(SW->rfollow);
}
void replyextra(void)
{
reply_msg(SW->rextra);
}
static void reply_msg(int type)
{
ADDRESS tmp;
msg *hlink = NULL;
msg *m = NULL;
unsigned long t = CurArea.current;
unsigned long tl = CurArea.lastread;
unsigned long link = t;
int oarea = SW->area;
int q = 0;
msg *oldmsg; /* contains all the old information */
unsigned long ulink;
int toarea, i;
scan_base = 0;
oldmsg = NULL;
RefreshMsg(NULL, 6);
if ((!(type & MT_NEW) && CurArea.messages == 0) || !CurArea.status)
return;
if (type & MT_ARC)
{
toarea = selectarea();
if (msgederr)
{
if ((type & MT_ARC) || scan_base || CurArea.msgtype == SQUISH)
set_area(oarea);
else
{
CurArea.current = link;
CurArea.messages++;
CurArea.last++;
}
return;
}
}
if (message)
oldmsg = duplicatemsg(message);
if (CurArea.messages == 0 || message == NULL)
if ((message = calloc(1, sizeof(msg))) == NULL)
outamemory();
ulink = message->msgnum;
/* we work with m, not message - the set_area() function */
/* kills message automatically */
m = message;
message = NULL;
if (type & MT_REP)
m->text = clearbuffer(m->text);
if (type & MT_NEW)
clearmsg(m);
if (type & MT_FOL)
{
release(m->msgid);
m->msgid = m->reply;
m->reply = NULL;
}
/* Uncomment the following code if you think there is a good
reason why a REPLYID should not be generated if you do a
cross-area reply */
/* if ((type & MT_ARC) && toarea != SW->area)
release(m->msgid); */
release(m->reply);
if (m->msgid)
{
m->reply = m->msgid;
m->msgid = NULL;
}
if (type & MT_FOL)
{
release(m->isfrom);
tmp = m->to;
}
else
{
if (!(type & MT_NEW))
{
release(m->isto);
m->isto = m->isfrom;
}
else
m->to.zone = CurArea.addr.zone;
tmp = m->from;
}
m->isfrom = strdup(ST->username);
if (type & MT_ARC)
{
set_area(toarea);
if (!CurArea.status)
{
dispose(oldmsg);
dispose(m);
set_area(oarea);
return;
}
}
do_lookup = (CurArea.netmail) ? TRUE : FALSE;
m->to = tmp;
m->timestamp = time(NULL);
m->replyto = 0;
m->new = 1;
m->cost = 0;
m->times_read = 0;
m->scanned = 0;
m->soteot = 0;
if (CurArea.echomail && CurArea.messages == 0)
m->msgnum = 2;
else
m->msgnum = MsgnToUid(CurArea.messages) + 1;
/* find a matching destination aka from the origin zone */
if (!(type & MT_NEW) && m->to.zone != m->from.zone)
{
for (i = 0; i < SW->aliascount; i++)
{
if (alias[i].zone == m->to.zone)
{
m->from = alias[i];
if (alias[i].domain)
{
m->from.domain = strdup(alias[i].domain);
}
break;
}
}
if (i == SW->aliascount) /* we didn't find anything */
{
m->from = CurArea.addr;
if (CurArea.addr.domain)
m->from.domain = strdup(CurArea.addr.domain);
}
}
else
{ /* we aren't seaching */
m->from = CurArea.addr;
if (CurArea.addr.domain)
m->from.domain = strdup(CurArea.addr.domain);
}
if (!(type & MT_NEW) && !(type & MT_ARC))
m->replyto = link;
else
m->replyto = 0;
clear_attributes(&m->attrib);
memset(&m->replies, 0, sizeof(m->replies));
while (!q)
{
if (EditHeader(m) == Key_Esc)
{
if (confirm())
{
dispose(oldmsg);
dispose(m);
if (type & MT_ARC)
set_area(oarea);
if (CurArea.status)
{
CurArea.current = (t) ? t : CurArea.current;
CurArea.lastread = (tl) ? tl : CurArea.lastread;
}
return;
}
}
else
q = 1;
}
/*
** Create the template for the message.
*/
MakeTemplateMsg(m, oldmsg, oarea, type|MT_NEW);
if (ST->editorName != NULL)
{
editRet = externalEditor(m);
}
else
{
editRet = editmsg(m, ((type & MT_NEW)||(type & MT_REP))?0:1);
}
switch (editRet)
{
case SAVE:
save(m);
if (!(type & MT_ARC) && !(type & MT_NEW))
{
link = UidToMsgn(ulink);
if ((hlink = MsgReadHeader(link, RD_HEADER)) != NULL)
{
if (CurArea.msgtype == FIDO)
{
hlink->replies[0] = UidToMsgn(m->msgnum);
}
MsgWriteHeader(hlink, WR_HEADER);
dispose(hlink);
}
}
break;
case ABORT:
scan_base = 1;
break;
}
dispose(oldmsg);
dispose(m);
if ((type & MT_ARC) || scan_base || CurArea.msgtype == SQUISH)
{
set_area(oarea);
CurArea.current = link;
}
else
{
CurArea.current = link;
CurArea.messages++;
CurArea.last++;
}
}
void change(void)
{
int q = 0;
unsigned long t = CurArea.current;
if (CurArea.messages == 0 || !CurArea.status || !message)
return;
if (message->attrib.sent || message->scanned)
{
if (!sent_msg())
return;
}
message->attrib.sent = 0;
message->attrib.orphan = 0;
message->attrib.local = 1;
message->scanned = 0;
message->change = 1;
do_lookup = FALSE;
while (!q)
{
if (EditHeader(message) == Key_Esc)
{
if (confirm())
{
CurArea.current = (t) ? t : CurArea.current;
return;
}
}
else
q = 1;
}
if (ST->editorName != NULL)
{
editRet = externalEditor(message);
}
else
{
editRet = editmsg(message, FALSE);
}
switch (editRet)
{
case SAVE:
save(message);
break;
case ABORT:
break;
}
CurArea.current = (t) ? t : CurArea.current;
message = KillMsg(message);
}
int ChangeAttrib(msg *m)
{
WND *hWnd, *hCurr;
int ch, done = 0;
hCurr = Wtop();
hWnd = WPopUp(40, 11, SBDR|SHADOW, cm[IN_BTXT], cm[IN_NTXT]);
/* put up some help for the befuddled user */
WTitle(" Message Attributes ", cm[IN_NTXT]);
WWriteStr(2, 1, cm[IN_NTXT], " P : Private C : Crash");
WWriteStr(2, 2, cm[IN_NTXT], " A : Attached K : Kill/Sent");
WWriteStr(2, 3, cm[IN_NTXT], " H : Hold D : Direct");
WWriteStr(2, 4, cm[IN_NTXT], " S : Sent R : Received");
WWriteStr(2, 5, cm[IN_NTXT], " O : Orphan F : File Request");
WWriteStr(2, 6, cm[IN_NTXT], " E : Return Rcpt Q : Ret Rcpt Req");
WWriteStr(2, 7, cm[IN_NTXT], " I : Audit Trail U : Update freq");
WWriteStr(2, 8, cm[IN_NTXT], " L : Local");
WCurr(hCurr); /* make parent window active so we can write to it */
ShowAttrib(m);
while (!done)
{
ch = GetKey();
switch (ch)
{
case Key_Up:
case Key_Dwn:
case Key_Ent:
case Key_Esc:
done = 1; /* we return these to the caller */
break;
default:
switch((toupper(ch & 0xff)))
{
case 'A': m->attrib.attached ^= 1; break;
case 'P': m->attrib.private ^= 1; break;
case 'C': m->attrib.crash ^= 1; break;
case 'U': m->attrib.ureq ^= 1; break;
case 'F': m->attrib.freq ^= 1; break;
case 'K': m->attrib.killsent ^= 1; break;
case 'H': m->attrib.hold ^= 1; break;
case 'D': m->attrib.direct ^= 1; break;
case 'Q': m->attrib.rreq ^= 1; break;
case 'E': m->attrib.rcpt ^= 1; break;
case 'R': m->attrib.recvd ^= 1; break;
case 'S': m->attrib.sent ^= 1; break;
case 'O': m->attrib.orphan ^= 1; break;
case 'I': m->attrib.areq ^= 1; break;
case 'L': m->attrib.local ^= 1; break;
default : break;
}
}
ShowAttrib(m);
}
WCurr(hWnd);
WClose(hWnd);
WCurr(hCurr);
return ch; /* pass the exit key back to caller */
}
/* looks up the alias list and returns the new name, and changes the passed */
/* address to the alias addres, if the passed name had a corresponding alias */
char * alias_lookup(ADDRESS *addr, char *isto)
{
int l;
char *name;
/* search for a matching alias */
for (l = 0; l < SW->otheraliases; l++)
{
if (!stricmp(aliaslist[l].alias,isto))
break;
}
if (l >= SW->otheraliases)
{
return NULL;
}
else
{
name = strdup(aliaslist[l].name);
if (aliaslist[l].addr.internet == 1)
{
*addr = uucp_gate;
addr->domain = NULL;
}
else
{
*addr = aliaslist[l].addr;
if (aliaslist[l].addr.domain)
addr->domain = strdup(aliaslist[l].addr.domain);
else
addr->domain = NULL;
}
}
return name;
}
/* looks up the alias list to see if the passed alias has a subject */
char * subj_lookup(char *isto)
{
int l;
char *subj;
for (l = 0; l < SW->otheraliases; l++)
{
if (!stricmp(aliaslist[l].alias, isto))
break;
}
if (l >= SW->otheraliases || aliaslist[l].subj == NULL)
{
return NULL;
}
subj = strdup(aliaslist[l].subj);
return subj;
}
/*
** Looks up name and addresses using alias, nodelist and fido userlist
** methods. Returns a pointer to allocated memory containing the name
** to be used, and writes to the passed address variable.
**
** Modifications by: Roland Gautschi (v7 lookup code - added flexibility).
*/
char * addr_lookup(char *name, ADDRESS *tmp)
{
char *nname = NULL;
char xname[73];
char namefound[73];
int ret;
tmp->fidonet = 1;
tmp->internet = 0;
tmp->bangpath = 0;
if ((nname = alias_lookup(tmp, name)) == NULL)
{
nname = strdup(name); /* couldn't find an alias, so.. */
strcpy(xname, name); /* make a copy, just in case */
if (do_lookup)
{
/*
** Userlists are checked first, because they may have
** overides wanted by the user.
*/
if (ST->fidolist != NULL) /* we check the fidolist(s) */
{
*tmp = lookup(name, ST->fidolist);
if ((tmp->notfound) && (ST->userlist != NULL))
{
*tmp = lookup(name, ST->userlist);
}
}
else
{
tmp->notfound = 1;
}
if (tmp->notfound == 1 && ST->nodepath != NULL) /* try v7 elsewise */
{
/*
** Check to see if an address has been entered.
*/
if (isdigit(xname[0]) || xname[0] ==':' || xname[0] =='/' || xname[0] =='.')
{
*tmp = parsenode(xname);
if (tmp->notfound == 0)
{
if (v7lookupnode(tmp, xname) == NULL)
tmp->notfound = 1;
else
{
free(nname);
nname = strdup(xname);
}
}
}
/*
** If the node still hasn't been found, then
** lookup normally (using the entered name).
*/
if (tmp->notfound == 1)
{
*tmp = v7lookup(xname);
/*
** If we found something, copy it.
*/
if (tmp->notfound == 0)
{
if (strcmp(nname, xname) != 0)
{
sprintf(namefound, "%s at %s found, change?", xname, show_address(tmp));
ret = ChoiceBox(" Change Name ", namefound, "Yes", "No", NULL);
if (ret == ID_ONE)
{
free(nname);
nname = strdup(xname);
}
}
}
}
}
}
}
return nname;
}
void GetAddress(ADDRESS *addr, char *from, char *subj)
{
char *name, *str;
if (strlen(from) != 0)
{
do_lookup = (CurArea.netmail) ? 1 : 0;
name = addr_lookup(from, addr);
/*
** Check for an Alias subject.
*/
if ((str = subj_lookup(from)) != NULL)
{
strcpy(subj, str);
release(str);
}
/*
** Check the name to see if it's a usenet message.
*/
if ((str = strchr(name, '@')) != NULL)
{
addr->fidonet = 0;
addr->notfound = 0;
if (str == name)
{
addr->bangpath = 1; str++;
}
else
{
addr->internet = 1; str = name;
}
release(addr->domain);
addr->domain = strdup(str);
}
else
{
strcpy(from, name);
}
release(name);
}
}
int ChangeName(ADDRESS *addr, char *from, char *subj, int y)
{
EVT e;
char tmp[70], tmp2[70];
int ch, pos, done = 0, disp = 1;
strcpy(tmp2, subj);
if (addr->internet)
strncpy(tmp, addr->domain, sizeof tmp - 1);
else
{
if (addr->bangpath)
strncat(strcpy(tmp,"@"), addr->domain, sizeof tmp - 1);
else
{
strncpy(tmp, from, sizeof tmp - 1);
}
}
pos = strlen(tmp);
while (!done)
{
if (addr->bangpath || addr->internet || CurArea.news || CurArea.uucp)
ch = WGetLine(7, y, 52, tmp, cm[CM_ETXT], &pos, disp, 0, disp, &e);
else
ch = WGetLine(7, y, 36, tmp, cm[CM_ETXT], &pos, disp, 0, disp, &e);
switch (e.msgtype)
{
case WM_CHAR:
switch (ch)
{
case Key_Esc:
done = 1;
break;
case Key_Up:
case Key_Dwn:
case Key_Rgt:
case Key_Lft:
case Key_Ent:
if (strcmp(from, tmp))
{
if (addr->fidonet)
{
if (strlen(tmp) > 36)
tmp[35] = '\0';
}
GetAddress(addr, tmp, tmp2);
strcpy(from, tmp);
if (strcmp(subj, tmp2))
{
strcpy(subj, tmp2);
ShowSubject(subj);
}
}
done = 1;
break;
default:
break;
}
break;
default:
break;
}
disp = 0;
}
return ch;
}
int ChangeAddress(ADDRESS *addr, int y, int nm_len)
{
EVT e;
char tmp[41];
int ch, pos, done = 0, disp = 1;
strncpy(tmp, show_address(addr), 40);
release(addr->domain);
pos = strlen(tmp);
while (!done)
{
ch = WGetLine(7 + nm_len + 2, y, 50 - nm_len, tmp, cm[CM_ETXT], &pos, disp, 0, disp, &e);
switch (e.msgtype)
{
case WM_CHAR:
switch (ch)
{
case Key_Esc:
done = 1;
break;
case Key_Up:
case Key_Dwn:
case Key_Rgt:
case Key_Lft:
case Key_Ent:
*addr = parsenode(tmp);
done = 1;
break;
default:
break;
}
break;
default:
break;
}
disp = 0;
}
return ch;
}
int ChangeSubject(char *subj)
{
EVT e;
struct _dta fileinfo;
char tmp[73];
int ch, pos, ch2, done = 0, disp = 1;
strncpy(tmp, subj, sizeof tmp - 1);
pos = strlen(tmp);
while (!done)
{
ch = WGetLine(7, 3, 72, tmp, cm[CM_ETXT], &pos, disp, 0, disp, &e);
switch (e.msgtype)
{
case WM_CHAR:
switch (ch)
{
case Key_Esc:
done = 1;
break;
case Key_Up:
case Key_Dwn:
case Key_Rgt:
case Key_Lft:
case Key_Ent:
strcpy(subj, tmp);
if (strlen(subj) > 3 && *(subj + 1) == ':' && (*(subj + 2) == '\\' || *(subj + 2) == '/'))
{
/*
** If the file doesn't exist, then ask if user wants
** to continue...
*/
if(dir_findfirst(subj, 0, &fileinfo) != 0)
{
ch2 = ChoiceBox(" File? ",
"File doesn't exist! Attach anyway?",
"Yes",
"No",
NULL);
if (ch2 == ID_ONE)
{
EdMsg->attrib.attached = 1;
}
else
{
/*
** Continue editing..
*/
continue;
}
}
else
EdMsg->attrib.attached = 1;
}
done = 1;
break;
default:
break;
}
break;
default:
break;
}
disp = 0;
}
ShowSubject(subj);
return ch;
}
static char *getstring(char *buf)
{
if (strlen(buf) > 0)
return strdup(buf);
else
return NULL;
}
#define FD_FROM 0
#define FD_FADD 1
#define FD_TO 2
#define FD_TADD 3
#define FD_SUBJ 4
#define FD_ATTR 5
int EditHeader(msg *m)
{
char tmp[80], tmp2[80];
int field = 2;
int ch, done = 0;
/*
** This is naughty, but it allows the functions to
** access the current message in those special cases.
*/
EdMsg = m;
ShowMsgHeader(m);
while (!done)
{
strcpy(tmp, "");
strcpy(tmp2, "");
switch (field)
{
case FD_FROM:
if (m->isfrom)
{
strcpy(tmp, m->isfrom);
free(m->isfrom);
}
if (m->subj)
{
strcpy(tmp2, m->subj);
free(m->subj);
}
ShowNameAddress(m->isfrom, &m->from, 1, 0, 1);
ch = ChangeName(&m->from, tmp, tmp2, 1);
m->isfrom = getstring(tmp);
m->subj = getstring(tmp2);
ShowNameAddress(m->isfrom, &m->from, 1, 0, 1);
break;
case FD_FADD:
if (CurArea.netmail && m->from.fidonet)
{
ch = ChangeAddress(&m->from,
1,
(m->isfrom) ? strlen(m->isfrom) : 0);
}
ShowNameAddress(m->isfrom, &m->from, 1, 0, 0);
break;
case FD_TO:
if (CurArea.news)
{
release(m->isto);
m->isto = strdup("All");
m->to = uucp_gate;
ShowNameAddress(m->isto, &m->to, 2, 0, 1);
ch = Key_Dwn;
break;
}
else
{
if (m->isto)
{
strcpy(tmp, m->isto);
free(m->isto);
}
if (m->subj)
{
strcpy(tmp2, m->subj);
free(m->subj);
}
ShowNameAddress(m->isto, &m->to, 2, 0, 1);
ch = ChangeName(&m->to, tmp, tmp2, 2);
m->isto = getstring(tmp);
m->subj = getstring(tmp2);
ShowNameAddress(m->isto, &m->to, 2, 0, 1);
}
break;
case FD_TADD:
if (CurArea.netmail && m->to.fidonet)
{
ch = ChangeAddress(&m->to,
2,
(m->isto) ? strlen(m->isto) : 0);
}
ShowNameAddress(m->isto, &m->to, 2, 0, 0);
break;
case FD_SUBJ:
if (m->subj)
{
strcpy(tmp, m->subj);
free(m->subj);
}
ch = ChangeSubject(tmp);
m->subj = getstring(tmp);
break;
case FD_ATTR:
ch = ChangeAttrib(m);
break;
default:
break;
}
if (ch == Key_Esc)
{
return ch;
}
else if (ch == Key_Up)
{
field--;
if (field < 0)
field = 5;
/*
** Handle the cases where going up stuffs the address showing.
*/
switch (field)
{
case FD_FADD:
ShowNameAddress(m->isto, &m->to, 2, 0, 0);
break;
case FD_ATTR:
ShowNameAddress(m->isfrom, &m->from, 1, 0, 0);
break;
default:
break;
}
}
else if (ch == Key_Dwn || ch == Key_Ent)
{
if ((field == 5) && (ch == Key_Ent))
break;
field++;
if (field > 5)
field = 0;
continue;
}
}
if (m->to.internet || m->to.bangpath)
{
release(m->isto);
m->isto = strdup(ST->uucpgate);
}
if (m->from.internet || m->from.bangpath)
{
release(m->isfrom);
m->isfrom = strdup(ST->uucpgate);
}
ShowMsgHeader(m); /* show the entire header */
cursor(0); /* turn the cursor off */
return 0;
}
/* Clears all the attributes of a message, leaving Local set to TRUE */
/* not static; is called from maintmsg.c module */
void clear_attributes(struct _attributes * h)
{
h->recvd = h->sent = h->attached = h->forward = h->orphan = 0;
h->freq = h->rreq = h->rcpt = h->areq = h->ureq = 0;
#ifdef TURBOFIX /* fix bug in TC++ */
memset(h, '\0', sizeof *h);
#endif
h->crash = CurArea.crash;
h->private = (h->private) ? h->private : CurArea.priv;
h->killsent = CurArea.killsent;
h->hold = CurArea.hold;
h->direct = CurArea.direct;
h->local = 1;
}
/* Contains the name and address of the recipient of the message */
typedef struct {
char *name;
ADDRESS addr;
} NA;
static void CreateNormalCC(msg *m, NA *names[])
{
LINE *current;
char dfn[256];
int i = 0;
m->text = insline(m->text);
m->text->text = strdup("\n");
m->text = insline(m->text);
sprintf(dfn, "* Original to: %s at %s\n", names[i]->name, show_address(&names[i]->addr));
i++;
m->text->text = strdup(dfn);
strcpy(dfn, " CC'd to: ");
current = m->text;
current = insline(current->next);
current->text = strdup("\n");
while (names[i] != NULL)
{
if (strlen(names[i]->name) + strlen(dfn) >= SW->rm)
{
strcat(dfn,"\n");
release(current->text);
current->text = strdup(dfn);
current = insline(current->next);
current->text = strdup("\n");
strcpy(dfn, " ");
}
strcat(dfn,names[i]->name);
/* We want the address to appear in the list instead of "UUCP", so */
/* we only put in the "UUCP" when we're finished with the address. */
if (strchr(names[i]->name,'@') != NULL)
{
release(names[i]->name);
names[i]->name = strdup(ST->uucpgate);
}
i++;
if (names[i] != NULL)
strcat(dfn,", ");
}
if (*(current->text) == '\n')
{
release(current->text);
current->text = strdup(dfn);
}
}
static void CreateVerboseCC(msg *m, NA *names[])
{
int i = 0;
char dfn[256];
m->text = insline(m->text);
m->text->text = strdup("\n");
while (names[i] != NULL)
{
if (strchr(names[i]->name,'@') == NULL)
sprintf(dfn, " %s at %s\n", names[i]->name, show_address(&names[i]->addr));
else
sprintf(dfn, " %s\n", names[i]->name);
m->text = insline(m->text);
m->text->text = strdup(dfn);
/* We want the address to appear in the list instead of "UUCP", so */
/* we only put in the "UUCP" when we're finished with the address. */
if (strchr(names[i]->name,'@') != NULL)
{
release(names[i]->name);
names[i]->name = strdup(ST->uucpgate);
}
i++;
}
m->text = insline(m->text);
m->text->text = strdup(" * Message was CC:'d to:\n");
}
/*
**
** Gets the CC:s from a response file.
**
**
*/
static void GetFileCCs(char *file, NA *names[], int *idx)
{
FILE *fp;
char buf[256];
char *s, *c, *t;
int i;
i = *idx;
if ((fp = fopen(file, "r")) == NULL)
return;
while (fgets(buf, sizeof(buf) - 1, fp) != NULL)
{
s = buf;
while (*s && isspace(*s)) s++;
if (!*s || *s == ';')
continue;
t = s + strlen(s) - 1;
while (t > s && isspace(*t)) t--;
if (t == s)
continue;
else
{
if (*(t + 1))
t++;
*t = '\0';
}
names[i] = calloc(1, sizeof(NA));
if (names[i] == NULL)
break;
if ((c = strchr(s, '@')) != NULL)
{
/*
** Then we have an internet/bangpath.
*/
names[i]->addr.fidonet = 0;
if (c == s)
{
names[i]->addr.bangpath = 1;
c++;
}
else
{
names[i]->addr.internet = 1;
c = s;
}
names[i]->name = strdup(c);
names[i]->addr.domain = strdup(c);
}
else
{
c = strchr(s, '!');
if (c)
{
*c = '\0';
names[i]->addr = parsenode(++c);
names[i]->name = strdup(s);
}
else
{
names[i]->name = addr_lookup(s, &names[i]->addr);
/*
** UUCP address from alias?
*/
if ((c = strchr(names[i]->name,'@')) != NULL)
{
names[i]->addr.fidonet = 0;
if (c == names[i]->name)
{
names[i]->addr.bangpath = 1;
c++;
}
else
{
names[i]->addr.internet = 1;
c = names[i]->name;
}
names[i]->addr.domain = strdup(c);
}
}
}
if (names[i]->addr.notfound)
{
names[i]->addr = CurArea.addr;
if (CurArea.addr.domain)
names[i]->addr.domain = strdup(CurArea.addr.domain);
}
i++;
}
names[i] = NULL;
*idx = i;
fclose(fp);
}
/*
** Saves a message, if the the first line does not contain "cc:" or "xc:".
** Else it continues and either makes a Carbon Copy(s) of the message or
** Crosspost(s) of the message.
**
** The idea here is: first get the addresses from the cc: list, if there
** IS one (if not, check for xc: & leave). If so, we then make up the text
** for the message (in a loop), then we go and save the messages using the
** names and addresses from the cc list. Fairly involved...
*/
void save(msg *m)
{
LINE *current;
NA *names[128];
int num = 1, i;
unsigned long k;
int verbose_cc = 0;
int blind_cc = 0;
char *s, *t, *sp;
current = m->text;
do_lookup = TRUE;
/*
** Crosspost? if so, call crosspost().
*/
if (!strncmpi(current->text,"xc:",3) && !CurArea.netmail)
{
crosspost(m);
return;
}
current = m->text;
s = current->text;
/*
** Is the msg a cc:? if not, save & bye-bye.
*/
if (!strncmpi(current->text,"bc:", 3))
{
blind_cc = 1;
}
else if (!strncmpi(current->text,"vc:", 3))
{
verbose_cc = 1;
}
else if (strncmpi(current->text,"cc:", 3))
{
writemsg(m);
return;
}
release(m->reply);
m->attrib.sent = 1;
if (SW->savecc && SW->rawcc)
{
writemsg(m);
m->attrib.killsent = 1;
}
memset(names, 0, sizeof names);
if ((names[0] = malloc(sizeof(NA))) == NULL)
return;
m->attrib.sent = 0;
names[0]->name = strdup(m->isto);
names[0]->addr = m->to;
if (m->to.domain)
names[0]->addr.domain = strdup(m->to.domain);
/*
** Get names & addresses from cc: list.
*/
while (current && *s && !strncmpi(s + 1,"c:", 2))
{
s += 3;
while (*s && isspace(*s)) s++;
if (*s == '~')
{
if ((sp = strchr(s, '\n')) != NULL)
*sp = '\0';
GetFileCCs(s + 1, names, &num);
}
else
{
while (*s != '\0' && s != NULL)
{
while (*s && isspace(*s)) s++;
if (*s == '\0')
break;
t = strchr(s,','); /* Get next name on line */
if (t)
*t = '\0';
else
{
t = strchr(s,'\n');
if (t)
*t = '\0';
else
t = s + strlen(s) - 1;
}
names[num] = calloc(1, sizeof(NA));
if (names[num] == NULL)
break;
/*
** UUCP address ?
*/
if ((sp = strchr(s,'@'))!=NULL)
{
names[num]->addr.fidonet = 0;
if (sp == s) {
names[num]->addr.bangpath = 1;
sp++;
}
else
{
names[num]->addr.internet = 1;
sp = s;
}
names[num]->name = strdup(s);
names[num]->addr.domain = strdup(s);
}
else
{
sp = strchr(s,'!'); /* look for address */
if (sp)
*sp = '\0';
if (sp)
{
names[num]->addr = parsenode(++sp);
names[num]->name = strdup(s);
}
else
{
names[num]->name = addr_lookup(s, &names[num]->addr);
/*
** UUCP address from alias?
*/
if ((sp = strchr(names[num]->name,'@'))!=NULL)
{
names[num]->addr.fidonet = 0;
if (sp == names[num]->name) {
names[num]->addr.bangpath = 1;
sp++;
}
else
{
names[num]->addr.internet = 1;
sp = names[num]->name;
}
names[num]->addr.domain = strdup(sp);
}
}
}
s = ++t;
num++;
}
}
if (current->next)
current = current->next;
else
{
i = 0;
while (names[i] != NULL)
{
if (names[i]->name)
free(names[i]->name);
if (names[i]->addr.domain)
free(names[i]->addr.domain);
free(names[i]);
}
return;
}
/*
** Sheesh! There's a bit of stuffing about here
*/
s = current->text;
m->text = current;
release(current->prev->text);
release(current->prev);
current->prev = NULL;
}
/*
** ok, we got the names & addresses - now lets make up the message
*/
names[num] = NULL;
if (blind_cc == 0)
{
if (verbose_cc)
CreateVerboseCC(m, names);
else
CreateNormalCC(m, names);
}
/*
** OK, now it's time to SAVE this msg with
** the appropriate number of names etc etc..
*/
i = 0;
release(m->msgid);
k = MsgnToUid(CurArea.messages) + 1;
m->new = 1;
while (names[i] != NULL)
{
release(m->isto);
release(m->to.domain);
m->isto = strdup(names[i]->name);
m->to = names[i]->addr;
if (names[i]->addr.domain)
m->to.domain = strdup(names[i]->addr.domain);
m->msgnum = k++; /* for *.msg bases - get the real msg num */
writemsg(m);
if (SW->savecc && !SW->rawcc)
m->attrib.killsent = 1;
release(names[i]->name);
release(names[i]->addr.domain);
i++;
}
scan_base = TRUE;
}
static void crosspost(msg *m)
{
LINE *current;
char *s,*t;
char dfn[128];
char *arean[128];
unsigned int num = 0, i = 0, k;
current = m->text;
s = current->text;
arean[num++] = strdup(CurArea.tag);
while (current && *s && !strncmpi(s,"xc:",3))
{
s += 3;
while (*s && isspace(*s)) s++;
while (*s != '\0' && s != NULL)
{
t = strchr(s,',');
if (t)
*t = '\0';
else
{
t = strchr(s,'\n');
if (t)
*t = '\0';
else
t = s + strlen(s) - 1;
}
while (*s && isspace(*s)) s++;
arean[num] = strdup(strupr(s));
if (arean[num++] == NULL)
break;
s = ++t;
}
if (current->next)
current = current->next;
else
{
i = 0;
while (arean[i] != NULL) free(arean[i]);
return;
}
s = current->text;
m->text = current;
if (current->prev->text)
free(current->prev->text);
free(current->prev);
current->prev = NULL;
}
arean[num] = NULL;
strcpy(dfn,"");
m->text = insline(m->text);
m->text->text = strdup("\n");
m->text = insline(m->text);
m->text->text = strdup("\n");
current = m->text;
i = 0;
strcpy(dfn," * Crossposted in area ");
while (arean[i] != NULL)
{
if (strlen(arean[i]) + 3 + strlen(dfn) >= SW->rm)
{
strcat(dfn,"\n");
release(current->text);
current->text = strdup(dfn);
current = insline(current->next);
current->text = strdup("\n");
strcpy(dfn," ");
}
strcat(dfn, arean[i]);
i++;
if (arean[i] != NULL)
strcat(dfn,", ");
}
if (*(current->text) == '\n')
{
release(current->text);
current->text = strdup(dfn);
}
m->new = 1;
i = 0;
while (arean[i] != NULL)
{
for (k = 0; k < SW->areas; k++)
{
if (arealist[k].tag && !stricmp(arean[i], arealist[k].tag))
break;
}
if (k == SW->areas || !arealist[k].echomail)
{
release(arean[i]);
i++;
continue;
}
release(m->from.domain)
m->from = CurArea.addr;
if (CurArea.addr.domain)
m->from.domain = strdup(CurArea.addr.domain);
set_area(k);
if (CurArea.status)
{
m->msgnum = MsgnToUid(CurArea.messages) + 1;
writemsg(m);
}
release(arean[i]);
i++;
}
scan_base = TRUE; /* reopen the base when we get back */
}
static int externalEditor(msg *m)
{
FILE *fq;
LINE *current;
char cmd[200];
WND *hWnd, *hCurr;
char linebuf[300];
current = m->text;
fq = fopen("msged.tmp", "w");
if (fq != NULL)
{
while (current != NULL)
{
if (current->text != NULL)
{
fputs(current->text, fq);
}
current = current->next;
}
fclose(fq);
maxx = term.NCol;
maxy = term.NRow;
hCurr = Wtop();
hWnd = WndOpen(0, 0, term.NCol - 1, term.NRow - 1,
NBDR, 0, cm[CM_NTXT]);
WCurr(hWnd);
MouseOFF();
cursor(1);
sprintf(cmd, "%s msged.tmp", ST->editorName);
system(cmd);
cursor(0);
MouseON();
clearbuffer(m->text);
fq = fopen("msged.tmp", "r");
if (fq != NULL)
{
while (fgets(linebuf, sizeof linebuf, fq) != NULL)
{
if (current == NULL)
{
m->text = calloc(1, sizeof(LINE));
current = m->text;
}
else
{
current = InsertLine(current);
}
current->text = strdup(linebuf);
}
fclose(fq);
}
WClose(hWnd);
WCurr(hCurr);
}
if (current == NULL) return (ABORT);
else return (SAVE);
}
/* end of file */