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