modules/mm/mm.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. MM_store
  2. MM_get_msg_headers
  3. MM_extract_mime
  4. is_supported_MIMEtype
  5. dispatch_to_driver
  6. parse_text_plain
  7. parse_message_rfc822
  8. parse_multipart_alternative
  9. parse_multipart_signed
  10. status
  11. get_mail_hdr_field
  12. get_header_line
  13. write_file
  14. read_file
  15. put_in_file
  16. do_regex_test
  17. mm_searched
  18. mm_exists
  19. mm_expunged
  20. mm_flags
  21. mm_notify
  22. mm_list
  23. mm_lsub
  24. mm_status
  25. mm_log
  26. mm_dlog
  27. mm_login
  28. mm_critical
  29. mm_nocritical
  30. mm_diskerror
  31. mm_fatal

   1 /***************************************
   2   $Revision: 2.29 $
   3 
   4   mm - MIME Parser module. Functions to parse a mail message part,
   5   find if it is MIME-encapsulated, dispatch the part to the
   6   appropriate drivers (also included) and return tree nodes 
   7   with all MIME information.
   8 
   9   Status: COMPLETE, NOT REVUED, TESTED
  10 
  11   Design and implementation by: daniele@ripe.net
  12 
  13   ******************/ /******************
  14   Copyright (c) 2000,2001,2002                       RIPE NCC
  15  
  16   All Rights Reserved
  17   
  18   Permission to use, copy, modify, and distribute this software and its
  19   documentation for any purpose and without fee is hereby granted,
  20   provided that the above copyright notice appear in all copies and that
  21   both that copyright notice and this permission notice appear in
  22   supporting documentation, and that the name of the author not be
  23   used in advertising or publicity pertaining to distribution of the
  24   software without specific, written prior permission.
  25   
  26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  32   ***************************************/
  33 
  34 /* Pieces of this code stolen and/or adapted from mtest.c, 
  35  * part of the IMAP toolkit by Mark Crispin:
  36  */
  37 
  38 /* Original version Copyright 1988 by The Leland Stanford Junior University
  39  * Copyright 1999 by the University of Washington
  40  *
  41  *  Permission to use, copy, modify, and distribute this software and its
  42  * documentation for any purpose and without fee is hereby granted, provided
  43  * that the above copyright notices appear in all copies and that both the
  44  * above copyright notices and this permission notice appear in supporting
  45  * documentation, and that the name of the University of Washington or The
  46  * Leland Stanford Junior University not be used in advertising or publicity
  47  * pertaining to distribution of the software without specific, written prior
  48  * permission.  This software is made available "as is", and
  49  * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
  50  * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
  51  * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  52  * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
  53  * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
  54  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  55  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  56  * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
  57  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  58  *
  59  */
  60 
  61 
  62 
  63 /**************************
  64 
  65 
  66 "Every program attempts to expand until it can read mail.
  67  Those programs which cannot so expand are replaced by
  68  ones which can."
  69                 (Jamie Zawinski)
  70 
  71 
  72 **************************/
  73 
  74 
  75 #include "rip.h"
  76 
  77 /* Standard headers */
  78 #include <stdio.h>
  79 #include <signal.h>
  80 #include <string.h>
  81 #include <sys/time.h>
  82 #include <sys/types.h>
  83 /* #include <sys/param.h> */
  84 #include <netdb.h>
  85 #include <regex.h>
  86 #include <unistd.h>
  87 
  88 /* c-client headers */
  89 #include "misc.h"
  90 
  91 
  92 /* 
  93  * Globals to store shared data for tree nodes 
  94  * These variables come from EP 
  95  */
  96 
  97 extern char EP_outputPrefix[FILENAME_LENGTH];
  98 extern char EP_keyRing[FILENAME_LENGTH];
  99 extern int EP_TreeHeight;
 100 extern int  EP_Node_ID;
 101 
 102 /* Global variables to be used in this module */
 103 long debug = DEFAULT_DEBUG;
 104 
 105 char *supported_MIME_types[MAXSUPPTYPES] = {
 106   "UNKNOWN/UNKNOWN", "TEXT/PLAIN", "APPLICATION/PGP", "MULTIPART/SIGNED", 
 107   "MULTIPART/MIXED", "MULTIPART/ALTERNATIVE", "MULTIPART/DIGEST",
 108   "MESSAGE/RFC822"
 109 };
 110 
 111 long pass = 0;
 112 
 113 
 114 /* 
 115    FIXMEs:
 116    - Revise the whole debug system, debug messages etc. - right now
 117      an enormous and globally useless quantity of information is dumped.
 118 */
 119 
 120 
 121 /*+++++++++++++++++++++++++++++++++++++++
 122  
 123   API functions
 124  
 125   +++++++++++++++++++++++++++++++++++++++*/
 126 
 127 
 128 
 129 /*++++++++++
 130  *
 131  * MM_store(). Stores a file (or stdin) in another file,
 132  * "escaping" the lines starting with "From " by adding
 133  * a ">" sign. This is necessary because we need to deal
 134  * with files that are "unix mailboxes".
 135  *
 136  * This function puts a limit to the line size that a mail
 137  * message may have; officially, there is no limit to this size,
 138  * but we prefer to add this limit to avoid buffer overflow.
 139  * The line size limit is MAXBUFSIZE, defined in mm.h .
 140  *
 141  ++++++++++*/
 142 
 143 
 144 int MM_store (char *source_file, char *destination_file, long custom_debug)
     /* [<][>][^][v][top][bottom][index][help] */
 145 {
 146 
 147 
 148 /* The regexp we will be looking for */
 149 #define REGEXP "^From "
 150 
 151 
 152   char line[MAXBUFSIZE];
 153   FILE *ifp;
 154   FILE *ofp;
 155   FILE *actualfile; /* Actual "file" to be opened (can be stdin) */
 156   char *tmpstr;
 157   short using_file = 0;
 158   long numlines = 0;
 159   time_t ti = time (0);
 160 
 161 
 162 
 163   if (custom_debug)
 164     debug = custom_debug;
 165 
 166   /* Check if we need to parse a file or stdin.
 167    * We parse stdin if source_file is "-" . 
 168    */
 169 
 170   if (strcmp(source_file,"-"))
 171     {
 172       if ((ifp = fopen(source_file,"r")) != NULL)
 173         {
 174           ER_dbg_va (FAC_MM, ASP_MM_GEN, "MM_store: input file %s",source_file);
 175           actualfile = ifp;
 176           using_file = 1;
 177         }
 178       else
 179         {
 180           /* XXX Use perror to state reason? */
 181           ER_perror(FAC_MM, MM_CANTOPEN, "%s for reading", source_file);
 182           die;
 183         }
 184     }
 185   else
 186     {
 187       ER_dbg_va (FAC_MM, ASP_MM_GEN, "MM_store: input from stdin");
 188       actualfile = stdin;
 189     }
 190 
 191   if ((ofp = fopen(destination_file,"w")) != NULL)
 192     {
 193       while ((tmpstr = fgets(line, MAXBUFSIZE, actualfile)) != NULL)
 194         {
 195           numlines++;
 196           if (strlen(line) >= MAXBUFSIZE - 1)
 197             {
 198               ER_inf_va(FAC_MM, ASP_MM_SEC, "Line too long error. Possible buffer overflow attempt.");
 199               ER_perror(FAC_MM, MM_LINETOOLONG, "%ld",numlines);
 200               /* XXX Should be handled better - report line too long to caller,
 201                  so that a failed ack can be sent */
 202               die;
 203             }
 204           if (numlines == 1)
 205             {
 206               /* If the first line is not a "^From " line, put a fake one */
 207               if (!do_regex_test(REGEXP,(char *)line))
 208                   fprintf (ofp,"From dbase@whois.ripe.net %s",ctime (&ti));
 209               fputs (line,ofp);
 210             }
 211           else
 212             {
 213               if (do_regex_test(REGEXP,(char *)line)) fprintf (ofp,">");
 214               fputs (line,ofp);
 215             }
 216         }
 217       fclose(ofp);
 218       if (using_file) fclose(ifp);
 219       return(0);
 220     }
 221   else
 222     {
 223       /* XXX Use perror to state reason? */
 224       ER_perror(FAC_MM, MM_CANTOPEN, "%s for writing", destination_file);
 225       die;
 226     }
 227 
 228   /* Even though we should never get here... */
 229   return(0);
 230 
 231 } /* MM_store() */
 232 
 233 
 234 
 235 /**********
 236  *
 237  * MM_get_msg_headers(). Get the headers of a mail contained in a file.
 238  *
 239  **********/
 240 
 241 int MM_get_msg_headers(
     /* [<][>][^][v][top][bottom][index][help] */
 242                    const char *mail_file,                       /* Input mail file */
 243                    EP_Mail_Descr *mail_descr,           /* Structure containing the headers */
 244                    long mesgno,                         /* msg number in the input file */
 245                    long custom_debug                    /* debug level */
 246                    )
 247 {
 248   MAILSTREAM *stream = NULL;            /* MAILSTREAM is defined in c-client */
 249   char tmp[MAILTMPLEN];                 /* MAILTMPLEN is set in c-client */
 250   int retcode;                          /* return code of the subroutine */
 251   STRINGLIST *lines;                    /* STRINGLIST is defined in c-client */
 252   STRINGLIST *cur;
 253   BODY *body;
 254 
 255 #include "linkage.c"            /* c-client requires it to be included... */
 256 
 257 
 258   /* If the supplied debug level is not null, then the global debug level
 259    * takes that value 
 260    */
 261   if (custom_debug)
 262     debug = custom_debug;
 263 
 264 
 265   /* open mailbox and get the mail stream */
 266   sprintf (tmp, "%s", mail_file);
 267   stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
 268 
 269   /* Process the stream */
 270   if (!stream)
 271     {
 272       ER_perror(FAC_MM, MM_INVMBX, "%s", mail_file);
 273       die;
 274     }
 275   else
 276     {
 277       ER_inf_va (FAC_MM, ASP_MM_GEN, "Getting message headers.");
 278       ER_dbg_va (FAC_MM, ASP_MM_GEN, "Message status:");
 279       status (stream);                  /* report message status */
 280       ER_dbg_va (FAC_MM, ASP_MM_GEN, "End of message status.");
 281       
 282       /* Get the headers */
 283 
 284       lines = mail_newstringlist ();      
 285       cur = lines;
 286       
 287       /* Get information about the mentioned lines in the header */
 288 
 289 
 290       mail_descr->from = get_mail_hdr_field(stream, mesgno, cur, "From");
 291 
 292       mail_descr->subject = get_mail_hdr_field(stream, mesgno, cur, "Subject");
 293 
 294       mail_descr->date = get_mail_hdr_field(stream, mesgno, cur, "Date");
 295       
 296       mail_descr->message_id = get_mail_hdr_field(stream, mesgno, cur, "Message-Id");
 297       
 298       mail_descr->reply_to = get_mail_hdr_field(stream, mesgno, cur, "Reply-To");
 299       
 300       mail_descr->cc = get_mail_hdr_field(stream, mesgno, cur, "Cc");
 301       
 302 
 303 
 304       mail_descr->content_type = (Mail_Header_Field *)UT_malloc(sizeof(Mail_Header_Field));
 305       /* This gets all the line (with encoding etc.) */
 306       /* mail_descr->content_type = get_mail_hdr_field(stream,mesgno,cur,"Content-Type"); */
 307 
 308       /* This only gets the content-type itself in canonized form: */
 309       mail_fetchstructure(stream,mesgno,&body);
 310       if (body)
 311         {
 312           mail_descr->content_type->field = (char *)UT_malloc(STR_M);
 313           mail_descr->content_type->next = NULL;
 314           sprintf(mail_descr->content_type->field,"%s",body_types[body->type]);
 315           if (body->subtype)
 316             sprintf(mail_descr->content_type->field+strlen(mail_descr->content_type->field),"/%s",body->subtype);
 317           sprintf(mail_descr->content_type->field+strlen(mail_descr->content_type->field),"\n\n");
 318         }
 319       
 320       mail_free_stringlist (&lines);
 321       
 322       ER_inf_va (FAC_MM, ASP_MM_GEN, "Got message headers.");
 323       
 324 
 325 
 326       mail_close(stream);
 327 
 328       retcode = 0;
 329 
 330       
 331     }
 332 
 333 
 334   return(retcode);
 335 
 336 } /* MM_get_msg_headers() */
 337 
 338 
 339 
 340 /* 
 341  * MM_extract_mime(): extract MIME information
 342  * This function was inspired by display_body() in mtest.c,
 343  * in the IMAP distribution. It has been largely re-engineered
 344  * to support MIME, and be modular.
 345  * It now only acts as an initializer of the mail stream,
 346  * sending then the stream to be dispatched to the appropriate
 347  * MIME drivers.
 348  */
 349 
 350 
 351 
 352 
 353 int MM_extract_mime (
     /* [<][>][^][v][top][bottom][index][help] */
 354                      const char *sourcefile,                    /* Input file containing the mail */
 355                      char *pfx,                         /* "prefix": this can be NULL at the
 356                                                          * first call of the function */
 357                      EP_mail_node *mailnode,            /* initialized node where to stock info */
 358                      long custom_debug                  /* debug level */
 359                      )
 360 {
 361 
 362   MAILSTREAM *stream = NULL;            /* MAILSTREAM is defined in c-client */
 363   BODY *body;                           /* BODY is defined in c-client */
 364   char tmp[MAILTMPLEN];                 /* MAILTMPLEN is set in c-client */
 365   int retcode = 0;                      /* return code of the subroutine */
 366   long mesgno = 1;
 367 
 368 
 369 #include "linkage.c"            /* c-client requires it to be included... */
 370 
 371   /* 
 372    * This (global) variable counts the number of times we pass through
 373    * MM_extract_mime().
 374    * It is useful in generating unique temporary files (see below).
 375    */
 376 
 377   pass++;
 378   ER_inf_va (FAC_MM, ASP_MM_GEN, "MM_extract_mime, pass %ld",pass);
 379 
 380   if (custom_debug)
 381     debug = custom_debug;
 382 
 383   /* ER_dbg_va (FAC_MM, ASP_MM_GEN, " EP_outputPrefix: %s",EP_outputPrefix);
 384      ER_dbg_va (FAC_MM, ASP_MM_GEN, " EP_keyRing: %s",EP_keyRing); */
 385 
 386 
 387   /* open file and get the mail stream from there*/
 388 
 389   sprintf (tmp, "%s", sourcefile);
 390   
 391   stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
 392 
 393   /* Process the stream */
 394   if (!stream)
 395     {
 396       ER_perror(FAC_MM, MM_INVMBX, "%s", sourcefile);
 397       die;
 398     }
 399   else
 400     {
 401       if (debug >=2)
 402         {
 403           ER_inf_va (FAC_MM, ASP_MM_GEN, "Getting message headers.");
 404           ER_dbg_va (FAC_MM, ASP_MM_GEN, "Message status:");
 405           status (stream);                      /* report message status */
 406           ER_dbg_va (FAC_MM, ASP_MM_GEN, "End of message status.");
 407         }
 408       if (debug >= 2) 
 409         ER_dbg_va (FAC_MM, ASP_MM_GEN, "Calling mail_fetchstructure...");
 410       mail_fetchstructure (stream,mesgno,&body);
 411 
 412       if (body)
 413         {
 414           ER_dbg_va (FAC_MM, ASP_MM_GEN, "Got body, dispatching to drivers...");
 415           dispatch_to_driver(stream, body, pfx, mailnode);
 416         }
 417       
 418     }
 419 
 420   ER_dbg_va (FAC_MM, ASP_MM_GEN, "Closing the stream %s...",stream->mailbox);
 421   mail_close(stream);
 422   ER_dbg_va (FAC_MM, ASP_MM_GEN, "Stream Closed.");
 423   
 424 
 425   return(retcode);
 426 
 427 } /* MM_extract_mime() */
 428 
 429 
 430 
 431 /*********************************************/
 432 
 433 /***************************************
 434  *
 435  * End of API functions
 436  *
 437  ***************************************/
 438 
 439 
 440 
 441 /* Internal functions */
 442 
 443 t_MM_type is_supported_MIMEtype (BODY *body)
     /* [<][>][^][v][top][bottom][index][help] */
 444 {
 445 
 446   char *mimetype_string;
 447   char tmpstr[STR_S];
 448   char *tmptype = tmpstr;
 449   int i;
 450   t_MM_type mtypecode = 0;
 451 
 452   
 453   /* mimetype_string is the MIME type of the message */
 454   mimetype_string = (char *)UT_malloc(STR_S);
 455   sprintf (mimetype_string,"%s",body_types[body->type]);
 456   if (body->subtype)
 457     sprintf (mimetype_string + strlen(mimetype_string),"/%s",body->subtype);
 458 
 459   /* 
 460    * We cycle to compare the MIME type of the message
 461    * to each of the MIME types we support
 462    */
 463   i = 0;
 464   tmptype = supported_MIME_types[i];
 465 
 466   while ((i < MAXSUPPTYPES) && (tmptype))
 467     {
 468       if (!strcmp(tmptype,mimetype_string))
 469         {
 470           mtypecode = i;
 471           break;
 472         }
 473       tmptype = supported_MIME_types[++i];
 474     }
 475 
 476   UT_free(mimetype_string);
 477 
 478   return(mtypecode);
 479 
 480 } /* is_supported_MIMEtype() */
 481 
 482 
 483 
 484 /****
 485  *
 486  * dispatch_to_driver()
 487  * This function dispatches a message to the proper driver
 488  * which will parse it, following the MIME type
 489  *
 490  ****/
 491 
 492 void dispatch_to_driver(MAILSTREAM *stream, BODY *body, char *pfx, EP_mail_node *mailnode)
     /* [<][>][^][v][top][bottom][index][help] */
 493 {
 494 
 495   t_MM_type is_supported;
 496 
 497   is_supported = is_supported_MIMEtype(body);
 498   /* We assign the given MIME Type to the node */
 499   mailnode->MIMEContentType = is_supported;
 500 
 501 
 502   ER_dbg_va (FAC_MM, ASP_MM_GEN, " mailnode->MIMEContentType: %s",supported_MIME_types[mailnode->MIMEContentType]);
 503 
 504   if (!strcmp(supported_MIME_types[is_supported],"TEXT/PLAIN"))
 505     {
 506       parse_text_plain(stream, body, pfx, mailnode);
 507     }
 508   else if (!strcmp(supported_MIME_types[is_supported],"APPLICATION/PGP"))
 509     {
 510       parse_application_pgp(stream, body, pfx, mailnode);
 511     }
 512   else if (!strcmp(supported_MIME_types[is_supported],"MULTIPART/ALTERNATIVE"))
 513     {
 514       parse_multipart_alternative(stream, body, pfx, mailnode);
 515     }
 516   else if (!strcmp(supported_MIME_types[is_supported],"MULTIPART/MIXED"))
 517     {
 518       parse_multipart_mixed(stream, body, pfx, mailnode);
 519     }
 520   else if (!strcmp(supported_MIME_types[is_supported],"MULTIPART/SIGNED"))
 521     {
 522       parse_multipart_signed(stream, body, pfx, mailnode);
 523     }
 524   else if (!strcmp(supported_MIME_types[is_supported],"MULTIPART/DIGEST"))
 525     {
 526       parse_multipart_digest(stream, body, pfx, mailnode);
 527     }
 528   else if (!strcmp(supported_MIME_types[is_supported],"MESSAGE/RFC822"))
 529     {
 530       parse_message_rfc822(stream, body, pfx, mailnode);
 531     }
 532   else
 533     {
 534       /* It's not a supported MIMEtype... */
 535       parse_unknown_unknown(stream, body, pfx, mailnode);
 536     }
 537 
 538 } /* dispatch_to_driver() */
 539 
 540 
 541 void parse_text_plain(MAILSTREAM *stream, BODY *body, char *pfx, EP_mail_node *mailnode)
     /* [<][>][^][v][top][bottom][index][help] */
 542 {
 543 
 544   char tmp[MAILTMPLEN];
 545   char *mailtext;
 546 
 547   
 548   if (debug >= 2)
 549     ER_dbg_va (FAC_MM, ASP_MM_GEN, " Lines: %lu",body->size.lines);
 550 
 551   if (pfx == NULL)                      /* If top level, is not inside a multipart */
 552     {
 553       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "MAILNODE->FILE: %s",mailnode->file);
 554       /* The filename of the root node has to be redefined to the processed file */
 555       /* remove(mailnode->file); */ /* This causes complaints by mail_close() */
 556       UT_free(mailnode->file);
 557       mailnode->file = (char *)UT_malloc(FILENAME_LENGTH);
 558       sprintf(mailnode->file,"%s%d",EP_outputPrefix,mailnode->nodeID);
 559       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "MAILNODE->FILE: %s",mailnode->file);
 560     }
 561   else
 562 
 563   ER_dbg_va (FAC_MM, ASP_MM_GEN, " mailnode->file: %s",mailnode->file);
 564 
 565   /* Get the plain text contents of the message */
 566   mailtext = tmp;
 567   mailtext = mail_fetchtext(stream, 1);
 568 
 569   if (debug >= 2)
 570     {
 571       ER_dbg_va (FAC_MM, ASP_MM_GEN, "Message contents:");
 572       ER_dbg_va (FAC_MM, ASP_MM_GEN, "\n\n%s\n",mailtext); 
 573     }
 574       
 575 
 576   /* Place the results in the file pointed by the node*/
 577   write_file(mailnode->file,mailtext,strlen(mailtext));
 578 
 579   PA_ParseMessage(mailnode);
 580 
 581   /* if (debug) printf ("mailnode->nodeID: %d\n",mailnode->nodeID); */
 582   /* if (debug) printf ("mailnode->MIMEContentType: %d\n",mailnode->MIMEContentType); */
 583 
 584 }
 585 
 586 void parse_message_rfc822(MAILSTREAM *stream, BODY *body, char *pfx, EP_mail_node *mailnode)
     /* [<][>][^][v][top][bottom][index][help] */
 587 {
 588 
 589   /* The idea here is to strip the message/rfc822 part from its mail headers,
 590    * and store it in a file to resend to MM_extract_mime().
 591    */
 592 
 593   char tmp[MAILTMPLEN];
 594   char *mailtext;
 595   char *content;
 596   char tmpfile[FILENAMELEN];
 597   time_t ti = time (0);
 598   
 599   
 600   if (pfx == NULL)                      /* If top level, is not inside a multipart */
 601     {
 602       /* pfx = (char *)UT_malloc(STR_L);
 603       pfx = "";         */      /* Dummy prefix */
 604       /* The filename of the root node has to be redefined to the processed file */
 605       mailnode->file = (char *)UT_malloc(FILENAME_LENGTH);
 606       sprintf(mailnode->file,"%s%d",EP_outputPrefix,mailnode->nodeID);
 607       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "MAILNODE->FILE: %s",mailnode->file);
 608     }
 609 
 610   /* Get the plain text contents of the message */
 611   mailtext = tmp;
 612   mailtext = mail_fetchtext(stream, 1);
 613 
 614 
 615   /* This buffer has to be dumped in a file from where it will be read by MM_extract_mime():
 616    * another stream will be opened, so the format of the file must be correct.
 617    * The LINELENGTH is to take the first 2 lines into account.
 618    */
 619 
 620   content = (char *)UT_malloc(2*LINELENGTH + strlen(mailtext) + 2);
 621   sprintf (content,"From dbase@whois.ripe.net %s",ctime (&ti));
 622   sprintf (content+strlen(content), "%s\n", mailtext);
 623      
 624 
 625   /* Generation of a temporary file:
 626    * The file must be unique inside the process. If we rewrite
 627    * on the same tmp file, which is used as a mailbox by c-client,
 628    * the c-client library has problems because it sees the mailbox changes
 629    * (I had problems with multipart/digest and message/rfc822).
 630    * "pass" is a global variable which increases every time we pass
 631    * through MM_extract_mime(): it should hence be unique each time
 632    * we call a driver.
 633    */
 634   sprintf (tmpfile,"%s.tmp.%ld",mailnode->file,pass);
 635   write_file(tmpfile,content,strlen(content));
 636 
 637   MM_extract_mime(tmpfile, pfx, mailnode, debug);
 638 
 639   /* Clean up... */
 640   UT_free(content);
 641   remove(tmpfile);
 642 
 643 }
 644 
 645 void parse_multipart_alternative (MAILSTREAM *stream, BODY *body, char *pfx, EP_mail_node *mailnode)
     /* [<][>][^][v][top][bottom][index][help] */
 646 {
 647 
 648   char tmppfx[MAILTMPLEN];
 649   char childpfx[MAILTMPLEN];
 650   char tmppart[MAILTMPLEN];
 651   /*   char *s = tmppfx; */
 652   EP_mail_node *newnode;
 653   EP_mail_node *parsednode;
 654   EP_mail_node *nextnode;
 655   long i;
 656   PART *part;
 657   char *result;
 658   char *content;
 659   unsigned long length;
 660   time_t ti = time (0);
 661   char tmpfile[FILENAMELEN];
 662   char nodefile[FILENAMELEN];
 663   
 664 
 665   if (debug >= 2)
 666     ER_dbg_va (FAC_MM, ASP_MM_GEN, "Bytes: %lu",body->size.bytes);
 667 
 668   /* if not first time, extend prefix */
 669   if (pfx == NULL) 
 670     {
 671       tmppfx[0] = '\0';
 672       pfx = tmppfx;
 673     }
 674 
 675 
 676   /* Initialize the first node: it is an inner node */
 677 
 678   /* The tree height increases */
 679   EP_TreeHeight++;
 680 
 681   /* The number of nodes increases */
 682   EP_Node_ID++;
 683 
 684   sprintf (nodefile,"%s%d",EP_outputPrefix,EP_Node_ID);
 685   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "inner-nodefile: %s",nodefile);
 686 
 687   newnode = EP_InitializeNode(nodefile, EP_Node_ID);
 688   mailnode->inner = newnode;
 689 
 690   for (i = 1,part = body->nested.part; part; part = part->next)
 691     {
 692       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "i: %ld, pfx: %s",i,pfx);
 693       if (debug >= 3) ER_dbg_va (FAC_MM, ASP_MM_GEN, "MYDEBUG: pfx=%s, tmppfx=%s,",pfx,tmppfx);
 694       sprintf (tmppart,"%ld",i);
 695       result = mail_fetch_mime(stream, (long)1, tmppart, &length, (long)0);
 696       if (debug >= 3)
 697         {
 698           ER_dbg_va (FAC_MM, ASP_MM_GEN, "body->size.bytes: %lu",body->size.bytes);
 699           ER_dbg_va (FAC_MM, ASP_MM_GEN, "(&part->body)->size.bytes: %lu",(&part->body)->size.bytes);
 700           ER_dbg_va (FAC_MM, ASP_MM_GEN, "length: %lu",length);
 701         }
 702       
 703 
 704       /* This buffer has to be dumped in a file from where it will be read by MM_extract_mime():
 705        * another stream will be opened, so the format of the file must be correct.
 706        * The LINELENGTH is to take the first 2 lines into account 
 707        */
 708       content = (char *)UT_malloc(2*LINELENGTH + length + (&part->body)->size.bytes + 2);
 709       sprintf (content,"From dbase@whois.ripe.net %sMIME-Version: 1.0\n",ctime (&ti));
 710       /* snprintf (content+strlen(content), (size_t)(length + (&part->body)->size.bytes) + 2, "%s\n", result); */
 711       g_snprintf ((gchar *)(content+strlen(content)), (gulong)(length + (&part->body)->size.bytes) + 2, "%s\n", result);
 712       
 713       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "Result: \n---\n%s\n---\nEnd results.\n", content);
 714 
 715       /* Generation of a temporary file:
 716        * The file must be unique inside the process. If we rewrite
 717        * on the same tmp file, which is used as a mailbox by c-client,
 718        * the c-client library has problems because it sees it changes
 719        * (I had problems with multipart/digest and message/rfc822).
 720        * "pass" is a global variable which increases every time we pass
 721        * through MM_extract_mime(): it should hence be unique each time
 722        * we call a driver.
 723        */
 724       sprintf (tmpfile,"%s.tmp.%ld",newnode->file,pass);
 725       write_file(tmpfile,content,strlen(content));
 726 
 727       /* This is needed to extend the prefix */
 728       sprintf (childpfx,"%s%ld.",pfx,i);
 729       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "childpfx: %s",childpfx);
 730       MM_extract_mime(tmpfile, childpfx, newnode, debug);
 731 
 732       /* Clean up... */
 733       UT_free(content);
 734       remove(tmpfile);
 735 
 736       /* Initialize the next node (if it exists) */
 737 
 738       if (part->next != NULL)
 739         {
 740           EP_Node_ID++;
 741           sprintf (nodefile,"%s%d",EP_outputPrefix,EP_Node_ID);
 742           if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "next-nodefile: %s",nodefile);
 743           nextnode = EP_InitializeNode(nodefile, EP_Node_ID);
 744           parsednode = newnode;
 745           newnode = nextnode;
 746           parsednode->next = newnode;
 747         }
 748 
 749       i++;
 750       
 751     }
 752   
 753 } /* parse_multipart_alternative() */
 754 
 755 
 756 void parse_multipart_signed (MAILSTREAM *stream, BODY *body, char *pfx, EP_mail_node *mailnode)
     /* [<][>][^][v][top][bottom][index][help] */
 757 {
 758 
 759   char tmppfx[MAILTMPLEN];
 760   char tmppart[MAILTMPLEN];
 761   EP_mail_node *newnode;
 762   PART *part;
 763   char *result;
 764   char *content;
 765   unsigned long length;
 766   char tmpfile[FILENAMELEN];
 767   char nodefile[FILENAMELEN];
 768   struct VerifySignObject vSO;
 769   /*  int retcode; */
 770 
 771   if (debug >= 2)
 772     ER_dbg_va (FAC_MM, ASP_MM_GEN, "Bytes: %lu",body->size.bytes);
 773 
 774 
 775   /* if not first time, extend prefix */
 776   if (pfx == NULL) 
 777     {
 778       tmppfx[0] = '\0';
 779       pfx = tmppfx;
 780     }
 781 
 782 
 783   /* Initialize the inner node */
 784 
 785   /* The tree height increases */
 786   EP_TreeHeight++;
 787 
 788   /* The number of nodes increases */
 789   EP_Node_ID++;
 790 
 791   sprintf (nodefile,"%s%d",EP_outputPrefix,EP_Node_ID);
 792   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "inner-nodefile: %s",nodefile);
 793 
 794   newnode = EP_InitializeNode(nodefile, EP_Node_ID);
 795   mailnode->inner = newnode;
 796 
 797   /* We give the same content-type to the child so as not to leave the default
 798      value (-1) */
 799   newnode->MIMEContentType = mailnode->MIMEContentType;
 800 
 801   /* We must get the two parts of the message. The signed part
 802    * and the signature. There can't be more than two parts
 803    * (see RFC2015).
 804    */
 805 
 806   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "pfx: %s",pfx);
 807 
 808   /* Signed part: it is the first part of the message. */
 809 
 810   part = body->nested.part;
 811 
 812   sprintf (tmppart,"%s1",tmppfx);
 813   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "tmppart: %s",tmppart);
 814 
 815   result = mail_fetch_mime(stream, (long)1, tmppart, &length, (long)0);
 816   if (debug >= 3)
 817     {
 818       ER_dbg_va (FAC_MM, ASP_MM_GEN, "body->size.bytes: %lu",body->size.bytes);
 819       ER_dbg_va (FAC_MM, ASP_MM_GEN, "(&part->body)->size.bytes: %lu",(&part->body)->size.bytes);
 820       ER_dbg_va (FAC_MM, ASP_MM_GEN, "length: %lu",length);
 821     }
 822 
 823   /* The signed part must be dumped in a file together with the MIME headers */
 824 
 825   content = (char *)UT_malloc(length + (&part->body)->size.bytes + 2);
 826   snprintf (content,(size_t)(length + (&part->body)->size.bytes) + 2, "%s\n", result);
 827 
 828   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "Result: \n---\n%s\n---\nEnd results.\n", content);
 829 
 830   if (debug) ER_dbg_va (FAC_MM, ASP_MM_GEN, "MSG file: %s",newnode->file);
 831   write_file(newnode->file,content,strlen(content));
 832 
 833 
 834   UT_free(content);
 835 
 836   /* Signature */
 837 
 838   part = part->next;
 839   sprintf (tmppart,"%s2",tmppfx);
 840   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "tmppart: %s",tmppart);
 841   
 842   result = mail_fetch_mime(stream, (long)1, tmppart, &length, (long)0);
 843   if (debug >= 2)
 844     {
 845       ER_dbg_va (FAC_MM, ASP_MM_GEN, "body->size.bytes: %lu\n",body->size.bytes);
 846       ER_dbg_va (FAC_MM, ASP_MM_GEN, "(&part->body)->size.bytes: %lu\n",(&part->body)->size.bytes);
 847       ER_dbg_va (FAC_MM, ASP_MM_GEN, "length: %lu\n",length);
 848     }
 849 
 850   /* The signature must be dumped _without_ MIME headers instead! 
 851    * Check where is the "length" variable... 
 852    */
 853 
 854   content = (char *)UT_malloc((&part->body)->size.bytes + 2);
 855 
 856   snprintf (content,(size_t)((&part->body)->size.bytes) + 2, "%s\n", result + length);
 857 
 858   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "Result: \n---\n%s\n---\nEnd results.\n", content);
 859 
 860   sprintf (tmpfile,"%s.sig",newnode->file);
 861   if (debug) ER_dbg_va (FAC_MM, ASP_MM_GEN, "SIG file: %s",tmpfile);
 862   write_file(tmpfile,content,strlen(content));
 863 
 864   /* Calling the verification procedure */
 865 
 866   strcpy(vSO.iDocSigFilename, newnode->file);
 867   strcpy(vSO.iSigFilename, tmpfile);
 868   strcpy(vSO.keyRing, EP_keyRing);
 869   
 870   PA_VerifySignature(&vSO);
 871 
 872   newnode->isValidPGPSignature = vSO.isValid;
 873   newnode->keyID= vSO.keyID;
 874 
 875   EP_MIMEParse(newnode);
 876 
 877   UT_free(content);
 878   remove(tmpfile);
 879 
 880 
 881 } /* parse_multipart_signed */
 882 
 883 
 884 
 885 /* MM status report
 886  * Accepts: MAIL stream
 887  */
 888 
 889 void status (MAILSTREAM *stream)
     /* [<][>][^][v][top][bottom][index][help] */
 890 {
 891   long i;
 892   char date[MAILTMPLEN];
 893   rfc822_date (date);
 894   ER_dbg_va (FAC_MM, ASP_MM_GEN, "%s",date);
 895   if (stream) 
 896     {
 897       if (stream->mailbox)
 898         {
 899           ER_dbg_va (FAC_MM, ASP_MM_GEN, " %s mailbox: %s",
 900                      stream->dtb->name,stream->mailbox);
 901           ER_dbg_va (FAC_MM, ASP_MM_GEN, " %lu messages, %lu recent",
 902                      stream->nmsgs,stream->recent);
 903         }
 904       else  ER_dbg_va (FAC_MM, ASP_MM_GEN, "% No mailbox is open on this stream");
 905       if (stream->user_flags[0]) 
 906         {
 907            ER_dbg_va (FAC_MM, ASP_MM_GEN, "Keywords: %s",stream->user_flags[0]);
 908           for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
 909            ER_dbg_va (FAC_MM, ASP_MM_GEN,", %s",stream->user_flags[i]);
 910           /* puts (""); */
 911         }
 912     }
 913 } /* status() */
 914 
 915 
 916 Mail_Header_Field *get_mail_hdr_field (MAILSTREAM *stream, 
     /* [<][>][^][v][top][bottom][index][help] */
 917                                        long mesgno, 
 918                                        STRINGLIST *cur, 
 919                                        const char *hdr_title)
 920 {
 921 
 922   char *tmphdr;
 923   char tmpline[MAXBUFSIZE];
 924   int i, j, k, c, tmpsize, titlesize;
 925   int continuation = 0;
 926   Mail_Header_Field *hdr_field;
 927   Mail_Header_Field *mhfp;
 928   Mail_Header_Field *newmhfp;
 929 
 930   mhfp = hdr_field = newmhfp = NULL;
 931 
 932   tmphdr = get_header_line(stream,mesgno,cur,hdr_title);
 933 
 934   tmpsize = strlen(tmphdr);
 935 
 936   /* Length of the header title plus ":" */
 937   titlesize = strlen(hdr_title) + 1;
 938 
 939   continuation = 0;   /* to detect continuation lines */
 940   j = 0;
 941   /* also initialize tmpline */
 942   for(i = 0; i < MAXBUFSIZE; i++){
 943     tmpline[i] = '\0';
 944   }
 945 
 946   /* Get one line at a time, and put the header lines in the Mail Header Field */
 947 
 948   for (i = 0; i < tmpsize; i++)
 949     {
 950       c = tmphdr[i];
 951       if (c == 10) /* EOL */
 952           {
 953             if ((j > 1) || ((mhfp == NULL) && (i == tmpsize - 1))) /* j>1 and not j>0 because "\r" is always read;
 954                                                                     * The second option is needed for
 955                                                                     * the empty headers */
 956             {
 957                 newmhfp = (Mail_Header_Field *)UT_malloc(sizeof(Mail_Header_Field));
 958                 newmhfp->next = NULL;
 959                 newmhfp->field = (char *)UT_malloc(j + 2);
 960                 if (j > 1)
 961             {
 962               if ( ! continuation )
 963                         /* We do not copy the header title from the first line */
 964                         sprintf (newmhfp->field,"%s\n",tmpline + titlesize);
 965               else
 966                         /* There is no header title on continuation lines */
 967                         sprintf (newmhfp->field,"%s\n",tmpline);
 968             }
 969                 else
 970                       sprintf (newmhfp->field,"\n");
 971 
 972                 if (mhfp == NULL)
 973                     {
 974                       mhfp = newmhfp;
 975                       hdr_field = newmhfp;
 976                     }
 977                 else
 978                     {
 979                       mhfp->next = newmhfp;
 980                       mhfp = newmhfp;
 981                     }
 982             }
 983         continuation = 1;   /* next time we are reading continuation lines */
 984             j = 0;        
 985         /* re-initialize tmpline */
 986         for (k = 0; k < MAXBUFSIZE; k++)
 987         {
 988           tmpline[k] = '\0';
 989         }
 990           }
 991       else
 992           {
 993             sprintf (tmpline + j++,"%c", c);
 994           }
 995     }
 996 
 997   UT_free(tmphdr);
 998 
 999   return (hdr_field);
1000 
1001 } /* get_mail_hdr_field() */
1002 
1003 
1004 
1005 char *get_header_line (MAILSTREAM *stream, long mesgno, STRINGLIST *cur, const char *hdr_title)
     /* [<][>][^][v][top][bottom][index][help] */
