Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Revision 12: http://theos.com/~deraadt/snprintf.c
  3.  *
  4.  * Copyright (c) 1997 Theo de Raadt
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  *
  15.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27. #ifndef __VMS
  28. # include <sys/param.h>
  29. #endif
  30. #include <sys/types.h>
  31. #include <sys/mman.h>
  32. #include <signal.h>
  33. #include <stdio.h>
  34. #if __STDC__
  35. #include <stdarg.h>
  36. #include <stdlib.h>
  37. #else
  38. #include <varargs.h>
  39. #endif
  40. #include <setjmp.h>
  41. #include <unistd.h>
  42. #include <string.h>
  43.  
  44. #ifndef roundup
  45. #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
  46. #endif
  47.  
  48. #ifdef __sgi
  49. #define size_t ssize_t
  50. #endif
  51.  
  52. static int pgsize;
  53. static char *curobj;
  54. static int caught;
  55. static sigjmp_buf bail;
  56.  
  57. #define EXTRABYTES      2       /* XXX: why 2? you don't want to know */
  58.  
  59. static char *
  60. msetup(str, n)
  61.         char *str;
  62.         size_t n;
  63. {
  64.         char *e;
  65.  
  66.         if (n == 0)
  67.                 return NULL;
  68.         if (pgsize == 0)
  69.                 pgsize = getpagesize();
  70.         curobj = (char *)malloc(n + EXTRABYTES + pgsize * 2);
  71.         if (curobj == NULL)
  72.                 return NULL;
  73.         e = curobj + n + EXTRABYTES;
  74.         e = (char *)roundup((unsigned long)e, pgsize);
  75.         if (mprotect(e, pgsize, PROT_NONE) == -1) {
  76.                 free(curobj);
  77.                 curobj = NULL;
  78.                 return NULL;
  79.         }
  80.         e = e - n - EXTRABYTES;
  81.         *e = '\0';
  82.         return (e);
  83. }
  84.  
  85. static void
  86.   mcatch( int a )
  87. {
  88.         siglongjmp(bail, 1);
  89. }
  90.  
  91. static void
  92. mcleanup(str, n, p)
  93.         char *str;
  94.         size_t n;
  95.         char *p;
  96. {
  97.         strncpy(str, p, n-1);
  98.         str[n-1] = '\0';
  99.         if (mprotect((caddr_t)(p + n + EXTRABYTES), pgsize,
  100.             PROT_READ|PROT_WRITE|PROT_EXEC) == -1)
  101.                 mprotect((caddr_t)(p + n + EXTRABYTES), pgsize,
  102.                     PROT_READ|PROT_WRITE);
  103.         free(curobj);
  104. }
  105.  
  106. int
  107. #if __STDC__
  108. vsnprintf(char *str, size_t n, char const *fmt, va_list ap)
  109. #else
  110. vsnprintf(str, n, fmt, ap)
  111.         char *str;
  112.         size_t n;
  113.         char *fmt;
  114.         char *ap;
  115. #endif
  116. {
  117.         struct sigaction osa, nsa;
  118.         char *p;
  119.         int ret = n + 1;        /* if we bail, indicated we overflowed */
  120.  
  121.         memset(&nsa, 0, sizeof nsa);
  122.         nsa.sa_handler = mcatch;
  123.         sigemptyset(&nsa.sa_mask);
  124.  
  125.         p = msetup(str, n);
  126.         if (p == NULL) {
  127.                 *str = '\0';
  128.                 return 0;
  129.         }
  130.         if (sigsetjmp(bail, 1) == 0) {
  131.                 if (sigaction(SIGSEGV, &nsa, &osa) == -1) {
  132.                         mcleanup(str, n, p);
  133.                         return (0);
  134.                 }
  135.                 ret = vsprintf(p, fmt, ap);
  136.         }
  137.         mcleanup(str, n, p);
  138.         (void) sigaction(SIGSEGV, &osa, NULL);
  139.         return (ret);
  140. }
  141.  
  142. int
  143. #if __STDC__
  144. snprintf(char *str, size_t n, char const *fmt, ...)
  145. #else
  146. snprintf(str, n, fmt, va_alist)
  147.         char *str;
  148.         size_t n;
  149.         char *fmt;
  150.         va_dcl
  151. #endif
  152. {
  153.         va_list ap;
  154. #if __STDC__
  155.         va_start(ap, fmt);
  156. #else
  157.         va_start(ap);
  158. #endif
  159.  
  160.         return (vsnprintf(str, n, fmt, ap));
  161.         va_end(ap);
  162. }
  163.  
  164.  
  165.  
  166.