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