home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / PPPBCKP / SRC15B17.ZIP / POP.C < prev    next >
Text File  |  1997-03-22  |  31KB  |  989 lines

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