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

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** safeio.c
  3. **
  4. ** Copyright (c) 1995-1997 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 <errno.h>
  21. #include <syslog.h>
  22. #include <string.h>
  23. #include <synch.h>
  24. #include <sys/mman.h>
  25. #include <netdb.h>
  26. #include "phttpd.h"
  27. /*
  28. ** Almost safe string printf
  29. */
  30. int s_sprintf(char *buf, int size, const char *format, ...)
  31. {
  32.     va_list ap;
  33.     int len;
  34.     
  35.     va_start(ap, format);
  36.     len = s_vsprintf(buf, size, format, ap);
  37.     va_end(ap);
  38.     return len;
  39. }
  40. #undef vsprintf
  41. int s_vsprintf(char *buf, int size, const char *format, va_list ap)
  42. {
  43.     int len;
  44.     
  45. #ifdef HAVE_VSNPRINTF
  46.     len = __vsnprintf(buf, size, format, ap);
  47. #else
  48.     len = vsprintf(buf, format, ap);
  49.     if (len > size)
  50. s_abort();
  51. #endif
  52.     return len;
  53. }
  54. /*
  55. ** Safe string copy.
  56. **
  57. ** If the source string is longer than will fit in the output buffer,
  58. ** then only copy as many as will fit, and then NUL terminate the destination
  59. ** string.
  60. **
  61. ** Returns the number of characters in the output buffer (not including
  62. ** the terminating NUL), or -1 if the buffer is of zero size.
  63. */
  64. int s_strcpy(char *dst, int dstsize, const char *src)
  65. {
  66.     int srclen;
  67.     if (dst == NULL)
  68.       s_abort();
  69.     
  70.     if (dstsize-- < 1)
  71.     {
  72. s_abort(); /* Temp, just to find all bad uses of it */
  73. return -1;
  74.     }
  75.     
  76.     if (src == NULL)
  77.     {
  78.         *dst = '';
  79. return 0;
  80.     }
  81.     srclen = strlen(src);
  82.     
  83.     if (srclen > dstsize)
  84. srclen = dstsize;
  85.     if (srclen > 0)
  86. memcpy(dst, src, srclen);
  87.     dst[srclen] = '';
  88.     return srclen;
  89. }
  90. /*
  91. ** Safe string limited copy.
  92. **
  93. ** If the source string is longer than will fit in the output buffer,
  94. ** then only copy as many as will fit, and then NUL terminate the destination
  95. ** string.
  96. **
  97. ** Returns the number of characters in the output buffer (not including
  98. ** the terminating NUL), or -1 if the buffer is of zero size.
  99. */
  100. int s_strncpy(char *dst, int dstsize, const char *src, int maxcopy)
  101. {
  102.     int srclen;
  103.     if (dst == NULL)
  104.       s_abort();
  105.     if (dstsize-- < 1 || maxcopy < 0)
  106.     {
  107. s_abort(); /* Temp, just to find all bad uses of it */
  108. return -1;
  109.     }
  110.     
  111.     if (src == NULL)
  112.     {
  113.         *dst = '';
  114. return 0;
  115.     }
  116.     srclen = strlen(src);
  117.     
  118.     if (srclen > maxcopy)
  119. srclen = maxcopy;
  120.     
  121.     if (srclen > dstsize)
  122. srclen = dstsize;
  123.     if (srclen > 0)
  124. memcpy(dst, src, srclen);
  125.     
  126.     dst[srclen] = '';
  127.     
  128.     return srclen;
  129. }
  130. /*
  131. ** Safe string concatenation.
  132. **
  133. ** If the source string is longer than will fit in the output buffer,
  134. ** then only copy as many as will fit, and then NUL terminate the destination
  135. ** string.
  136. **
  137. ** Returns the number of characters in the output buffer (not including
  138. ** the terminating NUL), or -1 if the buffer is of zero size.
  139. */
  140. int s_strcat(char *dst, int dstsize, const char *src)
  141. {
  142.     int srclen;
  143.     int dstlen;
  144.     if (dst == NULL)
  145.       s_abort();
  146.     if (dstsize-- < 1)
  147.     {
  148. s_abort(); /* Temp, just to find all bad uses of it */
  149. return -1;
  150.     }
  151.     
  152.     dstlen = strlen(dst);
  153.     
  154.     if (src == NULL)
  155.         return dstlen;
  156.     srclen = strlen(src);
  157.     
  158.     if (srclen+dstlen > dstsize)
  159. srclen = dstsize-dstlen;
  160.     
  161.     if (srclen < 0)
  162.     {
  163. syslog(LOG_ERR, "s_strcat(..., %d, ...): buffer overflow", dstsize);
  164. return dstlen;
  165.     }
  166.     if (srclen > 0)
  167. memcpy(dst+dstlen, src, srclen);
  168.     dst[dstlen+srclen] = '';
  169.     return srclen+dstlen;
  170. }
  171. /*
  172. ** Safe string limited concatenation.
  173. **
  174. ** If the source string is longer than will fit in the output buffer,
  175. ** then only copy as many as will fit, and then NUL terminate the destination
  176. ** string.
  177. **
  178. ** Returns the number of characters in the output buffer (not including
  179. ** the terminating NUL), or -1 if the buffer is of zero size.
  180. */
  181. int s_strncat(char *dst, int dstsize, const char *src, int maxcopy)
  182. {
  183.     int srclen;
  184.     int dstlen;
  185.     if (dst == NULL)
  186.       s_abort();
  187.     if (dstsize-- < 1)
  188.     {
  189. s_abort(); /* Temp, just to find all bad uses of it */
  190. return -1;
  191.     }
  192.     
  193.     dstlen = strlen(dst);
  194.     
  195.     if (src == NULL)
  196.         return dstlen;
  197.     srclen = strlen(src);
  198.     
  199.     if (srclen > maxcopy)
  200.       srclen = maxcopy;
  201.     if (srclen+dstlen > dstsize)
  202. srclen = dstsize-dstlen;
  203.     if (srclen < 0)
  204.     {
  205. syslog(LOG_ERR, "s_strncat(..., %d, ..., %d): buffer overflow",
  206.        dstsize, maxcopy);
  207.        
  208. return dstlen;
  209.     }
  210.     if (srclen > 0)
  211. memcpy(dst+dstlen, src, srclen);
  212.     dst[dstlen+srclen] = '';
  213.     
  214.     return srclen+dstlen;
  215. }
  216. /*
  217. ** Safe file descriptor open. Handles EINTR.
  218. ** Returns -1, or the opened file descriptor.
  219. */
  220. #undef open
  221. int s_open(path, oflag, mode)
  222.     const char *path;
  223.     int oflag;
  224.     mode_t mode;
  225. {
  226.     int s;
  227.     while ((s = open(path, oflag, mode)) < 0 && errno == EINTR)
  228. ;
  229.     if (s < 0 && (errno == EMFILE ||
  230.   errno == ENFILE ||
  231.   errno == ENOMEM ||
  232.   errno == ENOSR))
  233.     {
  234. /* Too many open files */
  235. syslog(LOG_WARNING, "s_open("%s", 0%o): %m", path, oflag);
  236. /* Should perhaps, sleep and retry - and if it fails
  237.    again restart the server? */
  238.     }
  239.     
  240.     return s;
  241. }
  242. #undef close
  243. int s_close(int fd)
  244. {
  245.     int s;
  246.     while ((s = close(fd)) < 0 && errno == EINTR)
  247. ;
  248.     return s;
  249. }
  250. #undef shutdown
  251. int s_shutdown(int fd, int how)
  252. {
  253.     int s;
  254.     
  255.     while ((s = shutdown(fd, how)) < 0 && errno == EINTR)
  256. ;
  257.     return s;
  258. }
  259. #undef connect
  260. int s_connect(int fd, struct sockaddr *sin, int len)
  261. {
  262.     int s;
  263.     if (debug > 7)
  264. fprintf(stderr, "s_connect(): Startn");
  265.     
  266.     while ((s = connect(fd, sin, len)) < 0 && errno == EINTR)
  267. if (debug > 7)
  268.     perror("connect()");
  269.     if (s < 0 && (errno == EMFILE ||
  270.   errno == ENFILE ||
  271.   errno == ENOMEM ||
  272.   errno == ENOSR))
  273.     {
  274. /* Too many open files */
  275. syslog(LOG_WARNING, "s_connect(%d, ...): %m", fd);
  276. /* Should perhaps, sleep and retry - and if it fails
  277.    again restart the server? */
  278.     }
  279.     if (debug > 7)
  280. fprintf(stderr, "s_connect(): Exitingn");
  281.     
  282.     return s;
  283. }
  284. #undef accept
  285. int s_accept(int fd, struct sockaddr *sin, int *lenp)
  286. {
  287.     int s;
  288.     while ((s = accept(fd, sin, lenp)) < 0 &&
  289.    (errno == EINTR || errno == EPROTO))
  290. ;
  291.     if (s < 0 && (errno == EMFILE ||
  292.   errno == ENFILE ||
  293.   errno == ENOMEM ||
  294.   errno == ENOSR))
  295.     {
  296. /* Too many open files */
  297. syslog(LOG_WARNING, "s_accept(%d, ...): %m", fd);
  298. /* Should perhaps, sleep and retry - and if it fails
  299.    again restart the server? */
  300.     }
  301.     
  302.     return s;
  303. }
  304. #undef ioctl
  305. int s_ioctl(int fd, int what, void *ptr)
  306. {
  307.     int s;
  308.     
  309.     while ((s = ioctl(fd, what, ptr)) < 0 && errno == EINTR)
  310. ;
  311.     return s;
  312. }
  313. #undef select
  314. int s_select(int nfd, fd_set *rs, fd_set *ws, fd_set *es, struct timeval *tv)
  315. {
  316.     int s;
  317.     while (( s = select(nfd, rs, ws, es, tv)) < 0 && errno == EINTR)
  318. ;
  319.     if (s < 0 && debug)
  320. perror("select");
  321.     
  322.     return s;
  323. }
  324. #undef read
  325. int s_read(int fd, char *buf, int len)
  326. {
  327.     int s;
  328.     while ((s = read(fd, buf, len)) < 0 && errno == EINTR)
  329. ;
  330.     if (s < 0 && debug)
  331. perror("read");
  332.     if (debug > 5)
  333. fprintf(stderr, "read(%d), len=%dn", fd, s);
  334.     
  335.     return s;
  336. }
  337. #undef write
  338. int s_write(int fd, const char *buf, int len)
  339. {
  340.     int s;
  341.     while ((s = write(fd, buf, len)) < 0 && errno == EINTR)
  342. ;
  343.     return s;
  344. }
  345. mutex_t *s_mutex_create(int type)
  346. {
  347.     mutex_t *mp;
  348.     
  349.     if (type == USYNC_PROCESS)
  350.     {
  351. int fd;
  352. fd = s_open("/dev/zero", 2);
  353. if (fd < 0)
  354.     return NULL;
  355. mp = (mutex_t *) mmap((caddr_t) NULL,
  356.   sizeof(mutex_t),
  357.   PROT_READ+PROT_WRITE,
  358.   MAP_SHARED, fd, 0);
  359. s_close(fd);
  360.     }
  361.     else
  362. mp = (mutex_t *) s_malloc(sizeof(mutex_t));
  363.     if (mp)
  364. mutex_init(mp, type, NULL);
  365.     
  366.     return mp;
  367. }
  368. void s_mutex_destroy(mutex_t *mp, int type)
  369. {
  370.     mutex_destroy(mp);
  371.     if (type == USYNC_PROCESS)
  372.         munmap((caddr_t) mp, sizeof(mutex_t));
  373.     else
  374. s_free((void *)mp);
  375. }
  376. sema_t *s_sema_create(int count, int type)
  377. {
  378.     sema_t *sp;
  379.     
  380.     if (type == USYNC_PROCESS)
  381.     {
  382. int fd;
  383. fd = s_open("/dev/zero", 2);
  384. if (fd < 0)
  385.     return NULL;
  386. sp = (sema_t *) mmap((caddr_t) NULL,
  387.   sizeof(sema_t),
  388.   PROT_READ+PROT_WRITE,
  389.   MAP_SHARED, fd, 0);
  390. s_close(fd);
  391.     }
  392.     else
  393. sp = (sema_t *) s_malloc(sizeof(sema_t));
  394.     if (sp)
  395. sema_init(sp, count, type, NULL);
  396.     
  397.     return sp;
  398. }
  399. void s_sema_destroy(sema_t *sp, int type)
  400. {
  401.     sema_destroy(sp);
  402.     if (type == USYNC_PROCESS)
  403. munmap((caddr_t) sp, sizeof(sema_t));
  404.     else
  405. s_free(sp);
  406. }
  407. pid_t s_sema_wait(sema_t *sp)
  408. {
  409.     pid_t s;
  410.     while ((s = sema_wait(sp)) && errno == EINTR)
  411. ;
  412.     return s;
  413. }
  414. #undef chdir
  415. int s_chdir(const char *path)
  416. {
  417.     int s;
  418.     while ((s = chdir(path)) < 0 && errno == EINTR)
  419. ;
  420.     return s;
  421. }
  422. #undef chroot
  423. int s_chroot(const char *path)
  424. {
  425.     int s;
  426.     while ((s = chroot(path)) < 0 && errno == EINTR)
  427. ;
  428.     return s;
  429. }
  430. #undef dup2
  431. /* dup2 is not MT-Safe according to the SunOS 5 man page */
  432. int s_dup2(int fd1, int fd2)
  433. {
  434.     int s;
  435.     static mutex_t dup2_lock;
  436.     
  437.     mutex_lock(&dup2_lock);
  438.     
  439.     while ((s = dup2(fd1, fd2)) < 0 && errno == EINTR)
  440. ;
  441.     
  442.     mutex_unlock(&dup2_lock);
  443.     
  444.     if (s < 0 && (errno == EMFILE))
  445.     {
  446. /* Too many open files */
  447. syslog(LOG_WARNING, "s_dup2(%d, &d): %m", fd1, fd2);
  448. /* Should perhaps, sleep and retry - and if it fails
  449.    again restart the server? */
  450.     }
  451.     
  452.     return s;
  453. }
  454. #undef waitpid
  455. pid_t s_waitpid(pid_t pid, int *status, int options)
  456. {
  457.     int s;
  458.     while ((s = waitpid(pid, status, options)) < 0 && errno == EINTR)
  459. ;
  460.     return s;
  461. }
  462. #undef execve
  463. int s_execve(const char *path, char *const argv[], char *const envp[])
  464. {
  465.     int s;
  466.     while ((s = execve(path, argv, envp)) > 0 && errno == EINTR)
  467. ;
  468.     return s;
  469. }
  470. #if 0
  471. DIR *s_opendir(const char *path)
  472. {
  473.     DIR *dp;
  474.     while ((dp = opendir(path)) == NULL && errno == EINTR)
  475. ;
  476.     return dp;
  477. }
  478. int s_closedir(DIR *dirp)
  479. {
  480.     int s;
  481.     while ((s = closedir(dirp)) < 0 && errno == EINTR)
  482. ;
  483.     return s;
  484. }
  485. struct dirent *s_readdir_r(DIR *dirp, struct dirent *res)
  486. {
  487.     struct dirent *s;
  488.     while ((s = readdir_r(dirp, res)) == NULL &&
  489.    (errno == EINTR || errno == EAGAIN))
  490. ;
  491.     return s;
  492. }
  493. #endif
  494.     
  495. #define SA_MAGIC 356834534
  496. #define SA_FREE  562368734
  497. struct allocinfo
  498. {
  499.     int magic;
  500.     int size;
  501. };
  502. #ifdef INCLUDE_ALLOC_STATS
  503. struct allocstats alloc_stats;
  504. #endif
  505. #undef malloc
  506. void *s_malloc(size_t size)
  507. {
  508.     struct allocinfo *p;
  509.     int i, as;
  510.     i = 0;
  511.     as = size + sizeof(struct allocinfo);
  512.     
  513.   Loop:
  514.     p = (struct allocinfo *) malloc(as);
  515.     if (p == NULL)
  516.     {
  517. if (i++ < 10)
  518. {
  519.     syslog(LOG_WARNING,
  520.    "s_malloc(%d): %m - retrying in %d seconds",
  521.    size, i);
  522.     s_sleep(i);
  523.     goto Loop;
  524. }
  525. else
  526. {
  527.     syslog(LOG_ERR, "s_malloc(%d): %m - aborting", size);
  528.     s_abort();
  529. }
  530.     }
  531.     p->magic = SA_MAGIC;
  532.     p->size = size;
  533.     ++p;
  534.     
  535.     memset((void *) p, 0, size);
  536. #ifdef INCLUDE_ALLOC_STATS
  537.     mutex_lock(&alloc_stats.lock);
  538.     alloc_stats.malloc_calls++;
  539.     alloc_stats.bytes += size;
  540.     alloc_stats.blocks++;
  541.     mutex_unlock(&alloc_stats.lock);
  542. #endif
  543.     
  544.     return (void *) p;
  545. }
  546. #undef free
  547. void s_free(void *ptr)
  548. {
  549.     struct allocinfo *p;
  550.     
  551.     if (ptr == NULL)
  552. return;
  553.     p = (struct allocinfo *) ptr;
  554.     --p;
  555.     if (p->magic != SA_MAGIC)
  556.     {
  557. if (p->magic == SA_FREE)
  558.     syslog(LOG_ERR, "s_free(): freeing freed block of size %d",
  559.    p->size);
  560. else
  561.     syslog(LOG_ERR, "s_free(): bad magic number");
  562. s_abort();
  563.     }
  564.     
  565. #ifdef INCLUDE_ALLOC_STATS
  566.     mutex_lock(&alloc_stats.lock);
  567.     alloc_stats.free_calls++;
  568.     alloc_stats.bytes -= p->size;
  569.     alloc_stats.blocks--;
  570.     mutex_unlock(&alloc_stats.lock);
  571. #endif
  572.     
  573.     p->magic = SA_FREE;
  574.     free(p);
  575. }
  576. #undef realloc
  577. void *s_realloc(void *ptr, size_t size)
  578. {
  579.     struct allocinfo *p, *op;
  580.     int os, sa, i;
  581.     
  582.     if (ptr == NULL)
  583. return s_malloc(size);
  584.     sa = size + sizeof(struct allocinfo);
  585.     op = (struct allocinfo *) ptr;
  586.     --op;
  587.     
  588.     os = op->size;
  589.     
  590.     if (op->magic != SA_MAGIC)
  591.     {
  592. if (op->magic == SA_FREE)
  593.     syslog(LOG_ERR, "s_realloc(): reallocating freed block of size %d",
  594.    op->size);
  595. else
  596.     syslog(LOG_ERR, "s_realloc(): bad magic number");
  597. s_abort();
  598.     }
  599.     i = 0;
  600.   Loop:
  601.     p = realloc(op, sa);
  602.     if (p == NULL)
  603.     {
  604. if (i++ < 10)
  605. {
  606.     syslog(LOG_WARNING,
  607.    "s_realloc(..., %d): %m - retrying in %d seconds",
  608.    size, i);
  609.     s_sleep(i);
  610.     goto Loop;
  611. }
  612. else
  613. {
  614.     syslog(LOG_ERR, "s_realloc(..., %d): %m - aborting", size);
  615.     s_abort();
  616. }
  617.     }
  618.     p->size = size;
  619.     ++p;
  620.     if (size > os)
  621.     {
  622. char *cp = (char *) p;
  623. memset(cp + os, 0, size - os);
  624.     }
  625.     
  626. #ifdef INCLUDE_ALLOC_STATS
  627.     mutex_lock(&alloc_stats.lock);
  628.     alloc_stats.realloc_calls++;
  629.     if (size > os)
  630. alloc_stats.bytes += (size - os);
  631.     else
  632. alloc_stats.bytes -= (os - size);
  633.     mutex_unlock(&alloc_stats.lock);
  634. #endif
  635.     
  636.     return (void *) p;
  637. }
  638. char *s_strdup(const char *str)
  639. {
  640.     char *ptr;
  641.     int len;
  642.     
  643.     
  644.     if (str == NULL)
  645. return NULL;
  646.     len = strlen(str);
  647.     ptr = s_malloc(len+1);
  648.     memcpy(ptr, str, len+1);
  649.     return ptr;
  650. }
  651. char *s_strndup(const char *str, int len)
  652. {
  653.     char *ptr;
  654.  
  655.     if (str == NULL)
  656.         return NULL;
  657.  
  658.     ptr = s_malloc(len+1);
  659.     memcpy(ptr, str, len);
  660.     *(ptr+len)=0x00;
  661.  
  662.     return ptr;
  663. }
  664. char *s_strxdup(const char *str, int extra, int *size)
  665. {
  666.     char *ptr;
  667.     int len;
  668.     
  669.     
  670.     if (str == NULL)
  671. return NULL;
  672.     len = strlen(str);
  673.     if (size)
  674.         *size = len+1+extra;
  675.     ptr = s_malloc(len+1+extra);
  676.     memcpy(ptr, str, len+1);
  677.     return ptr;
  678. }
  679. #undef readlink
  680. int s_readlink(const char *path, char *buf, int buflen)
  681. {
  682.     int s;
  683.     while ((s = readlink(path, buf, buflen)) < 0 && errno == EINTR)
  684. ;
  685.     return s;
  686. }
  687. #undef unlink
  688. int s_unlink(const char *path)
  689. {
  690.     int s;
  691.     while ((s = unlink(path)) < 0 && errno == EINTR)
  692. ;
  693.     return s;
  694. }
  695. /*
  696. ** The normal abort() uses a signal that forces threads to to switch
  697. ** to another thread, before turning over the control to the debugger.
  698. **
  699. ** That is not so optimal when using a non-threads-aware debugger like Gdb.
  700. */
  701. void s_abort(void)
  702. {
  703.     * (int *) 0 = 4711;
  704. }
  705. #undef stat
  706. int s_stat(const char *path, struct stat *buf)
  707. {
  708.     int status;
  709.     while ((status = stat(path, buf)) < 0 && errno == EINTR)
  710. ;
  711.     return status;
  712. }
  713. #undef lstat
  714. int s_lstat(const char *path, struct stat *buf)
  715. {
  716.     int status;
  717.     while ((status = lstat(path, buf)) < 0 && errno == EINTR)
  718. ;
  719.     return status;
  720. }
  721. /* Generate a unique filename */
  722. int s_tmpname(char *buf, int bufsize)
  723. {
  724.     static mutex_t tmplock;
  725.     static int count;
  726.     int i;
  727.     
  728.     mutex_lock(&tmplock);
  729.     i = count++;
  730.     mutex_unlock(&tmplock);
  731.     
  732.     return s_sprintf(buf, bufsize, "/tmp/.tmp.%d.%d", getpid(), i);
  733. }
  734. /* Create and open a unique temporary file */
  735. int s_tmpfile(char *buf, int bufsize)
  736. {
  737.     char buf2[1024];
  738.     int fd;
  739.     
  740.     if (buf == NULL)
  741.     {
  742. buf = buf2;
  743. bufsize = sizeof(buf2);
  744.     }
  745.     while (s_tmpname(buf, bufsize) >= 0)
  746.     {
  747. fd = s_open(buf, O_RDWR+O_CREAT+O_TRUNC, 0600);
  748. if (fd >= 0)
  749. {
  750.     if (s_unlink(buf) < 0)
  751.     {
  752. s_close(fd);
  753. return -1;
  754.     }
  755.     return fd;
  756. }
  757.     }
  758.     return -1;
  759. }