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