home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 2 BBS
/
02-BBS.zip
/
BTMTSRC3.ZIP
/
MAILOVLY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-21
|
21KB
|
876 lines
/*--------------------------------------------------------------------------*/
/* */
/* */
/* ------------ Bit-Bucket Software, Co. */
/* \ 10001101 / Writers and Distributors of */
/* \ 011110 / Freely Available<tm> Software. */
/* \ 1011 / */
/* ------ */
/* */
/* (C) Copyright 1987-90, Bit Bucket Software Co., a Delaware Corporation. */
/* */
/* */
/* This module was written by Bob Hartman */
/* */
/* */
/* BinkleyTerm Mail Control Routines */
/* */
/* */
/* For complete details of the licensing restrictions, please refer */
/* to the License agreement, which is published in its entirety in */
/* the MAKEFILE and BT.C, and also contained in the file LICENSE.240. */
/* */
/* USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE */
/* BINKLEYTERM LICENSING AGREEMENT. IF YOU DO NOT FIND THE TEXT OF */
/* THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO */
/* NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT BIT BUCKET */
/* SOFTWARE CO. AT ONE OF THE ADDRESSES LISTED BELOW. IN NO EVENT */
/* SHOULD YOU PROCEED TO USE THIS FILE WITHOUT HAVING ACCEPTED THE */
/* TERMS OF THE BINKLEYTERM LICENSING AGREEMENT, OR SUCH OTHER */
/* AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO. */
/* */
/* */
/* You can contact Bit Bucket Software Co. at any one of the following */
/* addresses: */
/* */
/* Bit Bucket Software Co. FidoNet 1:104/501, 1:132/491, 1:141/491 */
/* P.O. Box 460398 AlterNet 7:491/0 */
/* Aurora, CO 80046 BBS-Net 86:2030/1 */
/* Internet f491.n132.z1.fidonet.org */
/* */
/* Please feel free to contact us at any time to share your comments about */
/* our software and/or licensing policies. */
/* */
/*--------------------------------------------------------------------------*/
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include <conio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <dos.h>
#include <process.h>
#include <stdlib.h>
#include <io.h>
#include "com.h"
#include "xfer.h"
#include "zmodem.h"
#include "keybd.h"
#include "sbuf.h"
#include "sched.h"
#include "externs.h"
#include "prototyp.h"
#include "defines.h"
#include "vfossil.h"
static char mail_stat (MAILP);
static int xmit_install (MAILP, int, char *);
static void xmit_sort (void);
void xmit_sameplace()
{
MAILP p, p1;
/* Find the guy we just gave mail to */
p = find_mail (&remote_addr);
remote_addr.Zone = remote_addr.Net = remote_addr.Node = remote_addr.Point = 0;
remote_addr.Domain = NULL;
if (p == NULL)
{
/* He is not there */
return;
}
/* Save our current pointer */
p1 = next_mail;
if (p != next_mail)
{
/* If it is not the one we just gave mail to, save ptr and delete */
next_mail = p;
xmit_delete ();
next_mail = p1;
}
else
{
/* It was the guy at the head of the list, so just delete him */
xmit_delete ();
}
/* If we came in with a null, leave with a null */
if (p1 == NULL)
next_mail = NULL;
return;
}
MAILP find_mail(address)
ADDR *address;
{
MAILP p;
p = mail_top;
while (p != NULL)
{
if ((no_zones || (p->mail_addr.Zone == address->Zone)) &&
(p->mail_addr.Net == address->Net) &&
(p->mail_addr.Node == address->Node) &&
(p->mail_addr.Point == address->Point) &&
((p->mail_addr.Domain == address->Domain) ||
((p->mail_addr.Domain == my_addr.Domain) &&
(address->Domain == NULL))))
break;
p = p->next;
}
return (p);
}
static int xmit_install (p, zone, domain)
MAILP p;
int zone;
char *domain;
{
MAILP p1, p2;
int rettype;
ADDR tmp;
#ifdef IBMC
char tnet[5], tnode[5];
#endif
#ifndef IBMC
if (sscanf (dta_str.name, "%04x%04x.", &(tmp.Net), &(tmp.Node)) != 2)
return (1);
#else
if (sscanf (dta_str.name, "%4s%4s.", tnet, tnode) != 2)
return (1);
if (sscanf (tnet, "%04x", &(tmp.Net)) + sscanf (tnode, "%04x", &(tmp.Node)) != 2)
return (1);
#endif /* IBMC */
tmp.Zone = zone;
tmp.Domain = domain;
tmp.Point = 0;
p2 = find_mail (&tmp);
if (p2 == NULL)
{
/* We didn't find it in what we have already */
p1 = p;
p1->mail_addr.Zone = tmp.Zone;
p1->mail_addr.Net = tmp.Net;
p1->mail_addr.Node = tmp.Node;
p1->mail_addr.Point = tmp.Point;
p1->mail_addr.Domain = tmp.Domain;
rettype = 0;
}
else
{
/* We found it, so we have to make sure the higher level routine knows */
p1 = p2;
rettype = 1;
}
switch (dta_str.name[9])
{
case 'C': /* Crash */
p1->mailtypes |= MAIL_CRASH;
break;
case 'H': /* Hold */
p1->mailtypes |= MAIL_HOLD;
break;
case 'F': /* Normal */
case 'O':
p1->mailtypes |= MAIL_NORMAL;
break;
case 'D': /* Direct */
p1->mailtypes |= MAIL_DIRECT;
break;
case 'R': /* Request */
p1->mailtypes |= MAIL_REQUEST;
break;
}
if (!nodefind (&(p1->mail_addr), 0))
{
p1->mailtypes |= MAIL_UNKNOWN;
return (rettype);
}
/* Don't call for "HOLD" or "REQ" stuff. */
if ((dta_str.name[9] == 'H') || (dta_str.name[9] == 'R'))
return (rettype);
/* If there's no event, set mail to 'go' */
if (cur_event < 0)
{
p1->mailtypes |= MAIL_WILLGO;
return (rettype);
}
/* If it is a crash only event and this wasn't crash, return */
if ((dta_str.name[9] != 'C') && (e_ptrs[cur_event]->behavior & MAT_CM))
return (rettype);
/* Is this a local only event? */
if (e_ptrs[cur_event]->behavior & MAT_LOCAL)
{
/*
* If this is supposed to be only local, then get out if it isn't
*/
if (e_ptrs[cur_event]->node_cost >= 0)
{
if ((int) newnodedes.RealCost > e_ptrs[cur_event]->node_cost)
return (rettype);
}
else
{
if ((int) newnodedes.RealCost < -e_ptrs[cur_event]->node_cost)
return (rettype);
}
}
/* Is this a non-mail window event? */
if (newnodelist && (!(e_ptrs[cur_event]->behavior & MAT_NOMAIL24)))
{
/* If this guy can't handle crash, get out and try again */
if (!(newnodedes.NodeFlags & B_CM))
return (rettype);
}
/* Is this a receive only event? */
if (e_ptrs[cur_event]->behavior & MAT_NOOUT)
return (rettype);
/* Is this a non-CM event? */
if (newnodelist && (e_ptrs[cur_event]->behavior & MAT_NOCM) &&
(newnodedes.NodeFlags & B_CM))
return (rettype);
/* See if we spent too much calling him already */
if (bad_call (&(p1->mail_addr), 0))
{
p1->mailtypes |= MAIL_TOOBAD;
return (rettype);
}
p1->mailtypes |= MAIL_WILLGO;
return (rettype);
}
static char mail_stat (p)
MAILP p;
{
if (p->mailtypes & MAIL_UNKNOWN)
return ('!');
if (p->mailtypes & MAIL_TOOBAD)
return ('x');
if (p->mailtypes & MAIL_TRIED)
return ('#');
if (p->mailtypes & MAIL_WILLGO)
return ('*');
return ('-');
}
static char *mail_status_chars (unsigned int);
char msc[10];
static char *mail_status_chars (p)
unsigned int p;
{
char *q;
q = msc;
if (p & MAIL_CRASH )
*q++ = 'C';
if (p & MAIL_HOLD )
*q++ = 'H';
if (p & MAIL_DIRECT )
*q++ = 'D';
if (p & MAIL_NORMAL )
*q++ = 'N';
if (p & MAIL_REQUEST)
*q++ = 'R';
*q++ = '\0';
return (msc);
}
void xmit_window (p1)
MAILP p1;
{
MAILP p;
int i;
char j[40];
char j1[40];
if (!fullscreen)
return;
p = p1;
sb_fillc (holdwin, ' ');
if (p == NULL)
{
sb_move (holdwin, 3, 5);
sb_puts (holdwin, (unsigned char *) msgtxt[M_NOTHING_IN_OUTBOUND]);
return;
}
sb_move (holdwin, 1, 2);
sb_puts (holdwin, (unsigned char *) msgtxt[M_OUTBOUND_HEADER]);
for (i = 2; i < 6; i++)
{
if (p == NULL)
break;
sb_move (holdwin, i, 2);
sprintf (j, "%s", Full_Addr_Str (&(p->mail_addr)));
sprintf (j1, "%-21.21s %5.5s %c", j,
mail_status_chars (p->mailtypes),
mail_stat (p));
sb_puts (holdwin, (unsigned char *) j1);
p = p->next;
}
p = mail_top;
for (; i < 6; i++)
{
if ((p == p1) || (p == NULL))
break;
sb_move (holdwin, i, 2);
sprintf (j, "%s", Full_Addr_Str (&(p->mail_addr)));
sprintf (j1, "%-21.21s %5.5s %c", j,
mail_status_chars (p->mailtypes),
mail_stat (p));
sb_puts (holdwin, (unsigned char *) j1);
p = p->next;
}
sb_show ();
}
static void xmit_sort ()
{
MAILP p, p1, p2;
p = mail_top;
/* Find the first that is sendable */
while (p != NULL)
{
if ((p->mailtypes & MAIL_WILLGO) &&
(!(p->mailtypes & MAIL_TOOBAD)) &&
(!(p->mailtypes & MAIL_UNKNOWN)))
break;
p = p->next;
}
if (p == NULL)
return;
/* Put the first sendable one on top */
if (p != mail_top)
{
p->prev->next = p->next;
if (p->next != NULL)
p->next->prev = p->prev;
p->prev = NULL;
p->next = mail_top;
mail_top->prev = p;
mail_top = p;
}
p1 = p;
p = p1->next;
while (p != NULL)
{
if ((p->mailtypes & MAIL_WILLGO) &&
(!(p->mailtypes & MAIL_TOOBAD)) &&
(!(p->mailtypes & MAIL_UNKNOWN)))
{
if (p->prev == p1)
{
p1 = p;
p = p->next;
continue;
}
p2 = p->next;
p->prev->next = p->next;
if (p->next != NULL)
p->next->prev = p->prev;
p->next = p1->next;
if (p1->next != NULL)
p1->next->prev = p;
p->prev = p1;
p1->next = p;
p1 = p;
p = p2;
}
else
p = p->next;
}
}
void xmit_reset ()
{
MAILP p;
int i, j, k, done, zone;
char *domain;
ADDR tmp;
/* First get rid of all the old junk */
p = mail_top;
if (p != NULL)
{
while (p->next != NULL)
p = p->next;
while (p->prev != NULL)
{
p = p->prev;
free (p->next);
}
if (p != NULL)
free (p);
}
p = mail_top = NULL;
k = 0;
domain = domain_name[0];
do
{
zone = (int) alias[0].Zone;
while (zone > 0)
{
i = 0;
while (outb[i] != NULL)
{
tmp.Zone = zone;
tmp.Net = 0;
tmp.Node = 0;
tmp.Point = 0;
tmp.Domain = domain;
sprintf (next_one, "%s%s", HoldAreaNameMunge(&tmp), outb[i++]);
done = 0;
j = 0;
while (!done)
{
/* See if we have any more at this level */
#ifndef OS_2
if (dfind (&dta_str, next_one, j))
#else
if ( (j) ? dir_findnexta (&dta_str) : dir_findfirsta (next_one, _A_NORMAL, &dta_str))
#endif
{
/* No more at this level, so go to next level */
done = 1;
}
else
{
/* We found a name, remember it */
if (p == NULL)
p = mail_top = (MAILP) calloc (sizeof (MAIL), 1);
else
{
p->next = (MAILP) calloc (sizeof (MAIL), 1);
p->next->prev = p;
p = p->next;
}
if (xmit_install (p, zone, domain))
{
/* No good */
if (p->prev != NULL)
{
p = p->prev;
free (p->next);
p->next = NULL;
}
else
{
free (p);
p = mail_top = NULL;
}
}
++j;
} /* got one */
} /* while (!done) */
} /* while (outb[i] != null */
if (no_zones)
break;
/* Get the next zone number */
tmp.Zone = -1;
zone = nodefind (&tmp, 0);
if (zone == (int) alias[0].Zone)
zone = nodefind (&tmp, 0);
}
domain = domain_name[++k];
}
while (domain != NULL);
next_mail = NULL;
xmit_sort ();
xmit_window (mail_top);
}
int xmit_next (xaddr)
ADDR *xaddr;
{
/* Set up the proper pointer */
if ((next_mail == NULL) || (next_mail->next == NULL))
next_mail = mail_top;
else
next_mail = next_mail->next;
/* Loop through till we find something we can send */
while (next_mail != NULL)
{
if ((next_mail->mailtypes & MAIL_WILLGO) &&
(!(next_mail->mailtypes & MAIL_UNKNOWN)) &&
(!(next_mail->mailtypes & MAIL_TOOBAD)))
{
if (bad_call (&(next_mail->mail_addr), 0))
next_mail->mailtypes |= MAIL_TOOBAD;
else
{
xaddr->Zone = next_mail->mail_addr.Zone;
xaddr->Net = next_mail->mail_addr.Net;
xaddr->Node = next_mail->mail_addr.Node;
xaddr->Point = next_mail->mail_addr.Point;
xaddr->Domain = next_mail->mail_addr.Domain;
xmit_window (next_mail);
return (1);
}
}
next_mail = next_mail->next;
}
/* Read the disk again since we reached the end of the list */
#ifdef OS_2
xmit_reset ();
#endif
next_mail = mail_top;
/* Try the new list and see what happens */
while (next_mail != NULL)
{
if ((next_mail->mailtypes & MAIL_WILLGO) &&
(!(next_mail->mailtypes & MAIL_UNKNOWN)) &&
(!(next_mail->mailtypes & MAIL_TOOBAD)))
{
if (bad_call (&(next_mail->mail_addr), 0))
next_mail->mailtypes |= MAIL_TOOBAD;
else
{
xaddr->Zone = next_mail->mail_addr.Zone;
xaddr->Net = next_mail->mail_addr.Net;
xaddr->Node = next_mail->mail_addr.Node;
xaddr->Point = next_mail->mail_addr.Point;
xaddr->Domain = next_mail->mail_addr.Domain;
xmit_window (next_mail);
return (1);
}
}
next_mail = next_mail->next;
}
/* Oh well, we tried */
xmit_window (mail_top);
return (0);
}
void xmit_delete ()
{
MAILP p;
int i;
if (next_mail == NULL)
return;
i = 0;
while (outb[i] != NULL)
{
sprintf (next_one, "%s%s.%s",
HoldAreaNameMunge(&(next_mail->mail_addr)),
Hex_Addr_Str (&(next_mail->mail_addr)),
&(outb[i++][2]));
if (!dfind (&dta_str, next_one, 0))
{
status_line (msgtxt[M_STILL_HAVE_MAIL], Full_Addr_Str (&(next_mail->mail_addr)));
/* We still have something for him */
next_mail->mailtypes &= ~MAIL_WILLGO;
next_mail->mailtypes |= MAIL_TRIED;
return;
}
}
if (next_mail != mail_top)
{
p = next_mail->next;
next_mail = next_mail->prev;
free (next_mail->next);
next_mail->next = p;
if (p != NULL)
p->prev = next_mail;
xmit_window (next_mail);
}
else
{
mail_top = mail_top->next;
free (next_mail);
if (mail_top != NULL)
mail_top->prev = NULL;
xmit_window (mail_top);
next_mail = NULL;
}
}
static char fname[80];
static char fname1[80];
int bad_call (baddr, rwd)
ADDR *baddr;
int rwd;
{
int res;
int i, j;
struct FILEINFO bad_dta;
FILE *bad_wazoo;
char *p;
char *HoldName;
HoldName = HoldAreaNameMunge(baddr);
sprintf (fname, "%s%s.$$?", HoldName, Hex_Addr_Str (baddr));
j = (int) strlen (fname) - 1; /* Point at ? */
res = -1; /* Initialize to fail */
i = 0; /* This says findfirst */
while (!dfind (&bad_dta, fname, i)) /* as long as we match */
{
if (isdigit (bad_dta.name[11])) /* is there a digit? */
{
fname[j] = bad_dta.name[11]; /* Yes, copy to fname */
res = fname[j] - '0'; /* Save it for testing */
break; /* Get out of while */
}
else i = 1; /* Else use findnext */
}
if (res == -1) /* Successful search? */
fname[j] = '0'; /* No, base digit = 0 */
if (rwd > 0)
{
/* Writing a bad call */
/* First create a filename that is one higher than what we've got */
strcpy (fname1, fname);
fname1[j]++;
if (fname1[j] > '9')
fname1[j] = '9';
if (res == -1) /* Did we have a file? */
{ /* No, make one. */
if (rwd == 2) /* No carrier */
res = open (fname, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
else /* With carrier */
res = open (fname1, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
i = rwd - 1; /* zero-based count */
write (res, (char *) &i, sizeof (int)); /* write it out */
close (res); /* close the file */
}
else
{ /* There was a file */
/*
* 2 = Unsuccessful, No carrier. Update contents of the file.
*/
if (rwd == 2)
{
i = open (fname, O_RDONLY|O_BINARY);
read (i, (char *) &res, sizeof (int));
close (i);
++res;
i = open (fname, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
write (i, (char *) &res, sizeof (int));
close (i);
}
/*
* 1 = Unsuccessful, Carrier. Update file name to reflect the
* failure.
*/
else
{
rename (fname, fname1);
}
}
}
else if (rwd == 0)
{
/*
* 0 = We are reading a bad call status
*/
/* Is it automatically ok (no .$$ file there) ? */
if (res == -1)
return (0);
/* Were there too many connects with carrier? */
if (res >= max_connects)
return (1);
/* Ok, check for connects without carrier */
res = 0;
i = open (fname, O_RDONLY|O_BINARY);
read (i, (char *) &res, sizeof (int));
close (i);
return (res >= max_noconnects);
}
else
{
/*
* -1 = Cleanup of bad call status. This happens in two steps:
* a) delete 'netnode.$$?' in hold area;
* b) if a 'netnode.Z' file exists in hold area,
* 1) delete all BADWAZOO.xxx files listed in the .Z file;
* 2) delete the 'netnode.z' file.
*/
if (res != -1)
unlink (fname);
if (!mail_finished)
return (0);
sprintf (fname, "%s%s.Z", HoldName, Hex_Addr_Str (baddr));
if (dexists (fname))
{
if ((bad_wazoo = fopen (fname, read_ascii)) == NULL)
got_error (msgtxt[M_OPEN_MSG], fname);
else
{
while (!feof (bad_wazoo))
{
e_input[0] = '\0';
if (!fgets (e_input, 64, bad_wazoo))
break;
/* Point to BADWAZOO.xxx */
p = strchr (e_input, ' ') + 1;
/* Then just past it and terminate */
p = strchr (p, ' ');
*p = '\0';
/* Back to where we were */
p = strchr (e_input, ' ') + 1;
/* Build file name and delete file */
strcpy (fname1, CurrentNetFiles);
strcat (fname1, p);
unlink (fname1);
}
fclose (bad_wazoo);
}
unlink (fname);
}
}
return (0);
}
void set_up_outbound ()
{
MAILP mp;
xmit_reset ();
/* and remember where we left off */
if (hist.next_net != 0)
{
next_addr.Zone = hist.next_zone;
next_addr.Net = hist.next_net;
next_addr.Node = hist.next_node;
next_addr.Point = 0;
next_addr.Domain = NULL;
mp = find_mail (&next_addr);
if ((mp == NULL) || (mp->prev == NULL))
{
next_mail = NULL;
xmit_window (mail_top);
}
else
{
next_mail = mp->prev;
xmit_window (next_mail);
}
}
else
{
next_addr.Zone = 0;
next_addr.Net = 0;
next_addr.Node = 0;
next_addr.Point = 0;
next_addr.Domain = NULL;
xmit_window (mail_top);
}
}