1006 {
1007 
1008   unsigned long offset;
1009   size_t tmplength;
1010   char *curtmp;
1011   char *hdr_attr;
1012   long a,b;
1013 
1014 
1015   /* We need to insert the header title into a STRINGLIST structure, as
1016    * this is the type that must be supplied to mail_fetchheader_full.
1017    */
1018 
1019   cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *) 
1020                                      cpystr (hdr_title)));
1021   
1022   /* If we don't want to return the header title, but only the contents,
1023    * this offset allows us to strip the header title. The "magic number" 2
1024    * is the string ": " of the header.
1025    * This method is uneffective for multiple headers (ex. Cc, Reply-To, etc.).
1026    */
1027   
1028   offset = cur->text.size + 2;
1029   
1030   /* Get the header line, if it exists */
1031   
1032   curtmp = mail_fetchheader_full (stream,mesgno,cur,NIL,NIL);
1033 
1034   tmplength = strlen(curtmp);
1035   hdr_attr = (char *)UT_malloc(tmplength + 4);
1036   
1037   /* cur contains the header title string, like "From:", "Subject:" etc.
1038    * tmplength is the length of the corresponding header line extracted
1039    * from the message. If a real line is returned, the header title
1040    * ("From:", "Subject:" etc.) will be contained within, hence
1041    * tmplength >= cur->text.size . This means that if
1042    * (cur->text.size > tmplength), no such header is present in the mail:
1043    * we must return an (almost) empty string.
1044    */
1045   
1046   a = (long)tmplength;
1047   b = (long)cur->text.size;
1048   if (a > b)
1049     {
1050       /* If we want to strip the header */
1051       /*sprintf (hdr_attr,"%s",curtmp + offset); */
1052       sprintf (hdr_attr,"%s",curtmp);
1053       /* printf ("%s",hdr_attr); */
1054     }
1055   else
1056     {
1057       sprintf (hdr_attr,"\n\n");
1058     }
1059   
1060   return (hdr_attr);
1061 } /* get_header_line() */
1062 
1063 
1064 
1065 
1066 /* Subroutine for writing in a file */
1067 
1068 void write_file (char *filename, char *text, size_t text_size)
     /* [<][>][^][v][top][bottom][index][help] */
