
/*
 *  MBFILE.C - 1/20/89
 */

#include "mb.h"

#ifdef MCH_AMIGA
extern char passchr,vhfstream,hfstream;
extern short debug;
#endif

word filesize;
char *fm;
DIRPATH *dphd;

/*
 *  Prepend path given by opt2 to file spec given by p.
 */

DIRPATH *getdir(p)
char *p;
{
  register DIRPATH *dp;

  for (dp = dphd; dp isnt NULL; dp = dp->next) if (dp->id is port->opt2)
  {
    strcpy(port->line, dp->path);
#ifdef MCH_AMIGA
      /* Insert a '/' if sysop didn't specify it in the config file */
      if(*p && (port->line[strlen(port->line)-1] != '/'))
         strcat(port->line,"/");
#endif
    strcat(port->line, p);
    if (!(port->mode & p_sysop)) for (; *p; p++)
      if ((*p is ':') or (*p is '\\') or (*p is '/'))
      { port->msg = mcant; return NULL; }
    return dp;
  }
  port->msg = mndir;
  return NULL;
}

/*
 *  Display the directory paths.
 */

shpaths()
{
  register DIRPATH *dp;
  int crcount = 1;

  sprintf(port->line, "Use %c and directory ID:\n", port->opt1);
  outstr(port->line);
  for (dp = dphd; dp isnt NULL; dp = dp->next)
  {
    ++crcount;
    sprintf(port->line, "%c%c %-34s", port->opt1, dp->id, dp->name);
    outstr(port->line);
    if (crcount % 2) outstr("\n");
  }
  outstr("\n");
}

/*
 *  Display directory.
 */

