#include <sjcdef.h>

/*----------------------------------------------------------------------
    Output routine for rfc822_output_body

Normally this is used for writing a message down a TCP stream, but
writing a MIME body out is complex business so we use it here.
We must convert the network CRLF to the local new line convention, in this
case on UNIX it's LF.
 ----*/
static long
vms_puts(stream_x, string)
    void   *stream_x;
    char   *string;
{
    FILE *stream = (FILE *)stream_x;
    char *p;

    for(p = string; *p; p++)
      if(putc((*p=='\015' && *(p+1)=='\012') ? (p++,'\n') : *p, stream) == EOF)
	return(0L);

    return(1L);					/* T for c-client */
}


/*----------------------------------------------------------------------
    General function to write a message to Berkeley format folder

Args:  folder -- The name of the folder
       env    -- The envelope (header) of the message to save
       bod    -- The message body

Returns: 0 if susccessful, -1 if not

----*/
static int
append_message2(filename, header, bod)
    char    *filename;
    METAENV *header;
    BODY    *bod;
{
    int    rv, save_errno;
    FILE  *folder_stream;
    long   start_of_append;

    if(!filename || !(folder_stream = fopen(filename, "w"))){
        q_status_message2(1, 2, 4, "\007Error opening file \"%s\", %s",
			  filename ? pretty_fn(filename) : "<NO FILE NAME>",
			  error_description(errno));
        return(-1);
    }

    (void) chmod(filename, 0600);
    start_of_append = ftell(folder_stream);

    rv = pine_rfc822_output(header,bod,vms_puts,(TCPSTREAM *)folder_stream);

    fclose(folder_stream);

  done:
    if(!rv){
        save_errno = errno;
        q_status_message2(1, 2, 4, "\007Error \"%s\" writing \"%s\"",
                          error_description(save_errno), pretty_fn(filename));
        dprint(1, (debugfile, "Error writing %s: %s\n",
                   filename, error_description(save_errno)));
        return(-1);
    }
    else 
      return(0);
}


/*----------------------------------------------------------------------
    General function to write a message to Berkeley format folder

Args:  folder -- The name of the folder
       env    -- The envelope (header) of the message to save
       bod    -- The message body

Returns: 0 if susccessful, -1 if not

----*/
static int
append_message3(filename, header, bod)
     char    *filename;
     METAENV *header;
     BODY    *bod;
{
     int    rv, save_errno;
     FILE  *folder_stream;
     long   start_of_append;

     if(!filename || !(folder_stream = fopen(filename, "a"))){
         q_status_message2(1, 2, 4, "\007Error opening file \"%s\", %s",
                          filename ? pretty_fn(filename) : "<NO FILE NAME>",
                          error_description(errno));
         return(-1);
     }

     (void) chmod(filename, 0600);
     start_of_append = ftell(folder_stream);

     rv = pine_rfc822_output(header,bod,vms_puts,(TCPSTREAM *)folder_stream);

     fclose(folder_stream);

  done:
    if(!rv){
        save_errno = errno;
        q_status_message2(1, 2, 4, "\007Error \"%s\" writing \"%s\"",
                          error_description(save_errno), pretty_fn(filename));
        dprint(1, (debugfile, "Error writing %s: %s\n",
                   filename, error_description(save_errno)));
        return(-1);
    }
    else 
      return(0);
}


/*----------------------------------------------------------------------
   Hand off given message to local posting agent

  Args: envelope -- The envelope for the BCC and debugging
        header   -- The text of the message header
        errbuf   -- buffer for reporting errors (assumed non-NULL)
     
  Fork off mailer process and pipe the message into it
  Called to post news via Inews when NNTP is unavailable
  
BUG, this needs to be filled in 
   ----*/
char *
post_handoff(header, body, errbuf)
     METAENV *header;
     BODY    *body;
     char    *errbuf;
{
    sprintf(errbuf, "Can't post, NNTP-server must be defined!");
    return(errbuf);
}


/* ----------------------------------------------------------------------
   Hand off given message to local transport agent - VMS specific.

   Added support for Multinet SMTP and VMS-Sendmail local transports

     Luigi Fonti
     CNAF INFN Bologna, Italy (Luigi.Fonti@cnaf.infn.it)

     Claudio Allocchio, 
     Sincrotrone Trieste, Italy (Claudio.Allocchio@elettra.trieste.it)

  Args: envelope -- The envelope for the BCC and debugging
        header   -- The text of the message header
        errbuf   -- buffer for reporting errors (assumed non-NULL)

  ----*/