1069 {
1070 
1071   FILE *fd;
1072   size_t i;
1073 
1074   /* printf ("%s\n",filename); */
1075   
1076   if ((fd = fopen(filename,"w")) != NULL)
1077     {
1078       for (i = 0; i < text_size; i++)
1079         if (text[i] != 13) 
1080           fprintf (fd, "%c",text[i]);
1081       fclose(fd);
1082     }
1083   else
1084     {
1085       ER_perror(FAC_MM, MM_CANTOPEN, "%s for writing\n",filename);
1086       die;
1087     }
1088   
1089 } /* write_file() */
1090 
1091 
1092 void read_file (const char *filename)
     /* [<][>][^][v][top][bottom][index][help] */
1093 {
1094 
1095   FILE *fd;
1096   int c;
1097 
1098   if ((fd = fopen (filename,"r")) != NULL)
1099     {
1100       while ((c = getc(fd)) != EOF)
1101         putc (c, stdout);
1102       fclose (fd);
1103     }
1104   else
1105     {
1106       ER_perror(FAC_MM, MM_CANTOPEN, "%s for reading\n",filename);
1107       die;
1108     }
1109 
1110 } /* read_file() */
1111 
1112 
1113 void put_in_file (char *fileprefix, char *extension, char *text, size_t text_size)
     /* [<][>][^][v][top][bottom][index][help] */
