aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/cat.c54
-rw-r--r--coreutils/chroot.c57
-rw-r--r--coreutils/date.c451
-rw-r--r--coreutils/dd.c284
-rw-r--r--coreutils/df.c119
-rw-r--r--coreutils/du.c185
-rw-r--r--coreutils/head.c134
-rw-r--r--coreutils/hostid.c8
-rw-r--r--coreutils/length.c14
-rw-r--r--coreutils/ln.c150
-rw-r--r--coreutils/logname.c22
-rw-r--r--coreutils/ls.c297
-rw-r--r--coreutils/mkdir.c133
-rw-r--r--coreutils/mkfifo.c64
-rw-r--r--coreutils/mknod.c39
-rw-r--r--coreutils/printf.c632
-rw-r--r--coreutils/pwd.c12
-rw-r--r--coreutils/rm.c102
-rw-r--r--coreutils/rmdir.c20
-rw-r--r--coreutils/sleep.c19
-rw-r--r--coreutils/sort.c385
-rw-r--r--coreutils/sync.c13
-rw-r--r--coreutils/tail.c1789
-rw-r--r--coreutils/tee.c129
-rw-r--r--coreutils/touch.c79
-rw-r--r--coreutils/tty.c25
-rw-r--r--coreutils/uname.c139
-rw-r--r--coreutils/uniq.c225
-rw-r--r--coreutils/wc.c127
-rw-r--r--coreutils/whoami.c27
-rw-r--r--coreutils/yes.c14
31 files changed, 2841 insertions, 2907 deletions
diff --git a/coreutils/cat.c b/coreutils/cat.c
index 0d32efe84..86f85fe8e 100644
--- a/coreutils/cat.c
+++ b/coreutils/cat.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini Cat implementation for busybox 3 * Mini Cat implementation for busybox
3 * 4 *
@@ -24,36 +25,37 @@
24#include <stdio.h> 25#include <stdio.h>
25 26
26 27
27static void print_file( FILE *file) 28static void print_file(FILE * file)
28{ 29{
29 int c; 30 int c;
30 while ((c = getc(file)) != EOF) 31
31 putc(c, stdout); 32 while ((c = getc(file)) != EOF)
32 fclose(file); 33 putc(c, stdout);
33 fflush(stdout); 34 fclose(file);
35 fflush(stdout);
34} 36}
35 37
36extern int cat_main(int argc, char **argv) 38extern int cat_main(int argc, char **argv)
37{ 39{
38 FILE *file; 40 FILE *file;
39 41
40 if (argc==1) { 42 if (argc == 1) {
41 print_file( stdin); 43 print_file(stdin);
42 exit( TRUE); 44 exit(TRUE);
43 } 45 }
44 46
45 if ( **(argv+1) == '-' ) { 47 if (**(argv + 1) == '-') {
46 usage ("cat [file ...]\n"); 48 usage("cat [file ...]\n");
47 } 49 }
48 argc--; 50 argc--;
49 51
50 while (argc-- > 0 && *(argv++) != '\0' && strlen(*argv) ) { 52 while (argc-- > 0 && *(argv++) != '\0' && strlen(*argv)) {
51 file = fopen(*argv, "r"); 53 file = fopen(*argv, "r");
52 if (file == NULL) { 54 if (file == NULL) {
53 perror(*argv); 55 perror(*argv);
54 exit(FALSE); 56 exit(FALSE);
57 }
58 print_file(file);
55 } 59 }
56 print_file( file); 60 exit(TRUE);
57 }
58 exit(TRUE);
59} 61}
diff --git a/coreutils/chroot.c b/coreutils/chroot.c
index 16524d92e..6a01be603 100644
--- a/coreutils/chroot.c
+++ b/coreutils/chroot.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini chroot implementation for busybox 3 * Mini chroot implementation for busybox
3 * 4 *
@@ -28,39 +29,39 @@
28 29
29 30
30static const char chroot_usage[] = "chroot NEWROOT [COMMAND...]\n\n" 31static const char chroot_usage[] = "chroot NEWROOT [COMMAND...]\n\n"
31"Run COMMAND with root directory set to NEWROOT.\n"; 32
33 "Run COMMAND with root directory set to NEWROOT.\n";
32 34
33 35
34 36
35int chroot_main(int argc, char **argv) 37int chroot_main(int argc, char **argv)
36{ 38{
37 if ( (argc < 2) || (**(argv+1) == '-') ) { 39 if ((argc < 2) || (**(argv + 1) == '-')) {
38 usage( chroot_usage); 40 usage(chroot_usage);
39 } 41 }
40 argc--; 42 argc--;
41 argv++; 43 argv++;
42 44
43 if (chroot (*argv) || (chdir ("/"))) { 45 if (chroot(*argv) || (chdir("/"))) {
44 fprintf(stderr, "chroot: cannot change root directory to %s: %s\n", 46 fprintf(stderr, "chroot: cannot change root directory to %s: %s\n",
45 *argv, strerror(errno)); 47 *argv, strerror(errno));
46 exit( FALSE); 48 exit(FALSE);
47 } 49 }
48 50
49 argc--; 51 argc--;
50 argv++; 52 argv++;
51 if (argc >= 1) { 53 if (argc >= 1) {
52 fprintf(stderr, "command: %s\n", *argv); 54 fprintf(stderr, "command: %s\n", *argv);
53 execvp (*argv, argv); 55 execvp(*argv, argv);
54 } 56 } else {
55 else { 57 char *prog;
56 char *prog;
57 prog = getenv ("SHELL");
58 if (!prog)
59 prog = "/bin/sh";
60 execlp (prog, prog, NULL);
61 }
62 fprintf(stderr, "chroot: cannot execute %s: %s\n",
63 *argv, strerror(errno));
64 exit( FALSE);
65}
66 58
59 prog = getenv("SHELL");
60 if (!prog)
61 prog = "/bin/sh";
62 execlp(prog, prog, NULL);
63 }
64 fprintf(stderr, "chroot: cannot execute %s: %s\n",
65 *argv, strerror(errno));
66 exit(FALSE);
67}
diff --git a/coreutils/date.c b/coreutils/date.c
index a3528921d..b4c3e7153 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini date implementation for busybox 3 * Mini date implementation for busybox
3 * 4 *
@@ -38,12 +39,13 @@
38 an RFC 822 complient date output for shell scripting 39 an RFC 822 complient date output for shell scripting
39 mail commands */ 40 mail commands */
40 41
41static const char date_usage[] = "date [OPTION]... [+FORMAT]\n" 42static const char date_usage[] = "date [OPTION]... [+FORMAT]\n"
42" or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n\n" 43 " or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n\n"
43"Display the current time in the given FORMAT, or set the system date.\n" 44 "Display the current time in the given FORMAT, or set the system date.\n"
44"\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n" 45 "\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n"
45"\t-s\t\tset time described by STRING\n" 46 "\t-s\t\tset time described by STRING\n"
46"\t-u\t\tprint or set Coordinated Universal Time\n"; 47
48 "\t-u\t\tprint or set Coordinated Universal Time\n";
47 49
48 50
49/* Input parsing code is always bulky - used heavy duty libc stuff as 51/* Input parsing code is always bulky - used heavy duty libc stuff as
@@ -51,240 +53,233 @@ static const char date_usage[] = "date [OPTION]... [+FORMAT]\n"
51 53
52/* Default input handling to save suprising some people */ 54/* Default input handling to save suprising some people */
53 55
54struct tm * 56struct tm *date_conv_time(struct tm *tm_time, const char *t_string)
55date_conv_time(struct tm *tm_time, const char *t_string) { 57{
56 int nr; 58 int nr;
57 59
58 nr = sscanf(t_string, "%2d%2d%2d%2d%d", 60 nr = sscanf(t_string, "%2d%2d%2d%2d%d",
59 &(tm_time->tm_mon), 61 &(tm_time->tm_mon),
60 &(tm_time->tm_mday), 62 &(tm_time->tm_mday),
61 &(tm_time->tm_hour), 63 &(tm_time->tm_hour),
62 &(tm_time->tm_min), 64 &(tm_time->tm_min), &(tm_time->tm_year));
63 &(tm_time->tm_year)); 65
64 66 if (nr < 4 || nr > 5) {
65 if(nr < 4 || nr > 5) { 67 fprintf(stderr, invalid_date, "date", t_string);
66 fprintf(stderr, invalid_date, "date", t_string); 68 exit(FALSE);
67 exit( FALSE); 69 }
68 } 70
69 71 /* correct for century - minor Y2K problem here? */
70 /* correct for century - minor Y2K problem here? */ 72 if (tm_time->tm_year >= 1900)
71 if(tm_time->tm_year >= 1900) 73 tm_time->tm_year -= 1900;
72 tm_time->tm_year -= 1900; 74 /* adjust date */
73 /* adjust date */ 75 tm_time->tm_mon -= 1;
74 tm_time->tm_mon -= 1; 76
75 77 return (tm_time);
76 return(tm_time);
77 78
78} 79}
79 80
80 81
81/* The new stuff for LRP */ 82/* The new stuff for LRP */
82 83
83struct tm * 84struct tm *date_conv_ftime(struct tm *tm_time, const char *t_string)
84date_conv_ftime(struct tm *tm_time, const char *t_string) { 85{
85 struct tm itm_time, jtm_time, ktm_time, \ 86 struct tm itm_time, jtm_time, ktm_time, ltm_time, mtm_time, ntm_time;
86 ltm_time, mtm_time, ntm_time; 87
87 88 itm_time = *tm_time;
88 itm_time = *tm_time; 89 jtm_time = *tm_time;
89 jtm_time = *tm_time; 90 ktm_time = *tm_time;
90 ktm_time = *tm_time; 91 ltm_time = *tm_time;
91 ltm_time = *tm_time; 92 mtm_time = *tm_time;
92 mtm_time = *tm_time; 93 ntm_time = *tm_time;
93 ntm_time = *tm_time; 94
94 95 /* Parse input and assign appropriately to tm_time */
95 /* Parse input and assign appropriately to tm_time */ 96
96 97 if (sscanf(t_string, "%d:%d:%d",
97 if(sscanf(t_string, "%d:%d:%d", 98 &itm_time.tm_hour, &itm_time.tm_min, &itm_time.tm_sec) == 3) {
98 &itm_time.tm_hour, 99
99 &itm_time.tm_min, 100 *tm_time = itm_time;
100 &itm_time.tm_sec) == 3 ) { 101 return (tm_time);
101 102
102 *tm_time = itm_time; 103 } else if (sscanf(t_string, "%d:%d",
103 return(tm_time); 104 &jtm_time.tm_hour, &jtm_time.tm_min) == 2) {
104 105
105 } else if (sscanf(t_string, "%d:%d", 106 *tm_time = jtm_time;
106 &jtm_time.tm_hour, 107 return (tm_time);
107 &jtm_time.tm_min) == 2) { 108
108 109 } else if (sscanf(t_string, "%d.%d-%d:%d:%d",
109 *tm_time = jtm_time; 110 &ktm_time.tm_mon,
110 return(tm_time); 111 &ktm_time.tm_mday,
111 112 &ktm_time.tm_hour,
112 } else if (sscanf(t_string, "%d.%d-%d:%d:%d", 113 &ktm_time.tm_min, &ktm_time.tm_sec) == 5) {
113 &ktm_time.tm_mon, 114
114 &ktm_time.tm_mday, 115 ktm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
115 &ktm_time.tm_hour, 116 *tm_time = ktm_time;
116 &ktm_time.tm_min, 117 return (tm_time);
117 &ktm_time.tm_sec) == 5) { 118
118 119 } else if (sscanf(t_string, "%d.%d-%d:%d",
119 ktm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 120 &ltm_time.tm_mon,
120 *tm_time = ktm_time; 121 &ltm_time.tm_mday,
121 return(tm_time); 122 &ltm_time.tm_hour, &ltm_time.tm_min) == 4) {
122 123
123 } else if (sscanf(t_string, "%d.%d-%d:%d", 124 ltm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
124 &ltm_time.tm_mon, 125 *tm_time = ltm_time;
125 &ltm_time.tm_mday, 126 return (tm_time);
126 &ltm_time.tm_hour, 127
127 &ltm_time.tm_min) == 4) { 128 } else if (sscanf(t_string, "%d.%d.%d-%d:%d:%d",
128 129 &mtm_time.tm_year,
129 ltm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 130 &mtm_time.tm_mon,
130 *tm_time = ltm_time; 131 &mtm_time.tm_mday,
131 return(tm_time); 132 &mtm_time.tm_hour,
132 133 &mtm_time.tm_min, &mtm_time.tm_sec) == 6) {
133 } else if (sscanf(t_string, "%d.%d.%d-%d:%d:%d", 134
134 &mtm_time.tm_year, 135 mtm_time.tm_year -= 1900; /* Adjust years */
135 &mtm_time.tm_mon, 136 mtm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
136 &mtm_time.tm_mday, 137 *tm_time = mtm_time;
137 &mtm_time.tm_hour, 138 return (tm_time);
138 &mtm_time.tm_min, 139
139 &mtm_time.tm_sec) == 6) { 140 } else if (sscanf(t_string, "%d.%d.%d-%d:%d",
140 141 &ntm_time.tm_year,
141 mtm_time.tm_year -= 1900; /* Adjust years */ 142 &ntm_time.tm_mon,
142 mtm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 143 &ntm_time.tm_mday,
143 *tm_time = mtm_time; 144 &ntm_time.tm_hour, &ntm_time.tm_min) == 5) {
144 return(tm_time); 145 ntm_time.tm_year -= 1900; /* Adjust years */
145 146 ntm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
146 } else if (sscanf(t_string, "%d.%d.%d-%d:%d", 147 *tm_time = ntm_time;
147 &ntm_time.tm_year, 148 return (tm_time);
148 &ntm_time.tm_mon, 149
149 &ntm_time.tm_mday, 150 }
150 &ntm_time.tm_hour, 151
151 &ntm_time.tm_min) == 5) { 152 fprintf(stderr, invalid_date, "date", t_string);
152 ntm_time.tm_year -= 1900; /* Adjust years */ 153
153 ntm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 154 exit(FALSE);
154 *tm_time = ntm_time;
155 return(tm_time);
156
157 }
158
159 fprintf(stderr, invalid_date, "date", t_string);
160
161 exit( FALSE);
162 155
163} 156}
164 157
165 158
166int 159int date_main(int argc, char **argv)
167date_main(int argc, char * * argv)
168{ 160{
169 char *date_str = NULL; 161 char *date_str = NULL;
170 char *date_fmt = NULL; 162 char *date_fmt = NULL;
171 char *t_buff; 163 char *t_buff;
172 int i; 164 int i;
173 int set_time = 0; 165 int set_time = 0;
174 int rfc822 = 0; 166 int rfc822 = 0;
175 int utc = 0; 167 int utc = 0;
176 int use_arg = 0; 168 int use_arg = 0;
177 time_t tm; 169 time_t tm;
178 struct tm tm_time; 170 struct tm tm_time;
179 171
180 /* Interpret command line args */ 172 /* Interpret command line args */
181 i = --argc; 173 i = --argc;
182 argv++; 174 argv++;
183 while (i > 0 && **argv) { 175 while (i > 0 && **argv) {
184 if (**argv == '-') { 176 if (**argv == '-') {
185 while (i>0 && *++(*argv)) switch (**argv) { 177 while (i > 0 && *++(*argv))
186 case 'R': 178 switch (**argv) {
187 rfc822 = 1; 179 case 'R':
188 break; 180 rfc822 = 1;
189 case 's': 181 break;
190 set_time = 1; 182 case 's':
191 if(date_str != NULL) usage ( date_usage); 183 set_time = 1;
192 date_str = optarg; 184 if (date_str != NULL)
193 break; 185 usage(date_usage);
194 case 'u': 186 date_str = optarg;
195 utc = 1; 187 break;
196 if (putenv ("TZ=UTC0") != 0) { 188 case 'u':
197 fprintf(stderr, memory_exhausted, "date"); 189 utc = 1;
198 exit( FALSE); 190 if (putenv("TZ=UTC0") != 0) {
191 fprintf(stderr, memory_exhausted, "date");
192 exit(FALSE);
193 }
194 /* Look ma, no break. Don't fix it either. */
195 case 'd':
196 use_arg = 1;
197 if (date_str != NULL)
198 usage(date_usage);
199 date_str = optarg;
200 break;
201 case '-':
202 usage(date_usage);
203 }
204 } else {
205 if ((date_fmt == NULL) && (strcmp(*argv, "+") == 0))
206 date_fmt = *argv;
207 else if (date_str == NULL) {
208 set_time = 1;
209 date_str = *argv;
210 } else {
211 usage(date_usage);
212 }
199 } 213 }
200 /* Look ma, no break. Don't fix it either. */ 214 i--;
201 case 'd': 215 argv++;
202 use_arg = 1;
203 if(date_str != NULL) usage ( date_usage);
204 date_str = optarg;
205 break;
206 case '-':
207 usage ( date_usage);
208 }
209 } else {
210 if ( (date_fmt == NULL) && (strcmp(*argv, "+")==0) )
211 date_fmt=*argv;
212 else if (date_str == NULL) {
213 set_time = 1;
214 date_str=*argv;
215 } else {
216 usage ( date_usage);
217 }
218 } 216 }
219 i--; 217
220 argv++; 218
221 } 219 /* Now we have parsed all the information except the date format
222 220 which depends on whether the clock is being set or read */
223 221
224 /* Now we have parsed all the information except the date format 222 time(&tm);
225 which depends on whether the clock is being set or read */ 223 memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
226 224 /* Zero out fields - take her back to midnight! */
227 time(&tm); 225 if (date_str != NULL) {
228 memcpy(&tm_time, localtime(&tm), sizeof(tm_time)); 226 tm_time.tm_sec = 0;
229 /* Zero out fields - take her back to midnight!*/ 227 tm_time.tm_min = 0;
230 if(date_str != NULL) { 228 tm_time.tm_hour = 0;
231 tm_time.tm_sec = 0; 229 }
232 tm_time.tm_min = 0; 230
233 tm_time.tm_hour = 0; 231 /* Process any date input to UNIX time since 1 Jan 1970 */
234 } 232 if (date_str != NULL) {
235 233
236 /* Process any date input to UNIX time since 1 Jan 1970 */ 234 if (strchr(date_str, ':') != NULL) {
237 if(date_str != NULL) { 235 date_conv_ftime(&tm_time, date_str);
238 236 } else {
239 if(strchr(date_str, ':') != NULL) { 237 date_conv_time(&tm_time, date_str);
240 date_conv_ftime(&tm_time, date_str); 238 }
241 } else { 239
242 date_conv_time(&tm_time, date_str); 240 /* Correct any day of week and day of year etc fields */
243 } 241 tm = mktime(&tm_time);
244 242 if (tm < 0) {
245 /* Correct any day of week and day of year etc fields */ 243 fprintf(stderr, invalid_date, "date", date_str);
246 tm = mktime(&tm_time); 244 exit(FALSE);
247 if (tm < 0 ) { 245 }
248 fprintf(stderr, invalid_date, "date", date_str); 246
249 exit( FALSE); 247 /* if setting time, set it */
250 } 248 if (set_time) {
251 249 if (stime(&tm) < 0) {
252 /* if setting time, set it */ 250 fprintf(stderr, "date: can't set date.\n");
253 if(set_time) { 251 exit(FALSE);
254 if( stime(&tm) < 0) { 252 }
255 fprintf(stderr, "date: can't set date.\n"); 253 }
256 exit( FALSE); 254 }
257 } 255
258 } 256 /* Display output */
259 } 257
260 258 /* Deal with format string */
261 /* Display output */ 259 if (date_fmt == NULL) {
262 260 date_fmt = (rfc822
263 /* Deal with format string */ 261 ? (utc
264 if(date_fmt == NULL) { 262 ? "%a, %_d %b %Y %H:%M:%S GMT"
265 date_fmt = (rfc822 263 : "%a, %_d %b %Y %H:%M:%S %z")
266 ? (utc 264 : "%a %b %e %H:%M:%S %Z %Y");
267 ? "%a, %_d %b %Y %H:%M:%S GMT" 265
268 : "%a, %_d %b %Y %H:%M:%S %z") 266 } else if (*date_fmt == '\0') {
269 : "%a %b %e %H:%M:%S %Z %Y"); 267 /* Imitate what GNU 'date' does with NO format string! */
270 268 printf("\n");
271 } else if ( *date_fmt == '\0' ) { 269 exit(TRUE);
272 /* Imitate what GNU 'date' does with NO format string! */ 270 }
273 printf ("\n"); 271
274 exit( TRUE); 272 /* Handle special conversions */
275 } 273
276 274 if (strncmp(date_fmt, "%f", 2) == 0) {
277 /* Handle special conversions */ 275 date_fmt = "%Y.%m.%d-%H:%M:%S";
278 276 }
279 if( strncmp( date_fmt, "%f", 2) == 0 ) { 277
280 date_fmt = "%Y.%m.%d-%H:%M:%S"; 278 /* Print OUTPUT (after ALL that!) */
281 } 279 t_buff = malloc(201);
282 280 strftime(t_buff, 200, date_fmt, &tm_time);
283 /* Print OUTPUT (after ALL that!) */ 281 printf("%s\n", t_buff);
284 t_buff = malloc(201); 282
285 strftime(t_buff, 200, date_fmt, &tm_time); 283 exit(TRUE);
286 printf("%s\n", t_buff);
287
288 exit( TRUE);
289 284
290} 285}
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 3e1024a60..0d5b3e8ab 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini dd implementation for busybox 3 * Mini dd implementation for busybox
3 * 4 *
@@ -40,164 +41,159 @@ typedef unsigned long long int uintmax_t;
40#endif 41#endif
41 42
42static const char dd_usage[] = 43static const char dd_usage[] =
43"dd [if=name] [of=name] [bs=n] [count=n] [skip=n] [seek=n]\n\n" 44 "dd [if=name] [of=name] [bs=n] [count=n] [skip=n] [seek=n]\n\n"
44"Copy a file, converting and formatting according to options\n\n" 45 "Copy a file, converting and formatting according to options\n\n"
45"\tif=FILE\tread from FILE instead of stdin\n" 46 "\tif=FILE\tread from FILE instead of stdin\n"
46"\tof=FILE\twrite to FILE instead of stdout\n" 47 "\tof=FILE\twrite to FILE instead of stdout\n"
47"\tbs=n\tread and write n bytes at a time\n" 48 "\tbs=n\tread and write n bytes at a time\n"
48"\tcount=n\tcopy only n input blocks\n" 49 "\tcount=n\tcopy only n input blocks\n"
49"\tskip=n\tskip n input blocks\n" 50 "\tskip=n\tskip n input blocks\n"
50"\tseek=n\tskip n output blocks\n" 51 "\tseek=n\tskip n output blocks\n"
51"\n"
52"Numbers may be suffixed by w (x2), k (x1024), b (x512), or M (x1024^2)\n";
53 52
53 "\n"
54 "Numbers may be suffixed by w (x2), k (x1024), b (x512), or M (x1024^2)\n";
54 55
55 56
56extern int dd_main (int argc, char **argv) 57
58extern int dd_main(int argc, char **argv)
57{ 59{
58 const char *inFile = NULL; 60 const char *inFile = NULL;
59 const char *outFile = NULL; 61 const char *outFile = NULL;
60 char *cp; 62 char *cp;
61 int inFd; 63 int inFd;
62 int outFd; 64 int outFd;
63 int inCc = 0; 65 int inCc = 0;
64 int outCc; 66 int outCc;
65 long blockSize = 512; 67 long blockSize = 512;
66 uintmax_t skipBlocks = 0; 68 uintmax_t skipBlocks = 0;
67 uintmax_t seekBlocks = 0; 69 uintmax_t seekBlocks = 0;
68 uintmax_t count = (uintmax_t)-1; 70 uintmax_t count = (uintmax_t) - 1;
69 uintmax_t intotal; 71 uintmax_t intotal;
70 uintmax_t outTotal; 72 uintmax_t outTotal;
71 unsigned char *buf; 73 unsigned char *buf;
72 74
73 argc--; 75 argc--;
74 argv++; 76 argv++;
75
76 /* Parse any options */
77 while (argc) {
78 if (inFile == NULL && (strncmp(*argv, "if", 2) == 0))
79 inFile=((strchr(*argv, '='))+1);
80 else if (outFile == NULL && (strncmp(*argv, "of", 2) == 0))
81 outFile=((strchr(*argv, '='))+1);
82 else if (strncmp("count", *argv, 5) == 0) {
83 count = getNum ((strchr(*argv, '='))+1);
84 if (count <= 0) {
85 fprintf (stderr, "Bad count value %s\n", *argv);
86 goto usage;
87 }
88 }
89 else if (strncmp(*argv, "bs", 2) == 0) {
90 blockSize = getNum ((strchr(*argv, '='))+1);
91 if (blockSize <= 0) {
92 fprintf (stderr, "Bad block size value %s\n", *argv);
93 goto usage;
94 }
95 }
96 else if (strncmp(*argv, "skip", 4) == 0) {
97 skipBlocks = getNum ((strchr(*argv, '='))+1);
98 if (skipBlocks <= 0) {
99 fprintf (stderr, "Bad skip value %s\n", *argv);
100 goto usage;
101 }
102 77
78 /* Parse any options */
79 while (argc) {
80 if (inFile == NULL && (strncmp(*argv, "if", 2) == 0))
81 inFile = ((strchr(*argv, '=')) + 1);
82 else if (outFile == NULL && (strncmp(*argv, "of", 2) == 0))
83 outFile = ((strchr(*argv, '=')) + 1);
84 else if (strncmp("count", *argv, 5) == 0) {
85 count = getNum((strchr(*argv, '=')) + 1);
86 if (count <= 0) {
87 fprintf(stderr, "Bad count value %s\n", *argv);
88 goto usage;
89 }
90 } else if (strncmp(*argv, "bs", 2) == 0) {
91 blockSize = getNum((strchr(*argv, '=')) + 1);
92 if (blockSize <= 0) {
93 fprintf(stderr, "Bad block size value %s\n", *argv);
94 goto usage;
95 }
96 } else if (strncmp(*argv, "skip", 4) == 0) {
97 skipBlocks = getNum((strchr(*argv, '=')) + 1);
98 if (skipBlocks <= 0) {
99 fprintf(stderr, "Bad skip value %s\n", *argv);
100 goto usage;
101 }
102
103 } else if (strncmp(*argv, "seek", 4) == 0) {
104 seekBlocks = getNum((strchr(*argv, '=')) + 1);
105 if (seekBlocks <= 0) {
106 fprintf(stderr, "Bad seek value %s\n", *argv);
107 goto usage;
108 }
109
110 } else {
111 goto usage;
112 }
113 argc--;
114 argv++;
103 } 115 }
104 else if (strncmp(*argv, "seek", 4) == 0) {
105 seekBlocks = getNum ((strchr(*argv, '='))+1);
106 if (seekBlocks <= 0) {
107 fprintf (stderr, "Bad seek value %s\n", *argv);
108 goto usage;
109 }
110 116
117 buf = malloc(blockSize);
118 if (buf == NULL) {
119 fprintf(stderr, "Cannot allocate buffer\n");
120 exit(FALSE);
111 } 121 }
112 else { 122
113 goto usage; 123 intotal = 0;
124 outTotal = 0;
125
126 if (inFile == NULL)
127 inFd = fileno(stdin);
128 else
129 inFd = open(inFile, 0);
130
131 if (inFd < 0) {
132 perror(inFile);
133 free(buf);
134 exit(FALSE);
114 } 135 }
115 argc--; 136
116 argv++; 137 if (outFile == NULL)
117 } 138 outFd = fileno(stdout);
118 139 else
119 buf = malloc (blockSize); 140 outFd = open(outFile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
120 if (buf == NULL) { 141
121 fprintf (stderr, "Cannot allocate buffer\n"); 142 if (outFd < 0) {
122 exit( FALSE); 143 perror(outFile);
123 } 144 close(inFd);
124 145 free(buf);
125 intotal = 0; 146 exit(FALSE);
126 outTotal = 0;
127
128 if (inFile == NULL)
129 inFd = fileno(stdin);
130 else
131 inFd = open (inFile, 0);
132
133 if (inFd < 0) {
134 perror (inFile);
135 free (buf);
136 exit( FALSE);
137 }
138
139 if (outFile == NULL)
140 outFd = fileno(stdout);
141 else
142 outFd = open(outFile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
143
144 if (outFd < 0) {
145 perror (outFile);
146 close (inFd);
147 free (buf);
148 exit( FALSE);
149 }
150
151 lseek(inFd, skipBlocks*blockSize, SEEK_SET);
152 lseek(outFd, seekBlocks*blockSize, SEEK_SET);
153 //
154 //TODO: Convert to using fullRead & fullWrite
155 // from utility.c
156 // -Erik
157 while (outTotal < count * blockSize) {
158 inCc = read (inFd, buf, blockSize);
159 if (inCc < 0) {
160 perror (inFile);
161 goto cleanup;
162 } else if (inCc == 0) {
163 goto cleanup;
164 } 147 }
165 intotal += inCc; 148
166 cp = buf; 149 lseek(inFd, skipBlocks * blockSize, SEEK_SET);
167 150 lseek(outFd, seekBlocks * blockSize, SEEK_SET);
168 while (intotal > outTotal) { 151 //
169 if (outTotal + inCc > count * blockSize) 152 //TODO: Convert to using fullRead & fullWrite
170 inCc = count * blockSize - outTotal; 153 // from utility.c
171 outCc = write (outFd, cp, inCc); 154 // -Erik
172 if (outCc < 0) { 155 while (outTotal < count * blockSize) {
173 perror (outFile); 156 inCc = read(inFd, buf, blockSize);
174 goto cleanup; 157 if (inCc < 0) {
175 } else if (outCc == 0) { 158 perror(inFile);
176 goto cleanup; 159 goto cleanup;
177 } 160 } else if (inCc == 0) {
178 161 goto cleanup;
179 inCc -= outCc; 162 }
180 cp += outCc; 163 intotal += inCc;
181 outTotal += outCc; 164 cp = buf;
165
166 while (intotal > outTotal) {
167 if (outTotal + inCc > count * blockSize)
168 inCc = count * blockSize - outTotal;
169 outCc = write(outFd, cp, inCc);
170 if (outCc < 0) {
171 perror(outFile);
172 goto cleanup;
173 } else if (outCc == 0) {
174 goto cleanup;
175 }
176
177 inCc -= outCc;
178 cp += outCc;
179 outTotal += outCc;
180 }
182 } 181 }
183 }
184 182
185 if (inCc < 0) 183 if (inCc < 0)
186 perror (inFile); 184 perror(inFile);
187 185
188 cleanup: 186 cleanup:
189 close (inFd); 187 close(inFd);
190 close (outFd); 188 close(outFd);
191 free (buf); 189 free(buf);
192 190
193 printf ("%ld+%d records in\n", (long)(intotal / blockSize), 191 printf("%ld+%d records in\n", (long) (intotal / blockSize),
194 (intotal % blockSize) != 0); 192 (intotal % blockSize) != 0);
195 printf ("%ld+%d records out\n", (long)(outTotal / blockSize), 193 printf("%ld+%d records out\n", (long) (outTotal / blockSize),
196 (outTotal % blockSize) != 0); 194 (outTotal % blockSize) != 0);
197 exit( TRUE); 195 exit(TRUE);
198 usage: 196 usage:
199 197
200 usage( dd_usage); 198 usage(dd_usage);
201} 199}
202
203
diff --git a/coreutils/df.c b/coreutils/df.c
index 24c94a246..43d5d26e7 100644
--- a/coreutils/df.c
+++ b/coreutils/df.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini df implementation for busybox 3 * Mini df implementation for busybox
3 * 4 *
@@ -29,81 +30,81 @@
29#include <fstab.h> 30#include <fstab.h>
30 31
31static const char df_usage[] = "df [filesystem ...]\n" 32static const char df_usage[] = "df [filesystem ...]\n"
32 "\n" "\tPrint the filesystem space used and space available.\n";
33 33
34extern const char mtab_file[]; /* Defined in utility.c */ 34 "\n" "\tPrint the filesystem space used and space available.\n";
35
36extern const char mtab_file[]; /* Defined in utility.c */
35 37
36static int df(char *device, const char *mountPoint) 38static int df(char *device, const char *mountPoint)
37{ 39{
38 struct statfs s; 40 struct statfs s;
39 long blocks_used; 41 long blocks_used;
40 long blocks_percent_used; 42 long blocks_percent_used;
41 struct fstab* fstabItem; 43 struct fstab *fstabItem;
42
43 if (statfs(mountPoint, &s) != 0) {
44 perror(mountPoint);
45 return FALSE;
46 }
47 44
48 if (s.f_blocks > 0) { 45 if (statfs(mountPoint, &s) != 0) {
49 blocks_used = s.f_blocks - s.f_bfree; 46 perror(mountPoint);
50 blocks_percent_used = (long) 47 return FALSE;
51 (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
52 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */
53 if (strcmp (device, "/dev/root") == 0) {
54 fstabItem = getfsfile ("/");
55 if (fstabItem != NULL)
56 device = fstabItem->fs_spec;
57 } 48 }
58 printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",
59 device,
60 (long) (s.f_blocks * (s.f_bsize / 1024.0)),
61 (long) ((s.f_blocks - s.f_bfree) * (s.f_bsize / 1024.0)),
62 (long) (s.f_bavail * (s.f_bsize / 1024.0)),
63 blocks_percent_used, mountPoint);
64 49
65 } 50 if (s.f_blocks > 0) {
51 blocks_used = s.f_blocks - s.f_bfree;
52 blocks_percent_used = (long)
53 (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
54 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */
55 if (strcmp(device, "/dev/root") == 0) {
56 fstabItem = getfsfile("/");
57 if (fstabItem != NULL)
58 device = fstabItem->fs_spec;
59 }
60 printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",
61 device,
62 (long) (s.f_blocks * (s.f_bsize / 1024.0)),
63 (long) ((s.f_blocks - s.f_bfree) * (s.f_bsize / 1024.0)),
64 (long) (s.f_bavail * (s.f_bsize / 1024.0)),
65 blocks_percent_used, mountPoint);
66
67 }
66 68
67 return TRUE; 69 return TRUE;
68} 70}
69 71
70extern int df_main(int argc, char **argv) 72extern int df_main(int argc, char **argv)
71{ 73{
72 printf("%-20s %-14s %s %s %s %s\n", "Filesystem", 74 printf("%-20s %-14s %s %s %s %s\n", "Filesystem",
73 "1k-blocks", "Used", "Available", "Use%", "Mounted on"); 75 "1k-blocks", "Used", "Available", "Use%", "Mounted on");
74 76
75 if (argc > 1) { 77 if (argc > 1) {
76 struct mntent *mountEntry; 78 struct mntent *mountEntry;
77 int status; 79 int status;
78 80
79 while (argc > 1) { 81 while (argc > 1) {
80 if ((mountEntry = findMountPoint(argv[1], mtab_file)) == 82 if ((mountEntry = findMountPoint(argv[1], mtab_file)) == 0) {
81 0) { 83 fprintf(stderr, "%s: can't find mount point.\n", argv[1]);
82 fprintf(stderr, "%s: can't find mount point.\n", argv[1]); 84 exit(FALSE);
83 exit( FALSE); 85 }
84 } 86 status = df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
85 status = df(mountEntry->mnt_fsname, mountEntry->mnt_dir); 87 if (status != 0)
86 if (status != 0) 88 exit(status);
87 exit( status); 89 argc--;
88 argc--; 90 argv++;
89 argv++; 91 }
90 } 92 exit(TRUE);
91 exit( TRUE); 93 } else {
92 } else { 94 FILE *mountTable;
93 FILE *mountTable; 95 struct mntent *mountEntry;
94 struct mntent *mountEntry;
95 96
96 mountTable = setmntent(mtab_file, "r"); 97 mountTable = setmntent(mtab_file, "r");
97 if (mountTable == 0) { 98 if (mountTable == 0) {
98 perror(mtab_file); 99 perror(mtab_file);
99 exit(FALSE); 100 exit(FALSE);
100 } 101 }
101 102
102 while ((mountEntry = getmntent(mountTable))) { 103 while ((mountEntry = getmntent(mountTable))) {
103 df(mountEntry->mnt_fsname, mountEntry->mnt_dir); 104 df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
105 }
106 endmntent(mountTable);
104 } 107 }
105 endmntent(mountTable);
106 }
107 108
108 exit( TRUE); 109 exit(TRUE);
109} 110}
diff --git a/coreutils/du.c b/coreutils/du.c
index e2cf3f7c0..7151e3a9c 100644
--- a/coreutils/du.c
+++ b/coreutils/du.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini du implementation for busybox 3 * Mini du implementation for busybox
3 * 4 *
@@ -31,119 +32,121 @@
31#include <dirent.h> 32#include <dirent.h>
32#include <stdio.h> 33#include <stdio.h>
33#include <errno.h> 34#include <errno.h>
34#include <sys/param.h> /* for PATH_MAX */ 35#include <sys/param.h> /* for PATH_MAX */
35 36
36typedef void (Display)(long, char *); 37typedef void (Display) (long, char *);
37 38
38static const char du_usage[] = 39static const char du_usage[] =
39"du [OPTION]... [FILE]...\n\n"
40"\t-s\tdisplay only a total for each argument\n"
41;
42 40
43static int du_depth = 0; 41 "du [OPTION]... [FILE]...\n\n"
42 "\t-s\tdisplay only a total for each argument\n";
44 43
45static Display *print; 44static int du_depth = 0;
46 45
47static void 46static Display *print;
48print_normal(long size, char *filename) 47
48static void print_normal(long size, char *filename)
49{ 49{
50 fprintf(stdout, "%-7ld %s\n", size, filename); 50 fprintf(stdout, "%-7ld %s\n", size, filename);
51} 51}
52 52
53static void 53static void print_summary(long size, char *filename)
54print_summary(long size, char *filename)
55{ 54{
56 if (du_depth == 1) { 55 if (du_depth == 1) {
57 print_normal(size, filename); 56 print_normal(size, filename);
58 } 57 }
59} 58}
60 59
61 60
62/* tiny recursive du */ 61/* tiny recursive du */
63static long 62static long du(char *filename)
64du(char *filename)
65{ 63{
66 struct stat statbuf; 64 struct stat statbuf;
67 long sum; 65 long sum;
68 66
69 if ((lstat(filename, &statbuf)) != 0) { 67 if ((lstat(filename, &statbuf)) != 0) {
70 fprintf(stdout, "du: %s: %s\n", filename, strerror(errno)); 68 fprintf(stdout, "du: %s: %s\n", filename, strerror(errno));
71 return 0; 69 return 0;
72 }
73
74 du_depth++;
75 sum = statbuf.st_blocks;
76
77 if (S_ISDIR(statbuf.st_mode)) {
78 DIR *dir;
79 struct dirent *entry;
80
81 dir = opendir(filename);
82 if (!dir) { return 0; }
83 while ((entry = readdir(dir))) {
84 char newfile[PATH_MAX + 1];
85 char *name = entry->d_name;
86
87 if ( (strcmp(name, "..") == 0)
88 || (strcmp(name, ".") == 0))
89 { continue; }
90
91 if (strlen(filename) + strlen(name) + 1 > PATH_MAX) {
92 fprintf(stderr, name_too_long, "du");
93 return 0;
94 }
95 sprintf(newfile, "%s/%s", filename, name);
96
97 sum += du(newfile);
98 } 70 }
99 closedir(dir); 71
100 print(sum, filename); 72 du_depth++;
101 } 73 sum = statbuf.st_blocks;
102 du_depth--; 74
103 return sum; 75 if (S_ISDIR(statbuf.st_mode)) {
76 DIR *dir;
77 struct dirent *entry;
78
79 dir = opendir(filename);
80 if (!dir) {
81 return 0;
82 }
83 while ((entry = readdir(dir))) {
84 char newfile[PATH_MAX + 1];
85 char *name = entry->d_name;
86
87 if ((strcmp(name, "..") == 0)
88 || (strcmp(name, ".") == 0)) {
89 continue;
90 }
91
92 if (strlen(filename) + strlen(name) + 1 > PATH_MAX) {
93 fprintf(stderr, name_too_long, "du");
94 return 0;
95 }
96 sprintf(newfile, "%s/%s", filename, name);
97
98 sum += du(newfile);
99 }
100 closedir(dir);
101 print(sum, filename);
102 }
103 du_depth--;
104 return sum;
104} 105}
105 106
106int 107int du_main(int argc, char **argv)
107du_main(int argc, char **argv)
108{ 108{
109 int i; 109 int i;
110 char opt; 110 char opt;
111 111
112 /* default behaviour */ 112 /* default behaviour */
113 print = print_normal; 113 print = print_normal;
114 114
115 /* parse argv[] */ 115 /* parse argv[] */
116 for (i = 1; i < argc; i++) { 116 for (i = 1; i < argc; i++) {
117 if (argv[i][0] == '-') { 117 if (argv[i][0] == '-') {
118 opt = argv[i][1]; 118 opt = argv[i][1];
119 switch (opt) { 119 switch (opt) {
120 case 's': 120 case 's':
121 print = print_summary; 121 print = print_summary;
122 break; 122 break;
123 case 'h': 123 case 'h':
124 usage(du_usage); 124 usage(du_usage);
125 break; 125 break;
126 default: 126 default:
127 fprintf(stderr, "du: invalid option -- %c\n", opt); 127 fprintf(stderr, "du: invalid option -- %c\n", opt);
128 usage(du_usage); 128 usage(du_usage);
129 } 129 }
130 } else { 130 } else {
131 break; 131 break;
132 }
132 } 133 }
133 }
134 134
135 /* go through remaining args (if any) */ 135 /* go through remaining args (if any) */
136 if (i >= argc) { 136 if (i >= argc) {
137 du("."); 137 du(".");
138 } else { 138 } else {
139 long sum; 139 long sum;
140 for ( ; i < argc; i++) { 140
141 sum = du(argv[i]); 141 for (; i < argc; i++) {
142 if ((sum) && (isDirectory(argv[i], FALSE))) { print_normal(sum, argv[i]); } 142 sum = du(argv[i]);
143 if ((sum) && (isDirectory(argv[i], FALSE))) {
144 print_normal(sum, argv[i]);
145 }
146 }
143 } 147 }
144 }
145 148
146 exit(0); 149 exit(0);
147} 150}
148 151
149/* $Id: du.c,v 1.10 2000/02/07 05:29:42 erik Exp $ */ 152/* $Id: du.c,v 1.11 2000/02/08 19:58:47 erik Exp $ */
diff --git a/coreutils/head.c b/coreutils/head.c
index b80d06580..82a73de2a 100644
--- a/coreutils/head.c
+++ b/coreutils/head.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini head implementation for busybox 3 * Mini head implementation for busybox
3 * 4 *
@@ -26,83 +27,86 @@
26#include <stdio.h> 27#include <stdio.h>
27 28
28const char head_usage[] = 29const char head_usage[] =
29"head [OPTION] [FILE]...\n\n" 30 "head [OPTION] [FILE]...\n\n"
30"Print first 10 lines of each FILE to standard output.\n" 31 "Print first 10 lines of each FILE to standard output.\n"
31"With more than one FILE, precede each with a header giving the\n" 32 "With more than one FILE, precede each with a header giving the\n"
32"file name. With no FILE, or when FILE is -, read standard input.\n\n" 33 "file name. With no FILE, or when FILE is -, read standard input.\n\n"
33"Options:\n"
34"\t-n NUM\t\tPrint first NUM lines instead of first 10\n";
35 34
36int 35 "Options:\n" "\t-n NUM\t\tPrint first NUM lines instead of first 10\n";
37head(int len, FILE *src) 36
37int head(int len, FILE * src)
38{ 38{
39 int i; 39 int i;
40 char buffer[1024]; 40 char buffer[1024];
41 41
42 for (i = 0; i < len; i++) { 42 for (i = 0; i < len; i++) {
43 fgets(buffer, 1024, src); 43 fgets(buffer, 1024, src);
44 if (feof(src)) { break; } 44 if (feof(src)) {
45 fputs(buffer, stdout); 45 break;
46 } 46 }
47 return 0; 47 fputs(buffer, stdout);
48 }
49 return 0;
48} 50}
49 51
50/* BusyBoxed head(1) */ 52/* BusyBoxed head(1) */
51int 53int head_main(int argc, char **argv)
52head_main(int argc, char **argv)
53{ 54{
54 char opt; 55 char opt;
55 int len = 10, tmplen, i; 56 int len = 10, tmplen, i;
56 57
57 /* parse argv[] */ 58 /* parse argv[] */
58 for (i = 1; i < argc; i++) { 59 for (i = 1; i < argc; i++) {
59 if (argv[i][0] == '-') { 60 if (argv[i][0] == '-') {
60 opt = argv[i][1]; 61 opt = argv[i][1];
61 switch (opt) { 62 switch (opt) {
62 case 'n': 63 case 'n':
63 tmplen = 0; 64 tmplen = 0;
64 if (++i < argc) 65 if (++i < argc)
65 tmplen = atoi(argv[i]); 66 tmplen = atoi(argv[i]);
66 if (tmplen < 1) 67 if (tmplen < 1)
67 usage(head_usage); 68 usage(head_usage);
68 len = tmplen; 69 len = tmplen;
69 break; 70 break;
70 case '-': 71 case '-':
71 case 'h': 72 case 'h':
72 usage(head_usage); 73 usage(head_usage);
73 default: 74 default:
74 fprintf(stderr, "head: invalid option -- %c\n", opt); 75 fprintf(stderr, "head: invalid option -- %c\n", opt);
75 usage(head_usage); 76 usage(head_usage);
76 } 77 }
77 } else { 78 } else {
78 break; 79 break;
80 }
79 } 81 }
80 }
81 82
82 /* get rest of argv[] or stdin if nothing's left */ 83 /* get rest of argv[] or stdin if nothing's left */
83 if (i >= argc) { 84 if (i >= argc) {
84 head(len, stdin); 85 head(len, stdin);
85 86
86 } else { 87 } else {
87 int need_headers = ((argc - i) > 1); 88 int need_headers = ((argc - i) > 1);
88 for ( ; i < argc; i++) { 89
89 FILE *src; 90 for (; i < argc; i++) {
90 src = fopen(argv[i], "r"); 91 FILE *src;
91 if (!src) { 92
92 fprintf(stderr,"head: %s: %s\n", argv[i], strerror(errno)); 93 src = fopen(argv[i], "r");
93 } else { 94 if (!src) {
94 /* emulating GNU behaviour */ 95 fprintf(stderr, "head: %s: %s\n", argv[i],
95 if (need_headers) { 96 strerror(errno));
96 fprintf(stdout, "==> %s <==\n", argv[i]); 97 } else {
97 } 98 /* emulating GNU behaviour */
98 head(len, src); 99 if (need_headers) {
99 if (i < argc - 1) { 100 fprintf(stdout, "==> %s <==\n", argv[i]);
100 fprintf(stdout, "\n"); 101 }
102 head(len, src);
103 if (i < argc - 1) {
104 fprintf(stdout, "\n");
105 }
106 }
101 } 107 }
102 }
103 } 108 }
104 } 109 exit(0);
105 exit(0);
106} 110}
107 111
108/* $Id: head.c,v 1.7 2000/02/07 05:29:42 erik Exp $ */ 112/* $Id: head.c,v 1.8 2000/02/08 19:58:47 erik Exp $ */
diff --git a/coreutils/hostid.c b/coreutils/hostid.c
index f8d5862ae..9e503e598 100644
--- a/coreutils/hostid.c
+++ b/coreutils/hostid.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini hostid implementation for busybox 3 * Mini hostid implementation for busybox
3 * 4 *
@@ -22,7 +23,8 @@
22#include "internal.h" 23#include "internal.h"
23#include <stdio.h> 24#include <stdio.h>
24 25
25extern int hostid_main(int argc, char **argv) { 26extern int hostid_main(int argc, char **argv)
26 printf ("%lx\n", gethostid()); 27{
27 exit( TRUE); 28 printf("%lx\n", gethostid());
29 exit(TRUE);
28} 30}
diff --git a/coreutils/length.c b/coreutils/length.c
index 2c83cdfd2..00e5a171b 100644
--- a/coreutils/length.c
+++ b/coreutils/length.c
@@ -1,14 +1,14 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2#include <stdlib.h> 3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
4#include <stdio.h> 5#include <stdio.h>
5 6
6extern int 7extern int length_main(int argc, char **argv)
7length_main(int argc, char * * argv)
8{ 8{
9 if ( argc != 2 || **(argv+1) == '-' ) { 9 if (argc != 2 || **(argv + 1) == '-') {
10 usage("length string\n"); 10 usage("length string\n");
11 } 11 }
12 printf("%d\n", strlen(argv[1])); 12 printf("%d\n", strlen(argv[1]));
13 return( TRUE); 13 return (TRUE);
14} 14}
diff --git a/coreutils/ln.c b/coreutils/ln.c
index f20b340ea..bc51cb0d5 100644
--- a/coreutils/ln.c
+++ b/coreutils/ln.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini ln implementation for busybox 3 * Mini ln implementation for busybox
3 * 4 *
@@ -30,15 +31,16 @@
30#include <stdio.h> 31#include <stdio.h>
31#include <dirent.h> 32#include <dirent.h>
32#include <errno.h> 33#include <errno.h>
33#include <sys/param.h> /* for PATH_MAX */ 34#include <sys/param.h> /* for PATH_MAX */
34 35
35static const char ln_usage[] = 36static const char ln_usage[] =
36 "ln [OPTION] TARGET... LINK_NAME|DIRECTORY\n\n" 37 "ln [OPTION] TARGET... LINK_NAME|DIRECTORY\n\n"
37 "Create a link named LINK_NAME or DIRECTORY to the specified TARGET\n\n" 38 "Create a link named LINK_NAME or DIRECTORY to the specified TARGET\n\n"
38 "Options:\n" 39 "Options:\n"
39 "\t-s\tmake symbolic links instead of hard links\n" 40 "\t-s\tmake symbolic links instead of hard links\n"
40 "\t-f\tremove existing destination files\n" 41
41 "\t-n\tno dereference symlinks - treat like normal file\n"; 42 "\t-f\tremove existing destination files\n"
43 "\t-n\tno dereference symlinks - treat like normal file\n";
42 44
43static int symlinkFlag = FALSE; 45static int symlinkFlag = FALSE;
44static int removeoldFlag = FALSE; 46static int removeoldFlag = FALSE;
@@ -46,83 +48,83 @@ static int followLinks = TRUE;
46 48
47extern int ln_main(int argc, char **argv) 49extern int ln_main(int argc, char **argv)
48{ 50{
49 char *linkName; 51 char *linkName;
50 int linkIntoDirFlag; 52 int linkIntoDirFlag;
51 53
52 if (argc < 3) { 54 if (argc < 3) {
53 usage (ln_usage); 55 usage(ln_usage);
54 } 56 }
55 argc--;
56 argv++;
57
58 /* Parse any options */
59 while (**argv == '-') {
60 while (*++(*argv))
61 switch (**argv) {
62 case 's':
63 symlinkFlag = TRUE;
64 break;
65 case 'f':
66 removeoldFlag = TRUE;
67 break;
68 case 'n':
69 followLinks = FALSE;
70 break;
71 default:
72 usage (ln_usage);
73 }
74 argc--; 57 argc--;
75 argv++; 58 argv++;
76 }
77
78 linkName = argv[argc - 1];
79
80 if (strlen(linkName) > PATH_MAX) {
81 fprintf(stderr, name_too_long, "ln");
82 exit FALSE;
83 }
84 59
85 linkIntoDirFlag = isDirectory(linkName, TRUE); 60 /* Parse any options */
86 61 while (**argv == '-') {
87 if ((argc > 3) && !linkIntoDirFlag) { 62 while (*++(*argv))
88 fprintf(stderr, not_a_directory, "ln", linkName); 63 switch (**argv) {
89 exit FALSE; 64 case 's':
90 } 65 symlinkFlag = TRUE;
66 break;
67 case 'f':
68 removeoldFlag = TRUE;
69 break;
70 case 'n':
71 followLinks = FALSE;
72 break;
73 default:
74 usage(ln_usage);
75 }
76 argc--;
77 argv++;
78 }
91 79
92 while (argc-- >= 2) { 80 linkName = argv[argc - 1];
93 char srcName[PATH_MAX + 1];
94 int nChars, status;
95 81
96 if (strlen(*argv) > PATH_MAX) { 82 if (strlen(linkName) > PATH_MAX) {
97 fprintf(stderr, name_too_long, "ln"); 83 fprintf(stderr, name_too_long, "ln");
98 exit FALSE; 84 exit FALSE;
99 } 85 }
100 86
101 if (followLinks == FALSE) { 87 linkIntoDirFlag = isDirectory(linkName, TRUE);
102 strcpy(srcName, *argv);
103 } else {
104 /* Warning! This can silently truncate if > PATH_MAX, but
105 I don't think that there can be one > PATH_MAX anyway. */
106 nChars = readlink(*argv, srcName, PATH_MAX);
107 srcName[nChars] = '\0';
108 }
109 88
110 if (removeoldFlag == TRUE) { 89 if ((argc > 3) && !linkIntoDirFlag) {
111 status = ( unlink(linkName) && errno != ENOENT ); 90 fprintf(stderr, not_a_directory, "ln", linkName);
112 if (status != 0) {
113 perror(linkName);
114 exit FALSE; 91 exit FALSE;
115 }
116 } 92 }
117 93
118 if (symlinkFlag == TRUE) 94 while (argc-- >= 2) {
119 status = symlink(*argv, linkName); 95 char srcName[PATH_MAX + 1];
120 else 96 int nChars, status;
121 status = link(*argv, linkName); 97
122 if (status != 0) { 98 if (strlen(*argv) > PATH_MAX) {
123 perror(linkName); 99 fprintf(stderr, name_too_long, "ln");
124 exit FALSE; 100 exit FALSE;
101 }
102
103 if (followLinks == FALSE) {
104 strcpy(srcName, *argv);
105 } else {
106 /* Warning! This can silently truncate if > PATH_MAX, but
107 I don't think that there can be one > PATH_MAX anyway. */
108 nChars = readlink(*argv, srcName, PATH_MAX);
109 srcName[nChars] = '\0';
110 }
111
112 if (removeoldFlag == TRUE) {
113 status = (unlink(linkName) && errno != ENOENT);
114 if (status != 0) {
115 perror(linkName);
116 exit FALSE;
117 }
118 }
119
120 if (symlinkFlag == TRUE)
121 status = symlink(*argv, linkName);
122 else
123 status = link(*argv, linkName);
124 if (status != 0) {
125 perror(linkName);
126 exit FALSE;
127 }
125 } 128 }
126 } 129 exit TRUE;
127 exit TRUE;
128} 130}
diff --git a/coreutils/logname.c b/coreutils/logname.c
index 5c8275ab4..182f40ed2 100644
--- a/coreutils/logname.c
+++ b/coreutils/logname.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini logname implementation for busybox 3 * Mini logname implementation for busybox
3 * 4 *
@@ -23,18 +24,21 @@
23#include <stdio.h> 24#include <stdio.h>
24 25
25static const char logname_usage[] = "logname\n\n" 26static const char logname_usage[] = "logname\n\n"
26"Print the name of the current user.\n";
27 27
28extern int logname_main(int argc, char **argv) { 28 "Print the name of the current user.\n";
29
30extern int logname_main(int argc, char **argv)
31{
29 char *cp; 32 char *cp;
30 33
31 if (argc > 1) usage (logname_usage); 34 if (argc > 1)
35 usage(logname_usage);
32 36
33 cp = getlogin (); 37 cp = getlogin();
34 if (cp) { 38 if (cp) {
35 puts (cp); 39 puts(cp);
36 exit (TRUE); 40 exit(TRUE);
37 } 41 }
38 fprintf (stderr, "%s: no login name\n", argv[0]); 42 fprintf(stderr, "%s: no login name\n", argv[0]);
39 exit (FALSE); 43 exit(FALSE);
40} 44}
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 450ea1814..f23c1e086 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * tiny-ls.c version 0.1.0: A minimalist 'ls' 3 * tiny-ls.c version 0.1.0: A minimalist 'ls'
3 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com> 4 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com>
@@ -40,18 +41,18 @@
40 * 1. requires lstat (BSD) - how do you do it without? 41 * 1. requires lstat (BSD) - how do you do it without?
41 */ 42 */
42 43
43#define TERMINAL_WIDTH 80 /* use 79 if your terminal has linefold bug */ 44#define TERMINAL_WIDTH 80 /* use 79 if your terminal has linefold bug */
44#define COLUMN_WIDTH 14 /* default if AUTOWIDTH not defined */ 45#define COLUMN_WIDTH 14 /* default if AUTOWIDTH not defined */
45#define COLUMN_GAP 2 /* includes the file type char, if present */ 46#define COLUMN_GAP 2 /* includes the file type char, if present */
46#define HAS_REWINDDIR 47#define HAS_REWINDDIR
47 48
48/************************************************************************/ 49/************************************************************************/
49 50
50#include "internal.h" 51#include "internal.h"
51#if !defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 52#if !defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
52# include <linux/types.h> 53# include <linux/types.h>
53#else 54#else
54# include <sys/types.h> 55# include <sys/types.h>
55#endif 56#endif
56#include <sys/stat.h> 57#include <sys/stat.h>
57#include <stdio.h> 58#include <stdio.h>
@@ -75,28 +76,28 @@
75#endif 76#endif
76 77
77#define FMT_AUTO 0 78#define FMT_AUTO 0
78#define FMT_LONG 1 /* one record per line, extended info */ 79#define FMT_LONG 1 /* one record per line, extended info */
79#define FMT_SINGLE 2 /* one record per line */ 80#define FMT_SINGLE 2 /* one record per line */
80#define FMT_ROWS 3 /* print across rows */ 81#define FMT_ROWS 3 /* print across rows */
81#define FMT_COLUMNS 3 /* fill columns (same, since we don't sort) */ 82#define FMT_COLUMNS 3 /* fill columns (same, since we don't sort) */
82 83
83#define TIME_MOD 0 84#define TIME_MOD 0
84#define TIME_CHANGE 1 85#define TIME_CHANGE 1
85#define TIME_ACCESS 2 86#define TIME_ACCESS 2
86 87
87#define DISP_FTYPE 1 /* show character for file type */ 88#define DISP_FTYPE 1 /* show character for file type */
88#define DISP_EXEC 2 /* show '*' if regular executable file */ 89#define DISP_EXEC 2 /* show '*' if regular executable file */
89#define DISP_HIDDEN 4 /* show files starting . (except . and ..) */ 90#define DISP_HIDDEN 4 /* show files starting . (except . and ..) */
90#define DISP_DOT 8 /* show . and .. */ 91#define DISP_DOT 8 /* show . and .. */
91#define DISP_NUMERIC 16 /* numeric uid and gid */ 92#define DISP_NUMERIC 16 /* numeric uid and gid */
92#define DISP_FULLTIME 32 /* show extended time display */ 93#define DISP_FULLTIME 32 /* show extended time display */
93#define DIR_NOLIST 64 /* show directory as itself, not contents */ 94#define DIR_NOLIST 64 /* show directory as itself, not contents */
94#define DISP_DIRNAME 128 /* show directory name (for internal use) */ 95#define DISP_DIRNAME 128 /* show directory name (for internal use) */
95#define DIR_RECURSE 256 /* -R (not yet implemented) */ 96#define DIR_RECURSE 256 /* -R (not yet implemented) */
96 97
97static unsigned char display_fmt = FMT_AUTO; 98static unsigned char display_fmt = FMT_AUTO;
98static unsigned short opts = 0; 99static unsigned short opts = 0;
99static unsigned short column = 0; 100static unsigned short column = 0;
100 101
101#ifdef BB_FEATURE_AUTOWIDTH 102#ifdef BB_FEATURE_AUTOWIDTH
102static unsigned short terminal_width = 0, column_width = 0; 103static unsigned short terminal_width = 0, column_width = 0;
@@ -113,13 +114,14 @@ static unsigned char time_fmt = TIME_MOD;
113 114
114static void writenum(long val, short minwidth) 115static void writenum(long val, short minwidth)
115{ 116{
116 char scratch[128]; 117 char scratch[128];
117 118
118 char *p = scratch + sizeof(scratch); 119 char *p = scratch + sizeof(scratch);
119 short len = 0; 120 short len = 0;
120 short neg = (val < 0); 121 short neg = (val < 0);
121 122
122 if (neg) val = -val; 123 if (neg)
124 val = -val;
123 do 125 do
124 *--p = (val % 10) + '0', len++, val /= 10; 126 *--p = (val % 10) + '0', len++, val /= 10;
125 while (val); 127 while (val);
@@ -142,8 +144,9 @@ static void newline(void)
142static void tab(short col) 144static void tab(short col)
143{ 145{
144 static const char spaces[] = " "; 146 static const char spaces[] = " ";
145 #define nspaces ((sizeof spaces)-1) /* null terminator! */ 147
146 148#define nspaces ((sizeof spaces)-1) /* null terminator! */
149
147 short n = col - column; 150 short n = col - column;
148 151
149 if (n > 0) { 152 if (n > 0) {
@@ -155,7 +158,7 @@ static void tab(short col)
155 /* must be 1...(sizeof spaces) left */ 158 /* must be 1...(sizeof spaces) left */
156 wr(spaces, n); 159 wr(spaces, n);
157 } 160 }
158 #undef nspaces 161#undef nspaces
159} 162}
160 163
161#ifdef BB_FEATURE_LS_FILETYPES 164#ifdef BB_FEATURE_LS_FILETYPES
@@ -163,8 +166,8 @@ static char append_char(mode_t mode)
163{ 166{
164 if (!(opts & DISP_FTYPE)) 167 if (!(opts & DISP_FTYPE))
165 return '\0'; 168 return '\0';
166 if ((opts & DISP_EXEC) && S_ISREG(mode) && (mode & (S_IXUSR|S_IXGRP|S_IXOTH))) 169 if ((opts & DISP_EXEC) && S_ISREG(mode)
167 return '*'; 170 && (mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return '*';
168 return APPCHAR(mode); 171 return APPCHAR(mode);
169} 172}
170#endif 173#endif
@@ -176,89 +179,93 @@ static char append_char(mode_t mode)
176 ** 179 **
177 **/ 180 **/
178 181
179static void list_single(const char *name, struct stat *info, const char *fullname) 182static void list_single(const char *name, struct stat *info,
183 const char *fullname)
180{ 184{
181 char scratch[PATH_MAX + 1]; 185 char scratch[PATH_MAX + 1];
182 short len = strlen(name); 186 short len = strlen(name);
187
183#ifdef BB_FEATURE_LS_FILETYPES 188#ifdef BB_FEATURE_LS_FILETYPES
184 char append = append_char(info->st_mode); 189 char append = append_char(info->st_mode);
185#endif 190#endif
186 191
187 if (display_fmt == FMT_LONG) { 192 if (display_fmt == FMT_LONG) {
188 mode_t mode = info->st_mode; 193 mode_t mode = info->st_mode;
194
189 newline(); 195 newline();
190 wr(modeString(mode), 10); 196 wr(modeString(mode), 10);
191 column=10; 197 column = 10;
192 writenum((long)info->st_nlink,(short)5); 198 writenum((long) info->st_nlink, (short) 5);
193 fputs(" ", stdout); 199 fputs(" ", stdout);
194#ifdef BB_FEATURE_LS_USERNAME 200#ifdef BB_FEATURE_LS_USERNAME
195 if (!(opts & DISP_NUMERIC)) { 201 if (!(opts & DISP_NUMERIC)) {
196 memset ( scratch, 0, sizeof (scratch)); 202 memset(scratch, 0, sizeof(scratch));
197 my_getpwuid( scratch, info->st_uid); 203 my_getpwuid(scratch, info->st_uid);
198 if (*scratch) { 204 if (*scratch) {
199 fputs(scratch, stdout); 205 fputs(scratch, stdout);
200 if ( strlen( scratch) <= 8 ) 206 if (strlen(scratch) <= 8)
201 wr(" ", 9-strlen( scratch)); 207 wr(" ", 9 - strlen(scratch));
202 } 208 } else {
203 else { 209 writenum((long) info->st_uid, (short) 8);
204 writenum((long) info->st_uid,(short)8);
205 fputs(" ", stdout); 210 fputs(" ", stdout);
206 } 211 }
207 } else 212 } else
208#endif 213#endif
209 { 214 {
210 writenum((long) info->st_uid,(short)8); 215 writenum((long) info->st_uid, (short) 8);
211 fputs(" ", stdout); 216 fputs(" ", stdout);
212 } 217 }
213#ifdef BB_FEATURE_LS_USERNAME 218#ifdef BB_FEATURE_LS_USERNAME
214 if (!(opts & DISP_NUMERIC)) { 219 if (!(opts & DISP_NUMERIC)) {
215 memset ( scratch, 0, sizeof (scratch)); 220 memset(scratch, 0, sizeof(scratch));
216 my_getgrgid( scratch, info->st_gid); 221 my_getgrgid(scratch, info->st_gid);
217 if (*scratch) { 222 if (*scratch) {
218 fputs(scratch, stdout); 223 fputs(scratch, stdout);
219 if ( strlen( scratch) <= 8 ) 224 if (strlen(scratch) <= 8)
220 wr(" ", 8-strlen( scratch)); 225 wr(" ", 8 - strlen(scratch));
221 } 226 } else
222 else 227 writenum((long) info->st_gid, (short) 8);
223 writenum((long) info->st_gid,(short)8);
224 } else 228 } else
225#endif 229#endif
226 writenum((long) info->st_gid,(short)8); 230 writenum((long) info->st_gid, (short) 8);
227 //tab(26); 231 //tab(26);
228 if (S_ISBLK(mode) || S_ISCHR(mode)) { 232 if (S_ISBLK(mode) || S_ISCHR(mode)) {
229 writenum((long)MAJOR(info->st_rdev),(short)3); 233 writenum((long) MAJOR(info->st_rdev), (short) 3);
230 fputs(", ", stdout); 234 fputs(", ", stdout);
231 writenum((long)MINOR(info->st_rdev),(short)3); 235 writenum((long) MINOR(info->st_rdev), (short) 3);
232 } 236 } else
233 else 237 writenum((long) info->st_size, (short) 8);
234 writenum((long)info->st_size,(short)8);
235 fputs(" ", stdout); 238 fputs(" ", stdout);
236 //tab(32); 239 //tab(32);
237#ifdef BB_FEATURE_LS_TIMESTAMPS 240#ifdef BB_FEATURE_LS_TIMESTAMPS
238 { 241 {
239 time_t cal; 242 time_t cal;
240 char *string; 243 char *string;
241 244
242 switch(time_fmt) { 245 switch (time_fmt) {
243 case TIME_CHANGE: 246 case TIME_CHANGE:
244 cal=info->st_ctime; break; 247 cal = info->st_ctime;
248 break;
245 case TIME_ACCESS: 249 case TIME_ACCESS:
246 cal=info->st_atime; break; 250 cal = info->st_atime;
251 break;
247 default: 252 default:
248 cal=info->st_mtime; break; 253 cal = info->st_mtime;
254 break;
249 } 255 }
250 string=ctime(&cal); 256 string = ctime(&cal);
251 if (opts & DISP_FULLTIME) 257 if (opts & DISP_FULLTIME)
252 wr(string,24); 258 wr(string, 24);
253 else { 259 else {
254 time_t age = time(NULL) - cal; 260 time_t age = time(NULL) - cal;
255 wr(string+4,7); /* mmm_dd_ */ 261
256 if(age < 3600L*24*365/2 && age > -15*60) 262 wr(string + 4, 7); /* mmm_dd_ */
263 if (age < 3600L * 24 * 365 / 2 && age > -15 * 60)
257 /* hh:mm if less than 6 months old */ 264 /* hh:mm if less than 6 months old */
258 wr(string+11,5); 265 wr(string + 11, 5);
259 else 266 else
260 /* _yyyy otherwise */ 267 /* _yyyy otherwise */
261 wr(string+19,5); 268 wr(string + 19, 5);
262 } 269 }
263 wr(" ", 1); 270 wr(" ", 1);
264 } 271 }
@@ -269,7 +276,8 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
269 if (S_ISLNK(mode)) { 276 if (S_ISLNK(mode)) {
270 wr(" -> ", 4); 277 wr(" -> ", 4);
271 len = readlink(fullname, scratch, sizeof scratch); 278 len = readlink(fullname, scratch, sizeof scratch);
272 if (len > 0) fwrite(scratch, 1, len, stdout); 279 if (len > 0)
280 fwrite(scratch, 1, len, stdout);
273#ifdef BB_FEATURE_LS_FILETYPES 281#ifdef BB_FEATURE_LS_FILETYPES
274 /* show type of destination */ 282 /* show type of destination */
275 if (opts & DISP_FTYPE) { 283 if (opts & DISP_FTYPE) {
@@ -287,18 +295,17 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
287#endif 295#endif
288 } else { 296 } else {
289 static short nexttab = 0; 297 static short nexttab = 0;
290 298
291 /* sort out column alignment */ 299 /* sort out column alignment */
292 if (column == 0) 300 if (column == 0); /* nothing to do */
293 ; /* nothing to do */
294 else if (display_fmt == FMT_SINGLE) 301 else if (display_fmt == FMT_SINGLE)
295 newline(); 302 newline();
296 else { 303 else {
297 if (nexttab + column_width > terminal_width 304 if (nexttab + column_width > terminal_width
298#ifndef BB_FEATURE_AUTOWIDTH 305#ifndef BB_FEATURE_AUTOWIDTH
299 || nexttab + len >= terminal_width 306 || nexttab + len >= terminal_width
300#endif 307#endif
301 ) 308 )
302 newline(); 309 newline();
303 else 310 else
304 tab(nexttab); 311 tab(nexttab);
@@ -336,32 +343,33 @@ static int list_item(const char *name)
336 struct stat info; 343 struct stat info;
337 DIR *dir; 344 DIR *dir;
338 struct dirent *entry; 345 struct dirent *entry;
339 char fullname[MAXNAMLEN+1], *fnend; 346 char fullname[MAXNAMLEN + 1], *fnend;
340 347
341 if (lstat(name, &info)) 348 if (lstat(name, &info))
342 goto listerr; 349 goto listerr;
343 350
344 if (!S_ISDIR(info.st_mode) || 351 if (!S_ISDIR(info.st_mode) || (opts & DIR_NOLIST)) {
345 (opts & DIR_NOLIST)) {
346 list_single(name, &info, name); 352 list_single(name, &info, name);
347 return 0; 353 return 0;
348 } 354 }
349 355
350 /* Otherwise, it's a directory we want to list the contents of */ 356 /* Otherwise, it's a directory we want to list the contents of */
351 357
352 if (opts & DISP_DIRNAME) { /* identify the directory */ 358 if (opts & DISP_DIRNAME) { /* identify the directory */
353 if (column) 359 if (column)
354 wr("\n\n", 2), column = 0; 360 wr("\n\n", 2), column = 0;
355 wr(name, strlen(name)); 361 wr(name, strlen(name));
356 wr(":\n", 2); 362 wr(":\n", 2);
357 } 363 }
358 364
359 dir = opendir(name); 365 dir = opendir(name);
360 if (!dir) goto listerr; 366 if (!dir)
367 goto listerr;
361#ifdef BB_FEATURE_AUTOWIDTH 368#ifdef BB_FEATURE_AUTOWIDTH
362 column_width = 0; 369 column_width = 0;
363 while ((entry = readdir(dir)) != NULL) { 370 while ((entry = readdir(dir)) != NULL) {
364 short w = strlen(entry->d_name); 371 short w = strlen(entry->d_name);
372
365 if (column_width < w) 373 if (column_width < w)
366 column_width = w; 374 column_width = w;
367 } 375 }
@@ -370,39 +378,40 @@ static int list_item(const char *name)
370#else 378#else
371 closedir(dir); 379 closedir(dir);
372 dir = opendir(name); 380 dir = opendir(name);
373 if (!dir) goto listerr; 381 if (!dir)
382 goto listerr;
374#endif 383#endif
375#endif 384#endif
376 385
377 /* List the contents */ 386 /* List the contents */
378 387
379 strcpy(fullname,name); /* *** ignore '.' by itself */ 388 strcpy(fullname, name); /* *** ignore '.' by itself */
380 fnend=fullname+strlen(fullname); 389 fnend = fullname + strlen(fullname);
381 if (fnend[-1] != '/') 390 if (fnend[-1] != '/')
382 *fnend++ = '/'; 391 *fnend++ = '/';
383 392
384 while ((entry = readdir(dir)) != NULL) { 393 while ((entry = readdir(dir)) != NULL) {
385 const char *en=entry->d_name; 394 const char *en = entry->d_name;
395
386 if (en[0] == '.') { 396 if (en[0] == '.') {
387 if (!en[1] || (en[1] == '.' && !en[2])) { /* . or .. */ 397 if (!en[1] || (en[1] == '.' && !en[2])) { /* . or .. */
388 if (!(opts & DISP_DOT)) 398 if (!(opts & DISP_DOT))
389 continue; 399 continue;
390 } 400 } else if (!(opts & DISP_HIDDEN))
391 else if (!(opts & DISP_HIDDEN))
392 continue; 401 continue;
393 } 402 }
394 /* FIXME: avoid stat if not required */ 403 /* FIXME: avoid stat if not required */
395 strcpy(fnend, entry->d_name); 404 strcpy(fnend, entry->d_name);
396 if (lstat(fullname, &info)) 405 if (lstat(fullname, &info))
397 goto direrr; /* (shouldn't fail) */ 406 goto direrr; /* (shouldn't fail) */
398 list_single(entry->d_name, &info, fullname); 407 list_single(entry->d_name, &info, fullname);
399 } 408 }
400 closedir(dir); 409 closedir(dir);
401 return 0; 410 return 0;
402 411
403direrr: 412 direrr:
404 closedir(dir); 413 closedir(dir);
405listerr: 414 listerr:
406 newline(); 415 newline();
407 perror(name); 416 perror(name);
408 return 1; 417 return 1;
@@ -432,50 +441,79 @@ static const char ls_usage[] = "ls [-1a"
432#endif 441#endif
433 "] [filenames...]\n"; 442 "] [filenames...]\n";
434 443
435extern int 444extern int ls_main(int argc, char **argv)
436ls_main(int argc, char * * argv)
437{ 445{
438 int argi=1, i; 446 int argi = 1, i;
439 447
440 /* process options */ 448 /* process options */
441 while (argi < argc && argv[argi][0] == '-') { 449 while (argi < argc && argv[argi][0] == '-') {
442 const char *p = &argv[argi][1]; 450 const char *p = &argv[argi][1];
443 451
444 if (!*p) goto print_usage_message; /* "-" by itself not allowed */ 452 if (!*p)
453 goto print_usage_message; /* "-" by itself not allowed */
445 if (*p == '-') { 454 if (*p == '-') {
446 if (!p[1]) { /* "--" forces end of options */ 455 if (!p[1]) { /* "--" forces end of options */
447 argi++; 456 argi++;
448 break; 457 break;
449 } 458 }
450 /* it's a long option name - we don't support them */ 459 /* it's a long option name - we don't support them */
451 goto print_usage_message; 460 goto print_usage_message;
452 } 461 }
453 462
454 while (*p) 463 while (*p)
455 switch (*p++) { 464 switch (*p++) {
456 case 'l': display_fmt = FMT_LONG; break; 465 case 'l':
457 case '1': display_fmt = FMT_SINGLE; break; 466 display_fmt = FMT_LONG;
458 case 'x': display_fmt = FMT_ROWS; break; 467 break;
459 case 'C': display_fmt = FMT_COLUMNS; break; 468 case '1':
469 display_fmt = FMT_SINGLE;
470 break;
471 case 'x':
472 display_fmt = FMT_ROWS;
473 break;
474 case 'C':
475 display_fmt = FMT_COLUMNS;
476 break;
460#ifdef BB_FEATURE_LS_FILETYPES 477#ifdef BB_FEATURE_LS_FILETYPES
461 case 'p': opts |= DISP_FTYPE; break; 478 case 'p':
462 case 'F': opts |= DISP_FTYPE|DISP_EXEC; break; 479 opts |= DISP_FTYPE;
480 break;
481 case 'F':
482 opts |= DISP_FTYPE | DISP_EXEC;
483 break;
463#endif 484#endif
464 case 'A': opts |= DISP_HIDDEN; break; 485 case 'A':
465 case 'a': opts |= DISP_HIDDEN|DISP_DOT; break; 486 opts |= DISP_HIDDEN;
466 case 'n': opts |= DISP_NUMERIC; break; 487 break;
467 case 'd': opts |= DIR_NOLIST; break; 488 case 'a':
489 opts |= DISP_HIDDEN | DISP_DOT;
490 break;
491 case 'n':
492 opts |= DISP_NUMERIC;
493 break;
494 case 'd':
495 opts |= DIR_NOLIST;
496 break;
468#ifdef FEATURE_RECURSIVE 497#ifdef FEATURE_RECURSIVE
469 case 'R': opts |= DIR_RECURSE; break; 498 case 'R':
499 opts |= DIR_RECURSE;
500 break;
470#endif 501#endif
471#ifdef BB_FEATURE_LS_TIMESTAMPS 502#ifdef BB_FEATURE_LS_TIMESTAMPS
472 case 'u': time_fmt = TIME_ACCESS; break; 503 case 'u':
473 case 'c': time_fmt = TIME_CHANGE; break; 504 time_fmt = TIME_ACCESS;
474 case 'e': opts |= DISP_FULLTIME; break; 505 break;
506 case 'c':
507 time_fmt = TIME_CHANGE;
508 break;
509 case 'e':
510 opts |= DISP_FULLTIME;
511 break;
475#endif 512#endif
476 default: goto print_usage_message; 513 default:
514 goto print_usage_message;
477 } 515 }
478 516
479 argi++; 517 argi++;
480 } 518 }
481 519
@@ -483,29 +521,30 @@ ls_main(int argc, char * * argv)
483 if (display_fmt == FMT_AUTO) 521 if (display_fmt == FMT_AUTO)
484 display_fmt = isatty(fileno(stdout)) ? FMT_COLUMNS : FMT_SINGLE; 522 display_fmt = isatty(fileno(stdout)) ? FMT_COLUMNS : FMT_SINGLE;
485 if (argi < argc - 1) 523 if (argi < argc - 1)
486 opts |= DISP_DIRNAME; /* 2 or more items? label directories */ 524 opts |= DISP_DIRNAME; /* 2 or more items? label directories */
487#ifdef BB_FEATURE_AUTOWIDTH 525#ifdef BB_FEATURE_AUTOWIDTH
488 /* could add a -w option and/or TIOCGWINSZ call */ 526 /* could add a -w option and/or TIOCGWINSZ call */
489 if (terminal_width < 1) terminal_width = TERMINAL_WIDTH; 527 if (terminal_width < 1)
490 528 terminal_width = TERMINAL_WIDTH;
529
491 for (i = argi; i < argc; i++) { 530 for (i = argi; i < argc; i++) {
492 int len = strlen(argv[i]); 531 int len = strlen(argv[i]);
532
493 if (column_width < len) 533 if (column_width < len)
494 column_width = len; 534 column_width = len;
495 } 535 }
496#endif 536#endif
497 537
498 /* process files specified, or current directory if none */ 538 /* process files specified, or current directory if none */
499 i=0; 539 i = 0;
500 if (argi == argc) 540 if (argi == argc)
501 i = list_item("."); 541 i = list_item(".");
502 while (argi < argc) 542 while (argi < argc)
503 i |= list_item(argv[argi++]); 543 i |= list_item(argv[argi++]);
504 newline(); 544 newline();
505 exit( i); 545 exit(i);
506 546
507print_usage_message: 547 print_usage_message:
508 usage (ls_usage); 548 usage(ls_usage);
509 exit( FALSE); 549 exit(FALSE);
510} 550}
511
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c
index 8e3f51bfb..70fdbdfb5 100644
--- a/coreutils/mkdir.c
+++ b/coreutils/mkdir.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mkdir implementation for busybox 3 * Mini mkdir implementation for busybox
3 * 4 *
@@ -28,14 +29,15 @@
28 29
29#include <stdio.h> 30#include <stdio.h>
30#include <errno.h> 31#include <errno.h>
31#include <sys/param.h> /* for PATH_MAX */ 32#include <sys/param.h> /* for PATH_MAX */
32 33
33static const char mkdir_usage[] = 34static const char mkdir_usage[] =
34"mkdir [OPTION] DIRECTORY...\n\n" 35 "mkdir [OPTION] DIRECTORY...\n\n"
35"Create the DIRECTORY(ies), if they do not already exist\n\n" 36 "Create the DIRECTORY(ies), if they do not already exist\n\n"
36"Options:\n" 37 "Options:\n"
37"\t-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n" 38
38"\t-p\tno error if existing, make parent directories as needed\n"; 39 "\t-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n"
40 "\t-p\tno error if existing, make parent directories as needed\n";
39 41
40 42
41static int parentFlag = FALSE; 43static int parentFlag = FALSE;
@@ -44,71 +46,70 @@ static mode_t mode = 0777;
44 46
45extern int mkdir_main(int argc, char **argv) 47extern int mkdir_main(int argc, char **argv)
46{ 48{
47 int i = FALSE; 49 int i = FALSE;
48 argc--;
49 argv++;
50 50
51 /* Parse any options */
52 while (argc > 0 && **argv == '-') {
53 while (i == FALSE && *++(*argv)) {
54 switch (**argv) {
55 case 'm':
56 if (--argc == 0)
57 usage( mkdir_usage);
58 /* Find the specified modes */
59 mode = 0;
60 if (parse_mode(*(++argv), &mode) == FALSE ) {
61 fprintf(stderr, "Unknown mode: %s\n", *argv);
62 exit FALSE;
63 }
64 /* Set the umask for this process so it doesn't
65 * screw up whatever the user just entered. */
66 umask(0);
67 i = TRUE;
68 break;
69 case 'p':
70 parentFlag = TRUE;
71 break;
72 default:
73 usage( mkdir_usage);
74 }
75 }
76 argc--; 51 argc--;
77 argv++; 52 argv++;
78 }
79
80 if (argc < 1) {
81 usage( mkdir_usage);
82 }
83 53
84 while (argc > 0) { 54 /* Parse any options */
85 int status; 55 while (argc > 0 && **argv == '-') {
86 struct stat statBuf; 56 while (i == FALSE && *++(*argv)) {
87 char buf[PATH_MAX + 1]; 57 switch (**argv) {
88 if (strlen(*argv) > PATH_MAX - 1) { 58 case 'm':
89 fprintf(stderr, name_too_long, "mkdir"); 59 if (--argc == 0)
90 exit FALSE; 60 usage(mkdir_usage);
91 } 61 /* Find the specified modes */
92 strcpy (buf, *argv); 62 mode = 0;
93 status = stat(buf, &statBuf); 63 if (parse_mode(*(++argv), &mode) == FALSE) {
94 if (parentFlag == FALSE && status != -1 && errno != ENOENT) { 64 fprintf(stderr, "Unknown mode: %s\n", *argv);
95 fprintf(stderr, "%s: File exists\n", buf); 65 exit FALSE;
96 exit FALSE; 66 }
97 } 67 /* Set the umask for this process so it doesn't
98 if (parentFlag == TRUE) { 68 * screw up whatever the user just entered. */
99 strcat( buf, "/"); 69 umask(0);
100 createPath(buf, mode); 70 i = TRUE;
71 break;
72 case 'p':
73 parentFlag = TRUE;
74 break;
75 default:
76 usage(mkdir_usage);
77 }
78 }
79 argc--;
80 argv++;
101 } 81 }
102 else { 82
103 if (mkdir (buf, mode) != 0 && parentFlag == FALSE) { 83 if (argc < 1) {
104 perror(buf); 84 usage(mkdir_usage);
105 exit FALSE;
106 }
107 } 85 }
108 argc--;
109 argv++;
110 }
111 exit TRUE;
112}
113 86
87 while (argc > 0) {
88 int status;
89 struct stat statBuf;
90 char buf[PATH_MAX + 1];
114 91
92 if (strlen(*argv) > PATH_MAX - 1) {
93 fprintf(stderr, name_too_long, "mkdir");
94 exit FALSE;
95 }
96 strcpy(buf, *argv);
97 status = stat(buf, &statBuf);
98 if (parentFlag == FALSE && status != -1 && errno != ENOENT) {
99 fprintf(stderr, "%s: File exists\n", buf);
100 exit FALSE;
101 }
102 if (parentFlag == TRUE) {
103 strcat(buf, "/");
104 createPath(buf, mode);
105 } else {
106 if (mkdir(buf, mode) != 0 && parentFlag == FALSE) {
107 perror(buf);
108 exit FALSE;
109 }
110 }
111 argc--;
112 argv++;
113 }
114 exit TRUE;
115}
diff --git a/coreutils/mkfifo.c b/coreutils/mkfifo.c
index 676592ac7..c74402d4c 100644
--- a/coreutils/mkfifo.c
+++ b/coreutils/mkfifo.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mkfifo implementation for busybox 3 * Mini mkfifo implementation for busybox
3 * 4 *
@@ -26,36 +27,43 @@
26#include <errno.h> 27#include <errno.h>
27 28
28static const char mkfifo_usage[] = "mkfifo [OPTIONS] name\n\n" 29static const char mkfifo_usage[] = "mkfifo [OPTIONS] name\n\n"
29"Create the named fifo\n\n" 30 "Create the named fifo\n\n"
30"Options:\n" 31
31"\t-m\tcreate the fifo with the specified mode; default = a=rw-umask\n"; 32 "Options:\n"
33 "\t-m\tcreate the fifo with the specified mode; default = a=rw-umask\n";
32 34
33extern int mkfifo_main(int argc, char **argv) 35extern int mkfifo_main(int argc, char **argv)
34{ 36{
35 char *thisarg; 37 char *thisarg;
36 mode_t mode = 0666; 38 mode_t mode = 0666;
37 argc--; 39
38 argv++; 40 argc--;
41 argv++;
39 42
40 /* Parse any options */ 43 /* Parse any options */
41 while (argc > 1) { 44 while (argc > 1) {
42 if (**argv != '-') usage(mkfifo_usage); 45 if (**argv != '-')
43 thisarg = *argv; thisarg++; 46 usage(mkfifo_usage);
44 switch (*thisarg) { 47 thisarg = *argv;
45 case 'm': 48 thisarg++;
46 argc--; argv++; 49 switch (*thisarg) {
47 parse_mode(*argv, &mode); 50 case 'm':
48 break; 51 argc--;
49 default: 52 argv++;
50 usage (mkfifo_usage); 53 parse_mode(*argv, &mode);
51 } 54 break;
52 argc--; argv++; 55 default:
53 } 56 usage(mkfifo_usage);
54 if (argc < 1) usage (mkfifo_usage); 57 }
55 if (mkfifo(*argv, mode) < 0) { 58 argc--;
56 perror("mkfifo"); 59 argv++;
57 exit(255); 60 }
58 } else { 61 if (argc < 1)
59 exit(TRUE); 62 usage(mkfifo_usage);
60 } 63 if (mkfifo(*argv, mode) < 0) {
64 perror("mkfifo");
65 exit(255);
66 } else {
67 exit(TRUE);
68 }
61} 69}
diff --git a/coreutils/mknod.c b/coreutils/mknod.c
index 5822cd3ad..b11a81f2a 100644
--- a/coreutils/mknod.c
+++ b/coreutils/mknod.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mknod implementation for busybox 3 * Mini mknod implementation for busybox
3 * 4 *
@@ -28,22 +29,22 @@
28#include <unistd.h> 29#include <unistd.h>
29 30
30static const char mknod_usage[] = "mknod NAME TYPE MAJOR MINOR\n\n" 31static const char mknod_usage[] = "mknod NAME TYPE MAJOR MINOR\n\n"
31"Make block or character special files.\n\n" 32 "Make block or character special files.\n\n"
32"TYPEs include:\n" 33 "TYPEs include:\n"
33"\tb:\tMake a block (buffered) device.\n" 34 "\tb:\tMake a block (buffered) device.\n"
34"\tc or u:\tMake a character (un-buffered) device.\n"
35"\tp:\tMake a named pipe. Major and minor are ignored for named pipes.\n";
36 35
37int 36 "\tc or u:\tMake a character (un-buffered) device.\n"
38mknod_main(int argc, char** argv) 37 "\tp:\tMake a named pipe. Major and minor are ignored for named pipes.\n";
38
39int mknod_main(int argc, char **argv)
39{ 40{
40 mode_t mode = 0; 41 mode_t mode = 0;
41 dev_t dev = 0; 42 dev_t dev = 0;
42 43
43 if ( argc != 5 || **(argv+1) == '-' ) { 44 if (argc != 5 || **(argv + 1) == '-') {
44 usage (mknod_usage); 45 usage(mknod_usage);
45 } 46 }
46 switch(argv[2][0]) { 47 switch (argv[2][0]) {
47 case 'c': 48 case 'c':
48 case 'u': 49 case 'u':
49 mode = S_IFCHR; 50 mode = S_IFCHR;
@@ -55,21 +56,21 @@ mknod_main(int argc, char** argv)
55 mode = S_IFIFO; 56 mode = S_IFIFO;
56 break; 57 break;
57 default: 58 default:
58 usage (mknod_usage); 59 usage(mknod_usage);
59 } 60 }
60 61
61 if ( mode == S_IFCHR || mode == S_IFBLK ) { 62 if (mode == S_IFCHR || mode == S_IFBLK) {
62 dev = (atoi(argv[3]) << 8) | atoi(argv[4]); 63 dev = (atoi(argv[3]) << 8) | atoi(argv[4]);
63 if ( argc != 5 ) { 64 if (argc != 5) {
64 usage (mknod_usage); 65 usage(mknod_usage);
65 } 66 }
66 } 67 }
67 68
68 mode |= 0666; 69 mode |= 0666;
69 70
70 if ( mknod(argv[1], mode, dev) != 0 ) { 71 if (mknod(argv[1], mode, dev) != 0) {
71 perror(argv[1]); 72 perror(argv[1]);
72 return( FALSE); 73 return (FALSE);
73 } 74 }
74 return( TRUE); 75 return (TRUE);
75} 76}
diff --git a/coreutils/printf.c b/coreutils/printf.c
index 5fd5ea303..41ab2e442 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* printf - format and print data 2/* printf - format and print data
2 Copyright (C) 90, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. 3 Copyright (C) 90, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
3 4
@@ -42,7 +43,7 @@
42 to convert all of the given arguments. 43 to convert all of the given arguments.
43 44
44 David MacKenzie <djm@gnu.ai.mit.edu> */ 45 David MacKenzie <djm@gnu.ai.mit.edu> */
45 46
46 47
47// 19990508 Busy Boxed! Dave Cinege 48// 19990508 Busy Boxed! Dave Cinege
48 49
@@ -84,11 +85,11 @@
84#if !defined(S_ISSOCK) && defined(S_IFSOCK) 85#if !defined(S_ISSOCK) && defined(S_IFSOCK)
85# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) 86# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
86#endif 87#endif
87#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */ 88#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
88# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) 89# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
89# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) 90# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
90#endif 91#endif
91#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */ 92#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
92# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) 93# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
93#endif 94#endif
94 95
@@ -121,407 +122,358 @@
121#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0') 122#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
122#define octtobin(c) ((c) - '0') 123#define octtobin(c) ((c) - '0')
123 124
124static double xstrtod __P ((char *s)); 125static double xstrtod __P((char *s));
125static int print_esc __P ((char *escstart)); 126static int print_esc __P((char *escstart));
126static int print_formatted __P ((char *format, int argc, char **argv)); 127static int print_formatted __P((char *format, int argc, char **argv));
127static long xstrtol __P ((char *s)); 128static long xstrtol __P((char *s));
128static unsigned long xstrtoul __P ((char *s)); 129static unsigned long xstrtoul __P((char *s));
129static void print_direc __P ((char *start, size_t length, int field_width, int precision, char *argument)); 130static void print_direc
130static void print_esc_char __P ((int c)); 131__P(
131static void print_esc_string __P ((char *str)); 132
132static void verify __P ((char *s, char *end)); 133 (char *start, size_t length, int field_width, int precision,
134 char *argument));
135static void print_esc_char __P((int c));
136static void print_esc_string __P((char *str));
137static void verify __P((char *s, char *end));
133 138
134/* The value to return to the calling program. */ 139/* The value to return to the calling program. */
135static int exit_status; 140static int exit_status;
136 141
137static const char printf_usage[] = "printf format [argument...]\n"; 142static const char printf_usage[] = "printf format [argument...]\n";
138 143
139int 144int printf_main(int argc, char **argv)
140printf_main(int argc, char** argv)
141{ 145{
142 char *format; 146 char *format;
143 int args_used; 147 int args_used;
144 148
145 exit_status = 0; 149 exit_status = 0;
146 if ( argc <= 1 || **(argv+1) == '-' ) { 150 if (argc <= 1 || **(argv + 1) == '-') {
147 usage (printf_usage); 151 usage(printf_usage);
148 } 152 }
149 153
150 format = argv[1]; 154 format = argv[1];
151 argc -= 2; 155 argc -= 2;
152 argv += 2; 156 argv += 2;
153 157
154 do 158 do {
155 { 159 args_used = print_formatted(format, argc, argv);
156 args_used = print_formatted (format, argc, argv); 160 argc -= args_used;
157 argc -= args_used; 161 argv += args_used;
158 argv += args_used; 162 }
159 } 163 while (args_used > 0 && argc > 0);
160 while (args_used > 0 && argc > 0);
161 164
162/* 165/*
163 if (argc > 0) 166 if (argc > 0)
164 fprintf(stderr, "excess args ignored"); 167 fprintf(stderr, "excess args ignored");
165*/ 168*/
166 169
167 exit (exit_status); 170 exit(exit_status);
168} 171}
169 172
170/* Print the text in FORMAT, using ARGV (with ARGC elements) for 173/* Print the text in FORMAT, using ARGV (with ARGC elements) for
171 arguments to any `%' directives. 174 arguments to any `%' directives.
172 Return the number of elements of ARGV used. */ 175 Return the number of elements of ARGV used. */
173 176
174static int 177static int print_formatted(char *format, int argc, char **argv)
175print_formatted (char *format, int argc, char **argv)
176{ 178{
177 int save_argc = argc; /* Preserve original value. */ 179 int save_argc = argc; /* Preserve original value. */
178 char *f; /* Pointer into `format'. */ 180 char *f; /* Pointer into `format'. */
179 char *direc_start; /* Start of % directive. */ 181 char *direc_start; /* Start of % directive. */
180 size_t direc_length; /* Length of % directive. */ 182 size_t direc_length; /* Length of % directive. */
181 int field_width; /* Arg to first '*', or -1 if none. */ 183 int field_width; /* Arg to first '*', or -1 if none. */
182 int precision; /* Arg to second '*', or -1 if none. */ 184 int precision; /* Arg to second '*', or -1 if none. */
183 185
184 for (f = format; *f; ++f) 186 for (f = format; *f; ++f) {
185 { 187 switch (*f) {
186 switch (*f) 188 case '%':
187 { 189 direc_start = f++;
188 case '%': 190 direc_length = 1;
189 direc_start = f++; 191 field_width = precision = -1;
190 direc_length = 1; 192 if (*f == '%') {
191 field_width = precision = -1; 193 putchar('%');
192 if (*f == '%') 194 break;
193 { 195 }
194 putchar ('%'); 196 if (*f == 'b') {
195 break; 197 if (argc > 0) {
196 } 198 print_esc_string(*argv);
197 if (*f == 'b') 199 ++argv;
198 { 200 --argc;
199 if (argc > 0) 201 }
200 { 202 break;
201 print_esc_string (*argv); 203 }
202 ++argv; 204 if (strchr("-+ #", *f)) {
203 --argc; 205 ++f;
204 } 206 ++direc_length;
205 break; 207 }
206 } 208 if (*f == '*') {
207 if (strchr ("-+ #", *f)) 209 ++f;
208 { 210 ++direc_length;
209 ++f; 211 if (argc > 0) {
210 ++direc_length; 212 field_width = xstrtoul(*argv);
211 } 213 ++argv;
212 if (*f == '*') 214 --argc;
213 { 215 } else
214 ++f; 216 field_width = 0;
215 ++direc_length; 217 } else
216 if (argc > 0) 218 while (ISDIGIT(*f)) {
217 { 219 ++f;
218 field_width = xstrtoul (*argv); 220 ++direc_length;
219 ++argv; 221 }
220 --argc; 222 if (*f == '.') {
223 ++f;
224 ++direc_length;
225 if (*f == '*') {
226 ++f;
227 ++direc_length;
228 if (argc > 0) {
229 precision = xstrtoul(*argv);
230 ++argv;
231 --argc;
232 } else
233 precision = 0;
234 } else
235 while (ISDIGIT(*f)) {
236 ++f;
237 ++direc_length;
238 }
239 }
240 if (*f == 'l' || *f == 'L' || *f == 'h') {
241 ++f;
242 ++direc_length;
243 }
244 /*
245 if (!strchr ("diouxXfeEgGcs", *f))
246 fprintf(stderr, "%%%c: invalid directive", *f);
247 */
248 ++direc_length;
249 if (argc > 0) {
250 print_direc(direc_start, direc_length, field_width,
251 precision, *argv);
252 ++argv;
253 --argc;
254 } else
255 print_direc(direc_start, direc_length, field_width,
256 precision, "");
257 break;
258
259 case '\\':
260 f += print_esc(f);
261 break;
262
263 default:
264 putchar(*f);
221 } 265 }
222 else
223 field_width = 0;
224 }
225 else
226 while (ISDIGIT (*f))
227 {
228 ++f;
229 ++direc_length;
230 }
231 if (*f == '.')
232 {
233 ++f;
234 ++direc_length;
235 if (*f == '*')
236 {
237 ++f;
238 ++direc_length;
239 if (argc > 0)
240 {
241 precision = xstrtoul (*argv);
242 ++argv;
243 --argc;
244 }
245 else
246 precision = 0;
247 }
248 else
249 while (ISDIGIT (*f))
250 {
251 ++f;
252 ++direc_length;
253 }
254 }
255 if (*f == 'l' || *f == 'L' || *f == 'h')
256 {
257 ++f;
258 ++direc_length;
259 }
260 /*
261 if (!strchr ("diouxXfeEgGcs", *f))
262 fprintf(stderr, "%%%c: invalid directive", *f);
263 */
264 ++direc_length;
265 if (argc > 0)
266 {
267 print_direc (direc_start, direc_length, field_width,
268 precision, *argv);
269 ++argv;
270 --argc;
271 }
272 else
273 print_direc (direc_start, direc_length, field_width,
274 precision, "");
275 break;
276
277 case '\\':
278 f += print_esc (f);
279 break;
280
281 default:
282 putchar (*f);
283 } 266 }
284 }
285 267
286 return save_argc - argc; 268 return save_argc - argc;
287} 269}
288 270
289/* Print a \ escape sequence starting at ESCSTART. 271/* Print a \ escape sequence starting at ESCSTART.
290 Return the number of characters in the escape sequence 272 Return the number of characters in the escape sequence
291 besides the backslash. */ 273 besides the backslash. */
292 274
293static int 275static int print_esc(char *escstart)
294print_esc (char *escstart)
295{ 276{
296 register char *p = escstart + 1; 277 register char *p = escstart + 1;
297 int esc_value = 0; /* Value of \nnn escape. */ 278 int esc_value = 0; /* Value of \nnn escape. */
298 int esc_length; /* Length of \nnn escape. */ 279 int esc_length; /* Length of \nnn escape. */
299 280
300 /* \0ooo and \xhhh escapes have maximum length of 3 chars. */ 281 /* \0ooo and \xhhh escapes have maximum length of 3 chars. */
301 if (*p == 'x') 282 if (*p == 'x') {
302 { 283 for (esc_length = 0, ++p;
303 for (esc_length = 0, ++p; 284 esc_length < 3 && ISXDIGIT(*p); ++esc_length, ++p)
304 esc_length < 3 && ISXDIGIT (*p); 285 esc_value = esc_value * 16 + hextobin(*p);
305 ++esc_length, ++p)
306 esc_value = esc_value * 16 + hextobin (*p);
307/* if (esc_length == 0) 286/* if (esc_length == 0)
308 fprintf(stderr, "missing hex in esc"); 287 fprintf(stderr, "missing hex in esc");
309*/ 288*/
310 putchar (esc_value); 289 putchar(esc_value);
311 } 290 } else if (*p == '0') {
312 else if (*p == '0') 291 for (esc_length = 0, ++p;
313 { 292 esc_length < 3 && isodigit(*p); ++esc_length, ++p)
314 for (esc_length = 0, ++p; 293 esc_value = esc_value * 8 + octtobin(*p);
315 esc_length < 3 && isodigit (*p); 294 putchar(esc_value);
316 ++esc_length, ++p) 295 } else if (strchr("\"\\abcfnrtv", *p))
317 esc_value = esc_value * 8 + octtobin (*p); 296 print_esc_char(*p++);
318 putchar (esc_value);
319 }
320 else if (strchr ("\"\\abcfnrtv", *p))
321 print_esc_char (*p++);
322/* else 297/* else
323 fprintf(stderr, "\\%c: invalid esc", *p); 298 fprintf(stderr, "\\%c: invalid esc", *p);
324*/ 299*/
325 return p - escstart - 1; 300 return p - escstart - 1;
326} 301}
327 302
328/* Output a single-character \ escape. */ 303/* Output a single-character \ escape. */
329 304
330static void 305static void print_esc_char(int c)
331print_esc_char (int c)
332{ 306{
333 switch (c) 307 switch (c) {
334 { 308 case 'a': /* Alert. */
335 case 'a': /* Alert. */ 309 putchar(7);
336 putchar (7); 310 break;
337 break; 311 case 'b': /* Backspace. */
338 case 'b': /* Backspace. */ 312 putchar(8);
339 putchar (8); 313 break;
340 break; 314 case 'c': /* Cancel the rest of the output. */
341 case 'c': /* Cancel the rest of the output. */ 315 exit(0);
342 exit (0); 316 break;
343 break; 317 case 'f': /* Form feed. */
344 case 'f': /* Form feed. */ 318 putchar(12);
345 putchar (12); 319 break;
346 break; 320 case 'n': /* New line. */
347 case 'n': /* New line. */ 321 putchar(10);
348 putchar (10); 322 break;
349 break; 323 case 'r': /* Carriage return. */
350 case 'r': /* Carriage return. */ 324 putchar(13);
351 putchar (13); 325 break;
352 break; 326 case 't': /* Horizontal tab. */
353 case 't': /* Horizontal tab. */ 327 putchar(9);
354 putchar (9); 328 break;
355 break; 329 case 'v': /* Vertical tab. */
356 case 'v': /* Vertical tab. */ 330 putchar(11);
357 putchar (11); 331 break;
358 break; 332 default:
359 default: 333 putchar(c);
360 putchar (c); 334 break;
361 break; 335 }
362 }
363} 336}
364 337
365/* Print string STR, evaluating \ escapes. */ 338/* Print string STR, evaluating \ escapes. */
366 339
367static void 340static void print_esc_string(char *str)
368print_esc_string (char *str)
369{ 341{
370 for (; *str; str++) 342 for (; *str; str++)
371 if (*str == '\\') 343 if (*str == '\\')
372 str += print_esc (str); 344 str += print_esc(str);
373 else 345 else
374 putchar (*str); 346 putchar(*str);
375} 347}
376 348
377static void 349static void
378print_direc (char *start, size_t length, int field_width, int precision, char *argument) 350print_direc(char *start, size_t length, int field_width, int precision,
351 char *argument)
379{ 352{
380 char *p; /* Null-terminated copy of % directive. */ 353 char *p; /* Null-terminated copy of % directive. */
381 354
382 p = xmalloc ((unsigned) (length + 1)); 355 p = xmalloc((unsigned) (length + 1));
383 strncpy (p, start, length); 356 strncpy(p, start, length);
384 p[length] = 0; 357 p[length] = 0;
385 358
386 switch (p[length - 1]) 359 switch (p[length - 1]) {
387 { 360 case 'd':
388 case 'd': 361 case 'i':
389 case 'i': 362 if (field_width < 0) {
390 if (field_width < 0) 363 if (precision < 0)
391 { 364 printf(p, xstrtol(argument));
392 if (precision < 0) 365 else
393 printf (p, xstrtol (argument)); 366 printf(p, precision, xstrtol(argument));
394 else 367 } else {
395 printf (p, precision, xstrtol (argument)); 368 if (precision < 0)
396 } 369 printf(p, field_width, xstrtol(argument));
397 else 370 else
398 { 371 printf(p, field_width, precision, xstrtol(argument));
399 if (precision < 0) 372 }
400 printf (p, field_width, xstrtol (argument)); 373 break;
401 else 374
402 printf (p, field_width, precision, xstrtol (argument)); 375 case 'o':
403 } 376 case 'u':
404 break; 377 case 'x':
405 378 case 'X':
406 case 'o': 379 if (field_width < 0) {
407 case 'u': 380 if (precision < 0)
408 case 'x': 381 printf(p, xstrtoul(argument));
409 case 'X': 382 else
410 if (field_width < 0) 383 printf(p, precision, xstrtoul(argument));
411 { 384 } else {
412 if (precision < 0) 385 if (precision < 0)
413 printf (p, xstrtoul (argument)); 386 printf(p, field_width, xstrtoul(argument));
414 else 387 else
415 printf (p, precision, xstrtoul (argument)); 388 printf(p, field_width, precision, xstrtoul(argument));
416 } 389 }
417 else 390 break;
418 { 391
419 if (precision < 0) 392 case 'f':
420 printf (p, field_width, xstrtoul (argument)); 393 case 'e':
421 else 394 case 'E':
422 printf (p, field_width, precision, xstrtoul (argument)); 395 case 'g':
423 } 396 case 'G':
424 break; 397 if (field_width < 0) {
425 398 if (precision < 0)
426 case 'f': 399 printf(p, xstrtod(argument));
427 case 'e': 400 else
428 case 'E': 401 printf(p, precision, xstrtod(argument));
429 case 'g': 402 } else {
430 case 'G': 403 if (precision < 0)
431 if (field_width < 0) 404 printf(p, field_width, xstrtod(argument));
432 { 405 else
433 if (precision < 0) 406 printf(p, field_width, precision, xstrtod(argument));
434 printf (p, xstrtod (argument)); 407 }
435 else 408 break;
436 printf (p, precision, xstrtod (argument)); 409
437 } 410 case 'c':
438 else 411 printf(p, *argument);
439 { 412 break;
440 if (precision < 0) 413
441 printf (p, field_width, xstrtod (argument)); 414 case 's':
442 else 415 if (field_width < 0) {
443 printf (p, field_width, precision, xstrtod (argument)); 416 if (precision < 0)
444 } 417 printf(p, argument);
445 break; 418 else
446 419 printf(p, precision, argument);
447 case 'c': 420 } else {
448 printf (p, *argument); 421 if (precision < 0)
449 break; 422 printf(p, field_width, argument);
450 423 else
451 case 's': 424 printf(p, field_width, precision, argument);
452 if (field_width < 0) 425 }
453 { 426 break;
454 if (precision < 0)
455 printf (p, argument);
456 else
457 printf (p, precision, argument);
458 }
459 else
460 {
461 if (precision < 0)
462 printf (p, field_width, argument);
463 else
464 printf (p, field_width, precision, argument);
465 } 427 }
466 break;
467 }
468 428
469 free (p); 429 free(p);
470} 430}
471 431
472static unsigned long 432static unsigned long xstrtoul(char *s)
473xstrtoul (char *s)
474{ 433{
475 char *end; 434 char *end;
476 unsigned long val; 435 unsigned long val;
477 436
478 errno = 0; 437 errno = 0;
479 val = strtoul (s, &end, 0); 438 val = strtoul(s, &end, 0);
480 verify (s, end); 439 verify(s, end);
481 return val; 440 return val;
482} 441}
483 442
484static long 443static long xstrtol(char *s)
485xstrtol (char *s)
486{ 444{
487 char *end; 445 char *end;
488 long val; 446 long val;
489 447
490 errno = 0; 448 errno = 0;
491 val = strtol (s, &end, 0); 449 val = strtol(s, &end, 0);
492 verify (s, end); 450 verify(s, end);
493 return val; 451 return val;
494} 452}
495 453
496static double 454static double xstrtod(char *s)
497xstrtod (char *s)
498{ 455{
499 char *end; 456 char *end;
500 double val; 457 double val;
501 458
502 errno = 0; 459 errno = 0;
503 val = strtod (s, &end); 460 val = strtod(s, &end);
504 verify (s, end); 461 verify(s, end);
505 return val; 462 return val;
506} 463}
507 464
508static void 465static void verify(char *s, char *end)
509verify (char *s, char *end)
510{ 466{
511 if (errno) 467 if (errno) {
512 { 468 fprintf(stderr, "%s", s);
513 fprintf(stderr, "%s", s); 469 exit_status = 1;
514 exit_status = 1; 470 } else if (*end) {
515 } 471 /*
516 else if (*end) 472 if (s == end)
517 { 473 fprintf(stderr, "%s: expected numeric", s);
518 /* 474 else
519 if (s == end) 475 fprintf(stderr, "%s: not completely converted", s);
520 fprintf(stderr, "%s: expected numeric", s); 476 */
521 else 477 exit_status = 1;
522 fprintf(stderr, "%s: not completely converted", s); 478 }
523 */
524 exit_status = 1;
525 }
526} 479}
527
diff --git a/coreutils/pwd.c b/coreutils/pwd.c
index bacabd77a..00163178b 100644
--- a/coreutils/pwd.c
+++ b/coreutils/pwd.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini pwd implementation for busybox 3 * Mini pwd implementation for busybox
3 * 4 *
@@ -25,16 +26,15 @@
25#include <dirent.h> 26#include <dirent.h>
26#include <sys/param.h> 27#include <sys/param.h>
27 28
28extern int 29extern int pwd_main(int argc, char **argv)
29pwd_main(int argc, char * * argv)
30{ 30{
31 char buf[PATH_MAX + 1]; 31 char buf[PATH_MAX + 1];
32 32
33 if ( getcwd(buf, sizeof(buf)) == NULL ) { 33 if (getcwd(buf, sizeof(buf)) == NULL) {
34 perror("get working directory"); 34 perror("get working directory");
35 exit( FALSE); 35 exit(FALSE);
36 } 36 }
37 37
38 printf("%s\n", buf); 38 printf("%s\n", buf);
39 exit( TRUE); 39 exit(TRUE);
40} 40}
diff --git a/coreutils/rm.c b/coreutils/rm.c
index ee434fb39..41afedaf9 100644
--- a/coreutils/rm.c
+++ b/coreutils/rm.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini rm implementation for busybox 3 * Mini rm implementation for busybox
3 * 4 *
@@ -28,11 +29,12 @@
28#include <dirent.h> 29#include <dirent.h>
29#include <errno.h> 30#include <errno.h>
30 31
31static const char* rm_usage = "rm [OPTION]... FILE...\n\n" 32static const char *rm_usage = "rm [OPTION]... FILE...\n\n"
32"Remove (unlink) the FILE(s).\n\n" 33 "Remove (unlink) the FILE(s).\n\n"
33"Options:\n" 34 "Options:\n"
34"\t-f\t\tremove existing destinations, never prompt\n" 35
35"\t-r or -R\tremove the contents of directories recursively\n"; 36 "\t-f\t\tremove existing destinations, never prompt\n"
37 "\t-r or -R\tremove the contents of directories recursively\n";
36 38
37 39
38static int recursiveFlag = FALSE; 40static int recursiveFlag = FALSE;
@@ -40,63 +42,63 @@ static int forceFlag = FALSE;
40static const char *srcName; 42static const char *srcName;
41 43
42 44
43static int fileAction(const char *fileName, struct stat* statbuf) 45static int fileAction(const char *fileName, struct stat *statbuf)
44{ 46{
45 if (unlink( fileName) < 0 ) { 47 if (unlink(fileName) < 0) {
46 perror( fileName); 48 perror(fileName);
47 return ( FALSE); 49 return (FALSE);
48 } 50 }
49 return ( TRUE); 51 return (TRUE);
50} 52}
51 53
52static int dirAction(const char *fileName, struct stat* statbuf) 54static int dirAction(const char *fileName, struct stat *statbuf)
53{ 55{
54 if (rmdir( fileName) < 0 ) { 56 if (rmdir(fileName) < 0) {
55 perror( fileName); 57 perror(fileName);
56 return ( FALSE); 58 return (FALSE);
57 } 59 }
58 return ( TRUE); 60 return (TRUE);
59} 61}
60 62
61extern int rm_main(int argc, char **argv) 63extern int rm_main(int argc, char **argv)
62{ 64{
63 struct stat statbuf; 65 struct stat statbuf;
64 66
65 if (argc < 2) { 67 if (argc < 2) {
66 usage( rm_usage); 68 usage(rm_usage);
67 } 69 }
68 argc--;
69 argv++;
70
71 /* Parse any options */
72 while (**argv == '-') {
73 while (*++(*argv))
74 switch (**argv) {
75 case 'R':
76 case 'r':
77 recursiveFlag = TRUE;
78 break;
79 case 'f':
80 forceFlag = TRUE;
81 break;
82 default:
83 usage( rm_usage);
84 }
85 argc--; 70 argc--;
86 argv++; 71 argv++;
87 }
88 72
89 while (argc-- > 0) { 73 /* Parse any options */
90 srcName = *(argv++); 74 while (**argv == '-') {
91 if (forceFlag == TRUE && lstat(srcName, &statbuf) != 0 && errno == ENOENT) { 75 while (*++(*argv))
92 /* do not reports errors for non-existent files if -f, just skip them */ 76 switch (**argv) {
77 case 'R':
78 case 'r':
79 recursiveFlag = TRUE;
80 break;
81 case 'f':
82 forceFlag = TRUE;
83 break;
84 default:
85 usage(rm_usage);
86 }
87 argc--;
88 argv++;
93 } 89 }
94 else { 90
95 if (recursiveAction( srcName, recursiveFlag, FALSE, 91 while (argc-- > 0) {
96 TRUE, fileAction, dirAction) == FALSE) { 92 srcName = *(argv++);
97 exit( FALSE); 93 if (forceFlag == TRUE && lstat(srcName, &statbuf) != 0
98 } 94 && errno == ENOENT) {
95 /* do not reports errors for non-existent files if -f, just skip them */
96 } else {
97 if (recursiveAction(srcName, recursiveFlag, FALSE,
98 TRUE, fileAction, dirAction) == FALSE) {
99 exit(FALSE);
100 }
101 }
99 } 102 }
100 } 103 exit(TRUE);
101 exit( TRUE);
102} 104}
diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c
index 013fef1a4..f49569749 100644
--- a/coreutils/rmdir.c
+++ b/coreutils/rmdir.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini rmdir implementation for busybox 3 * Mini rmdir implementation for busybox
3 * 4 *
@@ -28,15 +29,16 @@
28 29
29extern int rmdir_main(int argc, char **argv) 30extern int rmdir_main(int argc, char **argv)
30{ 31{
31 if ( argc==1 || **(argv+1) == '-' ) { 32 if (argc == 1 || **(argv + 1) == '-') {
32 usage( "rmdir [OPTION]... DIRECTORY...\n\nRemove the DIRECTORY(ies), if they are empty.\n"); 33 usage
33 } 34 ("rmdir [OPTION]... DIRECTORY...\n\nRemove the DIRECTORY(ies), if they are empty.\n");
35 }
34 36
35 while (--argc > 0) { 37 while (--argc > 0) {
36 if ( rmdir(*(++argv)) == -1 ) { 38 if (rmdir(*(++argv)) == -1) {
37 fprintf(stderr, "%s: %s\n", *argv, strerror(errno)); 39 fprintf(stderr, "%s: %s\n", *argv, strerror(errno));
38 exit(FALSE); 40 exit(FALSE);
41 }
39 } 42 }
40 } 43 exit(TRUE);
41 exit(TRUE);
42} 44}
diff --git a/coreutils/sleep.c b/coreutils/sleep.c
index bfbb78f61..9687b8446 100644
--- a/coreutils/sleep.c
+++ b/coreutils/sleep.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini sleep implementation for busybox 3 * Mini sleep implementation for busybox
3 * 4 *
@@ -23,19 +24,17 @@
23#include "internal.h" 24#include "internal.h"
24#include <stdio.h> 25#include <stdio.h>
25 26
26const char sleep_usage[] = "sleep N\n\n" 27const char sleep_usage[] = "sleep N\n\n" "Pause for N seconds.\n";
27"Pause for N seconds.\n";
28 28
29extern int 29extern int sleep_main(int argc, char **argv)
30sleep_main(int argc, char * * argv)
31{ 30{
32 if ( (argc < 2) || (**(argv+1) == '-') ) { 31 if ((argc < 2) || (**(argv + 1) == '-')) {
33 usage( sleep_usage ); 32 usage(sleep_usage);
34 } 33 }
35 34
36 if ( sleep(atoi(*(++argv))) != 0 ) { 35 if (sleep(atoi(*(++argv))) != 0) {
37 perror( "sleep"); 36 perror("sleep");
38 exit (FALSE); 37 exit(FALSE);
39 } else 38 } else
40 exit (TRUE); 39 exit(TRUE);
41} 40}
diff --git a/coreutils/sort.c b/coreutils/sort.c
index d529ce722..609c5e08c 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini sort implementation for busybox 3 * Mini sort implementation for busybox
3 * 4 *
@@ -28,29 +29,27 @@
28#include <stdio.h> 29#include <stdio.h>
29#include <errno.h> 30#include <errno.h>
30 31
31static const char sort_usage[] = 32static const char sort_usage[] = "sort [OPTION]... [FILE]...\n\n";
32"sort [OPTION]... [FILE]...\n\n"
33;
34 33
35/* typedefs _______________________________________________________________ */ 34/* typedefs _______________________________________________________________ */
36 35
37/* line node */ 36/* line node */
38typedef struct Line { 37typedef struct Line {
39 char *data; /* line data */ 38 char *data; /* line data */
40 struct Line *next; /* pointer to next line node */ 39 struct Line *next; /* pointer to next line node */
41} Line; 40} Line;
42 41
43/* singly-linked list of lines */ 42/* singly-linked list of lines */
44typedef struct { 43typedef struct {
45 int len; /* number of Lines */ 44 int len; /* number of Lines */
46 Line **sorted; /* array fed to qsort */ 45 Line **sorted; /* array fed to qsort */
47 46
48 Line *head; /* head of List */ 47 Line *head; /* head of List */
49 Line *current; /* current Line */ 48 Line *current; /* current Line */
50} List; 49} List;
51 50
52/* comparison function */ 51/* comparison function */
53typedef int (Compare)(const void *, const void *); 52typedef int (Compare) (const void *, const void *);
54 53
55 54
56/* methods ________________________________________________________________ */ 55/* methods ________________________________________________________________ */
@@ -58,175 +57,176 @@ typedef int (Compare)(const void *, const void *);
58static const int max = 1024; 57static const int max = 1024;
59 58
60/* mallocate Line */ 59/* mallocate Line */
61static Line * 60static Line *line_alloc()
62line_alloc()
63{ 61{
64 Line *self; 62 Line *self;
65 self = malloc(1 * sizeof(Line)); 63
66 return self; 64 self = malloc(1 * sizeof(Line));
65 return self;
67} 66}
68 67
69/* Initialize Line with string */ 68/* Initialize Line with string */
70static Line * 69static Line *line_init(Line * self, const char *string)
71line_init(Line *self, const char *string)
72{ 70{
73 self->data = malloc((strlen(string) + 1) * sizeof(char)); 71 self->data = malloc((strlen(string) + 1) * sizeof(char));
74 if (self->data == NULL) { return NULL; } 72
75 strcpy(self->data, string); 73 if (self->data == NULL) {
76 self->next = NULL; 74 return NULL;
77 return self; 75 }
76 strcpy(self->data, string);
77 self->next = NULL;
78 return self;
78} 79}
79 80
80/* Construct Line from FILE* */ 81/* Construct Line from FILE* */
81static Line * 82static Line *line_newFromFile(FILE * src)
82line_newFromFile(FILE *src)
83{ 83{
84 char buffer[max]; 84 char buffer[max];
85 Line *self; 85 Line *self;
86 86
87 if (fgets(buffer, max, src)) { 87 if (fgets(buffer, max, src)) {
88 self = line_alloc(); 88 self = line_alloc();
89 if (self == NULL) { return NULL; } 89 if (self == NULL) {
90 line_init(self, buffer); 90 return NULL;
91 return self; 91 }
92 } 92 line_init(self, buffer);
93 return NULL; 93 return self;
94 }
95 return NULL;
94} 96}
95 97
96/* Line destructor */ 98/* Line destructor */
97static Line * 99static Line *line_release(Line * self)
98line_release(Line *self)
99{ 100{
100 if (self->data) { 101 if (self->data) {
101 free(self->data); 102 free(self->data);
102 free(self); 103 free(self);
103 } 104 }
104 return self; 105 return self;
105} 106}
106 107
107 108
108/* Comparison */ 109/* Comparison */
109 110
110/* ascii order */ 111/* ascii order */
111static int 112static int compare_ascii(const void *a, const void *b)
112compare_ascii(const void *a, const void *b)
113{ 113{
114 Line **doh; 114 Line **doh;
115 Line *x, *y; 115 Line *x, *y;
116 116
117 doh = (Line **) a; 117 doh = (Line **) a;
118 x = *doh; 118 x = *doh;
119 doh = (Line **) b; 119 doh = (Line **) b;
120 y = *doh; 120 y = *doh;
121 121
122 // fprintf(stdout, "> %p: %s< %p: %s", x, x->data, y, y->data); 122 // fprintf(stdout, "> %p: %s< %p: %s", x, x->data, y, y->data);
123 return strcmp(x->data, y->data); 123 return strcmp(x->data, y->data);
124} 124}
125 125
126/* numeric order */ 126/* numeric order */
127static int 127static int compare_numeric(const void *a, const void *b)
128compare_numeric(const void *a, const void *b)
129{ 128{
130 Line **doh; 129 Line **doh;
131 Line *x, *y; 130 Line *x, *y;
132 int xint, yint; 131 int xint, yint;
133 132
134 doh = (Line **) a; 133 doh = (Line **) a;
135 x = *doh; 134 x = *doh;
136 doh = (Line **) b; 135 doh = (Line **) b;
137 y = *doh; 136 y = *doh;
138 137
139 xint = strtoul(x->data, NULL, 10); 138 xint = strtoul(x->data, NULL, 10);
140 yint = strtoul(y->data, NULL, 10); 139 yint = strtoul(y->data, NULL, 10);
141 140
142 return (xint - yint); 141 return (xint - yint);
143} 142}
144 143
145 144
146/* List */ 145/* List */
147 146
148/* */ 147/* */
149static List * 148static List *list_init(List * self)
150list_init(List *self)
151{ 149{
152 self->len = 0; 150 self->len = 0;
153 self->sorted = NULL; 151 self->sorted = NULL;
154 self->head = NULL; 152 self->head = NULL;
155 self->current = NULL; 153 self->current = NULL;
156 return self; 154 return self;
157} 155}
158 156
159/* for simplicity, the List gains ownership of the line */ 157/* for simplicity, the List gains ownership of the line */
160static List * 158static List *list_insert(List * self, Line * line)
161list_insert(List *self, Line *line)
162{ 159{
163 if (line == NULL) { return NULL; } 160 if (line == NULL) {
164 161 return NULL;
165 /* first insertion */ 162 }
166 if (self->head == NULL) { 163
167 self->head = line; 164 /* first insertion */
168 self->current = line; 165 if (self->head == NULL) {
169 166 self->head = line;
170 /* all subsequent insertions */ 167 self->current = line;
171 } else { 168
172 self->current->next = line; 169 /* all subsequent insertions */
173 self->current = line; 170 } else {
174 } 171 self->current->next = line;
175 self->len++; 172 self->current = line;
176 return self; 173 }
174 self->len++;
175 return self;
177} 176}
178 177
179/* order the list according to compare() */ 178/* order the list according to compare() */
180static List * 179static List *list_sort(List * self, Compare * compare)
181list_sort(List *self, Compare *compare)
182{ 180{
183 int i; 181 int i;
184 Line *line; 182 Line *line;
185 183
186 /* mallocate array of Line*s */ 184 /* mallocate array of Line*s */
187 self->sorted = (Line **) malloc(self->len * sizeof(Line*)); 185 self->sorted = (Line **) malloc(self->len * sizeof(Line *));
188 if (self->sorted == NULL) { return NULL; } 186 if (self->sorted == NULL) {
189 187 return NULL;
190 /* fill array w/ List's contents */ 188 }
191 i = 0; 189
192 line = self->head; 190 /* fill array w/ List's contents */
193 while (line) { 191 i = 0;
194 self->sorted[i++] = line; 192 line = self->head;
195 line = line->next; 193 while (line) {
196 } 194 self->sorted[i++] = line;
197 195 line = line->next;
198 /* apply qsort */ 196 }
199 qsort(self->sorted, self->len, sizeof(Line*), compare); 197
200 return self; 198 /* apply qsort */
199 qsort(self->sorted, self->len, sizeof(Line *), compare);
200 return self;
201} 201}
202 202
203/* precondition: list must be sorted */ 203/* precondition: list must be sorted */
204static List * 204static List *list_writeToFile(List * self, FILE * dst)
205list_writeToFile(List *self, FILE* dst)
206{ 205{
207 int i; 206 int i;
208 Line **line = self->sorted; 207 Line **line = self->sorted;
209 208
210 if (self->sorted == NULL) { return NULL; } 209 if (self->sorted == NULL) {
211 for (i = 0; i < self->len; i++) { 210 return NULL;
212 fprintf(dst, "%s", line[i]->data); 211 }
213 } 212 for (i = 0; i < self->len; i++) {
214 return self; 213 fprintf(dst, "%s", line[i]->data);
214 }
215 return self;
215} 216}
216 217
217/* deallocate */ 218/* deallocate */
218static void 219static void list_release(List * self)
219list_release(List *self)
220{ 220{
221 Line *i; 221 Line *i;
222 Line *die; 222 Line *die;
223 223
224 i = self->head; 224 i = self->head;
225 while (i) { 225 while (i) {
226 die = i; 226 die = i;
227 i = die->next; 227 i = die->next;
228 line_release(die); 228 line_release(die);
229 } 229 }
230} 230}
231 231
232 232
@@ -237,76 +237,77 @@ list_release(List *self)
237 * and finally print it 237 * and finally print it
238 */ 238 */
239 239
240int 240int sort_main(int argc, char **argv)
241sort_main(int argc, char **argv)
242{ 241{
243 int i; 242 int i;
244 char opt; 243 char opt;
245 List list; 244 List list;
246 Line *l; 245 Line *l;
247 Compare *compare; 246 Compare *compare;
248 247
249 /* init */ 248 /* init */
250 compare = compare_ascii; 249 compare = compare_ascii;
251 list_init(&list); 250 list_init(&list);
252 251
253 /* parse argv[] */ 252 /* parse argv[] */
254 for (i = 1; i < argc; i++) { 253 for (i = 1; i < argc; i++) {
255 if (argv[i][0] == '-') { 254 if (argv[i][0] == '-') {
256 opt = argv[i][1]; 255 opt = argv[i][1];
257 switch (opt) { 256 switch (opt) {
258 case 'g': 257 case 'g':
259 /* what's the diff between -g && -n? */ 258 /* what's the diff between -g && -n? */
260 compare = compare_numeric; 259 compare = compare_numeric;
261 break; 260 break;
262 case 'h': 261 case 'h':
263 usage(sort_usage); 262 usage(sort_usage);
264 break; 263 break;
265 case 'n': 264 case 'n':
266 /* what's the diff between -g && -n? */ 265 /* what's the diff between -g && -n? */
267 compare = compare_numeric; 266 compare = compare_numeric;
268 break; 267 break;
269 case 'r': 268 case 'r':
270 /* reverse */ 269 /* reverse */
271 break; 270 break;
272 default: 271 default:
273 fprintf(stderr, "sort: invalid option -- %c\n", opt); 272 fprintf(stderr, "sort: invalid option -- %c\n", opt);
274 usage(sort_usage); 273 usage(sort_usage);
275 } 274 }
276 } else { 275 } else {
277 break; 276 break;
277 }
278 } 278 }
279 }
280 279
281 /* this could be factored better */ 280 /* this could be factored better */
282 281
283 /* work w/ stdin */ 282 /* work w/ stdin */
284 if (i >= argc) { 283 if (i >= argc) {
285 while ( (l = line_newFromFile(stdin))) { 284 while ((l = line_newFromFile(stdin))) {
286 list_insert(&list, l); 285 list_insert(&list, l);
287 } 286 }
288 list_sort(&list, compare); 287 list_sort(&list, compare);
289 list_writeToFile(&list, stdout); 288 list_writeToFile(&list, stdout);
290 list_release(&list); 289 list_release(&list);
291 290
292 /* work w/ what's left in argv[] */ 291 /* work w/ what's left in argv[] */
293 } else { 292 } else {
294 FILE *src; 293 FILE *src;
295 294
296 for ( ; i < argc; i++) { 295 for (; i < argc; i++) {
297 src = fopen(argv[i], "r"); 296 src = fopen(argv[i], "r");
298 if (src == NULL) { break; } 297 if (src == NULL) {
299 while ( (l = line_newFromFile(src))) { 298 break;
300 list_insert(&list, l); 299 }
301 } 300 while ((l = line_newFromFile(src))) {
302 fclose(src); 301 list_insert(&list, l);
302 }
303 fclose(src);
304 }
305 list_sort(&list, compare);
306 list_writeToFile(&list, stdout);
307 list_release(&list);
303 } 308 }
304 list_sort(&list, compare);
305 list_writeToFile(&list, stdout);
306 list_release(&list);
307 }
308 309
309 exit(0); 310 exit(0);
310} 311}
311 312
312/* $Id: sort.c,v 1.10 2000/02/07 05:29:42 erik Exp $ */ 313/* $Id: sort.c,v 1.11 2000/02/08 19:58:47 erik Exp $ */
diff --git a/coreutils/sync.c b/coreutils/sync.c
index 145ed1eda..f8160c8dc 100644
--- a/coreutils/sync.c
+++ b/coreutils/sync.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini sync implementation for busybox 3 * Mini sync implementation for busybox
3 * 4 *
@@ -23,12 +24,10 @@
23#include "internal.h" 24#include "internal.h"
24#include <stdio.h> 25#include <stdio.h>
25 26
26extern int 27extern int sync_main(int argc, char **argv)
27sync_main(int argc, char * * argv)
28{ 28{
29 if ( argc>1 && **(argv+1) == '-' ) { 29 if (argc > 1 && **(argv + 1) == '-') {
30 usage( "sync\n\nWrite all buffered filesystem blocks to disk.\n"); 30 usage("sync\n\nWrite all buffered filesystem blocks to disk.\n");
31 } 31 }
32 exit( sync()); 32 exit(sync());
33} 33}
34
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 0ab8f11b0..31705afa2 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2/* This file contains _two_ implementations of tail. One is 3/* This file contains _two_ implementations of tail. One is
3 * a bit more full featured, but costs 6k. The other (i.e. the 4 * a bit more full featured, but costs 6k. The other (i.e. the
@@ -68,22 +69,23 @@ static int forever;
68static int print_headers; 69static int print_headers;
69 70
70const char tail_usage[] = 71const char tail_usage[] =
71 "tail [OPTION] [FILE]...\n\n" 72 "tail [OPTION] [FILE]...\n\n"
72 "Print last 10 lines of each FILE to standard output.\n" 73 "Print last 10 lines of each FILE to standard output.\n"
73 "With more than one FILE, precede each with a header giving the\n" 74 "With more than one FILE, precede each with a header giving the\n"
74 "file name. With no FILE, or when FILE is -, read standard input.\n\n" 75 "file name. With no FILE, or when FILE is -, read standard input.\n\n"
75 "Options:\n" 76 "Options:\n"
76 "\t-n NUM\t\tPrint last NUM lines instead of first 10\n" 77 "\t-n NUM\t\tPrint last NUM lines instead of first 10\n"
77 "\t-f\t\tOutput data as the file grows. This version\n" 78
78 "\t\t\tof 'tail -f' supports only one file at a time.\n"; 79 "\t-f\t\tOutput data as the file grows. This version\n"
80 "\t\t\tof 'tail -f' supports only one file at a time.\n";
79 81
80 82
81static void write_header(const char *filename) 83static void write_header(const char *filename)
82{ 84{
83 static int first_file = 1; 85 static int first_file = 1;
84 86
85 printf("%s==> %s <==\n", (first_file ? "" : "\n"), filename); 87 printf("%s==> %s <==\n", (first_file ? "" : "\n"), filename);
86 first_file = 0; 88 first_file = 0;
87} 89}
88 90
89/* Print the last N_LINES lines from the end of file FD. 91/* Print the last N_LINES lines from the end of file FD.
@@ -97,57 +99,57 @@ static void write_header(const char *filename)
97static int 99static int
98file_lines(const char *filename, int fd, long int n_lines, off_t pos) 100file_lines(const char *filename, int fd, long int n_lines, off_t pos)
99{ 101{
100 char buffer[BUFSIZ]; 102 char buffer[BUFSIZ];
101 int bytes_read; 103 int bytes_read;
102 int i; /* Index into `buffer' for scanning. */ 104 int i; /* Index into `buffer' for scanning. */
103
104 if (n_lines == 0)
105 return 0;
106 105
107 /* Set `bytes_read' to the size of the last, probably partial, buffer; 106 if (n_lines == 0)
108 0 < `bytes_read' <= `BUFSIZ'. */
109 bytes_read = pos % BUFSIZ;
110 if (bytes_read == 0)
111 bytes_read = BUFSIZ;
112 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
113 reads will be on block boundaries, which might increase efficiency. */
114 pos -= bytes_read;
115 lseek(fd, pos, SEEK_SET);
116 bytes_read = fullRead(fd, buffer, bytes_read);
117 if (bytes_read == -1)
118 error("read error");
119
120 /* Count the incomplete line on files that don't end with a newline. */
121 if (bytes_read && buffer[bytes_read - 1] != '\n')
122 --n_lines;
123
124 do {
125 /* Scan backward, counting the newlines in this bufferfull. */
126 for (i = bytes_read - 1; i >= 0; i--) {
127 /* Have we counted the requested number of newlines yet? */
128 if (buffer[i] == '\n' && n_lines-- == 0) {
129 /* If this newline wasn't the last character in the buffer,
130 print the text after it. */
131 if (i != bytes_read - 1)
132 XWRITE(STDOUT_FILENO, &buffer[i + 1],
133 bytes_read - (i + 1));
134 return 0; 107 return 0;
135 } 108
136 } 109 /* Set `bytes_read' to the size of the last, probably partial, buffer;
137 /* Not enough newlines in that bufferfull. */ 110 0 < `bytes_read' <= `BUFSIZ'. */
138 if (pos == 0) { 111 bytes_read = pos % BUFSIZ;
139 /* Not enough lines in the file; print the entire file. */ 112 if (bytes_read == 0)
140 lseek(fd, (off_t) 0, SEEK_SET); 113 bytes_read = BUFSIZ;
141 return 0; 114 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
142 } 115 reads will be on block boundaries, which might increase efficiency. */
143 pos -= BUFSIZ; 116 pos -= bytes_read;
144 lseek(fd, pos, SEEK_SET); 117 lseek(fd, pos, SEEK_SET);
145 } 118 bytes_read = fullRead(fd, buffer, bytes_read);
146 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0); 119 if (bytes_read == -1)
147 if (bytes_read == -1) 120 error("read error");
148 error("read error"); 121
122 /* Count the incomplete line on files that don't end with a newline. */
123 if (bytes_read && buffer[bytes_read - 1] != '\n')
124 --n_lines;
125
126 do {
127 /* Scan backward, counting the newlines in this bufferfull. */
128 for (i = bytes_read - 1; i >= 0; i--) {
129 /* Have we counted the requested number of newlines yet? */
130 if (buffer[i] == '\n' && n_lines-- == 0) {
131 /* If this newline wasn't the last character in the buffer,
132 print the text after it. */
133 if (i != bytes_read - 1)
134 XWRITE(STDOUT_FILENO, &buffer[i + 1],
135 bytes_read - (i + 1));
136 return 0;
137 }
138 }
139 /* Not enough newlines in that bufferfull. */
140 if (pos == 0) {
141 /* Not enough lines in the file; print the entire file. */
142 lseek(fd, (off_t) 0, SEEK_SET);
143 return 0;
144 }
145 pos -= BUFSIZ;
146 lseek(fd, pos, SEEK_SET);
147 }
148 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
149 if (bytes_read == -1)
150 error("read error");
149 151
150 return 0; 152 return 0;
151} 153}
152 154
153/* Print the last N_LINES lines from the end of the standard input, 155/* Print the last N_LINES lines from the end of the standard input,
@@ -157,100 +159,100 @@ file_lines(const char *filename, int fd, long int n_lines, off_t pos)
157 159
158static int pipe_lines(const char *filename, int fd, long int n_lines) 160static int pipe_lines(const char *filename, int fd, long int n_lines)
159{ 161{
160 struct linebuffer { 162 struct linebuffer {
161 int nbytes, nlines; 163 int nbytes, nlines;
162 char buffer[BUFSIZ]; 164 char buffer[BUFSIZ];
163 struct linebuffer *next; 165 struct linebuffer *next;
164 }; 166 };
165 typedef struct linebuffer LBUFFER; 167 typedef struct linebuffer LBUFFER;
166 LBUFFER *first, *last, *tmp; 168 LBUFFER *first, *last, *tmp;
167 int i; /* Index into buffers. */ 169 int i; /* Index into buffers. */
168 int total_lines = 0; /* Total number of newlines in all buffers. */ 170 int total_lines = 0; /* Total number of newlines in all buffers. */
169 int errors = 0; 171 int errors = 0;
170 172
171 first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER)); 173 first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
172 first->nbytes = first->nlines = 0; 174 first->nbytes = first->nlines = 0;
173 first->next = NULL; 175 first->next = NULL;
174 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER)); 176 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
175 177
176 /* Input is always read into a fresh buffer. */ 178 /* Input is always read into a fresh buffer. */
177 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) { 179 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
178 tmp->nlines = 0; 180 tmp->nlines = 0;
179 tmp->next = NULL; 181 tmp->next = NULL;
180 182
181 /* Count the number of newlines just read. */ 183 /* Count the number of newlines just read. */
182 for (i = 0; i < tmp->nbytes; i++) 184 for (i = 0; i < tmp->nbytes; i++)
183 if (tmp->buffer[i] == '\n') 185 if (tmp->buffer[i] == '\n')
184 ++tmp->nlines; 186 ++tmp->nlines;
185 total_lines += tmp->nlines; 187 total_lines += tmp->nlines;
186 188
187 /* If there is enough room in the last buffer read, just append the new 189 /* If there is enough room in the last buffer read, just append the new
188 one to it. This is because when reading from a pipe, `nbytes' can 190 one to it. This is because when reading from a pipe, `nbytes' can
189 often be very small. */ 191 often be very small. */
190 if (tmp->nbytes + last->nbytes < BUFSIZ) { 192 if (tmp->nbytes + last->nbytes < BUFSIZ) {
191 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes); 193 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
192 last->nbytes += tmp->nbytes; 194 last->nbytes += tmp->nbytes;
193 last->nlines += tmp->nlines; 195 last->nlines += tmp->nlines;
194 } else { 196 } else {
195 /* If there's not enough room, link the new buffer onto the end of 197 /* If there's not enough room, link the new buffer onto the end of
196 the list, then either free up the oldest buffer for the next 198 the list, then either free up the oldest buffer for the next
197 read if that would leave enough lines, or else malloc a new one. 199 read if that would leave enough lines, or else malloc a new one.
198 Some compaction mechanism is possible but probably not 200 Some compaction mechanism is possible but probably not
199 worthwhile. */ 201 worthwhile. */
200 last = last->next = tmp; 202 last = last->next = tmp;
201 if (total_lines - first->nlines > n_lines) { 203 if (total_lines - first->nlines > n_lines) {
202 tmp = first; 204 tmp = first;
203 total_lines -= first->nlines; 205 total_lines -= first->nlines;
204 first = first->next; 206 first = first->next;
205 } else 207 } else
206 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER)); 208 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
209 }
207 } 210 }
208 } 211 if (tmp->nbytes == -1)
209 if (tmp->nbytes == -1) 212 error("read error");
210 error("read error"); 213
211 214 free((char *) tmp);
212 free((char *) tmp); 215
213 216 /* This prevents a core dump when the pipe contains no newlines. */
214 /* This prevents a core dump when the pipe contains no newlines. */ 217 if (n_lines == 0)
215 if (n_lines == 0) 218 goto free_lbuffers;
216 goto free_lbuffers; 219
217 220 /* Count the incomplete line on files that don't end with a newline. */
218 /* Count the incomplete line on files that don't end with a newline. */ 221 if (last->buffer[last->nbytes - 1] != '\n') {
219 if (last->buffer[last->nbytes - 1] != '\n') { 222 ++last->nlines;
220 ++last->nlines; 223 ++total_lines;
221 ++total_lines; 224 }
222 } 225
223 226 /* Run through the list, printing lines. First, skip over unneeded
224 /* Run through the list, printing lines. First, skip over unneeded 227 buffers. */
225 buffers. */ 228 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
226 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next) 229 total_lines -= tmp->nlines;
227 total_lines -= tmp->nlines; 230
228 231 /* Find the correct beginning, then print the rest of the file. */
229 /* Find the correct beginning, then print the rest of the file. */ 232 if (total_lines > n_lines) {
230 if (total_lines > n_lines) { 233 char *cp;
231 char *cp; 234
232 235 /* Skip `total_lines' - `n_lines' newlines. We made sure that
233 /* Skip `total_lines' - `n_lines' newlines. We made sure that 236 `total_lines' - `n_lines' <= `tmp->nlines'. */
234 `total_lines' - `n_lines' <= `tmp->nlines'. */ 237 cp = tmp->buffer;
235 cp = tmp->buffer; 238 for (i = total_lines - n_lines; i; --i)
236 for (i = total_lines - n_lines; i; --i) 239 while (*cp++ != '\n')
237 while (*cp++ != '\n') 240 /* Do nothing. */ ;
238 /* Do nothing. */ ; 241 i = cp - tmp->buffer;
239 i = cp - tmp->buffer; 242 } else
240 } else 243 i = 0;
241 i = 0; 244 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
242 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i); 245
243 246 for (tmp = tmp->next; tmp; tmp = tmp->next)
244 for (tmp = tmp->next; tmp; tmp = tmp->next) 247 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
245 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
246 248
247 free_lbuffers: 249 free_lbuffers:
248 while (first) { 250 while (first) {
249 tmp = first->next; 251 tmp = first->next;
250 free((char *) first); 252 free((char *) first);
251 first = tmp; 253 first = tmp;
252 } 254 }
253 return errors; 255 return errors;
254} 256}
255 257
256/* Display file FILENAME from the current position in FD to the end. 258/* Display file FILENAME from the current position in FD to the end.
@@ -259,25 +261,25 @@ static int pipe_lines(const char *filename, int fd, long int n_lines)
259 261
260static long dump_remainder(const char *filename, int fd) 262static long dump_remainder(const char *filename, int fd)
261{ 263{
262 char buffer[BUFSIZ]; 264 char buffer[BUFSIZ];
263 int bytes_read; 265 int bytes_read;
264 long total; 266 long total;
265 267
266 total = 0; 268 total = 0;
267 output: 269 output:
268 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) { 270 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
269 XWRITE(STDOUT_FILENO, buffer, bytes_read); 271 XWRITE(STDOUT_FILENO, buffer, bytes_read);
270 total += bytes_read; 272 total += bytes_read;
271 } 273 }
272 if (bytes_read == -1) 274 if (bytes_read == -1)
273 error("read error"); 275 error("read error");
274 if (forever) { 276 if (forever) {
275 fflush(stdout); 277 fflush(stdout);
276 sleep(1); 278 sleep(1);
277 goto output; 279 goto output;
278 } 280 }
279 281
280 return total; 282 return total;
281} 283}
282 284
283/* Output the last N_LINES lines of file FILENAME open for reading in FD. 285/* Output the last N_LINES lines of file FILENAME open for reading in FD.
@@ -285,31 +287,31 @@ static long dump_remainder(const char *filename, int fd)
285 287
286static int tail_lines(const char *filename, int fd, long int n_lines) 288static int tail_lines(const char *filename, int fd, long int n_lines)
287{ 289{
288 struct stat stats; 290 struct stat stats;
289 off_t length; 291 off_t length;
290 292
291 if (print_headers) 293 if (print_headers)
292 write_header(filename); 294 write_header(filename);
293 295
294 if (fstat(fd, &stats)) 296 if (fstat(fd, &stats))
295 error("fstat error"); 297 error("fstat error");
296 298
297 /* Use file_lines only if FD refers to a regular file with 299 /* Use file_lines only if FD refers to a regular file with
298 its file pointer positioned at beginning of file. */ 300 its file pointer positioned at beginning of file. */
299 /* FIXME: adding the lseek conjunct is a kludge. 301 /* FIXME: adding the lseek conjunct is a kludge.
300 Once there's a reasonable test suite, fix the true culprit: 302 Once there's a reasonable test suite, fix the true culprit:
301 file_lines. file_lines shouldn't presume that the input 303 file_lines. file_lines shouldn't presume that the input
302 file pointer is initially positioned to beginning of file. */ 304 file pointer is initially positioned to beginning of file. */
303 if (S_ISREG(stats.st_mode) 305 if (S_ISREG(stats.st_mode)
304 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) { 306 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
305 length = lseek(fd, (off_t) 0, SEEK_END); 307 length = lseek(fd, (off_t) 0, SEEK_END);
306 if (length != 0 && file_lines(filename, fd, n_lines, length)) 308 if (length != 0 && file_lines(filename, fd, n_lines, length))
307 return 1; 309 return 1;
308 dump_remainder(filename, fd); 310 dump_remainder(filename, fd);
309 } else 311 } else
310 return pipe_lines(filename, fd, n_lines); 312 return pipe_lines(filename, fd, n_lines);
311 313
312 return 0; 314 return 0;
313} 315}
314 316
315/* Display the last N_UNITS lines of file FILENAME. 317/* Display the last N_UNITS lines of file FILENAME.
@@ -318,78 +320,78 @@ static int tail_lines(const char *filename, int fd, long int n_lines)
318 320
319static int tail_file(const char *filename, off_t n_units) 321static int tail_file(const char *filename, off_t n_units)
320{ 322{
321 int fd, errors; 323 int fd, errors;
322 324
323 if (!strcmp(filename, "-")) { 325 if (!strcmp(filename, "-")) {
324 filename = "standard input"; 326 filename = "standard input";
325 errors = tail_lines(filename, 0, (long) n_units); 327 errors = tail_lines(filename, 0, (long) n_units);
326 } else { 328 } else {
327 /* Not standard input. */ 329 /* Not standard input. */
328 fd = open(filename, O_RDONLY); 330 fd = open(filename, O_RDONLY);
329 if (fd == -1) 331 if (fd == -1)
330 error("open error"); 332 error("open error");
331 333
332 errors = tail_lines(filename, fd, (long) n_units); 334 errors = tail_lines(filename, fd, (long) n_units);
333 close(fd); 335 close(fd);
334 } 336 }
335 337
336 return errors; 338 return errors;
337} 339}
338 340
339extern int tail_main(int argc, char **argv) 341extern int tail_main(int argc, char **argv)
340{ 342{
341 int exit_status = 0; 343 int exit_status = 0;
342 int n_units = DEFAULT_N_LINES; 344 int n_units = DEFAULT_N_LINES;
343 int n_tmp, i; 345 int n_tmp, i;
344 char opt; 346 char opt;
345 347
346 forever = print_headers = 0; 348 forever = print_headers = 0;
347 349
348 /* parse argv[] */ 350 /* parse argv[] */
349 for (i = 1; i < argc; i++) { 351 for (i = 1; i < argc; i++) {
350 if (argv[i][0] == '-') { 352 if (argv[i][0] == '-') {
351 opt = argv[i][1]; 353 opt = argv[i][1];
352 switch (opt) { 354 switch (opt) {
353 case 'f': 355 case 'f':
354 forever = 1; 356 forever = 1;
355 break; 357 break;
356 case 'n': 358 case 'n':
357 n_tmp = 0; 359 n_tmp = 0;
358 if (++i < argc) 360 if (++i < argc)
359 n_tmp = atoi(argv[i]); 361 n_tmp = atoi(argv[i]);
360 if (n_tmp < 1) 362 if (n_tmp < 1)
361 usage(tail_usage); 363 usage(tail_usage);
362 n_units = n_tmp; 364 n_units = n_tmp;
363 break; 365 break;
364 case '-': 366 case '-':
365 case 'h': 367 case 'h':
366 usage(tail_usage); 368 usage(tail_usage);
367 default: 369 default:
368 fprintf(stderr, "tail: invalid option -- %c\n", opt); 370 fprintf(stderr, "tail: invalid option -- %c\n", opt);
369 usage(tail_usage); 371 usage(tail_usage);
370 } 372 }
371 } else { 373 } else {
372 break; 374 break;
375 }
373 } 376 }
374 }
375 377
376 if (i + 1 < argc) { 378 if (i + 1 < argc) {
377 if (forever) { 379 if (forever) {
378 fprintf(stderr, 380 fprintf(stderr,
379 "tail: option -f is invalid with multiple files\n"); 381 "tail: option -f is invalid with multiple files\n");
380 usage(tail_usage); 382 usage(tail_usage);
383 }
384 print_headers = 1;
381 } 385 }
382 print_headers = 1;
383 }
384 386
385 if (i >= argc) { 387 if (i >= argc) {
386 exit_status |= tail_file("-", n_units); 388 exit_status |= tail_file("-", n_units);
387 } else { 389 } else {
388 for (; i < argc; i++) 390 for (; i < argc; i++)
389 exit_status |= tail_file(argv[i], n_units); 391 exit_status |= tail_file(argv[i], n_units);
390 } 392 }
391 393
392 exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 394 exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
393} 395}
394 396
395 397
@@ -441,15 +443,15 @@ extern int tail_main(int argc, char **argv)
441#define NDEBUG 1 443#define NDEBUG 1
442 444
443 445
444static void detailed_error(int i, int errnum, char* fmt, ...) 446static void detailed_error(int i, int errnum, char *fmt, ...)
445{ 447{
446 va_list arguments; 448 va_list arguments;
447 449
448 va_start(arguments, fmt); 450 va_start(arguments, fmt);
449 vfprintf(stderr, fmt, arguments); 451 vfprintf(stderr, fmt, arguments);
450 fprintf(stderr, "\n%s\n", strerror( errnum)); 452 fprintf(stderr, "\n%s\n", strerror(errnum));
451 va_end(arguments); 453 va_end(arguments);
452 exit(i); 454 exit(i);
453} 455}
454 456
455 457
@@ -494,9 +496,8 @@ static int from_start;
494static int print_headers; 496static int print_headers;
495 497
496/* When to print the filename banners. */ 498/* When to print the filename banners. */
497enum header_mode 499enum header_mode {
498{ 500 multiple_files, always, never
499 multiple_files, always, never
500}; 501};
501 502
502/* The name this program was run with. */ 503/* The name this program was run with. */
@@ -506,8 +507,7 @@ char *program_name;
506static int have_read_stdin; 507static int have_read_stdin;
507 508
508 509
509static const char tail_usage[] = 510static const char tail_usage[] = "tail [OPTION]... [FILE]...\n\
510"tail [OPTION]... [FILE]...\n\
511\n\ 511\n\
512Print last 10 lines of each FILE to standard output.\n\ 512Print last 10 lines of each FILE to standard output.\n\
513With more than one FILE, precede each with a header giving the file name.\n\ 513With more than one FILE, precede each with a header giving the file name.\n\
@@ -524,15 +524,13 @@ If the first character of N (bytes or lines) is a `+', output begins with \n\
524the Nth item from the start of each file, otherwise, print the last N items\n\ 524the Nth item from the start of each file, otherwise, print the last N items\n\
525in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n"; 525in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n";
526 526
527static void 527static void write_header(const char *filename, const char *comment)
528write_header (const char *filename, const char *comment)
529{ 528{
530 static int first_file = 1; 529 static int first_file = 1;
531 530
532 printf ("%s==> %s%s%s <==\n", (first_file ? "" : "\n"), filename, 531 printf("%s==> %s%s%s <==\n", (first_file ? "" : "\n"), filename,
533 (comment ? ": " : ""), 532 (comment ? ": " : ""), (comment ? comment : ""));
534 (comment ? comment : "")); 533 first_file = 0;
535 first_file = 0;
536} 534}
537 535
538/* Print the last N_LINES lines from the end of file FD. 536/* Print the last N_LINES lines from the end of file FD.
@@ -544,67 +542,62 @@ write_header (const char *filename, const char *comment)
544 Return 0 if successful, 1 if an error occurred. */ 542 Return 0 if successful, 1 if an error occurred. */
545 543
546static int 544static int
547file_lines (const char *filename, int fd, long int n_lines, off_t pos) 545file_lines(const char *filename, int fd, long int n_lines, off_t pos)
548{ 546{
549 char buffer[BUFSIZ]; 547 char buffer[BUFSIZ];
550 int bytes_read; 548 int bytes_read;
551 int i; /* Index into `buffer' for scanning. */ 549 int i; /* Index into `buffer' for scanning. */
552 550
553 if (n_lines == 0) 551 if (n_lines == 0)
554 return 0; 552 return 0;
555 553
556 /* Set `bytes_read' to the size of the last, probably partial, buffer; 554 /* Set `bytes_read' to the size of the last, probably partial, buffer;
557 0 < `bytes_read' <= `BUFSIZ'. */ 555 0 < `bytes_read' <= `BUFSIZ'. */
558 bytes_read = pos % BUFSIZ; 556 bytes_read = pos % BUFSIZ;
559 if (bytes_read == 0) 557 if (bytes_read == 0)
560 bytes_read = BUFSIZ; 558 bytes_read = BUFSIZ;
561 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all 559 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
562 reads will be on block boundaries, which might increase efficiency. */ 560 reads will be on block boundaries, which might increase efficiency. */
563 pos -= bytes_read; 561 pos -= bytes_read;
564 lseek (fd, pos, SEEK_SET); 562 lseek(fd, pos, SEEK_SET);
565 bytes_read = fullRead (fd, buffer, bytes_read); 563 bytes_read = fullRead(fd, buffer, bytes_read);
566 if (bytes_read == -1) 564 if (bytes_read == -1) {
567 { 565 detailed_error(0, errno, "%s", filename);
568 detailed_error (0, errno, "%s", filename); 566 return 1;
569 return 1; 567 }
570 } 568
571 569 /* Count the incomplete line on files that don't end with a newline. */
572 /* Count the incomplete line on files that don't end with a newline. */ 570 if (bytes_read && buffer[bytes_read - 1] != '\n')
573 if (bytes_read && buffer[bytes_read - 1] != '\n') 571 --n_lines;
574 --n_lines; 572
575 573 do {
576 do 574 /* Scan backward, counting the newlines in this bufferfull. */
577 { 575 for (i = bytes_read - 1; i >= 0; i--) {
578 /* Scan backward, counting the newlines in this bufferfull. */ 576 /* Have we counted the requested number of newlines yet? */
579 for (i = bytes_read - 1; i >= 0; i--) 577 if (buffer[i] == '\n' && n_lines-- == 0) {
580 { 578 /* If this newline wasn't the last character in the buffer,
581 /* Have we counted the requested number of newlines yet? */ 579 print the text after it. */
582 if (buffer[i] == '\n' && n_lines-- == 0) 580 if (i != bytes_read - 1)
583 { 581 XWRITE(STDOUT_FILENO, &buffer[i + 1],
584 /* If this newline wasn't the last character in the buffer, 582 bytes_read - (i + 1));
585 print the text after it. */ 583 return 0;
586 if (i != bytes_read - 1) 584 }
587 XWRITE (STDOUT_FILENO, &buffer[i + 1], bytes_read - (i + 1)); 585 }
588 return 0; 586 /* Not enough newlines in that bufferfull. */
589 } 587 if (pos == 0) {
588 /* Not enough lines in the file; print the entire file. */
589 lseek(fd, (off_t) 0, SEEK_SET);
590 return 0;
591 }
592 pos -= BUFSIZ;
593 lseek(fd, pos, SEEK_SET);
590 } 594 }
591 /* Not enough newlines in that bufferfull. */ 595 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
592 if (pos == 0) 596 if (bytes_read == -1) {
593 { 597 detailed_error(0, errno, "%s", filename);
594 /* Not enough lines in the file; print the entire file. */ 598 return 1;
595 lseek (fd, (off_t) 0, SEEK_SET);
596 return 0;
597 } 599 }
598 pos -= BUFSIZ; 600 return 0;
599 lseek (fd, pos, SEEK_SET);
600 }
601 while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0);
602 if (bytes_read == -1)
603 {
604 detailed_error (0, errno, "%s", filename);
605 return 1;
606 }
607 return 0;
608} 601}
609 602
610/* Print the last N_LINES lines from the end of the standard input, 603/* Print the last N_LINES lines from the end of the standard input,
@@ -612,301 +605,264 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
612 Buffer the text as a linked list of LBUFFERs, adding them as needed. 605 Buffer the text as a linked list of LBUFFERs, adding them as needed.
613 Return 0 if successful, 1 if an error occured. */ 606 Return 0 if successful, 1 if an error occured. */
614 607
615static int 608static int pipe_lines(const char *filename, int fd, long int n_lines)
616pipe_lines (const char *filename, int fd, long int n_lines)
617{ 609{
618 struct linebuffer 610 struct linebuffer {
619 { 611 int nbytes, nlines;
620 int nbytes, nlines; 612 char buffer[BUFSIZ];
621 char buffer[BUFSIZ]; 613 struct linebuffer *next;
622 struct linebuffer *next; 614 };
623 }; 615 typedef struct linebuffer LBUFFER;
624 typedef struct linebuffer LBUFFER; 616 LBUFFER *first, *last, *tmp;
625 LBUFFER *first, *last, *tmp; 617 int i; /* Index into buffers. */
626 int i; /* Index into buffers. */ 618 int total_lines = 0; /* Total number of newlines in all buffers. */
627 int total_lines = 0; /* Total number of newlines in all buffers. */ 619 int errors = 0;
628 int errors = 0; 620
629 621 first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
630 first = last = (LBUFFER *) xmalloc (sizeof (LBUFFER)); 622 first->nbytes = first->nlines = 0;
631 first->nbytes = first->nlines = 0; 623 first->next = NULL;
632 first->next = NULL; 624 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
633 tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); 625
634 626 /* Input is always read into a fresh buffer. */
635 /* Input is always read into a fresh buffer. */ 627 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
636 while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) 628 tmp->nlines = 0;
637 { 629 tmp->next = NULL;
638 tmp->nlines = 0; 630
639 tmp->next = NULL; 631 /* Count the number of newlines just read. */
640 632 for (i = 0; i < tmp->nbytes; i++)
641 /* Count the number of newlines just read. */ 633 if (tmp->buffer[i] == '\n')
642 for (i = 0; i < tmp->nbytes; i++) 634 ++tmp->nlines;
643 if (tmp->buffer[i] == '\n') 635 total_lines += tmp->nlines;
644 ++tmp->nlines; 636
645 total_lines += tmp->nlines; 637 /* If there is enough room in the last buffer read, just append the new
646 638 one to it. This is because when reading from a pipe, `nbytes' can
647 /* If there is enough room in the last buffer read, just append the new 639 often be very small. */
648 one to it. This is because when reading from a pipe, `nbytes' can 640 if (tmp->nbytes + last->nbytes < BUFSIZ) {
649 often be very small. */ 641 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
650 if (tmp->nbytes + last->nbytes < BUFSIZ) 642 last->nbytes += tmp->nbytes;
651 { 643 last->nlines += tmp->nlines;
652 memcpy (&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes); 644 } else {
653 last->nbytes += tmp->nbytes; 645 /* If there's not enough room, link the new buffer onto the end of
654 last->nlines += tmp->nlines; 646 the list, then either free up the oldest buffer for the next
647 read if that would leave enough lines, or else malloc a new one.
648 Some compaction mechanism is possible but probably not
649 worthwhile. */
650 last = last->next = tmp;
651 if (total_lines - first->nlines > n_lines) {
652 tmp = first;
653 total_lines -= first->nlines;
654 first = first->next;
655 } else
656 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
657 }
658 }
659 if (tmp->nbytes == -1) {
660 detailed_error(0, errno, "%s", filename);
661 errors = 1;
662 free((char *) tmp);
663 goto free_lbuffers;
655 } 664 }
656 else 665
657 { 666 free((char *) tmp);
658 /* If there's not enough room, link the new buffer onto the end of 667
659 the list, then either free up the oldest buffer for the next 668 /* This prevents a core dump when the pipe contains no newlines. */
660 read if that would leave enough lines, or else malloc a new one. 669 if (n_lines == 0)
661 Some compaction mechanism is possible but probably not 670 goto free_lbuffers;
662 worthwhile. */ 671
663 last = last->next = tmp; 672 /* Count the incomplete line on files that don't end with a newline. */
664 if (total_lines - first->nlines > n_lines) 673 if (last->buffer[last->nbytes - 1] != '\n') {
665 { 674 ++last->nlines;
666 tmp = first; 675 ++total_lines;
667 total_lines -= first->nlines; 676 }
668 first = first->next; 677
669 } 678 /* Run through the list, printing lines. First, skip over unneeded
670 else 679 buffers. */
671 tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); 680 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
681 total_lines -= tmp->nlines;
682
683 /* Find the correct beginning, then print the rest of the file. */
684 if (total_lines > n_lines) {
685 char *cp;
686
687 /* Skip `total_lines' - `n_lines' newlines. We made sure that
688 `total_lines' - `n_lines' <= `tmp->nlines'. */
689 cp = tmp->buffer;
690 for (i = total_lines - n_lines; i; --i)
691 while (*cp++ != '\n')
692 /* Do nothing. */ ;
693 i = cp - tmp->buffer;
694 } else
695 i = 0;
696 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
697
698 for (tmp = tmp->next; tmp; tmp = tmp->next)
699 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
700
701 free_lbuffers:
702 while (first) {
703 tmp = first->next;
704 free((char *) first);
705 first = tmp;
672 } 706 }
673 } 707 return errors;
674 if (tmp->nbytes == -1)
675 {
676 detailed_error (0, errno, "%s", filename);
677 errors = 1;
678 free ((char *) tmp);
679 goto free_lbuffers;
680 }
681
682 free ((char *) tmp);
683
684 /* This prevents a core dump when the pipe contains no newlines. */
685 if (n_lines == 0)
686 goto free_lbuffers;
687
688 /* Count the incomplete line on files that don't end with a newline. */
689 if (last->buffer[last->nbytes - 1] != '\n')
690 {
691 ++last->nlines;
692 ++total_lines;
693 }
694
695 /* Run through the list, printing lines. First, skip over unneeded
696 buffers. */
697 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
698 total_lines -= tmp->nlines;
699
700 /* Find the correct beginning, then print the rest of the file. */
701 if (total_lines > n_lines)
702 {
703 char *cp;
704
705 /* Skip `total_lines' - `n_lines' newlines. We made sure that
706 `total_lines' - `n_lines' <= `tmp->nlines'. */
707 cp = tmp->buffer;
708 for (i = total_lines - n_lines; i; --i)
709 while (*cp++ != '\n')
710 /* Do nothing. */ ;
711 i = cp - tmp->buffer;
712 }
713 else
714 i = 0;
715 XWRITE (STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
716
717 for (tmp = tmp->next; tmp; tmp = tmp->next)
718 XWRITE (STDOUT_FILENO, tmp->buffer, tmp->nbytes);
719
720free_lbuffers:
721 while (first)
722 {
723 tmp = first->next;
724 free ((char *) first);
725 first = tmp;
726 }
727 return errors;
728} 708}
729 709
730/* Print the last N_BYTES characters from the end of pipe FD. 710/* Print the last N_BYTES characters from the end of pipe FD.
731 This is a stripped down version of pipe_lines. 711 This is a stripped down version of pipe_lines.
732 Return 0 if successful, 1 if an error occurred. */ 712 Return 0 if successful, 1 if an error occurred. */
733 713
734static int 714static int pipe_bytes(const char *filename, int fd, off_t n_bytes)
735pipe_bytes (const char *filename, int fd, off_t n_bytes)
736{ 715{
737 struct charbuffer 716 struct charbuffer {
738 { 717 int nbytes;
739 int nbytes; 718 char buffer[BUFSIZ];
740 char buffer[BUFSIZ]; 719 struct charbuffer *next;
741 struct charbuffer *next; 720 };
742 }; 721 typedef struct charbuffer CBUFFER;
743 typedef struct charbuffer CBUFFER; 722 CBUFFER *first, *last, *tmp;
744 CBUFFER *first, *last, *tmp; 723 int i; /* Index into buffers. */
745 int i; /* Index into buffers. */ 724 int total_bytes = 0; /* Total characters in all buffers. */
746 int total_bytes = 0; /* Total characters in all buffers. */ 725 int errors = 0;
747 int errors = 0; 726
748 727 first = last = (CBUFFER *) xmalloc(sizeof(CBUFFER));
749 first = last = (CBUFFER *) xmalloc (sizeof (CBUFFER)); 728 first->nbytes = 0;
750 first->nbytes = 0; 729 first->next = NULL;
751 first->next = NULL; 730 tmp = (CBUFFER *) xmalloc(sizeof(CBUFFER));
752 tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); 731
753 732 /* Input is always read into a fresh buffer. */
754 /* Input is always read into a fresh buffer. */ 733 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
755 while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) 734 tmp->next = NULL;
756 { 735
757 tmp->next = NULL; 736 total_bytes += tmp->nbytes;
758 737 /* If there is enough room in the last buffer read, just append the new
759 total_bytes += tmp->nbytes; 738 one to it. This is because when reading from a pipe, `nbytes' can
760 /* If there is enough room in the last buffer read, just append the new 739 often be very small. */
761 one to it. This is because when reading from a pipe, `nbytes' can 740 if (tmp->nbytes + last->nbytes < BUFSIZ) {
762 often be very small. */ 741 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
763 if (tmp->nbytes + last->nbytes < BUFSIZ) 742 last->nbytes += tmp->nbytes;
764 { 743 } else {
765 memcpy (&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes); 744 /* If there's not enough room, link the new buffer onto the end of
766 last->nbytes += tmp->nbytes; 745 the list, then either free up the oldest buffer for the next
746 read if that would leave enough characters, or else malloc a new
747 one. Some compaction mechanism is possible but probably not
748 worthwhile. */
749 last = last->next = tmp;
750 if (total_bytes - first->nbytes > n_bytes) {
751 tmp = first;
752 total_bytes -= first->nbytes;
753 first = first->next;
754 } else {
755 tmp = (CBUFFER *) xmalloc(sizeof(CBUFFER));
756 }
757 }
767 } 758 }
768 else 759 if (tmp->nbytes == -1) {
769 { 760 detailed_error(0, errno, "%s", filename);
770 /* If there's not enough room, link the new buffer onto the end of 761 errors = 1;
771 the list, then either free up the oldest buffer for the next 762 free((char *) tmp);
772 read if that would leave enough characters, or else malloc a new 763 goto free_cbuffers;
773 one. Some compaction mechanism is possible but probably not 764 }
774 worthwhile. */ 765
775 last = last->next = tmp; 766 free((char *) tmp);
776 if (total_bytes - first->nbytes > n_bytes) 767
777 { 768 /* Run through the list, printing characters. First, skip over unneeded
778 tmp = first; 769 buffers. */
779 total_bytes -= first->nbytes; 770 for (tmp = first; total_bytes - tmp->nbytes > n_bytes; tmp = tmp->next)
780 first = first->next; 771 total_bytes -= tmp->nbytes;
781 } 772
782 else 773 /* Find the correct beginning, then print the rest of the file.
783 { 774 We made sure that `total_bytes' - `n_bytes' <= `tmp->nbytes'. */
784 tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); 775 if (total_bytes > n_bytes)
785 } 776 i = total_bytes - n_bytes;
777 else
778 i = 0;
779 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
780
781 for (tmp = tmp->next; tmp; tmp = tmp->next)
782 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
783
784 free_cbuffers:
785 while (first) {
786 tmp = first->next;
787 free((char *) first);
788 first = tmp;
786 } 789 }
787 } 790 return errors;
788 if (tmp->nbytes == -1)
789 {
790 detailed_error (0, errno, "%s", filename);
791 errors = 1;
792 free ((char *) tmp);
793 goto free_cbuffers;
794 }
795
796 free ((char *) tmp);
797
798 /* Run through the list, printing characters. First, skip over unneeded
799 buffers. */
800 for (tmp = first; total_bytes - tmp->nbytes > n_bytes; tmp = tmp->next)
801 total_bytes -= tmp->nbytes;
802
803 /* Find the correct beginning, then print the rest of the file.
804 We made sure that `total_bytes' - `n_bytes' <= `tmp->nbytes'. */
805 if (total_bytes > n_bytes)
806 i = total_bytes - n_bytes;
807 else
808 i = 0;
809 XWRITE (STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
810
811 for (tmp = tmp->next; tmp; tmp = tmp->next)
812 XWRITE (STDOUT_FILENO, tmp->buffer, tmp->nbytes);
813
814free_cbuffers:
815 while (first)
816 {
817 tmp = first->next;
818 free ((char *) first);
819 first = tmp;
820 }
821 return errors;
822} 791}
823 792
824/* Skip N_BYTES characters from the start of pipe FD, and print 793/* Skip N_BYTES characters from the start of pipe FD, and print
825 any extra characters that were read beyond that. 794 any extra characters that were read beyond that.
826 Return 1 on error, 0 if ok. */ 795 Return 1 on error, 0 if ok. */
827 796
828static int 797static int start_bytes(const char *filename, int fd, off_t n_bytes)
829start_bytes (const char *filename, int fd, off_t n_bytes)
830{ 798{
831 char buffer[BUFSIZ]; 799 char buffer[BUFSIZ];
832 int bytes_read = 0; 800 int bytes_read = 0;
833 801
834 while (n_bytes > 0 && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) 802 while (n_bytes > 0 && (bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0)
835 n_bytes -= bytes_read; 803 n_bytes -= bytes_read;
836 if (bytes_read == -1) 804 if (bytes_read == -1) {
837 { 805 detailed_error(0, errno, "%s", filename);
838 detailed_error (0, errno, "%s", filename); 806 return 1;
839 return 1; 807 } else if (n_bytes < 0)
840 } 808 XWRITE(STDOUT_FILENO, &buffer[bytes_read + n_bytes], -n_bytes);
841 else if (n_bytes < 0) 809 return 0;
842 XWRITE (STDOUT_FILENO, &buffer[bytes_read + n_bytes], -n_bytes);
843 return 0;
844} 810}
845 811
846/* Skip N_LINES lines at the start of file or pipe FD, and print 812/* Skip N_LINES lines at the start of file or pipe FD, and print
847 any extra characters that were read beyond that. 813 any extra characters that were read beyond that.
848 Return 1 on error, 0 if ok. */ 814 Return 1 on error, 0 if ok. */
849 815
850static int 816static int start_lines(const char *filename, int fd, long int n_lines)
851start_lines (const char *filename, int fd, long int n_lines)
852{ 817{
853 char buffer[BUFSIZ]; 818 char buffer[BUFSIZ];
854 int bytes_read = 0; 819 int bytes_read = 0;
855 int bytes_to_skip = 0; 820 int bytes_to_skip = 0;
856 821
857 while (n_lines && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) 822 while (n_lines && (bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
858 { 823 bytes_to_skip = 0;
859 bytes_to_skip = 0; 824 while (bytes_to_skip < bytes_read)
860 while (bytes_to_skip < bytes_read) 825 if (buffer[bytes_to_skip++] == '\n' && --n_lines == 0)
861 if (buffer[bytes_to_skip++] == '\n' && --n_lines == 0) 826 break;
862 break; 827 }
863 } 828 if (bytes_read == -1) {
864 if (bytes_read == -1) 829 detailed_error(0, errno, "%s", filename);
865 { 830 return 1;
866 detailed_error (0, errno, "%s", filename); 831 } else if (bytes_to_skip < bytes_read) {
867 return 1; 832 XWRITE(STDOUT_FILENO, &buffer[bytes_to_skip],
868 } 833 bytes_read - bytes_to_skip);
869 else if (bytes_to_skip < bytes_read) 834 }
870 { 835 return 0;
871 XWRITE (STDOUT_FILENO, &buffer[bytes_to_skip],
872 bytes_read - bytes_to_skip);
873 }
874 return 0;
875} 836}
876 837
877/* Display file FILENAME from the current position in FD to the end. 838/* Display file FILENAME from the current position in FD to the end.
878 If `forever' is nonzero, keep reading from the end of the file 839 If `forever' is nonzero, keep reading from the end of the file
879 until killed. Return the number of bytes read from the file. */ 840 until killed. Return the number of bytes read from the file. */
880 841
881static long 842static long dump_remainder(const char *filename, int fd)
882dump_remainder (const char *filename, int fd)
883{ 843{
884 char buffer[BUFSIZ]; 844 char buffer[BUFSIZ];
885 int bytes_read; 845 int bytes_read;
886 long total; 846 long total;
887 847
888 total = 0; 848 total = 0;
889output: 849 output:
890 while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) 850 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
891 { 851 XWRITE(STDOUT_FILENO, buffer, bytes_read);
892 XWRITE (STDOUT_FILENO, buffer, bytes_read); 852 total += bytes_read;
893 total += bytes_read; 853 }
894 } 854 if (bytes_read == -1)
895 if (bytes_read == -1) 855 detailed_error(EXIT_FAILURE, errno, "%s", filename);
896 detailed_error (EXIT_FAILURE, errno, "%s", filename); 856 if (forever) {
897 if (forever) 857 fflush(stdout);
898 { 858 sleep(1);
899 fflush (stdout); 859 goto output;
900 sleep (1); 860 } else {
901 goto output; 861 if (forever_multiple)
902 } 862 fflush(stdout);
903 else 863 }
904 { 864
905 if (forever_multiple) 865 return total;
906 fflush (stdout);
907 }
908
909 return total;
910} 866}
911 867
912/* Tail NFILES (>1) files forever until killed. The file names are in 868/* Tail NFILES (>1) files forever until killed. The file names are in
@@ -916,186 +872,161 @@ output:
916 none of them have changed size in one iteration, we sleep for a 872 none of them have changed size in one iteration, we sleep for a
917 second and try again. We do this until the user interrupts us. */ 873 second and try again. We do this until the user interrupts us. */
918 874
919static void 875static void tail_forever(char **names, int nfiles)
920tail_forever (char **names, int nfiles)
921{ 876{
922 int last; 877 int last;
923 878
924 last = -1; 879 last = -1;
925 880
926 while (1) 881 while (1) {
927 { 882 int i;
928 int i; 883 int changed;
929 int changed; 884
930 885 changed = 0;
931 changed = 0; 886 for (i = 0; i < nfiles; i++) {
932 for (i = 0; i < nfiles; i++) 887 struct stat stats;
933 { 888
934 struct stat stats; 889 if (file_descs[i] < 0)
935 890 continue;
936 if (file_descs[i] < 0) 891 if (fstat(file_descs[i], &stats) < 0) {
937 continue; 892 detailed_error(0, errno, "%s", names[i]);
938 if (fstat (file_descs[i], &stats) < 0) 893 file_descs[i] = -1;
939 { 894 continue;
940 detailed_error (0, errno, "%s", names[i]); 895 }
941 file_descs[i] = -1; 896 if (stats.st_size == file_sizes[i])
942 continue; 897 continue;
943 } 898
944 if (stats.st_size == file_sizes[i]) 899 /* This file has changed size. Print out what we can, and
945 continue; 900 then keep looping. */
946 901
947 /* This file has changed size. Print out what we can, and 902 changed = 1;
948 then keep looping. */ 903
949 904 if (stats.st_size < file_sizes[i]) {
950 changed = 1; 905 write_header(names[i], "file truncated");
951 906 last = i;
952 if (stats.st_size < file_sizes[i]) 907 lseek(file_descs[i], stats.st_size, SEEK_SET);
953 { 908 file_sizes[i] = stats.st_size;
954 write_header (names[i], "file truncated"); 909 continue;
955 last = i; 910 }
956 lseek (file_descs[i], stats.st_size, SEEK_SET); 911
957 file_sizes[i] = stats.st_size; 912 if (i != last) {
958 continue; 913 if (print_headers)
959 } 914 write_header(names[i], NULL);
960 915 last = i;
961 if (i != last) 916 }
962 { 917 file_sizes[i] += dump_remainder(names[i], file_descs[i]);
963 if (print_headers) 918 }
964 write_header (names[i], NULL);
965 last = i;
966 }
967 file_sizes[i] += dump_remainder (names[i], file_descs[i]);
968 }
969 919
970 /* If none of the files changed size, sleep. */ 920 /* If none of the files changed size, sleep. */
971 if (! changed) 921 if (!changed)
972 sleep (1); 922 sleep(1);
973 } 923 }
974} 924}
975 925
976/* Output the last N_BYTES bytes of file FILENAME open for reading in FD. 926/* Output the last N_BYTES bytes of file FILENAME open for reading in FD.
977 Return 0 if successful, 1 if an error occurred. */ 927 Return 0 if successful, 1 if an error occurred. */
978 928
979static int 929static int tail_bytes(const char *filename, int fd, off_t n_bytes)
980tail_bytes (const char *filename, int fd, off_t n_bytes)
981{ 930{
982 struct stat stats; 931 struct stat stats;
983 932
984 /* FIXME: resolve this like in dd.c. */ 933 /* FIXME: resolve this like in dd.c. */
985 /* Use fstat instead of checking for errno == ESPIPE because 934 /* Use fstat instead of checking for errno == ESPIPE because
986 lseek doesn't work on some special files but doesn't return an 935 lseek doesn't work on some special files but doesn't return an
987 error, either. */ 936 error, either. */
988 if (fstat (fd, &stats)) 937 if (fstat(fd, &stats)) {
989 { 938 detailed_error(0, errno, "%s", filename);
990 detailed_error (0, errno, "%s", filename); 939 return 1;
991 return 1; 940 }
992 } 941
993 942 if (from_start) {
994 if (from_start) 943 if (S_ISREG(stats.st_mode))
995 { 944 lseek(fd, n_bytes, SEEK_CUR);
996 if (S_ISREG (stats.st_mode)) 945 else if (start_bytes(filename, fd, n_bytes))
997 lseek (fd, n_bytes, SEEK_CUR); 946 return 1;
998 else if (start_bytes (filename, fd, n_bytes)) 947 dump_remainder(filename, fd);
999 return 1; 948 } else {
1000 dump_remainder (filename, fd); 949 if (S_ISREG(stats.st_mode)) {
1001 } 950 off_t current_pos, end_pos;
1002 else 951 size_t bytes_remaining;
1003 { 952
1004 if (S_ISREG (stats.st_mode)) 953 if ((current_pos = lseek(fd, (off_t) 0, SEEK_CUR)) != -1
1005 { 954 && (end_pos = lseek(fd, (off_t) 0, SEEK_END)) != -1) {
1006 off_t current_pos, end_pos; 955 off_t diff;
1007 size_t bytes_remaining; 956
1008 957 /* Be careful here. The current position may actually be
1009 if ((current_pos = lseek (fd, (off_t) 0, SEEK_CUR)) != -1 958 beyond the end of the file. */
1010 && (end_pos = lseek (fd, (off_t) 0, SEEK_END)) != -1) 959 bytes_remaining = (diff =
1011 { 960 end_pos - current_pos) < 0 ? 0 : diff;
1012 off_t diff; 961 } else {
1013 /* Be careful here. The current position may actually be 962 detailed_error(0, errno, "%s", filename);
1014 beyond the end of the file. */ 963 return 1;
1015 bytes_remaining = (diff = end_pos - current_pos) < 0 ? 0 : diff; 964 }
1016 } 965
1017 else 966 if (bytes_remaining <= n_bytes) {
1018 { 967 /* From the current position to end of file, there are no
1019 detailed_error (0, errno, "%s", filename); 968 more bytes than have been requested. So reposition the
1020 return 1; 969 file pointer to the incoming current position and print
1021 } 970 everything after that. */
1022 971 lseek(fd, current_pos, SEEK_SET);
1023 if (bytes_remaining <= n_bytes) 972 } else {
1024 { 973 /* There are more bytes remaining than were requested.
1025 /* From the current position to end of file, there are no 974 Back up. */
1026 more bytes than have been requested. So reposition the 975 lseek(fd, -n_bytes, SEEK_END);
1027 file pointer to the incoming current position and print 976 }
1028 everything after that. */ 977 dump_remainder(filename, fd);
1029 lseek (fd, current_pos, SEEK_SET); 978 } else
1030 } 979 return pipe_bytes(filename, fd, n_bytes);
1031 else
1032 {
1033 /* There are more bytes remaining than were requested.
1034 Back up. */
1035 lseek (fd, -n_bytes, SEEK_END);
1036 }
1037 dump_remainder (filename, fd);
1038 } 980 }
1039 else 981 return 0;
1040 return pipe_bytes (filename, fd, n_bytes);
1041 }
1042 return 0;
1043} 982}
1044 983
1045/* Output the last N_LINES lines of file FILENAME open for reading in FD. 984/* Output the last N_LINES lines of file FILENAME open for reading in FD.
1046 Return 0 if successful, 1 if an error occurred. */ 985 Return 0 if successful, 1 if an error occurred. */
1047 986
1048static int 987static int tail_lines(const char *filename, int fd, long int n_lines)
1049tail_lines (const char *filename, int fd, long int n_lines)
1050{ 988{
1051 struct stat stats; 989 struct stat stats;
1052 off_t length; 990 off_t length;
1053 991
1054 if (fstat (fd, &stats)) 992 if (fstat(fd, &stats)) {
1055 { 993 detailed_error(0, errno, "%s", filename);
1056 detailed_error (0, errno, "%s", filename); 994 return 1;
1057 return 1; 995 }
1058 } 996
1059 997 if (from_start) {
1060 if (from_start) 998 if (start_lines(filename, fd, n_lines))
1061 { 999 return 1;
1062 if (start_lines (filename, fd, n_lines)) 1000 dump_remainder(filename, fd);
1063 return 1; 1001 } else {
1064 dump_remainder (filename, fd); 1002 /* Use file_lines only if FD refers to a regular file with
1065 } 1003 its file pointer positioned at beginning of file. */
1066 else 1004 /* FIXME: adding the lseek conjunct is a kludge.
1067 { 1005 Once there's a reasonable test suite, fix the true culprit:
1068 /* Use file_lines only if FD refers to a regular file with 1006 file_lines. file_lines shouldn't presume that the input
1069 its file pointer positioned at beginning of file. */ 1007 file pointer is initially positioned to beginning of file. */
1070 /* FIXME: adding the lseek conjunct is a kludge. 1008 if (S_ISREG(stats.st_mode)
1071 Once there's a reasonable test suite, fix the true culprit: 1009 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
1072 file_lines. file_lines shouldn't presume that the input 1010 length = lseek(fd, (off_t) 0, SEEK_END);
1073 file pointer is initially positioned to beginning of file. */ 1011 if (length != 0 && file_lines(filename, fd, n_lines, length))
1074 if (S_ISREG (stats.st_mode) 1012 return 1;
1075 && lseek (fd, (off_t) 0, SEEK_CUR) == (off_t) 0) 1013 dump_remainder(filename, fd);
1076 { 1014 } else
1077 length = lseek (fd, (off_t) 0, SEEK_END); 1015 return pipe_lines(filename, fd, n_lines);
1078 if (length != 0 && file_lines (filename, fd, n_lines, length))
1079 return 1;
1080 dump_remainder (filename, fd);
1081 } 1016 }
1082 else 1017 return 0;
1083 return pipe_lines (filename, fd, n_lines);
1084 }
1085 return 0;
1086} 1018}
1087 1019
1088/* Display the last N_UNITS units of file FILENAME, open for reading 1020/* Display the last N_UNITS units of file FILENAME, open for reading
1089 in FD. 1021 in FD.
1090 Return 0 if successful, 1 if an error occurred. */ 1022 Return 0 if successful, 1 if an error occurred. */
1091 1023
1092static int 1024static int tail(const char *filename, int fd, off_t n_units)
1093tail (const char *filename, int fd, off_t n_units)
1094{ 1025{
1095 if (count_lines) 1026 if (count_lines)
1096 return tail_lines (filename, fd, (long) n_units); 1027 return tail_lines(filename, fd, (long) n_units);
1097 else 1028 else
1098 return tail_bytes (filename, fd, n_units); 1029 return tail_bytes(filename, fd, n_units);
1099} 1030}
1100 1031
1101/* Display the last N_UNITS units of file FILENAME. 1032/* Display the last N_UNITS units of file FILENAME.
@@ -1103,207 +1034,183 @@ tail (const char *filename, int fd, off_t n_units)
1103 FILENUM is this file's index in the list of files the user gave. 1034 FILENUM is this file's index in the list of files the user gave.
1104 Return 0 if successful, 1 if an error occurred. */ 1035 Return 0 if successful, 1 if an error occurred. */
1105 1036
1106static int 1037static int tail_file(const char *filename, off_t n_units, int filenum)
1107tail_file (const char *filename, off_t n_units, int filenum)
1108{ 1038{
1109 int fd, errors; 1039 int fd, errors;
1110 struct stat stats; 1040 struct stat stats;
1111 1041
1112 if (!strcmp (filename, "-")) 1042 if (!strcmp(filename, "-")) {
1113 { 1043 have_read_stdin = 1;
1114 have_read_stdin = 1; 1044 filename = "standard input";
1115 filename = "standard input"; 1045 if (print_headers)
1116 if (print_headers) 1046 write_header(filename, NULL);
1117 write_header (filename, NULL); 1047 errors = tail(filename, 0, n_units);
1118 errors = tail (filename, 0, n_units); 1048 if (forever_multiple) {
1119 if (forever_multiple) 1049 if (fstat(0, &stats) < 0) {
1120 { 1050 detailed_error(0, errno, "standard input");
1121 if (fstat (0, &stats) < 0) 1051 errors = 1;
1122 { 1052 } else if (!S_ISREG(stats.st_mode)) {
1123 detailed_error (0, errno, "standard input"); 1053 detailed_error(0, 0,
1124 errors = 1; 1054 "standard input: cannot follow end of non-regular file");
1125 } 1055 errors = 1;
1126 else if (!S_ISREG (stats.st_mode)) 1056 }
1127 { 1057 if (errors)
1128 detailed_error (0, 0, 1058 file_descs[filenum] = -1;
1129 "standard input: cannot follow end of non-regular file"); 1059 else {
1130 errors = 1; 1060 file_descs[filenum] = 0;
1131 } 1061 file_sizes[filenum] = stats.st_size;
1132 if (errors) 1062 }
1133 file_descs[filenum] = -1;
1134 else
1135 {
1136 file_descs[filenum] = 0;
1137 file_sizes[filenum] = stats.st_size;
1138 }
1139 }
1140 }
1141 else
1142 {
1143 /* Not standard input. */
1144 fd = open (filename, O_RDONLY);
1145 if (fd == -1)
1146 {
1147 if (forever_multiple)
1148 file_descs[filenum] = -1;
1149 detailed_error (0, errno, "%s", filename);
1150 errors = 1;
1151 }
1152 else
1153 {
1154 if (print_headers)
1155 write_header (filename, NULL);
1156 errors = tail (filename, fd, n_units);
1157 if (forever_multiple)
1158 {
1159 if (fstat (fd, &stats) < 0)
1160 {
1161 detailed_error (0, errno, "%s", filename);
1162 errors = 1;
1163 }
1164 else if (!S_ISREG (stats.st_mode))
1165 {
1166 detailed_error (0, 0, "%s: cannot follow end of non-regular file",
1167 filename);
1168 errors = 1;
1169 }
1170 if (errors)
1171 {
1172 close (fd);
1173 file_descs[filenum] = -1;
1174 }
1175 else
1176 {
1177 file_descs[filenum] = fd;
1178 file_sizes[filenum] = stats.st_size;
1179 } 1063 }
1180 } 1064 } else {
1181 else 1065 /* Not standard input. */
1182 { 1066 fd = open(filename, O_RDONLY);
1183 if (close (fd)) 1067 if (fd == -1) {
1184 { 1068 if (forever_multiple)
1185 detailed_error (0, errno, "%s", filename); 1069 file_descs[filenum] = -1;
1186 errors = 1; 1070 detailed_error(0, errno, "%s", filename);
1071 errors = 1;
1072 } else {
1073 if (print_headers)
1074 write_header(filename, NULL);
1075 errors = tail(filename, fd, n_units);
1076 if (forever_multiple) {
1077 if (fstat(fd, &stats) < 0) {
1078 detailed_error(0, errno, "%s", filename);
1079 errors = 1;
1080 } else if (!S_ISREG(stats.st_mode)) {
1081 detailed_error(0, 0,
1082 "%s: cannot follow end of non-regular file",
1083 filename);
1084 errors = 1;
1085 }
1086 if (errors) {
1087 close(fd);
1088 file_descs[filenum] = -1;
1089 } else {
1090 file_descs[filenum] = fd;
1091 file_sizes[filenum] = stats.st_size;
1092 }
1093 } else {
1094 if (close(fd)) {
1095 detailed_error(0, errno, "%s", filename);
1096 errors = 1;
1097 }
1098 }
1187 } 1099 }
1188 }
1189 } 1100 }
1190 }
1191 1101
1192 return errors; 1102 return errors;
1193} 1103}
1194 1104
1195extern int 1105extern int tail_main(int argc, char **argv)
1196tail_main (int argc, char **argv)
1197{ 1106{
1198 int stopit = 0; 1107 int stopit = 0;
1199 enum header_mode header_mode = multiple_files; 1108 enum header_mode header_mode = multiple_files;
1200 int exit_status = 0; 1109 int exit_status = 0;
1201 /* If from_start, the number of items to skip before printing; otherwise, 1110
1202 the number of items at the end of the file to print. Initially, -1 1111 /* If from_start, the number of items to skip before printing; otherwise,
1203 means the value has not been set. */ 1112 the number of items at the end of the file to print. Initially, -1
1204 off_t n_units = -1; 1113 means the value has not been set. */
1205 int n_files; 1114 off_t n_units = -1;
1206 char **file; 1115 int n_files;
1207 1116 char **file;
1208 program_name = argv[0]; 1117
1209 have_read_stdin = 0; 1118 program_name = argv[0];
1210 count_lines = 1; 1119 have_read_stdin = 0;
1211 forever = forever_multiple = from_start = print_headers = 0; 1120 count_lines = 1;
1212 1121 forever = forever_multiple = from_start = print_headers = 0;
1213 /* Parse any options */ 1122
1214 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv); 1123 /* Parse any options */
1215 while (--argc > 0 && ( **(++argv) == '-' || **argv == '+' )) { 1124 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv);
1216 if (**argv == '+') { 1125 while (--argc > 0 && (**(++argv) == '-' || **argv == '+')) {
1217 from_start = 1; 1126 if (**argv == '+') {
1127 from_start = 1;
1128 }
1129 stopit = 0;
1130 while (stopit == 0 && *(++(*argv))) {
1131 switch (**argv) {
1132 case 'c':
1133 count_lines = 0;
1134
1135 if (--argc < 1) {
1136 usage(tail_usage);
1137 }
1138 n_units = getNum(*(++argv));
1139 stopit = 1;
1140 break;
1141
1142 case 'f':
1143 forever = 1;
1144 break;
1145
1146 case 'n':
1147 count_lines = 1;
1148
1149 if (--argc < 1) {
1150 usage(tail_usage);
1151 }
1152 n_units = atol(*(++argv));
1153 stopit = 1;
1154 break;
1155
1156 case 'q':
1157 header_mode = never;
1158 break;
1159
1160 case 'v':
1161 header_mode = always;
1162 break;
1163
1164 default:
1165 usage(tail_usage);
1166 }
1167 }
1168 }
1169
1170
1171 if (n_units == -1)
1172 n_units = DEFAULT_N_LINES;
1173
1174 /* To start printing with item N_UNITS from the start of the file, skip
1175 N_UNITS - 1 items. `tail +0' is actually meaningless, but for Unix
1176 compatibility it's treated the same as `tail +1'. */
1177 if (from_start) {
1178 if (n_units)
1179 --n_units;
1218 } 1180 }
1219 stopit = 0; 1181
1220 while (stopit == 0 && *(++(*argv))) { 1182 n_files = argc;
1221 switch (**argv) { 1183 file = argv;
1222 case 'c': 1184
1223 count_lines = 0; 1185 if (n_files > 1 && forever) {
1224 1186 forever_multiple = 1;
1225 if (--argc < 1) { 1187 forever = 0;
1226 usage(tail_usage); 1188 file_descs = (int *) xmalloc(n_files * sizeof(int));
1227 } 1189
1228 n_units = getNum(*(++argv)); 1190 file_sizes = (off_t *) xmalloc(n_files * sizeof(off_t));
1229 stopit = 1;
1230 break;
1231
1232 case 'f':
1233 forever = 1;
1234 break;
1235
1236 case 'n':
1237 count_lines = 1;
1238
1239 if (--argc < 1) {
1240 usage(tail_usage);
1241 }
1242 n_units = atol(*(++argv));
1243 stopit = 1;
1244 break;
1245
1246 case 'q':
1247 header_mode = never;
1248 break;
1249
1250 case 'v':
1251 header_mode = always;
1252 break;
1253
1254 default:
1255 usage (tail_usage);
1256 }
1257 } 1191 }
1258 } 1192
1259 1193 if (header_mode == always
1260 1194 || (header_mode == multiple_files && n_files > 1))
1261 if (n_units == -1) 1195 print_headers = 1;
1262 n_units = DEFAULT_N_LINES; 1196
1263 1197 if (n_files == 0) {
1264 /* To start printing with item N_UNITS from the start of the file, skip 1198 exit_status |= tail_file("-", n_units, 0);
1265 N_UNITS - 1 items. `tail +0' is actually meaningless, but for Unix 1199 } else {
1266 compatibility it's treated the same as `tail +1'. */ 1200 int i;
1267 if (from_start) 1201
1268 { 1202 for (i = 0; i < n_files; i++)
1269 if (n_units) 1203 exit_status |= tail_file(file[i], n_units, i);
1270 --n_units; 1204
1271 } 1205 if (forever_multiple)
1272 1206 tail_forever(file, n_files);
1273 n_files = argc; 1207 }
1274 file = argv; 1208
1275 1209 if (have_read_stdin && close(0) < 0)
1276 if (n_files > 1 && forever) 1210 detailed_error(EXIT_FAILURE, errno, "-");
1277 { 1211 if (fclose(stdout) == EOF)
1278 forever_multiple = 1; 1212 detailed_error(EXIT_FAILURE, errno, "write error");
1279 forever = 0; 1213 exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1280 file_descs = (int *) xmalloc (n_files * sizeof (int));
1281 file_sizes = (off_t *) xmalloc (n_files * sizeof (off_t));
1282 }
1283
1284 if (header_mode == always
1285 || (header_mode == multiple_files && n_files > 1))
1286 print_headers = 1;
1287
1288 if (n_files == 0)
1289 {
1290 exit_status |= tail_file ("-", n_units, 0);
1291 }
1292 else
1293 {
1294 int i;
1295 for (i = 0; i < n_files; i++)
1296 exit_status |= tail_file (file[i], n_units, i);
1297
1298 if (forever_multiple)
1299 tail_forever (file, n_files);
1300 }
1301
1302 if (have_read_stdin && close (0) < 0)
1303 detailed_error (EXIT_FAILURE, errno, "-");
1304 if (fclose (stdout) == EOF)
1305 detailed_error (EXIT_FAILURE, errno, "write error");
1306 exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1307} 1214}
1308 1215
1309 1216
diff --git a/coreutils/tee.c b/coreutils/tee.c
index 4c5c691c6..2f746f96d 100644
--- a/coreutils/tee.c
+++ b/coreutils/tee.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini tee implementation for busybox 3 * Mini tee implementation for busybox
3 * 4 *
@@ -25,102 +26,100 @@
25#include <stdio.h> 26#include <stdio.h>
26 27
27static const char tee_usage[] = 28static const char tee_usage[] =
28 "tee [OPTION]... [FILE]...\n\n" 29 "tee [OPTION]... [FILE]...\n\n"
29 "Copy standard input to each FILE, and also to standard output.\n\n" 30 "Copy standard input to each FILE, and also to standard output.\n\n"
30 "Options:\n" 31 "Options:\n" "\t-a\tappend to the given FILEs, do not overwrite\n"
31 "\t-a\tappend to the given FILEs, do not overwrite\n"
32#if 0 32#if 0
33 "\t-i\tignore interrupt signals\n" 33 "\t-i\tignore interrupt signals\n"
34#endif 34#endif
35 ; 35;
36 36
37 37
38/* FileList _______________________________________________________________ */ 38/* FileList _______________________________________________________________ */
39 39
40#define FL_MAX 1024 40#define FL_MAX 1024
41static FILE *FileList[FL_MAX]; 41static FILE *FileList[FL_MAX];
42static int FL_end; 42static int FL_end;
43
44typedef void (FL_Function) (FILE * file, char c);
43 45
44typedef void (FL_Function)(FILE *file, char c);
45
46 46
47/* apply a function to everything in FileList */ 47/* apply a function to everything in FileList */
48static void 48static void FL_apply(FL_Function * f, char c)
49FL_apply(FL_Function *f, char c)
50{ 49{
51 int i; 50 int i;
52 for (i = 0; i <= FL_end; i++) { 51
53 f(FileList[i], c); 52 for (i = 0; i <= FL_end; i++) {
54 } 53 f(FileList[i], c);
54 }
55} 55}
56 56
57/* FL_Function for writing to files*/ 57/* FL_Function for writing to files*/
58static void 58static void tee_fwrite(FILE * file, char c)
59tee_fwrite(FILE *file, char c)
60{ 59{
61 fputc(c, file); 60 fputc(c, file);
62} 61}
63 62
64/* FL_Function for closing files */ 63/* FL_Function for closing files */
65static void 64static void tee_fclose(FILE * file, char c)
66tee_fclose(FILE *file, char c)
67{ 65{
68 fclose(file); 66 fclose(file);
69} 67}
70 68
71/* ________________________________________________________________________ */ 69/* ________________________________________________________________________ */
72 70
73/* BusyBoxed tee(1) */ 71/* BusyBoxed tee(1) */
74int 72int tee_main(int argc, char **argv)
75tee_main(int argc, char **argv)
76{ 73{
77 int i; 74 int i;
78 char c; 75 char c;
79 char opt; 76 char opt;
80 char opt_fopen[2] = "w"; 77 char opt_fopen[2] = "w";
81 FILE *file; 78 FILE *file;
82 79
83 /* parse argv[] */ 80 /* parse argv[] */
84 for (i = 1; i < argc; i++) { 81 for (i = 1; i < argc; i++) {
85 if (argv[i][0] == '-') { 82 if (argv[i][0] == '-') {
86 opt = argv[i][1]; 83 opt = argv[i][1];
87 switch (opt) { 84 switch (opt) {
88 case 'a': 85 case 'a':
89 opt_fopen[0] = 'a'; 86 opt_fopen[0] = 'a';
90 break; 87 break;
91#if 0 88#if 0
92 case 'i': 89 case 'i':
93 fprintf(stderr, "ignore interrupt not implemented\n"); 90 fprintf(stderr, "ignore interrupt not implemented\n");
94 break; 91 break;
95#endif 92#endif
96 default: 93 default:
97 usage(tee_usage); 94 usage(tee_usage);
98 } 95 }
99 } else { 96 } else {
100 break; 97 break;
98 }
101 } 99 }
102 } 100
103 101 /* init FILE pointers */
104 /* init FILE pointers */ 102 FL_end = 0;
105 FL_end = 0; 103 FileList[0] = stdout;
106 FileList[0] = stdout; 104 for (; i < argc; i++) {
107 for ( ; i < argc; i++) { 105 /* add a file to FileList */
108 /* add a file to FileList */ 106 file = fopen(argv[i], opt_fopen);
109 file = fopen(argv[i], opt_fopen); 107 if (!file) {
110 if (!file) { continue; } 108 continue;
111 if (FL_end < FL_MAX) { 109 }
112 FileList[++FL_end] = file; 110 if (FL_end < FL_MAX) {
111 FileList[++FL_end] = file;
112 }
113 } 113 }
114 }
115 114
116 /* read and redirect */ 115 /* read and redirect */
117 while ((c = (char) getchar()) && (!feof(stdin))) { 116 while ((c = (char) getchar()) && (!feof(stdin))) {
118 FL_apply(tee_fwrite, c); 117 FL_apply(tee_fwrite, c);
119 } 118 }
120 119
121 /* clean up */ 120 /* clean up */
122 FL_apply(tee_fclose, 0); 121 FL_apply(tee_fclose, 0);
123 exit(0); 122 exit(0);
124} 123}
125 124
126/* $Id: tee.c,v 1.5 2000/02/07 05:29:42 erik Exp $ */ 125/* $Id: tee.c,v 1.6 2000/02/08 19:58:47 erik Exp $ */
diff --git a/coreutils/touch.c b/coreutils/touch.c
index d2d3e9484..a0f21acdd 100644
--- a/coreutils/touch.c
+++ b/coreutils/touch.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini touch implementation for busybox 3 * Mini touch implementation for busybox
3 * 4 *
@@ -31,56 +32,50 @@
31 32
32 33
33static const char touch_usage[] = "touch [-c] file [file ...]\n\n" 34static const char touch_usage[] = "touch [-c] file [file ...]\n\n"
34"Update the last-modified date on the given file[s].\n";
35 35
36 "Update the last-modified date on the given file[s].\n";
36 37
37 38
38extern int
39touch_main(int argc, char **argv)
40{
41 int fd;
42 int create=TRUE;
43 39
44 if (argc < 2) { 40extern int touch_main(int argc, char **argv)
45 usage( touch_usage); 41{
46 } 42 int fd;
47 argc--; 43 int create = TRUE;
48 argv++;
49 44
50 /* Parse options */ 45 if (argc < 2) {
51 while (**argv == '-') { 46 usage(touch_usage);
52 while (*++(*argv)) switch (**argv) {
53 case 'c':
54 create = FALSE;
55 break;
56 default:
57 usage( touch_usage);
58 exit( FALSE);
59 } 47 }
60 argc--; 48 argc--;
61 argv++; 49 argv++;
62 }
63 50
64 fd = open (*argv, (create==FALSE)? O_RDWR : O_RDWR | O_CREAT, 0644); 51 /* Parse options */
65 if (fd < 0 ) { 52 while (**argv == '-') {
66 if (create==FALSE && errno == ENOENT) 53 while (*++(*argv))
67 exit( TRUE); 54 switch (**argv) {
68 else { 55 case 'c':
69 perror("touch"); 56 create = FALSE;
70 exit( FALSE); 57 break;
58 default:
59 usage(touch_usage);
60 exit(FALSE);
61 }
62 argc--;
63 argv++;
71 } 64 }
72 }
73 close( fd);
74 if (utime (*argv, NULL)) {
75 perror("touch");
76 exit( FALSE);
77 }
78 else
79 exit( TRUE);
80}
81
82
83
84
85
86 65
66 fd = open(*argv, (create == FALSE) ? O_RDWR : O_RDWR | O_CREAT, 0644);
67 if (fd < 0) {
68 if (create == FALSE && errno == ENOENT)
69 exit(TRUE);
70 else {
71 perror("touch");
72 exit(FALSE);
73 }
74 }
75 close(fd);
76 if (utime(*argv, NULL)) {
77 perror("touch");
78 exit(FALSE);
79 } else
80 exit(TRUE);
81}
diff --git a/coreutils/tty.c b/coreutils/tty.c
index 83abaffb5..8ac1c1fcd 100644
--- a/coreutils/tty.c
+++ b/coreutils/tty.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini tty implementation for busybox 3 * Mini tty implementation for busybox
3 * 4 *
@@ -24,19 +25,23 @@
24#include <sys/types.h> 25#include <sys/types.h>
25 26
26static const char tty_usage[] = "tty\n\n" 27static const char tty_usage[] = "tty\n\n"
27"Print the file name of the terminal connected to standard input.\n" 28 "Print the file name of the terminal connected to standard input.\n"
28"\t-s\tprint nothing, only return an exit status\n";
29 29
30extern int tty_main(int argc, char **argv) { 30 "\t-s\tprint nothing, only return an exit status\n";
31
32extern int tty_main(int argc, char **argv)
33{
31 char *tty; 34 char *tty;
32 35
33 if (argc > 1) { 36 if (argc > 1) {
34 if (argv[1][0] != '-' || argv[1][1] != 's') usage (tty_usage); 37 if (argv[1][0] != '-' || argv[1][1] != 's')
35 } 38 usage(tty_usage);
36 else { 39 } else {
37 tty = ttyname (0); 40 tty = ttyname(0);
38 if (tty) puts (tty); 41 if (tty)
39 else puts ("not a tty"); 42 puts(tty);
43 else
44 puts("not a tty");
40 } 45 }
41 exit (isatty (0) ? TRUE : FALSE); 46 exit(isatty(0) ? TRUE : FALSE);
42} 47}
diff --git a/coreutils/uname.c b/coreutils/uname.c
index 9083edb04..9a1cb808a 100644
--- a/coreutils/uname.c
+++ b/coreutils/uname.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* uname -- print system information 2/* uname -- print system information
2 Copyright (C) 1989-1999 Free Software Foundation, Inc. 3 Copyright (C) 1989-1999 Free Software Foundation, Inc.
3 4
@@ -41,16 +42,17 @@
41 42
42 43
43static const char uname_usage[] = 44static const char uname_usage[] =
44 "uname [OPTION]...\n\n" 45 "uname [OPTION]...\n\n"
45 "Print certain system information. With no OPTION, same as -s.\n\n" 46 "Print certain system information. With no OPTION, same as -s.\n\n"
46 "Options:\n" 47 "Options:\n"
47 "\t-a\tprint all information\n" 48 "\t-a\tprint all information\n"
48 "\t-m\tthe machine (hardware) type\n" 49 "\t-m\tthe machine (hardware) type\n"
49 "\t-n\tprint the machine's network node hostname\n" 50 "\t-n\tprint the machine's network node hostname\n"
50 "\t-r\tprint the operating system release\n" 51 "\t-r\tprint the operating system release\n"
51 "\t-s\tprint the operating system name\n" 52 "\t-s\tprint the operating system name\n"
52 "\t-p\tprint the host processor type\n" 53
53 "\t-v\tprint the operating system version\n"; 54 "\t-p\tprint the host processor type\n"
55 "\t-v\tprint the operating system version\n";
54 56
55 57
56static void print_element(unsigned int mask, char *element); 58static void print_element(unsigned int mask, char *element);
@@ -80,77 +82,78 @@ static unsigned char toprint;
80 82
81int uname_main(int argc, char **argv) 83int uname_main(int argc, char **argv)
82{ 84{
83 struct utsname name; 85 struct utsname name;
84 char processor[256]; 86 char processor[256];
87
85#if defined(__sparc__) && defined(__linux__) 88#if defined(__sparc__) && defined(__linux__)
86 char *fake_sparc = getenv("FAKE_SPARC"); 89 char *fake_sparc = getenv("FAKE_SPARC");
87#endif 90#endif
88 91
89 toprint = 0; 92 toprint = 0;
90 93
91 /* Parse any options */ 94 /* Parse any options */
92 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv); 95 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv);
93 while (--argc > 0 && **(++argv) == '-') { 96 while (--argc > 0 && **(++argv) == '-') {
94 while (*(++(*argv))) { 97 while (*(++(*argv))) {
95 switch (**argv) { 98 switch (**argv) {
96 case 's': 99 case 's':
97 toprint |= PRINT_SYSNAME; 100 toprint |= PRINT_SYSNAME;
98 break; 101 break;
99 case 'n': 102 case 'n':
100 toprint |= PRINT_NODENAME; 103 toprint |= PRINT_NODENAME;
101 break; 104 break;
102 case 'r': 105 case 'r':
103 toprint |= PRINT_RELEASE; 106 toprint |= PRINT_RELEASE;
104 break; 107 break;
105 case 'v': 108 case 'v':
106 toprint |= PRINT_VERSION; 109 toprint |= PRINT_VERSION;
107 break; 110 break;
108 case 'm': 111 case 'm':
109 toprint |= PRINT_MACHINE; 112 toprint |= PRINT_MACHINE;
110 break; 113 break;
111 case 'p': 114 case 'p':
112 toprint |= PRINT_PROCESSOR; 115 toprint |= PRINT_PROCESSOR;
113 break; 116 break;
114 case 'a': 117 case 'a':
115 toprint = (PRINT_SYSNAME | PRINT_NODENAME | PRINT_RELEASE | 118 toprint = (PRINT_SYSNAME | PRINT_NODENAME | PRINT_RELEASE |
116 PRINT_PROCESSOR | PRINT_VERSION | 119 PRINT_PROCESSOR | PRINT_VERSION |
117 PRINT_MACHINE); 120 PRINT_MACHINE);
118 break; 121 break;
119 default: 122 default:
120 usage(uname_usage); 123 usage(uname_usage);
121 } 124 }
125 }
122 } 126 }
123 }
124 127
125 if (toprint == 0) 128 if (toprint == 0)
126 toprint = PRINT_SYSNAME; 129 toprint = PRINT_SYSNAME;
127 130
128 if (uname(&name) == -1) 131 if (uname(&name) == -1)
129 perror("cannot get system name"); 132 perror("cannot get system name");
130 133
131#if defined (HAVE_SYSINFO) && defined (SI_ARCHITECTURE) 134#if defined (HAVE_SYSINFO) && defined (SI_ARCHITECTURE)
132 if (sysinfo(SI_ARCHITECTURE, processor, sizeof(processor)) == -1) 135 if (sysinfo(SI_ARCHITECTURE, processor, sizeof(processor)) == -1)
133 perror("cannot get processor type"); 136 perror("cannot get processor type");
134} 137}
135 138
136#else 139#else
137 strcpy(processor, "unknown"); 140 strcpy(processor, "unknown");
138#endif 141#endif
139 142
140#if defined(__sparc__) && defined(__linux__) 143#if defined(__sparc__) && defined(__linux__)
141 if (fake_sparc != NULL 144 if (fake_sparc != NULL
142 && (fake_sparc[0] == 'y' 145 && (fake_sparc[0] == 'y'
143 || fake_sparc[0] == 'Y')) strcpy(name.machine, "sparc"); 146 || fake_sparc[0] == 'Y')) strcpy(name.machine, "sparc");
144#endif 147#endif
145 148
146 print_element(PRINT_SYSNAME, name.sysname); 149 print_element(PRINT_SYSNAME, name.sysname);
147 print_element(PRINT_NODENAME, name.nodename); 150 print_element(PRINT_NODENAME, name.nodename);
148 print_element(PRINT_RELEASE, name.release); 151 print_element(PRINT_RELEASE, name.release);
149 print_element(PRINT_VERSION, name.version); 152 print_element(PRINT_VERSION, name.version);
150 print_element(PRINT_MACHINE, name.machine); 153 print_element(PRINT_MACHINE, name.machine);
151 print_element(PRINT_PROCESSOR, processor); 154 print_element(PRINT_PROCESSOR, processor);
152 155
153 exit(TRUE); 156 exit(TRUE);
154} 157}
155 158
156/* If the name element set in MASK is selected for printing in `toprint', 159/* If the name element set in MASK is selected for printing in `toprint',
@@ -159,8 +162,8 @@ int uname_main(int argc, char **argv)
159 162
160static void print_element(unsigned int mask, char *element) 163static void print_element(unsigned int mask, char *element)
161{ 164{
162 if (toprint & mask) { 165 if (toprint & mask) {
163 toprint &= ~mask; 166 toprint &= ~mask;
164 printf("%s%c", element, toprint ? ' ' : '\n'); 167 printf("%s%c", element, toprint ? ' ' : '\n');
165 } 168 }
166} 169}
diff --git a/coreutils/uniq.c b/coreutils/uniq.c
index 965d290c2..1e41eaacd 100644
--- a/coreutils/uniq.c
+++ b/coreutils/uniq.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini uniq implementation for busybox 3 * Mini uniq implementation for busybox
3 * 4 *
@@ -27,119 +28,116 @@
27#include <errno.h> 28#include <errno.h>
28 29
29static const char uniq_usage[] = 30static const char uniq_usage[] =
30"uniq [OPTION]... [INPUT [OUTPUT]]\n" 31 "uniq [OPTION]... [INPUT [OUTPUT]]\n"
31"Discard all but one of successive identical lines from INPUT (or\n" 32 "Discard all but one of successive identical lines from INPUT (or\n"
32"standard input), writing to OUTPUT (or standard output).\n" 33 "standard input), writing to OUTPUT (or standard output).\n"
33"\n" 34 "\n"
34"\t-h\tdisplay this help and exit\n" 35 "\t-h\tdisplay this help and exit\n"
35"\n" 36
36"A field is a run of whitespace, then non-whitespace characters.\n" 37 "\n"
37"Fields are skipped before chars.\n" 38 "A field is a run of whitespace, then non-whitespace characters.\n"
38; 39 "Fields are skipped before chars.\n";
39 40
40/* max chars in line */ 41/* max chars in line */
41#define UNIQ_MAX 4096 42#define UNIQ_MAX 4096
42 43
43typedef void (Print)(FILE *, const char *); 44typedef void (Print) (FILE *, const char *);
44 45
45typedef int (Decide)(const char *, const char *); 46typedef int (Decide) (const char *, const char *);
46 47
47/* container for two lines to be compared */ 48/* container for two lines to be compared */
48typedef struct { 49typedef struct {
49 char *a; 50 char *a;
50 char *b; 51 char *b;
51 int recurrence; 52 int recurrence;
52 FILE *in; 53 FILE *in;
53 FILE *out; 54 FILE *out;
54 void *func; 55 void *func;
55} Subject; 56} Subject;
56 57
57/* set up all the variables of a uniq operation */ 58/* set up all the variables of a uniq operation */
58static Subject * 59static Subject *subject_init(Subject * self, FILE * in, FILE * out,
59subject_init(Subject *self, FILE *in, FILE *out, void *func) 60 void *func)
60{ 61{
61 self->a = NULL; 62 self->a = NULL;
62 self->b = NULL; 63 self->b = NULL;
63 self->in = in; 64 self->in = in;
64 self->out = out; 65 self->out = out;
65 self->func = func; 66 self->func = func;
66 self->recurrence = 0; 67 self->recurrence = 0;
67 return self; 68 return self;
68} 69}
69 70
70/* point a and b to the appropriate lines; 71/* point a and b to the appropriate lines;
71 * count the recurrences (if any) of a string; 72 * count the recurrences (if any) of a string;
72 */ 73 */
73static Subject * 74static Subject *subject_next(Subject * self)
74subject_next(Subject *self)
75{ 75{
76 /* tmp line holders */ 76 /* tmp line holders */
77 static char line[2][UNIQ_MAX]; 77 static char line[2][UNIQ_MAX];
78 static int alternator = 0; 78 static int alternator = 0;
79 79
80 if (fgets(line[alternator], UNIQ_MAX, self->in)) { 80 if (fgets(line[alternator], UNIQ_MAX, self->in)) {
81 self->a = self->b; 81 self->a = self->b;
82 self->b = line[alternator]; 82 self->b = line[alternator];
83 alternator ^= 1; 83 alternator ^= 1;
84 return self; 84 return self;
85 } 85 }
86 86
87 return NULL; 87 return NULL;
88} 88}
89 89
90static Subject * 90static Subject *subject_last(Subject * self)
91subject_last(Subject *self)
92{ 91{
93 self->a = self->b; 92 self->a = self->b;
94 self->b = NULL; 93 self->b = NULL;
95 return self; 94 return self;
96} 95}
97 96
98static Subject * 97static Subject *subject_study(Subject * self)
99subject_study(Subject *self)
100{ 98{
101 if (self->a == NULL) { 99 if (self->a == NULL) {
102 return self; 100 return self;
103 } 101 }
104 if (self->b == NULL) { 102 if (self->b == NULL) {
105 fprintf(self->out, "%s", self->a); 103 fprintf(self->out, "%s", self->a);
104 return self;
105 }
106 if (strcmp(self->a, self->b) == 0) {
107 self->recurrence++;
108 } else {
109 fprintf(self->out, "%s", self->a);
110 self->recurrence = 0;
111 }
106 return self; 112 return self;
107 }
108 if (strcmp(self->a, self->b) == 0) {
109 self->recurrence++;
110 } else {
111 fprintf(self->out, "%s", self->a);
112 self->recurrence = 0;
113 }
114 return self;
115} 113}
116 114
117static int 115static int
118set_file_pointers(int schema, FILE **in, FILE **out, char **argv) 116set_file_pointers(int schema, FILE ** in, FILE ** out, char **argv)
119{ 117{
120 switch (schema) { 118 switch (schema) {
121 case 0: 119 case 0:
122 *in = stdin; 120 *in = stdin;
123 *out = stdout; 121 *out = stdout;
124 break; 122 break;
125 case 1: 123 case 1:
126 *in = fopen(argv[0], "r"); 124 *in = fopen(argv[0], "r");
127 *out = stdout; 125 *out = stdout;
128 break; 126 break;
129 case 2: 127 case 2:
130 *in = fopen(argv[0], "r"); 128 *in = fopen(argv[0], "r");
131 *out = fopen(argv[1], "w"); 129 *out = fopen(argv[1], "w");
132 break; 130 break;
133 } 131 }
134 if (*in == NULL) { 132 if (*in == NULL) {
135 fprintf(stderr, "uniq: %s: %s\n", argv[0], strerror(errno)); 133 fprintf(stderr, "uniq: %s: %s\n", argv[0], strerror(errno));
136 return errno; 134 return errno;
137 } 135 }
138 if (*out == NULL) { 136 if (*out == NULL) {
139 fprintf(stderr, "uniq: %s: %s\n", argv[1], strerror(errno)); 137 fprintf(stderr, "uniq: %s: %s\n", argv[1], strerror(errno));
140 return errno; 138 return errno;
141 } 139 }
142 return 0; 140 return 0;
143} 141}
144 142
145 143
@@ -152,45 +150,44 @@ set_file_pointers(int schema, FILE **in, FILE **out, char **argv)
152/* it seems like GNU/uniq only takes one or two files as an option */ 150/* it seems like GNU/uniq only takes one or two files as an option */
153 151
154/* ________________________________________________________________________ */ 152/* ________________________________________________________________________ */
155int 153int uniq_main(int argc, char **argv)
156uniq_main(int argc, char **argv)
157{ 154{
158 int i; 155 int i;
159 char opt; 156 char opt;
160 FILE *in, *out; 157 FILE *in, *out;
161 Subject s; 158 Subject s;
162 159
163 /* parse argv[] */ 160 /* parse argv[] */
164 for (i = 1; i < argc; i++) { 161 for (i = 1; i < argc; i++) {
165 if (argv[i][0] == '-') { 162 if (argv[i][0] == '-') {
166 opt = argv[i][1]; 163 opt = argv[i][1];
167 switch (opt) { 164 switch (opt) {
168 case '-': 165 case '-':
169 case 'h': 166 case 'h':
170 usage(uniq_usage); 167 usage(uniq_usage);
171 default: 168 default:
172 usage(uniq_usage); 169 usage(uniq_usage);
173 } 170 }
174 } else { 171 } else {
175 break; 172 break;
173 }
176 } 174 }
177 }
178 175
179 /* 0 src: stdin; dst: stdout */ 176 /* 0 src: stdin; dst: stdout */
180 /* 1 src: file; dst: stdout */ 177 /* 1 src: file; dst: stdout */
181 /* 2 src: file; dst: file */ 178 /* 2 src: file; dst: file */
182 if (set_file_pointers((argc - 1), &in, &out, &argv[i])) { 179 if (set_file_pointers((argc - 1), &in, &out, &argv[i])) {
183 exit(1); 180 exit(1);
184 } 181 }
185 182
186 subject_init(&s, in, out, NULL); 183 subject_init(&s, in, out, NULL);
187 while (subject_next(&s)) { 184 while (subject_next(&s)) {
185 subject_study(&s);
186 }
187 subject_last(&s);
188 subject_study(&s); 188 subject_study(&s);
189 }
190 subject_last(&s);
191 subject_study(&s);
192 189
193 exit(0); 190 exit(0);
194} 191}
195 192
196/* $Id: uniq.c,v 1.6 2000/02/07 05:29:42 erik Exp $ */ 193/* $Id: uniq.c,v 1.7 2000/02/08 19:58:47 erik Exp $ */
diff --git a/coreutils/wc.c b/coreutils/wc.c
index e69f0d899..8004e6294 100644
--- a/coreutils/wc.c
+++ b/coreutils/wc.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini wc implementation for busybox 3 * Mini wc implementation for busybox
3 * 4 *
@@ -23,78 +24,82 @@
23#include <stdio.h> 24#include <stdio.h>
24 25
25static const char wc_usage[] = "wc [OPTION]... [FILE]...\n\n" 26static const char wc_usage[] = "wc [OPTION]... [FILE]...\n\n"
26"Print line, word, and byte counts for each FILE, and a total line if\n" 27 "Print line, word, and byte counts for each FILE, and a total line if\n"
27"more than one FILE is specified. With no FILE, read standard input.\n" 28 "more than one FILE is specified. With no FILE, read standard input.\n"
28"\t-c\tprint the byte counts\n" 29 "\t-c\tprint the byte counts\n"
29"\t-l\tprint the newline counts\n" 30 "\t-l\tprint the newline counts\n"
30"\t-L\tprint the length of the longest line\n" 31
31"\t-w\tprint the word counts\n"; 32 "\t-L\tprint the length of the longest line\n"
33 "\t-w\tprint the word counts\n";
32 34
33static int total_lines, total_words, total_chars, max_length; 35static int total_lines, total_words, total_chars, max_length;
34static int print_lines, print_words, print_chars, print_length; 36static int print_lines, print_words, print_chars, print_length;
35 37
36void print_counts (int lines, int words, int chars, int length, 38void print_counts(int lines, int words, int chars, int length,
37 const char *name) { 39 const char *name)
40{
38 char const *space = ""; 41 char const *space = "";
42
39 if (print_lines) { 43 if (print_lines) {
40 printf ("%7d", lines); 44 printf("%7d", lines);
41 space = " "; 45 space = " ";
42 } 46 }
43 if (print_words) { 47 if (print_words) {
44 printf ("%s%7d", space, words); 48 printf("%s%7d", space, words);
45 space = " "; 49 space = " ";
46 } 50 }
47 if (print_chars) { 51 if (print_chars) {
48 printf ("%s%7d", space, chars); 52 printf("%s%7d", space, chars);
49 space = " "; 53 space = " ";
50 } 54 }
51 if (print_length) 55 if (print_length)
52 printf ("%s%7d", space, length); 56 printf("%s%7d", space, length);
53 if (*name) 57 if (*name)
54 printf (" %s", name); 58 printf(" %s", name);
55 putchar ('\n'); 59 putchar('\n');
56} 60}
57 61
58static void wc_file(FILE *file, const char *name) 62static void wc_file(FILE * file, const char *name)
59{ 63{
60 int lines, words, chars, length; 64 int lines, words, chars, length;
61 int in_word = 0, linepos = 0; 65 int in_word = 0, linepos = 0;
62 int c; 66 int c;
67
63 lines = words = chars = length = 0; 68 lines = words = chars = length = 0;
64 while ((c = getc(file)) != EOF) { 69 while ((c = getc(file)) != EOF) {
65 chars++; 70 chars++;
66 switch (c) { 71 switch (c) {
67 case '\n': 72 case '\n':
68 lines++; 73 lines++;
69 case '\r': 74 case '\r':
70 case '\f': 75 case '\f':
71 if (linepos > length) 76 if (linepos > length)
72 length = linepos; 77 length = linepos;
73 linepos = 0; 78 linepos = 0;
74 goto word_separator; 79 goto word_separator;
75 case '\t': 80 case '\t':
76 linepos += 8 - (linepos % 8); 81 linepos += 8 - (linepos % 8);
77 goto word_separator; 82 goto word_separator;
78 case ' ': 83 case ' ':
79 linepos++; 84 linepos++;
80 case '\v': 85 case '\v':
81 word_separator: 86 word_separator:
82 if (in_word) { 87 if (in_word) {
83 in_word = 0; 88 in_word = 0;
84 words++; 89 words++;
85 } 90 }
86 break; 91 break;
87 default: 92 default:
88 linepos++; 93 linepos++;
89 in_word = 1; 94 in_word = 1;
90 break; 95 break;
91 } 96 }
92 } 97 }
93 if (linepos > length) 98 if (linepos > length)
94 length = linepos; 99 length = linepos;
95 if (in_word) 100 if (in_word)
96 words++; 101 words++;
97 print_counts (lines, words, chars, length, name); 102 print_counts(lines, words, chars, length, name);
98 total_lines += lines; 103 total_lines += lines;
99 total_words += words; 104 total_words += words;
100 total_chars += chars; 105 total_chars += chars;
@@ -104,28 +109,30 @@ static void wc_file(FILE *file, const char *name)
104 fflush(stdout); 109 fflush(stdout);
105} 110}
106 111
107int wc_main(int argc, char **argv) { 112int wc_main(int argc, char **argv)
113{
108 FILE *file; 114 FILE *file;
115
109 total_lines = total_words = total_chars = max_length = 0; 116 total_lines = total_words = total_chars = max_length = 0;
110 print_lines = print_words = print_chars = print_length = 0; 117 print_lines = print_words = print_chars = print_length = 0;
111 118
112 while (--argc && **(++argv) == '-') { 119 while (--argc && **(++argv) == '-') {
113 while (*++(*argv)) 120 while (*++(*argv))
114 switch (**argv) { 121 switch (**argv) {
115 case 'c': 122 case 'c':
116 print_chars = 1; 123 print_chars = 1;
117 break; 124 break;
118 case 'l': 125 case 'l':
119 print_lines = 1; 126 print_lines = 1;
120 break; 127 break;
121 case 'L': 128 case 'L':
122 print_length = 1; 129 print_length = 1;
123 break; 130 break;
124 case 'w': 131 case 'w':
125 print_words = 1; 132 print_words = 1;
126 break; 133 break;
127 default: 134 default:
128 usage (wc_usage); 135 usage(wc_usage);
129 } 136 }
130 } 137 }
131 138
@@ -135,16 +142,14 @@ int wc_main(int argc, char **argv) {
135 if (argc == 0) { 142 if (argc == 0) {
136 wc_file(stdin, ""); 143 wc_file(stdin, "");
137 exit(TRUE); 144 exit(TRUE);
138 } 145 } else if (argc == 1) {
139 else if (argc == 1) {
140 file = fopen(*argv, "r"); 146 file = fopen(*argv, "r");
141 if (file == NULL) { 147 if (file == NULL) {
142 perror(*argv); 148 perror(*argv);
143 exit(FALSE); 149 exit(FALSE);
144 } 150 }
145 wc_file(file, *argv); 151 wc_file(file, *argv);
146 } 152 } else {
147 else {
148 while (argc-- > 0 && *argv != '\0' && strlen(*argv)) { 153 while (argc-- > 0 && *argv != '\0' && strlen(*argv)) {
149 file = fopen(*argv, "r"); 154 file = fopen(*argv, "r");
150 if (file == NULL) { 155 if (file == NULL) {
@@ -154,8 +159,8 @@ int wc_main(int argc, char **argv) {
154 wc_file(file, *argv); 159 wc_file(file, *argv);
155 argv++; 160 argv++;
156 } 161 }
157 print_counts (total_lines, total_words, total_chars, 162 print_counts(total_lines, total_words, total_chars,
158 max_length, "total"); 163 max_length, "total");
159 } 164 }
160 exit(TRUE); 165 exit(TRUE);
161} 166}
diff --git a/coreutils/whoami.c b/coreutils/whoami.c
index 7fd5d01b2..3677c2fbc 100644
--- a/coreutils/whoami.c
+++ b/coreutils/whoami.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini whoami implementation for busybox 3 * Mini whoami implementation for busybox
3 * 4 *
@@ -24,21 +25,25 @@
24#include <pwd.h> 25#include <pwd.h>
25 26
26static const char whoami_usage[] = "whoami\n\n" 27static const char whoami_usage[] = "whoami\n\n"
27"Print the user name associated with the current effective user id.\n" 28 "Print the user name associated with the current effective user id.\n"
28"Same as id -un.\n";
29 29
30extern int whoami_main(int argc, char **argv) { 30 "Same as id -un.\n";
31
32extern int whoami_main(int argc, char **argv)
33{
31 struct passwd *pw; 34 struct passwd *pw;
32 uid_t uid; 35 uid_t uid;
33 36
34 if (argc > 1) usage (whoami_usage); 37 if (argc > 1)
38 usage(whoami_usage);
35 39
36 uid = geteuid (); 40 uid = geteuid();
37 pw = getpwuid (uid); 41 pw = getpwuid(uid);
38 if (pw) { 42 if (pw) {
39 puts (pw->pw_name); 43 puts(pw->pw_name);
40 exit (TRUE); 44 exit(TRUE);
41 } 45 }
42 fprintf (stderr, "%s: cannot find username for UID %u\n", argv[0], (unsigned) uid); 46 fprintf(stderr, "%s: cannot find username for UID %u\n", argv[0],
43 exit (FALSE); 47 (unsigned) uid);
48 exit(FALSE);
44} 49}
diff --git a/coreutils/yes.c b/coreutils/yes.c
index 96d6257d0..ac67845ac 100644
--- a/coreutils/yes.c
+++ b/coreutils/yes.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini yes implementation for busybox 3 * Mini yes implementation for busybox
3 * 4 *
@@ -22,19 +23,22 @@
22#include "internal.h" 23#include "internal.h"
23#include <stdio.h> 24#include <stdio.h>
24 25
25extern int yes_main(int argc, char **argv) { 26extern int yes_main(int argc, char **argv)
27{
26 int i; 28 int i;
29
27 if (argc == 1) 30 if (argc == 1)
28 while (1) 31 while (1)
29 if (puts ("y") == EOF) { 32 if (puts("y") == EOF) {
30 perror ("yes"); 33 perror("yes");
31 exit(FALSE); 34 exit(FALSE);
32 } 35 }
33 36
34 while (1) 37 while (1)
35 for (i = 1; i < argc; i++) 38 for (i = 1; i < argc; i++)
36 if (fputs (argv[i], stdout) == EOF || putchar (i == argc - 1 ? '\n' : ' ') == EOF) { 39 if (fputs(argv[i], stdout) == EOF
37 perror ("yes"); 40 || putchar(i == argc - 1 ? '\n' : ' ') == EOF) {
41 perror("yes");
38 exit(FALSE); 42 exit(FALSE);
39 } 43 }
40 exit(TRUE); 44 exit(TRUE);