home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 2 BBS
/
02-BBS.zip
/
BSRC_250.LZH
/
B_FRPROC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-15
|
25KB
|
792 lines
/*--------------------------------------------------------------------------*/
/* */
/* */
/* ------------ Bit-Bucket Software, Co. */
/* \ 10001101 / Writers and Distributors of */
/* \ 011110 / Freely Available<tm> Software. */
/* \ 1011 / */
/* ------ */
/* */
/* (C) Copyright 1987-91, Bit Bucket Software Co., a Delaware Corporation. */
/* */
/* */
/* BinkleyTerm File Request Processor */
/* */
/* */
/* 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.250. */
/* */
/* 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:343/491 */
/* P.O. Box 460398 AlterNet 7:491/0 */
/* Aurora, CO 80046 BBS-Net 86:2030/1 */
/* Internet f491.n343.z1.fidonet.org */
/* */
/* Please feel free to contact us at any time to share your comments about */
/* our software and/or licensing policies. */
/* */
/* */
/* This module is based largely on a similar module in OPUS-CBCS V1.03b. */
/* The original work is (C) Copyright 1987, Wynn Wagner III. The original */
/* author has graciously allowed us to use his code in this work. */
/* */
/*--------------------------------------------------------------------------*/
/* Include this file before any other includes or defines! */
#include "includes.h"
static char *their_pwd; /* Password in REQ file */
static char required_pwd[10]; /* Password in OK file */
static int xfer_seconds;
int prep_match (char *, char *);
int match (char *, char *);
void run_prog (char *);
int check_password (void);
freq_abort (long, int (*)(long));
int what_event (int);
int what_event_sub (int, int, int, int, int, int);
int prep_match (char *template, char *buffer)
{
register int i, delim;
register char *sptr;
int start;
(void) memset (buffer, 0, 11);
i = (int) strlen (template);
sptr = template;
for (start = i = 0; sptr[i]; i++)
if ((sptr[i] == '\\') || (sptr[i] == ':'))
start = i + 1;
if (start)
sptr += start;
delim = 8; /* last column for ? */
(void) strupr (sptr);
for (i = 0; *sptr && i < 12; sptr++)
switch (*sptr)
{
case '.':
if (i > 8)
return (-1);
while (i < 8)
{
buffer[i++] = ' ';
}
buffer[i++] = *sptr;
delim = 12;
break;
case '*':
while (i < delim)
{
buffer[i++] = '?';
}
break;
default:
buffer[i++] = *sptr;
break;
} /* switch */
while (i < 12)
{
/* dean suggests:
buffer[i++] = (i == delim) ? '.' : ((i > delim) ? '?' : ' ');
to replace the if/else below...
*/
if (i == 8)
buffer[i++] = '.';
else buffer[i++] = ' ';
}
buffer[i] = '\0';
return 0;
}
int match (char *s1, char *s2)
{
register char *i, *j;
i = s1;
j = s2;
while (*i)
{
if ((*j != '?') && (*i != *j))
{
return 1;
}
i++;
j++;
}
return 0;
}
/*--------------------------------------------------------------------------*/
/* Process file requests from the remote system. The filespec requested is */
/* turned into a local filespec if possible, then transferred via the */
/* caller-supplied routine. */
/*--------------------------------------------------------------------------*/
int n_frproc (char *request, int nfiles,
int (*callback)(char *), int (*calltime)(long))
{
register int i;
register int j = 0;
static char s[80];
static char s1[80];
static char s2[80];
char *p;
FILE *approved;
struct FILEINFO dta;
struct stat st;
char *sptr;
char *after_pwd;
long updreq = 0L;
char updtype = 0;
int saved_nfiles;
char our_wildcard[15];
char their_wildcard[15];
int mfunc;
int magic_state = 0;
int tried_about = 0;
int failure_reason = 1; /* 1 = not available */
/* 2 = no update */
/* 3 = bad password */
if (freq_accum.time == 0L)
freq_accum.time = (long)time(NULL);
approved = NULL;
their_pwd = NULL;
after_pwd = NULL;
(void) strcpy (s1, request);
/*--------------------------------------------------------------------*/
/* Fix up the file name */
/*--------------------------------------------------------------------*/
for (i = 0; request[i]; i++)
{
if (request[i] <= ' ')
{
request[i++] = '\0';
j = i;
break;
}
}
if (j)
{
/* If we have a '!', find the end of the password, point j
past it, then truncate and fold if necessary. This leaves
j properly aligned for other fields.
*/
if (request[j] == '!')
{
their_pwd = request + (++j);
for (; request[j]; j++)
{
if (request[j] <= ' ')
{
request[j++] = '\0';
break;
}
}
if (strlen (their_pwd) > 6)
their_pwd[6] = '\0';
(void) fancy_str (their_pwd);
}
/* Test for update/backdate request */
if (request[j] == '+' || request[j] == '-')
{
updtype = request[j++];
updreq = atol (&request[j]);
}
}
if (!request[0]) /* Still any filename? */
return (nfiles); /* If not, return df=0. */
if (freq_abort(0L, calltime)) /* Any reason to abort? */
return (-2); /* If so, return error. */
/*--------------------------------------------------------------------*/
/* Initialization(s) */
/*--------------------------------------------------------------------*/
i = 0;
sptr = NULL;
(void) strupr (request);
status_line ("*%s %s (%s)", (updreq != 0L) ? MSG_TXT(M_UPDATE) : MSG_TXT(M_FILE), MSG_TXT(M_REQUEST), request);
saved_nfiles = nfiles;
/*--------------------------------------------------------------------*/
/* Reserved words */
/*--------------------------------------------------------------------*/
if (!strcmp (request, "FILES"))
{
if (CURRENT.rq_FILES)
(void) strcpy (s, CURRENT.rq_FILES);
else
{
s[0] = '\0';
sptr = MSG_TXT(M_NO_AVAIL);
}
goto avail;
}
else if (!strcmp (request, "ABOUT"))
{
s[0] = '\0';
goto avail;
}
(void) prep_match (request, their_wildcard);
/*--------------------------------------------------------------------*/
/* See if the file is approved for transmission */
/*--------------------------------------------------------------------*/
if ((approved = share_fopen (CURRENT.rq_OKFile, read_ascii, DENY_WRITE)) == NULL)
{
(void) got_error (MSG_TXT(M_OPEN_MSG), CURRENT.rq_OKFile);
goto err;
}
while (!feof (approved))
{
/* If we were magic, set flag to cause exit if we don't do it again */
if (magic_state)
magic_state = 1; /* 1 means done if no @ */
s[0] = required_pwd[0] = '\0';
(void) fgets (s, 78, approved);
for (i = 0; s[i]; i++)
if (s[i] == 0x09)
s[i] = ' ';
else if (s[i] < ' ')
s[i] = '\0';
if (!s[0] || s[0] == ';')
continue;
/*--------------------------------------------------------------*/
/* Check for transaction-level password */
/*--------------------------------------------------------------*/
for (i = 0; s[i]; i++)
{
if (s[i] == ' ')
{
s[i] = '\0';
if (s[i + 1] == '!')
{
(void) strncpy (required_pwd, s + i + 2, 8);
if (strlen (required_pwd) > 6)
required_pwd[6] = '\0';
after_pwd = skip_blanks (s + i + 1);
while (*after_pwd && (!isspace (*after_pwd)))
++after_pwd;
if (*after_pwd)
++after_pwd;
for (i = 0; required_pwd[i]; i++)
if (required_pwd[i] <= ' ')
required_pwd[i] = '\0';
break;
}
else
{
after_pwd = skip_blanks (s + i + 1);
break;
}
}
else if (s[i] < ' ')
s[i] = '\0';
}
if (!s[0])
continue;
if (strchr ("@+$",s[0]) != NULL)
{
/* Magic name or function */
if ((s[0] != '>') && stricmp (&s[1], request))
continue;
/* Name matches, check password */
if (!(check_password ()))
{
failure_reason = 3; /* Password doesn't match */
continue; /* Go on */
}
mfunc = 0;
if (s[0] == '$')
{
(void) sprintf (s2, after_pwd, remote_addr.Net,
remote_addr.Node, remote_addr.Point);
mfunc = 1;
}
if (s[0] == '+')
{
(void) sprintf (s, " %d %d %d %d", remote_addr.Zone, remote_addr.Net,
remote_addr.Node, remote_addr.Point);
(void) strcpy (s2, s1);
(void) strcat (s2, s);
mfunc = 2;
}
if (mfunc)
{
run_prog (s2);
goto check_HLO;
}
if (s[0] == '@')
{
(void) strcpy (s, after_pwd);
magic_state = 2; /* Will be reset up above */
}
}
/*
* We're past the magic stuff here. So check for whether this is
* a new iteration of a magic loop that somehow didn't catch.
* If not, then check out the filespec we have on this line.
*/
if (magic_state == 1)
goto check_HLO;
j = 1;
if (Netmail_Session == 2)
SENDBYTE (NUL);
if (!dfind (&dta, s, 0))
{
do
{
if (!(--j)) /* If we've looped a bit */
{
i = freq_abort (0L, calltime);
if (i) /* See if we want to quit */
{
if (i == 1) /* Yes, why? Carrier? */
goto finished; /* uh-huh -- get out fast */
else
{
failure_reason = i; /* Not carrier, get reason*/
goto make_RSP; /* Make a .RSP file */
}
}
j = 10; /* No, reset bounds */
}
if (!magic_state) /* If not "magic", */
{
if (prep_match (dta.name, our_wildcard) < 0)
continue;
if (match (our_wildcard, their_wildcard))
continue;
/* File names match, check password now */
if (!check_password ())
{
failure_reason = 3; /* Password doesn't match */
continue; /* Go on */
}
}
/* Good password, get full path with wildcard from OKFILE */
(void) strcpy (s2, s);
/* Subtract the wild card file name, keep path */
if ((p = strrchr (s2, '\\')) != NULL)
*++p = '\0';
else s2[0] = '\0';
/* Then add in the exact name found */
(void) strcat (s2, dta.name);
/* Got full filename, now do file update validation */
if (updtype && !stat (s2, &st))
{
if ((updtype == '+' && (st.st_atime <= updreq))
|| (updtype == '-' && (st.st_atime >= updreq)))
{
failure_reason = 2; /* No update available */
continue; /* Go on */
}
}
i = freq_abort (dta.size, calltime); /* Check file size */
if (i) /* See if we want to quit */
{
if (i == 1) /* Yes, why? Carrier? */
goto finished; /* uh-huh -- get out fast */
else
{
failure_reason = i; /* Not carrier, get reason*/
goto make_RSP; /* Make a .RSP file */
}
}
/* Everything is OK, send the file if we can */
CLEAR_INBOUND ();
if ((*callback) (s2))
{
++nfiles;
freq_accum.bytes += dta.size;
freq_accum.CumTime += xfer_seconds;
++freq_accum.files;
}
j = 1; /* Force abort test */
}
while (!dfind (&dta, s, 1));
} /* if dfind */
else status_line (MSG_TXT(M_OKFILE_ERR), s); /* if not dfind */
s[0] = '\0';
} /* while not eof(approved) */
if (saved_nfiles != nfiles)
failure_reason = 9;
make_RSP:
s[0] = '\0'; /* Initialize string */
if ((CURRENT.rq_Template != NULL) && (dexists(CURRENT.rq_Template )))
{
Make_Response(s1, failure_reason); /* Build a response */
(void) strcpy(s, s1); /* Copy it for xmission */
}
if ((!s[0]) && (failure_reason > 3)) /* if no .RSP file, */
goto finished; /* give it up */
/*--------------------------------------------------------------------*/
/* File requested not found, send the system ABOUT file. */
/*--------------------------------------------------------------------*/
avail:
if (!s[0])
{
if (CURRENT.rq_About)
(void) strcpy (s, CURRENT.rq_About);
else
{
if (tried_about)
{
sptr = MSG_TXT(M_NO_ABOUT);
goto err;
}
else
{
++tried_about;
(void) strcpy (s1, request);
failure_reason = 1; /* Didn't find what we wanted */
goto make_RSP; /* Make a .RSP file */
}
}
}
CLEAR_INBOUND ();
if ((*callback) (s))
++nfiles;
goto finished;
/*--------------------------------------------------------------------*/
/* See if we generated a .QLO file somehow, if so send listed files */
/*--------------------------------------------------------------------*/
check_HLO:
CLEAR_INBOUND ();
(void) do_FLOfile ("Q", callback);
/*--------------------------------------------------------------------*/
/* Maybe the magic request made a conventional .FLO file, try that too*/
/*--------------------------------------------------------------------*/
*ext_flags = 'F';
(void) do_FLOfile (ext_flags, callback);
goto finished;
/*--------------------------------------------------------------------*/
/* Error return */
/*--------------------------------------------------------------------*/
err:
if (sptr)
status_line ("!%s %s %s: %s",
(updreq != 0L) ? MSG_TXT(M_UPDATE) : MSG_TXT(M_FILE),
MSG_TXT(M_REQUEST), &(MSG_TXT(M_ERROR)[1]), sptr);
finished:
if (approved)
(void) fclose (approved);
return (nfiles);
}
void run_prog (char *s)
{
struct baud_str saved_baud;
status_line ("%s '%s'", MSG_TXT(M_EXECUTING), s);
if (fullscreen && un_attended)
{
screen_clear ();
}
scr_printf (&(MSG_TXT(M_EXECUTING)[1]));
scr_printf (s);
scr_printf ("\r\n");
vfossil_cursor (1);
saved_baud = cur_baud;
b_spawn (s);
vfossil_cursor (0);
if (fullscreen && un_attended)
{
screen_clear ();
sb_dirty ();
opening_banner ();
mailer_banner ();
}
(void) set_baud (saved_baud.rate_value, 0); /* Restore baud rate */
}
int check_password ()
{
if (required_pwd[0])
{
(void) fancy_str (required_pwd);
if ((stricmp (required_pwd, their_pwd)) &&
(stricmp (required_pwd, remote_password)))
{
status_line (MSG_TXT(M_FREQ_PW_ERR),
required_pwd,
their_pwd,
remote_password
);
return (0);
}
}
return (1);
}
int freq_abort (long file_size, int (*calltime)(long))
{
int w_event;
int xfer_time;
if (!CARRIER)
{
status_line (MSG_TXT(M_CARRIER_REQUEST_ERR));
return (1);
}
if ((CURRENT.rq_Limit != 0)
&& ((freq_accum.files + 1) >= CURRENT.rq_Limit))
{
status_line (MSG_TXT(M_FREQ_LIMIT));
return (4);
}
if ((CURRENT.byte_Limit != 0L)
&& ((freq_accum.bytes + file_size) > CURRENT.byte_Limit))
{
status_line (MSG_TXT(M_BYTE_LIMIT));
return (6);
}
/* Get file time in seconds for comparison with quota */
if (file_size != 0L)
xfer_time = calltime (file_size);
else
xfer_time = 0;
xfer_seconds = xfer_time;
if ((CURRENT.time_Limit != 0)
&& (((long)time(NULL) + xfer_time - freq_accum.time) > CURRENT.time_Limit))
{
status_line (MSG_TXT(M_TIME_LIMIT));
return (7);
}
xfer_time /= 60; /* We want minutes for event calculations */
w_event = what_event (xfer_time);
if ((w_event >= 0) && (w_event != cur_event))
{
if (e_ptrs[w_event].behavior & MAT_NOREQ)
{
status_line (MSG_TXT(M_EVENT_OVERRUN));
return (5);
}
}
else if (w_event == -2)
{
status_line (MSG_TXT(M_EVENT_OVERRUN));
return (5);
}
return (0);
}
int what_event (int delta_time)
{
time_t long_time;
struct tm *tm;
int now;
int tomorrow = 0;
int our_time;
int w_event;
int save_time;
/* Get the current time into a structure */
(void) time (&long_time);
tm = localtime (&long_time);
/* Calculate minutes since midnight */
now = tm->tm_hour * 60 + tm->tm_min;
/* Then number of minutes past midnight at end of delta_time */
save_time = our_time = delta_time + now;
/* Is the end in Tomorrow? (Sounds like a soap opera, eh?) */
if (1440 < our_time)
{
tomorrow = 1; /* Remember that we've wrapped */
our_time = 1439; /* Set event end = 23:59 for now */
}
/* Test "today," and if we find an event, get the hell out */
w_event = what_event_sub (tm->tm_mon, tm->tm_wday, tm->tm_mday,
now, our_time, 0);
if (w_event != -1)
return w_event;
/*
* If we need to test tomorrow, figure out all the salient info
* on what tomorrow is, and test that.
*/
if (tomorrow)
{
long_time += 86400L; /* Any time tomorrow will do. */
tm = localtime (&long_time);
w_event = what_event_sub (tm->tm_mon, tm->tm_wday, tm->tm_mday,
0, (save_time - 1440), 1);
}
return w_event;
}
int what_event_sub (int cur_mon, int cur_day, int cur_mday,
int now, int our_time, int tomorrow)
{
int i;
cur_day = 1 << cur_day; /* Make cur_day a bit mask */
for (i = 0; i < num_events; i++ )
{
/* If this is an event we need to think about (i.e., it started
* before the end of the transfer, and ends after "now") ...
*/
if ((our_time >= e_ptrs[i].minute)
&& (now <= ( e_ptrs[i].minute + e_ptrs[i].length)))
{
/* And if it's on a day we care about ... */
if ((cur_day & e_ptrs[i].days)
&& ((!e_ptrs[i].day) || (e_ptrs[i].day == (char)cur_mday))
&& ((!e_ptrs[i].month) || (e_ptrs[i].month == (char)cur_mon)))
{
/* Don't do events that have been exited already unless
* the tomorrow flag is set (in which case, no events have
* occurred, have they?)
*/
if (!tomorrow
&& (e_ptrs[i].last_ran == (char) cur_mday)
&& (e_ptrs[i].behavior & MAT_SKIP))
continue;
/* If the event we are considering does not allow requests,
* then this is a bugger we are looking for. Return its index.
*/
if ((e_ptrs[i].behavior & MAT_NOREQ))
return i;
} /* end of if ((cur_day & ... )) */
} /* end of if ( our_time >= ... ) */
} /* end of for ( ... ) */
return -1;
}