modules/mm/mm.c

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

DEFINITIONS

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

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