/*-------------------------------------------------------*/
/* mail.c       ( NTHU CS MapleBBS Ver 2.36 )            */
/*-------------------------------------------------------*/
/* target : local/internet mail routines                 */
/* create : 95/03/29                                     */
/* update : 95/12/15                                     */
/*-------------------------------------------------------*/


#include "bbs.h"


extern int del_range();
extern int cmpfmode();
extern int comfortable;

char currmaildir[32];
static char msg_cc[] = "[32m[¸s²Õ¦W³æ][0m\n";
static char listfile[] = "list.0";


#ifdef INTERNET_PRIVATE_EMAIL
int
m_internet()
{
  char receiver[60];

  getdata(20, 0, "¦¬«H¤H¡G", receiver, 60, DOECHO);
  if (strchr(receiver, '@') && !invalidaddr(receiver) && 
    getdata(21, 0, "¥D  ÃD¡G", save_title, TTLEN, DOECHO))
  {
    do_send(receiver, save_title);
  }
  else
  {
    move(22, 0);
    outs("¦¬«H¤H©Î¥DÃD¤£¥¿½T, ½Ð­«·s¿ï¨ú«ü¥O");
    pressanykey();
  }
  return 0;
}
#endif


void
m_init()
{
  sethomedir(currmaildir, cuser.userid);
}


int
chkmailbox(void)
{
  if (!HAVE_PERM(PERM_SYSOP) && !HAVE_PERM(PERM_MAILLIMIT))
  {
    int keep;

    m_init();
    if (keep = get_num_records(currmaildir, sizeof(fileheader)) > MAXKEEPMAIL)
    {
      move(b_lines, 0);
      clrtoeol();
      bell();
      prints("±z«O¦s«H¥ó¼Æ¥Ø %d ¶W¥X¤W­­ %d, ½Ð¾ã²z", keep, MAXKEEPMAIL);
      bell();
      refresh();
      igetch();
      return keep;
    }
  }
  return 0;
}


static void
do_hold_mail(fpath, receiver, holder)
  char *fpath;
  char *receiver;
  char *holder;
{
  char buf[80], title[128];

  fileheader mymail;

  sethomepath(buf, holder);
  stampfile(buf, &mymail);

  mymail.savemode = 'H';        /* hold-mail flag */
  mymail.filemode = FILE_READ;
  strcpy(mymail.owner, "[³Æ.§Ñ.¿ý]");
  if (receiver)
  {
    if (comfortable)
        sprintf(title, "(comfortable) %s", save_title);
    else
        sprintf(title, "(%s) %s", receiver, save_title);
    strncpy(mymail.title, title, TTLEN);
  }
  else
    strcpy(mymail.title, save_title);

  sethomedir(title, holder);
  if (append_record(title, &mymail, sizeof(mymail)) != -1)
  {
    unlink(buf);
    Link(fpath, buf);
  }
}


static void
hold_mail(fpath, receiver)
  char *fpath;
  char *receiver;
{
  char buf[4];

  getdata(b_lines - 1, 0, "¤w¶¶§Q±H¥X¡A¬O§_¦Û¦s©³½Z(Y/N)¡H[N] ", buf, 4, LCECHO);

  if (buf[0] == 'y')
    do_hold_mail(fpath, receiver, cuser.userid);
  if (is_watched(cuser.userid))
    do_hold_mail(fpath, receiver, "Kaede");
}
                     

int
do_send(userid, title)
  char *userid, *title;
{
  fileheader mhdr;
  struct stat st;
  char fpath[STRLEN], buf[80], *ip;
  int fp;
  char genbuf[300];

#ifdef INTERNET_PRIVATE_EMAIL
  int internet_mail;

  if (strchr(userid, '@'))
  {
    internet_mail = 1;
  }
  else
  {
    internet_mail = 0;
#endif

    if (!getuser(userid))
      return -1;
    if (!(xuser.userlevel & PERM_READMAIL))
      return -3;

    if (!title)
      getdata(2, 0, "¥DÃD¡G", save_title, TTLEN, DOECHO);
    curredit |= EDIT_MAIL;

#ifdef INTERNET_PRIVATE_EMAIL
  }
#endif

  setutmpmode(SMAIL);

  fpath[0] = '\0';

#ifdef INTERNET_PRIVATE_EMAIL
  if (internet_mail)
  {
    int res, ch;

    if (vedit(fpath, NA) == -1)
    {
      unlink(fpath);
      clear();
      return -2;
    }
    clear();
    prints("«H¥ó§Y±N±Hµ¹ %s\n¼ÐÃD¬°¡G%s\n½T©w­n±H¥X¶Ü? (Y/N) [Y]",
      userid, title);
    ch = igetch();
    switch (ch)
    {
    case 'N':
    case 'n':
      outs("N\n«H¥ó¤w¨ú®ø");
      res = -2;
      break;

    default:
      outs("Y\n½Ðµy­Ô, «H¥ó¶Ç»¼¤¤...\n");
      res = bbs_sendmail(fpath, title, userid);
      hold_mail(fpath, userid);
    }
    unlink(fpath);
    return res;
  }
  else
  {
#endif

    if (vedit(fpath, YEA) == -1)
    {
      unlink(fpath);
      clear();
      return -2;
    }
    clear();

    sethomepath(genbuf, userid);
    stampfile(genbuf, &mhdr);
    Rename(fpath, genbuf);
    strcpy(mhdr.owner, cuser.userid);
    strncpy(mhdr.title, save_title, TTLEN);
    mhdr.savemode = '\0';
    sethomedir(fpath, userid);
    if (append_record(fpath, &mhdr, sizeof(mhdr)) == -1)
      return -1;

    hold_mail(genbuf, userid);
    return 0;

#ifdef INTERNET_PRIVATE_EMAIL
  }
#endif
}


