Back to index

courier  0.68.2
esmtpiov.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2001 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 #if    HAVE_UNISTD_H
00011 #include      <unistd.h>
00012 #endif
00013 #if    HAVE_FCNTL_H
00014 #include      <fcntl.h>
00015 #endif
00016 #include      <ctype.h>
00017 #include      <string.h>
00018 #include      <stdlib.h>
00019 #include      <sys/types.h>
00020 #include      <sys/uio.h>
00021 #include      <sys/time.h>
00022 #include      <signal.h>
00023 #include      <errno.h>
00024 
00025 #include      "esmtpiov.h"
00026 
00027 time_t iovread_timeout=300;
00028 time_t iovwrite_timeout=60;
00029 static char inputbuf[5120];
00030 static char *inputbufhead=inputbuf, *inputbuftail=inputbuf;
00031 static int overflowed=0;
00032 static struct iovec iov[10];
00033 static int    niovec=0;
00034 
00035 void iovreset()
00036 {
00037        inputbufhead=inputbuftail=inputbuf;
00038 }
00039 
00040 void iovflush()
00041 {
00042 struct iovec *iovp=iov;
00043 unsigned niovp=niovec;
00044 int    n;
00045 fd_set fds;
00046 struct timeval       tv;
00047 
00048        while (niovp && niovec)
00049        {
00050               FD_ZERO(&fds);
00051               FD_SET(1, &fds);
00052               tv.tv_sec=iovwrite_timeout;
00053               tv.tv_usec=0;
00054               if (select(2, 0, &fds, 0, &tv) <= 0 ||
00055                      !FD_ISSET(1, &fds) ||
00056                      (n=writev(1, iov, niovec)) <= 0)
00057               {
00058                      iov_logerror("writev: ",
00059 #if HAVE_STRERROR
00060                                  strerror(errno)
00061 
00062 #else
00063                                  "write error"
00064 #endif
00065                                  );
00066                      exit(1);
00067               }
00068 
00069               while (n && niovp)
00070               {
00071                      if (n >= iovp->iov_len)
00072                      {
00073                             n -= iovp->iov_len;
00074                             ++iovp;
00075                             --niovp;
00076                             continue;
00077                      }
00078                      iovp->iov_base=(caddr_t)
00079                             ( (char *)iovp->iov_base + n);
00080                      iovp->iov_len -= n;
00081                      break;
00082               }
00083        }
00084        niovec=0;
00085 }
00086 
00087 int iovwaitfordata(time_t *t, int abort)
00088 {
00089 time_t now;
00090 
00091        time(&now);
00092        if (now < *t)
00093        {
00094        fd_set fds;
00095        struct timeval       tv;
00096 
00097               FD_ZERO(&fds);
00098               FD_SET(0, &fds);
00099               tv.tv_sec=*t - now;
00100               tv.tv_usec=0;
00101               if (select(1, &fds, 0, 0, &tv) > 0 &&
00102                      FD_ISSET(0, &fds))
00103                      return (0);
00104        }
00105 
00106        errno=ETIMEDOUT;
00107 
00108        {
00109 #if HAVE_STRERROR
00110               const char *ip=getenv("TCPREMOTEIP");
00111 
00112               if (ip && *ip)
00113                      fprintf(stderr, "[%s]: %s\n", ip,
00114                             strerror(errno));
00115               else
00116 #endif
00117                      perror("read");
00118        }
00119        if (abort)
00120               exit(1);
00121        return (-1);
00122 }
00123 
00124 char *iovreadline()
00125 {
00126 char *p=inputbufhead;
00127 time_t t;
00128 
00129        time(&t);
00130        t += iovread_timeout;
00131        iovflush();
00132        for (;;)
00133        {
00134               if (p >= inputbuftail)
00135               {
00136               int    n;
00137 
00138                      if (inputbufhead == inputbuftail)
00139                      {
00140                             inputbufhead=inputbuftail=inputbuf;
00141                             iovwaitfordata(&t, 1);
00142                             n=read(0, inputbuf, sizeof(inputbuf));
00143                             if (n <= 0)   _exit(0);
00144                             inputbuftail=inputbuf+n;
00145                             p=inputbuf;
00146                             continue;
00147                      }
00148                      if (inputbufhead > inputbuf)
00149                      {
00150                             n=0;
00151                             while (inputbufhead < inputbuftail)
00152                                    inputbuf[n++]= *inputbufhead++;
00153                             inputbuftail=p=inputbuf+n;
00154                             inputbufhead=inputbuf;
00155                      }
00156                      if (inputbuftail >= inputbuf+sizeof(inputbuf))
00157                      {
00158                             if (overflowed)      /* Already overflowed once */
00159                             {
00160                                    inputbuf[0]=inputbuftail[-1];
00161                                    inputbufhead=inputbuf;
00162                                    inputbuftail=inputbufhead+1;
00163                                    p=inputbuftail;
00164                                    continue;
00165                             }
00166                             overflowed=1;
00167                             inputbuftail[-2]=0;
00168                             inputbufhead=inputbuftail-1;
00169                             return (inputbuf);
00170                      }
00171                      iovwaitfordata(&t, 1);
00172                      n=read(0, inputbuftail, inputbuf+sizeof(inputbuf)-
00173                                    inputbuftail);
00174                      if (n <= 0)   _exit(0);
00175                      inputbuftail += n;
00176               }
00177 
00178               if (*p == '\n' && p > inputbufhead && p[-1] == '\r')
00179               {
00180               char *q=inputbufhead;
00181 
00182                      p[-1]=0;
00183                      *p++=0;
00184                      inputbufhead=p;
00185                      if (overflowed)
00186                      {
00187                             overflowed=0;
00188                             continue;
00189                      }
00190                      return (q);
00191               }
00192               ++p;
00193        }
00194 }
00195 
00196 void addiovec(const char *p, size_t l)
00197 {
00198        iov[niovec].iov_base=(caddr_t)p;
00199        iov[niovec].iov_len=l;
00200        if (++niovec >= sizeof(iov)/sizeof(iov[0]))
00201               iovflush();
00202 }