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-96, Bit Bucket Software Co. */
- /* */
- /* */
- /* */
- /* 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.260. */
- /* */
- /* 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:42/1491 */
- /* 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"
-
- #define AREA_ID 0x54414441L /* "ADAT" */
-
- #define MAX_ALEN 10 /* Max length of usr.msg[] and usr.files[] */
- #define MAX_OVR 16 /* Maximum # of override privs per area */
- #define NUM_MENU 256 /* Max. # of options in a menu file */
- #define MAXCLASS 12 /* number of possible priv levels */
-
- /* New Max 2.xx format for MAXFILES.IDX. The file is simply an array of *
- * these structures. */
-
- struct _maxfile
- {
- byte name[12];
- word areaofs;
- word fileofs;
- };
-
- struct _override
- {
- signed short priv; /* Override priv level */
- unsigned long lock; /* Override lock setting */
-
- byte ch; /* First letter of menu option to override */
- byte fill; /* Reserved by Maximus */
- };
-
- struct _area
- {
- long id; /* Unique identifier for AREA.DAT structure.*
- * Should be AREA_ID, above. */
-
- word struct_len; /* Length of _area structure -- this needs *
- * only to be read from the first record in *
- * an area data file, since it can be *
- * assumed to remain the same throughout the*
- * entire file. This is GUARANTEED to be at*
- * offset four for this and all future *
- * versions of this structure. */
-
- word areano; /* OBSOLETE. Two-byte integer representation*
- * of the area name. Use area.name instead. */
-
- byte name[40]; /* String format of area's name. USE THIS! */
-
- /************************************************************************/
- /** Message Area Information **/
- /************************************************************************/
-
- word type; /* Message base type. MSGTYPE_SDM = *.MSG. *
- * MSGTYPE_SQUISH = SquishMail. (Constants *
- * are in MSGAPI.H) */
-
- byte msgpath[80]; /* Path to messages */
- byte msgname[40]; /* The 'tag' of area, used in ECHOTOSS.LOG */
- byte msginfo[80]; /* The DIR.BBS-like desc for msg section */
- byte msgbar[80]; /* Barricade file for message area */
- byte origin[62]; /* The ORIGIN line for this area */
-
- short msgpriv; /* This is the priv required to access the *
- * msg section of this area. */
- byte fill0; /* The lock for the message area (obsolete) */
-
- byte fill1;
-
- short origin_aka; /* The AKA number to use on the origin line.*
- * See the normal SysOp documentation on *
- * the "Origin" statement, for info on how *
- * this number is used. */
-
- /************************************************************************/
- /** File Area Information **/
- /************************************************************************/
-
- byte filepath[80]; /* Path for downloads */
- byte uppath[80]; /* Path for uploads */
- byte filebar[80]; /* Barricade file for file areas */
- byte filesbbs[80]; /* Path to FILES.BBS-like catalog for area */
- byte fileinfo[80]; /* The DIR.BBS-like desc for file section */
-
- short filepriv; /* The priv required to access the file *
- * section of this area. */
- byte fill15; /* The locks for the file area (obsolete) */
- byte fill2;
-
- /************************************************************************/
- /** Miscellaneous Information **/
- /************************************************************************/
-
- byte msgmenuname[13]; /* Alternate *.MNU name to use for msg.area */
- byte filemenuname[13]; /* Alternate *.MNU name to use for file area */
-
- word attrib[MAXCLASS]; /* This is an array of attributes for the *
- * msg/file areas. These are dependant on PRIV *
- * level. Once you have the CLASS number for a *
- * particular user (via Find_Class_Number()),you*
- * can find the attributes for that particular *
- * priv level like this: "area.attrib[class]" *
- * ...which will get you the attribute for that *
- * priv level. */
-
- /************************************************************************/
- /** Stuff hacked on later **/
- /************************************************************************/
-
- struct _override movr[MAX_OVR]; /* Override privs for msg/file areas */
- struct _override fovr[MAX_OVR];
-
- unsigned long msglock; /* 32-bit locks for message areas */
- unsigned long filelock; /* 32-bit locks for file areas */
-
- word killbyage; /* MAXREN: max # of days to keep msgs in area */
- /* (use 0 for no deletion by age) */
- word killbynum; /* MAXREN: max # of msgs to keep in area (use 0 */
- /* for no deletion by #msgs.) */
-
- };
-
- 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);
- int 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)
- {
- 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 ((int) (*i - *j));
- }
- 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 = {0};
- 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 */
- struct _area area;
- struct _maxfile filmax;
- int fmax = 0, fdat = 0, slen = 0;
- long fmaxpos = 0L;
- unsigned int fmaxstep = 30;
- long fmaxmax = 0L;
- long fmaxsiz = (long) sizeof (struct _maxfile);
-
- 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 ((request[i] == ':') || (request[i] == '\\'))
- {
- request[0] = '\0';
- j = 0;
- 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++];
- #ifdef ANSI_TIME_T
- updreq = atol (&request[j]) + ANSI_TIME_T_DELTA;
- #else
- updreq = atol (&request[j]);
- #endif
- }
- }
-
- 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);
-
- /*--------------------------------------------------------------*/
- /* Check MAXFILES.IDX */
- /*--------------------------------------------------------------*/
-
- if ((s[0] == '*') && (max_areadat != NULL))
- {
-
- p = s;
- p++;
-
- if ((fmax = share_open (p, O_RDONLY | O_BINARY, DENY_NONE)) == -1)
- {
- (void) got_error (MSG_TXT (M_OPEN_MSG), p);
- fmax = 0;
- goto err;
- }
-
- if ((fdat = share_open (max_areadat, O_RDONLY | O_BINARY, DENY_NONE)) == -1)
- {
- (void) got_error (MSG_TXT (M_OPEN_MSG), max_areadat);
- (void) close (fmax);
- fmax = fdat = 0;
- goto err;
- }
-
- /* Read the first record of the file, to grab the structure-length *
- * byte.
- */
-
- (void) read (fdat, &area, sizeof (struct _area));
-
- slen = area.struct_len;
-
- (void) stat (p, &st);
- fmaxmax = st.st_size / fmaxsiz;
- if (fmaxmax > 5000L)
- fmaxstep = 60;
-
- if (abs (loglevel) == 5)
- status_line (MSG_TXT (M_MAXFILE_SCANNING), fmaxmax, fmaxstep, p);
-
- /* original while (!eof (fmax)) */
- for (;;)
- {
-
- if (fmaxstep)
- {
- fmaxpos += fmaxstep;
- if (fmaxpos >= fmaxmax)
- {
- fmaxpos -= (long) fmaxstep;
- fmaxstep = 0;
- }
- lseek (fmax, fmaxpos * fmaxsiz, SEEK_SET);
- }
-
- /* original (void) read (fmax, &filmax, (unsigned)fmaxsiz); */
-
- /* This should work same as the eof test and be more portable */
-
- if (read (fmax, &filmax, (unsigned) fmaxsiz) != (int) fmaxsiz)
- break;
-
- if (!(--j)) /* If we've looped a bit */
- {
- i = freq_abort (0L, calltime);
- if (i) /* See if we want to quit */
- {
- (void) close (fmax);
- (void) close (fdat);
- fmax = fdat = 0;
- 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 */
- }
-
- filmax.fileofs = filmax.areaofs;/* save the offset... :-) */
- filmax.name[12] = '\0';
-
- if (prep_match ((char *) filmax.name, our_wildcard) < 0)
- continue;
-
- i = match (our_wildcard, their_wildcard);
-
- if (i < 0)
- continue;
- else
- {
- if (fmaxstep)
- {
- fmaxpos -= (long) fmaxstep;
- fmaxstep = 0;
- lseek (fmax, fmaxpos * fmaxsiz, SEEK_SET);
- continue;
- }
- else
- if (i > 0)
- break;
- }
-
- fmaxstep = 0;
-
- /* File names match, check security now */
-
- lseek (fdat, (long) filmax.fileofs * (long) slen, SEEK_SET);
- read (fdat, &area, sizeof (struct _area));
-
- if (CURRENT.security < area.filepriv)
- {
- failure_reason = 3; /* Security doesn't match */
- if (abs (loglevel) == 5)
- status_line (MSG_TXT (M_MAX_SECURITY_MISMATCH), (int) CURRENT.security,
- (int) area.filepriv);
- continue; /* Go on */
- }
-
- /* Add in the exact name found */
-
- (void) strcpy (s2, (char *) area.filepath);
- (void) strcat (s2, (char *) filmax.name);
-
- /* Now find the "real" file */
-
- if ((i = stat (s2, &st)) != -1)
- {
-
- /* Got full filename, now do file update validation */
-
- if (updtype && !i)
- {
- if ((updtype == '+' && (st.st_atime <= (time_t) updreq)) ||
- (updtype == '-' && (st.st_atime >= (time_t) updreq)))
- {
- failure_reason = 2; /* No update available */
- continue; /* Go on */
- }
- }
-
- i = freq_abort (st.st_size, calltime); /* Check file size */
-
- if (i) /* See if we want to quit */
- {
- (void) close (fmax);
- (void) close (fdat);
- fmax = fdat = 0;
- 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 += st.st_size;
- freq_accum.CumTime += xfer_seconds;
- ++freq_accum.files;
- }
- j = 1; /* Force abort test */
- }
-
- } /* end of while */
-
- /* close open max files */
- if (fmax)
- (void) close (fmax);
- if (fdat)
- (void) close (fdat);
-
- } /* end of MAXFILES.IDX check */
- else
- {
- /*--------------------------------------------------------------*/
- /* Check for any other line */
- /*--------------------------------------------------------------*/
- 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; /* No, 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) != 0)
- continue;
-
- /* File names match, check password now */
-
- if (!check_password ())
- {
- failure_reason = 3; /* Password doesn't match */
- continue; /* Go on */
- }
- }
-
- /* Good password, get 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 <= (time_t) updreq))
- || (updtype == '-' && (st.st_atime >= (time_t) 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));
- (void) dfind (&dta, s, 2);
- } /* 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 != NULL && required_pwd[0])
- {
- if (their_pwd == NULL && remote_password == NULL)
- {
- status_line (MSG_TXT (M_FREQ_PW_ERR),
- required_pwd,
- "(NULL)",
- "(NULL)"
- );
- return (0);
- }
- (void) fancy_str (required_pwd);
- if ((stricmp (required_pwd, their_pwd)) &&
- (remote_password == NULL ||
- (remote_password != NULL && 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;
- }
-