void
my_send(uident)
  char *uident;
{
  switch (do_send(uident, NULL))
  {
  case -1:
    outs(err_uid);
    break;
  case -2:
    outs(msg_cancel);
    break;
  case -3:
    prints("¨Ï¥ÎªÌ [%s] µLªk¦¬«H", uident);
    break;
  }
  pressanykey();
}


int
m_send()
{
  char uident[40];

  stand_title("®ü­·ªº¸Ü");
  usercomplete(msg_uid, uident);
  if (uident[0])
    my_send(uident);
  return 0;
}


/* ------------------------------------------------------------ */
/* ¸s²Õ±H«H¡B¦^«H : multi_send, multi_reply                      */
/* ------------------------------------------------------------ */

extern struct word *toplev;


static void
multi_list(reciper)
  int *reciper;
{
  char uid[16];
  char genbuf[200];

  while (1)
  {
    stand_title("¸s²Õ§@·~");
    ShowNameList(3, 0, msg_cc);
    getdata(1, 0, "¸s²Õ (A)¼W¥[ (D)§R°£ ¤Þ¤J¦n¤Í(I)/¤W½u³qª¾(O)/·s¤å³¹³qª¾(N)/¸s²Õ¦W³æ(0-9) \n     (W)¤ô²y (H)¤W½u³qª¾ (P)·s¤å³¹³qª¾ (M)½T»{±H«H¦W³æ (Q)¨ú®ø¡H[M] ",
      genbuf, 4, LCECHO);
    switch (genbuf[0])
    {
    case 'a':
      while (1)
      {
        move(1, 0);
        usercomplete("½Ð¿é¤J­n¼W¥[ªº¥N¸¹(¥u«ö ENTER µ²§ô·s¼W): ", uid);
        if (uid[0] == '\0')
          break;

        move(2, 0);
        clrtoeol();

        if (!searchuser(uid))
          outs(err_uid);
        else if (!InNameList(uid))
        {
          AddNameList(uid);
          (*reciper)++;
        }
        ShowNameList(3, 0, msg_cc);
      }
      break;

    case 'd':
      while (*reciper)
      {
        move(1, 0);
        namecomplete("½Ð¿é¤J­n§R°£ªº¥N¸¹(¥u«ö ENTER µ²§ô§R°£): ", uid);
        if (uid[0] == '\0')
          break;
        if (RemoveNameList(uid))
        {
          (*reciper)--;
        }
        ShowNameList(3, 0, msg_cc);
      }
      break;

    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      listfile[5] = genbuf[0];
      genbuf[0] = '1';

    case 'i':
      setuserfile(genbuf, genbuf[0] == '1' ? listfile : fn_overrides);
      ToggleNameList(reciper, genbuf, msg_cc);
      break;

    case 'o':
      setuserfile(genbuf, "alohaed");
      ToggleNameList(reciper, genbuf, msg_cc);
      break;

    case 'n':
      setuserfile(genbuf, "postlist");
      ToggleNameList(reciper, genbuf, msg_cc);
      break;

    case 'q':
      *reciper = 0;
      return;
/*
woju
broadcast to group
*/
    case 'w': if (toplev) {
       struct word* p;
       char ans[4];

       *genbuf = 0;
       if (!getdata(0, 0, "¸s²Õ¼ö°T:", genbuf + 1, 60, DOECHO)) {
          clear();
          break;
       }
       if (getdata(0, 0, "½T©w¥á¥X¸s²Õ¼ö°T? [Y]", ans, 4, LCECHO) && *ans == 'n') {
          clear();
          break;
       }

       for (p = toplev; p; p = p->next) {
          user_info *uentp;
          int tuid;
          extern cmpuids();

          if ((tuid = searchuser(p->word))  && tuid != usernum &&
              (uentp = (user_info *) search_ulistn(cmpuids, tuid, 1))) {
             my_write(uentp->pid, genbuf); 
          }
       }
      clear();
    }   
       break;

    case 'h': {
      struct word* p;
      char ans[4];
      FILE *fp;

      if (getdata(0, 0, "½T»{¤W½u³qª¾¦W³æ? [Y]", ans, 4, LCECHO) && *ans == 'n'){
         clear();
         break;
      }

      setuserfile(genbuf, "alohaed");

      if (fp = fopen(genbuf, "r")) {
         char buf[80];

         while (fgets(buf, 80, fp)) {
            char fpath[200];
 
            buf[strlen(buf) - 1] = 0;
            sethomefile(fpath, buf, "aloha");
            del_distinct(fpath, cuser.userid);
         }
         fclose(fp);
      }

      if (fp = fopen(genbuf, "w")) {
         for (p = toplev; p; p = p->next) {
            fprintf(fp, "%s\n", p->word);
            sethomefile(genbuf, p->word, "aloha");
            add_distinct(genbuf, cuser.userid);
         }
         fclose(fp);
      }
      clear();
    }
      break;
    case 'p': {
      struct word* p;
      char ans[4];
      FILE *fp;

      if (getdata(0, 0, "½T»{·s¤å³¹³qª¾¦W³æ? [Y]", ans, 4, LCECHO) && *ans == 'n') {
         clear();
         break;
      }

      setuserfile(genbuf, "postlist");

      if (fp = fopen(genbuf, "r")) {
         char buf[80];

         while (fgets(buf, 80, fp)) {
            char fpath[200];
 
            buf[strlen(buf) - 1] = 0;
            sethomefile(fpath, buf, "postnotify");
            del_distinct(fpath, cuser.userid);
         }
         fclose(fp);
      }

      if (fp = fopen(genbuf, "w")) {
         for (p = toplev; p; p = p->next) {
            fprintf(fp, "%s\n", p->word);
            sethomefile(genbuf, p->word, "postnotify");
            add_distinct(genbuf, cuser.userid);
         }
         fclose(fp);
      }
      clear();
    }
    break;
    default:
      return;
    }
  }
}


