fdstdio.c
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:29k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** fdstdio.c
  3. **
  4. ** Copyright (c) 1995 Peter Eriksson <pen@signum.se>
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  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., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdio.h>
  20. #include <stdarg.h>
  21. #include <stdlib.h>
  22. #include <unistd.h>
  23. #include <fcntl.h>
  24. #include <errno.h>
  25. #include <thread.h>
  26. #include <string.h>
  27. #include <syslog.h>
  28. #ifdef __sgi
  29. #include <bstring.h>
  30. #endif
  31. #include <sys/time.h>
  32. #include <sys/types.h>
  33. #include <sys/wait.h>
  34. #include <sys/ioctl.h>
  35. #ifndef __osf__
  36. #include <sys/filio.h>
  37. #endif
  38. #include <sys/socket.h>
  39. #include <netinet/in.h>
  40. #include <netinet/in_systm.h>
  41. #include <netinet/ip.h>
  42. #include <netinet/tcp.h>
  43. #include <arpa/inet.h>
  44. #include <netdb.h>
  45. #include <sys/resource.h>
  46. #include "phttpd.h"
  47. int so_sndbuf = 0;
  48. int so_rcvbuf = 0;
  49. int select_timeout = 2*60;
  50. int max_fds = 0;
  51. static struct fd_buffer **buffer = NULL;
  52. #define FD_INVALID(fd) ((fd) < 0 || (fd) >= max_fds)
  53.     
  54. /*
  55. ** Terminate (generate a core) with an error message
  56. */
  57. static void fd_error(char *format, ...)
  58. {
  59.     va_list ap;
  60.     
  61.     va_start(ap, format);
  62.     syslog(LOG_ERR, "fatal fdstdio error: %s", format);
  63.     
  64.     if (debug > 1)
  65.     {
  66. fprintf(stderr, "*** FDStdio Error: ");
  67. vfprintf(stderr, format, ap);
  68. perror("");
  69. putc('n', stderr);
  70. fflush(stderr);
  71.     }
  72.     
  73.     va_end(ap);
  74.     s_abort();
  75. }
  76. /*
  77. ** Initialize the FDSTDIO subsystem
  78. */
  79. void fd_init(void)
  80. {
  81.     int i;
  82.     struct rlimit rlb;
  83.     
  84.     if (getrlimit(RLIMIT_NOFILE, &rlb) < 0)
  85.     {
  86. syslog(LOG_ERR, "getrlimit() failed: %m");
  87. if (debug > 1)
  88.     perror("getrlimit()");
  89. rlb.rlim_max = 64;
  90.     }
  91.     
  92.     rlb.rlim_cur = rlb.rlim_max;
  93.     
  94.     if (setrlimit(RLIMIT_NOFILE, &rlb) < 0)
  95.     {
  96. syslog(LOG_ERR, "setrlimit() failed: %m");
  97. if (debug > 1)
  98.     perror("setrlimit()");
  99.     }
  100.     
  101.     max_fds = rlb.rlim_cur;
  102.     
  103.     buffer = s_malloc(sizeof(struct fd_buffer *) * max_fds);
  104.     
  105.     for (i = 0; i < max_fds; i++)
  106.     {
  107. struct fd_buffer *bp;
  108. bp = buffer[i] = s_malloc(sizeof(struct fd_buffer));
  109. mutex_init(&bp->in.lock, USYNC_THREAD, NULL);
  110. mutex_init(&bp->out.lock, USYNC_THREAD, NULL);
  111. bp->in.buf = NULL;
  112. bp->in.size = 0;
  113. bp->out.buf = NULL;
  114. bp->out.size = 0;
  115. bp->in.state = FDS_FREE;
  116. bp->out.state = FDS_FREE;
  117.     }
  118. }
  119. /*
  120. ** Associate an FDSTDIO buffer with a file descriptor
  121. */
  122. void fd_reopen(int fd, int how, int type)
  123. {
  124.     int val;
  125.     struct fd_buffer *bp = buffer[fd];
  126.     if (FD_INVALID(fd))
  127. fd_error("fd_reopen(%d): Invalid file descriptor!n", fd);
  128.     
  129.     if (bp->in.state != FDS_FREE || bp->out.state != FDS_FREE)
  130. fd_error("fd_reopen(%d): Already opened!n", fd);
  131.     
  132.     bp->type = type;
  133.     
  134.     bp->in.start = 2;
  135.     bp->in.end = 2;
  136.     bp->in.save = 0;
  137.     bp->in.count = 0;
  138.     how &= 3;
  139.     
  140.     if (how == O_RDONLY || how == O_RDWR)
  141.     {
  142. /* XXX - if O_RDONLY and FDT_FILE, use mmap :-) */
  143. bp->in.buf = s_malloc(BUFFER_SIZE+2);
  144. bp->in.size = BUFFER_SIZE+2;
  145. bp->in.state = FDS_OPEN;
  146.     }
  147.     else
  148.     {
  149. bp->in.buf = NULL;
  150. bp->in.size = 0;
  151. bp->in.state = FDS_EOF;
  152.     }
  153.     bp->out.start = 0;
  154.     bp->out.end = 0;
  155.     bp->out.save = 0;
  156.     bp->out.count = 0;
  157.     
  158.     if (how == O_WRONLY || how == O_RDWR)
  159.     {
  160. bp->out.buf = s_malloc(BUFFER_SIZE);
  161. bp->out.size = BUFFER_SIZE;
  162. bp->out.state = FDS_OPEN;
  163.     }
  164.     else
  165.     {
  166. bp->out.buf = NULL;
  167. bp->out.size = 0;
  168. bp->out.state = FDS_EOF;
  169.     }
  170.     if (type == FDT_SOCKET)
  171.     {
  172. if (so_sndbuf > 0)
  173.     setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
  174.        (void *) &so_sndbuf, sizeof(so_sndbuf));
  175. if (so_rcvbuf > 0)
  176.     setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
  177.        (void *) &so_rcvbuf, sizeof(so_rcvbuf));
  178. val = 1;
  179. setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *) &val, sizeof(val));
  180. val = 1;
  181. setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *) &val, sizeof(val));
  182. val = IPTOS_LOWDELAY;
  183. setsockopt(fd, IPPROTO_IP, IP_TOS, (void *) &val, sizeof(val));
  184.     }
  185. }
  186. int fd_close(int fd)
  187. {
  188.     struct fd_buffer *bp = buffer[fd];
  189.     int length;
  190.     
  191.     if (FD_INVALID(fd))
  192. fd_error("fd_close(%d): Invalid file descriptor!n", fd);
  193.     
  194.     fd_flush(fd);
  195.     mutex_lock(&bp->in.lock);
  196.     bp->in.state = FDS_FREE;
  197.     if (bp->in.buf)
  198.     {
  199. s_free(bp->in.buf);
  200. bp->in.buf = NULL;
  201. bp->in.size = 0;
  202.     }
  203.     mutex_unlock(&bp->in.lock);
  204.     
  205.     mutex_lock(&bp->out.lock);
  206.     bp->out.state = FDS_FREE;
  207.     if (bp->out.buf)
  208.     {
  209. s_free(bp->out.buf);
  210. bp->out.buf = NULL;
  211. bp->out.size = 0;
  212.     }
  213.     length = bp->out.count;
  214.     mutex_unlock(&bp->out.lock);
  215.     s_close(fd);
  216.     return length;
  217. }
  218. int fd_shutdown(int fd, int how)
  219. {
  220.     struct fd_buffer *bp;
  221.     int status, dont_lock;
  222.     
  223.     if (FD_INVALID(fd))
  224. fd_error("fd_shutdown(%d): Invalid file descriptor!n", fd);
  225.     
  226.     bp = buffer[fd];
  227.     
  228.     if (how < 0)
  229.     {
  230. how = -how;
  231. dont_lock = 1;
  232.     }
  233.     else
  234. dont_lock = 0;
  235.     if (how == 1 || how == 2)
  236.     {
  237. if (!dont_lock)
  238. {
  239.     fd_flush(fd);
  240.     mutex_lock(&bp->out.lock);
  241. }
  242. bp->out.state = FDS_EOF;
  243. if (!dont_lock)
  244.     mutex_unlock(&bp->out.lock);
  245.     }
  246.     if (how == 0 || how == 2)
  247.     {
  248. if (!dont_lock)
  249.     mutex_lock(&bp->in.lock);
  250. bp->in.state = FDS_EOF;
  251. if (!dont_lock)
  252.     mutex_unlock(&bp->in.lock);
  253.     }
  254.     status = 0;
  255.     if (bp->type != FDT_FILE)
  256. s_shutdown(fd, how);
  257.     return status;
  258. }
  259. int fd_foreach(int (*fcnp)(int fd,
  260.    struct fd_buffer *bp,
  261.    void *misc),
  262.        void *misc)
  263. {
  264.     int i, status;
  265.     status = 0;
  266.     
  267.     for (i = 0; i < max_fds; i++)
  268.     {
  269. if (mutex_trylock(&buffer[i]->in.lock))
  270. {
  271.     /* fd buffer was busy, call fd_foreach, but with a
  272.        NULL buffer pointer */
  273.     if ((status = (*fcnp)(i, NULL, misc)) != 0)
  274. break;
  275.     
  276.     continue;
  277. }
  278. if (mutex_trylock(&buffer[i]->out.lock))
  279. {
  280.     /* We got the input lock, but the output lock was busy.
  281.        So we just call fd_foreach with a NULL buffer pointer */
  282.     
  283.     mutex_unlock(&buffer[i]->in.lock);
  284.     
  285.     if ((status = (*fcnp)(i, NULL, misc)) != 0)
  286. break;
  287.     continue;
  288. }
  289. if (buffer[i]->in.state != FDS_FREE)
  290.     if ((status = (*fcnp)(i, buffer[i], misc)) != 0)
  291.     {
  292. mutex_unlock(&buffer[i]->out.lock);
  293. mutex_unlock(&buffer[i]->in.lock);
  294. break;
  295.     }
  296. mutex_unlock(&buffer[i]->out.lock);
  297. mutex_unlock(&buffer[i]->in.lock);
  298.     }
  299.     return status;
  300. }
  301. int fd_open(const char *file, int how, ...)
  302. {
  303.     int fd, mode;
  304.     va_list ap;
  305.     
  306.     va_start(ap, how);
  307.     if (how & O_CREAT)
  308.     {
  309. mode = va_arg(ap, int);
  310. fd = s_open(file, how, mode);
  311.     }
  312.     else
  313. fd = s_open(file, how);
  314.     
  315.     va_end(ap);
  316.     
  317.     if (fd < 0)
  318. return -1;
  319.     fd_reopen(fd, how, FDT_FILE);
  320.     
  321.     return fd;
  322. }
  323. int fd_connect(struct sockaddr *sap, int len)
  324. {
  325.     int sock, status;
  326.     if (debug > 6)
  327. fprintf(stderr, "fd_connect(): socket()n");
  328.     
  329.     sock = socket(AF_INET, SOCK_STREAM, 0);
  330.     if (sock < 0)
  331. return -1;
  332.     if (debug > 6)
  333. fprintf(stderr, "fd_connect(): s_connect()n");
  334.     
  335.     status = s_connect(sock, sap, len);
  336.     
  337.     if (status < 0)
  338.     {
  339. s_close(sock);
  340. return -1;
  341.     }
  342.     if (debug > 6)
  343. fprintf(stderr, "fd_connect(): fd_reopen()n");
  344.     
  345.     fd_reopen(sock, 2, FDT_SOCKET);
  346.     return sock;
  347. }
  348. int fd_mksockaddr_in(const char *host,
  349.      char *service,
  350.      struct sockaddr_in *sin)
  351. {
  352.     memset(sin, 0, sizeof(sin));
  353.     
  354.     sin->sin_family = AF_INET;
  355.     if (s_isdigit(host[0]))
  356. sin->sin_addr.s_addr = inet_addr(host);
  357.     else
  358.     {
  359. struct hostent hp;
  360. char buf[2048];
  361. if (s_gethostbyname_r(host, &hp, buf, sizeof(buf), &h_errno) == NULL)
  362.     return -1;
  363. memcpy(&sin->sin_addr, hp.h_addr_list[0], hp.h_length);
  364.     }
  365.     if (s_isdigit(service[0]))
  366. sin->sin_port = htons(atoi(service));
  367.     else
  368.     {
  369. struct servent sp;
  370. char buf[2048];
  371. if (getservbyname_r(service, "tcp", &sp, buf, sizeof(buf)) == NULL)
  372.     return -1;
  373. sin->sin_port = sp.s_port;
  374.     }
  375.     return 0;
  376. }
  377. /*
  378. ** Initiate a socket TCP/IP connection to a foreign host/port
  379. */
  380. int fd_sconnect(const char *host, char *service)
  381. {
  382.     struct sockaddr_in sin;
  383.     if (debug > 5)
  384. fprintf(stderr, "fd_sconnect(): Calling fd_mksockaddr()n");
  385.     
  386.     if (fd_mksockaddr_in(host, service, &sin) < 0)
  387. return -1;
  388.     if (debug > 5)
  389. fprintf(stderr, "fd_sconnect(): Calling fd_connect()n");
  390.     
  391.     return fd_connect((struct sockaddr *) &sin, sizeof(sin));
  392. }
  393. /* ********************************************************************** */
  394. static int _fd_fionread(int fd)
  395. {
  396.     struct fd_buffer *bp = buffer[fd];
  397.     int avail, status;
  398.     
  399.     if (bp->in.state == FDS_EOF)
  400. return -1;
  401.     if (bp->type == FDT_SOCKET)
  402. return 65536;
  403.     
  404.     if (bp->type == FDT_FILE)
  405.     {
  406. struct stat sb;
  407. int cpos;
  408. if (fstat(fd, &sb) < 0)
  409. {
  410.     syslog(LOG_INFO,
  411.    "_fd_fionread(): fstat() failed: %m");
  412.     bp->in.state = FDS_EOF;
  413.     return -1;
  414. }
  415. cpos = lseek(fd, 0, SEEK_CUR);
  416. if (cpos < 0)
  417. {
  418.     syslog(LOG_INFO, "_fd_fionread(): lseek() failed: %m");
  419.     bp->in.state = FDS_EOF;
  420.     return -1;
  421. }
  422. avail = sb.st_size - cpos;
  423.     }
  424.     else
  425.     {
  426. avail = -2;
  427. status = s_ioctl(fd, FIONREAD, &avail);
  428.     
  429. if (status < 0 || avail < 0)
  430. {
  431.     syslog(LOG_INFO, "_fd_fionread(): ioctl(FIONREAD) failed: %m");
  432.     bp->in.state = FDS_EOF;
  433.     return status;
  434. }
  435.     }
  436.     return avail;
  437. }
  438. static int _fd_avail(int fd)
  439. {
  440.     struct fd_buffer *bp = buffer[fd];
  441.     int avail, status;
  442.     
  443.     avail = bp->in.end - bp->in.start;
  444.     status = _fd_fionread(fd);
  445.     if (status > 0)
  446. avail += status;
  447.     return avail;
  448. }
  449. int fd_avail(int fd)
  450. {
  451.     struct fd_buffer *bp = buffer[fd];
  452.     int avail;
  453.     
  454.     if (FD_INVALID(fd))
  455. fd_error("fd_avail(%d): Invalid file descriptor!n", fd);
  456.     
  457.     mutex_lock(&bp->in.lock);
  458.     if (bp->in.state == FDS_FREE)
  459. fd_error("fd_avail(%d): Not openedn", fd);
  460.     
  461.     avail = _fd_avail(fd);
  462.     
  463.     mutex_unlock(&bp->in.lock);
  464.     
  465.     return avail;
  466. }
  467. static int _fd_wait(int fd)
  468. {
  469.     struct fd_buffer *bp = buffer[fd];
  470.     int status;
  471.     fd_set fds;
  472.     if (bp->in.state == FDS_EOF)
  473. return -1;
  474.     if (bp->type == FDT_FILE)
  475. return 1;
  476.     
  477.     FD_ZERO(&fds);
  478.     FD_SET(fd, &fds);
  479.     if (select_timeout)
  480.     {
  481. struct timeval tvb;
  482. tvb.tv_sec = select_timeout;
  483. tvb.tv_usec = 0;
  484.     
  485. /*
  486. ** Why oh why can't all Unixes be like Linux and automatically
  487. ** update the Timeout structure if select() exits prematurely?
  488. */
  489. status = s_select(fd+1, &fds, NULL, NULL, &tvb);
  490.     }
  491.     else
  492. status = s_select(fd+1, &fds, NULL, NULL, NULL);
  493.     if (status < 0)
  494. syslog(LOG_INFO, "_fd_wait(): select() failed: %m");
  495.     
  496.     if (status <= 0)
  497. bp->in.state = FDS_EOF;
  498.     
  499.     if (_fd_fionread(fd) <= 0)
  500.     {
  501. if (debug > 10)
  502.     fprintf(stderr,
  503.     "fdstdio.c: _fd_wait(%d): _fd_fionread() <= 0: EOFn", fd);
  504. bp->in.state = FDS_EOF;
  505. status = -1;
  506.     }
  507.     
  508.     return status;
  509. }
  510. int fd_wait(int fd)
  511. {
  512.     struct fd_buffer *bp = buffer[fd];
  513.     int status, avail;
  514.     
  515.     if (FD_INVALID(fd))
  516. fd_error("fd_wait(%d): Invalid file descriptor!n", fd);
  517.     
  518.     mutex_lock(&bp->in.lock);
  519.     if (bp->in.state == FDS_FREE)
  520. fd_error("fd_avail(%d): Not openedn", fd);
  521.     avail = _fd_avail(fd);
  522.     if (avail < 0)
  523. status = -1;
  524.     else if (avail == 0)
  525. status = _fd_wait(fd);
  526.     else
  527. status = 1;
  528.     
  529.     mutex_unlock(&bp->in.lock);
  530.     return status;
  531. }
  532. #define FD_AVAIL(bp)   (bp->in.end - bp->in.start)
  533. /*
  534. ** Returns the number of bytes available in the input buffer,
  535. ** or -1 when there is nothing in the buffer and EOF or an error
  536. ** has been seen.
  537. */
  538. static int _fd_fill(int fd)
  539. {
  540.     struct fd_buffer *bp = buffer[fd];
  541.     int empty, avail, status;
  542.     if (bp->in.start == bp->in.end)
  543.     {
  544. bp->in.start = 2;
  545. bp->in.end = 2;
  546.     }
  547.     /* Get the number of bytes available in the buffer */
  548.     empty = bp->in.size - bp->in.end;
  549.     if (empty == 0)
  550.     {
  551. avail = FD_AVAIL(bp);
  552. if (debug > 9)
  553.     fprintf(stderr, "_fd_fill(), returning %dn", avail);
  554.     
  555. return avail;
  556.     }
  557.     
  558.     /* Get the number of bytes awaiting in the kernel */
  559.     avail = _fd_fionread(fd);
  560.     if (debug > 9)
  561. fprintf(stderr, "_fd_fill(): _fd_fionread(%d) = %dn", fd, avail);
  562.     if (avail < 0)
  563.     {
  564. avail = FD_AVAIL(bp);
  565. if (avail == 0)
  566.     return -1;
  567. else
  568.     return avail;
  569.     }
  570.     if (avail > 0)
  571.     {
  572. if (empty < avail)
  573.     avail = empty;
  574. if (bp->in.state == FDS_EOF)
  575.     status = -1;
  576. else
  577. {
  578.     if (debug > 9)
  579. fprintf(stderr, "_fd_fill(): s_read(%d, .., %d)n",
  580. fd, avail);
  581.     
  582.     status = s_read(fd, bp->in.buf + bp->in.end, avail);
  583.     if (status < 0)
  584. syslog((errno == EPIPE || errno == ECONNRESET) ?
  585.        LOG_INFO : LOG_ERR,
  586.        "_fd_fill(): s_read(%d, .., %d) failed: %m",
  587.        fd, avail);
  588. }
  589. if (status <= 0)
  590. {
  591.     bp->in.state = FDS_EOF;
  592.     
  593.     avail = FD_AVAIL(bp);
  594.     
  595.     if (avail == 0)
  596. return -1;
  597.     else
  598. return avail;
  599. }
  600. bp->in.end += status;
  601.     }
  602.     return FD_AVAIL(bp);
  603. }     
  604. static int _fd_bfill(int fd)
  605. {
  606.     int avail;
  607.     
  608.     avail = _fd_fill(fd);
  609.     if (avail == 0)
  610.     {
  611. if (debug > 10)
  612.     fprintf(stderr, "_fd_bfill(%d): before _fd_wait()n", fd);
  613. if (_fd_wait(fd) < 0)
  614. {
  615.     if (debug > 10)
  616. fprintf(stderr, "_fd_bfill(%d): _fd_wait() failedn", fd);
  617.     return -1;
  618. }
  619. avail = _fd_fill(fd);
  620.     }
  621.     
  622.     return avail;
  623. }
  624. static int _fd_read(int fd, char *buf, int len)
  625. {
  626.     struct fd_buffer *bp = buffer[fd];
  627.     int avail, got;
  628.     got = 0;
  629.     if (debug > 10)
  630. fprintf(stderr, "_fd_read(%d, ..., %d): Startn",
  631. fd, len);
  632.     
  633.     avail = FD_AVAIL(bp);
  634.     if (avail == 0)
  635.     {
  636. if (bp->type != FDT_FILE)
  637.     if (_fd_wait(fd) < 0)
  638.     {
  639. if (debug > 10)
  640.     fprintf(stderr, "_fd_read(%d): _fd_wait(): failedn", fd);
  641. return -1;
  642.     }
  643.     }
  644.     else
  645.     {
  646.         if (avail > len)
  647.     avail = len;
  648.     
  649. memcpy(buf, bp->in.buf + bp->in.start, avail);
  650. buf += avail;
  651. got += avail;
  652. len -= avail;
  653. bp->in.start += avail;
  654.     }
  655.     
  656.     while (len > 0 && (avail = _fd_fionread(fd)) > 0)
  657.     {
  658. if (avail > len)
  659.     avail = len;
  660. avail = s_read(fd, buf, avail);
  661. if (avail > 0)
  662. {
  663.     got += avail;
  664.     len -= avail;
  665.     buf += avail;
  666. }
  667. else
  668.     if (avail <= 0)
  669.     {
  670. if (debug > 10)
  671.     fprintf(stderr, "_fd_read(%d): _s_read() failedn",
  672.     fd);
  673. bp->in.state = FDS_EOF;
  674. len = -1;
  675.     }
  676.     }
  677.     return got;
  678. }
  679. int fd_read(int fd, char *buf, int len)
  680. {
  681.     struct fd_buffer *bp = buffer[fd];
  682.     int avail;
  683.     
  684.     if (FD_INVALID(fd))
  685. fd_error("fd_read(%d): Invalid file descriptor!n", fd);
  686.     
  687.     mutex_lock(&bp->in.lock);
  688.     
  689.     if (bp->in.state == FDS_FREE)
  690. fd_error("fd_read(%d): Not openedn", fd);
  691.     avail = _fd_read(fd, buf, len);
  692.     
  693.     mutex_unlock(&bp->in.lock);
  694.     return avail;
  695. }
  696. static int _fd_rungetc(int c, int fd)
  697. {
  698.     struct fd_buffer *bp = buffer[fd];
  699.     
  700.     if (c == EOF)
  701. bp->in.save = FDIS_EOF;
  702.     else
  703. if (bp->in.start > 0)
  704. {
  705.     bp->in.buf[--bp->in.start] = (char) c;
  706.     return c;
  707. }
  708.     return EOF;
  709. }
  710. static int _fd_ungetc(int c, int fd)
  711. {
  712.     struct fd_buffer *bp = buffer[fd];
  713.     
  714.     if (c != 'n' || bp->type != FDT_SOCKET)
  715. return _fd_rungetc(c, fd);
  716.     switch (bp->in.save)
  717.     {
  718.       case FDIS_START:
  719. return _fd_rungetc(c, fd);
  720.       case FDIS_CR:
  721. return _fd_rungetc('r', fd);
  722.    
  723.       case FDIS_LF:
  724. return _fd_rungetc('n', fd);
  725.       case FDIS_CRLF:
  726. (void) _fd_rungetc('n', fd);
  727. return _fd_rungetc('r', fd);
  728.       case FDIS_LFCR:
  729. (void) _fd_rungetc('r', fd);
  730. return _fd_rungetc('n', fd);
  731.     }
  732.     return EOF;
  733. }
  734. int fd_ungetc(int c, int fd)
  735. {
  736.     struct fd_buffer *bp = buffer[fd];
  737.     int status;
  738.     
  739.     if (FD_INVALID(fd))
  740. fd_error("fd_ungetc(%d): Invalid file descriptor!n", fd);
  741.     
  742.     mutex_lock(&bp->in.lock);
  743.     if (bp->in.state == FDS_FREE)
  744. fd_error("fd_ungetc(%d): Not openedn", fd);
  745.     status = _fd_ungetc(c, fd);
  746.     
  747.     mutex_unlock(&bp->in.lock);
  748.     
  749.     return status;
  750. }
  751. static int _fd_rgetc(int fd)
  752. {
  753.     struct fd_buffer *bp = buffer[fd];
  754.     int avail;
  755.     
  756.     
  757.     avail = FD_AVAIL(bp);
  758.     if (avail == 0)
  759. avail = _fd_bfill(fd);
  760.     if (avail > 0)
  761. return bp->in.buf[bp->in.start++];;
  762.     return EOF;
  763. }
  764. static int _fd_getc(int fd)
  765. {
  766.     struct fd_buffer *bp = buffer[fd];
  767.     int c, c2;
  768.     c = _fd_rgetc(fd);
  769.     if (c == EOF)
  770. return c;
  771.     if (bp->type == FDT_SOCKET)
  772.     {
  773. if (bp->in.save == FDIS_START &&
  774.     (c == 'r' || c == 'n'))
  775. {
  776.     if (c == 'n')
  777. bp->in.save = FDIS_LF_START;
  778.     else
  779. bp->in.save = FDIS_CR_START;
  780.     
  781.     return 'n';
  782. }
  783. if (bp->in.save == FDIS_LF_START)
  784. {
  785.     if (c == 'r')
  786.     {
  787. bp->in.save = FDIS_LFCR;
  788. return _fd_getc(fd);
  789.     }
  790.     else
  791. bp->in.save = FDIS_LF;
  792.     
  793.     return c;
  794. }
  795. if (bp->in.save == FDIS_CR_START)
  796. {
  797.     if (c == 'n')
  798.     {
  799. bp->in.save = FDIS_CRLF;
  800. return _fd_getc(fd);
  801.     }
  802.     else
  803.     {
  804. bp->in.save = FDIS_CR;
  805. if (c == 'r')
  806.     return 'n';
  807.     }
  808.     
  809.     return c;
  810. }
  811. if (bp->in.save == FDIS_CRLF && c == 'r')
  812. {
  813.     c2 = _fd_getc(fd);
  814.     
  815.     if (c2 != 'n')
  816. _fd_ungetc(c2, fd);
  817.     
  818.     return 'n';
  819. }
  820. if (bp->in.save == FDIS_LFCR && c == 'n')
  821. {
  822.     c2 = _fd_getc(fd);
  823.     
  824.     if (c2 != 'r')
  825. _fd_ungetc(c2, fd);
  826.     
  827.     return 'n';
  828. }
  829. if (bp->in.save == FDIS_CR && c == 'r')
  830.     return 'n';
  831. if (bp->in.save == FDIS_LF && c == 'n')
  832.     return 'n';
  833.     }
  834.     
  835.     return c;
  836. }
  837. int fd_getc(int fd)
  838. {
  839.     struct fd_buffer *bp = buffer[fd];
  840.     int c;
  841.     
  842.     if (FD_INVALID(fd))
  843. fd_error("fd_getc(%d): Invalid file descriptor!n", fd);
  844.     
  845.     mutex_lock(&bp->in.lock);
  846.     
  847.     if (bp->in.state == FDS_FREE)
  848. fd_error("fd_getc(%d): Not openedn", fd);
  849.     c = _fd_getc(fd);
  850.     
  851.     mutex_unlock(&bp->in.lock);
  852.     return c;
  853. }
  854. /* ********************************************************************** */
  855. static int _fd_flush(int fd)
  856. {
  857.     struct fd_buffer *bp = buffer[fd];
  858.     int avail, status;
  859.     
  860.     
  861.     if (bp->out.state == FDS_EOF)
  862. return -1;
  863.     
  864.     while ((avail = bp->out.end - bp->out.start) > 0)
  865.     {
  866. status = s_write(fd, bp->out.buf - bp->out.start, avail);
  867. if (status < 0)
  868. {
  869.     syslog((errno == EPIPE || errno == ECONNRESET || errno == ENXIO) ?
  870.    LOG_INFO : LOG_ERR,
  871.    "_fd_flush(): s_write(%d, ..., %d) failed: %m",
  872.    fd, avail);
  873.     
  874.     bp->out.state = FDS_EOF;
  875.     return -1;
  876. }
  877. if (status == 0)
  878.     syslog(LOG_ERR, "_fd_flush(): write(%d, ..., %d): Wrote zero",
  879.    fd, avail);
  880.     
  881. bp->out.count += status;
  882. bp->out.start += status;
  883.     }
  884.     bp->out.start = 0;
  885.     bp->out.end = 0;
  886.     return 0;
  887. }
  888. void *flush_thread(void *data)
  889. {
  890.     int fd = (int) data;
  891.     struct fd_buffer *bp = buffer[fd];
  892.     
  893.     _fd_flush(fd);
  894.     
  895.     mutex_unlock(&bp->out.lock);
  896.     return NULL;
  897. }
  898. int fd_flush(int fd)
  899. {
  900.     struct fd_buffer *bp = buffer[fd];
  901.     
  902.     if (FD_INVALID(fd))
  903. fd_error("fd_flush(%d): Invalid file descriptor!n", fd);
  904.     mutex_lock(&bp->out.lock);
  905.     
  906.     if (bp->in.state == FDS_FREE)
  907. fd_error("fd_flush(%d): Not openedn", fd);
  908.     if (thr_create(NULL,
  909.    0,
  910.    (void *(*)(void *)) flush_thread,
  911.    (void *) fd,
  912.    THR_DETACHED+THR_DAEMON,
  913.    NULL))
  914.     {
  915. syslog(LOG_ERR, "thr_create(flush_thread) failed: %m");
  916. exit(1);
  917.     }
  918.     return 0;
  919. }
  920. static int _fd_write(int fd, const char *buf, int len)
  921. {
  922.     struct fd_buffer *bp = buffer[fd];
  923.     int avail, status;
  924.     
  925.     avail = bp->out.size - bp->out.end;
  926.     if (avail < len)
  927.     {
  928. if (_fd_flush(fd) < 0)
  929.     return -1;
  930. avail = bp->out.size;
  931.     }
  932.     if (len < avail)
  933.     {
  934. memcpy(bp->out.buf + bp->out.end, buf, len);
  935. bp->out.end += len;
  936.     }
  937.     else
  938.     {
  939. while (len > 0)
  940. {
  941.     status = s_write(fd, buf, len);
  942.     if (status < 0)
  943.     {
  944. syslog((errno == EPIPE ||
  945. errno == ECONNRESET ||
  946. errno == ENXIO) ? LOG_INFO : LOG_ERR,
  947.        "_fd_write(): write(%d, ..., %d) failed: %m",
  948.        fd, avail);
  949.     
  950. bp->out.state = FDS_EOF;
  951. return -1;
  952.     }
  953.     if (status == 0)
  954. syslog(LOG_ERR, "_fd_write(): write(%d, ..., %d): Wrote zero",
  955.        fd, avail);
  956.     
  957.     bp->out.count += status;
  958.     buf += status;
  959.     len -= status;
  960. }
  961.     }
  962.     return 0;
  963. }
  964. int fd_write(int fd, const char *buf, int len)
  965. {
  966.     struct fd_buffer *bp = buffer[fd];
  967.     int status;
  968.     
  969.     if (FD_INVALID(fd))
  970. fd_error("fd_write(%d): Invalid file descriptor!n", fd);
  971.     
  972.     mutex_lock(&bp->out.lock);
  973.     
  974.     if (bp->in.state == FDS_FREE)
  975. fd_error("fd_write(%d): Not openedn", fd);
  976.     status = _fd_write(fd, buf, len);
  977.     
  978.     mutex_unlock(&bp->out.lock);
  979.     return status;
  980. }
  981. static int _fd_rputc(int c, int fd)
  982. {
  983.     struct fd_buffer *bp = buffer[fd];
  984.     int avail;
  985.     
  986.     avail = bp->out.size - bp->out.end;
  987.     if (avail == 0)
  988.     {
  989. if (_fd_flush(fd) < 0)
  990.     return -1;
  991.     }
  992.     bp->out.buf[bp->out.end++] = (char) c;
  993.     return c;
  994. }
  995. static int _fd_putc(int c, int fd)
  996. {
  997.     struct fd_buffer *bp = buffer[fd];
  998.     
  999.     if (bp->type == FDT_SOCKET)
  1000.     {
  1001. if (c == 'n')
  1002.     if (bp->out.save != 'r')
  1003. if (_fd_rputc('r', fd) == EOF)
  1004.     return EOF;
  1005.     }
  1006.     
  1007.     bp->out.save = c;
  1008.     
  1009.     return _fd_rputc(c, fd);
  1010. }
  1011. int fd_putc(int c, int fd)
  1012. {
  1013.     struct fd_buffer *bp = buffer[fd];
  1014.     int status;
  1015.     
  1016.     if (FD_INVALID(fd))
  1017. fd_error("fd_putc(%d): Invalid file descriptor!n", fd);
  1018.     
  1019.     mutex_lock(&bp->out.lock);
  1020.     
  1021.     if (bp->in.state == FDS_FREE)
  1022. fd_error("fd_putc(%d): Not openedn", fd);
  1023.     status = _fd_putc(c, fd);
  1024.     
  1025.     mutex_unlock(&bp->out.lock);
  1026.     return status;
  1027. }
  1028. /* ********************************************************************** */
  1029. static char *fd_mgets(int maxsize, int fd)
  1030. {
  1031.     int c, i;
  1032.     char *buf;
  1033.     int csize = 0;
  1034.     
  1035.     buf = s_malloc(csize = 1024);
  1036.     
  1037.     for (i = 0; (maxsize ? (i < maxsize-1) : 1) &&
  1038.      (c = fd_getc(fd)) != EOF; i++)
  1039.     {
  1040. if (i >= csize-1)
  1041.     buf = s_realloc(buf, csize+=1024);
  1042.     
  1043. buf[i] = c;
  1044. if (c == 'n' || c == 'r')
  1045. {
  1046.     i++;
  1047.     break;
  1048. }
  1049.     }
  1050.     if (i == 0)
  1051. return NULL;
  1052.     buf[i] = '';
  1053.     return buf;
  1054. }
  1055. /* Get a line of text from the file
  1056. **
  1057. ** If buf == NULL, allocate it dynamically
  1058. ** If size != 0, use a maximum size limit of buffer
  1059. */
  1060. char *fd_gets(char *buf, int size, int fd)
  1061. {
  1062.     int c, i;
  1063.     if (buf == NULL)
  1064. return fd_mgets(size, fd);
  1065.     
  1066.     for (i = 0; i < size-1 && (c = fd_getc(fd)) != EOF; i++)
  1067.     {
  1068. buf[i] = c;
  1069. if (c == 'n' || c == 'r') 
  1070. {
  1071.     i++;
  1072.     break;
  1073. }
  1074.     }
  1075.     if (i == 0)
  1076. return NULL;
  1077.     buf[i] = '';
  1078.     return buf;
  1079. }
  1080. /* Get a line of text from the file
  1081. **
  1082. ** If buf == NULL, allocate it dynamically
  1083. ** If size != 0, use a maximum size limit of buffer
  1084. */
  1085. char *fd_gets_nl(char *buf, int size, int fd)
  1086. {
  1087.     int c, i;
  1088.     int r=0;
  1089.     if (buf == NULL)
  1090. return fd_mgets(size, fd);
  1091.     
  1092.     for (i = 0; i < size-1 && (c = fd_getc(fd)) != EOF; i++)
  1093.     {
  1094. buf[i] = c;
  1095. if (c == 'n' )
  1096. {
  1097.     if ( r == 1 ) { buf[i-1]=c; buf[i]=0x00; }
  1098.     else  i++;
  1099.     break;
  1100. }
  1101. if (c == 'r' ) r=1;
  1102. else r=0;
  1103.     }
  1104.     if (i == 0)
  1105. return NULL;
  1106.     buf[i] = '';
  1107.     return buf;
  1108. }
  1109. int fd_puts(const char *str, int fd)
  1110. {
  1111.     struct fd_buffer *bp = buffer[fd];
  1112.     int len = strlen(str);
  1113.     
  1114.     if (FD_INVALID(fd))
  1115. fd_error("fd_puts(%d): Invalid file descriptor!n", fd);
  1116.     
  1117.     mutex_lock(&bp->out.lock);
  1118.     
  1119.     if (bp->out.state == FDS_FREE)
  1120. fd_error("fd_puts(%d): Not openedn", fd);
  1121.     while (*str)
  1122. if (_fd_putc(*str++, fd) == EOF)
  1123. {
  1124.     mutex_unlock(&bp->out.lock);
  1125.     return -1;
  1126. }
  1127.     
  1128.     mutex_unlock(&bp->out.lock);
  1129.     
  1130.     return len;
  1131. }
  1132. int fd_puti(int val, int fd)
  1133. {
  1134.     char buf[256];
  1135.     s_sprintf(buf, sizeof(buf), "%d", val);
  1136.     return fd_puts(buf, fd);
  1137. }
  1138. int fd_puts2nl(const char *s1, const char *s2, int fd)
  1139. {
  1140.     fd_puts(s1, fd);
  1141.     fd_puts(s2, fd);
  1142.     return fd_putc('n', fd);
  1143. }
  1144. int fd_putsinl(const char *s1, int val, int fd)
  1145. {
  1146.     fd_puts(s1, fd);
  1147.     fd_puti(val, fd);
  1148.     return fd_putc('n', fd);
  1149. }
  1150. /*
  1151. ** XXX: Fixme: I _hate_ statically allocated buffers...
  1152. */
  1153. int fd_vprintf(int fd,
  1154.        const char *format,
  1155.        va_list ap)
  1156. {
  1157.     int len, ret;
  1158.     char *buf;
  1159.     
  1160.     buf = s_malloc(20480);
  1161.     len = s_vsprintf(buf, 20480, format, ap);
  1162.     if (len < 0)
  1163.     {
  1164. s_free(buf);
  1165. return -1;
  1166.     }
  1167.     
  1168.     ret = fd_puts(buf, fd);
  1169.     s_free(buf);
  1170.     return ret;
  1171. }
  1172. int fd_printf(int fd,
  1173.       const char *format,
  1174.       ...)
  1175. {
  1176.     va_list ap;
  1177.     int len;
  1178.     
  1179.     
  1180.     va_start(ap, format);
  1181.     
  1182.     len = fd_vprintf(fd, format, ap);
  1183.     va_end(ap);
  1184.     
  1185.     return len;
  1186. }
  1187. int fd_written(int fd)
  1188. {
  1189.     struct fd_buffer *bp = buffer[fd];
  1190.     int length;
  1191.     
  1192.     if (FD_INVALID(fd))
  1193. fd_error("fd_written(%d): Invalid file descriptor!n", fd);
  1194.     
  1195.     mutex_lock(&bp->out.lock);
  1196.     length = bp->out.count + (bp->out.end - bp->out.start);
  1197.     mutex_unlock(&bp->out.lock);
  1198.     return length;
  1199. }
  1200. struct relayinfo
  1201. {
  1202.     int read_fd;
  1203.     int write_fd;
  1204.     int bytes;
  1205. };
  1206. /* Relay a stream from one fd to another */
  1207. static void *relay_data(struct relayinfo *rip)
  1208. {
  1209.     char buf[8192];
  1210.     int len, status;
  1211.     int to_read;
  1212.     if (debug > 6)
  1213. fprintf(stderr, "fdstdio: relay_data(%d -> %d): Start[%d]n",
  1214. rip->read_fd, rip->write_fd,rip->bytes);
  1215.     
  1216.     len = 0;
  1217.     to_read = rip->bytes;
  1218. /* was != 0 -> > 0 */    
  1219.     while (to_read != 0 &&
  1220.    (len = fd_read(rip->read_fd,
  1221.   buf,
  1222.   (to_read > 0 && to_read < sizeof(buf))
  1223.   ? to_read : sizeof(buf))) > 0)
  1224.     {
  1225. if (debug > 7)
  1226.     fprintf(stderr, "fd_relay(): fd_read(%d), len=%dn",
  1227.     rip->read_fd, len);
  1228. if (to_read > 0)
  1229.     to_read -= len;
  1230. if (debug > 8)
  1231.     fprintf(stderr, "fd_relay(): before fd_write(%d, ..., %d)n",
  1232.     rip->write_fd, len);
  1233. status = fd_write(rip->write_fd, buf, len);
  1234. if (status < 0)
  1235.     break;
  1236. if (debug > 8)
  1237.     fprintf(stderr, "fd_relay(): before fd_flush(%d)n",
  1238.     rip->write_fd);
  1239. fd_flush(rip->write_fd);
  1240.     }
  1241.     if (debug > 7)
  1242. fprintf(stderr, "fdstdio: relay_data(): shutting down fd %dn",
  1243. rip->write_fd);
  1244.     
  1245.     fd_shutdown(rip->write_fd, 1);
  1246.     
  1247.     if (debug > 7)
  1248. fprintf(stderr, "fdstdio: relay_data(): Stopn");
  1249.     
  1250.     return NULL;
  1251. }
  1252. int fd_relay(int fd1, int fd2, int bidir)
  1253. {
  1254.     thread_t tid1, tid2;
  1255.     struct relayinfo rb1, rb2;
  1256.     
  1257.     if (debug > 6)
  1258. fprintf(stderr, "fd_relay(%d,%d,%d): Startn",
  1259. fd1, fd2, bidir);
  1260.     
  1261.     if (bidir)
  1262.     {
  1263. rb1.read_fd = fd2;
  1264. rb1.write_fd = fd1;
  1265. rb1.bytes = -1;
  1266. if (thr_create(NULL, 0,
  1267.        (void *(*)(void *)) relay_data, (void *) &rb1,
  1268.        0,
  1269.        &tid1))
  1270. {
  1271.     syslog(LOG_ERR, "fd_relay(): thr_create() failed");
  1272.     return -1;
  1273. }
  1274.     }
  1275.     rb2.read_fd = fd1;
  1276.     rb2.write_fd = fd2;
  1277.     rb2.bytes = -1;
  1278.     if (thr_create(NULL, 0,
  1279.    (void *(*)(void *)) relay_data, (void *) &rb2,
  1280.    0,
  1281.    &tid2))
  1282.     {
  1283. syslog(LOG_ERR, "fd_relay(): thr_create() failed");
  1284. return -1;
  1285.     }
  1286.     if (bidir)
  1287.     {
  1288. if (debug > 6)
  1289.     fprintf(stderr, "fd_relay(), before thr_join(tid1)n");
  1290.     
  1291. thr_join(tid1, NULL, NULL);
  1292.     }
  1293.     if (debug > 6)
  1294. fprintf(stderr, "fd_relay(), before thr_join(tid2)n");
  1295.     
  1296.     thr_join(tid2, NULL, NULL);
  1297.     
  1298.     return 0;
  1299. }
  1300. int fd_nrelay(int fd1, int fd2, int bidir, int bytes)
  1301. {
  1302.     thread_t tid1, tid2;
  1303.     struct relayinfo rb1, rb2;
  1304.     if (debug > 6)
  1305. fprintf(stderr, "fd_nrelay(%d,%d,%d,%d): Startn",
  1306. fd1, fd2, bidir, bytes);
  1307.     
  1308.     if (bidir)
  1309.     {
  1310. rb1.read_fd = fd2;
  1311. rb1.write_fd = fd1;
  1312. rb1.bytes = bytes;
  1313. if (thr_create(NULL, 0,
  1314.        (void *(*)(void *)) relay_data, (void *) &rb1,
  1315.        0,
  1316.        &tid1))
  1317. {
  1318.     syslog(LOG_ERR, "fd_nrelay(): thr_create() failed");
  1319.     return -1;
  1320. }
  1321.     }
  1322.     rb2.read_fd = fd1;
  1323.     rb2.write_fd = fd2;
  1324.     rb2.bytes = bytes;
  1325.     if (thr_create(NULL, 0,
  1326.    (void *(*)(void *)) relay_data, (void *) &rb2,
  1327.    0,
  1328.    &tid2))
  1329.     {
  1330. syslog(LOG_ERR, "fd_relay(): thr_create() failed");
  1331. return -1;
  1332.     }
  1333.     
  1334.     if (bidir)
  1335.     {
  1336. if (debug > 6)
  1337.     fprintf(stderr, "fd_relay(), before thr_join(tid1)n");
  1338.     
  1339. thr_join(tid1, NULL, NULL);
  1340.     }
  1341.     if (debug > 6)
  1342. fprintf(stderr, "fd_relay(), before thr_join(tid2)n");
  1343.     
  1344.     thr_join(tid2, NULL, NULL);
  1345.     
  1346.     return 0;
  1347. }
  1348. int fd_prelay(int fd1, int fd2, int bidir, int bytes)
  1349. {
  1350.     thread_t tid1, tid2;
  1351.     struct relayinfo rb1, rb2;
  1352.     if (debug > 6)
  1353.         fprintf(stderr, "fd_nrelay(%d,%d,%d,%d): Startn",
  1354.                 fd1, fd2, bidir, bytes);
  1355.     if (bidir)
  1356.     {
  1357.         rb1.read_fd = fd2;
  1358.         rb1.write_fd = fd1;
  1359.         rb1.bytes = bytes;
  1360.         if (thr_create(NULL, 0,
  1361.                        (void *(*)(void *)) relay_data, (void *) &rb1,
  1362.                        0,
  1363.                        &tid1))
  1364.         {
  1365.             syslog(LOG_ERR, "fd_nrelay(): thr_create() failed");
  1366.             return -1;
  1367.         }
  1368.     }
  1369.     rb2.read_fd = fd1;
  1370.     rb2.write_fd = fd2;
  1371.     rb2.bytes = -1;
  1372.     if (thr_create(NULL, 0,
  1373.                    (void *(*)(void *)) relay_data, (void *) &rb2,
  1374.                    0,
  1375.                    &tid2))
  1376.     {
  1377.         syslog(LOG_ERR, "fd_relay(): thr_create() failed");
  1378.         return -1;
  1379.     }
  1380.     if (bidir)
  1381.     {
  1382.         if (debug > 6)
  1383.             fprintf(stderr, "fd_relay(), before thr_join(tid1)n");
  1384.         thr_join(tid1, NULL, NULL);
  1385.     }
  1386.     if (debug > 6)
  1387.         fprintf(stderr, "fd_relay(), before thr_join(tid2)n");
  1388.     thr_join(tid2, NULL, NULL);
  1389.     return 0;
  1390. }