home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / msq31004.zip / readmail.c < prev    next >
C/C++ Source or Header  |  1995-07-20  |  33KB  |  1,330 lines

  1. /* readmail.c
  2. **
  3. ** released into the PUBLIC DOMAIN 30 jul 1990 by jim nutt
  4. ** Changes released into the PUBLIC DOMAIN 10 jul 1994 by John Dennis
  5. **
  6. ** Handles high level message i/o.
  7. **
  8. */
  9.  
  10. #include "msged.h"
  11. #include "date.h"
  12. #include "bmg.h"
  13. #include "main.h"
  14. #include "menu.h"
  15.  
  16. #if 0
  17. #ifdef __EMX__
  18.     #include <sys/types.h>
  19. #endif    
  20. #endif
  21. #ifdef __MSC__ 
  22.     #include <sys\types.h>
  23.     #include <sys\timeb.h>
  24.     #include <direct.h>
  25. #endif
  26. #if defined(MSDOS) && defined(__TURBOC__)
  27.     #include <dos.h>
  28.     #include <dir.h>
  29. #endif
  30. #if 0
  31. #include <sys\stat.h>
  32. #endif
  33. #ifdef __OS2__
  34.     #define INCL_DOSFILEMGR
  35.     #include <fcntl.h>
  36. #endif
  37.  
  38. #define TEXTLEN 96
  39.  
  40. #include "normal.h"
  41.  
  42. int     setcwd(char *path);
  43. int     wrap(LINE *cl, int x, int y,int rm);
  44. int     is_quote(char *text);
  45. char *  striptwhite(char *s);
  46. void    checkrecvd(msg *m, unsigned long n);
  47. void           parse_tokens(char *str, char *tokens[], int num);
  48. static void deleteCrapLine(LINE *crap);
  49. static int is_sameaddr(ADDRESS *msg);
  50.  
  51. extern int set_rcvd;     /* located in msged.c */
  52.  
  53. #ifdef __OS2__
  54. static unsigned long setDefaultDisk(unsigned long x);
  55. #endif
  56. static int changeDir(char *path);
  57.  
  58. LINE *  clearbuffer(LINE *buffer)
  59. {
  60.     LINE *curline;
  61.     
  62.     if ((curline = buffer) != NULL)
  63.     {
  64.         while (curline->next != NULL)
  65.         {
  66.             curline = curline->next;
  67.             if (curline->prev == NULL)
  68.                 continue;
  69.             if (curline->prev->text != NULL)
  70.                 free(curline->prev->text);
  71.             curline->prev->next = NULL;
  72.             free(curline->prev);
  73.             curline->prev = NULL;
  74.         }
  75.         if (curline != NULL)
  76.         {
  77.             if (curline->text)
  78.                 free(curline->text);
  79.             curline->text = NULL;
  80.             free(curline);
  81.             curline = NULL;
  82.         }
  83.     }
  84.     return NULL;
  85. }
  86.  
  87. static void  KillTrailingLF(char *text)
  88. {
  89.     char *s;
  90.  
  91.     if (text == NULL)
  92.         return;
  93.  
  94.     if ((s = strchr(text, '\n')) != NULL)
  95.         *s = '\0';
  96. }
  97.  
  98. msg *  readmsg(unsigned long n)
  99. {
  100.     ADDRESS  a;
  101.     LINE    *l;
  102.     char    *tokens[10];
  103.     int      headerfin = 0;
  104.     int      afound    = 0;
  105.     msg      *m;
  106.     char     *text;
  107.     char     *t, *s;
  108.     char     *ptmp;
  109.     char      tmp[128];
  110.     int       goteot = 0;
  111.     int       gotsot = 0;
  112.  
  113.     l = NULL;
  114.  
  115.     memset(&a, 0, sizeof(ADDRESS));
  116.  
  117.     if ((m = MsgReadHeader(n, RD_ALL)) == NULL)
  118.         return NULL;
  119.  
  120.     stripSoft = 1;
  121.     while ((text = MsgReadText(n)) != NULL)
  122.     {
  123.         if (*text == '\n' || !strlen(text) || !stricmp(text, "Lines:"))
  124.         {
  125.             headerfin = 1;    /* want to stop looking unix header info */
  126.         }
  127.  
  128.         if (*text == '\01')
  129.         {
  130.             switch (*(text+1))
  131.             {
  132.                 case 'M' :
  133.                     if (strncmp(text+1,"MSGID:",6)!=0)
  134.                         break;
  135.                     s = text + 7;
  136.  
  137.                     while (isspace(*s)) s++;
  138.  
  139.                     release(m->msgid);
  140.                     m->msgid = strdup(s);
  141.  
  142.                     KillTrailingLF(m->msgid);
  143.                     break;
  144.  
  145.                 case 'R' :
  146.                     if (strncmp(text+1,"REPLY:",6)!=0)
  147.                         break;
  148.                     s = text + 7;
  149.  
  150.                     while (isspace(*s)) s++;
  151.  
  152.                     release(m->reply);
  153.                     m->reply = strdup(s);
  154.  
  155.                     KillTrailingLF(m->reply);
  156.                     break;
  157.  
  158.                 case 'E' :
  159.                     if (strncmp(text+1, "EOT:", 4) == 0)
  160.                     {
  161.                         goteot = 1;
  162.                         if (gotsot && !(SW->seenbys || SW->shownotes))
  163.                         {
  164.                             m->soteot = 1;
  165.                         }
  166.                     }
  167.                     break;
  168.  
  169.                 case 'S' :
  170.                     if (strncmp(text+1, "SOT:", 4) == 0) 
  171.                     {
  172.                         gotsot = 1;
  173.                         stripSoft = 0;
  174.                     }
  175.                     break;
  176.  
  177.                 case 'F' :
  178.                     if (strncmp(text+1, "FMPT", 4)!=0)
  179.                         break;
  180.  
  181.                     s = text + 5;
  182.                     m->from.point = atoi(s + 1);
  183.                     break;
  184.  
  185.                 case 'T' :
  186.                     if (strncmp(text+1, "TOPT", 4)!=0)
  187.                         break;
  188.                     s = text + 5;
  189.                     m->to.point = atoi(s + 1);
  190.                     break;
  191.  
  192.                 case 'D' :
  193.                     if (strncmp(text+1, "DOMAIN", 6)!=0)
  194.                         break;
  195.  
  196.                     s = text + 7;
  197.                     strcpy(tmp, s);
  198.                     memset(tokens, 0, sizeof(tokens));
  199.                     parse_tokens(tmp, tokens, 4);
  200.  
  201.                     if (!tokens[3])
  202.                         break;
  203.  
  204.                     memset(&a, 0, sizeof(ADDRESS));
  205.                     a = parsenode(tokens[1]);
  206.                     if (a.fidonet)
  207.                     {
  208.                         release(m->to.domain);
  209.                         m->to        = a;
  210.                         m->to.domain = strdup(tokens[0]);
  211.                     }
  212.  
  213.                     memset(&a, 0, sizeof(ADDRESS));
  214.                     a = parsenode(tokens[3]);
  215.                     if (a.fidonet)
  216.                     {
  217.                         release(m->from.domain);
  218.                         m->from        = a;
  219.                         m->from.domain = strdup(tokens[2]);
  220.                     }
  221.                     break;
  222.  
  223.                 case 'I' :
  224.                     if (strncmp(text+1,"INTL", 4)!=0)
  225.                         break;
  226.  
  227.                     s = text + 5;
  228.                     strcpy(tmp, s + 1);
  229.                     memset(tokens, 0, sizeof(tokens));
  230.                     parse_tokens(tmp, tokens, 2);
  231.  
  232.                     if (!tokens[1])
  233.                         break;
  234.  
  235.                     memset(&a, 0, sizeof(ADDRESS));
  236.                     a = parsenode(tokens[0]);
  237.                     if (a.fidonet)
  238.                     {
  239.                         release(m->to.domain);
  240.                         m->to = a;
  241.                     }
  242.                     memset(&a, 0, sizeof(ADDRESS));
  243.                     a = parsenode(tokens[1]);
  244.                     if (a.fidonet)
  245.                     {
  246.                         release(m->from.domain);
  247.                         m->from = a;
  248.                     }
  249.                     break;
  250.             }
  251.  
  252.             if (!SW->shownotes)
  253.             {
  254.                 release(text);
  255.                 continue;
  256.             }
  257.         }
  258.  
  259.         if (*text == 'S')
  260.         {
  261.             if ((strncmp(text,"SEEN-BY:",8) == 0) 
  262.                 && (!(SW->seenbys || SW->shownotes))
  263.                 && (!gotsot || goteot))
  264.             {
  265.                 release(text);
  266.                 continue;
  267.             }
  268.         }
  269.         
  270.         /*
  271.         ** From Roland Gautschi
  272.         */
  273.  
  274.         if (SW->tabexpand && strchr(text, '\t') != NULL)
  275.         {
  276.             do
  277.             {
  278.                 if ((ptmp = strdup(text)) != NULL)
  279.                 {
  280.                     release(text);
  281.  
  282.                     text = malloc(strlen(ptmp) + SW->tabsize);
  283.                     t    = strchr(ptmp,'\t');
  284.  
  285.                     /*
  286.                     ** characters before \t
  287.                     */
  288.  
  289.                     strncpy(text,ptmp, (size_t)(t - ptmp));
  290.  
  291.                     /*
  292.                     ** replace \t with spaces
  293.                     */
  294.  
  295.                     memset(text + (size_t)(t - ptmp), ' ', SW->tabsize);
  296.  
  297.                     /*
  298.                     ** copy the rest
  299.                     */
  300.  
  301.                     strcpy(text + (size_t)(t - ptmp) + SW->tabsize, t + 1);
  302.                     free(ptmp);
  303.                 }
  304.                 else
  305.                 {
  306.                     outamemory();                  /* shouldn't happen :-) */
  307.                 }
  308.             } while(strchr(text, '\t') != NULL);
  309.         }
  310.  
  311.         if (CurArea.echomail)
  312.         {
  313.             if (afound == 0 && strlen(text) > 10 && *(text + 1) == '*')
  314.             {
  315.                 if (!strncmp(text, " * Origin:", 10))  /* probably the origin line */
  316.                 {      
  317.                     if ((s = strrchr(text, '(')) != NULL)
  318.                     {
  319.                         while (*s && !isdigit(*s) && *s != ')')
  320.                             s++;
  321.  
  322.                         if (isdigit(*s))
  323.                             m->from = parsenode(s);
  324.                     }
  325.                     else
  326.                         m->from.notfound = 1;
  327.                 }
  328.             }
  329.         }
  330.  
  331.  
  332.  
  333.         if (SW->soteot)
  334.         {
  335.             if ((strncmp(text, "---", 3) == 0) 
  336.                 && (strncmp(text, "----", 4) != 0)
  337.                 && !(SW->seenbys || SW->shownotes)
  338.                 && (!gotsot || goteot))
  339.             {
  340.                 release(text);
  341.                 continue;
  342.             }
  343.         
  344.                 if ((strncmp(text, " * Origin:", 10) == 0) 
  345.                 && !(SW->seenbys || SW->shownotes)
  346.                 && (!gotsot || goteot))
  347.             {
  348.                 release(text);
  349.                 continue;
  350.             } 
  351.         }
  352.  
  353.         
  354.         if ((CurArea.uucp || CurArea.news) && headerfin == 0)
  355.         {
  356.             char *s;
  357.  
  358.             if (CurArea.uucp)
  359.             {
  360.                 if (strncmp(text,"To:",3) == 0)
  361.                 {
  362.                     s = strchr(text,' ');
  363.                     m->to.fidonet  = 0;
  364.                     m->to.internet = 0;
  365.                     m->to.bangpath = 0;
  366.                     m->to.notfound = 0;
  367.                     while (isspace(*s)) s++;
  368.                     if (strchr(s,'@') != NULL)
  369.                         m->to.internet = 1;
  370.                     else
  371.                         m->to.bangpath = 1;
  372.                     release(m->to.domain);
  373.                     m->to.domain = strdup(s);
  374.                     striptwhite(m->to.domain);
  375.                     if (!SW->shownotes)
  376.                     {
  377.                         release(text);
  378.                         continue;
  379.                     }
  380.                 }
  381.             }
  382.  
  383.             if (strncmp(text,"From:",5) == 0)
  384.             {
  385.                 s = strrchr(text,'(');
  386.                 if (s == NULL)
  387.                 {
  388.                     release(m->isfrom);
  389.                     m->isfrom = strdup("UUCP");
  390.                 }
  391.                 else
  392.                 {
  393.                     *s = '\0';
  394.                     if ((t = strrchr(s+1,')')) != NULL)
  395.                         *t = '\0';
  396.                     m->isfrom = strdup(s+1);
  397.                 }
  398.                 s = strchr(text,' ') + 1;
  399.                 m->from.fidonet  = 0;
  400.                 m->from.internet = 0;
  401.                 m->from.bangpath = 0;
  402.                 m->from.notfound = 0;
  403.                 while (isspace(*s)) s++;
  404.                 if (strchr(s,'@') != NULL)
  405.                     m->from.internet = 1;
  406.                 else
  407.                     m->from.bangpath = 1;
  408.                 release(m->from.domain);
  409.                 m->from.domain = strdup(s);
  410.                 striptwhite(m->from.domain);
  411.                 if (!SW->shownotes)
  412.                 {
  413.                     release(text);
  414.                     continue;
  415.                 }
  416.             }
  417. /*
  418. ** Commented out code...
  419. **
  420. ** We don't parse the date; we hope the gate has done that
  421. ** for us...
  422. **
  423.             if (strncmp(text,"Date:",5) == 0)
  424.             {
  425.                 s = strchr(text,' ');
  426.                 if (s != NULL)
  427.                 {
  428.                     while (isspace(*s)) s++;
  429.                     m->timestamp = parsedate(s);
  430.                 }
  431.                 if (!SW->shownotes)
  432.                 {
  433.                     release(text);
  434.                     continue;
  435.                 }
  436.             }
  437.  
  438. ** End of commented out code.
  439. **
  440. */
  441.         }
  442.  
  443.         if ((*text != '\01') || SW->shownotes)
  444.         {
  445.             if (l == NULL)
  446.             {
  447.                 l       = calloc(1, sizeof(LINE));
  448.                 m->text = l;
  449.                 l->next = l->prev = NULL;
  450.             }
  451.             else
  452.             {
  453.                 l->next = (LINE *) calloc(1, sizeof(LINE));
  454.                 if (l->next == NULL)
  455.                 {
  456.                     free(text);  /* outamemory! (?) */
  457.                     break;
  458.                 }
  459.                 l->next->next = NULL;
  460.                 l->next->prev = l;
  461.                 l             = l->next;
  462.             }
  463.  
  464.             l->block = 0;
  465.             l->text  = text;
  466.             l->hide  = (*text ==  '\x01');
  467.  
  468.             if (is_quote(text))
  469.                 l->quote = 1;
  470.             else
  471.                 l->quote = 0;
  472.  
  473.             if (l->quote)
  474.             {
  475.                 if (strlen(l->text) > maxx)
  476.                 {
  477.                     wrap(l,1,maxy, maxx);
  478.                     while (l->next)
  479.                         l = l->next;
  480.                 }
  481.             }
  482.             else
  483.             {
  484.                 if ((*text != '\01') && (*text != '\n') && (strlen(text) > maxx))
  485.                 {
  486.                     wrap(l, 1, maxy, maxx);
  487.                     while (l->next)
  488.                         l = l->next;
  489.                 }
  490.             }
  491.         }
  492.         else
  493.             release(text);
  494.     }
  495.     
  496.     MsgClose();
  497.  
  498.     if (set_rcvd)
  499.         checkrecvd(m, n);
  500.  
  501.     return m;
  502. }
  503.  
  504.  
  505. /*
  506. **
  507. ** Checks to see if a message has been recieved. If so,
  508. ** it reads the msg header again (avoiding translations
  509. ** done in the original readinf process) and then writes
  510. ** the header to the msgbase.
  511. **
  512. */
  513.  
  514. void  checkrecvd(msg *m, unsigned long n)
  515. {
  516.     msg *mn;
  517.  
  518.     if (m->attrib.recvd)
  519.         return;
  520.  
  521.     m->times_read++;
  522.  
  523.     if ((stricmp(ST->username, m->isto) == 0) && is_sameaddr(&m->to)) 
  524.     {
  525.         if ((mn = MsgReadHeader(n, RD_HEADER)) == NULL)
  526.             return;
  527.  
  528.         mn->attrib.recvd = 1;
  529.         m->attrib.recvd  = 1;
  530.         m->newrcvd      = 1;
  531.         mn->times_read++;
  532.         MsgWriteHeader(mn, WR_HEADER);
  533.         dispose(mn);
  534.     }
  535. }
  536.  
  537. static int is_sameaddr(ADDRESS *msg)
  538. {
  539.     if (msg->zone != CurArea.addr.zone)
  540.     {
  541.         return (0);
  542.     }
  543.     if (msg->net != CurArea.addr.net)
  544.     {
  545.         return (0);
  546.     }
  547.     if (msg->node != CurArea.addr.node)
  548.     {
  549.         return (0);
  550.     }
  551.     if (msg->point != CurArea.addr.point)
  552.     {
  553.         return (0);
  554.     }
  555.     return (1);
  556. }
  557.  
  558. /*
  559. **
  560. ** Clears a message only - wipes the slate clean.
  561. **
  562. */
  563.  
  564. void  clearmsg(msg *m)
  565. {
  566.     if (m == NULL)
  567.         return;
  568.                                            /* kill the header stuff */
  569.     release(m->reply);
  570.     release(m->msgid);
  571.     release(m->isfrom);
  572.     release(m->isto);
  573.     release(m->subj);
  574.     release(m->to.domain);
  575.     release(m->from.domain);
  576.  
  577.     if (m->text)
  578.         m->text = clearbuffer(m->text);    /* kill the text */
  579.                                            /* clear the whole lot */
  580.     memset(m, 0, sizeof(msg));
  581.                                            /* set the defaults */
  582.     m->attrib.private  = CurArea.priv;
  583.     m->attrib.crash    = CurArea.crash;
  584.     m->attrib.hold     = CurArea.hold;
  585.     m->attrib.direct   = CurArea.direct;
  586.     m->attrib.killsent = CurArea.killsent;
  587.     m->attrib.local    = 1;
  588. }
  589.  
  590.  
  591. int  setcwd(char *path)
  592. {
  593.     char *p;
  594.  
  595.     if ((p = strchr(path,':')) == NULL)
  596.         p = path;
  597.  
  598.     if (*p == ':') {
  599.         p++;
  600. #ifdef __OS2__
  601.         (void) setDefaultDisk((unsigned short)(toupper(*path) - 'A'+1));
  602. #else
  603.         bdos(14,toupper(*path) - 'A',0);
  604. #endif
  605.     }
  606.     return(changeDir(p));
  607. }
  608.  
  609.  
  610. /* Gives us the time down to 10th of a second granulinity.   */
  611. /* Originally from MsgPost.c by Colin Wheat @ 3:690/613      */
  612. /* Modified to reflect a routine by Lincoln Dale @ 3:690/626 */
  613. /* Modified by Paul Edwards to make it 1 second granularity  */
  614. /* but portable                                              */
  615.  
  616. unsigned long  sec_time(void)
  617. {
  618.     static unsigned long old_id = 0;
  619.     unsigned long i;
  620.     time_t now;
  621.     struct tm *t;
  622.  
  623.     now = time(NULL);
  624.     t   = localtime(&now);
  625.     i = (t->tm_sec  * 10L) +
  626.         (t->tm_min  * 600L) +
  627.         (t->tm_hour * 36000L) +
  628.         (t->tm_mday  * 864000L) +
  629.         (t->tm_mon  * 26784000L) +
  630.         (t->tm_year * 321408000L);
  631.  
  632.     if (i <= old_id)
  633.     {
  634.         i = old_id + 1;
  635.     }
  636.  
  637.     return (old_id = i);
  638. }
  639.  
  640.  
  641. /*
  642. **
  643. ** Inserts a line after the passed line and returns a pointer to it.
  644. **
  645. */
  646.  
  647. static LINE *InsertAfter(LINE *l, char *text)
  648. {
  649.     LINE *nl;
  650.  
  651.     if ((nl = calloc(1, sizeof(LINE))) == NULL)
  652.         return NULL;
  653.  
  654.     nl->text = strdup(text);
  655.  
  656.     if (l == NULL)
  657.         return nl;
  658.  
  659.     nl->next = l->next;
  660.     nl->prev = l;
  661.     l->next  = nl;
  662.     if (nl->next)
  663.         nl->next->prev = nl;
  664.  
  665.     return nl;
  666. }
  667.  
  668.  
  669. /*
  670. **
  671. ** Strips all the kludges from the message, kludges being
  672. ** defined as ^a, SEEN-BY:, tear + origin lines.
  673. **
  674. */
  675.  
  676. static void  StripKludges(msg *m)
  677. {
  678.     LINE *l, *ol;
  679.  
  680.     ol = NULL;
  681.     l = m->text;
  682.     while (l != NULL)
  683.     {
  684.         if ((l->text == NULL) 
  685.             || ((*(l->text) == '\x01')
  686.                 || ((!SW->soteot || SW->seenbys || SW->shownotes)
  687.                     && ((strncmp(l->text, "SEEN-BY:", 8) == 0)
  688. // orig                       || (strncmp(l->text, "---", 3) == 0)
  689. // orig                       || (strncmp(l->text, " * Origin:", 10) == 0)))))
  690. //                        || ((strncmp(l->text, "---", 3) == 0) && !m->new && (!m->change || SW->soteot) && (!m->movecopy || SW->soteot) )
  691. //                        || ((strncmp(l->text, " * Origin:", 10) == 0) && !m->new && (!m->change || SW->soteot) && (!m->movecopy || SW->soteot) )
  692.                         || ((strncmp(l->text, "--- ", 4) == 0) && (!m->change || SW->soteot) && (!m->movecopy || SW->soteot) && !CurArea.netmail)
  693.                         || ((strncmp(l->text, " * Origin:", 10) == 0) && (!m->change || SW->soteot) && (!m->movecopy || SW->soteot) && !CurArea.netmail)
  694.                             ))))
  695.         {
  696.             if (ol == NULL)
  697.             {
  698.                 if (l->next != NULL)
  699.                 {
  700.                     l->next->prev = l->prev;
  701.                 }
  702.                 m->text = l->next;
  703.                 if (l->text != NULL)
  704.                 {
  705.                     release(l->text);
  706.                 }
  707.                 release(l);
  708.                 l = m->text;
  709.             }
  710.             else
  711.             {
  712.                 if (l->next != NULL)
  713.                 {
  714.                     l->next->prev = l->prev;
  715.                 }
  716.                 ol->next = l->next;
  717.                 if (l->text != NULL)
  718.                 {
  719.                     release(l->text);
  720.                 }
  721.                 release(l);
  722.                 l = ol;
  723.             }
  724.         }
  725.         else
  726.         {
  727.             ol = l;
  728.             l = l->next;
  729.         }
  730.     }
  731.  
  732.     l = ol;
  733.     while (l != NULL)
  734.     {
  735.         if ((l->text == NULL)
  736.             || (*(l->text) == '\0')
  737.             || (*(l->text) == '\n')
  738.             || (*(l->text) == '\r'))
  739.         {
  740.             ol = l->prev;
  741.             if (l->text != NULL)
  742.             {
  743.                 release(l->text);
  744.             }
  745.             if (ol == NULL)
  746.             {
  747.                 m->text = NULL;
  748.             }
  749.             else
  750.             {
  751.                 ol->next = NULL;
  752.                 release(l);
  753.             }
  754.             l = ol;
  755.         }
  756.         else break;
  757.     }
  758.     return;
  759. }
  760.  
  761.  
  762. /*
  763. **
  764. ** Gets the origin line to use.
  765. **
  766. */
  767.  
  768. static void  GetOrigin(char *origin)
  769. {
  770.     FILE *fp;
  771.     char  path[255];
  772.  
  773.     if (!SW->override)
  774.     {
  775.         if (CurArea.msgtype == SQUISH)
  776.             sprintf(path, "%s.SQO",     CurArea.path);
  777.         else
  778.             sprintf(path, "%s\\origin", CurArea.path);
  779.  
  780.         if ((fp = fopen(path,"r")) != NULL)
  781.         {
  782.             fgets(origin, 65, fp);
  783.             fclose(fp);
  784.         }
  785.         else
  786.         {
  787.             if (ST->origin != NULL)
  788.                 strcpy(origin, ST->origin);
  789.             else
  790.                 strcpy(origin, ST->username);
  791.         }
  792.     }
  793.     else
  794.     {
  795.         if (ST->origin != NULL)
  796.             strcpy(origin, ST->origin);
  797.         else
  798.             strcpy(origin, ST->username);
  799.     }
  800.     striptwhite(origin);
  801. }
  802.  
  803.  
  804. /*
  805. ** Sequence of events:
  806. **
  807. ** Original address is saved (what is displayed);
  808. ** Domain gates are checked for and address is modified if one found;
  809. ** if no domain gates, search for UUCP gate && mod address if found.
  810. ** check INTL
  811. ** check MSGID
  812. ** check REPLY
  813. ** do PID if one,
  814. ** If we found domain gate, do DOMAIN with original saved addresses.
  815. ** if we found UUCP, then do a "to:" kludge.
  816. */
  817.  
  818. /*
  819. **
  820. ** Writes a message to disk.
  821. **
  822. **
  823. */
  824.  
  825. int  writemsg(msg *m)
  826. {
  827.     LINE    *curr, *l, *ufrom, *uto, *xblank, *xtear, *xorigin;
  828.     ADDRESS  to;
  829.     ADDRESS  from;
  830.     unsigned long now;
  831.     unsigned long    n;                            /* UMSGID msgnum */
  832.     unsigned long    length;                       /* length in bytes of the message */
  833.     char     text   [255];                 /* buffer useage */
  834.     char     origin [255];                 /* out origin line */
  835.     char    *uucp_from;                    /* saved UUCP from address */
  836.     char    *uucp_to;                      /* saved UUCP to address */
  837.     int      domain_gated;
  838.     int      uucp_gated;
  839.     char    *s;
  840.     int      i;
  841.     int      abortWrite;
  842.  
  843.     domain_gated = 0;
  844.     uucp_gated   = 0;
  845.     length       = 0;
  846.     n            = m->msgnum;
  847.     curr         = NULL;
  848.     uto          = NULL;
  849.     ufrom        = NULL;
  850.     uucp_from    = NULL;
  851.     uucp_to      = NULL;
  852.     xorigin      = NULL;
  853.     xtear        = NULL;
  854.     xblank       = NULL;
  855.     now          = sec_time();
  856.  
  857.     StripKludges(m);
  858.  
  859.     /*
  860.     ** Save the original address.
  861.     */
  862.  
  863.     to   = m->to;
  864.     from = m->from;
  865.  
  866.     /*
  867.     **
  868.     ** Do domain gating...
  869.     **
  870.     */
  871.  
  872.     if ((SW->gate == GDOMAINS || SW->gate == BOTH) && SW->domains && m->to.domain)
  873.     {
  874.         /*
  875.         ** If we have two domains and they're different, then we want to gate.
  876.         ** If we have a to: domain and no from: domain, then we still may
  877.         ** wand to gate.  If we don't have a to: domain, then we don't want
  878.         ** to gate the message (we assume it's destined to our own network).
  879.         */
  880.  
  881.         if (m->to.domain || (m->from.domain && m->to.domain && stricmp(m->from.domain, m->to.domain)))
  882.         {
  883.             for (i = 0; i < SW->domains; i++)
  884.             {
  885.                 if (!stricmp(domain_list[i].domain, m->to.domain))
  886.                 {
  887.                     domain_gated = 1;
  888.  
  889.                     if (m->attrib.crash || m->attrib.crash)
  890.                     {
  891.                         int ret;
  892.  
  893.                         ret = ChoiceBox(" Crash ", "Crash message to?", "Domain Gate", "Dest Node", NULL);
  894.                         if (ret == ID_ONE)
  895.                         {
  896.                             m->to = domain_list[i];
  897.                             if (domain_list[i].domain)
  898.                                 m->to.domain = strdup(domain_list[i].domain);
  899.                         }
  900.                     }
  901.                     else
  902.                     {
  903.                         m->to = domain_list[i];
  904.                         if (domain_list[i].domain)
  905.                             m->to.domain = strdup(domain_list[i].domain);
  906.                     }
  907.                     break;
  908.                 }
  909.             }
  910.         }
  911.     }
  912.  
  913.     /*
  914.     **
  915.     ** Do UUCP gating...
  916.     **
  917.     */
  918.  
  919.     if (m->to.internet || m->to.bangpath)
  920.     {
  921.         uucp_gated = 1;
  922.         uucp_to    = m->to.domain;
  923.         m->to      = uucp_gate;
  924.         if (uucp_gate.domain)
  925.             m->to.domain = strdup(uucp_gate.domain);
  926.     }
  927.  
  928.     if (m->from.internet || m->from.bangpath)
  929.     {
  930.         uucp_gated = 1;
  931.         uucp_from  = m->from.domain;
  932.         m->from    = uucp_gate;
  933.         if (uucp_gate.domain)
  934.             m->from.domain = strdup(uucp_gate.domain);
  935.     }
  936.  
  937.     /*
  938.     **
  939.     ** Do the netmail stuff;
  940.     **
  941.     */
  942.  
  943.     if (CurArea.netmail || CurArea.uucp)
  944.     {
  945.         if (m->from.zone != m->to.zone || m->from.zone != thisnode.zone)
  946.         {
  947.             sprintf(text, "\01INTL %d:%d/%d %d:%d/%d\r", m->to.zone, m->to.net, m->to.node, m->from.zone, m->from.net, m->from.node);
  948.             curr = InsertAfter(curr, text);
  949.         }
  950.         if (m->to.point)
  951.         {
  952.             sprintf(text, "\01TOPT %d\r", m->to.point);
  953.             curr = InsertAfter(curr, text);
  954.         }
  955.         if (m->from.point)
  956.         {
  957.             sprintf(text, "\01FMPT %d\r", m->from.point);
  958.             curr = InsertAfter(curr, text);
  959.         }
  960.     }
  961.  
  962.     /*
  963.     **
  964.     ** These babies go everywhere.
  965.     **
  966.     */
  967.  
  968.     if (m->new)
  969.     {
  970.         if (SW->msgids)
  971.         {
  972.             sprintf(text, "\01MSGID: %s %08lx\r", show_address(&from), now);
  973.             curr = InsertAfter(curr, text);
  974.         }
  975.     }
  976.     else
  977.     {
  978.         if (m->msgid)
  979.         {
  980.             sprintf(text, "\01MSGID: %s\r", m->msgid);
  981.             curr = InsertAfter(curr, text);
  982.         }
  983.     }
  984.  
  985.     if (m->reply)
  986.     {
  987.         sprintf(text, "\01REPLY: %s\r", m->reply);
  988.         curr = InsertAfter(curr, text);
  989.     }
  990.  
  991.     if (SW->usepid || CurArea.netmail)
  992.     {
  993.         sprintf(text, "\01PID: %s %s\r", PROG, PIDVER PIDALPHA);
  994.         curr = InsertAfter(curr, text);
  995.     }
  996.  
  997.     /*
  998.     **
  999.     ** Domain gating?
  1000.     **
  1001.     */
  1002.  
  1003.     if (domain_gated)
  1004.     {
  1005.         sprintf(text, "\01DOMAIN %s %d:%d/%d.%d %s %d:%d/%d.%d\r",
  1006.                     to.domain,
  1007.                     to.zone,
  1008.                     to.net,
  1009.                     to.node,
  1010.                     to.point,
  1011.                     from.domain,
  1012.                     from.zone,
  1013.                     from.net,
  1014.                     from.node,
  1015.                     from.point);
  1016.         curr = InsertAfter(curr, text);
  1017.     }
  1018.     
  1019.     if (SW->soteot)
  1020.     {
  1021.         strcpy(text, "\01SOT:\r");
  1022.         curr = InsertAfter(curr, text);
  1023.     }
  1024.     
  1025.     if (uucp_gated)
  1026.     {
  1027.             int cr = 0;   /* we want to insert a \n after header info */
  1028.  
  1029.             if (uucp_from)
  1030.             {
  1031.                 sprintf(text, "From: %s\r", uucp_from);
  1032.                 curr  = InsertAfter(curr, text);
  1033.                 ufrom = curr;
  1034.                 cr      = 1;
  1035.             }
  1036.             if (uucp_to)
  1037.             {
  1038.                 sprintf(text, "To: %s\r", uucp_to);
  1039.                 curr = InsertAfter(curr, text);
  1040.                 uto  = curr;
  1041.                 cr     = 1;
  1042.             }
  1043.             if (cr == 1)
  1044.             {
  1045.                 strcpy(text, "\n");
  1046.                 curr = InsertAfter(curr, text);
  1047.             }
  1048.     }
  1049.     
  1050.     /*
  1051.     ** Actually assign the kludges we just created to
  1052.     ** the message body (before the text);
  1053.     */
  1054.  
  1055.     if (curr)
  1056.     {
  1057.         curr->next = m->text;
  1058.         if (m->text)
  1059.             m->text->prev = curr;
  1060.  
  1061.         while (curr->prev)
  1062.             curr = curr->prev;
  1063.  
  1064.         m->text = curr;
  1065.     }
  1066.  
  1067.     l = m->text;
  1068.     while (l)
  1069.     {
  1070.         if (l->text == NULL)
  1071.             l->text = strdup("\r");
  1072.  
  1073.         if (strlen(l->text) > 0)
  1074.         {
  1075.             if ((s = strchr(l->text, '\n')) != NULL)
  1076.                 *s = '\r';
  1077.                 
  1078.             if (s == NULL)
  1079.             {
  1080.                 strcpy(text, l->text);
  1081.                 if (l->quote)
  1082.                     strcat(text, "\r");
  1083.                 else
  1084.                 {
  1085.                     if (l->next && *(l->next->text) == '\n')
  1086.                         strcat(text, "\r");
  1087.                     else
  1088.                     {
  1089.                         if (!isspace(*(text + strlen(text) - 1)))
  1090.                             strcat(text, " ");
  1091.                     }
  1092.                 }
  1093.                 release(l->text);
  1094.                 l->text = strdup(text);
  1095.             }
  1096.         }
  1097.         else
  1098.         {
  1099.             if (l->next)
  1100.             {
  1101.                 release(l->text);
  1102.                 l->text = strdup("\r");
  1103.             }
  1104.         }
  1105.         l = l->next;
  1106.     }
  1107.  
  1108.     /*
  1109.     ** Find the end of the message.
  1110.     */
  1111.  
  1112.     curr = m->text;
  1113.     while (curr->next)
  1114.     {
  1115.         curr = curr->next;
  1116.     }
  1117.     /*
  1118.     ** If there isnt't a terminating '\r' on the last line, add one.
  1119.     */
  1120.  
  1121.     if (!curr->text || (curr->text && strchr(curr->text, '\r') == NULL))
  1122.     {
  1123.         sprintf(text, "%s\r", curr->text);
  1124.         release(curr->text);
  1125.         curr->text = strdup(text);
  1126.     }
  1127.     
  1128.     if (SW->soteot)
  1129.     {
  1130.         strcpy(text, "\01EOT:\r");
  1131.         curr = InsertAfter(curr, text);
  1132.     }
  1133.     
  1134. //    if (CurArea.echomail)
  1135.     if (CurArea.echomail && (!m->change || SW->soteot) && (!m->movecopy || SW->soteot) && SW->tearline)
  1136.     {
  1137.         strcpy(text, "\r");
  1138.         curr = InsertAfter(curr, text);
  1139.         xblank = curr;
  1140.     
  1141.         /*
  1142.         ** Do the tearline.
  1143.         */
  1144.  
  1145.         if (SW->usepid)
  1146.             sprintf(text, "---\r");
  1147.         else
  1148.             sprintf(text, "--- %s %s\r", PROG, VERSION CLOSED);
  1149.  
  1150.         curr = InsertAfter(curr, text);
  1151.         xtear = curr;
  1152.  
  1153.         /*
  1154.         ** Do the origin line.
  1155.         */
  1156.  
  1157.         GetOrigin(origin);
  1158.         sprintf(text, " * Origin: %s (%s", origin, show_address(&from));
  1159.  
  1160.         /*
  1161.         ** Eliminate the '@' in a fido address (if there is one).
  1162.         */
  1163.  
  1164.         s = text + strlen(text) - 1;
  1165.         while (*s != '(')
  1166.         {
  1167.             if (*s == '@')
  1168.             {
  1169.                 *s = '\0';
  1170.                 break;
  1171.             }
  1172.             s--;
  1173.         }
  1174.         strcat(text, ")\r");
  1175.         curr = InsertAfter(curr, text);
  1176.         xorigin = curr;
  1177.     }
  1178.  
  1179.     /*
  1180.     ** Ok, we've made the new message up; return it's length.
  1181.     */
  1182.  
  1183.     l = m->text;
  1184.     while (l)
  1185.     {
  1186.         length += strlen(l->text);
  1187.         l       = l->next;
  1188.     }
  1189.         
  1190.     /*
  1191.     **
  1192.     ** Remap point originated crashmail.
  1193.     **
  1194.     */
  1195.  
  1196.     if (!m->attrib.direct && !m->attrib.crash && m->from.point && SW->pointnet != 0 && CurArea.netmail)
  1197.     {
  1198.         m->from.net   = SW->pointnet;
  1199.         m->from.node  = m->from.point;
  1200.         m->from.point = 0;
  1201.     }
  1202.  
  1203.     /*
  1204.     **
  1205.     ** Do any required zone gating.
  1206.     **
  1207.     */
  1208.  
  1209.     if (CurArea.addr.zone != m->to.zone && !m->attrib.direct && !m->attrib.crash && CurArea.netmail && (SW->gate == GZONES || SW->gate == BOTH))
  1210.     {
  1211.         m->to.node = m->to.zone;
  1212.         m->to.zone = CurArea.addr.zone;
  1213.         m->to.net  = CurArea.addr.zone;
  1214.     }
  1215.  
  1216.     abortWrite = 0;    
  1217.     while ((MsgWriteHeader(m, WR_ALL) == ERR_OPEN_MSG) && !abortWrite)
  1218.     {
  1219.         int ret;
  1220.  
  1221.         ret = ChoiceBox(" Error! ", "Could not write message!", "Retry", "Cancel", NULL);
  1222.         if (ret == ID_TWO)
  1223.         {
  1224.             abortWrite = 1;
  1225.         }
  1226.     }
  1227.  
  1228.     if (!abortWrite)
  1229.     {
  1230.         l = m->text;
  1231.         while (l)
  1232.         {
  1233.             MsgWriteText(l->text, n, length);
  1234.  
  1235.             /*
  1236.             ** The \r's have to be turned back into \n's because
  1237.             ** the message might be a CC: and so be needed again.
  1238.             */
  1239.  
  1240.             if ((s = strchr(l->text, '\r')) != NULL)
  1241.                 *s = '\n';
  1242.  
  1243.             l = l->next;
  1244.         }
  1245.  
  1246.         MsgWriteText(NULL, n, length);
  1247.     }
  1248.     MsgClose();
  1249.  
  1250.     CurArea.new = 1;
  1251.  
  1252.     /*
  1253.     ** Clean up;  If this message is a CC, then we
  1254.     ** don't want this temporary information to remain.
  1255.     */
  1256.  
  1257.     if (uucp_from)
  1258.     {
  1259.         release(uucp_from);
  1260.         deleteCrapLine(ufrom);
  1261.     }
  1262.  
  1263.     if (uucp_to)
  1264.     {
  1265.         release(uucp_to);
  1266.         deleteCrapLine(uto);
  1267.     }
  1268.     
  1269.     deleteCrapLine(xblank);
  1270.     deleteCrapLine(xtear);
  1271.     deleteCrapLine(xorigin);
  1272.     
  1273.     if (abortWrite) return FALSE;
  1274.     else return TRUE;
  1275. }
  1276.  
  1277. static void deleteCrapLine(LINE *crap)
  1278. {
  1279.     if (crap != NULL)
  1280.     {
  1281.         if (crap->prev != NULL) crap->prev->next = crap->next;
  1282.         if (crap->next != NULL) crap->next->prev = crap->prev;
  1283.         release(crap->text);
  1284.         release(crap);
  1285.     }
  1286.     return;
  1287. }
  1288.  
  1289. #ifdef __OS2__
  1290.  
  1291. #include <os2.h>
  1292.  
  1293. static unsigned long setDefaultDisk(unsigned long x)
  1294. {
  1295.     return (DosSetDefaultDisk(x));
  1296. }
  1297.  
  1298. static int changeDir(char *path)
  1299. {
  1300.     return (DosSetCurrentDir(path));
  1301. }
  1302.  
  1303. void mygetcwd(char *buf, int len)
  1304. {
  1305.     unsigned long ulen;
  1306.     
  1307.     ulen = len;
  1308.     DosQueryCurrentDir(0, buf, &ulen);
  1309.     return;
  1310. }
  1311.  
  1312. #else
  1313.  
  1314. static int changeDir(char *path)
  1315. {
  1316.     return (chdir(path));
  1317. }
  1318.  
  1319. void mygetcwd(char *buf, int len)
  1320. {
  1321.     getcwd(buf, len);
  1322.     return;
  1323. }
  1324.  
  1325. #endif
  1326.  
  1327. /*--- end ---*/
  1328.  
  1329.  
  1330.