char *
send_handoff(header, body, errbuf)
    METAENV *header;
    BODY    *body;
    char    *errbuf;
{
    char    *vms_mail_send();
    char    *vms_sendmail_submit();
    char     mail_cmd[MAXPATH+1];
    char    *tmpfile;
    char    *MailSendErrorMess;

    static char *namon[] =
    {
      "JAN","FEB","MAR","APR","MAY","JUN",
      "JUL","AUG","SEP","OCT","NOV","DEC"
    };
    char    *p, *pmpu, MailSendmailQueue[256];

    unsigned long bintime[2];
    void          sys$gettim();

    time_t now;
    struct tm *ptm;
    int year;
    FILE *ftm;
    ADDRESS *ap;

    *errbuf = '\0';

    if(!header->env->to && !header->env->cc && !header->env->bcc)
      return(NULL);             /* nobody to send to, fail silently */

    /* check if we use VMS Mail interface or Sendmail */

     if((p = getenv("PINE_SENDMAIL_QUEUE")) != NULL)
          strcpy(MailSendmailQueue, p);
     else
          MailSendmailQueue[0] = '\0';

    pmpu = MailSendmailQueue;

    if (*pmpu != '\0') { /* we use VMS Sendmail */

        /* create a temporary file 'tmpfile' named as 
              TMPYYYYMMDDhhmmsscc.MailProtocol_used
           example:
              TMP1997012111072426.GV2$SMTP_SYNW06 */

        sys$gettim(&bintime);
        bintime[0] = ( bintime[0] / 100000 ) % 100;
        time(&now);
        ptm = localtime(&now);
        year = ptm->tm_year;
        if (year > 90) year += 1900; else year += 2000;

        if((tmpfile = malloc(256)) != NULL) {

           if((p = getenv("GV2$MSG")) != NULL)
              sprintf(tmpfile,"GV2$MSG:TMP%04d%02d%02d%02d%02d%02d%02d.%s",
                  year,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,
                  ptm->tm_min,ptm->tm_sec,bintime[0],pmpu);
           else if((p = getenv("GV2$DIR")) != NULL)
              sprintf(tmpfile,"GV2$DIR:TMP%04d%02d%02d%02d%02d%02d%02d.%s",
                  year,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,
                  ptm->tm_min,ptm->tm_sec,bintime[0],pmpu);
           else if((p = getenv("PINE_SPOOL")) != NULL)
              sprintf(tmpfile,"PINE_SPOOL:TMP%04d%02d%02d%02d%02d%02d%02d.%s",
                  year,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,
                  ptm->tm_min,ptm->tm_sec,bintime[0],pmpu);
           else if((p = getenv("MULTINET_SPOOL")) != NULL)
              sprintf(tmpfile,"MULTINET_SPOOL:TMP%04d%02d%02d%02d%02d%02d%02d.%s",
                  year,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,
                  ptm->tm_min,ptm->tm_sec,bintime[0],pmpu);
           else
              sprintf(tmpfile,"SYS$LOGIN:TMP%04d%02d%02d%02d%02d%02d%02d.%s",
                  year,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,
                  ptm->tm_min,ptm->tm_sec,bintime[0],pmpu);
           ftm = fopen(tmpfile,"w");

           if (ftm != NULL) { /* temporary file open is OK */
               ap = header->env->from;
               fprintf(ftm,"MAIL FROM:<%s@%s>\n", ap->mailbox, ap->host);
               ap = header->env->to;
               while (ap != NULL) {
                   fprintf(ftm,"RCPT TO:<%s@%s>\n", ap->mailbox,ap->host);
                   ap = ap->next;
               }
               ap = header->env->cc;
               while (ap != NULL) {
                   fprintf(ftm,"RCPT TO:<%s@%s>\n", ap->mailbox,ap->host);
                   ap = ap->next;
               }
               fprintf(ftm,"ARRIVAL_TIME: %d-%s-%d %d:%02d:%02d\n",
                   ptm->tm_mday,namon[ptm->tm_mon],year,
                   ptm->tm_hour,ptm->tm_min,ptm->tm_sec);
               fclose(ftm);
               if (append_message3(tmpfile, header, body) >= 0) {
                   MailSendErrorMess = vms_sendmail_submit(tmpfile, pmpu);
                   if(MailSendErrorMess)
                        sprintf(errbuf, "\007%s %s",MailSendErrorMess,pmpu);
               }
               else
                 sprintf(errbuf, "\007Can't append temp file for sending: %s",
                         error_description(errno));
           }
           else
             sprintf(errbuf, "\007Can't open %s: %s",tmpfile,
                     error_description(errno));
        }
        else
          sprintf(errbuf, "\007Can't allocate temp file name: %s",
                  error_description(errno));

    }  /* end section using VMS Sendmail */

    else {  /*  no chance, we must user VMS Mail MAIL$xxxxx interface */
        if((tmpfile = temp_nam(NULL, "pinesend"))
           && append_message2(tmpfile, header, body) >= 0){
              MailSendErrorMess = vms_mail_send(tmpfile, header->env->from,
                        header->env->to, header->env->cc, header->env->subject);
              delete(tmpfile);
              if(MailSendErrorMess)
                       strcpy(errbuf, MailSendErrorMess);
        }
        else
          sprintf(errbuf, "\007Can't write temp file for sending: %s",
                  error_description(errno));
    } /* end section using VMS Mail MAIL$xxxxx interface */

    if(tmpfile)
      fs_give((void **)&tmpfile);

    return(*errbuf ? errbuf : NULL);
}


