diff options
Diffstat (limited to '')
-rw-r--r-- | coreutils/cut.c | 455 | ||||
-rw-r--r-- | coreutils/date.c | 2 | ||||
-rw-r--r-- | coreutils/df.c | 33 | ||||
-rw-r--r-- | coreutils/expr.c | 4 | ||||
-rw-r--r-- | coreutils/ls.c | 246 | ||||
-rw-r--r-- | coreutils/md5_sha1_sum.c | 58 | ||||
-rw-r--r-- | coreutils/stty.c | 148 | ||||
-rw-r--r-- | coreutils/truncate.c | 6 |
8 files changed, 661 insertions, 291 deletions
diff --git a/coreutils/cut.c b/coreutils/cut.c index f7b501a46..d81f36bcd 100644 --- a/coreutils/cut.c +++ b/coreutils/cut.c | |||
@@ -27,21 +27,34 @@ | |||
27 | //kbuild:lib-$(CONFIG_CUT) += cut.o | 27 | //kbuild:lib-$(CONFIG_CUT) += cut.o |
28 | 28 | ||
29 | //usage:#define cut_trivial_usage | 29 | //usage:#define cut_trivial_usage |
30 | //usage: "[OPTIONS] [FILE]..." | 30 | //usage: "{-b|c LIST | -f"IF_FEATURE_CUT_REGEX("|F")" LIST [-d SEP] [-s]} [-D] [-O SEP] [FILE]..." |
31 | // --output-delimiter SEP is too long to fit into 80 char-wide help ----------------^^^^^^^^ | ||
31 | //usage:#define cut_full_usage "\n\n" | 32 | //usage:#define cut_full_usage "\n\n" |
32 | //usage: "Print selected fields from FILEs to stdout\n" | 33 | //usage: "Print selected fields from FILEs to stdout\n" |
33 | //usage: "\n -b LIST Output only bytes from LIST" | 34 | //usage: "\n -b LIST Output only bytes from LIST" |
34 | //usage: "\n -c LIST Output only characters from LIST" | 35 | //usage: "\n -c LIST Output only characters from LIST" |
35 | //usage: "\n -d SEP Field delimiter for input (default -f TAB, -F run of whitespace)" | 36 | //usage: IF_FEATURE_CUT_REGEX( |
36 | //usage: "\n -O SEP Field delimeter for output (default = -d for -f, one space for -F)" | 37 | //usage: "\n -d SEP Input field delimiter (default -f TAB, -F run of whitespace)" |
37 | //usage: "\n -D Don't sort/collate sections or match -fF lines without delimeter" | 38 | //usage: ) IF_NOT_FEATURE_CUT_REGEX( |
39 | //usage: "\n -d SEP Input field delimiter (default TAB)" | ||
40 | //usage: ) | ||
38 | //usage: "\n -f LIST Print only these fields (-d is single char)" | 41 | //usage: "\n -f LIST Print only these fields (-d is single char)" |
39 | //usage: IF_FEATURE_CUT_REGEX( | 42 | //usage: IF_FEATURE_CUT_REGEX( |
40 | //usage: "\n -F LIST Print only these fields (-d is regex)" | 43 | //usage: "\n -F LIST Print only these fields (-d is regex)" |
41 | //usage: ) | 44 | //usage: ) |
42 | //usage: "\n -s Output only lines containing delimiter" | 45 | //usage: "\n -s Drop lines with no delimiter (else print them in full)" |
46 | //usage: "\n -D Don't sort ranges; line without delimiters has one field" | ||
47 | //usage: IF_LONG_OPTS( | ||
48 | //usage: "\n --output-delimiter SEP Output field delimeter" | ||
49 | //usage: ) IF_NOT_LONG_OPTS( | ||
50 | //usage: IF_FEATURE_CUT_REGEX( | ||
51 | //usage: "\n -O SEP Output field delimeter (default = -d for -f, one space for -F)" | ||
52 | //usage: ) IF_NOT_FEATURE_CUT_REGEX( | ||
53 | //usage: "\n -O SEP Output field delimeter (default = -d)" | ||
54 | //usage: ) | ||
55 | //usage: ) | ||
43 | //usage: "\n -n Ignored" | 56 | //usage: "\n -n Ignored" |
44 | //(manpage:-n with -b: don't split multibyte characters) | 57 | //(manpage:-n with -b: don't split multibyte characters) |
45 | //usage: | 58 | //usage: |
46 | //usage:#define cut_example_usage | 59 | //usage:#define cut_example_usage |
47 | //usage: "$ echo \"Hello world\" | cut -f 1 -d ' '\n" | 60 | //usage: "$ echo \"Hello world\" | cut -f 1 -d ' '\n" |
@@ -53,11 +66,6 @@ | |||
53 | 66 | ||
54 | #if ENABLE_FEATURE_CUT_REGEX | 67 | #if ENABLE_FEATURE_CUT_REGEX |
55 | #include "xregex.h" | 68 | #include "xregex.h" |
56 | #else | ||
57 | #define regex_t int | ||
58 | typedef struct { int rm_eo, rm_so; } regmatch_t; | ||
59 | #define xregcomp(x, ...) *(x) = 0 | ||
60 | #define regexec(...) 0 | ||
61 | #endif | 69 | #endif |
62 | 70 | ||
63 | /* This is a NOEXEC applet. Be very careful! */ | 71 | /* This is a NOEXEC applet. Be very careful! */ |
@@ -65,265 +73,346 @@ typedef struct { int rm_eo, rm_so; } regmatch_t; | |||
65 | 73 | ||
66 | /* option vars */ | 74 | /* option vars */ |
67 | #define OPT_STR "b:c:f:d:O:sD"IF_FEATURE_CUT_REGEX("F:")"n" | 75 | #define OPT_STR "b:c:f:d:O:sD"IF_FEATURE_CUT_REGEX("F:")"n" |
68 | #define CUT_OPT_BYTE_FLGS (1 << 0) | 76 | #define OPT_BYTE (1 << 0) |
69 | #define CUT_OPT_CHAR_FLGS (1 << 1) | 77 | #define OPT_CHAR (1 << 1) |
70 | #define CUT_OPT_FIELDS_FLGS (1 << 2) | 78 | #define OPT_FIELDS (1 << 2) |
71 | #define CUT_OPT_DELIM_FLGS (1 << 3) | 79 | #define OPT_DELIM (1 << 3) |
72 | #define CUT_OPT_ODELIM_FLGS (1 << 4) | 80 | #define OPT_ODELIM (1 << 4) |
73 | #define CUT_OPT_SUPPRESS_FLGS (1 << 5) | 81 | #define OPT_SUPPRESS (1 << 5) |
74 | #define CUT_OPT_NOSORT_FLGS (1 << 6) | 82 | #define OPT_NOSORT (1 << 6) |
75 | #define CUT_OPT_REGEX_FLGS ((1 << 7) * ENABLE_FEATURE_CUT_REGEX) | 83 | #define OPT_REGEX ((1 << 7) * ENABLE_FEATURE_CUT_REGEX) |
76 | 84 | ||
77 | struct cut_list { | 85 | #define opt_REGEX (option_mask32 & OPT_REGEX) |
78 | int startpos; | 86 | |
79 | int endpos; | 87 | struct cut_range { |
88 | unsigned startpos; | ||
89 | unsigned endpos; | ||
80 | }; | 90 | }; |
81 | 91 | ||
82 | static int cmpfunc(const void *a, const void *b) | 92 | static int cmpfunc(const void *a, const void *b) |
83 | { | 93 | { |
84 | return (((struct cut_list *) a)->startpos - | 94 | const struct cut_range *aa = a; |
85 | ((struct cut_list *) b)->startpos); | 95 | const struct cut_range *bb = b; |
96 | return aa->startpos - bb->startpos; | ||
86 | } | 97 | } |
87 | 98 | ||
99 | #define END_OF_LIST(list_elem) ((list_elem).startpos == UINT_MAX) | ||
100 | #define NOT_END_OF_LIST(list_elem) ((list_elem).startpos != UINT_MAX) | ||
101 | |||
88 | static void cut_file(FILE *file, const char *delim, const char *odelim, | 102 | static void cut_file(FILE *file, const char *delim, const char *odelim, |
89 | const struct cut_list *cut_lists, unsigned nlists) | 103 | const struct cut_range *cut_list) |
90 | { | 104 | { |
91 | char *line; | 105 | char *line; |
92 | unsigned linenum = 0; /* keep these zero-based to be consistent */ | 106 | unsigned linenum = 0; /* keep these zero-based to be consistent */ |
93 | regex_t reg; | 107 | int first_print = 1; |
94 | int spos, shoe = option_mask32 & CUT_OPT_REGEX_FLGS; | ||
95 | |||
96 | if (shoe) xregcomp(®, delim, REG_EXTENDED); | ||
97 | 108 | ||
98 | /* go through every line in the file */ | 109 | /* go through every line in the file */ |
99 | while ((line = xmalloc_fgetline(file)) != NULL) { | 110 | while ((line = xmalloc_fgetline(file)) != NULL) { |
100 | 111 | ||
101 | /* set up a list so we can keep track of what's been printed */ | 112 | /* set up a list so we can keep track of what's been printed */ |
102 | int linelen = strlen(line); | 113 | unsigned linelen = strlen(line); |
103 | char *printed = xzalloc(linelen + 1); | ||
104 | char *orig_line = line; | ||
105 | unsigned cl_pos = 0; | 114 | unsigned cl_pos = 0; |
106 | 115 | ||
107 | /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ | 116 | /* Cut based on chars/bytes XXX: only works when sizeof(char) == byte */ |
108 | if (option_mask32 & (CUT_OPT_CHAR_FLGS | CUT_OPT_BYTE_FLGS)) { | 117 | if (option_mask32 & (OPT_CHAR | OPT_BYTE)) { |
118 | char *printed = xzalloc(linelen + 1); | ||
119 | int need_odelim = 0; | ||
120 | |||
109 | /* print the chars specified in each cut list */ | 121 | /* print the chars specified in each cut list */ |
110 | for (; cl_pos < nlists; cl_pos++) { | 122 | for (; NOT_END_OF_LIST(cut_list[cl_pos]); cl_pos++) { |
111 | for (spos = cut_lists[cl_pos].startpos; spos < linelen;) { | 123 | unsigned spos = cut_list[cl_pos].startpos; |
124 | while (spos < linelen) { | ||
112 | if (!printed[spos]) { | 125 | if (!printed[spos]) { |
113 | printed[spos] = 'X'; | 126 | printed[spos] = 'X'; |
127 | if (need_odelim && spos != 0 && !printed[spos-1]) { | ||
128 | need_odelim = 0; | ||
129 | fputs_stdout(odelim); | ||
130 | } | ||
114 | putchar(line[spos]); | 131 | putchar(line[spos]); |
115 | } | 132 | } |
116 | if (++spos > cut_lists[cl_pos].endpos) { | 133 | spos++; |
134 | if (spos > cut_list[cl_pos].endpos) { | ||
135 | /* will print OSEP (if not empty) */ | ||
136 | need_odelim = (odelim && odelim[0]); | ||
117 | break; | 137 | break; |
118 | } | 138 | } |
119 | } | 139 | } |
120 | } | 140 | } |
121 | } else if (*delim == '\n') { /* cut by lines */ | 141 | free(printed); |
122 | spos = cut_lists[cl_pos].startpos; | 142 | /* Cut by lines */ |
143 | } else if (!opt_REGEX && *delim == '\n') { | ||
144 | unsigned spos = cut_list[cl_pos].startpos; | ||
123 | 145 | ||
124 | /* get out if we have no more lists to process or if the lines | 146 | linenum++; |
147 | /* get out if we have no more ranges to process or if the lines | ||
125 | * are lower than what we're interested in */ | 148 | * are lower than what we're interested in */ |
126 | if (((int)linenum < spos) || (cl_pos >= nlists)) | 149 | if (linenum <= spos || END_OF_LIST(cut_list[cl_pos])) |
127 | goto next_line; | 150 | goto next_line; |
128 | 151 | ||
129 | /* if the line we're looking for is lower than the one we were | 152 | /* if the line we're looking for is lower than the one we were |
130 | * passed, it means we displayed it already, so move on */ | 153 | * passed, it means we displayed it already, so move on */ |
131 | while (spos < (int)linenum) { | 154 | while (++spos < linenum) { |
132 | spos++; | ||
133 | /* go to the next list if we're at the end of this one */ | 155 | /* go to the next list if we're at the end of this one */ |
134 | if (spos > cut_lists[cl_pos].endpos) { | 156 | if (spos > cut_list[cl_pos].endpos) { |
135 | cl_pos++; | 157 | cl_pos++; |
136 | /* get out if there's no more lists to process */ | 158 | /* get out if there's no more ranges to process */ |
137 | if (cl_pos >= nlists) | 159 | if (END_OF_LIST(cut_list[cl_pos])) |
138 | goto next_line; | 160 | goto next_line; |
139 | spos = cut_lists[cl_pos].startpos; | 161 | spos = cut_list[cl_pos].startpos; |
140 | /* get out if the current line is lower than the one | 162 | /* get out if the current line is lower than the one |
141 | * we just became interested in */ | 163 | * we just became interested in */ |
142 | if ((int)linenum < spos) | 164 | if (linenum <= spos) |
143 | goto next_line; | 165 | goto next_line; |
144 | } | 166 | } |
145 | } | 167 | } |
146 | 168 | ||
147 | /* If we made it here, it means we've found the line we're | 169 | /* If we made it here, it means we've found the line we're |
148 | * looking for, so print it */ | 170 | * looking for, so print it */ |
149 | puts(line); | 171 | if (first_print) { |
172 | first_print = 0; | ||
173 | fputs_stdout(line); | ||
174 | } else | ||
175 | printf("%s%s", odelim, line); | ||
150 | goto next_line; | 176 | goto next_line; |
151 | } else { /* cut by fields */ | 177 | /* Cut by fields */ |
152 | unsigned uu = 0, start = 0, end = 0, out = 0; | 178 | } else { |
153 | int dcount = 0; | 179 | unsigned next = 0, start = 0, end = 0; |
180 | unsigned dcount = 0; /* we saw Nth delimiter (0 - didn't see any yet) */ | ||
181 | |||
182 | /* Blank line? Check -s (later check for -s does not catch empty lines) */ | ||
183 | if (linelen == 0) { | ||
184 | if (option_mask32 & OPT_SUPPRESS) | ||
185 | goto next_line; | ||
186 | } | ||
187 | |||
188 | if (!odelim) | ||
189 | odelim = "\t"; | ||
190 | first_print = 1; | ||
154 | 191 | ||
155 | #if ENABLE_PLATFORM_MINGW32 | ||
156 | /* An empty line can't contain a delimiter */ | ||
157 | if (linelen == 0 && (option_mask32 & CUT_OPT_SUPPRESS_FLGS)) | ||
158 | goto next_line; | ||
159 | #endif | ||
160 | /* Loop through bytes, finding next delimiter */ | 192 | /* Loop through bytes, finding next delimiter */ |
161 | for (;;) { | 193 | for (;;) { |
162 | /* End of current range? */ | 194 | /* End of current range? */ |
163 | if (end == linelen || dcount > cut_lists[cl_pos].endpos) { | 195 | if (end == linelen || dcount > cut_list[cl_pos].endpos) { |
164 | if (++cl_pos >= nlists) break; | 196 | end_of_range: |
165 | if (option_mask32 & CUT_OPT_NOSORT_FLGS) | 197 | cl_pos++; |
166 | start = dcount = uu = 0; | 198 | if (END_OF_LIST(cut_list[cl_pos])) |
167 | end = 0; | 199 | break; |
200 | if (option_mask32 & OPT_NOSORT) | ||
201 | start = dcount = next = 0; | ||
202 | end = 0; /* (why?) */ | ||
203 | //bb_error_msg("End of current range"); | ||
168 | } | 204 | } |
169 | /* End of current line? */ | 205 | /* End of current line? */ |
170 | if (uu == linelen) { | 206 | if (next == linelen) { |
171 | /* If we've seen no delimiters, check -s */ | 207 | end = linelen; /* print up to end */ |
172 | if (!cl_pos && !dcount && !shoe) { | 208 | /* If we've seen no delimiters, and no -D, check -s */ |
173 | if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) | 209 | if (!(option_mask32 & OPT_NOSORT) && cl_pos == 0 && dcount == 0) { |
210 | if (option_mask32 & OPT_SUPPRESS) | ||
174 | goto next_line; | 211 | goto next_line; |
175 | } else if (dcount < cut_lists[cl_pos].startpos) | 212 | /* else: will print entire line */ |
176 | start = linelen; | 213 | } else if (dcount < cut_list[cl_pos].startpos) { |
177 | end = linelen; | 214 | /* echo 1.2 | cut -d. -f1,3: prints "1", not "1." */ |
215 | //break; | ||
216 | /* ^^^ this fails a case with -D: | ||
217 | * echo 1 2 | cut -DF 1,3,2: | ||
218 | * do not end line processing when didn't find field#3 | ||
219 | */ | ||
220 | //if (option_mask32 & OPT_NOSORT) - no, just do it always | ||
221 | goto end_of_range; | ||
222 | } | ||
223 | //bb_error_msg("End of current line: s:%d e:%d", start, end); | ||
178 | } else { | 224 | } else { |
179 | /* Find next delimiter */ | 225 | /* Find next delimiter */ |
180 | if (shoe) { | 226 | #if ENABLE_FEATURE_CUT_REGEX |
181 | regmatch_t rr = {-1, -1}; | 227 | if (opt_REGEX) { |
182 | 228 | regmatch_t rr; | |
183 | if (!regexec(®, line+uu, 1, &rr, REG_NOTBOL|REG_NOTEOL)) { | 229 | regex_t *reg = (void*) delim; |
184 | end = uu + rr.rm_so; | 230 | |
185 | uu += rr.rm_eo; | 231 | if (regexec(reg, line + next, 1, &rr, REG_NOTBOL|REG_NOTEOL) != 0) { |
186 | } else { | 232 | /* not found, go to "end of line" logic */ |
187 | uu = linelen; | 233 | next = linelen; |
188 | continue; | 234 | continue; |
189 | } | 235 | } |
190 | } else if (line[end = uu++] != *delim) | 236 | end = next + rr.rm_so; |
191 | continue; | 237 | next += (rr.rm_eo ? rr.rm_eo : 1); |
192 | 238 | /* ^^^ advancing by at least 1 prevents infinite loops */ | |
193 | /* Got delimiter. Loop if not yet within range. */ | 239 | /* testcase: echo "no at sign" | cut -d'@*' -F 1- */ |
194 | if (dcount++ < cut_lists[cl_pos].startpos) { | 240 | } else |
195 | start = uu; | 241 | #endif |
242 | { | ||
243 | end = next++; | ||
244 | if (line[end] != *delim) | ||
245 | continue; | ||
246 | } | ||
247 | /* Got delimiter */ | ||
248 | dcount++; | ||
249 | if (dcount <= cut_list[cl_pos].startpos) { | ||
250 | /* Not yet within range - loop */ | ||
251 | start = next; | ||
196 | continue; | 252 | continue; |
197 | } | 253 | } |
254 | /* -F N-M preserves intermediate delimiters: */ | ||
255 | //printf "1 2 3 4 5 6 7\n" | toybox cut -O: -F2,4-6,7 | ||
256 | //2:4 5 6:7 | ||
257 | if (opt_REGEX && dcount <= cut_list[cl_pos].endpos) | ||
258 | continue; | ||
259 | // NB: toybox does the above for -f too, but it's a compatibility bug: | ||
260 | //printf "1 2 3 4 5 6 7 8\n" | toybox cut -d' ' -O: -f2,4-6,7 | ||
261 | //2:4 5 6:7 // WRONG! | ||
262 | //printf "1 2 3 4 5 6 7 8\n" | cut -d' ' --output-delimiter=: -f2,4-6,7 | ||
263 | //2:4:5:6:7 // GNU coreutils 9.1 | ||
198 | } | 264 | } |
199 | if (end != start || !shoe) | 265 | #if ENABLE_FEATURE_CUT_REGEX |
200 | printf("%s%.*s", out++ ? odelim : "", end-start, line + start); | 266 | if (end != start || !opt_REGEX) |
201 | start = uu; | 267 | #endif |
202 | if (!dcount) | 268 | { |
203 | break; | 269 | if (first_print) { |
204 | } | 270 | first_print = 0; |
271 | printf("%.*s", end - start, line + start); | ||
272 | } else | ||
273 | printf("%s%.*s", odelim, end - start, line + start); | ||
274 | } | ||
275 | start = next; | ||
276 | //if (dcount == 0) | ||
277 | // break; - why? | ||
278 | } /* byte loop */ | ||
205 | } | 279 | } |
206 | /* if we printed anything, finish with newline */ | 280 | /* if we printed anything, finish with newline */ |
207 | putchar('\n'); | 281 | putchar('\n'); |
208 | next_line: | 282 | next_line: |
209 | linenum++; | 283 | free(line); |
210 | free(printed); | 284 | } /* while (got line) */ |
211 | free(orig_line); | 285 | |
212 | } | 286 | /* For -d$'\n' --output-delimiter=^, the overall output is still terminated with \n, not ^ */ |
287 | if (!opt_REGEX && *delim == '\n' && !first_print) | ||
288 | putchar('\n'); | ||
213 | } | 289 | } |
214 | 290 | ||
215 | int cut_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 291 | int cut_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
216 | int cut_main(int argc UNUSED_PARAM, char **argv) | 292 | int cut_main(int argc UNUSED_PARAM, char **argv) |
217 | { | 293 | { |
218 | /* growable array holding a series of lists */ | 294 | /* growable array holding a series of ranges */ |
219 | struct cut_list *cut_lists = NULL; | 295 | struct cut_range *cut_list = NULL; |
220 | unsigned nlists = 0; /* number of elements in above list */ | 296 | unsigned nranges = 0; /* number of elements in above list */ |
221 | char *sopt, *ltok; | 297 | char *LIST, *ltok; |
222 | const char *delim = NULL; | 298 | const char *delim = NULL; |
223 | const char *odelim = NULL; | 299 | const char *odelim = NULL; |
224 | unsigned opt; | 300 | unsigned opt; |
301 | #if ENABLE_FEATURE_CUT_REGEX | ||
302 | regex_t reg; | ||
303 | #endif | ||
304 | #if ENABLE_LONG_OPTS | ||
305 | static const char cut_longopts[] ALIGN1 = | ||
306 | "output-delimiter\0" Required_argument "O" | ||
307 | ; | ||
308 | #endif | ||
225 | 309 | ||
226 | #define ARG "bcf"IF_FEATURE_CUT_REGEX("F") | 310 | #define ARG "bcf"IF_FEATURE_CUT_REGEX("F") |
227 | opt = getopt32(argv, "^" | 311 | #if ENABLE_LONG_OPTS |
312 | opt = getopt32long | ||
313 | #else | ||
314 | opt = getopt32 | ||
315 | #endif | ||
316 | (argv, "^" | ||
228 | OPT_STR // = "b:c:f:d:O:sD"IF_FEATURE_CUT_REGEX("F:")"n" | 317 | OPT_STR // = "b:c:f:d:O:sD"IF_FEATURE_CUT_REGEX("F:")"n" |
229 | "\0" "b--"ARG":c--"ARG":f--"ARG IF_FEATURE_CUT_REGEX("F--"ARG), | 318 | "\0" "b:c:f:" IF_FEATURE_CUT_REGEX("F:") /* one of -bcfF is required */ |
230 | &sopt, &sopt, &sopt, &delim, &odelim IF_FEATURE_CUT_REGEX(, &sopt) | 319 | "b--"ARG":c--"ARG":f--"ARG IF_FEATURE_CUT_REGEX(":F--"ARG), /* they are mutually exclusive */ |
231 | ); | 320 | IF_LONG_OPTS(cut_longopts,) |
232 | if (!delim || !*delim) | 321 | &LIST, &LIST, &LIST, &delim, &odelim IF_FEATURE_CUT_REGEX(, &LIST) |
233 | delim = (opt & CUT_OPT_REGEX_FLGS) ? "[[:space:]]+" : "\t"; | 322 | ); |
234 | if (!odelim) odelim = (opt & CUT_OPT_REGEX_FLGS) ? " " : delim; | 323 | if (!odelim) |
324 | odelim = (opt & OPT_REGEX) ? " " : delim; | ||
325 | if (!delim) | ||
326 | delim = (opt & OPT_REGEX) ? "[[:space:]]+" : "\t"; | ||
235 | 327 | ||
236 | // argc -= optind; | 328 | // argc -= optind; |
237 | argv += optind; | 329 | argv += optind; |
238 | if (!(opt & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS | CUT_OPT_REGEX_FLGS))) | 330 | //if (!(opt & (OPT_BYTE | OPT_CHAR | OPT_FIELDS | OPT_REGEX))) |
239 | bb_simple_error_msg_and_die("expected a list of bytes, characters, or fields"); | 331 | // bb_simple_error_msg_and_die("expected a list of bytes, characters, or fields"); |
240 | 332 | //^^^ handled by getopt32 | |
241 | /* non-field (char or byte) cutting has some special handling */ | 333 | |
242 | if (!(opt & (CUT_OPT_FIELDS_FLGS|CUT_OPT_REGEX_FLGS))) { | 334 | /* non-field (char or byte) cutting has some special handling */ |
243 | static const char _op_on_field[] ALIGN1 = " only when operating on fields"; | 335 | if (!(opt & (OPT_FIELDS|OPT_REGEX))) { |
244 | 336 | static const char requires_f[] ALIGN1 = " requires -f" | |
245 | if (opt & CUT_OPT_SUPPRESS_FLGS) { | 337 | IF_FEATURE_CUT_REGEX(" or -F"); |
246 | bb_error_msg_and_die | 338 | if (opt & OPT_SUPPRESS) |
247 | ("suppressing non-delimited lines makes sense%s", _op_on_field); | 339 | bb_error_msg_and_die("-s%s", requires_f); |
248 | } | 340 | if (opt & OPT_DELIM) |
249 | if (opt & CUT_OPT_DELIM_FLGS) { | 341 | bb_error_msg_and_die("-d DELIM%s", requires_f); |
250 | bb_error_msg_and_die | ||
251 | ("a delimiter may be specified%s", _op_on_field); | ||
252 | } | ||
253 | } | 342 | } |
254 | 343 | ||
255 | /* | 344 | /* |
256 | * parse list and put values into startpos and endpos. | 345 | * parse list and put values into startpos and endpos. |
257 | * valid list formats: N, N-, N-M, -M | 346 | * valid range formats: N, N-, N-M, -M |
258 | * more than one list can be separated by commas | 347 | * more than one range can be separated by commas |
259 | */ | 348 | */ |
260 | { | 349 | /* take apart the ranges, one by one (separated with commas) */ |
350 | while ((ltok = strsep(&LIST, ",")) != NULL) { | ||
261 | char *ntok; | 351 | char *ntok; |
262 | int s = 0, e = 0; | 352 | int s, e; |
263 | 353 | ||
264 | /* take apart the lists, one by one (they are separated with commas) */ | 354 | /* it's actually legal to pass an empty list */ |
265 | while ((ltok = strsep(&sopt, ",")) != NULL) { | 355 | //if (!ltok[0]) |
356 | // continue; | ||
357 | //^^^ testcase? | ||
358 | |||
359 | /* get the start pos */ | ||
360 | ntok = strsep(<ok, "-"); | ||
361 | if (!ntok[0]) { | ||
362 | if (!ltok) /* testcase: -f '' */ | ||
363 | bb_show_usage(); | ||
364 | if (!ltok[0]) /* testcase: -f - */ | ||
365 | bb_show_usage(); | ||
366 | s = 0; /* "-M" means "1-M" */ | ||
367 | } else { | ||
368 | /* "N" or "N-[M]" */ | ||
369 | /* arrays are zero based, while the user expects | ||
370 | * the first field/char on the line to be char #1 */ | ||
371 | s = xatoi_positive(ntok) - 1; | ||
372 | } | ||
266 | 373 | ||
267 | /* it's actually legal to pass an empty list */ | 374 | /* get the end pos */ |
268 | if (!ltok[0]) | 375 | if (!ltok) { |
269 | continue; | 376 | e = s; /* "N" means "N-N" */ |
377 | } else if (!ltok[0]) { | ||
378 | /* "N-" means "until the end of the line" */ | ||
379 | e = INT_MAX; | ||
380 | } else { | ||
381 | /* again, arrays are zero based, fields are 1 based */ | ||
382 | e = xatoi_positive(ltok) - 1; | ||
383 | } | ||
270 | 384 | ||
271 | /* get the start pos */ | 385 | if (s < 0 || e < s) |
272 | ntok = strsep(<ok, "-"); | 386 | bb_error_msg_and_die("invalid range %s-%s", ntok, ltok ?: ntok); |
273 | if (!ntok[0]) { | ||
274 | s = 0; | ||
275 | } else { | ||
276 | s = xatoi_positive(ntok); | ||
277 | /* account for the fact that arrays are zero based, while | ||
278 | * the user expects the first char on the line to be char #1 */ | ||
279 | #if !ENABLE_PLATFORM_MINGW32 | ||
280 | if (s != 0) | ||
281 | s--; | ||
282 | #else | ||
283 | s--; | ||
284 | #endif | ||
285 | } | ||
286 | 387 | ||
287 | /* get the end pos */ | 388 | /* add the new range */ |
288 | if (ltok == NULL) { | 389 | cut_list = xrealloc_vector(cut_list, 4, nranges); |
289 | e = s; | 390 | /* NB: s is always >= 0 */ |
290 | } else if (!ltok[0]) { | 391 | cut_list[nranges].startpos = s; |
291 | e = INT_MAX; | 392 | cut_list[nranges].endpos = e; |
292 | } else { | 393 | nranges++; |
293 | e = xatoi_positive(ltok); | 394 | } |
294 | /* if the user specified no end position, | 395 | cut_list[nranges].startpos = UINT_MAX; /* end indicator */ |
295 | * that means "til the end of the line" */ | ||
296 | #if !ENABLE_PLATFORM_MINGW32 | ||
297 | if (!*ltok) | ||
298 | e = INT_MAX; | ||
299 | else if (e < s) | ||
300 | bb_error_msg_and_die("%d<%d", e, s); | ||
301 | #endif | ||
302 | e--; /* again, arrays are zero based, lines are 1 based */ | ||
303 | } | ||
304 | #if ENABLE_PLATFORM_MINGW32 | ||
305 | if (s < 0 || e < s) | ||
306 | bb_error_msg_and_die("invalid range %s-%s", ntok, ltok ?: ntok); | ||
307 | #endif | ||
308 | 396 | ||
309 | /* add the new list */ | 397 | /* make sure we got some cut positions out of all that */ |
310 | cut_lists = xrealloc_vector(cut_lists, 4, nlists); | 398 | //if (nranges == 0) |
311 | /* NB: startpos is always >= 0 */ | 399 | // bb_simple_error_msg_and_die("missing list of positions"); |
312 | cut_lists[nlists].startpos = s; | 400 | //^^^ this is impossible since one of -bcfF is required, |
313 | cut_lists[nlists].endpos = e; | 401 | // they populate LIST with non-NULL string and when it is parsed, |
314 | nlists++; | 402 | // cut_list[] gets at least one element. |
315 | } | ||
316 | 403 | ||
317 | /* make sure we got some cut positions out of all that */ | 404 | /* now that the lists are parsed, we need to sort them to make life |
318 | if (nlists == 0) | 405 | * easier on us when it comes time to print the chars / fields / lines |
319 | bb_simple_error_msg_and_die("missing list of positions"); | 406 | */ |
407 | if (!(opt & OPT_NOSORT)) | ||
408 | qsort(cut_list, nranges, sizeof(cut_list[0]), cmpfunc); | ||
320 | 409 | ||
321 | /* now that the lists are parsed, we need to sort them to make life | 410 | #if ENABLE_FEATURE_CUT_REGEX |
322 | * easier on us when it comes time to print the chars / fields / lines | 411 | if (opt & OPT_REGEX) { |
323 | */ | 412 | xregcomp(®, delim, REG_EXTENDED); |
324 | if (!(opt & CUT_OPT_NOSORT_FLGS)) | 413 | delim = (void*) ® |
325 | qsort(cut_lists, nlists, sizeof(cut_lists[0]), cmpfunc); | ||
326 | } | 414 | } |
415 | #endif | ||
327 | 416 | ||
328 | { | 417 | { |
329 | exitcode_t retval = EXIT_SUCCESS; | 418 | exitcode_t retval = EXIT_SUCCESS; |
@@ -337,12 +426,12 @@ int cut_main(int argc UNUSED_PARAM, char **argv) | |||
337 | retval = EXIT_FAILURE; | 426 | retval = EXIT_FAILURE; |
338 | continue; | 427 | continue; |
339 | } | 428 | } |
340 | cut_file(file, delim, odelim, cut_lists, nlists); | 429 | cut_file(file, delim, odelim, cut_list); |
341 | fclose_if_not_stdin(file); | 430 | fclose_if_not_stdin(file); |
342 | } while (*++argv); | 431 | } while (*++argv); |
343 | 432 | ||
344 | if (ENABLE_FEATURE_CLEAN_UP) | 433 | if (ENABLE_FEATURE_CLEAN_UP) |
345 | free(cut_lists); | 434 | free(cut_list); |
346 | fflush_stdout_and_exit(retval); | 435 | fflush_stdout_and_exit(retval); |
347 | } | 436 | } |
348 | } | 437 | } |
diff --git a/coreutils/date.c b/coreutils/date.c index 3a89b6caf..ef482af1b 100644 --- a/coreutils/date.c +++ b/coreutils/date.c | |||
@@ -289,7 +289,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
289 | 289 | ||
290 | /* if setting time, set it */ | 290 | /* if setting time, set it */ |
291 | if ((opt & OPT_SET) && clock_settime(CLOCK_REALTIME, &ts) < 0) { | 291 | if ((opt & OPT_SET) && clock_settime(CLOCK_REALTIME, &ts) < 0) { |
292 | bb_simple_perror_msg("can't set date"); | 292 | bb_simple_perror_msg_and_die("can't set date"); |
293 | } | 293 | } |
294 | } | 294 | } |
295 | 295 | ||
diff --git a/coreutils/df.c b/coreutils/df.c index 03aa78148..01c41db38 100644 --- a/coreutils/df.c +++ b/coreutils/df.c | |||
@@ -64,7 +64,9 @@ | |||
64 | //usage: "[-Pk" | 64 | //usage: "[-Pk" |
65 | //usage: IF_FEATURE_HUMAN_READABLE("mh") | 65 | //usage: IF_FEATURE_HUMAN_READABLE("mh") |
66 | //usage: "T" | 66 | //usage: "T" |
67 | //usage: IF_FEATURE_DF_FANCY("ai] [-B SIZE") | 67 | //usage: IF_FEATURE_DF_FANCY("a" |
68 | //usage: IF_PLATFORM_POSIX("i") | ||
69 | //usage: "] [-B SIZE") | ||
68 | //usage: "] [-t TYPE] [FILESYSTEM]..." | 70 | //usage: "] [-t TYPE] [FILESYSTEM]..." |
69 | //usage:#define df_full_usage "\n\n" | 71 | //usage:#define df_full_usage "\n\n" |
70 | //usage: "Print filesystem usage statistics\n" | 72 | //usage: "Print filesystem usage statistics\n" |
@@ -78,7 +80,9 @@ | |||
78 | //usage: "\n -t TYPE Print only mounts of this type" | 80 | //usage: "\n -t TYPE Print only mounts of this type" |
79 | //usage: IF_FEATURE_DF_FANCY( | 81 | //usage: IF_FEATURE_DF_FANCY( |
80 | //usage: "\n -a Show all filesystems" | 82 | //usage: "\n -a Show all filesystems" |
83 | //usage: IF_PLATFORM_POSIX( | ||
81 | //usage: "\n -i Inodes" | 84 | //usage: "\n -i Inodes" |
85 | //usage: ) | ||
82 | //usage: "\n -B SIZE Blocksize" | 86 | //usage: "\n -B SIZE Blocksize" |
83 | //usage: ) | 87 | //usage: ) |
84 | //usage: | 88 | //usage: |
@@ -109,6 +113,12 @@ static unsigned long kscale(unsigned long b, unsigned long bs) | |||
109 | } | 113 | } |
110 | #endif | 114 | #endif |
111 | 115 | ||
116 | #if ENABLE_PLATFORM_MINGW32 | ||
117 | # define ENABLE_FEATURE_DF_FANCY_POSIX 0 | ||
118 | #else | ||
119 | # define ENABLE_FEATURE_DF_FANCY_POSIX ENABLE_FEATURE_DF_FANCY | ||
120 | #endif | ||
121 | |||
112 | int df_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 122 | int df_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
113 | int df_main(int argc UNUSED_PARAM, char **argv) | 123 | int df_main(int argc UNUSED_PARAM, char **argv) |
114 | { | 124 | { |
@@ -124,11 +134,11 @@ int df_main(int argc UNUSED_PARAM, char **argv) | |||
124 | OPT_FSTYPE = (1 << 2), | 134 | OPT_FSTYPE = (1 << 2), |
125 | OPT_t = (1 << 3), | 135 | OPT_t = (1 << 3), |
126 | OPT_ALL = (1 << 4) * ENABLE_FEATURE_DF_FANCY, | 136 | OPT_ALL = (1 << 4) * ENABLE_FEATURE_DF_FANCY, |
127 | OPT_INODE = (1 << 5) * ENABLE_FEATURE_DF_FANCY, | 137 | OPT_INODE = (1 << 5) * ENABLE_FEATURE_DF_FANCY_POSIX, |
128 | OPT_BSIZE = (1 << 6) * ENABLE_FEATURE_DF_FANCY, | 138 | OPT_BSIZE = (1 << (5 + ENABLE_FEATURE_DF_FANCY_POSIX)) * ENABLE_FEATURE_DF_FANCY, |
129 | OPT_HUMAN = (1 << (4 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, | 139 | OPT_HUMAN = (1 << (4 + 2*ENABLE_FEATURE_DF_FANCY + ENABLE_FEATURE_DF_FANCY_POSIX)) * ENABLE_FEATURE_HUMAN_READABLE, |
130 | OPT_HUMANDEC = (1 << (5 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, | 140 | OPT_HUMANDEC = (1 << (5 + 2*ENABLE_FEATURE_DF_FANCY + ENABLE_FEATURE_DF_FANCY_POSIX)) * ENABLE_FEATURE_HUMAN_READABLE, |
131 | OPT_MEGA = (1 << (6 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, | 141 | OPT_MEGA = (1 << (6 + 2*ENABLE_FEATURE_DF_FANCY + ENABLE_FEATURE_DF_FANCY_POSIX)) * ENABLE_FEATURE_HUMAN_READABLE, |
132 | }; | 142 | }; |
133 | const char *disp_units_hdr = NULL; | 143 | const char *disp_units_hdr = NULL; |
134 | char *chp, *opt_t; | 144 | char *chp, *opt_t; |
@@ -144,7 +154,11 @@ int df_main(int argc UNUSED_PARAM, char **argv) | |||
144 | 154 | ||
145 | opt = getopt32(argv, "^" | 155 | opt = getopt32(argv, "^" |
146 | "kPTt:" | 156 | "kPTt:" |
157 | #if ENABLE_PLATFORM_POSIX | ||
147 | IF_FEATURE_DF_FANCY("aiB:") | 158 | IF_FEATURE_DF_FANCY("aiB:") |
159 | #else | ||
160 | IF_FEATURE_DF_FANCY("aB:") | ||
161 | #endif | ||
148 | IF_FEATURE_HUMAN_READABLE("hHm") | 162 | IF_FEATURE_HUMAN_READABLE("hHm") |
149 | "\0" | 163 | "\0" |
150 | #if ENABLE_FEATURE_HUMAN_READABLE && ENABLE_FEATURE_DF_FANCY | 164 | #if ENABLE_FEATURE_HUMAN_READABLE && ENABLE_FEATURE_DF_FANCY |
@@ -155,6 +169,9 @@ int df_main(int argc UNUSED_PARAM, char **argv) | |||
155 | , &opt_t | 169 | , &opt_t |
156 | IF_FEATURE_DF_FANCY(, &chp) | 170 | IF_FEATURE_DF_FANCY(, &chp) |
157 | ); | 171 | ); |
172 | /* -k overrides $POSIXLY_CORRECT: */ | ||
173 | if (opt & OPT_KILO) | ||
174 | df_disp_hr = 1024; | ||
158 | if (opt & OPT_MEGA) | 175 | if (opt & OPT_MEGA) |
159 | df_disp_hr = 1024*1024; | 176 | df_disp_hr = 1024*1024; |
160 | 177 | ||
@@ -185,8 +202,8 @@ int df_main(int argc UNUSED_PARAM, char **argv) | |||
185 | if (disp_units_hdr == NULL) { | 202 | if (disp_units_hdr == NULL) { |
186 | #if ENABLE_FEATURE_HUMAN_READABLE | 203 | #if ENABLE_FEATURE_HUMAN_READABLE |
187 | disp_units_hdr = xasprintf("%s-blocks", | 204 | disp_units_hdr = xasprintf("%s-blocks", |
188 | /* print df_disp_hr, show no fractionals, | 205 | /* print df_disp_hr; show no fractionals; |
189 | * use suffixes if OPT_POSIX is set in opt */ | 206 | * if -P, unit=1 (print it in full, no KMG suffixes) */ |
190 | make_human_readable_str(df_disp_hr, 0, !!(opt & OPT_POSIX)) | 207 | make_human_readable_str(df_disp_hr, 0, !!(opt & OPT_POSIX)) |
191 | ); | 208 | ); |
192 | #else | 209 | #else |
diff --git a/coreutils/expr.c b/coreutils/expr.c index 3f7e21871..c00559e4c 100644 --- a/coreutils/expr.c +++ b/coreutils/expr.c | |||
@@ -97,6 +97,10 @@ typedef long arith_t; | |||
97 | 97 | ||
98 | /* TODO: use bb_strtol[l]? It's easier to check for errors... */ | 98 | /* TODO: use bb_strtol[l]? It's easier to check for errors... */ |
99 | 99 | ||
100 | #if ENABLE_PLATFORM_MINGW32 | ||
101 | # define STRING BB_STRING | ||
102 | #endif | ||
103 | |||
100 | /* The kinds of value we can have. */ | 104 | /* The kinds of value we can have. */ |
101 | enum { | 105 | enum { |
102 | INTEGER, | 106 | INTEGER, |
diff --git a/coreutils/ls.c b/coreutils/ls.c index 5d2e96a1e..2153554e8 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c | |||
@@ -129,6 +129,8 @@ | |||
129 | //usage: "\n -F Append indicator (one of */=@|) to names" | 129 | //usage: "\n -F Append indicator (one of */=@|) to names" |
130 | //usage: ) | 130 | //usage: ) |
131 | //usage: "\n -l Long format" | 131 | //usage: "\n -l Long format" |
132 | ////usage: "\n -g Long format without group column" | ||
133 | ////TODO: support -G too ("suppress owner column", GNUism) | ||
132 | //usage: "\n -i List inode numbers" | 134 | //usage: "\n -i List inode numbers" |
133 | //usage: "\n -n List numeric UIDs and GIDs instead of names" | 135 | //usage: "\n -n List numeric UIDs and GIDs instead of names" |
134 | //usage: "\n -s List allocated blocks" | 136 | //usage: "\n -s List allocated blocks" |
@@ -162,6 +164,8 @@ | |||
162 | //usage: IF_FEATURE_LS_WIDTH( | 164 | //usage: IF_FEATURE_LS_WIDTH( |
163 | //usage: "\n -w N Format N columns wide" | 165 | //usage: "\n -w N Format N columns wide" |
164 | //usage: ) | 166 | //usage: ) |
167 | ////usage: "\n -Q Double-quote names" | ||
168 | ////usage: "\n -q Replace unprintable chars with '?'" | ||
165 | //usage: IF_FEATURE_LS_COLOR( | 169 | //usage: IF_FEATURE_LS_COLOR( |
166 | //usage: "\n --color[={always,never,auto}]" | 170 | //usage: "\n --color[={always,never,auto}]" |
167 | //usage: ) | 171 | //usage: ) |
@@ -199,27 +203,47 @@ SPLIT_SUBDIR = 2, | |||
199 | 203 | ||
200 | /* -Cadi1l Std options, busybox always supports */ | 204 | /* -Cadi1l Std options, busybox always supports */ |
201 | /* -gnsxA Std options, busybox always supports */ | 205 | /* -gnsxA Std options, busybox always supports */ |
202 | /* -Q GNU option, busybox always supports */ | 206 | /* -Q GNU option, busybox always supports: */ |
203 | /* -k Std option, busybox always supports (by ignoring) */ | 207 | /* -Q, --quote-name */ |
204 | /* It means "for -s, show sizes in kbytes" */ | 208 | /* enclose entry names in double quotes */ |
205 | /* Seems to only affect "POSIXLY_CORRECT=1 ls -sk" */ | ||
206 | /* since otherwise -s shows kbytes anyway */ | ||
207 | /* -LHRctur Std options, busybox optionally supports */ | 209 | /* -LHRctur Std options, busybox optionally supports */ |
208 | /* -Fp Std options, busybox optionally supports */ | 210 | /* -Fp Std options, busybox optionally supports */ |
209 | /* -SXvhTw GNU options, busybox optionally supports */ | 211 | /* -SXvhTw GNU options, busybox optionally supports */ |
210 | /* -T WIDTH Ignored (we don't use tabs on output) */ | 212 | /* -T WIDTH Ignored (we don't use tabs on output) */ |
211 | /* -Z SELinux mandated option, busybox optionally supports */ | 213 | /* -Z SELinux mandated option, busybox optionally supports */ |
214 | /* -q Std option, busybox always supports: */ | ||
215 | /* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html: */ | ||
216 | /* Force each instance of non-printable filename characters and */ | ||
217 | /* <tab> characters to be written as the <question-mark> ('?') */ | ||
218 | /* character. Implementations may provide this option by default */ | ||
219 | /* if the output is to a terminal device. */ | ||
220 | /* -k Std option, busybox always supports (by ignoring) */ | ||
221 | /* It means "for -s, show sizes in kbytes" */ | ||
222 | /* Seems to only affect "POSIXLY_CORRECT=1 ls -sk" */ | ||
223 | /* since otherwise -s shows kbytes anyway */ | ||
212 | #define ls_options \ | 224 | #define ls_options \ |
213 | "Cadi1lgnsxAk" /* 12 opts, total 12 */ \ | 225 | "Cadi1lgnsxA" /* 11 opts, total 11 */ \ |
214 | IF_FEATURE_LS_FILETYPES("Fp") /* 2, 14 */ \ | 226 | IF_FEATURE_LS_FILETYPES("Fp") /* 2, 13 */ \ |
215 | IF_FEATURE_LS_RECURSIVE("R") /* 1, 15 */ \ | 227 | IF_FEATURE_LS_RECURSIVE("R") /* 1, 14 */ \ |
216 | IF_SELINUX("Z") /* 1, 16 */ \ | 228 | IF_SELINUX("Z") /* 1, 15 */ \ |
217 | "Q" /* 1, 17 */ \ | 229 | "Q" /* 1, 16 */ \ |
218 | IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 20 */ \ | 230 | IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 19 */ \ |
219 | IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 24 */ \ | 231 | IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 23 */ \ |
220 | IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 26 */ \ | 232 | IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 25 */ \ |
221 | IF_FEATURE_HUMAN_READABLE("h") /* 1, 27 */ \ | 233 | IF_FEATURE_HUMAN_READABLE("h") /* 1, 26 */ \ |
222 | IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */ | 234 | IF_FEATURE_LS_WIDTH("T:w:") /* 2, 28 */ \ |
235 | IF_LONG_OPTS("\xff") /* 1, 29 */ \ | ||
236 | IF_LONG_OPTS("\xfe") /* 1, 30 */ \ | ||
237 | IF_LONG_OPTS("\xfd") /* 1, 31 */ \ | ||
238 | "qk" /* 2, 33 */ | ||
239 | |||
240 | #if ENABLE_LONG_OPTS | ||
241 | static const char ls_longopts[] ALIGN1 = | ||
242 | "full-time\0" No_argument "\xff" | ||
243 | "group-directories-first\0" No_argument "\xfe" | ||
244 | IF_FEATURE_LS_COLOR("color\0" Optional_argument "\xfd") | ||
245 | ; | ||
246 | #endif | ||
223 | 247 | ||
224 | enum { | 248 | enum { |
225 | OPT_C = (1 << 0), | 249 | OPT_C = (1 << 0), |
@@ -233,29 +257,31 @@ enum { | |||
233 | OPT_s = (1 << 8), | 257 | OPT_s = (1 << 8), |
234 | OPT_x = (1 << 9), | 258 | OPT_x = (1 << 9), |
235 | OPT_A = (1 << 10), | 259 | OPT_A = (1 << 10), |
236 | //OPT_k = (1 << 11), | ||
237 | 260 | ||
238 | OPTBIT_F = 12, | 261 | OPTBIT_F = 11, |
239 | OPTBIT_p, /* 13 */ | 262 | OPTBIT_p, /* 12 */ |
240 | OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES, | 263 | OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES, |
241 | OPTBIT_Z = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE, | 264 | OPTBIT_Z = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE, |
242 | OPTBIT_Q = OPTBIT_Z + 1 * ENABLE_SELINUX, | 265 | OPTBIT_Q = OPTBIT_Z + 1 * ENABLE_SELINUX, |
243 | OPTBIT_c, /* 17 */ | 266 | OPTBIT_c, /* 16 */ |
244 | OPTBIT_t, /* 18 */ | 267 | OPTBIT_t, /* 17 */ |
245 | OPTBIT_u, /* 19 */ | 268 | OPTBIT_u, /* 18 */ |
246 | OPTBIT_S = OPTBIT_c + 3 * ENABLE_FEATURE_LS_TIMESTAMPS, | 269 | OPTBIT_S = OPTBIT_c + 3 * ENABLE_FEATURE_LS_TIMESTAMPS, |
247 | OPTBIT_X, /* 21 */ | 270 | OPTBIT_X, /* 20 */ |
248 | OPTBIT_r, /* 22 */ | 271 | OPTBIT_r, /* 21 */ |
249 | OPTBIT_v, /* 23 */ | 272 | OPTBIT_v, /* 22 */ |
250 | OPTBIT_L = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES, | 273 | OPTBIT_L = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES, |
251 | OPTBIT_H, /* 25 */ | 274 | OPTBIT_H, /* 24 */ |
252 | OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS, | 275 | OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS, |
253 | OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE, | 276 | OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE, |
254 | OPTBIT_w, /* 28 */ | 277 | OPTBIT_w, /* 27 */ |
255 | OPTBIT_full_time = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH, | 278 | OPTBIT_full_time = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH, |
256 | OPTBIT_dirs_first, | 279 | OPTBIT_dirs_first, |
257 | OPTBIT_color, /* 31 */ | 280 | OPTBIT_color, /* 30 */ |
258 | /* with long opts, we use all 32 bits */ | 281 | OPTBIT_q = OPTBIT_color + 1, /* 31 */ |
282 | OPTBIT_k = OPTBIT_q + 1, /* 32 */ | ||
283 | /* with all options enabled, we use all 32 bits and even one extra bit! */ | ||
284 | /* this works because -k is ignored, and getopt32 allows such "ignore" options past 31th bit */ | ||
259 | 285 | ||
260 | OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES, | 286 | OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES, |
261 | OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES, | 287 | OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES, |
@@ -277,6 +303,8 @@ enum { | |||
277 | OPT_full_time = (1 << OPTBIT_full_time ) * ENABLE_LONG_OPTS, | 303 | OPT_full_time = (1 << OPTBIT_full_time ) * ENABLE_LONG_OPTS, |
278 | OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS, | 304 | OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS, |
279 | OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR, | 305 | OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR, |
306 | OPT_q = (1 << OPTBIT_q), | ||
307 | //-k is ignored: OPT_k = (1 << OPTBIT_k), | ||
280 | }; | 308 | }; |
281 | 309 | ||
282 | /* | 310 | /* |
@@ -333,6 +361,7 @@ struct globals { | |||
333 | #endif | 361 | #endif |
334 | smallint exit_code; | 362 | smallint exit_code; |
335 | smallint show_dirname; | 363 | smallint show_dirname; |
364 | smallint tty_out; | ||
336 | #if ENABLE_FEATURE_LS_WIDTH | 365 | #if ENABLE_FEATURE_LS_WIDTH |
337 | unsigned terminal_width; | 366 | unsigned terminal_width; |
338 | # define G_terminal_width (G.terminal_width) | 367 | # define G_terminal_width (G.terminal_width) |
@@ -353,16 +382,21 @@ struct globals { | |||
353 | setup_common_bufsiz(); \ | 382 | setup_common_bufsiz(); \ |
354 | /* we have to zero it out because of NOEXEC */ \ | 383 | /* we have to zero it out because of NOEXEC */ \ |
355 | memset(&G, 0, sizeof(G)); \ | 384 | memset(&G, 0, sizeof(G)); \ |
356 | IF_FEATURE_LS_WIDTH(G_terminal_width = TERMINAL_WIDTH;) \ | 385 | IF_FEATURE_LS_WIDTH(G_terminal_width = ~0U;) \ |
357 | IF_FEATURE_LS_TIMESTAMPS(time(&G.current_time_t);) \ | 386 | IF_FEATURE_LS_TIMESTAMPS(time(&G.current_time_t);) \ |
358 | } while (0) | 387 | } while (0) |
359 | 388 | ||
360 | #define ESC "\033" | 389 | #define ESC "\033" |
361 | 390 | ||
391 | static int G_isatty(void) | ||
392 | { | ||
393 | if (!G.tty_out) /* not known yet? */ | ||
394 | G.tty_out = isatty(STDOUT_FILENO) + 1; | ||
395 | return (G.tty_out == 2); | ||
396 | } | ||
362 | 397 | ||
363 | /*** Output code ***/ | 398 | /*** Output code ***/ |
364 | 399 | ||
365 | |||
366 | /* FYI type values: 1:fifo 2:char 4:dir 6:blk 8:file 10:link 12:socket | 400 | /* FYI type values: 1:fifo 2:char 4:dir 6:blk 8:file 10:link 12:socket |
367 | * (various wacky OSes: 13:Sun door 14:BSD whiteout 5:XENIX named file | 401 | * (various wacky OSes: 13:Sun door 14:BSD whiteout 5:XENIX named file |
368 | * 3/7:multiplexed char/block device) | 402 | * 3/7:multiplexed char/block device) |
@@ -425,56 +459,93 @@ static char append_char(mode_t mode) | |||
425 | } | 459 | } |
426 | #endif | 460 | #endif |
427 | 461 | ||
462 | /* Return the number of used columns. | ||
463 | * Note that only columnar output uses return value. | ||
464 | * -l and -1 modes don't care. | ||
465 | * coreutils 7.2 also supports: | ||
466 | * ls -b (--escape) = octal escapes (although it doesn't look like working) | ||
467 | * ls -N (--literal) = not escape at all | ||
468 | */ | ||
428 | static unsigned calc_name_len(const char *name) | 469 | static unsigned calc_name_len(const char *name) |
429 | { | 470 | { |
430 | unsigned len; | 471 | unsigned len; |
431 | uni_stat_t uni_stat; | 472 | uni_stat_t uni_stat; |
432 | 473 | ||
433 | // TODO: quote tab as \t, etc, if -Q | 474 | if (!(option_mask32 & (OPT_q|OPT_Q))) |
434 | name = printable_string2(&uni_stat, name); | 475 | return strlen(name); |
435 | 476 | ||
436 | if (!(option_mask32 & OPT_Q)) { | 477 | if (!(option_mask32 & OPT_Q)) { |
478 | /* the most likely branch: "ls" to tty (it auto-enables -q behavior) */ | ||
479 | printable_string2(&uni_stat, name); | ||
437 | return uni_stat.unicode_width; | 480 | return uni_stat.unicode_width; |
438 | } | 481 | } |
439 | 482 | ||
440 | len = 2 + uni_stat.unicode_width; | 483 | len = 2 + strlen(name); |
441 | while (*name) { | 484 | while (*name) { |
485 | unsigned char ch = (unsigned char)*name; | ||
486 | if (ch < ' ' || ch > 0x7e) { | ||
487 | ch -= 7; | ||
488 | if (ch <= 6) { | ||
489 | /* quote chars 7..13 as \a,b,t,n,v,f,r */ | ||
490 | goto two; | ||
491 | } | ||
492 | /* other chars <32 or >126 as \ooo octal */ | ||
493 | len += 3; | ||
494 | goto next; | ||
495 | } | ||
442 | if (*name == '"' || *name == '\\') { | 496 | if (*name == '"' || *name == '\\') { |
497 | two: | ||
443 | len++; | 498 | len++; |
444 | } | 499 | } |
500 | next: | ||
445 | name++; | 501 | name++; |
446 | } | 502 | } |
447 | return len; | 503 | return len; |
448 | } | 504 | } |
449 | |||
450 | /* Return the number of used columns. | ||
451 | * Note that only columnar output uses return value. | ||
452 | * -l and -1 modes don't care. | ||
453 | * coreutils 7.2 also supports: | ||
454 | * ls -b (--escape) = octal escapes (although it doesn't look like working) | ||
455 | * ls -N (--literal) = not escape at all | ||
456 | */ | ||
457 | static unsigned print_name(const char *name) | 505 | static unsigned print_name(const char *name) |
458 | { | 506 | { |
459 | unsigned len; | 507 | unsigned len; |
460 | uni_stat_t uni_stat; | 508 | uni_stat_t uni_stat; |
461 | 509 | ||
462 | // TODO: quote tab as \t, etc, if -Q | 510 | if (!(option_mask32 & (OPT_q|OPT_Q))) { |
463 | name = printable_string2(&uni_stat, name); | 511 | fputs_stdout(name); |
512 | return strlen(name); | ||
513 | } | ||
464 | 514 | ||
465 | if (!(option_mask32 & OPT_Q)) { | 515 | if (!(option_mask32 & OPT_Q)) { |
516 | /* the most likely branch: "ls" to tty (it auto-enables -q behavior) */ | ||
517 | name = printable_string2(&uni_stat, name); | ||
466 | fputs_stdout(name); | 518 | fputs_stdout(name); |
467 | return uni_stat.unicode_width; | 519 | return uni_stat.unicode_width; |
468 | } | 520 | } |
469 | 521 | ||
470 | len = 2 + uni_stat.unicode_width; | 522 | len = 2 + strlen(name); |
471 | putchar('"'); | 523 | putchar('"'); |
472 | while (*name) { | 524 | while (*name) { |
473 | if (*name == '"' || *name == '\\') { | 525 | unsigned char ch = (unsigned char)*name; |
526 | if (ch < ' ' || ch > 0x7e) { | ||
474 | putchar('\\'); | 527 | putchar('\\'); |
528 | ch -= 7; | ||
529 | if (ch <= 6) { | ||
530 | /* quote chars 7..13 as \a,b,t,n,v,f,r */ | ||
531 | ch = c_escape_conv_str07[1 + 3 * ch]; | ||
532 | goto two; | ||
533 | } | ||
534 | /* other chars <32 or >126 as \ooo octal */ | ||
535 | ch = (unsigned char)*name; | ||
536 | putchar('0' + (ch>>6)); | ||
537 | putchar('0' + ((ch>>3) & 7)); | ||
538 | ch = '0' + (ch & 7); | ||
539 | len += 3; | ||
540 | goto put_ch; | ||
541 | } | ||
542 | if (ch == '"' || ch == '\\') { | ||
543 | putchar('\\'); | ||
544 | two: | ||
475 | len++; | 545 | len++; |
476 | } | 546 | } |
477 | putchar(*name); | 547 | put_ch: |
548 | putchar(ch); | ||
478 | name++; | 549 | name++; |
479 | } | 550 | } |
480 | putchar('"'); | 551 | putchar('"'); |
@@ -660,7 +731,7 @@ static void display_files(struct dnode **dn, unsigned nfiles) | |||
660 | unsigned i, ncols, nrows, row, nc; | 731 | unsigned i, ncols, nrows, row, nc; |
661 | unsigned column; | 732 | unsigned column; |
662 | unsigned nexttab; | 733 | unsigned nexttab; |
663 | unsigned column_width = 0; /* used only by coulmnal output */ | 734 | unsigned column_width = 0; /* used only by columnar output */ |
664 | 735 | ||
665 | if (option_mask32 & (OPT_l|OPT_1)) { | 736 | if (option_mask32 & (OPT_l|OPT_1)) { |
666 | ncols = 1; | 737 | ncols = 1; |
@@ -709,6 +780,11 @@ static void display_files(struct dnode **dn, unsigned nfiles) | |||
709 | } | 780 | } |
710 | nexttab = column + column_width; | 781 | nexttab = column + column_width; |
711 | column += display_single(dn[i]); | 782 | column += display_single(dn[i]); |
783 | } else { | ||
784 | /* if -w999999999, ncols can be very large */ | ||
785 | //bb_error_msg(" col:%u ncol:%u i:%i", nc, ncols, i); sleep1(); | ||
786 | /* without "break", we loop millions of times here */ | ||
787 | break; | ||
712 | } | 788 | } |
713 | } | 789 | } |
714 | putchar('\n'); | 790 | putchar('\n'); |
@@ -1155,25 +1231,11 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
1155 | /* need to initialize since --color has _an optional_ argument */ | 1231 | /* need to initialize since --color has _an optional_ argument */ |
1156 | const char *color_opt = color_str; /* "always" */ | 1232 | const char *color_opt = color_str; /* "always" */ |
1157 | #endif | 1233 | #endif |
1158 | #if ENABLE_LONG_OPTS | ||
1159 | static const char ls_longopts[] ALIGN1 = | ||
1160 | "full-time\0" No_argument "\xff" | ||
1161 | "group-directories-first\0" No_argument "\xfe" | ||
1162 | IF_FEATURE_LS_COLOR("color\0" Optional_argument "\xfd") | ||
1163 | ; | ||
1164 | #endif | ||
1165 | 1234 | ||
1166 | INIT_G(); | 1235 | INIT_G(); |
1167 | 1236 | ||
1168 | init_unicode(); | 1237 | init_unicode(); |
1169 | 1238 | ||
1170 | #if ENABLE_FEATURE_LS_WIDTH | ||
1171 | /* obtain the terminal width */ | ||
1172 | G_terminal_width = get_terminal_width(STDIN_FILENO); | ||
1173 | /* go one less... */ | ||
1174 | G_terminal_width--; | ||
1175 | #endif | ||
1176 | |||
1177 | /* process options */ | 1239 | /* process options */ |
1178 | opt = getopt32long(argv, "^" | 1240 | opt = getopt32long(argv, "^" |
1179 | ls_options | 1241 | ls_options |
@@ -1211,6 +1273,29 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
1211 | exit(0); | 1273 | exit(0); |
1212 | #endif | 1274 | #endif |
1213 | 1275 | ||
1276 | /* ftpd secret backdoor? */ | ||
1277 | if (ENABLE_FTPD && applet_name[0] == 'f') { | ||
1278 | /* dirs first are much nicer */ | ||
1279 | opt = option_mask32 |= OPT_dirs_first; | ||
1280 | /* don't show SEcontext */ | ||
1281 | IF_SELINUX(opt = option_mask32 &= ~OPT_Z;) | ||
1282 | /* do not query stdout about size and tty-ness */ | ||
1283 | IF_FEATURE_LS_WIDTH(G_terminal_width = INT_MAX;) | ||
1284 | G.tty_out = 1; /* not a tty */ | ||
1285 | goto skip_if_ftpd; | ||
1286 | } | ||
1287 | |||
1288 | #if ENABLE_FEATURE_LS_WIDTH | ||
1289 | if ((int)G_terminal_width < 0) { | ||
1290 | /* obtain the terminal width */ | ||
1291 | G_terminal_width = get_terminal_width(STDIN_FILENO); | ||
1292 | /* go one less... */ | ||
1293 | G_terminal_width--; | ||
1294 | } | ||
1295 | if (G_terminal_width == 0) /* -w0 */ | ||
1296 | G_terminal_width = INT_MAX; /* "infinite" */ | ||
1297 | #endif | ||
1298 | |||
1214 | #if ENABLE_SELINUX | 1299 | #if ENABLE_SELINUX |
1215 | if (opt & OPT_Z) { | 1300 | if (opt & OPT_Z) { |
1216 | if (!is_selinux_enabled()) | 1301 | if (!is_selinux_enabled()) |
@@ -1229,7 +1314,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
1229 | # endif | 1314 | # endif |
1230 | /* LS_COLORS is unset, or (not empty && not "none") ? */ | 1315 | /* LS_COLORS is unset, or (not empty && not "none") ? */ |
1231 | if (!p || (p[0] && strcmp(p, "none") != 0)) { | 1316 | if (!p || (p[0] && strcmp(p, "none") != 0)) { |
1232 | if (isatty(STDOUT_FILENO)) { | 1317 | if (G_isatty()) { |
1233 | /* check isatty() last because it's expensive (syscall) */ | 1318 | /* check isatty() last because it's expensive (syscall) */ |
1234 | G_show_color = 1; | 1319 | G_show_color = 1; |
1235 | } | 1320 | } |
@@ -1238,23 +1323,28 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
1238 | if (opt & OPT_color) { | 1323 | if (opt & OPT_color) { |
1239 | if (color_opt[0] == 'n') | 1324 | if (color_opt[0] == 'n') |
1240 | G_show_color = 0; | 1325 | G_show_color = 0; |
1241 | else switch (index_in_substrings(color_str, color_opt)) { | 1326 | else if (!G_show_color) { |
1242 | case 3: | 1327 | /* if() is not needed, but avoids extra isatty() if G_show_color is already set */ |
1243 | case 4: | 1328 | /* Check --color=COLOR_OPT and maybe set show_color=1 */ |
1244 | case 5: | 1329 | switch (index_in_substrings(color_str, color_opt)) { |
1245 | if (!is_TERM_dumb() && isatty(STDOUT_FILENO)) { | 1330 | case 3: // auto |
1246 | case 0: | 1331 | case 4: // tty |
1247 | case 1: | 1332 | case 5: // if-tty |
1248 | case 2: | 1333 | if (!is_TERM_dumb() && G_isatty()) { |
1249 | G_show_color = 1; | 1334 | case 0: // always |
1335 | case 1: // yes | ||
1336 | case 2: // force | ||
1337 | G_show_color = 1; | ||
1338 | } | ||
1250 | } | 1339 | } |
1251 | } | 1340 | } |
1252 | } | 1341 | } |
1253 | #endif | 1342 | #endif |
1343 | skip_if_ftpd: | ||
1254 | 1344 | ||
1255 | /* sort out which command line options take precedence */ | 1345 | /* sort out which command line options take precedence */ |
1256 | if (ENABLE_FEATURE_LS_RECURSIVE && (opt & OPT_d)) | 1346 | if (ENABLE_FEATURE_LS_RECURSIVE && (opt & OPT_d)) |
1257 | option_mask32 &= ~OPT_R; /* no recurse if listing only dir */ | 1347 | opt = option_mask32 &= ~OPT_R; /* no recurse if listing only dir */ |
1258 | if (!(opt & OPT_l)) { /* not -l? */ | 1348 | if (!(opt & OPT_l)) { /* not -l? */ |
1259 | if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { | 1349 | if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { |
1260 | /* when to sort by time? -t[cu] sorts by time even with -l */ | 1350 | /* when to sort by time? -t[cu] sorts by time even with -l */ |
@@ -1262,19 +1352,17 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
1262 | /* without -l, bare -c or -u enable sort too */ | 1352 | /* without -l, bare -c or -u enable sort too */ |
1263 | /* (with -l, bare -c or -u just select which time to show) */ | 1353 | /* (with -l, bare -c or -u just select which time to show) */ |
1264 | if (opt & (OPT_c|OPT_u)) { | 1354 | if (opt & (OPT_c|OPT_u)) { |
1265 | option_mask32 |= OPT_t; | 1355 | opt = option_mask32 |= OPT_t; |
1266 | } | 1356 | } |
1267 | } | 1357 | } |
1268 | } | 1358 | } |
1269 | 1359 | ||
1270 | /* choose a display format if one was not already specified by an option */ | 1360 | /* choose a display format if one was not already specified by an option */ |
1271 | if (!(option_mask32 & (OPT_l|OPT_1|OPT_x|OPT_C))) | 1361 | if (!(opt & (OPT_l|OPT_1|OPT_x|OPT_C))) |
1272 | option_mask32 |= (isatty(STDOUT_FILENO) ? OPT_C : OPT_1); | 1362 | opt = option_mask32 |= (G_isatty() ? OPT_C : OPT_1); |
1273 | 1363 | ||
1274 | if (ENABLE_FTPD && applet_name[0] == 'f') { | 1364 | if (!(opt & OPT_q) && G_isatty()) |
1275 | /* ftpd secret backdoor. dirs first are much nicer */ | 1365 | opt = option_mask32 |= OPT_q; |
1276 | option_mask32 |= OPT_dirs_first; | ||
1277 | } | ||
1278 | 1366 | ||
1279 | #if ENABLE_FEATURE_EXTRA_FILE_DATA | 1367 | #if ENABLE_FEATURE_EXTRA_FILE_DATA |
1280 | /* Enable accurate link counts for directories */ | 1368 | /* Enable accurate link counts for directories */ |
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index 978d328f1..4506aeb56 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c | |||
@@ -23,6 +23,12 @@ | |||
23 | //config: help | 23 | //config: help |
24 | //config: Compute and check SHA256 message digest | 24 | //config: Compute and check SHA256 message digest |
25 | //config: | 25 | //config: |
26 | //config:config SHA384SUM | ||
27 | //config: bool "sha384sum (7.3 kb)" | ||
28 | //config: default y | ||
29 | //config: help | ||
30 | //config: Compute and check SHA384 message digest | ||
31 | //config: | ||
26 | //config:config SHA512SUM | 32 | //config:config SHA512SUM |
27 | //config: bool "sha512sum (7.3 kb)" | 33 | //config: bool "sha512sum (7.3 kb)" |
28 | //config: default y | 34 | //config: default y |
@@ -35,13 +41,13 @@ | |||
35 | //config: help | 41 | //config: help |
36 | //config: Compute and check SHA3 message digest | 42 | //config: Compute and check SHA3 message digest |
37 | //config: | 43 | //config: |
38 | //config:comment "Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum" | 44 | //config:comment "Common options for md5sum, sha1sum, sha256sum, ..., sha3sum" |
39 | //config: depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM || SHA3SUM | 45 | //config: depends on MD5SUM || SHA1SUM || SHA256SUM || SHA384SUM || SHA512SUM || SHA3SUM |
40 | //config: | 46 | //config: |
41 | //config:config FEATURE_MD5_SHA1_SUM_CHECK | 47 | //config:config FEATURE_MD5_SHA1_SUM_CHECK |
42 | //config: bool "Enable -c, -s and -w options" | 48 | //config: bool "Enable -c, -s and -w options" |
43 | //config: default y | 49 | //config: default y |
44 | //config: depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM || SHA3SUM | 50 | //config: depends on MD5SUM || SHA1SUM || SHA256SUM || SHA384SUM || SHA512SUM || SHA3SUM |
45 | //config: help | 51 | //config: help |
46 | //config: Enabling the -c options allows files to be checked | 52 | //config: Enabling the -c options allows files to be checked |
47 | //config: against pre-calculated hash values. | 53 | //config: against pre-calculated hash values. |
@@ -51,11 +57,13 @@ | |||
51 | //applet:IF_SHA1SUM(APPLET_NOEXEC(sha1sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha1sum)) | 57 | //applet:IF_SHA1SUM(APPLET_NOEXEC(sha1sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha1sum)) |
52 | //applet:IF_SHA3SUM(APPLET_NOEXEC(sha3sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha3sum)) | 58 | //applet:IF_SHA3SUM(APPLET_NOEXEC(sha3sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha3sum)) |
53 | //applet:IF_SHA256SUM(APPLET_NOEXEC(sha256sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha256sum)) | 59 | //applet:IF_SHA256SUM(APPLET_NOEXEC(sha256sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha256sum)) |
60 | //applet:IF_SHA384SUM(APPLET_NOEXEC(sha384sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha384sum)) | ||
54 | //applet:IF_SHA512SUM(APPLET_NOEXEC(sha512sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha512sum)) | 61 | //applet:IF_SHA512SUM(APPLET_NOEXEC(sha512sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha512sum)) |
55 | 62 | ||
56 | //kbuild:lib-$(CONFIG_MD5SUM) += md5_sha1_sum.o | 63 | //kbuild:lib-$(CONFIG_MD5SUM) += md5_sha1_sum.o |
57 | //kbuild:lib-$(CONFIG_SHA1SUM) += md5_sha1_sum.o | 64 | //kbuild:lib-$(CONFIG_SHA1SUM) += md5_sha1_sum.o |
58 | //kbuild:lib-$(CONFIG_SHA256SUM) += md5_sha1_sum.o | 65 | //kbuild:lib-$(CONFIG_SHA256SUM) += md5_sha1_sum.o |
66 | //kbuild:lib-$(CONFIG_SHA384SUM) += md5_sha1_sum.o | ||
59 | //kbuild:lib-$(CONFIG_SHA512SUM) += md5_sha1_sum.o | 67 | //kbuild:lib-$(CONFIG_SHA512SUM) += md5_sha1_sum.o |
60 | //kbuild:lib-$(CONFIG_SHA3SUM) += md5_sha1_sum.o | 68 | //kbuild:lib-$(CONFIG_SHA3SUM) += md5_sha1_sum.o |
61 | 69 | ||
@@ -99,6 +107,16 @@ | |||
99 | //usage: "\n -w Warn about improperly formatted checksum lines" | 107 | //usage: "\n -w Warn about improperly formatted checksum lines" |
100 | //usage: ) | 108 | //usage: ) |
101 | //usage: | 109 | //usage: |
110 | //usage:#define sha384sum_trivial_usage | ||
111 | //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK("[-c[sw]] ")"[FILE]..." | ||
112 | //usage:#define sha384sum_full_usage "\n\n" | ||
113 | //usage: "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA384 checksums" | ||
114 | //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" | ||
115 | //usage: "\n -c Check sums against list in FILEs" | ||
116 | //usage: "\n -s Don't output anything, status code shows success" | ||
117 | //usage: "\n -w Warn about improperly formatted checksum lines" | ||
118 | //usage: ) | ||
119 | //usage: | ||
102 | //usage:#define sha512sum_trivial_usage | 120 | //usage:#define sha512sum_trivial_usage |
103 | //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK("[-c[sw]] ")"[FILE]..." | 121 | //usage: IF_FEATURE_MD5_SHA1_SUM_CHECK("[-c[sw]] ")"[FILE]..." |
104 | //usage:#define sha512sum_full_usage "\n\n" | 122 | //usage:#define sha512sum_full_usage "\n\n" |
@@ -130,11 +148,12 @@ | |||
130 | 148 | ||
131 | enum { | 149 | enum { |
132 | /* 4th letter of applet_name is... */ | 150 | /* 4th letter of applet_name is... */ |
133 | HASH_MD5 = 's', /* "md5>s<um" */ | 151 | HASH_MD5 = 's', /* "md5>s<um" */ |
134 | HASH_SHA1 = '1', | 152 | HASH_SHA1 = '1', |
135 | HASH_SHA256 = '2', | 153 | HASH_SHA256 = '2', |
136 | HASH_SHA3 = '3', | 154 | HASH_SHA3 = '3', |
137 | HASH_SHA512 = '5', | 155 | HASH_SHA512 = '5', |
156 | /* unfortunately, sha384sum has the same '3' as sha3 */ | ||
138 | }; | 157 | }; |
139 | 158 | ||
140 | #define FLAG_SILENT 1 | 159 | #define FLAG_SILENT 1 |
@@ -158,10 +177,11 @@ static unsigned char *hash_bin_to_hex(unsigned char *hash_value, | |||
158 | #endif | 177 | #endif |
159 | static uint8_t *hash_file(unsigned char *in_buf, const char *filename, unsigned sha3_width) | 178 | static uint8_t *hash_file(unsigned char *in_buf, const char *filename, unsigned sha3_width) |
160 | { | 179 | { |
161 | int src_fd, hash_len, count; | 180 | int src_fd, count; |
162 | union _ctx_ { | 181 | union _ctx_ { |
163 | sha3_ctx_t sha3; | 182 | sha3_ctx_t sha3; |
164 | sha512_ctx_t sha512; | 183 | sha512_ctx_t sha512; |
184 | sha384_ctx_t sha384; | ||
165 | sha256_ctx_t sha256; | 185 | sha256_ctx_t sha256; |
166 | sha1_ctx_t sha1; | 186 | sha1_ctx_t sha1; |
167 | md5_ctx_t md5; | 187 | md5_ctx_t md5; |
@@ -183,25 +203,31 @@ static uint8_t *hash_file(unsigned char *in_buf, const char *filename, unsigned | |||
183 | md5_begin(&context.md5); | 203 | md5_begin(&context.md5); |
184 | update = (void*)md5_hash; | 204 | update = (void*)md5_hash; |
185 | final = (void*)md5_end; | 205 | final = (void*)md5_end; |
186 | hash_len = 16; | ||
187 | } | 206 | } |
188 | else if (ENABLE_SHA1SUM && hash_algo == HASH_SHA1) { | 207 | else if (ENABLE_SHA1SUM && hash_algo == HASH_SHA1) { |
189 | sha1_begin(&context.sha1); | 208 | sha1_begin(&context.sha1); |
190 | update = (void*)sha1_hash; | 209 | update = (void*)sha1_hash; |
191 | final = (void*)sha1_end; | 210 | final = (void*)sha1_end; |
192 | hash_len = 20; | ||
193 | } | 211 | } |
194 | else if (ENABLE_SHA256SUM && hash_algo == HASH_SHA256) { | 212 | else if (ENABLE_SHA256SUM && hash_algo == HASH_SHA256) { |
195 | sha256_begin(&context.sha256); | 213 | sha256_begin(&context.sha256); |
196 | update = (void*)sha256_hash; | 214 | update = (void*)sha256_hash; |
197 | final = (void*)sha256_end; | 215 | final = (void*)sha256_end; |
198 | hash_len = 32; | 216 | } |
217 | else if (ENABLE_SHA384SUM | ||
218 | && (ENABLE_SHA3SUM | ||
219 | ? (applet_name[4] == '8') /* check for "sha384", but do not match "sha3" */ | ||
220 | : (hash_algo == '3') /* applet_name = "sha3sum" is not possible */ | ||
221 | ) | ||
222 | ) { | ||
223 | sha384_begin(&context.sha384); | ||
224 | update = (void*)sha384_hash; | ||
225 | final = (void*)sha384_end; | ||
199 | } | 226 | } |
200 | else if (ENABLE_SHA512SUM && hash_algo == HASH_SHA512) { | 227 | else if (ENABLE_SHA512SUM && hash_algo == HASH_SHA512) { |
201 | sha512_begin(&context.sha512); | 228 | sha512_begin(&context.sha512); |
202 | update = (void*)sha512_hash; | 229 | update = (void*)sha512_hash; |
203 | final = (void*)sha512_end; | 230 | final = (void*)sha512_end; |
204 | hash_len = 64; | ||
205 | } | 231 | } |
206 | #if ENABLE_SHA3SUM | 232 | #if ENABLE_SHA3SUM |
207 | else if (ENABLE_SHA3SUM && hash_algo == HASH_SHA3) { | 233 | else if (ENABLE_SHA3SUM && hash_algo == HASH_SHA3) { |
@@ -219,9 +245,7 @@ static uint8_t *hash_file(unsigned char *in_buf, const char *filename, unsigned | |||
219 | ) { | 245 | ) { |
220 | bb_error_msg_and_die("bad -a%u", sha3_width); | 246 | bb_error_msg_and_die("bad -a%u", sha3_width); |
221 | } | 247 | } |
222 | sha3_width /= 4; | 248 | context.sha3.input_block_bytes = 1600/8 - sha3_width/4; |
223 | context.sha3.input_block_bytes = 1600/8 - sha3_width; | ||
224 | hash_len = sha3_width/2; | ||
225 | } | 249 | } |
226 | #endif | 250 | #endif |
227 | else { | 251 | else { |
@@ -236,7 +260,7 @@ static uint8_t *hash_file(unsigned char *in_buf, const char *filename, unsigned | |||
236 | if (count < 0) | 260 | if (count < 0) |
237 | bb_perror_msg("can't read '%s'", filename); | 261 | bb_perror_msg("can't read '%s'", filename); |
238 | else /* count == 0 */ { | 262 | else /* count == 0 */ { |
239 | final(&context, in_buf); | 263 | unsigned hash_len = final(&context, in_buf); |
240 | hash_value = hash_bin_to_hex(in_buf, hash_len); | 264 | hash_value = hash_bin_to_hex(in_buf, hash_len); |
241 | } | 265 | } |
242 | } | 266 | } |
@@ -262,14 +286,14 @@ int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv) | |||
262 | /* -b "binary", -t "text" are ignored (shaNNNsum compat) */ | 286 | /* -b "binary", -t "text" are ignored (shaNNNsum compat) */ |
263 | /* -s and -w require -c */ | 287 | /* -s and -w require -c */ |
264 | #if ENABLE_SHA3SUM | 288 | #if ENABLE_SHA3SUM |
265 | if (applet_name[3] == HASH_SHA3) | 289 | if (applet_name[3] == HASH_SHA3 && (!ENABLE_SHA384SUM || applet_name[4] != '8')) |
266 | flags = getopt32(argv, "^" "scwbta:+" "\0" "s?c:w?c", &sha3_width); | 290 | flags = getopt32(argv, "^" "scwbta:+" "\0" "s?c:w?c", &sha3_width); |
267 | else | 291 | else |
268 | #endif | 292 | #endif |
269 | flags = getopt32(argv, "^" "scwbt" "\0" "s?c:w?c"); | 293 | flags = getopt32(argv, "^" "scwbt" "\0" "s?c:w?c"); |
270 | } else { | 294 | } else { |
271 | #if ENABLE_SHA3SUM | 295 | #if ENABLE_SHA3SUM |
272 | if (applet_name[3] == HASH_SHA3) | 296 | if (applet_name[3] == HASH_SHA3 && (!ENABLE_SHA384SUM || applet_name[4] != '8')) |
273 | getopt32(argv, "a:+", &sha3_width); | 297 | getopt32(argv, "a:+", &sha3_width); |
274 | else | 298 | else |
275 | #endif | 299 | #endif |
diff --git a/coreutils/stty.c b/coreutils/stty.c index c88ef07f4..92d5838c0 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c | |||
@@ -20,14 +20,30 @@ | |||
20 | //kbuild:lib-$(CONFIG_STTY) += stty.o | 20 | //kbuild:lib-$(CONFIG_STTY) += stty.o |
21 | 21 | ||
22 | //usage:#define stty_trivial_usage | 22 | //usage:#define stty_trivial_usage |
23 | //usage: IF_NOT_PLATFORM_MINGW32( | ||
23 | //usage: "[-a|g] [-F DEVICE] [SETTING]..." | 24 | //usage: "[-a|g] [-F DEVICE] [SETTING]..." |
25 | //usage: ) | ||
26 | //usage: IF_PLATFORM_MINGW32( | ||
27 | //usage: "[-a] [SETTING]..." | ||
28 | //usage: ) | ||
24 | //usage:#define stty_full_usage "\n\n" | 29 | //usage:#define stty_full_usage "\n\n" |
30 | //usage: IF_NOT_PLATFORM_MINGW32( | ||
25 | //usage: "Without arguments, prints baud rate, line discipline,\n" | 31 | //usage: "Without arguments, prints baud rate, line discipline,\n" |
26 | //usage: "and deviations from stty sane\n" | 32 | //usage: "and deviations from stty sane\n" |
27 | //usage: "\n -F DEVICE Open device instead of stdin" | 33 | //usage: "\n -F DEVICE Open device instead of stdin" |
34 | //usage: ) | ||
35 | //usage: IF_PLATFORM_MINGW32( | ||
36 | //usage: "Without arguments, prints deviations from stty sane\n" | ||
37 | //usage: ) | ||
28 | //usage: "\n -a Print all current settings in human-readable form" | 38 | //usage: "\n -a Print all current settings in human-readable form" |
39 | //usage: IF_NOT_PLATFORM_MINGW32( | ||
29 | //usage: "\n -g Print in stty-readable form" | 40 | //usage: "\n -g Print in stty-readable form" |
30 | //usage: "\n [SETTING] See manpage" | 41 | //usage: "\n [SETTING] See manpage" |
42 | //usage: ) | ||
43 | //usage: IF_PLATFORM_MINGW32( | ||
44 | //usage: "\n [SETTING] [-]echo [-]cooked [-]raw sane" | ||
45 | //usage: "\n cols N rows N size" | ||
46 | //usage: ) | ||
31 | 47 | ||
32 | /* If no args are given, write to stdout the baud rate and settings that | 48 | /* If no args are given, write to stdout the baud rate and settings that |
33 | * have been changed from their defaults. Mode reading and changes | 49 | * have been changed from their defaults. Mode reading and changes |
@@ -294,6 +310,7 @@ struct mode_info { | |||
294 | const tcflag_t bits; /* Bits to set for this mode */ | 310 | const tcflag_t bits; /* Bits to set for this mode */ |
295 | }; | 311 | }; |
296 | 312 | ||
313 | #if !ENABLE_PLATFORM_MINGW32 | ||
297 | enum { | 314 | enum { |
298 | /* Must match mode_name[] and mode_info[] order! */ | 315 | /* Must match mode_name[] and mode_info[] order! */ |
299 | IDX_evenp = 0, | 316 | IDX_evenp = 0, |
@@ -320,19 +337,30 @@ enum { | |||
320 | IDX_LCASE, | 337 | IDX_LCASE, |
321 | #endif | 338 | #endif |
322 | }; | 339 | }; |
340 | #else | ||
341 | enum { | ||
342 | /* Must match mode_name[] and mode_info[] order! */ | ||
343 | IDX_sane = 0, | ||
344 | IDX_cooked, | ||
345 | IDX_raw, | ||
346 | }; | ||
347 | #endif | ||
323 | 348 | ||
324 | #define MI_ENTRY(N,T,F,B,M) N "\0" | 349 | #define MI_ENTRY(N,T,F,B,M) N "\0" |
325 | 350 | ||
326 | /* Mode names given on command line */ | 351 | /* Mode names given on command line */ |
327 | static const char mode_name[] ALIGN1 = | 352 | static const char mode_name[] ALIGN1 = |
353 | #if !ENABLE_PLATFORM_MINGW32 | ||
328 | MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 ) | 354 | MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 ) |
329 | MI_ENTRY("parity", combination, REV | OMIT, 0, 0 ) | 355 | MI_ENTRY("parity", combination, REV | OMIT, 0, 0 ) |
330 | MI_ENTRY("oddp", combination, REV | OMIT, 0, 0 ) | 356 | MI_ENTRY("oddp", combination, REV | OMIT, 0, 0 ) |
331 | MI_ENTRY("nl", combination, REV | OMIT, 0, 0 ) | 357 | MI_ENTRY("nl", combination, REV | OMIT, 0, 0 ) |
332 | MI_ENTRY("ek", combination, OMIT, 0, 0 ) | 358 | MI_ENTRY("ek", combination, OMIT, 0, 0 ) |
359 | #endif | ||
333 | MI_ENTRY("sane", combination, OMIT, 0, 0 ) | 360 | MI_ENTRY("sane", combination, OMIT, 0, 0 ) |
334 | MI_ENTRY("cooked", combination, REV | OMIT, 0, 0 ) | 361 | MI_ENTRY("cooked", combination, REV | OMIT, 0, 0 ) |
335 | MI_ENTRY("raw", combination, REV | OMIT, 0, 0 ) | 362 | MI_ENTRY("raw", combination, REV | OMIT, 0, 0 ) |
363 | #if !ENABLE_PLATFORM_MINGW32 | ||
336 | MI_ENTRY("pass8", combination, REV | OMIT, 0, 0 ) | 364 | MI_ENTRY("pass8", combination, REV | OMIT, 0, 0 ) |
337 | MI_ENTRY("litout", combination, REV | OMIT, 0, 0 ) | 365 | MI_ENTRY("litout", combination, REV | OMIT, 0, 0 ) |
338 | MI_ENTRY("cbreak", combination, REV | OMIT, 0, 0 ) | 366 | MI_ENTRY("cbreak", combination, REV | OMIT, 0, 0 ) |
@@ -454,7 +482,9 @@ static const char mode_name[] ALIGN1 = | |||
454 | #if IEXTEN | 482 | #if IEXTEN |
455 | MI_ENTRY("iexten", local, SANE_SET | REV, IEXTEN, 0 ) | 483 | MI_ENTRY("iexten", local, SANE_SET | REV, IEXTEN, 0 ) |
456 | #endif | 484 | #endif |
485 | #endif /* !ENABLE_PLATFORM_MINGW32 */ | ||
457 | MI_ENTRY("echo", local, SANE_SET | REV, ECHO, 0 ) | 486 | MI_ENTRY("echo", local, SANE_SET | REV, ECHO, 0 ) |
487 | #if !ENABLE_PLATFORM_MINGW32 | ||
458 | MI_ENTRY("echoe", local, SANE_SET | REV, ECHOE, 0 ) | 488 | MI_ENTRY("echoe", local, SANE_SET | REV, ECHOE, 0 ) |
459 | MI_ENTRY("crterase", local, OMIT | REV, ECHOE, 0 ) | 489 | MI_ENTRY("crterase", local, OMIT | REV, ECHOE, 0 ) |
460 | MI_ENTRY("echok", local, SANE_SET | REV, ECHOK, 0 ) | 490 | MI_ENTRY("echok", local, SANE_SET | REV, ECHOK, 0 ) |
@@ -482,6 +512,7 @@ static const char mode_name[] ALIGN1 = | |||
482 | #ifdef EXTPROC | 512 | #ifdef EXTPROC |
483 | MI_ENTRY("extproc", local, SANE_UNSET | REV, EXTPROC, 0 ) | 513 | MI_ENTRY("extproc", local, SANE_UNSET | REV, EXTPROC, 0 ) |
484 | #endif | 514 | #endif |
515 | #endif /* !ENABLE_PLATFORM_MINGW32 */ | ||
485 | ; | 516 | ; |
486 | 517 | ||
487 | #undef MI_ENTRY | 518 | #undef MI_ENTRY |
@@ -489,14 +520,17 @@ static const char mode_name[] ALIGN1 = | |||
489 | 520 | ||
490 | static const struct mode_info mode_info[] ALIGN4 = { | 521 | static const struct mode_info mode_info[] ALIGN4 = { |
491 | /* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */ | 522 | /* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */ |
523 | #if !ENABLE_PLATFORM_MINGW32 | ||
492 | MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 ) | 524 | MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 ) |
493 | MI_ENTRY("parity", combination, REV | OMIT, 0, 0 ) | 525 | MI_ENTRY("parity", combination, REV | OMIT, 0, 0 ) |
494 | MI_ENTRY("oddp", combination, REV | OMIT, 0, 0 ) | 526 | MI_ENTRY("oddp", combination, REV | OMIT, 0, 0 ) |
495 | MI_ENTRY("nl", combination, REV | OMIT, 0, 0 ) | 527 | MI_ENTRY("nl", combination, REV | OMIT, 0, 0 ) |
496 | MI_ENTRY("ek", combination, OMIT, 0, 0 ) | 528 | MI_ENTRY("ek", combination, OMIT, 0, 0 ) |
529 | #endif | ||
497 | MI_ENTRY("sane", combination, OMIT, 0, 0 ) | 530 | MI_ENTRY("sane", combination, OMIT, 0, 0 ) |
498 | MI_ENTRY("cooked", combination, REV | OMIT, 0, 0 ) | 531 | MI_ENTRY("cooked", combination, REV | OMIT, 0, 0 ) |
499 | MI_ENTRY("raw", combination, REV | OMIT, 0, 0 ) | 532 | MI_ENTRY("raw", combination, REV | OMIT, 0, 0 ) |
533 | #if !ENABLE_PLATFORM_MINGW32 | ||
500 | MI_ENTRY("pass8", combination, REV | OMIT, 0, 0 ) | 534 | MI_ENTRY("pass8", combination, REV | OMIT, 0, 0 ) |
501 | MI_ENTRY("litout", combination, REV | OMIT, 0, 0 ) | 535 | MI_ENTRY("litout", combination, REV | OMIT, 0, 0 ) |
502 | MI_ENTRY("cbreak", combination, REV | OMIT, 0, 0 ) | 536 | MI_ENTRY("cbreak", combination, REV | OMIT, 0, 0 ) |
@@ -618,7 +652,9 @@ static const struct mode_info mode_info[] ALIGN4 = { | |||
618 | #if IEXTEN | 652 | #if IEXTEN |
619 | MI_ENTRY("iexten", local, SANE_SET | REV, IEXTEN, 0 ) | 653 | MI_ENTRY("iexten", local, SANE_SET | REV, IEXTEN, 0 ) |
620 | #endif | 654 | #endif |
655 | #endif /* !ENABLE_PLATFORM_MINGW32 */ | ||
621 | MI_ENTRY("echo", local, SANE_SET | REV, ECHO, 0 ) | 656 | MI_ENTRY("echo", local, SANE_SET | REV, ECHO, 0 ) |
657 | #if !ENABLE_PLATFORM_MINGW32 | ||
622 | MI_ENTRY("echoe", local, SANE_SET | REV, ECHOE, 0 ) | 658 | MI_ENTRY("echoe", local, SANE_SET | REV, ECHOE, 0 ) |
623 | MI_ENTRY("crterase", local, OMIT | REV, ECHOE, 0 ) | 659 | MI_ENTRY("crterase", local, OMIT | REV, ECHOE, 0 ) |
624 | MI_ENTRY("echok", local, SANE_SET | REV, ECHOK, 0 ) | 660 | MI_ENTRY("echok", local, SANE_SET | REV, ECHOK, 0 ) |
@@ -646,6 +682,7 @@ static const struct mode_info mode_info[] ALIGN4 = { | |||
646 | #ifdef EXTPROC | 682 | #ifdef EXTPROC |
647 | MI_ENTRY("extproc", local, SANE_UNSET | REV, EXTPROC, 0 ) | 683 | MI_ENTRY("extproc", local, SANE_UNSET | REV, EXTPROC, 0 ) |
648 | #endif | 684 | #endif |
685 | #endif /* !ENABLE_PLATFORM_MINGW32 */ | ||
649 | }; | 686 | }; |
650 | 687 | ||
651 | enum { | 688 | enum { |
@@ -653,6 +690,7 @@ enum { | |||
653 | }; | 690 | }; |
654 | 691 | ||
655 | 692 | ||
693 | #if !ENABLE_PLATFORM_MINGW32 | ||
656 | /* Control characters */ | 694 | /* Control characters */ |
657 | struct control_info { | 695 | struct control_info { |
658 | const uint8_t saneval; /* Value to set for 'stty sane' */ | 696 | const uint8_t saneval; /* Value to set for 'stty sane' */ |
@@ -786,6 +824,7 @@ static const struct control_info control_info[] ALIGN2 = { | |||
786 | enum { | 824 | enum { |
787 | NUM_control_info = ARRAY_SIZE(control_info) | 825 | NUM_control_info = ARRAY_SIZE(control_info) |
788 | }; | 826 | }; |
827 | #endif | ||
789 | 828 | ||
790 | 829 | ||
791 | struct globals { | 830 | struct globals { |
@@ -803,6 +842,7 @@ struct globals { | |||
803 | G.current_col = 0; /* we are noexec, must clear */ \ | 842 | G.current_col = 0; /* we are noexec, must clear */ \ |
804 | } while (0) | 843 | } while (0) |
805 | 844 | ||
845 | #if !ENABLE_PLATFORM_MINGW32 | ||
806 | static void set_speed_or_die(enum speed_setting type, const char *arg, | 846 | static void set_speed_or_die(enum speed_setting type, const char *arg, |
807 | struct termios *mode) | 847 | struct termios *mode) |
808 | { | 848 | { |
@@ -817,6 +857,7 @@ static void set_speed_or_die(enum speed_setting type, const char *arg, | |||
817 | cfsetospeed(mode, baud); | 857 | cfsetospeed(mode, baud); |
818 | } | 858 | } |
819 | } | 859 | } |
860 | #endif | ||
820 | 861 | ||
821 | static NORETURN void perror_on_device_and_die(const char *fmt) | 862 | static NORETURN void perror_on_device_and_die(const char *fmt) |
822 | { | 863 | { |
@@ -918,6 +959,7 @@ static const struct mode_info *find_mode(const char *name) | |||
918 | return i >= 0 ? &mode_info[i] : NULL; | 959 | return i >= 0 ? &mode_info[i] : NULL; |
919 | } | 960 | } |
920 | 961 | ||
962 | #if !ENABLE_PLATFORM_MINGW32 | ||
921 | static const struct control_info *find_control(const char *name) | 963 | static const struct control_info *find_control(const char *name) |
922 | { | 964 | { |
923 | int i = index_in_strings(control_name, name); | 965 | int i = index_in_strings(control_name, name); |
@@ -954,7 +996,32 @@ static int find_param(const char *name) | |||
954 | i |= 0x80; | 996 | i |= 0x80; |
955 | return i; | 997 | return i; |
956 | } | 998 | } |
999 | #else | ||
1000 | enum { | ||
1001 | param_need_arg = 0x80, | ||
1002 | param_rows = 1 | 0x80, | ||
1003 | param_cols = 2 | 0x80, | ||
1004 | param_columns = 3 | 0x80, | ||
1005 | param_size = 4, | ||
1006 | }; | ||
957 | 1007 | ||
1008 | static int find_param(const char *name) | ||
1009 | { | ||
1010 | static const char params[] ALIGN1 = | ||
1011 | "rows\0" /* 1 */ | ||
1012 | "cols\0" /* 2 */ | ||
1013 | "columns\0" /* 3 */ | ||
1014 | "size\0"; /* 4 */ | ||
1015 | int i = index_in_strings(params, name) + 1; | ||
1016 | if (i == 0) | ||
1017 | return 0; | ||
1018 | if (i != 4) | ||
1019 | i |= 0x80; | ||
1020 | return i; | ||
1021 | } | ||
1022 | #endif | ||
1023 | |||
1024 | #if !ENABLE_PLATFORM_MINGW32 | ||
958 | static int recover_mode(const char *arg, struct termios *mode) | 1025 | static int recover_mode(const char *arg, struct termios *mode) |
959 | { | 1026 | { |
960 | int i, n; | 1027 | int i, n; |
@@ -1013,6 +1080,9 @@ static void display_speed(const struct termios *mode, int fancy) | |||
1013 | if (fancy) fmt_str += 9; | 1080 | if (fancy) fmt_str += 9; |
1014 | wrapf(fmt_str, tty_baud_to_value(ispeed), tty_baud_to_value(ospeed)); | 1081 | wrapf(fmt_str, tty_baud_to_value(ispeed), tty_baud_to_value(ospeed)); |
1015 | } | 1082 | } |
1083 | #else | ||
1084 | # define display_speed(m, f) ((void)0) | ||
1085 | #endif | ||
1016 | 1086 | ||
1017 | static void do_display(const struct termios *mode, int all) | 1087 | static void do_display(const struct termios *mode, int all) |
1018 | { | 1088 | { |
@@ -1030,6 +1100,7 @@ static void do_display(const struct termios *mode, int all) | |||
1030 | newline(); | 1100 | newline(); |
1031 | #endif | 1101 | #endif |
1032 | 1102 | ||
1103 | #if !ENABLE_PLATFORM_MINGW32 | ||
1033 | for (i = 0; i != CIDX_min; ++i) { | 1104 | for (i = 0; i != CIDX_min; ++i) { |
1034 | char ch; | 1105 | char ch; |
1035 | char buf10[10]; | 1106 | char buf10[10]; |
@@ -1059,6 +1130,7 @@ static void do_display(const struct termios *mode, int all) | |||
1059 | #endif | 1130 | #endif |
1060 | wrapf("min = %u; time = %u;", mode->c_cc[VMIN], mode->c_cc[VTIME]); | 1131 | wrapf("min = %u; time = %u;", mode->c_cc[VMIN], mode->c_cc[VTIME]); |
1061 | newline(); | 1132 | newline(); |
1133 | #endif | ||
1062 | 1134 | ||
1063 | for (i = 0; i < NUM_mode_info; ++i) { | 1135 | for (i = 0; i < NUM_mode_info; ++i) { |
1064 | if (mode_info[i].flags & OMIT) | 1136 | if (mode_info[i].flags & OMIT) |
@@ -1086,6 +1158,7 @@ static void do_display(const struct termios *mode, int all) | |||
1086 | 1158 | ||
1087 | static void sane_mode(struct termios *mode) | 1159 | static void sane_mode(struct termios *mode) |
1088 | { | 1160 | { |
1161 | #if !ENABLE_PLATFORM_MINGW32 | ||
1089 | int i; | 1162 | int i; |
1090 | 1163 | ||
1091 | for (i = 0; i < NUM_control_info; ++i) { | 1164 | for (i = 0; i < NUM_control_info; ++i) { |
@@ -1110,6 +1183,11 @@ static void sane_mode(struct termios *mode) | |||
1110 | *bitsp = val & ~mode_info[i].bits; | 1183 | *bitsp = val & ~mode_info[i].bits; |
1111 | } | 1184 | } |
1112 | } | 1185 | } |
1186 | #else | ||
1187 | mode->c_lflag |= ECHO; | ||
1188 | mode->w_mode |= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | | ||
1189 | ENABLE_PROCESSED_INPUT; | ||
1190 | #endif | ||
1113 | } | 1191 | } |
1114 | 1192 | ||
1115 | static void set_mode(const struct mode_info *info, int reversed, | 1193 | static void set_mode(const struct mode_info *info, int reversed, |
@@ -1129,6 +1207,7 @@ static void set_mode(const struct mode_info *info, int reversed, | |||
1129 | } | 1207 | } |
1130 | 1208 | ||
1131 | /* !bitsp - it's a "combination" mode */ | 1209 | /* !bitsp - it's a "combination" mode */ |
1210 | #if !ENABLE_PLATFORM_MINGW32 | ||
1132 | if (info == &mode_info[IDX_evenp] || info == &mode_info[IDX_parity]) { | 1211 | if (info == &mode_info[IDX_evenp] || info == &mode_info[IDX_parity]) { |
1133 | if (reversed) | 1212 | if (reversed) |
1134 | mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8; | 1213 | mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8; |
@@ -1150,9 +1229,14 @@ static void set_mode(const struct mode_info *info, int reversed, | |||
1150 | } else if (info == &mode_info[IDX_ek]) { | 1229 | } else if (info == &mode_info[IDX_ek]) { |
1151 | mode->c_cc[VERASE] = CERASE; | 1230 | mode->c_cc[VERASE] = CERASE; |
1152 | mode->c_cc[VKILL] = CKILL; | 1231 | mode->c_cc[VKILL] = CKILL; |
1153 | } else if (info == &mode_info[IDX_sane]) { | 1232 | } |
1233 | else | ||
1234 | #endif /* !ENABLE_PLATFORM_MINGW32 */ | ||
1235 | if (info == &mode_info[IDX_sane]) { | ||
1154 | sane_mode(mode); | 1236 | sane_mode(mode); |
1155 | } else if (info == &mode_info[IDX_cbreak]) { | 1237 | } |
1238 | #if !ENABLE_PLATFORM_MINGW32 | ||
1239 | else if (info == &mode_info[IDX_cbreak]) { | ||
1156 | if (reversed) | 1240 | if (reversed) |
1157 | mode->c_lflag |= ICANON; | 1241 | mode->c_lflag |= ICANON; |
1158 | else | 1242 | else |
@@ -1175,11 +1259,14 @@ static void set_mode(const struct mode_info *info, int reversed, | |||
1175 | mode->c_iflag &= ~ISTRIP; | 1259 | mode->c_iflag &= ~ISTRIP; |
1176 | mode->c_oflag &= ~OPOST; | 1260 | mode->c_oflag &= ~OPOST; |
1177 | } | 1261 | } |
1178 | } else if (info == &mode_info[IDX_raw] || info == &mode_info[IDX_cooked]) { | 1262 | } |
1263 | #endif /* !ENABLE_PLATFORM_MINGW32 */ | ||
1264 | else if (info == &mode_info[IDX_raw] || info == &mode_info[IDX_cooked]) { | ||
1179 | if ((info == &mode_info[IDX_raw] && reversed) | 1265 | if ((info == &mode_info[IDX_raw] && reversed) |
1180 | || (info == &mode_info[IDX_cooked] && !reversed) | 1266 | || (info == &mode_info[IDX_cooked] && !reversed) |
1181 | ) { | 1267 | ) { |
1182 | /* Cooked mode */ | 1268 | /* Cooked mode */ |
1269 | #if !ENABLE_PLATFORM_MINGW32 | ||
1183 | mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON; | 1270 | mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON; |
1184 | mode->c_oflag |= OPOST; | 1271 | mode->c_oflag |= OPOST; |
1185 | mode->c_lflag |= ISIG | ICANON; | 1272 | mode->c_lflag |= ISIG | ICANON; |
@@ -1189,15 +1276,23 @@ static void set_mode(const struct mode_info *info, int reversed, | |||
1189 | #if VTIME == VEOL | 1276 | #if VTIME == VEOL |
1190 | mode->c_cc[VEOL] = CEOL; | 1277 | mode->c_cc[VEOL] = CEOL; |
1191 | #endif | 1278 | #endif |
1279 | #else | ||
1280 | mode->w_mode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; | ||
1281 | #endif | ||
1192 | } else { | 1282 | } else { |
1193 | /* Raw mode */ | 1283 | /* Raw mode */ |
1284 | #if !ENABLE_PLATFORM_MINGW32 | ||
1194 | mode->c_iflag = 0; | 1285 | mode->c_iflag = 0; |
1195 | mode->c_oflag &= ~OPOST; | 1286 | mode->c_oflag &= ~OPOST; |
1196 | mode->c_lflag &= ~(ISIG | ICANON | XCASE); | 1287 | mode->c_lflag &= ~(ISIG | ICANON | XCASE); |
1197 | mode->c_cc[VMIN] = 1; | 1288 | mode->c_cc[VMIN] = 1; |
1198 | mode->c_cc[VTIME] = 0; | 1289 | mode->c_cc[VTIME] = 0; |
1290 | #else | ||
1291 | mode->w_mode &= ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT); | ||
1292 | #endif | ||
1199 | } | 1293 | } |
1200 | } | 1294 | } |
1295 | #if !ENABLE_PLATFORM_MINGW32 | ||
1201 | #if IXANY | 1296 | #if IXANY |
1202 | else if (info == &mode_info[IDX_decctlq]) { | 1297 | else if (info == &mode_info[IDX_decctlq]) { |
1203 | if (reversed) | 1298 | if (reversed) |
@@ -1244,8 +1339,10 @@ static void set_mode(const struct mode_info *info, int reversed, | |||
1244 | mode->c_lflag |= ECHOE | ECHOCTL | ECHOKE; | 1339 | mode->c_lflag |= ECHOE | ECHOCTL | ECHOKE; |
1245 | if (IXANY) mode->c_iflag &= ~IXANY; | 1340 | if (IXANY) mode->c_iflag &= ~IXANY; |
1246 | } | 1341 | } |
1342 | #endif /*!ENABLE_PLATFORM_MINGW32 */ | ||
1247 | } | 1343 | } |
1248 | 1344 | ||
1345 | #if !ENABLE_PLATFORM_MINGW32 | ||
1249 | static void set_control_char_or_die(const struct control_info *info, | 1346 | static void set_control_char_or_die(const struct control_info *info, |
1250 | const char *arg, struct termios *mode) | 1347 | const char *arg, struct termios *mode) |
1251 | { | 1348 | { |
@@ -1265,6 +1362,7 @@ static void set_control_char_or_die(const struct control_info *info, | |||
1265 | value = xatoul_range_sfx(arg, 0, 0xff, stty_suffixes); | 1362 | value = xatoul_range_sfx(arg, 0, 0xff, stty_suffixes); |
1266 | mode->c_cc[info->offset] = value; | 1363 | mode->c_cc[info->offset] = value; |
1267 | } | 1364 | } |
1365 | #endif | ||
1268 | 1366 | ||
1269 | #define STTY_require_set_attr (1 << 0) | 1367 | #define STTY_require_set_attr (1 << 0) |
1270 | #define STTY_speed_was_set (1 << 1) | 1368 | #define STTY_speed_was_set (1 << 1) |
@@ -1277,7 +1375,9 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1277 | { | 1375 | { |
1278 | struct termios mode; | 1376 | struct termios mode; |
1279 | void (*output_func)(const struct termios *, int); | 1377 | void (*output_func)(const struct termios *, int); |
1378 | #if !ENABLE_PLATFORM_MINGW32 | ||
1280 | const char *file_name = NULL; | 1379 | const char *file_name = NULL; |
1380 | #endif | ||
1281 | int display_all = 0; | 1381 | int display_all = 0; |
1282 | int stty_state; | 1382 | int stty_state; |
1283 | int k; | 1383 | int k; |
@@ -1291,7 +1391,9 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1291 | k = 0; | 1391 | k = 0; |
1292 | while (argv[++k]) { | 1392 | while (argv[++k]) { |
1293 | const struct mode_info *mp; | 1393 | const struct mode_info *mp; |
1394 | #if !ENABLE_PLATFORM_MINGW32 | ||
1294 | const struct control_info *cp; | 1395 | const struct control_info *cp; |
1396 | #endif | ||
1295 | const char *arg = argv[k]; | 1397 | const char *arg = argv[k]; |
1296 | const char *argnext = argv[k+1]; | 1398 | const char *argnext = argv[k+1]; |
1297 | int param; | 1399 | int param; |
@@ -1314,6 +1416,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1314 | output_func = do_display; | 1416 | output_func = do_display; |
1315 | display_all = 1; | 1417 | display_all = 1; |
1316 | break; | 1418 | break; |
1419 | #if !ENABLE_PLATFORM_MINGW32 | ||
1317 | case 'g': | 1420 | case 'g': |
1318 | stty_state |= STTY_recoverable_output; | 1421 | stty_state |= STTY_recoverable_output; |
1319 | output_func = display_recoverable; | 1422 | output_func = display_recoverable; |
@@ -1334,11 +1437,14 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1334 | } | 1437 | } |
1335 | } | 1438 | } |
1336 | goto end_option; | 1439 | goto end_option; |
1440 | #endif | ||
1337 | default: | 1441 | default: |
1338 | goto invalid_argument; | 1442 | goto invalid_argument; |
1339 | } | 1443 | } |
1340 | } | 1444 | } |
1445 | #if !ENABLE_PLATFORM_MINGW32 | ||
1341 | end_option: | 1446 | end_option: |
1447 | #endif | ||
1342 | continue; | 1448 | continue; |
1343 | } | 1449 | } |
1344 | 1450 | ||
@@ -1348,6 +1454,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1348 | continue; | 1454 | continue; |
1349 | } | 1455 | } |
1350 | 1456 | ||
1457 | #if !ENABLE_PLATFORM_MINGW32 | ||
1351 | cp = find_control(arg); | 1458 | cp = find_control(arg); |
1352 | if (cp) { | 1459 | if (cp) { |
1353 | if (!argnext) | 1460 | if (!argnext) |
@@ -1358,6 +1465,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1358 | ++k; | 1465 | ++k; |
1359 | continue; | 1466 | continue; |
1360 | } | 1467 | } |
1468 | #endif | ||
1361 | 1469 | ||
1362 | param = find_param(arg); | 1470 | param = find_param(arg); |
1363 | if (param & param_need_arg) { | 1471 | if (param & param_need_arg) { |
@@ -1381,7 +1489,11 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1381 | xatoul_range_sfx(argnext, 1, INT_MAX, stty_suffixes); | 1489 | xatoul_range_sfx(argnext, 1, INT_MAX, stty_suffixes); |
1382 | break; | 1490 | break; |
1383 | case param_size: | 1491 | case param_size: |
1492 | # if ENABLE_PLATFORM_MINGW32 | ||
1493 | break; | ||
1494 | # endif | ||
1384 | #endif | 1495 | #endif |
1496 | #if !ENABLE_PLATFORM_MINGW32 | ||
1385 | case param_speed: | 1497 | case param_speed: |
1386 | break; | 1498 | break; |
1387 | case param_ispeed: | 1499 | case param_ispeed: |
@@ -1392,15 +1504,19 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1392 | /* called for the side effect of xfunc death only */ | 1504 | /* called for the side effect of xfunc death only */ |
1393 | set_speed_or_die(output_speed, argnext, &mode); | 1505 | set_speed_or_die(output_speed, argnext, &mode); |
1394 | break; | 1506 | break; |
1507 | #endif | ||
1395 | default: | 1508 | default: |
1509 | #if !ENABLE_PLATFORM_MINGW32 | ||
1396 | if (recover_mode(arg, &mode) == 1) break; | 1510 | if (recover_mode(arg, &mode) == 1) break; |
1397 | if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) break; | 1511 | if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) break; |
1512 | #endif | ||
1398 | invalid_argument: | 1513 | invalid_argument: |
1399 | bb_error_msg_and_die("invalid argument '%s'", arg); | 1514 | bb_error_msg_and_die("invalid argument '%s'", arg); |
1400 | } | 1515 | } |
1401 | stty_state &= ~STTY_noargs; | 1516 | stty_state &= ~STTY_noargs; |
1402 | } | 1517 | } |
1403 | 1518 | ||
1519 | #if !ENABLE_PLATFORM_MINGW32 | ||
1404 | /* Specifying both -a and -g is an error */ | 1520 | /* Specifying both -a and -g is an error */ |
1405 | if ((stty_state & (STTY_verbose_output | STTY_recoverable_output)) == | 1521 | if ((stty_state & (STTY_verbose_output | STTY_recoverable_output)) == |
1406 | (STTY_verbose_output | STTY_recoverable_output) | 1522 | (STTY_verbose_output | STTY_recoverable_output) |
@@ -1413,13 +1529,22 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1413 | ) { | 1529 | ) { |
1414 | bb_simple_error_msg_and_die("modes may not be set when -a or -g is used"); | 1530 | bb_simple_error_msg_and_die("modes may not be set when -a or -g is used"); |
1415 | } | 1531 | } |
1532 | #else | ||
1533 | /* Specifying -a with non-options is an error */ | ||
1534 | if ((stty_state & STTY_verbose_output) && !(stty_state & STTY_noargs) | ||
1535 | ) { | ||
1536 | bb_simple_error_msg_and_die("modes may not be set when -a is used"); | ||
1537 | } | ||
1538 | #endif | ||
1416 | 1539 | ||
1540 | #if !ENABLE_PLATFORM_MINGW32 | ||
1417 | /* Now it is safe to start doing things */ | 1541 | /* Now it is safe to start doing things */ |
1418 | if (file_name) { | 1542 | if (file_name) { |
1419 | G.device_name = file_name; | 1543 | G.device_name = file_name; |
1420 | xmove_fd(xopen_nonblocking(G.device_name), STDIN_FILENO); | 1544 | xmove_fd(xopen_nonblocking(G.device_name), STDIN_FILENO); |
1421 | ndelay_off(STDIN_FILENO); | 1545 | ndelay_off(STDIN_FILENO); |
1422 | } | 1546 | } |
1547 | #endif | ||
1423 | 1548 | ||
1424 | /* Initialize to all zeroes so there is no risk memcmp will report a | 1549 | /* Initialize to all zeroes so there is no risk memcmp will report a |
1425 | spurious difference in an uninitialized portion of the structure */ | 1550 | spurious difference in an uninitialized portion of the structure */ |
@@ -1437,7 +1562,9 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1437 | k = 0; | 1562 | k = 0; |
1438 | while (argv[++k]) { | 1563 | while (argv[++k]) { |
1439 | const struct mode_info *mp; | 1564 | const struct mode_info *mp; |
1565 | #if !ENABLE_PLATFORM_MINGW32 | ||
1440 | const struct control_info *cp; | 1566 | const struct control_info *cp; |
1567 | #endif | ||
1441 | const char *arg = argv[k]; | 1568 | const char *arg = argv[k]; |
1442 | const char *argnext = argv[k+1]; | 1569 | const char *argnext = argv[k+1]; |
1443 | int param; | 1570 | int param; |
@@ -1459,6 +1586,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1459 | continue; | 1586 | continue; |
1460 | } | 1587 | } |
1461 | 1588 | ||
1589 | #if !ENABLE_PLATFORM_MINGW32 | ||
1462 | cp = find_control(arg); | 1590 | cp = find_control(arg); |
1463 | if (cp) { | 1591 | if (cp) { |
1464 | ++k; | 1592 | ++k; |
@@ -1466,6 +1594,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1466 | stty_state |= STTY_require_set_attr; | 1594 | stty_state |= STTY_require_set_attr; |
1467 | continue; | 1595 | continue; |
1468 | } | 1596 | } |
1597 | #endif | ||
1469 | 1598 | ||
1470 | param = find_param(arg); | 1599 | param = find_param(arg); |
1471 | if (param & param_need_arg) { | 1600 | if (param & param_need_arg) { |
@@ -1491,6 +1620,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1491 | set_window_size(xatoul_sfx(argnext, stty_suffixes), -1); | 1620 | set_window_size(xatoul_sfx(argnext, stty_suffixes), -1); |
1492 | break; | 1621 | break; |
1493 | #endif | 1622 | #endif |
1623 | #if !ENABLE_PLATFORM_MINGW32 | ||
1494 | case param_speed: | 1624 | case param_speed: |
1495 | display_speed(&mode, 0); | 1625 | display_speed(&mode, 0); |
1496 | break; | 1626 | break; |
@@ -1502,7 +1632,9 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1502 | set_speed_or_die(output_speed, argnext, &mode); | 1632 | set_speed_or_die(output_speed, argnext, &mode); |
1503 | stty_state |= (STTY_require_set_attr | STTY_speed_was_set); | 1633 | stty_state |= (STTY_require_set_attr | STTY_speed_was_set); |
1504 | break; | 1634 | break; |
1635 | #endif | ||
1505 | default: | 1636 | default: |
1637 | #if !ENABLE_PLATFORM_MINGW32 | ||
1506 | if (recover_mode(arg, &mode) == 1) | 1638 | if (recover_mode(arg, &mode) == 1) |
1507 | stty_state |= STTY_require_set_attr; | 1639 | stty_state |= STTY_require_set_attr; |
1508 | else /* true: if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) */{ | 1640 | else /* true: if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) */{ |
@@ -1510,15 +1642,24 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1510 | stty_state |= (STTY_require_set_attr | STTY_speed_was_set); | 1642 | stty_state |= (STTY_require_set_attr | STTY_speed_was_set); |
1511 | } /* else - impossible (caught in the first pass): | 1643 | } /* else - impossible (caught in the first pass): |
1512 | bb_error_msg_and_die("invalid argument '%s'", arg); */ | 1644 | bb_error_msg_and_die("invalid argument '%s'", arg); */ |
1645 | #endif | ||
1513 | } | 1646 | } |
1514 | } | 1647 | } |
1515 | 1648 | ||
1516 | if (stty_state & STTY_require_set_attr) { | 1649 | if (stty_state & STTY_require_set_attr) { |
1650 | #if !ENABLE_PLATFORM_MINGW32 | ||
1517 | struct termios new_mode; | 1651 | struct termios new_mode; |
1652 | #else | ||
1653 | if (mode.c_lflag & ECHO) | ||
1654 | mode.w_mode |= ENABLE_ECHO_INPUT; | ||
1655 | else | ||
1656 | mode.w_mode &= ~ENABLE_ECHO_INPUT; | ||
1657 | #endif | ||
1518 | 1658 | ||
1519 | if (tcsetattr(STDIN_FILENO, TCSADRAIN, &mode)) | 1659 | if (tcsetattr(STDIN_FILENO, TCSADRAIN, &mode)) |
1520 | perror_on_device_and_die("%s"); | 1660 | perror_on_device_and_die("%s"); |
1521 | 1661 | ||
1662 | #if !ENABLE_PLATFORM_MINGW32 | ||
1522 | /* POSIX (according to Zlotnick's book) tcsetattr returns zero if | 1663 | /* POSIX (according to Zlotnick's book) tcsetattr returns zero if |
1523 | it performs *any* of the requested operations. This means it | 1664 | it performs *any* of the requested operations. This means it |
1524 | can report 'success' when it has actually failed to perform | 1665 | can report 'success' when it has actually failed to perform |
@@ -1554,6 +1695,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
1554 | #endif | 1695 | #endif |
1555 | perror_on_device_and_die("%s: cannot perform all requested operations"); | 1696 | perror_on_device_and_die("%s: cannot perform all requested operations"); |
1556 | } | 1697 | } |
1698 | #endif | ||
1557 | } | 1699 | } |
1558 | 1700 | ||
1559 | return EXIT_SUCCESS; | 1701 | return EXIT_SUCCESS; |
diff --git a/coreutils/truncate.c b/coreutils/truncate.c index 8826e6b4c..87a47bb09 100644 --- a/coreutils/truncate.c +++ b/coreutils/truncate.c | |||
@@ -73,6 +73,12 @@ int truncate_main(int argc UNUSED_PARAM, char **argv) | |||
73 | * do not report error, exitcode is also 0. | 73 | * do not report error, exitcode is also 0. |
74 | */ | 74 | */ |
75 | } else { | 75 | } else { |
76 | #if ENABLE_PLATFORM_MINGW32 | ||
77 | struct stat st; | ||
78 | |||
79 | if (fstat(fd, &st) == 0 && size > st.st_size) | ||
80 | make_sparse(fd, st.st_size, size); | ||
81 | #endif | ||
76 | if (ftruncate(fd, size) == -1) { | 82 | if (ftruncate(fd, size) == -1) { |
77 | bb_perror_msg("%s: truncate", *argv); | 83 | bb_perror_msg("%s: truncate", *argv); |
78 | ret = EXIT_FAILURE; | 84 | ret = EXIT_FAILURE; |