1139969Simp/*-
21556Srgrimes * Copyright (c) 1989, 1993, 1994
31556Srgrimes *	The Regents of the University of California.  All rights reserved.
41556Srgrimes *
51556Srgrimes * This code is derived from software contributed to Berkeley by
61556Srgrimes * Michael Fischbein.
71556Srgrimes *
81556Srgrimes * Redistribution and use in source and binary forms, with or without
91556Srgrimes * modification, are permitted provided that the following conditions
101556Srgrimes * are met:
111556Srgrimes * 1. Redistributions of source code must retain the above copyright
121556Srgrimes *    notice, this list of conditions and the following disclaimer.
131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141556Srgrimes *    notice, this list of conditions and the following disclaimer in the
151556Srgrimes *    documentation and/or other materials provided with the distribution.
161556Srgrimes * 4. Neither the name of the University nor the names of its contributors
171556Srgrimes *    may be used to endorse or promote products derived from this software
181556Srgrimes *    without specific prior written permission.
191556Srgrimes *
201556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301556Srgrimes * SUCH DAMAGE.
311556Srgrimes */
321556Srgrimes
3390153Smarkm#if 0
341556Srgrimes#ifndef lint
3527967Sstevestatic char sccsid[] = "@(#)util.c	8.3 (Berkeley) 4/2/94";
3690153Smarkm#endif /* not lint */
3727967Ssteve#endif
38114583Smarkm#include <sys/cdefs.h>
3999109Sobrien__FBSDID("$FreeBSD$");
401556Srgrimes
411556Srgrimes#include <sys/types.h>
421556Srgrimes#include <sys/stat.h>
431556Srgrimes
441556Srgrimes#include <ctype.h>
4535373Sdes#include <err.h>
461556Srgrimes#include <fts.h>
47128823Stjr#include <limits.h>
481556Srgrimes#include <stdio.h>
491556Srgrimes#include <stdlib.h>
501556Srgrimes#include <string.h>
51128823Stjr#include <wchar.h>
52128823Stjr#include <wctype.h>
531556Srgrimes
541556Srgrimes#include "ls.h"
551556Srgrimes#include "extern.h"
561556Srgrimes
5762597Sassarint
58128823Stjrprn_normal(const char *s)
59128823Stjr{
60128823Stjr	mbstate_t mbs;
61128823Stjr	wchar_t wc;
62128823Stjr	int i, n;
63128823Stjr	size_t clen;
64128823Stjr
65128823Stjr	memset(&mbs, 0, sizeof(mbs));
66128823Stjr	n = 0;
67128823Stjr	while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) {
68128823Stjr		if (clen == (size_t)-2) {
69128823Stjr			n += printf("%s", s);
70128823Stjr			break;
71128823Stjr		}
72128823Stjr		if (clen == (size_t)-1) {
73128823Stjr			memset(&mbs, 0, sizeof(mbs));
74128823Stjr			putchar((unsigned char)*s);
75128823Stjr			s++;
76128823Stjr			n++;
77128823Stjr			continue;
78128823Stjr		}
79128823Stjr		for (i = 0; i < (int)clen; i++)
80128823Stjr			putchar((unsigned char)s[i]);
81128823Stjr		s += clen;
82128868Stjr		if (iswprint(wc))
83128868Stjr			n += wcwidth(wc);
84128823Stjr	}
85128823Stjr	return (n);
86128823Stjr}
87128823Stjr
88128823Stjrint
8990110Simpprn_printable(const char *s)
901556Srgrimes{
91128823Stjr	mbstate_t mbs;
92128823Stjr	wchar_t wc;
93128823Stjr	int i, n;
94128823Stjr	size_t clen;
951556Srgrimes
96128823Stjr	memset(&mbs, 0, sizeof(mbs));
97128823Stjr	n = 0;
98128823Stjr	while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) {
99128823Stjr		if (clen == (size_t)-1) {
10062597Sassar			putchar('?');
101128823Stjr			s++;
102128823Stjr			n++;
103128823Stjr			memset(&mbs, 0, sizeof(mbs));
104128823Stjr			continue;
105128823Stjr		}
106128823Stjr		if (clen == (size_t)-2) {
107128823Stjr			putchar('?');
108128823Stjr			n++;
109128823Stjr			break;
110128823Stjr		}
111128823Stjr		if (!iswprint(wc)) {
112128823Stjr			putchar('?');
113128823Stjr			s += clen;
114128823Stjr			n++;
115128823Stjr			continue;
116128823Stjr		}
117128823Stjr		for (i = 0; i < (int)clen; i++)
118128823Stjr			putchar((unsigned char)s[i]);
119128823Stjr		s += clen;
120128823Stjr		n += wcwidth(wc);
121128823Stjr	}
122128823Stjr	return (n);
1231556Srgrimes}
1241556Srgrimes
12535373Sdes/*
12635373Sdes * The fts system makes it difficult to replace fts_name with a different-
12735373Sdes * sized string, so we just calculate the real length here and do the
12835373Sdes * conversion in prn_octal()
12935417Sdes *
13035417Sdes * XXX when using f_octal_escape (-b) rather than f_octal (-B), the
13135417Sdes * length computed by len_octal may be too big. I just can't be buggered
13235417Sdes * to fix this as an efficient fix would involve a lookup table. Same goes
13335417Sdes * for the rather inelegant code in prn_octal.
13435417Sdes *
135242807Sgrog *						DES 1998/04/23
13635373Sdes */
13735417Sdes
13890150Smarkmsize_t
13990110Simplen_octal(const char *s, int len)
14035373Sdes{
141128823Stjr	mbstate_t mbs;
142128823Stjr	wchar_t wc;
143128823Stjr	size_t clen, r;
14435373Sdes
145128823Stjr	memset(&mbs, 0, sizeof(mbs));
146128823Stjr	r = 0;
147128823Stjr	while (len != 0 && (clen = mbrtowc(&wc, s, len, &mbs)) != 0) {
148128823Stjr		if (clen == (size_t)-1) {
149128823Stjr			r += 4;
150128823Stjr			s++;
151128823Stjr			len--;
152128823Stjr			memset(&mbs, 0, sizeof(mbs));
153128823Stjr			continue;
154128823Stjr		}
155128823Stjr		if (clen == (size_t)-2) {
156128823Stjr			r += 4 * len;
157128823Stjr			break;
158128823Stjr		}
159128823Stjr		if (iswprint(wc))
160128823Stjr			r++;
161128823Stjr		else
162128823Stjr			r += 4 * clen;
163128823Stjr		s += clen;
164128823Stjr	}
165128823Stjr	return (r);
16635373Sdes}
16735373Sdes
16835373Sdesint
16990110Simpprn_octal(const char *s)
17035373Sdes{
171128823Stjr	static const char esc[] = "\\\\\"\"\aa\bb\ff\nn\rr\tt\vv";
172128823Stjr	const char *p;
173128823Stjr	mbstate_t mbs;
174128823Stjr	wchar_t wc;
175128823Stjr	size_t clen;
176128823Stjr	unsigned char ch;
177128823Stjr	int goodchar, i, len, prtlen;
178242725Sgrog
179128823Stjr	memset(&mbs, 0, sizeof(mbs));
180128823Stjr	len = 0;
181128823Stjr	while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) {
182128823Stjr		goodchar = clen != (size_t)-1 && clen != (size_t)-2;
183128823Stjr		if (goodchar && iswprint(wc) && wc != L'\"' && wc != L'\\') {
184128823Stjr			for (i = 0; i < (int)clen; i++)
185128823Stjr				putchar((unsigned char)s[i]);
186128823Stjr			len += wcwidth(wc);
187245091Sandrew		} else if (goodchar && f_octal_escape &&
188245091Sandrew#if WCHAR_MIN < 0
189245091Sandrew                    wc >= 0 &&
190245091Sandrew#endif
191128823Stjr		    wc <= (wchar_t)UCHAR_MAX &&
192128823Stjr		    (p = strchr(esc, (char)wc)) != NULL) {
193128823Stjr			putchar('\\');
194128823Stjr			putchar(p[1]);
195128823Stjr			len += 2;
196128823Stjr		} else {
197128823Stjr			if (goodchar)
198128823Stjr				prtlen = clen;
199128823Stjr			else if (clen == (size_t)-1)
200128823Stjr				prtlen = 1;
201128823Stjr			else
202128823Stjr				prtlen = strlen(s);
203128823Stjr			for (i = 0; i < prtlen; i++) {
204128823Stjr				ch = (unsigned char)s[i];
205128823Stjr				putchar('\\');
206242807Sgrog				putchar('0' + (ch >> 6));
207242807Sgrog				putchar('0' + ((ch >> 3) & 7));
208242807Sgrog				putchar('0' + (ch & 7));
209128823Stjr				len += 4;
210128823Stjr			}
21135417Sdes		}
212128823Stjr		if (clen == (size_t)-2)
213128823Stjr			break;
214128823Stjr		if (clen == (size_t)-1) {
215128823Stjr			memset(&mbs, 0, sizeof(mbs));
216128823Stjr			s++;
217128823Stjr		} else
218128823Stjr			s += clen;
21935373Sdes	}
220128823Stjr	return (len);
22135373Sdes}
22235373Sdes
2231556Srgrimesvoid
22490110Simpusage(void)
2251556Srgrimes{
22661324Sache	(void)fprintf(stderr,
22761324Sache#ifdef COLORLS
228242725Sgrog	"usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
22961324Sache#else
230242725Sgrog	"usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
23161324Sache#endif
23235426Sdes		      " [file ...]\n");
2331556Srgrimes	exit(1);
2341556Srgrimes}
235