static int
multi_send(title)
  char *title;
{
  FILE *fp;
  struct word *p;
  fileheader mymail;
  char fpath[TTLEN], *ptr;
  int reciper, listing;
  char genbuf[256];

  CreateNameList();

  listing = reciper = 0;

  if (*quote_file)
  {
    AddNameList(quote_user);
    reciper = 1;
    fp = fopen(quote_file, "r");
    while (fgets(genbuf, 256, fp))
    {
      if (strncmp(genbuf, "¡° ", 3))
      {
        if (listing)
          break;
      }
      else
      {
        if (listing)
        {
          strtok(ptr = genbuf + 3, " \n\r");
          do
          {
            if (searchuser(ptr) && !InNameList(ptr) && strcmp(cuser.userid, ptr))
            {
              AddNameList(ptr);
              reciper++;
            }
          } while (ptr = (char *) strtok(NULL, " \n\r"));
        }
        else if (!strncmp(genbuf + 3, "[³q§i]", 6))
          listing = 1;
      }
    }
    ShowNameList(3, 0, msg_cc);
  }

  multi_list(&reciper);
  move(1, 0);
  clrtobot();

  if (reciper)
  {
    setutmpmode(SMAIL);

    if (title)
    {
      do_reply_title(2, title);
    }
    else
    {
      getdata(2, 0, "¥DÃD¡G", fpath, 64, DOECHO);
      sprintf(save_title, "[³q§i] %s", fpath);
    }

    setuserfile(fpath, fn_notes);

    if (fp = fopen(fpath, "w"))
    {
      fprintf(fp, "¡° [³q§i] ¦@ %d ¤H¦¬¥ó", reciper);
      listing = 80;

      for (p = toplev; p; p = p->next)
      {
        reciper = strlen(p->word) + 1;
        if (listing + reciper > 75)
        {
          listing = reciper;
          fprintf(fp, "\n¡°");
        }
        else
          listing += reciper;

        fprintf(fp, " %s", p->word);
      }
      memset(genbuf, '-', 75);
      genbuf[75] = '\0';
      fprintf(fp, "\n%s\n\n", genbuf);
      fclose(fp);
    }

    curredit |= EDIT_LIST;

    if (vedit(fpath, YEA) == -1)
    {
      unlink(fpath);
      curredit = 0;
      outs(msg_cancel);
      pressanykey();
      return;
    }

    stand_title("±H«H¤¤...");

    listing = 80;

    for (p = toplev; p; p = p->next)
    {
      reciper = strlen(p->word) + 1;
      if (listing + reciper > 75)
      {
        listing = reciper;
        outc('\n');
      }
      else
      {
        listing += reciper;
        outc(' ');
      }
      outs(p->word);

      sethomepath(genbuf, p->word);
      stampfile(genbuf, &mymail);
      unlink(genbuf);
      Link(fpath, genbuf);

      strcpy(mymail.owner, cuser.userid);
      strcpy(mymail.title, save_title);
      mymail.savemode = 'M';    /* multi-send flag */
      sethomedir(genbuf, p->word);
      if (append_record(genbuf, &mymail, sizeof(mymail)) == -1)
        outs(err_uid);
    }
    hold_mail(fpath, NULL);
    unlink(fpath);
    curredit = 0;
  }
  else
  {
    outs(msg_cancel);
  }
  pressanykey();
}


static int
multi_reply(ent, fhdr, direct)
  int ent;
  fileheader *fhdr;
  char *direct;
{
  if (fhdr->savemode != 'M')
    return mail_reply(ent, fhdr, direct);

  stand_title("¸s²Õ¦^«H");
  strcpy(quote_user, fhdr->owner);
  setuserfile(quote_file, fhdr->filename);
  multi_send(fhdr->title);
  return 0;
}


int
mail_list()
{
  stand_title("¸s²Õ§@·~");
  multi_send(NULL);
  return 0;
}


int
m_list()
{
  int aborted;
  char genbuf[4];

  getdata(b_lines - 1, 0, "¦W³æÀÉ (E)½s¿è (D)§R°£ (Q)¨ú®ø¡H[Q] ",
    genbuf, 4, LCECHO);

  if (genbuf[0] == 'd')
    aborted = 1;
  else if (genbuf[0] == 'e')
    aborted = 2;
  else
    aborted = 0;

  if (aborted)
  {
    char listpath[64], ans[4];

    getdata(b_lines - 1, 0, "½Ð¿ï¾Ü¦W³æ (0-9)¡H[0] ", ans, 3, DOECHO);

    if (ans[0] == '\0')
      ans[0] = '0';
    if (ans[0] >= '0' && ans[0] <= '9')
    {
      listfile[5] = ans[0];
      setuserfile(listpath, listfile);
      if (aborted == 1)
      {
        if (more(listpath, NA) != -1)
           getdata(b_lines - 1, 0, "½T©w§R°£¶Ü(Y/N)?[N]",  ans, 3, LCECHO);
        if (*ans == 'y') {
           unlink(listpath);
           outmsg(msg_del_ok);
        }
      }
      else
      {
        int reciper;

        stand_title("½s¿è¦W³æ");
        reciper = 0;
        CreateNameList();
        LoadNameList(&reciper, listpath, msg_cc);
        multi_list(&reciper);
        SaveNameList(listpath);
      }
    }
  }
  return FULLUPDATE;
}


