home *** CD-ROM | disk | FTP | other *** search
/ The Best of Windows 95.com 1996 September / WIN95_09962.iso / command / BLAT14.ZIP / BLAT.CPP < prev    next >
C/C++ Source or Header  |  1995-10-25  |  26KB  |  992 lines

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <iostream.h>
  5. /* generic socket DLL support */
  6. #include "gensock.h"
  7.  
  8. #ifdef WIN32         
  9.   #define __far far
  10.   #define huge far
  11.   #define __near near
  12. #endif               
  13.  
  14. #define MAXOUTLINE 255
  15.  
  16. HANDLE    gensock_lib = 0;
  17.  
  18. int (FAR PASCAL *pgensock_connect) (char FAR * hostname, char FAR * service, socktag FAR * pst);
  19. int (FAR PASCAL *pgensock_getchar) (socktag st, int wait, char FAR * ch);
  20. int (FAR PASCAL *pgensock_put_data) (socktag st, char FAR * data, unsigned long length);
  21. int (FAR PASCAL *pgensock_close) (socktag st);
  22. int (FAR PASCAL *pgensock_gethostname) (char FAR * name, int namelen);
  23. int (FAR PASCAL *pgensock_put_data_buffered) (socktag st, char FAR * data, unsigned long length);
  24. int (FAR PASCAL *pgensock_put_data_flush) (socktag st);
  25.  
  26.  
  27. socktag SMTPSock;
  28. #define SERVER_SIZE    256     // #defines (bleah!) from Beverly Brown "beverly@datacube.com"
  29. #define SENDER_SIZE    256
  30. char SMTPHost[SERVER_SIZE];
  31. char Sender[SENDER_SIZE];
  32. char *Recipients;
  33. char my_hostname[1024];
  34. char *destination="";
  35. char *cc_list="";
  36. char *bcc_list="";
  37. char *loginname="";
  38. char *senderid="";
  39. char *subject="";
  40. int quiet=0;
  41.  
  42. char *usage[]=
  43. {
  44.  "Blat v1.4: WinNT console utility to mail a file via SMTP",
  45.  "",
  46.  "syntax:",
  47.  "Blat <filename> -t <recipient> [optional switches (see below)]",
  48.  "Blat -install <server addr> <sender's addr> [-q]",
  49.  "Blat -h [-q]",
  50.  "",
  51.  "-install <server addr> <sender's addr>: set's default SMTP server and sender",
  52.  "",
  53.  "<filename>    : file with the message body ('-' for console input, end with ^Z)",
  54.  "-t <recipient>: recipient list (comma separated)",
  55.  "-s <subj>     : subject line",
  56.  "-f <sender>   : overrides the default sender address (must be known to server)",
  57.  "-i <addr>     : a 'From:' address, not necessarily known to the SMTP server.",
  58.  "-c <recipient>: carbon copy recipient list (comma separated)",
  59.  "-b <recipient>: blind carbon copy recipient list (comma separated)",
  60.  "-h            : displays this help.",
  61.  "-q            : supresses *all* output.",
  62.  "-server <addr>: overrides the default SMTP server to be used.",
  63.  "",
  64.  "Note that if the '-i' option is used, <sender> is included in 'Reply-to:'",
  65.  "and 'Sender:' fields in the header of the message."
  66. };
  67. const NMLINES=22;
  68.  
  69. void
  70. gensock_error (char * function, int retval)
  71. {
  72.  if( ! quiet )
  73.   cout << "error " << retval << " in function '" << function;
  74. }
  75.  
  76. // loads the GENSOCK DLL file
  77. int load_gensock()
  78. {
  79.   if( (gensock_lib = LoadLibrary("gwinsock.dll")) == NULL )
  80.   {
  81.    if( (gensock_lib = LoadLibrary("gensock.dll")) == NULL )
  82.    {
  83.     if( ! quiet )
  84.      cout << "Couldn't load either 'GWINSOCK.DLL' or 'GENSOCK.DLL'\nInstall one of these in your path.";
  85.     return -1;
  86.    }
  87.   }
  88.  
  89.   if( 
  90.      ( pgensock_connect = 
  91.       (  int (FAR PASCAL *)(char FAR *, char FAR *, socktag FAR *) )
  92.       GetProcAddress(gensock_lib, "gensock_connect")
  93.      ) == NULL
  94.     )
  95.   {
  96.    if( ! quiet )
  97.     cout << "couldn't getprocaddress for gensock_connect\n";
  98.    return -1;
  99.   }
  100.  
  101.   if (
  102.       ( pgensock_getchar =
  103.        ( int (FAR PASCAL *) (socktag, int, char FAR *) )
  104.        GetProcAddress(gensock_lib, "gensock_getchar")
  105.       ) == NULL
  106.      )
  107.   {
  108.    if( ! quiet )
  109.     cout << "couldn't getprocaddress for gensock_getchar\n";
  110.    return -1;
  111.   }
  112.  
  113.   if(
  114.      ( pgensock_put_data =
  115.        ( int (FAR PASCAL *) (socktag, char FAR *, unsigned long) )
  116.        GetProcAddress(gensock_lib, "gensock_put_data")
  117.      ) == NULL
  118.     )
  119.   {
  120.    if( ! quiet )
  121.     cout << "couldn't getprocaddress for gensock_put_data\n";
  122.    return -1;
  123.   }
  124.  
  125.   if(
  126.      ( pgensock_close =
  127.        (int (FAR PASCAL *) (socktag) )
  128.        GetProcAddress(gensock_lib, "gensock_close")
  129.      ) == NULL
  130.     )
  131.   {
  132.    if( ! quiet )
  133.     cout << "couldn't getprocaddress for gensock_close\n";
  134.    return -1;
  135.   }
  136.  
  137.   if(
  138.      ( pgensock_gethostname =
  139.        (int (FAR PASCAL *) (char FAR *, int) )       
  140.        GetProcAddress(gensock_lib, "gensock_gethostname")
  141.      ) == NULL
  142.     )
  143.   {
  144.    if( ! quiet )
  145.     cout << "couldn't getprocaddress for gensock_gethostname\n";
  146.    return -1;
  147.   }
  148.  
  149.   if(
  150.      ( pgensock_put_data_buffered =
  151.        ( int (FAR PASCAL *) (socktag, char FAR *, unsigned long) )
  152.        GetProcAddress(gensock_lib, "gensock_put_data_buffered")
  153.      ) == NULL
  154.     )
  155.   {
  156.    if( ! quiet )
  157.     cout << "couldn't getprocaddress for gensock_put_data_buffered\n";
  158.    return -1;
  159.   }
  160.  
  161.   if(
  162.      ( pgensock_put_data_flush =
  163.        ( int (FAR PASCAL *) (socktag) )
  164.        GetProcAddress(gensock_lib, "gensock_put_data_flush")
  165.      ) == NULL
  166.     )
  167.   {
  168.    if( ! quiet )
  169.     cout << "couldn't getprocaddress for gensock_put_data_flush\n";
  170.    return -1;
  171.   }
  172.  
  173.   return 0;
  174. }
  175.  
  176. int open_smtp_socket( void )
  177. {
  178.   int retval;
  179.  
  180.   /* load the library if it's not loaded */
  181. //  if (!gensock_lib)
  182.     if ( ( retval = load_gensock() ) ) return ( retval );
  183.  
  184.   if ( (retval = (*pgensock_connect) ((LPSTR) SMTPHost,
  185.                      (LPSTR)"smtp",
  186.                      &SMTPSock)))
  187.   {
  188.     if (retval == ERR_CANT_RESOLVE_SERVICE)
  189.     {
  190.      if ((retval = (*pgensock_connect) ((LPSTR)SMTPHost,
  191.                      (LPSTR)"25",
  192.                      &SMTPSock)))
  193.      {
  194.        gensock_error ("gensock_connect", retval);
  195.        return -1;
  196.      }
  197.     }
  198.   // error other than can't resolve service 
  199.     else
  200.     {
  201.      gensock_error ("gensock_connect", retval);
  202.      return -1;
  203.     }
  204.   }
  205.  
  206.   // we wait to do this until here because WINSOCK is
  207.   // guaranteed to be already initialized at this point.
  208.  
  209.   // get the local hostname (needed by SMTP) 
  210.   if ((retval = (*pgensock_gethostname) (my_hostname, sizeof(my_hostname))))
  211.   {
  212.     gensock_error ("gensock_gethostname", retval);
  213.     return -1;
  214.   }
  215.   return 0;
  216. }
  217.  
  218.  
  219. int close_smtp_socket( void )
  220. {
  221.   int retval;
  222.  
  223.   if( (retval = (*pgensock_close) (SMTPSock)) )
  224.   {
  225.     gensock_error ("gensock_close", retval);
  226.     return -1;
  227.   }
  228.   FreeLibrary( gensock_lib );
  229.   return (0);
  230. }
  231.  
  232. int get_smtp_line( void )
  233. {
  234.   char ch = '.';
  235.   char in_data [MAXOUTLINE];
  236.   char * index;
  237.   int retval = 0;
  238.  
  239.   index = in_data;
  240.  
  241.   while (ch != '\n')
  242.   {
  243.    if( (retval = (*pgensock_getchar) (SMTPSock, 0, &ch) ) )
  244.    {
  245.       gensock_error ("gensock_getchar", retval);
  246.       return -1;
  247.     }
  248.     else
  249.     {
  250.       *index = ch;
  251.       index++;
  252.     }
  253.   }
  254.  
  255.   /* this is to support multi-line responses, common with */
  256.   /* servers that speak ESMTP */
  257.  
  258.   /* I know, I know, it's a hack 8^) */
  259.   if( in_data[3] == '-' ) return( get_smtp_line() );
  260.   else return atoi(in_data);
  261. }
  262.  
  263. int put_smtp_line( socktag sock, char far * line, unsigned int nchars )
  264. {
  265.   int retval;
  266.  
  267.   if( (retval = (*pgensock_put_data) (sock, line, (unsigned long) nchars)))
  268.   {
  269.     gensock_error ("gensock_put_data", retval);
  270.     return -1;
  271.   }
  272.   return (0);
  273. }
  274.  
  275. int putline_internal (socktag sock, char * line, unsigned int nchars)
  276. {
  277.   int retval;
  278.  
  279.   if ((retval =
  280.        (*pgensock_put_data) (sock,
  281.                 (char FAR *) line,
  282.                 (unsigned long) nchars)))
  283.   {
  284.     switch (retval)
  285.     {
  286.      case ERR_NOT_CONNECTED:
  287.       gensock_error( "SMTP server has closed the connection", retval );
  288.       break;
  289.  
  290.      default:
  291.       gensock_error ("gensock_put_data", retval);
  292.     }
  293.     return -1;
  294.   }
  295.   return (0);
  296. }
  297.  
  298. void smtp_error (char * message)
  299. {
  300.  if( ! quiet )
  301.   cout << message << "\n";
  302.  put_smtp_line (SMTPSock, "QUIT\r\n", 6);
  303.  close_smtp_socket();
  304. }
  305.  
  306.  
  307. // 'destination' is the address the message is to be sent to
  308. // 'message' is a pointer to a null-terminated 'string' containing the 
  309. // entire text of the message. 
  310.  
  311. int prepare_smtp_message(char * MailAddress, char * destination)
  312. {
  313.   char out_data[MAXOUTLINE];
  314.   char str[1024];
  315.   char *ptr;
  316.   int len, startLen;
  317.  
  318.   if ( open_smtp_socket() ) return -1;
  319.  
  320.   if ( get_smtp_line() != 220 )
  321.   {
  322.     smtp_error ("SMTP server error");
  323.     return(-1);
  324.   }
  325.  
  326.   sprintf( out_data, "HELO %s\r\n", my_hostname );
  327.   put_smtp_line( SMTPSock, out_data, strlen (out_data) );
  328.  
  329.   if ( get_smtp_line() != 250 )
  330.   {
  331.     smtp_error ("SMTP server error");
  332.     return -1;
  333.   }
  334.  
  335.   sprintf (out_data, "MAIL From:<%s>\r\n", loginname);
  336.   put_smtp_line( SMTPSock, out_data, strlen (out_data) );
  337.  
  338.   if (get_smtp_line() != 250)
  339.   {
  340.     smtp_error ("The mail server doesn't like the sender name,\nhave you set your mail address correctly?");
  341.     return -1;
  342.   }
  343.  
  344.   // do a series of RCPT lines for each name in address line
  345.   for (ptr = destination; *ptr; ptr += len + 1)
  346.   {
  347.     // if there's only one token left, then len will = startLen,
  348.     // and we'll iterate once only
  349.     startLen = strlen (ptr);
  350.     if ((len = strcspn (ptr, " ,\n\t\r")) != startLen)
  351.     {
  352.       ptr[len] = '\0';            // replace delim with NULL char
  353.       while (strchr (" ,\n\t\r", ptr[len+1]))    // eat white space
  354.         ptr[len++] = '\0';
  355.     }
  356.  
  357.     sprintf (out_data, "RCPT To: <%s>\r\n", ptr);
  358.     putline_internal( SMTPSock, out_data, strlen (out_data) );
  359.  
  360.     if (get_smtp_line() != 250)
  361.     {
  362.       sprintf (str, "The mail server doesn't like the name %s.\nHave you set the 'To: ' field correctly?", ptr);
  363.       smtp_error (str);
  364.       return -1;
  365.     }
  366.  
  367.     if (len == startLen)    // last token, we're done
  368.       break;
  369.   }
  370.  
  371.   sprintf (out_data, "DATA\r\n");
  372.   put_smtp_line (SMTPSock, out_data, strlen (out_data));
  373.  
  374.   if (get_smtp_line() != 354)
  375.   {
  376.     smtp_error ("Mail server error accepting message data");
  377.     return -1;
  378.   }
  379.  
  380.   return(0);
  381.  
  382. }
  383.  
  384. int transform_and_send_edit_data( socktag sock, char * editptr )
  385. {
  386.   char *index;
  387.   char *header_end;
  388.   char previous_char = 'x';
  389.   unsigned int send_len;
  390.   int retval;
  391.   BOOL done = 0;
  392.  
  393.   send_len = lstrlen(editptr);
  394.   index = editptr;
  395.  
  396.   header_end = strstr (editptr, "\r\n\r\n");
  397.  
  398.   while (!done)
  399.   {
  400.     // room for extra char for double dot on end case
  401.     while ((unsigned int) (index - editptr) < send_len)
  402.     {
  403.       switch (*index)
  404.       {
  405.        case '.':
  406.                  if (previous_char == '\n')
  407.                   /* send _two_ dots... */
  408.                   if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) return (retval);
  409.                    if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) return (retval);
  410.                  break;
  411.        case '\r':
  412.                  // watch for soft-breaks in the header, and ignore them
  413.                  if (index < header_end && (strncmp (index, "\r\r\n", 3) == 0))
  414.                    index += 2;
  415.                  else
  416.                   if (previous_char != '\r')
  417.                    if ((retval = (*pgensock_put_data_buffered) (sock, index, 1)))
  418.                     return (retval);
  419.                   // soft line-break (see EM_FMTLINES), skip extra CR */
  420.                  break;
  421.        default:
  422.                if ((retval = (*pgensock_put_data_buffered) (sock, index, 1)))
  423.                 return (retval);
  424.       }
  425.       previous_char = *index;
  426.       index++;
  427.     }
  428.     if( (unsigned int) (index - editptr) == send_len) done = 1;
  429.   }
  430.  
  431.   // this handles the case where the user doesn't end the last
  432.   // line with a <return>
  433.  
  434.   if (editptr[send_len-1] != '\n')
  435.   {
  436.     if ((retval = (*pgensock_put_data_buffered) (sock, "\r\n.\r\n", 5)))
  437.       return (retval);
  438.   }
  439.   else
  440.     if ((retval = (*pgensock_put_data_buffered) (sock, ".\r\n", 3)))
  441.       return (retval);
  442.  
  443.   /* now make sure it's all sent... */
  444.   if ((retval = (*pgensock_put_data_flush)(sock))) return (retval);
  445.   return (TRUE);
  446. }
  447.  
  448.  
  449.  
  450. int send_smtp_edit_data (char * message)
  451. {
  452.   transform_and_send_edit_data( SMTPSock, message );
  453.  
  454.   if (get_smtp_line() != 250)
  455.   {
  456.     smtp_error ("Message not accepted by server");
  457.     return -1;
  458.   }
  459.   return(0);
  460. }
  461.  
  462.  
  463. int finish_smtp_message( void )
  464. {
  465.   return put_smtp_line( SMTPSock, "QUIT\r\n", 6 );
  466. }
  467.  
  468. // create a registry entries for this program 
  469. int CreateRegEntry( void )
  470. {
  471.   HKEY  hKey1;
  472.   DWORD  dwDisposition;
  473.   LONG   lRetCode;
  474.  
  475.   /* try to create the .INI file key */
  476.   lRetCode = RegCreateKeyEx ( HKEY_LOCAL_MACHINE,
  477.                               "SOFTWARE\\Public Domain\\Blat",
  478.                               0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE,NULL, &hKey1,&dwDisposition
  479.                             );
  480.  
  481.   /* if we failed, note it, and leave */
  482.   if (lRetCode != ERROR_SUCCESS)
  483.   {
  484.     if( ! quiet ) printf ("Error in creating blat key in the registry\n");
  485.     return 10;
  486.   }
  487.  
  488.   /* try to set a section value */
  489.   lRetCode = RegSetValueEx( hKey1,"SMTP server",0,REG_SZ, (BYTE *) &SMTPHost[0], (strlen(SMTPHost)+1));
  490.  
  491.   /* if we failed, note it, and leave */
  492.   if (lRetCode != ERROR_SUCCESS)
  493.   {
  494.     if( ! quiet ) printf ( "Error in setting SMTP server value in the registry\n");
  495.     return 11;
  496.   }
  497.   
  498.   /* try to set another section value */
  499.   lRetCode = RegSetValueEx( hKey1,"Sender",0,REG_SZ, (BYTE *) &Sender[0], (strlen(Sender)+1));
  500.  
  501.   /* if we failed, note it, and leave */
  502.   if (lRetCode != ERROR_SUCCESS)
  503.   {
  504.    if( ! quiet ) printf ( "Error in setting sender address value in the registry\n");
  505.     return 11;
  506.   }
  507.   
  508.   return 0;
  509. }
  510.  
  511. // get the registry entries for this program 
  512. int GetRegEntry( void )
  513. {
  514.   HKEY  hKey1;
  515.   DWORD  dwType;
  516.   DWORD  dwBytesRead;
  517.   LONG   lRetCode;
  518.  
  519.   // open the registry key in read mode
  520.   lRetCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  521.                            "SOFTWARE\\Public Domain\\Blat",
  522.                            0, KEY_READ, &hKey1
  523.                          );
  524.   if( lRetCode != ERROR_SUCCESS )
  525.   {
  526.      if( ! quiet ) printf( "Failed to open registry key for Blat\n" );
  527.      return 12;
  528.   }
  529.   // set the size of the buffer to contain the data returned from the registry
  530.   // thanks to Beverly Brown "beverly@datacube.com" and "chick@cyberspace.com" for spotting it...
  531.   dwBytesRead=SERVER_SIZE;
  532.   // read the value of the SMTP server entry
  533.   lRetCode = RegQueryValueEx( hKey1, "SMTP server", NULL , &dwType, (BYTE *) &SMTPHost, &dwBytesRead); 
  534.   // if we failed, note it, and leave
  535.   if( lRetCode != ERROR_SUCCESS )
  536.   {
  537.     if( ! quiet ) printf( "Failed to read SMTP server value from the registry\n" );
  538.     return 12;
  539.   }
  540.  
  541.   dwBytesRead=SENDER_SIZE;
  542.   // read the value of the SMTP server entry
  543.   lRetCode = RegQueryValueEx( hKey1, "Sender", NULL , &dwType, (BYTE *) &Sender, &dwBytesRead); 
  544.   // if we failed, note it, and leave
  545.   if( lRetCode != ERROR_SUCCESS )
  546.   {
  547.     if( ! quiet ) printf( "Failed to read senders user name from the registry\n" );
  548.     return 12;
  549.   }
  550.  
  551.  return 0;
  552. }
  553.  
  554.  
  555. int main( int argc,        /* Number of strings in array argv          */
  556.            char *argv[],    /* Array of command-line argument strings   */
  557.            char **envp )    /* Array of environment variable strings    */
  558. {
  559.  int next_arg=2;
  560.  int impersonating = 0;
  561.  int penguin = 0;
  562.  int i, j;
  563.  char tempdir[MAX_PATH+1];
  564.  char tempfile[MAX_PATH+1];
  565.  HANDLE fileh;
  566.  FILE *tf;
  567.  int hours, minutes;
  568.  OFSTRUCT of;
  569.  
  570.  
  571.  // by default Blat is very noisy!
  572.  quiet = 0;
  573.  
  574.  // no tempfile so far...
  575.  tempfile[0] = '\0';
  576.  
  577.  if(argc<2)
  578.  {
  579.   // must have at least file name to send
  580.   for(i=0;i<NMLINES;i++) cout<<usage[i]<<'\n';
  581.   return 1;
  582.  }
  583.  
  584.  for( i=1; i < argc; i++ )
  585.   if( lstrcmpi( "-q",argv[i] ) == 0 ) quiet = 1;
  586.  
  587.  // get file name from argv[1]
  588.  char *filename=argv[1];
  589.  
  590.  Sender[0] = '\0';
  591.  SMTPHost[0] = '\0';
  592.  
  593.  GetRegEntry();
  594.  
  595.  senderid  = Sender;
  596.  loginname = Sender;
  597.         
  598.  // thanks to Beverly Brown "beverly@datacube.com" for
  599.  // fixing the argument parsing, I "fixed" the brackets
  600.  // to conform approximately to our "style"  :-)
  601.  // Starts here
  602.  for(next_arg=1;next_arg < argc;next_arg++)
  603.  {
  604.     if(lstrcmpi("-h",argv[next_arg])==0)
  605.     {
  606.      if( ! quiet ) for(int i=0;i<NMLINES;i++) cout<<usage[i]<<'\n';
  607.      return 1;
  608.     }
  609.  
  610.           // is argv[2] "-install"? If so, indicate error and return
  611.     else if(lstrcmpi("-install",argv[next_arg])==0)
  612.     {
  613.        if((argc == 3) || (argc == 4)) 
  614.              {
  615.             strcpy( SMTPHost, argv[++next_arg] );
  616.              if(argc == 4) 
  617.                  strcpy( Sender, argv[++next_arg] );
  618.             else
  619.                 strcpy( Sender, "" );
  620.              if( CreateRegEntry() == 0 ) 
  621.                  {
  622.                    if( ! quiet ) printf("\nSMTP server set to %s\n", SMTPHost );
  623.                   return 0;
  624.                  }
  625.              }
  626.        else
  627.           {
  628.            if( ! quiet )
  629.             printf( "to set the SMTP server's address and the user name at that address do:\nblat -install server username");
  630.              return 6;
  631.           }
  632.     }
  633.  
  634.         // is argv[2] "-s"? If so, argv[3] is the subject
  635.     else if(lstrcmpi("-s",argv[next_arg])==0)
  636.     {
  637.      subject=argv[++next_arg];
  638.     }
  639.  
  640.        // is argv[2] "-c"? If so, argv[3] is the carbon-copy list
  641.     else if(lstrcmpi("-c",argv[next_arg])==0)
  642.     {
  643.      cc_list=argv[++next_arg];
  644.     }
  645.  
  646.        // is argv[2] "-b"? If so, argv[3] is the blind carbon-copy list
  647.     else if(lstrcmpi("-b",argv[next_arg])==0)
  648.     {
  649.      bcc_list=argv[++next_arg];
  650.     }
  651.  
  652.         // is next argv "-t"? If so, succeeding argv is the destination
  653.     else if(lstrcmpi("-t",argv[next_arg])==0)
  654.     {
  655.      destination=argv[++next_arg];
  656.     }
  657.  
  658.     // is next argv "-server"? If so, succeeding argv is the SMTPHost    
  659.     else if(lstrcmpi("-server",argv[next_arg])==0)
  660.     {
  661.      strcpy(SMTPHost,argv[++next_arg]);
  662.     }
  663.  
  664.      //is next argv '-f'? If so, succeeding argv is the loginname
  665.     else if(lstrcmp("-f",argv[next_arg])==0)
  666.       loginname=argv[++next_arg];
  667.  
  668.     else if(lstrcmp("-penguin",argv[next_arg])==0)
  669.     {
  670.      penguin = 1;
  671.     }
  672.     
  673.     // if next arg is a '-q' just increase and continue looking
  674.     // we have already dealt with -q at the beggining
  675.     else if(lstrcmp("-q",argv[next_arg])==0)
  676.     {
  677.      next_arg++;
  678.     }
  679.  
  680.     //is next argv '-i'? If so, succeeding argv is the sender id
  681.     else if(lstrcmp("-i",argv[next_arg])==0)
  682.     {
  683.      senderid=argv[++next_arg];
  684.      impersonating = 1;
  685.     }
  686.     else if(next_arg == 1) 
  687.     {
  688.       if (lstrcmp(filename, "-") != 0)
  689.      {
  690.       if( lstrlen(filename)<=0 || OpenFile(filename,&of,OF_EXIST) == HFILE_ERROR )
  691.       {
  692.        if( ! quiet ) cout<<filename<<" does not exist\n";        
  693.         return 2;
  694.       }
  695.      }
  696.     } 
  697.     else 
  698.     {
  699.      if( ! quiet )
  700.       for(i=0;i<NMLINES;i++)
  701.         cout<<usage[i]<<'\n';
  702.      return 1;
  703.     }
  704.  }
  705.  
  706.     // if we are not impersonating loginname is the same as the sender
  707.     if( ! impersonating )
  708.           senderid = loginname;
  709.  
  710.       // fixing the argument parsing
  711.       // Ends here
  712.  
  713.     if ((SMTPHost[0]=='\0')||(loginname[0]=='\0'))
  714.     {
  715.      if( ! quiet )
  716.      {
  717.       printf( "to set the SMTP server's address and the user name at that address do:\nblat -install server username\n");
  718.       printf( "or use '-server <server name>' and '-f <user name>'\n");
  719.       printf( "aborting, nothing sent\n" );
  720.      }
  721.      return 12;
  722.     }
  723.     
  724.     // make sure filename exists, get full pathname
  725.     if (lstrcmp(filename, "-") != 0)
  726.      if(lstrlen(filename)<=0 || OpenFile(filename,&of,OF_EXIST)==HFILE_ERROR)
  727.      {
  728.       if( ! quiet ) cout<<filename<<" does not exist\n";        
  729.       return 2;
  730.      }
  731.  
  732.     // build temporary recipients list for parsing the "To:" line
  733.     char *temp = new char [ strlen(destination) + strlen(cc_list) + strlen(bcc_list) + 4 ];
  734.     // build the recipients list
  735.     Recipients = new char [ strlen(destination) + strlen(cc_list) + strlen(bcc_list) + 4 ];
  736.     
  737.     // Parse the "To:" line
  738.     for (i = j = 0; i < (int) strlen(destination); i++)
  739.     {
  740.       // strip white space
  741.       while (destination[i]==' ')
  742.         i++;
  743.       // look for comments in brackets, and omit
  744.       if (destination[i]=='(')
  745.       {
  746.         while (destination[i]!=')')
  747.           i++;
  748.         i++;
  749.       }      
  750.         // look for comments in quotes, and omit
  751.         if (destination[i]=='\'')
  752.       {
  753.       i++;
  754.         while (destination[i]!='\'')
  755.           i++;
  756.         i++;
  757.       }      
  758.       
  759.       temp[j++] = destination[i];
  760.     }
  761.  
  762.     strcpy( Recipients, temp);
  763.  
  764.     // Parse the "Cc:" line
  765.     for (i = j = 0; i < (int) strlen(cc_list); i++)
  766.     {
  767.      // strip white space
  768.      while (cc_list[i]==' ') i++;
  769.      // look for comments in brackets, and omit
  770.      if (cc_list[i]=='(')
  771.      {
  772.       while (cc_list[i]!=')') i++;
  773.       i++;
  774.      }      
  775.        // look for comments in quotes, and omit
  776.        if (cc_list[i]=='\'')
  777.      {
  778.       i++;
  779.       while (cc_list[i]!='\'') i++;
  780.       i++;
  781.      }      
  782.      temp[j++] = cc_list[i];
  783.     }
  784.     if( strlen(cc_list) > 0 )
  785.     {
  786.      strcat(Recipients, "," );
  787.      strcat(Recipients, temp);
  788.     }
  789.  
  790.     // Parse the "Bcc:" line
  791.     for (i = j = 0; i < (int) strlen(bcc_list); i++)
  792.     {
  793.      // strip white space
  794.      while (bcc_list[i]==' ') i++;
  795.      // look for comments in brackets, and omit
  796.      if (bcc_list[i]=='(')
  797.      {
  798.       while (bcc_list[i]!=')') i++;
  799.       i++;
  800.      }      
  801.        // look for comments in quotes, and omit
  802.        if (bcc_list[i]=='\'')
  803.      {
  804.       i++;
  805.       while (bcc_list[i]!='\'') i++;
  806.       i++;
  807.      }      
  808.      temp[j++] = bcc_list[i];
  809.     }
  810.  
  811.     if( strlen(bcc_list) > 0 )
  812.     {
  813.      strcat(Recipients, "," );
  814.      strcat(Recipients, temp);
  815.     }
  816.    
  817.  
  818.     // create a header for the message
  819.     char tmpstr[256];
  820.     char header[2048];
  821.     int  headerlen;
  822.     SYSTEMTIME curtime;
  823.     TIME_ZONE_INFORMATION tzinfo;
  824.     char * days[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  825.     char * months[] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
  826.     DWORD retval;
  827.  
  828.     GetLocalTime( &curtime );
  829.     retval = GetTimeZoneInformation( &tzinfo );
  830.     hours = (int) tzinfo.Bias / 60;
  831.     minutes = (int) tzinfo.Bias % 60;
  832.     if( retval == TIME_ZONE_ID_STANDARD ) 
  833.     {
  834.      hours += (int) tzinfo.StandardBias / 60;
  835.      minutes += (int) tzinfo.StandardBias % 60;
  836.     }
  837.     else
  838.       {
  839.      hours += (int) tzinfo.DaylightBias / 60;
  840.      minutes += (int) tzinfo.DaylightBias % 60;
  841.     }
  842.     
  843.     // rfc1036 & rfc822 acceptable format
  844.     // Mon, 29 Jun 94 02:15:23 GMT
  845.     sprintf (tmpstr, "Date: %s, %.2d %s %.2d %.2d:%.2d:%.2d ",
  846.       days[curtime.wDayOfWeek],
  847.       curtime.wDay,
  848.       months[curtime.wMonth - 1],
  849.       curtime.wYear,
  850.       curtime.wHour,
  851.       curtime.wMinute,
  852.       curtime.wSecond);
  853.     strcpy( header, tmpstr );
  854.  
  855.     sprintf( tmpstr, "%+03d%02d", -hours, -minutes );
  856.     //for(i=0;i<32;i++)
  857.     //{
  858.     // if( retval == TIME_ZONE_ID_STANDARD ) tmpstr[i] = (char) tzinfo.StandardName[i];
  859.     // else tmpstr[i] = (char) tzinfo.DaylightName[i];
  860.     //}
  861.     strcat( header, tmpstr );
  862.     strcat( header, "\r\n" );
  863.     sprintf( tmpstr, "From: %s\r\n", senderid );
  864.     strcat( header, tmpstr );
  865.     if( impersonating )
  866.     {
  867.      sprintf( tmpstr, "Sender: %s\r\n", loginname );
  868.      strcat( header, tmpstr );
  869.     if (!(penguin == 1))
  870.      {
  871.      sprintf( tmpstr, "Reply-to: %s\r\n", loginname );
  872.      strcat( header, tmpstr );
  873.      }
  874.     }
  875.     if( *subject )
  876.     {
  877.      sprintf( tmpstr, "Subject: %s\r\n", subject );
  878.      strcat( header, tmpstr );
  879.     }
  880.     else
  881.     {
  882.      if (!(penguin == 1))
  883.      {
  884.       if (lstrcmp(filename, "-") == 0)
  885.        sprintf( tmpstr, "Subject: Contents of console input\r\n", filename );
  886.       else
  887.        sprintf( tmpstr, "Subject: Contents of file: %s\r\n", filename );
  888.       strcat( header, tmpstr );
  889.      }
  890.     }
  891.     
  892.     sprintf( tmpstr, "To: %s\r\n", destination );
  893.     strcat( header, tmpstr );
  894.     if( *cc_list )
  895.     {
  896.      // Add line for the Carbon Copies
  897.      sprintf( tmpstr, "Cc: %s\r\n", cc_list );
  898.      strcat( header, tmpstr );
  899.     }
  900.     strcat( header, "X-Mailer: <WinNT's Blat ver 1.4>\r\n" );
  901.     
  902.     if (!(penguin == 1))
  903.         strcat( header, "\r\n" );
  904.  
  905.     headerlen = strlen( header );
  906.  
  907.     // if reading from the console, read everything into a temporary file first
  908.     if (lstrcmp(filename, "-") == 0)
  909.     {
  910.      // create a unique temporary file name
  911.      GetTempPath( MAX_PATH, tempdir );
  912.      GetTempFileName( tempdir, "blt", 0, tempfile );
  913.  
  914.      // open the file in write mode
  915.      tf = fopen(tempfile,"w");
  916.      if( tf==NULL )
  917.      {
  918.       if( ! quiet ) cout<<"error opening temporary file "<<filename<<", aborting\n";        
  919.       delete [] Recipients;
  920.       return 13;
  921.      }
  922.  
  923.      do
  924.      {
  925.       i = getc( stdin );
  926.       putc( i, tf );
  927.      }
  928.      while( i != EOF );
  929.  
  930.      fclose( tf );
  931.      filename = tempfile;
  932.     }
  933.  
  934.     //get the text of the file into a string buffer
  935.     if((fileh=CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
  936.                          FILE_FLAG_SEQUENTIAL_SCAN,NULL))==INVALID_HANDLE_VALUE)
  937.     {
  938.      if( ! quiet ) cout<<"error reading "<<filename<<", aborting\n";        
  939.      delete [] Recipients;
  940.      return 3;
  941.     }
  942.     if(GetFileType(fileh)!=FILE_TYPE_DISK)
  943.     {
  944.      if( ! quiet ) cout<<"Sorry, I can only mail messages from disk files...\n";        
  945.      delete [] Recipients;
  946.      return 4;
  947.     }
  948.     DWORD filesize = GetFileSize( fileh,NULL );
  949.     char *buffer = new char[filesize+headerlen+1];
  950.     char *tmpptr;
  951.  
  952.     // put the header at the top...
  953.     strcpy( buffer, header );
  954.     // point to the end of the header
  955.     tmpptr = buffer + headerlen;
  956.     // and put the whole file there
  957.     DWORD dummy;
  958.     if(!ReadFile(fileh,tmpptr,filesize,&dummy,NULL))
  959.     {
  960.      if( ! quiet ) cout<<"error reading "<<filename<<", aborting\n";
  961.      CloseHandle(fileh);
  962.      delete [] buffer;        
  963.      delete [] Recipients;
  964.      return 5;
  965.     }
  966.     CloseHandle(fileh);
  967.     
  968.     // delete the temporary file if it has been used
  969.     if ( *tempfile ) remove( tempfile );
  970.         
  971.     // make some noise about what we are doing
  972.     if( ! quiet )
  973.     {    
  974.      cout<<"Sending "<<filename<<" to "<< (lstrlen(Recipients) ? Recipients : "<unspecified>")<<'\n';
  975.      if(lstrlen(subject)) cout<<"Subject:"<<subject<<'\n';
  976.      if(lstrlen(loginname)) cout<<"Login name is "<<loginname<<'\n';
  977.     }
  978.  
  979.   // send the message to the SMTP server!
  980.   if( !prepare_smtp_message( loginname, Recipients ) )
  981.   {
  982.    if( !send_smtp_edit_data( buffer ) )
  983.     finish_smtp_message();
  984.    close_smtp_socket();
  985.   }
  986.  
  987.   delete [] buffer;
  988.   delete [] Recipients;
  989.   return 0;
  990. }
  991.  
  992.