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