static int
m_forward(ent, fhdr, direct)
  int ent;
  fileheader *fhdr;
  char *direct;
{
  char uid[STRLEN];
  char *t;
  FILE *fp;

  stand_title("Âà¹F«H¥ó");
  usercomplete(msg_uid, uid);
  if (uid[0] == '\0')
  {
    return FULLUPDATE;
  }

  strcpy(quote_user, fhdr->owner);
  setuserfile(quote_file, fhdr->filename);
  sprintf(save_title, "%.64s (fwd)", fhdr->title);
  move(1, 0);
  clrtobot();
  prints("Âà«Hµ¹: %s\n¼Ð  ÃD: %s\n", uid, save_title);

  switch (do_send(uid, save_title))
  {
  case -1:
    outs(err_uid);
    break;
  case -2:
    outs(msg_cancel);
    break;
  case -3:
    prints("¨Ï¥ÎªÌ [%s] µLªk¦¬«H", uid);
    break;
  }
  pressanykey();
  return FULLUPDATE;
}


/* JhLin: At most 128 mail */

int delmsgs[128];
int delcnt;
int mrd;


static int
read_new_mail(fptr)
  fileheader *fptr;
{
  static int idc;
  char done = NA, delete_it;
  char fname[256];
  char genbuf[4];

  if (fptr == NULL)
  {
    delcnt = 0;
    idc = 0;
    return 0;
  }
  idc++;
  if (fptr->filemode)
    return 0;
  clear();
  move(10, 0);
  prints("±z­nÅª¨Ó¦Û[%s]ªº°T®§(%s)¶Ü¡H", fptr->owner, fptr->title);
  getdata(11, 0, "½Ð±z½T©w(Y/N/Q)?[Y] ", genbuf, 3, DOECHO);
  if (genbuf[0] == 'q')
    return QUIT;
  if (genbuf[0] == 'n')
    return 0;

  setuserfile(fname, fptr->filename);
  fptr->filemode |= FILE_READ;
  if (substitute_record(currmaildir, fptr, sizeof(*fptr), idc))
    return -1;

  mrd = 1;
  delete_it = NA;
  while (!done)
  {
    int more_result = more(fname, YEA);
    switch (more_result) {
    case 1:
       return READ_PREV;
    case 2:
       return RELATE_PREV;
    case 3:
       return READ_NEXT;
    case 4:
       return RELATE_NEXT;
    case 5:
       return RELATE_FIRST;
    case 6:
       return 0;
    case 7:
      mail_reply(idc, fptr, currmaildir);
      return FULLUPDATE;
    case 8:
      multi_reply(idc, fptr, currmaildir);
      return FULLUPDATE;
    }
    move(b_lines, 0);
    clrtoeol();
    outs(msg_mailer);
    refresh();

    switch (egetch())
    {
    case 'r':
    case 'R':
      mail_reply(idc, fptr, currmaildir);
      break;
    case 'x':
      m_forward(idc, fptr, currmaildir);
      break;
    case 'y':
      multi_reply(idc, fptr, currmaildir);
      break;
    case 'd':
    case 'D':
      delete_it = YEA;
    default:
      done = YEA;
    }
  }
  if (delete_it)
  {
    clear();
    prints("§R°£«H¥ó¡m%s¡n", fptr->title);
    getdata(1, 0, msg_sure_ny, genbuf, 2, LCECHO);
    if (genbuf[0] == 'y')
    {
      unlink(fname);
      delmsgs[delcnt++] = idc;
    }
  }
  clear();
  return 0;
}


int
m_new()
{
  clear();
  mrd = 0;
  setutmpmode(RMAIL);
  read_new_mail(NULL);
  clear();
  curredit |= EDIT_MAIL;
  if (apply_record(currmaildir, read_new_mail, sizeof(fileheader)) == -1)
  {
    outs("¨S¦³·s«H¥ó¤F");
    pressanykey();
    return -1;
  }
  curredit = 0;
  if (delcnt)
  {
    while (delcnt--)
      delete_record(currmaildir, sizeof(fileheader), delmsgs[delcnt]);
  }
  outs(mrd ? "«H¤w¾\\²¦" : "¨S¦³·s«H¥ó¤F");
  pressanykey();
  return -1;
}


static void
mailtitle()
{
  showtitle("\0¶l¥ó¿ï³æ", BoardName);
  outs("\
[¡ö]Â÷¶}  [¡ô,¡õ]¿ï¾Ü  [¡÷,r]¾\\Åª«H¥ó  [R]¦^«H  [x]Âà¹F  [y]¸s²Õ¦^«H  [h]¨D§U\n[7m\
 ½s¸¹   ¤é ´Á  §@ ªÌ          «H  ¥ó  ¼Ð  ÃD                                  [0m");
}


static void
maildoent(num, ent)
  fileheader *ent;
{
  char *title, *mark, color, type = "+ Mm"[ent->filemode];

/*
woju
taged for delete
*/
  if (ent->filemode > 3)
     type = '*';

  title = subject(mark = ent->title);
  if (title == mark)
  {
    color = '1';
    mark = "¡º";
  }
  else
  {
    color = '3';
    mark = "R:";
  }

  if (strncmp(currtitle, title, 40))
    prints("%5d %c %-7s%-15.14s%s %.46s\n", num, type,
      ent->date, ent->owner, mark, title);
  else
    prints("%5d %c %-7s%-15.14s[1;3%cm%s %.46s[0m\n", num, type,
      ent->date, ent->owner, color, mark, title);
}


#ifdef POSTBUG
extern int bug_possible;
#endif


/*
woju
*/
static int
mail_del_tag(ent, fhdr, direct)
  int ent;
  fileheader *fhdr;
  char *direct;
{
  char genbuf[3];

  getdata(1, 0, "½T©w§R°£¼Ð°O«H¥ó(Y/N)? [Y]", genbuf, 3, LCECHO);
  if (genbuf[0] != 'n')
  {
    char buf[STRLEN];

    currfmode = FILE_TAGED;
    if (delete_files(direct, cmpfmode))
       return DIRCHANGED;
  }
  return FULLUPDATE;
}