1114 {
1115 
1116   char filename[FILENAMELEN];
1117 
1118 
1119   /* Write in a file */
1120   
1121   sprintf (filename,"%s-%s",fileprefix,extension);
1122   /* printf ("%s\n",filename); */
1123   
1124   write_file(filename,text,text_size);
1125   
1126 }/* put_in_file() */
1127 
1128 
1129 /* Stolen from which_keytypes.c and converted to use regex.h instead of libgen.h */
1130 
1131 
1132 int do_regex_test (const char *pattern, char *string)
     /* [<][>][^][v][top][bottom][index][help] */
1133 {
1134 
1135   int match = 0;
1136 
1137   /* These are not used, since REG_NOSUB is specified in regcomp() */
1138   size_t nmatch = 0;
1139   regmatch_t pmatch[1];
1140 
1141   regex_t *re;
1142 
1143   re = (regex_t *)UT_malloc(STR_XL);
1144 
1145   regcomp(re, pattern, REG_NOSUB || REG_NEWLINE);
1146   if (regexec(re, string, nmatch, pmatch, 0))
1147     match = 0;
1148   else
1149     match = 1;
1150 
1151   regfree(re);
1152 
1153   /* Caution! regfree() does not do this job... */
1154   UT_free(re);
1155 
1156   return(match);
1157 
1158 } /* do_regex_test() */
1159 
1160 
1161 /* Interfaces to c-client.
1162  * They must be here for the code to be compiled,
1163  * but most can stay empty.
1164  */
1165 
1166 void mm_searched (MAILSTREAM *stream,unsigned long number)
     /* [<][>][^][v][top][bottom][index][help] */
