1 /* 2 * Copyright (c) 1989, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Michael Fischbein. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)util.c 8.3 (Berkeley) 4/2/94 33 * $FreeBSD: src/bin/ls/util.c,v 1.35 2004/05/03 11:48:55 tjr Exp $ 34 * $DragonFly: src/bin/ls/util.c,v 1.7 2005/09/18 18:35:23 asmodai Exp $ 35 */ 36 37 #include <sys/types.h> 38 #include <sys/stat.h> 39 40 #include <ctype.h> 41 #include <err.h> 42 #include <fts.h> 43 #include <limits.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <wchar.h> 48 #include <wctype.h> 49 50 #include "ls.h" 51 #include "extern.h" 52 53 int 54 prn_normal(const char *s) 55 { 56 mbstate_t mbs; 57 wchar_t wc; 58 int i, n; 59 size_t clen; 60 61 memset(&mbs, 0, sizeof(mbs)); 62 n = 0; 63 while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) { 64 if (clen == (size_t)-2) { 65 n += printf("%s", s); 66 break; 67 } 68 if (clen == (size_t)-1) { 69 memset(&mbs, 0, sizeof(mbs)); 70 putchar((unsigned char)*s); 71 s++; 72 n++; 73 continue; 74 } 75 for (i = 0; i < (int)clen; i++) 76 putchar((unsigned char)s[i]); 77 s += clen; 78 if (iswprint(wc)) 79 n += wcwidth(wc); 80 } 81 return (n); 82 } 83 84 int 85 prn_printable(const char *s) 86 { 87 mbstate_t mbs; 88 wchar_t wc; 89 int i, n; 90 size_t clen; 91 92 memset(&mbs, 0, sizeof(mbs)); 93 n = 0; 94 while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) { 95 if (clen == (size_t)-1) { 96 putchar('?'); 97 s++; 98 n++; 99 memset(&mbs, 0, sizeof(mbs)); 100 continue; 101 } 102 if (clen == (size_t)-2) { 103 putchar('?'); 104 n++; 105 break; 106 } 107 if (!iswprint(wc)) { 108 putchar('?'); 109 s += clen; 110 n++; 111 continue; 112 } 113 for (i = 0; i < (int)clen; i++) 114 putchar((unsigned char)s[i]); 115 s += clen; 116 n += wcwidth(wc); 117 } 118 return (n); 119 } 120 121 /* 122 * The fts system makes it difficult to replace fts_name with a different- 123 * sized string, so we just calculate the real length here and do the 124 * conversion in prn_octal() 125 * 126 * XXX when using f_octal_escape (-b) rather than f_octal (-B), the 127 * length computed by len_octal may be too big. I just can't be buggered 128 * to fix this as an efficient fix would involve a lookup table. Same goes 129 * for the rather inelegant code in prn_octal. 130 * 131 * DES 1998/04/23 132 */ 133 134 size_t 135 len_octal(const char *s, int len) 136 { 137 mbstate_t mbs; 138 wchar_t wc; 139 size_t clen, r; 140 141 memset(&mbs, 0, sizeof(mbs)); 142 r = 0; 143 while (len != 0 && (clen = mbrtowc(&wc, s, len, &mbs)) != 0) { 144 if (clen == (size_t)-1) { 145 r += 4; 146 s++; 147 len--; 148 memset(&mbs, 0, sizeof(mbs)); 149 continue; 150 } 151 if (clen == (size_t)-2) { 152 r += 4 * len; 153 break; 154 } 155 if (iswprint(wc)) 156 r++; 157 else 158 r += 4 * clen; 159 s += clen; 160 } 161 return (r); 162 } 163 164 int 165 prn_octal(const char *s) 166 { 167 static const char esc[] = "\\\\\"\"\aa\bb\ff\nn\rr\tt\vv"; 168 const char *p; 169 mbstate_t mbs; 170 wchar_t wc; 171 size_t clen; 172 unsigned char ch; 173 int goodchar, i, len, prtlen; 174 175 memset(&mbs, 0, sizeof(mbs)); 176 len = 0; 177 while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) { 178 goodchar = clen != (size_t)-1 && clen != (size_t)-2; 179 if (goodchar && iswprint(wc) && wc != L'\"' && wc != L'\\') { 180 for (i = 0; i < (int)clen; i++) 181 putchar((unsigned char)s[i]); 182 len += wcwidth(wc); 183 } else if (goodchar && f_octal_escape && wc >= 0 && 184 wc <= (wchar_t)UCHAR_MAX && 185 (p = strchr(esc, (char)wc)) != NULL) { 186 putchar('\\'); 187 putchar(p[1]); 188 len += 2; 189 } else { 190 if (goodchar) 191 prtlen = clen; 192 else if (clen == (size_t)-1) 193 prtlen = 1; 194 else 195 prtlen = strlen(s); 196 for (i = 0; i < prtlen; i++) { 197 ch = (unsigned char)s[i]; 198 putchar('\\'); 199 putchar('0' + (ch >> 6)); 200 putchar('0' + ((ch >> 3) & 7)); 201 putchar('0' + (ch & 7)); 202 len += 4; 203 } 204 } 205 if (clen == (size_t)-2) 206 break; 207 if (clen == (size_t)-1) { 208 memset(&mbs, 0, sizeof(mbs)); 209 s++; 210 } else 211 s += clen; 212 } 213 return (len); 214 } 215 216 void 217 usage(void) 218 { 219 fprintf(stderr, 220 #ifdef COLORLS 221 "usage: ls [-ABCFGHLPRTWabcdfghiklmnoqrstuwxy1]" 222 #else 223 "usage: ls [-ABCFHLPRTWabcdfghiklmnoqrstuwxy1]" 224 #endif 225 " [file ...]\n"); 226 exit(1); 227 } 228