home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / PPPBCKP / SRC / SRC15B81.ZIP / POP.CPP < prev    next >
Text File  |  1998-01-02  |  50KB  |  1,643 lines

  1. #include <stdio.h>
  2. #include <stdarg.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <dos.h>
  6. #include <fcntl.h>
  7. #include <sys/stat.h>
  8. #include <ctype.h>
  9. #include <mem.h>
  10. #include <conio.h>
  11. #include <io.h>
  12. #include <share.h>
  13. #include <errno.h>
  14. #include <malloc.h>
  15. #include <dir.h>
  16. extern "C" {
  17. #include "tcp.h"
  18. }
  19. #include "version.h"
  20. #include "retcode.h"
  21.  
  22. #define POP_PORT 110
  23.  
  24. #define SMTP_PORT 25
  25.  
  26. #define SMTP_STATUS   211
  27. #define SMTP_HELP     214
  28. #define SMTP_READY    220
  29. #define SMTP_BYE      221
  30. #define SMTP_OK       250
  31. #define SMTP_WILL_FWD 251
  32.  
  33. #define SMTP_GIMME    354
  34.  
  35. #define SMTP_OOPS     421
  36. #define SMTP_BUSY     450
  37. #define SMTP_ERROR    451
  38. #define SMTP_SQUEEZED 452
  39.  
  40. #define SMTP_SYNTAX   500
  41. #define SMTP_PARAM    501
  42. #define SMTP_COM_NI   502
  43. #define SMTP_BAD_SEQ  503
  44. #define SMTP_BAD_PARM 504
  45. #define SMTP_ACCESS   550
  46. #define SMTP_YOU_FWD  551
  47. #define SMTP_FULL     552
  48. #define SMTP_BAD_NAM  553
  49. #define SMTP_FAILED   554
  50.  
  51.  
  52. #define POP_OK               200
  53. #define POP_NOT_MSG          400
  54. #define POP_BAD_HOST         500
  55. #define POP_HOST_UNAVAILABLE 501
  56. #define POP_BAD_MBOX         510
  57. #define POP_BAD_PASS         511
  58. #define POP_UNKNOWN          599
  59.  
  60.  
  61. #define POPLIB_OK        200
  62. #define POPLIB_BAD_FILE  401
  63. #define POPLIB_BAD_HOST  510
  64. #define POPLIB_S_TIMEOU  510
  65. #define POPLIB_S_CLOSED  511
  66. #define POPLIB_SMTP_ERR  520
  67. #define POPLIB_POP_ERR   521
  68. #define POPLIB_SMTP_PROB 410
  69. #define POPLIB_POP_PROB  411
  70.  
  71. typedef struct {
  72.   tcp_Socket *sock;
  73. } Mail_Socket;
  74.  
  75. typedef struct {
  76.   char msgid[81];
  77. } Message_ID;
  78.  
  79. typedef struct {
  80.   char popname[20];
  81.   char pophost[40];
  82.   char poppass[20];
  83. } ACCT;
  84.  
  85. ACCT *acct;
  86.  
  87. #define _TEMP_BUFFER_LEN 2048
  88. #define LAST(s) s[strlen(s)-1]
  89.  
  90. #define SHARE_LEVEL 10
  91. #define WAIT_TIME 10
  92. #define TRIES 100
  93.  
  94. #define MT_DESQVIEW 0x01
  95. #define MT_WINDOWS  0x02
  96. #define MT_OS2      0x04
  97. #define MT_NB       0x40
  98.  
  99.  
  100. #define free_Mail_Socket(SOCK) if (SOCK != NULL) {                              \
  101.   farfree(SOCK->sock); farfree(SOCK); SOCK=NULL; }
  102.  
  103. int POP_Err_Cond, SMTP_Err_Cond;
  104. char from_user[81], net_data[MAXPATH], fdlfn[21], id[81];
  105. char POPHOST[60], POPNAME[20], POPPASS[20], DOMAIN[60];
  106. int WatTCP_initialized = 0, fdl;
  107. static unsigned char _temp_buffer[_TEMP_BUFFER_LEN];
  108. static int POP_stat, SMTP_stat;
  109. int multitasker = 0, DEBUG = 1, ALLMAIL, compact_ids = 0;
  110.  
  111. char *version = "Freeware PPP Project POP/SMTP Client " VERSION;
  112.  
  113. char pktowner[26];
  114.  
  115. #define SOCK_READ_ERR(PROTOCOL, ACTION)                                         \
  116.   sock_err:                                                                     \
  117.     switch (PROTOCOL##_stat) {                                                  \
  118.       case 1 :                                                                  \
  119.         PROTOCOL##_Err_Cond = PROTOCOL##_OK;                                    \
  120.         fprintf(stderr, "\n ! "#PROTOCOL"> Session error : %s",                        \
  121.             sockerr(PROTOCOL##_sock->sock));                                    \
  122.         ACTION;                                                                 \
  123.         return 0;                                                               \
  124.       case -1:                                                                  \
  125.         PROTOCOL##_Err_Cond = PROTOCOL##_OK;                                    \
  126.         fprintf(stderr, "\n ! "#PROTOCOL"> Timeout : %s",                              \
  127.                 sockerr(PROTOCOL##_sock->sock));                                \
  128.         ACTION;                                                                 \
  129.         return 0;                                                               \
  130.     }
  131.  
  132. #define SOCK_GETS(PROTOCOL)                                                     \
  133.   sock_wait_input(PROTOCOL##_sock->sock, sock_delay, NULL, &PROTOCOL##_stat);   \
  134.   sock_gets(PROTOCOL##_sock->sock, _temp_buffer, sizeof(_temp_buffer));         \
  135.   if (DEBUG) fprintf(stderr, "\n"#PROTOCOL"> %s\n", _temp_buffer);                  \
  136.   PROTOCOL##_Err_Cond = atoi(_temp_buffer);                                     \
  137.  
  138. #define SMTP_FAIL_ON(NUM, ACTION)                                               \
  139.   if (SMTP_Err_Cond == NUM) {                                                   \
  140.     if (DEBUG) fprintf(stderr, "\nSMTP Failure> '" #NUM "'\n");                   \
  141.     sock_puts(SMTP_sock->sock, "QUIT");                                         \
  142.     ACTION;                                                                     \
  143.     return 0;                                                                   \
  144.   }
  145.  
  146. #define SMTP_RESET_ON(NUM, ACTION)                                              \
  147.   if (SMTP_Err_Cond == NUM) {                                                   \
  148.     if (DEBUG) fprintf(stderr, "\nSMTP Failure> '" #NUM "'\n");                   \
  149.     sock_puts(SMTP_sock->sock, "RSET");                                         \
  150.     sock_wait_input(SMTP_sock->sock, sock_delay, NULL, &SMTP_stat);             \
  151.     sock_gets(SMTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));             \
  152.     ACTION;                                                                     \
  153.     return(0);                                                                  \
  154.   }
  155.  
  156.  
  157. void output(char *fmt,...)
  158. {
  159.   va_list v;
  160.   char s[255];
  161.  
  162.   va_start(v, fmt);
  163.   vsprintf(s, fmt, v);
  164.   va_end(v);
  165.   fputs(s, stderr);
  166. }
  167.  
  168. void dv_pause(void)
  169. {
  170.   __emit__(0xb8, 0x1a, 0x10, 0xcd, 0x15);
  171.   __emit__(0xb8, 0x00, 0x10, 0xcd, 0x15);
  172.   __emit__(0xb8, 0x25, 0x10, 0xcd, 0x15);
  173. }
  174.  
  175. void win_pause(void)
  176. {
  177.   __emit__(0x55, 0xb8, 0x80, 0x16, 0xcd, 0x2f, 0x5d);
  178. }
  179.  
  180. int get_dos_version(void)
  181. {
  182.   _AX = 0x3000;
  183.   geninterrupt(0x21);
  184.   if (_AX % 256 >= 10) {
  185.     multitasker |= MT_OS2;
  186.   }
  187.   return (_AX);
  188. }
  189.  
  190. int get_dv_version(void)
  191. {
  192.   int v;
  193.  
  194.   if (multitasker & MT_OS2)
  195.     return 0;
  196.   _AX = 0x2b01;
  197.   _CX = 0x4445;
  198.   _DX = 0x5351;
  199.   geninterrupt(0x21);
  200.   if (_AL == 0xff) {
  201.     return 0;
  202.   } else {
  203.     v = _BX;
  204.     multitasker |= MT_DESQVIEW;
  205.     return v;
  206.   }
  207. }
  208.  
  209. int get_win_version(void)
  210. {
  211.   int v = 0;
  212.  
  213.   __emit__(0x55, 0x06, 0x53);
  214.   _AX = 0x352f;
  215.   geninterrupt(0x21);
  216.   _AX = _ES;
  217.   if (_AX | _BX) {
  218.     _AX = 0x1600;
  219.     geninterrupt(0x2f);
  220.     v = _AX;
  221.     if (v % 256 <= 1)
  222.       v = 0;
  223.   }
  224.   __emit__(0x5b, 0x07, 0x5d);
  225.   if (v != 0)
  226.     multitasker |= MT_WINDOWS;
  227.   return (v);
  228. }
  229.  
  230. int get_nb_version(void)
  231. {
  232.   _AX = 0;
  233.   geninterrupt(0x2A);
  234.   return (_AH);
  235. }
  236.  
  237. void detect_multitask(void)
  238. {
  239.   get_dos_version();
  240.   get_win_version();
  241.   get_dv_version();
  242.   if (multitasker < 2)
  243.     if (get_nb_version())
  244.       multitasker = MT_NB;
  245. }
  246.  
  247. unsigned char *trim(unsigned char *str)
  248. {
  249.   int i;
  250.  
  251.   if (str == NULL)
  252.     return (str);
  253.   for (i = strlen(str) - 1; (i >= 0) && isspace(str[i]); str[i--] = '\0');
  254.   while (isspace(str[0]))
  255.     strcpy(str, str + 1);
  256.   return (str);
  257. }
  258.  
  259. char *fix_quoted_commas(char *string)
  260. {
  261.   char *ptr;
  262.   int quoted = 0;
  263.  
  264.   ptr = string;
  265.   if (ptr) {
  266.     while (*ptr != 0) {
  267.       if (*ptr == '\"')
  268.         quoted = (!quoted);
  269.       if (*ptr == ',' && quoted)
  270.         *ptr = '│';
  271.       ptr = &ptr[1];
  272.     }
  273.   }
  274.   return (string);
  275. }
  276.  
  277. void giveup_timeslice(void)
  278. {
  279.   if (multitasker) {
  280.     switch (multitasker) {
  281.  case 1: 
  282.  case 3: 
  283.         dv_pause();
  284.         break;
  285.       case 2:
  286.       case 4:
  287.       case 5:
  288.       case 6:
  289.       case 7:
  290.         win_pause();
  291.         break;
  292.       default:
  293.         break;
  294.     }
  295.   }
  296. }
  297.  
  298.  
  299. int sh_write(int handle, void *buffer, unsigned long len)
  300. {
  301.   if (handle == -1) {
  302.     return (-1);
  303.   }
  304.   return (write(handle, buffer, (unsigned) len));
  305. }
  306.  
  307. int sh_open(char *path, int file_access, unsigned fmode)
  308. {
  309.   int handle, count, share;
  310.   char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  311.  
  312.   if ((file_access & O_RDWR) || (file_access & O_WRONLY) || (fmode & S_IWRITE)) {
  313.     share = SH_DENYRW;
  314.   } else {
  315.     share = SH_DENYWR;
  316.   }
  317.   handle = open(path, file_access | share, fmode);
  318.   if (handle < 0) {
  319.     count = 1;
  320.     fnsplit(path, drive, dir, file, ext);
  321.     if (access(path, 0) != -1) {
  322.       delay(WAIT_TIME);
  323.       handle = open(path, file_access | share, fmode);
  324.       while (((handle < 0) && (errno == EACCES)) && (count < TRIES)) {
  325.         if (count % 2)
  326.           delay(WAIT_TIME);
  327.         else
  328.           giveup_timeslice();
  329.         count++;
  330.         handle = open(path, file_access | share, fmode);
  331.       }
  332.     }
  333.   }
  334.   return (handle);
  335. }
  336.  
  337. int sh_close(int f)
  338. {
  339.   if (f != -1)
  340.     close(f);
  341.   return (-1);
  342. }
  343.  
  344. int sh_read(int handle, void *buf, unsigned len)
  345. {
  346.   if (handle == -1) {
  347.     return (-1);
  348.   }
  349.   return (read(handle, buf, len));
  350. }
  351.  
  352. long sh_lseek(int handle, long offset, int fromwhere)
  353. {
  354.   if (handle == -1) {
  355.     return (-1L);
  356.   }
  357.   return (lseek(handle, offset, fromwhere));
  358. }
  359.  
  360. FILE *fsh_open(char *path, char *fmode)
  361. {
  362.   FILE *f;
  363.   int count, share, md, fd;
  364.   char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  365.  
  366.   share = SH_DENYWR;
  367.   md = 0;
  368.   if (((char *) _fstrchr(fmode, 'w')) != NULL) {
  369.     share = SH_DENYRD;
  370.     md = O_RDWR | O_CREAT | O_TRUNC;
  371.   } else
  372.     if (((char *) _fstrchr(fmode, 'a')) != NULL) {
  373.     share = SH_DENYRD;
  374.     md = O_RDWR | O_CREAT;
  375.   } else {
  376.     md = O_RDONLY;
  377.   }
  378.   if (((char *) _fstrchr(fmode, 'b')) != NULL) {
  379.     md |= O_BINARY;
  380.   }
  381.   if (((char *) _fstrchr(fmode, '+')) != NULL) {
  382.     md &= ~O_RDONLY;
  383.     md |= O_RDWR;
  384.     share = SH_DENYRD;
  385.   }
  386.   fd = open(path, md | share, S_IREAD | S_IWRITE);
  387.   if (fd < 0) {
  388.     count = 1;
  389.     fnsplit(path, drive, dir, file, ext);
  390.     if ((access(path, 0)) != -1) {
  391.       delay(WAIT_TIME);
  392.       fd = open(path, md | share, S_IREAD | S_IWRITE);
  393.       while (((fd < 0) && (errno == EACCES)) && (count < TRIES)) {
  394.         delay(WAIT_TIME);
  395.         count++;
  396.         fd = open(path, md | share, S_IREAD | S_IWRITE);
  397.       }
  398.     }
  399.   }
  400.   if (fd > 0) {
  401.     if (((char *) _fstrchr(fmode, 'a')) != NULL)
  402.       sh_lseek(fd, 0L, SEEK_END);
  403.     f = fdopen(fd, fmode);
  404.     if (!f) {
  405.       close(fd);
  406.     }
  407.   } else
  408.     f = 0;
  409.   return (f);
  410. }
  411.  
  412. int log_it(int display, char *fmt,...)
  413. {
  414.   va_list v;
  415.   char s[255], fn[161];
  416.   FILE *fp;
  417.  
  418.   sprintf(fn, "%sNEWS.LOG", net_data);
  419.   if ((fp = fsh_open(fn, "at")) == NULL)
  420.     return 1;
  421.   va_start(v, fmt);
  422.   vsprintf(s, fmt, v);
  423.   va_end(v);
  424.   fputs(s, fp);
  425.   fclose(fp);
  426.   if (display)
  427.     fputs(s, stderr);
  428.   return 0;
  429. }
  430.  
  431. Mail_Socket *smtp_start(char *host, char *dom)
  432. {
  433.   longword h;
  434.   Mail_Socket *SMTP_sock = NULL;
  435.  
  436.   if (!WatTCP_initialized) {
  437.     sock_init();
  438.     WatTCP_initialized = 1;
  439.   }
  440.   if (!(h = resolve(host))) {
  441.     if (!(h = resolve(host))) {
  442.       SMTP_Err_Cond = SMTP_FAILED;
  443.       log_it(1, "\n ■ Error : Cannot resolve host %s", host);
  444.       return NULL;
  445.     }
  446.   }
  447.   if ((SMTP_sock = (Mail_Socket *) farmalloc(sizeof(Mail_Socket))) == NULL) {
  448.     log_it(1, "\n ■ Insufficient memory to create socket... aborting");
  449.     exit(EXIT_FAILURE);
  450.   }
  451.   if ((SMTP_sock->sock = (tcp_Socket *) farmalloc(sizeof(tcp_Socket))) == NULL) {
  452.     log_it(1, "\n ■ Insufficient memory to create socket... aborting");
  453.     farfree(SMTP_sock);
  454.     exit(EXIT_FAILURE);
  455.   }
  456.   if (!tcp_open(SMTP_sock->sock, 0, h, SMTP_PORT, NULL)) {
  457.     SMTP_Err_Cond = SMTP_FAILED;
  458.     log_it(1, "\n ■ Error : Unable to connect to %s", host);
  459.     farfree(SMTP_sock);
  460.     return NULL;
  461.   }
  462.   sock_sturdy(SMTP_sock->sock, 100);
  463.   sock_mode(SMTP_sock->sock, TCP_MODE_ASCII);
  464.   sock_wait_established(SMTP_sock->sock, sock_delay, NULL, &SMTP_stat);
  465.  
  466.   sock_wait_input(SMTP_sock->sock, sock_delay, NULL, &SMTP_stat);
  467.   sock_gets(SMTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  468.   log_it(DEBUG, "\n - SMTP> %s", _temp_buffer);
  469.  
  470.   sprintf(_temp_buffer, "HELO %s", dom);
  471.   sock_puts(SMTP_sock->sock, _temp_buffer);
  472.   sock_wait_input(SMTP_sock->sock, sock_delay, NULL, &SMTP_stat);
  473.   while (sock_tbused(SMTP_sock->sock) > 0) {
  474.     SOCK_GETS(SMTP);
  475.     SMTP_FAIL_ON(SMTP_OOPS,);
  476.     SMTP_FAIL_ON(SMTP_SYNTAX,);
  477.     SMTP_FAIL_ON(SMTP_PARAM,);
  478.     SMTP_FAIL_ON(SMTP_BAD_PARM,);
  479.   }
  480.   SOCK_READ_ERR(SMTP,);
  481.   return (SMTP_sock);
  482. }
  483.  
  484. char *smtp_parse_from_line(FILE * f)
  485. {
  486.   char s[161];
  487.   int found = 0, done = 0, beginfocus, endfocus;
  488.  
  489.   rewind(f);
  490.   while (!feof(f) && !done) {
  491.     fgets(s, 160, f);
  492.     if (*s == '\n')
  493.       done = 1;
  494.     else
  495.       if ((strncmpi(s, "from:", 5) == 0 &&
  496.            _fstrchr(s, '@') != 0)) {
  497.       found = 1;
  498.       done = 1;
  499.       }
  500.   }
  501.   if (found) {
  502.     if ((beginfocus = _fstrcspn(s, "<")) != strlen(s)) {
  503.       ++beginfocus;
  504.       endfocus = _fstrcspn(s, ">");
  505.       s[endfocus] = NULL;
  506.     } else
  507.       beginfocus = 5;
  508.     return (trim(_fstrdup(&s[beginfocus])));
  509.   }
  510.   return 0;
  511. }
  512.  
  513. unsigned char *trimstr1(unsigned char *s)
  514. {
  515.   int i;
  516.   static char *whitespace = " \r\n\t";
  517.  
  518.   i = strlen(s);
  519.   if (i) {
  520.     while ((i > 0) && (_fstrchr(whitespace, s[i - 1])))
  521.       --i;
  522.     while ((i > 0) && (_fstrchr(whitespace, *s))) {
  523.       memmove(s, s + 1, --i);
  524.     }
  525.     s[i] = 0;
  526.   }
  527.   return (s);
  528. }
  529.  
  530. char **smtp_parse_to_line(FILE * f)
  531. {
  532.   int i, i1, done = 0, current = 0;
  533.   char **list = NULL;
  534.   char *addr, _temp_addr[120], buf[120];
  535.  
  536.   rewind(f);
  537.   while (!feof(f) && !done) {
  538.     fgets(_temp_buffer, sizeof(_temp_buffer), f);
  539.     if (*_temp_buffer == '\n')
  540.       done = 1;
  541.     else
  542.       if ((strncmpi(_temp_buffer, "to:", 3) == 0) ||
  543.           (strncmpi(_temp_buffer, "cc:", 3) == 0) ||
  544.           (strncmpi(_temp_buffer, "bcc:", 4) == 0)) {
  545.       fix_quoted_commas(_temp_buffer);
  546.       addr = strtok(_temp_buffer, ":");
  547.       addr = strtok(NULL, "\r\n");
  548.       trimstr1(addr);
  549.       strcpy(_temp_addr, addr);
  550.       if ((_fstrchr(_temp_addr, ' ')) || (_fstrchr(_temp_addr, ')')) || (_fstrchr(_temp_addr, '\"'))) {
  551.         *buf = i1 = 0;
  552.         i = _fstrcspn(_temp_addr, "@");
  553.         while ((i > 0) && (_temp_addr[i - 1] != ' ') && (_temp_addr[i - 1] != '<'))
  554.           --i;
  555.         while (*_temp_addr && (_temp_addr[i] != ' ') && (_temp_addr[i] != '>'))
  556.           buf[i1++] = _temp_addr[i++];
  557.         buf[i1] = 0;
  558.         addr = buf;
  559.       }
  560.       list = (char **) farrealloc(list, sizeof(char *) * ((current) + 2));
  561.       list[current] = strdup(addr);
  562.       list[current + 1] = NULL;
  563.       current++;
  564.       }
  565.   }
  566.   return (list);
  567. }
  568.  
  569. int smtp_send_MAIL_FROM_line(Mail_Socket * SMTP_sock, FILE * f)
  570. {
  571.   char *from;
  572.  
  573.   from = smtp_parse_from_line(f);
  574.   if (from) {
  575.     if (DEBUG)
  576.       output("\n - SMTP> Mail From:<%s>", from);
  577.     sprintf(_temp_buffer, "MAIL FROM:<%s>", from);
  578.     sock_puts(SMTP_sock->sock, _temp_buffer);
  579.     free(from);
  580.     while (sock_tbused(SMTP_sock->sock) > 0) {
  581.       SOCK_GETS(SMTP);
  582.       SMTP_FAIL_ON(SMTP_OOPS,);
  583.     }
  584.   }
  585.   SOCK_READ_ERR(SMTP,);
  586.   return 1;
  587. }
  588.  
  589. #define FREE_ALL for (i=0; to_list[i]!=NULL; i++) if (to_list[i]) free(to_list[i]); if (to_list) free(to_list);
  590.  
  591. int smtp_send_RCPT_TO_line(Mail_Socket * SMTP_sock, FILE * f)
  592. {
  593.   char **to_list;
  594.   int i, done = 0;
  595.  
  596.   to_list = smtp_parse_to_line(f);
  597.   for (i = 0; ((to_list[i] != NULL) && (!done)); i++) {
  598.     if ((_fstrchr(to_list[i], '@') == NULL) || (_fstrchr(to_list[i], '.') == NULL)) {
  599.       log_it(1, "\n ! Invalid recipient - %s - aborting message.", to_list[i]);
  600.       sock_puts(SMTP_sock->sock, "RSET");
  601.       done = 1;
  602.     } else {
  603.       log_it(DEBUG, "\n - SMTP> Rcpt To:<%s>", to_list[i]);
  604.       sprintf(_temp_buffer, "RCPT TO:<%s>", to_list[i]);
  605.       sock_puts(SMTP_sock->sock, _temp_buffer);
  606.     }
  607.     while (sock_tbused(SMTP_sock->sock) > 0) {
  608.       SOCK_GETS(SMTP);
  609.       SMTP_FAIL_ON(SMTP_OOPS, FREE_ALL);
  610.       SMTP_RESET_ON(SMTP_SYNTAX, FREE_ALL);
  611.       SMTP_RESET_ON(SMTP_PARAM, FREE_ALL);
  612.       SMTP_RESET_ON(SMTP_BAD_SEQ, FREE_ALL);
  613.     }
  614.   }
  615.  
  616.   SOCK_READ_ERR(SMTP, FREE_ALL);
  617.  
  618.   FREE_ALL;
  619.  
  620.   return 1;
  621. }
  622.  
  623. #undef FREE_ALL
  624.  
  625. void go_back(int from, int to)
  626. {
  627.   int i;
  628.  
  629.   for (i = from; i > to; i--)
  630.     output("\b \b");
  631. }
  632.  
  633.  
  634. int smtp_sendf(Mail_Socket * SMTP_sock, char *msg, char *hostname, int *stop)
  635. {
  636.   int abort, pos;
  637.   long nbytes, obytes, rbytes;
  638.   char fname[10], ext[5];
  639.   FILE *fp;
  640.  
  641.   abort = 0;
  642.   if ((fp = fsh_open(msg, "r")) != NULL) {
  643.     SMTP_Err_Cond = SMTP_OK;
  644.     if (DEBUG)
  645.       output("\n");
  646.     fnsplit(msg, NULL, NULL, fname, ext);
  647.     output("\r ■ SND : %-8s%-4s : %-18.18s : [Space] aborts", fname, ext, hostname);
  648.     if (!smtp_send_MAIL_FROM_line(SMTP_sock, fp))
  649.       abort = 1;
  650.     if (!smtp_send_RCPT_TO_line(SMTP_sock, fp))
  651.       abort = 1;
  652.     if (!abort) {
  653.       fseek(fp, 0L, SEEK_END);
  654.       obytes = ftell(fp);
  655.       rewind(fp);
  656.       sock_puts(SMTP_sock->sock, "DATA");
  657.       sock_wait_input(SMTP_sock->sock, sock_delay, NULL, &SMTP_stat);
  658.       while (sock_tbused(SMTP_sock->sock) > 0) {
  659.         SOCK_GETS(SMTP);
  660.         if (DEBUG)
  661.           log_it(DEBUG, "\n - SMTP> %s", _temp_buffer);
  662.         SMTP_FAIL_ON(SMTP_OOPS,);
  663.         SMTP_RESET_ON(SMTP_BAD_SEQ,);
  664.         SMTP_RESET_ON(SMTP_SYNTAX,);
  665.         SMTP_RESET_ON(SMTP_PARAM,);
  666.         SMTP_RESET_ON(SMTP_COM_NI,);
  667.         SMTP_RESET_ON(SMTP_FAILED,);
  668.         SMTP_RESET_ON(SMTP_ERROR,);
  669.       }
  670.       nbytes = 0L;
  671.       rbytes = 1024L;
  672.       output(" : ");
  673.       pos = wherex();
  674.       tcp_set_debug_state(1);
  675.       while (feof(fp) == 0) {
  676.         sock_tick(SMTP_sock->sock, &SMTP_stat);
  677.         fgets(_temp_buffer, sizeof(_temp_buffer), fp);
  678.         rip(_temp_buffer);
  679.         if (*_temp_buffer == '.') {
  680.           movmem(_temp_buffer, _temp_buffer + 1, sizeof(_temp_buffer) - 1);
  681.           *_temp_buffer = '.';
  682.         }
  683.         nbytes += sock_puts(SMTP_sock->sock, _temp_buffer) + 2;
  684.         if (nbytes > rbytes) {
  685.           go_back(wherex(), pos);
  686.           output("%ld/%ld", nbytes, obytes);
  687.           rbytes += 256L;
  688.         }
  689.         if (kbhit()) {
  690.           if (fp != NULL)
  691.             fclose(fp);
  692.           go_back(wherex(), pos);
  693.           output(" aborted.");
  694.           *stop = 1;
  695.           return 0;
  696.         }
  697.       }
  698.       if (fp != NULL)
  699.         fclose(fp);
  700.       if (!abort) {
  701.         sock_puts(SMTP_sock->sock, ".");
  702.         sock_wait_input(SMTP_sock->sock, sock_delay, NULL, &SMTP_stat);
  703.         while (sock_tbused(SMTP_sock->sock) > 0) {
  704.           SOCK_GETS(SMTP);
  705.           if (*_temp_buffer == '2')
  706.             log_it(DEBUG, "\n - SMTP> %s", _temp_buffer);
  707.           else {
  708.             if (DEBUG)
  709.               output("\n - SMTP> %s", _temp_buffer);
  710.           }
  711.           SMTP_FAIL_ON(SMTP_OOPS,);
  712.           SMTP_RESET_ON(SMTP_ERROR,);
  713.           SMTP_RESET_ON(SMTP_SQUEEZED,);
  714.           SMTP_RESET_ON(SMTP_FULL,);
  715.           SMTP_RESET_ON(SMTP_FAILED,);
  716.         }
  717.         go_back(wherex(), pos);
  718.         output("accepted.");
  719.         return 1;
  720.       }
  721.     } else {
  722.       if (fp != NULL)
  723.         fclose(fp);
  724.       return 0;
  725.     }
  726.   } else {
  727.     log_it(1, "\n ! Error accessing %s.", msg);
  728.     return 0;
  729.   }
  730.   SOCK_READ_ERR(SMTP, fcloseall());
  731.   return 1;
  732. }
  733.  
  734.  
  735. int smtp_shutdown(Mail_Socket * SMTP_sock)
  736. {
  737.   if (SMTP_sock->sock) {
  738.     sock_puts(SMTP_sock->sock, "QUIT");
  739.     sock_wait_input(SMTP_sock->sock, sock_delay, NULL, &SMTP_stat);
  740.     sock_gets(SMTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  741.     sock_close(SMTP_sock->sock);
  742.  
  743.   }
  744.   SOCK_READ_ERR(SMTP, free_Mail_Socket(SMTP_sock));
  745.   return 0;
  746. }
  747.  
  748.  
  749. Mail_Socket *pop_init(char *host)
  750. {
  751.   longword h;
  752.   Mail_Socket *POP_sock = NULL;
  753.  
  754.   if (!WatTCP_initialized) {
  755.     sock_init();
  756.     WatTCP_initialized = 1;
  757.   }
  758.   if (!(h = resolve(host))) {
  759.     if (!(h = resolve(host))) {
  760.       POP_Err_Cond = POP_BAD_HOST;
  761.       log_it(1, "\n ■ Error : Cannot resolve host %s", host);
  762.       return NULL;
  763.     }
  764.   }
  765.   if ((POP_sock = (Mail_Socket *) farmalloc(sizeof(Mail_Socket))) == NULL) {
  766.     log_it(1, "\n ■ Insufficient memory to create socket... aborting.");
  767.     exit(EXIT_FAILURE);
  768.   }
  769.   if ((POP_sock->sock = (tcp_Socket *) farmalloc(sizeof(tcp_Socket))) == NULL) {
  770.     log_it(1, "\n ■ Insufficient memory to create socket... aborting.");
  771.     farfree(POP_sock);
  772.     exit(EXIT_FAILURE);
  773.   }
  774.   if (!tcp_open(POP_sock->sock, 0, h, POP_PORT, NULL)) {
  775.     POP_Err_Cond = POP_BAD_HOST;
  776.     log_it(1, "\n ■ Error : Unable to connect to host %s", host);
  777.     return NULL;
  778.   }
  779.   sock_mode(POP_sock->sock, TCP_MODE_ASCII);
  780.   sock_wait_established(POP_sock->sock, sock_delay, NULL, &POP_stat);
  781.   sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  782.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  783.   log_it(DEBUG, "\n - POP> %s", _temp_buffer);
  784.   if (*_temp_buffer != '+') {
  785.     POP_Err_Cond = POP_HOST_UNAVAILABLE;
  786.     log_it(1, "\n ■ Error : Host %s is unavailable.", host);
  787.     return NULL;
  788.   } else {
  789.     POP_Err_Cond = POP_OK;
  790.     log_it(DEBUG, "\n - POP socket initialized.");
  791.     return (POP_sock);
  792.   }
  793.   SOCK_READ_ERR(POP,);
  794.   return (POP_sock);
  795. }
  796.  
  797. int pop_login(Mail_Socket * POP_sock, char *userid, char *password)
  798. {
  799.   sprintf(_temp_buffer, "USER %s", userid);
  800.   sock_puts(POP_sock->sock, _temp_buffer);
  801.   sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  802.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  803.   log_it(DEBUG, "\n - POP> %s", _temp_buffer);
  804.   if (*_temp_buffer != '+') {
  805.     POP_Err_Cond = POP_BAD_MBOX;
  806.     log_it(1, "\n ■ Error : host report mailbox %s does not exist", userid);
  807.     if (POP_sock->sock) {
  808.       sock_puts(POP_sock->sock, "QUIT");
  809.       sock_close(POP_sock->sock);
  810.     }
  811.     return 0;
  812.   }
  813.   sprintf(_temp_buffer, "PASS %s", password);
  814.   sock_puts(POP_sock->sock, _temp_buffer);
  815.   sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  816.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  817.   log_it(DEBUG, "\n - POP> %s", _temp_buffer);
  818.   if (*_temp_buffer != '+') {
  819.     POP_Err_Cond = POP_BAD_PASS;
  820.     log_it(1, "\n ■ Error : Host reports password incorrect or account locked.");
  821.     if (POP_sock->sock) {
  822.       sock_puts(POP_sock->sock, "QUIT");
  823.       sock_close(POP_sock->sock);
  824.     }
  825.     return 0;
  826.   }
  827.   SOCK_READ_ERR(POP,);
  828.   return 1;
  829. }
  830.  
  831. int pop_status(Mail_Socket * POP_sock, unsigned int *count, unsigned long *totallength)
  832. {
  833.   char junk[12];
  834.  
  835.   sock_puts(POP_sock->sock, "STAT");
  836.   sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  837.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  838.   if (*_temp_buffer != '+') {
  839.     POP_Err_Cond = POP_UNKNOWN;
  840.     log_it(DEBUG, "\n ■ Error : Unknown POP error.");
  841.     return 0;
  842.   } else
  843.     sscanf(_temp_buffer, "%s %u %lu", junk, count, totallength);
  844.  
  845.   SOCK_READ_ERR(POP,);
  846.   return 1;
  847. }
  848.  
  849. long pop_length(Mail_Socket * POP_sock, unsigned int msg_num, unsigned long *size)
  850. {
  851.   char junk[21];
  852.   unsigned int dummy;
  853.  
  854.   sprintf(_temp_buffer, "LIST %u", msg_num);
  855.   sock_puts(POP_sock->sock, _temp_buffer);
  856.   sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  857.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  858.   if (*_temp_buffer != '+') {
  859.     POP_Err_Cond = POP_NOT_MSG;
  860.     log_it(DEBUG, "\n ■ Error : No message #%u", msg_num);
  861.     return 0;
  862.   } else
  863.     sscanf(_temp_buffer, "%s %u %lu", &junk, &dummy, size);
  864.  
  865.   SOCK_READ_ERR(POP,);
  866.   if (*size == 0L) {
  867.     log_it(1, "\n ■ Mailbox contains a zero byte file -- deleting Message #%u!", msg_num);
  868.     sprintf(_temp_buffer, "DELE %u", msg_num);
  869.     sock_puts(POP_sock->sock, _temp_buffer);
  870.     sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  871.     sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  872.     log_it(DEBUG, "\n - POP> %s", _temp_buffer);
  873.     if (*_temp_buffer != '+') {
  874.       POP_Err_Cond = POP_NOT_MSG;
  875.       log_it(1, "\n ■ Error : No message #%u", msg_num);
  876.     }
  877.     sock_puts(POP_sock->sock, "QUIT");
  878.     sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  879.     sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  880.     if (*_temp_buffer != '+') {
  881.       POP_Err_Cond = POP_UNKNOWN;
  882.       log_it(1, "\n ■ Error : Unable to update mailbox.");
  883.     } else
  884.       log_it(1, "\n ■ Updated mailbox on %s.", POPHOST);
  885.     sock_close(POP_sock->sock);
  886.   }
  887.   return (*size);
  888. }
  889.  
  890. char *stristr(char *String, char *Pattern)
  891. {
  892.   char *pptr, *sptr, *start;
  893.   unsigned int slen, plen;
  894.  
  895.   for (start = String, pptr = Pattern, slen = strlen(String),
  896.        plen = strlen(Pattern); slen >= plen; start++, slen--) {
  897.     while (toupper(*start) != toupper(*Pattern)) {
  898.       start++;
  899.       slen--;
  900.       if (slen < plen)
  901.         return (NULL);
  902.     }
  903.     sptr = start;
  904.  
  905.     pptr = Pattern;
  906.     while (toupper(*sptr) == toupper(*pptr)) {
  907.       sptr++;
  908.       pptr++;
  909.       if ('\0' == *pptr)
  910.         return (start);
  911.     }
  912.   }
  913.   return (NULL);
  914. }
  915.  
  916. int checkspam(char *text)
  917. {
  918.   char fn[161], buf[81], tmp[81];
  919.   int spam, ok;
  920.   FILE *fp;
  921.  
  922.   spam = 0;
  923.   sprintf(fn, "%sNOSPAM.TXT", net_data);
  924.   if ((fp = fsh_open(fn, "r")) != NULL) {
  925.     while ((!feof(fp)) && (!spam)) {
  926.       fgets(buf, 80, fp);
  927.       trimstr1(buf);
  928.       if (strlen(buf) > 2) {
  929.         if (buf[0] == '\"') {
  930.           strcpy(tmp, &(buf[1]));
  931.           LAST(tmp) = '\0';
  932.           strcpy(buf, tmp);
  933.         }
  934.         if (buf[0] == '[') {
  935.           if ((strnicmp(buf, "[GLOBAL]", 8) == 0) || (strnicmp(buf, "[MAIL]", 6) == 0))
  936.             ok = 1;
  937.           else
  938.             ok = 0;
  939.         }
  940.         if ((ok) && (stristr(text, buf)))
  941.           spam = 1;
  942.       }
  943.     }
  944.     fclose(fp);
  945.   }
  946.   return spam;
  947. }
  948.  
  949. #define MAX_IDS 100
  950.  
  951. int compact_msgid(void)
  952. {
  953.   char fn[161], oldfn[161];
  954.   int i, f1, f2, num_ids;
  955.   Message_ID messageid;
  956.  
  957.   num_ids = 0;
  958.   sprintf(oldfn, "%sMSGID.OLD", net_data);
  959.   unlink(oldfn);
  960.   sprintf(fn, "%sMSGID.DAT", net_data);
  961.   rename(fn, oldfn);
  962.   f1 = sh_open(oldfn, O_RDWR | O_BINARY | O_CREAT, S_IREAD | S_IWRITE);
  963.   if (f1 < 0) {
  964.     log_it(1, "\n ! Unable to read %s.", oldfn);
  965.     return 1;
  966.   }
  967.   f2 = sh_open(fn, O_RDWR | O_BINARY | O_CREAT, S_IREAD | S_IWRITE);
  968.  
  969.   if (f2 < 0) {
  970.     log_it(1, "\n ! Unable to create %s.", fn);
  971.     return 1;
  972.   }
  973.   for (i = 50; i < MAX_IDS; i++) {
  974.     sh_lseek(f1, ((long) (i)) * ((long) sizeof(Message_ID)), SEEK_SET);
  975.     sh_read(f1, (void *) &messageid, sizeof(Message_ID));
  976.     sh_lseek(f2, ((long) (num_ids++)) * ((long) sizeof(Message_ID)), SEEK_SET);
  977.     sh_write(f2, &messageid, sizeof(Message_ID));
  978.   }
  979.   f1 = sh_close(f1);
  980.   f2 = sh_close(f2);
  981.   unlink(oldfn);
  982.   return 0;
  983. }
  984.  
  985. int check_messageid(int add, char *msgid)
  986. {
  987.   char fn[MAXPATH];
  988.   int i, f, dupe, num_ids;
  989.   Message_ID messageid;
  990.  
  991.   num_ids = dupe = 0;
  992.   sprintf(fn, "%sMSGID.DAT", net_data);
  993.   f = sh_open(fn, O_RDWR | O_BINARY | O_CREAT, S_IREAD | S_IWRITE);
  994.   if (f < 0) {
  995.     log_it(1, "\n ! Unable to create %s.", fn);
  996.     return -1;
  997.   }
  998.   num_ids = (int) (filelength(f) / sizeof(Message_ID));
  999.  
  1000.   if (num_ids > MAX_IDS)
  1001.     compact_ids = 1;
  1002.   if (!add) {
  1003.     log_it(DEBUG, "\n ■ Scanning previous %d Message-IDs.", num_ids);
  1004.     for (i = 0; ((i < num_ids) && (!dupe)); i++) {
  1005.       sh_lseek(f, ((long) (i)) * ((long) sizeof(Message_ID)), SEEK_SET);
  1006.       sh_read(f, (void *) &messageid, sizeof(Message_ID));
  1007.       if (strcmp(messageid.msgid, msgid) == 0)
  1008.         dupe = 1;
  1009.     }
  1010.   } else {
  1011.     strncpy(messageid.msgid, msgid, 80);
  1012.     messageid.msgid[81] = '\0';
  1013.     log_it(DEBUG, "\n ■ Adding new Message-ID:%s", messageid.msgid);
  1014.     sh_lseek(f, ((long) (num_ids)) * ((long) sizeof(Message_ID)), SEEK_SET);
  1015.     sh_write(f, &messageid, sizeof(Message_ID));
  1016.   }
  1017.   f = sh_close(f);
  1018.   return dupe;
  1019. }
  1020.  
  1021. int pop_top(Mail_Socket * POP_sock, unsigned int msg_num, int usernum)
  1022. {
  1023.   int okpkt, found_from, found_subj, dupe;
  1024.   char *ss, subject[81];
  1025.  
  1026.   sprintf(_temp_buffer, "TOP %u 40", msg_num);
  1027.   sock_puts(POP_sock->sock, _temp_buffer);
  1028.   sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  1029.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  1030.   if (*_temp_buffer != '+') {
  1031.     POP_Err_Cond = POP_NOT_MSG;
  1032.     log_it(1, "\n ■ Error : No message #%u.", msg_num);
  1033.     return -1;
  1034.   }
  1035.   okpkt = -1;
  1036.  
  1037.   dupe = 0;
  1038.   found_from = found_subj = fdl = 0;
  1039.   while (1) {
  1040.     sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  1041.     sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  1042.     if (*_temp_buffer == '.' && _temp_buffer[1] == 0)
  1043.       break;
  1044.     if (usernum == 0) {
  1045.       if ((strnicmp(_temp_buffer, "begin ", 6) == 0) &&
  1046.           (stristr(_temp_buffer, "WINMAIL") == NULL)) {
  1047.         if (okpkt != 4)
  1048.           okpkt = 1;
  1049.         if ((stristr(_temp_buffer, ".ZIP") != NULL) ||
  1050.             (stristr(_temp_buffer, ".ARJ") != NULL) ||
  1051.             (stristr(_temp_buffer, ".LZH") != NULL))
  1052.           okpkt = 2;
  1053.         if ((stristr(_temp_buffer, ".GIF") != NULL) ||
  1054.             (stristr(_temp_buffer, ".JPG") != NULL))
  1055.           okpkt = 3;
  1056.         if ((okpkt == 2) || (okpkt == 3) || (fdl)) {
  1057.           ss = strtok(_temp_buffer, "6");
  1058.           if (ss) {
  1059.             ss = strtok(NULL, " ");
  1060.             if (ss)
  1061.               ss = strtok(NULL, "\r\n");
  1062.           }
  1063.           if (ss) {
  1064.             strcpy(fdlfn, ss);
  1065.             trimstr1(fdlfn);
  1066.           }
  1067.         }
  1068.       }
  1069.       if (strnicmp(_temp_buffer, "FDL Type:", 9) == 0)
  1070.         fdl = 1;
  1071.     }
  1072.     if ((strnicmp(_temp_buffer, "from:", 5) == 0) && (!found_from)) {
  1073.       if (((stristr(_temp_buffer, "mailer-daemon") != NULL) ||
  1074.            (stristr(_temp_buffer, "mail delivery") != NULL) ||
  1075.            (stristr(_temp_buffer, "administrator") != NULL) ||
  1076.            (stristr(_temp_buffer, from_user) != NULL)) && (usernum == 0))
  1077.         okpkt = 4;
  1078.       else {
  1079.         if (_temp_buffer[6] != 0)
  1080.           strncpy(pktowner, &_temp_buffer[6], 25);
  1081.         else
  1082.           strcpy(pktowner, "Unknown");
  1083.       }
  1084.       found_from = 1;
  1085.     }
  1086.     if ((strnicmp(_temp_buffer, "subject:", 8) == 0) && (!found_subj)) {
  1087.       if (_temp_buffer[9] != 0)
  1088.         strncpy(subject, &_temp_buffer[9], 60);
  1089.       else
  1090.         strcpy(subject, "Unknown");
  1091.       found_subj = 1;
  1092.     }
  1093.     if (usernum == 0) {
  1094.       if ((strnicmp(_temp_buffer, "Message-ID:", 11) == 0) && (!found_subj)) {
  1095.         if (_temp_buffer[11] != 0) {
  1096.           strncpy(id, &_temp_buffer[11], 80);
  1097.           id[81] = '\0';
  1098.           if (check_messageid(0, id))
  1099.             dupe = 1;
  1100.         }
  1101.       }
  1102.     }
  1103.   }
  1104.   if (found_from && found_subj) {
  1105.     if (okpkt == -1)
  1106.       if ((checkspam(pktowner)) || (checkspam(subject)))
  1107.         okpkt = 5;
  1108.   }
  1109.   if (found_subj) {
  1110.     if ((strnicmp(subject, "subscribe", 9) == 0) ||
  1111.         (strnicmp(subject, "unsubscribe", 11) == 0))
  1112.       okpkt = 6;
  1113.   }
  1114.   if (dupe)
  1115.     okpkt = 7;
  1116.   SOCK_READ_ERR(POP,);
  1117.   return okpkt;
  1118. }
  1119.  
  1120. int pop_getf(Mail_Socket * POP_sock, char *fn, unsigned int msg_num, int usernum)
  1121. {
  1122.   unsigned long size;
  1123.   long nbytes, rbytes;
  1124.   int pos, ctld, len;
  1125.   FILE *fp;
  1126.  
  1127.   if (!pop_length(POP_sock, msg_num, &size))
  1128.     return 0;
  1129.   sprintf(_temp_buffer, "RETR %u", msg_num);
  1130.   sock_puts(POP_sock->sock, _temp_buffer);
  1131.   sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  1132.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  1133.   if (*_temp_buffer != '+') {
  1134.     POP_Err_Cond = POP_NOT_MSG;
  1135.     log_it(1, "\n ■ Error : No message #%u", msg_num);
  1136.     return 0;
  1137.   }
  1138.   nbytes = 0L;
  1139.  
  1140.   rbytes = 1024L;
  1141.   output(" : ");
  1142.   pos = wherex();
  1143.   if ((fp = fsh_open(fn, "w")) == NULL) {
  1144.     log_it(1, "\n ■ Unable to create %s... aborting!", fn);
  1145.     return 0;
  1146.   }
  1147.   if (usernum > 0)
  1148.     fprintf(fp, "0RX-WWIV-User: #%d\n", usernum);
  1149.   ctld = 1;
  1150.   while (1) {
  1151.     sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  1152.     len = (sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer)));
  1153.     if ((ctld == 1) && (len == 0))
  1154.       ctld = 0;
  1155.     if ((strnicmp(_temp_buffer, "begin ", 6) == 0) &&
  1156.         (stristr(_temp_buffer, "WINMAIL") != NULL))
  1157.       ctld = 2;
  1158.     if ((ctld == 2) && (strnicmp(_temp_buffer, "end", 3) == 0))
  1159.       ctld = 0;
  1160.     if (_temp_buffer[0] == '.' && _temp_buffer[1] == 0)
  1161.       break;
  1162.     if (EOF == (nbytes += fprintf(fp, "%s%s\n", ctld ? "0R" : "", _temp_buffer))) {
  1163.       if (fp != NULL)
  1164.         fclose(fp);
  1165.       return 0;
  1166.     }
  1167.     if (nbytes > rbytes) {
  1168.       go_back(wherex(), pos);
  1169.       output("%ld/%ld", nbytes, size);
  1170.       rbytes += 512L;
  1171.     }
  1172.   }
  1173.   if (fp != NULL)
  1174.     fclose(fp);
  1175.   go_back(wherex(), pos);
  1176.   output("message received!");
  1177.   SOCK_READ_ERR(POP,);
  1178.   return 1;
  1179. }
  1180.  
  1181. int pop_delete(Mail_Socket * POP_sock, unsigned int msg_num)
  1182. {
  1183.   sprintf(_temp_buffer, "DELE %u", msg_num);
  1184.   sock_puts(POP_sock->sock, _temp_buffer);
  1185.   sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  1186.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  1187.   log_it(DEBUG, "\n - POP> %s", _temp_buffer);
  1188.   if (*_temp_buffer != '+') {
  1189.     POP_Err_Cond = POP_NOT_MSG;
  1190.     log_it(1, "\n ■ Error : No message #%u", msg_num);
  1191.     return 2;
  1192.   }
  1193.   SOCK_READ_ERR(POP,);
  1194.  
  1195.   return 1;
  1196. }
  1197.  
  1198.  
  1199. int pop_shutdown(Mail_Socket * POP_sock)
  1200. {
  1201.   if (POP_sock->sock) {
  1202.     sock_puts(POP_sock->sock, "QUIT");
  1203.     sock_wait_input(POP_sock->sock, sock_delay, NULL, &POP_stat);
  1204.     sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  1205.     if (*_temp_buffer != '+') {
  1206.       POP_Err_Cond = POP_UNKNOWN;
  1207.       log_it(1, "\n ■ Error : Unable to update mailbox.");
  1208.       return 0;
  1209.     } else
  1210.       log_it(DEBUG, "\n ■ Closed and updated mailbox.");
  1211.     sock_close(POP_sock->sock);
  1212.     return 1;
  1213.   }
  1214. sock_err:
  1215.   free_Mail_Socket(POP_sock);
  1216.  
  1217.   return 0;
  1218. }
  1219.  
  1220. int pop_get_nextf(Mail_Socket * POP_sock, char *fn, int msgnum, int usernum)
  1221. {
  1222.   if (!pop_getf(POP_sock, fn, msgnum, usernum))
  1223.     return 0;
  1224.   return (pop_delete(POP_sock, msgnum));
  1225. }
  1226.  
  1227. int exist(char *s)
  1228. {
  1229.   int i;
  1230.   struct ffblk ff;
  1231.  
  1232.   i = findfirst(s, &ff, FA_HIDDEN);
  1233.   if (i)
  1234.     return 0;
  1235.   else
  1236.     return 1;
  1237. }
  1238.  
  1239. int find_acct(char *username, char *hostname, char *password)
  1240. {
  1241.   char *ss, fn[161], s[121];
  1242.   int num;
  1243.   FILE *fp;
  1244.  
  1245.   num = 0;
  1246.   sprintf(fn, "%sACCT.INI", net_data);
  1247.   if ((fp = fsh_open(fn, "rt")) == NULL)
  1248.     return 0;
  1249.   while ((fgets(s, 120, fp)) && (num == 0)) {
  1250.     if (strnicmp(s, "ACCT", 4) == 0) {
  1251.       if ((_fstrstr(s, username) != 0) && (_fstrstr(s, hostname) != 0) &&
  1252.           (_fstrstr(s, password) != 0)) {
  1253.         ss = strtok(s, "=");
  1254.         num = atoi(&(ss[4]));
  1255.         log_it(DEBUG, "\n ■ Checking mailbox %s on %s for user #%d.", username,
  1256.                hostname, num);
  1257.       }
  1258.     }
  1259.   }
  1260.   if (fp != NULL)
  1261.     fclose(fp);
  1262.   return num;
  1263. }
  1264.  
  1265. int count_accts(int build)
  1266. {
  1267.   FILE *fp;
  1268.   char *ss, s[101], fn[MAXPATH];
  1269.   int accts = 0;
  1270.  
  1271.   sprintf(fn, "%sACCT.INI", net_data);
  1272.   if ((fp = fsh_open(fn, "rt")) == NULL)
  1273.     return 0;
  1274.  
  1275.   while (fgets(s, 100, fp)) {
  1276.     if (strnicmp(s, "ACCT", 4) == 0) {
  1277.       if (build) {
  1278.         ss = strtok(s, "=");
  1279.         if (ss) {
  1280.           ss = strtok(NULL, "@");
  1281.           trimstr1(ss);
  1282.           if (ss) {
  1283.             strcpy(acct[accts].popname, ss);
  1284.             ss = strtok(NULL, " ");
  1285.             trimstr1(ss);
  1286.             if (ss) {
  1287.               strcpy(acct[accts].pophost, ss);
  1288.               ss = strtok(NULL, " \r\n");
  1289.               trimstr1(ss);
  1290.               if (ss)
  1291.                 strcpy(acct[accts].poppass, ss);
  1292.             }
  1293.           }
  1294.           log_it(DEBUG, "\n - Account : %s - %s - %s", acct[accts].pophost,
  1295.                  acct[accts].popname, acct[accts].poppass);
  1296.         }
  1297.       }
  1298.       ++accts;
  1299.     }
  1300.   }
  1301.   if (fp != NULL)
  1302.     fclose(fp);
  1303.   return accts;
  1304. }
  1305.  
  1306. void main(int argc, char *argv[])
  1307. {
  1308.   unsigned int count, failed;
  1309.   unsigned long size;
  1310.   int aborted, f1, i, i1, okpkt, result, usernum, num_accts, accts;
  1311.   char fn[MAXPATH], temp[181], inbound[MAXPATH], mqueue[MAXPATH], s[21], s1[21];
  1312.   Mail_Socket *pop_sock = NULL;
  1313.   Mail_Socket *smtp_sock = NULL;
  1314.   struct ffblk ff;
  1315.  
  1316.   detect_multitask();
  1317.  
  1318.   if (strncmpi(argv[1], "-send", strlen(argv[1])) == 0) {
  1319.     if (argc < 5) {
  1320.       output("\n ■ %s", version);
  1321.       output("\n ■ Invalid arguments for %s\n", argv[0]);
  1322.       exit(EXIT_FAILURE);
  1323.     }
  1324.     if (argc == 6)
  1325.       DEBUG = atoi(argv[5]);
  1326.  
  1327.     strcpy(mqueue, argv[4]);
  1328.     strcpy(net_data, argv[4]);
  1329.     LAST(net_data) = '\0';
  1330.     while (LAST(net_data) != '\\')
  1331.       LAST(net_data) = '\0';
  1332.     output("\n");
  1333.     if ((smtp_sock = smtp_start(argv[2], argv[3])) != NULL) {
  1334.       failed = count = aborted = 0;
  1335.       sprintf(fn, "%s*.*", mqueue);
  1336.       f1 = findfirst(fn, &ff, FA_ARCH);
  1337.       while ((count < 3) && (f1 == 0) && (failed < 5) && (!aborted)) {
  1338.         sprintf(fn, "%s%s", mqueue, ff.ff_name);
  1339.         if (count > 1)
  1340.           output(" ■ SMTP pass %d...\n", count);
  1341.         if (!smtp_sendf(smtp_sock, fn, argv[2], &aborted))
  1342.           ++failed;
  1343.         else
  1344.           unlink(fn);
  1345.         f1 = findnext(&ff);
  1346.         if (f1 != 0) {
  1347.           sprintf(fn, "%s*.*", mqueue);
  1348.           f1 = findfirst(fn, &ff, FA_ARCH);
  1349.           ++count;
  1350.         }
  1351.       }
  1352.       if (failed >= 5)
  1353.         log_it(1, "\n ■ Too many SMTP failures.  Try again later.");
  1354.       smtp_shutdown(smtp_sock);
  1355.     } else
  1356.       log_it(1, "\n ■ SMTP connection failed.");
  1357.     fcloseall();
  1358.   } else if (strncmpi(argv[1], "-receive", strlen(argv[1])) == 0) {
  1359.     if (argc < 8) {
  1360.       output("\n ■ %s", version);
  1361.       output("\n ■ Invalid arguments for %s\n", argv[0]);
  1362.       exit(EXIT_FAILURE);
  1363.     }
  1364.     sprintf(from_user, "%s@%s", argv[3], argv[7]);
  1365.     if (argc == 9)
  1366.       DEBUG = atoi(argv[8]);
  1367.     ALLMAIL = atoi(argv[6]);
  1368.     strcpy(POPHOST, argv[2]);
  1369.     strcpy(net_data, argv[5]);
  1370.     LAST(net_data) = '\0';
  1371.     while (LAST(net_data) != '\\')
  1372.       LAST(net_data) = '\0';
  1373.     POP_Err_Cond = POP_OK;
  1374.     strcpy(POPNAME, argv[3]);
  1375.     strcpy(POPPASS, argv[4]);
  1376.     strcpy(inbound, argv[5]);
  1377.     strcpy(DOMAIN, argv[7]);
  1378.     num_accts = accts = usernum = 0;
  1379.     log_it(DEBUG, "\n - POPHOST=%s\n - POPNAME=%s\n - POPPASS=%s\n - DOMAIN=%s\n - inbound=%s\n - net_data=%s",
  1380.         POPHOST, POPNAME, POPPASS, DOMAIN, inbound, net_data);
  1381.     do {
  1382.       log_it(1, "\n ■ Checking %s... ", POPHOST);
  1383.       if ((pop_sock = pop_init(argv[2])) != NULL) {
  1384.         if (pop_login(pop_sock, POPNAME, POPPASS)) {
  1385.           if (pop_status(pop_sock, &count, &size)) {
  1386.             okpkt = 0;
  1387.             output("%s has %u message%s (%luK).", POPNAME, count,
  1388.                   count == 1 ? "" : "s", ((size + 1023) / 1024));
  1389.             i1 = 1;
  1390.             while (i1 <= count) {
  1391.               okpkt = 0;
  1392.               okpkt = pop_top(pop_sock, i1, usernum);
  1393.               switch (okpkt) {
  1394.                 case -1:
  1395.                   if ((!ALLMAIL) && (!fdl))
  1396.                     log_it(1, "\n ■ Non-network message %d left on server.", i1);
  1397.                   else {
  1398.                     i = 0;
  1399.                     sprintf(temp, "%sUNK-%03d.MSG", inbound, i);
  1400.                     while (exist(temp))
  1401.                       sprintf(temp, "%sUNK-%03d.MSG", inbound, ++i);
  1402.                     fnsplit(temp, NULL, NULL, s, s1);
  1403.                     log_it(1, "\n ■ RCV : %3.3d : %-25s : %s%s", i1, pktowner[0] == 0 ?
  1404.                            "non-network packet" : pktowner, s, s1);
  1405.                     result = (pop_get_nextf(pop_sock, temp, i1, usernum));
  1406.                     switch (result) {
  1407.                       case 0:
  1408.                         log_it(1, "\n ■ Unable to retrieve message %d.", i1);
  1409.                         fcloseall();
  1410.                         exit(EXIT_FAILURE);
  1411.                       case 1:
  1412.                         break;
  1413.                       case 2:
  1414.                         log_it(1, "\n ■ Unable to delete message %d from host!", i1);
  1415.                         exit(EXIT_FAILURE);
  1416.                     }
  1417.                   }
  1418.                   break;
  1419.                 case 0:
  1420.                   log_it(1, "\n ■ Error accessing message %d", i1);
  1421.                   fcloseall();
  1422.                   exit(EXIT_FAILURE);
  1423.                 case 1:
  1424.                   i = 0;
  1425.                   sprintf(temp, "%sPKT-%03d.UUE", inbound, i);
  1426.                   while (exist(temp))
  1427.                     sprintf(temp, "%sPKT-%03d.UUE", inbound, ++i);
  1428.                   fnsplit(temp, NULL, NULL, s, s1);
  1429.                   log_it(1, "\n ■ RCV : %3.3d : %-25s : %s%s", i1, pktowner, s, s1);
  1430.                   result = (pop_get_nextf(pop_sock, temp, i1, usernum));
  1431.                   switch (result) {
  1432.                     case 0:
  1433.                       log_it(1, "\n ■ Unable to retrieve message %d.", i1);
  1434.                       fcloseall();
  1435.                       exit(EXIT_FAILURE);
  1436.                     case 1:
  1437.                       check_messageid(1, id);
  1438.                       break;
  1439.                     case 2:
  1440.                       log_it(1, "\n ■ Unable to delete message %d on host!", i1);
  1441.                       exit(EXIT_FAILURE);
  1442.                   }
  1443.                   break;
  1444.                 case 2:
  1445.                   if ((!ALLMAIL) && (!fdl))
  1446.                     log_it(1, "\n ■ Non-network message %d left on server.", i1);
  1447.                   else {
  1448.                     i = 0;
  1449.                     sprintf(temp, "%sARC-%03d.UUE", inbound, i);
  1450.                     while (exist(temp))
  1451.                       sprintf(temp, "%sARC-%03d.UUE", inbound, ++i);
  1452.                     fnsplit(temp, NULL, NULL, s, s1);
  1453.                     if (*fdlfn)
  1454.                       log_it(1, "\n ■ RCV : %3.3d : %-25s : %s", i1, "archived file", fdlfn);
  1455.                     else
  1456.                       log_it(1, "\n ■ RCV : %3.3d : %-25s : %s%s", i1, "archived file", s, s1);
  1457.                     result = (pop_get_nextf(pop_sock, temp, i1, usernum));
  1458.                     switch (result) {
  1459.                       case 0:
  1460.                         log_it(1, "\n ■ Unable to retrieve message %d.", i1);
  1461.                         fcloseall();
  1462.                         exit(EXIT_FAILURE);
  1463.                       case 1:
  1464.                         check_messageid(1, id);
  1465.                         break;
  1466.                       case 2:
  1467.                         log_it(1, "\n ■ Unable to delete message %d on host!", i1);
  1468.                         exit(EXIT_FAILURE);
  1469.                     }
  1470.                   }
  1471.                   break;
  1472.                 case 3:
  1473.                   if ((!ALLMAIL) && (!fdl))
  1474.                     log_it(1, "\n ■ Non-network message %d left on server.", i1);
  1475.                   else {
  1476.                     i = 0;
  1477.                     sprintf(temp, "%sGIF-%03d.UUE", inbound, i);
  1478.                     while (exist(temp))
  1479.                       sprintf(temp, "%sGIF-%03d.UUE", inbound, ++i);
  1480.                     fnsplit(temp, NULL, NULL, s, s1);
  1481.                     log_it(1, "\n ■ RCV : %3.3d : %-25s : %s%s", i1, "graphic/image file", s, s1);
  1482.                     result = (pop_get_nextf(pop_sock, temp, i1, usernum));
  1483.                     switch (result) {
  1484.                       case 0:
  1485.                         log_it(1, "\n ■ Unable to retrieve message %d.", i1);
  1486.                         fcloseall();
  1487.                         exit(EXIT_FAILURE);
  1488.                       case 1:
  1489.                         check_messageid(1, id);
  1490.                         break;
  1491.                       case 2:
  1492.                         log_it(1, "\n ■ Unable to delete message %d from host!", i1);
  1493.                         exit(EXIT_FAILURE);
  1494.                     }
  1495.                   }
  1496.                   break;
  1497.                 case 4:
  1498.                   i = 0;
  1499.                   sprintf(temp, "%sBAD-%03d.UUE", inbound, i);
  1500.                   while (exist(temp))
  1501.                     sprintf(temp, "%sBAD-%03d.UUE", inbound, ++i);
  1502.                   fnsplit(temp, NULL, NULL, s, s1);
  1503.                   log_it(1, "\n ■ RCV : %3.3d : %-25s : %s%s", i1, "mailer-daemon/bounced", s, s1);
  1504.                   result = (pop_get_nextf(pop_sock, temp, i1, usernum));
  1505.                   switch (result) {
  1506.                     case 0:
  1507.                       log_it(1, "\n ■ Unable to retrieve message %d.", i1);
  1508.                       fcloseall();
  1509.                       exit(EXIT_FAILURE);
  1510.                     case 1:
  1511.                       check_messageid(1, id);
  1512.                       break;
  1513.                     case 2:
  1514.                       log_it(1, "\n ■ Unable to delete message %d from host!", i1);
  1515.                       exit(EXIT_FAILURE);
  1516.                   }
  1517.                   break;
  1518.                 case 5:
  1519.                   if ((!ALLMAIL) && (!fdl))
  1520.                     log_it(1, "\n ■ Non-network message %d left on server.", i1);
  1521.                   else {
  1522.                     i = 0;
  1523.                     sprintf(temp, "%sSPM-%03d.MSG", inbound, i);
  1524.                     while (exist(temp))
  1525.                       sprintf(temp, "%sSPM-%03d.MSG", inbound, ++i);
  1526.                     fnsplit(temp, NULL, NULL, s, s1);
  1527.                     log_it(1, "\n ■ RCV : %3.3d : %-25s : %s%s", i1, "matched NOSPAM.TXT", s, s1);
  1528.                     result = (pop_get_nextf(pop_sock, temp, i1, usernum));
  1529.                     switch (result) {
  1530.                       case 0:
  1531.                         log_it(1, "\n ■ Unable to retrieve message %d.", i1);
  1532.                         fcloseall();
  1533.                         exit(EXIT_FAILURE);
  1534.                       case 1:
  1535.                         check_messageid(1, id);
  1536.                         break;
  1537.                       case 2:
  1538.                         log_it(1, "\n ■ Unable to delete message %d from host!", i1);
  1539.                         exit(EXIT_FAILURE);
  1540.                     }
  1541.                   }
  1542.                   break;
  1543.                 case 6:
  1544.                   if ((!ALLMAIL) && (!fdl))
  1545.                     log_it(1, "\n ■ Non-network message %d left on server.", i1);
  1546.                   else {
  1547.                     i = 0;
  1548.                     sprintf(temp, "%sSUB-%03d.MSG", inbound, i);
  1549.                     while (exist(temp))
  1550.                       sprintf(temp, "%sSUB-%03d.MSG", inbound, ++i);
  1551.                     fnsplit(temp, NULL, NULL, s, s1);
  1552.                     log_it(1, "\n ■ RCV : %3.3d : %-25s : %s%s", i1, "subscribe request", s, s1);
  1553.                     result = (pop_get_nextf(pop_sock, temp, i1, usernum));
  1554.                     switch (result) {
  1555.                       case 0:
  1556.                         log_it(1, "\n ■ Unable to retrieve message %d.", i1);
  1557.                         fcloseall();
  1558.                         exit(EXIT_FAILURE);
  1559.                       case 1:
  1560.                         check_messageid(1, id);
  1561.                         break;
  1562.                       case 2:
  1563.                         log_it(1, "\n ■ Unable to delete message %d from host!", i1);
  1564.                         exit(EXIT_FAILURE);
  1565.                     }
  1566.                   }
  1567.                   break;
  1568.                 case 7:
  1569.                   if ((!ALLMAIL) && (!fdl))
  1570.                     log_it(1, "\n ■ Duplicate message %d left on server.", i1);
  1571.                   else {
  1572.                     i = 0;
  1573.                     sprintf(temp, "%sDUP-%03d.MSG", inbound, i);
  1574.                     while (exist(temp))
  1575.                       sprintf(temp, "%sDUP-%03d.MSG", inbound, ++i);
  1576.                     fnsplit(temp, NULL, NULL, s, s1);
  1577.                     log_it(1, "\n ■ RCV : %3.3d : %-25s : %s%s", i1, "duplicate message", s, s1);
  1578.                     result = (pop_get_nextf(pop_sock, temp, i1, usernum));
  1579.                     switch (result) {
  1580.                       case 0:
  1581.                         log_it(1, "\n ■ Unable to retrieve message %d.", i1);
  1582.                         fcloseall();
  1583.                         exit(EXIT_FAILURE);
  1584.                       case 1:
  1585.                         break;
  1586.                       case 2:
  1587.                         log_it(1, "\n ■ Unable to delete message %d from host!", i1);
  1588.                         exit(EXIT_FAILURE);
  1589.                     }
  1590.                   }
  1591.                   break;
  1592.               }
  1593.               i1++;
  1594.               fcloseall();
  1595.             }
  1596.             if (compact_ids) {
  1597.               log_it(1, "\n ■ Compacting Message-ID database...");
  1598.               compact_msgid();
  1599.             }
  1600.           } else
  1601.             log_it(1, "\n ■ Unknown POP access error - try again later.");
  1602.           pop_shutdown(pop_sock);
  1603.         } else {
  1604.           log_it(1, "\n ■ Unable to log into POP server!");
  1605.           pop_shutdown(pop_sock);
  1606.         }
  1607.       } else
  1608.         log_it(1, "\n ■ POP socket connect failed.");
  1609.       if (strncmp(DOMAIN, "filenet.ml.org", 14) == 0)
  1610.         num_accts = 0;
  1611.       else {
  1612.         if (!accts) {
  1613.           num_accts = count_accts(0);
  1614.           log_it(DEBUG, "\n - Found %d extra account%s.", num_accts, num_accts == 1 ? "" : "s");
  1615.           if (num_accts) {
  1616.             acct = (ACCT *) farmalloc(sizeof(ACCT) * num_accts);
  1617.             if (acct != NULL) {
  1618.               num_accts = count_accts(1);
  1619.             } else {
  1620.               log_it(DEBUG, "\n ! Insufficient memory for extra accounts.");
  1621.               num_accts = 0;
  1622.             }
  1623.             accts = 1;
  1624.           }
  1625.         }
  1626.       }
  1627.       if (num_accts) {
  1628.         strcpy(POPNAME, acct[num_accts - 1].popname);
  1629.         argv[2] = POPHOST;
  1630.         strcpy(POPHOST, acct[num_accts - 1].pophost);
  1631.         strcpy(POPPASS, acct[num_accts - 1].poppass);
  1632.         usernum = find_acct(POPNAME, POPHOST, POPPASS);
  1633.       }
  1634.     } while (num_accts-- > 0);
  1635.     if (acct != NULL) {
  1636.       farfree((void *)acct);
  1637.       acct = NULL;
  1638.     }
  1639.     exit(EXIT_SUCCESS);
  1640.   }
  1641.   exit(EXIT_FAILURE);
  1642. }
  1643.