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