ipop2d.c
上传用户:ycwykj01
上传日期:2007-01-04
资源大小:1819k
文件大小:19k
源码类别:

网络编程

开发平台:

Unix_Linux

  1. /*
  2.  * Program: IPOP2D - IMAP to POP2 conversion server
  3.  *
  4.  * Author: Mark Crispin
  5.  * Networks and Distributed Computing
  6.  * Computing & Communications
  7.  * University of Washington
  8.  * Administration Building, AG-44
  9.  * Seattle, WA  98195
  10.  * Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date: 28 October 1990
  13.  * Last Edited: 16 November 1999
  14.  *
  15.  * Copyright 1999 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35. /* Parameter files */
  36. #include "mail.h"
  37. #include "osdep.h"
  38. #include <stdio.h>
  39. #include <ctype.h>
  40. #include <errno.h>
  41. extern int errno; /* just in case */
  42. #include <signal.h>
  43. #include "misc.h"
  44. /* Autologout timer */
  45. #define KODTIMEOUT 60*5
  46. #define LOGINTIMEOUT 60*3
  47. #define TIMEOUT 60*30
  48. /* Size of temporary buffers */
  49. #define TMPLEN 1024
  50. /* Server states */
  51. #define LISN 0
  52. #define AUTH 1
  53. #define MBOX 2
  54. #define ITEM 3
  55. #define NEXT 4
  56. #define DONE 5
  57. /* Global storage */
  58. char *version = "4.55"; /* server version */
  59. short state = LISN; /* server state */
  60. short critical = NIL; /* non-zero if in critical code */
  61. MAILSTREAM *stream = NIL; /* mailbox stream */
  62. long idletime = 0; /* time we went idle */
  63. unsigned long nmsgs = 0; /* number of messages */
  64. unsigned long current = 1; /* current message number */
  65. unsigned long size = 0; /* size of current message */
  66. char status[MAILTMPLEN]; /* space for status string */
  67. char *user = ""; /* user name */
  68. char *pass = ""; /* password */
  69. unsigned long *msg = NIL; /* message translation vector */
  70. /* Function prototypes */
  71. int main (int argc,char *argv[]);
  72. void clkint ();
  73. void kodint ();
  74. void hupint ();
  75. void trmint ();
  76. short c_helo (char *t,int argc,char *argv[]);
  77. short c_fold (char *t);
  78. short c_read (char *t);
  79. short c_retr (char *t);
  80. short c_acks (char *t);
  81. short c_ackd (char *t);
  82. short c_nack (char *t);
  83. /* Main program */
  84. int main (int argc,char *argv[])
  85. {
  86.   char *s,*t;
  87.   char cmdbuf[TMPLEN];
  88. #ifdef PLAINTEXT_DISABLED
  89.   printf ("- POP2 server disabled on this system1512");
  90.   fflush (stdout);
  91.   _exit (1);
  92. #endif
  93. #include "linkage.c"
  94. /* initialize server */
  95.   server_init (argv[0],"pop",NIL,"pop",clkint,kodint,hupint,trmint);
  96.   /* There are reports of POP2 clients which get upset if anything appears
  97.    * between the "+" and the "POP2" in the greeting.
  98.    */
  99.   printf ("+ POP2 %s v%s server ready1512",tcp_serverhost (),version);
  100.   fflush (stdout); /* dump output buffer */
  101.   state = AUTH; /* initial server state */
  102.   while (state != DONE) { /* command processing loop */
  103.     idletime = time (0); /* get a command under timeout */
  104.     alarm ((state != AUTH) ? TIMEOUT : LOGINTIMEOUT);
  105.     clearerr (stdin); /* clear stdin errors */
  106.     while (!fgets (cmdbuf,TMPLEN-1,stdin)) {
  107.       if (ferror (stdin) && (errno == EINTR)) clearerr (stdin);
  108.       else {
  109. char *e = ferror (stdin) ?
  110.   strerror (errno) : "Command stream end of file";
  111. alarm (0); /* disable all interrupts */
  112. server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
  113. syslog (LOG_INFO,"%s while reading line user=%.80s host=%.80s",
  114. e,user ? user : "???",tcp_clienthost ());
  115. state = DONE;
  116. mail_close (stream); /* try to close the stream gracefully */
  117. stream = NIL;
  118. _exit (1);
  119.       }
  120.     }
  121.     alarm (0); /* make sure timeout disabled */
  122.     idletime = 0; /* no longer idle */
  123. /* find end of line */
  124.     if (!strchr (cmdbuf,'12')) {
  125.       server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
  126.       fputs ("- Command line too long1512",stdout);
  127.       state = DONE;
  128.     }
  129.     else if (!(s = strtok (cmdbuf," 1512"))) {
  130.       server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
  131.       fputs ("- Missing or null command1512",stdout);
  132.       state = DONE;
  133.     }
  134.     else { /* dispatch based on command */
  135.       ucase (s); /* canonicalize case */
  136. /* snarf argument */
  137.       t = strtok (NIL,"1512");
  138.       if ((state == AUTH) && !strcmp (s,"HELO")) state = c_helo (t,argc,argv);
  139.       else if ((state == MBOX || state == ITEM) && !strcmp (s,"FOLD"))
  140.   state = c_fold (t);
  141.       else if ((state == MBOX || state == ITEM) && !strcmp (s,"READ"))
  142. state = c_read (t);
  143.       else if ((state == ITEM) && !strcmp (s,"RETR")) state = c_retr (t);
  144.       else if ((state == NEXT) && !strcmp (s,"ACKS")) state = c_acks (t);
  145.       else if ((state == NEXT) && !strcmp (s,"ACKD")) state = c_ackd (t);
  146.       else if ((state == NEXT) && !strcmp (s,"NACK")) state = c_nack (t);
  147.       else if ((state == AUTH || state == MBOX || state == ITEM) &&
  148.        !strcmp (s,"QUIT")) {
  149. server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
  150. state = DONE; /* done in either case */
  151. if (t) fputs ("- Bogus argument given to QUIT1512",stdout);
  152. else { /* expunge the stream */
  153.   if (stream && nmsgs) stream = mail_close_full (stream,CL_EXPUNGE);
  154.   stream = NIL; /* don't repeat it */
  155. /* acknowledge the command */
  156.   fputs ("+ Sayonara1512",stdout);
  157. }
  158.       }
  159.       else { /* some other or inappropriate command */
  160. server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
  161. printf ("- Bogus or out of sequence command - %s1512",s);
  162. state = DONE;
  163.       }
  164.     }
  165.     fflush (stdout); /* make sure output blatted */
  166.   }
  167. /* clean up the stream */
  168.   if (stream) mail_close (stream);
  169.   syslog (LOG_INFO,"Logout user=%.80s host=%.80s",user ? user : "???",
  170.   tcp_clienthost ());
  171.   return 0; /* all done */
  172. }
  173. /* Clock interrupt
  174.  */
  175. void clkint ()
  176. {
  177.   alarm (0); /* disable all interrupts */
  178.   server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
  179.   fputs ("- Autologout; idle for too long1512",stdout);
  180.   syslog (LOG_INFO,"Autologout user=%.80s host=%.80s",user ? user : "???",
  181.   tcp_clienthost ());
  182.   fflush (stdout); /* make sure output blatted */
  183.   state = DONE; /* mark state done in either case */
  184.   if (!critical) { /* badly host if in critical code */
  185.     if (stream && !stream->lock) mail_close (stream);
  186.     stream = NIL;
  187.     _exit (1); /* die die die */
  188.   }
  189. }
  190. /* Kiss Of Death interrupt
  191.  */
  192. void kodint ()
  193. {
  194. /* only if in command wait */
  195.   if (idletime && ((time (0) - idletime) > KODTIMEOUT)) {
  196.     alarm (0); /* disable all interrupts */
  197.     server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
  198.     fputs ("- Received Kiss of Death1512",stdout);
  199.     syslog (LOG_INFO,"Killed (lost mailbox lock) user=%.80s host=%.80s",
  200.     user ? user : "???",tcp_clienthost ());
  201.     fflush (stdout); /* make sure output blatted */
  202.     state = DONE; /* mark state done in either case */
  203.     if (!critical) { /* badly host if in critical code */
  204.       if (stream && !stream->lock) mail_close (stream);
  205.       stream = NIL;
  206.       _exit (1); /* die die die */
  207.     }
  208.   }
  209. }
  210. /* Hangup interrupt
  211.  */
  212. void hupint ()
  213. {
  214.   alarm (0); /* disable all interrupts */
  215.   server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
  216.   syslog (LOG_INFO,"Hangup user=%.80s host=%.80s",user ? user : "???",
  217.   tcp_clienthost ());
  218.   state = DONE; /* mark state done in either case */
  219.   if (!critical) { /* badly host if in critical code */
  220.     if (stream && !stream->lock) mail_close (stream);
  221.     stream = NIL;
  222.     _exit (1); /* die die die */
  223.   }
  224. }
  225. /* Termination interrupt
  226.  */
  227. void trmint ()
  228. {
  229.   alarm (0); /* disable all interrupts */
  230.   server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
  231.   fputs ("- Killed1512",stdout);
  232.   syslog (LOG_INFO,"Killed user=%.80s host=%.80s",user ? user : "???",
  233.   tcp_clienthost ());
  234.   fflush (stdout); /* make sure output blatted */
  235.   state = DONE; /* mark state done in either case */
  236.   if (!critical) { /* badly host if in critical code */
  237.     if (stream && !stream->lock) mail_close (stream);
  238.     stream = NIL;
  239.     _exit (1); /* die die die */
  240.   }
  241. }
  242. /* Parse HELO command
  243.  * Accepts: pointer to command argument
  244.  * Returns: new state
  245.  */
  246. short c_helo (char *t,int argc,char *argv[])
  247. {
  248.   char *s,*u,*p;
  249.   char tmp[TMPLEN];
  250.   if ((!(t && *t && (u = strtok (t," ")) && (p = strtok (NIL,"1512")))) ||
  251.       (strlen (p) >= TMPLEN)) { /* get user name and password */
  252.     fputs ("- Missing user or password1512",stdout);
  253.     return DONE;
  254.   }
  255. /* copy password, handle quoting */
  256.   for (s = tmp; *p; p++) *s++ = (*p == '\') ? *++p : *p;
  257.   *s = ''; /* tie off string */
  258.   pass = cpystr (tmp);
  259. #ifndef DISABLE_POP_PROXY
  260. /* want remote mailbox? */
  261.   if ((s = strchr (u,':')) && anonymous_login (argc,argv)) {
  262.     *s++ = ''; /* separate host name from user name */
  263.     user = cpystr (s); /* note user name */
  264.     syslog (LOG_INFO,"IMAP login to host=%.80s user=%.80s host=%.80s",u,user,
  265.     tcp_clienthost ());
  266. /* initially remote INBOX */
  267.     sprintf (tmp,"{%.128s/user=%.128s}INBOX",u,user);
  268. /* disable rimap just in case */
  269.     mail_parameters (NIL,SET_RSHTIMEOUT,0);
  270.   }
  271.   else
  272. #endif
  273.   if (!s && server_login (user = cpystr (u),pass,argc,argv)) {
  274.     syslog (LOG_INFO,"Login user=%.80s host=%.80s",user,tcp_clienthost ());
  275.     strcpy (tmp,"INBOX"); /* local; attempt login, select INBOX */
  276.   }
  277.   else {
  278.     fputs ("- Bad login1512",stdout);
  279.     return DONE;
  280.   }
  281.   return c_fold (tmp); /* open default mailbox */
  282. }
  283. /* Parse FOLD command
  284.  * Accepts: pointer to command argument
  285.  * Returns: new state
  286.  */
  287. short c_fold (char *t)
  288. {
  289.   unsigned long i,j,flags;
  290.   char *s = NIL,tmp[2*TMPLEN];
  291.   NETMBX mb;
  292.   if (!(t && *t)) { /* make sure there's an argument */
  293.     fputs ("- Missing mailbox name1512",stdout);
  294.     return DONE;
  295.   }
  296.   myusername_full (&flags); /* get user type flags */
  297. /* expunge old stream */
  298.   if (stream && nmsgs) mail_expunge (stream);
  299.   nmsgs = 0; /* no more messages */
  300.   if (msg) fs_give ((void **) &msg);
  301. #ifndef DISABLE_POP_PROXY
  302.   if (flags == MU_ANONYMOUS) { /* don't permit proxy to leave IMAP */
  303.     if (stream) { /* not first time */
  304.       if (!(stream->mailbox && (s = strchr (stream->mailbox,'}'))))
  305. fatal ("bad previous mailbox name");
  306.       strncpy (tmp,stream->mailbox,i = (++s - stream->mailbox));
  307.       if (i >= TMPLEN) fatal ("ridiculous network prefix");
  308.       strcpy (tmp+i,t); /* append mailbox to initial spec */
  309.       t = tmp;
  310.     }
  311. /* must be net name first time */
  312.     else if (!mail_valid_net_parse (t,&mb)) fatal ("anonymous folder bogon");
  313.   }
  314. #endif
  315. /* open mailbox, note # of messages */
  316.   if (j = (stream = mail_open (stream,t,NIL)) ? stream->nmsgs : 0) {
  317.     sprintf (tmp,"1:%lu",j); /* fetch fast information for all messages */
  318.     mail_fetch_fast (stream,tmp,NIL);
  319.     msg = (unsigned long *) fs_get ((stream->nmsgs + 1) *
  320.     sizeof (unsigned long));
  321.     for (i = 1; i <= j; i++) /* find undeleted messages, add to vector */
  322.       if (!mail_elt (stream,i)->deleted) msg[++nmsgs] = i;
  323.   }
  324. #ifndef DISABLE_POP_PROXY
  325.   if (!stream && (flags == MU_ANONYMOUS)) {
  326.     fputs ("- Bad login1512",stdout);
  327.     return DONE;
  328.   }
  329. #endif
  330.   printf ("#%lu messages in %s1512",nmsgs,stream ? stream->mailbox :
  331.   "<none>");
  332.   return MBOX;
  333. }
  334. /* Parse READ command
  335.  * Accepts: pointer to command argument
  336.  * Returns: new state
  337.  */
  338. short c_read (char *t)
  339. {
  340.   MESSAGECACHE *elt = NIL;
  341.   if (t && *t) { /* have a message number argument? */
  342. /* validity check message number */
  343.     if (((current = strtoul (t,NIL,10)) < 1) || (current > nmsgs)) {
  344.       fputs ("- Invalid message number given to READ1512",stdout);
  345.       return DONE;
  346.     }
  347.   }
  348.   else if (current > nmsgs) { /* at end of mailbox? */
  349.     fputs ("=0 No more messages1512",stdout);
  350.     return MBOX;
  351.   }
  352. /* set size if message valid and exists */
  353.   size = msg[current] ? (elt = mail_elt(stream,msg[current]))->rfc822_size : 0;
  354.   if (elt) sprintf (status,"Status: %s%s1512",
  355.     elt->seen ? "R" : " ",elt->recent ? " " : "O");
  356.   else status[0] = ''; /* no status */
  357.   size += strlen (status); /* update size to reflect status */
  358. /* display results */
  359.   printf ("=%lu characters in message %lu1512",size + 2,current);
  360.   return ITEM;
  361. }
  362. /* Parse RETR command
  363.  * Accepts: pointer to command argument
  364.  * Returns: new state
  365.  */
  366. short c_retr (char *t)
  367. {
  368.   if (t) { /* disallow argument */
  369.     fputs ("- Bogus argument given to RETR1512",stdout);
  370.     return DONE;
  371.   }
  372.   if (size) { /* message size valid? */
  373.     unsigned long i,j;
  374.     t = mail_fetch_header (stream,msg[current],NIL,NIL,&i,FT_PEEK);
  375.     if (i > 2) { /* only if there is something */
  376.       i -= 2; /* lop off last two octets */
  377.       while (i) { /* blat the header */
  378. j = fwrite (t,sizeof (char),i,stdout);
  379. if (i -= j) t += j; /* advance to incomplete data */
  380.       }
  381.     }
  382.     fputs (status,stdout); /* yes, output message */
  383.     fputs ("1512",stdout); /* delimit header from text */
  384.     t = mail_fetch_text (stream,msg[current],NIL,&i,NIL);
  385.     while (i) { /* blat the text */
  386.       j = fwrite (t,sizeof (char),i,stdout);
  387.       if (i -= j) t += j; /* advance to incomplete data */
  388.     }
  389.     fputs ("1512",stdout); /* trailer to coddle PCNFS' NFSMAIL */
  390.   }
  391.   else return DONE; /* otherwise go away */
  392.   return NEXT;
  393. }
  394. /* Parse ACKS command
  395.  * Accepts: pointer to command argument
  396.  * Returns: new state
  397.  */
  398. short c_acks (char *t)
  399. {
  400.   char tmp[TMPLEN];
  401.   if (t) { /* disallow argument */
  402.     fputs ("- Bogus argument given to ACKS1512",stdout);
  403.     return DONE;
  404.   }
  405. /* mark message as seen */
  406.   sprintf (tmp,"%lu",msg[current++]);
  407.   mail_setflag (stream,tmp,"\Seen");
  408.   return c_read (NIL); /* end message reading transaction */
  409. }
  410. /* Parse ACKD command
  411.  * Accepts: pointer to command argument
  412.  * Returns: new state
  413.  */
  414. short c_ackd (char *t)
  415. {
  416.   char tmp[TMPLEN];
  417.   if (t) { /* disallow argument */
  418.     fputs ("- Bogus argument given to ACKD1512",stdout);
  419.     return DONE;
  420.   }
  421. /* mark message as seen and deleted */
  422.   sprintf (tmp,"%lu",msg[current]);
  423.   mail_setflag (stream,tmp,"\Seen \Deleted");
  424.   msg[current++] = 0; /* mark message as deleted */
  425.   return c_read (NIL); /* end message reading transaction */
  426. }
  427. /* Parse NACK command
  428.  * Accepts: pointer to command argument
  429.  * Returns: new state
  430.  */
  431. short c_nack (char *t)
  432. {
  433.   if (t) { /* disallow argument */
  434.     fputs ("- Bogus argument given to NACK1512",stdout);
  435.     return DONE;
  436.   }
  437.   return c_read (NIL); /* end message reading transaction */
  438. }
  439. /* Co-routines from MAIL library */
  440. /* Message matches a search
  441.  * Accepts: MAIL stream
  442.  *     message number
  443.  */
  444. void mm_searched (MAILSTREAM *stream,unsigned long msgno)
  445. {
  446.   /* Never called */
  447. }
  448. /* Message exists (i.e. there are that many messages in the mailbox)
  449.  * Accepts: MAIL stream
  450.  *     message number
  451.  */
  452. void mm_exists (MAILSTREAM *stream,unsigned long number)
  453. {
  454.   /* Can't use this mechanism.  POP has no means of notifying the client of
  455.      new mail during the session. */
  456. }
  457. /* Message expunged
  458.  * Accepts: MAIL stream
  459.  *     message number
  460.  */
  461. void mm_expunged (MAILSTREAM *stream,unsigned long number)
  462. {
  463.   if (state != DONE) { /* ignore if closing */
  464. /* this should never happen */
  465.     fputs ("- Mailbox expunged from under me!1512",stdout);
  466.     if (stream && !stream->lock) mail_close (stream);
  467.     stream = NIL;
  468.     _exit (1);
  469.   }
  470. }
  471. /* Message status changed
  472.  * Accepts: MAIL stream
  473.  *     message number
  474.  */
  475. void mm_flags (MAILSTREAM *stream,unsigned long number)
  476. {
  477.   /* This isn't used */
  478. }
  479. /* Mailbox found
  480.  * Accepts: MAIL stream
  481.  *     hierarchy delimiter
  482.  *     mailbox name
  483.  *     mailbox attributes
  484.  */
  485. void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
  486. {
  487.   /* This isn't used */
  488. }
  489. /* Subscribe mailbox found
  490.  * Accepts: MAIL stream
  491.  *     hierarchy delimiter
  492.  *     mailbox name
  493.  *     mailbox attributes
  494.  */
  495. void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
  496. {
  497.   /* This isn't used */
  498. }
  499. /* Mailbox status
  500.  * Accepts: MAIL stream
  501.  *     mailbox name
  502.  *     mailbox status
  503.  */
  504. void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
  505. {
  506.   /* This isn't used */
  507. }
  508. /* Notification event
  509.  * Accepts: MAIL stream
  510.  *     string to log
  511.  *     error flag
  512.  */
  513. void mm_notify (MAILSTREAM *stream,char *string,long errflg)
  514. {
  515.   mm_log (string,errflg); /* just do mm_log action */
  516. }
  517. /* Log an event for the user to see
  518.  * Accepts: string to log
  519.  *     error flag
  520.  */
  521. void mm_log (char *string,long errflg)
  522. {
  523.   /* Not doing anything here for now */
  524. }
  525. /* Log an event to debugging telemetry
  526.  * Accepts: string to log
  527.  */
  528. void mm_dlog (char *string)
  529. {
  530.   /* Not doing anything here for now */
  531. }
  532. /* Get user name and password for this host
  533.  * Accepts: parse of network mailbox name
  534.  *     where to return user name
  535.  *     where to return password
  536.  *     trial count
  537.  */
  538. void mm_login (NETMBX *mb,char *username,char *password,long trial)
  539. {
  540. /* set user name */
  541.   strncpy (username,*mb->user ? mb->user : user,NETMAXUSER-1);
  542.   strncpy (password,pass,255); /* and password */
  543.   username[NETMAXUSER] = password[255] = '';
  544. }
  545. /* About to enter critical code
  546.  * Accepts: stream
  547.  */
  548. void mm_critical (MAILSTREAM *stream)
  549. {
  550.   critical = T;
  551. }
  552. /* About to exit critical code
  553.  * Accepts: stream
  554.  */
  555. void mm_nocritical (MAILSTREAM *stream)
  556. {
  557.   critical = NIL;
  558. }
  559. /* Disk error found
  560.  * Accepts: stream
  561.  *     system error code
  562.  *     flag indicating that mailbox may be clobbered
  563.  * Returns: abort flag
  564.  */
  565. long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
  566. {
  567.   if (serious) { /* try your damnest if clobberage likely */
  568.     syslog (LOG_ALERT,
  569.     "Retrying after disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
  570.     user,tcp_clienthost (),
  571.     (stream && stream->mailbox) ? stream->mailbox : "???",
  572.     strerror (errcode));
  573.     alarm (0); /* make damn sure timeout disabled */
  574.     sleep (60); /* give it some time to clear up */
  575.     return NIL;
  576.   }
  577.   syslog (LOG_ALERT,"Fatal disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
  578.   user,tcp_clienthost (),
  579.   (stream && stream->mailbox) ? stream->mailbox : "???",
  580.   strerror (errcode));
  581.   return T;
  582. }
  583. /* Log a fatal error event
  584.  * Accepts: string to log
  585.  */
  586. void mm_fatal (char *string)
  587. {
  588.   mm_log (string,ERROR); /* shouldn't happen normally */
  589. }