Back to index

courier  0.68.2
imapwrite.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2006 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #if    HAVE_CONFIG_H
00007 #include      "config.h"
00008 #endif
00009 #include      <stdio.h>
00010 #include      <stdlib.h>
00011 #include      <string.h>
00012 #include      <errno.h>
00013 #if    HAVE_UNISTD_H
00014 #include      <unistd.h>
00015 #endif
00016 #include      <sys/types.h>
00017 #if TIME_WITH_SYS_TIME
00018 #include        <sys/time.h>
00019 #include        <time.h>
00020 #else
00021 #if HAVE_SYS_TIME_H
00022 #include        <sys/time.h>
00023 #else
00024 #include        <time.h>
00025 #endif
00026 #endif
00027 
00028 #include      "imapwrite.h"
00029 
00030 
00031 static char outbuf[BUFSIZ]; /* Ye olde output buffer */
00032 static size_t outbuf_cnt=0; /* How much stuff's in ye olde output buffer */
00033 
00034 extern FILE *debugfile;
00035 
00036 extern unsigned long bytes_sent_count; /* counter for sent bytes (imapwrite.c) */
00037 
00038 extern void disconnected();
00039 
00040 void writeflush()
00041 {
00042 const char *p=outbuf;
00043 unsigned s=outbuf_cnt;
00044 time_t t, tend;
00045 fd_set fds;
00046 struct timeval       tv;
00047 int    n;
00048 
00049        if (s == 0)   return;
00050        time(&t);
00051        tend=t+SOCKET_TIMEOUT;
00052        if (debugfile)
00053        {
00054               fprintf(debugfile, "WRITE: ");
00055               if (fwrite(p, 1, s, debugfile) == 1)
00056                      fprintf(debugfile, "\n");
00057               fflush(debugfile);
00058        }
00059        while (t < tend)
00060        {
00061               FD_ZERO(&fds);
00062               FD_SET(1, &fds);
00063               tv.tv_sec=tend-t;
00064               tv.tv_usec=0;
00065               /* BUG: if client closes connection BEFORE we flush it, select "stucks"
00066                * until timeout. To workaround this, we should "write" first, and then
00067                * if we get EPIPE connection is already closed. Othervise, try select
00068                */
00069               if ((n=write(1, p, s)) <= 0)
00070               {
00071                      if (errno == EPIPE ||
00072                             select(2, 0, &fds, 0, &tv) <= 0 ||
00073                             !FD_ISSET(1, &fds) ||
00074                             (n=write(1, p, s)) <= 0)
00075                      {
00076                             disconnected();
00077                             return;
00078                      }
00079               }
00080               bytes_sent_count += n;
00081               p += n;
00082               s -= n;
00083               if (s == 0)   break;
00084               time(&t);
00085        }
00086        if (s) disconnected();
00087        outbuf_cnt=0;
00088 }
00089 
00090 void writemem(const char *s, size_t l)
00091 {
00092 size_t n;
00093 
00094        while (l)
00095        {
00096               n=sizeof(outbuf) - outbuf_cnt;
00097 
00098               if (n >= l)
00099               {
00100                      memcpy(outbuf+outbuf_cnt, s, l);
00101                      outbuf_cnt += l;
00102                      break;
00103               }
00104               if (n == 0)
00105               {
00106                      writeflush();
00107                      continue;
00108               }
00109               if (n > l)    n=l;
00110               memcpy(outbuf+outbuf_cnt, s, n);
00111               outbuf_cnt += n;
00112               l -= n;
00113               s += n;
00114        }
00115 }
00116 
00117 void writes(const char *s)
00118 {
00119        writemem(s, strlen(s));
00120 }
00121 
00122 void writen(unsigned long n)
00123 {
00124 char   buf[40];
00125 
00126        sprintf(buf, "%lu", n);
00127        writemem(buf, strlen(buf));
00128 }
00129 
00130 void writeqs(const char *s)
00131 {
00132 size_t i=strlen(s), j;
00133 
00134        while (i)
00135        {
00136               for (j=0; j<i; j++)
00137               {
00138                      if ( s[j] == '"' || s[j] == '\\')
00139                      {
00140                             writemem(s, j);
00141                             writemem("\\", 1);
00142                             writemem(s+j, 1);
00143                             ++j;
00144                             s += j;
00145                             i -= j;
00146                             j=0;
00147                             break;
00148                      }
00149 #if 0
00150                      if (s[j] == '&')
00151                      {
00152                             writemem(s, j);
00153                             writemem("&-", 2);
00154                             ++j;
00155                             s += j;
00156                             i -= j;
00157                             j=0;
00158                             break;
00159                      }
00160 
00161                      if (s[j] < ' ' || s[j] >= 0x7F)
00162                      {
00163                      char   *q;
00164 
00165                             writemem(s, j);
00166                             ++j;
00167                             s += j;
00168                             i -= j;
00169                             for (j=0; j<i; j++)
00170                                    if (s[j] >= ' ' && s[j] < 0x7F)
00171                                           break;
00172                             q=imap_utf7_encode(s, j);
00173                             if (!q)       write_error_exit(0);
00174                             writemem("&", 1);
00175                             writes(q);
00176                             writemem("-", 1);
00177                             s += j;
00178                             i -= j;
00179                             j=0;
00180                             break;
00181                      }
00182 #endif
00183               }
00184               writemem(s, j);
00185               s += j;
00186               i -= j;
00187        }
00188 }
00189 
00190 void write_error_exit(const char *funcname)
00191 {
00192        outbuf_cnt=0;
00193        writes("* BYE [ALERT] Fatal error: ");
00194        if (funcname && *funcname)
00195        {
00196               writes(funcname);
00197               writes(": ");
00198        }
00199 
00200        if (errno)
00201        {
00202 #if    HAVE_STRERROR
00203        const  char *p;
00204 
00205               p=strerror(errno);
00206 #else
00207        char   p[40];
00208 
00209               sprintf(p, "Error %d", (int)errno);
00210 #endif
00211 
00212 
00213               writes(p);
00214        }
00215        writes("\r\n");
00216        writeflush();
00217 
00218        if (funcname && *funcname)
00219        {
00220               fprintf(stderr, "ERR: %s: %s\n", getenv("AUTHENTICATED"),
00221                      funcname);
00222               fflush(stderr);
00223        }
00224        _exit(1);
00225 }