diff options
| author | Eric Andersen <andersen@codepoet.org> | 1999-10-05 16:24:54 +0000 |
|---|---|---|
| committer | Eric Andersen <andersen@codepoet.org> | 1999-10-05 16:24:54 +0000 |
| commit | cc8ed39b240180b58810784f844e253263594ac3 (patch) | |
| tree | 15feebbb4be9a9168209609f48f0b100f9364420 /coreutils | |
| download | busybox-w32-0_29alpha2.tar.gz busybox-w32-0_29alpha2.tar.bz2 busybox-w32-0_29alpha2.zip | |
Initial revision0_29alpha2
Diffstat (limited to 'coreutils')
| -rw-r--r-- | coreutils/cat.c | 54 | ||||
| -rw-r--r-- | coreutils/chgrp.c | 89 | ||||
| -rw-r--r-- | coreutils/chmod.c | 163 | ||||
| -rw-r--r-- | coreutils/chown.c | 63 | ||||
| -rw-r--r-- | coreutils/chroot.c | 32 | ||||
| -rw-r--r-- | coreutils/cp.c | 89 | ||||
| -rw-r--r-- | coreutils/date.c | 305 | ||||
| -rw-r--r-- | coreutils/dd.c | 307 | ||||
| -rw-r--r-- | coreutils/df.c | 103 | ||||
| -rw-r--r-- | coreutils/length.c | 13 | ||||
| -rw-r--r-- | coreutils/ln.c | 52 | ||||
| -rw-r--r-- | coreutils/ls.c | 542 | ||||
| -rw-r--r-- | coreutils/mkdir.c | 58 | ||||
| -rw-r--r-- | coreutils/mknod.c | 52 | ||||
| -rw-r--r-- | coreutils/mv.c | 38 | ||||
| -rw-r--r-- | coreutils/printf.c | 531 | ||||
| -rw-r--r-- | coreutils/pwd.c | 18 | ||||
| -rw-r--r-- | coreutils/rm.c | 30 | ||||
| -rw-r--r-- | coreutils/rmdir.c | 17 | ||||
| -rw-r--r-- | coreutils/sleep.c | 15 | ||||
| -rw-r--r-- | coreutils/sync.c | 11 | ||||
| -rw-r--r-- | coreutils/touch.c | 20 |
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 | |||
| 25 | const char cat_usage[] = "[file ...]"; | ||
| 26 | |||
| 27 | extern 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 | |||
| 26 | const 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 | |||
| 30 | int 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 | ||
| 82 | int | ||
| 83 | recursive(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 | |||
| 7 | const 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 | |||
| 31 | int | ||
| 32 | parse_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 | |||
| 138 | extern int | ||
| 139 | chmod_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 | |||
| 7 | const 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 | |||
| 12 | int | ||
| 13 | parse_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 | |||
| 42 | extern int | ||
| 43 | chown_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 | |||
| 6 | const char chroot_usage[] = "chroot directory [command]\n" | ||
| 7 | "Run a command with special root directory.\n"; | ||
| 8 | |||
| 9 | extern int | ||
| 10 | chroot_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 | |||
| 8 | const 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 | |||
| 16 | extern int | ||
| 17 | cp_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 | |||
| 17 | const char date_usage[] = "date [-uR] [+FORMAT|+%f] [ [-s|-d] MMDDhhmm[[CC]YY]\n | [[[[CCYY.]MM.DD-]hh:mm[:ss]]]] ]"; | ||
| 18 | |||
| 19 | static 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 | |||
| 37 | struct tm * | ||
| 38 | date_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 | |||
| 66 | struct tm * | ||
| 67 | date_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 | <m_time.tm_mon, | ||
| 108 | <m_time.tm_mday, | ||
| 109 | <m_time.tm_hour, | ||
| 110 | <m_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 | |||
| 149 | void | ||
| 150 | date_err(void) { | ||
| 151 | fprintf(stderr, "date: only one date argument can be given at a time.\n"); | ||
| 152 | exit(1); | ||
| 153 | } | ||
| 154 | |||
| 155 | int | ||
| 156 | date_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 | |||
| 15 | const char dd_usage[] = | ||
| 16 | "Copy a file, converting and formatting according to options\n\ | ||
| 17 | \n\ | ||
| 18 | usage: [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\ | ||
| 24 | BYTES 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 | |||
| 42 | typedef struct | ||
| 43 | { | ||
| 44 | const char * name; | ||
| 45 | int value; | ||
| 46 | } PARAM; | ||
| 47 | |||
| 48 | |||
| 49 | static 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 | |||
| 59 | static long getNum(const char * cp); | ||
| 60 | |||
| 61 | extern int | ||
| 62 | dd_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 | |||
| 239 | cleanup: | ||
| 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; | ||
| 254 | usage: | ||
| 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 | */ | ||
| 265 | static long | ||
| 266 | getNum(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 | |||
| 7 | const char df_usage[] = "df [filesystem ...]\n" | ||
| 8 | "\n" | ||
| 9 | "\tPrint the filesystem space used and space available.\n"; | ||
| 10 | |||
| 11 | |||
| 12 | static int | ||
| 13 | df(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 | |||
| 54 | extern int | ||
| 55 | df_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 | |||
| 6 | const char length_usage[] = "length string"; | ||
| 7 | |||
| 8 | int | ||
| 9 | length_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 | |||
| 7 | const 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 | |||
| 14 | int | ||
| 15 | ln_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 | |||
| 96 | static 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 | |||
| 104 | static 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 | |||
| 130 | static unsigned char display_fmt = FMT_AUTO; | ||
| 131 | static unsigned short opts = 0; | ||
| 132 | static unsigned short column = 0; | ||
| 133 | |||
| 134 | #ifdef FEATURE_AUTOWIDTH | ||
| 135 | static 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 | ||
| 142 | static unsigned char time_fmt = TIME_MOD; | ||
| 143 | #endif | ||
| 144 | |||
| 145 | #define wr(data,len) fwrite(data, 1, len, stdout) | ||
| 146 | |||
| 147 | static 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 | |||
| 167 | static void newline(void) | ||
| 168 | { | ||
| 169 | if (column > 0) { | ||
| 170 | wr("\n", 1); | ||
| 171 | column = 0; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | static 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 | ||
| 195 | static 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 | |||
| 212 | static 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 | |||
| 366 | static 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 | |||
| 435 | direrr: | ||
| 436 | closedir(dir); | ||
| 437 | listerr: | ||
| 438 | newline(); | ||
| 439 | name_and_error(name); | ||
| 440 | return 1; | ||
| 441 | } | ||
| 442 | |||
| 443 | const 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 | |||
| 467 | extern int | ||
| 468 | ls_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 | |||
| 539 | print_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 | |||
| 5 | const 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*/ | ||
| 12 | int 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 | |||
| 44 | int | ||
| 45 | mkdir_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 | |||
| 8 | const 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 | |||
| 15 | int | ||
| 16 | mknod_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 | |||
| 5 | const 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 | |||
| 11 | extern int | ||
| 12 | mv_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 | |||
| 128 | char *xmalloc (); | ||
| 129 | |||
| 130 | static double xstrtod __P ((char *s)); | ||
| 131 | static int print_esc __P ((char *escstart)); | ||
| 132 | static int print_formatted __P ((char *format, int argc, char **argv)); | ||
| 133 | static long xstrtol __P ((char *s)); | ||
| 134 | static unsigned long xstrtoul __P ((char *s)); | ||
| 135 | static void print_direc __P ((char *start, size_t length, int field_width, int precision, char *argument)); | ||
| 136 | static void print_esc_char __P ((int c)); | ||
| 137 | static void print_esc_string __P ((char *str)); | ||
| 138 | static void verify __P ((char *s, char *end)); | ||
| 139 | |||
| 140 | /* The value to return to the calling program. */ | ||
| 141 | static int exit_status; | ||
| 142 | |||
| 143 | const char printf_usage[] = "Usage: printf format [argument...]\n"; | ||
| 144 | |||
| 145 | int | ||
| 146 | printf_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 | |||
| 177 | static int | ||
| 178 | print_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 | |||
| 296 | static int | ||
| 297 | print_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 | |||
| 333 | static void | ||
| 334 | print_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 | |||
| 370 | static void | ||
| 371 | print_esc_string (char *str) | ||
| 372 | { | ||
| 373 | for (; *str; str++) | ||
| 374 | if (*str == '\\') | ||
| 375 | str += print_esc (str); | ||
| 376 | else | ||
| 377 | putchar (*str); | ||
| 378 | } | ||
| 379 | |||
| 380 | static void | ||
| 381 | print_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 | |||
| 475 | static unsigned long | ||
| 476 | xstrtoul (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 | |||
| 487 | static long | ||
| 488 | xstrtol (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 | |||
| 499 | static double | ||
| 500 | xstrtod (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 | |||
| 511 | static void | ||
| 512 | verify (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 | |||
| 4 | const char pwd_usage[] = "Print the current directory.\n"; | ||
| 5 | |||
| 6 | extern int | ||
| 7 | pwd_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 | |||
| 4 | const 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 | |||
| 10 | extern int | ||
| 11 | rm_main(struct FileInfo * i, int argc, char * * argv) | ||
| 12 | { | ||
| 13 | i->processDirectoriesAfterTheirContents = 1; | ||
| 14 | return monadic_main(i, argc, argv); | ||
| 15 | } | ||
| 16 | |||
| 17 | extern int | ||
| 18 | rm_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 | |||
| 4 | const char rmdir_usage[] = "rmdir directory [directory ...]\n" | ||
| 5 | "\n" | ||
| 6 | "\tDelete directories.\n"; | ||
| 7 | |||
| 8 | extern int | ||
| 9 | rmdir_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 | |||
| 4 | const char sleep_usage[] = "sleep seconds\n" | ||
| 5 | "\n" | ||
| 6 | "\tPause program execution for the given number of seconds.\n"; | ||
| 7 | |||
| 8 | extern int | ||
| 9 | sleep_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 | |||
| 3 | const char sync_usage[] = "sync\n" | ||
| 4 | "\n" | ||
| 5 | "\tWrite all buffered filesystem blocks to disk.\n"; | ||
| 6 | |||
| 7 | extern int | ||
| 8 | sync_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 | |||
| 6 | const char touch_usage[] = "touch [-c] file [file ...]\n" | ||
| 7 | "\n" | ||
| 8 | "\tUpdate the last-modified date on the given file[s].\n"; | ||
| 9 | |||
| 10 | extern int | ||
| 11 | touch_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 | } | ||