/* ----------------------------------------------------------------------
   Submit message file to the appropriate sendmail queue - VMS specific.

     Luigi Fonti
     CNAF INFN Bologna, Italy (Luigi.Fonti@cnaf.infn.it)

     Claudio Allocchio, 
     Sincrotrone Trieste, Italy (Claudio.Allocchio@elettra.trieste.it)

  Args: file     -- The file containing the complete message
        queue    -- The sendmail execution queue

  ----*/

char *
vms_sendmail_submit (char *file, char *queue)
{
   struct itmlst
   {
      short buflen, itmcod;
      char  *bufadr, *retadr;
   } submit_list[8];

   struct iosblk
   {
      long sts, zeroed;
   } iosb;

   static char *gv2     = "GV2$DIR:GIVEME2_SMTP_SUBMIT.COM";
   static char *jobuser = "SYSTEM";

   int sys$sndjbcw();
   int retcod = 0, dij, last, lf, lq;
   char *pi, *pj;

   lf = strlen(file);
   lq = strlen(queue);

   if (!strncmp(ucase(queue),"GV2$SMTP_",9))  /* VMS-Sendmail queue */
   {
      pi = strchr(file,']');		/* get time stamp for job name */
      if (!pi) pi = strchr(file,':');
      pj = strchr(pi,'.');
      dij = pj-pi-1;

      submit_list[0].buflen = lq;		/* prepare item list */
      submit_list[0].itmcod = SJC$_QUEUE;
      submit_list[0].bufadr = queue;
      submit_list[0].retadr = 0;

      submit_list[1].buflen = 31;
      submit_list[1].itmcod = SJC$_FILE_SPECIFICATION;
      submit_list[1].bufadr = gv2;
      submit_list[1].retadr = 0;

      submit_list[2].buflen = lf;
      submit_list[2].itmcod = SJC$_PARAMETER_1;
      submit_list[2].bufadr = file;
      submit_list[2].retadr = 0;

      submit_list[3].buflen = (dij > 1 ? dij : 1);
      submit_list[3].itmcod = SJC$_JOB_NAME;
      submit_list[3].bufadr = pi+1;
      submit_list[3].retadr = 0;

      submit_list[4].buflen = 0;
      submit_list[4].itmcod = SJC$_NO_LOG_SPECIFICATION;
      submit_list[4].bufadr = 0;
      submit_list[4].retadr = 0;

      submit_list[5].buflen = 6;
      submit_list[5].itmcod = SJC$_USERNAME;
      submit_list[5].bufadr = jobuser;
      submit_list[5].retadr = 0;

      last = 6;
   }
   else		/* we use MULTINET SMTP sendmail queue */
   {
      submit_list[0].buflen = lq;
      submit_list[0].itmcod = SJC$_QUEUE;
      submit_list[0].bufadr = queue;
      submit_list[0].retadr = 0;

      submit_list[1].buflen = lf;
      submit_list[1].itmcod = SJC$_FILE_SPECIFICATION;
      submit_list[1].bufadr = file;
      submit_list[1].retadr = 0;

      submit_list[2].buflen = 0;
      submit_list[2].itmcod = SJC$_DELETE_FILE;
      submit_list[2].bufadr = 0;
      submit_list[2].retadr = 0;

      last = 3;
   }

   submit_list[last].buflen = 0;   /* end of item list */
   submit_list[last].itmcod = 0;

   /* now submit message on queue */

   retcod = sys$sndjbcw(0,SJC$_ENTER_FILE,0,submit_list,&iosb,0,0);
   if (retcod) retcod = iosb.sts;

   if ((retcod & 1) == 0) 
      return "Error submitting message on queue";
   else
      return(NULL); /* success */
}
