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