home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------------*/
- /* */
- /* */
- /* ------------ 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;
- }
-
-
-