home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / PPPBCKP / SRC15B50.ZIP / POP.C < prev    next >
Text File  |  1997-10-11  |  33KB  |  1,106 lines

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