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