home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / BBS / MISC / XSRC_117.ZIP / XMSGOUT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-27  |  32.6 KB  |  1,095 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*   XBBS SOURCE CODE copyright (c) 1990 by M. Kimes                        */
  4. /*   All Rights Reserved                                                    */
  5. /*                                                                          */
  6. /*    For complete details of the licensing restrictions, please refer      */
  7. /*    to the License agreement, which is published in its entirety in       */
  8. /*    the in the file LICENSE.XBS.                                          */
  9. /*                                                                          */
  10. /*    USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE      */
  11. /*    XBBS LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF            */
  12. /*    THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO       */
  13. /*    NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT M. KIMES         */
  14. /*    AT THE ADDRESS LISTED BELOW.  IN NO EVENT SHOULD YOU PROCEED TO USE   */
  15. /*    THIS FILE WITHOUT HAVING ACCEPTED THE TERMS OF THE XBBS LICENSING     */
  16. /*    AGREEMENT, OR SUCH OTHER AGREEMENT AS YOU ARE ABLE TO REACH WITH      */
  17. /*    M. KIMES                                                              */
  18. /*                                                                          */
  19. /*                                                                          */
  20. /* You can contact M. Kimes at the following address:                       */
  21. /*                                                                          */
  22. /* M. Kimes                         1:380/16.0@FidoNet                      */
  23. /* 542 Merrick                      (318)222-3455 data                      */
  24. /* Shreveport, LA  71104                                                    */
  25. /*                                                                          */
  26. /*                                                                          */
  27. /* Please feel free to contact me at any time to share your comments about  */
  28. /* my software and/or licensing policies.                                   */
  29. /*                                                                          */
  30. /*--------------------------------------------------------------------------*/
  31. /*======================================================================*/
  32. /*  XBBS Bulletin Board System.....Msg writing routines                 */
  33. /*======================================================================*/
  34.  
  35. #include "msg.h"
  36. #include "xext.h"
  37.  
  38. long pascal make_msgid (void);
  39.  
  40.  
  41.  
  42. word pascal makemessage (char type) {
  43.      /* Makes a msg from a MSGTMP? and header struct */
  44.  
  45.  int comval;
  46.  static char comstring[26]="";
  47.  word register x;
  48.  char filename[127];
  49.  char textname[127];
  50.  char *p;
  51.  char message[81];
  52.  word lenmess;
  53.  struct date dos_date;
  54.  int handlem;
  55.  int handlet=-1;
  56.  int handlef;
  57.  long mlen;
  58.  long tlen;
  59.  long flen;
  60.  struct ffblk f;
  61.  char numcarbons=0;
  62.  
  63.  /* Make checks to see if message good... */
  64.  
  65.  if(!*comstring) {
  66.       strncpy(comstring,say_prompt(435),26);
  67.  }
  68.  
  69.  msg.o_point=0;
  70.  if (nodenumber!=1) sprintf(message,"MSGTMP%hu",nodenumber);
  71.  else strcpy(message,"MSGTMP");
  72.  strcpy(filename,message);
  73.  strcat(filename,".HDR");
  74.  strcpy(textname,message);
  75.  strcat(textname,".INF");
  76.  unlink(textname);
  77.  level=0;
  78.  if (findfirst(message,&filestat,0)) level=1;
  79.  
  80. Aborted:
  81.  
  82.   printm("\n");
  83.   carrchk();
  84.   if(level==1) {
  85.     say_prompt(54);
  86.     unlink(message);
  87.     unlink(filename);
  88.     return(1);
  89.   }
  90.   else if ((filestat.ff_fsize)<3L) {
  91.     level=1;
  92.     goto Aborted;
  93.   }
  94.  
  95.   if(!findfirst(filename,&filestat,0)) {
  96.     handlem=oopen(filename,O_RDONLY | O_DENYNONE | O_BINARY);
  97.     if(handlem!=-1) {
  98.         while(!eof(handlem)) {
  99.             fgetsx(filename,127,handlem);
  100.             stripcr(filename);
  101.             p=strtok(filename," ");
  102.             p=strtok(0,"\n");
  103.             if(!stricmp(filename,"NEWTO")) {
  104.                 if((!(msg.attr & MSGPRIVATE)) && (strcmp(mboard.forceto,msg.to))) {
  105.                     strncpy(msg.to,p,36);
  106.                     msg.to[35]=0;
  107.                     handlet=0;
  108.                 }
  109.             }
  110.             if(!stricmp(filename,"NEWSUBJ")) {
  111.                 strncpy(msg.subj,p,64);
  112.                 msg.subj[63]=0;
  113.                 handlet=0;
  114.             }
  115.         }
  116.     }
  117.     cclose(handlem);
  118.   }
  119.   if (!(type & 8)) {
  120.     while (1) {             /* Pre-save menu */
  121.       if(handlet!=-1) {
  122.           if ((mboard.attr & ECHO) || (mboard.attr & ALTECHO) &&
  123.               (mboard.attr & NET) || (mboard.attr & ALTERNATE) &&
  124.               (mboard.attr & ANSI) || ((*mboard.forceto) ||
  125.               !(mboard.forceto==NULL)) || (!conf.carbons)) break;
  126.       }
  127.       say_prompt(332);
  128.       printm(msg.subj);
  129.       say_prompt(333);
  130.       printm(msg.to);
  131.       if (numcarbons) {
  132.         for(x=0;x<numcarbons;x++) {
  133.             gprintf(0,"\nCC:   %s",&buffer[650+(37*x)]);
  134.         }
  135.       }
  136.       say_prompt(55);
  137.       if ((!(msg.attr & MSGPRIVATE)) && (strcmp(mboard.forceto,msg.to))) {
  138.         say_prompt(334);
  139.       }
  140.       if (!(mboard.attr & ECHO) && !(mboard.attr & ALTECHO) &&
  141.           !(mboard.attr & NET) && !(mboard.attr & ALTERNATE) &&
  142.           !(mboard.attr & ANSI) && ((!*mboard.forceto) ||
  143.           (mboard.forceto==NULL)) && (conf.carbons)) {
  144.             if(numcarbons<conf.carbons)say_prompt(414);
  145.             if (numcarbons) say_prompt(417);
  146.       }
  147.       say_prompt(335);
  148.       helpnum=537;
  149.       p=genin(1,0,1,1,ALPHA);
  150.       helpnum=0;
  151.       if(*p) comval=-1;
  152.       else comval=0;
  153.       if(comval) {
  154.         for(x=0;x<6;x++) {
  155.             if(!comstring[x])break;
  156.             if(*p==comstring[x]) {
  157.                 comval=(int)x+1;
  158.                 break;
  159.             }
  160.         }
  161.       }
  162.       switch (comval) {
  163.         case 1:       /* Abort it */
  164.             printm("\n");
  165.             level=1;
  166.             goto Aborted;
  167.         case 2:       /* Finished, save it */
  168.         case 0:
  169.             printm("\n");
  170.             goto BreakOut;
  171.         case 3:       /* Change Subject field */
  172.             say_prompt(56);
  173.             helpnum=538;
  174.             strcpy(message,genin(64,0,0,0,SUBJECT));
  175.             helpnum=0;
  176.             if (!strlen(message)) break;
  177.             strcpy(msg.subj,message);
  178.             break;
  179.         case 4: say_prompt(430);
  180.                            break;
  181.         case 5:       /* Change To field */
  182.             if ((!(msg.attr & MSGPRIVATE)) && (strcmp(mboard.forceto,msg.to))) {
  183.                 say_prompt(319);
  184.                 helpnum=539;
  185.                 strcpy(message,genin(36,0,0,0,NAME));
  186.                 helpnum=0;
  187.                 if (strlen(message)) strcpy(msg.to,message);
  188.             }
  189.         case 6:       /* Carbon maker */
  190.             if (!(mboard.attr & ECHO) && !(mboard.attr & ALTECHO) &&
  191.                   !(mboard.attr & NET) && !(mboard.attr & ALTERNATE) &&
  192.                   !(mboard.attr & ANSI) && (!*mboard.forceto ||
  193.                   mboard.forceto==NULL) && (conf.carbons)) {
  194.                 if(numcarbons<conf.carbons) {
  195.  
  196.                     char temp[37];
  197.  
  198.                     say_prompt(415);
  199.                     helpnum=540;
  200.                     strcpy(temp,genin(36,0,0,0,NAME));
  201.                     helpnum=0;
  202.                     for(x=0;x<numcarbons;x++) {
  203.                         if(!strcmp(temp,&buffer[650+(37*x)])) break;
  204.                     }
  205.                     if(verify_user(temp))break;
  206.                     strcpy(&buffer[650+(37*numcarbons)],temp);
  207.                     if(buffer[650+(37*numcarbons)]==0) break;
  208.                     numcarbons++;
  209.                 }
  210.             }
  211.             break;
  212.         case 7:       /* Delete last carbons */
  213.             if (numcarbons) numcarbons--;
  214.             break;
  215.       }
  216.     }
  217.   }
  218. BreakOut:       /* Set up save filenames */
  219.   sprintf(filename,"%sXDATA.%03x",messpath,mboard.number);
  220.   sprintf(textname,"%sXTEXT.%03x",messpath,mboard.number);
  221.  
  222. AccessLoop1:    /* Open datafile, loop if no access */
  223.   if (findfirst(filename,&f,0)) flen=0;
  224.   else flen=f.ff_fsize;
  225.   if ((handlef=oopen(filename,O_RDWR | O_BINARY | O_DENYNONE))==-1)
  226.     if ((handlef=ccreat(filename,S_IWRITE))==-1) {
  227.         if (errno==EACCES) {
  228.             say_prompt(57);
  229.             carrchk();
  230.             getxbbstime();
  231.             goto AccessLoop1;
  232.         }
  233.         say_prompt(58);
  234.         return(4);
  235.     }
  236.     if (conf.share) {
  237.         x=0;
  238.         while (lock(handlef,flen,(long)sizeof(struct _xmsg))){
  239.             x++;
  240.             if(x>2) {
  241.                 say_prompt(50);
  242.                 return 1;
  243.             }
  244.             say_prompt(57);
  245.             sleep(1);
  246.         }
  247.     }
  248.     lseek(handlef,0L,SEEK_END);
  249.  
  250. AccessLoop:     /* Open textfile, loop if no access */
  251.   if (findfirst(textname,&f,0))tlen=0;
  252.   else tlen=f.ff_fsize;
  253.   if ((handlet=oopen(textname,O_RDWR | O_BINARY | O_DENYNONE))==-1)
  254.     if((handlet=ccreat(textname,S_IWRITE))==-1) {
  255.         if (errno==EACCES) {
  256.             say_prompt(57);
  257.             carrchk();
  258.             getxbbstime();
  259.             goto AccessLoop;
  260.         }
  261.         say_prompt(59);
  262.         cclose(handlef);
  263.         return(4);
  264.     }
  265.     if (conf.share) {
  266.         x=0;
  267.         while (lock(handlet,tlen,65535L)){
  268.             x++;
  269.             if(x>2) {
  270.                 say_prompt(50);
  271.                 return 1;
  272.             }
  273.             say_prompt(57);
  274.             sleep(1);
  275.         }
  276.     }
  277.     lseek(handlet,0L,SEEK_END);
  278.  
  279.   /* Open MSGTMP? file */
  280.  
  281.  if (nodenumber!=1) sprintf(message,"MSGTMP%hu",nodenumber);
  282.  else strcpy(message,"MSGTMP");
  283.  if (findfirst(message,&f,0)) mlen=0;
  284.  else mlen=f.ff_fsize;
  285.  if ((handlem=oopen(message,O_RDONLY | O_BINARY | O_DENYNONE))==-1) {
  286.    say_prompt(60);
  287.    cclose(handlef);
  288.    cclose(handlet);
  289.    return(4);
  290.  }
  291.  if(conf.share)lock(handlem,0L,mlen);
  292.  msg.start=(ulong)tell(handlet);
  293.  lenmess=0;
  294.  
  295.  /* Kludge lines for netmail */
  296.  
  297.    lastfilemsgid=make_msgid();
  298.    if (mboard.attr & ALTECHO || mboard.attr & ALTERNATE)
  299.       lenmess+=ffprintf(handlet,"\01MSGID: %u:%u/%01u.0@%s %lX\r",conf.alt_zone,conf.alt_net,conf.alt_node,conf.alt_domain,lastfilemsgid);
  300.    else lenmess+=ffprintf(handlet,"\01MSGID: %u:%u/%01u.0@%s %lX\r",conf.zone,conf.net,conf.node,conf.domain,lastfilemsgid);
  301.  
  302.    if(*replyid) {
  303.         lenmess+=ffprintf(handlet,"\01REPLY: %s\r",replyid);
  304.         *replyid=0;
  305.    }
  306.  
  307.    if ((mboard.attr & NET) || (mboard.attr & ALTERNATE)) {
  308.       lenmess+=ffprintf(handlet,"\01MSGTO: %u:%u/%01u.%01u@%s\r",msg.d_zone,msg.dest_net,msg.dest,msg.d_point,to_domain);
  309.  
  310.         if(mboard.attr & NET) {
  311.             if (conf.zone!=msg.d_zone && msg.d_zone && conf.zone) {
  312.                 lenmess+=ffprintf(handlet,"\01INTL %u:%u/%u %u:%u/%u\r",msg.d_zone,msg.dest_net,msg.dest,conf.zone,conf.net,conf.node);
  313.             }
  314.             else msg.d_zone=conf.zone;
  315.         }
  316.         else {
  317.             if (conf.alt_zone!=msg.d_zone && msg.d_zone && conf.alt_zone) {
  318.                 lenmess+=ffprintf(handlet,"\01INTL %u:%u/%u %u:%u/%u\r",msg.d_zone,msg.dest_net,msg.dest,conf.alt_zone,conf.alt_net,conf.alt_node);
  319.             }
  320.             else msg.d_zone=conf.alt_zone;
  321.         }
  322.         if(msg.d_point) lenmess+=ffprintf(handlet,"\01TOPT %01u\r",msg.d_point);
  323.    }
  324.    if(*msginfo) {
  325.         lenmess+=ffprintf(handlet,"\01INFO: %s\r",msginfo);
  326.         *msginfo=0;
  327.    }
  328.  
  329.     /* Kludge lines for associated messages */
  330.  
  331.  if ((mboard.attr & ASSOC) && (fboard.flags & FILEASSOC) && *assocfile) {
  332.     lenmess+=ffprintf(handlet,"\01ASSOC: %s\r",assocfile);
  333.  }
  334.  
  335.  while(!eof(handlem)) {     /* Load and save MSGTMP? */
  336.    if (!fgetsx(message,81,handlem)) break;
  337.    while (p=strstr(message,"\r\n")) memmove(&p[1],&p[2],strlen(&p[2])+1);
  338.    while (p=strchr(message,'\n')) *p='\r';
  339.    while (p=strstr(message," \x8d")) memmove(&p[1],&p[2],strlen(&p[2])+1);
  340.    while (p=strchr(message,'\x8d')) *p=' ';
  341.    while (p=strchr(message,'\x1a')) memmove(p,&p[1],strlen(&p[1])+1);
  342.    lenmess+=strlen(message);
  343.    _write(handlet,message,strlen(message));
  344.    if(lenmess>65100) break;
  345.  }
  346.  if(conf.share)unlock(handlem,0L,mlen);
  347.  cclose(handlem);
  348.  msg.m_attr=(msg.m_attr | MSGTREATED);
  349.  
  350.  if (numcarbons) {      /* Tack carbon notes on the end */
  351.     lenmess+=ffprintf(handlet,"%s%s\r",say_prompt(100),msg.to);
  352.     for(x=0;x<numcarbons;x++) {
  353.         lenmess+=ffprintf(handlet,"%s%s\r",say_prompt(124),&buffer[650+(37*x)]);
  354.     }
  355.  }
  356.  
  357.  if ((mboard.attr & ECHO) || (mboard.attr & ALTECHO)) {     /* Origins for echo mail */
  358.  
  359.    word tempzone;
  360.    word tempnet;
  361.    word tempnode;
  362.  
  363.    if(mboard.attr & ECHO) {
  364.         tempzone=conf.zone;
  365.         tempnet=conf.net;
  366.         tempnode=conf.node;
  367.    }
  368.    else {
  369.         tempzone=conf.alt_zone;
  370.         tempnet=conf.alt_net;
  371.         tempnode=conf.alt_node;
  372.    }
  373.    if (mboard.attr & ANSI) lenmess+=ffprintf(handlet,"\x1b[22;1H\x1b[K");
  374.    sprintf(buffer,"%sORIGINS.BBS",messpath);
  375.    if ((handlem=oopen(buffer,O_RDONLY | O_TEXT | O_DENYNONE))==-1) goto SkipOrigins;
  376.    while (!(eof(handlem)) && (atoi(message)!=mboard.number)) {
  377.      fgetsx(message,80,handlem);
  378.      message[66]=0;
  379.      stripcr(message);
  380.    }
  381.    cclose(handlem);
  382.    if (atoi(message)!=mboard.number) goto SkipOrigins;
  383.    strtok(message,"; ");
  384.    lenmess+=(ffprintf(handlet,"\r\n--- XBBS %s\r\n * Origin: %s (%u:%u/%u)\r",XVERSION,strtok(0,"\n"),tempzone,tempnet,tempnode));
  385.    goto GotOrigin;
  386. SkipOrigins:
  387.    lenmess+=(ffprintf(handlet,"\r\n--- XBBS %s\r\n * Origin: %s (%u:%u/%u)\r",XVERSION,conf.origin,tempzone,tempnet,tempnode));
  388.  }
  389.  else {
  390.     _write(handlet,"\r",1);
  391.     lenmess++;
  392.  }
  393.  
  394. GotOrigin:
  395.  
  396.    _write(handlet,"\0",1);  /* Finish the text entry */
  397.    msg.length=lenmess+2;
  398.    if(conf.share)unlock(handlet,tlen,65535L);
  399.    strcpy(msg.date,fidodate()); /* Set up msg header */
  400.    if (msg.date[18]==0) msg.date[18]=' ';
  401.    getdate(&dos_date);
  402.    msg.indate[0]=dos_date.da_year-1989;
  403.    msg.indate[1]=dos_date.da_mon;
  404.    msg.indate[2]=dos_date.da_day;
  405.    msg.indate[3]=0;
  406.    msg.times=0;
  407.  
  408.    x=0;
  409.  
  410.    if((mboard.attr & COMPRESS) && msg.length>conf.packsize) {
  411.  
  412.         char *hold;
  413.  
  414.         hold=(char *)malloc(msg.length+1);
  415.         if(!hold) {
  416.             gprintf(LOCALONLY,"\n\04Can't malloc memory to compress\n");
  417.         }
  418.         else {
  419.             lseek(handlet,msg.start,SEEK_SET);
  420.             if(_read(handlet,hold,msg.length)<(msg.length-1)) {
  421.                 gprintf(LOCALONLY,"\n\04Can't compress\n");
  422.             }
  423.             else {
  424.                 hold[msg.length]=0;
  425.                 hold[msg.length-1]=0;
  426.                 if(strlen(hold)>conf.packsize) {
  427.                     hold[msg.length]=0;
  428.                     hold[msg.length-1]=0;
  429.                     hold=pack_msg(hold);
  430.                     if(!hold || !codesize) {
  431.                        gprintf(LOCALONLY,"\n\04Compression failed\n");
  432.                     }
  433.                     else {
  434.                         lseek(handlet,msg.start,SEEK_SET);
  435.                         msg.m_attr = msg.m_attr | MSGPACKED;
  436.                         _write(handlet,hold,msg.length);
  437.                         free(hold);
  438.                     }
  439.                 }
  440.                 else free(hold);
  441.             }
  442.         }
  443.    }
  444.  
  445.    cclose(handlet);
  446.    gprintf(LOGONLY,say_prompt(320),msg.subj);
  447.    gprintf(LOGONLY,say_prompt(321),msg.to,mboard.name);
  448.  
  449. CarbonLoop:
  450.  
  451.    _write(handlef,&msg,sizeof(struct _xmsg));   /* Save header */
  452.    if(conf.share)unlock(handlef,flen,(long)sizeof(struct _xmsg));
  453.    findfirst(filename,&filestat,0);
  454.    if ((long)(filestat.ff_fsize/(long)sizeof(struct _xmsg)) > (long)mboard.max) {
  455.  
  456.         struct _xmsg msgtwo;
  457.         long pos;
  458.  
  459.      /* Do "rollover" if over max msgs */
  460.  
  461.      lseek(handlef,(filestat.ff_fsize-((long)(mboard.max)-1L)*(long)sizeof(struct _xmsg)),SEEK_SET);
  462.      pos=tell(handlef);
  463.      if (conf.share) {
  464.  
  465.          int y=0;
  466.  
  467.          while (lock(handlef,pos,(long)sizeof(struct _xmsg))){
  468.             y++;
  469.             if(y>2) {
  470.                 say_prompt(50);
  471.                 return 1;
  472.             }
  473.             say_prompt(57);
  474.             sleep(1);
  475.          }
  476.      }
  477.      if (_read(handlef,&msgtwo,sizeof(struct _xmsg))>0) {
  478.          if (!(msgtwo.m_attr & MSGKEEP)) {
  479.              msgtwo.m_attr = msgtwo.m_attr & (~MSGDELETED);
  480.              lseek(handlef,pos,SEEK_SET);
  481.              _write(handlef,&msgtwo,sizeof(struct _xmsg));
  482.          }
  483.      }
  484.      if(conf.share)unlock(handlef,pos,(long)sizeof(struct _xmsg));
  485.    }
  486.  
  487.    /* Copy header for each carbon recipient */
  488.  
  489.    if (numcarbons>x) {
  490.       strcpy(msg.to,&buffer[650+(37*x)]);
  491.       x++;
  492.       lseek(handlef,0L,SEEK_END);
  493.       flen=tell(handlef);
  494.       if (conf.share) {
  495.  
  496.           int y=0;
  497.  
  498.           while (lock(handlef,flen,(long)sizeof(struct _xmsg))){
  499.             y++;
  500.             if(y>2) {
  501.                 say_prompt(50);
  502.                 return 1;
  503.             }
  504.             say_prompt(57);
  505.             sleep(1);
  506.           }
  507.       }
  508.       goto CarbonLoop;
  509.    }
  510.  
  511.    cclose(handlef);
  512.  
  513.     /* Clean up and exit */
  514.  
  515.    if (nodenumber!=1) sprintf(message,"MSGTMP%hu",nodenumber);
  516.    else strcpy(message,"MSGTMP");
  517.    unlink(message);
  518.  
  519.    /* Update user stats */
  520.  
  521.    user.posts++;
  522.    if ((mboard.attr & NET || mboard.attr & ALTERNATE)) {
  523.         if (msg.cost>0) user.credit-=msg.cost;
  524.    }
  525.  
  526.    /* Log entries */
  527.  
  528.    if (numcarbons) {
  529.         for (x=0;x<numcarbons;x++) {
  530.             gprintf(LOGONLY,"CC: %s",&buffer[650+(37*x)]);
  531.         }
  532.    }
  533.    return(0);
  534. }
  535.  
  536.  
  537.  
  538. word pascal writemessage (char type) {
  539.  
  540.  int handle;
  541.  char message[81];
  542.  char msghdr[89];
  543.  struct ffblk f;
  544.  char *p;
  545.  
  546.  if (nodenumber!=1) sprintf(message,"MSGTMP%hu",nodenumber);
  547.  else strcpy(message,"MSGTMP");
  548.  level=0;
  549.  
  550.  strcpy(msghdr,message);
  551.  strcat(msghdr,".INF");
  552.  unlink(msghdr);
  553.  if(!(type & 4)) {
  554.     if((handle=(ccreat(msghdr,S_IWRITE)))!=-1) {
  555.         if((mboard.attr & NET) || (mboard.attr & ALTERNATE)) {
  556.             ffprintf(handle,"NET\r\n");
  557.             if(mboard.attr & NET) p=conf.domain;
  558.             else p=conf.alt_domain;
  559.             ffprintf(handle,"ORIG %01u:%01u/%01u.0@%s\r\n",
  560.                 msg.o_zone,msg.orig_net,msg.orig,p);
  561.             ffprintf(handle,"DEST %01u:%01u/%01u.%01u@%s\r\n",
  562.                 msg.d_zone,msg.dest_net,msg.dest,msg.d_point,to_domain);
  563.         }
  564.         if(*oldmsg.from) {
  565.             ffprintf(handle,"REPLY\r\n");
  566.             ffprintf(handle,"FROM %s\r\n",oldmsg.from);
  567.             if(*oldmsg.date)ffprintf(handle,"DATE %s\r\n",oldmsg.date);
  568.             if(*oldmsg.to)ffprintf(handle,"WASTO %s\r\n",oldmsg.to);
  569.         }
  570.         if((mboard.attr & ECHO) || (mboard.attr & ALTECHO)) {
  571.             ffprintf(handle,"ECHO\r\n");
  572.         }
  573.         ffprintf(handle,"TO %s\r\n",msg.to);
  574.         ffprintf(handle,"SUBJ %s\r\n",msg.subj);
  575.         ffprintf(handle,"WRITER %s\r\n",msg.from);
  576.         ffprintf(handle,"AREANAME %s\r\n",mboard.name);
  577.         ffprintf(handle,"AREA# %01u\r\n",mboard.number);
  578.         ffprintf(handle,"AREAATTRIB %u\r\n",mboard.attr);
  579.         ffprintf(handle,"MSGATTRIB %u\r\n",msg.attr);
  580.         ffprintf(handle,"MSGATTRIB2 %u\r\n",msg.m_attr);
  581.         ffprintf(handle,"READER XBBS %s\r\n",XVERSION);
  582.         ffprintf(handle,"NODE# %01u\r\n",nodenumber);
  583.         cclose(handle);
  584.    }
  585.  }
  586.  
  587.  strcpy(msghdr,message);
  588.  strcat(msghdr,".HDR");
  589.  unlink(msghdr);
  590.  if (!(type & 4)) {
  591.     if((handle=ccreat(msghdr,S_IWRITE))!=-1) {
  592.         if ((mboard.attr & REAL) || (mboard.attr & NET)) ffprintf(handle,"USER %s\r\n",user.name);
  593.         else ffprintf(handle,"USER %s\r\n",user.handle);
  594.         if(*oldmsg.from)ffprintf(handle,"FROM %s\r\n",oldmsg.from);
  595.         else ffprintf(handle,"RECP %s\r\n",msg.to);
  596.         if(*oldmsg.to)ffprintf(handle,"TO   %s\r\n",oldmsg.to);
  597.         ffprintf(handle,"SUBJ %s\r\n",msg.subj);
  598.         if(*oldmsg.date)ffprintf(handle,"DATE %s\r\n",oldmsg.date);
  599.         cclose(handle);
  600.         memset(&oldmsg,0,sizeof(struct _xmsg));
  601.     }
  602.  
  603.     if (!baud) {
  604.       strcpy(buffer,conf.edlocal);
  605.     }
  606.     else if ((user.graphics) && (user.fullscreen) && (*conf.edansi)) strcpy(buffer,conf.edansi);
  607.     else strcpy(buffer,conf.edline);
  608.     if (mboard.attr & ANSI) {
  609.       strcpy(buffer,conf.edgraph);
  610.     }
  611.     level=(word)spawnit(buffer,0,0);
  612.  }
  613.  else {
  614.     say_prompt(61);
  615.     sprintf(buffer,say_prompt(322),message);
  616.     if (spawnit(buffer,3,0)) level=1;
  617.  }
  618.  carrchk();
  619.  if (!level) if (findfirst(message,&f,0))level=1;
  620.  if (!level) {
  621.     if (searchpath("MESSCHEK.EXE")) {
  622.         sprintf(buffer,"%s %s",searchpath("MESSCHEK.EXE"),message);
  623.         level=(word)spawnit(buffer,0,0);
  624.     }
  625.     else readfile("aftermsg.xbs",0,0,1);
  626.  }
  627.  if(!level) return 0;
  628.  
  629.  unlink(message);
  630.  unlink(msghdr);
  631.  strcpy(msghdr,message);
  632.  strcat(msghdr,".INF");
  633.  unlink(msghdr);
  634.  if (level==1) say_prompt(64);
  635.  if (level==2) {
  636.     say_prompt(63);
  637.     exit(254);
  638.  }
  639.  if (level==3) {
  640.     say_prompt(275);
  641.     if (conf.debug) say_prompt(62);
  642.  }
  643.  return level;
  644. }
  645.  
  646.  
  647.  
  648. int pascal askwrite (char type) {
  649.  
  650.  struct nodeidx nid;
  651.  char temp[131];
  652.  int tempcost;
  653.  
  654.   msg.attr=0;
  655.   msg.m_attr=0;
  656.   if(!(type & 1)) *replyid=0;
  657.  
  658.   if(mboard.attr & ALTERNATE) strcpy(to_domain,conf.alt_domain);
  659.   else strcpy(to_domain,conf.domain);
  660.   if ((mboard.attr & READONLY) && ((user.stat[0]<mboard.substat1) || (user.stat[1]<mboard.substat2))) {
  661.     say_prompt(65);
  662.     return(1);
  663.   }
  664.   if((mboard.attr & FORCE) && mboard.forceto!=NULL && ((user.stat[0]<mboard.substat1) || (user.stat[1]<mboard.substat2))) type = type | 2;
  665.   if ((type & 2) && (!stricmp(user.name,mboard.forceto) || !stricmp(user.handle,mboard.forceto))) type = type & (~2);
  666.   if (type & 2) {
  667.     if (mboard.forceto!=NULL && *mboard.forceto) strcpy(msg.to,mboard.forceto);
  668.     else strcpy(msg.to,conf.sysop);
  669.     if((mboard.attr & PRIVATE) && !(mboard.attr & PUBLIC)) goto Reply1;
  670.     else if ((mboard.attr & PUBLIC) && !(mboard.attr & PRIVATE)) {
  671.         msg.m_attr = msg.m_attr & (~MSGPRIVATE);
  672.         goto GoTo;
  673.     }
  674.     else {
  675.         say_prompt(89);
  676.         printm("y/N) ");
  677.         if(*genin(1,0,1,1,YESNO)=='Y') goto Reply1;
  678.         else msg.m_attr = msg.m_attr & (~MSGPRIVATE);
  679.         goto GoTo;
  680.     }
  681.   }
  682.   if ((user.stat[0]>=mboard.substat1) && (user.stat[1]>=mboard.substat2)) goto Both;
  683.   if ((mboard.attr & PRIVATE) && (mboard.attr & PUBLIC)) goto Both;
  684.   if (mboard.attr & PRIVATE) {
  685. Private:
  686.      if (!stricmp(msg.to,say_prompt(47))) goto Public;
  687.      say_prompt(70);
  688.      if (type & 1) goto Reply1;
  689.      else msg.d_point=0;
  690.      say_prompt(323);
  691.      helpnum=541;
  692.      strcpy(temp,genin(36,0,0,0,NAME));
  693.      helpnum=0;
  694.      if (strlen(temp)<2) return(1);
  695.      if ((!(mboard.attr & NET)) && !(mboard.attr & ALTERNATE) && !(mboard.attr & ALTECHO) && (!(mboard.attr & ECHO))) {
  696.        if (!stricmp(temp,user.handle) || !stricmp(temp,user.name)) {
  697.             say_prompt(416);
  698.             return(1);
  699.        }
  700.        if(verify_user(temp))goto Private;
  701.      }
  702.      strcpy(msg.to,temp);
  703. Reply1:
  704.      msg.attr=(msg.attr | MSGPRIVATE);
  705.      goto GoTo;
  706.   }
  707.  
  708.  else {
  709.  
  710. Public:
  711.     say_prompt(68);
  712.     msg.attr=(msg.attr & (~MSGPRIVATE));
  713.     if ((type & 1) or (type & 2)) goto GoTo;
  714.     say_prompt(324);
  715.     helpnum=542;
  716.     strcpy(temp,genin(36,0,0,0,NAME));
  717.     helpnum=0;
  718.     if (strlen(temp)<1) {
  719.       printm("All");
  720.       strcpy(temp,"All");
  721.     }
  722.     strcpy(msg.to,temp);
  723.     if (!stricmp(msg.to,"Sysop")) {
  724.         if ((mboard.attr & ECHO) || (mboard.attr & ALTECHO)) {
  725.             say_prompt(71);
  726.             return(1);
  727.         }
  728.         strcpy(msg.to,conf.sysop);
  729.     }
  730.     if ((mboard.attr & ANON)) {
  731.       say_prompt(265);
  732.       helpnum=543;
  733.       if (*genin(1,0,0,1,YESNO)=='Y') msg.m_attr = (msg.m_attr | MSGANON);
  734.       helpnum=0;
  735.     }
  736.  }
  737.  
  738. GoTo:
  739.  
  740.   if ((mboard.attr & REAL) || (mboard.attr & NET)) strcpy(msg.from,user.name);
  741.   else strcpy(msg.from,user.handle);
  742.  
  743.   msg.attr=(msg.attr | MSGLOCAL);
  744.  
  745.   if (mboard.attr & NET || mboard.attr & ALTERNATE) {
  746.     msg.m_attr=msg.m_attr | MSGNET;
  747.     nid.node=((word)65535);
  748.     nid.type=255;
  749.  
  750.     if (type & 1) {
  751.       nid.zone=msg.d_zone;
  752.       if (!nid.zone) {
  753.         if (mboard.attr & ALTERNATE) nid.zone=conf.alt_zone;
  754.         else nid.zone=conf.zone;
  755.       }
  756.       nid.net=msg.dest_net;
  757.       nid.node=msg.dest;
  758.       goto ReplyNode;
  759.     }
  760.     else {
  761.         if((mboard.attr & ALTERNATE)) {
  762.           nid.zone=conf.alt_zone;
  763.           nid.net=conf.alt_net;
  764.         }
  765.         else {
  766.            nid.zone=conf.zone;
  767.            nid.net=conf.net;
  768.         }
  769.     }
  770. Nodeover:
  771.     nid.node=((word)65535);
  772.     nid.type=255;
  773.     pauser=0;
  774.     say_prompt(72);
  775.     if ((nodelist(&nid,0))<0) return(1);
  776. Pointover:
  777.     if(msg.d_point)gprintf(0,"\nTo point #%u\n",msg.d_point);
  778. Domainover:
  779.     if(*to_domain) gprintf(0,"\nTo domain: %s\n",to_domain);
  780.     say_prompt(73);
  781.     helpnum=544;
  782.     strcpy(temp,genin(5,0,1,0,ALPHANUM));
  783.     helpnum=0;
  784.     printm("\n");
  785.     if ((*temp!='L') && (*temp!='Z') && (*temp!='N') && (*temp!='P') && (*temp!='D') && (strcmp(temp,"0")) && (!atoi(temp))) return(1);
  786.     if (*temp=='L') {
  787.  
  788.          word tempzone;
  789.          word  tempnet;
  790.  
  791.         tempzone=nid.zone;
  792.         tempnet=nid.net;
  793.         nid.node=0;
  794.         nid.type=255;
  795.         if ((nodelist(&nid,1))==(-1)) {
  796.             say_prompt(74);
  797.             nid.zone=tempzone;
  798.             nid.net=tempnet;
  799.             goto Nodeover;
  800.         }
  801.         nid.type=0;
  802.         lines=3;
  803.         pauser=1;
  804.         while((nodelist(&nid,2))>(-1)) if (toupper(inkey())=='S') break;
  805.         nid.zone=tempzone;
  806.         nid.net=tempnet;
  807.         goto Nodeover;
  808.     }
  809.     if (*temp=='Z') {
  810.       say_prompt(83);
  811.       helpnum=545;
  812.       strcpy(temp,genin(5,0,1,0,NUM));
  813.       helpnum=0;
  814.       if (!(word)atol(temp)) return(1);
  815.       nid.zone=(word)atol(temp);
  816.       nid.net= (word)65535;
  817.       goto Nodeover;
  818.     }
  819.     if (*temp=='N') {
  820.       say_prompt(84);
  821.       helpnum=546;
  822.       strcpy(temp,genin(5,0,1,0,NUM));
  823.       helpnum=0;
  824.       if (!(word)atol(temp)) return(1);
  825.       nid.net=(word)atol(temp);
  826.       nid.type=255;
  827.       goto Nodeover;
  828.     }
  829.     if(*temp=='P') {
  830.         say_prompt(445);
  831.         helpnum=547;
  832.         strcpy(temp,genin(3,0,1,0,NUM));
  833.         helpnum=0;
  834.         if(*temp) msg.d_point=(word)atol(temp);
  835.         goto Pointover;
  836.     }
  837.     if(*temp=='D') {
  838.         say_prompt(362);
  839.         helpnum=574;
  840.         strcpy(temp,genin(36,0,1,0,NUM));
  841.         helpnum=0;
  842.         if(*temp) strcpy(to_domain,temp);
  843.         goto Domainover;
  844.     }
  845.     nid.node=(word)atol(temp);
  846.  
  847. ReplyNode:
  848.  
  849.     if ((tempcost=nodelist(&nid,1))<0) {
  850.         if (userno!=1) return(1);
  851.         say_prompt(75);
  852.         helpnum=548;
  853.         if (*genin(1,0,1,1,YESNO)!='Y') {
  854.             helpnum=0;
  855.             return (1);
  856.         }
  857.         say_prompt(76);
  858.         helpnum=549;
  859.         if (*genin(1,0,1,1,YESNO)=='Y') msg.m_attr = msg.m_attr | MSGHOST;
  860.         helpnum=0;
  861.     }
  862.     if (tempcost>(-1)) msg.cost=(word)tempcost;
  863.     printm("\n");
  864.     gprintf(0,say_prompt(325),msg.cost,user.credit);
  865.     if (msg.cost>user.credit && stricmp(user.name,conf.sysop)) {
  866.       say_prompt(77);
  867.       return(1);
  868.     }
  869.     say_prompt(78);
  870.     if (*genin(1,0,0,1,YESNOM)=='N') goto Nodeover;
  871.     msg.dest=nid.node;
  872.     msg.dest_net=nid.net;
  873.     msg.d_zone=nid.zone;
  874.  
  875.     if (((user.stat[0]>=mboard.substat1) && (user.stat[1]>=mboard.substat2))) {
  876.       say_prompt(79);
  877.       helpnum=550;
  878.       if (*genin(1,0,0,1,YESNO)!='N') msg.attr = (msg.attr | MSGKILL);
  879.       say_prompt(80);
  880.       helpnum=551;
  881.       if (*genin(1,0,0,1,YESNO)!='N') msg.attr = (msg.attr | MSGCRASH);
  882.       else {
  883.          say_prompt(81);
  884.          helpnum=552;
  885.          if (*genin(1,0,0,1,YESNO)!='N') msg.m_attr = (msg.m_attr | MSGHOLD);
  886.       }
  887.       say_prompt(82);
  888.       helpnum=553;
  889.       if (*genin(1,0,0,1,YESNO)=='Y') {
  890.         msg.attr = (msg.attr | MSGFILE);
  891.         say_prompt(85);
  892.         goto SkipRequest;
  893.       }
  894.       say_prompt(86);
  895.       helpnum=554;
  896.       if (*genin(1,0,0,1,YESNO)=='Y') {
  897.         msg.attr = (msg.attr | MSGFRQ);
  898.         say_prompt(87);
  899.       }
  900. SkipRequest:
  901. ;
  902.     }
  903.     helpnum=0;
  904.     printm("\n");
  905.   }
  906.  
  907.   msg.o_point=0;
  908.   if ((mboard.attr & ECHO) || (mboard.attr & ALTECHO)) msg.m_attr=(msg.m_attr | MSGECHO);
  909.   if ((mboard.attr & ALTERNATE) || (mboard.attr & ALTECHO)) {
  910.     msg.o_zone=conf.alt_zone;
  911.     msg.orig_net=conf.alt_net;
  912.     msg.orig=conf.alt_node;
  913.   }
  914.   else {
  915.      msg.o_zone=conf.zone;
  916.      msg.orig_net=conf.net;
  917.      msg.orig=conf.node;
  918.   }
  919.  
  920.   if (!(type & 1)) {
  921.     say_prompt(88);
  922.     helpnum=555;
  923.     strcpy(temp,genin(64,0,0,0,SUBJECT));
  924.     helpnum=0;
  925.     if (!strlen(temp)) return(1);
  926.     strcpy(msg.subj,temp);
  927.   }
  928.   if(!(type & 1)) memset(&oldmsg,0,sizeof(struct _xmsg));
  929.   return(0);
  930.  
  931. Both:
  932.  
  933.   say_prompt(89);
  934.   if (type & 16 || ((mboard.attr & NET))) {
  935.    printm("Y-n) ");
  936.    if (*genin(1,0,0,1,YESNO)=='N') goto Public;
  937.    goto Private;
  938.   }
  939.   else {
  940.    printm("y-N) ");
  941.    if (*genin(1,0,0,1,YESNO)!='Y') goto Public;
  942.    goto Private;
  943.   }
  944. }
  945.  
  946.  
  947. char pascal verify_user (char *uname) {
  948.  
  949.     int fphandle;
  950.     struct _user check;
  951.     register word x;
  952.  
  953.        if ((fphandle=oopen(searchpath("USERS.BBS"),O_RDONLY | O_BINARY | O_DENYNONE))==-1) {
  954.          say_prompt(67);
  955.          return(1);
  956.        }
  957.        x=0;
  958.        say_prompt(69);
  959.        while (!eof(fphandle) && _read(fphandle,&check,sizeof(struct _user))>0) {
  960.            if (mboard.attr & REAL) strcpy(check.handle,check.name);
  961.            if (!(stricmp(check.handle,uname)) && (!check.deleted)) break;
  962.            if ((++x%50)==0) printm(".");
  963.        }
  964.        cclose(fphandle);
  965.        printm("\n");
  966.        if ((stricmp(check.handle,uname)) || (check.deleted)) {
  967.            say_prompt(66);
  968.            helpnum=556;
  969.            if (*genin(1,0,0,1,YESNO)!='N') {
  970.                 helpnum=0;
  971.                 userlist((mboard.attr & REAL));
  972.            }
  973.            helpnum=0;
  974.            return 1;
  975.        }
  976.        return 0;
  977. }
  978.  
  979. int pascal nodelist (struct nodeidx *nii,char type) {
  980.  
  981.  struct nodeinfo nif;
  982.  struct nodeidx nid;
  983.  static int cidx;
  984.  char temp[129];
  985.  char len;
  986.  int handle;
  987.  
  988.  nif.zone=nii->zone;
  989.  nif.net=nii->net;
  990.  nif.node=nii->node;
  991.  nif.type=nii->type;
  992.  if (type==2) cidx++;
  993.  else if ((nif.net==((word)65535)) || (nif.type==255)) cidx=0;
  994.  
  995.  
  996.  sprintf(temp,"%sQNL_IDX.BBS",conf.nodelist);
  997.  if ((handle=oopen(temp,O_RDONLY | O_BINARY | O_DENYNONE))==-1) {
  998.    say_prompt(90);
  999.    return(-1);
  1000.  }
  1001.  lseek(handle,(long)(cidx)*(long)sizeof(struct nodeidx),SEEK_SET);
  1002.  
  1003.  nid.zone=0;
  1004.  nid.net=0;
  1005.  nid.node=0;
  1006.  nid.type=0;
  1007.  
  1008.  while((nif.zone!=nid.zone) && (!eof(handle))) {
  1009.    if (_read(handle,&nid,sizeof(struct nodeidx))<1) {
  1010.         cclose(handle);
  1011.         return (-1);
  1012.    }
  1013.    if (!((cidx++)%50)) if (type==1) printm(".");
  1014.  }
  1015.  if (nif.net!=((word)65535)) {
  1016.      while((nif.net!=nid.net) && (!eof(handle))) {
  1017.        if (_read(handle,&nid,sizeof(struct nodeidx))<1) {
  1018.             cclose(handle);
  1019.             return (-1);
  1020.        }
  1021.    if (!((cidx++)%50)) if (type==1) printm(".");
  1022.      }
  1023.  }
  1024.  if (nif.node!=((word)65535) && type!=2) {
  1025.      while((nif.node!=nid.node) && (!eof(handle))) {
  1026.        if (_read(handle,&nid,sizeof(struct nodeidx))<1) {
  1027.             cclose(handle);
  1028.             return (-1);
  1029.        }
  1030.    if (!((cidx++)%50)) if (type==1) printm(".");
  1031.         }
  1032.  }
  1033.  
  1034.   if (type!=2) {
  1035.      if (eof(handle) || (nif.node!=((word)65535) && nid.node!=nif.node) || (nif.net!=((word)65535) && nid.net!=nif.net) || (nif.zone!=((word)65535) && nid.zone!=nif.zone)) {
  1036.        say_prompt(91);
  1037.        cclose(handle);
  1038.        return(-1);
  1039.      }
  1040.   }
  1041.   if (eof(handle)) {
  1042.     cclose(handle);
  1043.     return (-1);
  1044.   }
  1045.  
  1046. GotwhatIwant:
  1047.  
  1048.  cclose(handle);
  1049.  if (type==2 && (nif.zone!=nid.zone || nif.net!=nid.net)) return (-1);
  1050.  sprintf(temp,"%sQNL_DAT.BBS",conf.nodelist);
  1051.  if ((handle=oopen(temp,O_RDONLY | O_BINARY | O_DENYNONE))==-1) {
  1052.    say_prompt(92);
  1053.    return(-1);
  1054.  }
  1055.  lseek(handle,(long)(--cidx)*(long)sizeof(struct nodeinfo),SEEK_SET);
  1056.  if (_read(handle,&nif,sizeof(struct nodeinfo))<1) {
  1057.     cclose(handle);
  1058.     return (-1);
  1059.  }
  1060.  cclose(handle);
  1061.  len=*nif.name;
  1062.  memmove(nif.name,&nif.name[1],len);
  1063.  nif.name[len]=0;
  1064.  len=*nif.city;
  1065.  memmove(nif.city,&nif.city[1],len);
  1066.  nif.city[len]=0;
  1067.  len=*nif.phone;
  1068.  memmove(nif.phone,&nif.phone[1],len);
  1069.  nif.phone[len]=0;
  1070.  len=*nif.password;
  1071.  memmove(nif.password,&nif.password[1],len);
  1072.  nif.password[len]=0;
  1073.  if (gprintf(0,say_prompt(326),'\n',nif.type,nif.zone,nif.net,nif.node,nif.name,nif.city)) return (-1);
  1074.  if (pauser==1) if ((char)strlen(temp)>user.width) lines++;
  1075.  sprintf(temp,say_prompt(327),nif.phone,nif.baud,nif.cost);
  1076.  if (nif.flags & B_hub) strcat(temp,"Hub  ");
  1077.  if (nif.flags & B_host) strcat(temp,"Host  ");
  1078.  if (nif.flags & B_region) strcat(temp,"RC  ");
  1079.  if (nif.flags & B_zone) strcat(temp,"ZC  ");
  1080.  if (nif.flags & B_CM) strcat(temp,"CM");
  1081.  if (printm(temp)) return (-1);
  1082.  if (pauser==1) if ((char)strlen(temp)>user.width) lines++;
  1083.  return(nif.cost);
  1084.  
  1085. }
  1086.  
  1087. long pascal make_msgid (void) {
  1088.  
  1089.     time_t t;
  1090.  
  1091.     (void)time(&t);
  1092.     t = (t<<4) | (nodenumber);
  1093.     return t;
  1094. }
  1095.