summaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/cat.c54
-rw-r--r--coreutils/chgrp.c89
-rw-r--r--coreutils/chmod.c163
-rw-r--r--coreutils/chown.c63
-rw-r--r--coreutils/chroot.c32
-rw-r--r--coreutils/cp.c89
-rw-r--r--coreutils/date.c305
-rw-r--r--coreutils/dd.c307
-rw-r--r--coreutils/df.c103
-rw-r--r--coreutils/length.c13
-rw-r--r--coreutils/ln.c52
-rw-r--r--coreutils/ls.c542
-rw-r--r--coreutils/mkdir.c58
-rw-r--r--coreutils/mknod.c52
-rw-r--r--coreutils/mv.c38
-rw-r--r--coreutils/printf.c531
-rw-r--r--coreutils/pwd.c18
-rw-r--r--coreutils/rm.c30
-rw-r--r--coreutils/rmdir.c17
-rw-r--r--coreutils/sleep.c15
-rw-r--r--coreutils/sync.c11
-rw-r--r--coreutils/touch.c20
22 files changed, 2602 insertions, 0 deletions
diff --git a/coreutils/cat.c b/coreutils/cat.c
new file mode 100644
index 000000000..12faf55ab
--- /dev/null
+++ b/coreutils/cat.c
@@ -0,0 +1,54 @@
1/*
2 * Mini Cat implementation for busybox
3 *
4 * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include "internal.h"
23#include <stdio.h>
24
25const char cat_usage[] = "[file ...]";
26
27extern int cat_more_main(int argc, char **argv)
28{
29 int c;
30 FILE *file = stdin;
31
32 if (argc < 2) {
33 fprintf(stderr, "Usage: %s %s", *argv, cat_usage);
34 return 1;
35 }
36 argc--;
37 argv++;
38
39 while (argc-- > 0) {
40 file = fopen(*argv, "r");
41 if (file == NULL) {
42 name_and_error(*argv);
43 return 1;
44 }
45 while ((c = getc(file)) != EOF)
46 putc(c, stdout);
47 fclose(file);
48 fflush(stdout);
49
50 argc--;
51 argv++;
52 }
53 return 0;
54}
diff --git a/coreutils/chgrp.c b/coreutils/chgrp.c
new file mode 100644
index 000000000..038c665dd
--- /dev/null
+++ b/coreutils/chgrp.c
@@ -0,0 +1,89 @@
1/*
2 * Mini chgrp implementation for busybox
3 *
4 * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include "internal.h"
23#include <grp.h>
24#include <stdio.h>
25
26const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n"
27 "Change the group membership of each FILE to GROUP.\n"
28 "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
29
30int chgrp_main(int argc, char **argv)
31{
32 const char *cp;
33 int gid;
34 struct group *grp;
35 struct stat statBuf;
36
37 if (argc < 2) {
38 fprintf(stderr, "Usage: %s %s", *argv, chgrp_usage);
39 return 1;
40 }
41 argc--;
42 argv++;
43
44 cp = argv[1];
45 if (isDecimal(*cp)) {
46 gid = 0;
47 while (isDecimal(*cp))
48 gid = gid * 10 + (*cp++ - '0');
49 if (*cp) {
50 fprintf(stderr, "Bad gid value\n");
51 return -1;
52 }
53 } else {
54 grp = getgrnam(cp);
55 if (grp == NULL) {
56 fprintf(stderr, "Unknown group name\n");
57 return -1;
58 }
59 gid = grp->gr_gid;
60 }
61 argc--;
62 argv++;
63 while (argc-- > 1) {
64 argv++;
65 if ((stat(*argv, &statBuf) < 0) ||
66 (chown(*argv, statBuf.st_uid, gid) < 0)) {
67 perror(*argv);
68 }
69 }
70 return 1;
71}
72
73
74
75
76
77
78
79
80
81#if 0
82int
83recursive(const char *fileName, BOOL followLinks, const char *pattern,
84 int (*fileAction) (const char *fileName,
85 const struct stat * statbuf),
86 int (*dirAction) (const char *fileName,
87 const struct stat * statbuf))
88
89#endif
diff --git a/coreutils/chmod.c b/coreutils/chmod.c
new file mode 100644
index 000000000..225c92d10
--- /dev/null
+++ b/coreutils/chmod.c
@@ -0,0 +1,163 @@
1#include <stdlib.h>
2#include <stdio.h>
3#include <unistd.h>
4#include <sys/stat.h>
5#include "internal.h"
6
7const char chmod_usage[] = "chmod [-R] mode file [file ...]\n"
8"\nmode may be an octal integer representing the bit pattern for the\n"
9"\tnew mode, or a symbolic value matching the pattern\n"
10"\t[ugoa]{+|-|=}[rwxst] .\n"
11"\t\tu:\tUser\n"
12"\t\tg:\tGroup\n"
13"\t\to:\tOthers\n"
14"\t\ta:\tAll\n"
15"\n"
16"\n+:\tAdd privilege\n"
17"\n-:\tRemove privilege\n"
18"\n=:\tSet privilege\n"
19"\n"
20"\t\tr:\tRead\n"
21"\t\tw:\tWrite\n"
22"\t\tx:\tExecute\n"
23"\t\ts:\tSet User ID\n"
24"\t\tt:\t\"Sticky\" Text\n"
25"\n"
26"\tModes may be concatenated, as in \"u=rwx,g=rx,o=rx,-t,-s\n"
27"\n"
28"\t-R:\tRecursively change the mode of all files and directories\n"
29"\t\tunder the argument directory.";
30
31int
32parse_mode(
33 const char * s
34,mode_t * or
35,mode_t * and
36,int * group_execute)
37{
38 /* [ugoa]{+|-|=}[rwxstl] */
39 mode_t mode = 0;
40 mode_t groups = S_ISVTX;
41 char type;
42 char c;
43
44 do {
45 for ( ; ; ) {
46 switch ( c = *s++ ) {
47 case '\0':
48 return -1;
49 case 'u':
50 groups |= S_ISUID|S_IRWXU;
51 continue;
52 case 'g':
53 groups |= S_ISGID|S_IRWXG;
54 continue;
55 case 'o':
56 groups |= S_IRWXO;
57 continue;
58 case 'a':
59 groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
60 continue;
61 case '+':
62 case '=':
63 case '-':
64 type = c;
65 if ( groups == S_ISVTX ) /* The default is "all" */
66 groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
67 break;
68 default:
69 if ( c >= '0' && c <= '7' && mode == 0 && groups == S_ISVTX ) {
70 *and = 0;
71 *or = strtol(--s, 0, 010);
72 return 0;
73 }
74 else
75 return -1;
76 }
77 break;
78 }
79
80 while ( (c = *s++) != '\0' ) {
81 switch ( c ) {
82 case ',':
83 break;
84 case 'r':
85 mode |= S_IRUSR|S_IRGRP|S_IROTH;
86 continue;
87 case 'w':
88 mode |= S_IWUSR|S_IWGRP|S_IWOTH;
89 continue;
90 case 'x':
91 mode |= S_IXUSR|S_IXGRP|S_IXOTH;
92 continue;
93 case 's':
94 if ( group_execute != 0 && (groups & S_IRWXG) ) {
95 if ( *group_execute < 0 )
96 return -1;
97 if ( type != '-' ) {
98 mode |= S_IXGRP;
99 *group_execute = 1;
100 }
101 }
102 mode |= S_ISUID|S_ISGID;
103 continue;
104 case 'l':
105 if ( *group_execute > 0 )
106 return -1;
107 if ( type != '-' ) {
108 *and &= ~S_IXGRP;
109 *group_execute = -1;
110 }
111 mode |= S_ISGID;
112 groups |= S_ISGID;
113 continue;
114 case 't':
115 mode |= S_ISVTX;
116 continue;
117 default:
118 return -1;
119 }
120 break;
121 }
122 switch ( type ) {
123 case '=':
124 *and &= ~(groups);
125 /* fall through */
126 case '+':
127 *or |= mode & groups;
128 break;
129 case '-':
130 *and &= ~(mode & groups);
131 *or &= *and;
132 break;
133 }
134 } while ( c == ',' );
135 return 0;
136}
137
138extern int
139chmod_main(struct FileInfo * i, int argc, char * * argv)
140{
141 i->andWithMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
142 i->orWithMode = 0;
143
144 while ( argc >= 3 ) {
145 if ( parse_mode(argv[1], &i->orWithMode, &i->andWithMode, 0)
146 == 0 ) {
147 argc--;
148 argv++;
149 }
150 else if ( strcmp(argv[1], "-R") == 0 ) {
151 i->recursive = 1;
152 argc--;
153 argv++;
154 }
155 else
156 break;
157 }
158
159 i->changeMode = 1;
160 i->complainInPostProcess = 1;
161
162 return monadic_main(i, argc, argv);
163}
diff --git a/coreutils/chown.c b/coreutils/chown.c
new file mode 100644
index 000000000..a611f92f1
--- /dev/null
+++ b/coreutils/chown.c
@@ -0,0 +1,63 @@
1#include "internal.h"
2#include <pwd.h>
3#include <grp.h>
4#include <string.h>
5#include <stdio.h>
6
7const char chown_usage[] = "chown [-R] user-name file [file ...]\n"
8"\n\tThe group list is kept in the file /etc/groups.\n\n"
9"\t-R:\tRecursively change the mode of all files and directories\n"
10"\t\tunder the argument directory.";
11
12int
13parse_user_name(const char * s, struct FileInfo * i)
14{
15 struct passwd * p;
16 char * dot = strchr(s, '.');
17
18 if (! dot )
19 dot = strchr(s, ':');
20
21 if ( dot )
22 *dot = '\0';
23
24 if ( (p = getpwnam(s)) == 0 ) {
25 fprintf(stderr, "%s: no such user.\n", s);
26 return 1;
27 }
28 i->userID = p->pw_uid;
29
30 if ( dot ) {
31 struct group * g = getgrnam(++dot);
32 if ( g == 0 ) {
33 fprintf(stderr, "%s: no such group.\n", dot);
34 return 1;
35 }
36 i->groupID = g->gr_gid;
37 i->changeGroupID = 1;
38 }
39 return 0;
40}
41
42extern int
43chown_main(struct FileInfo * i, int argc, char * * argv)
44{
45 int status;
46
47 while ( argc >= 3 && strcmp("-R", argv[1]) == 0 ) {
48 i->recursive = 1;
49 argc--;
50 argv++;
51 }
52
53 if ( (status = parse_user_name(argv[1], i)) != 0 )
54 return status;
55
56 argv++;
57 argc--;
58
59 i->changeUserID = 1;
60 i->complainInPostProcess = 1;
61
62 return monadic_main(i, argc, argv);
63}
diff --git a/coreutils/chroot.c b/coreutils/chroot.c
new file mode 100644
index 000000000..ca0bfcf3f
--- /dev/null
+++ b/coreutils/chroot.c
@@ -0,0 +1,32 @@
1#include "internal.h"
2#include <stdio.h>
3#include <unistd.h>
4
5
6const char chroot_usage[] = "chroot directory [command]\n"
7 "Run a command with special root directory.\n";
8
9extern int
10chroot_main (struct FileInfo *i, int argc, char **argv)
11{
12 char *prog;
13
14 if (chroot (argv[1]))
15 {
16 name_and_error ("cannot chroot to that directory");
17 return 1;
18 }
19 if (argc > 2)
20 {
21 execvp (argv[2], argv + 2);
22 }
23 else
24 {
25 prog = getenv ("SHELL");
26 if (!prog)
27 prog = "/bin/sh";
28 execlp (prog, prog, NULL);
29 }
30 name_and_error ("cannot exec");
31 return 1;
32}
diff --git a/coreutils/cp.c b/coreutils/cp.c
new file mode 100644
index 000000000..078a57c56
--- /dev/null
+++ b/coreutils/cp.c
@@ -0,0 +1,89 @@
1#include "internal.h"
2#include <stdio.h>
3#include <sys/stat.h>
4#include <sys/fcntl.h>
5#include <sys/param.h>
6#include <errno.h>
7
8const char cp_usage[] = "cp [-r] source-file destination-file\n"
9"\t\tcp [-r] source-file [source-file ...] destination-directory\n"
10"\n"
11"\tCopy the source files to the destination.\n"
12"\n"
13"\t-r:\tRecursively copy all files and directories\n"
14"\t\tunder the argument directory.";
15
16extern int
17cp_fn(const struct FileInfo * i)
18{
19 int sourceFd;
20 int destinationFd;
21 const char * destination = i->destination;
22 struct stat destination_stat;
23 int status;
24 char buf[8192];
25 char d[PATH_MAX];
26
27 if ( (i->stat.st_mode & S_IFMT) == S_IFDIR ) {
28 if ( mkdir(destination, i->stat.st_mode & ~S_IFMT)
29 != 0 && errno != EEXIST ) {
30 name_and_error(destination);
31 return 1;
32 }
33 return 0;
34 }
35 if ( (sourceFd = open(i->source, O_RDONLY)) < 0 ) {
36 name_and_error(i->source);
37 return 1;
38 }
39 if ( stat(destination, &destination_stat) == 0 ) {
40 if ( i->stat.st_ino == destination_stat.st_ino
41 && i->stat.st_dev == destination_stat.st_dev ) {
42 fprintf(stderr
43 ,"copy of %s to %s would copy file to itself.\n"
44 ,i->source
45 ,destination);
46 close(sourceFd);
47 return 1;
48 }
49 }
50 /*
51 * If the destination is a directory, create a file within it.
52 */
53 if ( (destination_stat.st_mode & S_IFMT) == S_IFDIR ) {
54 destination = join_paths(
55 d
56 ,i->destination
57 ,&i->source[i->directoryLength]);
58
59 if ( stat(destination, &destination_stat) == 0 ) {
60 if ( i->stat.st_ino == destination_stat.st_ino
61 && i->stat.st_dev == destination_stat.st_dev ) {
62 fprintf(stderr
63 ,"copy of %s to %s would copy file to itself.\n"
64 ,i->source
65 ,destination);
66 close(sourceFd);
67 return 1;
68 }
69 }
70 }
71
72 destinationFd = creat(destination, i->stat.st_mode & 07777);
73
74 while ( (status = read(sourceFd, buf, sizeof(buf))) > 0 ) {
75 if ( write(destinationFd, buf, status) != status ) {
76 name_and_error(destination);
77 close(sourceFd);
78 close(destinationFd);
79 return 1;
80 }
81 }
82 close(sourceFd);
83 close(destinationFd);
84 if ( status < 0 ) {
85 name_and_error(i->source);
86 return 1;
87 }
88 return 0;
89}
diff --git a/coreutils/date.c b/coreutils/date.c
new file mode 100644
index 000000000..a52a9a4a8
--- /dev/null
+++ b/coreutils/date.c
@@ -0,0 +1,305 @@
1#include "internal.h"
2#include <stdlib.h>
3#include <errno.h>
4#include <sys/time.h>
5#include <unistd.h>
6#include <time.h>
7#include <stdio.h>
8#include <getopt.h>
9
10
11/* This 'date' command supports only 2 time setting formats,
12 all the GNU strftime stuff (its in libc, lets use it),
13 setting time using UTC and displaying int, as well as
14 an RFC 822 complient date output for shell scripting
15 mail commands */
16
17const char date_usage[] = "date [-uR] [+FORMAT|+%f] [ [-s|-d] MMDDhhmm[[CC]YY]\n | [[[[CCYY.]MM.DD-]hh:mm[:ss]]]] ]";
18
19static struct option const long_options[] =
20{
21 {"date", required_argument, NULL, 'd'},
22 /* {"rfc-822", no_argument, NULL, 'R'},
23 {"set", required_argument, NULL, 's'},
24 {"uct", no_argument, NULL, 'u'},
25 {"utc", no_argument, NULL, 'u'},
26 {"universal", no_argument, NULL, 'u'}, */
27 {NULL, 0, NULL, 0}
28};
29
30
31
32/* Input parsing code is always bulky - used heavy duty libc stuff as
33 much as possible, missed out a lot of bounds checking */
34
35/* Default input handling to save suprising some people */
36
37struct tm *
38date_conv_time(struct tm *tm_time, const char *t_string) {
39 int nr;
40
41 nr = sscanf(t_string, "%2d%2d%2d%2d%d",
42 &(tm_time->tm_mon),
43 &(tm_time->tm_mday),
44 &(tm_time->tm_hour),
45 &(tm_time->tm_min),
46 &(tm_time->tm_year));
47
48 if(nr < 4 || nr > 5) {
49 fprintf(stderr, "date: invalid date `%s'\n", t_string);
50 exit(1);
51 }
52
53 /* correct for century - minor Y2K problem here? */
54 if(tm_time->tm_year >= 1900)
55 tm_time->tm_year -= 1900;
56 /* adjust date */
57 tm_time->tm_mon -= 1;
58
59 return(tm_time);
60
61}
62
63
64/* The new stuff for LRP */
65
66struct tm *
67date_conv_ftime(struct tm *tm_time, const char *t_string) {
68 struct tm itm_time, jtm_time, ktm_time, \
69 ltm_time, mtm_time, ntm_time;
70
71 itm_time = *tm_time;
72 jtm_time = *tm_time;
73 ktm_time = *tm_time;
74 ltm_time = *tm_time;
75 mtm_time = *tm_time;
76 ntm_time = *tm_time;
77
78 /* Parse input and assign appropriately to tm_time */
79
80 if(sscanf(t_string, "%d:%d:%d",
81 &itm_time.tm_hour,
82 &itm_time.tm_min,
83 &itm_time.tm_sec) == 3 ) {
84
85 *tm_time = itm_time;
86 return(tm_time);
87
88 } else if (sscanf(t_string, "%d:%d",
89 &jtm_time.tm_hour,
90 &jtm_time.tm_min) == 2) {
91
92 *tm_time = jtm_time;
93 return(tm_time);
94
95 } else if (sscanf(t_string, "%d.%d-%d:%d:%d",
96 &ktm_time.tm_mon,
97 &ktm_time.tm_mday,
98 &ktm_time.tm_hour,
99 &ktm_time.tm_min,
100 &ktm_time.tm_sec) == 5) {
101
102 ktm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
103 *tm_time = ktm_time;
104 return(tm_time);
105
106 } else if (sscanf(t_string, "%d.%d-%d:%d",
107 &ltm_time.tm_mon,
108 &ltm_time.tm_mday,
109 &ltm_time.tm_hour,
110 &ltm_time.tm_min) == 4) {
111
112 ltm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
113 *tm_time = ltm_time;
114 return(tm_time);
115
116 } else if (sscanf(t_string, "%d.%d.%d-%d:%d:%d",
117 &mtm_time.tm_year,
118 &mtm_time.tm_mon,
119 &mtm_time.tm_mday,
120 &mtm_time.tm_hour,
121 &mtm_time.tm_min,
122 &mtm_time.tm_sec) == 6) {
123
124 mtm_time.tm_year -= 1900; /* Adjust years */
125 mtm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
126 *tm_time = mtm_time;
127 return(tm_time);
128
129 } else if (sscanf(t_string, "%d.%d.%d-%d:%d",
130 &ntm_time.tm_year,
131 &ntm_time.tm_mon,
132 &ntm_time.tm_mday,
133 &ntm_time.tm_hour,
134 &ntm_time.tm_min) == 5) {
135 ntm_time.tm_year -= 1900; /* Adjust years */
136 ntm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
137 *tm_time = ntm_time;
138 return(tm_time);
139
140 }
141
142 fprintf(stderr, "date: invalid date `%s'\n", t_string);
143
144 exit(1);
145
146}
147
148
149void
150date_err(void) {
151 fprintf(stderr, "date: only one date argument can be given at a time.\n");
152 exit(1);
153}
154
155int
156date_main(struct FileInfo * i, int argc, char * * argv)
157{
158 char *date_str = NULL;
159 char *date_fmt = NULL;
160 char *t_buff;
161 int set_time = 0;
162 int rfc822 = 0;
163 int utc = 0;
164 int use_arg = 0;
165 int n_args;
166 time_t tm;
167 struct tm tm_time;
168 char optc;
169
170 /* Interpret command line args */
171
172
173 while ((optc = getopt_long (argc, argv, "d:Rs:u", long_options, NULL))
174 != EOF) {
175 switch (optc) {
176 case 0:
177 break;
178
179 case 'R':
180 rfc822 = 1;
181 break;
182
183 case 's':
184 set_time = 1;
185 if(date_str != NULL) date_err();
186 date_str = optarg;
187 break;
188
189 case 'u':
190 utc = 1;
191 if (putenv ("TZ=UTC0") != 0) {
192 fprintf(stderr,"date: memory exhausted\n");
193 return(1);
194 }
195#if LOCALTIME_CACHE
196 tzset ();
197#endif break;
198
199 case 'd':
200 use_arg = 1;
201 if(date_str != NULL) date_err();
202 date_str = optarg;
203 break;
204
205 default:
206 usage(date_usage);
207 break;
208 }
209 }
210
211
212 n_args = argc - optind;
213
214 while (n_args--){
215 switch(argv[optind][0]) {
216 case '+':
217 /* Date format strings */
218 if(date_fmt != NULL) {
219 fprintf(stderr, "date: only one date format can be given.\n");
220 return(1);
221 }
222 date_fmt = &argv[optind][1];
223 break;
224
225 case '\0':
226 break;
227
228 default:
229 /* Anything left over must be a date string to set the time */
230 set_time = 1;
231 if(date_str != NULL) date_err();
232 date_str = argv[optind];
233 break;
234 }
235 optind++;
236 }
237
238
239 /* Now we have parsed all the information except the date format
240 which depends on whether the clock is being set or read */
241
242 time(&tm);
243 memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
244 /* Zero out fields - take her back to midnight!*/
245 if(date_str != NULL) {
246 tm_time.tm_sec = 0;
247 tm_time.tm_min = 0;
248 tm_time.tm_hour = 0;
249 }
250
251 /* Process any date input to UNIX time since 1 Jan 1970 */
252 if(date_str != NULL) {
253
254 if(strchr(date_str, ':') != NULL) {
255 date_conv_ftime(&tm_time, date_str);
256 } else {
257 date_conv_time(&tm_time, date_str);
258 }
259
260 /* Correct any day of week and day of year etc fields */
261 tm = mktime(&tm_time);
262 if (tm < 0 ) {
263 fprintf(stderr, "date: invalid date `%s'\n", date_str);
264 exit(1);
265 }
266
267 /* if setting time, set it */
268 if(set_time) {
269 if( stime(&tm) < 0) {
270 fprintf(stderr, "date: can't set date.\n");
271 exit(1);
272 }
273 }
274 }
275
276 /* Display output */
277
278 /* Deal with format string */
279 if(date_fmt == NULL) {
280 date_fmt = (rfc822
281 ? (utc
282 ? "%a, %_d %b %Y %H:%M:%S GMT"
283 : "%a, %_d %b %Y %H:%M:%S %z")
284 : "%a %b %e %H:%M:%S %Z %Y");
285
286 } else if ( *date_fmt == '\0' ) {
287 /* Imitate what GNU 'date' does with NO format string! */
288 printf ("\n");
289 return(0);
290 }
291
292 /* Handle special conversions */
293
294 if( strncmp( date_fmt, "%f", 2) == 0 ) {
295 date_fmt = "%Y.%m.%d-%H:%M:%S";
296 }
297
298 /* Print OUTPUT (after ALL that!) */
299 t_buff = malloc(201);
300 strftime(t_buff, 200, date_fmt, &tm_time);
301 printf("%s\n", t_buff);
302
303 return(0);
304
305}
diff --git a/coreutils/dd.c b/coreutils/dd.c
new file mode 100644
index 000000000..8f1b9d409
--- /dev/null
+++ b/coreutils/dd.c
@@ -0,0 +1,307 @@
1/*
2 * Copyright (c) 1999 by David I. Bell
3 * Permission is granted to use, distribute, or modify this source,
4 * provided that this copyright notice remains intact.
5 *
6 * The "dd" command, originally taken from sash.
7 *
8 * Permission to distribute this code under the GPL has been granted.
9 * Majorly modified, and bugs fixed for busybox by Erik Andersen <andersee@debian.org> <andersen@lineo.com>
10 */
11
12#include "internal.h"
13#ifdef BB_DD
14
15const char dd_usage[] =
16"Copy a file, converting and formatting according to options\n\
17\n\
18usage: [if=name] [of=name] [bs=n] [count=n]\n\
19\tif=FILE\tread from FILE instead of stdin\n\
20\tof=FILE\twrite to FILE instead of stout\n\
21\tbs=n\tread and write N bytes at a time\n\
22\tcount=n\tcopy only n input blocks\n\
23\n\
24BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n";
25
26
27#include <stdio.h>
28#include <dirent.h>
29#include <errno.h>
30#include <fcntl.h>
31#include <signal.h>
32#include <time.h>
33
34
35#define PAR_NONE 0
36#define PAR_IF 1
37#define PAR_OF 2
38#define PAR_BS 3
39#define PAR_COUNT 4
40
41
42typedef struct
43{
44 const char * name;
45 int value;
46} PARAM;
47
48
49static const PARAM params[] =
50{
51 {"if", PAR_IF},
52 {"of", PAR_OF},
53 {"bs", PAR_BS},
54 {"count", PAR_COUNT},
55 {NULL, PAR_NONE}
56};
57
58
59static long getNum(const char * cp);
60
61extern int
62dd_main (struct FileInfo *unused, int argc, char **argv)
63{
64 const char * str;
65 const PARAM * par;
66 const char * inFile;
67 const char * outFile;
68 char * cp;
69 int inFd;
70 int outFd;
71 int inCc=0;
72 int outCc;
73 int blockSize;
74 long count;
75 long intotal;
76 long outTotal;
77 unsigned char* buf;
78 unsigned char localBuf[BUF_SIZE];
79
80 inFile = NULL;
81 outFile = NULL;
82 blockSize = 512;
83 count = 1;
84
85
86 while (--argc > 0)
87 {
88 str = *++argv;
89 cp = strchr(str, '=');
90
91 if (cp == NULL)
92 {
93 fprintf(stderr, "Bad dd argument\n");
94 goto usage;
95 }
96
97 *cp++ = '\0';
98
99 for (par = params; par->name; par++)
100 {
101 if (strcmp(str, par->name) == 0)
102 break;
103 }
104
105 switch (par->value)
106 {
107 case PAR_IF:
108 if (inFile)
109 {
110 fprintf(stderr, "Multiple input files illegal\n");
111 goto usage;
112 }
113
114 //fprintf(stderr, "if=%s\n", cp);
115 inFile = cp;
116 break;
117
118 case PAR_OF:
119 if (outFile)
120 {
121 fprintf(stderr, "Multiple output files illegal\n");
122 goto usage;
123 }
124
125 //fprintf(stderr, "of=%s\n", cp);
126 outFile = cp;
127 break;
128
129 case PAR_BS:
130 blockSize = getNum(cp);
131 //fprintf(stderr, "bs=%d\n", blockSize);
132
133 if (blockSize <= 0)
134 {
135 fprintf(stderr, "Bad block size value\n");
136 goto usage;
137 }
138
139 break;
140
141 case PAR_COUNT:
142 count = getNum(cp);
143 //fprintf(stderr, "count=%ld\n", count);
144
145 if (count < 0)
146 {
147 fprintf(stderr, "Bad count value\n");
148 goto usage;
149 }
150
151 break;
152
153 default:
154 goto usage;
155 }
156 }
157
158 buf = localBuf;
159
160 if (blockSize > sizeof(localBuf))
161 {
162 buf = malloc(blockSize);
163
164 if (buf == NULL)
165 {
166 fprintf(stderr, "Cannot allocate buffer\n");
167 return 1;
168 }
169 }
170
171 intotal = 0;
172 outTotal = 0;
173
174 if (inFile == NULL)
175 inFd = STDIN;
176 else
177 inFd = open(inFile, 0);
178
179 if (inFd < 0)
180 {
181 perror(inFile);
182
183 if (buf != localBuf)
184 free(buf);
185
186 return 1;
187 }
188
189 if (outFile == NULL)
190 outFd = STDOUT;
191 else
192 outFd = creat(outFile, 0666);
193
194 if (outFd < 0)
195 {
196 perror(outFile);
197 close(inFd);
198
199 if (buf != localBuf)
200 free(buf);
201
202 return 1;
203 }
204
205 while ( outTotal < count*blockSize )
206 {
207 inCc = read(inFd, buf, blockSize);
208 if (inCc < 0) {
209 perror(inFile);
210 goto cleanup;
211 }
212 //fprintf(stderr, "read in =%d\n", inCc);
213 intotal += inCc;
214 cp = buf;
215
216
217 while ( intotal > outTotal )
218 {
219 if (outTotal+inCc > count*blockSize)
220 inCc=count*blockSize-outTotal;
221 outCc = write(outFd, cp, inCc);
222 if (outCc < 0)
223 {
224 perror(outFile);
225 goto cleanup;
226 }
227 //fprintf(stderr, "wrote out =%d\n", outCc);
228
229 inCc -= outCc;
230 cp += outCc;
231 outTotal += outCc;
232 //fprintf(stderr, "outTotal=%ld\n", outTotal);
233 }
234 }
235
236 if (inCc < 0)
237 perror(inFile);
238
239cleanup:
240 close(inFd);
241
242 if (close(outFd) < 0)
243 perror(outFile);
244
245 if (buf != localBuf)
246 free(buf);
247
248 printf("%ld+%d records in\n", intotal / blockSize,
249 (intotal % blockSize) != 0);
250
251 printf("%ld+%d records out\n", outTotal / blockSize,
252 (outTotal % blockSize) != 0);
253 return 0;
254usage:
255
256 fprintf(stderr, "%s", dd_usage);
257 return 1;
258}
259
260
261/*
262 * Read a number with a possible multiplier.
263 * Returns -1 if the number format is illegal.
264 */
265static long
266getNum(const char * cp)
267{
268 long value;
269
270 if (!isDecimal(*cp))
271 return -1;
272
273 value = 0;
274
275 while (isDecimal(*cp))
276 value = value * 10 + *cp++ - '0';
277
278 switch (*cp++)
279 {
280 case 'k':
281 value *= 1024;
282 break;
283
284 case 'b':
285 value *= 512;
286 break;
287
288 case 'w':
289 value *= 2;
290 break;
291
292 case '\0':
293 return value;
294
295 default:
296 return -1;
297 }
298
299 if (*cp)
300 return -1;
301
302 return value;
303}
304
305#endif
306/* END CODE */
307
diff --git a/coreutils/df.c b/coreutils/df.c
new file mode 100644
index 000000000..a0692afc5
--- /dev/null
+++ b/coreutils/df.c
@@ -0,0 +1,103 @@
1#include "internal.h"
2#include <stdio.h>
3#include <mntent.h>
4#include <sys/stat.h>
5#include <sys/vfs.h>
6
7const char df_usage[] = "df [filesystem ...]\n"
8"\n"
9"\tPrint the filesystem space used and space available.\n";
10
11
12static int
13df(const char * device, const char * mountPoint)
14{
15 struct statfs s;
16 long blocks_used;
17 long blocks_percent_used;
18
19 if ( statfs(mountPoint, &s) != 0 ) {
20 name_and_error(mountPoint);
21 return 1;
22 }
23
24 if ( s.f_blocks > 0 ) {
25 blocks_used = s.f_blocks - s.f_bfree;
26 blocks_percent_used = (long)
27 (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
28
29/*
30 printf(
31 "%-20s %7ld %7ld %7ld %5ld%% %s\n"
32 ,device
33 ,s.f_blocks
34 ,s.f_blocks - s.f_bfree
35 ,s.f_bavail
36 ,blocks_percent_used
37 ,mountPoint);
38*/
39
40 printf(
41 "%-20s %7.0f %7.0f %7.0f %5ld%% %s\n"
42 ,device
43 ,s.f_blocks * (s.f_bsize / 1024.0)
44 ,(s.f_blocks - s.f_bfree) * (s.f_bsize / 1024.0)
45 ,s.f_bavail * (s.f_bsize / 1024.0)
46 ,blocks_percent_used
47 ,mountPoint);
48
49 }
50
51 return 0;
52}
53
54extern int
55df_main(struct FileInfo * i, int argc, char * * argv)
56{
57 static const char header[] =
58 "Filesystem 1024-blocks Used Available Capacity Mounted on\n";
59 printf(header);
60
61 if ( argc > 1 ) {
62 struct mntent * mountEntry;
63 int status;
64
65 while ( argc > 1 ) {
66 if ( (mountEntry = findMountPoint(argv[1], "/etc/mtab")) == 0
67 && (mountEntry = findMountPoint(argv[1], "/proc/mounts")) == 0 )
68 {
69 fprintf(stderr, "%s: can't find mount point.\n"
70 ,argv[1]);
71 return 1;
72 }
73 status = df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
74 if ( status != 0 )
75 return status;
76 argc--;
77 argv++;
78 }
79 return 0;
80 }
81 else {
82 FILE * mountTable;
83 struct mntent * mountEntry;
84
85 if ( (mountTable = setmntent("/etc/mtab", "r")) == 0
86 && (mountTable = setmntent("/proc/mounts", "r")) == 0
87 ) {
88 name_and_error("/etc/mtab");
89 return 1;
90 }
91
92 while ( (mountEntry = getmntent(mountTable)) != 0 ) {
93 int status = df(
94 mountEntry->mnt_fsname
95 ,mountEntry->mnt_dir);
96 if ( status != 0 )
97 return status;
98 }
99 endmntent(mountTable);
100 }
101
102 return 0;
103}
diff --git a/coreutils/length.c b/coreutils/length.c
new file mode 100644
index 000000000..284bbfdf9
--- /dev/null
+++ b/coreutils/length.c
@@ -0,0 +1,13 @@
1#include "internal.h"
2#include <stdlib.h>
3#include <string.h>
4#include <stdio.h>
5
6const char length_usage[] = "length string";
7
8int
9length_main(struct FileInfo * i, int argc, char * * argv)
10{
11 printf("%d\n", strlen(argv[1]));
12 return 0;
13}
diff --git a/coreutils/ln.c b/coreutils/ln.c
new file mode 100644
index 000000000..3e87b579e
--- /dev/null
+++ b/coreutils/ln.c
@@ -0,0 +1,52 @@
1#include "internal.h"
2#include <stdio.h>
3#include <sys/stat.h>
4#include <sys/param.h>
5#include <errno.h>
6
7const char ln_usage[] = "ln [-s] [-f] original-name additional-name\n"
8"\n"
9"\tAdd a new name that refers to the same file as \"original-name\"\n"
10"\n"
11"\t-s:\tUse a \"symbolic\" link, instead of a \"hard\" link.\n"
12"\t-f:\tRemove existing destination files.\n";
13
14int
15ln_fn(const struct FileInfo * i)
16{
17 int status = 0;
18 char d[PATH_MAX];
19 const char * destination = i->destination;
20
21 if ( !i->makeSymbolicLink && (i->stat.st_mode & S_IFMT) == S_IFDIR ) {
22 fprintf(stderr, "Please use \"ln -s\" to link directories.\n");
23 return 1;
24 }
25
26 /*
27 * If the destination is a directory, create a file within it.
28 */
29 if ( is_a_directory(i->destination) ) {
30 destination = join_paths(
31 d
32 ,i->destination
33 ,&i->source[i->directoryLength]);
34 }
35
36 if ( i->force )
37 status = ( unlink(destination) && errno != ENOENT );
38
39 if ( status == 0 ) {
40 if ( i->makeSymbolicLink )
41 status = symlink(i->source, destination);
42 else
43 status = link(i->source, destination);
44 }
45
46 if ( status != 0 ) {
47 name_and_error(destination);
48 return 1;
49 }
50 else
51 return 0;
52}
diff --git a/coreutils/ls.c b/coreutils/ls.c
new file mode 100644
index 000000000..2566beea0
--- /dev/null
+++ b/coreutils/ls.c
@@ -0,0 +1,542 @@
1#include "internal.h"
2/*
3 * tiny-ls.c version 0.1.0: A minimalist 'ls'
4 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21/*
22 * To achieve a small memory footprint, this version of 'ls' doesn't do any
23 * file sorting, and only has the most essential command line switches
24 * (i.e. the ones I couldn't live without :-) All features which involve
25 * linking in substantial chunks of libc can be disabled.
26 *
27 * Although I don't really want to add new features to this program to
28 * keep it small, I *am* interested to receive bug fixes and ways to make
29 * it more portable.
30 *
31 * KNOWN BUGS:
32 * 1. messy output if you mix files and directories on the command line
33 * 2. ls -l of a directory doesn't give "total <blocks>" header
34 * 3. ls of a symlink to a directory doesn't list directory contents
35 * 4. hidden files can make column width too large
36 * NON-OPTIMAL BEHAVIOUR:
37 * 1. autowidth reads directories twice
38 * 2. if you do a short directory listing without filetype characters
39 * appended, there's no need to stat each one
40 * PORTABILITY:
41 * 1. requires lstat (BSD) - how do you do it without?
42 */
43
44#define FEATURE_USERNAME /* show username/groupnames (libc6 uses NSS) */
45#define FEATURE_TIMESTAMPS /* show file timestamps */
46#define FEATURE_AUTOWIDTH /* calculate terminal & column widths */
47#define FEATURE_FILETYPECHAR /* enable -p and -F */
48
49#undef OP_BUF_SIZE 1024 /* leave undefined for unbuffered output */
50
51#define TERMINAL_WIDTH 80 /* use 79 if your terminal has linefold bug */
52#define COLUMN_WIDTH 14 /* default if AUTOWIDTH not defined */
53#define COLUMN_GAP 2 /* includes the file type char, if present */
54
55/************************************************************************/
56
57#define HAS_REWINDDIR
58
59#if 1 /* FIXME libc 6 */
60# include <linux/types.h>
61#else
62# include <sys/types.h>
63#endif
64#include <sys/stat.h>
65#include <stdio.h>
66#include <unistd.h>
67#include <dirent.h>
68#include <errno.h>
69#include <stdio.h>
70#ifdef FEATURE_USERNAME
71#include <pwd.h>
72#include <grp.h>
73#endif
74#ifdef FEATURE_TIMESTAMPS
75#include <time.h>
76#endif
77
78#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
79#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
80#ifdef FEATURE_FILETYPECHAR
81#define APPCHAR(mode) ("\0|\0\0/\0\0\0\0\0@\0=\0\0\0" [TYPEINDEX(mode)])
82#endif
83
84#ifndef MAJOR
85#define MAJOR(dev) (((dev)>>8)&0xff)
86#define MINOR(dev) ((dev)&0xff)
87#endif
88
89#define MODE1 "rwxrwxrwx"
90#define MODE0 "---------"
91#define SMODE1 "..s..s..t"
92#define SMODE0 "..S..S..T"
93
94/* The 9 mode bits to test */
95
96static const umode_t MBIT[] = {
97 S_IRUSR, S_IWUSR, S_IXUSR,
98 S_IRGRP, S_IWGRP, S_IXGRP,
99 S_IROTH, S_IWOTH, S_IXOTH
100};
101
102/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */
103
104static const umode_t SBIT[] = {
105 0, 0, S_ISUID,
106 0, 0, S_ISGID,
107 0, 0, S_ISVTX
108};
109
110#define FMT_AUTO 0
111#define FMT_LONG 1 /* one record per line, extended info */
112#define FMT_SINGLE 2 /* one record per line */
113#define FMT_ROWS 3 /* print across rows */
114#define FMT_COLUMNS 3 /* fill columns (same, since we don't sort) */
115
116#define TIME_MOD 0
117#define TIME_CHANGE 1
118#define TIME_ACCESS 2
119
120#define DISP_FTYPE 1 /* show character for file type */
121#define DISP_EXEC 2 /* show '*' if regular executable file */
122#define DISP_HIDDEN 4 /* show files starting . (except . and ..) */
123#define DISP_DOT 8 /* show . and .. */
124#define DISP_NUMERIC 16 /* numeric uid and gid */
125#define DISP_FULLTIME 32 /* show extended time display */
126#define DIR_NOLIST 64 /* show directory as itself, not contents */
127#define DISP_DIRNAME 128 /* show directory name (for internal use) */
128#define DIR_RECURSE 256 /* -R (not yet implemented) */
129
130static unsigned char display_fmt = FMT_AUTO;
131static unsigned short opts = 0;
132static unsigned short column = 0;
133
134#ifdef FEATURE_AUTOWIDTH
135static unsigned short terminal_width = 0, column_width = 0;
136#else
137#define terminal_width TERMINAL_WIDTH
138#define column_width COLUMN_WIDTH
139#endif
140
141#ifdef FEATURE_TIMESTAMPS
142static unsigned char time_fmt = TIME_MOD;
143#endif
144
145#define wr(data,len) fwrite(data, 1, len, stdout)
146
147static void writenum(long val, short minwidth)
148{
149 char scratch[20];
150
151 char *p = scratch + sizeof(scratch);
152 short len = 0;
153 short neg = (val < 0);
154
155 if (neg) val = -val;
156 do
157 *--p = (val % 10) + '0', len++, val /= 10;
158 while (val);
159 if (neg)
160 *--p = '-', len++;
161 while (len < minwidth)
162 *--p = ' ', len++;
163 wr(p, len);
164 column += len;
165}
166
167static void newline(void)
168{
169 if (column > 0) {
170 wr("\n", 1);
171 column = 0;
172 }
173}
174
175static void tab(short col)
176{
177 static const char spaces[] = " ";
178 #define nspaces ((sizeof spaces)-1) /* null terminator! */
179
180 short n = col - column;
181
182 if (n > 0) {
183 column = col;
184 while (n > nspaces) {
185 wr(spaces, nspaces);
186 n -= nspaces;
187 }
188 /* must be 1...(sizeof spaces) left */
189 wr(spaces, n);
190 }
191 #undef nspaces
192}
193
194#ifdef FEATURE_FILETYPECHAR
195static char append_char(umode_t mode)
196{
197 if (!(opts & DISP_FTYPE))
198 return '\0';
199 if ((opts & DISP_EXEC) && S_ISREG(mode) && (mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
200 return '*';
201 return APPCHAR(mode);
202}
203#endif
204
205/**
206 **
207 ** Display a file or directory as a single item
208 ** (in either long or short format)
209 **
210 **/
211
212static void list_single(const char *name, struct stat *info)
213{
214 char scratch[20];
215 short len = strlen(name);
216#ifdef FEATURE_FILETYPECHAR
217 char append = append_char(info->st_mode);
218#endif
219
220 if (display_fmt == FMT_LONG) {
221 umode_t mode = info->st_mode;
222 int i;
223
224 scratch[0] = TYPECHAR(mode);
225 for (i=0; i<9; i++)
226 if (mode & SBIT[i])
227 scratch[i+1] = (mode & MBIT[i])
228 ? SMODE1[i]
229 : SMODE0[i];
230 else
231 scratch[i+1] = (mode & MBIT[i])
232 ? MODE1[i]
233 : MODE0[i];
234 newline();
235 wr(scratch, 10);
236 column=10;
237 writenum((long)info->st_nlink,(short)4);
238 fputs(" ", stdout);
239#ifdef FEATURE_USERNAME
240 if (!(opts & DISP_NUMERIC)) {
241 struct passwd *pw = getpwuid(info->st_uid);
242 if (pw)
243 fputs(pw->pw_name, stdout);
244 else
245 writenum((long)info->st_uid,(short)0);
246 } else
247#endif
248 writenum((long)info->st_uid,(short)0);
249 tab(24);
250#ifdef FEATURE_USERNAME
251 if (!(opts & DISP_NUMERIC)) {
252 struct group *gr = getgrgid(info->st_gid);
253 if (gr)
254 fputs(gr->gr_name, stdout);
255 else
256 writenum((long)info->st_gid,(short)0);
257 } else
258#endif
259 writenum((long)info->st_gid,(short)0);
260 tab(33);
261 if (S_ISBLK(mode) || S_ISCHR(mode)) {
262 writenum((long)MAJOR(info->st_rdev),(short)3);
263 fputs(", ", stdout);
264 writenum((long)MINOR(info->st_rdev),(short)3);
265 }
266 else
267 writenum((long)info->st_size,(short)8);
268 fputs(" ", stdout);
269#ifdef FEATURE_TIMESTAMPS
270 {
271 time_t cal;
272 char *string;
273
274 switch(time_fmt) {
275 case TIME_CHANGE:
276 cal=info->st_ctime; break;
277 case TIME_ACCESS:
278 cal=info->st_atime; break;
279 default:
280 cal=info->st_mtime; break;
281 }
282 string=ctime(&cal);
283 if (opts & DISP_FULLTIME)
284 wr(string,24);
285 else {
286 time_t age = time(NULL) - cal;
287 wr(string+4,7); /* mmm_dd_ */
288 if(age < 3600L*24*365/2 && age > -15*60)
289 /* hh:mm if less than 6 months old */
290 wr(string+11,5);
291 else
292 /* _yyyy otherwise */
293 wr(string+19,5);
294 }
295 wr(" ", 1);
296 }
297#else
298 fputs("--- -- ----- ", stdout);
299#endif
300 wr(name, len);
301 if (S_ISLNK(mode)) {
302 wr(" -> ", 4);
303 len = readlink(name, scratch, sizeof scratch);
304 if (len > 0) fwrite(scratch, 1, len, stdout);
305#ifdef FEATURE_FILETYPECHAR
306 /* show type of destination */
307 if (opts & DISP_FTYPE) {
308 if (!stat(name, info)) {
309 append = append_char(info->st_mode);
310 if (append)
311 fputc(append, stdout);
312 }
313 }
314#endif
315 }
316#ifdef FEATURE_FILETYPECHAR
317 else if (append)
318 wr(&append, 1);
319#endif
320 } else {
321 static short nexttab = 0;
322
323 /* sort out column alignment */
324 if (column == 0)
325 ; /* nothing to do */
326 else if (display_fmt == FMT_SINGLE)
327 newline();
328 else {
329 if (nexttab + column_width > terminal_width
330#ifndef FEATURE_AUTOWIDTH
331 || nexttab + len >= terminal_width
332#endif
333 )
334 newline();
335 else
336 tab(nexttab);
337 }
338 /* work out where next column starts */
339#ifdef FEATURE_AUTOWIDTH
340 /* we know the calculated width is big enough */
341 nexttab = column + column_width + COLUMN_GAP;
342#else
343 /* might cover more than one fixed-width column */
344 nexttab = column;
345 do
346 nexttab += column_width + COLUMN_GAP;
347 while (nexttab < (column + len + COLUMN_GAP));
348#endif
349 /* now write the data */
350 wr(name, len);
351 column = column + len;
352#ifdef FEATURE_FILETYPECHAR
353 if (append)
354 wr(&append, 1), column++;
355#endif
356 }
357}
358
359/**
360 **
361 ** List the given file or directory, expanding a directory
362 ** to show its contents if required
363 **
364 **/
365
366static int list_item(const char *name)
367{
368 struct stat info;
369 DIR *dir;
370 struct dirent *entry;
371 char fullname[MAXNAMLEN+1], *fnend;
372
373 if (lstat(name, &info))
374 goto listerr;
375
376 if (!S_ISDIR(info.st_mode) ||
377 (opts & DIR_NOLIST)) {
378 list_single(name, &info);
379 return 0;
380 }
381
382 /* Otherwise, it's a directory we want to list the contents of */
383
384 if (opts & DISP_DIRNAME) { /* identify the directory */
385 if (column)
386 wr("\n\n", 2), column = 0;
387 wr(name, strlen(name));
388 wr(":\n", 2);
389 }
390
391 dir = opendir(name);
392 if (!dir) goto listerr;
393#ifdef FEATURE_AUTOWIDTH
394 column_width = 0;
395 while ((entry = readdir(dir)) != NULL) {
396 short w = strlen(entry->d_name);
397 if (column_width < w)
398 column_width = w;
399 }
400#ifdef HAS_REWINDDIR
401 rewinddir(dir);
402#else
403 closedir(dir);
404 dir = opendir(name);
405 if (!dir) goto listerr;
406#endif
407#endif
408
409 /* List the contents */
410
411 strcpy(fullname,name); /* *** ignore '.' by itself */
412 fnend=fullname+strlen(fullname);
413 if (fnend[-1] != '/')
414 *fnend++ = '/';
415
416 while ((entry = readdir(dir)) != NULL) {
417 const char *en=entry->d_name;
418 if (en[0] == '.') {
419 if (!en[1] || (en[1] == '.' && !en[2])) { /* . or .. */
420 if (!(opts & DISP_DOT))
421 continue;
422 }
423 else if (!(opts & DISP_HIDDEN))
424 continue;
425 }
426 /* FIXME: avoid stat if not required */
427 strcpy(fnend, entry->d_name);
428 if (lstat(fullname, &info))
429 goto direrr; /* (shouldn't fail) */
430 list_single(entry->d_name, &info);
431 }
432 closedir(dir);
433 return 0;
434
435direrr:
436 closedir(dir);
437listerr:
438 newline();
439 name_and_error(name);
440 return 1;
441}
442
443const char ls_usage[] = "Usage: ls [-1a"
444#ifdef FEATURE_TIMESTAMPS
445 "c"
446#endif
447 "d"
448#ifdef FEATURE_TIMESTAMPS
449 "e"
450#endif
451 "ln"
452#ifdef FEATURE_FILETYPECHAR
453 "p"
454#endif
455#ifdef FEATURE_TIMESTAMPS
456 "u"
457#endif
458 "xAC"
459#ifdef FEATURE_FILETYPECHAR
460 "F"
461#endif
462#ifdef FEATURE_RECURSIVE
463 "R"
464#endif
465 "] [filenames...]\n";
466
467extern int
468ls_main(struct FileInfo * not_used, int argc, char * * argv)
469{
470 int argi=1, i;
471
472 /* process options */
473 while (argi < argc && argv[argi][0] == '-') {
474 const char *p = &argv[argi][1];
475
476 if (!*p) goto print_usage_message; /* "-" by itself not allowed */
477 if (*p == '-') {
478 if (!p[1]) { /* "--" forces end of options */
479 argi++;
480 break;
481 }
482 /* it's a long option name - we don't support them */
483 goto print_usage_message;
484 }
485
486 while (*p)
487 switch (*p++) {
488 case 'l': display_fmt = FMT_LONG; break;
489 case '1': display_fmt = FMT_SINGLE; break;
490 case 'x': display_fmt = FMT_ROWS; break;
491 case 'C': display_fmt = FMT_COLUMNS; break;
492#ifdef FEATURE_FILETYPECHAR
493 case 'p': opts |= DISP_FTYPE; break;
494 case 'F': opts |= DISP_FTYPE|DISP_EXEC; break;
495#endif
496 case 'A': opts |= DISP_HIDDEN; break;
497 case 'a': opts |= DISP_HIDDEN|DISP_DOT; break;
498 case 'n': opts |= DISP_NUMERIC; break;
499 case 'd': opts |= DIR_NOLIST; break;
500#ifdef FEATURE_RECURSIVE
501 case 'R': opts |= DIR_RECURSE; break;
502#endif
503#ifdef FEATURE_TIMESTAMPS
504 case 'u': time_fmt = TIME_ACCESS; break;
505 case 'c': time_fmt = TIME_CHANGE; break;
506 case 'e': opts |= DISP_FULLTIME; break;
507#endif
508 default: goto print_usage_message;
509 }
510
511 argi++;
512 }
513
514 /* choose a display format */
515 if (display_fmt == FMT_AUTO)
516 display_fmt = isatty(STDOUT_FILENO) ? FMT_COLUMNS : FMT_SINGLE;
517 if (argi < argc - 1)
518 opts |= DISP_DIRNAME; /* 2 or more items? label directories */
519#ifdef FEATURE_AUTOWIDTH
520 /* could add a -w option and/or TIOCGWINSZ call */
521 if (terminal_width < 1) terminal_width = TERMINAL_WIDTH;
522
523 for (i = argi; i < argc; i++) {
524 int len = strlen(argv[i]);
525 if (column_width < len)
526 column_width = len;
527 }
528#endif
529
530 /* process files specified, or current directory if none */
531 i=0;
532 if (argi == argc)
533 i = list_item(".");
534 while (argi < argc)
535 i |= list_item(argv[argi++]);
536 newline();
537 return i;
538
539print_usage_message:
540 usage(ls_usage);
541 return 1;
542}
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c
new file mode 100644
index 000000000..8f1fa04db
--- /dev/null
+++ b/coreutils/mkdir.c
@@ -0,0 +1,58 @@
1#include "internal.h"
2#include <errno.h>
3#include <sys/param.h>
4
5const char mkdir_usage[] = "mkdir [-m mode] directory [directory ...]\n"
6"\tCreate directories.\n"
7"\n"
8"\t-m mode:\tSpecifiy the mode for the new directory\n"
9"\t\tunder the argument directory.";
10
11/*make directories skipping the last part of the path. Used here and by untar*/
12int mkdir_until(const char *fpath, const struct FileInfo * fi)
13{
14 char path[PATH_MAX];
15 char * s = path;
16
17 strcpy(path, fpath);
18 if ( s[0] == '\0' && s[1] == '\0' ) {
19 usage(mkdir_usage);
20 return 1;
21 }
22 s++;
23 while ( *s != '\0' ) {
24 if ( *s == '/' ) {
25 int status;
26
27 *s = '\0';
28 status = mkdir(path, (fi?fi->orWithMode:0700) );
29 *s = '/';
30
31 if ( status != 0 ) {
32 if ( errno != EEXIST ) {
33 name_and_error(fpath);
34 return 1;
35 }
36 }
37
38 }
39 s++;
40 }
41 return 0;
42}
43
44int
45mkdir_fn(const struct FileInfo * i)
46{
47 if ( i->makeParentDirectories ) {
48 if(mkdir_until(i->source, i)) return 1;
49 }
50
51 if ( mkdir(i->source, i->orWithMode) != 0 && errno != EEXIST ) {
52 name_and_error(i->source);
53 return 1;
54 }
55 else
56 return 0;
57}
58
diff --git a/coreutils/mknod.c b/coreutils/mknod.c
new file mode 100644
index 000000000..b18394bec
--- /dev/null
+++ b/coreutils/mknod.c
@@ -0,0 +1,52 @@
1#include "internal.h"
2#include <errno.h>
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <fcntl.h>
6#include <unistd.h>
7
8const char mknod_usage[] = "mknod file b|c|u|p major minor\n"
9"\tMake special files.\n"
10"\n"
11"\tb:\tMake a block (buffered) device.\n"
12"\tc or u:\tMake a character (un-buffered) device.\n"
13"\tp:\tMake a named pipe. Major and minor are ignored for named pipes.\n";
14
15int
16mknod_main(struct FileInfo * i, int argc, char * * argv)
17{
18 mode_t mode = 0;
19 dev_t dev = 0;
20
21 switch(argv[2][0]) {
22 case 'c':
23 case 'u':
24 mode = S_IFCHR;
25 break;
26 case 'b':
27 mode = S_IFBLK;
28 break;
29 case 'p':
30 mode = S_IFIFO;
31 break;
32 default:
33 usage(mknod_usage);
34 return 1;
35 }
36
37 if ( mode == S_IFCHR || mode == S_IFBLK ) {
38 dev = (atoi(argv[3]) << 8) | atoi(argv[4]);
39 if ( argc != 5 ) {
40 usage(mknod_usage);
41 return 1;
42 }
43 }
44
45 mode |= 0666;
46
47 if ( mknod(argv[1], mode, dev) != 0 ) {
48 name_and_error(argv[1]);
49 return 1;
50 }
51 return 0;
52}
diff --git a/coreutils/mv.c b/coreutils/mv.c
new file mode 100644
index 000000000..22c4a1207
--- /dev/null
+++ b/coreutils/mv.c
@@ -0,0 +1,38 @@
1#include "internal.h"
2#include <stdio.h>
3#include <errno.h>
4
5const char mv_usage[] = "mv source-file destination-file\n"
6"\t\tmv source-file [source-file ...] destination-directory\n"
7"\n"
8"\tMove the source files to the destination.\n"
9"\n";
10
11extern int
12mv_fn(const struct FileInfo * i)
13{
14 struct stat destination_stat;
15 char d[1024];
16 struct FileInfo n;
17
18 if ( stat(i->destination, &destination_stat) == 0 ) {
19 if ( i->stat.st_ino == destination_stat.st_ino
20 && i->stat.st_dev == destination_stat.st_dev )
21 return 0; /* Move file to itself. */
22 }
23 if ( (destination_stat.st_mode & S_IFMT) == S_IFDIR ) {
24 n = *i;
25 n.destination = join_paths(d, i->destination, basename(i->source));
26 i = &n;
27 }
28 if ( rename(i->source, i->destination) == 0 )
29 return 0;
30 else if ( errno == EXDEV && is_a_directory(i->source) ) {
31 fprintf(stderr
32 ,"%s: Can't move directory across filesystems.\n"
33 ,i->source);
34 return 1;
35 }
36 else
37 return cp_fn(i);
38}
diff --git a/coreutils/printf.c b/coreutils/printf.c
new file mode 100644
index 000000000..e79843c80
--- /dev/null
+++ b/coreutils/printf.c
@@ -0,0 +1,531 @@
1// I may still need some more cleaning...fix my error checking
2
3#include "internal.h"
4#ifdef BB_PRINTF
5
6/* printf - format and print data
7 Copyright (C) 90, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22
23/* Usage: printf format [argument...]
24
25 A front end to the printf function that lets it be used from the shell.
26
27 Backslash escapes:
28
29 \" = double quote
30 \\ = backslash
31 \a = alert (bell)
32 \b = backspace
33 \c = produce no further output
34 \f = form feed
35 \n = new line
36 \r = carriage return
37 \t = horizontal tab
38 \v = vertical tab
39 \0ooo = octal number (ooo is 0 to 3 digits)
40 \xhhh = hexadecimal number (hhh is 1 to 3 digits)
41
42 Additional directive:
43
44 %b = print an argument string, interpreting backslash escapes
45
46 The `format' argument is re-used as many times as necessary
47 to convert all of the given arguments.
48
49 David MacKenzie <djm@gnu.ai.mit.edu> */
50
51
52// 19990508 Busy Boxed! Dave Cinege
53
54#include <unistd.h>
55#include <stdio.h>
56#include <sys/types.h>
57#include <getopt.h>
58#include <sys/stat.h>
59#include <string.h>
60#include <errno.h>
61#include <stdlib.h>
62#include <fcntl.h>
63#include <ctype.h>
64#include <libintl.h>
65
66
67#ifndef S_IFMT
68# define S_IFMT 0170000
69#endif
70#if !defined(S_ISBLK) && defined(S_IFBLK)
71# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
72#endif
73#if !defined(S_ISCHR) && defined(S_IFCHR)
74# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
75#endif
76#if !defined(S_ISDIR) && defined(S_IFDIR)
77# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
78#endif
79#if !defined(S_ISREG) && defined(S_IFREG)
80# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
81#endif
82#if !defined(S_ISFIFO) && defined(S_IFIFO)
83# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
84#endif
85#if !defined(S_ISLNK) && defined(S_IFLNK)
86# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
87#endif
88#if !defined(S_ISSOCK) && defined(S_IFSOCK)
89# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
90#endif
91#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
92# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
93# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
94#endif
95#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
96# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
97#endif
98
99#define IN_CTYPE_DOMAIN(c) 1
100
101#ifdef isblank
102# define ISBLANK(c) (IN_CTYPE_DOMAIN (c) && isblank (c))
103#else
104# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
105#endif
106#ifdef isgraph
107# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isgraph (c))
108#else
109# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isprint (c) && !isspace (c))
110#endif
111
112#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
113#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c))
114#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
115#define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (c))
116#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c))
117#define ISPUNCT(c) (IN_CTYPE_DOMAIN (c) && ispunct (c))
118#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
119#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c))
120#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c))
121#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
122#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
123
124#define isodigit(c) ((c) >= '0' && (c) <= '7')
125#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
126#define octtobin(c) ((c) - '0')
127
128char *xmalloc ();
129
130static double xstrtod __P ((char *s));
131static int print_esc __P ((char *escstart));
132static int print_formatted __P ((char *format, int argc, char **argv));
133static long xstrtol __P ((char *s));
134static unsigned long xstrtoul __P ((char *s));
135static void print_direc __P ((char *start, size_t length, int field_width, int precision, char *argument));
136static void print_esc_char __P ((int c));
137static void print_esc_string __P ((char *str));
138static void verify __P ((char *s, char *end));
139
140/* The value to return to the calling program. */
141static int exit_status;
142
143const char printf_usage[] = "Usage: printf format [argument...]\n";
144
145int
146printf_main(struct FileInfo * i, int argc, char * * argv)
147{
148 char *format;
149 int args_used;
150
151 exit_status = 0;
152
153 format = argv[1];
154 argc -= 2;
155 argv += 2;
156
157 do
158 {
159 args_used = print_formatted (format, argc, argv);
160 argc -= args_used;
161 argv += args_used;
162 }
163 while (args_used > 0 && argc > 0);
164
165/*
166 if (argc > 0)
167 fprintf(stderr, "excess args ignored");
168*/
169
170 exit (exit_status);
171}
172
173/* Print the text in FORMAT, using ARGV (with ARGC elements) for
174 arguments to any `%' directives.
175 Return the number of elements of ARGV used. */
176
177static int
178print_formatted (char *format, int argc, char **argv)
179{
180 int save_argc = argc; /* Preserve original value. */
181 char *f; /* Pointer into `format'. */
182 char *direc_start; /* Start of % directive. */
183 size_t direc_length; /* Length of % directive. */
184 int field_width; /* Arg to first '*', or -1 if none. */
185 int precision; /* Arg to second '*', or -1 if none. */
186
187 for (f = format; *f; ++f)
188 {
189 switch (*f)
190 {
191 case '%':
192 direc_start = f++;
193 direc_length = 1;
194 field_width = precision = -1;
195 if (*f == '%')
196 {
197 putchar ('%');
198 break;
199 }
200 if (*f == 'b')
201 {
202 if (argc > 0)
203 {
204 print_esc_string (*argv);
205 ++argv;
206 --argc;
207 }
208 break;
209 }
210 if (strchr ("-+ #", *f))
211 {
212 ++f;
213 ++direc_length;
214 }
215 if (*f == '*')
216 {
217 ++f;
218 ++direc_length;
219 if (argc > 0)
220 {
221 field_width = xstrtoul (*argv);
222 ++argv;
223 --argc;
224 }
225 else
226 field_width = 0;
227 }
228 else
229 while (ISDIGIT (*f))
230 {
231 ++f;
232 ++direc_length;
233 }
234 if (*f == '.')
235 {
236 ++f;
237 ++direc_length;
238 if (*f == '*')
239 {
240 ++f;
241 ++direc_length;
242 if (argc > 0)
243 {
244 precision = xstrtoul (*argv);
245 ++argv;
246 --argc;
247 }
248 else
249 precision = 0;
250 }
251 else
252 while (ISDIGIT (*f))
253 {
254 ++f;
255 ++direc_length;
256 }
257 }
258 if (*f == 'l' || *f == 'L' || *f == 'h')
259 {
260 ++f;
261 ++direc_length;
262 }
263 /*
264 if (!strchr ("diouxXfeEgGcs", *f))
265 fprintf(stderr, "%%%c: invalid directive", *f);
266 */
267 ++direc_length;
268 if (argc > 0)
269 {
270 print_direc (direc_start, direc_length, field_width,
271 precision, *argv);
272 ++argv;
273 --argc;
274 }
275 else
276 print_direc (direc_start, direc_length, field_width,
277 precision, "");
278 break;
279
280 case '\\':
281 f += print_esc (f);
282 break;
283
284 default:
285 putchar (*f);
286 }
287 }
288
289 return save_argc - argc;
290}
291
292/* Print a \ escape sequence starting at ESCSTART.
293 Return the number of characters in the escape sequence
294 besides the backslash. */
295
296static int
297print_esc (char *escstart)
298{
299 register char *p = escstart + 1;
300 int esc_value = 0; /* Value of \nnn escape. */
301 int esc_length; /* Length of \nnn escape. */
302
303 /* \0ooo and \xhhh escapes have maximum length of 3 chars. */
304 if (*p == 'x')
305 {
306 for (esc_length = 0, ++p;
307 esc_length < 3 && ISXDIGIT (*p);
308 ++esc_length, ++p)
309 esc_value = esc_value * 16 + hextobin (*p);
310/* if (esc_length == 0)
311 fprintf(stderr, "missing hex in esc");
312*/
313 putchar (esc_value);
314 }
315 else if (*p == '0')
316 {
317 for (esc_length = 0, ++p;
318 esc_length < 3 && isodigit (*p);
319 ++esc_length, ++p)
320 esc_value = esc_value * 8 + octtobin (*p);
321 putchar (esc_value);
322 }
323 else if (strchr ("\"\\abcfnrtv", *p))
324 print_esc_char (*p++);
325/* else
326 fprintf(stderr, "\\%c: invalid esc", *p);
327*/
328 return p - escstart - 1;
329}
330
331/* Output a single-character \ escape. */
332
333static void
334print_esc_char (int c)
335{
336 switch (c)
337 {
338 case 'a': /* Alert. */
339 putchar (7);
340 break;
341 case 'b': /* Backspace. */
342 putchar (8);
343 break;
344 case 'c': /* Cancel the rest of the output. */
345 exit (0);
346 break;
347 case 'f': /* Form feed. */
348 putchar (12);
349 break;
350 case 'n': /* New line. */
351 putchar (10);
352 break;
353 case 'r': /* Carriage return. */
354 putchar (13);
355 break;
356 case 't': /* Horizontal tab. */
357 putchar (9);
358 break;
359 case 'v': /* Vertical tab. */
360 putchar (11);
361 break;
362 default:
363 putchar (c);
364 break;
365 }
366}
367
368/* Print string STR, evaluating \ escapes. */
369
370static void
371print_esc_string (char *str)
372{
373 for (; *str; str++)
374 if (*str == '\\')
375 str += print_esc (str);
376 else
377 putchar (*str);
378}
379
380static void
381print_direc (char *start, size_t length, int field_width, int precision, char *argument)
382{
383 char *p; /* Null-terminated copy of % directive. */
384
385 p = xmalloc ((unsigned) (length + 1));
386 strncpy (p, start, length);
387 p[length] = 0;
388
389 switch (p[length - 1])
390 {
391 case 'd':
392 case 'i':
393 if (field_width < 0)
394 {
395 if (precision < 0)
396 printf (p, xstrtol (argument));
397 else
398 printf (p, precision, xstrtol (argument));
399 }
400 else
401 {
402 if (precision < 0)
403 printf (p, field_width, xstrtol (argument));
404 else
405 printf (p, field_width, precision, xstrtol (argument));
406 }
407 break;
408
409 case 'o':
410 case 'u':
411 case 'x':
412 case 'X':
413 if (field_width < 0)
414 {
415 if (precision < 0)
416 printf (p, xstrtoul (argument));
417 else
418 printf (p, precision, xstrtoul (argument));
419 }
420 else
421 {
422 if (precision < 0)
423 printf (p, field_width, xstrtoul (argument));
424 else
425 printf (p, field_width, precision, xstrtoul (argument));
426 }
427 break;
428
429 case 'f':
430 case 'e':
431 case 'E':
432 case 'g':
433 case 'G':
434 if (field_width < 0)
435 {
436 if (precision < 0)
437 printf (p, xstrtod (argument));
438 else
439 printf (p, precision, xstrtod (argument));
440 }
441 else
442 {
443 if (precision < 0)
444 printf (p, field_width, xstrtod (argument));
445 else
446 printf (p, field_width, precision, xstrtod (argument));
447 }
448 break;
449
450 case 'c':
451 printf (p, *argument);
452 break;
453
454 case 's':
455 if (field_width < 0)
456 {
457 if (precision < 0)
458 printf (p, argument);
459 else
460 printf (p, precision, argument);
461 }
462 else
463 {
464 if (precision < 0)
465 printf (p, field_width, argument);
466 else
467 printf (p, field_width, precision, argument);
468 }
469 break;
470 }
471
472 free (p);
473}
474
475static unsigned long
476xstrtoul (char *s)
477{
478 char *end;
479 unsigned long val;
480
481 errno = 0;
482 val = strtoul (s, &end, 0);
483 verify (s, end);
484 return val;
485}
486
487static long
488xstrtol (char *s)
489{
490 char *end;
491 long val;
492
493 errno = 0;
494 val = strtol (s, &end, 0);
495 verify (s, end);
496 return val;
497}
498
499static double
500xstrtod (char *s)
501{
502 char *end;
503 double val;
504
505 errno = 0;
506 val = strtod (s, &end);
507 verify (s, end);
508 return val;
509}
510
511static void
512verify (char *s, char *end)
513{
514 if (errno)
515 {
516 fprintf(stderr, "%s", s);
517 exit_status = 1;
518 }
519 else if (*end)
520 {
521 /*
522 if (s == end)
523 fprintf(stderr, "%s: expected numeric", s);
524 else
525 fprintf(stderr, "%s: not completely converted", s);
526 */
527 exit_status = 1;
528 }
529}
530
531#endif
diff --git a/coreutils/pwd.c b/coreutils/pwd.c
new file mode 100644
index 000000000..d9ab54e48
--- /dev/null
+++ b/coreutils/pwd.c
@@ -0,0 +1,18 @@
1#include "internal.h"
2#include <stdio.h>
3
4const char pwd_usage[] = "Print the current directory.\n";
5
6extern int
7pwd_main(struct FileInfo * i, int argc, char * * argv)
8{
9 char buf[1024];
10
11 if ( getcwd(buf, sizeof(buf)) == NULL ) {
12 name_and_error("get working directory");
13 return 1;
14 }
15
16 printf("%s\n", buf);
17 return 0;
18}
diff --git a/coreutils/rm.c b/coreutils/rm.c
new file mode 100644
index 000000000..dc35b0297
--- /dev/null
+++ b/coreutils/rm.c
@@ -0,0 +1,30 @@
1#include "internal.h"
2#include <errno.h>
3
4const char rm_usage[] = "rm [-r] file [file ...]\n"
5"\n"
6"\tDelete files.\n"
7"\n"
8"\t-r:\tRecursively remove files and directories.\n";
9
10extern int
11rm_main(struct FileInfo * i, int argc, char * * argv)
12{
13 i->processDirectoriesAfterTheirContents = 1;
14 return monadic_main(i, argc, argv);
15}
16
17extern int
18rm_fn(const struct FileInfo * i)
19{
20 if ( i->recursive
21 && !i->isSymbolicLink
22 && (i->stat.st_mode & S_IFMT) == S_IFDIR )
23 return rmdir_fn(i);
24 else if ( unlink(i->source) != 0 && errno != ENOENT && !i->force ) {
25 name_and_error(i->source);
26 return 1;
27 }
28 else
29 return 0;
30}
diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c
new file mode 100644
index 000000000..069e68546
--- /dev/null
+++ b/coreutils/rmdir.c
@@ -0,0 +1,17 @@
1#include "internal.h"
2#include <errno.h>
3
4const char rmdir_usage[] = "rmdir directory [directory ...]\n"
5"\n"
6"\tDelete directories.\n";
7
8extern int
9rmdir_fn(const struct FileInfo * i)
10{
11 if ( rmdir(i->source) != 0 && errno != ENOENT && !i->force ) {
12 name_and_error(i->source);
13 return 1;
14 }
15 else
16 return 0;
17}
diff --git a/coreutils/sleep.c b/coreutils/sleep.c
new file mode 100644
index 000000000..e48e14b2f
--- /dev/null
+++ b/coreutils/sleep.c
@@ -0,0 +1,15 @@
1#include "internal.h"
2#include <stdio.h>
3
4const char sleep_usage[] = "sleep seconds\n"
5"\n"
6"\tPause program execution for the given number of seconds.\n";
7
8extern int
9sleep_main(struct FileInfo * i, int argc, char * * argv)
10{
11 if ( sleep(atoi(argv[1])) != 0 )
12 return -1;
13 else
14 return 0;
15}
diff --git a/coreutils/sync.c b/coreutils/sync.c
new file mode 100644
index 000000000..6fa5b380b
--- /dev/null
+++ b/coreutils/sync.c
@@ -0,0 +1,11 @@
1#include "internal.h"
2
3const char sync_usage[] = "sync\n"
4"\n"
5"\tWrite all buffered filesystem blocks to disk.\n";
6
7extern int
8sync_main(struct FileInfo * i, int argc, char * * argv)
9{
10 return sync();
11}
diff --git a/coreutils/touch.c b/coreutils/touch.c
new file mode 100644
index 000000000..ca4b98108
--- /dev/null
+++ b/coreutils/touch.c
@@ -0,0 +1,20 @@
1#include "internal.h"
2#include <sys/types.h>
3#include <stdio.h>
4#include <utime.h>
5
6const char touch_usage[] = "touch [-c] file [file ...]\n"
7"\n"
8"\tUpdate the last-modified date on the given file[s].\n";
9
10extern int
11touch_fn(const struct FileInfo * i)
12{
13 if ( (utime(i->source, 0) != 0) && (i->create != 1) ) {
14 if ( fopen(i->source, "w") == NULL ) {
15 name_and_error(i->source);
16 return 1;
17 }
18 }
19 return 0;
20}