1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
/*
* cook - file construction tool
* Copyright (C) 1994, 1997, 1998, 2006, 2007 Peter Miller;
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
* MANIFEST: insulate against <string.h> vs <strings.h> differences
*/
#ifndef COMMON_AC_STRING_H
#define COMMON_AC_STRING_H
#include <common/config.h>
/*
* We could have used __USE_BSD, but that defines prototypes for the
* index, rindex, bcmp, bzero and bcopy functions, and we don't want
* them. This prototype does not conflict, however.
*/
#if !defined(HAVE_STRCASECMP) || defined(__linux__)
# if __STDC__ >= 1
# ifdef __USE_BSD
# undef __USE_BSD
# endif
int strcasecmp(const char *, const char *);
# endif
#endif
/*
* We could have used __USE_GNU, but that defines prototypes for
* too many other things. This prototype does not conflict, however.
*/
#if !defined(HAVE_STRSIGNAL) || defined(__linux__)
# if __STDC__ >= 1
char *strsignal(int);
# endif
#endif
#if STDC_HEADERS || HAVE_STRING_H
# include <string.h>
/* An ANSI string.h and pre-ANSI memory.h might conflict. */
# if !STDC_HEADERS && HAVE_MEMORY_H
# include <memory.h>
# endif
#else
/* memory.h and strings.h conflict on some systems. */
# include <strings.h>
#endif
/*
* Cook is built with the -frequire-prototypes flag, but this can cause
* problems with dumb systems. Linux is usually pretty good, but...
*
* The Linux string.h does not declare these, because then they can
* be inlined. It should use the OPTIMIZE define, and only not declare
* them when not optimizing.
*/
#if defined(linux) || defined(__linux__)
__ptr_t memcpy __P ((__ptr_t, __const __ptr_t, size_t));
int memcmp __P ((__const __ptr_t, __const __ptr_t, size_t));
#endif
#if !HAVE_STRLCPY
size_t strlcpy(char *dst, const char *src, size_t size);
#endif
#if !HAVE_STRLCAT
size_t strlcat(char *dst, const char *src, size_t size);
#endif
#if !HAVE_STRENDCPY
/**
* The strendcpy function is a buffer-overrun-safe replacement for
* strcpy, strcat, and a more efficient replacement for strlcpy and
* strlcat.
*
* Unless there is no space left in the buffer (dst >= end), the result
* will always be NUL terminated.
*
* @param dst
* The position within the destination string buffer to be copied into.
* @param src
* The string to be copied into the buffer.
* @param end
* The end of the string buffer being copied into. In most cases
* this is of the form "buffer + sizeof(buffer)", a constant which
* may be calculated at compile time.
* @returns
* A pointer into the buffer where at the NUL terminator of the
* string in the buffer. EXCEPT when an overrun would occur, in
* which case the \a end parameter is returned.
*
* @note
* The return value is where the next string would be written into the
* buffer. For example, un-safe code such as
*
* strcat(strcpy(buffer, "Hello, "), "World\n");
*
* can be safely replaced by
*
* strendcpy(strendcpy(buffer, "Hello, ", buffer + sizeof(buffer)),
* "World\n", buffer + sizeof(buffer));
*
* and overruns will be handled safely. Similarly, more complex string
* manipulations can be written
*
* char buffer[100];
* char *bp = buffer;
* bp = strendcpy(bp, "Hello, ", buffer + sizeof(buffer));
* bp = strendcpy(bp, "World!\n", buffer + sizeof(buffer));
*
* all that is required to test for an overrun is
*
* if (bp == buffer + sizeof(buffer))
* fprintf(stderr, "Overrun!\n");
*
* On the plus side, there is only one functionto remember, not two,
* replacing both strcpy and strcat.
*
* There have been some quite viable replacements for strcpy and strcat
* in the BSD strlcpy and strlcat functions. These functions are
* indeed buffer-ovrrun-safe but they suffer from doing too much work
* (and touching too much memory) in the case of overruns.
*
* Code such as
*
* strlcpy(buffer, "Hello, ", sizeof(buffer));
* strlcat(buffer, "World!\n", sizeof(buffer));
*
* suffers from O(n**2) problem, constantly re-tracing the initial
* portions of the buffer. In addition, in the case of overruns, the
* BSD versions of these functions return how big the buffer should
* have been. This functionality is rarely used, but still requires
* the \a src to be traversed all the way to the NUL (and it could be
* megabytes away) before they can return. The strendcpy function does
* not suffer from either of these performance problems.
*/
char *strendcpy(char *dst, const char *src, const char *end);
#endif
#undef strcat
#define strcat strcat_is_unsafe__use_strendcpy_instead@
#undef strcpy
#define strcpy strcpy_is_unsafe__use_strendcpy_instead@
#undef strlcat
#define strlcat strlcat_is_inefficient__use_strendcpy_instead@
#undef strlcpy
#define strlcpy strlcpy_is_inefficient__use_strendcpy_instead@
#endif /* COMMON_AC_STRING_H */
|