1/*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1997-2005 5 * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Kenneth Almquist. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35/* 36 * String functions. 37 * 38 * equal(s1, s2) Return true if strings are equal. 39 * scopy(from, to) Copy a string. 40 * scopyn(from, to, n) Like scopy, but checks for overflow. 41 * number(s) Convert a string of digits to an integer. 42 * is_number(s) Return true if s is a string of digits. 43 */ 44 45#include <ctype.h> 46#include <errno.h> 47#include <inttypes.h> 48#include <limits.h> 49#include <inttypes.h> 50#include <stdlib.h> 51#include "shell.h" 52#include "syntax.h" 53#include "error.h" 54#include "mystring.h" 55#include "memalloc.h" 56#include "parser.h" 57#include "system.h" 58 59 60char nullstr[1]; /* zero length string */ 61const char spcstr[] = " "; 62const char snlfmt[] = "%s\n"; 63const char dolatstr[] = { CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', 64 CTLQUOTEMARK, '\0' }; 65const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 }; 66const char illnum[] = "Illegal number: %s"; 67const char homestr[] = "HOME"; 68 69/* 70 * equal - #defined in mystring.h 71 */ 72 73/* 74 * scopy - #defined in mystring.h 75 */ 76 77 78#if 0 79/* 80 * scopyn - copy a string from "from" to "to", truncating the string 81 * if necessary. "To" is always nul terminated, even if 82 * truncation is performed. "Size" is the size of "to". 83 */ 84 85void 86scopyn(const char *from, char *to, int size) 87{ 88 89 while (--size > 0) { 90 if ((*to++ = *from++) == '\0') 91 return; 92 } 93 *to = '\0'; 94} 95#endif 96 97 98/* 99 * prefix -- see if pfx is a prefix of string. 100 */ 101 102char * 103prefix(const char *string, const char *pfx) 104{ 105 while (*pfx) { 106 if (*pfx++ != *string++) 107 return 0; 108 } 109 return (char *) string; 110} 111 112void badnum(const char *s) 113{ 114 sh_error(illnum, s); 115} 116 117/* 118 * Convert a string into an integer of type intmax_t. Alow trailing spaces. 119 */ 120intmax_t atomax(const char *s, int base) 121{ 122 char *p; 123 intmax_t r; 124 125 errno = 0; 126 r = strtoimax(s, &p, base); 127 128 if (errno != 0) 129 badnum(s); 130 131 /* 132 * Disallow completely blank strings in non-arithmetic (base != 0) 133 * contexts. 134 */ 135 if (p == s && base) 136 badnum(s); 137 138 while (isspace((unsigned char)*p)) 139 p++; 140 141 if (*p) 142 badnum(s); 143 144 return r; 145} 146 147intmax_t atomax10(const char *s) 148{ 149 return atomax(s, 10); 150} 151 152/* 153 * Convert a string of digits to an integer, printing an error message on 154 * failure. 155 */ 156 157int 158number(const char *s) 159{ 160 intmax_t n = atomax10(s); 161 162 if (n < 0 || n > INT_MAX) 163 badnum(s); 164 165 return n; 166} 167 168 169 170/* 171 * Check for a valid number. This should be elsewhere. 172 */ 173 174int 175is_number(const char *p) 176{ 177 do { 178 if (! is_digit(*p)) 179 return 0; 180 } while (*++p != '\0'); 181 return 1; 182} 183 184 185/* 186 * Produce a possibly single quoted string suitable as input to the shell. 187 * The return string is allocated on the stack. 188 */ 189 190char * 191single_quote(const char *s) { 192 char *p; 193 194 STARTSTACKSTR(p); 195 196 do { 197 char *q; 198 size_t len; 199 200 len = strchrnul(s, '\'') - s; 201 202 q = p = makestrspace(len + 3, p); 203 204 *q++ = '\''; 205 q = mempcpy(q, s, len); 206 *q++ = '\''; 207 s += len; 208 209 STADJUST(q - p, p); 210 211 len = strspn(s, "'"); 212 if (!len) 213 break; 214 215 q = p = makestrspace(len + 3, p); 216 217 *q++ = '"'; 218 q = mempcpy(q, s, len); 219 *q++ = '"'; 220 s += len; 221 222 STADJUST(q - p, p); 223 } while (*s); 224 225 USTPUTC(0, p); 226 227 return stackblock(); 228} 229 230/* 231 * Like strdup but works with the ash stack. 232 */ 233 234char * 235sstrdup(const char *p) 236{ 237 size_t len = strlen(p) + 1; 238 return memcpy(stalloc(len), p, len); 239} 240 241/* 242 * Wrapper around strcmp for qsort/bsearch/... 243 */ 244int 245pstrcmp(const void *a, const void *b) 246{ 247 return strcmp(*(const char *const *) a, *(const char *const *) b); 248} 249 250/* 251 * Find a string is in a sorted array. 252 */ 253const char *const * 254findstring(const char *s, const char *const *array, size_t nmemb) 255{ 256 return bsearch(&s, array, nmemb, sizeof(const char *), pstrcmp); 257} 258