/* funcs.c */

/* Some replacement routines for the amiga */
#include <stdio.h>
#include <time.h>
/* for Execute call at the end */
#include <libraries/dos.h>
#include "mb.h"
extern short debug;
extern char l_date[7], l_time[5],tmpstr[];
extern char optflags[];
extern char passchr, vhfstream,hfstream;
extern char *inittnc();
#define true 1
#define false 0

extern char hostport;
/*
 * Force some commands at the TNC
 */

ioinit()
{
   register char *p;
   char tnc_on[12];

   if(hostport == 'A')strcpy(&tnc_on[0],"tnc.on");
   else               sprintf(&tnc_on[0],"tnc.on.%c",hostport);
/*
   Don't do this here. open the device on each beep. It's in beep() now.
   initbeep();
*/
   if(p = inittnc(&tnc_on[0],1))ttputs(p);
}

/* This is supposed to turn off interrupts but since it is the last
   thing called by done() in mb.c I use it to do any cleanup for the
   amiga
*/
iooff()
{
   register char *p;
   char tnc_off[12];

   if(hostport == 'A')strcpy(&tnc_off[0],"tnc.off");
   else               sprintf(&tnc_off[0],"tnc.off.%c",hostport);
   if(p = inittnc(&tnc_off[0],1))printf(p);
/*   donebeep(); */
}


/*
 *  Fill the globals "l_date", "l_time", and "dt" with
 *  the current date and time by reading the system clock.
 *  l_time is HHMM, l_date is YYMMDD.
 *  dt has the format of a directory item date/time.
 */
extern short timezone;
int cursecs;
curtim()
{
   struct tm *ct;
   time_t ltime;

   time(&ltime);
   ct = localtime(&ltime);
   cursecs = ct->tm_sec;

   sprintf(l_time, "%02d%02d", ct->tm_hour, ct->tm_min);
   sprintf(l_date, "%02d%02d%02d", ct->tm_year, ct->tm_mon + 1, ct->tm_mday);
   /* month returned by localtime is 0-11 */

   /* Change the local time into UTC and generate date/time string for
      initmsg and cremsg which store the date/time in UTC.
      Adjust for daylight savings - dst() returns the number of minutes of
      time required to adjust local time to UTC.
   */
   ltime += dst(timezone)*60L;
   ct = localtime(&ltime);
   sprintf(z_time, "%02d%02d", ct->tm_hour, ct->tm_min);
   sprintf(z_date, "%02d%02d%02d", ct->tm_year, ct->tm_mon + 1, ct->tm_mday);
}
long gettime()
{
   long cur[3],now;
   DateStamp((struct DateStamp *)&cur[0]);
   now = cur[0]*24*60*60;
   now += cur[1]*60;
   now += cur[2]/50;
   return(now);
}

/* Timestamp output to the console - mostly for debugging */
t_stamp()
{
   extern long gettime();
   char tstring[7];
   long cur[3];

return;
   DateStamp((struct DateStamp *)&cur[0]);
   sprintf(tstring,"%2ld:%02ld ",cur[1]/60,cur[1]%60);
   ttputs(tstring);
}

/*
 *  Check a timer.
 */

chktmr(l)
long l;
{
   extern long gettime();
   long cur[3];

   if (gettime() > l) return (false);
   return (true);
}

/*
 *  Set a timer.
 */

settmr(l, i)
long *l;
int i;
{
   extern  long gettime();
   *l = gettime() + (long)i;
}

