/*--------------------------------------------------------------------------*/ /* */ /* */ /* ------------ 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 FTSC Mail Session 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" #define rb_plus "r+b" static int FTSC_callback (char *); static int FTSC_time (long); static int LOCALFUNC FTSC_sendmail (void); static int LOCALFUNC FTSC_recvmail (int); #define NUM_FLAGS 4 void FTSC_sender (int wz) { int j; char junkbuff[128]; long t1; XON_DISABLE (); first_block = 0; if (!wz) { first_block = 1; status_line (MSG_TXT (M_SEND_FALLBACK)); who_is_he = 0; (void) sprintf (junkbuff, "*%s (%s)", newnodedes.SystemName, Full_Addr_Str (&remote_addr)); status_line (junkbuff); } Netmail_Session = 1; (void) FTSC_sendmail (); t1 = timerset (4500); /* See what the receiver would like us to do */ while ((!timeup (t1)) && CARRIER) { if ((j = PEEKBYTE ()) >= 0) { switch (j) { case TSYNC: CLEAR_INBOUND (); if (FTSC_recvmail (1)) goto get_out; t1 = timerset (4500); break; case SYN: CLEAR_INBOUND (); if (on_our_nickel) (void) SEA_recvreq (); else { SENDBYTE (CAN); status_line (MSG_TXT (M_REFUSING_IN_FREQ)); } t1 = timerset (4500); break; case ENQ: CLEAR_INBOUND (); SEA_sendreq (); goto get_out; case NAK: case 'C': CLEAR_INBOUND (); SENDBYTE (EOT); t1 = timerset (4500); break; default: CLEAR_INBOUND (); SENDBYTE (SUB); break; } } else { time_release (); } } if (!CARRIER) { status_line (MSG_TXT (M_NO_CARRIER)); CLEAR_INBOUND (); first_block = 0; return; } if (timeup (t1)) { (void) FTSC_recvmail (1); status_line (MSG_TXT (M_TOO_LONG)); } get_out: first_block = 0; t1 = timerset (100); while (!timeup (t1)) time_release (); if (!wz) status_line (MSG_TXT (M_0001_END)); } int FTSC_receiver (int wz) { char fname[64]; int havemail, done, np; unsigned int i; long t1, t2; struct stat buf; char *HoldName; struct FILEINFO dta = {0}; ADDR tmp; first_block = 0; XON_DISABLE (); if (!wz) { first_block = 1; status_line (MSG_TXT (M_RECV_FALLBACK)); who_is_he = 1; } Netmail_Session = 1; CLEAR_INBOUND (); /* Save the state of pickup for now */ done = no_pickup; no_pickup = 0; if (FTSC_recvmail (0)) { /* Restore the state of pickup */ no_pickup = done; if (!wz) status_line (MSG_TXT (M_0001_END)); first_block = 0; return (1); } /* Restore the state of pickup */ no_pickup = done; remote_addr = called_addr; HoldName = HoldAreaNameMunge (&called_addr); /* Now see if we should send anything back to him */ (void) sprintf (fname, "%s%s.?UT", HoldName, Hex_Addr_Str (&remote_addr)); havemail = !dfind (&dta, fname, 0); if (!havemail) { (void) sprintf (fname, "%s%s.?LO", HoldName, Hex_Addr_Str (&remote_addr)); havemail = !dfind (&dta, fname, 0); } if (!havemail) { for (np = 0; np <= ALIAS_CNT; np++) { if (alias[np].Net == 0) break; (void) sprintf (fname, "%s%s.REQ", CURRENT.sc_Inbound, Hex_Addr_Str (&(alias[np]))); havemail = !dfind (&dta, fname, 0); if (havemail) break; } } if (!havemail) { status_line (MSG_TXT (M_NOTHING_TO_SEND), Full_Addr_Str (&remote_addr)); } else { /* Release any resource involved in finding the mail */ (void) dfind (&dta, NULL, 2); status_line (MSG_TXT (M_GIVING_MAIL), Full_Addr_Str (&remote_addr)); /* Send the TSYNC's until we get a C or NAK or CAN back */ t1 = timerset (3000); /* set 30 second timeout */ done = 0; while (!timeup (t1) && CARRIER && !done) /* till then or CD lost */ { SENDBYTE (TSYNC); t2 = timerset (300); while (CARRIER && (!timeup (t2)) && !done) { switch (TIMED_READ (0)) { case 'C': case NAK: done = 1; (void) FTSC_sendmail (); break; case CAN: done = 1; status_line (MSG_TXT (M_REFUSE_PICKUP), Full_Addr_Str (&remote_addr)); break; default: time_release (); } } } } first_block = 0; if (wz) return TRUE; /* All done if this is WaZOO */ /* Now see if we want to request anything */ tmp = remote_addr; /* 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 int) pvtnet : 0; } (void) sprintf (fname, "%s%s.REQ", HoldName, Hex_Addr_Str (&tmp)); if (!stat (fname, &buf)) { /* Send the SYN character and wait for an ENQ or CAN */ t1 = timerset (3000); /* set 30 second timeout */ done = 0; while (!timeup (t1) && CARRIER && !done) /* till then or CD lost */ { SENDBYTE (SYN); t2 = timerset (500); while (CARRIER && (!timeup (t2)) && !done) { i = (unsigned) TIMED_READ (0); switch (i) { case ENQ: SEA_sendreq (); break; case CAN: done = 1; break; case 'C': case NAK: SENDBYTE (EOT); break; case SUB: SENDBYTE (SYN); break; default: time_release (); } } } } /* Finally, can he request anything from us */ if (!no_requests) (void) SEA_recvreq (); status_line (MSG_TXT (M_0001_END)); return TRUE; } static int LOCALFUNC FTSC_sendmail () { FILE *fp; char fname[80]; char s[80]; char *sptr; char *HoldName; int c; int i; int j = 0; struct stat buf; struct _pkthdr *tmppkt; time_t t1; struct tm *tm1; XON_DISABLE (); (void) n_getpassword (&called_addr); /* Update "assumed" */ sptr = s; /*--------------------------------------------------------------------*/ /* Send all waiting ?UT files (mail packets) */ /*--------------------------------------------------------------------*/ *ext_flags = 'O'; HoldName = HoldAreaNameMunge (&called_addr); for (c = 0; c < NUM_FLAGS; c++) { #ifndef JACK_DECKER if (caller && (ext_flags[c] == 'H')) continue; #endif (void) sprintf (fname, "%s%s.%cUT", HoldName, Hex_Addr_Str (&called_addr), ext_flags[c]); if (!stat (fname, &buf)) break; } /* for */ /*--- Build a dummy PKT file name */ invent_pkt_name (s); status_line (MSG_TXT (M_PACKET_MSG)); if (c == NUM_FLAGS) { (void) sprintf (fname, "%s%s.OUT", HoldName, Hex_Addr_Str (&called_addr)); if ((fp = fopen (fname, write_binary)) == NULL) { (void) got_error (MSG_TXT (M_OPEN_MSG), fname); return (1); } t1 = time (NULL); tm1 = localtime (&t1); tmppkt = (struct _pkthdr *) calloc (1, sizeof (struct _pkthdr)); if (tmppkt == NULL) { status_line (MSG_TXT (M_MEM_ERROR)); (void) fclose (fp); return (1); } tmppkt->orig_node = (int) alias[assumed].Node; tmppkt->dest_node = called_addr.Node; tmppkt->ver = PKTVER; tmppkt->orig_net = (int) alias[assumed].Net; tmppkt->dest_net = called_addr.Net; tmppkt->product = PRDCT_CODE; if (n_getpassword (&called_addr) > 0) { if (remote_password != NULL) { (void) strupr (remote_password); (void) strncpy ((char *) (tmppkt->password), remote_password, 8); } } tmppkt->orig_zone = (int) alias[assumed].Zone; tmppkt->dest_zone = called_addr.Zone; if (((called_addr.Domain != NULL) && (called_addr.Domain != alias[assumed].Domain) && (my_addr.Domain != NULL)) || (alias[assumed].Point != 0)) { /* Make it a type 2.2 packet instead */ tmppkt->year = alias[assumed].Point; tmppkt->month = called_addr.Point; tmppkt->day = 0; tmppkt->hour = 0; tmppkt->minute = 0; tmppkt->second = 0; tmppkt->rate = 2; if (alias[assumed].Domain != NULL) { for (i = 0; domain_name[i] != NULL; i++) { if (domain_name[i] == alias[assumed].Domain) { break; } } if (i < 49) { (void) strncpy ((char *) tmppkt->B_fill2, domain_abbrev[i], 8); } } for (i = 0; domain_name[i] != NULL; i++) { if (domain_name[i] == called_addr.Domain) { break; } } if ((i < 49) && (domain_name[i] != NULL)) { (void) strncpy ((char *) &(tmppkt->B_fill2[8]), domain_abbrev[i], 8); } } else { tmppkt->year = tm1->tm_year; tmppkt->month = tm1->tm_mon; tmppkt->day = tm1->tm_mday; tmppkt->hour = tm1->tm_hour; tmppkt->minute = tm1->tm_min; tmppkt->second = tm1->tm_sec; tmppkt->rate = 0; } (void) fwrite ((char *) tmppkt, sizeof (struct _pkthdr), 1, fp); free (tmppkt); (void) fwrite ("\0\0", 2, 1, fp); (void) fclose (fp); } else { if ((fp = fopen (fname, rb_plus)) == NULL) { (void) got_error (MSG_TXT (M_OPEN_MSG), fname); return (1); } tmppkt = (struct _pkthdr *) calloc (1, sizeof (struct _pkthdr)); if (tmppkt == NULL) { status_line (MSG_TXT (M_MEM_ERROR)); return (1); } if (fread (tmppkt, 1, sizeof (struct _pkthdr), fp) < sizeof (struct _pkthdr)) { (void) got_error (MSG_TXT (M_READ_MSG), fname); free (tmppkt); (void) fclose (fp); return (1); } if (n_getpassword (&called_addr) > 0) { if (remote_password != NULL) { (void) strupr (remote_password); (void) strncpy ((char *) (tmppkt->password), remote_password, 8); } } /* Make sure the zone info is in there */ tmppkt->orig_node = (int) alias[assumed].Node; tmppkt->orig_net = (int) alias[assumed].Net; tmppkt->orig_zone = (int) alias[assumed].Zone; tmppkt->dest_zone = called_addr.Zone; if ((called_addr.Domain != NULL) && (called_addr.Domain != alias[assumed].Domain) && (my_addr.Domain != NULL)) { /* Make it a type 2.2 packet instead */ tmppkt->year = alias[assumed].Point; tmppkt->month = called_addr.Point; tmppkt->day = 0; tmppkt->hour = 0; tmppkt->minute = 0; tmppkt->second = 0; tmppkt->rate = 2; if (alias[assumed].Domain != NULL) { for (i = 0; domain_name[i] != NULL; i++) { if (domain_name[i] == alias[assumed].Domain) { break; } } if (i < 49) { (void) strncpy ((char *) tmppkt->B_fill2, domain_abbrev[i], 8); } } for (i = 0; domain_name[i] != NULL; i++) { if (domain_name[i] == called_addr.Domain) { break; } } if (i < 49) { (void) strncpy ((char *) &(tmppkt->B_fill2[8]), domain_abbrev[i], 8); } } (void) fseek (fp, 0L, SEEK_SET); (void) fwrite (tmppkt, 1, sizeof (struct _pkthdr), fp); (void) fclose (fp); free (tmppkt); } net_problems = (no_sealink) ? Telink_Send_File (fname, s) : SEAlink_Send_File (fname, s); if (net_problems != 0) { if (c == NUM_FLAGS) (void) unlink (fname); return (net_problems); } /* Delete the sent packet */ (void) unlink (fname); /*--------------------------------------------------------------------*/ /* Send files listed in ?LO files (attached files) */ /*--------------------------------------------------------------------*/ *ext_flags = 'F'; status_line (" %s %s", MSG_TXT (M_OUTBOUND), MSG_TXT (M_FILE_ATTACHES)); if (!do_FLOfile (ext_flags, FTSC_callback)) return FALSE; /*--------------------------------------------------------------------*/ /* Send our File requests to other system if it's a WaZOO */ /*--------------------------------------------------------------------*/ if (requests_ok && remote_capabilities) { (void) sprintf (fname, "%s%s.REQ", HoldName, Hex_Addr_Str (&called_addr)); if (!stat (fname, &buf)) { if (!(((unsigned) remote_capabilities) & WZ_FREQ)) status_line (MSG_TXT (M_FREQ_DECLINED)); else { status_line (MSG_TXT (M_MAKING_FREQ)); if (FTSC_callback (fname)) (void) unlink (fname); } } } /*--------------------------------------------------------------------*/ /* Process WaZOO file requests from other system */ /*--------------------------------------------------------------------*/ j = respond_to_file_requests (j, FTSC_callback, FTSC_time); /* Now close out the file attaches */ sent_mail = 1; *sptr = 0; status_line (" %s %s %s", MSG_TXT (M_END_OF), MSG_TXT (M_OUTBOUND), MSG_TXT (M_FILE_ATTACHES)); (void) Batch_Send (NULL); return TRUE; } static int LOCALFUNC FTSC_recvmail (int outbound_session) { char fname[80]; char fname1[80]; char fname2[80]; struct _pkthdr tmppkt; FILE *fp, *fp1; int done; int i = 0; int j; int logit = TRUE; char *starting_inbound; status_line (MSG_TXT (M_RECV_MAIL)); if (!CARRIER) { status_line (MSG_TXT (M_NO_CARRIER)); CLEAR_INBOUND (); return (1); } XON_DISABLE (); done = 0; /* If we don't want to pickup stuff */ if (no_pickup) { status_line (MSG_TXT (M_NO_PICKUP)); SENDBYTE (CAN); } else { status_line (" %s %s", MSG_TXT (M_INBOUND), MSG_TXT (M_MAIL_PACKET)); /* Invent a dummy name for the packet */ invent_pkt_name (fname1); /* Receive the packet with special netmail protocol */ CLEAR_INBOUND (); starting_inbound = CURRENT.sc_Inbound; if (Xmodem_Receive_File (CURRENT.sc_Inbound, fname1) == 0) { got_packet = 1; } (void) sprintf (fname, "%s%s", starting_inbound, fname1); /* Check the password if there is one */ if ((!remote_capabilities) && (!outbound_session)) i = n_getpassword (&remote_addr); if (i < 0) { status_line (MSG_TXT (M_NUISANCE_CALLER)); LOWER_DTR (); /* Hang up right now */ goto bad_caller; } if (i != 0) { if (remote_password != NULL) { got_packet = 0; if ((fp = fopen (fname, rb_plus)) == NULL) { (void) got_error (MSG_TXT (M_OPEN_MSG), fname); status_line (MSG_TXT (M_PWD_ERR_ASSUMED)); return (1); } if (fread (&tmppkt, 1, sizeof (struct _pkthdr), fp) < sizeof (struct _pkthdr)) { (void) got_error (MSG_TXT (M_OPEN_MSG), fname); status_line (MSG_TXT (M_PWD_ERR_ASSUMED)); (void) fclose (fp); return (1); } (void) fclose (fp); if (n_password ((char *) (tmppkt.password), remote_password, &logit)) { bad_caller: (void) strcpy (fname1, fname); j = (int) strlen (fname) - 3; (void) strcpy (&(fname[j]), "Bad"); if (rename (fname1, fname)) { status_line (MSG_TXT (M_CANT_RENAME_MAIL), fname1); } else { status_line (MSG_TXT (M_MAIL_PACKET_RENAMED), fname); } return (1); } } got_packet = 1; } /* * See if things changed after the fact. If so, we want to move * the mail packet from the non-secured directory into the * secured one. This is slightly tricky. Start with a simple rename * and if that doesn't work (it might not if we're spanning drives) * do a simple copy/unlink. * * Steal resources such as 'done' and 'Secbuf' wherever that makes sense. */ if (strcmp (starting_inbound, CURRENT.sc_Inbound) != 0) { (void) strcpy (fname2, CURRENT.sc_Inbound); (void) strcat (fname2, fname1); /* Try the easy case first. A straight rename. */ done = 1; if (rename (fname2, fname)) { /* If we get here, the straight rename didn't work. Let's * do a copy. Use Secbuf since while we are here, we're * not doing any file transfers. */ done = 0; /* default is failure till files are open */ if ((fp = fopen (fname, rb_plus)) == NULL) { (void) got_error (MSG_TXT (M_OPEN_MSG), fname); } else if ((fp1 = fopen (fname2, write_binary)) == NULL) { (void) got_error (MSG_TXT (M_OPEN_MSG), fname2); } else { /* Here both packets are open */ /* Steal Secbuf because nobody's using it now */ done = 1; /* default is success now */ while ((j = fread (Secbuf, 1, WAZOOMAX, fp)) > 0) { if (fwrite (Secbuf, j, 1, fp1) != 1) { (void) got_error (MSG_TXT (M_WRITE_MSG), fname2); done = 0; /* only possible failure = write err */ break; } } (void) fclose (fp1); if (done == 0) /* Figure out which file to delete */ (void) unlink (fname2); else (void) unlink (fname); } } if (done == 0) status_line (MSG_TXT (M_CANT_RENAME_MAIL), fname); else status_line (MSG_TXT (M_MAIL_PACKET_RENAMED), fname2); } /* * If this was an inbound session, we need to set up the * node flags for the node. */ got_mail = got_packet; if (!outbound_session) { if (flag_file (TEST_AND_SET, &remote_addr, 1)) return (1); called_addr = remote_addr; } done = 0; /* Now receive the files if possible */ status_line (" %s %s", MSG_TXT (M_INBOUND), MSG_TXT (M_FILE_ATTACHES)); done = Batch_Receive (CURRENT.sc_Inbound); } status_line (" %s %s %s", MSG_TXT (M_END_OF), MSG_TXT (M_INBOUND), MSG_TXT (M_FILE_ATTACHES)); CLEAR_INBOUND (); return (done); } static int FTSC_callback (char *sptr) { net_problems = Batch_Send (sptr); if (net_problems != 0) { net_problems = 1; return FALSE; } return TRUE; } static int FTSC_time (long filesize) { long ltemp; ltemp = filesize * 10L / cur_baud.rate_value * 100L / 94L; return (ltemp < 20L) ? 20 : (int) ltemp; }