1157016Sdes/* $OpenBSD: vis.c,v 1.19 2005/09/01 17:15:49 millert Exp $ */ 2113908Sdes/*- 3113908Sdes * Copyright (c) 1989, 1993 4113908Sdes * The Regents of the University of California. All rights reserved. 5113908Sdes * 6113908Sdes * Redistribution and use in source and binary forms, with or without 7113908Sdes * modification, are permitted provided that the following conditions 8113908Sdes * are met: 9113908Sdes * 1. Redistributions of source code must retain the above copyright 10113908Sdes * notice, this list of conditions and the following disclaimer. 11113908Sdes * 2. Redistributions in binary form must reproduce the above copyright 12113908Sdes * notice, this list of conditions and the following disclaimer in the 13113908Sdes * documentation and/or other materials provided with the distribution. 14124208Sdes * 3. Neither the name of the University nor the names of its contributors 15113908Sdes * may be used to endorse or promote products derived from this software 16113908Sdes * without specific prior written permission. 17113908Sdes * 18113908Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19113908Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20113908Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21113908Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22113908Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23113908Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24113908Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25113908Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26113908Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27113908Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28113908Sdes * SUCH DAMAGE. 29113908Sdes */ 30157016Sdes 31157016Sdes/* OPENBSD ORIGINAL: lib/libc/gen/vis.c */ 32157016Sdes 33124208Sdes#include "includes.h" 34251135Sdes#if !defined(HAVE_STRNVIS) || defined(BROKEN_STRNVIS) 35113908Sdes 36113908Sdes#include <ctype.h> 37124208Sdes#include <string.h> 38113908Sdes 39113908Sdes#include "vis.h" 40113908Sdes 41113908Sdes#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') 42157016Sdes#define isvisible(c) \ 43157016Sdes (((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) && \ 44157016Sdes (((c) != '*' && (c) != '?' && (c) != '[' && (c) != '#') || \ 45157016Sdes (flag & VIS_GLOB) == 0) && isgraph((u_char)(c))) || \ 46157016Sdes ((flag & VIS_SP) == 0 && (c) == ' ') || \ 47157016Sdes ((flag & VIS_TAB) == 0 && (c) == '\t') || \ 48157016Sdes ((flag & VIS_NL) == 0 && (c) == '\n') || \ 49157016Sdes ((flag & VIS_SAFE) && ((c) == '\b' || \ 50157016Sdes (c) == '\007' || (c) == '\r' || \ 51157016Sdes isgraph((u_char)(c))))) 52113908Sdes 53113908Sdes/* 54113908Sdes * vis - visually encode characters 55113908Sdes */ 56113908Sdeschar * 57157016Sdesvis(char *dst, int c, int flag, int nextc) 58113908Sdes{ 59113908Sdes if (isvisible(c)) { 60113908Sdes *dst++ = c; 61113908Sdes if (c == '\\' && (flag & VIS_NOSLASH) == 0) 62113908Sdes *dst++ = '\\'; 63113908Sdes *dst = '\0'; 64113908Sdes return (dst); 65113908Sdes } 66113908Sdes 67113908Sdes if (flag & VIS_CSTYLE) { 68113908Sdes switch(c) { 69113908Sdes case '\n': 70113908Sdes *dst++ = '\\'; 71113908Sdes *dst++ = 'n'; 72113908Sdes goto done; 73113908Sdes case '\r': 74113908Sdes *dst++ = '\\'; 75113908Sdes *dst++ = 'r'; 76113908Sdes goto done; 77113908Sdes case '\b': 78113908Sdes *dst++ = '\\'; 79113908Sdes *dst++ = 'b'; 80113908Sdes goto done; 81113908Sdes case '\a': 82113908Sdes *dst++ = '\\'; 83113908Sdes *dst++ = 'a'; 84113908Sdes goto done; 85113908Sdes case '\v': 86113908Sdes *dst++ = '\\'; 87113908Sdes *dst++ = 'v'; 88113908Sdes goto done; 89113908Sdes case '\t': 90113908Sdes *dst++ = '\\'; 91113908Sdes *dst++ = 't'; 92113908Sdes goto done; 93113908Sdes case '\f': 94113908Sdes *dst++ = '\\'; 95113908Sdes *dst++ = 'f'; 96113908Sdes goto done; 97113908Sdes case ' ': 98113908Sdes *dst++ = '\\'; 99113908Sdes *dst++ = 's'; 100113908Sdes goto done; 101113908Sdes case '\0': 102113908Sdes *dst++ = '\\'; 103113908Sdes *dst++ = '0'; 104113908Sdes if (isoctal(nextc)) { 105113908Sdes *dst++ = '0'; 106113908Sdes *dst++ = '0'; 107113908Sdes } 108113908Sdes goto done; 109113908Sdes } 110113908Sdes } 111157016Sdes if (((c & 0177) == ' ') || (flag & VIS_OCTAL) || 112157016Sdes ((flag & VIS_GLOB) && (c == '*' || c == '?' || c == '[' || c == '#'))) { 113113908Sdes *dst++ = '\\'; 114113908Sdes *dst++ = ((u_char)c >> 6 & 07) + '0'; 115113908Sdes *dst++ = ((u_char)c >> 3 & 07) + '0'; 116113908Sdes *dst++ = ((u_char)c & 07) + '0'; 117113908Sdes goto done; 118113908Sdes } 119113908Sdes if ((flag & VIS_NOSLASH) == 0) 120113908Sdes *dst++ = '\\'; 121113908Sdes if (c & 0200) { 122113908Sdes c &= 0177; 123113908Sdes *dst++ = 'M'; 124113908Sdes } 125157016Sdes if (iscntrl((u_char)c)) { 126113908Sdes *dst++ = '^'; 127113908Sdes if (c == 0177) 128113908Sdes *dst++ = '?'; 129113908Sdes else 130113908Sdes *dst++ = c + '@'; 131113908Sdes } else { 132113908Sdes *dst++ = '-'; 133113908Sdes *dst++ = c; 134113908Sdes } 135113908Sdesdone: 136113908Sdes *dst = '\0'; 137113908Sdes return (dst); 138113908Sdes} 139113908Sdes 140113908Sdes/* 141113908Sdes * strvis, strnvis, strvisx - visually encode characters from src into dst 142113908Sdes * 143113908Sdes * Dst must be 4 times the size of src to account for possible 144113908Sdes * expansion. The length of dst, not including the trailing NULL, 145113908Sdes * is returned. 146113908Sdes * 147113908Sdes * Strnvis will write no more than siz-1 bytes (and will NULL terminate). 148113908Sdes * The number of bytes needed to fully encode the string is returned. 149113908Sdes * 150113908Sdes * Strvisx encodes exactly len bytes from src into dst. 151113908Sdes * This is useful for encoding a block of data. 152113908Sdes */ 153113908Sdesint 154157016Sdesstrvis(char *dst, const char *src, int flag) 155113908Sdes{ 156157016Sdes char c; 157113908Sdes char *start; 158113908Sdes 159113908Sdes for (start = dst; (c = *src);) 160113908Sdes dst = vis(dst, c, flag, *++src); 161113908Sdes *dst = '\0'; 162113908Sdes return (dst - start); 163113908Sdes} 164113908Sdes 165113908Sdesint 166157016Sdesstrnvis(char *dst, const char *src, size_t siz, int flag) 167113908Sdes{ 168113908Sdes char *start, *end; 169124208Sdes char tbuf[5]; 170157016Sdes int c, i; 171113908Sdes 172124208Sdes i = 0; 173113908Sdes for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) { 174113908Sdes if (isvisible(c)) { 175124208Sdes i = 1; 176113908Sdes *dst++ = c; 177113908Sdes if (c == '\\' && (flag & VIS_NOSLASH) == 0) { 178113908Sdes /* need space for the extra '\\' */ 179113908Sdes if (dst < end) 180113908Sdes *dst++ = '\\'; 181113908Sdes else { 182113908Sdes dst--; 183124208Sdes i = 2; 184113908Sdes break; 185113908Sdes } 186113908Sdes } 187113908Sdes src++; 188113908Sdes } else { 189124208Sdes i = vis(tbuf, c, flag, *++src) - tbuf; 190124208Sdes if (dst + i <= end) { 191124208Sdes memcpy(dst, tbuf, i); 192124208Sdes dst += i; 193124208Sdes } else { 194124208Sdes src--; 195113908Sdes break; 196124208Sdes } 197113908Sdes } 198113908Sdes } 199124208Sdes if (siz > 0) 200124208Sdes *dst = '\0'; 201124208Sdes if (dst + i > end) { 202113908Sdes /* adjust return value for truncation */ 203113908Sdes while ((c = *src)) 204113908Sdes dst += vis(tbuf, c, flag, *++src) - tbuf; 205113908Sdes } 206113908Sdes return (dst - start); 207113908Sdes} 208113908Sdes 209113908Sdesint 210157016Sdesstrvisx(char *dst, const char *src, size_t len, int flag) 211113908Sdes{ 212157016Sdes char c; 213113908Sdes char *start; 214113908Sdes 215113908Sdes for (start = dst; len > 1; len--) { 216113908Sdes c = *src; 217113908Sdes dst = vis(dst, c, flag, *++src); 218113908Sdes } 219113908Sdes if (len) 220113908Sdes dst = vis(dst, *src, flag, '\0'); 221113908Sdes *dst = '\0'; 222113908Sdes return (dst - start); 223113908Sdes} 224113908Sdes 225113908Sdes#endif 226