/*--------------------------------------------------------------------------*/ /* */ /* */ /* ------------ 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 Vince Perriello */ /* */ /* BinkleyTerm Mail Session Initiator */ /* */ /* */ /* 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" extern int CallerSendSync (void); extern int CalledRecvSync (void); extern int EMSI_Sender (void); extern int EMSI_Receiver (void); void b_session (int was_initiator) { int i; ADDR tmp; isOriginator = was_initiator; start_hist = hist; CURRENT = DEFAULT; mail_finished = 0; (void) time (&etm); freq_accum.bytes = 0L; freq_accum.files = 0; freq_accum.time = 0L; if (un_attended && fullscreen) do_ready (MSG_TXT (M_READY_CONNECT)); /* Remove the old .REQ and .RSP files */ for (i = 0; i < 10; i++) { if (alias[i].Net == 0) break; tmp = alias[i]; /* For a point, massage the address to get the right .REQ filename */ if (tmp.Point != 0) { tmp.Node = tmp.Point; tmp.Point = 0; tmp.Net = (pvtnet > 0) ? (unsigned short) pvtnet : 0; } (void) sprintf (junk, request_template, CURRENT.sc_Inbound, Hex_Addr_Str (&tmp), TaskNumber); (void) unlink (junk); if (!pktrsp) /* MB 93-12-12 PKTRSP */ { (void) sprintf (junk, "%s.RSP", Hex_Addr_Str (&tmp)); (void) unlink (junk); } } /* remove old response PKTs */ if (pktrsp) /* MB 93-12-12 PKTRSP */ { struct FILEINFO dta = {0}; char fname[80]; (void) sprintf (junk, "%s%02x*.PKT", flag_dir, TaskNumber); if (!dfind (&dta, junk, 0)) { do { (void) sprintf (fname, "%s%s", flag_dir, dta.name); (void) unlink (fname); } while (!dfind (&dta, junk, 1)); dfind (&dta, NULL, 2); } } tmp.Zone = 0; tmp.Net = 0; tmp.Node = 0; tmp.Point = 0; tmp.Domain = NULL; remote_capabilities = 0; my_capabilities = (no_zapzed) ? 0 : (ZED_ZAPPER | ZED_ZIPPER); my_capabilities |= (no_dietifna) ? 0 : Y_DIETIFNA; if ((janus_baud >= cur_baud.rate_value) || (janus_OK)) { if (!no_janus) my_capabilities |= DOES_IANUS; #ifdef HAVE_HYDRA if (!no_hydra) my_capabilities |= DOES_HYDRA; #endif } (void) flag_file (SET_SESSION_FLAG, &called_addr, 0); if (was_initiator) { /* * OUTBOUND -- meaning call was made by us. */ last_type (1, &remote_addr); /* See if this address is serviced by an external mail agent. If so, call WaZOO with a special argument. */ if (ExtMailMask && (newnodedes.ModemType == (byte)ExtMailMask)) { no_EMSI_Session = 1; remote_pickup = -2; remote_capabilities = my_capabilities = 0; WaZOO (1); } else if (Whack_CR () == 0) { retry_outbound: switch (i = CallerSendSync ()) { case 1: no_EMSI_Session = TRUE; FTSC_sender (0); break; case 2: if (YooHoo_Sender ()) { if ((remote_capabilities & my_capabilities) == 0) { no_EMSI_Session = 1; no_WaZOO_Session = 1; status_line (MSG_TXT (M_NO_COMMON_PROTO)); goto retry_outbound; } no_EMSI_Session = TRUE; remote_pickup = -1; WaZOO (1); } break; case 4: if (EMSI_Sender ()) { if ((remote_capabilities & my_capabilities) == 0) { no_EMSI_Session = 1; no_WaZOO_Session = 1; status_line (MSG_TXT (M_NO_COMMON_PROTO)); goto retry_outbound; } WaZOO (1); } break; default: break; } /* end switch */ } } else { /* * INBOUND -- meaning we were connected to by another system. */ retry_inbound: b_init (); /* String following "Connect [xxxx]" is a special case of an external mail string. */ for (i = 0; i < num_ext_mail; i++) { if (stricmp (saved_response, ext_mail_string[i]) == 0) { i += 5; goto ext_mail; } } switch (i = CalledRecvSync ()) { case 1: /* ESCape or Timeout */ if (CARRIER && !mail_only) { last_type (3, &tmp); (void) flag_file (CLEAR_SESSION_FLAG, &called_addr, 0); BBSexit (); } break; case 2: /* FTSC Netmail Session */ if (CARRIER) { tmp.Zone = (unsigned short) -1000; last_type (2, &tmp); tmp.Zone = 0; ++hist.mail_calls; if (un_attended && fullscreen) { (void) sprintf (junk, "%d/%d", hist.bbs_calls, hist.mail_calls); sb_move (historywin, HIST_MAIL_ROW, HIST_COL); sb_puts (historywin, junk); sb_show (); } no_EMSI_Session = TRUE; (void) FTSC_receiver (0); } break; case 3: /* WaZOO Netmail Session*/ if (YooHoo_Receiver ()) { if ((remote_capabilities & my_capabilities) == 0) { no_WaZOO_Session = 1; no_EMSI_Session = TRUE; status_line (MSG_TXT (M_NO_COMMON_PROTO)); goto retry_inbound; } last_type (1, &remote_addr); ++hist.mail_calls; if (un_attended && fullscreen) { (void) sprintf (junk, "%d/%d", hist.bbs_calls, hist.mail_calls); sb_move (historywin, HIST_MAIL_ROW, HIST_COL); sb_puts (historywin, junk); sb_show (); } remote_pickup = -1; no_EMSI_Session = TRUE; WaZOO (0); /* do WaZOO!!! */ } break; case 4: /* EMSI Netmail Session*/ if (EMSI_Receiver ()) { if ((remote_capabilities & my_capabilities) == 0) { no_WaZOO_Session = 1; no_EMSI_Session = TRUE; status_line (MSG_TXT (M_NO_COMMON_PROTO)); goto retry_inbound; } last_type (1, &remote_addr); ++hist.mail_calls; if (un_attended && fullscreen) { (void) sprintf (junk, "%d/%d", hist.bbs_calls, hist.mail_calls); sb_move (historywin, HIST_MAIL_ROW, HIST_COL); sb_puts (historywin, junk); sb_show (); } WaZOO (0); /* do EMSI!!! */ } break; default: if (CARRIER && (i >= 5) && (i < (5 + num_ext_mail))) /* See if ext mail */ { ext_mail: last_type (4, &tmp); (void) flag_file (CLEAR_SESSION_FLAG, &called_addr, 0); UUCPexit (lev_ext_mail[i - 5], 1); } break; } /* end switch */ } /* end if (was_initiator) */ saved_response[0] = '\0'; no_WaZOO_Session = no_WaZOO; no_EMSI_Session = no_EMSI; (void) flag_file (CLEAR_FLAG, &called_addr, 1); /* ensure flag's gone */ (void) flag_file (CLEAR_SESSION_FLAG, &called_addr, 0); return; } void b_init () { got_arcmail = got_packet = got_mail = sent_mail = got_fax = 0; remote_addr.Zone = remote_addr.Net = remote_addr.Node = remote_addr.Point = 0; remote_addr.Domain = NULL; assumed = 0; Netmail_Session = 0; remote_capabilities = 0; mail_finished = 0; CURRENT = DEFAULT; } /* * Send banner-type lines to remote. Since strange modems like Courier HST * have a propensity for thinking they are connected when talking to a dial * tone (but do leave CTS down just to screw us up) we have to use a timeout * to figure out if we are in trouble, and if so, we drop DTR to make the * bogus carrier go away. * * This routine is used in modules B_BBS.C and RECVSYNC.C, both of which * are called from this module only. * */ int SendBanner (char far * string) { long t1; register char c; t1 = timerset (600); /* 60 secs to send banner*/ while (!timeup (t1) && CARRIER) { if (got_ESC ()) /* Manual abort? */ break; /* Use failure logic */ if (!OUT_FULL ()) { c = *string++; if (!c || c == 0x1a)/* Test for end */ return (1); /* Yes, success */ SENDBYTE ((unsigned char) c); } else /* If output was full*/ time_release (); /* give up timeslice */ } /* * If we get here we had trouble. Drop DTR now to hopefully get out of * this trouble. Flush outbound. Pause for 1 second. */ LOWER_DTR (); CLEAR_OUTBOUND (); timer (10); CLEAR_INBOUND (); return (0); } int flag_file (int function, ADDRP address, int do_stat) { FILE *fptr; char *HoldName; static ADDR last_set[ALIAS_CNT]; static last_count; char flagname[128]; char tmpname[128]; char BSYname[15]; static int had_to_punt[ALIAS_CNT]; int i, j; if (!TaskNumber) return (FALSE); HoldName = HoldAreaNameMunge (address); switch (function) { case INITIALIZE: last_count = 0; /* Fall through for cleanup purposes */ case CLEAR_SESSION_FLAG: /* At the end of a session, delete the task file */ if (flag_dir) { (void) sprintf (flagname, "%sTask.%02x", flag_dir, TaskNumber); (void) unlink (flagname); } return (FALSE); case SET_SESSION_FLAG: /* At the start of a session, set up the task number */ if (flag_dir) { (void) sprintf (flagname, "%sTask.%02x", flag_dir, TaskNumber); fptr = fopen (flagname, write_binary); (void) fclose (fptr); } return (FALSE); case TEST_AND_SET: /* * First see if we already HAVE this lock! If so, return now. * */ for (i = 0; i < last_count; i++) { if (memcmp (&last_set[i], address, sizeof (ADDR)) == 0) return (FALSE); } /* * Next determine the directory in which we will create the flagfile. * Also, the name of the file. * */ if (address->Point != 0) { (void) sprintf (flagname, "%s%04hx%04hx.PNT\\", HoldName, address->Net, address->Node); (void) sprintf (BSYname, "%08hx.BSY", address->Point); } else { (void) strcpy (flagname, HoldName); (void) sprintf (BSYname, "%04hx%04hx.BSY", address->Net, address->Node); } /* * File opens are destructive by nature. Therefore use a file name * that's unique to us. Create it in the chosen target. If we can't * do that, try to use the flag directory. * */ had_to_punt[last_count] = 0; (void) sprintf (tmpname, "%sBINKBSY.%02x", flagname, TaskNumber); fptr = fopen (tmpname, write_binary); if ((fptr == NULL) && (flag_dir)) { had_to_punt[last_count] = 1; (void) strcpy (flagname, flag_dir); (void) sprintf (tmpname, "%sBINKBSY.%02x", flagname, TaskNumber); fptr = fopen (tmpname, write_binary); } /* * Now we've done all we can. The file is either open in the * appropriate outbound or it's in the flag directory. * If neither option worked out, go away. There's nothing to do. * */ if (fptr == NULL) { if (do_stat) status_line (MSG_TXT (M_FAILED_CREATE_FLAG), tmpname); return (TRUE); } (void) fclose (fptr); /* * Now the test&set. Attempt to rename the file to a value specific * to the remote node's address. If we succeed, we have the lock. * If we do not, delete the temp file. * */ (void) strcat (flagname, BSYname); /* Add the .BSY file name */ if (!rename (tmpname, flagname)) { if (do_stat) status_line (MSG_TXT (M_CREATED_FLAGFILE), flagname); last_set[last_count++] = *address; return (FALSE); } if (do_stat) status_line (MSG_TXT (M_THIS_ADDRESS_LOCKED), Full_Addr_Str (address)); (void) unlink (tmpname); return (TRUE); case CLEAR_FLAG: /* * Make sure we need to clear something. * Zone should be something other than -1 if that's the case. * */ if (!last_count) return (TRUE); /* * Next compare what we want to clear with what we think we have. * */ for (i = 0; i < last_count; i++) if (!memcmp (&last_set[i], address, sizeof (ADDR))) break; if (i >= last_count) /* not yet set ??? */ { if (do_stat) status_line (MSG_TXT (M_BAD_CLEAR_FLAGFILE), Full_Addr_Str (address)); return (TRUE); } /* * We match. Recalculate the directory. Yeah, that's redundant * code, but it saves static space. * */ if (address->Point != 0) { (void) sprintf (flagname, "%s%04hx%04hx.PNT\\", HoldName, address->Net, address->Node); (void) sprintf (BSYname, "%08hx.BSY", address->Point); } else { (void) strcpy (flagname, HoldName); (void) sprintf (BSYname, "%04hx%04hx.BSY", address->Net, address->Node); } if (had_to_punt[i]) (void) strcpy (flagname, flag_dir); (void) strcat (flagname, BSYname); had_to_punt[i] = 0; j = i++; for (; i < last_count; j++, i++) { last_set[j] = last_set[i]; had_to_punt[j] = had_to_punt[i]; } last_count--; if (!unlink (flagname)) { if (do_stat) status_line (MSG_TXT (M_CLEARED_FLAGFILE), flagname); return (TRUE); } if (do_stat) status_line (MSG_TXT (M_FAILED_CLEAR_FLAG), flagname); return (FALSE); default: break; } return (TRUE); } void forcexitcheck () { struct stat buf; struct FILEINFO dta = {0}; static char fname[256]; static long next_time = 0L; if (!flag_dir) return; if (next_time && !timeup (next_time)) return; if (forcexit) { if (TaskNumber) { sprintf (fname, "%sFORCEXIT.%u", flag_dir, TaskNumber); } else { sprintf (fname, "%sFORCEXIT", flag_dir); } if (!stat (fname, &buf)) { unlink (fname); screen_blank = 0; if (errlvlshell[forcexit - 1] == NULL) { status_line (MSG_TXT (M_FORCED_EXIT), forcexit); errl_exit (forcexit); } else { status_line (MSG_TXT (M_FORCED_SHELL), forcexit); errl_shell (forcexit); } } } sprintf (fname, "%sBTEXIT??.??", flag_dir); if (!dfind (&dta, fname, 0)) { do { int sExit = 0, sTask = 0; int cScanned = 0; cScanned = sscanf (dta.name, "BTEXIT%02x.%02x", &sExit, &sTask); if (cScanned && (sTask == TaskNumber)) { sprintf (fname, "%s%s", flag_dir, dta.name); unlink (fname); screen_blank = 0; if (errlvlshell[sExit - 1] == NULL) { status_line (MSG_TXT (M_FORCED_EXIT), sExit); errl_exit (sExit); } else { status_line (MSG_TXT (M_FORCED_SHELL), sExit); errl_shell (sExit); } break; } } while (!dfind (&dta, fname, 1)); dfind (&dta, NULL, 2); } next_time = timerset (200); /* Don't check for at least 2 seconds */ } int forcerescancheck () { struct stat buf; static char fname[256]; static long next_time = 0L; if (!flag_dir) return (0); if (next_time && !timeup (next_time)) return (0); sprintf (fname, "%sBTRESCAN.%02x", flag_dir, TaskNumber); if (!stat (fname, &buf)) { unlink (fname); next_time = timerset (1000); /* At least 10 seconds before next */ return (1); } next_time = timerset (200); /* Don't check for at least 2 seconds */ return 0; }