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