Initial revision
This commit is contained in:
54
coreutils/cat.c
Normal file
54
coreutils/cat.c
Normal file
@@ -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;
|
||||
}
|
89
coreutils/chgrp.c
Normal file
89
coreutils/chgrp.c
Normal file
@@ -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
|
163
coreutils/chmod.c
Normal file
163
coreutils/chmod.c
Normal file
@@ -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);
|
||||
}
|
63
coreutils/chown.c
Normal file
63
coreutils/chown.c
Normal file
@@ -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);
|
||||
}
|
32
coreutils/chroot.c
Normal file
32
coreutils/chroot.c
Normal file
@@ -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;
|
||||
}
|
89
coreutils/cp.c
Normal file
89
coreutils/cp.c
Normal file
@@ -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;
|
||||
}
|
305
coreutils/date.c
Normal file
305
coreutils/date.c
Normal file
@@ -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",
|
||||
<m_time.tm_mon,
|
||||
<m_time.tm_mday,
|
||||
<m_time.tm_hour,
|
||||
<m_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);
|
||||
|
||||
}
|
307
coreutils/dd.c
Normal file
307
coreutils/dd.c
Normal file
@@ -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 */
|
||||
|
103
coreutils/df.c
Normal file
103
coreutils/df.c
Normal file
@@ -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;
|
||||
}
|
13
coreutils/length.c
Normal file
13
coreutils/length.c
Normal file
@@ -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;
|
||||
}
|
52
coreutils/ln.c
Normal file
52
coreutils/ln.c
Normal file
@@ -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;
|
||||
}
|
542
coreutils/ls.c
Normal file
542
coreutils/ls.c
Normal file
@@ -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;
|
||||
}
|
58
coreutils/mkdir.c
Normal file
58
coreutils/mkdir.c
Normal file
@@ -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;
|
||||
}
|
||||
|
52
coreutils/mknod.c
Normal file
52
coreutils/mknod.c
Normal file
@@ -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;
|
||||
}
|
38
coreutils/mv.c
Normal file
38
coreutils/mv.c
Normal file
@@ -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);
|
||||
}
|
531
coreutils/printf.c
Normal file
531
coreutils/printf.c
Normal file
@@ -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
|
18
coreutils/pwd.c
Normal file
18
coreutils/pwd.c
Normal file
@@ -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;
|
||||
}
|
30
coreutils/rm.c
Normal file
30
coreutils/rm.c
Normal file
@@ -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;
|
||||
}
|
17
coreutils/rmdir.c
Normal file
17
coreutils/rmdir.c
Normal file
@@ -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;
|
||||
}
|
15
coreutils/sleep.c
Normal file
15
coreutils/sleep.c
Normal file
@@ -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;
|
||||
}
|
11
coreutils/sync.c
Normal file
11
coreutils/sync.c
Normal file
@@ -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();
|
||||
}
|
20
coreutils/touch.c
Normal file
20
coreutils/touch.c
Normal file
@@ -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;
|
||||
}
|
Reference in New Issue
Block a user