/*--------------------------------------------------------------------------*/ /* */ /* */ /* ------------ Bit-Bucket Software, Co. */ /* \ 10001101 / Writers and Distributors of */ /* \ 011110 / Freely Available Software. */ /* \ 1011 / */ /* ------ */ /* */ /* (C) Copyright 1987-96, Bit Bucket Software Co. */ /* */ /* 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.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. */ /* */ /*--------------------------------------------------------------------------*/ /* Include this file before any other includes or defines! */ #include "includes.h" static char *LOCALFUNC estring (int, int); static void scan_netmail (char *); int do_mail (ADDRP baddr, int type) /* 1 = manual, 0 = normal, -1 = CM */ { int i; long callstart = 0, callend; b_init (); caller = 1; got_packet = 0; got_arcmail = 0; got_mail = 0; got_fax = 0; sent_mail = 0; no_WaZOO_Session = no_WaZOO; no_EMSI_Session = no_EMSI; callstart = 0L; (void) sprintf (junk, "%s", Full_Addr_Str (baddr)); called_addr = remote_addr = *baddr; /* structure assignment */ if (!net_params) { status_line (MSG_TXT (M_INSUFFICIENT_DATA)); set_xy (""); return (0); } if (!nodeproc (junk)) return (0); if (type > 0) { if (flag_file (TEST_AND_SET, &called_addr, 1)) { if (CARRIER) mdm_hangup (); return (0); } if (CARRIER || /* called manually maybe? */ (ExtMailMask && (newnodedes.ModemType == (byte)ExtMailMask))) goto process_the_damned_mail; /* yup, just do some mail */ do_dial_strings (); try_2_connect ((char *) (newnodedes.PhoneNumber)); /* try to connect */ } else { /* If this is supposed to be only local, then get out if it isn't */ if (type == 0) { if (e_ptrs[cur_event].behavior & MAT_LOCAL) { if (e_ptrs[cur_event].node_cost < 0) { if ((int) newnodedes.RealCost < -e_ptrs[cur_event].node_cost) { return (0); } } else { if ((int) newnodedes.RealCost > e_ptrs[cur_event].node_cost) { return (0); } } } /* If it is supposed to be 24 hour mail only, get out if it isn't */ if ((newnodelist || version7) && (!(e_ptrs[cur_event].behavior & MAT_NOMAIL24)) && (!(newnodedes.NodeFlags & B_CM))) return (0); /* If we aren't supposed to send to CM's now, get out */ if ((newnodelist || version7) && (e_ptrs[cur_event].behavior & MAT_NOCM) && (newnodedes.NodeFlags & B_CM)) return (0); } /* Try to connect */ if (flag_file (TEST_AND_SET, &called_addr, 1)) { if (CARRIER) mdm_hangup (); return (0); } do_dial_strings (); if (un_attended && fullscreen) { sb_move (holdwin, 2, 1); sb_wa (holdwin, colors.calling, 31); } callstart = time (NULL); if (!blank_on_key) screen_blank = 0; if (ExtMailMask && (newnodedes.ModemType == (byte)ExtMailMask)) goto process_the_damned_mail; if ((i = try_1_connect ((char *) (newnodedes.PhoneNumber))) < 0) { if (un_attended && fullscreen) { sb_move (holdwin, 2, 1); sb_wa (holdwin, colors.hold, 31); } (void) flag_file (CLEAR_FLAG, &called_addr, 1); return (i); } } process_the_damned_mail: if (CARRIER || /* if we did, */ (ExtMailMask && (newnodedes.ModemType == (byte)ExtMailMask))) { if (!callstart) callstart = time (NULL); b_session (1); /* do a mail session */ if (remote_pickup != -2) mdm_hangup (); callend = time (NULL); hist.last_Elapsed = callend - callstart; hist.callcost += cost_of_call (1, callstart, callend); ++hist.connects; if (un_attended && fullscreen) { do_today (); } write_stats (); if (un_attended && (got_arcmail || got_packet || got_mail)) { (void) bad_call (baddr, -1); receive_exit (); } if (un_attended && fullscreen) { sb_move (holdwin, 2, 1); sb_wa (holdwin, colors.hold, 31); } return (1); } else { status_line (MSG_TXT (M_END_OF_ATTEMPT)); (void) flag_file (CLEAR_FLAG, &called_addr, 1); } if (un_attended && fullscreen) { sb_move (holdwin, 2, 1); sb_wa (holdwin, colors.hold, 31); } write_stats (); return (2); } int handle_inbound_mail (int answer_now) { long t; /* used for timeouts */ long lEndTime; /* master timeout */ int iRingCount = 0; /* for counting 'em */ int mr; /* Modem response */ int iInterval = 6000; /* Default wait = 1min*/ long callstart, callend; no_WaZOO_Session = no_WaZOO; no_EMSI_Session = no_EMSI; caller = 0; (void) memset ((char *) &remote_addr, 0, sizeof (remote_addr)); remote_addr.Domain = NULL; /* only Microsoft can explain this */ /* Master timeout of 2 minutes */ lEndTime = timerset (12000); inloop: /* Do we have carrier, RING, or NO DIAL TONE? */ if (timeup (lEndTime) || ((answer_now <= 0) && !(server_mode && CARRIER) && !CHAR_AVAIL ())) { time_release (); return (0); /* No, nothing to do */ } mail_only = 1; if ((cur_event >= 0) && (e_ptrs[cur_event].behavior & MAT_BBS)) mail_only = 0; if (KEYPRESS ()) /* If aborted by user, */ return (1); /* get out */ if (server_mode && CARRIER) { mr = CONNECTED; goto got_carrier; } if (answer_now > 0) { mr = RINGING; /* say it rang */ iRingCount = ring_wait; /* we want to answer right now */ answer_now = -1; } else mr = modem_response (500); if ((mr == RINGING) && (ans_str != NULL)) /* saw RING */ { iRingCount++; /* Unblank on the first ring */ if ((answer_now < 0) || (iRingCount == 1)) { if (!blank_on_key) screen_blank = 0; if (un_attended && fullscreen) sb_show (); } /* Answer if we've reached the correct ring number */ if (iRingCount >= ring_wait) { /* * Try to make sure we don't send out the answer string * while stuff is still coming from the modem. Most modems * don't like that kind of sequence (including HST's!). */ t = timerset (100); while (CHAR_AVAIL () && (!timeup (t))) { t = timerset (100); (void) MODEM_IN (); } CLEAR_INBOUND (); mdm_cmd_string (ans_str, 0); /* transmit the answer string */ iInterval = 6000; } /* Otherwise wait up to 15 seconds for something to happen */ else iInterval = 1500; } else if (mr == FAILURE) /* If we got "No Carrier" */ { time_release (); return (0); /* Nothing happened... */ } else if (mr == CONNECTED || mr >= FAX) goto got_carrier; t = timerset (iInterval);/* set the interval timer */ while ((!timeup (t)) && (!CHAR_AVAIL ()) && (!KEYPRESS ())) { time_release (); /* wait for another result */ } goto inloop; /* then proceed along */ got_carrier: if (!blank_on_key) screen_blank = 0; if (un_attended && fullscreen) sb_show (); callstart = time (NULL); if (mr >= FAX) /* FAX is > 16 */ { int gotfax = 1; int i; if (!fax_in) { /* We have a FAX result code but are not configured to receive any. See if the user has set up a fax exit using the external mail strings */ for (i = 0; i < num_ext_mail; i++) { if (stricmp (saved_response, ext_mail_string[i]) == 0) { last_type (5, &alias[0]); UUCPexit (lev_ext_mail[i], 0); } } } else { start_hist = hist; last_type (5, &alias[0]); gotfax = faxreceive (FAX); /* Try to get a FAX */ } mdm_hangup (); /* Then hang up */ callend = time (NULL); hist.last_Elapsed = callend - callstart; hist.callcost += cost_of_call (0, callstart, callend); if (gotfax) /* If we got one, */ { got_fax = 1; /* Say we got mail */ receive_exit (); /* And try to exit */ } } else if (CARRIER) /* if we have a carrier, */ { b_session (0); /* do a mail session */ mdm_hangup (); /* Make sure to hang up */ callend = time (NULL); hist.last_Elapsed = callend - callstart; hist.callcost += cost_of_call (0, callstart, callend); /* We got inbound mail */ if (got_arcmail || got_packet || got_mail) { receive_exit (); } } else { mdm_hangup (); /* Try to reset modem */ callend = time (NULL); hist.last_Elapsed = callend - callstart; hist.callcost += cost_of_call (0, callstart, callend); } mailer_banner (); return (1); } void receive_exit () { char junk1[150]; int i; BINK_EVENT evt; if (cur_event >= 0) evt = e_ptrs[cur_event]; if (cur_event >= 0) { int errlvl = 0; int exitlvl = 0; if (got_arcmail && (evt.errlevel[2])) { exitlvl = evt.errlevel[2]; if (errlvlshell[exitlvl - 1] == NULL) { errlvl = exitlvl; status_line (MSG_TXT (M_EXIT_COMPRESSED), errlvl); } else { status_line (MSG_TXT (M_SHELL_COMPRESSED), exitlvl); errl_shell (exitlvl); got_arcmail = got_mail = got_packet = 0; } } for (i = 0; i < 6; i++) { if (user_exits[i]) { user_exits[i] = 0; exitlvl = evt.errlevel[i + 3]; if (errlvlshell[exitlvl - 1] == NULL) { if (errlvl == 0) { errlvl = exitlvl; status_line (MSG_TXT (M_EXIT_AFTER_EXTENT), &(evt.err_extent[i][0]), errlvl); } } else { status_line (MSG_TXT (M_SHELL_AFTER_EXTENT), &(evt.err_extent[i][0]), exitlvl); errl_shell (exitlvl); } } } #ifdef BINKLEY_SOUNDS /* If we got an exit level, it's still set even if we shelled. So use its presence to determine whether to make noise */ if (exitlvl) Make_Sound (fnFileSound); #endif /* See if we still want to exit */ if (errlvl) errl_exit (errlvl); } if (got_fax && cur_event >= 0 && (evt.faxerrlevel)) { #ifdef BINKLEY_SOUNDS Make_Sound (fnFAXSound); #endif if (errlvlshell[evt.faxerrlevel - 1] != NULL) { status_line (MSG_TXT (M_SHELL_FAX), evt.faxerrlevel); errl_shell (evt.faxerrlevel); got_fax = 0; } else { status_line (MSG_TXT (M_EXIT_FAX), evt.faxerrlevel); errl_exit (evt.faxerrlevel); } } if ((got_fax || got_mail || got_packet) && (cur_event >= 0) && (evt.errlevel[1])) { #ifdef BINKLEY_SOUNDS Make_Sound (fnMailSound); #endif if (errlvlshell[evt.errlevel[1] - 1] != NULL) { status_line (MSG_TXT (M_SHELL_AFTER_MAIL), evt.errlevel[1]); errl_shell (evt.errlevel[1]); got_fax = got_mail = got_packet = 0; } else { status_line (MSG_TXT (M_EXIT_AFTER_MAIL), evt.errlevel[1]); errl_exit (evt.errlevel[1]); } } if ((aftermail != NULL) && (got_fax || got_mail || got_packet || got_arcmail)) { status_line (MSG_TXT (M_AFTERMAIL)); #ifdef BINKLEY_SOUNDS Make_Sound (fnMailSound); #endif mdm_init (modem_busy); exit_DTR (); screen_clear (); vfossil_cursor (1); (void) strcpy (junk1, aftermail); if (cur_event >= 0) (void) strcat (junk1, evt.cmd); close_up (); b_spawn (junk1); come_back (); RAISE_DTR (); status_line (MSG_TXT (M_OK_AFTERMAIL)); mdm_init (modem_init); xmit_reset (0); waitfor_line = timerset ((unsigned int) 6000); } got_arcmail = 0; got_packet = 0; got_mail = 0; got_fax = 0; } void errl_exit (int n) { write_sched (); status_line (MSG_TXT (M_BINK_END), ANNOUNCE, COMPILER_NAME); mdm_init (modem_busy); /* Reinitialize the modem */ exit_DTR (); if (fullscreen) gotoxy (0, SB_ROWS); if (vfossil_installed) vfossil_close (); if (!share) MDM_DISABLE (); exit (n); } void errl_shell (int n) { write_sched (); if (!strnicmp ("start ", errlvlshell[n - 1], 6)) { status_line (MSG_TXT (M_START_ERRLVL_SESSION), n); system (errlvlshell[n - 1]); } else { mdm_init (modem_busy); exit_DTR (); close_up (); screen_clear (); vfossil_cursor (1); b_spawn (errlvlshell[n - 1]); come_back (); RAISE_DTR (); status_line (MSG_TXT (M_RETURN_ERRLVL_SHELL)); mdm_init (modem_init); xmit_reset (0); waitfor_line = timerset ((unsigned int) 6000); } } long random_time (int x) { int i; if (x == 0) { return (0L); } /* Number of seconds to delay is random based on x +/- 50% */ i = (rand () % (x + 1)) + (x / 2); return (timerset ((unsigned int) (i * 100))); } char * HoldAreaNameMunge (ADDRP maddr) { static char munged[127]; register char *p, *q; int i; if ((maddr->Domain != my_addr.Domain) && (maddr->Domain != NULL)) { *domain_loc = '\0'; (void) strcpy (munged, domain_area); q = &(munged[strlen (munged)]); for (i = 0; domain_name[i] != NULL; i++) { if (domain_name[i] == maddr->Domain) { if (domain_abbrev[i] != NULL) { p = domain_abbrev[i]; while (*p) *q++ = *p++; if (no_zones) (void) sprintf (q, "\\"); else (void) sprintf (q, ".%03x\\", maddr->Zone); } break; } } } else { (void) strcpy (munged, hold_area); q = &(munged[strlen (munged)]); if (!((maddr->Zone == alias[0].Zone) || (no_zones))) { --q; (void) sprintf (q, ".%03x\\", maddr->Zone); } } return (munged); } void mailer_banner () { if (fullscreen && un_attended) { vfossil_cursor (0); (void) sprintf (junk, "%-2d", cur_event + 1); sb_move (settingswin, SET_EVNT_ROW, SET_COL); sb_puts (settingswin, junk); (void) sprintf (junk, "%-6lu Com%d", cur_baud.rate_value, port_ptr + 1); sb_move (settingswin, SET_PORT_ROW, SET_COL); sb_puts (settingswin, junk); clear_filetransfer (); if (TaskNumber) (void) sprintf (junk, "M'Task: %-7s %02x", mtask_name, TaskNumber); else (void) sprintf (junk, "M'Task: %s", mtask_name); sb_move (settingswin, SET_TASK_ROW, 2); sb_puts (settingswin, " "); sb_move (settingswin, SET_TASK_ROW, 2); sb_puts (settingswin, junk); } (void) set_baud (max_baud.rate_value, 0); } void clear_filetransfer () { if (fullscreen && un_attended) sb_fillc (filewin, ' '); } static char ebuf[50]; static char *LOCALFUNC estring (int e, int how_big) { char j[30]; char *p, *q; *(p = &ebuf[0]) = '\0'; if (e >= 0) { if (e_ptrs[e].behavior & MAT_BBS) { *p++ = 'B'; if (how_big) *p++ = ' '; } if (e_ptrs[e].behavior & MAT_CM) { *p++ = 'C'; if (how_big) *p++ = ' '; } if (e_ptrs[e].behavior & MAT_DYNAM) { *p++ = 'D'; if (how_big) *p++ = ' '; } if (how_big && (e_ptrs[e].behavior & MAT_FORCED)) { *p++ = 'F'; *p++ = ' '; } if (e_ptrs[e].behavior & MAT_HIPRICM) { *p++ = 'H'; if (how_big) *p++ = ' '; } if (e_ptrs[e].behavior & MAT_NOCM) { *p++ = 'K'; if (how_big) *p++ = ' '; } if (e_ptrs[e].behavior & MAT_LOCAL) { *p++ = 'L'; if (how_big) { if (e_ptrs[e].node_cost >= 0) (void) sprintf (j, "<%d ", (e_ptrs[e].node_cost) + 1); else (void) sprintf (j, ">%d ", -(e_ptrs[e].node_cost) - 1); q = j; while (*q) *p++ = *q++; } } if (how_big && (e_ptrs[e].behavior & MAT_NOMAIL24)) { *p++ = 'M'; *p++ = ' '; } if (e_ptrs[e].behavior & MAT_NOREQ) { *p++ = 'N'; if (how_big) *p++ = ' '; } if (e_ptrs[e].behavior & MAT_OUTONLY) { *p++ = 'S'; if (how_big) *p++ = ' '; } if (e_ptrs[e].behavior & MAT_NOOUT) { *p++ = 'R'; if (how_big) *p++ = ' '; } if (how_big && (e_ptrs[e].behavior & MAT_NOOUTREQ)) *p++ = 'X'; } *p = '\0'; return (ebuf); } void do_ready (char *str) { if (fullscreen && un_attended) { if (!doing_poll) { clear_filetransfer (); } (void) sprintf (junk, "%-2d/%-6.6s", cur_event + 1, estring (cur_event, 0)); sb_move (settingswin, SET_EVNT_ROW, SET_COL); sb_puts (settingswin, junk); sb_move (settingswin, SET_STAT_ROW, SET_COL); sb_puts (settingswin, str); sb_show (); } } void list_next_event () { int i; char *p; char j[100]; i = time_to_next (0); if ((next_event >= 0) && fullscreen) { clear_filetransfer (); (void) sprintf (j, MSG_TXT (M_NEXT_EVENT), next_event + 1, i); sb_move (filewin, 1, 2); sb_puts (filewin, j); p = estring (next_event, 1); if (*p != '\0') { (void) sprintf (j, MSG_TXT (M_EVENT_FLAGS), p); sb_move (filewin, 2, 2); sb_puts (filewin, j); } if (netmail != NULL) scan_netmail (j); sb_show (); } /* If next event and fullscreen */ } /* Temp area j passed from function above. Sorta messy but can't afford too many stack variables on DOS */ static void scan_netmail (char *j) { int i, k; short iReadT[2]; FILE *fpt; struct FILEINFO dta = {0}; if (*netmail == '$') { if (SquishScan (netmail + 1)) { sb_move (filewin, 2, 50); sb_puts (filewin, MSG_TXT (M_UNREAD_NETMAIL)); } } else { (void) strcpy (j, netmail); (void) strcat (j, "LASTREAD"); /* Full path to LASTREAD */ fpt = share_fopen (j, read_binary, DENY_WRITE); /* Open the file */ if (fpt != NULL) { /* * Try to read two records. If there are two, the first record is the * current pointer and the second one is the last-read. If there is * one record, it is the last-read. */ i = fread (iReadT, sizeof (short), 2, fpt); /* Get lastread ptr */ (void) fclose (fpt); /* Then close the file*/ if (i) { int f = 0; k = iReadT[i - 1]; /* Last msg read */ (void) strcpy (j, netmail); (void) strcat (j, "*.msg"); /* Wildcard for .MSG */ while (!dfind (&dta, j, f)) /* If there are any, */ { f = 1; if (atoi (dta.name) > k) /* See if one's more */ { sb_move (filewin, 2, 50); sb_puts (filewin, MSG_TXT (M_UNREAD_NETMAIL)); break; } } if (f) (void) dfind (&dta, NULL, 2); } /* If any records read from LASTREAD */ } /* If we were able to open LASTREAD */ } /* If the user specified NetMail */ }