/* -*- linux-c -*- * String Functions * Copyright (C) 2005, 2006, 2007, 2009 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ #ifndef _STRING_C_ #define _STRING_C_ #include "string.h" /** @file string.c * @brief Implements string functions. */ /** @addtogroup string String Functions * * @{ */ /** Sprintf into a string. * Like printf, except output goes into a string. * * NB: these are script language printf formatting directives, where * %d ints are 64-bits etc, so we can't use gcc level attribute printf * to type-check the arguments. * * @param str string * @param fmt A printf-style format string followed by a * variable number of args. */ static int _stp_snprintf(char *buf, size_t size, const char *fmt, ...) { va_list args; int i; va_start(args, fmt); i = _stp_vsnprintf(buf,size,fmt,args); va_end(args); return i; } static int _stp_vscnprintf(char *buf, size_t size, const char *fmt, va_list args) { unsigned i = _stp_vsnprintf(buf,size,fmt,args); return (i >= size) ? (size - 1) : i; } /** Return a printable text string. * * Takes a string, and any ASCII characters that are not printable are * replaced by the corresponding escape sequence in the returned * string. * * @param outstr Output string pointer * @param in Input string pointer * @param len Maximum length of string to return not including terminating 0. * 0 means MAXSTRINGLEN. * @param quoted Put double quotes around the string. If input string is truncated * in will have "..." after the second quote. * @param user Set this to indicate the input string pointer is a userspace pointer. */ static void _stp_text_str(char *outstr, char *in, int len, int quoted, int user) { char c, *out = outstr; if (len <= 0 || len > MAXSTRINGLEN-1) len = MAXSTRINGLEN-1; if (quoted) { len = max(len, 5) - 2; *out++ = '"'; } if (user) { if (!access_ok(VERIFY_READ, (char __user *)in, 1)) goto bad; if (__stp_get_user(c, in)) goto bad; } else c = *in; while (c && len > 0) { int num = 1; if (isprint(c) && isascii(c) && c != '"' && c != '\\') /* quoteworthy characters */ *out++ = c; else { switch (c) { case '\a': case '\b': case '\f': case '\n': case '\r': case '\t': case '\v': case '"': case '\\': num = 2; break; default: num = 4; break; } if (len < num) break; *out++ = '\\'; switch (c) { case '\a': *out++ = 'a'; break; case '\b': *out++ = 'b'; break; case '\f': *out++ = 'f'; break; case '\n': *out++ = 'n'; break; case '\r': *out++ = 'r'; break; case '\t': *out++ = 't'; break; case '\v': *out++ = 'v'; break; case '"': *out++ = '"'; break; case '\\': *out++ = '\\'; break; default: /* output octal representation */ *out++ = to_oct_digit((c >> 6) & 03); *out++ = to_oct_digit((c >> 3) & 07); *out++ = to_oct_digit(c & 07); break; } } len -= num; in++; if (user) { if (__stp_get_user(c, in)) goto bad; } else c = *in; } if (quoted) { if (c) { out = out - 3 + len; *out++ = '"'; *out++ = '.'; *out++ = '.'; *out++ = '.'; } else *out++ = '"'; } *out = '\0'; return; bad: strlcpy (outstr, "", len); } /** @} */ #endif /* _STRING_C_ */