m_idle(ent, fhdr, direct)
  int ent;
  fileheader *fhdr;
  char *direct;
{
   t_idle();
   return FULLUPDATE;
}


static int
mail_del(ent, fhdr, direct)
  int ent;
  fileheader *fhdr;
  char *direct;
{
  char genbuf[200];

  if (fhdr->filemode & FILE_MARKED)
    return DONOTHING;

  getdata(1, 0, msg_del_ny, genbuf, 3, LCECHO);
  if (genbuf[0] == 'y')
  {
    char buf[STRLEN];
    char *t;
    extern int cmpfilename();

    strcpy(currfile, fhdr->filename);
    if (!delete_file(direct, sizeof(*fhdr), ent, cmpfilename))
    {
      setdirpath(genbuf, direct, fhdr->filename);
      unlink(genbuf);
      return DIRCHANGED;
    }
  }
  return FULLUPDATE;
}


/*
woju
static int
*/
mail_read(ent, fhdr, direct)
  int ent;
  fileheader *fhdr;
  char *direct;
{
  char buf[64];
  char *t;
  char done, delete_it, replied;

  clear();
  setdirpath(buf, direct, fhdr->filename);
  strncpy(currtitle, subject(fhdr->title), 40);
  done = delete_it = replied = NA;
  while (!done)
  {
/*
woju
*/
    int more_result =  more(buf, YEA);
    if (more_result != -1) {
       fhdr->filemode |= FILE_READ;
       if (!strncmp("[·s]", fhdr->title, 4))
          fhdr->filemode |= FILE_TAGED;
       substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent);
    }
    switch (more_result) {
    case 1:
       return READ_PREV;
    case 2:
       return RELATE_PREV;
    case 3:
       return READ_NEXT;
    case 4:
       return RELATE_NEXT;
    case 5:
       return RELATE_FIRST;
    case 6:
       return FULLUPDATE;
    case 7:
      mail_reply(ent, fhdr, direct);
      return FULLUPDATE;
    case 8:
      multi_reply(ent, fhdr, direct);
      return FULLUPDATE;
    }
    move(b_lines, 0);
    clrtoeol();
    refresh();
    outs(msg_mailer);

    switch (egetch())
    {
    case 'r':
    case 'R':
      replied = YEA;
      mail_reply(ent, fhdr, direct);
      break;
    case 'x':
      m_forward(ent, fhdr, direct);
      break;
    case 'y':
      multi_reply(ent, fhdr, direct);
      break;
    case 'd':
      delete_it = YEA;
    default:
      done = YEA;
    }
  }
  if (delete_it)
    mail_del(ent, fhdr, direct);
  else
  {
    fhdr->filemode |= FILE_READ;

#ifdef POSTBUG
    if (replied)
      bug_possible = YEA;
#endif

    substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent);

#ifdef POSTBUG
    bug_possible = NA;
#endif
  }
  return FULLUPDATE;
}


/* ---------------------------------------------- */
/* in boards/mail ¦^«Hµ¹­ì§@ªÌ¡AÂà«H¯¸¥ç¥i        */
/* ---------------------------------------------- */

int
mail_reply(ent, fhdr, direct)
  int ent;
  fileheader *fhdr;
  char *direct;
{
  char uid[STRLEN];
  char *t;
  FILE *fp;
  char genbuf[512];

  stand_title("¦^  «H");

  /* §PÂ_¬O boards ©Î mail */

  if (curredit & EDIT_MAIL)
    setuserfile(quote_file, fhdr->filename);
  else
    setbfile(quote_file, currboard, fhdr->filename);

  /* find the author */

  strcpy(quote_user, fhdr->owner);

  if (strchr(quote_user, '.'))
  {
    genbuf[0] = '\0';
    if (fp = fopen(quote_file, "r"))
    {
      fgets(genbuf, 512, fp);
      fclose(fp);
    }

    t = strtok(genbuf, str_space);
    if (!strcmp(t, str_author1) || !strcmp(t, str_author2))
    {
      strcpy(uid, strtok(NULL, str_space));
    }
    else
    {
      outs("¿ù»~: §ä¤£¨ì§@ªÌ¡C");
      pressanykey();
      return FULLUPDATE;
    }
  }
  else
    strcpy(uid, quote_user);

  /* make the title */

  do_reply_title(3, fhdr->title);
  if(!comfortable)
    prints("\n¦¬«H¤H: %s\n¼Ð  ÃD: %s\n", uid, save_title);

  /* edit, then send the mail */

  ent = curredit;
  switch (do_send(uid, save_title))
  {
  case -1:
    outs(err_uid);
    break;
  case -2:
    outs(msg_cancel);
    break;
  case -3:
    prints("¨Ï¥ÎªÌ [%s] µLªk¦¬«H", uid);
    break;
  }
  curredit = ent;
  pressanykey();
  return FULLUPDATE;
}

int
mail_edit(ent, fhdr, direct)
  int ent;
  fileheader *fhdr;
  char *direct;
{
  char uid[STRLEN];
  char *t;
  FILE *fp;
  char genbuf[200];

  if (!HAVE_PERM(PERM_SYSOP))
     return DONOTHING;
  setdirpath(genbuf, direct, fhdr->filename);
  strcpy(save_title, fhdr->title);
  vedit(genbuf, NA);
  if (strcmp(fhdr->title, save_title)) {
     strcpy(fhdr->title, save_title);
     substitute_record(direct, fhdr, sizeof(*fhdr), ent);
  }
  return FULLUPDATE;
}


static int
mail_mark(ent, fhdr, direct)
  int ent;
  fileheader *fhdr;
  char *direct;
{
  fhdr->filemode ^= FILE_MARKED;
  substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent);
  return (PART_REDRAW);
}



