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