home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / PPPBCKP / SRC15B41.ZIP / POP.C < prev    next >
Text File  |  1997-09-14  |  34KB  |  1,151 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. #include "tcp.h"
  17. #include "pop.h"
  18. #include "version.h"
  19. #include "retcode.h"
  20.  
  21. #define POP_PORT 110
  22.  
  23. #define SMTP_PORT 25
  24.  
  25. #define _TEMP_BUFFER_LEN 1024
  26.  
  27. #define SHARE_LEVEL 10
  28. #define WAIT_TIME 10
  29. #define TRIES 100
  30.  
  31. #define MT_DESQVIEW 0x01
  32. #define MT_WINDOWS  0x02
  33. #define MT_OS2      0x04
  34. #define MT_NB       0x40
  35.  
  36.  
  37. #define blankline(LINE) (strspn(LINE, " \n\t\r")==strlen(LINE))
  38.  
  39. #define free_Mail_Socket(SOCK) if (SOCK!=NULL) {     \
  40.   farfree(SOCK->sock); farfree(SOCK); SOCK=NULL; }
  41.  
  42. int POP_Err_Cond;
  43. char *POP_Err_Msg = NULL;
  44. static char _POP_err_msg_buf[100] = "";
  45. int SMTP_Err_Cond;
  46. char *SMTP_Err_Msg = NULL;
  47. static char _SMTP_err_msg_buf[100] = "";
  48. char *POPLIB_Err_Msg = NULL;
  49. char from_user[41], POPHOST[81];
  50. int WatTCP_initialized = 0;
  51. static char _temp_buffer[_TEMP_BUFFER_LEN];
  52. int POP_stat;
  53. int SMTP_stat;
  54. int SOCK_DELAY = 60;
  55. int multitasker = 0;
  56. int DEBUG = 1;
  57.  
  58. char pktowner[21];
  59.  
  60. #define SOCK_READ_ERR(PROTOCOL)                                                 \
  61.   sock_err:                                                                     \
  62.   if (DEBUG) {                                                                  \
  63.     switch (PROTOCOL##_stat) {                                                  \
  64.       case 1 : /* foreign host closed */                                        \
  65.         sprintf(PROTOCOL##_Err_Msg, #PROTOCOL " Ok");                           \
  66.         sprintf(POPLIB_Err_Msg, "Connection reset: %s.",                        \
  67.             sockerr(PROTOCOL##_sock->sock));                                    \
  68.         output(#PROTOCOL " > %s\n", POPLIB_Err_Msg);                            \
  69.       case -1: /* timeout */                                                    \
  70.         sprintf(PROTOCOL##_Err_Msg, #PROTOCOL " Ok");                           \
  71.         sprintf(POPLIB_Err_Msg, "Timeout: %s.", sockerr(PROTOCOL##_sock->sock));\
  72.         output(#PROTOCOL " > %s\n", POPLIB_Err_Msg);                            \
  73.     }                                                                           \
  74.   }
  75.  
  76. #define SOCK_GETS(PROTOCOL)                                                     \
  77.   sock_wait_input( PROTOCOL##_sock->sock, SOCK_DELAY, NULL,                     \
  78.        &PROTOCOL##_stat );                                                      \
  79.   sock_gets( PROTOCOL##_sock->sock, _temp_buffer, sizeof( _temp_buffer ));      \
  80.   if (DEBUG)                                                                    \
  81.     output(#PROTOCOL"> %s\n", _temp_buffer);                                    \
  82.   strncpy(PROTOCOL##_Err_Msg, &_temp_buffer[5], 100);
  83.  
  84. #define SMTP_FAIL_ON(NUM, SHUTDOWN)                                             \
  85.   if ( SMTP_Err_Cond == NUM ) {                                                 \
  86.     if (DEBUG)                                                                  \
  87.       output("SMTP Failure > '" #NUM "'\n");                                    \
  88.     sock_puts( SMTP_sock->sock, "QUIT" );                                       \
  89.     sock_close( SMTP_sock->sock );                                              \
  90.     free_Mail_Socket(SMTP_sock);                                                \
  91.     if (DEBUG)                                                                  \
  92.       output("SMTP Error - '" #NUM "'", 100);                                   \
  93.     SHUTDOWN;                                                                   \
  94.     return(0);                                                                  \
  95.   }
  96.  
  97. #define SMTP_FAIL_IF(COND, SHUTDOWN)                                            \
  98.   if ( COND ) {                                                                 \
  99.     if (DEBUG)                                                                  \
  100.       output("SMTP Failure > (" #COND ")\n");                                   \
  101.     sock_puts( SMTP_sock->sock, "QUIT" );                                       \
  102.     sock_close( SMTP_sock->sock );                                              \
  103.     free_Mail_Socket(SMTP_sock);                                                \
  104.     output("SMTP Error - (" #COND ")", 100);                                    \
  105.     SHUTDOWN;                                                                   \
  106.     return(0);                                                                  \
  107.   }
  108.  
  109. #define SMTP_RESET_ON(NUM, SHUTDOWN)                                            \
  110.   if ( SMTP_Err_Cond == NUM ) {                                                 \
  111.     if (DEBUG)                                                                  \
  112.       output("SMTP Problem > '" #NUM "'\n");                                    \
  113.     sock_puts( SMTP_sock->sock, "RSET" );                                       \
  114.     sock_wait_input( SMTP_sock->sock, SOCK_DELAY, NULL, &SMTP_stat );           \
  115.     sock_gets( SMTP_sock->sock, _temp_buffer, sizeof( _temp_buffer ));          \
  116.     if (DEBUG)                                                                  \
  117.       output("SMTP Problem - '" #NUM "'", 100);                                 \
  118.     SHUTDOWN;                                                                   \
  119.     return(0);                                                                  \
  120.   }
  121.  
  122. void output(char *fmt,...)
  123. {
  124.   va_list v;
  125.   char s[255];
  126.  
  127.   va_start(v, fmt);
  128.   vsprintf(s, fmt, v);
  129.   va_end(v);
  130.   fputs(s, stderr);
  131. }
  132.  
  133. void backline(void)
  134. {
  135.   int i;
  136.  
  137.   i = wherex();
  138.   if (i < 80)
  139.     output(" ");
  140.   else
  141.     i--;
  142.   while (i-- > 0)
  143.     output("\b \b");
  144. }
  145.  
  146.  
  147. int get_dos_version(void)
  148. {
  149.   _AX = 0x3000;
  150.   geninterrupt(0x21);
  151.   if (_AX % 256 >= 10) {
  152.     multitasker |= MT_OS2;
  153.   }
  154.   return (_AX);
  155. }
  156.  
  157. int get_dv_version(void)
  158. {
  159.   int v;
  160.  
  161.   if (multitasker & MT_OS2)
  162.     return 0;
  163.   _AX = 0x2b01;
  164.   _CX = 0x4445;
  165.   _DX = 0x5351;
  166.   geninterrupt(0x21);
  167.   if (_AL == 0xff) {
  168.     return 0;
  169.   } else {
  170.     v = _BX;
  171.     multitasker |= MT_DESQVIEW;
  172.     return v;
  173.   }
  174. }
  175.  
  176. int get_win_version(void)
  177. {
  178.   int v = 0;
  179.  
  180.   __emit__(0x55, 0x06, 0x53);
  181.   _AX = 0x352f;
  182.   geninterrupt(0x21);
  183.   _AX = _ES;
  184.   if (_AX | _BX) {
  185.     _AX = 0x1600;
  186.     geninterrupt(0x2f);
  187.     v = _AX;
  188.     if (v % 256 <= 1)
  189.       v = 0;
  190.   }
  191.   __emit__(0x5b, 0x07, 0x5d);
  192.   if (v != 0)
  193.     multitasker |= MT_WINDOWS;
  194.   return (v);
  195. }
  196.  
  197. int get_nb_version(void)
  198. {
  199.   _AX = 0;
  200.   geninterrupt(0x2A);
  201.   return (_AH);
  202. }
  203.  
  204. void detect_multitask(void)
  205. {
  206.   get_dos_version();
  207.   get_win_version();
  208.   get_dv_version();
  209.   if (multitasker < 2)
  210.     if (get_nb_version())
  211.       multitasker = MT_NB;
  212. }
  213.  
  214. unsigned char *trim(char *str)
  215. {
  216.   int i;
  217.  
  218.   if (str == NULL)
  219.     return (str);
  220.   for (i = strlen(str) - 1; (i >= 0) && isspace(str[i]); str[i--] = '\0');
  221.   while (isspace(str[0]))
  222.     strcpy(str, str + 1);
  223.   return (str);
  224. }
  225.  
  226. unsigned char *strrep(char *str, char old, char New)
  227. {
  228.   int i;
  229.  
  230.   for (i = 0; str[i]; i++)
  231.     if (str[i] == old)
  232.       str[i] = New;
  233.   return (str);
  234. }
  235.  
  236. int getnumbers(unsigned char *ascii, unsigned int *d1, unsigned long *d2)
  237. {
  238.   char *p;
  239.  
  240.   /* it must return a number after the white space */
  241.   if ((p = (char *) _fstrchr((char *) ascii, ' ')) == NULL)
  242.     return 0;
  243.   /* skip space */
  244.   while (*p == ' ')
  245.     p++;
  246.   *d1 = atoi(p);
  247.   if ((p = (char *) _fstrchr(p, ' ')) == NULL)
  248.     return 1;
  249.   /* skip space */
  250.   while (*p == ' ')
  251.     p++;
  252.   *d2 = atol(p);
  253.   return 2;
  254. }
  255.  
  256. char *fix_quoted_commas(char *string)
  257. {
  258.   char *ptr;
  259.   int quoted = 0;
  260.  
  261.   ptr = string;
  262.   if (ptr) {
  263.     while (*ptr != 0) {
  264.       if (*ptr == '\"')
  265.         quoted = (!quoted);
  266.       if (*ptr == ',' && quoted)
  267.         *ptr = '│';
  268.       ptr = &ptr[1];
  269.     }
  270.   }
  271.   return (string);
  272. }
  273.  
  274. long sh_lseek(int handle, long offset, int fromwhere)
  275. {
  276.   if (handle == -1) {
  277.     return (-1L);
  278.   }
  279.   return (lseek(handle, offset, fromwhere));
  280. }
  281.  
  282. FILE *fsh_open(char *path, char *fmode)
  283. {
  284.   FILE *f;
  285.   int count, share, md, fd;
  286.   char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  287.  
  288.   share = SH_DENYWR;
  289.   md = 0;
  290.   if (((char *) _fstrchr(fmode, 'w')) != NULL) {
  291.     share = SH_DENYRD;
  292.     md = O_RDWR | O_CREAT | O_TRUNC;
  293.   } else
  294.     if (((char *) _fstrchr(fmode, 'a')) != NULL) {
  295.     share = SH_DENYRD;
  296.     md = O_RDWR | O_CREAT;
  297.   } else {
  298.     md = O_RDONLY;
  299.   }
  300.   if (((char *) _fstrchr(fmode, 'b')) != NULL) {
  301.     md |= O_BINARY;
  302.   }
  303.   if (((char *) _fstrchr(fmode, '+')) != NULL) {
  304.     md &= ~O_RDONLY;
  305.     md |= O_RDWR;
  306.     share = SH_DENYRD;
  307.   }
  308.   fd = open(path, md | share, S_IREAD | S_IWRITE);
  309.   if (fd < 0) {
  310.     count = 1;
  311.     fnsplit(path, drive, dir, file, ext);
  312.     if ((access(path, 0)) != -1) {
  313.       delay(WAIT_TIME);
  314.       fd = open(path, md | share, S_IREAD | S_IWRITE);
  315.       while (((fd < 0) && (errno == EACCES)) && (count < TRIES)) {
  316.         delay(WAIT_TIME);
  317.         count++;
  318.         fd = open(path, md | share, S_IREAD | S_IWRITE);
  319.       }
  320.     }
  321.   }
  322.   if (fd > 0) {
  323.     if (((char *) _fstrchr(fmode, 'a')) != NULL)
  324.       sh_lseek(fd, 0L, SEEK_END);
  325.     f = fdopen(fd, fmode);
  326.     if (!f) {
  327.       close(fd);
  328.     }
  329.   } else
  330.     f = 0;
  331.   return (f);
  332. }
  333.  
  334. Mail_Socket *smtp_start(char *host, char *dom)
  335. {
  336.   longword h;
  337.   Mail_Socket *SMTP_sock = NULL;
  338.  
  339.   if (!SMTP_Err_Msg)
  340.     SMTP_Err_Msg = _SMTP_err_msg_buf;
  341.   if (!WatTCP_initialized) {
  342.     sock_init();
  343.     WatTCP_initialized = 1;
  344.   }
  345.   if ((h = resolve(host)) == 0L) {
  346.     if ((h = resolve(host)) == 0L) {
  347.       SMTP_Err_Cond = SMTP_FAILED;
  348.       if (DEBUG) {
  349.         sprintf(SMTP_Err_Msg, "Cannot resolve host %s", host);
  350.         output("\nSMTP> %s", SMTP_Err_Msg);
  351.       }
  352.       return NULL;
  353.     }
  354.   }
  355.   if ((SMTP_sock = (Mail_Socket *) farmalloc(sizeof(Mail_Socket))) == NULL) {
  356.     output("\n ■ Insufficient memory to create socket... aborting");
  357.     exit(EXIT_FAILURE);
  358.   }
  359.   if ((SMTP_sock->sock = (tcp_Socket *) farmalloc(sizeof(tcp_Socket))) == NULL) {
  360.     output("\n ■ Insufficient memory to create socket... aborting");
  361.     farfree(SMTP_sock);
  362.     exit(EXIT_FAILURE);
  363.   }
  364.   if (!tcp_open(SMTP_sock->sock, 0, h, SMTP_PORT, NULL)) {
  365.     SMTP_Err_Cond = SMTP_FAILED;
  366.     if (DEBUG) {
  367.       sprintf(SMTP_Err_Msg, "Unable to connect to %s", host);
  368.       output("\nSMTP> %s", SMTP_Err_Msg);
  369.     }
  370.     farfree(SMTP_sock);
  371.     return NULL;
  372.   }
  373.   sock_mode(SMTP_sock->sock, TCP_MODE_ASCII);
  374.   sock_wait_established(SMTP_sock->sock, SOCK_DELAY, NULL, &SMTP_stat);
  375.   while (sock_tbused(SMTP_sock->sock) > 0) {
  376.     SOCK_GETS(SMTP);
  377.     SMTP_FAIL_ON(SMTP_OOPS,);
  378.   }
  379.   sock_printf(SMTP_sock->sock, "HELO %s", dom);
  380.   sock_wait_input(SMTP_sock->sock, SOCK_DELAY, NULL, &SMTP_stat);
  381.   while (sock_tbused(SMTP_sock->sock) > 0) {
  382.     SOCK_GETS(SMTP);
  383.     SMTP_FAIL_ON(SMTP_OOPS,);
  384.     SMTP_FAIL_ON(SMTP_SYNTAX,);
  385.     SMTP_FAIL_ON(SMTP_PARAM,);
  386.     SMTP_FAIL_ON(SMTP_BAD_PARM,);
  387.   }
  388.   return (SMTP_sock);
  389.   SOCK_READ_ERR(SMTP);
  390.   return NULL;
  391. }
  392.  
  393. char *smtp_parse_from_line(FILE * f)
  394. {
  395.   int found = 0, done = 0;
  396.  
  397.   rewind(f);
  398.   while (!feof(f) && !done) {
  399.     fgets(_temp_buffer, sizeof(_temp_buffer), f);
  400.     if (*_temp_buffer == '\n')
  401.       done = 1;
  402.     else
  403.       if (strncmpi(_temp_buffer, "from:", 5) == 0 &&
  404.           _fstrchr(_temp_buffer, '@') != 0)
  405.       found = 1, done = 1;
  406.   }
  407.   if (found)
  408.     return (trim(strdup(&_temp_buffer[5])));
  409.   return 0;
  410. }
  411.  
  412. char **smtp_parse_to_line(FILE * f)
  413. {
  414.   int done = 0, current = 0;
  415.   char **list = NULL;
  416.   char *addr;
  417.  
  418.   rewind(f);
  419.   while (!feof(f) && !done) {
  420.     fgets(_temp_buffer, sizeof(_temp_buffer), f);
  421.     if (*_temp_buffer == '\n')
  422.       done = 1;
  423.     else
  424.       if ((strncmpi(_temp_buffer, "to:", 3) == 0) ||
  425.           (strncmpi(_temp_buffer, "cc:", 3) == 0) ||
  426.           (strncmpi(_temp_buffer, "bcc:", 4) == 0)) {
  427.       fix_quoted_commas(_temp_buffer);
  428.       addr = strtok(_temp_buffer, ":");
  429.       while ((addr = strtok(NULL, ",\n")) != NULL) {
  430.         strrep(addr, '│', ',');
  431.         list = (char **) realloc(list, sizeof(char *) * ((current) + 2));
  432.         list[current] = strdup(addr);
  433.         list[current + 1] = NULL;
  434.         current++;
  435.       }
  436.       }
  437.   }
  438.   return (list);
  439. }
  440.  
  441. int smtp_send_MAIL_FROM_line(Mail_Socket * SMTP_sock, FILE * f)
  442. {
  443.   char *from;
  444.  
  445.   from = smtp_parse_from_line(f);
  446.   if (from) {
  447.     if (DEBUG)
  448.       output("\nSMTP> Mail From:<%s>\n", from);
  449.     sock_printf(SMTP_sock->sock, "MAIL FROM:<%s>", from);
  450.     free(from);
  451.     while (sock_tbused(SMTP_sock->sock) > 0) {
  452.       SOCK_GETS(SMTP);
  453.       SMTP_FAIL_ON(SMTP_OOPS,);
  454.     }
  455.   }
  456.   return 1;
  457.   SOCK_READ_ERR(SMTP);
  458.   return 0;
  459. }
  460.  
  461. #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);
  462.  
  463. int smtp_send_RCPT_TO_line(Mail_Socket * SMTP_sock, FILE * f)
  464. {
  465.   char **to_list;
  466.   int i;
  467.  
  468.   to_list = smtp_parse_to_line(f);
  469.   for (i = 0; to_list[i] != NULL; i++) {
  470.     if (DEBUG)
  471.       output("SMTP> Rcpt To:<%s>\n", to_list[i]);
  472.     sock_printf(SMTP_sock->sock, "RCPT TO:<%s>", to_list[i]);
  473.     while (sock_tbused(SMTP_sock->sock) > 0) {
  474.       SOCK_GETS(SMTP);
  475.       SMTP_FAIL_ON(SMTP_OOPS, FREE_ALL);
  476.       SMTP_RESET_ON(SMTP_SYNTAX, FREE_ALL);
  477.       SMTP_RESET_ON(SMTP_PARAM, FREE_ALL);
  478.       SMTP_RESET_ON(SMTP_BAD_SEQ, FREE_ALL);
  479.     }
  480.   }
  481.   FREE_ALL;
  482.   return 1;
  483.   SOCK_READ_ERR(SMTP);
  484.   return 0;
  485. }
  486.  
  487. void go_back(int from, int to)
  488. {
  489.   int i;
  490.  
  491.   for (i = from; i > to; i--)
  492.     output("\b \b");
  493. }
  494.  
  495. #undef FREE_ALL
  496.  
  497. int smtp_sendf(Mail_Socket * SMTP_sock, FILE * f)
  498. {
  499.   int in_header = 1, in_bcc = 0, pos;
  500.   long nbytes, obytes, rbytes;
  501.   char *temp, ch;
  502.  
  503.   if (smtp_send_MAIL_FROM_line(SMTP_sock, f) == 0)
  504.     return 0;
  505.   if (smtp_send_RCPT_TO_line(SMTP_sock, f) == 0)
  506.     return 0;
  507.   fseek(f, 0L, SEEK_END);
  508.   obytes = ftell(f);
  509.   rewind(f);
  510.   sock_puts(SMTP_sock->sock, "DATA");
  511.   sock_wait_input(SMTP_sock->sock, SOCK_DELAY, NULL, &SMTP_stat);
  512.   while (sock_tbused(SMTP_sock->sock) > 0) {
  513.     SOCK_GETS(SMTP);
  514.     if (DEBUG)
  515.       output("\nSMTP> %s", _temp_buffer);
  516.     SMTP_FAIL_ON(SMTP_OOPS,);
  517.     SMTP_RESET_ON(SMTP_BAD_SEQ,)
  518.         SMTP_RESET_ON(SMTP_SYNTAX,);
  519.     SMTP_RESET_ON(SMTP_PARAM,);
  520.     SMTP_RESET_ON(SMTP_COM_NI,);
  521.     SMTP_RESET_ON(SMTP_FAILED,);
  522.     SMTP_RESET_ON(SMTP_ERROR,);
  523.   }
  524.   nbytes = 0L;
  525.   rbytes = 1024L;
  526.   output(" - ");
  527.   pos = wherex();
  528.   while (!feof(f)) {
  529.     if (kbhit()) {
  530.       ch = (getch());
  531.       switch (ch) {
  532.         case 27:
  533.         case 32:
  534.           go_back(wherex(), pos);
  535.           return -1;
  536.         default:
  537.           break;
  538.       }
  539.     }
  540.     fgets(_temp_buffer, sizeof(_temp_buffer), f);
  541.     strrep(_temp_buffer, '\n', '\0');
  542.     strrep(_temp_buffer, '\r', '\0');
  543.     temp = trim(strdup(_temp_buffer));
  544.     if (strlen(temp) == 0)
  545.       in_header = 0;
  546.     if (temp)
  547.       free(temp);
  548.     if (in_header && !in_bcc && strncmpi(_temp_buffer, "bcc:", 4) == 0) {
  549.       in_bcc = 1;
  550.       continue;
  551.     }
  552.     if (in_bcc)
  553.       in_bcc = isspace(*_temp_buffer);
  554.     if (in_bcc)
  555.       continue;
  556.     if (*_temp_buffer == '.') {
  557.       movmem(_temp_buffer, _temp_buffer + 1, sizeof(_temp_buffer) - 1);
  558.       *_temp_buffer = '.';
  559.       if (DEBUG)
  560.         output("\nSMTP> %s", _temp_buffer);
  561.     }
  562.     nbytes += sock_puts(SMTP_sock->sock, _temp_buffer);
  563.     nbytes += 2;
  564.     if (nbytes > rbytes) {
  565.       go_back(wherex(), pos);
  566.       output("%ld/%ld", nbytes, obytes);
  567.       rbytes += 512L;
  568.     }
  569.   }
  570.   sock_puts(SMTP_sock->sock, ".");
  571.   sock_wait_input(SMTP_sock->sock, SOCK_DELAY, NULL, &SMTP_stat);
  572.   while (sock_tbused(SMTP_sock->sock) > 0) {
  573.     SOCK_GETS(SMTP);
  574.     SMTP_FAIL_ON(SMTP_OOPS,);
  575.     SMTP_RESET_ON(SMTP_ERROR,);
  576.     SMTP_RESET_ON(SMTP_SQUEEZED,);
  577.     SMTP_RESET_ON(SMTP_FULL,);
  578.     SMTP_RESET_ON(SMTP_FAILED,);
  579.   }
  580.   go_back(wherex(), pos);
  581.   return 1;
  582.   SOCK_READ_ERR(SMTP);
  583.   go_back(wherex(), pos);
  584.   return 0;
  585. }
  586.  
  587. int smtp_shutdown(Mail_Socket * SMTP_sock)
  588. {
  589.   if (SMTP_sock->sock) {
  590.     sock_puts(SMTP_sock->sock, "QUIT");
  591.     sock_close(SMTP_sock->sock);
  592.     return 1;
  593.   }
  594.   return 0;
  595. }
  596.  
  597.  
  598. Mail_Socket *pop_init(char *host)
  599. {
  600.   longword h;
  601.   Mail_Socket *POP_sock = NULL;
  602.  
  603.   if (!POP_Err_Msg)
  604.     POP_Err_Msg = _POP_err_msg_buf;
  605.  
  606.   if (!WatTCP_initialized) {
  607.     sock_init();
  608.     WatTCP_initialized = 1;
  609.   }
  610.   if (!(h = resolve(host))) {
  611.     output("\n ■ Cannot resolve host %s.", host);
  612.     POP_Err_Cond = POP_BAD_HOST;
  613.     if (DEBUG) {
  614.       sprintf(POP_Err_Msg, "Cannot resolve host %s", host);
  615.       output("\n%s", POP_Err_Msg);
  616.     }
  617.     return NULL;
  618.   }
  619.   if ((POP_sock = (Mail_Socket *) farmalloc(sizeof(Mail_Socket))) == NULL) {
  620.     output("\n ■ Insufficient memory to create socket... aborting.");
  621.     exit(EXIT_FAILURE);
  622.   }
  623.   if ((POP_sock->sock = (tcp_Socket *) farmalloc(sizeof(tcp_Socket))) == NULL) {
  624.     output("\n ■ Insufficient memory to create socket... aborting.");
  625.     farfree(POP_sock);
  626.     exit(EXIT_FAILURE);
  627.   }
  628.   if (!tcp_open(POP_sock->sock, 0, h, POP_PORT, NULL)) {
  629.     output("\n ■ Unable to connect to host %s.", host);
  630.     POP_Err_Cond = POP_BAD_HOST;
  631.     if (DEBUG) {
  632.       sprintf(POP_Err_Msg, "Unable to connect to host %s", host);
  633.       output("\n%s", POP_Err_Msg);
  634.     }
  635.     return NULL;
  636.   }
  637.   sock_mode(POP_sock->sock, TCP_MODE_ASCII);
  638.   sock_wait_established(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  639.   sock_wait_input(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  640.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  641.   if (DEBUG)
  642.     output("\nPOP> %s", _temp_buffer);
  643.   if (*_temp_buffer != '+') {
  644.     output("\n ■ Host %s is unavailable.", host);
  645.     POP_Err_Cond = POP_HOST_UNAVAILABLE;
  646.     if (DEBUG)
  647.       sprintf(POP_Err_Msg, "Host %s unavailable", host);
  648.     if (POP_sock->sock) {
  649.       sock_puts(POP_sock->sock, "QUIT");
  650.       sock_close(POP_sock->sock);
  651.     }
  652.     return NULL;
  653.   }
  654.   return (POP_sock);
  655.   SOCK_READ_ERR(POP);
  656.   return NULL;
  657. }
  658.  
  659. int pop_login(Mail_Socket * POP_sock, char *userid, char *password)
  660. {
  661.   sprintf(_temp_buffer, "USER %s", userid);
  662.   sock_puts(POP_sock->sock, _temp_buffer);
  663.   sock_wait_input(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  664.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  665.   if (DEBUG)
  666.     output("\nPOP> %s", _temp_buffer);
  667.   if (*_temp_buffer != '+') {
  668.     output("\n ■ Host reports mailbox \"%s\" does not exist!", userid);
  669.     POP_Err_Cond = POP_BAD_MBOX;
  670.     if (DEBUG)
  671.       sprintf(POP_Err_Msg, "Mailbox %s does not exist", userid);
  672.     return 0;
  673.   }
  674.   sprintf(_temp_buffer, "PASS %s", password);
  675.   sock_puts(POP_sock->sock, _temp_buffer);
  676.   sock_wait_input(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  677.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  678.   if (DEBUG)
  679.     output("\nPOP> %s", _temp_buffer);
  680.   if (*_temp_buffer != '+') {
  681.     output("\n ■ Host reports \"%s\" is incorrect password or account is locked.", password);
  682.     POP_Err_Cond = POP_BAD_PASS;
  683.     if (DEBUG)
  684.       sprintf(POP_Err_Msg, "Password incorrect");
  685.     return 0;
  686.   }
  687.   return 1;
  688.   SOCK_READ_ERR(POP);
  689.   return 0;
  690. }
  691.  
  692. int pop_status(Mail_Socket * POP_sock, unsigned int *count, unsigned long *totallength)
  693. {
  694.   sock_puts(POP_sock->sock, "STAT");
  695.   sock_wait_input(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  696.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  697.   if (DEBUG)
  698.     output("\nPOP> %s", _temp_buffer);
  699.   if ((*_temp_buffer != '+') ||
  700.       (getnumbers(_temp_buffer, count, totallength) < 2)) {
  701.     POP_Err_Cond = POP_UNKNOWN;
  702.     if (DEBUG) {
  703.       sprintf(POP_Err_Msg, "Unknown POP error");
  704.       output("\n%s", POP_Err_Msg);
  705.     }
  706.     return 0;
  707.   }
  708.   return 1;
  709.   SOCK_READ_ERR(POP);
  710.   return 0;
  711. }
  712.  
  713. long pop_length(Mail_Socket * POP_sock, unsigned int msg_num, unsigned long *size)
  714. {
  715.   unsigned int dummy;
  716.  
  717.   sprintf(_temp_buffer, "LIST %u", msg_num);
  718.   sock_puts(POP_sock->sock, _temp_buffer);
  719.   sock_wait_input(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  720.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  721.   if (DEBUG)
  722.     output("\nPOP> %s", _temp_buffer);
  723.   if ((*_temp_buffer != '+') ||
  724.       (getnumbers(_temp_buffer, &dummy, size) < 2)) {
  725.     POP_Err_Cond = POP_NOT_MSG;
  726.     if (DEBUG) {
  727.       sprintf(POP_Err_Msg, "No message #%u", msg_num);
  728.       output("\n%s", POP_Err_Msg);
  729.     }
  730.     return 0;
  731.   }
  732.   return (*size);
  733.   SOCK_READ_ERR(POP);
  734.   return 0;
  735. }
  736.  
  737. char *stristr(char *String, char *Pattern)
  738. {
  739.   char *pptr, *sptr, *start;
  740.   unsigned int slen, plen;
  741.  
  742.   for (start = String, pptr = Pattern, slen = strlen(String),
  743.        plen = strlen(Pattern); slen >= plen; start++, slen--) {
  744.     while (toupper(*start) != toupper(*Pattern)) {
  745.       start++;
  746.       slen--;
  747.       if (slen < plen)
  748.         return (NULL);
  749.     }
  750.     sptr = start;
  751.     pptr = Pattern;
  752.     while (toupper(*sptr) == toupper(*pptr)) {
  753.       sptr++;
  754.       pptr++;
  755.       if ('\0' == *pptr)
  756.         return (start);
  757.     }
  758.   }
  759.   return (NULL);
  760. }
  761.  
  762. int pop_top(Mail_Socket * POP_sock, unsigned int msg_num)
  763. {
  764.   int okpkt;
  765.  
  766.   sprintf(_temp_buffer, "TOP %u 50", msg_num);
  767. /*  sock_printf(POP_sock->sock, "TOP %u 50\n", msg_num); */
  768.   sock_puts(POP_sock->sock, _temp_buffer);
  769.   sock_wait_input(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  770.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  771.   if (DEBUG)
  772.     output("\nPOP> %s", _temp_buffer);
  773.   if (*_temp_buffer != '+') {
  774.     POP_Err_Cond = POP_NOT_MSG;
  775.     if (DEBUG) {
  776.       sprintf(POP_Err_Msg, "No message #%u.", msg_num);
  777.       output("\n%s", POP_Err_Msg);
  778.     }
  779.     return -1;
  780.   }
  781.   okpkt = 0;
  782.   while (1) {
  783.     sock_wait_input(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  784.     sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  785.     if (_temp_buffer[0] == '.' && _temp_buffer[1] == 0)
  786.       break;
  787.     if ((strnicmp(_temp_buffer, "begin 6", 7) == 0) &&
  788.         (stristr(_temp_buffer, "WINMAIL") == NULL)) {
  789.       if (okpkt != 4)
  790.         okpkt = 1;
  791.       if ((stristr(_temp_buffer, ".ZIP") != NULL) ||
  792.           (stristr(_temp_buffer, ".ARJ") != NULL) ||
  793.           (stristr(_temp_buffer, ".LZH") != NULL))
  794.         okpkt = 2;
  795.       if ((stristr(_temp_buffer, ".GIF") != NULL) ||
  796.           (stristr(_temp_buffer, ".JPG") != NULL))
  797.         okpkt = 3;
  798.     }
  799.     if (strnicmp(_temp_buffer, "from:", 5) == 0) {
  800.       if ((stristr(_temp_buffer, "mailer-daemon") != NULL) ||
  801.           (stristr(_temp_buffer, "mail delivery") != NULL) ||
  802.           (stristr(_temp_buffer, "administrator") != NULL) ||
  803.           (stristr(_temp_buffer, from_user) != NULL))
  804.         okpkt = 4;
  805.       else
  806.         strncpy(pktowner, &_temp_buffer[6], 20);
  807.     }
  808.   }
  809.   return okpkt;
  810.   SOCK_READ_ERR(POP);
  811.   return -1;
  812. }
  813.  
  814. int pop_getf(Mail_Socket * POP_sock, char *fn, unsigned int msg_num)
  815. {
  816.   unsigned long size;
  817.   long nbytes, rbytes;
  818.   int i, pos, ctld;
  819.   FILE *fp;
  820.  
  821.   if (!pop_length(POP_sock, msg_num, &size)) {
  822.     output("\n ■ Unable to retrieve message number %d", msg_num);
  823.     return 0;
  824.   }
  825.   sprintf(_temp_buffer, "RETR %u", msg_num);
  826.   sock_puts(POP_sock->sock, _temp_buffer);
  827.   sock_wait_input(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  828.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  829.   if (DEBUG)
  830.     output("\nPOP> %s", _temp_buffer);
  831.   if (*_temp_buffer != '+') {
  832.     POP_Err_Cond = POP_NOT_MSG;
  833.     if (DEBUG) {
  834.       sprintf(POP_Err_Msg, "No message #%u", msg_num);
  835.       output("\n%s", POP_Err_Msg);
  836.     }
  837.     return 0;
  838.   }
  839.   nbytes = 0L;
  840.   rbytes = 1024L;
  841.   output(" - ");
  842.   pos = wherex();
  843.   if ((fp = fsh_open(fn, "w")) == NULL) {
  844.     output("\n ■ Unable to create %s... aborting!", fn);
  845.     return 0;
  846.   }
  847.   ctld = 1;
  848.   while (1) {
  849.     sock_wait_input(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  850.     sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  851.     if ((ctld == 1) || (ctld == 2)) {
  852.       if ((*_temp_buffer == '\r') || (*_temp_buffer == '\n') || (*_temp_buffer == 0))
  853.         ctld = 2;
  854.       else if (ctld == 2) {
  855.         for (i = 0; (i < strlen(_temp_buffer)) && (ctld == 2); i++)
  856.           if (_temp_buffer[i] == ':')
  857.             ctld = 1;
  858.           else if (_temp_buffer[i] == ' ')
  859.             ctld = 0;
  860.         if (ctld == 2)
  861.           ctld = 0;
  862.         }
  863.     }
  864.     if ((strnicmp(_temp_buffer, "begin ", 6) == 0) &&
  865.         (stristr(_temp_buffer, "WINMAIL") != NULL))
  866.       ctld = 3;
  867.     if ((ctld == 3) && (strnicmp(_temp_buffer, "end", 3) == 0))
  868.       ctld = 0;
  869.     if (_temp_buffer[0] == '.' && _temp_buffer[1] == 0)
  870.       break;
  871.     if (EOF == (nbytes += fprintf(fp, "%s%s\n", ctld ? "0R" : "", _temp_buffer))) {
  872.       if (fp != NULL)
  873.         fclose(fp);
  874.       return 0;
  875.     }
  876.     if (nbytes > rbytes) {
  877.       go_back(wherex(), pos);
  878.       output("%ld/%ld", nbytes, size);
  879.       rbytes += 512L;
  880.     }
  881.   }
  882.   if (fp != NULL)
  883.     fclose(fp);
  884.   go_back(wherex(), pos);
  885.   output("message received!");
  886.   return 1;
  887.   SOCK_READ_ERR(POP);
  888.   return 0;
  889. }
  890.  
  891. int pop_delete(Mail_Socket * POP_sock, unsigned int msg_num)
  892. {
  893.   sprintf(_temp_buffer, "DELE %u", msg_num);
  894.   sock_puts(POP_sock->sock, _temp_buffer);
  895.   sock_wait_input(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  896.   sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  897.   if (DEBUG)
  898.     output("\nPOP> %s", _temp_buffer);
  899.   if (*_temp_buffer != '+') {
  900.     POP_Err_Cond = POP_NOT_MSG;
  901.     if (DEBUG) {
  902.       sprintf(POP_Err_Msg, "No message #%u", msg_num);
  903.       output("\n%s", POP_Err_Msg);
  904.     }
  905.     return 2;
  906.   }
  907.   return 1;
  908.   SOCK_READ_ERR(POP);
  909.   return 0;
  910. }
  911.  
  912.  
  913. int pop_shutdown(Mail_Socket * POP_sock)
  914. {
  915.   if (POP_sock->sock) {
  916.     sock_puts(POP_sock->sock, "QUIT");
  917.     sock_wait_input(POP_sock->sock, SOCK_DELAY, NULL, &POP_stat);
  918.     sock_gets(POP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  919.     if (*_temp_buffer != '+') {
  920.       POP_Err_Cond = POP_UNKNOWN;
  921.       if (DEBUG) {
  922.         sprintf(POP_Err_Msg, "Unable to update mailbox!");
  923.         output("\n%s", POP_Err_Msg);
  924.     }
  925.       return 0;
  926.     } else
  927.       output("\n ■ Closed and updated mailbox on %s.", POPHOST);
  928.     sock_close(POP_sock->sock);
  929.     return 1;
  930.   }
  931. sock_err:
  932.   free_Mail_Socket(POP_sock);
  933.   return 0;
  934. }
  935.  
  936. int pop_get_nextf(Mail_Socket * POP_sock, char *fn, int msgnum)
  937. {
  938.   if (!pop_getf(POP_sock, fn, msgnum))
  939.     return 0;
  940.   return (pop_delete(POP_sock, msgnum));
  941. }
  942.  
  943. int exist(char *s)
  944. {
  945.   int i;
  946.   struct ffblk ff;
  947.  
  948.   i = findfirst(s, &ff, FA_HIDDEN);
  949.   if (i)
  950.     return 0;
  951.   else
  952.     return 1;
  953. }
  954.  
  955. void main(int argc, char *argv[])
  956. {
  957.   unsigned int count;
  958.   unsigned long size;
  959.   int i, i1, okpkt;
  960.   char temp[181], s[21], s1[21];
  961.   FILE *fp;
  962.   Mail_Socket *pop_sock = NULL;
  963.   Mail_Socket *smtp_sock = NULL;
  964.  
  965.   detect_multitask();
  966.  
  967.   if (strncmpi(argv[1], "-send", strlen(argv[1])) == 0) {
  968.     if (argc < 5)
  969.       exit(EXIT_FAILURE);
  970.     output("- %s - [Space] skips", argv[2]);
  971.     if (argc == 6)
  972.       DEBUG = atoi(argv[5]);
  973.     if ((smtp_sock = smtp_start(argv[2], argv[3])) != NULL) {
  974.       if ((fp = fsh_open(argv[4], "r")) != NULL) {
  975.         switch (smtp_sendf(smtp_sock, fp)) {
  976.           case 1:
  977.             output("message sent!");
  978.             smtp_shutdown(smtp_sock);
  979.             if (fp != NULL)
  980.               fclose(fp);
  981.             exit(EXIT_SUCCESS);
  982.           case 0:
  983.             output(" - SMTP failure!");
  984.             smtp_shutdown(smtp_sock);
  985.             if (fp != NULL)
  986.               fclose(fp);
  987.             break;
  988.           case -1:
  989.             output("SMTP aborted!");
  990.             smtp_shutdown(smtp_sock);
  991.             if (fp != NULL)
  992.               fclose(fp);
  993.             break;
  994.         }
  995.       } else {
  996.         smtp_shutdown(smtp_sock);
  997.         output("\n ■ Error accessing file %s.", argv[4]);
  998.       }
  999.     } else
  1000.       output("\n ■ SMTP socket connect failed.");
  1001.   } else if (strncmpi(argv[1], "-receive", strlen(argv[1])) == 0) {
  1002.     if (argc < 8) {
  1003.       output("Received: ");
  1004.       for (i = 0; i < argc; i++)
  1005.         output("%s ", argv[i]);
  1006.       exit(EXIT_FAILURE);
  1007.     }
  1008.     if (argc == 9)
  1009.       DEBUG = atoi(argv[8]);
  1010.     sprintf(from_user, "%s@%s", argv[3], argv[7]);
  1011.     strcpy(POPHOST, argv[2]);
  1012.     if ((pop_sock = pop_init(argv[2])) != NULL) {
  1013.       if (pop_login(pop_sock, argv[3], argv[4])) {
  1014.         if (pop_status(pop_sock, &count, &size)) {
  1015.           okpkt = 0;
  1016.           output("%u message%s (%ldK).\n", count, count == 1 ? "" : "s", ((size + 1023)/ 1024));
  1017.           i1 = 1;
  1018.           while (i1 <= count) {
  1019.             okpkt = -1;
  1020.             okpkt = pop_top(pop_sock, i1);
  1021.             switch (okpkt) {
  1022.               case -1:
  1023.                 output("\n ■ Error accessing message %d", i1);
  1024.                 break;
  1025.               case 0:
  1026.                 i = atoi(argv[6]);
  1027.                 if (i == 0)
  1028.                   output("\n ■ Non-network message %d left on server.", i1);
  1029.                 else {
  1030.                   i = 0;
  1031.                   sprintf(temp, "%sUNK-%03d.MSG", argv[5], i);
  1032.                   while (exist(temp))
  1033.                     sprintf(temp, "%sUNK-%03d.MSG", argv[5], ++i);
  1034.                   fnsplit(temp, NULL, NULL, s, s1);
  1035.                   go_back(wherex(), 0);
  1036.                   output(" ■ RCV : %3.3d - %-20s - %s%s", i1, "non-network packet", s, s1);
  1037.                   switch (pop_get_nextf(pop_sock, temp, i1)) {
  1038.                     case 0:
  1039.                       output("\n ■ Unable to retrieve message %d.", i1);
  1040.                       unlink(temp);
  1041.                       break;
  1042.                     case 1:
  1043.                       break;
  1044.                     case 2:
  1045.                       output("\n ■ Unable to delete message %d from host!", i1);
  1046.                       break;
  1047.                   }
  1048.                 }
  1049.                 break;
  1050.               case 1:
  1051.                 i = 0;
  1052.                 sprintf(temp, "%sPKT-%03d.UUE", argv[5], i);
  1053.                 while (exist(temp))
  1054.                   sprintf(temp, "%sPKT-%03d.UUE", argv[5], ++i);
  1055.                 fnsplit(temp, NULL, NULL, s, s1);
  1056.                 go_back(wherex(), 0);
  1057.                 output(" ■ RCV : %3.3d - %-20s - %s%s", i1, pktowner, s, s1);
  1058.                 switch (pop_get_nextf(pop_sock, temp, i1)) {
  1059.                   case 0:
  1060.                     output("\n ■ Unable to retrieve message %d.", i1);
  1061.                     unlink(temp);
  1062.                     break;
  1063.                   case 1:
  1064.                     break;
  1065.                   case 2:
  1066.                     output("\n ■ Unable to delete message %d on host!", i1);
  1067.                     break;
  1068.                 }
  1069.                 break;
  1070.               case 2:
  1071.                 i = 0;
  1072.                 sprintf(temp, "%sARC-%03d.UUE", argv[5], i);
  1073.                 while (exist(temp))
  1074.                   sprintf(temp, "%sARC-%03d.UUE", argv[5], ++i);
  1075.                 fnsplit(temp, NULL, NULL, s, s1);
  1076.                 go_back(wherex(), 0);
  1077.                 output(" ■ RCV : %3.3d - %-20s - %s%s", i1, "archived file", s, s1);
  1078.                 switch (pop_get_nextf(pop_sock, temp, i1)) {
  1079.                   case 0:
  1080.                     output("\n ■ Unable to retrieve message %d.", i1);
  1081.                     unlink(temp);
  1082.                     break;
  1083.                   case 1:
  1084.                     break;
  1085.                   case 2:
  1086.                     output("\n ■ Unable to delete message %d on host!", i1);
  1087.                     break;
  1088.                 }
  1089.                 break;
  1090.               case 3:
  1091.                 i = 0;
  1092.                 sprintf(temp, "%sGIF-%03d.UUE", argv[5], i);
  1093.                 while (exist(temp))
  1094.                   sprintf(temp, "%sGIF-%03d.UUE", argv[5], ++i);
  1095.                 fnsplit(temp, NULL, NULL, s, s1);
  1096.                 go_back(wherex(), 0);
  1097.                 output(" ■ RCV : %3.3d - %-20s - %s%s", i1, "graphic/image file", s, s1);
  1098.                 switch (pop_get_nextf(pop_sock, temp, i1)) {
  1099.                   case 0:
  1100.                     output("\n ■ Unable to retrieve message %d.", i1);
  1101.                     unlink(temp);
  1102.                     break;
  1103.                   case 1:
  1104.                     break;
  1105.                   case 2:
  1106.                     output("\n ■ Unable to delete message %d from host!", i1);
  1107.                     break;
  1108.                 }
  1109.                 break;
  1110.               case 4:
  1111.                 i = 0;
  1112.                 sprintf(temp, "%sBAD-%03d.UUE", argv[5], i);
  1113.                 while (exist(temp))
  1114.                   sprintf(temp, "%sBAD-%03d.UUE", argv[5], ++i);
  1115.                 fnsplit(temp, NULL, NULL, s, s1);
  1116.                 go_back(wherex(), 0);
  1117.                 output(" ■ RCV : %3.3d - %-20s - %s%s", i1, "mailer-daemon", s, s1);
  1118.                 switch (pop_get_nextf(pop_sock, temp, i1)) {
  1119.                   case 0:
  1120.                     output("\n ■ Unable to retrieve message %d.", i1);
  1121.                     unlink(temp);
  1122.                     break;
  1123.                   case 1:
  1124.                     break;
  1125.                   case 2:
  1126.                     output("\n ■ Unable to delete message %d from host!", i1);
  1127.                     break;
  1128.                 }
  1129.                 break;
  1130.             }
  1131.             i1++;
  1132.           }
  1133.           backline();
  1134.           output("\r ■ Mailbox scan of %d message%s completed.", count,
  1135.             count == 1 ? "" : "s");
  1136.         } else
  1137.           output("\n ■ Unknown POP access error - try again later.");
  1138.         pop_shutdown(pop_sock);
  1139.         fcloseall();
  1140.         exit(EXIT_SUCCESS);
  1141.       } else {
  1142.         output("\n ■ Unable to log into POP server!");
  1143.         pop_shutdown(pop_sock);
  1144.         fcloseall();
  1145.       }
  1146.     } else
  1147.       output("\n ■ POP socket connect failed.");
  1148.     }
  1149.   exit(EXIT_FAILURE);
  1150. }
  1151.