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