char port_flag,cmnd_flag;
putp_flag(c)
char c;
{
   port_flag = c;
}
getp_flag()
{
   return(port_flag);
}
putc_flag(c)
char c;
{
   cmnd_flag = c;
}
getc_flag()
{
   return(cmnd_flag);
}
#ifdef NEWPASS
int numpass,pwdint[MAXPASS];
pass()
{
   char tmpnum[MAXPASS];

   register char *p;
   register int i,j;
   int sum;
   /* don't do the thing at all if there's no integers to use
      or there was an error in reading the list in mbinit
   */
   if(numpass == 0)return false;
   sum = 0;
   /* clear tmpnum array
      It is used to ensure that four distinct integers are
      produced.
   */
   for(p = &tmpnum[0];p<&tmpnum[MAXPASS];p++)*p = 0;
   /* get four distinct random integers to generate the password */
   for(i = 0;i < 4;i++) {
      do {
         j = ((rand() & 0x7fff) >> 4) % numpass;
         /* make sure rand produces four distinct numbers otherwise
            it weakens the password scheme
         */
         if(tmpnum[j])continue;
         tmpnum[j] = 1;
         sum += pwdint[j];
         sprintf(tmpstr, " %2d", j+1);
         outstr(tmpstr);
         break;
      }while(1);
   }
   outstr("\n");
   getdat();
   if(atoi(port->line) == sum)return true;
   return false;
}
/*
   New and more secure password function called from mbinit to set up
   the password array.
*/
initpwd()
{
   register int i,j;
   register char *p;
   char *rdstr();
   p = rdstr();
   while(*p == ' ')p++;
   for(i=0;i<MAXPASS;i++) {
      if((pwdint[i] = atoi(p)) <= 0) {
         return(0);
      }
      while(*p && (*p >= '0') && (*p <= '9'))p++;
      if((*p == 0) || (*p == '\n') || (*p == '\r')){
         if(i+1 < MINPASS)return;
         return(i+1);
      }
      while(*p == ' ')p++;
      /* a backslash at the end of a line indicates more integers
         on the next line.
      */
      if(*p == '\\') {
         p = rdstr();
         while(*p == ' ')p++;
         continue;
      }
   }
   return(i+1);
}
#endif
donefunc()
{
   done(0);
}
titles()
{
   window_title(mfhs->next_msg-1,mfhs->count);
}
funlink(file)
UBYTE  *file;
{
   return(DeleteFile(file));
}
replace_bbs()
{
   int user_num;
   USER ubuf;
   /* the extra tests here try to avoid the expense of the disk I/O
      required if we must look in the user file
   */
   if(!optflags[1])return(1);
   if(!iscall(port->mmhs->to))return(2);
   if((user_num = finduser(port->mmhs->to)) == 0)return(3);
   read_rec(ufl,user_num,&ubuf);
   /* Is there a call in the home_bbs ? */
   if(ubuf.home_bbs[0] == ' ')return(4);
   strncpy(port->mmhs->bbs,&ubuf.home_bbs[0],ln_call);
   /* This new call may have a hierarchical address */
   chkhier();
   return(0);
}
do_system(cmd)
UBYTE *cmd;
{
   /* Using Open("*",...) to get a handle on the window does not work.
      It gives a handle to the CLI that started up CBBS ... NOT the
      window that CBBS is in ... so the output goes to the wrong window
      anyway
   */
   long Execute(),Open();
   if(Execute(cmd,0L,0L)) {
      return(0);
   }
   return(1);
}

/* Clean up a string before it is sent to the TNC or to the screen.
   The input string to this routine must NOT be tmpstr.
*/

str_search(str)
unsigned char *str;
{
   register unsigned char *cp,*tp;
   short in_out;

   cp = str;
   /* If the TNC is in transparent mode, then don't change anything */
   if(port->flags & p_trans) {
      outstr(cp);
      return;
   }
   /* Is this going to the console or to TNC? */
   in_out = (port->dev != p_console);
   tp = (unsigned char *) &tmpstr[0];
   while(*cp) {
      /* insert the pass character for stream characters */
      if(in_out && passchr) {
         if((*cp == (unsigned char) vhfstream) ||
            (*cp == (unsigned char) hfstream)) {
            *tp++ = passchr;
            *tp++ = *cp++;
            continue;
         }
      }
      if((*cp >= ' ') && (*cp <= 0176)) {
         *tp++ = *cp++;
         continue;
      }
      /* Allow BEL HT CR and ^Z through. All others are omitted
      */
      switch(*cp) {
      case  7:    /* BEL */
      case 26:    /* Control -Z */
         if(!in_out)break;
      case  9:    /* TAB */
      case 13:    /* CR */
      case 10:    /* LF */
         *tp++ = *cp;
         break;
      default:
         *tp++ = 0177;
      }
      cp++;
   }
   *tp = 0;
   outstr(tmpstr);
}