/*
woju
*/
static int
mail_tag(ent, fhdr, direct)
  int ent;
  fileheader *fhdr;
  char *direct;
{
  fhdr->filemode ^= FILE_TAGED;
  substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent);
  return POS_NEXT;
}


/* help for mail reading */

static char *mail_help[] =
{
  "\0¹q¤l«H½c¾Þ§@»¡©ú",
  "\01°ò¥»©R¥O",
  "(p)(¡ô)    «e¤@½g¤å³¹",
  "(n)(¡õ)    ¤U¤@½g¤å³¹",
  "(P)(PgUp)  «e¤@­¶",
  "(N)(PgDn)  ¤U¤@­¶",
  "(##)(cr)   ¸õ¨ì²Ä ## µ§",
  "($)        ¸õ¨ì³Ì«á¤@µ§",
  "\01¶i¶¥©R¥O",
  "(r)(¡÷)    Åª«H",
  "(R)        ¦^«H",
  "(x)        Âà¹F«H¥ó",
  "(y)        ¸s²Õ¦^«H",

#ifdef INTERNET_EMAIL
  "(F)        ±N«H¶Ç°e¦^±zªº¹q¤l«H½c",
#endif

  "(d)        ±þ±¼¦¹«H",
  "(D)        ±þ±¼«ü©w½d³òªº«H",
  "(m)        ±N«H¼Ð°O¡A¥H¨¾³Q²M°£",
  "(Z)        Z-modem ¶ÇÀÉ",
  NULL
};


static int
m_help()
{
  show_help(mail_help);
  return FULLUPDATE;
}


static struct one_key mail_comms[] = {
  'd', mail_del,
  'D', del_range,
  'r', mail_read,
  'R', mail_reply,
  'E', mail_edit,
  'm', mail_mark,
  't', mail_tag,
  'x', m_forward,
  Ctrl('D'), mail_del_tag,
  'y', multi_reply,
  Ctrl('I'), m_idle,
  'h', m_help,
  '\0', NULL
};


int
m_read()
{
  if (get_num_records(currmaildir, sizeof(fileheader)))
  {
    curredit = EDIT_MAIL;
    i_read(RMAIL, currmaildir, mailtitle, maildoent, mail_comms);
    currfmode = FILE_TAGED;
    if (search_rec(currmaildir, cmpfmode))
      mail_del_tag(0, 0, currmaildir);
    curredit = 0;
    return 0;
  }
  else
  {
    outs("±z¨S¦³¨Ó«H");
    return XEASY;
  }
}


#ifdef INTERNET_EMAIL
#include <netdb.h>
#include <pwd.h>
#include <time.h>


int
invalidaddr(addr)
char *addr;
{
  if (*addr == '\0')
    return 1;                   /* blank */
  while (*addr)
  {
    if (not_alnum(*addr) && !strchr("[].%!@:-_", *addr))
      return 1;
    addr++;
  }
  return 0;
}


/* ±H«H¥æµ¹ sendmail¡A¤U¦C¥i¥H¬Ù²¤ */

#if 0
#define BBSMAILDIR "/usr/spool/mqueue"


static void
spacestozeros(s)
  char *s;
{
  while (*s)
  {
    if (*s == ' ')
      *s = '0';
    s++;
  }
}


static int
getqsuffix(s)
  char *s;
{
  struct stat stbuf;
  char qbuf[STRLEN], dbuf[STRLEN];
  char c1 = 'A', c2 = 'A';
  int pos = strlen(BBSMAILDIR) + 3;

  sprintf(dbuf, "%s/dfAA%5d", BBSMAILDIR, currpid);
  sprintf(qbuf, "%s/qfAA%5d", BBSMAILDIR, currpid);
  spacestozeros(dbuf);
  spacestozeros(qbuf);
  while (1)
  {
    if (stat(dbuf, &stbuf) && stat(qbuf, &stbuf))
      break;
    if (c2 == 'Z')
    {
      c2 = 'A';
      if (c1 == 'Z')
        return -1;
      else
        c1++;
      dbuf[pos] = c1;
      qbuf[pos] = c1;
    }
    else
      c2++;
    dbuf[pos + 1] = c2;
    qbuf[pos + 1] = c2;
  }
  strcpy(s, &(qbuf[pos]));
  return 0;
}


static void
convert_tz(local, gmt, buf)
  int gmt, local;
  char *buf;
{
  local -= gmt;
  if (local < -11)
    local += 24;
  else if (local > 12)
    local -= 24;
  sprintf(buf, " %4d", abs(local * 100));
  spacestozeros(buf);
  if (local < 0)
    buf[0] = '-';
  else if (local > 0)
    buf[0] = '+';
  else
    buf[0] = '\0';
}


