aboutsummaryrefslogtreecommitdiff
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 @@
+/*
+ * Mini Cat implementation for busybox
+ *
+ * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "internal.h"
+#include <stdio.h>
+
+const char cat_usage[] = "[file ...]";
+
+extern int cat_more_main(int argc, char **argv)
+{
+ int c;
+ FILE *file = stdin;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s %s", *argv, cat_usage);
+ return 1;
+ }
+ argc--;
+ argv++;
+
+ while (argc-- > 0) {
+ file = fopen(*argv, "r");
+ if (file == NULL) {
+ name_and_error(*argv);
+ return 1;
+ }
+ while ((c = getc(file)) != EOF)
+ putc(c, stdout);
+ fclose(file);
+ fflush(stdout);
+
+ argc--;
+ argv++;
+ }
+ return 0;
+}
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 @@
+/*
+ * Mini chgrp implementation for busybox
+ *
+ * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "internal.h"
+#include <grp.h>
+#include <stdio.h>
+
+const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n"
+ "Change the group membership of each FILE to GROUP.\n"
+ "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
+
+int chgrp_main(int argc, char **argv)
+{
+ const char *cp;
+ int gid;
+ struct group *grp;
+ struct stat statBuf;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s %s", *argv, chgrp_usage);
+ return 1;
+ }
+ argc--;
+ argv++;
+
+ cp = argv[1];
+ if (isDecimal(*cp)) {
+ gid = 0;
+ while (isDecimal(*cp))
+ gid = gid * 10 + (*cp++ - '0');
+ if (*cp) {
+ fprintf(stderr, "Bad gid value\n");
+ return -1;
+ }
+ } else {
+ grp = getgrnam(cp);
+ if (grp == NULL) {
+ fprintf(stderr, "Unknown group name\n");
+ return -1;
+ }
+ gid = grp->gr_gid;
+ }
+ argc--;
+ argv++;
+ while (argc-- > 1) {
+ argv++;
+ if ((stat(*argv, &statBuf) < 0) ||
+ (chown(*argv, statBuf.st_uid, gid) < 0)) {
+ perror(*argv);
+ }
+ }
+ return 1;
+}
+
+
+
+
+
+
+
+
+
+#if 0
+int
+recursive(const char *fileName, BOOL followLinks, const char *pattern,
+ int (*fileAction) (const char *fileName,
+ const struct stat * statbuf),
+ int (*dirAction) (const char *fileName,
+ const struct stat * statbuf))
+
+#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 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "internal.h"
+
+const char chmod_usage[] = "chmod [-R] mode file [file ...]\n"
+"\nmode may be an octal integer representing the bit pattern for the\n"
+"\tnew mode, or a symbolic value matching the pattern\n"
+"\t[ugoa]{+|-|=}[rwxst] .\n"
+"\t\tu:\tUser\n"
+"\t\tg:\tGroup\n"
+"\t\to:\tOthers\n"
+"\t\ta:\tAll\n"
+"\n"
+"\n+:\tAdd privilege\n"
+"\n-:\tRemove privilege\n"
+"\n=:\tSet privilege\n"
+"\n"
+"\t\tr:\tRead\n"
+"\t\tw:\tWrite\n"
+"\t\tx:\tExecute\n"
+"\t\ts:\tSet User ID\n"
+"\t\tt:\t\"Sticky\" Text\n"
+"\n"
+"\tModes may be concatenated, as in \"u=rwx,g=rx,o=rx,-t,-s\n"
+"\n"
+"\t-R:\tRecursively change the mode of all files and directories\n"
+"\t\tunder the argument directory.";
+
+int
+parse_mode(
+ const char * s
+,mode_t * or
+,mode_t * and
+,int * group_execute)
+{
+ /* [ugoa]{+|-|=}[rwxstl] */
+ mode_t mode = 0;
+ mode_t groups = S_ISVTX;
+ char type;
+ char c;
+
+ do {
+ for ( ; ; ) {
+ switch ( c = *s++ ) {
+ case '\0':
+ return -1;
+ case 'u':
+ groups |= S_ISUID|S_IRWXU;
+ continue;
+ case 'g':
+ groups |= S_ISGID|S_IRWXG;
+ continue;
+ case 'o':
+ groups |= S_IRWXO;
+ continue;
+ case 'a':
+ groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+ continue;
+ case '+':
+ case '=':
+ case '-':
+ type = c;
+ if ( groups == S_ISVTX ) /* The default is "all" */
+ groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+ break;
+ default:
+ if ( c >= '0' && c <= '7' && mode == 0 && groups == S_ISVTX ) {
+ *and = 0;
+ *or = strtol(--s, 0, 010);
+ return 0;
+ }
+ else
+ return -1;
+ }
+ break;
+ }
+
+ while ( (c = *s++) != '\0' ) {
+ switch ( c ) {
+ case ',':
+ break;
+ case 'r':
+ mode |= S_IRUSR|S_IRGRP|S_IROTH;
+ continue;
+ case 'w':
+ mode |= S_IWUSR|S_IWGRP|S_IWOTH;
+ continue;
+ case 'x':
+ mode |= S_IXUSR|S_IXGRP|S_IXOTH;
+ continue;
+ case 's':
+ if ( group_execute != 0 && (groups & S_IRWXG) ) {
+ if ( *group_execute < 0 )
+ return -1;
+ if ( type != '-' ) {
+ mode |= S_IXGRP;
+ *group_execute = 1;
+ }
+ }
+ mode |= S_ISUID|S_ISGID;
+ continue;
+ case 'l':
+ if ( *group_execute > 0 )
+ return -1;
+ if ( type != '-' ) {
+ *and &= ~S_IXGRP;
+ *group_execute = -1;
+ }
+ mode |= S_ISGID;
+ groups |= S_ISGID;
+ continue;
+ case 't':
+ mode |= S_ISVTX;
+ continue;
+ default:
+ return -1;
+ }
+ break;
+ }
+ switch ( type ) {
+ case '=':
+ *and &= ~(groups);
+ /* fall through */
+ case '+':
+ *or |= mode & groups;
+ break;
+ case '-':
+ *and &= ~(mode & groups);
+ *or &= *and;
+ break;
+ }
+ } while ( c == ',' );
+ return 0;
+}
+
+extern int
+chmod_main(struct FileInfo * i, int argc, char * * argv)
+{
+ i->andWithMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+ i->orWithMode = 0;
+
+ while ( argc >= 3 ) {
+ if ( parse_mode(argv[1], &i->orWithMode, &i->andWithMode, 0)
+ == 0 ) {
+ argc--;
+ argv++;
+ }
+ else if ( strcmp(argv[1], "-R") == 0 ) {
+ i->recursive = 1;
+ argc--;
+ argv++;
+ }
+ else
+ break;
+ }
+
+ i->changeMode = 1;
+ i->complainInPostProcess = 1;
+
+ return monadic_main(i, argc, argv);
+}
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 @@
+#include "internal.h"
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <stdio.h>
+
+const char chown_usage[] = "chown [-R] user-name file [file ...]\n"
+"\n\tThe group list is kept in the file /etc/groups.\n\n"
+"\t-R:\tRecursively change the mode of all files and directories\n"
+"\t\tunder the argument directory.";
+
+int
+parse_user_name(const char * s, struct FileInfo * i)
+{
+ struct passwd * p;
+ char * dot = strchr(s, '.');
+
+ if (! dot )
+ dot = strchr(s, ':');
+
+ if ( dot )
+ *dot = '\0';
+
+ if ( (p = getpwnam(s)) == 0 ) {
+ fprintf(stderr, "%s: no such user.\n", s);
+ return 1;
+ }
+ i->userID = p->pw_uid;
+
+ if ( dot ) {
+ struct group * g = getgrnam(++dot);
+ if ( g == 0 ) {
+ fprintf(stderr, "%s: no such group.\n", dot);
+ return 1;
+ }
+ i->groupID = g->gr_gid;
+ i->changeGroupID = 1;
+ }
+ return 0;
+}
+
+extern int
+chown_main(struct FileInfo * i, int argc, char * * argv)
+{
+ int status;
+
+ while ( argc >= 3 && strcmp("-R", argv[1]) == 0 ) {
+ i->recursive = 1;
+ argc--;
+ argv++;
+ }
+
+ if ( (status = parse_user_name(argv[1], i)) != 0 )
+ return status;
+
+ argv++;
+ argc--;
+
+ i->changeUserID = 1;
+ i->complainInPostProcess = 1;
+
+ return monadic_main(i, argc, argv);
+}
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 @@
+#include "internal.h"
+#include <stdio.h>
+#include <unistd.h>
+
+
+const char chroot_usage[] = "chroot directory [command]\n"
+ "Run a command with special root directory.\n";
+
+extern int
+chroot_main (struct FileInfo *i, int argc, char **argv)
+{
+ char *prog;
+
+ if (chroot (argv[1]))
+ {
+ name_and_error ("cannot chroot to that directory");
+ return 1;
+ }
+ if (argc > 2)
+ {
+ execvp (argv[2], argv + 2);
+ }
+ else
+ {
+ prog = getenv ("SHELL");
+ if (!prog)
+ prog = "/bin/sh";
+ execlp (prog, prog, NULL);
+ }
+ name_and_error ("cannot exec");
+ return 1;
+}
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 @@
+#include "internal.h"
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/param.h>
+#include <errno.h>
+
+const char cp_usage[] = "cp [-r] source-file destination-file\n"
+"\t\tcp [-r] source-file [source-file ...] destination-directory\n"
+"\n"
+"\tCopy the source files to the destination.\n"
+"\n"
+"\t-r:\tRecursively copy all files and directories\n"
+"\t\tunder the argument directory.";
+
+extern int
+cp_fn(const struct FileInfo * i)
+{
+ int sourceFd;
+ int destinationFd;
+ const char * destination = i->destination;
+ struct stat destination_stat;
+ int status;
+ char buf[8192];
+ char d[PATH_MAX];
+
+ if ( (i->stat.st_mode & S_IFMT) == S_IFDIR ) {
+ if ( mkdir(destination, i->stat.st_mode & ~S_IFMT)
+ != 0 && errno != EEXIST ) {
+ name_and_error(destination);
+ return 1;
+ }
+ return 0;
+ }
+ if ( (sourceFd = open(i->source, O_RDONLY)) < 0 ) {
+ name_and_error(i->source);
+ return 1;
+ }
+ if ( stat(destination, &destination_stat) == 0 ) {
+ if ( i->stat.st_ino == destination_stat.st_ino
+ && i->stat.st_dev == destination_stat.st_dev ) {
+ fprintf(stderr
+ ,"copy of %s to %s would copy file to itself.\n"
+ ,i->source
+ ,destination);
+ close(sourceFd);
+ return 1;
+ }
+ }
+ /*
+ * If the destination is a directory, create a file within it.
+ */
+ if ( (destination_stat.st_mode & S_IFMT) == S_IFDIR ) {
+ destination = join_paths(
+ d
+ ,i->destination
+ ,&i->source[i->directoryLength]);
+
+ if ( stat(destination, &destination_stat) == 0 ) {
+ if ( i->stat.st_ino == destination_stat.st_ino
+ && i->stat.st_dev == destination_stat.st_dev ) {
+ fprintf(stderr
+ ,"copy of %s to %s would copy file to itself.\n"
+ ,i->source
+ ,destination);
+ close(sourceFd);
+ return 1;
+ }
+ }
+ }
+
+ destinationFd = creat(destination, i->stat.st_mode & 07777);
+
+ while ( (status = read(sourceFd, buf, sizeof(buf))) > 0 ) {
+ if ( write(destinationFd, buf, status) != status ) {
+ name_and_error(destination);
+ close(sourceFd);
+ close(destinationFd);
+ return 1;
+ }
+ }
+ close(sourceFd);
+ close(destinationFd);
+ if ( status < 0 ) {
+ name_and_error(i->source);
+ return 1;
+ }
+ return 0;
+}
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 @@
+#include "internal.h"
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdio.h>
+#include <getopt.h>
+
+
+/* This 'date' command supports only 2 time setting formats,
+ all the GNU strftime stuff (its in libc, lets use it),
+ setting time using UTC and displaying int, as well as
+ an RFC 822 complient date output for shell scripting
+ mail commands */
+
+const char date_usage[] = "date [-uR] [+FORMAT|+%f] [ [-s|-d] MMDDhhmm[[CC]YY]\n | [[[[CCYY.]MM.DD-]hh:mm[:ss]]]] ]";
+
+static struct option const long_options[] =
+{
+ {"date", required_argument, NULL, 'd'},
+ /* {"rfc-822", no_argument, NULL, 'R'},
+ {"set", required_argument, NULL, 's'},
+ {"uct", no_argument, NULL, 'u'},
+ {"utc", no_argument, NULL, 'u'},
+ {"universal", no_argument, NULL, 'u'}, */
+ {NULL, 0, NULL, 0}
+};
+
+
+
+/* Input parsing code is always bulky - used heavy duty libc stuff as
+ much as possible, missed out a lot of bounds checking */
+
+/* Default input handling to save suprising some people */
+
+struct tm *
+date_conv_time(struct tm *tm_time, const char *t_string) {
+ int nr;
+
+ nr = sscanf(t_string, "%2d%2d%2d%2d%d",
+ &(tm_time->tm_mon),
+ &(tm_time->tm_mday),
+ &(tm_time->tm_hour),
+ &(tm_time->tm_min),
+ &(tm_time->tm_year));
+
+ if(nr < 4 || nr > 5) {
+ fprintf(stderr, "date: invalid date `%s'\n", t_string);
+ exit(1);
+ }
+
+ /* correct for century - minor Y2K problem here? */
+ if(tm_time->tm_year >= 1900)
+ tm_time->tm_year -= 1900;
+ /* adjust date */
+ tm_time->tm_mon -= 1;
+
+ return(tm_time);
+
+}
+
+
+/* The new stuff for LRP */
+
+struct tm *
+date_conv_ftime(struct tm *tm_time, const char *t_string) {
+ struct tm itm_time, jtm_time, ktm_time, \
+ ltm_time, mtm_time, ntm_time;
+
+ itm_time = *tm_time;
+ jtm_time = *tm_time;
+ ktm_time = *tm_time;
+ ltm_time = *tm_time;
+ mtm_time = *tm_time;
+ ntm_time = *tm_time;
+
+ /* Parse input and assign appropriately to tm_time */
+
+ if(sscanf(t_string, "%d:%d:%d",
+ &itm_time.tm_hour,
+ &itm_time.tm_min,
+ &itm_time.tm_sec) == 3 ) {
+
+ *tm_time = itm_time;
+ return(tm_time);
+
+ } else if (sscanf(t_string, "%d:%d",
+ &jtm_time.tm_hour,
+ &jtm_time.tm_min) == 2) {
+
+ *tm_time = jtm_time;
+ return(tm_time);
+
+ } else if (sscanf(t_string, "%d.%d-%d:%d:%d",
+ &ktm_time.tm_mon,
+ &ktm_time.tm_mday,
+ &ktm_time.tm_hour,
+ &ktm_time.tm_min,
+ &ktm_time.tm_sec) == 5) {
+
+ ktm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
+ *tm_time = ktm_time;
+ return(tm_time);
+
+ } else if (sscanf(t_string, "%d.%d-%d:%d",
+ &ltm_time.tm_mon,
+ &ltm_time.tm_mday,
+ &ltm_time.tm_hour,
+ &ltm_time.tm_min) == 4) {
+
+ ltm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
+ *tm_time = ltm_time;
+ return(tm_time);
+
+ } else if (sscanf(t_string, "%d.%d.%d-%d:%d:%d",
+ &mtm_time.tm_year,
+ &mtm_time.tm_mon,
+ &mtm_time.tm_mday,
+ &mtm_time.tm_hour,
+ &mtm_time.tm_min,
+ &mtm_time.tm_sec) == 6) {
+
+ mtm_time.tm_year -= 1900; /* Adjust years */
+ mtm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
+ *tm_time = mtm_time;
+ return(tm_time);
+
+ } else if (sscanf(t_string, "%d.%d.%d-%d:%d",
+ &ntm_time.tm_year,
+ &ntm_time.tm_mon,
+ &ntm_time.tm_mday,
+ &ntm_time.tm_hour,
+ &ntm_time.tm_min) == 5) {
+ ntm_time.tm_year -= 1900; /* Adjust years */
+ ntm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
+ *tm_time = ntm_time;
+ return(tm_time);
+
+ }
+
+ fprintf(stderr, "date: invalid date `%s'\n", t_string);
+
+ exit(1);
+
+}
+
+
+void
+date_err(void) {
+ fprintf(stderr, "date: only one date argument can be given at a time.\n");
+ exit(1);
+}
+
+int
+date_main(struct FileInfo * i, int argc, char * * argv)
+{
+ char *date_str = NULL;
+ char *date_fmt = NULL;
+ char *t_buff;
+ int set_time = 0;
+ int rfc822 = 0;
+ int utc = 0;
+ int use_arg = 0;
+ int n_args;
+ time_t tm;
+ struct tm tm_time;
+ char optc;
+
+ /* Interpret command line args */
+
+
+ while ((optc = getopt_long (argc, argv, "d:Rs:u", long_options, NULL))
+ != EOF) {
+ switch (optc) {
+ case 0:
+ break;
+
+ case 'R':
+ rfc822 = 1;
+ break;
+
+ case 's':
+ set_time = 1;
+ if(date_str != NULL) date_err();
+ date_str = optarg;
+ break;
+
+ case 'u':
+ utc = 1;
+ if (putenv ("TZ=UTC0") != 0) {
+ fprintf(stderr,"date: memory exhausted\n");
+ return(1);
+ }
+#if LOCALTIME_CACHE
+ tzset ();
+#endif break;
+
+ case 'd':
+ use_arg = 1;
+ if(date_str != NULL) date_err();
+ date_str = optarg;
+ break;
+
+ default:
+ usage(date_usage);
+ break;
+ }
+ }
+
+
+ n_args = argc - optind;
+
+ while (n_args--){
+ switch(argv[optind][0]) {
+ case '+':
+ /* Date format strings */
+ if(date_fmt != NULL) {
+ fprintf(stderr, "date: only one date format can be given.\n");
+ return(1);
+ }
+ date_fmt = &argv[optind][1];
+ break;
+
+ case '\0':
+ break;
+
+ default:
+ /* Anything left over must be a date string to set the time */
+ set_time = 1;
+ if(date_str != NULL) date_err();
+ date_str = argv[optind];
+ break;
+ }
+ optind++;
+ }
+
+
+ /* Now we have parsed all the information except the date format
+ which depends on whether the clock is being set or read */
+
+ time(&tm);
+ memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
+ /* Zero out fields - take her back to midnight!*/
+ if(date_str != NULL) {
+ tm_time.tm_sec = 0;
+ tm_time.tm_min = 0;
+ tm_time.tm_hour = 0;
+ }
+
+ /* Process any date input to UNIX time since 1 Jan 1970 */
+ if(date_str != NULL) {
+
+ if(strchr(date_str, ':') != NULL) {
+ date_conv_ftime(&tm_time, date_str);
+ } else {
+ date_conv_time(&tm_time, date_str);
+ }
+
+ /* Correct any day of week and day of year etc fields */
+ tm = mktime(&tm_time);
+ if (tm < 0 ) {
+ fprintf(stderr, "date: invalid date `%s'\n", date_str);
+ exit(1);
+ }
+
+ /* if setting time, set it */
+ if(set_time) {
+ if( stime(&tm) < 0) {
+ fprintf(stderr, "date: can't set date.\n");
+ exit(1);
+ }
+ }
+ }
+
+ /* Display output */
+
+ /* Deal with format string */
+ if(date_fmt == NULL) {
+ date_fmt = (rfc822
+ ? (utc
+ ? "%a, %_d %b %Y %H:%M:%S GMT"
+ : "%a, %_d %b %Y %H:%M:%S %z")
+ : "%a %b %e %H:%M:%S %Z %Y");
+
+ } else if ( *date_fmt == '\0' ) {
+ /* Imitate what GNU 'date' does with NO format string! */
+ printf ("\n");
+ return(0);
+ }
+
+ /* Handle special conversions */
+
+ if( strncmp( date_fmt, "%f", 2) == 0 ) {
+ date_fmt = "%Y.%m.%d-%H:%M:%S";
+ }
+
+ /* Print OUTPUT (after ALL that!) */
+ t_buff = malloc(201);
+ strftime(t_buff, 200, date_fmt, &tm_time);
+ printf("%s\n", t_buff);
+
+ return(0);
+
+}
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 @@
+/*
+ * Copyright (c) 1999 by David I. Bell
+ * Permission is granted to use, distribute, or modify this source,
+ * provided that this copyright notice remains intact.
+ *
+ * The "dd" command, originally taken from sash.
+ *
+ * Permission to distribute this code under the GPL has been granted.
+ * Majorly modified, and bugs fixed for busybox by Erik Andersen <andersee@debian.org> <andersen@lineo.com>
+ */
+
+#include "internal.h"
+#ifdef BB_DD
+
+const char dd_usage[] =
+"Copy a file, converting and formatting according to options\n\
+\n\
+usage: [if=name] [of=name] [bs=n] [count=n]\n\
+\tif=FILE\tread from FILE instead of stdin\n\
+\tof=FILE\twrite to FILE instead of stout\n\
+\tbs=n\tread and write N bytes at a time\n\
+\tcount=n\tcopy only n input blocks\n\
+\n\
+BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n";
+
+
+#include <stdio.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <time.h>
+
+
+#define PAR_NONE 0
+#define PAR_IF 1
+#define PAR_OF 2
+#define PAR_BS 3
+#define PAR_COUNT 4
+
+
+typedef struct
+{
+ const char * name;
+ int value;
+} PARAM;
+
+
+static const PARAM params[] =
+{
+ {"if", PAR_IF},
+ {"of", PAR_OF},
+ {"bs", PAR_BS},
+ {"count", PAR_COUNT},
+ {NULL, PAR_NONE}
+};
+
+
+static long getNum(const char * cp);
+
+extern int
+dd_main (struct FileInfo *unused, int argc, char **argv)
+{
+ const char * str;
+ const PARAM * par;
+ const char * inFile;
+ const char * outFile;
+ char * cp;
+ int inFd;
+ int outFd;
+ int inCc=0;
+ int outCc;
+ int blockSize;
+ long count;
+ long intotal;
+ long outTotal;
+ unsigned char* buf;
+ unsigned char localBuf[BUF_SIZE];
+
+ inFile = NULL;
+ outFile = NULL;
+ blockSize = 512;
+ count = 1;
+
+
+ while (--argc > 0)
+ {
+ str = *++argv;
+ cp = strchr(str, '=');
+
+ if (cp == NULL)
+ {
+ fprintf(stderr, "Bad dd argument\n");
+ goto usage;
+ }
+
+ *cp++ = '\0';
+
+ for (par = params; par->name; par++)
+ {
+ if (strcmp(str, par->name) == 0)
+ break;
+ }
+
+ switch (par->value)
+ {
+ case PAR_IF:
+ if (inFile)
+ {
+ fprintf(stderr, "Multiple input files illegal\n");
+ goto usage;
+ }
+
+ //fprintf(stderr, "if=%s\n", cp);
+ inFile = cp;
+ break;
+
+ case PAR_OF:
+ if (outFile)
+ {
+ fprintf(stderr, "Multiple output files illegal\n");
+ goto usage;
+ }
+
+ //fprintf(stderr, "of=%s\n", cp);
+ outFile = cp;
+ break;
+
+ case PAR_BS:
+ blockSize = getNum(cp);
+ //fprintf(stderr, "bs=%d\n", blockSize);
+
+ if (blockSize <= 0)
+ {
+ fprintf(stderr, "Bad block size value\n");
+ goto usage;
+ }
+
+ break;
+
+ case PAR_COUNT:
+ count = getNum(cp);
+ //fprintf(stderr, "count=%ld\n", count);
+
+ if (count < 0)
+ {
+ fprintf(stderr, "Bad count value\n");
+ goto usage;
+ }
+
+ break;
+
+ default:
+ goto usage;
+ }
+ }
+
+ buf = localBuf;
+
+ if (blockSize > sizeof(localBuf))
+ {
+ buf = malloc(blockSize);
+
+ if (buf == NULL)
+ {
+ fprintf(stderr, "Cannot allocate buffer\n");
+ return 1;
+ }
+ }
+
+ intotal = 0;
+ outTotal = 0;
+
+ if (inFile == NULL)
+ inFd = STDIN;
+ else
+ inFd = open(inFile, 0);
+
+ if (inFd < 0)
+ {
+ perror(inFile);
+
+ if (buf != localBuf)
+ free(buf);
+
+ return 1;
+ }
+
+ if (outFile == NULL)
+ outFd = STDOUT;
+ else
+ outFd = creat(outFile, 0666);
+
+ if (outFd < 0)
+ {
+ perror(outFile);
+ close(inFd);
+
+ if (buf != localBuf)
+ free(buf);
+
+ return 1;
+ }
+
+ while ( outTotal < count*blockSize )
+ {
+ inCc = read(inFd, buf, blockSize);
+ if (inCc < 0) {
+ perror(inFile);
+ goto cleanup;
+ }
+ //fprintf(stderr, "read in =%d\n", inCc);
+ intotal += inCc;
+ cp = buf;
+
+
+ while ( intotal > outTotal )
+ {
+ if (outTotal+inCc > count*blockSize)
+ inCc=count*blockSize-outTotal;
+ outCc = write(outFd, cp, inCc);
+ if (outCc < 0)
+ {
+ perror(outFile);
+ goto cleanup;
+ }
+ //fprintf(stderr, "wrote out =%d\n", outCc);
+
+ inCc -= outCc;
+ cp += outCc;
+ outTotal += outCc;
+ //fprintf(stderr, "outTotal=%ld\n", outTotal);
+ }
+ }
+
+ if (inCc < 0)
+ perror(inFile);
+
+cleanup:
+ close(inFd);
+
+ if (close(outFd) < 0)
+ perror(outFile);
+
+ if (buf != localBuf)
+ free(buf);
+
+ printf("%ld+%d records in\n", intotal / blockSize,
+ (intotal % blockSize) != 0);
+
+ printf("%ld+%d records out\n", outTotal / blockSize,
+ (outTotal % blockSize) != 0);
+ return 0;
+usage:
+
+ fprintf(stderr, "%s", dd_usage);
+ return 1;
+}
+
+
+/*
+ * Read a number with a possible multiplier.
+ * Returns -1 if the number format is illegal.
+ */
+static long
+getNum(const char * cp)
+{
+ long value;
+
+ if (!isDecimal(*cp))
+ return -1;
+
+ value = 0;
+
+ while (isDecimal(*cp))
+ value = value * 10 + *cp++ - '0';
+
+ switch (*cp++)
+ {
+ case 'k':
+ value *= 1024;
+ break;
+
+ case 'b':
+ value *= 512;
+ break;
+
+ case 'w':
+ value *= 2;
+ break;
+
+ case '\0':
+ return value;
+
+ default:
+ return -1;
+ }
+
+ if (*cp)
+ return -1;
+
+ return value;
+}
+
+#endif
+/* END CODE */
+
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 @@
+#include "internal.h"
+#include <stdio.h>
+#include <mntent.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+
+const char df_usage[] = "df [filesystem ...]\n"
+"\n"
+"\tPrint the filesystem space used and space available.\n";
+
+
+static int
+df(const char * device, const char * mountPoint)
+{
+ struct statfs s;
+ long blocks_used;
+ long blocks_percent_used;
+
+ if ( statfs(mountPoint, &s) != 0 ) {
+ name_and_error(mountPoint);
+ return 1;
+ }
+
+ if ( s.f_blocks > 0 ) {
+ blocks_used = s.f_blocks - s.f_bfree;
+ blocks_percent_used = (long)
+ (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
+
+/*
+ printf(
+ "%-20s %7ld %7ld %7ld %5ld%% %s\n"
+ ,device
+ ,s.f_blocks
+ ,s.f_blocks - s.f_bfree
+ ,s.f_bavail
+ ,blocks_percent_used
+ ,mountPoint);
+*/
+
+ printf(
+ "%-20s %7.0f %7.0f %7.0f %5ld%% %s\n"
+ ,device
+ ,s.f_blocks * (s.f_bsize / 1024.0)
+ ,(s.f_blocks - s.f_bfree) * (s.f_bsize / 1024.0)
+ ,s.f_bavail * (s.f_bsize / 1024.0)
+ ,blocks_percent_used
+ ,mountPoint);
+
+ }
+
+ return 0;
+}
+
+extern int
+df_main(struct FileInfo * i, int argc, char * * argv)
+{
+ static const char header[] =
+ "Filesystem 1024-blocks Used Available Capacity Mounted on\n";
+ printf(header);
+
+ if ( argc > 1 ) {
+ struct mntent * mountEntry;
+ int status;
+
+ while ( argc > 1 ) {
+ if ( (mountEntry = findMountPoint(argv[1], "/etc/mtab")) == 0
+ && (mountEntry = findMountPoint(argv[1], "/proc/mounts")) == 0 )
+ {
+ fprintf(stderr, "%s: can't find mount point.\n"
+ ,argv[1]);
+ return 1;
+ }
+ status = df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
+ if ( status != 0 )
+ return status;
+ argc--;
+ argv++;
+ }
+ return 0;
+ }
+ else {
+ FILE * mountTable;
+ struct mntent * mountEntry;
+
+ if ( (mountTable = setmntent("/etc/mtab", "r")) == 0
+ && (mountTable = setmntent("/proc/mounts", "r")) == 0
+ ) {
+ name_and_error("/etc/mtab");
+ return 1;
+ }
+
+ while ( (mountEntry = getmntent(mountTable)) != 0 ) {
+ int status = df(
+ mountEntry->mnt_fsname
+ ,mountEntry->mnt_dir);
+ if ( status != 0 )
+ return status;
+ }
+ endmntent(mountTable);
+ }
+
+ return 0;
+}
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 @@
+#include "internal.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+const char length_usage[] = "length string";
+
+int
+length_main(struct FileInfo * i, int argc, char * * argv)
+{
+ printf("%d\n", strlen(argv[1]));
+ return 0;
+}
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 @@
+#include "internal.h"
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <errno.h>
+
+const char ln_usage[] = "ln [-s] [-f] original-name additional-name\n"
+"\n"
+"\tAdd a new name that refers to the same file as \"original-name\"\n"
+"\n"
+"\t-s:\tUse a \"symbolic\" link, instead of a \"hard\" link.\n"
+"\t-f:\tRemove existing destination files.\n";
+
+int
+ln_fn(const struct FileInfo * i)
+{
+ int status = 0;
+ char d[PATH_MAX];
+ const char * destination = i->destination;
+
+ if ( !i->makeSymbolicLink && (i->stat.st_mode & S_IFMT) == S_IFDIR ) {
+ fprintf(stderr, "Please use \"ln -s\" to link directories.\n");
+ return 1;
+ }
+
+ /*
+ * If the destination is a directory, create a file within it.
+ */
+ if ( is_a_directory(i->destination) ) {
+ destination = join_paths(
+ d
+ ,i->destination
+ ,&i->source[i->directoryLength]);
+ }
+
+ if ( i->force )
+ status = ( unlink(destination) && errno != ENOENT );
+
+ if ( status == 0 ) {
+ if ( i->makeSymbolicLink )
+ status = symlink(i->source, destination);
+ else
+ status = link(i->source, destination);
+ }
+
+ if ( status != 0 ) {
+ name_and_error(destination);
+ return 1;
+ }
+ else
+ return 0;
+}
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 @@
+#include "internal.h"
+/*
+ * tiny-ls.c version 0.1.0: A minimalist 'ls'
+ * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * To achieve a small memory footprint, this version of 'ls' doesn't do any
+ * file sorting, and only has the most essential command line switches
+ * (i.e. the ones I couldn't live without :-) All features which involve
+ * linking in substantial chunks of libc can be disabled.
+ *
+ * Although I don't really want to add new features to this program to
+ * keep it small, I *am* interested to receive bug fixes and ways to make
+ * it more portable.
+ *
+ * KNOWN BUGS:
+ * 1. messy output if you mix files and directories on the command line
+ * 2. ls -l of a directory doesn't give "total <blocks>" header
+ * 3. ls of a symlink to a directory doesn't list directory contents
+ * 4. hidden files can make column width too large
+ * NON-OPTIMAL BEHAVIOUR:
+ * 1. autowidth reads directories twice
+ * 2. if you do a short directory listing without filetype characters
+ * appended, there's no need to stat each one
+ * PORTABILITY:
+ * 1. requires lstat (BSD) - how do you do it without?
+ */
+
+#define FEATURE_USERNAME /* show username/groupnames (libc6 uses NSS) */
+#define FEATURE_TIMESTAMPS /* show file timestamps */
+#define FEATURE_AUTOWIDTH /* calculate terminal & column widths */
+#define FEATURE_FILETYPECHAR /* enable -p and -F */
+
+#undef OP_BUF_SIZE 1024 /* leave undefined for unbuffered output */
+
+#define TERMINAL_WIDTH 80 /* use 79 if your terminal has linefold bug */
+#define COLUMN_WIDTH 14 /* default if AUTOWIDTH not defined */
+#define COLUMN_GAP 2 /* includes the file type char, if present */
+
+/************************************************************************/
+
+#define HAS_REWINDDIR
+
+#if 1 /* FIXME libc 6 */
+# include <linux/types.h>
+#else
+# include <sys/types.h>
+#endif
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#ifdef FEATURE_USERNAME
+#include <pwd.h>
+#include <grp.h>
+#endif
+#ifdef FEATURE_TIMESTAMPS
+#include <time.h>
+#endif
+
+#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
+#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
+#ifdef FEATURE_FILETYPECHAR
+#define APPCHAR(mode) ("\0|\0\0/\0\0\0\0\0@\0=\0\0\0" [TYPEINDEX(mode)])
+#endif
+
+#ifndef MAJOR
+#define MAJOR(dev) (((dev)>>8)&0xff)
+#define MINOR(dev) ((dev)&0xff)
+#endif
+
+#define MODE1 "rwxrwxrwx"
+#define MODE0 "---------"
+#define SMODE1 "..s..s..t"
+#define SMODE0 "..S..S..T"
+
+/* The 9 mode bits to test */
+
+static const umode_t MBIT[] = {
+ S_IRUSR, S_IWUSR, S_IXUSR,
+ S_IRGRP, S_IWGRP, S_IXGRP,
+ S_IROTH, S_IWOTH, S_IXOTH
+};
+
+/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */
+
+static const umode_t SBIT[] = {
+ 0, 0, S_ISUID,
+ 0, 0, S_ISGID,
+ 0, 0, S_ISVTX
+};
+
+#define FMT_AUTO 0
+#define FMT_LONG 1 /* one record per line, extended info */
+#define FMT_SINGLE 2 /* one record per line */
+#define FMT_ROWS 3 /* print across rows */
+#define FMT_COLUMNS 3 /* fill columns (same, since we don't sort) */
+
+#define TIME_MOD 0
+#define TIME_CHANGE 1
+#define TIME_ACCESS 2
+
+#define DISP_FTYPE 1 /* show character for file type */
+#define DISP_EXEC 2 /* show '*' if regular executable file */
+#define DISP_HIDDEN 4 /* show files starting . (except . and ..) */
+#define DISP_DOT 8 /* show . and .. */
+#define DISP_NUMERIC 16 /* numeric uid and gid */
+#define DISP_FULLTIME 32 /* show extended time display */
+#define DIR_NOLIST 64 /* show directory as itself, not contents */
+#define DISP_DIRNAME 128 /* show directory name (for internal use) */
+#define DIR_RECURSE 256 /* -R (not yet implemented) */
+
+static unsigned char display_fmt = FMT_AUTO;
+static unsigned short opts = 0;
+static unsigned short column = 0;
+
+#ifdef FEATURE_AUTOWIDTH
+static unsigned short terminal_width = 0, column_width = 0;
+#else
+#define terminal_width TERMINAL_WIDTH
+#define column_width COLUMN_WIDTH
+#endif
+
+#ifdef FEATURE_TIMESTAMPS
+static unsigned char time_fmt = TIME_MOD;
+#endif
+
+#define wr(data,len) fwrite(data, 1, len, stdout)
+
+static void writenum(long val, short minwidth)
+{
+ char scratch[20];
+
+ char *p = scratch + sizeof(scratch);
+ short len = 0;
+ short neg = (val < 0);
+
+ if (neg) val = -val;
+ do
+ *--p = (val % 10) + '0', len++, val /= 10;
+ while (val);
+ if (neg)
+ *--p = '-', len++;
+ while (len < minwidth)
+ *--p = ' ', len++;
+ wr(p, len);
+ column += len;
+}
+
+static void newline(void)
+{
+ if (column > 0) {
+ wr("\n", 1);
+ column = 0;
+ }
+}
+
+static void tab(short col)
+{
+ static const char spaces[] = " ";
+ #define nspaces ((sizeof spaces)-1) /* null terminator! */
+
+ short n = col - column;
+
+ if (n > 0) {
+ column = col;
+ while (n > nspaces) {
+ wr(spaces, nspaces);
+ n -= nspaces;
+ }
+ /* must be 1...(sizeof spaces) left */
+ wr(spaces, n);
+ }
+ #undef nspaces
+}
+
+#ifdef FEATURE_FILETYPECHAR
+static char append_char(umode_t mode)
+{
+ if (!(opts & DISP_FTYPE))
+ return '\0';
+ if ((opts & DISP_EXEC) && S_ISREG(mode) && (mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
+ return '*';
+ return APPCHAR(mode);
+}
+#endif
+
+/**
+ **
+ ** Display a file or directory as a single item
+ ** (in either long or short format)
+ **
+ **/
+
+static void list_single(const char *name, struct stat *info)
+{
+ char scratch[20];
+ short len = strlen(name);
+#ifdef FEATURE_FILETYPECHAR
+ char append = append_char(info->st_mode);
+#endif
+
+ if (display_fmt == FMT_LONG) {
+ umode_t mode = info->st_mode;
+ int i;
+
+ scratch[0] = TYPECHAR(mode);
+ for (i=0; i<9; i++)
+ if (mode & SBIT[i])
+ scratch[i+1] = (mode & MBIT[i])
+ ? SMODE1[i]
+ : SMODE0[i];
+ else
+ scratch[i+1] = (mode & MBIT[i])
+ ? MODE1[i]
+ : MODE0[i];
+ newline();
+ wr(scratch, 10);
+ column=10;
+ writenum((long)info->st_nlink,(short)4);
+ fputs(" ", stdout);
+#ifdef FEATURE_USERNAME
+ if (!(opts & DISP_NUMERIC)) {
+ struct passwd *pw = getpwuid(info->st_uid);
+ if (pw)
+ fputs(pw->pw_name, stdout);
+ else
+ writenum((long)info->st_uid,(short)0);
+ } else
+#endif
+ writenum((long)info->st_uid,(short)0);
+ tab(24);
+#ifdef FEATURE_USERNAME
+ if (!(opts & DISP_NUMERIC)) {
+ struct group *gr = getgrgid(info->st_gid);
+ if (gr)
+ fputs(gr->gr_name, stdout);
+ else
+ writenum((long)info->st_gid,(short)0);
+ } else
+#endif
+ writenum((long)info->st_gid,(short)0);
+ tab(33);
+ if (S_ISBLK(mode) || S_ISCHR(mode)) {
+ writenum((long)MAJOR(info->st_rdev),(short)3);
+ fputs(", ", stdout);
+ writenum((long)MINOR(info->st_rdev),(short)3);
+ }
+ else
+ writenum((long)info->st_size,(short)8);
+ fputs(" ", stdout);
+#ifdef FEATURE_TIMESTAMPS
+ {
+ time_t cal;
+ char *string;
+
+ switch(time_fmt) {
+ case TIME_CHANGE:
+ cal=info->st_ctime; break;
+ case TIME_ACCESS:
+ cal=info->st_atime; break;
+ default:
+ cal=info->st_mtime; break;
+ }
+ string=ctime(&cal);
+ if (opts & DISP_FULLTIME)
+ wr(string,24);
+ else {
+ time_t age = time(NULL) - cal;
+ wr(string+4,7); /* mmm_dd_ */
+ if(age < 3600L*24*365/2 && age > -15*60)
+ /* hh:mm if less than 6 months old */
+ wr(string+11,5);
+ else
+ /* _yyyy otherwise */
+ wr(string+19,5);
+ }
+ wr(" ", 1);
+ }
+#else
+ fputs("--- -- ----- ", stdout);
+#endif
+ wr(name, len);
+ if (S_ISLNK(mode)) {
+ wr(" -> ", 4);
+ len = readlink(name, scratch, sizeof scratch);
+ if (len > 0) fwrite(scratch, 1, len, stdout);
+#ifdef FEATURE_FILETYPECHAR
+ /* show type of destination */
+ if (opts & DISP_FTYPE) {
+ if (!stat(name, info)) {
+ append = append_char(info->st_mode);
+ if (append)
+ fputc(append, stdout);
+ }
+ }
+#endif
+ }
+#ifdef FEATURE_FILETYPECHAR
+ else if (append)
+ wr(&append, 1);
+#endif
+ } else {
+ static short nexttab = 0;
+
+ /* sort out column alignment */
+ if (column == 0)
+ ; /* nothing to do */
+ else if (display_fmt == FMT_SINGLE)
+ newline();
+ else {
+ if (nexttab + column_width > terminal_width
+#ifndef FEATURE_AUTOWIDTH
+ || nexttab + len >= terminal_width
+#endif
+ )
+ newline();
+ else
+ tab(nexttab);
+ }
+ /* work out where next column starts */
+#ifdef FEATURE_AUTOWIDTH
+ /* we know the calculated width is big enough */
+ nexttab = column + column_width + COLUMN_GAP;
+#else
+ /* might cover more than one fixed-width column */
+ nexttab = column;
+ do
+ nexttab += column_width + COLUMN_GAP;
+ while (nexttab < (column + len + COLUMN_GAP));
+#endif
+ /* now write the data */
+ wr(name, len);
+ column = column + len;
+#ifdef FEATURE_FILETYPECHAR
+ if (append)
+ wr(&append, 1), column++;
+#endif
+ }
+}
+
+/**
+ **
+ ** List the given file or directory, expanding a directory
+ ** to show its contents if required
+ **
+ **/
+
+static int list_item(const char *name)
+{
+ struct stat info;
+ DIR *dir;
+ struct dirent *entry;
+ char fullname[MAXNAMLEN+1], *fnend;
+
+ if (lstat(name, &info))
+ goto listerr;
+
+ if (!S_ISDIR(info.st_mode) ||
+ (opts & DIR_NOLIST)) {
+ list_single(name, &info);
+ return 0;
+ }
+
+ /* Otherwise, it's a directory we want to list the contents of */
+
+ if (opts & DISP_DIRNAME) { /* identify the directory */
+ if (column)
+ wr("\n\n", 2), column = 0;
+ wr(name, strlen(name));
+ wr(":\n", 2);
+ }
+
+ dir = opendir(name);
+ if (!dir) goto listerr;
+#ifdef FEATURE_AUTOWIDTH
+ column_width = 0;
+ while ((entry = readdir(dir)) != NULL) {
+ short w = strlen(entry->d_name);
+ if (column_width < w)
+ column_width = w;
+ }
+#ifdef HAS_REWINDDIR
+ rewinddir(dir);
+#else
+ closedir(dir);
+ dir = opendir(name);
+ if (!dir) goto listerr;
+#endif
+#endif
+
+ /* List the contents */
+
+ strcpy(fullname,name); /* *** ignore '.' by itself */
+ fnend=fullname+strlen(fullname);
+ if (fnend[-1] != '/')
+ *fnend++ = '/';
+
+ while ((entry = readdir(dir)) != NULL) {
+ const char *en=entry->d_name;
+ if (en[0] == '.') {
+ if (!en[1] || (en[1] == '.' && !en[2])) { /* . or .. */
+ if (!(opts & DISP_DOT))
+ continue;
+ }
+ else if (!(opts & DISP_HIDDEN))
+ continue;
+ }
+ /* FIXME: avoid stat if not required */
+ strcpy(fnend, entry->d_name);
+ if (lstat(fullname, &info))
+ goto direrr; /* (shouldn't fail) */
+ list_single(entry->d_name, &info);
+ }
+ closedir(dir);
+ return 0;
+
+direrr:
+ closedir(dir);
+listerr:
+ newline();
+ name_and_error(name);
+ return 1;
+}
+
+const char ls_usage[] = "Usage: ls [-1a"
+#ifdef FEATURE_TIMESTAMPS
+ "c"
+#endif
+ "d"
+#ifdef FEATURE_TIMESTAMPS
+ "e"
+#endif
+ "ln"
+#ifdef FEATURE_FILETYPECHAR
+ "p"
+#endif
+#ifdef FEATURE_TIMESTAMPS
+ "u"
+#endif
+ "xAC"
+#ifdef FEATURE_FILETYPECHAR
+ "F"
+#endif
+#ifdef FEATURE_RECURSIVE
+ "R"
+#endif
+ "] [filenames...]\n";
+
+extern int
+ls_main(struct FileInfo * not_used, int argc, char * * argv)
+{
+ int argi=1, i;
+
+ /* process options */
+ while (argi < argc && argv[argi][0] == '-') {
+ const char *p = &argv[argi][1];
+
+ if (!*p) goto print_usage_message; /* "-" by itself not allowed */
+ if (*p == '-') {
+ if (!p[1]) { /* "--" forces end of options */
+ argi++;
+ break;
+ }
+ /* it's a long option name - we don't support them */
+ goto print_usage_message;
+ }
+
+ while (*p)
+ switch (*p++) {
+ case 'l': display_fmt = FMT_LONG; break;
+ case '1': display_fmt = FMT_SINGLE; break;
+ case 'x': display_fmt = FMT_ROWS; break;
+ case 'C': display_fmt = FMT_COLUMNS; break;
+#ifdef FEATURE_FILETYPECHAR
+ case 'p': opts |= DISP_FTYPE; break;
+ case 'F': opts |= DISP_FTYPE|DISP_EXEC; break;
+#endif
+ case 'A': opts |= DISP_HIDDEN; break;
+ case 'a': opts |= DISP_HIDDEN|DISP_DOT; break;
+ case 'n': opts |= DISP_NUMERIC; break;
+ case 'd': opts |= DIR_NOLIST; break;
+#ifdef FEATURE_RECURSIVE
+ case 'R': opts |= DIR_RECURSE; break;
+#endif
+#ifdef FEATURE_TIMESTAMPS
+ case 'u': time_fmt = TIME_ACCESS; break;
+ case 'c': time_fmt = TIME_CHANGE; break;
+ case 'e': opts |= DISP_FULLTIME; break;
+#endif
+ default: goto print_usage_message;
+ }
+
+ argi++;
+ }
+
+ /* choose a display format */
+ if (display_fmt == FMT_AUTO)
+ display_fmt = isatty(STDOUT_FILENO) ? FMT_COLUMNS : FMT_SINGLE;
+ if (argi < argc - 1)
+ opts |= DISP_DIRNAME; /* 2 or more items? label directories */
+#ifdef FEATURE_AUTOWIDTH
+ /* could add a -w option and/or TIOCGWINSZ call */
+ if (terminal_width < 1) terminal_width = TERMINAL_WIDTH;
+
+ for (i = argi; i < argc; i++) {
+ int len = strlen(argv[i]);
+ if (column_width < len)
+ column_width = len;
+ }
+#endif
+
+ /* process files specified, or current directory if none */
+ i=0;
+ if (argi == argc)
+ i = list_item(".");
+ while (argi < argc)
+ i |= list_item(argv[argi++]);
+ newline();
+ return i;
+
+print_usage_message:
+ usage(ls_usage);
+ return 1;
+}
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 @@
+#include "internal.h"
+#include <errno.h>
+#include <sys/param.h>
+
+const char mkdir_usage[] = "mkdir [-m mode] directory [directory ...]\n"
+"\tCreate directories.\n"
+"\n"
+"\t-m mode:\tSpecifiy the mode for the new directory\n"
+"\t\tunder the argument directory.";
+
+/*make directories skipping the last part of the path. Used here and by untar*/
+int mkdir_until(const char *fpath, const struct FileInfo * fi)
+{
+ char path[PATH_MAX];
+ char * s = path;
+
+ strcpy(path, fpath);
+ if ( s[0] == '\0' && s[1] == '\0' ) {
+ usage(mkdir_usage);
+ return 1;
+ }
+ s++;
+ while ( *s != '\0' ) {
+ if ( *s == '/' ) {
+ int status;
+
+ *s = '\0';
+ status = mkdir(path, (fi?fi->orWithMode:0700) );
+ *s = '/';
+
+ if ( status != 0 ) {
+ if ( errno != EEXIST ) {
+ name_and_error(fpath);
+ return 1;
+ }
+ }
+
+ }
+ s++;
+ }
+ return 0;
+}
+
+int
+mkdir_fn(const struct FileInfo * i)
+{
+ if ( i->makeParentDirectories ) {
+ if(mkdir_until(i->source, i)) return 1;
+ }
+
+ if ( mkdir(i->source, i->orWithMode) != 0 && errno != EEXIST ) {
+ name_and_error(i->source);
+ return 1;
+ }
+ else
+ return 0;
+}
+
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 @@
+#include "internal.h"
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+const char mknod_usage[] = "mknod file b|c|u|p major minor\n"
+"\tMake special files.\n"
+"\n"
+"\tb:\tMake a block (buffered) device.\n"
+"\tc or u:\tMake a character (un-buffered) device.\n"
+"\tp:\tMake a named pipe. Major and minor are ignored for named pipes.\n";
+
+int
+mknod_main(struct FileInfo * i, int argc, char * * argv)
+{
+ mode_t mode = 0;
+ dev_t dev = 0;
+
+ switch(argv[2][0]) {
+ case 'c':
+ case 'u':
+ mode = S_IFCHR;
+ break;
+ case 'b':
+ mode = S_IFBLK;
+ break;
+ case 'p':
+ mode = S_IFIFO;
+ break;
+ default:
+ usage(mknod_usage);
+ return 1;
+ }
+
+ if ( mode == S_IFCHR || mode == S_IFBLK ) {
+ dev = (atoi(argv[3]) << 8) | atoi(argv[4]);
+ if ( argc != 5 ) {
+ usage(mknod_usage);
+ return 1;
+ }
+ }
+
+ mode |= 0666;
+
+ if ( mknod(argv[1], mode, dev) != 0 ) {
+ name_and_error(argv[1]);
+ return 1;
+ }
+ return 0;
+}
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 @@
+#include "internal.h"
+#include <stdio.h>
+#include <errno.h>
+
+const char mv_usage[] = "mv source-file destination-file\n"
+"\t\tmv source-file [source-file ...] destination-directory\n"
+"\n"
+"\tMove the source files to the destination.\n"
+"\n";
+
+extern int
+mv_fn(const struct FileInfo * i)
+{
+ struct stat destination_stat;
+ char d[1024];
+ struct FileInfo n;
+
+ if ( stat(i->destination, &destination_stat) == 0 ) {
+ if ( i->stat.st_ino == destination_stat.st_ino
+ && i->stat.st_dev == destination_stat.st_dev )
+ return 0; /* Move file to itself. */
+ }
+ if ( (destination_stat.st_mode & S_IFMT) == S_IFDIR ) {
+ n = *i;
+ n.destination = join_paths(d, i->destination, basename(i->source));
+ i = &n;
+ }
+ if ( rename(i->source, i->destination) == 0 )
+ return 0;
+ else if ( errno == EXDEV && is_a_directory(i->source) ) {
+ fprintf(stderr
+ ,"%s: Can't move directory across filesystems.\n"
+ ,i->source);
+ return 1;
+ }
+ else
+ return cp_fn(i);
+}
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 @@
+// I may still need some more cleaning...fix my error checking
+
+#include "internal.h"
+#ifdef BB_PRINTF
+
+/* printf - format and print data
+ Copyright (C) 90, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Usage: printf format [argument...]
+
+ A front end to the printf function that lets it be used from the shell.
+
+ Backslash escapes:
+
+ \" = double quote
+ \\ = backslash
+ \a = alert (bell)
+ \b = backspace
+ \c = produce no further output
+ \f = form feed
+ \n = new line
+ \r = carriage return
+ \t = horizontal tab
+ \v = vertical tab
+ \0ooo = octal number (ooo is 0 to 3 digits)
+ \xhhh = hexadecimal number (hhh is 1 to 3 digits)
+
+ Additional directive:
+
+ %b = print an argument string, interpreting backslash escapes
+
+ The `format' argument is re-used as many times as necessary
+ to convert all of the given arguments.
+
+ David MacKenzie <djm@gnu.ai.mit.edu> */
+
+
+// 19990508 Busy Boxed! Dave Cinege
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <getopt.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <libintl.h>
+
+
+#ifndef S_IFMT
+# define S_IFMT 0170000
+#endif
+#if !defined(S_ISBLK) && defined(S_IFBLK)
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#endif
+#if !defined(S_ISCHR) && defined(S_IFCHR)
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISDIR) && defined(S_IFDIR)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG) && defined(S_IFREG)
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISFIFO) && defined(S_IFIFO)
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK) && defined(S_IFSOCK)
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
+# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
+# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
+#endif
+#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
+# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
+#endif
+
+#define IN_CTYPE_DOMAIN(c) 1
+
+#ifdef isblank
+# define ISBLANK(c) (IN_CTYPE_DOMAIN (c) && isblank (c))
+#else
+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#endif
+#ifdef isgraph
+# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isgraph (c))
+#else
+# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isprint (c) && !isspace (c))
+#endif
+
+#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
+#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c))
+#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
+#define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (c))
+#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c))
+#define ISPUNCT(c) (IN_CTYPE_DOMAIN (c) && ispunct (c))
+#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
+#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c))
+#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c))
+#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
+#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
+
+#define isodigit(c) ((c) >= '0' && (c) <= '7')
+#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
+#define octtobin(c) ((c) - '0')
+
+char *xmalloc ();
+
+static double xstrtod __P ((char *s));
+static int print_esc __P ((char *escstart));
+static int print_formatted __P ((char *format, int argc, char **argv));
+static long xstrtol __P ((char *s));
+static unsigned long xstrtoul __P ((char *s));
+static void print_direc __P ((char *start, size_t length, int field_width, int precision, char *argument));
+static void print_esc_char __P ((int c));
+static void print_esc_string __P ((char *str));
+static void verify __P ((char *s, char *end));
+
+/* The value to return to the calling program. */
+static int exit_status;
+
+const char printf_usage[] = "Usage: printf format [argument...]\n";
+
+int
+printf_main(struct FileInfo * i, int argc, char * * argv)
+{
+ char *format;
+ int args_used;
+
+ exit_status = 0;
+
+ format = argv[1];
+ argc -= 2;
+ argv += 2;
+
+ do
+ {
+ args_used = print_formatted (format, argc, argv);
+ argc -= args_used;
+ argv += args_used;
+ }
+ while (args_used > 0 && argc > 0);
+
+/*
+ if (argc > 0)
+ fprintf(stderr, "excess args ignored");
+*/
+
+ exit (exit_status);
+}
+
+/* Print the text in FORMAT, using ARGV (with ARGC elements) for
+ arguments to any `%' directives.
+ Return the number of elements of ARGV used. */
+
+static int
+print_formatted (char *format, int argc, char **argv)
+{
+ int save_argc = argc; /* Preserve original value. */
+ char *f; /* Pointer into `format'. */
+ char *direc_start; /* Start of % directive. */
+ size_t direc_length; /* Length of % directive. */
+ int field_width; /* Arg to first '*', or -1 if none. */
+ int precision; /* Arg to second '*', or -1 if none. */
+
+ for (f = format; *f; ++f)
+ {
+ switch (*f)
+ {
+ case '%':
+ direc_start = f++;
+ direc_length = 1;
+ field_width = precision = -1;
+ if (*f == '%')
+ {
+ putchar ('%');
+ break;
+ }
+ if (*f == 'b')
+ {
+ if (argc > 0)
+ {
+ print_esc_string (*argv);
+ ++argv;
+ --argc;
+ }
+ break;
+ }
+ if (strchr ("-+ #", *f))
+ {
+ ++f;
+ ++direc_length;
+ }
+ if (*f == '*')
+ {
+ ++f;
+ ++direc_length;
+ if (argc > 0)
+ {
+ field_width = xstrtoul (*argv);
+ ++argv;
+ --argc;
+ }
+ else
+ field_width = 0;
+ }
+ else
+ while (ISDIGIT (*f))
+ {
+ ++f;
+ ++direc_length;
+ }
+ if (*f == '.')
+ {
+ ++f;
+ ++direc_length;
+ if (*f == '*')
+ {
+ ++f;
+ ++direc_length;
+ if (argc > 0)
+ {
+ precision = xstrtoul (*argv);
+ ++argv;
+ --argc;
+ }
+ else
+ precision = 0;
+ }
+ else
+ while (ISDIGIT (*f))
+ {
+ ++f;
+ ++direc_length;
+ }
+ }
+ if (*f == 'l' || *f == 'L' || *f == 'h')
+ {
+ ++f;
+ ++direc_length;
+ }
+ /*
+ if (!strchr ("diouxXfeEgGcs", *f))
+ fprintf(stderr, "%%%c: invalid directive", *f);
+ */
+ ++direc_length;
+ if (argc > 0)
+ {
+ print_direc (direc_start, direc_length, field_width,
+ precision, *argv);
+ ++argv;
+ --argc;
+ }
+ else
+ print_direc (direc_start, direc_length, field_width,
+ precision, "");
+ break;
+
+ case '\\':
+ f += print_esc (f);
+ break;
+
+ default:
+ putchar (*f);
+ }
+ }
+
+ return save_argc - argc;
+}
+
+/* Print a \ escape sequence starting at ESCSTART.
+ Return the number of characters in the escape sequence
+ besides the backslash. */
+
+static int
+print_esc (char *escstart)
+{
+ register char *p = escstart + 1;
+ int esc_value = 0; /* Value of \nnn escape. */
+ int esc_length; /* Length of \nnn escape. */
+
+ /* \0ooo and \xhhh escapes have maximum length of 3 chars. */
+ if (*p == 'x')
+ {
+ for (esc_length = 0, ++p;
+ esc_length < 3 && ISXDIGIT (*p);
+ ++esc_length, ++p)
+ esc_value = esc_value * 16 + hextobin (*p);
+/* if (esc_length == 0)
+ fprintf(stderr, "missing hex in esc");
+*/
+ putchar (esc_value);
+ }
+ else if (*p == '0')
+ {
+ for (esc_length = 0, ++p;
+ esc_length < 3 && isodigit (*p);
+ ++esc_length, ++p)
+ esc_value = esc_value * 8 + octtobin (*p);
+ putchar (esc_value);
+ }
+ else if (strchr ("\"\\abcfnrtv", *p))
+ print_esc_char (*p++);
+/* else
+ fprintf(stderr, "\\%c: invalid esc", *p);
+*/
+ return p - escstart - 1;
+}
+
+/* Output a single-character \ escape. */
+
+static void
+print_esc_char (int c)
+{
+ switch (c)
+ {
+ case 'a': /* Alert. */
+ putchar (7);
+ break;
+ case 'b': /* Backspace. */
+ putchar (8);
+ break;
+ case 'c': /* Cancel the rest of the output. */
+ exit (0);
+ break;
+ case 'f': /* Form feed. */
+ putchar (12);
+ break;
+ case 'n': /* New line. */
+ putchar (10);
+ break;
+ case 'r': /* Carriage return. */
+ putchar (13);
+ break;
+ case 't': /* Horizontal tab. */
+ putchar (9);
+ break;
+ case 'v': /* Vertical tab. */
+ putchar (11);
+ break;
+ default:
+ putchar (c);
+ break;
+ }
+}
+
+/* Print string STR, evaluating \ escapes. */
+
+static void
+print_esc_string (char *str)
+{
+ for (; *str; str++)
+ if (*str == '\\')
+ str += print_esc (str);
+ else
+ putchar (*str);
+}
+
+static void
+print_direc (char *start, size_t length, int field_width, int precision, char *argument)
+{
+ char *p; /* Null-terminated copy of % directive. */
+
+ p = xmalloc ((unsigned) (length + 1));
+ strncpy (p, start, length);
+ p[length] = 0;
+
+ switch (p[length - 1])
+ {
+ case 'd':
+ case 'i':
+ if (field_width < 0)
+ {
+ if (precision < 0)
+ printf (p, xstrtol (argument));
+ else
+ printf (p, precision, xstrtol (argument));
+ }
+ else
+ {
+ if (precision < 0)
+ printf (p, field_width, xstrtol (argument));
+ else
+ printf (p, field_width, precision, xstrtol (argument));
+ }
+ break;
+
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ if (field_width < 0)
+ {
+ if (precision < 0)
+ printf (p, xstrtoul (argument));
+ else
+ printf (p, precision, xstrtoul (argument));
+ }
+ else
+ {
+ if (precision < 0)
+ printf (p, field_width, xstrtoul (argument));
+ else
+ printf (p, field_width, precision, xstrtoul (argument));
+ }
+ break;
+
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ if (field_width < 0)
+ {
+ if (precision < 0)
+ printf (p, xstrtod (argument));
+ else
+ printf (p, precision, xstrtod (argument));
+ }
+ else
+ {
+ if (precision < 0)
+ printf (p, field_width, xstrtod (argument));
+ else
+ printf (p, field_width, precision, xstrtod (argument));
+ }
+ break;
+
+ case 'c':
+ printf (p, *argument);
+ break;
+
+ case 's':
+ if (field_width < 0)
+ {
+ if (precision < 0)
+ printf (p, argument);
+ else
+ printf (p, precision, argument);
+ }
+ else
+ {
+ if (precision < 0)
+ printf (p, field_width, argument);
+ else
+ printf (p, field_width, precision, argument);
+ }
+ break;
+ }
+
+ free (p);
+}
+
+static unsigned long
+xstrtoul (char *s)
+{
+ char *end;
+ unsigned long val;
+
+ errno = 0;
+ val = strtoul (s, &end, 0);
+ verify (s, end);
+ return val;
+}
+
+static long
+xstrtol (char *s)
+{
+ char *end;
+ long val;
+
+ errno = 0;
+ val = strtol (s, &end, 0);
+ verify (s, end);
+ return val;
+}
+
+static double
+xstrtod (char *s)
+{
+ char *end;
+ double val;
+
+ errno = 0;
+ val = strtod (s, &end);
+ verify (s, end);
+ return val;
+}
+
+static void
+verify (char *s, char *end)
+{
+ if (errno)
+ {
+ fprintf(stderr, "%s", s);
+ exit_status = 1;
+ }
+ else if (*end)
+ {
+ /*
+ if (s == end)
+ fprintf(stderr, "%s: expected numeric", s);
+ else
+ fprintf(stderr, "%s: not completely converted", s);
+ */
+ exit_status = 1;
+ }
+}
+
+#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 @@
+#include "internal.h"
+#include <stdio.h>
+
+const char pwd_usage[] = "Print the current directory.\n";
+
+extern int
+pwd_main(struct FileInfo * i, int argc, char * * argv)
+{
+ char buf[1024];
+
+ if ( getcwd(buf, sizeof(buf)) == NULL ) {
+ name_and_error("get working directory");
+ return 1;
+ }
+
+ printf("%s\n", buf);
+ return 0;
+}
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 @@
+#include "internal.h"
+#include <errno.h>
+
+const char rm_usage[] = "rm [-r] file [file ...]\n"
+"\n"
+"\tDelete files.\n"
+"\n"
+"\t-r:\tRecursively remove files and directories.\n";
+
+extern int
+rm_main(struct FileInfo * i, int argc, char * * argv)
+{
+ i->processDirectoriesAfterTheirContents = 1;
+ return monadic_main(i, argc, argv);
+}
+
+extern int
+rm_fn(const struct FileInfo * i)
+{
+ if ( i->recursive
+ && !i->isSymbolicLink
+ && (i->stat.st_mode & S_IFMT) == S_IFDIR )
+ return rmdir_fn(i);
+ else if ( unlink(i->source) != 0 && errno != ENOENT && !i->force ) {
+ name_and_error(i->source);
+ return 1;
+ }
+ else
+ return 0;
+}
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 @@
+#include "internal.h"
+#include <errno.h>
+
+const char rmdir_usage[] = "rmdir directory [directory ...]\n"
+"\n"
+"\tDelete directories.\n";
+
+extern int
+rmdir_fn(const struct FileInfo * i)
+{
+ if ( rmdir(i->source) != 0 && errno != ENOENT && !i->force ) {
+ name_and_error(i->source);
+ return 1;
+ }
+ else
+ return 0;
+}
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 @@
+#include "internal.h"
+#include <stdio.h>
+
+const char sleep_usage[] = "sleep seconds\n"
+"\n"
+"\tPause program execution for the given number of seconds.\n";
+
+extern int
+sleep_main(struct FileInfo * i, int argc, char * * argv)
+{
+ if ( sleep(atoi(argv[1])) != 0 )
+ return -1;
+ else
+ return 0;
+}
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 @@
+#include "internal.h"
+
+const char sync_usage[] = "sync\n"
+"\n"
+"\tWrite all buffered filesystem blocks to disk.\n";
+
+extern int
+sync_main(struct FileInfo * i, int argc, char * * argv)
+{
+ return sync();
+}
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 @@
+#include "internal.h"
+#include <sys/types.h>
+#include <stdio.h>
+#include <utime.h>
+
+const char touch_usage[] = "touch [-c] file [file ...]\n"
+"\n"
+"\tUpdate the last-modified date on the given file[s].\n";
+
+extern int
+touch_fn(const struct FileInfo * i)
+{
+ if ( (utime(i->source, 0) != 0) && (i->create != 1) ) {
+ if ( fopen(i->source, "w") == NULL ) {
+ name_and_error(i->source);
+ return 1;
+ }
+ }
+ return 0;
+}