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