io.c
上传用户:pycemail
上传日期:2007-01-04
资源大小:329k
文件大小:10k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /*
  2.  * ProFTPD - FTP server daemon
  3.  * Copyright (c) 1997, 1998 Public Flood Software
  4.  *  
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
  18.  */
  19. #include "conf.h"
  20. #include <signal.h>
  21. #ifndef IAC
  22. #define IAC 255
  23. #endif
  24. #ifndef DONT
  25. #define DONT 254
  26. #endif
  27. #ifndef DO
  28. #define DO 253
  29. #endif
  30. #ifndef WONT
  31. #define WONT 252
  32. #endif
  33. #ifndef WILL
  34. #define WILL 251
  35. #endif
  36. void init_io()
  37. {
  38.   signal(SIGPIPE,SIG_IGN);
  39.   signal(SIGURG,SIG_IGN);
  40. }
  41. IOFILE *io_create(pool *p)
  42. {
  43.   IOFILE *res;
  44.   pool *newp;
  45.   newp = make_sub_pool(p);
  46.   res = (IOFILE*)pcalloc(newp,sizeof(IOFILE));
  47.   res->pool = newp;
  48.   res->fd = -1;
  49.   return res;
  50. }
  51. IOBUF *io_newbuf(IOFILE *f)
  52. {
  53.   IOBUF *newbuf;
  54.   newbuf = pcalloc(f->pool,sizeof(IOBUF));
  55.   newbuf->buf = newbuf->cp = palloc(f->pool,1024);
  56.   newbuf->left = newbuf->bufsize = 1024;
  57.   f->buf = newbuf;
  58.   return newbuf;
  59. }
  60. IOFILE *io_open(pool *p, int fd, int mode)
  61. {
  62.   IOFILE *res;
  63.   res = io_create(p);
  64.   res->fd = fd;
  65.   res->mode = mode;
  66.   return res;
  67. }
  68. IOFILE *io_reopen(IOFILE *f, int fd, int mode)
  69. {
  70.   if(f->fd != -1)
  71.     close(f->fd);
  72.   f->fd = fd;
  73.   f->mode = mode;
  74.   return f;
  75. }
  76. int io_close(IOFILE *f)
  77. {
  78.   int res;
  79.   res = close(f->fd);
  80.   f->fd = -1;
  81.   destroy_pool(f->pool);
  82.   return res;
  83. }
  84. void io_set_errno(IOFILE *f, int xerrno)
  85. {
  86.   f->xerrno = xerrno;
  87. }
  88. void io_abort(IOFILE *f)
  89. {
  90.   f->flags |= IO_ABORT;
  91. }
  92. void io_set_restart(IOFILE *f, int bool)
  93. {
  94.   if(bool)
  95.     f->flags &= ~IO_NORESTART;
  96.   else
  97.     f->flags |= IO_NORESTART;
  98. }
  99. void io_set_poll_sleep(IOFILE *f, unsigned int secs)
  100. {
  101.   f->flags |= IO_INTR;
  102.   f->restart_secs = secs;
  103. }
  104. /* io_poll is needed instead of simply blocking read/write because
  105.  * there is a race condition if the syscall _should_ be interrupted
  106.  * inside read(), or write(), but the signal is received before we
  107.  * actually hit the read or write call.  select() elleviates this
  108.  * problem by timing out (configurable by io_set_restart_interval()),
  109.  * restarting the syscall if IO_INTR is not set, or returning if it
  110.  * is set and we were interrupted by a signal.  If after the timeout
  111.  * IO_ABORT is set (presumably by a signal handler) or IO_INTR &
  112.  * errno == EINTR, we return 1.  Otherwise, return when data
  113.  * is available retunr 0 or -1 on other errors
  114.  */
  115. int io_poll(IOFILE *f)
  116. {
  117.   fd_set rs,ws,*rfds = NULL,*wfds = NULL;
  118.   struct timeval tv;
  119.   int res;
  120.   if(f->fd == -1) {
  121.     errno = EBADF;
  122.     return -1;
  123.   }
  124.   if(f->flags & IO_ABORT) {
  125.     f->flags &= ~IO_ABORT;
  126.     return 1;
  127.   }
  128.   while(1) {
  129.     run_schedule();
  130.     FD_ZERO(&rs); FD_ZERO(&ws);
  131.     if(f->mode == IO_READ) {
  132.       FD_SET(f->fd,&rs);
  133.       rfds = &rs;
  134.     } else {
  135.       FD_SET(f->fd,&ws);
  136.       wfds = &ws;
  137.     }
  138.     tv.tv_sec = ((f->flags & IO_INTR) ? f->restart_secs : 60);
  139.     tv.tv_usec = 0;
  140.     res = select(f->fd + 1,rfds,wfds,NULL,&tv);
  141.     switch(res) {
  142.     case -1:
  143.       if(errno == EINTR) {
  144.         if(f->flags & IO_ABORT) {
  145.           f->flags &= ~IO_ABORT;
  146.           return 1;
  147.         }
  148. /* otherwise, restart the call */
  149.         continue;
  150.       }
  151.       /* some other error occured */
  152.       io_set_errno(f,errno);
  153.       return -1;
  154.     case 0:
  155.       /* in case the kernel doesn't support interrupted syscalls */
  156.       if(f->flags & IO_ABORT) {
  157.         f->flags &= ~IO_ABORT;
  158.         return 1;
  159.       }
  160.       continue;
  161.     default:
  162.       return 0;
  163.     }
  164.   }
  165.   /* this will never be reached */
  166.   return -1;
  167. }
  168. int io_write(IOFILE *f, char *buf, int size)
  169. {
  170.   int written,total = 0;
  171.   if(f->fd == -1) {
  172.     errno = (f->xerrno ? f->xerrno : EBADF);
  173.     return -1;
  174.   }
  175.   while(size) {
  176.     switch(io_poll(f)) {
  177.       case 1: return -2;
  178.       case -1: return -1;
  179.       default:
  180.         /* we have to potentially restart here as well, in case
  181.          * we get EINTR.
  182.          */
  183.         do {
  184.           run_schedule();
  185.           written = write(f->fd,buf,size);
  186.         } while(written == -1 && errno == EINTR);
  187.         break;
  188.     }
  189.     if(written == -1) {
  190.       io_set_errno(f,errno);
  191.       return -1;
  192.     }
  193.     buf += written; total += written;
  194.     size -= written;
  195.     /* if IO_NORESTART is set, drop out of the loop now and simply
  196.      * return the data received
  197.      */
  198.     if(f->flags & IO_NORESTART)
  199.       break;
  200.   }
  201.   return total;
  202. }
  203. /* This is a bit odd, because io_ functions are opaque, we can't be sure
  204.  * we are dealing with a conn_t or that it is in O_NONBLOCK mode.  Trying
  205.  * to do this without O_NONBLOCK would cause the kernel itself to block
  206.  * here, and thus invalidate the whole principal.  Instead we save
  207.  * the flags and put the fd in O_NONBLOCK mode.
  208.  */
  209. int io_write_async(IOFILE *f, char *buf, int size)
  210. {
  211.   int flags;
  212.   int written,total = 0;
  213.   if(f->fd == -1) {
  214.     errno = (f->xerrno ? f->xerrno : EBADF);
  215.     return -1;
  216.   }
  217.   
  218.   if((flags = fcntl(f->fd,F_GETFL)) == -1)
  219.     return -1;
  220.   if(fcntl(f->fd,F_SETFL,flags|O_NONBLOCK) == -1)
  221.     return -1;
  222.   while(size) {
  223.     do {
  224.       written = write(f->fd,buf,size);
  225.     } while(written == -1 && errno == EINTR);
  226.     
  227.     if(written < 0) {
  228.       io_set_errno(f,errno);
  229.       fcntl(f->fd,F_SETFL,flags);
  230.       if(f->xerrno == EWOULDBLOCK)
  231.         /* Give up ... */
  232.         return total;
  233.    
  234.       return -1;
  235.     }
  236.     buf += written; total += written;
  237.     size -= written;
  238.   }
  239.   fcntl(f->fd,F_SETFL,flags);
  240.   return total;
  241. }
  242. /* size - buffer size
  243.  * min  - min. octets to read before returning (1 or >)
  244.  *        (ignored if IO_NORESTART is set for the file)
  245.  */
  246. int io_read(IOFILE *f, char *buf, int size, int min)
  247. {
  248.   int bread = 0,total = 0;
  249.   if(f->fd == -1) {
  250.     errno = (f->xerrno ? f->xerrno : EBADF);
  251.     return -1;
  252.   }
  253.   if(min < 1)
  254.     min = 1;
  255.   if(min > size)
  256.     min = size;
  257.   while(min > 0) {
  258.     switch(io_poll(f)) {
  259.       case 1: return -2;
  260.       case -1: return -1;
  261.       default:
  262.         do {
  263. #if 0
  264.   if(bread == 1 && errno == EINTR)
  265. log_debug(DEBUG4,"io_read: interrupted syscall");
  266. #endif
  267.           run_schedule();
  268.           bread = read(f->fd,buf,size);
  269.         } while(bread == -1 && errno == EINTR);
  270.         break;
  271.     }
  272.     if(bread == -1) {
  273.       io_set_errno(f,errno);
  274.       return -1;
  275.     }
  276.     /* EOF? */
  277.     if(bread == 0) {
  278.       io_set_errno(f,0);
  279.       break;
  280.     }
  281.     
  282.     buf += bread; total += bread;
  283.     min -= bread;
  284.     size -= bread;
  285.     /* minimum octets to receive is ignored if IO_NORESTART is set */
  286.     if(f->flags & IO_NORESTART)
  287.       break;
  288.   }
  289.   return total;
  290. }
  291. int io_printf(IOFILE *f, char *fmt, ...)
  292. {
  293.   va_list msg;
  294.   char buf[1025];
  295.   va_start(msg,fmt);
  296.   vsnprintf(buf,sizeof(buf),fmt,msg);
  297.   va_end(msg);
  298.   buf[1024] = '';
  299.   return io_write(f,buf,strlen(buf));
  300. }
  301. /* io_printf_async() is for use inside alarm handlers, where no io_poll()
  302.  * blocking is allowed.  This is necessary because otherwise, io_poll()
  303.  * can potentially hang forever if the Send-Q is maxed and the socket
  304.  * has been closed.
  305.  */
  306. int io_printf_async(IOFILE *f, char *fmt, ...)
  307. {
  308.   va_list msg;
  309.   char buf[1025];
  310.   va_start(msg,fmt);
  311.   vsnprintf(buf,sizeof(buf),fmt,msg);
  312.   va_end(msg);
  313.   buf[1024] = '';
  314.   return io_write_async(f,buf,strlen(buf));
  315. }
  316. char *io_gets(char *buf, int size, IOFILE *f)
  317. {
  318.   char *bp = buf;
  319.   int toread;
  320.   IOBUF *iobuf;
  321.   size--;
  322.   if(!f->buf)
  323.     iobuf = io_newbuf(f);
  324.   else
  325.     iobuf = f->buf;
  326.   while(size) {
  327.     if(!iobuf->cp || iobuf->left == 1024) { /* Empty buffer */
  328.       toread = io_read(f,iobuf->buf,(size < 1024 ? size : 1024),1);
  329.       if(toread <= 0) {
  330.         if(bp != buf) {
  331.           *bp = '';
  332.           return buf;
  333.         } else
  334.           return NULL;
  335.       }
  336.       iobuf->left = 1024 - toread;
  337.       iobuf->cp = iobuf->buf;
  338.     } else
  339.       toread = 1024 - iobuf->left;
  340.     while(size && *iobuf->cp != 'n' && toread--) {
  341.       if(*iobuf->cp & 0x80)
  342.         iobuf->cp++;
  343.       else {
  344.         *bp++ = *iobuf->cp++;
  345.         size--;
  346.       }
  347.       iobuf->left++;
  348.     }
  349.     if(size && toread && *iobuf->cp == 'n') {
  350.       size--; toread--;
  351.       *bp++ = *iobuf->cp++;
  352.       iobuf->left++;
  353.       break;
  354.     }
  355.     if(!toread)
  356.       iobuf->cp = NULL;
  357.   }
  358.   *bp = '';
  359.   return buf;
  360. }
  361. /* io_telnet_gets() is exactly like io_gets, except a few special
  362.  * telnet characters are handled (which takes care of the [IAC]ABOR
  363.  * command, and odd clients
  364.  */
  365. char *io_telnet_gets(char *buf, int size, IOFILE *f, IOFILE *o)
  366. {
  367.   char *bp = buf;
  368.   unsigned char cp;
  369.   static unsigned char mode = 0;
  370.   int toread;
  371.   IOBUF *iobuf;
  372.   size--;
  373.   if(!f->buf)
  374.     iobuf = io_newbuf(f);
  375.   else
  376.     iobuf = f->buf;
  377.   while(size) {
  378.     if(!iobuf->cp || iobuf->left == 1024) { /* Empty buffer */
  379.       toread = io_read(f,iobuf->buf,(size < 1024 ? size : 1024),1);
  380.       if(toread <= 0) {
  381.         if(bp != buf) {
  382.           *bp = '';
  383.           return buf;
  384.         } else
  385.           return NULL;
  386.       }
  387.       iobuf->left = 1024 - toread;
  388.       iobuf->cp = iobuf->buf;
  389.     } else
  390.       toread = 1024 - iobuf->left;
  391.     while(size && *iobuf->cp != 'n' && toread--) {
  392.       cp = *iobuf->cp++; iobuf->left++;
  393.       switch(mode) {
  394.       case IAC:
  395.         switch(cp) {
  396.         case WILL:
  397.         case WONT:
  398.         case DO:
  399.         case DONT:
  400.           mode = cp;
  401.           continue;
  402.         case IAC:
  403.           mode = 0;
  404.           break;
  405.         default:
  406.           /* ignore */
  407.           mode = 0;
  408.           continue;
  409.         }       
  410.         break;
  411.       case WILL:
  412.       case WONT:
  413.         io_printf(o,"%c%c%c", IAC, DONT, cp);
  414.         mode = 0;
  415.         continue;
  416.       case DO:
  417.       case DONT:
  418.         io_printf(o,"%c%c%c", IAC, WONT, cp);
  419.         mode = 0;
  420.         continue;
  421.       default:
  422.         if(cp == IAC) {
  423.           mode = cp;
  424.           continue;
  425.         }
  426.         break;
  427.       }
  428.       *bp++ = cp;
  429.       size--;
  430.     }
  431.     if(size && toread && *iobuf->cp == 'n') {
  432.       size--; toread--;
  433.       *bp++ = *iobuf->cp++;
  434.       iobuf->left++;
  435.       break;
  436.     }
  437.     if(!toread)
  438.       iobuf->cp = NULL;
  439.   }
  440.   *bp = '';
  441.   return buf;
  442. }