1167 {
1168 }
1169 
1170 
1171 void mm_exists (MAILSTREAM *stream,unsigned long number)
     /* [<][>][^][v][top][bottom][index][help] */
1172 {
1173 }
1174 
1175 
1176 void mm_expunged (MAILSTREAM *stream,unsigned long number)
     /* [<][>][^][v][top][bottom][index][help] */
1177 {
1178 }
1179 
1180 
1181 void mm_flags (MAILSTREAM *stream,unsigned long number)
     /* [<][>][^][v][top][bottom][index][help] */
1182 {
1183 }
1184 
1185 void mm_notify (MAILSTREAM *stream,char *string,long errflg)
     /* [<][>][^][v][top][bottom][index][help] */
1186 {
1187 }
1188 
1189 void mm_list (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
     /* [<][>][^][v][top][bottom][index][help] */
1190 {
1191 }
1192 
1193 void mm_lsub (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
     /* [<][>][^][v][top][bottom][index][help] */
1194 {
1195 }
1196 
1197 void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
     /* [<][>][^][v][top][bottom][index][help] */
1198 {
1199 }
1200 
1201 void mm_log (char *string,long errflg)
     /* [<][>][^][v][top][bottom][index][help] */
1202 {
1203   switch ((short) errflg) {
1204   case NIL:
1205     ER_dbg_va (FAC_MM, ASP_MM_GEN, "[%s]",string);
1206     break;
1207   case PARSE:
1208   case WARN:
1209     ER_perror (FAC_MM, MM_WARNCCL, "%%%s",string);
1210     break;
1211   case ERROR:
1212     ER_perror (FAC_MM, MM_ERRCCL, "%s",string);
1213     break;
1214   }
1215 }
1216 
1217 void mm_dlog (char *string)
     /* [<][>][^][v][top][bottom][index][help] */
1218 {
1219   puts (string);
1220 }
1221 
1222 void mm_login (NETMBX *mb,char *user,char *pwd,long trial)
     /* [<][>][^][v][top][bottom][index][help] */
1223 {
1224 }
1225 
1226 void mm_critical (MAILSTREAM *stream)
     /* [<][>][^][v][top][bottom][index][help] */
1227 {
1228 }
1229 
1230 void mm_nocritical (MAILSTREAM *stream)
     /* [<][>][^][v][top][bottom][index][help] */
1231 {
1232 }
1233 
1234 long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
     /* [<][>][^][v][top][bottom][index][help] */
1235 {
1236 #if UNIXLIKE
1237   kill (getpid (),SIGSTOP);
1238 #else
1239   abort ();
1240 #endif
1241   return NIL;
1242 }
1243 
1244 void mm_fatal (char *string)
     /* [<][>][^][v][top][bottom][index][help] */
1245 {
1246   ER_perror(FAC_MM, MM_FATCCL, "%s\n",string);
1247   die;
1248 }
1249 

/* [<][>][^][v][top][bottom][index][help] */