/* Replacement command parser. This fixes up the problem with THEBOX
   which sends a command of the form:
   sb amsat @dl <df3ix $bid #7
   where CBBS expects to see
   sb amsat @ dl < df3ix $bid #7
*/
parse()
{
   register char *in, *out;
   register short i;
   for(i = 0; i < maxflds;i++) {
      port->fld[i] = nullstr;
   }
   in  = port->line;
   out = port->cmd;
   port->flds = 0;

   /* Remove the high order bit from commands */
   while(*in) {
      if(*in != 0200)
         *in = *in & 0177;
      else
         *in = ' ';
      in++;
   }
   in  = port->line;
   while(*in && (port->flds < maxflds) && (out < (port->cmd + cmdlen - 1))) {
      /* Process each string
         Start by removing leading blanks, tabs etc.
         Note that when this gets to the end of the line this will
         skip by the linefeed too
      */
      while(*in && (*in <= ' '))in++;
      if(*in == 0)break;
      port->fld[port->flds++] = out;
      /* Now process the field itself.
         If it begins with one of the special characters @ or < then 
         treat this as though it has a space after it, even if it
         doesn't.
         If it begins with " then look for the trailing " and store it
         all as one string. This fix allows a tweak to the 'L' command.
      */
      switch(*in) {
      case '@':
      case '<':
         *out++ = *in++;
         break;
      case '"':
         /*
            Allow a quoted string as an argument.
            The quotes are stored in the output argument string.
            If the trailing quote is missing then just store a
            null and don't try to copy the linefeed
         */
         *out++ = *in++;
         while(*in && (*in != '"') && (*in != '\n')
                   && (out < (port->cmd + cmdlen - 1)))
            *out++ = toupper(*in++);
         if(*in == '"')
            *out++ = *in++;
         break;
      default:
         while(*in && (*in > ' ') && (out < (port->cmd + cmdlen - 1))) {
            /*
               If the user types ve5va@n8gtc then split it up.
            */
            if((port->flds == 2) && (*in == '@'))break;
            *out++ = toupper(*in++);
         }
         break;
      }
      *out++ = 0;
   }
   *out = '\0';

   port->opt1 = *port->fld[0];
   port->opt2 = *(port->fld[0] + 1);
   if(!port->opt2)
      port->opt2 = ' ';
}

/* Send Reply command */
int srcmd_flag = 0;
srpmsg()
{
/* Until this command works properly send out a 'Sorry' message */
outstr("Sorry - this command has been removed until it works properly\n");
srcmd_flag = 0;
last_msg.type = 0;
return;
/* Comment out this code until it works properly.
   if((last_msg.type == 0) || (port->flds != 1)) {
      port->msg = mwhat;
      return;
   }

   sprintf(port->line,"SP %s %s%s",last_msg.from,(last_msg.bbs[0] ? "@":""),
                  last_msg.bbs);
   outstr(port->line);
   outstr("\n");
   srcmd_flag = 1;
   parse();
   sndmsg();
   last_msg.type = 0;
   srcmd_flag = 0;
*/
}
/* This next routine must not use tmpstr */
prt_subj()
{
   if(toupper(last_msg.title[0]) != 'R' ||
      toupper(last_msg.title[1]) != 'E' ||
      last_msg.title[2] != ':') {
      /* Prefix the title with "Re:" if there isn't already one there */
      strncpy(port->mmhs->title,"Re: ",4);
      strncpy(&port->mmhs->title[4],last_msg.title,mhtitl-4);
   }
   else strncpy(port->mmhs->title,last_msg.title,mhtitl);
   outstr("Subject: \n");
   outstr(port->mmhs->title);
   outstr("\n");
}

/* Create file names based on the port name */
portfile()
{
   if(hostport == 'A')return;
   fchange(hrdfile);
   fchange(monfile);
   fchange(lgfile);
/*   fchange(fwdfile);  */
}
fchange(s)
char *s;
{
   register char *p;
   p = s;
   /* Find the null character at the end of the string */
   while(*p)p++;

   /* There's nothing in the string!! */
   if(p == s)return;

   /* Then backup until we find a period */
   while((p!=s) && (*p != '.'))p--;
   /* If there's no period, then add one */
   if(*p != '.') {
      while(*p)p++;
      *p = '.';
   }
   p++;
   *p++ = hostport;
   *p = 0;
}

test_bbs()
{
   FILE *fpi;
   char tmp_call[8];

   /* Check for unknown @BBS field - make sure tmpstr is non-null to start*/

   strcpy(tmpstr,msgdir);
   if((port->mmhs->bbs[0] != ' ') && !iscall(port->mmhs->bbs)) {
      unbl(tmp_call,port->mmhs->bbs,ln_call);
      strcat(tmpstr,tmp_call);
      strcat(tmpstr,".dis");
      if((fpi = fopen(tmpstr,"r")) == NULL) {
         unbl(tmpstr,port->mmhs->bbs,ln_call);
         return(1);
      }
      fclose(fpi);
   }
   return(0);
}

opchange()
{
   register char c;

   c = toupper(*port->fld[1]);
   if((c < 'A') || (c > 'J')) {
      port->msg = mwhat;
      return;
   }
   optflags[c-'A'] ^= 1;
   sprintf(tmpstr,"Option %c now %s\n",c,optflags[c-'A']?"ON":"OFF");
   ttputs(tmpstr);
}
