util.c revision 139969
1105068Sphk/*- 2105068Sphk * Copyright (c) 1989, 1993, 1994 3105068Sphk * The Regents of the University of California. All rights reserved. 4105068Sphk * 5105068Sphk * This code is derived from software contributed to Berkeley by 6105068Sphk * Michael Fischbein. 7105068Sphk * 8105068Sphk * Redistribution and use in source and binary forms, with or without 9105068Sphk * modification, are permitted provided that the following conditions 10105068Sphk * are met: 11105068Sphk * 1. Redistributions of source code must retain the above copyright 12105068Sphk * notice, this list of conditions and the following disclaimer. 13105068Sphk * 2. Redistributions in binary form must reproduce the above copyright 14105068Sphk * notice, this list of conditions and the following disclaimer in the 15105068Sphk * documentation and/or other materials provided with the distribution. 16105068Sphk * 4. Neither the name of the University nor the names of its contributors 17105068Sphk * may be used to endorse or promote products derived from this software 18105068Sphk * without specific prior written permission. 19105068Sphk * 20105068Sphk * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21105068Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22105068Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23105068Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24105068Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25105068Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26105068Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27105068Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28105068Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29105068Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30105068Sphk * SUCH DAMAGE. 31105068Sphk */ 32105068Sphk 33105068Sphk#if 0 34105068Sphk#ifndef lint 35105068Sphkstatic char sccsid[] = "@(#)util.c 8.3 (Berkeley) 4/2/94"; 36105068Sphk#endif /* not lint */ 37105068Sphk#endif 38105068Sphk#include <sys/cdefs.h> 39105068Sphk__FBSDID("$FreeBSD: head/bin/ls/util.c 139969 2005-01-10 08:39:26Z imp $"); 40105068Sphk 41105068Sphk#include <sys/types.h> 42105068Sphk#include <sys/stat.h> 43105068Sphk 44105068Sphk#include <ctype.h> 45105068Sphk#include <err.h> 46105068Sphk#include <fts.h> 47105068Sphk#include <limits.h> 48105068Sphk#include <stdio.h> 49113892Sphk#include <stdlib.h> 50105068Sphk#include <string.h> 51105068Sphk#include <wchar.h> 52105068Sphk#include <wctype.h> 53112511Sphk 54112511Sphk#include "ls.h" 55112511Sphk#include "extern.h" 56112511Sphk 57105068Sphkint 58105068Sphkprn_normal(const char *s) 59112709Sphk{ 60112511Sphk mbstate_t mbs; 61112511Sphk wchar_t wc; 62105068Sphk int i, n; 63113892Sphk size_t clen; 64113892Sphk 65105068Sphk memset(&mbs, 0, sizeof(mbs)); 66105068Sphk n = 0; 67112534Sphk while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) { 68112534Sphk if (clen == (size_t)-2) { 69112534Sphk n += printf("%s", s); 70112534Sphk break; 71112534Sphk } 72105068Sphk if (clen == (size_t)-1) { 73105068Sphk memset(&mbs, 0, sizeof(mbs)); 74112534Sphk putchar((unsigned char)*s); 75105068Sphk s++; 76105068Sphk n++; 77105068Sphk continue; 78112534Sphk } 79112534Sphk for (i = 0; i < (int)clen; i++) 80112709Sphk putchar((unsigned char)s[i]); 81112709Sphk s += clen; 82112709Sphk if (iswprint(wc)) 83112709Sphk n += wcwidth(wc); 84105068Sphk } 85105068Sphk return (n); 86112511Sphk} 87112511Sphk 88112511Sphkint 89112511Sphkprn_printable(const char *s) 90112511Sphk{ 91112511Sphk mbstate_t mbs; 92112709Sphk wchar_t wc; 93113892Sphk int i, n; 94112511Sphk size_t clen; 95112511Sphk 96113892Sphk memset(&mbs, 0, sizeof(mbs)); 97113892Sphk n = 0; 98112511Sphk while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) { 99113892Sphk if (clen == (size_t)-1) { 100113892Sphk putchar('?'); 101113892Sphk s++; 102113892Sphk n++; 103113892Sphk memset(&mbs, 0, sizeof(mbs)); 104113892Sphk continue; 105113892Sphk } 106113892Sphk if (clen == (size_t)-2) { 107113892Sphk putchar('?'); 108113892Sphk n++; 109113892Sphk break; 110113892Sphk } 111113892Sphk if (!iswprint(wc)) { 112112511Sphk putchar('?'); 113112511Sphk s += clen; 114113892Sphk n++; 115112511Sphk continue; 116112511Sphk } 117112511Sphk for (i = 0; i < (int)clen; i++) 118112511Sphk putchar((unsigned char)s[i]); 119112511Sphk s += clen; 120112511Sphk n += wcwidth(wc); 121112511Sphk } 122112511Sphk return (n); 123112709Sphk} 124112511Sphk 125112511Sphk/* 126112511Sphk * The fts system makes it difficult to replace fts_name with a different- 127112511Sphk * sized string, so we just calculate the real length here and do the 128112511Sphk * conversion in prn_octal() 129112511Sphk * 130112511Sphk * XXX when using f_octal_escape (-b) rather than f_octal (-B), the 131112511Sphk * length computed by len_octal may be too big. I just can't be buggered 132112511Sphk * to fix this as an efficient fix would involve a lookup table. Same goes 133112511Sphk * for the rather inelegant code in prn_octal. 134112511Sphk * 135112709Sphk * DES 1998/04/23 136112511Sphk */ 137112511Sphk 138112511Sphksize_t 139112511Sphklen_octal(const char *s, int len) 140112511Sphk{ 141112511Sphk mbstate_t mbs; 142112511Sphk wchar_t wc; 143112511Sphk size_t clen, r; 144112511Sphk 145112511Sphk memset(&mbs, 0, sizeof(mbs)); 146112511Sphk r = 0; 147112511Sphk while (len != 0 && (clen = mbrtowc(&wc, s, len, &mbs)) != 0) { 148112511Sphk if (clen == (size_t)-1) { 149112511Sphk r += 4; 150112511Sphk s++; 151112709Sphk len--; 152112511Sphk memset(&mbs, 0, sizeof(mbs)); 153112511Sphk continue; 154112709Sphk } 155112511Sphk if (clen == (size_t)-2) { 156112511Sphk r += 4 * len; 157112511Sphk break; 158112709Sphk } 159112709Sphk if (iswprint(wc)) 160112709Sphk r++; 161112511Sphk else 162112709Sphk r += 4 * clen; 163112709Sphk s += clen; 164112511Sphk } 165112709Sphk return (r); 166112709Sphk} 167112709Sphk 168112709Sphkint 169113862Sphkprn_octal(const char *s) 170112709Sphk{ 171112511Sphk static const char esc[] = "\\\\\"\"\aa\bb\ff\nn\rr\tt\vv"; 172112709Sphk const char *p; 173112709Sphk mbstate_t mbs; 174112511Sphk wchar_t wc; 175112709Sphk size_t clen; 176112709Sphk unsigned char ch; 177112709Sphk int goodchar, i, len, prtlen; 178112511Sphk 179112709Sphk memset(&mbs, 0, sizeof(mbs)); 180112709Sphk len = 0; 181112511Sphk while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) { 182112511Sphk goodchar = clen != (size_t)-1 && clen != (size_t)-2; 183112511Sphk if (goodchar && iswprint(wc) && wc != L'\"' && wc != L'\\') { 184112709Sphk for (i = 0; i < (int)clen; i++) 185112709Sphk putchar((unsigned char)s[i]); 186112511Sphk len += wcwidth(wc); 187112511Sphk } else if (goodchar && f_octal_escape && wc >= 0 && 188112511Sphk wc <= (wchar_t)UCHAR_MAX && 189112511Sphk (p = strchr(esc, (char)wc)) != NULL) { 190112511Sphk putchar('\\'); 191112511Sphk putchar(p[1]); 192112511Sphk len += 2; 193112511Sphk } else { 194112511Sphk if (goodchar) 195112511Sphk prtlen = clen; 196112511Sphk else if (clen == (size_t)-1) 197112511Sphk prtlen = 1; 198112511Sphk else 199114531Sphk prtlen = strlen(s); 200114531Sphk for (i = 0; i < prtlen; i++) { 201114531Sphk ch = (unsigned char)s[i]; 202114531Sphk putchar('\\'); 203114531Sphk putchar('0' + (ch >> 6)); 204114531Sphk putchar('0' + ((ch >> 3) & 7)); 205114531Sphk putchar('0' + (ch & 7)); 206114531Sphk len += 4; 207114531Sphk } 208114531Sphk } 209114531Sphk if (clen == (size_t)-2) 210114531Sphk break; 211112709Sphk if (clen == (size_t)-1) { 212112511Sphk memset(&mbs, 0, sizeof(mbs)); 213112511Sphk s++; 214112511Sphk } else 215112709Sphk s += clen; 216112511Sphk } 217112511Sphk return (len); 218112511Sphk} 219112709Sphk 220112511Sphkvoid 221112709Sphkusage(void) 222112511Sphk{ 223112511Sphk (void)fprintf(stderr, 224112511Sphk#ifdef COLORLS 225112511Sphk "usage: ls [-ABCFGHLPRTWZabcdfghiklmnoqrstuwx1]" 226112511Sphk#else 227112511Sphk "usage: ls [-ABCFHLPRTWZabcdfghiklmnoqrstuwx1]" 228112511Sphk#endif 229112511Sphk " [file ...]\n"); 230113862Sphk exit(1); 231112709Sphk} 232112709Sphk