Category : Recently Uploaded Files
Archive   : MSQ320.ZIP
Filename : MAKEMSGN.C

 
Output of file : MAKEMSGN.C contained in archive : MSQ320.ZIP
/* 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;
m->time_arvd = 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;
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->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 (m->new)
{
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 */


  3 Responses to “Category : Recently Uploaded Files
Archive   : MSQ320.ZIP
Filename : MAKEMSGN.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/