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