prtdir()
{
  DIRDEF dirdef;
  DIRENT *dp;

  register short gap, i, k, l, ndir;
#ifndef MCH_AMIGA
  register word totsize;
#else
  register long totsize;
#endif

  if (port->mode & ops)
  {
    if (port->opt2 is ' ')
    {
      if (port->flds is 1) { shpaths(); return; }
      strcpy(port->line, port->fld[1]);
    }
#ifndef MCH_AMIGA
    else if (getdir(port->fld[1]) is NULL) return;
#else
    else if(setdir(port->fld[1]) is NULL) return;
#endif
  }
  else
  {
    if (port->opt2 is ' ') { shpaths(); return; }
#ifndef MCH_AMIGA
    if (getdir(port->fld[1]) is NULL) return;
#else
    if(setdir(port->fld[1]) is NULL) return;
#endif
  }

  ndir = 0;
  dp = (DIRENT *)tmp->scr;

/*
 *  Get first directory entry.
 */

  if (!diropen(port->line, dp, &dirdef)) { port->msg = mfind; return; }

/*
 *  Get the rest of the directory entries.
 */

  while ((ndir < dirmax) and (dp->size >= 0))
  {
    ndir++;
    dirnext(++dp, &dirdef);
  }

/*
 *  Sort 'em.
 */

  sort(tmp->scr, ndir, sizeof(DIRENT), tmp->scr + (sizeof(DIRENT) * ndir));

/*
 *  Print 'em.
 */

  pgst(NULL);
  outchar('\n');
  totsize = 0;
  gap = (ndir + 2) / 3;
  for (i = 0; i < gap; i++)
  {
    if (pgck() is 'Q') break;
    for (l = 0, k = i; (l < 4) and (k < ndir); l++, k += gap)
    {
      totsize += tmp->dirent[k].size;
#ifndef MCH_AMIGA
      if (k isnt i) outstr(" | ");
#else
/* The | symbol could be the streamswitch char so check for it and
   pass it if necessary
*/
      if(k isnt i) {
         if(passchr && ((vhfstream == '|') || (hfstream == '|'))) {
            outchar(' ');
            outchar(passchr);
            outstr("| ");
         }
         else {
            outstr(" | ");
         }
      }
#endif
      sprintf (port->line,
        "%-12s %4uk", tmp->dirent[k].name, tmp->dirent[k].size);
      outstr(port->line);
    }
    outchar('\n');
  }
#ifndef MCH_AMIGA
  sprintf(port->line, "\n%uk of %uk used, %uk free.\n\n",
#else
   /* %lu makes no difference in Manx */
  sprintf(port->line, "\n%ldk of %ldk used, %ldk free.\n\n",
#endif
    totsize, dirdef.size, dirdef.free);
  outstr(port->line);
}

/*
 *  Output a line from the help file.
 */

helpo()
{
  if ((*port->line isnt '!') or (port->user->options & u_sysop))
  { if (*port->line is '!') *port->line = ' '; outstr(port->line); }
}

/*
 *  Find specific subject header in file.
 */

helps()
{
  register short found = false;

  while (!found and (fgets(port->line, linelen, port->fl) isnt NULL))
    if ((port->line[0] is port->opt1) and
        (port->line[2] is port->opt2)) found = true;

  if (!found)
  {
    sprintf(port->line, "\nNo help for - %c\n\n", port->opt2);
    port->msg = port->line;
    return;
  }

  found = false;
  while (!found and (fgets(port->line, linelen, port->fl) isnt NULL))
  {
    found = ((*port->line is '#') or (*port->line is '?'));
    if (!found) helpo();
  }
}

/*
 *  Dump all the help information.
 */

helpa()
{
  register short ok = false;

  while ((fgets(port->line, linelen, port->fl) isnt NULL))
  {
    if ((*port->line is '#') or (*port->line is '?'))
    {
      ok = (*port->line is port->opt1);
    }
    else if (ok) helpo();
  }
}

/*
 *  User wants help.
 */

help()
{
  if (port->flds is 1) port->opt2 = '_'; else port->opt2 = *port->fld[1];
  if (port->opt1 is 'H') port->opt1 = '#';

  if ((port->fl = fopen(helpfile, "r")) is NULL) { port->msg = mfind; return; }

  if (port->opt2 is '?') helpa(); else helps();

  fclose(port->fl);
}

/*
 *  N command, rename a file.
 */

renfil()
{
  register int fl;

  if ((fl = open(port->fld[1], O_RDONLY)) < 0)
    { nofile(port->fld[1]); return; }

  close(fl);

  if ((fl = open(port->fld[2], O_RDONLY)) >= 0)
    { close(fl); port->msg = mexst; }
  else rename (port->fld[1], port->fld[2]);
}

/*
 *  Z command, delete a file.
 */

kilfil()
{
  if (port->opt2 is ' ') strcpy(port->line, port->fld[1]);
  else if (getdir(port->fld[1]) is NULL) return;

  if (!unlink(port->line)) port->msg = mdone; else nofile(port->line);
}

/*
 *  Are the two files in the same directory?
 */

samedir(t, f)
char *t, *f;
{
  register char *te, *fe;

/*
 *  Are they on the same device?
 */

  te = strchr(t, ':');
  fe = strchr(f, ':');
  if ((te isnt NULL) or (fe isnt NULL))
  {
    if ((te - t) isnt (fe - f)) return false;
    if (!matchn(te, fe, (int)(fe - f) + 1)) return false;
  }

/*
 *  Are they in the same subdirectory on the device?
 */

#ifndef MCH_AMIGA
  te = strrchr(t, '\\');
  fe = strrchr(f, '\\');
#else
  te = strrchr(t, '/');
  fe = strrchr(f, '/');
#endif
  if ((te is NULL) and (fe is NULL)) return true;
  if ((te - t) isnt (fe - f)) return false;
  return matchn(t, f, (int)(fe - f) + 1);
}

/*
 *  Copy a file.
 */

copy(f, t, h)
char *f, *t;
int h;
{
  register int n, in, out;

  filesize = 0;

  if ((in = open(f, O_RDONLY | O_BINARY)) < 0) return false;

  out = open(t, O_CREAT | O_RDWR | O_BINARY, pmode);
  if (h) lseek(out, (long)RECSIZE, 0);

  while ((n = read(in, tmp->scr, scrmax)) > 0)
  { filesize += n; write (out, tmp->scr, n); }

  close(in);
  close(out);
  return true;
}

/*
 *  V command: copy a file.
 */

copfil()
{
  register int n;

  if ((n = open(port->fld[2], O_RDONLY | O_BINARY)) >= 0)
  { port->msg = mexst; close(n); return; }

  if ((n = open(port->fld[1], O_RDONLY | O_BINARY)) < 0)
    { nofile(port->fld[1]); return;}

  close(n);
  copy(port->fld[1], port->fld[2], false);
}

/*
 *  Upload, common code.
 */

uload(tname)
char *tname;
{
  register char *tp;
  register PORTS *p;

  p = port;

  if ((p->fl = fopen(tname, "w")) is NULL) { p->msg = mcant; return; }

  filesize = 0;
  while (true)
  {
    while(!getdat());

/*
 *  If user disconnected, timed out, or forced off, zap the file.
 */

    if (p->mode & gone)
    {
      fclose(p->fl);
      unlink(tname);
      return;
    }

    if ((tp = strchr(p->line, cpmeof)) is NULL)
    {
      filesize += strlen(p->line);
      fputs(p->line, p->fl);
    }
    else
    {
      if (tp isnt p->line)
      {
        *tp++ = '\n';
        *tp   = '\0';
        filesize += strlen(p->line);
        fputs(p->line, p->fl);
      }
      fclose(p->fl);
      return;
    }
  }
}

/*
 *  Upload a file, from local console and remote sysop.
 */

uloadl()
{
  if ((port->fl = fopen(port->fld[1], "r")) isnt NULL)
    { port->msg = mexst; fclose(port->fl); return; }
  prtx(fm);
  uload(port->fld[1]);
}

/*
 *  Upload a file, from logged in user.
 */

uloadr()
{
  register DIRPATH *dp;

  if (port->opt2 is ' ') { shpaths(); return; }
  if ((dp = getdir(port->fld[1])) is NULL) return;
  if (!(dp->flags & dp_upload)) { port->msg = mcant; return; }
  if (!(port->priv & p_upload)) { port->msg = mcant; return; }
  if ((port->fl = fopen(port->line, "r")) isnt NULL)
    { port->msg = mexst; fclose(port->fl); return; }
  log('F', 'U', ' ', port->line);
  prtx(fm);
  uload(port->line);
}

/*
 *  Download, common code.
 */

dload(fname)
char *fname;
{
#ifdef MCH_AMIGA
   register char *cp;
#endif
  if ((port->fl = fopen(fname, "r")) is NULL) { nofile(fname); return; }

  while(fgets(tmp->scr, scrmax, port->fl) isnt NULL)
  {
     if (chkdis()) break;
#ifdef MCH_AMIGA
      cp = tmp->scr;
      while(*cp) {
         /* insert the pass character for stream characters */
         if((*cp == vhfstream) && passchr) {
            outchar(passchr);
         }
         else {
            if((*cp == hfstream) && passchr) {
               outchar(passchr);
            }
         }
         /* Don't send fancy ctl chars such as ^Q ^S etc.*/
         if(*cp < 0)continue;
         if((*cp == '\021') || (*cp == '\023'))continue;
         outchar(*cp++);
      }
#else
      outstr(tmp->scr);
#endif
  }
  fclose (port->fl);
}

/*
 *  Display the "info" file.
 */

dloadi()
{
  dload(infofile);
}


/*
 *  Download a file, by logged in user.
 */

dloadr()
{
  register DIRPATH *dp;

  if (port->opt2 is ' ') { shpaths(); return; }
  if ((dp = getdir(port->fld[1])) is NULL) return;
  if (!(dp->flags & dp_dnload)) { port->msg = mcant; return; }
  if (!(port->priv & p_dnload)) { port->msg = mcant; return; }
  log('F', 'D', ' ', port->line);
  dload(port->line);
}

/*
 *  Download a file, by remote sysop.
 */

dloads()
{
  if (port->opt2 is ' ')
  {
    if (port->flds is 1) { shpaths(); return; }
    strcpy(port->line, port->fld[1]);
  }
  else if (getdir(port->fld[1]) is NULL) return;

  log('F', 'D', ' ', port->line);
  dload(port->line);
}

/*
 *  Download a file, by local console.
 */

dloadl()
{
#ifdef MCH_AMIGA
   register char *cp;
#endif
  register PORTS *tp;

  if (port->opt2 is ' ') port->opt2 = 'L';
  if ((tp = findport(port->opt2)) is NULL) { port->msg = mnport; return; }
  if ((cport->fl = fopen(cport->fld[1], "r")) is NULL)
    { nofile(cport->fld[1]); return; }

  ioport(tp);
  pgst(NULL);
  while(fgets(tmp->scr, scrmax, cport->fl) isnt NULL)
  {
#ifdef MCH_AMIGA
      cp = tmp->scr;
      while(*cp) {
         /* insert the pass character for stream characters */
         if((*cp == vhfstream) && passchr) {
            outchar(passchr);
         }
         else {
            if((*cp == hfstream) && passchr) {
               outchar(passchr);
            }
         }
         /* Don't send fancy ctl chars such as ^Q ^S etc.*/
         if(*cp < 0)continue;
         if((*cp == '\021') || (*cp == '\023'))continue;
         outchar(*cp++);
      }
#else
      outstr(tmp->scr);
#endif
    if (pgck() is 'Q') break;
  }
  fclose (cport->fl);
  if (tp isnt cport) term(tp);
  ioport(cport);
}

/*
 *  Move killed mail over to a subdirectory if it exists. NTS for all
 *  type 'T' and 'S' mail. Sysop's call for all to and from the sysop
 *  and KILL for non-bbs mail.
 */

arcmsg()
{
  register int n, in, out;
  static char bbs[8];
  FILE *index;

  msgfile(port->line, port->mmhs->number);
  strcpy(bbs, "KILL");

  if (*port->mmhs->bbs isnt ' ')
    unbl(bbs, port->mmhs->bbs, ln_call);
  if ((matchn(port->mmhs->to, cport->user->call, ln_call)) or
    (matchn(port->mmhs->from, cport->user->call, ln_call)))
    unbl(bbs, cport->user->call, ln_call);
  if ((port->mmhs->type is 'T') or (port->mmhs->type is 'S'))
    strcpy(bbs, "NTS");
  if (port->mmhs->stat & m_busy) strcpy( bbs, "BUSY");

  while (true)
  {
#ifndef MCH_AMIGA
    sprintf(port->cmd, "%s%s\\%u", msgdir, bbs, port->mmhs->number);
#else
    sprintf(port->cmd, "%s%s/%u", msgdir, bbs, port->mmhs->number);
#endif

    if ((out = open(port->cmd, O_CREAT | O_RDWR | O_BINARY, pmode)) < 0)
    {
      if((matchn(bbs, "KILL", 4)) or (matchn(bbs, "BUSY", 4)))
      {
         unlink(port->line);
         outstr(" Deleted\n");
         return;
      }
      strcpy(bbs, "KILL");
    }
    else break;
  }
  makehdr();
#ifndef MCH_AMIGA
  sprintf(port->cmd, "%s%s\\INDEX", msgdir, bbs);
#else
  sprintf(port->cmd, "%s%s/INDEX", msgdir, bbs);
#endif
  if ((index = fopen(port->cmd, "a+")) isnt NULL)
  {
    fprintf( index, "%s", tmp->scr);
    fclose(index);
  }
  remnl (tmp->scr);
  strcat (tmp->scr, "\r\n");

  if (*port->mmhs->bid isnt ' ') {
    sprintf(port->cmd, "   BID: -%12.12s\r\n", port->mmhs->bid);
    strcat(tmp->scr, port->cmd);
    }
  write(out, tmp->scr, strlen(tmp->scr));

  in = open(port->line, O_RDONLY | O_BINARY);
  lseek(in, (long)RECSIZE, 0);

  while ((n = read(in, tmp->scr, scrmax)) > 0)
    write( out, tmp->scr, n);

  close(out);
  close(in);
  unlink(port->line);
  sprintf(port->line," Copied to %s\n", bbs);
  outstr(port->line);
}