static int
createqf(title, qsuffix)
  char *title, *qsuffix;
{
  static int configured = 0;
  static char myhostname[STRLEN];
  static char myusername[20];
  char mytime[STRLEN];
  char idtime[STRLEN];
  char qfname[STRLEN];
  char t_offset[6];
  FILE *qfp;
  time_t timenow;
  int savehour;
  struct tm *gtime, *ltime;
  struct hostent *hbuf;
  struct passwd *pbuf;

  if (!configured)
  {
    /* get host name */
    gethostname(myhostname, STRLEN);
    hbuf = gethostbyname(myhostname);
    if (hbuf)
      strncpy(myhostname, hbuf->h_name, STRLEN);

    /* get bbs uident */
    pbuf = getpwuid(getuid());
    if (pbuf)
      strncpy(myusername, pbuf->pw_name, 20);
    if (hbuf && pbuf)
      configured = 1;
    else
      return -1;
  }

  /* get file name */
  sprintf(qfname, "%s/qf%s", BBSMAILDIR, qsuffix);
  if ((qfp = fopen(qfname, "w")) == NULL)
    return -1;

  /* get time */
  time(&timenow);
  ltime = localtime(&timenow);

#ifdef SYSV
  ascftime(mytime, "%a, %d %b %Y %T ", ltime);
#else
  strftime(mytime, sizeof(mytime), "%a, %d %b %Y %T ", ltime);
#endif

  savehour = ltime->tm_hour;
  gtime = gmtime(&timenow);
  strftime(idtime, sizeof(idtime), "%Y%m%d%y%H%M", gtime);
  convert_tz(savehour, gtime->tm_hour, t_offset);
  strcat(mytime, t_offset);
  fprintf(qfp, "P1000\nT%lu\nDdf%s\nS%s\nR%s\n", timenow, qsuffix,
    myusername, cuser.email);

  /* do those headers! */
  fprintf(qfp, "HReceived: by %s (" MYVERSION ")\n\tid %s; %s\n",
    myhostname, qsuffix, mytime);
  fprintf(qfp, "HReturn-Path: <%s@%s>\n", myusername, myhostname);
  fprintf(qfp, "HDate: %s\n", mytime);
  fprintf(qfp, "HMessage-Id: <%s.%s@%s>\n", idtime, qsuffix,
    myhostname);
  fprintf(qfp, "HFrom: %s@%s (%s in NTHU CS BBS)\n", myusername, myhostname, cuser.userid);
  fprintf(qfp, "HSubject: %s (fwd)\n", title);
  fprintf(qfp, "HTo: %s\n", cuser.email);
  fprintf(qfp, "HX-Forwarded-By: %s (%s)\n", cuser.userid,

#ifdef REALNAME
    cuser.realname);
#else
    cuser.username);
#endif

  fprintf(qfp, "HX-Disclaimer: %s ¹ï¥»«H¤º®e®¤¤£­t³d¡C\n", BoardName);
  fclose(qfp);
  return 0;
}
#endif

int
bbs_sendmail(fpath, title, receiver)
  char *fpath, *title, *receiver;
{
  static int configured = 0;
  static char myhostname[STRLEN];
  static char myusername[20];
  struct hostent *hbuf;
  struct passwd *pbuf;
  char *ptr;
  char genbuf[200];

  FILE *fin, *fout;

  /* ¤¤³~ÄdºI */
  if (ptr = strchr(receiver, ';'))
  {
    struct tm *ptime;
    time_t now;
      
    if (fout = fopen("hackerlog", "a+"))
    {
      time(&now);
      ptime = localtime(&now);
      fprintf(fout, "[%d/%d %d:%02d] %s from %s\n\t\t±H¥X %s\n", 
        ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, 
        cuser.userid, getenv("RFC931"), receiver);
      fclose(fout);
    }     
    *ptr = '\0';  
  }

  if (ptr = strstr(receiver, str_mail_address))
  {
    fileheader mymail;
    char hacker[20];
    int len;

    len = ptr - receiver;
    memcpy(hacker, receiver, len);
    hacker[len] = '\0';
    if (!searchuser(hacker))
    {
      return -2;
    }
    sethomepath(genbuf, hacker);
    stampfile(genbuf, &mymail);
    if (!strcmp(hacker, cuser.userid))
    {
      strcpy(mymail.owner, "[«H±æ·R¯¸]");
      mymail.filemode = FILE_READ;
    }
    else
      strcpy(mymail.owner, cuser.userid);
    strncpy(mymail.title, title, TTLEN);
    unlink(genbuf);
    Link(fpath, genbuf);
    sethomedir(genbuf, hacker);
    return append_record(genbuf, &mymail, sizeof(mymail));
  }

  /* setup the hostname and username */
  if (!configured)
  {
    /* get host name */
    gethostname(myhostname, STRLEN);
    hbuf = gethostbyname(myhostname);
    if (hbuf)
      strncpy(myhostname, hbuf->h_name, STRLEN);

    /* get bbs uident */
    pbuf = getpwuid(getuid());
    if (pbuf)
      strncpy(myusername, pbuf->pw_name, 20);
    if (hbuf && pbuf)
      configured = 1;
    else
      return -1;
  }

  /* Running the sendmail */

#ifdef  INTERNET_PRIVATE_EMAIL
  if (fpath == NULL)
  {
    sprintf(genbuf, "/usr/sbin/sendmail %s > /dev/null", receiver);
    fin = fopen("etc/confirm", "r");
  }
  else
  {
    sprintf(genbuf, "/usr/sbin/sendmail -f %s%s %s > /dev/null", cuser.userid, str_mail_address, receiver);
    fin = fopen(fpath, "r");
  }
  fout = popen(genbuf, "w");
  if (fin == NULL || fout == NULL)
    return -1;
  /**** for mail list *****/
  //if ((fpath)&&strcmp("test@Stalin.AD.nthu.edu.tw",receiver))
  if (fpath)
    fprintf(fout, "Reply-To: %s%s\nFrom: %s%s\n",
      cuser.userid, str_mail_address, cuser.userid, str_mail_address);
#else
  sprintf(genbuf, "/usr/sbin/sendmail %-150s > /dev/null", receiver);
  fout = popen(genbuf, "w");
  fin = fopen(fpath ? fpath : "etc/confirm", "r");
  if (fin == NULL || fout == NULL)
    return -1;

  if (fpath)
    fprintf(fout, "From: %s@%s (%s)\n",
      myusername, myhostname, BBSNAME);
#endif

  fprintf(fout, "To: %s\nSubject: %-100s\n", receiver, title);
  //fprintf(fout, "X-Disclaimer: " BOARDNAME
  //  "¹ï¥»«H¤º®e®¤¤£­t³d¡C\n\n");

  fprintf(fout, "X-Disclaimer: FHL.BBS (fhl.ee.nctu.edu.tw) will NOT take "
  "responsibility for any issues by this letter.\n\n");

  while (fgets(genbuf, 255, fin))
  {
    if (genbuf[0] == '.' && genbuf[1] == '\n')
      fputs(". \n", fout);
    else
      fputs(genbuf, fout);
  }
  fclose(fin);
  fprintf(fout, ".\n");
  pclose(fout);
     //outmsg("Âà±H´ú¸Õ¤¤4!");
     //refresh();
  return 0;
}


