home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / niftp / pn_wtmail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-11  |  16.9 KB  |  676 lines

  1. #include "util.h"
  2. #include "mmdf.h"
  3. /*                                                                      */
  4. /*                  CH_NIFTP: NIFTP MAIL DONOR CHANNEL                  */
  5. /*                                                                      */
  6. /*         This module does all the hard work for the donor channel     */
  7. /*              Chris Bennett University College London 24/2/81         */
  8. /*                                                                      */
  9. /*      Rewritten to incorporate new release MMDF stuff and             */
  10. /*      to generally streamline the code                                */
  11. /*              Steve Kille             July 1982                       */
  12. /*      SEK  Feb 84     Rewrite to reformat sender                      */
  13. /*
  14. /*                  CH_NIFTP: NIFTP MAIL DONOR CHANNEL                  */
  15.  
  16. #include <signal.h>
  17. #include "ch.h"
  18. #include "ap.h"
  19. #include "jnt.h"                /* JNT Mail return value definition     */
  20.  
  21. extern struct ll_struct   *logptr;
  22.  
  23. extern char     *pn_quedir;
  24.                 /* Location of JNTmail queues for NIFTP */
  25.  
  26. extern int      ap_outtype;     /* Default output format                */
  27.  
  28. extern Chan  *chanptr;          /* Current channel                      */
  29.  
  30.  
  31. char    *pn_chname;             /* Name of channel we are called as     */
  32. char    *pn_sender;             /* Sender of the message being processed*/
  33. char    *pn_msgfile;            /* name of file with message in         */
  34. char    pn_fname[ LINESIZE ];   /* Name of file for NIFTP output        */
  35. int     pn_fd;                  /* fd of NIFTP ouput file               */
  36. char    pn_curhost[ LINESIZE ]; /* Host being processed                 */
  37. short   firstadr;               /* Boolean - first address for host     */
  38.  
  39. char    jnt_hedsep[] = "\n\n";
  40.                 /* Separatpr between header and text    */
  41.                 /* for JNT mail                         */
  42. char    jnt_adrsep[] = ",\n"; /* Separator between addresses          */
  43.                 /* for JNT mail                         */
  44.  
  45. LOCVAR  int inheader;           /* flags for text copy                  */
  46. LOCVAR  int donesender;
  47.  
  48.                 /* This lot need to be glbal to allow   */
  49.                 /* the structure to be initialised      */
  50. LOCVAR  char TSname [LINESIZE];
  51.                 /* The TS address to be handed down     */
  52. LOCVAR char    senderbuf [LINESIZE];
  53. LOCVAR char    *vararray[] = {
  54.     "file", pn_fname,
  55.     "host", pn_curhost,
  56.     "adr",  TSname,
  57.     "sender", senderbuf,
  58.     0, 0
  59. };
  60.  
  61.  
  62. extern char *index ();
  63. extern char *blt ();
  64. extern char *ap_p2s();
  65.  
  66. /*
  67. */
  68.  
  69.  
  70. pn_init ()                        /* session initialization             */
  71. {
  72. #ifdef DEBUG
  73.     ll_log (logptr, LLOGBTR, "pn_init ()");
  74. #endif
  75.     return (RP_OK);
  76. }
  77.  
  78. pn_end (state)                   /* end of session                     */
  79. int     state;
  80. {
  81. #ifdef DEBUG
  82.     ll_log (logptr, LLOGBTR, "pn_end (%d)", state);
  83. #endif
  84.     return (RP_OK);               /* no-op                          */
  85. }
  86.  
  87. pn_sbinit ()                      /* ready for submission               */
  88. {
  89. #ifdef DEBUG
  90.     ll_log (logptr, LLOGBTR, "pn_sbinit()");
  91. #endif
  92.     return (RP_OK);
  93. }
  94.  
  95. pn_sbend ()                       /* end of submission                  */
  96. {
  97. #ifdef DEBUG
  98.     ll_log (logptr, LLOGBTR, "pn_sbend ()");
  99. #endif
  100.  
  101.     return (RP_OK);               /* no-op                          */
  102. }
  103.  
  104. /*             DELIVER MESSAGE TO NIFTP DONOR                          */
  105.  
  106.  
  107.  
  108.  
  109. pn_winit (chname, sender, msgfile)/* initialize for one message         */
  110. char    chname[],                 /* what channel coming in from        */
  111.     sender[],                 /* return address for error msgs      */
  112.     msgfile[];                /* name of file with msg text         */
  113. {
  114.     extern char *strdup ();
  115.     AP_ptr ap;
  116.     AP_ptr local,
  117.     domain,
  118.     route;
  119.  
  120. #ifdef DEBUG
  121.     ll_log (logptr, LLOGBTR, "pn_winit");
  122. #endif
  123.  
  124.     if (pn_chname != (char *) 0)
  125.     free (pn_chname);
  126.     pn_chname = strdup (chname);
  127.     if (pn_sender != (char *) 0)
  128.     free (pn_sender);
  129.     ap = ap_s2tree (sender);
  130.     if (ap != (AP_ptr) NOTOK)
  131.     {
  132.     ap_t2parts (ap, (AP_ptr *) 0, (AP_ptr *) 0, &local, &domain, &route);
  133.     pn_sender = ap_p2s ((AP_ptr) 0, (AP_ptr) 0, local, domain, route);
  134.     }
  135.             /* ap_outtype will have corect value*/
  136.  
  137.     else
  138.     ll_log (logptr, LLOGTMP,  "Illegal sender '%s'", sender);
  139.  
  140.     if (pn_msgfile != (char *) 0)
  141.     free (pn_msgfile);
  142.     pn_msgfile = strdup (msgfile);
  143.  
  144.     ll_log (logptr, LLOGFTR, "c='%s', s='%s', f='%s'",
  145.         pn_chname, (pn_sender==(char *)MAYBE)?"":pn_sender, pn_msgfile);
  146.  
  147.     if(pn_sender == (char *)MAYBE)
  148.     return (RP_NS);
  149.     return (RP_OK);
  150. }
  151.  
  152.  
  153. /*
  154. */
  155.  
  156. pn_wainit ()                           /* generate and open file        */
  157.                        /* needed befor we can start     */
  158.                        /* and get ready for next set of */
  159.                        /* addresses                     */
  160. {
  161.     extern char *mktemp ();     /* Stuff for filename genration         */
  162.     static char template[] = "niDDMM.aXXXXXX";
  163.     char fi[6];
  164.     struct tm *tm;
  165.     long ti;
  166.     short tries;
  167.     extern char *multcpy ();
  168.  
  169. #ifdef DEBUG
  170.     ll_log (logptr, LLOGBTR, "pn_wainit ()" );
  171. #endif
  172.  
  173.     firstadr = TRUE;            /* Ready for first host         */
  174.     ti = time(0);
  175.     tm = gmtime(&ti);
  176.     /* On a busy machine running a gateway, the PID's recycle quickly */
  177.     /* so add the month and the day to the file to allow this to happen */
  178.     if (template[2] == 'D') {
  179.          /* not sure the %02 is portable - if not then you */
  180.      /* will need to add some space detection code to */
  181.      /* assignments below */
  182.          (void) sprintf(fi, "%02d%02d", tm->tm_mon, tm->tm_mday);
  183.          template[2] = fi[0];
  184.          template[3] = fi[1];
  185.          template[4] = fi[2];
  186.          template[5] = fi[3];
  187.     }
  188. /* File name generation extracted from submit.
  189.  * make the unique part of the queue entry file name.  if mktemp
  190.  * can't do it, goose the value of the first char in the filename
  191.  * part.  mktemp uses qf_mfname, rather than qf_filnam, so that its
  192.  * stat() can accurately tell if the name is unique.  the goosing
  193.  * strategy permits up to 1352 messages under the same process id.
  194.  * mmdf will probably fall apart before that limit is hit.
  195.  */
  196.     for (tries = 51; tries-- >= 0; template[7]++)
  197.     {                             /* template[7] limited to lower/upper  */
  198.     multcpy (pn_fname, pn_quedir, "/", template, (char *)0);
  199.                   /* add standard part of unique name   */
  200.     if (strcmp (mktemp(pn_fname), "/") != 0)
  201.         break;                /* add unique part                    */
  202.         if (template[7] == 'z')
  203.         template[7] = 'A' - 1; /* Case change - allow the ++ above */
  204.     }
  205. #ifdef DEBUG
  206.     ll_log (logptr, LLOGFTR, "JNT mail file is = \"%s\"", pn_fname);
  207. #endif
  208.  
  209.     if (rp_isbad (pn_fd = creat (pn_fname, 0444)))
  210.     {
  211.     ll_err (logptr, LLOGBTR, "Failure to open file" );
  212.     return (RP_FCRT);
  213.     }
  214.  
  215.     return (RP_OK);
  216. }
  217. /*
  218. /*      Process individual address                                      */
  219. /*      Produce JNT style address from host and address and place       */
  220. /*      into file.  "," separator if not first one                      */
  221.  
  222. extern      AP_ptr ap_s2tree ();
  223.  
  224. pn_wadr (host, adr)
  225. char    *host;          /* host official name                           */
  226. char    *adr;           /* rest of address / route                      */
  227. {
  228.     char        *jntadr;    /* 733 /JNT format address              */
  229.     int         len;
  230.  
  231. #ifdef DEBUG
  232.     ll_log (logptr, LLOGBTR, "pn_wadr (h= '%s' a= '%s')", host, adr);
  233. #endif
  234.  
  235.     jntadr = adr;
  236.     ll_log (logptr, LLOGFST, "JNT address = '%s'", jntadr);
  237.  
  238.     if (firstadr)
  239.     {
  240.     firstadr = FALSE;
  241.     strcpy (pn_curhost, host);
  242.     }
  243.     else
  244.     {
  245.     len = strlen (jnt_adrsep);
  246.     if (write (pn_fd, jnt_adrsep, len) != len)
  247.     {
  248.         ll_err (logptr, LLOGBTR, "File write error (separator)" );
  249.         return (RP_FIO);
  250.     }
  251.     }
  252.     len = strlen(jntadr);
  253.     if (write (pn_fd, jntadr, len) != len)
  254.     {
  255.     ll_err (logptr, LLOGBTR, "File write error" );
  256.     return (RP_FIO);
  257.     }
  258.  
  259.     return (RP_AOK );
  260. }
  261.  
  262. /*
  263. */
  264. LOCVAR  char partialbuf [LINESIZE];
  265.  
  266. pn_wtinit()
  267.                 /* End of addres list for this host     */
  268.                 /* Write separtator between address     */
  269.                 /* and start of body                    */
  270. {
  271.     int     len;
  272. #ifdef DEBUG
  273.     ll_log (logptr, LLOGBTR, "pn_wtinit ()");
  274. #endif
  275.  
  276.     inheader  = TRUE;
  277.     donesender = FALSE;
  278.     partialbuf [0] = '\0';
  279.     ap_outtype = chanptr -> ch_apout;
  280.     len = strlen (jnt_hedsep);
  281.     if (write (pn_fd, jnt_hedsep, len) != len)
  282.     {
  283.         ll_err (logptr, LLOGBTR, "Failure writing separator" );
  284.         return (RP_FIO);
  285.     }
  286.  
  287.     return(RP_OK);
  288. }
  289. /*
  290. */
  291.  
  292. #ifndef VIATRACE
  293.  
  294. LOCVAR char *txt_sender = "Sender: ";
  295. LOCVAR char *txt_original = "Original-";
  296.                 /* Write block of text to file          */
  297. pn_wtxt (buffer, len)
  298. char *buffer;
  299. int len;
  300. {
  301.     int retval;
  302.     char  *front;
  303.     char  *back;
  304.     char  csav;
  305. #ifdef DEBUG
  306.     ll_log (logptr, LLOGBTR, "pn_wttxt()");
  307. #endif
  308.                 /* whilst in header split into lines */
  309.                 /*for reformatting                   */
  310.  
  311.     if (inheader)
  312.     {
  313.     back = index (buffer, '\n');
  314.     if (back == (char *) 0)
  315.     {
  316.         strcat (partialbuf, buffer);
  317.         return (RP_OK);
  318.     }
  319.     back++;
  320.     csav = *back;
  321.     *back = '\0';
  322.     strcat (partialbuf, buffer);
  323.     if (rp_isbad (retval = pn_whdr (partialbuf, strlen (partialbuf))))
  324.        return (retval);
  325.     *back = csav;
  326.  
  327.  
  328.     while ((front = index (back, '\n')) != (char *) 0)
  329.     {
  330.         front++;
  331.         csav = *front;
  332.         *front = '\0';
  333.         if (rp_isbad (retval = pn_whdr (back, strlen (back))))
  334.         return (retval);
  335.         *front = csav;
  336.         back = front;
  337.     }
  338.     if (!inheader)  /* reached end of header                */
  339.        return (pn_wtxt (back, strlen (back)));
  340.     strcpy (partialbuf, back);
  341.     return (RP_OK);
  342.     }
  343.     else
  344.     {
  345.     if (write (pn_fd, buffer, len) != len)
  346.     {
  347.         ll_err (logptr, LLOGBTR, "Failure writing text to file" );
  348.         return (RP_FIO);
  349.     }
  350.     }
  351.     return(RP_OK);
  352. }
  353.  
  354.  
  355. /*  */
  356.  
  357.             /* take  single line and mungle it      */
  358.  
  359. LOCFUN pn_whdr (buffer, len)
  360. char *buffer;
  361. int  len;
  362. {
  363.     int namlen;
  364.     char *cp;
  365.     char name [LINESIZE];
  366.     AP_ptr  ap,
  367.         local,
  368.         domain,
  369.         route;
  370.  
  371. #ifdef DEBUG
  372.     ll_log (logptr , LLOGFTR, "pn_whdr ('%s',%d)", buffer,  len);
  373. #endif
  374.  
  375.     if (inheader)
  376.     {
  377.     if (buffer [0] == '\n')
  378.     {
  379.          inheader = FALSE;
  380.          if (!donesender)
  381.          {
  382. #ifdef DEBUG
  383.         ll_log (logptr, LLOGBTR, "Outputting new sender '%s'",
  384.                 pn_sender);
  385. #endif
  386.         namlen = strlen (txt_sender);
  387.         if (write (pn_fd, txt_sender, namlen) != namlen)
  388.         {
  389.             ll_err (logptr, LLOGBTR, "Failure writing text to file" );
  390.             return (RP_FIO);
  391.         }
  392.         namlen = strlen (pn_sender);
  393.         if (write (pn_fd, pn_sender, namlen) != namlen)
  394.         {
  395.             ll_err (logptr, LLOGBTR, "Failure writing text to file" );
  396.             return (RP_FIO);
  397.         }
  398.         if (write (pn_fd, "\n\n", 2) != 2)
  399.         {
  400.             ll_err (logptr, LLOGBTR, "Failure writing text to file" );
  401.             return (RP_FIO);
  402.         }
  403.         }
  404.         else
  405.         if (write (pn_fd, "\n", 1) != 1)
  406.         {
  407.             ll_err (logptr, LLOGBTR, "Failure writing text to file" );
  408.             return (RP_FIO);
  409.         }
  410.         return (RP_OK);
  411.     }
  412.  
  413.                 /* Now get name of line                 */
  414.                 /* just output continuations at once    */
  415.     if (!isspace (buffer [0]) &&
  416.         (cp = index (buffer, ':')) != (char *) 0)
  417.     {
  418.         namlen = cp - buffer;
  419.         blt (buffer, name, namlen);
  420.         name [namlen]= '\0';
  421.         if (lexequ (name, "via"))
  422.         {
  423.         namlen = strlen (txt_original);
  424.         if (write (pn_fd, txt_original, namlen) != namlen)
  425.         {
  426.             ll_err (logptr, LLOGBTR, "Failure writing text to file" );
  427.             return (RP_FIO);
  428.         }
  429.         }
  430.  
  431.         if (lexequ (name, "from"))
  432.         {
  433.         ap = ap_s2tree (cp + 1);
  434.         if (ap  != (AP_ptr) NOTOK)
  435.         {
  436.             ap_t2parts (ap, (AP_ptr *) 0, (AP_ptr *) 0,
  437.                 &local, &domain, &route);
  438.             cp = ap_p2s ((AP_ptr) 0, (AP_ptr) 0,
  439.                 local, domain, route);
  440.             if(cp == (char *)MAYBE)
  441.             return (RP_NS);
  442.             if (lexequ (pn_sender, cp))
  443.             {
  444.             donesender = TRUE;
  445. #ifdef DEBUG
  446.             ll_log (logptr, LLOGFTR, "Found matching From '%s'",
  447.                 cp);
  448. #endif
  449.             }
  450.             free (cp);
  451.         }
  452.         }
  453.  
  454.         if (lexequ (name, "sender"))
  455.         {
  456.         ap = ap_s2tree (cp + 1);
  457.         if (ap  != (AP_ptr) NOTOK)
  458.         {
  459.             ap_t2parts (ap, (AP_ptr *) 0, (AP_ptr *) 0,
  460.                 &local, &domain, &route);
  461.             cp = ap_p2s ((AP_ptr) 0, (AP_ptr) 0,
  462.                 local, domain, route);
  463.             if(cp == (char *)MAYBE)
  464.             return (RP_NS);
  465.             if (lexequ (pn_sender, cp))
  466.             {
  467.             donesender = TRUE;
  468.  
  469. #ifdef DEBUG
  470.                ll_log (logptr, LLOGFTR, "Found matching Sender '%s'",
  471.                 cp);
  472. #endif
  473.             }
  474.             else
  475.             {
  476.             donesender = FALSE;
  477.                     /* in case a matchin From: field */
  478.             namlen = strlen (txt_original);
  479.             if (write (pn_fd, txt_original, namlen) != namlen)
  480.             {
  481.                 ll_err (logptr, LLOGBTR,
  482.                 "Failure writing text to file" );
  483.                 return (RP_FIO);
  484.             }
  485.             }
  486.             free (cp);
  487.         }
  488.         }
  489.     }
  490.     }
  491.     if (write (pn_fd, buffer, len) != len)
  492.     {
  493.     ll_err (logptr, LLOGBTR, "Failure writing text to file" );
  494.     return (RP_FIO);
  495.     }
  496.     return(RP_OK);
  497. }
  498.  
  499. #else VIATRACE
  500.  
  501. /*
  502. */
  503.                 /* Write block of text to file          */
  504.                 /* simple non-munging version           */
  505. pn_wtxt (buffer, len)
  506. char *buffer;
  507. int len;
  508. {
  509. #ifdef DEBUG
  510.     ll_log (logptr, LLOGBTR, "pn_wttxt()");
  511. #endif
  512.  
  513.     if (write (pn_fd, buffer, len) != len)
  514.     {
  515.         ll_err (logptr, LLOGBTR, "Failure writing text to file" );
  516.         return (RP_FIO);
  517.     }
  518.  
  519.     return(RP_OK);
  520. }
  521. #endif VIATRACE
  522. /*
  523. /*      End of text                                                     */
  524. /*      Close file and pass to NIFTP                                    */
  525. /*      The host name is translated into the standard UCL TS address    */
  526. /*      of the form TSservice/hostaddres/service (e.g. tcp/isid/mail    */
  527.  
  528.  
  529. pn_wtend (tmp_result)
  530. int     tmp_result;
  531. {
  532. int     i;
  533. char    *p,*q;
  534. int     pid;                    /* Process id for fork                  */
  535. int     status;                 /* Status for wait                      */
  536. char    buf [LINESIZE];
  537. int     argc;
  538. char    *argv[50];
  539. extern  char *expand();
  540.  
  541. #ifdef DEBUG
  542.     ll_log (logptr, LLOGBTR, "pn_wtend ()");
  543. #endif
  544.  
  545.     if (close(pn_fd) == NOTOK)         /* close file                   */
  546.     {
  547.     ll_err (logptr, LLOGBTR, "Failure to close file" );
  548.     return (RP_LIO);
  549.     }
  550.  
  551.                 /* if status so far is bad unlink file  */
  552.                 /* and pass on                          */
  553.     if (rp_isbad (tmp_result))
  554.     {
  555.     if (unlink (pn_fname) == NOTOK) /* delete file */
  556.     {
  557.         ll_err (logptr, LLOGFAT, "Failure to unlink file '%s'", pn_fname);
  558.         return (RP_FOPN);
  559.     }
  560.     ll_log (logptr, LLOGBTR, "Failure (%s) for file '%s'",
  561.         rp_valstr (tmp_result), pn_fname);
  562.     return (tmp_result);
  563.     }
  564.  
  565.                 /* Now extract the TS address           */
  566.     if (tb_k2val (chanptr->ch_table, TRUE,
  567.     (chanptr->ch_host == NORELAY ? pn_curhost :  chanptr->ch_host),
  568.     TSname)!=OK)
  569.     {
  570.     ll_err (logptr,  LLOGBTR, "TS address not found for '%s'",
  571.                                  pn_curhost );
  572.     return (RP_PARM);
  573.     }
  574.  
  575.                 /* 'quote' chars in sender              */
  576.     for (p=pn_sender, q=senderbuf; *p != '\0';)
  577.     {
  578.      switch (*p)
  579.      {
  580.         case '\"':
  581.         case '\\':
  582.         *q++ = '\\';
  583.         *q++ = *p++;
  584.         break;
  585.         default:
  586.         *q++ = *p++;
  587.         break;
  588.     }
  589.     }
  590.     *q = '\0';
  591.                 /* Now build execl string using         */
  592.                 /* ch_ipcsstring as format              */
  593.     expand  (buf, chanptr -> ch_confstr, vararray);
  594.     ll_log (logptr, LLOGFST, "execl (%s)", buf);
  595.  
  596.     argc = cstr2arg (buf, 50, argv, ' ');
  597.  
  598. #ifdef DEBUG
  599.     ll_log (logptr, LLOGFTR, "n=(%d) 0='%s', 1='%s', 2='%s', 3='%s', 4='%s'",
  600.         argc, argv[0], argv[1], argv[2], argv[3], argv[4]);
  601. #endif
  602.  
  603.  
  604.     if  ((pid = fork()) == NOTOK)
  605.     {
  606.     ll_err (logptr, LLOGTMP, "Unable to fork for %s", argv[0]);
  607.     if (unlink (pn_fname) == NOTOK) /* delete file */
  608.     {
  609.         ll_err (logptr, LLOGFAT, "Failure to unlink file '%s'", pn_fname);
  610.         return (RP_FOPN);
  611.     }
  612. #ifdef DEBUG
  613.     ll_log (logptr, LLOGFTR, "File: %s deleted", pn_fname);
  614. #endif
  615.     return (RP_NET);
  616.     }
  617.     if (pid == 0)               /* In child so do execl                 */
  618.     {
  619.  
  620. ll_log (logptr, LLOGFTR, "In the child");
  621.                 /* Close down all of the pipes to child  */
  622.  
  623.     signal (SIGHUP, SIG_IGN);
  624.     signal (SIGINT, SIG_IGN);
  625.     signal (SIGQUIT, SIG_IGN);
  626.  
  627.     for (i = _NFILE - 1; i > 0; i--)
  628.         close (i);
  629.     open("/dev/null", 2);
  630.     open("/dev/null", 1);
  631.  
  632.     execv (argv[0], &argv[1]);
  633.  
  634.     ll_log (logptr, LLOGTMP, "Unable to execl %s", argv[0]);
  635.     exit (-1);
  636.     }
  637.  
  638.     alarm (300);                 /* The NIFTP is not file size          */
  639.                  /* dependent so 5 mins is ample        */
  640.     status = pgmwait (pid);      /* Parent waits for child              */
  641.     alarm (0);
  642.  
  643.     if (status != JNT_OK)
  644.     {                           /* Killed by alarm or general failure   */
  645.     if (unlink (pn_fname) == NOTOK) /* delete file */
  646.     {
  647.         ll_err (logptr, LLOGFAT, "Failure to unlink file '%s'", pn_fname);
  648.         return (RP_FOPN);
  649.     }
  650. #ifdef DEBUG
  651.     ll_log (logptr, LLOGFTR, "File: %s deleted", pn_fname);
  652. #endif
  653.     switch (status)
  654.     {
  655.         case JNT_TEMP:
  656.         default:            /* temporary error                      */
  657.         ll_log (logptr, LLOGTMP,
  658.         "Temporary failure (%d) for file: '%s' - requeued, h='%s'",
  659.             status, pn_fname, pn_curhost);
  660.         return (RP_DHST);
  661.  
  662.  
  663.         case JNT_PERM:      /* permanent error                     */
  664.         ll_log (logptr, LLOGTMP,
  665.             "Permanent USP failure (%d) - rejected", status);
  666.         return (RP_NDEL);
  667.     }
  668.     }
  669.  
  670.  
  671.     ll_log (logptr, LLOGFST, "Result is GOOD (%d)", status);
  672.                  /* For NIFTP evidence                  */
  673.  
  674.     return(RP_MOK);
  675. }
  676.