home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / MXMS_160.LZH / QWKSPT.C < prev    next >
C/C++ Source or Header  |  1991-06-24  |  36KB  |  992 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*    Qwkspt.c    :QWK format routines for MaxMail                          */
  4. /*                                                                          */
  5. /****************************************************************************/
  6.  
  7. #include "MaxMail.h"
  8.  
  9. /* Some QWK specifics */
  10.  
  11. struct QWKmsghd {        /* Messages.dat header */
  12.    char  Msgstat;            /* message status byte */
  13.    char  Msgnum[7];          /* message number in ascii */
  14.    char  Msgdate[8];         /* date in ascii */
  15.    char  Msgtime[5];         /* time in ascii */
  16.    char  Msgto[25];          /* Person addressed to */
  17.    char  Msgfrom[25];        /* Person who wrote message */
  18.    char  Msgsubj[25];        /* Subject of message */
  19.    char  Msgpass[12];        /* password */
  20.    char  Msgrply[8];         /* message # this refers to */
  21.    char  Msgrecs[6];           /* # of 128 byte recs in message,inc header */
  22.    char  Msglive;            /* always 0xe1 */
  23.    char  Msgarealo;         /* area number, low byte */
  24.    char  Msgareahi;         /* area number, hi byte */
  25.    char  Msgfiller[3];        /* fill out to 128 bytes */
  26. };
  27.  
  28. union Converter {
  29.    unsigned char  uc[10];
  30.    unsigned int   ui[5];
  31.    unsigned long  ul[2];
  32.    float           f[2];
  33.    double          d[1];
  34. };
  35.  
  36. struct repmsg {
  37.    int count;
  38.    int areano;
  39.    word flags;
  40.    struct repmsg _far *next;
  41. };
  42.  
  43. #define RP_CMDFLAG  0x0001
  44.  
  45. static int Indx;        /* Message NDX file */
  46. static int PIndx;        /* Personal NDX file */
  47. static int upmsgs;
  48. static int repfile;
  49. static int msgrecs;
  50. static int confreqs;
  51. static word lastarea;
  52.  
  53. static struct repmsg _far *RP1;
  54. static struct repmsg _far *rp;
  55. static struct repmsg _far *RPprev;
  56.  
  57. static FILE *MsgFile; /* Messages.dat file */
  58. static TotRecs;
  59. extern char msg_line[];
  60. static int Aindex;
  61. static struct _aidx IDX;
  62.  
  63. static char *monthstr[] =  {  {"Jan"},{"Feb"},{"Mar"},{"Apr"},
  64.                             {"May"},{"Jun"},{"Jul"},{"Aug"},
  65.                             {"Sep"},{"Oct"},{"Nov"},{"Dec"}
  66.                          };                         
  67.  
  68.  
  69. static struct QWKmsghd *QMsgHead;
  70. extern struct _msg   amsg;
  71.  
  72. extern char _far  *msgbuffer;
  73. extern int fido_init;
  74. extern int HaveUpl;
  75.  
  76. /* Create the control.dat file for QWK packets, this only called
  77.    once per session. It also does some other initialization for
  78.    QWK handling.. */
  79.  
  80. void qwkinit(void)
  81. {
  82.    static First = TRUE;
  83.    struct find_t fbuf;
  84.  
  85.    if (First) {        /* Do this only once */
  86.       Indx = -1;
  87.       PIndx = -1;
  88.       if (!fido_init)
  89.          fidomsg_init();
  90.  
  91.       if (tdir[0])
  92.          switch_dir(tdir);        /* Switch to temp dir */
  93.  
  94.       sprintf(QWKDir,"QWK%04x",Task);
  95.       if(mkdir(QWKDir) != 0) {
  96.          if(chdir(QWKDir) != 0)
  97.             QWKDir[0] = 0;
  98.          else {        /* We are in QWKDir, let's cleanup */
  99.             if (!_dos_findfirst("*.*",_A_NORMAL,&fbuf)) {    /* Kill everything */
  100.                unlink(fbuf.name);
  101.                while (!_dos_findnext(&fbuf)) 
  102.                   unlink(fbuf.name);
  103.             }
  104.             chdir("..");        /* Restore back to parent */
  105.          }
  106.       }
  107.  
  108.       if (tdir[0])
  109.          switch_dir(PRM(sys_path));
  110.  
  111.       First = FALSE;
  112.    }
  113.    lastarea = 0xffff;
  114. }
  115.  
  116.  
  117. int openqwk(void)
  118. {
  119.    int code=0;
  120.    int x,keys,totals;
  121.    char *p;
  122.    FILE *datfile;
  123.    time_t     aclock;
  124.    struct tm  *newtime;
  125.    char fname[_MAX_FNAME];
  126.    char fext[_MAX_EXT];
  127.  
  128.  
  129.    QMsgHead = (struct QWKmsghd *) malloc(sizeof(struct QWKmsghd));
  130.    if (QMsgHead == NULL)
  131.       return 1;
  132.  
  133. /* Fill out some defaults in the Messages.dat file header */
  134.    memset(QMsgHead->Msgpass,' ',12);
  135.    memset(QMsgHead->Msgfiller,' ',3);
  136.    QMsgHead->Msglive = 0xe1;
  137.  
  138.    tempdir();
  139.    datfile = _fsopen("Control.dat","wt",SH_DENYRW);
  140.    if (datfile != NULL) {
  141.       setcolor(TextAttr[HILITE_TEXT]);
  142.       strout("\r\nCreating the Control.Dat file for your QWK packet...\r\n");
  143.       totals = 0;
  144.       strcpy(temp,PRM(system_name));
  145.       p = strtok(temp," \r\n");
  146.       fputs(p,datfile);        /* Line #1 */
  147.       fputs("\n",datfile);
  148.       fputs("               \n",datfile);
  149.       fputs(BBSphone,datfile);
  150.       fputs("\n",datfile);
  151.       fputs(PRM(sysop),datfile);
  152.       fputs("\n",datfile);
  153.       if (!BBSid[0]) {
  154.          strncpy(BBSid,PRM(system_name),8);
  155.          BBSid[8] = 0;
  156.       }
  157.       sprintf(temp,"00000,%s\n",BBSid);        /* Line #5 */
  158.       fputs(temp,datfile);
  159.       sprintf(temp,"%s.qwk",BBSid);
  160.       unlink(temp);
  161.       time(&aclock);
  162.       newtime = localtime(&aclock);
  163.       sprintf(temp,"%02d-%02d-19%02d,%02d:%02d:%02d\n",
  164.          newtime->tm_mon+1,newtime->tm_mday,newtime->tm_year,
  165.          newtime->tm_hour,newtime->tm_min,newtime->tm_sec);
  166.       fputs(temp,datfile);        /* Line #6 */
  167.       fputs(strupr(USERCFG.name),datfile);
  168.       fputs("\n",datfile);
  169.       fputs(" \n",datfile);        /* Line #8 */
  170.       fputs("0\n",datfile);
  171.       fputs("0\n",datfile);        /* Line #10 */
  172.       Aindex = sopen(PRM(aidx_name),O_BINARY | O_RDONLY,SH_DENYNO,S_IREAD);
  173.       if (Aindex == -1)
  174.          aborterror(FILEOPEN,"Error opening Area index file");
  175.       for (x=0; x < 1000; x++) {    /* Display the first 1000 msg areas */
  176.          if((read(Aindex,(char *)&IDX,sizeof(struct _aidx))) != sizeof(struct _aidx))
  177.             break;
  178.          fseek(afile,IDX.offset,SEEK_SET);
  179.          fread(&AREA,astrlen,1,afile);
  180.          keys = AREA.msglock;
  181.          if (!keys)         /* No locks for this area */
  182.             keys = TRUE;
  183.          else {        /* User must have same locks */
  184.             keys = AREA.msglock & LastUser.key;
  185.             if (keys != (int) AREA.msglock)
  186.                keys = FALSE;
  187.          }
  188.          if (!isskiparea(x)) {
  189.             if (AREA.msgpath[0] && (LastUser.priv >= AREA.msgpriv) && keys) {
  190.                if(check_barareas(&AREA,-1)) 
  191.                   totals++;
  192.             }
  193.          }
  194.       }
  195.       sprintf(temp,"%d\n",totals-1);
  196.       fputs(temp,datfile);
  197.       lseek(Aindex,0L,SEEK_SET);        /* Rewind again */
  198.       for (x=0; x < 1000; x++) {    /* Display the first 1000 msg areas */
  199.          if((read(Aindex,(char *)&IDX,sizeof(struct _aidx))) != sizeof(struct _aidx))
  200.             break;
  201.          fseek(afile,IDX.offset,SEEK_SET);
  202.          fread(&AREA,astrlen,1,afile);
  203.          keys = AREA.msglock;
  204.          if (!keys)         /* No locks for this area */
  205.             keys = TRUE;
  206.          else {        /* User must have same locks */
  207.             keys = AREA.msglock & LastUser.key;
  208.             if (keys != (int) AREA.msglock)
  209.                keys = FALSE;
  210.          }
  211.          if (!isskiparea(x)) {
  212.             if (AREA.msgpath[0] && (LastUser.priv >= AREA.msgpriv) && keys) {
  213.                if(check_barareas(&AREA,-1)) {
  214.                   sprintf(temp,"%d\n",x);
  215.                   fputs(temp,datfile);
  216.                   memset(temp,0,11);
  217.                   strncpy(temp,AREA.msginfo,10);
  218.                   fputs(temp,datfile);
  219.                   fputs("\n",datfile);
  220.                }
  221.             }
  222.          }
  223.       }
  224.       close(Aindex);
  225.  
  226.       if (QWKWelcome[0]) {
  227.          _splitpath(QWKWelcome,temp,temp,fname,fext);
  228.          sprintf(temp,"%s%s\n",fname,fext);
  229.          fputs(temp,datfile);        /* This is QWK welcome file */
  230.       }
  231.       else fputs("WELCOME\n",datfile);        /* This is QWK welcome file */
  232.  
  233.       if (QWKnews[0]) {
  234.          _splitpath(QWKnews,temp,temp,fname,fext);
  235.          sprintf(temp,"%s%s\n",fname,fext);
  236.          fputs(temp,datfile);        /* This is QWK news file */
  237.       }
  238.       else fputs("WELCOME\n",datfile);        /* This is QWK news file */
  239.  
  240.       if (QWKbye[0]) {
  241.          _splitpath(QWKbye,temp,temp,fname,fext);
  242.          sprintf(temp,"%s%s\n",fname,fext);
  243.          fputs(temp,datfile);        /* This is QWK bye file */
  244.       }
  245.       else fputs("GOODBYE\n",datfile);        /* This is QWK bye file */
  246.  
  247.       fclose(datfile);
  248.       datfile = _fsopen("DOOR.ID","wt",SH_DENYRW);
  249.       if (datfile != NULL) {
  250.          sprintf(temp,"DOOR = MaxMail   \n");
  251.          fputs(temp,datfile);        /* Line #1 */
  252.  
  253.          sprintf(temp,"VERSION = %2.2f  \n",Version);
  254.          fputs(temp,datfile);        /* Line #2 */
  255.  
  256.          sprintf(temp,"SYSTEM = Maximus   \n");
  257.          fputs(temp,datfile);        /* Line #3 */
  258.  
  259.          sprintf(temp,"CONTROLNAME = MAXMAIL\n");
  260.          fputs(temp,datfile);        /* Line #4 */
  261.  
  262.          sprintf(temp,"CONTROLTYPE = ADD\n");
  263.          fputs(temp,datfile);        /* Line #5 */
  264.  
  265.          sprintf(temp,"CONTROLTYPE = DROP\n");
  266.          fputs(temp,datfile);        /* Line #6 */
  267.          sprintf(temp,"CONTROLTYPE = REQUEST\n");
  268.          fputs(temp,datfile);        /* Line #6 */
  269.          fclose(datfile);
  270.       }
  271.  
  272.       MsgFile = _fsopen("Messages.dat","wb",SH_DENYNO);
  273.       if (MsgFile != NULL) {        /* Write out the header */
  274.          fwrite("Produced by Qmail...",20,1,MsgFile);
  275.          fwrite("Copywright (c) 1987 by Sparkware.  ",35,1,MsgFile);
  276.          fwrite("All Rights Reserved",19,1,MsgFile);
  277.          for (x=0; x < 54; x++)
  278.             fwrite(" ",1,1,MsgFile);        /* Fill out rest of 128 byte record */
  279.       }
  280.       else code = 1;
  281.    }
  282.    else code = 1;
  283.  
  284.    homedir();
  285.  
  286.    TotRecs = 1;
  287.    return code;
  288. }
  289.  
  290. /* This function is called whenever a new message
  291.    area to scan is started */
  292. void qwk_newarea(struct msgupd_st *msgupd)
  293. {
  294.  
  295.    char tname[10];
  296.    if (Indx != -1)
  297.       close(Indx);
  298.  
  299.    tempdir();
  300.    sprintf(tname,"%03d.ndx",msgupd->areano);
  301.    Indx = sopen(tname,O_CREAT | O_TRUNC | O_BINARY | O_RDWR,SH_DENYRW,S_IWRITE);
  302.    homedir();
  303. }
  304.  
  305. /* This function is called whenever a new message
  306.     needs to be imported to QWK */
  307. int qwk_fidomsg(int i,int flags,struct msgupd_st *msgupd,struct msghead *MSGHD)
  308. {
  309.    char        c;
  310.    int         j,n,recs,start,origin;
  311.    int         newline,IsOurs = FALSE;
  312.    struct      find_t c_file;
  313.    long          size,filepos;
  314.    float       in,out;
  315.  
  316.    j = n = 0;
  317.    sprintf(temp1,"%s%u%s",msgupd->msgpath,i,".MSG");
  318.    if (_dos_findfirst(temp1,0,&c_file) !=0) 
  319.       return(FILE_SRCH_ERR);
  320.  
  321.    if (c_file.size >= (long) MAXFMSGSIZ)         /* Message is too big! */
  322.       return(FILE_SIZE_ERR);
  323.  
  324.    size=c_file.size - ((long) sizeof(struct _msg));
  325.    recs=sopen(temp1,O_RDONLY|O_BINARY,SH_DENYNO,S_IREAD);
  326.    if (recs < 0) 
  327.       return(FILE_OPEN_ERR);
  328.  
  329.    j = read(recs,(char *) &amsg,sizeof(struct _msg));
  330.    if (j != sizeof(struct _msg)) 
  331.       return(FILE_READ_ERR);
  332.  
  333.    _dos_read(recs,msgbuffer,(unsigned)size,&j);
  334.    if (j != (int)size) 
  335.       return(FILE_READ_ERR);
  336.  
  337.    close(recs);        /* Close the fido message */
  338.  
  339.  
  340.    if (strcmpi(amsg.to,MSGHD->ourname) == 0) {
  341.       IsOurs = TRUE;
  342.       MSGHD->ourmail++;
  343.       if (PIndx == -1) {        /* Start the Personal Index file */
  344.          tempdir();
  345.          PIndx = sopen("Personal.ndx",O_CREAT | O_TRUNC | O_BINARY | O_RDWR,SH_DENYRW,S_IWRITE);
  346.          homedir();
  347.        }
  348.    }
  349.    else {        /* Not ours */
  350.       if ((flags & PRIVATE) && (amsg.attr & MSGPRIVATE)) 
  351.          return(PVTMSG_ERR);        /* No messages to read */
  352.       IsOurs = FALSE;
  353.    }
  354.  
  355.    if (recs >= 0) {        /* We had a valid MSG file, here's the main stuff */
  356.       if (lastarea != msgupd->areano) {        /* A new area */
  357.          qwk_newarea(msgupd);
  358.          lastarea = msgupd->areano;
  359.       }
  360.       recs = 1;        /* Becomes # of 128 byte records */
  361.       TotRecs++;
  362. /* First write out the index position */
  363.       sprintf(msg_line,"%u",TotRecs);    /* Stringized version of current position */
  364.       in = (float) atof(msg_line);
  365.       out = IEEToMSBIN(in);
  366.       write(Indx,&out,sizeof(float));
  367.  
  368.  
  369.       c = 0;
  370.       write(Indx,&c,sizeof(char));        /* Conference # */
  371.  
  372.       if (IsOurs && PIndx != -1)    {    /* Set up PERSONAL area */
  373.          write(PIndx,&out,sizeof(float));
  374.          write(PIndx,&c,sizeof(char));        /* Conference # */
  375.       }
  376.  
  377. /* Now build the messages.dat msg header */
  378.       if (amsg.attr & MSGPRIVATE)
  379.          QMsgHead->Msgstat = '*';
  380.       else {
  381.          if (!(msgupd->attribute & ECHOMAIL)) {        /* Local area */
  382.             if ((amsg.attr & MSGREAD) && IsOurs)
  383.                QMsgHead->Msgstat = '-';
  384.             else QMsgHead->Msgstat = ' ';
  385.          }
  386.          else QMsgHead->Msgstat = ' ';
  387.       }
  388.       sprintf(msg_line,"%d",i);
  389.       ljstring(QMsgHead->Msgnum,msg_line,7);
  390.       sprintf(msg_line,"%02d-%02d-%02d",amsg.date_written.date.mo,amsg.date_written.date.da,
  391.          amsg.date_written.date.yr+80);
  392.       memcpy(QMsgHead->Msgdate,msg_line,8);
  393.       sprintf(msg_line,"%02d:%02d",amsg.date_written.time.hh,amsg.date_written.time.mm);
  394.       memcpy(QMsgHead->Msgtime,msg_line,5);
  395.  
  396.       ljstring(QMsgHead->Msgto,strupr(amsg.to),25);
  397.       ljstring(QMsgHead->Msgfrom,strupr(amsg.from),25);
  398.       ljstring(QMsgHead->Msgsubj,amsg.subj,25);
  399.       sprintf(msg_line,"%d",amsg.reply);
  400.       ljstring(QMsgHead->Msgrply,msg_line,8);
  401.  
  402.       QMsgHead->Msgarealo = (char) (msgupd->areano % 255); /* Lo byte area # */
  403.       QMsgHead->Msgareahi = (char) (msgupd->areano / 255); /* Hi byte area # */
  404.  
  405.       filepos = ftell(MsgFile);        /* save position for later */
  406.       fwrite(QMsgHead,128,1,MsgFile);        /* Write out the header */
  407.  
  408. /* Ok, now the tough part. We have to plunge thru the message buffer
  409.    strip hidden lines, translate cr's to 0xe3, write out
  410.    messge text in 128 byte record chunks. */
  411.  
  412.        j=0;
  413.        start=0;
  414.       while (msgbuffer[j] == '\0') {
  415.          j++;
  416.          start++;
  417.       }
  418.  
  419.       n = 0;
  420.       origin = FALSE;
  421.       newline = TRUE;
  422.       for (j = start; j < (int) size; j++) {
  423.          switch ((byte) msgbuffer[j]) {
  424.             case 1:        /* Hidden line */
  425.                while (msgbuffer[j] != 0x0d && msgbuffer[j] != 0x8d)     /* Skip special lines */
  426.                   j++;
  427.                newline = FALSE;
  428.                break;
  429.  
  430.             case 'S':        /* Maybe a seenby? */
  431.                if (newline) {
  432.                   _fstrncpy((char _far *)temp1,msgbuffer+j,8);
  433.                   temp1[8] = 0;
  434.                   if (strcmpi(temp1,"SEEN-BY:") == 0) {
  435.                      while (msgbuffer[j] != 0x0d)        /* Skip special lines */
  436.                         j++;
  437.                   }
  438.                   else msg_line[n++] = msgbuffer[j];
  439.                   newline = FALSE;
  440.                }
  441.                else msg_line[n++] = msgbuffer[j];
  442.                break;
  443.  
  444.             case ' ':        /* Maybe an origin line? */
  445.                if (newline) {
  446.                   _fstrncpy((char _far *)temp1,msgbuffer+j,10);
  447.                   temp1[10] = 0;
  448.                   if (strcmpi(temp1," * Origin:") == 0) {
  449.                      msg_line[n++] = msgbuffer[j];
  450.                      origin = TRUE;
  451.                   }
  452.                   else msg_line[n++] = msgbuffer[j];
  453.                   newline = FALSE;
  454.                }
  455.                else msg_line[n++] = msgbuffer[j];
  456.                break;
  457.  
  458.             case 'P':
  459.                if (newline) {
  460.                   _fstrncpy((char _far *)temp1,msgbuffer+j,4);
  461.                   temp1[4] = 0;
  462.                   if (strcmpi(temp1,"PATH") == 0) {
  463.                      while (msgbuffer[j] != 0x0d)        /* Skip special lines */
  464.                         j++;
  465.                   }
  466.                   else msg_line[n++] = msgbuffer[j];
  467.                   newline = FALSE;
  468.                }
  469.                else msg_line[n++] = msgbuffer[j];
  470.                break;
  471.  
  472.             case 0x8d:        /* Soft c/r */
  473.             case 0x0d:        /* Standard c/r */
  474.                msg_line[n] = 0xe3;
  475.                n++;
  476.                newline = TRUE;
  477.                if (origin) /* Eliminate further copying after origin line */
  478.                   j = (int) size;
  479.                break;
  480.  
  481.             case 0x0a:        /* Skip linefeeds */
  482.                newline = TRUE;
  483.                break;
  484.  
  485.             case 0:
  486.             case 0x80:
  487.                newline = FALSE;
  488.                break;
  489.  
  490.             default:
  491.                newline = FALSE;
  492.                msg_line[n++] = msgbuffer[j];
  493.                break;
  494.          }
  495.          if (n >= 128) {
  496.             msg_line[128] = 0;
  497.             fwrite(msg_line,128,1,MsgFile);     /* Write out a record */
  498.             n = 0;
  499.             TotRecs++;
  500.             recs++;
  501.             memset(msg_line,' ',128);
  502.          }
  503.       }
  504.       if (n) {        /* Partial record */
  505.          recs++;
  506.          msg_line[128] = 0;
  507.          fwrite(msg_line,128,1,MsgFile);     /* Write out a record */
  508.          TotRecs++;
  509.       }
  510.  
  511. /* Now update with record count */
  512.       fseek(MsgFile,filepos,SEEK_SET);        /* Restore back to header start */
  513.       sprintf(msg_line,"%d",recs);
  514.       ljstring(QMsgHead->Msgrecs,msg_line,6);
  515.       fwrite(QMsgHead,128,1,MsgFile);        /* Write out the header */
  516.       fseek(MsgFile,0L,SEEK_END);        /* Bump back to end of file */
  517.    }
  518.    return(i);        /* No errors!, return message number */
  519. }
  520.  
  521. /* QWK handling cleanup */
  522. void closeqwk(void)
  523. {
  524.    if (Indx != -1) {
  525.       close(Indx);
  526.       Indx = -1;
  527.    }
  528.  
  529.    if (PIndx != -1) {
  530.       close(PIndx);
  531.       PIndx = -1;
  532.    }
  533.  
  534.    if (MsgFile != NULL) {
  535.       fclose(MsgFile);
  536.       MsgFile = NULL;
  537.    }
  538. }
  539.  
  540. /* Convert an IEEE floating point number to MSBIN
  541.    floating point decimal */
  542.  
  543. float IEEToMSBIN(float f)
  544. {
  545.    union Converter t;
  546.    int   sign,exp;
  547.  
  548.    t.f[0] = f;
  549.  
  550. /* Extract sign & change exponent bias from 0x7f to 0x81 */
  551.  
  552.    sign = t.uc[3] / 0x80;
  553.    exp  = ((t.ui[1] >> 7) - 0x7f + 0x81) & 0xff;
  554.  
  555. /* reassemble them in MSBIN format */
  556.    t.ui[1] = (t.ui[1] & 0x7f) | (sign << 7) | (exp << 8);
  557.    return t.f[0];
  558. }
  559.  
  560.  
  561. /* Fetch REP packet from user and import if ok */
  562. void getrep(void)
  563. {
  564.    int x,y,z,msgfile;
  565.    int endspace;
  566.    char  *msgbuff,*p;
  567.    struct dostime_t time;
  568.    struct dosdate_t date;
  569.    struct QWKmsghd *MsgHead;
  570.    struct msgupd_st *msgupd;
  571.  
  572.    if (repupload() > 0) {        /* We have received a REP packet perhaps */
  573.       Aindex = sopen(PRM(aidx_name),O_BINARY | O_RDONLY,SH_DENYNO,S_IREAD);
  574.       if (Aindex == -1)
  575.          aborterror(FILEOPEN,"Error opening Area index file");
  576.       tempdir();
  577.       sprintf(temp,"%s.rep",BBSid);
  578.       if(!extractarc(temp)) {        /* Parse the bbs.msg file and import */
  579.          upmsgs = 0;
  580.          confreqs = 0;
  581.          sprintf(temp,"%s.msg",BBSid);
  582.          repfile = sopen(temp,O_BINARY | O_RDONLY,SH_DENYRW,S_IREAD);
  583.          if (repfile >= 0) {
  584.             MsgHead = (struct QWKmsghd *) malloc(sizeof(struct QWKmsghd));
  585.             if (MsgHead == NULL)
  586.                aborterror(BADALLOC,NULL);
  587.             msgbuff = (char *) malloc(150);
  588.             if (msgbuff == NULL)
  589.                aborterror(BADALLOC,NULL);
  590.             read(repfile,msgbuff,128);        /* Ignore first record */
  591.             msgbuff[8] = 0;
  592.             stripwhite(msgbuff);
  593.             RP1 = NULL;
  594.             if (strcmpi(BBSid,msgbuff) == 0) {        /* Make sure it's ours! */
  595.                setcolor(TextAttr[STD_TEXT]);
  596.                strout("\r\nHang on while I import the messages.\r\n\r\n");
  597.                setcolor(TextAttr[HILITE_TEXT]);
  598.                x = read(repfile,(struct QWKmsghd *) MsgHead,128);
  599.                while (x == 128) {        /* This is the BBS.MSG import loop */
  600.          /* Build the Fidonet message head */
  601.                   x = atoi(MsgHead->Msgnum);        /* Area number */
  602.                   rp = RP1;
  603.                   RPprev = RP1;
  604.                   while (rp != NULL) {        /* Search for same area */
  605.                      if (rp->areano == x)
  606.                         break;
  607.                      else {
  608.                         RPprev = rp;
  609.                         rp = rp->next;
  610.                      }
  611.                   }
  612.                   if (rp == NULL) {        /* New message area */
  613.                      rp = (struct repmsg _far *) _fmalloc(sizeof(struct repmsg));
  614.                      if (rp == NULL)
  615.                         aborterror(BADALLOC,NULL);
  616.                      rp->count = 0;
  617.                      rp->next = NULL;
  618.                      rp->areano = x;
  619.                      rp->flags = 0;
  620.                      if (RP1 == NULL) {        /* First one */
  621.                         RP1 = rp;
  622.                      }
  623.                      else RPprev->next = rp;        /* Link it in */
  624.                   }
  625.                   msgupd = MSGUPD_1;
  626.                   while (msgupd != NULL) {        /* Is it selected area? */
  627.                      if (msgupd->areano == (word) x)
  628.                         break;
  629.                      else msgupd = msgupd->next;
  630.                   }
  631.                   if (msgupd == NULL) { /* Not user selected area, create a fake one */
  632.                      msgupd = (struct msgupd_st *) malloc(sizeof(struct msgupd_st));
  633.                      if (msgupd != NULL) {
  634.                         msgupd->areano = x;
  635.                         if ((lseek(Aindex,(long) (x * sizeof(struct _aidx)),SEEK_SET)) != -1L) {
  636.                            if((read(Aindex,(char *)&IDX,sizeof(struct _aidx))) == sizeof(struct _aidx)) {
  637.                               fseek(afile,IDX.offset,SEEK_SET);
  638.                               fread(&AREA,astrlen,1,afile);
  639.                               msgupd->attribute = (word) AREA.attrib[UserClass];
  640.                               msgupd->next = NULL;
  641.                               if (AREA.msgpath[0] && (AREA.areano == IDX.area)) {
  642.                                  strcpy(msgupd->msgpath,AREA.msgpath);
  643.                                  msgupd->update = -2;        /* Flag that its fake */
  644.                                  msgupd->readmsgs = 0;        /* # of replies */
  645.                               }
  646.                               else {
  647.                                  free(msgupd);
  648.                                  msgupd = NULL;
  649.                               }
  650.                            }
  651.                            else {
  652.                               free(msgupd);
  653.                               msgupd = NULL;
  654.                            }
  655.                         }
  656.                         else {
  657.                            free(msgupd);
  658.                            msgupd = NULL;
  659.                         }
  660.                      }
  661.                   }
  662.                   upmsgs++;
  663.                   sprintf(temp,"Importing message # %d\r",upmsgs);
  664.                   strout(temp);
  665.                   if (msgupd != NULL) { /* Create the fidonet message */
  666.                      msgrecs = atoi(MsgHead->Msgrecs) - 1;
  667.                   /* Parse date and time junk */
  668.                      strncpy(temp,MsgHead->Msgdate,8);
  669.                      temp[8] = 0;
  670.                      p = strtok(temp,"-");        /* Fetch month */
  671.                      x = amsg.date_written.date.mo = atoi(p);
  672.                      p = strtok(NULL,"-");        /* Fetch day */
  673.                      z = amsg.date_written.date.da = atoi(p);
  674.                      p = strtok(NULL," \0-");        /* Fetch year */
  675.                      y = amsg.date_written.date.yr = (atoi(p) - 80);
  676.  
  677.                      strncpy(temp,MsgHead->Msgtime,5);
  678.                      temp[5] = 0;
  679.                      sprintf(amsg.date,"%d %s %d %s:00",z,monthstr[x-1],y+80,temp);
  680.  
  681.                      p = strtok(temp,":");        /* Fetch hour */
  682.                      amsg.date_written.time.hh = atoi(p);
  683.                      p = strtok(NULL,"\0:");        /* Fetch minutes */
  684.                      amsg.date_written.time.mm = atoi(p);
  685.                      amsg.date_written.time.ss = 0; /* Clear seconds */
  686.  
  687.                      _dos_getdate(&date);
  688.                      _dos_gettime(&time);
  689.  
  690.                      amsg.date_arrived.date.mo = date.month;
  691.                      amsg.date_arrived.date.da = date.day;
  692.                      amsg.date_arrived.date.yr = date.year - 1980;
  693.                      amsg.date_arrived.time.hh = time.hour;
  694.                      amsg.date_arrived.time.mm = time.minute;
  695.                      amsg.date_arrived.time.ss = time.hsecond;
  696.                      amsg.attr = 0;
  697.                      if (MsgHead->Msgstat == '*') {
  698.                         if (!(msgupd->attribute & NOPRIVATE))
  699.                            amsg.attr |= MSGPRIVATE;
  700.                      }
  701.                      amsg.orig = prm.address[0].Node;     /* Original node number */
  702.                      amsg.orig_net = prm.address[0].Net; /* Original net number */
  703.                      amsg.dest = prm.address[0].Node;     /* Original node number */
  704.                      amsg.dest_net = prm.address[0].Net; /* Original net number */
  705.                      amsg.reply = atoi(MsgHead->Msgrply);
  706.                      amsg.times = 1;
  707.                      amsg.up = 0;
  708.                      amsg.cost = 0;
  709.    
  710.                      memset(amsg.from,0,36);
  711.                      memset(amsg.to,0,36);
  712.                      memset(amsg.subj,0,72);
  713.                      strcpy(amsg.to,namefixup(MsgHead->Msgto));
  714.                      strcpy(amsg.from,namefixup(MsgHead->Msgfrom));
  715.                      strcpy(amsg.subj,namefixup(MsgHead->Msgsubj));
  716.  
  717.                      if(!qwkfunct(msgupd,msgbuff)) {        /* A genuine message */
  718.                      /* Ok write out the fidonet header */
  719.                         lseek(Aindex,(long) (msgupd->areano * sizeof(struct _aidx)),SEEK_SET);
  720.                         read(Aindex,(char *)&IDX,sizeof(struct _aidx));
  721.                         fseek(afile,IDX.offset,SEEK_SET);
  722.                         fread(&AREA,astrlen,1,afile);
  723.                         switch (AREA.area_type) {
  724.                            case 0:        /* Fido 1.msg style */
  725.                               msgupd->himsg = find_fidohigh(AREA.msgpath);
  726.                               break;
  727.  
  728.                            default:
  729.                               msgupd->himsg = find_fidohigh(AREA.msgpath);
  730.                               break;
  731.                         }
  732.                         if (msgupd->himsg == 0xffff )
  733.                            msgupd->himsg = 0;
  734.                         msgupd->startmsg = get_lastread(msgupd->msgpath);
  735.                         sprintf(temp1,"%s%d.msg",msgupd->msgpath,msgupd->himsg+1);
  736.                         msgfile = sopen(temp1,O_TRUNC | O_CREAT | O_BINARY | O_RDWR,SH_DENYRW,S_IWRITE);
  737.                         y = sizeof(struct _msg);
  738.                         write(msgfile,(char *) &amsg,y);
  739.                         rp->count += 1;
  740.  
  741.                   /* Now prepare to read in the REP msg and convert to fidonet */
  742.                         for (x=0; x < msgrecs; x++) {
  743.                            read(repfile,msgbuff,128);
  744.                            msgbuff[128] = 0;
  745.                            p = strchr(msgbuff,0xe3);        /* Look for special linefeeds */
  746.                            while (p) {
  747.                               *p = 0x0d;        /* Replace as a cr */
  748.                               p = strchr(p+1,0xe3);
  749.                            }
  750.                            p = msgbuff + 127;
  751.                            endspace = TRUE;
  752.                   /* Now go backwards and strip out '---' after a c/r */
  753.                            while (p > msgbuff) {
  754.                               if (*p == '-' && StripTags && (msgupd->attribute & ECHOMAIL)) {
  755.                                  endspace = FALSE;
  756.                                  p--;
  757.                                  if (*p == '-') {
  758.                                     p--;
  759.                                     if (*p == '-') {
  760.                                        if (*(p-1) == '\r') {
  761.                                           *p = ' ';
  762.                                           *(p+1) = ' ';
  763.                                           *(p+2) = ' ';
  764.                                        }
  765.                                        break;
  766.                                     }
  767.                                  }
  768.                               }
  769.                               if (*p & 0x80) {    /* Hi bit set? */
  770.                                  if(!(msgupd->attribute & HIGHBIT))
  771.                                     *p &= 0x7f;        /* Make it harmless */
  772.                                  endspace = FALSE;
  773.                               }
  774.                               if ((x == (msgrecs - 1)) && *p == ' ' && endspace && *(p-1) == ' ') 
  775.                                  *p = 0;
  776.                               else endspace = FALSE;
  777.                               p--;
  778.                            }
  779.                            y = strlen(msgbuff);
  780.                            write(msgfile,msgbuff,y);
  781.                         }
  782.                         strcpy(msgbuff,"\r\n");
  783.                         write(msgfile,msgbuff,3);
  784.                         close(msgfile);
  785.                         msgupd->startmsg++;
  786.                         msgupd->himsg++;
  787.                         adjust_lastread(msgupd->msgpath,msgupd->himsg);
  788.                         if (msgupd->update == -2)     /* A fake one? */
  789.                            free(msgupd);
  790.                      }
  791.                   }
  792.                   else {        /* Invlaid message, skip to next one */
  793.                      msgrecs = atoi(MsgHead->Msgrecs) - 1;
  794.                      for (x=0; x < msgrecs; x++) 
  795.                         read(repfile,msgbuff,128);
  796.                   }
  797.                   x = read(repfile,(struct QWKmsghd *) MsgHead,128);
  798.                }
  799.                free(MsgHead);
  800.                free(msgbuff);
  801.                close(repfile);
  802.             }
  803.             else {
  804.                setcolor(TextAttr[ATTN_TEXT]);
  805.                strout("\r\nSorry, but this REP packet is not addressed to us!\r\n\r\n");
  806.                logit("REP packet upload has invalid BBS id",'!');
  807.             }
  808.          }
  809.          else {
  810.             setcolor(TextAttr[ATTN_TEXT]);
  811.             strout("\r\nSorry but the REP pack can not be opened.\r\n");
  812.             logit("REP open file error",'!');
  813.          }
  814.       }
  815.       else {
  816.          setcolor(TextAttr[ATTN_TEXT]);
  817.          strout("\r\nSorry but the REP pack can not be extracted.\r\n");
  818.          logit("REP packet extraction error",'!');
  819.       }
  820.    /* Cleanup */
  821.       sprintf(temp,"%s.rep",BBSid);
  822.       unlink(temp);
  823.       sprintf(temp,"%s.msg",BBSid);
  824.       unlink(temp);
  825.       homedir();
  826.       if (upmsgs) {
  827.          Exitcode = 6;
  828.          HaveUpl = TRUE;
  829.          sprintf(temp,"Total of %d messages were uploaded",upmsgs);
  830.          setcolor(TextAttr[MENU_KEY]);
  831.          strout("\r\n");
  832.          strout(temp);
  833.          strout("\r\n");
  834.          logit(temp,'#');
  835.          setcolor(TextAttr[HILITE_TEXT]);
  836.          rp = RP1;
  837.          while (rp) {
  838.             if (rp->count) {        /* A valid import message */
  839.                lseek(Aindex,(long) (rp->areano * sizeof(struct _aidx)),SEEK_SET);
  840.                read(Aindex,(char *)&IDX,sizeof(struct _aidx)); 
  841.                fseek(afile,IDX.offset,SEEK_SET);
  842.                fread(&AREA,astrlen,1,afile);
  843.                strncpy(temp1,AREA.msginfo,25);
  844.                temp1[25] = 0;
  845.                stripwhite(temp1);
  846.                sprintf(temp,"Importing %d messages into [%s]",rp->count,temp1);
  847.                strout(temp);
  848.                strout("\r\n");
  849.                logit(temp,'#');
  850.             }
  851.             else {
  852.                if (rp->flags == 0) 
  853.                   sprintf(temp,"Messages to area # %d were ignored",rp->areano);
  854.                else sprintf(temp,"Messages to area # %d were MaxMail commands",rp->areano);
  855.                strout(temp);
  856.                strout("\r\n");
  857.                logit(temp,'#');
  858.             }
  859.             RPprev = rp;
  860.             rp = rp->next;
  861.             _ffree(RPprev);
  862.          }
  863.       }
  864.       setcolor(TextAttr[HILITE_TEXT]);
  865.       strout("\r\n");
  866.       if (confreqs) {
  867.          sprintf(temp,"User made %d requests for area changes",confreqs);
  868.          strout(temp);
  869.          strout("\r\n");
  870.          logit(temp,'#');
  871.       }
  872.       close(Aindex);
  873.    }
  874. }
  875.  
  876. /* Test and process special door functions from QWK messages.
  877.    return FALSE if none */
  878. int qwkfunct(struct msgupd_st *msgupd,char *msgbuff)
  879. {
  880.    char *p;
  881.  
  882.    if ((strcmpi(amsg.to,"QMAIL") == 0)  ||        /* Default */
  883.          (strcmpi(amsg.to,"MAXMAIL") == 0)) {        /* Uh oh, its for us! */
  884.       rp->flags |=  RP_CMDFLAG;
  885.       if (strcmpi(amsg.subj,"CONFIG") == 0) {        /* Sometimes its this one */
  886.          read(repfile,msgbuff,128);
  887.          msgbuff[128] = 0;
  888.          stripwhite(msgbuff);
  889.          p = strtok(msgbuff," \n\r");
  890.          if (strcmpi(p,"ADD") == 0) {        /* Add this conference */
  891.             if(!isskiparea(msgupd->areano)) {
  892.                if(is_selarea(msgupd->areano)) {
  893.                   sprintf(temp,"You already have Conference #%03d enabled\r\n",msgupd->areano);
  894.                   setcolor(TextAttr[ATTN_TEXT]);
  895.                   strout(temp);
  896.                }
  897.                else {
  898.                   sprintf(temp,"Adding conference #%03d",msgupd->areano);
  899.                   strout(temp);
  900.                   logit(temp,'#');
  901.                   strout("\r\n");
  902.                   msgmark(msgupd->areano);
  903.                   confreqs++;
  904.                   upmsgs--;
  905.                }
  906.             }
  907.          }
  908.          else if (strcmpi(p,"DROP") == 0) {        /* Remove this conference */
  909.             if(!isForcearea(msgupd->areano)) {
  910.                if (!is_selarea(msgupd->areano)) {
  911.                   sprintf(temp,"Conference #%03d was not enabled\r\n",msgupd->areano);
  912.                   setcolor(TextAttr[ATTN_TEXT]);
  913.                   strout(temp);
  914.                }
  915.                else {
  916.                   sprintf(temp,"Dropping conference #%03d",msgupd->areano);
  917.                   strout(temp);
  918.                   logit(temp,'#');
  919.                   strout("\r\n");
  920.                   confreqs++;
  921.                   msgunmark(msgupd->areano);
  922.                   upmsgs--;
  923.                }
  924.             }
  925.          }
  926.       }
  927.       else if (strcmpi(amsg.subj,"DROP") == 0) {        /* But usually this way */
  928.          read(repfile,msgbuff,128);        /* Drop a conference */
  929.          if(!isForcearea(msgupd->areano)) {
  930.             if(!is_selarea(msgupd->areano)) {
  931.                sprintf(temp,"Conference #%03d was not enabled\r\n",msgupd->areano);
  932.                setcolor(TextAttr[ATTN_TEXT]);
  933.                strout(temp);
  934.             }
  935.             else {
  936.                sprintf(temp,"Dropping conference #%03d",msgupd->areano);
  937.                strout(temp);
  938.                logit(temp,'#');
  939.                strout("\r\n");
  940.                confreqs++;
  941.                msgunmark(msgupd->areano);
  942.                upmsgs--;
  943.             }
  944.          }
  945.       }
  946.       else if (strcmpi(amsg.subj,"ADD") == 0) {
  947.          read(repfile,msgbuff,128);        /* Add a conference */
  948.          if(!isskiparea(msgupd->areano)) {
  949.             if(is_selarea(msgupd->areano)) {
  950.                sprintf(temp,"You already have Conference #%03d enabled\r\n",msgupd->areano);
  951.                setcolor(TextAttr[ATTN_TEXT]);
  952.                strout(temp);
  953.             }
  954.             else {
  955.                sprintf(temp,"Adding conference #%03d",msgupd->areano);
  956.                strout(temp);
  957.                logit(temp,'#');
  958.                strout("\r\n");
  959.                msgmark(msgupd->areano);
  960.                confreqs++;
  961.                upmsgs--;
  962.             }
  963.          }
  964.       }
  965.       return TRUE;
  966.    }
  967.    else return FALSE;
  968. }
  969.  
  970. char *namefixup(char *name)
  971. {
  972.    int x,y;
  973.    static char tname[81];
  974.  
  975.    strncpy(tname,name,80);
  976.    tname[20] = 0;
  977.    stripwhite(tname);
  978.    strlwr(tname);
  979.  
  980.    tname[0] = (char) toupper((int) tname[0]);
  981.    y = (int) strlen(tname);
  982.  
  983.    for (x = 0; x < y; x++) {
  984.       if (isspace(tname[x])) {
  985.          x++;
  986.          tname[x] = (char) toupper((int) tname[x]);
  987.       }
  988.    }
  989.    return (&tname[0]);
  990. }
  991.  
  992.