home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / MBOXMAIL.C < prev    next >
C/C++ Source or Header  |  1994-08-26  |  45KB  |  1,383 lines

  1. /* The are the MAILCMDS */
  2. #include <time.h>
  3. #include <ctype.h>
  4. #ifdef MSDOS
  5. #include <alloc.h>
  6. #endif
  7. #ifdef  UNIX
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #endif
  11. #include "global.h"
  12. #ifdef MAILCMDS
  13. #include "timer.h"
  14. #include "proc.h"
  15. #include "socket.h"
  16. #include "usock.h"
  17. #include "session.h"
  18. #include "smtp.h"
  19. #include "dirutil.h"
  20. #include "telnet.h"
  21. #include "ftp.h"
  22. #include "ftpserv.h"
  23. #include "commands.h"
  24. #include "netuser.h"
  25. #include "files.h"
  26. #include "bm.h"
  27. #include "pktdrvr.h"
  28. #include "ax25.h"
  29. #include "mailbox.h"
  30. #include "ax25mail.h"
  31. #include "nr4mail.h"
  32. #include "cmdparse.h"
  33. #include "mailfor.h"
  34.   
  35. /* By setting the fp to NULL, we can check in exitbbs()
  36.  * wether a tempfile has been closed or not - WG7J
  37.  */
  38. #define MYFCLOSE(x) { fclose(x); x = (FILE *) 0; }
  39.   
  40. char CcLine[] = "Cc: ";
  41. char Mbwarning[] = "Third Party mail is not permitted.\n";
  42. char InvalidNameChars[] = "?*<>[],;:+=\"";
  43.   
  44. int MbSent;
  45. int MbRead;
  46. int MbRecvd;
  47.   
  48. #ifdef MBFWD
  49. int MbForwarded;
  50. #endif
  51.   
  52. int
  53. dosid(argc,argv,p)
  54. int argc;
  55. char *argv[];
  56. void *p;
  57. {
  58.     struct mbx *m;
  59.     char *cp;
  60.   
  61.     m = (struct mbx *)p;
  62.     if(argc == 1)
  63.         return 1;
  64.     if(argv[1][strlen(argv[1]) - 1] != ']') /* must be an SID */
  65.         return 1;
  66. #ifdef notdef
  67.     if(m->stype == 'Z' && strncmp(argv[1],"cz",2) == 0) {
  68.         /* LAN-LINK's [ZCZ] */
  69.         m->sid |= MBX_LL;
  70.         return 0;
  71.     }
  72. #endif
  73.     /* Other bbs's */
  74.     m->sid = MBX_SID;
  75.   
  76.     /* Now check to see if this is an RLI board.
  77.      * As usual, Hank does it a bit differently from
  78.      * the rest of the world.
  79.      */
  80.     if(m->stype == 'R' && strncmp(argv[1],"li",2) == 0)/* [RLI] at a minimum */
  81.         m->sid |= MBX_RLI_SID;
  82.     /* Or maybe it is F6FBB ? */
  83.     else if(m->stype == 'F')
  84.         m->sid |= MBX_FBB;
  85.     /* Check to see if the BBS supports a kludge called "hierarchical
  86.      * routing designators."
  87.      *
  88.      * No need to check for ']' -- it must be there or this is not
  89.      * a valid mbox id -- it is checked earlier (fix de OH3LKU)
  90.      *
  91.      * Sid format is [BBSTYPE-VERSION-OPTIONS]
  92.      * check for LAST -, to allow for version portion. - WG7J
  93.      */
  94.     if((cp = strrchr(argv[1],'-')) != NULLCHAR) {
  95.         cp++;
  96.     /* Okay, now parse the options */
  97.         if((strchr(cp,'h') != NULLCHAR) && (strchr(cp,'$') != NULLCHAR))
  98.             m->sid |= MBX_HIER_SID;
  99.         if(strchr(cp,'m') != NULLCHAR)
  100.             m->sid |= MBX_MID;
  101.     }
  102.     return 0;
  103. }
  104.   
  105. int
  106. doarea(argc,argv,p)
  107. int argc;
  108. char *argv[];
  109. void *p;
  110. {
  111.     struct mbx *m;
  112.     FILE *fp;
  113.     char buf[MBXLINE];
  114.   
  115.     m = (struct mbx *) p;
  116.   
  117.     if(argc < 2){
  118. #ifdef USERLOG
  119.         if(m->stype == 'N') {
  120.             listnewmail(m,0);
  121.             return 0;
  122.         }
  123. #endif
  124.         tprintf("Current message area is: %s\n\n",m->area);
  125.         tprintf("Available areas are:\n%-15s",m->name);
  126.         if(m->stype == 'F')
  127.             tputs("  Your private mail area\n");
  128.         else
  129.             tputc('\n');
  130.         if((fp = fopen(Arealist,READ_TEXT)) == NULLFILE)
  131.             return 0;
  132.         if(m->stype == 'F')
  133.             sendfile(fp,m->user,ASCII_TYPE,0,m);
  134.         else {
  135.             /* send only the area names, not the description */
  136.             while(fgets(buf,MBXLINE,fp) != NULLCHAR) {
  137.                 if(buf[0] != '#') { /* skip comments */
  138.                     firsttoken(buf);
  139.                     tprintf("%s\n",buf);
  140.                 }
  141.             }
  142.             tputs("\nType AF to get description of areas\n\n");
  143.         }
  144.         fclose(fp);
  145.         return 0;
  146.     } else {
  147.         dotformat(argv[1]);
  148.         if(!strcmp(m->name,argv[1]) || isarea(argv[1]) ||
  149.            ((m->privs&SYSOP_CMD) && strpbrk(argv[1],InvalidNameChars)==NULLCHAR
  150.             && *(argv[1]+strlen(argv[1])-1)!='.' )){
  151.             changearea(m,argv[1]);
  152.             if(m->areatype == PRIVATE)
  153.                 tputs("You have ");
  154.             else
  155.                 tprintf("%s: ",m->area);
  156.             if(m->nmsgs){
  157. #ifdef USERLOG
  158.                 tprintf("%d message%s -  %d new.\n",m->nmsgs,
  159.                 m->nmsgs == 1 ? " " : "s ", m->newmsgs);
  160. #else
  161.                 if(m->areatype == PRIVATE)
  162.                     tprintf("%d message%s -  %d new.\n", m->nmsgs,
  163.                     m->nmsgs == 1 ? " " : "s ", m->newmsgs);
  164.                 else
  165.                     tprintf("%d message%s.\n", m->nmsgs,
  166.                     m->nmsgs == 1 ? "" : "s");
  167. #endif
  168.             } else
  169.                 tputs("0 messages.\n");
  170.         } else
  171.             tprintf("No such message area: %s\n",argv[1]);
  172.     }
  173.     return 0;
  174. }
  175.   
  176. /* subroutine to do the actual switch from one area to another */
  177. /* USERLOGGING added by WG7J */
  178. void
  179. changearea(m,area)
  180. struct mbx *m;
  181. char *area;
  182. {
  183.     if (m->area[0]) {    /* current area non-null? */
  184. #ifdef USERLOG
  185.         setlastread(m);
  186. #endif
  187.         closenotes(m);
  188.     }
  189.     dotformat(area);
  190.     strcpy(m->area,area);
  191.     /* Check areas first, so regular users loging in with areaname
  192.      * cannot gain permission to kill messages in areas
  193.      * (if univperm in ftpusers doesn't allow that)
  194.      */
  195.     if(isarea(area))
  196.         m->areatype = AREA;
  197.     else if(!strcmp(m->name,area))
  198.         m->areatype = PRIVATE;
  199.     else    /* Sysop checking someone else's area */
  200.         m->areatype = USER;
  201.   
  202. #ifdef USERLOG
  203.     /* only read last read message-id if this is not a bbs,
  204.      * current area is a public area and not 'help'
  205.      * or area starts with 'sys'
  206.      */
  207.     if(!(m->sid & MBX_SID))
  208.         if( (strcmp(area,"help") && m->areatype == AREA) || \
  209.             !strncmp(m->area,"sys",3) || \
  210.             (m->privs & MBX_SYSOP) )
  211.             getlastread(m);
  212. #endif
  213.   
  214.     scanmail(m);
  215. }
  216.   
  217. /* States for send line parser state machine */
  218. #define         LOOK_FOR_USER           2
  219. #define         IN_USER                 3
  220. #define         AFTER_USER              4
  221. #define         LOOK_FOR_HOST           5
  222. #define         IN_HOST                 6
  223. #define         AFTER_HOST              7
  224. #define         LOOK_FOR_FROM           8
  225. #define         IN_FROM                 9
  226. #define         AFTER_FROM              10
  227. #define         LOOK_FOR_MSGID          11
  228. #define         IN_MSGID                12
  229. #define         FINAL_STATE             13
  230. #define         ERROR_STATE             14
  231.   
  232. /* Prepare the addressee.  If the address is bad, return -1, otherwise
  233.  * return 0
  234.  */
  235. int
  236. mbx_to(argc,argv,p)
  237. int argc;
  238. char *argv[];
  239. void *p;
  240. {
  241.     char *cp;
  242.     int state, i;
  243.     char *user, *host, *from, *msgid;
  244.     int userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0;
  245.     struct mbx *m;
  246.   
  247.     m = (struct mbx *)p;
  248.     /* Free anything that might be allocated
  249.      * since the last call to mbx_to() or mbx_reply()
  250.      */
  251.     free(m->to);
  252.     m->to = NULLCHAR;
  253.     free(m->tofrom);
  254.     m->tofrom = NULLCHAR;
  255.     free(m->tomsgid);
  256.     m->tomsgid = NULLCHAR;
  257.     free(m->origto);
  258.     m->origto = NULLCHAR;
  259.     free(m->origbbs);
  260.     m->origbbs = NULLCHAR;
  261.     free(m->subject);
  262.     m->subject = NULLCHAR;
  263.     free(m->date);
  264.     m->date = NULLCHAR;
  265.   
  266.     if(argc == 1)
  267.         return -1;
  268.     i = 1;
  269.     cp = argv[i];
  270.     state = LOOK_FOR_USER;
  271.     while(state < FINAL_STATE){
  272. #ifdef MBDEBUG
  273.         tprintf("State is %d, char is %c\n", state, *cp);
  274. #endif
  275.         switch(state){
  276.             case LOOK_FOR_USER:
  277.                 if(*cp == '@' || *cp == '<' || *cp == '$'){
  278.                     state = ERROR_STATE;            /* no user */
  279.                 } else {
  280.                     user = cp;                      /* point at start */
  281.                     userlen++;                      /* start counting */
  282.                     state = IN_USER;
  283.                 }
  284.                 break;
  285.             case IN_USER:
  286.             switch(*cp){
  287.                 case '\0':
  288.                     state = AFTER_USER;             /* done with username */
  289.                     break;
  290.                 case '@':
  291.                     state = LOOK_FOR_HOST;          /* hostname should follow */
  292.                     break;
  293.                 case '<':
  294.                     state = LOOK_FOR_FROM;          /* from name should follow */
  295.                     break;
  296.                 case '$':
  297.                     state = LOOK_FOR_MSGID; /* message id should follow */
  298.                     break;
  299.                 default:
  300.                     userlen++;                      /* part of username */
  301.             }
  302.                 break;
  303.             case AFTER_USER:
  304.             switch(*cp){
  305.                 case '@':
  306.                     state = LOOK_FOR_HOST;          /* hostname follows */
  307.                     break;
  308.                 case '<':
  309.                     state = LOOK_FOR_FROM;          /* fromname follows */
  310.                     break;
  311.                 case '$':
  312.                     state = LOOK_FOR_MSGID; /* message id follows */
  313.                     break;
  314.                 default:
  315.                     state = ERROR_STATE;
  316.             }
  317.                 break;
  318.             case LOOK_FOR_HOST:
  319.                 if(*cp == '@' || *cp == '<' || *cp == '$'){
  320.                     state = ERROR_STATE;
  321.                     break;
  322.                 }
  323.                 if(*cp == '\0')
  324.                     break;
  325.                 host = cp;
  326.                 hostlen++;
  327.                 state = IN_HOST;
  328.                 break;
  329.             case IN_HOST:
  330.             switch(*cp){
  331.                 case '\0':
  332.                     state = AFTER_HOST;             /* found user@host */
  333.                     break;
  334.                 case '@':
  335.                     state = ERROR_STATE;            /* user@host@? */
  336.                     break;
  337.                 case '<':
  338.                     state = LOOK_FOR_FROM;          /* fromname follows */
  339.                     break;
  340.                 case '$':
  341.                     state = LOOK_FOR_MSGID; /* message id follows */
  342.                     break;
  343.                 default:
  344.                     hostlen++;
  345.             }
  346.                 break;
  347.             case AFTER_HOST:
  348.             switch(*cp){
  349.                 case '@':
  350.                     state = ERROR_STATE;            /* user@host @ */
  351.                     break;
  352.                 case '<':
  353.                     state = LOOK_FOR_FROM;          /* user@host < */
  354.                     break;
  355.                 case '$':
  356.                     state = LOOK_FOR_MSGID; /* user@host $ */
  357.                     break;
  358.                 default:
  359.                     state = ERROR_STATE;            /* user@host foo */
  360.             }
  361.                 break;
  362.             case LOOK_FOR_FROM:
  363.                 if(*cp == '@' || *cp == '<' || *cp == '$'){
  364.                     state = ERROR_STATE;
  365.                     break;
  366.                 }
  367.                 if(*cp == '\0')
  368.                     break;
  369.                 from = cp;
  370.                 fromlen++;
  371.                 state = IN_FROM;
  372.                 break;
  373.             case IN_FROM:
  374.             switch(*cp){
  375.                 case '\0':
  376.                     state = AFTER_FROM;             /* user@host <foo */
  377.                     break;
  378.                 case '<':
  379.                     state = ERROR_STATE;            /* user@host <foo< */
  380.                     break;
  381.                 case '$':
  382.                     state = LOOK_FOR_MSGID; /* message id follows */
  383.                     break;
  384.                 default:
  385.                     fromlen++;
  386.             }
  387.                 break;
  388.             case AFTER_FROM:
  389.             switch(*cp){
  390.                 case '@':                               /* user@host <foo @ */
  391.                 case '<':                               /* user@host <foo < */
  392.                     state = ERROR_STATE;
  393.                     break;
  394.                 case '$':
  395.                     state = LOOK_FOR_MSGID; /* user@host <foo $ */
  396.                     break;
  397.                 default:
  398.                     state = ERROR_STATE;            /* user@host foo */
  399.             }
  400.                 break;
  401.             case LOOK_FOR_MSGID:
  402.                 if(*cp == '\0')
  403.                     break;
  404.                 msgid = cp;
  405.                 msgidlen++;
  406.                 state = IN_MSGID;
  407.                 break;
  408.             case IN_MSGID:
  409.                 if(*cp == '\0')
  410.                     state = FINAL_STATE;
  411.                 else
  412.                     msgidlen++;
  413.                 break;
  414.             default:
  415.             /* what are we doing in this state? */
  416.                 state = ERROR_STATE;
  417.         }
  418.         if(*(cp) == '\0'){
  419.             ++i;
  420.             if(i < argc)
  421.                 cp = argv[i];
  422.             else break;
  423.         } else
  424.             ++cp;
  425.     }
  426.     if(state == ERROR_STATE || state == LOOK_FOR_HOST
  427.         || state == LOOK_FOR_FROM || state == LOOK_FOR_MSGID)
  428.         return -1;              /* syntax error */
  429.   
  430.     m->to = mallocw(userlen + hostlen + 2);
  431.   
  432.     strncpy(m->to, user, userlen);
  433.     m->to[userlen] = '\0';
  434.   
  435.     if(hostlen){
  436.         m->to[userlen] = '@';
  437.         strncpy(m->to + userlen + 1, host, hostlen);
  438.         m->to[userlen + hostlen + 1] = '\0';
  439.     }
  440.     if(fromlen){
  441.         m->tofrom = mallocw(fromlen + 1);
  442.         strncpy(m->tofrom, from, fromlen);
  443.         m->tofrom[fromlen] = '\0';
  444.     }
  445.     if(msgidlen){
  446.         m->tomsgid = mallocw(msgidlen + 1);
  447.         strncpy(m->tomsgid, msgid, msgidlen);
  448.         m->tomsgid[msgidlen] = '\0';
  449.     }
  450.     return 0;
  451. }
  452.   
  453. /* This opens the data file and writes the mail header into it.
  454.  * Returns 0 if OK, and -1 if not.
  455.  */
  456. int
  457. mbx_data(m,cclist,extra)
  458. struct mbx *m;
  459. struct list *cclist;    /* list of carbon copy recipients */
  460. char *extra;        /* optional extra header lines */
  461. {
  462.     time_t t;
  463.     struct list *ap;
  464.     int cccnt = 0;
  465.   
  466. #ifdef notdef
  467.     time(&t);
  468.     /*These 2 lines get added again when the smtp-server handles the mail
  469.      *not really needed - WG7J
  470.      */
  471.     fprintf(m->tfile,Hdrs[RECEIVED]);
  472.     if(m->tofrom != NULLCHAR)
  473.         fprintf(m->tfile,"from %s ",m->name);
  474.     fprintf(m->tfile,"by %s (%s)\n\tid AA%ld ; %s",
  475.     Hostname, Version, get_msgid(),ptime(&t));
  476. #endif
  477.   
  478.     /* If m->date is set, use this one (comes from bbs-forwarded mail) */
  479.     if(m->date != NULLCHAR)
  480.         fprintf(m->tfile,"%s%s",Hdrs[DATE],m->date);
  481.     else {
  482.         time(&t);
  483.         fprintf(m->tfile,"%s%s",Hdrs[DATE],ptime(&t));
  484.     }
  485.   
  486.     /* Bulletin ID, if any */
  487.     fprintf(m->tfile,Hdrs[MSGID]);
  488.     if(m->tomsgid)
  489.         fprintf(m->tfile,"<%s@%s.bbs>\n", m->tomsgid, m->name);
  490.     else
  491.   
  492.         fprintf(m->tfile,"<%ld@%s>\n",get_msgid(), Hostname);
  493.   
  494.     /* From : , could use 'real bbs address', if origbbs is set */
  495.     fprintf(m->tfile,Hdrs[FROM]);
  496.     if(m->tofrom) {  /* BBS style '< call' */
  497.         if(m->origbbs != NULLCHAR)
  498.             fprintf(m->tfile,"%s@%s\n",m->tofrom,m->origbbs);
  499.         else
  500.             fprintf(m->tfile,"%s%%%s.bbs@%s\n",m->tofrom, m->name, Hostname);
  501.     } else {
  502.         if(m->origbbs != NULLCHAR)
  503.             fprintf(m->tfile,"%s@%s\n",m->name,m->origbbs);
  504.         else {
  505.             int found = 0;
  506.             char *cp,*cp2;
  507.             FILE *fp;
  508.             char line[128];
  509.   
  510.             if((fp = fopen(Pdbase,READ_TEXT)) != NULLFILE) {
  511.                 while(fgets(line,128,fp) != NULLCHAR) {
  512.                     rip(line);
  513.                     cp = skipwhite(line);
  514.                     if(*cp == '#')
  515.                         continue;
  516.                     /* Now find end of fist entry */
  517.                     cp2 = cp;
  518.                     while(*cp2 && *cp2 != ' ' && *cp2 != '\t')
  519.                         cp2++;
  520.                     if(*cp2 == '\0') /* No additional data */
  521.                         continue;
  522.                     *cp2 = '\0';    /* terminate first entry */
  523.                     if(!stricmp(cp,m->name)) {
  524.                         /* Found one, now get the name */
  525.                         cp = skipwhite(++cp2);
  526.                         if(*cp) {
  527.                             found = 1;
  528.                             fprintf(m->tfile,"%s <%s@%s>\n",cp,m->name,Hostname);
  529.                         }
  530.                     }
  531.                 }
  532.                 fclose(fp);
  533.             }
  534.             if(!found)
  535.                 fprintf(m->tfile,"%s@%s\n",m->name,Hostname);
  536.         }
  537.     }
  538.   
  539. #if defined USERLOG && defined REGISTER
  540.     if((m->sid & MBX_REPLYADDR) && m->IPemail)
  541.         fprintf(m->tfile,"%s%s\n",Hdrs[REPLYTO],m->IPemail);
  542. #endif /* REPLY-TO HEADER */
  543.   
  544.     fprintf(m->tfile,"%s%s\n",Hdrs[TO],m->origto != NULLCHAR ? m->origto : m->to);
  545.   
  546.     /* Write Cc: line */
  547.     for(ap = cclist; ap != NULLLIST; ap = ap->next) {
  548.         if(cccnt == 0){
  549.             fprintf(m->tfile,"%s",Hdrs[CC]);
  550.             cccnt = 4;
  551.         }
  552.         else {
  553.             fprintf(m->tfile,", ");
  554.             cccnt += 2;
  555.         }
  556.         if(cccnt + strlen(ap->val) > 80 - 3) {
  557.             fprintf(m->tfile,"\n    ");
  558.             cccnt = 4;
  559.         }
  560.         fputs(ap->val,m->tfile);
  561.         cccnt += strlen(ap->val);
  562.     }
  563.     if(cccnt)
  564.         fputc('\n',m->tfile);
  565.     fprintf(m->tfile,"%s%s\n",Hdrs[SUBJECT],m->subject);
  566.     if(!isspace(m->stype) && ((m->stype != 'R' && m->stype != 'F') ||
  567.         (m->sid & MBX_SID) !=0))
  568.         fprintf(m->tfile,"%s%c\n", Hdrs[BBSTYPE],m->stype);
  569.   
  570. #ifdef notdef
  571.     /*not really needed, the 'From <user%fwdbbs@host>' shows this too!*/
  572.     /* Also store the 'real smtp from' address */
  573.     if((m->tofrom != NULLCHAR) && (m->origbbs != NULLCHAR))
  574.         fprintf(m->tfile,"%s%s%%%s@%s\n",Hdrs[XFROM],m->tofrom,m->name, Hostname);
  575. #endif
  576.   
  577.     if(extra != NULLCHAR)
  578.         fprintf(m->tfile,extra);
  579.   
  580.     return 0;
  581. }
  582.   
  583. /* Returns true if string is in history file or if string appears to be a
  584.  * message id generated by our system.
  585.  */
  586. int
  587. msgidcheck(string)
  588. char *string;
  589. {
  590.     FILE *fp;
  591.     char *cp,buf[LINELEN];
  592.   
  593.     if(string == NULLCHAR)
  594.         return 0;
  595.   
  596.     /* BID's that we have generated ourselves are not kept in the history
  597.      * file. Such BID's are in the nnnn_hhhh form, where hhhh is a part of
  598.      * our hostname, truncated so that the BID is no longer than 11
  599.      * characters.
  600.      */
  601.     if((cp = strchr(string,'_')) != NULLCHAR && *(cp+1) != '\0' &&
  602.         strnicmp(cp+1,Hostname,strlen(cp+1)) == 0)
  603.         return 1;
  604.   
  605.     if((fp = fopen(Historyfile,READ_TEXT)) == NULLFILE)
  606.         return 0;
  607.     while(fgets(buf,LINELEN,fp) != NULLCHAR) {
  608.         firsttoken(buf);
  609.         if(stricmp(string,buf) == 0) {    /* found */
  610.             fclose(fp);
  611.             return 1;
  612.         }
  613.     }
  614.     fclose(fp);
  615.     return 0;
  616. }
  617.   
  618. /* Attempt to determine if this is third-pary mail. */
  619. int
  620. thirdparty(m)
  621. struct mbx *m;
  622. {
  623.     char buf[MBXLINE], *cp, *rp;
  624.     FILE *fp;
  625.   
  626.     if(strchr(m->to,'@') != NULLCHAR || strchr(m->to,'%') != NULLCHAR
  627.         || strchr(m->to,'!') != NULLCHAR)
  628.         return 0;
  629.   
  630.     rp = strdup(Hostname);
  631.   
  632.     if((cp = strchr(rp, '.')) != NULLCHAR)
  633.         *cp = '\0';
  634.   
  635.     if(stricmp(m->to,rp) == 0){
  636.         free(rp);
  637.         return -1;
  638.     }
  639.     free(rp);
  640.   
  641.     if(stricmp(m->to,"sysop") == 0)
  642.         return -1;
  643.   
  644.     if((fp = fopen(Arealist,READ_TEXT)) == NULLFILE)
  645.         return 0;
  646.   
  647.     while(fgets(buf,MBXLINE,fp) != NULLCHAR){
  648.         /* The first word on each line is all that matters */
  649.         firsttoken(buf);
  650.         if(stricmp(m->to,buf) == 0){
  651.             fclose(fp);
  652.             return -1;
  653.         }
  654.     }
  655.     fclose(fp);
  656.     return 0;
  657. }
  658.   
  659. /* Move messages from current area to another */
  660. int
  661. dombmovemail(argc,argv,p)
  662. int argc;
  663. char *argv[];
  664. void *p;
  665. {
  666.     long pos;
  667.     int num,i,j;
  668.     int move[NARG];
  669.     char *to;
  670.     struct mbx *m;
  671.     char *cp;
  672.     FILE * Mfile;           /* file to move to */
  673.     int not_area;           /* is to-file an area or a regular file? */
  674.     struct let *cmsg;
  675.     int thisone;
  676.     int start;
  677.     int end;
  678.     char *area;
  679.     struct mailindex ind;
  680.     char buf[MBXLINE];
  681.   
  682.     m = (struct mbx *)p;
  683.   
  684.     if(argc == 1) {
  685.         tputs("Syntax: MM area - moves current message\n"
  686.         "        MM n1 [n2...] area - move message n1 (n2...)\n");
  687.         return 0;
  688.     }
  689.     if(argc == 2) {
  690.         /* NO message #, use current message */
  691.         num = 1;
  692.         to = argv[1];
  693.         move[0] = m->current;
  694.     } else {
  695.         /* See if x - y format was used and use a for i = x to y loop */
  696.         if(argv[2][0] == '-') {
  697.             num=0;
  698.             start = atoi(argv[1]);
  699.             end   = atoi(argv[3]);
  700.             if(start < 0 || start > m->nmsgs || end < 0 || end > m->nmsgs ) {
  701.                 tprintf(Badmsg,start);
  702.                 start = end+1;
  703.             }
  704.             for(i=start;i<=end;i++) {
  705.                 if((move[num]=i) != 0 ) {
  706.                     if(move[num] <= m->nmsgs)
  707.                         num++;
  708.                 } else
  709.                     tprintf(Badmsg,argv[i]);
  710.             } /* endfor */
  711.         } else {
  712.             /* Scan all message # to move */
  713.             num=0;
  714.             for(i=1;i<argc-1;i++) {
  715.                 if( (move[num]=atoi(argv[i])) != 0 ) {
  716.                     if(move[num] <= m->nmsgs)
  717.                         num++;
  718.                 } else
  719.                     tprintf(Badmsg,argv[i]);
  720.             }
  721.         }
  722.         to = argv[argc-1];
  723.     }
  724.  
  725. #ifdef UNIX  
  726.     if (*to == '/') {  /* not area if begins with slash */
  727. #else
  728.     if (*to == '/' || *to == '\\' || *(to+1) == ':') {  /* not area if begins with slash or drive spec */
  729. #endif
  730.         not_area=1;
  731.         strncpy(buf, to, sizeof(buf));  buf[sizeof(buf)-1] = '\0';
  732.     }
  733.     else {
  734.         int c;
  735.  
  736.         not_area=0;
  737.         dotformat(to);
  738.         if (!isarea(to)) {
  739.             tprintf("%s is not a public area... Are you sure? ",to);
  740.             if(charmode_ok(m))
  741.                 c = tkeywait("Move(N=no)?",0);
  742.             else  /* For AX.25 and NET/ROM connects */
  743.                 c = mykeywait("Move(N=No)?",m);
  744.             if(c == -1 || c == 'n' || c == 'N') {
  745.                 tputs("Aborted.\n");
  746.                 return 0;
  747.             }
  748.         } /* endif */
  749.         dirformat(to);
  750.  
  751.         /* Now try to lock the destination file */
  752.         if(mlock(Mailspool,to) == -1) {
  753.             tprintf("Can't lock '%s', please try later\n",to);
  754.             return 0;
  755.         }
  756.         sprintf(buf,"%s/%s.txt",Mailspool,to);
  757.     }
  758.     /* open the destination file for appending, and set file pos for ftell() */
  759.     if( ((Mfile=fopen(buf,"a+")) == NULLFILE) || fseek(Mfile, 0L, SEEK_END)) {
  760.         tprintf("Can't open/seek '%s'\n",buf);
  761.         if(!not_area) rmlock(Mailspool,to);
  762.         return 0;
  763.     }
  764.   
  765.     /* Open the mailbox file for reading */
  766.     area = strdup(m->area);
  767.     dirformat(area);
  768.     sprintf(buf,"%s/%s.txt",Mailspool,area);
  769.     if((m->mfile=fopen(buf,"rt")) == NULLFILE) {
  770.         tprintf("Can't open '%s'\n",buf);
  771.         fclose(Mfile);
  772.         if(!not_area) rmlock(Mailspool,to);
  773.         free(area);
  774.         return 0;
  775.     }
  776.     memset(&ind,0,sizeof(struct mailindex));
  777.   
  778.     /* Okay, let's do the work */
  779.     for(i=0;i<num;i++) {
  780.         thisone = move[i];
  781.         cmsg = &m->mbox[thisone];
  782.   
  783.         /* find start of this message */
  784.         fseek(m->mfile,cmsg->start,0);
  785.   
  786.         /* Get the index for this message */
  787.         get_index(thisone,area,&ind);
  788.   
  789.         /* now read this message */
  790.         fgets(buf,MBXLINE,m->mfile);    /* The 'From ' line */
  791.         pos = ftell(Mfile);
  792.         fputs(buf,Mfile);
  793.         while(fgets(buf,MBXLINE,m->mfile)!= NULL) {
  794.             if(!strncmp(buf,"From ",5))
  795.                 break;
  796.             fputs(buf,Mfile);
  797.         }
  798.         if (!not_area) {
  799.             /* Update the index with the new message */
  800.             ind.size = ftell(Mfile) - pos;
  801.             if (write_index(to,&ind) == -1)
  802.                 log(m->user, "index update failed for %s", to);
  803.         }
  804.   
  805.         if((m->stype == 'C') || (m->stype == 'c')) {
  806.             tprintf("Message %d copied...\n",thisone);
  807.         } else {
  808.             /* delete this message */
  809.             cmsg->status |= BM_DELETE;
  810.             m->change = 1;
  811.             tprintf("Message %d moved...\n",thisone);
  812.         }
  813.     }
  814.     fclose(Mfile);
  815.     free(area);
  816.   
  817.     fclose(m->mfile);
  818.     m->mfile = NULL;
  819.     if(!not_area) rmlock(Mailspool,to);
  820.   
  821.     return 0;
  822. }
  823.   
  824. /*Some additional security - WG7J
  825.  *NO_3PARTY =  disallow all 3rd party mail
  826.  *NO_SENDCMD = only allow mail to sysop
  827.  */
  828. int
  829. dosend(argc,argv,p)
  830. int argc;
  831. char *argv[];
  832. void *p;
  833. {
  834.     int cccnt = 0, fail = 0;
  835.     char *host, *cp, fullfrom[MBXLINE], sigwork[LINELEN], *rhdr = NULLCHAR;
  836.     struct list *ap, *cclist = NULLLIST;
  837.     struct mbx *m;
  838.     FILE *fp;
  839. #ifdef notdef
  840.     time_t now;
  841. #endif
  842.     int done = 0;
  843.     char *cp2;
  844.     int c;
  845.   
  846. #ifdef RLINE
  847.     struct tm t;
  848. #define ODLEN   16
  849. #define OBLEN   32
  850.     char tmpline[MBXLINE];
  851.     char fwdbbs[NUMFWDBBS][FWDBBSLEN+1];
  852.     int myfwds = 0;
  853.     int i;
  854.     int zulu;
  855.     int check_r = 0;
  856.     int found_r = 0;
  857.     char origdate[ODLEN];
  858.     char origbbs[OBLEN];
  859.     int loops = 0;
  860.     char Me[15];
  861.   
  862.     origdate[0] = '\0';
  863.     origbbs[0] = '\0';
  864. #endif
  865.   
  866.     m = (struct mbx *)p;
  867.   
  868.     if((m->stype != 'R' || (m->sid & MBX_SID)) && mbx_to(argc,argv,m)
  869.     == -1){
  870.         tputs((m->sid & MBX_SID) ? "NO - syntax error\n" : \
  871.         "S command syntax error - format is:\n" \
  872.         "S[C|F] name [@ host] [< from_addr] [$bulletin_id]\n" \
  873.         "SR [number]\n");
  874. #ifdef MAILERROR
  875.         mail_error("%s: MBOX S syntax error - %s\n",m->name,cmd_line(argc,argv,m->stype));
  876. #endif
  877.         return 0;
  878.     }
  879.   
  880.     /*Check for send permission */
  881.     if(m->privs & NO_SENDCMD) { /*is this to 'SYSOP' or 'sysop' ?*/
  882.         if(stricmp(m->to,"sysop")) {
  883.             tputs((m->sid & MBX_SID) ? "NO - permission denied\n" : \
  884.             "Sorry, only mail to 'sysop' allowed!\n");
  885. #ifdef MAILERROR
  886.             mail_error("%s: no mail permission - %s\n",m->name,m->to);
  887. #endif
  888.             return 0;
  889.         }
  890.     }
  891.   
  892.     /* Check for a BID on bulletins from other bbs's - WG7J */
  893.     if((m->sid & MBX_SID) && !NoBid &&
  894.     (m->stype == 'B') && (m->tomsgid == NULLCHAR)) {
  895.         tputs("NO - No BID!\n");
  896.         log(m->user,"MBOX %s: SB without BID - %s",m->name,m->to);
  897. #ifdef MAILERROR
  898.         mail_error("MBOX %s: SB without BID - %s",m->name,m->to);
  899. #endif
  900.         return 0;
  901.     }
  902.   
  903.     if(m->stype != 'R' && msgidcheck(m->tomsgid)) {
  904.         if(m->sid & MBX_SID)
  905.             tputs("NO - ");
  906.         tprintf("Already have %s\n",m->tomsgid);
  907.         return 0;
  908.     }
  909.     if(m->stype == 'R' && !(m->sid & MBX_SID) &&
  910.     mbx_reply(argc,argv,m,&cclist,&rhdr) == -1) {
  911.         tputs("Can not reply\n");
  912.         return 0;
  913.     }
  914.     if((cp = rewrite_address(m->to)) != NULLCHAR)
  915.         if(strcmp(m->to,cp) != 0){
  916.             m->origto = m->to;
  917.             m->to = cp;
  918.         }
  919.         else
  920.             free(cp);
  921.   
  922.     /* refuse any mail that gets rewritten into 'refuse' - WG7J */
  923.     if(!strcmp(m->to,"refuse")) {
  924.         tputs((m->sid & MBX_SID) ? "NO - refused\n" : \
  925.         "Bad user or hostname,  please mail 'sysop' for help\n");
  926.         return 0;
  927.     }
  928.   
  929.     if( (!ThirdParty && !(m->privs & SYSOP_CMD)) || (m->privs & NO_3PARTY) )
  930.         if(thirdparty(m) == 0){
  931.             tputs(Mbwarning);
  932. #ifdef MAILERROR
  933.             mail_error("%s: 3rd party mail refused - %s\n",m->name,m->to);
  934. #endif
  935.             return 0;
  936.         }
  937.   
  938.     /* Send the new 'To:' line to sysops only - WG7J */
  939.     if((m->privs&SYSOP_CMD) && (m->origto != NULLCHAR || m->stype == 'R') \
  940.         && !(m->sid & MBX_SID))
  941.         tprintf("To: %s\n", m->to);
  942.     if(validate_address(m->to) == 0){
  943.         tputs((m->sid & MBX_SID) ? "NO - bad address\n" : \
  944.         "Bad user or hostname,  please mail 'sysop' for help\n");
  945.         free(rhdr);
  946.         del_list(cclist);
  947.         /* We don't free any more buffers here. They are freed upon
  948.          * the next call to mbx_to() or to domboxbye()
  949.          */
  950.         return 0;
  951.     }
  952.     /* Display the Cc: line (during SR command) */
  953.     for(ap = cclist; ap != NULLLIST; ap = ap->next) {
  954.         if(cccnt == 0){
  955.             tprintf("%s",Hdrs[CC]);
  956.             cccnt = 4;
  957.         }
  958.         else {
  959.             tputs(", ");
  960.             cccnt += 2;
  961.         }
  962.         if(cccnt + strlen(ap->val) > 80 - 3) {
  963.             tputs("\n    ");
  964.             cccnt = 4;
  965.         }
  966.         tputs(ap->val);
  967.         cccnt += strlen(ap->val);
  968.     }
  969.     if(cccnt)
  970.         tputc('\n');
  971.   
  972.     /* If the the command was 'SC' then read the Cc: list now - WG7J */
  973.     if((m->stype == 'C') && !(m->sid & MBX_SID)) {
  974.         m->stype = 'P'; /* make everything private */
  975.         tputs(CcLine);
  976.         if(mbxrecvline(m) != -1) {
  977.             if(strlen(m->line)) {
  978.                 if(*m->line == 0x01) { /* CTRL-A, abort */
  979.                     free(rhdr);
  980.                     del_list(cclist);
  981.                     tputs(MsgAborted);
  982.                     return 0;
  983.                 }
  984.                 cp = m->line;
  985.         /* get all the Cc addresses, separated by comma's */
  986.                 while((cp2=strchr(cp,',')) != NULLCHAR) {
  987.                     *cp2 = '\0';
  988.             /*get rid of leading spaces or tabs*/
  989.                     while(*cp == ' ' || *cp == '\t')
  990.                         cp++;
  991.                     if(strlen(cp))
  992.                         addlist(&cclist,cp,0);
  993.                     cp = cp2 + 1;
  994.                 }
  995.         /* Do the last or only one */
  996.         /* get rid of leading spaces or tabs*/
  997.                 while(*cp == ' ' || *cp == '\t')
  998.                     cp++;
  999.                 if(strlen(cp))
  1000.                     addlist(&cclist,cp,0);
  1001.             }
  1002.         } else {
  1003.             free(rhdr);
  1004.             del_list(cclist);
  1005.             return 0;
  1006.         }
  1007.     }
  1008.   
  1009.     /* Now check to make sure we can create the needed tempfiles - WG7J */
  1010.     if((m->tfile = tmpfile()) == NULLFILE) {
  1011.         free(rhdr);
  1012.         del_list(cclist);
  1013. /*
  1014.     tputs((m->sid & MBX_SID) ? "NO - no temp file\n" : \
  1015.         "Can't create temp file for mail\n");
  1016.     return 0;
  1017.  */
  1018.     /* instead of saying NO and have the other bbs think we already
  1019.      * have the message, disconnect !
  1020.      */
  1021.         if(m->sid & MBX_SID)
  1022.             return -2;
  1023.     /* tell regualr users about it */
  1024.         tputs("Can't create temp file for mail\n");
  1025.         return 0;
  1026.     }
  1027. #ifdef RLINE
  1028.     /* Only accept R: lines from bbs's */
  1029.     if((m->sid & MBX_SID)&&(Rdate || Rreturn || Rfwdcheck || Mbloophold)){
  1030.     /* Going to interpret R:headers,
  1031.      * we need another tempfile !
  1032.      */
  1033.         if((m->tfp = tmpfile()) == NULLFILE) {
  1034.             free(rhdr);
  1035.             del_list(cclist);
  1036. /*
  1037.         tputs("NO - no temp file\n");
  1038.         return 0;
  1039.  */
  1040.         /* disconnect to avoid the other bbs to think that we already have
  1041.          * the message !
  1042.          */
  1043.             return -2;
  1044.         }
  1045.     /* Now we got enough :-) */
  1046.         check_r = 1;
  1047.         Checklock++;
  1048.     /* Set the call, used in loop detect code - WG7J */
  1049.         if(Mbloophold) {
  1050.             pax25(Me,Mycall);
  1051.             if((cp = strchr(Me,'-')) != NULLCHAR)
  1052.                 *cp = '\0'; /* remove SSID */
  1053.         }
  1054.     }
  1055. #endif
  1056.   
  1057.     m->state = MBX_SUBJ;
  1058.     if(m->stype != 'R' || (m->sid & MBX_SID)) {
  1059.         tputs((m->sid & MBX_SID) ? "OK\n" : "Subject:\n");
  1060.         if(mbxrecvline(m) == -1) {
  1061. #ifdef RLINE
  1062.             if(check_r) {
  1063.                 MYFCLOSE(m->tfp);
  1064.                 Checklock--;
  1065.             }
  1066. #endif
  1067.             return 0;
  1068.         }
  1069.     }
  1070.     else                            /* Replying to a message */
  1071.         tprintf("Subject: %s\n",m->line);
  1072.   
  1073.     m->subject = strdup(m->line);
  1074.   
  1075. #ifdef RLINE
  1076.     if(!check_r) {
  1077. #endif
  1078.         mbx_data(m,cclist,rhdr);
  1079.     /*Finish smtp headers*/
  1080.         fprintf(m->tfile,"\n");
  1081. #ifdef RLINE
  1082.     }
  1083. #endif
  1084.     m->state = MBX_DATA;
  1085.     if(!(m->sid & MBX_SID) && m->stype != 'F')
  1086.         tprintf("Enter message.  %s",Howtoend);
  1087.   
  1088.     if(m->stype != 'F' || (m->sid & MBX_SID) != 0) {
  1089.         while(mbxrecvline(m) != -1){
  1090.             if(m->line[0] == 0x01){  /* CTRL-A */
  1091.                 MYFCLOSE(m->tfile);
  1092. #ifdef RLINE
  1093.                 if(check_r)
  1094.                     MYFCLOSE(m->tfp);
  1095. #endif
  1096.                 tputs(MsgAborted);
  1097.                 free(rhdr);
  1098.                 del_list(cclist);
  1099.                 return 0;
  1100.             }
  1101.             if(m->line[0] != CTLZ && stricmp(m->line, "/ex")) {
  1102. #ifdef RLINE
  1103.                 if(check_r) {
  1104.             /* Check for R: lines to start with */
  1105.                     if(!strncmp(m->line,"R:",2)) { /*found one*/
  1106.                         found_r = 1;
  1107.             /*Write this line to the second tempfile
  1108.              *for later rewriting to the real one
  1109.              */
  1110.                         fprintf(m->tfp,"%s\n",m->line);
  1111.             /* Find the '@[:]CALL.STATE.COUNTRY'or
  1112.              * or the '?[:]CALL.STATE.COUNTRY' string
  1113.              * The : is optional.
  1114.              */
  1115.                         if( ((cp=strchr(m->line,'@')) != NULLCHAR) ||
  1116.                         ((cp=strchr(m->line,'?')) != NULLCHAR) ) {
  1117.                             if((cp2=strchr(cp,' ')) != NULLCHAR)
  1118.                                 *cp2 = '\0';
  1119.                             if((cp2=strchr(cp,'\n')) != NULLCHAR)
  1120.                                 *cp2 = '\0';
  1121.                             if((cp2=strchr(cp,'\t')) != NULLCHAR)
  1122.                                 *cp2 = '\0';
  1123.                 /* Some bbs's send @bbs instead of @:bbs*/
  1124.                             if (*++cp == ':')
  1125.                                 cp++;
  1126.                 /* if we use 'return addres'
  1127.                  * copy whole 'domain' name
  1128.                  */
  1129.                             if(Rreturn)
  1130.                                 if(strlen(cp) <= OBLEN)
  1131.                                     strcpy(origbbs,cp);
  1132.                 /* Optimize forwarding ? */
  1133.                             if(Rfwdcheck || Mbloophold) {
  1134.                 /*if there is a HADDRESS, cut off after '.'*/
  1135.                                 if((cp2=strchr(cp,'.')) != NULLCHAR)
  1136.                                     *cp2 = '\0';
  1137.                                 if(Mbloophold)
  1138.                     /* check to see if this is my call ! */
  1139.                                     if(!stricmp(Me,cp))
  1140.                                         loops++;
  1141.                 /*cross-check with MyFwds list*/
  1142.                                 if(Rfwdcheck) {
  1143.                                     for(i=0;i<Numfwds;i++) {
  1144.                                         if(!strcmp(MyFwds[i],cp)) {
  1145.                         /*Found one !*/
  1146.                                             strcpy(fwdbbs[myfwds++],cp);
  1147.                                             break;
  1148.                                         }
  1149.                                     }
  1150.                                 }
  1151.                             }
  1152.                         }
  1153.                         if(Rdate) {
  1154.                 /* Find the 'R:yymmdd/hhmmz' string */
  1155.                             if((cp=strchr(m->line,' ')) != NULLCHAR) {
  1156.                                 *cp = '\0';
  1157.                                 if(strlen(m->line+2) <= ODLEN)
  1158.                                     strcpy(origdate,m->line+2);
  1159.                             }
  1160.                         }
  1161.                     } else {
  1162.             /* The previous line was last R: line
  1163.              * so we're done checking
  1164.              * now write the smtp headers and
  1165.              * all saved R: lines to the right tempfile
  1166.              */
  1167.                         check_r = 0;
  1168.                         Checklock--;
  1169.             /*Did we actually find one ?*/
  1170.                         if(found_r) {
  1171.                             if(Rreturn)
  1172.                                 m->origbbs = strdup(strlwr(origbbs));
  1173.                             if(Rdate) {
  1174.                                 if((cp=strchr(origdate,'/')) != NULLCHAR) {
  1175.                                     if((*(cp+5) == 'z') || (*(cp+5) == 'Z')) {
  1176.                                         *(cp+5) = '\0';
  1177.                                         zulu = 1;
  1178.                                     }
  1179.                                     t.tm_min = atoi(cp+3);
  1180.                                     *(cp+3) = '\0';
  1181.                                     t.tm_hour = atoi(cp+1);
  1182.                                     *cp = '\0';
  1183.                                     t.tm_mday = atoi(&origdate[4]);
  1184.                                     origdate[4] = '\0';
  1185.                                     t.tm_mon = (atoi(&origdate[2]) - 1);
  1186.                                     origdate[2] = '\0';
  1187.                                     t.tm_year = atoi(origdate);
  1188.                     /* Set the date in rfc 822 format */
  1189.                                     m->date = mallocw(40);
  1190.                                     sprintf(m->date,"%.2d %s %02d %02d:%02d:00 %.3s\n",
  1191.                                     t.tm_mday,
  1192.                                     Months[t.tm_mon],
  1193.                                     t.tm_year,
  1194.                                     t.tm_hour,
  1195.                                     t.tm_min,
  1196.                                     zulu ? "UTC" : "");
  1197.                                 }
  1198.                             }
  1199.                         }
  1200.             /* Now write the headers,
  1201.              * possibly adding Xforwarded lines for bulletins,
  1202.              * or anything that has a BID.
  1203.              * Add the X-Forwarded lines and loop detect
  1204.              * headers FIRST,
  1205.              * this speeds up forwarding...
  1206.              */
  1207.                         if(Mbloophold && loops >= Mbloophold)
  1208.                             fprintf(m->tfile,"%sLoop\n",Hdrs[XBBSHOLD]);
  1209.                         if(Rfwdcheck && found_r && \
  1210.                         ((m->stype == 'B') || (m->tomsgid)) ){
  1211.                 /*write Xforwarded headers*/
  1212.                             for(i=0;i<myfwds;i++) {
  1213.                                 fprintf(m->tfile,"%s%s\n",Hdrs[XFORWARD],fwdbbs[i]);
  1214.                             }
  1215.                         }
  1216.             /*write regular headers*/
  1217.                         mbx_data(m,cclist,rhdr);
  1218.             /* Finish smtp headers */
  1219.                         fprintf(m->tfile,"\n");
  1220.   
  1221.             /* Now copy the R: lines back */
  1222.                         if(found_r) {
  1223.                             rewind(m->tfp);
  1224.                             while(fgets(tmpline,sizeof(tmpline),m->tfp)!=NULLCHAR)
  1225.                                 fputs(tmpline,m->tfile);
  1226.                         }
  1227.                         MYFCLOSE(m->tfp);
  1228.   
  1229.             /* And add this first non-R: line */
  1230.                         fprintf(m->tfile,"%s\n",m->line);
  1231.                         if(m->line[strlen(m->line)-1] == CTLZ)
  1232.                             goto eol_ctlz;
  1233.                     }
  1234.                 } else
  1235. #endif
  1236.                     fprintf(m->tfile,"%s\n",m->line);
  1237.                 if(m->line[strlen(m->line)-1] == CTLZ)
  1238.                     goto eol_ctlz;
  1239.             } else {
  1240.                 eol_ctlz:
  1241. #ifdef RLINE
  1242.                 if(check_r) {
  1243.             /* Hmm, this means we never finished the R: headers
  1244.              * tmp file still open !
  1245.              */
  1246.                     MYFCLOSE(m->tfp);
  1247.                 }
  1248. #endif
  1249.                 done = 1; /* To indicate the difference between
  1250.                * mbxrecvline() returning -1 and /ex ! - WG7J
  1251.                * Now also used to indicate if the message should
  1252.                * be sent or not !
  1253.                */
  1254.         /* Now ask users if they want to send this ! - WG7J */
  1255.                 if( Mbsendquery && !(m->sid & MBX_SID)) {
  1256.                     if(m->type == TELNET_LINK || m->type == TIP_LINK)
  1257.                         c = tkeywait("Send(N=no)?",0);
  1258.                     else  /* For AX.25 and NET/ROM connects */
  1259.                         c = mykeywait("Send(N=no)?",m);
  1260.                     if(c == -1 || c == 'n' || c == 'N') {
  1261.                         done = 0;   /* signal delete of message */
  1262.                         tputs(MsgAborted);
  1263.                     }
  1264.                 }
  1265.                 break;  /* all done */
  1266.             }
  1267.         }
  1268.         if(!done) {
  1269.         /* We did NOT get ^Z or /EX, but mbxrecvline returned -1 !!!
  1270.          * This means the connection is gone ! - WG7J
  1271.          * Now can also mean that the user doesn't want to send msg !
  1272.          */
  1273.             MYFCLOSE(m->tfile);
  1274. #ifdef RLINE
  1275.             if(check_r)
  1276.                 MYFCLOSE(m->tfp);
  1277. #endif
  1278.             del_list(cclist);
  1279.             free(rhdr); /*Just in case*/
  1280.             return 0;
  1281.         }
  1282.     } else {
  1283.         fprintf(m->tfile,"----- Forwarded message -----\n\n");
  1284.         msgtofile(m);
  1285.         fprintf(m->tfile,"----- End of forwarded message -----\n");
  1286.     }
  1287.   
  1288.     free(rhdr);
  1289.     /* Insert customised signature if one is found */
  1290.     if(!(m->sid & MBX_SID)) {       /* not a forwarding BBS */
  1291.         sprintf(sigwork,"%s/%s.sig",Signature,
  1292.         m->tofrom ? m->tofrom : m->name);
  1293.         if((fp = fopen(sigwork,READ_TEXT)) != NULLFILE){
  1294.             while(fgets(sigwork,LINELEN,fp) != NULLCHAR)
  1295.                 fputs(sigwork,m->tfile);
  1296.             fclose(fp);
  1297.         }
  1298.     }
  1299.   
  1300.     if((host = strrchr(m->to,'@')) == NULLCHAR) {
  1301.         host = Hostname;        /* use our hostname */
  1302.         if(m->origto != NULLCHAR) {
  1303.             /* rewrite_address() will be called again by our
  1304.              * SMTP server, so revert to the original address.
  1305.              */
  1306.             free(m->to);
  1307.             m->to = m->origto;
  1308.             m->origto = NULLCHAR;
  1309.         }
  1310.     }
  1311.     else
  1312.         host++; /* use the host part of address */
  1313.   
  1314.     /* make up full from name for work file */
  1315.     if(m->tofrom != NULLCHAR)
  1316.         sprintf(fullfrom,"%s%%%s@%s",m->tofrom, m->name, Hostname);
  1317.     else
  1318.         sprintf(fullfrom,"%s@%s",m->name,Hostname);
  1319.     if(cclist != NULLLIST && stricmp(host,Hostname) != 0) {
  1320.         fseek(m->tfile,0L,0);   /* reset to beginning */
  1321.         fail = queuejob(m->tfile,Hostname,cclist,fullfrom);
  1322.         del_list(cclist);
  1323.         cclist = NULLLIST;
  1324.     }
  1325.     addlist(&cclist,m->to,0);
  1326.     fseek(m->tfile,0L,0);
  1327.     fail += queuejob(m->tfile,host,cclist,fullfrom);
  1328.     del_list(cclist);
  1329.     MYFCLOSE(m->tfile);
  1330.     if(fail){
  1331.         if(!(m->sid & MBX_SID)) /* only when we're not a bbs */
  1332.             tputs("Couldn't queue msg!\n");
  1333.     } else {
  1334.         if(m->sid & MBX_SID)
  1335.             MbRecvd++;
  1336.         else {
  1337.             tputs("Msg queued\n");
  1338.             MbSent++;
  1339.         }
  1340. #ifdef notdef
  1341.     /* BID is now saved in the smtp server ! - WG7J */
  1342.         if(m->tomsgid != NULLCHAR && \
  1343.         (fp = fopen(Historyfile,APPEND_TEXT)) != NULLFILE) {
  1344.         /* Timestamp added to allow automatic expiry of bid file - WG7J */
  1345.             time(&now);
  1346.             fprintf(fp,"%s %ld\n",m->tomsgid,now); /* Save BID */
  1347.             fclose(fp);
  1348.         }
  1349. #endif
  1350.     }
  1351.     /* Instead of kicking off the smtp now, let it happen in a short time.
  1352.      * That way the user gets the prompt back immediately, and the smtp kick
  1353.      * will run when the user most likely is working on typing the next command.
  1354.      * this *should* improve the user's perception of system's speed, and
  1355.      * might speed up bbs forwarding a bit too... :-) - WG7J
  1356.      */
  1357.     {
  1358.         #define WAITTM 5000L
  1359.         extern struct timer Smtpcli_t;
  1360.         int32 t,orig_dur;
  1361.   
  1362.         stop_timer(&Smtpcli_t);
  1363.         orig_dur = Smtpcli_t.duration;
  1364.         t = read_timer(&Smtpcli_t);
  1365.         if(t <= 0  || t > WAITTM)
  1366.             set_timer(&Smtpcli_t,WAITTM);  /* set timer duration */
  1367.         if(Smtpcli_t.func == NULL) {    /* in case not set yet */
  1368.             Smtpcli_t.func = (void (*)__ARGS((void*)))smtptick;/* what to call on timeout */
  1369.             Smtpcli_t.arg = NULL;       /* dummy value */
  1370.         }
  1371.         start_timer(&Smtpcli_t);        /* and fire it up */
  1372.         Smtpcli_t.duration = orig_dur;  /* then back to previous interval */
  1373.     }
  1374.  #ifdef notdef
  1375.     smtptick(NULL);     /* wake SMTP to send that mail */
  1376.  #endif
  1377.   
  1378.     return 0;
  1379. }
  1380.   
  1381.   
  1382. #endif /* MAILCMDS */
  1383.