int
doforward(direct, fh, mode)
  char *direct;
  fileheader *fh;
  int mode;                     /* ¬O§_ uuencode */
{
  static char address[60];
  char fname[STRLEN];
  int return_no;
  char genbuf[200];

  if (!address[0])
    strcpy(address, cuser.email);
  
  if (address[0])
  {
    sprintf(genbuf, "½T©wÂà±Hµ¹ [%s] ¶Ü(Y/N/Q)¡H[Y] ", address);
    getdata(b_lines - 1, 0, genbuf, fname, 3, LCECHO);

    if (fname[0] == 'q')
    {
      outmsg("¨ú®øÂà±H");
      return 1;
    }
    if (fname[0] == 'n')
      address[0] = '\0';
  }
  
  if (!address[0])
  {
    getdata(b_lines - 1, 0, "½Ð¿é¤JÂà±H¦a§}¡G", fname, 60, DOECHO);
    if (fname[0])
    {
      if (strchr(fname, '.'))
        strcpy(address, fname);
      else
        sprintf(address, "%s.bbs@%s", fname, MYHOSTNAME);
    }
    else
    {
      outmsg("¨ú®øÂà±H");
      return 1;
    }
  }

  if (invalidaddr(address))
    return -2;

  sprintf(fname, "¥¿Âà±Hµ¹ %s, ½Ðµy­Ô...", address);
  outmsg(fname);
  move(b_lines - 1, 0);
  refresh();

  if (mode)
  {
    char tmp_buf[128];

    sprintf(fname, "/tmp/bbs.uu%05d", currpid);
    sprintf(tmp_buf, "/usr/bin/uuencode %s/%s uu.%05d > %s",
      direct, fh->filename, currpid, fname);
    system(tmp_buf);
    //sleep(1);
  }
  else
    sprintf(fname, "%s/%s", direct, fh->filename);

  /**** down ***/
  return_no = bbs_sendmail(fname, fh->title, address);
  if (mode)
    unlink(fname);
  return (return_no);
}
#endif


int
chkmail(rechk)
  int rechk;
{
  static time_t lasttime = 0;
  static int ismail = 0;
  struct stat st;
  fileheader fh;
  int fd;
  register numfiles;
  unsigned char ch;

  if (!HAS_PERM(PERM_BASIC))
    return 0;

  if (stat(currmaildir, &st) < 0)
    return (ismail = 0);

  if ((lasttime >= st.st_mtime) && !rechk)
    return ismail;

  lasttime = st.st_mtime;
  numfiles = st.st_size / sizeof(fileheader);
  if (numfiles <= 0)
    return (ismail = 0);

  /* ------------------------------------------------ */
  /* ¬Ý¬Ý¦³¨S¦³«H¥óÁÙ¨SÅª¹L¡H±qÀÉ§À¦^ÀYÀË¬d¡A®Ä²v¸û°ª */
  /* ------------------------------------------------ */

  if ((fd = open(currmaildir, O_RDONLY)) > 0)
  {
    lseek(fd, st.st_size - 1, SEEK_SET);
    while (numfiles--)
    {
      read(fd, &ch, 1);
      if (!(ch & FILE_READ))
      {
        close(fd);
        return (ismail = 1);
      }
      lseek(fd, (off_t) -sizeof(fileheader) - 1, SEEK_CUR);
    }
    close(fd);
  }
  return (ismail = 0);
}


#ifdef  EMAIL_JUSTIFY
void
mail_justify()
{
  more("etc/justify", NA);
  if (valid_ident(cuser.email) && !invalidaddr(cuser.email))
  {
    char title[80], *ptr;
    ushort checksum;            /* 16-bit is enough */
    char ch;

    checksum = usernum;
    ptr = cuser.email;
    while (ch = *ptr++)
    {
      if (ch <= ' ')
        break;
      if (ch >= 'A' && ch <= 'Z')
        ch |= 0x20;
      checksum = (checksum << 1) ^ ch;
    }

    sprintf(title, "[SOB BBS]To %s(%d:%d) [User Justify]",
      cuser.userid, usernum + MAGIC_KEY, checksum);
    if (bbs_sendmail(NULL, title, cuser.email) < 0)
      outs("[1m¨­¥÷»{ÃÒ«H¨çµLªk±H¥X¡A½Ð±z¶ñ¼g¯u¹ê E-mail address[0m");
    else
      prints("\n%s(%s)±z¦n¡A¥Ñ©ó±z§ó·s E-mail address ªº³]©w¡A\n"
        "½Ð±z¾¨§Ö¨ì [44m%s[m ©Ò¦bªº¤u§@¯¸¦^ÂÐ¡y¨­¥÷»{ÃÒ«H¨ç¡z¡C",
        cuser.userid, cuser.username, cuser.email);
  }
  else
  {
    prints("\n%s(%s)±z¦n¡A¥Ñ©ó±z¨S¦³¯u¹ê E-mail address¡A\n"
      "±N·|·l¥¢³¡¥÷¥\\¯à¡A½Ð±z¨ì [1;42m (U)ser¡÷(R)egister [0m ¶ñ¼gµù¥Uªí³æ¡C",
      cuser.userid, cuser.username);
  }
  pressanykey();
}
#endif                          /* EMAIL_JUSTIFY */
