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