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 * 3. 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 */ 35 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 39 #include <ctype.h> 40 #include <err.h> 41 #include <fts.h> 42 #include <limits.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <wchar.h> 47 #include <wctype.h> 48 49 #include "ls.h" 50 #include "extern.h" 51 52 int 53 prn_normal(const char *s) 54 { 55 mbstate_t mbs; 56 wchar_t wc; 57 int i, n; 58 size_t clen; 59 60 memset(&mbs, 0, sizeof(mbs)); 61 n = 0; 62 while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) { 63 if (clen == (size_t)-2) { 64 n += printf("%s", s); 65 break; 66 } 67 if (clen == (size_t)-1) { 68 memset(&mbs, 0, sizeof(mbs)); 69 putchar((unsigned char)*s); 70 s++; 71 n++; 72 continue; 73 } 74 for (i = 0; i < (int)clen; i++) 75 putchar((unsigned char)s[i]); 76 s += clen; 77 if (iswprint(wc)) 78 n += wcwidth(wc); 79 } 80 return (n); 81 } 82 83 int 84 prn_printable(const char *s) 85 { 86 mbstate_t mbs; 87 wchar_t wc; 88 int i, n; 89 size_t clen; 90 91 memset(&mbs, 0, sizeof(mbs)); 92 n = 0; 93 while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) { 94 if (clen == (size_t)-1) { 95 putchar('?'); 96 s++; 97 n++; 98 memset(&mbs, 0, sizeof(mbs)); 99 continue; 100 } 101 if (clen == (size_t)-2) { 102 putchar('?'); 103 n++; 104 break; 105 } 106 if (!iswprint(wc)) { 107 putchar('?'); 108 s += clen; 109 n++; 110 continue; 111 } 112 for (i = 0; i < (int)clen; i++) 113 putchar((unsigned char)s[i]); 114 s += clen; 115 n += wcwidth(wc); 116 } 117 return (n); 118 } 119 120 /* 121 * The fts system makes it difficult to replace fts_name with a different- 122 * sized string, so we just calculate the real length here and do the 123 * conversion in prn_octal() 124 * 125 * XXX when using f_octal_escape (-b) rather than f_octal (-B), the 126 * length computed by len_octal may be too big. I just can't be buggered 127 * to fix this as an efficient fix would involve a lookup table. Same goes 128 * for the rather inelegant code in prn_octal. 129 * 130 * DES 1998/04/23 131 */ 132 133 size_t 134 len_octal(const char *s, int len) 135 { 136 mbstate_t mbs; 137 wchar_t wc; 138 size_t clen, r; 139 140 memset(&mbs, 0, sizeof(mbs)); 141 r = 0; 142 while (len != 0 && (clen = mbrtowc(&wc, s, len, &mbs)) != 0) { 143 if (clen == (size_t)-1) { 144 r += 4; 145 s++; 146 len--; 147 memset(&mbs, 0, sizeof(mbs)); 148 continue; 149 } 150 if (clen == (size_t)-2) { 151 r += 4 * len; 152 break; 153 } 154 if (iswprint(wc)) 155 r++; 156 else 157 r += 4 * clen; 158 s += clen; 159 } 160 return (r); 161 } 162 163 int 164 prn_octal(const char *s) 165 { 166 static const char esc[] = "\\\\\"\"\aa\bb\ff\nn\rr\tt\vv"; 167 const char *p; 168 mbstate_t mbs; 169 wchar_t wc; 170 size_t clen; 171 unsigned char ch; 172 int goodchar, i, len, prtlen; 173 174 memset(&mbs, 0, sizeof(mbs)); 175 len = 0; 176 while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) { 177 goodchar = clen != (size_t)-1 && clen != (size_t)-2; 178 if (goodchar && iswprint(wc) && wc != L'\"' && wc != L'\\') { 179 for (i = 0; i < (int)clen; i++) 180 putchar((unsigned char)s[i]); 181 len += wcwidth(wc); 182 } else if (goodchar && f_octal_escape && wc >= 0 && 183 wc <= (wchar_t)UCHAR_MAX && 184 (p = strchr(esc, (char)wc)) != NULL) { 185 putchar('\\'); 186 putchar(p[1]); 187 len += 2; 188 } else { 189 if (goodchar) 190 prtlen = clen; 191 else if (clen == (size_t)-1) 192 prtlen = 1; 193 else 194 prtlen = strlen(s); 195 for (i = 0; i < prtlen; i++) { 196 ch = (unsigned char)s[i]; 197 putchar('\\'); 198 putchar('0' + (ch >> 6)); 199 putchar('0' + ((ch >> 3) & 7)); 200 putchar('0' + (ch & 7)); 201 len += 4; 202 } 203 } 204 if (clen == (size_t)-2) 205 break; 206 if (clen == (size_t)-1) { 207 memset(&mbs, 0, sizeof(mbs)); 208 s++; 209 } else 210 s += clen; 211 } 212 return (len); 213 } 214 215 void 216 usage(void) 217 { 218 fprintf(stderr, 219 #ifdef COLORLS 220 "usage: ls [-1ABCFGHILPRSTW_abcdfghiklmnopqrstuwxy] [-D format]" 221 #else 222 "usage: ls [-1ABCFHILPRSTW_abcdfghiklmnopqrstuwxy] [-D format]" 223 #endif 224 " [file ...]\n"); 225 exit(1); 226 } 227