Initial revision

This commit is contained in:
Eric Andersen
1999-10-05 16:24:54 +00:00
commit cc8ed39b24
113 changed files with 24504 additions and 0 deletions

54
coreutils/cat.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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",
&ltm_time.tm_mon,
&ltm_time.tm_mday,
&ltm_time.tm_hour,
&ltm_time.tm_min) == 4) {
ltm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
*tm_time = ltm_time;
return(tm_time);
} else if (sscanf(t_string, "%d.%d.%d-%d:%d:%d",
&mtm_time.tm_year,
&mtm_time.tm_mon,
&mtm_time.tm_mday,
&mtm_time.tm_hour,
&mtm_time.tm_min,
&mtm_time.tm_sec) == 6) {
mtm_time.tm_year -= 1900; /* Adjust years */
mtm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
*tm_time = mtm_time;
return(tm_time);
} else if (sscanf(t_string, "%d.%d.%d-%d:%d",
&ntm_time.tm_year,
&ntm_time.tm_mon,
&ntm_time.tm_mday,
&ntm_time.tm_hour,
&ntm_time.tm_min) == 5) {
ntm_time.tm_year -= 1900; /* Adjust years */
ntm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
*tm_time = ntm_time;
return(tm_time);
}
fprintf(stderr, "date: invalid date `%s'\n", t_string);
exit(1);
}
void
date_err(void) {
fprintf(stderr, "date: only one date argument can be given at a time.\n");
exit(1);
}
int
date_main(struct FileInfo * i, int argc, char * * argv)
{
char *date_str = NULL;
char *date_fmt = NULL;
char *t_buff;
int set_time = 0;
int rfc822 = 0;
int utc = 0;
int use_arg = 0;
int n_args;
time_t tm;
struct tm tm_time;
char optc;
/* Interpret command line args */
while ((optc = getopt_long (argc, argv, "d:Rs:u", long_options, NULL))
!= EOF) {
switch (optc) {
case 0:
break;
case 'R':
rfc822 = 1;
break;
case 's':
set_time = 1;
if(date_str != NULL) date_err();
date_str = optarg;
break;
case 'u':
utc = 1;
if (putenv ("TZ=UTC0") != 0) {
fprintf(stderr,"date: memory exhausted\n");
return(1);
}
#if LOCALTIME_CACHE
tzset ();
#endif break;
case 'd':
use_arg = 1;
if(date_str != NULL) date_err();
date_str = optarg;
break;
default:
usage(date_usage);
break;
}
}
n_args = argc - optind;
while (n_args--){
switch(argv[optind][0]) {
case '+':
/* Date format strings */
if(date_fmt != NULL) {
fprintf(stderr, "date: only one date format can be given.\n");
return(1);
}
date_fmt = &argv[optind][1];
break;
case '\0':
break;
default:
/* Anything left over must be a date string to set the time */
set_time = 1;
if(date_str != NULL) date_err();
date_str = argv[optind];
break;
}
optind++;
}
/* Now we have parsed all the information except the date format
which depends on whether the clock is being set or read */
time(&tm);
memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
/* Zero out fields - take her back to midnight!*/
if(date_str != NULL) {
tm_time.tm_sec = 0;
tm_time.tm_min = 0;
tm_time.tm_hour = 0;
}
/* Process any date input to UNIX time since 1 Jan 1970 */
if(date_str != NULL) {
if(strchr(date_str, ':') != NULL) {
date_conv_ftime(&tm_time, date_str);
} else {
date_conv_time(&tm_time, date_str);
}
/* Correct any day of week and day of year etc fields */
tm = mktime(&tm_time);
if (tm < 0 ) {
fprintf(stderr, "date: invalid date `%s'\n", date_str);
exit(1);
}
/* if setting time, set it */
if(set_time) {
if( stime(&tm) < 0) {
fprintf(stderr, "date: can't set date.\n");
exit(1);
}
}
}
/* Display output */
/* Deal with format string */
if(date_fmt == NULL) {
date_fmt = (rfc822
? (utc
? "%a, %_d %b %Y %H:%M:%S GMT"
: "%a, %_d %b %Y %H:%M:%S %z")
: "%a %b %e %H:%M:%S %Z %Y");
} else if ( *date_fmt == '\0' ) {
/* Imitate what GNU 'date' does with NO format string! */
printf ("\n");
return(0);
}
/* Handle special conversions */
if( strncmp( date_fmt, "%f", 2) == 0 ) {
date_fmt = "%Y.%m.%d-%H:%M:%S";
}
/* Print OUTPUT (after ALL that!) */
t_buff = malloc(201);
strftime(t_buff, 200, date_fmt, &tm_time);
printf("%s\n", t_buff);
return(0);
}

307
coreutils/dd.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}