home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / internet / tcpipsrc / h / if / Radio / c / ax_mbx next >
Encoding:
Text File  |  1994-06-05  |  34.5 KB  |  871 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <ctype.h>
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "ax25.h"
  9. #include "timer.h"
  10. #include "iface.h"
  11. #include "lapb.h"
  12. #include "netrom.h"
  13. #include "nr4.h"
  14. #include "ax_mbx.h"
  15. #include "cmdparse.h"
  16. #include "smtp.h"
  17. #include "misc.h"
  18.  
  19. /*
  20. #define MBDEBUG
  21. */
  22.  
  23. struct mbx *mbox[NUMMBX] ;
  24. int ax25mbox ;
  25.  
  26. static char mbbanner[] =
  27. "[NET-$]\rWelcome %s to the %s TCP/IP Personal Mailbox.\r(C)hat, (S)end, (B)ye >\r" ;
  28. static char mbmenu[] = "(C)hat, (S)end, (B)ye >\r" ;
  29.  
  30. static void domboxdisplay(void);
  31. static struct mbx *newmbx(void);
  32. static void free_mbx(struct mbx *);
  33. static int mbx_line(struct mbx *);
  34. static int mbx_msg(struct mbx *, char *);
  35. static int mbx_to(struct mbx *);
  36. static int mbx_data(struct mbx *);
  37.  
  38. int dombox(int argc, char **argv)
  39. {
  40.         if (argc < 2)
  41.         {
  42.                 domboxdisplay() ;
  43.                 return 0 ;
  44.         }
  45.  
  46.         if (argv[1][0] == 'y' || (strcmp(argv[1],"on") == 0))
  47.                 ax25mbox = 1 ;
  48.         else if (argv[1][0] == 'n' || (strcmp(argv[1],"off") == 0))
  49.                 ax25mbox = 0 ;
  50.         else if (argv[1][0] == '?')
  51.                 cwprintf(NULL, "ax25 mailbox is %s\r\n", ax25mbox ? "on" : "off") ;
  52.         else
  53.                 cwprintf(NULL, "usage: mbox [y|n|?]\r\n") ;
  54.  
  55.         return 0 ;
  56. }
  57.  
  58. static void domboxdisplay(void)
  59. {
  60.         int i ;
  61.         struct mbx *m ;
  62.   static char *states[] = {
  63.     "NONE","CMD","SUBJ","DATA"    }
  64.   ;
  65.   static char *mbtype[] = {
  66.     "NONE","AX25 ","NET/ROM"    }
  67.   ;
  68.  
  69.         cwprintf(NULL, " User     State     Type      &cb     &mbx   BBS\r\n") ;
  70.  
  71.         for (i = 0 ; i < NUMMBX ; i++)
  72.                 if ((m = mbox[i]) != NULLMBX)
  73.                         cwprintf(NULL, "%-10s %-4s     %-7s   %04x    %04x   %s\r\n", m->name,
  74.                         states[m->state], mbtype[m->type],
  75.                         m->type == MBX_AX25 ? (int)m->cb.ax25_cb : (int)m->cb.nr4_cb,
  76.                         (int)m, m->mblforw ? "Yes" : " No") ;
  77. }
  78.  
  79.  
  80. static struct mbx *newmbx(void)
  81. {
  82.         int i ;
  83.         struct mbx *m ;
  84.  
  85.         for (i = 0 ; i < NUMMBX ; i++)
  86.     if (mbox[i] == NULLMBX)
  87.     {
  88.                         if ((m = mbox[i] = (struct mbx *)calloc(1,sizeof(struct mbx))) == NULLMBX)
  89.                                 return NULLMBX ;
  90.                         m->mbnum = i ;
  91.                         return m ;
  92.                 }
  93.  
  94.         /* If we get here, there are no free mailbox sessions */
  95.  
  96.         return NULLMBX ;
  97. }
  98.  
  99.  
  100. /* Incoming mailbox session via ax.25 */
  101.  
  102. void mbx_incom(register struct ax25_cb *axp, int16 cnt)
  103. {
  104.         struct mbx *m ;
  105.         struct mbuf *bp;
  106.         char *cp ;
  107.         extern char hostname[] ;
  108.  
  109.   if ((m = newmbx()) == NULLMBX)
  110.   {
  111.                 disc_ax25(axp) ;        /* no memory! */
  112.                 return ;
  113.         }
  114.  
  115.         m->state = MBX_CMD ;    /* start in command state */
  116.         m->type = MBX_AX25 ;    /* this is an ax.25 mailbox session */
  117.         m->cb.ax25_cb = axp ;
  118.  
  119.         pax25(m->name,&axp->addr.dest) ;
  120.         cp = strchr(m->name,'-') ;
  121.         if (cp != NULLCHAR)                     /* get rid of SSID */
  122.                 *cp = '\0' ;
  123.  
  124.         m->lp = m->line ;               /* point line pointer at buffer */
  125.         axp->r_upcall = (void(*)())mbx_rx ;
  126.         axp->s_upcall = mbx_state ;
  127.         axp->user = (char *)m ;
  128.  
  129.         /* The following is necessary because we didn't know we had a */
  130.         /* "real" ax25 connection until a data packet came in.  We    */
  131.         /* can't be spitting banners out at every station who connects, */
  132.         /* since they might be a net/rom or IP station.  Sorry.  */
  133.  
  134.         bp = recv_ax25(axp,cnt) ;               /* get the initial input */
  135.         free_p(bp) ;                                    /* and throw it away to avoid confusion */
  136.  
  137.         /* Now say hi */
  138.  
  139.         if ((bp = alloc_mbuf(strlen(hostname) + strlen(m->name)
  140.       + strlen(mbbanner) + 2)) == NULLBUF)
  141.   {
  142.                 disc_ax25(axp) ; /* mbx_state will fix stuff up */
  143.                 return ;
  144.         }
  145.  
  146.         *bp->data = PID_NO_L3 ;  /* pid */
  147.         sprintf(bp->data+1,mbbanner,m->name,hostname) ;
  148.         bp->cnt = strlen(bp->data+1) + 1 ;
  149.  
  150.         send_ax25(axp,bp) ;     /* send greeting message and menu */
  151.         log_event(NULL,"AX25 Mailbox session requested : %s",m->name);
  152.  
  153. }
  154.  
  155. /* receive upcall for ax.25 */
  156. /* mbx_rx collects lines, and calls mbx_line when they are complete. */
  157. /* If the lines get too long, it arbitrarily breaks them. */
  158.  
  159. void mbx_rx(struct ax25_cb *axp, int16 cnt)
  160. {
  161.         struct mbuf *bp;
  162.         struct mbx *m ;
  163.         char c ;
  164.  
  165.         m = (struct mbx *)axp->user ;
  166.  
  167.         if ((bp = recv_ax25(axp,cnt)) == NULLBUF)
  168.                 return ;
  169.  
  170.         while (pullone(&bp,&c) == 1)
  171.         {
  172.                 if (c == '\r')
  173.                 {
  174.                         *m->lp = '\0' ;                 /* null terminate */
  175.                         if (mbx_line(m) == -1)
  176.                         {        /* call the line processor */
  177.                                 free_p(bp) ;            /* toss the rest */
  178.                                 break ;                         /* get out - we're obsolete */
  179.                         }
  180.                         m->lp = m->line ;               /* reset the pointer */
  181.                 }
  182.                 else if ((m->lp - m->line) == (MBXLINE - 1)) {
  183.                         *m->lp++ = c ;
  184.                         *m->lp = '\0' ;
  185.                         if (mbx_line(m) == -1) {
  186.                                 free_p(bp) ;
  187.                                 break ;
  188.                         }
  189.                         m->lp = m->line ;
  190.                 }
  191.                 else
  192.                         *m->lp++ = c ;
  193.         }
  194. }
  195.  
  196. /* state upcall for ax.25 */
  197.  
  198. void mbx_state(struct ax25_cb *axp, int old, int new)
  199. {
  200.         struct mbx *m ;
  201.  
  202.         old = old;
  203.  
  204.         m = (struct mbx *)axp->user ;
  205.  
  206.         /* dummy for now ... */
  207.         if (new == DISCONNECTED && axp->user != NULLCHAR) {
  208.                 axp->user = NULLCHAR ;
  209.                 free_mbx(m) ;
  210.         }
  211. }
  212.  
  213.  
  214. /* Incoming mailbox session via net/rom */
  215.  
  216. void mbx_nr4incom(register struct nr4cb *cb)
  217. {
  218.         struct mbx *m ;
  219.         struct mbuf *bp ;
  220.         char *cp ;
  221.         extern char hostname[] ;
  222.  
  223.         if ((m = newmbx()) == NULLMBX) {
  224.                 disc_nr4(cb) ;  /* no memory! */
  225.                 return ;
  226.         }
  227.  
  228.         m->state = MBX_CMD ;    /* start in command state */
  229.         m->type = MBX_NETROM ;  /* mailbox session type is net/rom */
  230.         m->cb.nr4_cb = cb ;
  231.  
  232.         pax25(m->name,&cb->user) ;
  233.         cp = strchr(m->name,'-') ;
  234.         if (cp != NULLCHAR)                     /* get rid of SSID */
  235.                 *cp = '\0' ;
  236.  
  237.         m->lp = m->line ;               /* point line pointer at buffer */
  238.         cb->r_upcall = (void(*)())mbx_nr4rx ;
  239.         cb->s_upcall = mbx_nr4state ;
  240.         cb->puser = (char *)m ;
  241.  
  242.         /* Say hi */
  243.  
  244.         if ((bp = alloc_mbuf(strlen(hostname) + strlen(m->name)
  245.                         + strlen(mbbanner) + 1)) == NULLBUF) {
  246.                 disc_nr4(cb) ; /* mbx_nr4state will fix stuff up */
  247.                 return ;
  248.         }
  249.  
  250.         sprintf(bp->data,mbbanner,m->name,hostname) ;
  251.         bp->cnt = strlen(bp->data) ;
  252.  
  253.         send_nr4(cb,bp) ;           /* send greeting message and menu */
  254.         log_event(NULL,"NET/ROM Mailbox session requested : %s",m->name);
  255.  
  256. }
  257.  
  258. /* receive upcall for net/rom */
  259. /* mbx_nr4rx collects lines, and calls mbx_line when they are complete. */
  260. /* If the lines get too long, it arbitrarily breaks them. */
  261.  
  262. void mbx_nr4rx(struct nr4cb *cb, int16 cnt)
  263. {
  264.         struct mbuf *bp ;
  265.         struct mbx *m ;
  266.         char c ;
  267.  
  268.         m = (struct mbx *)cb->puser ;
  269.  
  270.         if ((bp = recv_nr4(cb,cnt)) == NULLBUF)
  271.                 return ;
  272.  
  273.         while (pullone(&bp,&c) == 1)
  274.         {
  275.                 if (c == '\r')
  276.                 {
  277.                         *m->lp = '\0' ;                 /* null terminate */
  278.                         if (mbx_line(m) == -1) {        /* call the line processor */
  279.                                 free_p(bp) ;            /* toss the rest */
  280.                                 break ;                 /* get out - we're obsolete */
  281.                         }
  282.                         m->lp = m->line ;               /* reset the pointer */
  283.                 }
  284.                 else if ((m->lp - m->line) == (MBXLINE - 1)) {
  285.                         *m->lp++ = c ;
  286.                         *m->lp = '\0' ;
  287.                         if (mbx_line(m) == -1) {
  288.                                 free_p(bp) ;
  289.                                 break ;
  290.                         }
  291.                         m->lp = m->line ;
  292.                 }
  293.                 else
  294.                         *m->lp++ = c ;
  295.         }
  296. }
  297.  
  298. /* state upcall for net/rom */
  299.  
  300. void mbx_nr4state(struct nr4cb *cb, int old, int new)
  301. {
  302.         struct mbx *m ;
  303.  
  304.         old = old;
  305.  
  306.         m = (struct mbx *)cb->puser ;
  307.  
  308.         if (new == NR4STDISC && cb->puser != NULLCHAR) {
  309.                 cb->puser = NULLCHAR ;
  310.                 free_mbx(m) ;
  311.         }
  312. }
  313.  
  314. static void free_mbx(struct mbx *m)
  315. {
  316.         if (m->to != NULLCHAR)
  317.                 free(m->to) ;
  318.  
  319.         if (m->tofrom != NULLCHAR)
  320.                 free(m->tofrom) ;
  321.  
  322.         if (m->tomsgid != NULLCHAR)
  323.                 free(m->tomsgid) ;
  324.  
  325.         if (m->tfile != NULLFILE)
  326.                 fclose(m->tfile) ;
  327.  
  328.         mbox[m->mbnum] = NULLMBX ;
  329.  
  330.         free(m) ;
  331. }
  332.  
  333.  
  334. static int mbx_line(struct mbx *m)
  335. {
  336.         char *host ;
  337.         extern char hostname[] ;
  338.         extern int attended;
  339.         char fullfrom[80] ;
  340.  
  341.         if (m->state == MBX_CMD) {
  342.                 switch (tolower(m->line[0])) {
  343.                         case '*':       /* could be MBL/RLI *** Done */
  344.                                 if (!m->mblforw || strncmp(m->line,"*** Done",8))
  345.                                         {
  346.                                         mbx_msg(m,"Huh?\r") ;
  347.                                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  348.                                         break ;
  349.                                         }       /* drop thru if MBL and *** Done */
  350.                         case 'b':       /* bye - bye */
  351.                                 switch (m->type) {
  352.                                   case MBX_AX25:
  353.                                         m->cb.ax25_cb->user = NULLCHAR ;
  354.                                         disc_ax25(m->cb.ax25_cb) ;
  355.                                         break ;
  356.                                   case MBX_NETROM:
  357.                                         m->cb.nr4_cb->puser = NULLCHAR ;
  358.                                         disc_nr4(m->cb.nr4_cb) ;
  359.                                         break ;
  360.                                 }
  361.                                 free_mbx(m);
  362.                                 return -1 ;     /* tell line processor to quit */
  363.                                 break ;
  364.                         case 'c':       /* chat */
  365.                                 if(attended)
  366.                                         {
  367.                                         switch (m->type) {
  368.                                                 case MBX_AX25:
  369.                                                         m->cb.ax25_cb->user = NULLCHAR ;
  370.                                                         log_event(NULL,"AX25 Mailbox -> Chat requested : %s",m->name);
  371.                                                         ax_session(m->cb.ax25_cb,0) ;   /* make it a chat session */
  372.                                                         break ;
  373.                                                 case MBX_NETROM:
  374.                                                         m->cb.nr4_cb->puser = NULLCHAR ;
  375.                                                         log_event(NULL,"NET/ROM Mailbox -> Chat requested : %s",m->name);
  376.                                                         nr4_session(m->cb.nr4_cb) ;
  377.                                                         break ;
  378.                                                         }
  379.                                         free_mbx(m);
  380.                                         }
  381.                                 else
  382.                                         {
  383.                                         mbx_msg(m,"Sorry..the system is UNATTENDED at the moment.\r") ;
  384.                                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  385.                                         break ;
  386.                                         }
  387.                                 return -1 ;
  388.                                 break ;
  389.                         case 's': {
  390.                                 int badsubj = 0 ;
  391.  
  392.                                 /* Get S-command type (B,P,T, etc.) */
  393.  
  394.                                 if (m->line[1] == '\0')
  395.                                         m->stype = ' ' ;
  396.                                 else
  397.                                         m->stype = toupper(m->line[1]) ;
  398.  
  399.                                 if (mbx_to(m) == -1) {
  400.                                         if (m->mblforw)
  401.                                                 mbx_msg(m,"NO\r") ;
  402.                                         else {
  403.                                                 mbx_msg(m,
  404.                                                         "S command syntax error - format is:\r") ;
  405.                                                 mbx_msg(m,
  406.                                                   "  S name [@ host] [< from_addr] [$bulletin_id]\r") ;
  407.                                         }
  408.                                         badsubj++ ;
  409.                                 }
  410.                                 else if (validate_address(m->to) == 0)   {
  411.                                         if (m->mblforw)
  412.                                                 mbx_msg(m, "NO\r") ;
  413.                                         else
  414.                                                 mbx_msg(m, "Bad user or host name\r") ;
  415.                                         free(m->to) ;
  416.                                         m->to = NULLCHAR ;
  417.                                         if (m->tofrom) {
  418.                                                 free(m->tofrom) ;
  419.                                                 m->tofrom = NULLCHAR ;
  420.                                         }
  421.                                         if (m->tomsgid) {
  422.                                                 free(m->tomsgid) ;
  423.                                                 m->tomsgid = NULLCHAR ;
  424.                                         }
  425.                                         badsubj++ ;
  426.                                 }
  427.  
  428.                                 if (badsubj)
  429.                                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  430.                                 else {
  431.                                         m->state = MBX_SUBJ ;
  432.                                         mbx_msg(m,      m->mblforw ? "OK\r" : "Subject:\r") ;
  433.                                 }
  434.                                 break ;
  435.                         }
  436.                         case '[':
  437.                                 if (m->line[strlen(m->line)-1] == ']')
  438.                                         {
  439.                                         m->mblforw = 1 ;
  440.                                         mbx_msg(m,">\r") ;
  441.                                         }
  442.                                 else
  443.                                         {
  444.                                         mbx_msg(m,"Huh?\r") ;
  445.                                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  446.                                         }
  447.                                 break ;
  448.                         case 'f':
  449.                                 if (m->line[1] == '>' && m->mblforw)
  450.                                         {
  451.                                         mbx_msg(m,"*** Done\r>\r") ;
  452.                                         break ;
  453.                                         }
  454.                                 /* Otherwise drop through to "huh?" */
  455.                         default:
  456.                                 mbx_msg(m,"Huh?\r") ;
  457.                                 mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  458.                 }
  459.         return 0 ;
  460.         }
  461.         else if (m->state == MBX_SUBJ) {
  462.                 if (mbx_data(m) == -1) {
  463.                         mbx_msg(m,"Can't create temp file for mail\r") ;
  464.                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  465.                         free(m->to) ;
  466.                         m->to = NULLCHAR ;
  467.                         if (m->tofrom) {
  468.                                 free(m->tofrom) ;
  469.                                 m->tofrom = NULLCHAR ;
  470.                         }
  471.                         if (m->tomsgid) {
  472.                                 free(m->tomsgid) ;
  473.                                 m->tomsgid = NULLCHAR ;
  474.                         }
  475.                         m->state = MBX_CMD ;
  476.                         return 0 ;
  477.                 }
  478.                 m->state = MBX_DATA ;
  479.                 if (m->mblforw == 0)
  480.                         mbx_msg(m,
  481.                           "Enter message.  Terminate with /EX or ^Z in first column:\r") ;
  482.                 return 0 ;
  483.         }
  484.         else if (m->state == MBX_DATA) {
  485.                 if (m->line[0] == 0x1a ||
  486.                         strcmp(m->line, "/ex") == 0 ||
  487.                         strcmp(m->line, "/EX") == 0) {
  488.                         if ((host = strchr(m->to,'@')) == NULLCHAR)
  489.                                 host = hostname ;               /* use our hostname */
  490.                         else
  491.                                 host++ ;                                /* use the host part of address */
  492.  
  493.                         /* make up full from name for work file */
  494.                         sprintf(fullfrom,"%s@%s",m->name,hostname) ;
  495.  
  496.                         fseek(m->tfile,0L,0) ;          /* reset to beginning */
  497.                         if (queuejob((void *)0,m->tfile,host,m->to,fullfrom) != 0)
  498.                                 mbx_msg(m,"Couldn't queue message for delivery\r") ;
  499.  
  500.                         free(m->to) ;
  501.                         m->to = NULLCHAR ;
  502.                         if (m->tofrom) {
  503.                                 free(m->tofrom) ;
  504.                                 m->tofrom = NULLCHAR ;
  505.                         }
  506.                         if (m->tomsgid) {
  507.                                 free(m->tomsgid) ;
  508.                                 m->tomsgid = NULLCHAR ;
  509.                         }
  510.                         fclose(m->tfile) ;
  511.                         m->tfile = NULLFILE ;
  512.                         m->state = MBX_CMD ;
  513.                         smtptick();
  514.                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  515.                         return 0 ;
  516.                 }
  517.                 /* not done yet! */
  518.                 fprintf(m->tfile,"%s\r\n",m->line) ;
  519.                 return 0 ;
  520.         }
  521.  
  522.         return 0;  /* JSN Not sure */
  523. }
  524.  
  525. static int mbx_msg(struct mbx *m, char *msg)
  526. {
  527.         int len ;
  528.         struct mbuf *bp ;
  529.         struct ax25_cb *axp ;
  530.         struct nr4cb *cb ;
  531.  
  532.         len = strlen(msg) ;
  533.  
  534.         switch (m->type) {
  535.           case MBX_AX25:
  536.             axp = m->cb.ax25_cb ;
  537.  
  538.                 if ((bp = alloc_mbuf(len+1)) == NULLBUF) {
  539.                         disc_ax25(axp) ;
  540.                         return -1 ;
  541.                 }
  542.  
  543.                 bp->cnt = len + 1 ;
  544.  
  545.                 *bp->data = PID_NO_L3 ;
  546.  
  547.                 memcpy(bp->data+1, msg, len) ;
  548.  
  549.                 send_ax25(axp,bp) ;
  550.  
  551.                 break ;
  552.  
  553.           case MBX_NETROM:
  554.             cb = m->cb.nr4_cb ;
  555.  
  556.                 if ((bp = alloc_mbuf(len)) == NULLBUF) {
  557.                         disc_nr4(cb) ;
  558.                         return -1 ;
  559.                 }
  560.  
  561.                 bp->cnt = len ;
  562.  
  563.                 memcpy(bp->data, msg, len) ;
  564.  
  565.                 send_nr4(cb, bp) ;
  566.  
  567.                 break ;
  568.         }
  569.         return 0 ;
  570. }
  571.  
  572.  
  573. /* States for send line parser state machine */
  574.  
  575. #define         SKIP_CMD                1
  576. #define         LOOK_FOR_USER           2
  577. #define         IN_USER                 3
  578. #define         AFTER_USER              4
  579. #define         LOOK_FOR_HOST           5
  580. #define         IN_HOST                 6
  581. #define         AFTER_HOST              7
  582. #define         LOOK_FOR_FROM           8
  583. #define         IN_FROM                 9
  584. #define         AFTER_FROM              10
  585. #define         LOOK_FOR_MSGID          11
  586. #define         IN_MSGID                12
  587. #define         FINAL_STATE             13
  588. #define         ERROR_STATE             14
  589.  
  590. /* Prepare the addressee.  If the address is bad, return -1, otherwise
  591.  * return 0
  592.  */
  593. static int mbx_to(struct mbx *m)
  594. {
  595.         register char *cp;
  596.         int state ;
  597.         char *user, *host, *from, *msgid ;
  598.         int userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0 ;
  599.  
  600.         cp = m->line ;
  601.  
  602.         for (state = SKIP_CMD ; state < FINAL_STATE ; cp++) {
  603. #ifdef MBDEBUG
  604.                 cwprintf(NULL, "State is %d, char is %c\r\n", state, *cp) ;
  605. #endif
  606.                 switch (state) {
  607.                         case SKIP_CMD:
  608.                                 if (*cp == '\0')
  609.                                         state = ERROR_STATE ;           /* no user */
  610.                                 else if (isspace(*cp))
  611.                                         state = LOOK_FOR_USER ;
  612.                                 break ;
  613.                         case LOOK_FOR_USER:
  614.                                 if (*cp == '\0' || *cp == '@' || *cp == '<' || *cp == '$')
  615.                                         state = ERROR_STATE ;           /* no user */
  616.                                 else if (!isspace(*cp)) {               /* found start of user */
  617.                                         user = cp ;                                     /* point at start */
  618.                                         userlen++ ;                                     /* start counting */
  619.                                         state = IN_USER ;
  620.                                 }
  621.                                 break ;
  622.                         case IN_USER:
  623.                                 switch (*cp) {
  624.                                         case '\0':                                      /* found username only */
  625.                                                 state = FINAL_STATE ;
  626.                                                 break ;
  627.                                         case '@':
  628.                                                 state = LOOK_FOR_HOST ; /* hostname should follow */
  629.                                                 break ;
  630.                                         case '<':
  631.                                                 state = LOOK_FOR_FROM ; /* from name should follow */
  632.                                                 break ;
  633.                                         case '$':
  634.                                                 state = LOOK_FOR_MSGID ; /* message id should follow */
  635.                                                 break ;
  636.                                         default:
  637.                                                 if (isspace(*cp))
  638.                                                         state = AFTER_USER ;    /* white space */
  639.                                                 else
  640.                                                         userlen++ ;                             /* part of username */
  641.                                 }
  642.                                 break ;
  643.                         case AFTER_USER:
  644.                                 switch (*cp) {
  645.                                         case '\0':
  646.                                                 state = FINAL_STATE ;           /* found username only */
  647.                                                 break ;
  648.                                         case '@':
  649.                                                 state = LOOK_FOR_HOST ;         /* hostname follows */
  650.                                                 break ;
  651.                                         case '<':
  652.                                                 state = LOOK_FOR_FROM ;         /* fromname follows */
  653.                                                 break ;
  654.                                         case '$':
  655.                                                 state = LOOK_FOR_MSGID ;        /* message id follows */
  656.                                                 break ;
  657.                                         default:
  658.                                                 if (!isspace(*cp))
  659.                                                         state = ERROR_STATE ;
  660.                                 }
  661.                                 break ;
  662.                         case LOOK_FOR_HOST:
  663.                                 switch (*cp) {
  664.                                         case '\0':                                      /* user@? */
  665.                                         case '@':                                       /* user@@ */
  666.                                         case '<':                                       /* user@< */
  667.                                         case '$':                                       /* user@$ */
  668.                                                 state = ERROR_STATE ;
  669.                                                 break ;
  670.                                         default:
  671.                                                 if (!isspace(*cp)) {
  672.                                                         host = cp ;
  673.                                                         hostlen++ ;
  674.                                                         state = IN_HOST ;
  675.                                                 }
  676.                                 }
  677.                                 break ;
  678.                         case IN_HOST:
  679.                                 switch (*cp) {
  680.                                         case '\0':
  681.                                                 state = FINAL_STATE ;           /* found user@host */
  682.                                                 break ;
  683.                                         case '@':
  684.                                                 state = ERROR_STATE ;           /* user@host@? */
  685.                                                 break ;
  686.                                         case '<':
  687.                                                 state = LOOK_FOR_FROM ;         /* fromname follows */
  688.                                                 break ;
  689.                                         case '$':
  690.                                                 state = LOOK_FOR_MSGID ;        /* message id follows */
  691.                                                 break ;
  692.                                         default:
  693.                                                 if (isspace(*cp))
  694.                                                         state = AFTER_HOST ;
  695.                                                 else
  696.                                                         hostlen++ ;
  697.                                 }
  698.                                 break ;
  699.                         case AFTER_HOST:
  700.                                 switch (*cp) {
  701.                                         case '\0':
  702.                                                 state = FINAL_STATE ;           /* user@host */
  703.                                                 break ;
  704.                                         case '@':
  705.                                                 state = ERROR_STATE ;           /* user@host @ */
  706.                                                 break ;
  707.                                         case '<':
  708.                                                 state = LOOK_FOR_FROM ;         /* user@host < */
  709.                                                 break ;
  710.                                         case '$':
  711.                                                 state = LOOK_FOR_MSGID ;        /* user@host $ */
  712.                                                 break ;
  713.                                         default:
  714.                                                 if (!isspace(*cp))
  715.                                                         state = ERROR_STATE ;   /* user@host foo */
  716.                                 }
  717.                                 break ;
  718.                         case LOOK_FOR_FROM:
  719.                                 switch (*cp) {
  720.                                         case '\0':                                      /* user@host <? */
  721.                                         case '@':                                       /* user@host <@ */
  722.                                         case '<':                                       /* user@host << */
  723.                                         case '$':                                       /* user@host <$ */
  724.                                                 state = ERROR_STATE ;
  725.                                                 break ;
  726.                                         default:
  727.                                                 if (!isspace(*cp)) {
  728.                                                         from = cp ;
  729.                                                         fromlen++ ;
  730.                                                         state = IN_FROM ;
  731.                                                 }
  732.                                 }
  733.                                 break ;
  734.                         case IN_FROM:
  735.                                 switch (*cp) {
  736.                                         case '\0':
  737.                                                 state = FINAL_STATE ;           /* user@host <foo */
  738.                                                 break ;
  739.                                         case '<':
  740.                                                 state = ERROR_STATE ;           /* user@host <foo< */
  741.                                                 break ;
  742.                                         case '$':
  743.                                                 state = LOOK_FOR_MSGID ;        /* message id follows */
  744.                                                 break ;
  745.                                         default:
  746.                                                 if (isspace(*cp))
  747.                                                         state = AFTER_FROM ;
  748.                                                 else
  749.                                                         fromlen++ ;
  750.                                 }
  751.                                 break ;
  752.                         case AFTER_FROM:
  753.                                 switch (*cp) {
  754.                                         case '\0':
  755.                                                 state = FINAL_STATE ;           /* user@host <foo */
  756.                                                 break ;
  757.                                         case '@':                                               /* user@host <foo @ */
  758.                                         case '<':                                               /* user@host <foo < */
  759.                                                 state = ERROR_STATE ;
  760.                                                 break ;
  761.                                         case '$':
  762.                                                 state = LOOK_FOR_MSGID ;        /* user@host <foo $ */
  763.                                                 break ;
  764.                                         default:
  765.                                                 if (!isspace(*cp))
  766.                                                         state = ERROR_STATE ;   /* user@host foo */
  767.                                 }
  768.                                 break ;
  769.                         case LOOK_FOR_MSGID:
  770.                                 if (*cp == '\0')
  771.                                         state = ERROR_STATE ;                   /* msgid = $? */
  772.                                 else if (isspace(*cp))
  773.                                         state = ERROR_STATE ;                   /* user@host <foo $ bar */
  774.                                 else {
  775.                                         msgid = cp ;
  776.                                         msgidlen++ ;
  777.                                         state = IN_MSGID ;
  778.                                 }
  779.                                 break ;
  780.                         case IN_MSGID:
  781.                                 if (*cp == '\0')
  782.                                         state = FINAL_STATE ;
  783.                                 else if (isspace(*cp))
  784.                                         state = FINAL_STATE ;
  785.                                 else
  786.                                         msgidlen++ ;
  787.                                 break ;
  788.                         default:
  789.                                 /* what are we doing in this state? */
  790.                                 state = ERROR_STATE ;
  791.                 }
  792.         }
  793.  
  794.         if (state == ERROR_STATE)
  795.                 return -1 ;             /* syntax error */
  796.  
  797.         if ((m->to = malloc(userlen + hostlen + 2)) == NULLCHAR)
  798.                 return -1 ;             /* no room for to address */
  799.  
  800.         strncpy(m->to, user, userlen) ;
  801.         m->to[userlen] = '\0' ;
  802.  
  803.         if (hostlen) {
  804.                 m->to[userlen] = '@' ;
  805.                 strncpy(m->to + userlen + 1, host, hostlen) ;
  806.                 m->to[userlen + hostlen + 1] = '\0' ;
  807.         }
  808.  
  809.         if (fromlen) {
  810.                 if ((m->tofrom = malloc(fromlen + 1)) == NULLCHAR) {
  811.                         free(m->to) ;
  812.                         m->to = NULLCHAR ;
  813.                         return -1 ;
  814.                 }
  815.                 strncpy(m->tofrom, from, fromlen) ;
  816.                 m->tofrom[fromlen] = '\0' ;
  817.         }
  818.  
  819.         if (msgidlen) {
  820.                 if ((m->tomsgid = malloc(msgidlen + 1)) == NULLCHAR) {
  821.                         free(m->to) ;
  822.                         m->to = NULLCHAR ;
  823.                         if (fromlen) {
  824.                                 free(m->tofrom) ;
  825.                                 m->tofrom = NULLCHAR ;
  826.                         }
  827.                         return -1 ;
  828.                 }
  829.                 strncpy(m->tomsgid, msgid, msgidlen) ;
  830.                 m->tomsgid[msgidlen] = '\0' ;
  831.         }
  832.  
  833.         return 0 ;
  834. }
  835.  
  836. /* This opens the data file and writes the mail header into it.
  837.  * Returns 0 if OK, and -1 if not.
  838.  */
  839.  
  840. static int mbx_data(struct mbx *m)
  841. {
  842.         time_t t;
  843.         extern char hostname[] ;
  844.  
  845.         if ((m->tfile = tmpfile()) == NULLFILE)
  846.                 return -1 ;
  847.  
  848.         time(&t) ;
  849.         fprintf(m->tfile,"Date: %s",ptime(&t)) ;
  850.  
  851.         if (m->tomsgid)
  852.                 fprintf(m->tfile, "Message-Id: <%s@%s>\n", m->tomsgid, hostname) ;
  853.         else
  854.                 fprintf(m->tfile,"Message-Id: <%ld@%s>\n",get_msgid(),hostname) ;
  855.  
  856.         fprintf(m->tfile,"From: %s%%%s.BBS@%s\n",m->tofrom ? m->tofrom : m->name, m->name, hostname) ;
  857.  
  858.         fprintf(m->tfile,"Reply-To: %s@%s\n",m->tofrom ? m->tofrom : m->name, m->name) ;
  859.  
  860.         fprintf(m->tfile,"To: %s\n",m->to) ;
  861.  
  862.         fprintf(m->tfile,"Subject: %s\n\n",m->line) ;
  863.  
  864.         if (m->stype != ' ')
  865.                 fprintf(m->tfile,"X-BBS-Msg-Type: %c\n", m->stype) ;
  866.  
  867.         fprintf(m->tfile,"\n") ;
  868.  
  869.         return 0 ;
  870. }
  871.