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

1
.cvsignore Normal file
View File

@ -0,0 +1 @@
busybox

8
Changelog Normal file
View File

@ -0,0 +1,8 @@
0.27
Mount now supports -a, and -t auto.
Mount now updates mtab correctly for 'ro'.
More checks screen rows size, outputs bytes percentage.
Printf added as module.
0.26
Touch now creates files. -c option for no create.

24
LICENSE Normal file
View File

@ -0,0 +1,24 @@
Original release code (unless otherwise noted)
Copyright 1995, 1996 Bruce Perens <bruce@pixar.com>
mkswap
Copyright 1991 Linus Torvalds
tiny-ls(ls)
Copyright 1996 Brian Candler <B.Candler@pobox.com>
tarcat, loadkmap, various fixes, Debian maintenance
Copyright 1998 Enrique Zanardi <ezanardi@ull.es>
more(v2), makedevs, dutmp, modularization, auto links file,
various fixes, Linux Router Project maintenance
Copyright 1998 Dave Cinege <dcinege@psychosis.com>
mini-gzip(gzip), mini-netcat(mnc)
Copyright 1998 Charles P. Wright <cpwright@villagenet.com>
Please see the top of the source files for more precise indivigual
copyright and license info.
This program suite may be distributed under the GNU General Public License.

38
Makefile Normal file
View File

@ -0,0 +1,38 @@
VERSION=0.29alpha1
BUILDTIME=$(shell date "+%Y%m%d-%H%M")
#This will choke on a non-debian system
ARCH=`uname -m | sed -e 's/i.86/i386/' | sed -e 's/sparc.*/sparc/'`
STRIP= strip --remove-section=.note --remove-section=.comment busybox
LDFLAGS= -s
# -D_GNU_SOURCE is needed because environ is used in init.c
CFLAGS=-Wall -O2 -fomit-frame-pointer -fno-builtin -D_GNU_SOURCE
# For debugging only
#CFLAGS=-Wall -g -D_GNU_SOURCE
LIBRARIES=-lc
OBJECTS=$(shell ./busybox.obj) utility.o
CFLAGS+= -DBB_VER='"$(VERSION)"'
CFLAGS+= -DBB_BT='"$(BUILDTIME)"'
#all: busybox links
all: busybox
busybox: $(OBJECTS)
$(CC) $(CFLAGS) $(LDFLAGS) -o busybox $(OBJECTS) $(LIBRARIES)
#$(STRIP)
links:
- ./busybox.mkll | sort >busybox.links
clean:
- rm -f busybox busybox.links *~ *.o
distclean: clean
- rm -f busybox
force:

27
README Normal file
View File

@ -0,0 +1,27 @@
Please see the LICENSE file for copyright information.
Busybox is a multicall binary used to provide a minimal subset of
POSIX style commands and specialized functions.
It is geared toward 'mini-systems' like boot floppies. Specifically
it is used in the Debian Rescue/Install system (which caused the
original busybox to be made), the Linux Router Project, and others.
As of version 0.20 there is a version number. : )
Also as of version 0.20, BB is modularized to allow an easy build of
only the BB parts you need, to reduce binary size.
Edit the file busybox.def.h and comment out the parts you do not need
using C++ comments (//)
After the build is complete a busybox.links file is generated to allow
you to easily make the sym/hard links to the busybox binary.
Note the modular system is Makefile based, and purposly very
simplistic. It does no dependency checking. That is left for you
to figure out by trial and error.
Please feed patches back to:
Dave Cinege <dcinege@psychosis.com>
and:
Enrique Zanardi <ezanardi@ull.es>

230
applets/busybox.c Normal file
View File

@ -0,0 +1,230 @@
#include "internal.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
static int been_there_done_that = 0;
static const struct Applet applets[] = {
#ifdef BB_BUSYBOX //bin
{"busybox", busybox_main},
#endif
#ifdef BB_BLOCK_DEVICE //sbin
{"block_device", block_device_main},
#endif
#ifdef BB_CAT //bin
{"cat", cat_more_main},
#endif
#ifdef BB_CHGRP //bin
{"chgrp", chgrp_main},
#endif
#ifdef BB_CHMOD //bin
{"chmod", chmod_main},
#endif
#ifdef BB_CHOWN //bin
{"chown", chown_main},
#endif
#ifdef BB_CHROOT //sbin
{"chroot", chroot_main},
#endif
#ifdef BB_CLEAR //usr/bin
{"clear", clear_main},
#endif
#ifdef BB_CP //bin
{"cp", dyadic_main},
#endif
#ifdef BB_DATE //bin
{"date", date_main},
#endif
#ifdef BB_DD //bin
{"dd", dd_main},
#endif
#ifdef BB_DF //bin
{"df", df_main},
#endif
#ifdef BB_DMESG //bin
{"dmesg", dmesg_main},
#endif
#ifdef BB_DUTMP //usr/sbin
{"dutmp", cat_more_main},
#endif
#ifdef BB_FALSE //bin
{"false", false_main},
#endif
#ifdef BB_FDFLUSH //bin
{"fdflush", monadic_main},
#endif
#ifdef BB_FIND //usr/bin
{"find", find_main},
#endif
#ifdef BB_GREP //bin
{"grep", grep_main},
#endif
#ifdef BB_HALT //sbin
{"halt", halt_main},
#endif
#ifdef BB_INIT //sbin
{"init", init_main},
#endif
#ifdef BB_KILL //bin
{"kill", kill_main},
#endif
#ifdef BB_LENGTH //usr/bin
{"length", length_main},
#endif
#ifdef BB_LN //bin
{"ln", dyadic_main},
#endif
#ifdef BB_LOADKMAP //sbin
{"loadkmap", loadkmap_main},
#endif
#ifdef BB_LOSETUP //sbin
{"losetup", losetup_main},
#endif
#ifdef BB_LS //bin
{"ls", ls_main},
#endif
#ifdef BB_MAKEDEVS //sbin
{"makedevs", makedevs_main},
#endif
#ifdef BB_MATH //usr/bin
{"math", math_main},
#endif
#ifdef BB_MKDIR //bin
{"mkdir", monadic_main},
#endif
#ifdef BB_MKNOD //bin
{"mknod", mknod_main},
#endif
#ifdef BB_MKSWAP //sbin
{"mkswap", mkswap_main},
#endif
#ifdef BB_MNC //usr/bin
{"mnc", mnc_main},
#endif
#ifdef BB_MORE //bin
{"more", cat_more_main},
#endif
#ifdef BB_MOUNT //bin
{"mount", mount_main},
#endif
#ifdef BB_MT //bin
{"mt", mt_main},
#endif
#ifdef BB_MV //bin
{"mv", dyadic_main},
#endif
#ifdef BB_PRINTF //usr/bin
{"printf", printf_main},
#endif
#ifdef BB_PWD //bin
{"pwd", pwd_main},
#endif
#ifdef BB_REBOOT //sbin
{"reboot", reboot_main},
#endif
#ifdef BB_RM //bin
{"rm", rm_main},
#endif
#ifdef BB_RMDIR //bin
{"rmdir", monadic_main},
#endif
#ifdef BB_SLEEP //bin
{"sleep", sleep_main},
#endif
#ifdef BB_TAR //bin
{"tar", tar_main},
#endif
#ifdef BB_SWAPOFF //sbin
{"swapoff", monadic_main},
#endif
#ifdef BB_SWAPON //sbin
{"swapon", monadic_main},
#endif
#ifdef BB_SYNC //bin
{"sync", sync_main},
#endif
#ifdef BB_TOUCH //usr/bin
{"touch", monadic_main},
#endif
#ifdef BB_TRUE //bin
{"true", true_main},
#endif
#ifdef BB_UMOUNT //bin
{"umount", umount_main},
#endif
#ifdef BB_UPDATE //sbin
{"update", update_main},
#endif
#ifdef BB_ZCAT //bin
{"zcat", zcat_main},
{"gunzip", zcat_main},
#endif
#ifdef BB_GZIP //bin
{"gzip", gzip_main},
#endif
{0}
};
int main(int argc, char **argv)
{
char *s = argv[0];
char *name = argv[0];
const struct Applet *a = applets;
while (*s != '\0') {
if (*s++ == '/')
name = s;
}
while (a->name != 0) {
if (strcmp(name, a->name) == 0) {
int status;
status = ((*(a->main)) (argc, argv));
if (status < 0) {
fprintf(stderr, "%s: %s\n", a->name, strerror(errno));
}
fprintf(stderr, "\n");
exit(status);
}
a++;
}
return (busybox_main(argc, argv));
}
int busybox_main(int argc, char **argv)
{
argc--;
argv++;
/* If we've already been here once, exit now */
if (been_there_done_that == 1)
return -1;
been_there_done_that = 1;
if (argc < 1) {
const struct Applet *a = applets;
fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n",
BB_VER, BB_BT);
fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
fprintf(stderr,
"\n\tMost people will create a symlink to busybox for each\n"
"\tfunction name, and busybox will act like whatever you invoke it as.\n");
fprintf(stderr, "\nCurrently defined functions:\n");
if (a->name != 0) {
fprintf(stderr, "%s", a->name);
a++;
}
while (a->name != 0) {
fprintf(stderr, ", %s", a->name);
a++;
}
fprintf(stderr, "\n\n");
exit(-1);
} else
return (main(argc, argv));
}

17
applets/busybox.mkll Executable file
View File

@ -0,0 +1,17 @@
#!/bin/sh
#Make busybox links list file
DF="busybox.def.h"
MF="main.c"
LIST="$(sed -n '/^#define/{s/^#define //p;}' $DF)"
for def in ${LIST}; do
set -- $(sed -n '/^#ifdef '$def'[ +| +].*/,/^#endif/{s/.*\/\///p; /^{ /{ s/^{ "//; s/",.*$//p;}; }' $MF)
path=$1; shift
for n in $@; do
echo "$path/$n"
done
done

3231
archival/gzip.c Normal file

File diff suppressed because it is too large Load Diff

1425
archival/tar.c Normal file

File diff suppressed because it is too large Load Diff

64
block_device.c Normal file
View File

@ -0,0 +1,64 @@
#include "internal.h"
#include <dirent.h>
#include <string.h>
#include <stdio.h>
const char block_device_usage[] = "block_device mount-point";
static dev_t *my_device;
static char *my_device_name;
int
match_mount(const struct FileInfo * i) {
if ( S_ISBLK(i->stat.st_mode)
&& (i->stat.st_rdev == *my_device)) {
my_device_name=strdup(i->source);
return 1;
} else
return 0;
}
extern int
block_device_main(struct FileInfo * i, int argc, char * * argv)
{
char *device_name = block_device(argv[1],i);
if ( device_name == NULL )
return -1;
printf("%s\n", device_name);
exit(0);
}
char * block_device(const char *name, struct FileInfo *i)
{
struct stat s;
char *buf;
int dinam=0;
if ( stat(name, &s) ) return (char *) NULL;
if (!i) {
i=(struct FileInfo*)malloc(sizeof(struct FileInfo));
dinam = 1;
}
memset((void *)i, 0, sizeof(struct FileInfo));
my_device=(dev_t *)malloc(sizeof(dev_t));
*my_device = s.st_dev;
my_device_name = NULL;
i->source = "/dev";
i->stat = s;
i->processDirectoriesAfterTheirContents=1;
descend(i, match_mount);
if (dinam) free(i);
if ( my_device_name ) {
buf = strdup(my_device_name);
free(my_device);
free(my_device_name);
return buf;
} else {
fprintf( stderr
,"Can't find special file for block device %d, %d.\n"
,(int) *my_device >> 8 & 0xff
,(int) *my_device & 0xff);
free(my_device);
return (char *) NULL;
}
}

230
busybox.c Normal file
View File

@ -0,0 +1,230 @@
#include "internal.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
static int been_there_done_that = 0;
static const struct Applet applets[] = {
#ifdef BB_BUSYBOX //bin
{"busybox", busybox_main},
#endif
#ifdef BB_BLOCK_DEVICE //sbin
{"block_device", block_device_main},
#endif
#ifdef BB_CAT //bin
{"cat", cat_more_main},
#endif
#ifdef BB_CHGRP //bin
{"chgrp", chgrp_main},
#endif
#ifdef BB_CHMOD //bin
{"chmod", chmod_main},
#endif
#ifdef BB_CHOWN //bin
{"chown", chown_main},
#endif
#ifdef BB_CHROOT //sbin
{"chroot", chroot_main},
#endif
#ifdef BB_CLEAR //usr/bin
{"clear", clear_main},
#endif
#ifdef BB_CP //bin
{"cp", dyadic_main},
#endif
#ifdef BB_DATE //bin
{"date", date_main},
#endif
#ifdef BB_DD //bin
{"dd", dd_main},
#endif
#ifdef BB_DF //bin
{"df", df_main},
#endif
#ifdef BB_DMESG //bin
{"dmesg", dmesg_main},
#endif
#ifdef BB_DUTMP //usr/sbin
{"dutmp", cat_more_main},
#endif
#ifdef BB_FALSE //bin
{"false", false_main},
#endif
#ifdef BB_FDFLUSH //bin
{"fdflush", monadic_main},
#endif
#ifdef BB_FIND //usr/bin
{"find", find_main},
#endif
#ifdef BB_GREP //bin
{"grep", grep_main},
#endif
#ifdef BB_HALT //sbin
{"halt", halt_main},
#endif
#ifdef BB_INIT //sbin
{"init", init_main},
#endif
#ifdef BB_KILL //bin
{"kill", kill_main},
#endif
#ifdef BB_LENGTH //usr/bin
{"length", length_main},
#endif
#ifdef BB_LN //bin
{"ln", dyadic_main},
#endif
#ifdef BB_LOADKMAP //sbin
{"loadkmap", loadkmap_main},
#endif
#ifdef BB_LOSETUP //sbin
{"losetup", losetup_main},
#endif
#ifdef BB_LS //bin
{"ls", ls_main},
#endif
#ifdef BB_MAKEDEVS //sbin
{"makedevs", makedevs_main},
#endif
#ifdef BB_MATH //usr/bin
{"math", math_main},
#endif
#ifdef BB_MKDIR //bin
{"mkdir", monadic_main},
#endif
#ifdef BB_MKNOD //bin
{"mknod", mknod_main},
#endif
#ifdef BB_MKSWAP //sbin
{"mkswap", mkswap_main},
#endif
#ifdef BB_MNC //usr/bin
{"mnc", mnc_main},
#endif
#ifdef BB_MORE //bin
{"more", cat_more_main},
#endif
#ifdef BB_MOUNT //bin
{"mount", mount_main},
#endif
#ifdef BB_MT //bin
{"mt", mt_main},
#endif
#ifdef BB_MV //bin
{"mv", dyadic_main},
#endif
#ifdef BB_PRINTF //usr/bin
{"printf", printf_main},
#endif
#ifdef BB_PWD //bin
{"pwd", pwd_main},
#endif
#ifdef BB_REBOOT //sbin
{"reboot", reboot_main},
#endif
#ifdef BB_RM //bin
{"rm", rm_main},
#endif
#ifdef BB_RMDIR //bin
{"rmdir", monadic_main},
#endif
#ifdef BB_SLEEP //bin
{"sleep", sleep_main},
#endif
#ifdef BB_TAR //bin
{"tar", tar_main},
#endif
#ifdef BB_SWAPOFF //sbin
{"swapoff", monadic_main},
#endif
#ifdef BB_SWAPON //sbin
{"swapon", monadic_main},
#endif
#ifdef BB_SYNC //bin
{"sync", sync_main},
#endif
#ifdef BB_TOUCH //usr/bin
{"touch", monadic_main},
#endif
#ifdef BB_TRUE //bin
{"true", true_main},
#endif
#ifdef BB_UMOUNT //bin
{"umount", umount_main},
#endif
#ifdef BB_UPDATE //sbin
{"update", update_main},
#endif
#ifdef BB_ZCAT //bin
{"zcat", zcat_main},
{"gunzip", zcat_main},
#endif
#ifdef BB_GZIP //bin
{"gzip", gzip_main},
#endif
{0}
};
int main(int argc, char **argv)
{
char *s = argv[0];
char *name = argv[0];
const struct Applet *a = applets;
while (*s != '\0') {
if (*s++ == '/')
name = s;
}
while (a->name != 0) {
if (strcmp(name, a->name) == 0) {
int status;
status = ((*(a->main)) (argc, argv));
if (status < 0) {
fprintf(stderr, "%s: %s\n", a->name, strerror(errno));
}
fprintf(stderr, "\n");
exit(status);
}
a++;
}
return (busybox_main(argc, argv));
}
int busybox_main(int argc, char **argv)
{
argc--;
argv++;
/* If we've already been here once, exit now */
if (been_there_done_that == 1)
return -1;
been_there_done_that = 1;
if (argc < 1) {
const struct Applet *a = applets;
fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n",
BB_VER, BB_BT);
fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
fprintf(stderr,
"\n\tMost people will create a symlink to busybox for each\n"
"\tfunction name, and busybox will act like whatever you invoke it as.\n");
fprintf(stderr, "\nCurrently defined functions:\n");
if (a->name != 0) {
fprintf(stderr, "%s", a->name);
a++;
}
while (a->name != 0) {
fprintf(stderr, ", %s", a->name);
a++;
}
fprintf(stderr, "\n\n");
exit(-1);
} else
return (main(argc, argv));
}

64
busybox.def.h Normal file
View File

@ -0,0 +1,64 @@
/*
* This file is parsed by sed. You MUST use single line comments.
* IE //#define BB_BLAH
*/
//#define BB_BLOCK_DEVICE
#define BB_BUSYBOX
#define BB_CAT
#define BB_CHGRP
//#define BB_CHMOD
//#define BB_CHOWN
//#define BB_CHROOT
//#define BB_CLEAR
//#define BB_CP
//#define BB_DATE
//#define BB_DD
//#define BB_DESCEND
//#define BB_DF
//#define BB_DMESG
//#define BB_DUTMP
//#define BB_DYADIC
//#define BB_FALSE
//#define BB_FDFLUSH
//#define BB_FIND
//#define BB_FINDMOUNT
//#define BB_GREP
////#define BB_HALT
//#define BB_INIT
//#define BB_KILL
////#define BB_LENGTH
//#define BB_LN
//#define BB_LOADKMAP
////#define BB_LOSETUP
//#define BB_LS
//#define BB_MAIN
//#define BB_MAKEDEVS
////#define BB_MATH
//#define BB_MKDIR
//#define BB_MKNOD
////#define BB_MKSWAP
//#define BB_MNC
//#define BB_MONADIC
//#define BB_MORE
//#define BB_MOUNT
////#define BB_MT
//#define BB_MV
//#define BB_POSTPROCESS
//#define BB_PRINTF
//#define BB_PWD
//#define BB_REBOOT
//#define BB_RM
//#define BB_RMDIR
//#define BB_SLEEP
////#define BB_SWAPOFF
//#define BB_SWAPON
//#define BB_SYNC
//#define BB_TAR
//#define BB_TOUCH
//#define BB_TRUE
//#define BB_UMOUNT
//#define BB_UPDATE
//#define BB_UTILITY
//#define BB_ZCAT
//#define BB_GZIP

17
busybox.mkll Executable file
View File

@ -0,0 +1,17 @@
#!/bin/sh
#Make busybox links list file
DF="busybox.def.h"
MF="main.c"
LIST="$(sed -n '/^#define/{s/^#define //p;}' $DF)"
for def in ${LIST}; do
set -- $(sed -n '/^#ifdef '$def'[ +| +].*/,/^#endif/{s/.*\/\///p; /^{ /{ s/^{ "//; s/",.*$//p;}; }' $MF)
path=$1; shift
for n in $@; do
echo "$path/$n"
done
done

43
busybox.spec Normal file
View File

@ -0,0 +1,43 @@
Name: busybox
Version: 0.29alpha
Release: 1
Group: System/Utilities
Summary: BusyBox is a tiny suite of Unix utilities in a multi-call binary.
Copyright: GPL
Packager : Erik Andersen <andersen@lineo.com>
Conflicts: fileutils grep shellutils
Buildroot: /tmp/%{Name}-%{Version}
Source: busybox-0.29a1.tar.gz
%Description
BusyBox is a suite of "tiny" Unix utilities in a multi-call binary. It
provides a pretty complete environment that fits on a floppy or in a
ROM. Just add "ash" (Keith Almquists tiny Bourne shell clone) and "ae",
and a kernel and you have a full system. This is used on the Debian
install disk and in an internet router, and it makes a good environment
for a "rescue" disk or any small or embedded system.
%Prep
%setup -q -n busybox
%Build
make
%Install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/bin
h=`cat busybox.links`
for i in $h ; do
mkdir -p $RPM_BUILD_ROOT/`echo $i | sed -e 's/\(^.*\/\)\(.*\)/\1/g' `
(cd $RPM_BUILD_ROOT/bin ; ln -s ln `echo $i | sed -e 's/\(^.*\/\)\(.*\)/\2/g' ` );
done
rm -f $RPM_BUILD_ROOT/bin/ln
install -m 755 busybox $RPM_BUILD_ROOT/bin/ln
%Clean
rm -rf $RPM_BUILD_ROOT
%Files
%defattr(-,root,root)
/

11
busybox_functions.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef __BUSYBOX_FUNCTIONS_H__
#define __BUSYBOX_FUNCTIONS_H__
int
mkswap(char *device_name, int pages, int check);
/* pages = 0 for autodetection */
int
fdflush(char *filename);
#endif /* __BUSYBOX_FUNCTIONS_H__ */

54
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
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
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
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
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;
}

13
clear.c Normal file
View File

@ -0,0 +1,13 @@
#include "internal.h"
#include <stdio.h>
const char clear_usage[] = "clear\n"
"\n"
"\tClears the screen.\n";
extern int
clear_main(struct FileInfo * i, int argc, char * * argv)
{
printf("\033[H\033[J");
return 0;
}

13
console-tools/clear.c Normal file
View File

@ -0,0 +1,13 @@
#include "internal.h"
#include <stdio.h>
const char clear_usage[] = "clear\n"
"\n"
"\tClears the screen.\n";
extern int
clear_main(struct FileInfo * i, int argc, char * * argv)
{
printf("\033[H\033[J");
return 0;
}

68
console-tools/loadkmap.c Normal file
View File

@ -0,0 +1,68 @@
#include "internal.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/kd.h>
#include <linux/keyboard.h>
#include <sys/ioctl.h>
const char loadkmap_usage[] = "loadkmap\n"
"\n"
"\tLoad a binary keyboard translation table from standard input.\n"
"\n";
int
loadkmap_main(struct FileInfo * info, int argc, char * * argv)
{
struct kbentry ke;
u_short *ibuff;
int i,j,fd,readsz,pos,ibuffsz=NR_KEYS * sizeof(u_short);
char flags[MAX_NR_KEYMAPS],magic[]="bkeymap",buff[7];
fd = open("/dev/tty0", O_RDWR);
if (fd < 0) {
fprintf(stderr, "Error opening /dev/tty0: %s\n", strerror(errno));
return 1;
}
read(0,buff,7);
if (0 != strncmp(buff,magic,7)) {
fprintf(stderr, "This is not a valid binary keymap.\n");
return 1;
}
if ( MAX_NR_KEYMAPS != read(0,flags,MAX_NR_KEYMAPS) ) {
fprintf(stderr, "Error reading keymap flags: %s\n", strerror(errno));
return 1;
}
ibuff=(u_short *) malloc(ibuffsz);
if (!ibuff) {
fprintf(stderr, "Out of memory.\n");
return 1;
}
for(i=0; i<MAX_NR_KEYMAPS; i++) {
if (flags[i]==1){
pos=0;
while (pos < ibuffsz) {
if ( (readsz = read(0,ibuff+pos,ibuffsz-pos)) < 0 ) {
fprintf(stderr, "Error reading keymap: %s\n",
strerror(errno));
return 1;
}
pos += readsz;
}
for(j=0; j<NR_KEYS; j++) {
ke.kb_index = j;
ke.kb_table = i;
ke.kb_value = ibuff[j];
ioctl(fd, KDSKBENT, &ke);
}
}
}
close (fd);
return 0;
}

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;
}

89
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
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
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 */

124
descend.c Normal file
View File

@ -0,0 +1,124 @@
#include "internal.h"
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
static int
noDots(const struct dirent * e)
{
if ( e->d_name[0] == '.'
&& (e->d_name[1] == '\0'
|| (e->d_name[1] == '.' && e->d_name[2] == '\0')) )
return 0;
else
return 1;
}
extern int
descend(
struct FileInfo *oldInfo
,int (*function)(const struct FileInfo * i))
{
char pathname[1024];
struct dirent * * names;
struct dirent * * n;
int length;
char * filename;
int status = 0;
int count;
if ( *oldInfo->source == '\0' ) {
errno = EINVAL;
return -1;
}
if ( oldInfo->stat.st_dev == 0
&& oldInfo->stat.st_ino == 0
&& oldInfo->stat.st_mode == 0 ) {
if ( lstat(oldInfo->source, &oldInfo->stat) != 0 )
return -1;
oldInfo->isSymbolicLink = ((oldInfo->stat.st_mode & S_IFMT) == S_IFLNK);
if ( oldInfo->isSymbolicLink )
if ( stat(oldInfo->source, &oldInfo->stat) != 0 )
memset((void *)&oldInfo->stat, 0, sizeof(oldInfo->stat));
}
if ( !oldInfo->processDirectoriesAfterTheirContents ) {
if ( function )
status = (*function)(oldInfo);
if ( status == 0 )
status = post_process(oldInfo);
}
if ( (count = scandir(oldInfo->source, &names, noDots, alphasort)) < 0 )
return -1;
length = strlen(oldInfo->source);
if ( oldInfo->source[length-1] == '/' )
length--;
memcpy(pathname, oldInfo->source, length+1);
pathname[length] = '/';
filename = &pathname[length+1];
n = names;
while ( count-- > 0 ) {
struct FileInfo i = *oldInfo;
strcpy(filename, (*n)->d_name);
free(*n++);
if ( lstat(pathname, &i.stat) != 0 && errno != ENOENT ) {
fprintf(stderr, "Can't stat %s: %s\n", pathname, strerror(errno));
return -1;
}
i.isSymbolicLink = ((i.stat.st_mode & S_IFMT) == S_IFLNK);
if ( i.isSymbolicLink )
if ( stat(pathname, &i.stat) != 0 )
memset((void *)&i.stat, 0, sizeof(i.stat));
i.source = pathname;
if ( i.dyadic ) {
char d[1024];
i.destination = join_paths(d, i.destination, &i.source[i.directoryLength]);
}
else
i.destination = i.source;
if ( !i.isSymbolicLink && (i.stat.st_mode & S_IFMT) == S_IFDIR )
status = descend(&i, function);
else {
if ( function )
status = (*function)(&i);
if ( status == 0 )
status = post_process(&i);
}
if ( !i.processDirectoriesAfterTheirContents
&& status == 0
&& (i.stat.st_mode & S_IFMT) == S_IFDIR )
descend(&i, function);
if ( status != 0 && !i.force ) {
while ( count-- > 0 )
free(*n++);
break;
}
}
free(names);
if ( oldInfo->processDirectoriesAfterTheirContents ) {
if ( function )
status = (*function)(oldInfo);
if ( status == 0 )
status = post_process(oldInfo);
}
return status;
}

103
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;
}

95
dmesg.c Normal file
View File

@ -0,0 +1,95 @@
#include "internal.h"
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
/* dmesg.c -- Print out the contents of the kernel ring buffer
* Created: Sat Oct 9 16:19:47 1993
* Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu
* Copyright 1993 Theodore Ts'o (tytso@athena.mit.edu)
* This program comes with ABSOLUTELY NO WARRANTY.
* Modifications by Rick Sladkey (jrs@world.std.com)
* from util-linux; adapted for busybox
*/
#include <linux/unistd.h>
#include <stdio.h>
#include <getopt.h>
#define __NR_klog __NR_syslog
#if defined(__GLIBC__)
#include <sys/klog.h>
#define klog klogctl
#else
static inline _syscall3(int,klog,int,type,char *,b,int,len)
#endif /* __GLIBC__ */
const char dmesg_usage[] = "dmesg";
int
dmesg_main(struct FileInfo * info, int argc, char * * argv)
{
char buf[4096];
int i;
int n;
int c;
int level = 0;
int lastc;
int cmd = 3;
while ((c = getopt( argc, argv, "cn:" )) != EOF) {
switch (c) {
case 'c':
cmd = 4;
break;
case 'n':
cmd = 8;
level = atoi(optarg);
break;
case '?':
default:
usage(dmesg_usage);
exit(1);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
usage(dmesg_usage);
exit(1);
}
if (cmd == 8) {
n = klog( cmd, NULL, level );
if (n < 0) {
perror( "klog" );
exit( 1 );
}
exit( 0 );
}
n = klog( cmd, buf, sizeof( buf ) );
if (n < 0) {
perror( "klog" );
exit( 1 );
}
lastc = '\n';
for (i = 0; i < n; i++) {
if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') {
i++;
while (buf[i] >= '0' && buf[i] <= '9')
i++;
if (buf[i] == '>')
i++;
}
lastc = buf[i];
putchar( lastc );
}
if (lastc != '\n')
putchar( '\n' );
return 0;
}

47
dutmp.c Normal file
View File

@ -0,0 +1,47 @@
/*
* public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
*
* dutmp
* Takes utmp formated file on stdin and dumps it's contents
* out in colon delimited fields. Easy to 'cut' for shell based
* versions of 'who', 'last', etc. IP Addr is output in hex,
* little endian on x86.
*
* made against libc6
*/
#include "internal.h"
#include <stdio.h>
#include <utmp.h>
const char dutmp_usage[] = "dutmp\n"
"\n"
"\tDump file or stdin utmp file format to stdout, pipe delimited.\n"
"\tdutmp /var/run/utmp\n";
extern int
dutmp_fn(const struct FileInfo * i)
{
FILE * f = stdin;
struct utmp * ut = (struct utmp *) malloc(sizeof(struct utmp) );
if ( i )
if (! (f = fopen(i->source, "r"))) {
name_and_error(i->source);
return 1;
}
while (fread (ut, 1, sizeof(struct utmp), f)) {
//printf("%d:%d:%s:%s:%s:%s:%d:%d:%ld:%ld:%ld:%x\n",
printf("%d|%d|%s|%s|%s|%s|%d|%d|%ld|%ld|%ld|%x\n",
ut->ut_type, ut->ut_pid, ut->ut_line,
ut->ut_id, ut->ut_user, ut->ut_host,
ut->ut_exit.e_termination, ut->ut_exit.e_exit,
ut->ut_session,
ut->ut_tv.tv_sec, ut->ut_tv.tv_usec,
ut->ut_addr);
}
return 0;
}

28
dyadic.c Normal file
View File

@ -0,0 +1,28 @@
#include "internal.h"
#include <stdio.h>
extern int
dyadic_main(
struct FileInfo * i
,int argc
,char * * argv)
{
int flags;
i->dyadic = 1;
i->destination = argv[argc - 1];
for ( flags = 0; flags < (argc - 1) && argv[flags + 1][0] == '-' ; flags++ )
;
if ( argc - flags < 3 ) {
usage(i->applet->usage);
return 1;
}
else if ( argc - flags > 3 ) {
if ( !is_a_directory(i->destination) ) {
fprintf(stderr, "%s: not a directory.\n", i->destination);
return 1;
}
}
return monadic_main(i, argc - 1, argv);
}

43
examples/busybox.spec Normal file
View File

@ -0,0 +1,43 @@
Name: busybox
Version: 0.29alpha
Release: 1
Group: System/Utilities
Summary: BusyBox is a tiny suite of Unix utilities in a multi-call binary.
Copyright: GPL
Packager : Erik Andersen <andersen@lineo.com>
Conflicts: fileutils grep shellutils
Buildroot: /tmp/%{Name}-%{Version}
Source: busybox-0.29a1.tar.gz
%Description
BusyBox is a suite of "tiny" Unix utilities in a multi-call binary. It
provides a pretty complete environment that fits on a floppy or in a
ROM. Just add "ash" (Keith Almquists tiny Bourne shell clone) and "ae",
and a kernel and you have a full system. This is used on the Debian
install disk and in an internet router, and it makes a good environment
for a "rescue" disk or any small or embedded system.
%Prep
%setup -q -n busybox
%Build
make
%Install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/bin
h=`cat busybox.links`
for i in $h ; do
mkdir -p $RPM_BUILD_ROOT/`echo $i | sed -e 's/\(^.*\/\)\(.*\)/\1/g' `
(cd $RPM_BUILD_ROOT/bin ; ln -s ln `echo $i | sed -e 's/\(^.*\/\)\(.*\)/\2/g' ` );
done
rm -f $RPM_BUILD_ROOT/bin/ln
install -m 755 busybox $RPM_BUILD_ROOT/bin/ln
%Clean
rm -rf $RPM_BUILD_ROOT
%Files
%defattr(-,root,root)
/

36
fdflush.c Normal file
View File

@ -0,0 +1,36 @@
#include "internal.h"
#include <sys/ioctl.h>
#include <linux/fd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
const char fdflush_usage[] = "fdflush device";
int
fdflush(const char *filename)
{
int status;
int fd = open(filename, 0);
if ( fd < 0 ) {
name_and_error(filename);
return 1;
}
status = ioctl(fd, FDFLUSH, 0);
close(fd);
if ( status != 0 ) {
name_and_error(filename);
return 1;
}
return 0;
}
int
fdflush_fn(const struct FileInfo * i)
{
return fdflush(i->source);
}

23
find.c Normal file
View File

@ -0,0 +1,23 @@
#include "internal.h"
#include <errno.h>
#include <stdio.h>
const char find_usage[] = "find dir [pattern]\n"
"\n"
"\tFind files.\n";
extern int
find_main(struct FileInfo * i, int argc, char * * argv)
{
i->recursive=1;
i->processDirectoriesAfterTheirContents=1;
return monadic_main(i, argc, argv);
}
extern int
find_fn(const struct FileInfo * i)
{
printf("%s\n",i->source);
return(0);
}

46
findmount.c Normal file
View File

@ -0,0 +1,46 @@
#include "internal.h"
#include <stdio.h>
#include <mntent.h>
#include <sys/stat.h>
/*
* Given a block device, find the mount table entry if that block device
* is mounted.
*
* Given any other file (or directory), find the mount table entry for its
* filesystem.
*/
extern struct mntent *
findMountPoint(const char * name, const char * table)
{
struct stat s;
dev_t mountDevice;
FILE * mountTable;
struct mntent * mountEntry;
if ( stat(name, &s) != 0 )
return 0;
if ( (s.st_mode & S_IFMT) == S_IFBLK )
mountDevice = s.st_rdev;
else
mountDevice = s.st_dev;
if ( (mountTable = setmntent(table, "r")) == 0 )
return 0;
while ( (mountEntry = getmntent(mountTable)) != 0 ) {
if ( strcmp(name, mountEntry->mnt_dir) == 0
|| strcmp(name, mountEntry->mnt_fsname) == 0 ) /* String match. */
break;
if ( stat(mountEntry->mnt_fsname, &s) == 0
&& s.st_rdev == mountDevice ) /* Match the device. */
break;
if ( stat(mountEntry->mnt_dir, &s) == 0
&& s.st_dev == mountDevice ) /* Match the directory's mount point. */
break;
}
endmntent(mountTable);
return mountEntry;
}

23
findutils/find.c Normal file
View File

@ -0,0 +1,23 @@
#include "internal.h"
#include <errno.h>
#include <stdio.h>
const char find_usage[] = "find dir [pattern]\n"
"\n"
"\tFind files.\n";
extern int
find_main(struct FileInfo * i, int argc, char * * argv)
{
i->recursive=1;
i->processDirectoriesAfterTheirContents=1;
return monadic_main(i, argc, argv);
}
extern int
find_fn(const struct FileInfo * i)
{
printf("%s\n",i->source);
return(0);
}

210
findutils/grep.c Normal file
View File

@ -0,0 +1,210 @@
/*
* 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 "grep" command, taken from sash.
* This provides basic file searching.
*
* Permission to distribute this code under the GPL has been granted.
* Modified for busybox by Erik Andersen <andersee@debian.org> <andersen@lineo.com>
*/
#include "internal.h"
#ifdef BB_GREP
#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <ctype.h>
const char grep_usage[] =
"Search the input file(s) for lines matching the given pattern.\n"
"\tI search stdin if no files are given.\n"
"\tI can't grok full regular expressions.\n"
"usage: grep [in] PATTERN [FILES]...\n"
"\ti=ignore case, n=list line numbers\n";
static BOOL search
(const char * string, const char * word, BOOL ignoreCase);
extern int
grep_main(struct FileInfo * unused, int argc, char ** argv)
{
FILE * fp;
const char * word;
const char * name;
const char * cp;
BOOL tellName;
BOOL ignoreCase;
BOOL tellLine;
long line;
char buf[BUF_SIZE];
ignoreCase = FALSE;
tellLine = FALSE;
argc--;
argv++;
if (argc < 1)
{
fprintf(stderr, "%s", grep_usage);
return 1;
}
if (**argv == '-')
{
argc--;
cp = *argv++;
while (*++cp) switch (*cp)
{
case 'i':
ignoreCase = TRUE;
break;
case 'n':
tellLine = TRUE;
break;
default:
fprintf(stderr, "Unknown option\n");
return 1;
}
}
word = *argv++;
argc--;
tellName = (argc > 1);
while (argc-- > 0)
{
name = *argv++;
fp = fopen(name, "r");
if (fp == NULL)
{
perror(name);
continue;
}
line = 0;
while (fgets(buf, sizeof(buf), fp))
{
line++;
cp = &buf[strlen(buf) - 1];
if (*cp != '\n')
fprintf(stderr, "%s: Line too long\n", name);
if (search(buf, word, ignoreCase))
{
if (tellName)
printf("%s: ", name);
if (tellLine)
printf("%ld: ", line);
fputs(buf, stdout);
}
}
if (ferror(fp))
perror(name);
fclose(fp);
}
return 0;
}
/*
* See if the specified word is found in the specified string.
*/
static BOOL
search(const char * string, const char * word, BOOL ignoreCase)
{
const char * cp1;
const char * cp2;
int len;
int lowFirst;
int ch1;
int ch2;
len = strlen(word);
if (!ignoreCase)
{
while (TRUE)
{
string = strchr(string, word[0]);
if (string == NULL)
return FALSE;
if (memcmp(string, word, len) == 0)
return TRUE;
string++;
}
}
/*
* Here if we need to check case independence.
* Do the search by lower casing both strings.
*/
lowFirst = *word;
if (isupper(lowFirst))
lowFirst = tolower(lowFirst);
while (TRUE)
{
while (*string && (*string != lowFirst) &&
(!isupper(*string) || (tolower(*string) != lowFirst)))
{
string++;
}
if (*string == '\0')
return FALSE;
cp1 = string;
cp2 = word;
do
{
if (*cp2 == '\0')
return TRUE;
ch1 = *cp1++;
if (isupper(ch1))
ch1 = tolower(ch1);
ch2 = *cp2++;
if (isupper(ch2))
ch2 = tolower(ch2);
}
while (ch1 == ch2);
string++;
}
}
#endif
/* END CODE */

210
grep.c Normal file
View File

@ -0,0 +1,210 @@
/*
* 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 "grep" command, taken from sash.
* This provides basic file searching.
*
* Permission to distribute this code under the GPL has been granted.
* Modified for busybox by Erik Andersen <andersee@debian.org> <andersen@lineo.com>
*/
#include "internal.h"
#ifdef BB_GREP
#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <ctype.h>
const char grep_usage[] =
"Search the input file(s) for lines matching the given pattern.\n"
"\tI search stdin if no files are given.\n"
"\tI can't grok full regular expressions.\n"
"usage: grep [in] PATTERN [FILES]...\n"
"\ti=ignore case, n=list line numbers\n";
static BOOL search
(const char * string, const char * word, BOOL ignoreCase);
extern int
grep_main(struct FileInfo * unused, int argc, char ** argv)
{
FILE * fp;
const char * word;
const char * name;
const char * cp;
BOOL tellName;
BOOL ignoreCase;
BOOL tellLine;
long line;
char buf[BUF_SIZE];
ignoreCase = FALSE;
tellLine = FALSE;
argc--;
argv++;
if (argc < 1)
{
fprintf(stderr, "%s", grep_usage);
return 1;
}
if (**argv == '-')
{
argc--;
cp = *argv++;
while (*++cp) switch (*cp)
{
case 'i':
ignoreCase = TRUE;
break;
case 'n':
tellLine = TRUE;
break;
default:
fprintf(stderr, "Unknown option\n");
return 1;
}
}
word = *argv++;
argc--;
tellName = (argc > 1);
while (argc-- > 0)
{
name = *argv++;
fp = fopen(name, "r");
if (fp == NULL)
{
perror(name);
continue;
}
line = 0;
while (fgets(buf, sizeof(buf), fp))
{
line++;
cp = &buf[strlen(buf) - 1];
if (*cp != '\n')
fprintf(stderr, "%s: Line too long\n", name);
if (search(buf, word, ignoreCase))
{
if (tellName)
printf("%s: ", name);
if (tellLine)
printf("%ld: ", line);
fputs(buf, stdout);
}
}
if (ferror(fp))
perror(name);
fclose(fp);
}
return 0;
}
/*
* See if the specified word is found in the specified string.
*/
static BOOL
search(const char * string, const char * word, BOOL ignoreCase)
{
const char * cp1;
const char * cp2;
int len;
int lowFirst;
int ch1;
int ch2;
len = strlen(word);
if (!ignoreCase)
{
while (TRUE)
{
string = strchr(string, word[0]);
if (string == NULL)
return FALSE;
if (memcmp(string, word, len) == 0)
return TRUE;
string++;
}
}
/*
* Here if we need to check case independence.
* Do the search by lower casing both strings.
*/
lowFirst = *word;
if (isupper(lowFirst))
lowFirst = tolower(lowFirst);
while (TRUE)
{
while (*string && (*string != lowFirst) &&
(!isupper(*string) || (tolower(*string) != lowFirst)))
{
string++;
}
if (*string == '\0')
return FALSE;
cp1 = string;
cp2 = word;
do
{
if (*cp2 == '\0')
return TRUE;
ch1 = *cp1++;
if (isupper(ch1))
ch1 = tolower(ch1);
ch2 = *cp2++;
if (isupper(ch2))
ch2 = tolower(ch2);
}
while (ch1 == ch2);
string++;
}
}
#endif
/* END CODE */

3231
gzip.c Normal file

File diff suppressed because it is too large Load Diff

12
halt.c Normal file
View File

@ -0,0 +1,12 @@
#include "internal.h"
#include <signal.h>
const char halt_usage[] = "halt\n"
"\n\t"
"\thalt the system.\n";
extern int
halt_main(struct FileInfo * i, int argc, char * * argv)
{
return kill(1, SIGUSR1);
}

438
init.c Normal file
View File

@ -0,0 +1,438 @@
#include "internal.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/reboot.h>
#include <sys/kdaemon.h>
#include <sys/swap.h>
#include <sys/sysmacros.h>
const char init_usage[] = "Used internally by the system.";
char console[16] = "";
const char * default_console = "/dev/tty1";
char * first_terminal = NULL;
const char * second_terminal = "/dev/tty2";
const char log[] = "/dev/tty3";
char * term_ptr = NULL;
static void
message(const char * terminal, const char * pattern, ...)
{
int fd;
FILE * con = 0;
va_list arguments;
/*
* Open the console device each time a message is printed. If the user
* has switched consoles, the open will get the new console. If we kept
* the console open, we'd always print to the same one.
*/
if ( ((fd = open(terminal, O_WRONLY|O_NOCTTY)) < 0)
|| ((con = fdopen(fd, "w")) == NULL) )
return;
va_start(arguments, pattern);
vfprintf(con, pattern, arguments);
va_end(arguments);
fclose(con);
}
static int
waitfor(int pid)
{
int status;
int wpid;
message(log, "Waiting for process %d.\n", pid);
while ( (wpid = wait(&status)) != pid ) {
if ( wpid > 0 ) {
message(
log
,"pid %d exited, status=%x.\n"
,wpid
,status);
}
}
return wpid;
}
static int
run(
const char * program
,const char * const * arguments
,const char * terminal
,int get_enter)
{
static const char control_characters[] = {
'\003',
'\034',
'\177',
'\025',
'\004',
'\0',
'\1',
'\0',
'\021',
'\023',
'\032',
'\0',
'\022',
'\017',
'\027',
'\026',
'\0'
};
static char * environment[] = {
"HOME=/",
"PATH=/bin:/sbin:/usr/bin:/usr/sbin",
"SHELL=/bin/sh",
0,
"USER=root",
0
};
static const char press_enter[] =
"Please press Enter to activate this console. ";
int pid;
environment[3]=term_ptr;
pid = fork();
if ( pid == 0 ) {
struct termios t;
const char * const * arg;
close(0);
close(1);
close(2);
setsid();
open(terminal, O_RDWR);
dup(0);
dup(0);
tcsetpgrp(0, getpgrp());
tcgetattr(0, &t);
memcpy(t.c_cc, control_characters, sizeof(control_characters));
t.c_line = 0;
t.c_iflag = ICRNL|IXON|IXOFF;
t.c_oflag = OPOST|ONLCR;
t.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN;
tcsetattr(0, TCSANOW, &t);
if ( get_enter ) {
/*
* Save memory by not exec-ing anything large (like a shell)
* before the user wants it. This is critical if swap is not
* enabled and the system has low memory. Generally this will
* be run on the second virtual console, and the first will
* be allowed to start a shell or the installation system.
*/
char c;
write(1, press_enter, sizeof(press_enter) - 1);
read(0, &c, 1);
}
message(log, "Executing ");
arg = arguments;
while ( *arg != 0 )
message(log, "%s ", *arg++);
message(log, "\n");
execve(program, (char * *)arguments, (char * *)environment);
message(log, "%s: could not execute: %s.\r\n", program, strerror(errno));
exit(-1);
}
return pid;
}
static int
mem_total()
{
char s[80];
char *p;
FILE *f;
const char pattern[]="MemTotal:";
f=fopen("/proc/meminfo","r");
while (NULL != fgets(s,79,f)) {
p=strstr(s, pattern);
if (NULL != p) {
fclose(f);
return(atoi(p+strlen(pattern)));
}
}
return -1;
}
static void
set_free_pages()
{
char s[80];
FILE *f;
f=fopen("/proc/sys/vm/freepages","r");
fgets(s,79,f);
if (atoi(s) < 32) {
fclose(f);
f=fopen("/proc/sys/vm/freepages","w");
fprintf(f,"30\t40\t50\n");
printf("\nIncreased /proc/sys/vm/freepages values to 30/40/50\n");
}
fclose(f);
}
static void
shutdown_system(int do_reboot)
{
static const char * const umount_args[] = {"/bin/umount", "-a", "-n", 0};
sync();
/* Allow Ctrl-Alt-Del to reboot system. */
reboot(RB_ENABLE_CAD);
/* Send signals to every process _except_ pid 1 */
message(console, "Sending SIGHUP to all processes.\r\n");
kill(-1, SIGHUP);
sleep(2);
sync();
message(console, "Sending SIGKILL to all processes.\r\n");
kill(-1, SIGKILL);
sleep(1);
waitfor(run("/bin/umount", umount_args, console, 0));
sync();
bdflush(1, 0);
sync();
reboot(do_reboot ?RB_AUTOBOOT : RB_HALT_SYSTEM);
exit(0);
}
static void
halt_signal(int sig)
{
shutdown_system(0);
}
static void
reboot_signal(int sig)
{
shutdown_system(1);
}
static void
exit_signal(int sig)
{
/* initrd doesn't work anyway */
shutdown_system(1);
/* This is used on the initial ramdisk */
/* message(log, "Init exiting.");
exit(0);
*/
}
void
configure_terminals( int serial_cons );
extern int
init_main(struct FileInfo * i, int argc, char * * argv)
{
static const char * const rc = "etc/rc";
const char * arguments[100];
int run_rc = 1;
int j;
int pid1 = 0;
int pid2 = 0;
int create_swap= -1;
struct stat statbuf;
#ifndef INCLUDE_DINSTALL
const char * tty_commands[2] = { "bin/sh", "bin/sh"};
#else
const char * tty_commands[2] = { "sbin/dinstall", "bin/sh"};
#endif
char swap[20];
int serial_console = 0;
/*
* If I am started as /linuxrc instead of /sbin/init, I don't have the
* environment that init expects. I can't fix the signal behavior. Try
* to divorce from the controlling terminal with setsid(). This won't work
* if I am the process group leader.
*/
setsid();
signal(SIGUSR1, halt_signal);
signal(SIGUSR2, reboot_signal);
signal(SIGINT, reboot_signal);
signal(SIGTERM, exit_signal);
reboot(RB_DISABLE_CAD);
message(log, "%s: started. ", argv[0]);
for ( j = 1; j < argc; j++ ) {
if ( strcmp(argv[j], "single") == 0 ) {
run_rc = 0;
tty_commands[0] = "bin/sh";
tty_commands[1] = 0;
}
}
for ( j = 0; __environ[j] != 0; j++ ) {
if ( strncmp(__environ[j], "tty", 3) == 0
&& __environ[j][3] >= '1'
&& __environ[j][3] <= '2'
&& __environ[j][4] == '=' ) {
const char * s = &__environ[j][5];
if ( *s == 0 || strcmp(s, "off") == 0 )
s = 0;
tty_commands[__environ[j][3] - '1'] = s;
}
/* Should catch the syntax of Sparc kernel console setting. */
/* The kernel does not recognize a serial console when getting*/
/* console=/dev/ttySX !! */
else if ( strcmp(__environ[j], "console=ttya") == 0 ) {
serial_console=1;
}
else if ( strcmp(__environ[j], "console=ttyb") == 0 ) {
serial_console=2;
}
/* standard console settings */
else if ( strncmp(__environ[j], "console=", 8) == 0 ) {
first_terminal=&(__environ[j][8]);
}
else if ( strncmp(__environ[j], "TERM=", 5) == 0) {
term_ptr=__environ[j];
}
}
configure_terminals( serial_console );
printf("mounting /proc ...\n");
if (mount("/proc","/proc","proc",0,0)) {
perror("mounting /proc failed\n");
}
printf("\tdone.\n");
set_free_pages();
if (mem_total() < 3500) { /* not enough memory for standard install */
int retval;
retval= stat("/etc/swappartition",&statbuf);
if (retval) {
printf("
You do not have enough RAM, hence you must boot using the Boot Disk
for Low Memory systems.
Read the instructions in the install.html file.
");
while (1) {;}
} else { /* everything OK */
FILE *f;
f=fopen("/etc/swappartition","r");
fgets(swap,19,f);
fclose(f);
*(strstr(swap,"\n"))='\0';
if (swapon(swap,0)) {
perror("swapon failed\n");
} else {
f=fopen("/etc/swaps","w");
fprintf(f,"%s none swap rw 0 0",swap);
fclose(f);
create_swap = 0;
}
}
}
/*
* Don't modify **argv directly, it would show up in the "ps" display.
* I don't want "init" to look like "rc".
*/
arguments[0] = rc;
for ( j = 1; j < argc; j++ ) {
arguments[j] = argv[j];
}
arguments[j] = 0;
if ( run_rc )
waitfor(run(rc, arguments, console, 0));
if ( 0 == create_swap) {
if (unlink("/etc/swappartition")) {
perror("unlinking /etc/swappartition");
}
}
arguments[0] = "-sh";
arguments[1] = 0;
for ( ; ; ) {
int wpid;
int status;
if ( pid1 == 0 && tty_commands[0] ) {
/* Ask before starting a shell */
/*
arguments[0] = tty_commands[0];
*/
pid1 = run(tty_commands[0], arguments, first_terminal, 0);
}
if ( pid2 == 0 && tty_commands[1] )
pid2 = run(tty_commands[1], arguments, second_terminal, 1);
wpid = wait(&status);
if ( wpid > 0 ) {
/* DEBUGGING */
message(log, "pid %d exited, status=%x.\n", wpid, status);
}
if ( wpid == pid1 ) {
pid1 = 0;
}
if ( wpid == pid2 )
pid2 = 0;
}
}
void
configure_terminals( int serial_cons )
{
//struct stat statbuf;
char *tty;
switch (serial_cons) {
case 1:
strcpy( console, "/dev/ttyS0" );
break;
case 2:
strcpy( console, "/dev/ttyS1" );
break;
default:
tty = ttyname(0);
if (tty) {
strcpy( console, tty );
if (!strncmp( tty, "/dev/ttyS", 9 ))
serial_cons=1;
}
else
/* falls back to /dev/tty1 if an error occurs */
strcpy( console, default_console );
}
if (!first_terminal)
first_terminal = console;
if (serial_cons && !strncmp(term_ptr,"TERM=linux",10))
term_ptr = "TERM=vt100";
}

12
init/halt.c Normal file
View File

@ -0,0 +1,12 @@
#include "internal.h"
#include <signal.h>
const char halt_usage[] = "halt\n"
"\n\t"
"\thalt the system.\n";
extern int
halt_main(struct FileInfo * i, int argc, char * * argv)
{
return kill(1, SIGUSR1);
}

438
init/init.c Normal file
View File

@ -0,0 +1,438 @@
#include "internal.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/reboot.h>
#include <sys/kdaemon.h>
#include <sys/swap.h>
#include <sys/sysmacros.h>
const char init_usage[] = "Used internally by the system.";
char console[16] = "";
const char * default_console = "/dev/tty1";
char * first_terminal = NULL;
const char * second_terminal = "/dev/tty2";
const char log[] = "/dev/tty3";
char * term_ptr = NULL;
static void
message(const char * terminal, const char * pattern, ...)
{
int fd;
FILE * con = 0;
va_list arguments;
/*
* Open the console device each time a message is printed. If the user
* has switched consoles, the open will get the new console. If we kept
* the console open, we'd always print to the same one.
*/
if ( ((fd = open(terminal, O_WRONLY|O_NOCTTY)) < 0)
|| ((con = fdopen(fd, "w")) == NULL) )
return;
va_start(arguments, pattern);
vfprintf(con, pattern, arguments);
va_end(arguments);
fclose(con);
}
static int
waitfor(int pid)
{
int status;
int wpid;
message(log, "Waiting for process %d.\n", pid);
while ( (wpid = wait(&status)) != pid ) {
if ( wpid > 0 ) {
message(
log
,"pid %d exited, status=%x.\n"
,wpid
,status);
}
}
return wpid;
}
static int
run(
const char * program
,const char * const * arguments
,const char * terminal
,int get_enter)
{
static const char control_characters[] = {
'\003',
'\034',
'\177',
'\025',
'\004',
'\0',
'\1',
'\0',
'\021',
'\023',
'\032',
'\0',
'\022',
'\017',
'\027',
'\026',
'\0'
};
static char * environment[] = {
"HOME=/",
"PATH=/bin:/sbin:/usr/bin:/usr/sbin",
"SHELL=/bin/sh",
0,
"USER=root",
0
};
static const char press_enter[] =
"Please press Enter to activate this console. ";
int pid;
environment[3]=term_ptr;
pid = fork();
if ( pid == 0 ) {
struct termios t;
const char * const * arg;
close(0);
close(1);
close(2);
setsid();
open(terminal, O_RDWR);
dup(0);
dup(0);
tcsetpgrp(0, getpgrp());
tcgetattr(0, &t);
memcpy(t.c_cc, control_characters, sizeof(control_characters));
t.c_line = 0;
t.c_iflag = ICRNL|IXON|IXOFF;
t.c_oflag = OPOST|ONLCR;
t.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN;
tcsetattr(0, TCSANOW, &t);
if ( get_enter ) {
/*
* Save memory by not exec-ing anything large (like a shell)
* before the user wants it. This is critical if swap is not
* enabled and the system has low memory. Generally this will
* be run on the second virtual console, and the first will
* be allowed to start a shell or the installation system.
*/
char c;
write(1, press_enter, sizeof(press_enter) - 1);
read(0, &c, 1);
}
message(log, "Executing ");
arg = arguments;
while ( *arg != 0 )
message(log, "%s ", *arg++);
message(log, "\n");
execve(program, (char * *)arguments, (char * *)environment);
message(log, "%s: could not execute: %s.\r\n", program, strerror(errno));
exit(-1);
}
return pid;
}
static int
mem_total()
{
char s[80];
char *p;
FILE *f;
const char pattern[]="MemTotal:";
f=fopen("/proc/meminfo","r");
while (NULL != fgets(s,79,f)) {
p=strstr(s, pattern);
if (NULL != p) {
fclose(f);
return(atoi(p+strlen(pattern)));
}
}
return -1;
}
static void
set_free_pages()
{
char s[80];
FILE *f;
f=fopen("/proc/sys/vm/freepages","r");
fgets(s,79,f);
if (atoi(s) < 32) {
fclose(f);
f=fopen("/proc/sys/vm/freepages","w");
fprintf(f,"30\t40\t50\n");
printf("\nIncreased /proc/sys/vm/freepages values to 30/40/50\n");
}
fclose(f);
}
static void
shutdown_system(int do_reboot)
{
static const char * const umount_args[] = {"/bin/umount", "-a", "-n", 0};
sync();
/* Allow Ctrl-Alt-Del to reboot system. */
reboot(RB_ENABLE_CAD);
/* Send signals to every process _except_ pid 1 */
message(console, "Sending SIGHUP to all processes.\r\n");
kill(-1, SIGHUP);
sleep(2);
sync();
message(console, "Sending SIGKILL to all processes.\r\n");
kill(-1, SIGKILL);
sleep(1);
waitfor(run("/bin/umount", umount_args, console, 0));
sync();
bdflush(1, 0);
sync();
reboot(do_reboot ?RB_AUTOBOOT : RB_HALT_SYSTEM);
exit(0);
}
static void
halt_signal(int sig)
{
shutdown_system(0);
}
static void
reboot_signal(int sig)
{
shutdown_system(1);
}
static void
exit_signal(int sig)
{
/* initrd doesn't work anyway */
shutdown_system(1);
/* This is used on the initial ramdisk */
/* message(log, "Init exiting.");
exit(0);
*/
}
void
configure_terminals( int serial_cons );
extern int
init_main(struct FileInfo * i, int argc, char * * argv)
{
static const char * const rc = "etc/rc";
const char * arguments[100];
int run_rc = 1;
int j;
int pid1 = 0;
int pid2 = 0;
int create_swap= -1;
struct stat statbuf;
#ifndef INCLUDE_DINSTALL
const char * tty_commands[2] = { "bin/sh", "bin/sh"};
#else
const char * tty_commands[2] = { "sbin/dinstall", "bin/sh"};
#endif
char swap[20];
int serial_console = 0;
/*
* If I am started as /linuxrc instead of /sbin/init, I don't have the
* environment that init expects. I can't fix the signal behavior. Try
* to divorce from the controlling terminal with setsid(). This won't work
* if I am the process group leader.
*/
setsid();
signal(SIGUSR1, halt_signal);
signal(SIGUSR2, reboot_signal);
signal(SIGINT, reboot_signal);
signal(SIGTERM, exit_signal);
reboot(RB_DISABLE_CAD);
message(log, "%s: started. ", argv[0]);
for ( j = 1; j < argc; j++ ) {
if ( strcmp(argv[j], "single") == 0 ) {
run_rc = 0;
tty_commands[0] = "bin/sh";
tty_commands[1] = 0;
}
}
for ( j = 0; __environ[j] != 0; j++ ) {
if ( strncmp(__environ[j], "tty", 3) == 0
&& __environ[j][3] >= '1'
&& __environ[j][3] <= '2'
&& __environ[j][4] == '=' ) {
const char * s = &__environ[j][5];
if ( *s == 0 || strcmp(s, "off") == 0 )
s = 0;
tty_commands[__environ[j][3] - '1'] = s;
}
/* Should catch the syntax of Sparc kernel console setting. */
/* The kernel does not recognize a serial console when getting*/
/* console=/dev/ttySX !! */
else if ( strcmp(__environ[j], "console=ttya") == 0 ) {
serial_console=1;
}
else if ( strcmp(__environ[j], "console=ttyb") == 0 ) {
serial_console=2;
}
/* standard console settings */
else if ( strncmp(__environ[j], "console=", 8) == 0 ) {
first_terminal=&(__environ[j][8]);
}
else if ( strncmp(__environ[j], "TERM=", 5) == 0) {
term_ptr=__environ[j];
}
}
configure_terminals( serial_console );
printf("mounting /proc ...\n");
if (mount("/proc","/proc","proc",0,0)) {
perror("mounting /proc failed\n");
}
printf("\tdone.\n");
set_free_pages();
if (mem_total() < 3500) { /* not enough memory for standard install */
int retval;
retval= stat("/etc/swappartition",&statbuf);
if (retval) {
printf("
You do not have enough RAM, hence you must boot using the Boot Disk
for Low Memory systems.
Read the instructions in the install.html file.
");
while (1) {;}
} else { /* everything OK */
FILE *f;
f=fopen("/etc/swappartition","r");
fgets(swap,19,f);
fclose(f);
*(strstr(swap,"\n"))='\0';
if (swapon(swap,0)) {
perror("swapon failed\n");
} else {
f=fopen("/etc/swaps","w");
fprintf(f,"%s none swap rw 0 0",swap);
fclose(f);
create_swap = 0;
}
}
}
/*
* Don't modify **argv directly, it would show up in the "ps" display.
* I don't want "init" to look like "rc".
*/
arguments[0] = rc;
for ( j = 1; j < argc; j++ ) {
arguments[j] = argv[j];
}
arguments[j] = 0;
if ( run_rc )
waitfor(run(rc, arguments, console, 0));
if ( 0 == create_swap) {
if (unlink("/etc/swappartition")) {
perror("unlinking /etc/swappartition");
}
}
arguments[0] = "-sh";
arguments[1] = 0;
for ( ; ; ) {
int wpid;
int status;
if ( pid1 == 0 && tty_commands[0] ) {
/* Ask before starting a shell */
/*
arguments[0] = tty_commands[0];
*/
pid1 = run(tty_commands[0], arguments, first_terminal, 0);
}
if ( pid2 == 0 && tty_commands[1] )
pid2 = run(tty_commands[1], arguments, second_terminal, 1);
wpid = wait(&status);
if ( wpid > 0 ) {
/* DEBUGGING */
message(log, "pid %d exited, status=%x.\n", wpid, status);
}
if ( wpid == pid1 ) {
pid1 = 0;
}
if ( wpid == pid2 )
pid2 = 0;
}
}
void
configure_terminals( int serial_cons )
{
//struct stat statbuf;
char *tty;
switch (serial_cons) {
case 1:
strcpy( console, "/dev/ttyS0" );
break;
case 2:
strcpy( console, "/dev/ttyS1" );
break;
default:
tty = ttyname(0);
if (tty) {
strcpy( console, tty );
if (!strncmp( tty, "/dev/ttyS", 9 ))
serial_cons=1;
}
else
/* falls back to /dev/tty1 if an error occurs */
strcpy( console, default_console );
}
if (!first_terminal)
first_terminal = console;
if (serial_cons && !strncmp(term_ptr,"TERM=linux",10))
term_ptr = "TERM=vt100";
}

12
init/reboot.c Normal file
View File

@ -0,0 +1,12 @@
#include "internal.h"
#include <signal.h>
const char reboot_usage[] = "reboot\n"
"\n\t"
"\treboot the system.\n";
extern int
reboot_main(struct FileInfo * i, int argc, char * * argv)
{
return kill(1, SIGUSR2);
}

189
internal.h Normal file
View File

@ -0,0 +1,189 @@
#ifndef _INTERNAL_H_
#define _INTERNAL_H_
#include "busybox.def.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
/* Some useful definitions */
typedef int BOOL;
#define STDIN 0
#define STDOUT 1
#define FALSE ((BOOL) 0)
#define TRUE ((BOOL) 1)
#define PATH_LEN 1024
#define BUF_SIZE 8192
#define EXPAND_ALLOC 1024
#define isBlank(ch) (((ch) == ' ') || ((ch) == '\t'))
#define isDecimal(ch) (((ch) >= '0') && ((ch) <= '9'))
#define isOctal(ch) (((ch) >= '0') && ((ch) <= '7'))
#define isWildCard(ch) (((ch) == '*') || ((ch) == '?') || ((ch) == '['))
struct FileInfo {
unsigned int complainInPostProcess:1;
unsigned int changeUserID:1;
unsigned int changeGroupID:1;
unsigned int changeMode:1;
unsigned int create:1;
unsigned int force:1;
unsigned int recursive:1;
unsigned int processDirectoriesAfterTheirContents;
unsigned int makeParentDirectories:1;
unsigned int didOperation:1;
unsigned int isSymbolicLink:1;
unsigned int makeSymbolicLink:1;
unsigned int dyadic:1;
const char* source;
const char* destination;
int directoryLength;
uid_t userID;
gid_t groupID;
mode_t andWithMode;
mode_t orWithMode;
struct stat stat;
const struct Applet *
applet;
};
struct Applet {
const char* name;
int (*main)(int argc, char** argv);
};
extern void name_and_error(const char*);
extern int is_a_directory(const char*);
extern char* join_paths(char *, const char *, const char *);
extern int descend(
struct FileInfo *o
,int (*function)(const struct FileInfo * i));
extern struct mntent *
findMountPoint(const char*, const char *);
extern void usage(const char*);
extern int busybox_main(int argc, char** argv);
extern int block_device_main(int argc, char** argv);
extern int cat_more_main(int argc, char** argv);
extern int chgrp_main(int argc, char** argv);
extern int chmod_main(int argc, char** argv);
extern int chown_main(int argc, char** argv);
extern int chroot_main(int argc, char** argv);
extern int clear_main(int argc, char** argv);
extern int date_main(int argc, char** argv);
extern int dd_main(int argc, char** argv);
extern int df_main(int argc, char** argv);
extern int dmesg_main(int argc, char** argv);
extern int dyadic_main(int argc, char** argv);
extern int false_main(int argc, char** argv);
extern int fdisk_main(int argc, char** argv);
extern int find_main(int argc, char** argv);
extern int grep_main(int argc, char** argv);
extern int halt_main(int argc, char** argv);
extern int init_main(int argc, char** argv);
extern int kill_main(int argc, char** argv);
extern int length_main(int argc, char** argv);
extern int ln_main(int argc, char** argv);
extern int loadkmap_main(int argc, char** argv);
extern int losetup_main(int argc, char** argv);
extern int ls_main(int argc, char** argv);
extern int makedevs_main(int argc, char** argv);
extern int math_main(int argc, char** argv);
extern int mknod_main(int argc, char** argv);
extern int mkswap_main(int argc, char** argv);
extern int mnc_main(int argc, char** argv);
extern int monadic_main(int argc, char** argv);
extern int mount_main(int argc, char** argv);
extern int mt_main(int argc, char** argv);
extern int printf_main(int argc, char** argv);
extern int pwd_main(int argc, char** argv);
extern int reboot_main(int argc, char** argv);
extern int rm_main(int argc, char** argv);
extern int scan_partitions_main(int argc, char** argv);
extern int sh_main(int argc, char** argv);
extern int sleep_main(int argc, char** argv);
extern int tar_main(int argc, char** argv);
extern int sync_main(int argc, char** argv);
extern int tput_main(int argc, char** argv);
extern int true_main(int argc, char** argv);
extern int tryopen_main(int argc, char** argv);
extern int umount_main(int argc, char** argv);
extern int update_main(int argc, char** argv);
extern int zcat_main(int argc, char** argv);
extern int gzip_main(int argc, char** argv);
extern int
parse_mode(
const char* s
,mode_t * or
,mode_t * and
,int * group_execute);
extern int parse_user_name(const char* string, struct FileInfo * i);
extern const char block_device_usage[];
extern const char chgrp_usage[];
extern const char chmod_usage[];
extern const char chown_usage[];
extern const char chroot_usage[];
extern const char clear_usage[];
extern const char cp_usage[];
extern const char date_usage[];
extern const char dd_usage[];
extern const char df_usage[];
extern const char dmesg_usage[];
extern const char dutmp_usage[];
extern const char false_usage[];
extern const char fdflush_usage[];
extern const char find_usage[];
extern const char grep_usage[];
extern const char halt_usage[];
extern const char init_usage[];
extern const char kill_usage[];
extern const char length_usage[];
extern const char ln_usage[];
extern const char loadkmap_usage[];
extern const char losetup_usage[];
extern const char ls_usage[];
extern const char math_usage[];
extern const char makedevs_usage[];
extern const char mkdir_usage[];
extern const char mknod_usage[];
extern const char mkswap_usage[];
extern const char mnc_usage[];
extern const char more_usage[];
extern const char mount_usage[];
extern const char mt_usage[];
extern const char mv_usage[];
extern const char printf_usage[];
extern const char pwd_usage[];
extern const char reboot_usage[];
extern const char rm_usage[];
extern const char rmdir_usage[];
extern const char scan_partitions_usage[];
extern const char sleep_usage[];
extern const char tar_usage[];
extern const char swapoff_usage[];
extern const char swapon_usage[];
extern const char sync_usage[];
extern const char touch_usage[];
extern const char tput_usage[];
extern const char true_usage[];
extern const char tryopen_usage[];
extern const char umount_usage[];
extern const char update_usage[];
extern const char zcat_usage[];
extern const char gzip_usage[];
#endif

140
kill.c Normal file
View File

@ -0,0 +1,140 @@
#include "internal.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
const char kill_usage[] = "kill [-signal] process-id [process-id ...]\n";
struct signal_name {
const char * name;
int number;
};
const struct signal_name signames[] = {
{ "HUP", SIGHUP },
{ "INT", SIGINT },
{ "QUIT", SIGQUIT },
{ "ILL", SIGILL },
{ "TRAP", SIGTRAP },
{ "ABRT", SIGABRT },
#ifndef __alpha__
{ "IOT", SIGIOT },
#endif
#if defined(sparc) || defined(__alpha__)
{ "EMT", SIGEMT },
#else
{ "BUS", SIGBUS },
#endif
{ "FPE", SIGFPE },
{ "KILL", SIGKILL },
#if defined(sparc) || defined(__alpha__)
{ "BUS", SIGBUS },
#else
{ "USR1", SIGUSR1 },
#endif
{ "SEGV", SIGSEGV },
#if defined(sparc) || defined(__alpha__)
{ "SYS", SIGSYS },
#else
{ "USR2", SIGUSR2 },
#endif
{ "PIPE", SIGPIPE },
{ "ALRM", SIGALRM },
{ "TERM", SIGTERM },
#if defined(sparc) || defined(__alpha__)
{ "URG", SIGURG },
{ "STOP", SIGSTOP },
{ "TSTP", SIGTSTP },
{ "CONT", SIGCONT },
{ "CHLD", SIGCHLD },
{ "TTIN", SIGTTIN },
{ "TTOU", SIGTTOU },
{ "IO", SIGIO },
# ifndef __alpha__
{ "POLL", SIGIO },
# endif
{ "XCPU", SIGXCPU },
{ "XFSZ", SIGXFSZ },
{ "VTALRM", SIGVTALRM },
{ "PROF", SIGPROF },
{ "WINCH", SIGWINCH },
# ifdef __alpha__
{ "INFO", SIGINFO },
# else
{ "LOST", SIGLOST },
# endif
{ "USR1", SIGUSR1 },
{ "USR2", SIGUSR2 },
#else
{ "STKFLT", SIGSTKFLT },
{ "CHLD", SIGCHLD },
{ "CONT", SIGCONT },
{ "STOP", SIGSTOP },
{ "TSTP", SIGTSTP },
{ "TTIN", SIGTTIN },
{ "TTOU", SIGTTOU },
{ "URG", SIGURG },
{ "XCPU", SIGXCPU },
{ "XFSZ", SIGXFSZ },
{ "VTALRM", SIGVTALRM },
{ "PROF", SIGPROF },
{ "WINCH", SIGWINCH },
{ "IO", SIGIO },
{ "POLL", SIGPOLL },
{ "PWR", SIGPWR },
{ "UNUSED", SIGUNUSED },
#endif
{ 0, 0 }
};
extern int
kill_main(struct FileInfo * i, int argc, char * * argv)
{
int had_error = 0;
int sig = SIGTERM;
if ( argv[1][0] == '-' ) {
if ( argv[1][1] >= '0' && argv[1][1] <= '9' ) {
sig = atoi(&argv[1][1]);
if ( sig < 0 || sig >= NSIG ) {
usage(kill_usage);
exit(-1);
}
}
else {
const struct signal_name * s = signames;
for ( ; ; ) {
if ( strcmp(s->name, &argv[1][1]) == 0 ) {
sig = s->number;
break;
}
s++;
if ( s->name == 0 ) {
usage(kill_usage);
exit(-1);
}
}
}
argv++;
argc--;
}
while ( argc > 1 ) {
int pid;
if ( argv[1][0] < '0' || argv[1][0] > '9' ) {
usage(kill_usage);
exit(-1);
}
pid = atoi(argv[1]);
if ( kill(pid, sig) != 0 ) {
had_error = 1;
perror(argv[1]);
}
argv++;
argc--;
}
if ( had_error )
return -1;
else
return 0;
}

13
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
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;
}

68
loadkmap.c Normal file
View File

@ -0,0 +1,68 @@
#include "internal.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/kd.h>
#include <linux/keyboard.h>
#include <sys/ioctl.h>
const char loadkmap_usage[] = "loadkmap\n"
"\n"
"\tLoad a binary keyboard translation table from standard input.\n"
"\n";
int
loadkmap_main(struct FileInfo * info, int argc, char * * argv)
{
struct kbentry ke;
u_short *ibuff;
int i,j,fd,readsz,pos,ibuffsz=NR_KEYS * sizeof(u_short);
char flags[MAX_NR_KEYMAPS],magic[]="bkeymap",buff[7];
fd = open("/dev/tty0", O_RDWR);
if (fd < 0) {
fprintf(stderr, "Error opening /dev/tty0: %s\n", strerror(errno));
return 1;
}
read(0,buff,7);
if (0 != strncmp(buff,magic,7)) {
fprintf(stderr, "This is not a valid binary keymap.\n");
return 1;
}
if ( MAX_NR_KEYMAPS != read(0,flags,MAX_NR_KEYMAPS) ) {
fprintf(stderr, "Error reading keymap flags: %s\n", strerror(errno));
return 1;
}
ibuff=(u_short *) malloc(ibuffsz);
if (!ibuff) {
fprintf(stderr, "Out of memory.\n");
return 1;
}
for(i=0; i<MAX_NR_KEYMAPS; i++) {
if (flags[i]==1){
pos=0;
while (pos < ibuffsz) {
if ( (readsz = read(0,ibuff+pos,ibuffsz-pos)) < 0 ) {
fprintf(stderr, "Error reading keymap: %s\n",
strerror(errno));
return 1;
}
pos += readsz;
}
for(j=0; j<NR_KEYS; j++) {
ke.kb_index = j;
ke.kb_table = i;
ke.kb_value = ibuff[j];
ioctl(fd, KDSKBENT, &ke);
}
}
}
close (fd);
return 0;
}

190
losetup.c Normal file
View File

@ -0,0 +1,190 @@
/*
* losetup.c - setup and control loop devices
*/
#include "internal.h"
const char losetup_usage[] = "losetup\n"
"\n"
"\tlosetup loop_device give info\n"
"\tlosetup -d loop_device delete\n"
"\tlosetup [ -o offset ] loop_device file setup\n";
/* from mount-2.6d */
/*
* losetup.c - setup and control loop devices
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
/* #include "loop.h" */
/*
* include/linux/loop.h
*
* Written by Theodore Ts'o, 3/29/93.
*
* Copyright 1993 by Theodore Ts'o. Redistribution of this file is
* permitted under the GNU Public License.
*/
#define LO_NAME_SIZE 64
#define LO_KEY_SIZE 32
struct loop_info {
int lo_number; /* ioctl r/o */
dev_t lo_device; /* ioctl r/o */
unsigned long lo_inode; /* ioctl r/o */
dev_t lo_rdevice; /* ioctl r/o */
int lo_offset;
int lo_encrypt_type;
int lo_encrypt_key_size; /* ioctl w/o */
int lo_flags; /* ioctl r/o */
char lo_name[LO_NAME_SIZE];
unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
unsigned long lo_init[2];
char reserved[4];
};
/*
* IOCTL commands --- we will commandeer 0x4C ('L')
*/
#define LOOP_SET_FD 0x4C00
#define LOOP_CLR_FD 0x4C01
#define LOOP_SET_STATUS 0x4C02
#define LOOP_GET_STATUS 0x4C03
/* #include "lomount.h" */
extern int set_loop (const char *, const char *, int, int *);
extern int del_loop (const char *);
static void show_loop(const char *device)
{
struct loop_info loopinfo;
int fd;
if ((fd = open(device, O_RDWR)) < 0) {
perror(device);
return;
}
if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) < 0) {
perror("Cannot get loop info");
close(fd);
return;
}
printf("%s: [%04x]:%ld (%s) offset %d\n",
device, (unsigned int)loopinfo.lo_device, loopinfo.lo_inode,
loopinfo.lo_name, loopinfo.lo_offset);
close(fd);
}
int set_loop(const char *device, const char *file, int offset, int *loopro)
{
struct loop_info loopinfo;
int fd, ffd, mode;
mode = *loopro ? O_RDONLY : O_RDWR;
if ((ffd = open (file, mode)) < 0 && !*loopro
&& (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
perror (file);
return 1;
}
if ((fd = open (device, mode)) < 0) {
close(ffd);
perror (device);
return 1;
}
*loopro = (mode == O_RDONLY);
memset(&loopinfo, 0, sizeof(loopinfo));
strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
loopinfo.lo_offset = offset;
loopinfo.lo_encrypt_key_size = 0;
if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
perror("ioctl: LOOP_SET_FD");
exit(1);
}
if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
(void) ioctl(fd, LOOP_CLR_FD, 0);
perror("ioctl: LOOP_SET_STATUS");
exit(1);
}
close(fd);
close(ffd);
return 0;
}
int del_loop(const char *device)
{
int fd;
if ((fd = open(device, O_RDONLY)) < 0) {
perror(device);
exit(1);
}
if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
perror("ioctl: LOOP_CLR_FD");
exit(1);
}
close(fd);
return(0);
}
static int losetup_usage_fn(void)
{
fprintf(stderr, losetup_usage);
exit(1);
}
int losetup_main(struct FileInfo * i, int argc, char * * argv)
{
char *offset;
int delete,off,c;
int ro = 0;
delete = off = 0;
offset = NULL;
while ((c = getopt(argc,argv,"do:")) != EOF) {
switch (c) {
case 'd':
delete = 1;
break;
case 'o':
offset = optarg;
break;
default:
losetup_usage_fn();
}
}
if (argc == 1) losetup_usage_fn();
if ((delete && (argc != optind+1 || offset)) ||
(!delete && (argc < optind+1 || argc > optind+2)))
losetup_usage_fn();
if (argc == optind+1)
if (delete)
del_loop(argv[optind]);
else
show_loop(argv[optind]);
else {
if (offset && sscanf(offset,"%d",&off) != 1)
losetup_usage_fn();
set_loop(argv[optind],argv[optind+1],off,&ro);
}
return 0;
}

542
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;
}

95
makedevs.c Normal file
View File

@ -0,0 +1,95 @@
/*
* public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
*
* makedevs
* Make ranges of device files quickly.
* known bugs: can't deal with alpha ranges
*/
#include "internal.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
const char makedevs_usage[] =
"makedevs 0.01 -- Create an entire range of device files\n\n"
"\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n"
"\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n";
int
makedevs_main(struct FileInfo * i, int argc, char * * argv)
{
const char *basedev = argv[1];
const char *type = argv[2];
int major = atoi(argv[3]);
int Sminor = atoi(argv[4]);
int S = atoi(argv[5]);
int E = atoi(argv[6]);
int sbase = argc == 8 ? 1 : 0;
mode_t mode = 0;
dev_t dev = 0;
char devname[255];
char buf[255];
switch (type[0]) {
case 'c':
mode = S_IFCHR; break;
case 'b':
mode = S_IFBLK; break;
case 'f':
mode = S_IFIFO; break;
default:
usage(makedevs_usage);
return 2;
}
mode |= 0660;
while ( S <= E ) {
if (type[0] != 'f')
dev = (major << 8) | Sminor;
strcpy(devname, basedev);
if (sbase == 0) {
sprintf(buf, "%d", S);
strcat(devname, buf);
} else {
sbase = 0;
}
if (mknod (devname, mode, dev))
printf("Failed to create: %s\n", devname);
S++; Sminor++;
}
return 0;
}
/*
And this is what this program replaces. The shell is too slow!
makedev () {
local basedev=$1; local S=$2; local E=$3
local major=$4; local Sminor=$5; local type=$6
local sbase=$7
if [ ! "$sbase" = "" ]; then
mknod "$basedev" $type $major $Sminor
S=`expr $S + 1`
Sminor=`expr $Sminor + 1`
fi
while [ $S -le $E ]; do
mknod "$basedev$S" $type $major $Sminor
S=`expr $S + 1`
Sminor=`expr $Sminor + 1`
done
}
*/

149
math.c Normal file
View File

@ -0,0 +1,149 @@
#include "internal.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */
const char math_usage[] = "math expression ...";
static double stack[100];
static unsigned int pointer;
static void
push(double a)
{
if ( pointer >= (sizeof(stack) / sizeof(*stack)) ) {
fprintf(stderr, "math: stack overflow\n");
exit(-1);
}
else
stack[pointer++] = a;
}
static double
pop()
{
if ( pointer == 0 ) {
fprintf(stderr, "math: stack underflow\n");
exit(-1);
}
return stack[--pointer];
}
static void
add()
{
push(pop() + pop());
}
static void
sub()
{
double subtrahend = pop();
push(pop() - subtrahend);
}
static void
mul()
{
push(pop() * pop());
}
static void
divide()
{
double divisor = pop();
push(pop() / divisor);
}
static void
and()
{
push((unsigned int)pop() & (unsigned int)pop());
}
static void
or()
{
push((unsigned int)pop() | (unsigned int)pop());
}
static void
eor()
{
push((unsigned int)pop() ^ (unsigned int)pop());
}
static void
not()
{
push(~(unsigned int)pop());
}
static void
print()
{
printf("%g\n", pop());
}
struct op {
const char * name;
void (*function)();
};
static const struct op operators[] = {
{ "add", add },
{ "and", and },
{ "div", divide },
{ "eor", eor },
{ "mul", mul },
{ "not", not },
{ "or", or },
{ "sub", sub },
{ 0, 0 }
};
static void
stack_machine(const char * argument)
{
char * endPointer = 0;
double d;
const struct op * o = operators;
if ( argument == 0 ) {
print();
return;
}
d = strtod(argument, &endPointer);
if ( endPointer != argument ) {
push(d);
return;
}
while ( o->name != 0 ) {
if ( strcmp(o->name, argument) == 0 ) {
(*(o->function))();
return;
}
o++;
}
fprintf(stderr, "math: %s: syntax error.\n", argument);
exit(-1);
}
int
math_main(struct FileInfo * i, int argc, char * * argv)
{
while ( argc >= 2 ) {
stack_machine(argv[1]);
argv++;
argc--;
}
stack_machine(0);
return 0;
}

47
miscutils/dutmp.c Normal file
View File

@ -0,0 +1,47 @@
/*
* public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
*
* dutmp
* Takes utmp formated file on stdin and dumps it's contents
* out in colon delimited fields. Easy to 'cut' for shell based
* versions of 'who', 'last', etc. IP Addr is output in hex,
* little endian on x86.
*
* made against libc6
*/
#include "internal.h"
#include <stdio.h>
#include <utmp.h>
const char dutmp_usage[] = "dutmp\n"
"\n"
"\tDump file or stdin utmp file format to stdout, pipe delimited.\n"
"\tdutmp /var/run/utmp\n";
extern int
dutmp_fn(const struct FileInfo * i)
{
FILE * f = stdin;
struct utmp * ut = (struct utmp *) malloc(sizeof(struct utmp) );
if ( i )
if (! (f = fopen(i->source, "r"))) {
name_and_error(i->source);
return 1;
}
while (fread (ut, 1, sizeof(struct utmp), f)) {
//printf("%d:%d:%s:%s:%s:%s:%d:%d:%ld:%ld:%ld:%x\n",
printf("%d|%d|%s|%s|%s|%s|%d|%d|%ld|%ld|%ld|%x\n",
ut->ut_type, ut->ut_pid, ut->ut_line,
ut->ut_id, ut->ut_user, ut->ut_host,
ut->ut_exit.e_termination, ut->ut_exit.e_exit,
ut->ut_session,
ut->ut_tv.tv_sec, ut->ut_tv.tv_usec,
ut->ut_addr);
}
return 0;
}

95
miscutils/makedevs.c Normal file
View File

@ -0,0 +1,95 @@
/*
* public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
*
* makedevs
* Make ranges of device files quickly.
* known bugs: can't deal with alpha ranges
*/
#include "internal.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
const char makedevs_usage[] =
"makedevs 0.01 -- Create an entire range of device files\n\n"
"\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n"
"\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n";
int
makedevs_main(struct FileInfo * i, int argc, char * * argv)
{
const char *basedev = argv[1];
const char *type = argv[2];
int major = atoi(argv[3]);
int Sminor = atoi(argv[4]);
int S = atoi(argv[5]);
int E = atoi(argv[6]);
int sbase = argc == 8 ? 1 : 0;
mode_t mode = 0;
dev_t dev = 0;
char devname[255];
char buf[255];
switch (type[0]) {
case 'c':
mode = S_IFCHR; break;
case 'b':
mode = S_IFBLK; break;
case 'f':
mode = S_IFIFO; break;
default:
usage(makedevs_usage);
return 2;
}
mode |= 0660;
while ( S <= E ) {
if (type[0] != 'f')
dev = (major << 8) | Sminor;
strcpy(devname, basedev);
if (sbase == 0) {
sprintf(buf, "%d", S);
strcat(devname, buf);
} else {
sbase = 0;
}
if (mknod (devname, mode, dev))
printf("Failed to create: %s\n", devname);
S++; Sminor++;
}
return 0;
}
/*
And this is what this program replaces. The shell is too slow!
makedev () {
local basedev=$1; local S=$2; local E=$3
local major=$4; local Sminor=$5; local type=$6
local sbase=$7
if [ ! "$sbase" = "" ]; then
mknod "$basedev" $type $major $Sminor
S=`expr $S + 1`
Sminor=`expr $Sminor + 1`
fi
while [ $S -le $E ]; do
mknod "$basedev$S" $type $major $Sminor
S=`expr $S + 1`
Sminor=`expr $Sminor + 1`
done
}
*/

98
miscutils/mt.c Normal file
View File

@ -0,0 +1,98 @@
#include "internal.h"
#include <stdio.h>
#include <sys/mtio.h>
#include <sys/fcntl.h>
const char mt_usage[] = "mt [-f device] opcode value\n";
struct mt_opcodes {
char * name;
short value;
};
/* missing: eod/seod, stoptions, stwrthreshold, densities */
static const struct mt_opcodes opcodes[] = {
{ "bsf", MTBSF },
{ "bsfm", MTBSFM },
{ "bsr", MTBSR },
{ "bss", MTBSS },
{ "datacompression", MTCOMPRESSION },
{ "eom", MTEOM },
{ "erase", MTERASE },
{ "fsf", MTFSF },
{ "fsfm", MTFSFM },
{ "fsr", MTFSR },
{ "fss", MTFSS },
{ "load", MTLOAD },
{ "lock", MTLOCK },
{ "mkpart", MTMKPART },
{ "nop", MTNOP },
{ "offline",MTOFFL },
{ "rewoffline",MTOFFL },
{ "ras1", MTRAS1 },
{ "ras2", MTRAS2 },
{ "ras3", MTRAS3 },
{ "reset", MTRESET },
{ "retension", MTRETEN },
{ "rew", MTREW },
{ "seek", MTSEEK },
{ "setblk", MTSETBLK },
{ "setdensity", MTSETDENSITY },
{ "drvbuffer", MTSETDRVBUFFER },
{ "setpart", MTSETPART },
{ "tell", MTTELL },
{ "wset", MTWSM },
{ "unload", MTUNLOAD },
{ "unlock", MTUNLOCK },
{ "eof", MTWEOF },
{ "weof", MTWEOF },
{ 0, 0 }
};
extern int
mt_main(struct FileInfo * i, int argc, char * * argv)
{
const char * file = "/dev/tape";
const struct mt_opcodes * code = opcodes;
struct mtop op;
int fd;
if ( strcmp(argv[1], "-f") == 0 ) {
if ( argc < 4 ) {
usage(mt_usage);
return 1;
}
file = argv[2];
argv += 2;
argc -= 2;
}
while ( code->name != 0 ) {
if ( strcmp(code->name, argv[1]) == 0 )
break;
code++;
}
if ( code->name == 0 ) {
fprintf(stderr, "mt: unrecognized opcode %s.\n", argv[1]);
return 1;
}
op.mt_op = code->value;
if ( argc >= 3 )
op.mt_count = atoi(argv[2]);
else
op.mt_count = 1; /* One, not zero, right? */
if ( (fd = open(file, O_RDONLY, 0)) < 0 ) {
name_and_error(file);
return 1;
}
if ( ioctl(fd, MTIOCTOP, &op) != 0 ) {
name_and_error(file);
return 1;
}
return 0;
}

48
miscutils/update.c Normal file
View File

@ -0,0 +1,48 @@
#include "internal.h"
#include <linux/unistd.h>
const char update_usage[] = "update\n"
"\n"
"\tFlush buffered data to the disk devices every 30 seconds.\n";
#if defined(__GLIBC__)
#include <sys/kdaemon.h>
#else
_syscall2(int, bdflush, int, func, int, data);
#endif /* __GLIBC__ */
extern int
update_main(struct FileInfo * i, int argc, char * * argv)
{
/*
* Update is actually two daemons, bdflush and update.
*/
int pid;
pid = fork();
if ( pid < 0 )
return pid;
else if ( pid == 0 ) {
/*
* This is no longer necessary since 1.3.5x, but it will harmlessly
* exit if that is the case.
*/
strcpy(argv[0], "bdflush (update)");
argv[1] = 0;
argv[2] = 0;
bdflush(1, 0);
_exit(0);
}
pid = fork();
if ( pid < 0 )
return pid;
else if ( pid == 0 ) {
argv[0] = "update";
for ( ; ; ) {
sync();
sleep(30);
}
}
return 0;
}

58
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
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;
}

253
mkswap.c Normal file
View File

@ -0,0 +1,253 @@
#include "internal.h"
/*
* mkswap.c - set up a linux swap device
*
* (C) 1991 Linus Torvalds. This file may be redistributed as per
* the Linux copyright.
*/
/*
* 20.12.91 - time began. Got VM working yesterday by doing this by hand.
*
* Usage: mkswap [-c] device [size-in-blocks]
*
* -c for readablility checking (use it unless you are SURE!)
*
* The device may be a block device or a image of one, but this isn't
* enforced (but it's not much fun on a character device :-).
*
* Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
* size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995.
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <asm/page.h>
#include <linux/fs.h>
#ifndef __linux__
# define volatile
#endif
#define TEST_BUFFER_PAGES 8
const char mkswap_usage[] = "mkswap [-c] partition [block-count]\n"
"\n"
"\tPrepare a disk partition to be used as a swap partition.\n"
"\tThe default block count is the size of the entire partition.\n"
"\n"
"\t-c:\tCheck for read-ability.\n"
"\tblock-count\tUse only this many blocks.\n";
static const char * program_name = "mkswap";
static const char * device_name = NULL;
static int DEV = -1;
static long PAGES = 0;
static int do_check = 0;
static int badpages = 0;
static long bit_test_and_set (unsigned int *addr, unsigned int nr)
{
unsigned int r, m;
addr += nr / (8 * sizeof(int));
r = *addr;
m = 1 << (nr & (8 * sizeof(int) - 1));
*addr = r | m;
return (r & m) != 0;
}
static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
{
unsigned int r, m;
addr += nr / (8 * sizeof(int));
r = *addr;
m = 1 << (nr & (8 * sizeof(int) - 1));
*addr = r & ~m;
return (r & m) != 0;
}
/*
* Volatile to let gcc know that this doesn't return. When trying
* to compile this under minix, volatile gives a warning, as
* exit() isn't defined as volatile under minix.
*/
volatile void fatal_error(const char * fmt_string)
{
fprintf(stderr,fmt_string,program_name,device_name);
exit(1);
}
#define die(str) fatal_error("%s: " str "\n")
static void check_blocks(int * signature_page)
{
unsigned int current_page;
int do_seek = 1;
char buffer[PAGE_SIZE];
current_page = 0;
while (current_page < PAGES) {
if (!do_check) {
bit_test_and_set(signature_page,current_page++);
continue;
} else {
printf("\r%d", current_page);
}
if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) !=
current_page*PAGE_SIZE)
die("seek failed in check_blocks");
if ( (do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE))) ) {
bit_test_and_clear(signature_page,current_page++);
badpages++;
continue;
}
bit_test_and_set(signature_page,current_page++);
}
if (do_check)
printf("\n");
if (badpages)
printf("%d bad page%s\n",badpages,(badpages>1)?"s":"");
}
static long valid_offset (int fd, int offset)
{
char ch;
if (lseek (fd, offset, 0) < 0)
return 0;
if (read (fd, &ch, 1) < 1)
return 0;
return 1;
}
static int count_blocks (int fd)
{
int high, low;
low = 0;
for (high = 1; valid_offset (fd, high); high *= 2)
low = high;
while (low < high - 1)
{
const int mid = (low + high) / 2;
if (valid_offset (fd, mid))
low = mid;
else
high = mid;
}
valid_offset (fd, 0);
return (low + 1);
}
static int get_size(const char *file)
{
int fd;
int size;
fd = open(file, O_RDWR);
if (fd < 0) {
perror(file);
exit(1);
}
if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
close(fd);
return (size * 512);
}
size = count_blocks(fd);
close(fd);
return size;
}
int
mkswap(char *device_name, int pages, int check)
{
struct stat statbuf;
int goodpages;
int signature_page[PAGE_SIZE/sizeof(int)];
PAGES = pages;
do_check = check;
memset(signature_page,0,PAGE_SIZE);
if (device_name && !PAGES) {
PAGES = get_size(device_name) / PAGE_SIZE;
}
if (!device_name || PAGES<10) {
fprintf(stderr,
"%s: error: swap area needs to be at least %ldkB\n",
program_name, 10 * PAGE_SIZE / 1024);
/* usage(mkswap_usage); */
exit(1);
}
if (PAGES > 8 * (PAGE_SIZE - 10)) {
PAGES = 8 * (PAGE_SIZE - 10);
fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
program_name, PAGES * PAGE_SIZE / 1024);
}
DEV = open(device_name,O_RDWR);
if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
perror(device_name);
exit(1);
}
if (!S_ISBLK(statbuf.st_mode))
do_check=0;
else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
die("Will not try to make swapdevice on '%s'");
check_blocks(signature_page);
if (!bit_test_and_clear(signature_page,0))
die("fatal: first page unreadable");
goodpages = PAGES - badpages - 1;
if (goodpages <= 0)
die("Unable to set up swap-space: unreadable");
printf("Setting up swapspace, size = %ld bytes\n",goodpages*PAGE_SIZE);
strncpy((char*)signature_page+PAGE_SIZE-10,"SWAP-SPACE",10);
if (lseek(DEV, 0, SEEK_SET))
die("unable to rewind swap-device");
if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE))
die("unable to write signature page");
close(DEV);
return 0;
}
int mkswap_main(struct FileInfo * unnecessary, int argc, char ** argv)
{
char * tmp;
long int pages=0;
int check=0;
if (argc && *argv)
program_name = *argv;
while (argc > 1) {
argv++;
argc--;
if (argv[0][0] != '-')
if (device_name) {
pages = strtol(argv[0],&tmp,0)>>(PAGE_SHIFT-10);
if (*tmp) {
usage(mkswap_usage);
exit(1);
}
} else
device_name = argv[0];
else while (*++argv[0])
switch (argv[0][0]) {
case 'c': check=1; break;
default: usage(mkswap_usage);
exit(1);
}
}
return mkswap(device_name, pages, check);
}

148
mnc.c Normal file
View File

@ -0,0 +1,148 @@
/* mnc: mini-netcat - built from the ground up for LRP
Copyright (C) 1998 Charles P. Wright
0.0.1 6K It works.
0.0.2 5K Smaller and you can also check the exit condition if you wish.
19980918 Busy Boxed! Dave Cinege
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>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/ioctl.h>
const char mnc_usage[] =
"mini-netcat 0.0.1 -- Open pipe to IP:port\n"
"\tmnc [IP] [port]\n";
int
mnc_main(struct FileInfo * i, int argc, char **argv)
{
int sfd;
int result;
int len;
int pid;
char ch;
struct sockaddr_in address;
struct hostent *hostinfo;
#ifdef SELECT
fd_set readfds, testfds;
#endif
sfd = socket(AF_INET, SOCK_STREAM, 0);
hostinfo = (struct hostent *) gethostbyname(argv[1]);
if (!hostinfo)
{
exit(1);
}
address.sin_family = AF_INET;
address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
address.sin_port = htons(atoi(argv[2]));
len = sizeof(address);
result = connect(sfd, (struct sockaddr *)&address, len);
if (result < 0)
{
exit(2);
}
#ifdef SELECT
FD_ZERO(&readfds);
FD_SET(sfd, &readfds);
FD_SET(fileno(stdin), &readfds);
while(1)
{
int fd;
int nread;
testfds = readfds;
result = select(FD_SETSIZE, &testfds, (fd_set *) NULL, (fd_set *) NULL, (struct timeval *) 0);
if(result < 1)
{
exit(3);
}
for(fd = 0; fd < FD_SETSIZE; fd++)
{
if(FD_ISSET(fd,&testfds))
{
ioctl(fd, FIONREAD, &nread);
if (nread == 0)
exit(0);
if(fd == sfd)
{
read(sfd, &ch, 1);
write(fileno(stdout), &ch, 1);
}
else
{
read(fileno(stdin), &ch, 1);
write(sfd, &ch, 1);
}
}
}
}
#else
pid = fork();
if (!pid)
{
int retval;
retval = 1;
while(retval == 1)
{
retval = read(fileno(stdin), &ch, 1);
write(sfd, &ch, 1);
}
}
else
{
int retval;
retval = 1;
while(retval == 1)
{
retval = read(sfd, &ch, 1);
write(fileno(stdout), &ch, 1);
}
}
exit(0);
#endif
}

126
monadic.c Normal file
View File

@ -0,0 +1,126 @@
#include "internal.h"
#include <stdio.h>
#include <string.h>
#include <grp.h>
extern int
monadic_main(
struct FileInfo * i
,int argc
,char * * argv)
{
int status = 0;
while ( argc > 1 && argv[1][0] == '-' ) {
switch ( argv[1][1] ) {
case 'c':
i->create = 1;
break;
case 'f':
i->force = 1;
break;
case 'g':
if ( argc > 2 ) {
struct group * g;
if ( (g = getgrnam(argv[2])) == 0 ) {
fprintf(stderr, "%s: no such group.\n", argv[1]);
return 1;
}
i->groupID = g->gr_gid;
i->changeGroupID = 1;
i->complainInPostProcess = 1;
argc--;
argv++;
break;
}
usage(i->applet->usage);
return 1;
case 'm':
if ( argc > 2 ) {
status = parse_mode(
argv[2]
,&i->orWithMode
,&i->andWithMode, 0);
if ( status == 0 ) {
i->changeMode = 1;
i->complainInPostProcess = 1;
argc--;
argv++;
break;
}
}
usage(i->applet->usage);
return 1;
case 'o':
if ( argc > 2 ) {
status = parse_user_name(argv[2], i);
if ( status != 0 )
return status;
i->changeUserID = 1;
i->complainInPostProcess = 1;
argc--;
argv++;
break;
}
usage(i->applet->usage);
return 1;
case 'p':
i->makeParentDirectories = 1;
break;
case 'r':
case 'R':
i->recursive = 1;
break;
case 's':
i->makeSymbolicLink = 1;
break;
default:
usage(i->applet->usage);
return 1;
}
argv++;
argc--;
}
while ( argc > 1 ) {
char * slash;
i->source = argv[1];
if ( (slash = strrchr(i->source, '/')) != 0 ) {
i->directoryLength = slash - i->source;
if ( i->source[i->directoryLength] == '\0' )
i->directoryLength = 0;
}
else
i->directoryLength = 0;
if ( !i->dyadic )
i->destination = i->source;
if ( lstat(i->source, &i->stat) == 0 ) {
i->isSymbolicLink = (i->stat.st_mode & S_IFMT)==S_IFLNK;
if ( i->isSymbolicLink )
if ( stat(i->source, &i->stat) != 0 )
memset(&i->stat, 0, sizeof(i->stat));
}
else
memset(&i->stat, 0, sizeof(i->stat));
if ( i->isSymbolicLink
|| !i->recursive
|| ((i->stat.st_mode & S_IFMT) != S_IFDIR) ) {
if ( i->applet->function )
status = i->applet->function(i);
if ( status == 0 )
status = post_process(i);
}
else
status = descend(i, i->applet->function);
if ( status != 0 && !i->force )
return status;
argv++;
argc--;
}
return 0;
}

110
more.c Normal file
View File

@ -0,0 +1,110 @@
#include "internal.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#define BB_MORE_TERM
#ifdef BB_MORE_TERM
#include <termios.h>
#include <signal.h>
FILE *cin;
struct termios initial_settings, new_settings;
void gotsig(int sig) {
tcsetattr(fileno(cin), TCSANOW, &initial_settings);
exit(0);
}
#endif
const char more_usage[] = "more [file]\n"
"\n"
"\tDisplays a file, one page at a time.\n"
"\tIf there are no arguments, the standard input is displayed.\n";
extern int
more_fn(const struct FileInfo * i)
{
FILE * f = stdin;
int c;
int lines = 0, tlines = 0;
int next_page = 0;
int rows = 24, cols = 79;
#ifdef BB_MORE_TERM
long sizeb = 0;
struct stat st;
struct winsize win;
#endif
if ( i ) {
if (! (f = fopen(i->source, "r") )) {
name_and_error(i->source);
return 1;
}
fstat(fileno(f), &st);
sizeb = st.st_size / 100;
}
#ifdef BB_MORE_TERM
cin = fopen("/dev/tty", "r");
tcgetattr(fileno(cin),&initial_settings);
new_settings = initial_settings;
new_settings.c_lflag &= ~ICANON;
new_settings.c_lflag &= ~ECHO;
tcsetattr(fileno(cin), TCSANOW, &new_settings);
(void) signal(SIGINT, gotsig);
ioctl(STDOUT_FILENO, TIOCGWINSZ, &win);
if (win.ws_row > 4) rows = win.ws_row - 2;
if (win.ws_col > 0) cols = win.ws_col - 1;
#endif
while ( (c = getc(f)) != EOF ) {
if ( next_page ) {
char garbage;
int len;
tlines += lines;
lines = 0;
next_page = 0; //Percentage is based on bytes, not lines.
if ( i && i->source ) //It is not very acurate, but still useful.
len = printf("%s - %%%2ld - line: %d", i->source, (ftell(f) - sizeb - sizeb) / sizeb, tlines);
else
len = printf("line: %d", tlines);
fflush(stdout);
#ifndef BB_MORE_TERM
read(2, &garbage, 1);
#else
do {
fread(&garbage, 1, 1, cin);
} while ((garbage != ' ') && (garbage != '\n'));
if (garbage == '\n') {
lines = rows;
tlines -= rows;
}
garbage = 0;
//clear line, since tabs don't overwrite.
while(len-- > 0) putchar('\b');
while(len++ < cols) putchar(' ');
while(len-- > 0) putchar('\b');
fflush(stdout);
#endif
}
putchar(c);
if ( c == '\n' && ++lines == (rows + 1) )
next_page = 1;
}
if ( f != stdin )
fclose(f);
#ifdef BB_MORE_TERM
gotsig(0);
#endif
return 0;
}

430
mount.c Normal file
View File

@ -0,0 +1,430 @@
/*
3/21/1999 Charles P. Wright <cpwright@cpwright.com>
searches through fstab when -a is passed
will try mounting stuff with all fses when passed -t auto
1999-04-17 Dave Cinege...Rewrote -t auto. Fixed ro mtab.
*/
#include "internal.h"
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <mntent.h>
#include <sys/mount.h>
#include <ctype.h>
const char mount_usage[] = "mount\n"
"\t\tmount [flags] special-device directory\n"
"\n"
"Flags:\n"
"\t-a:\tMount all file systems in fstab.\n"
"\t-f:\t\"Fake\" mount. Add entry to mount table but don't mount it.\n"
"\t-n:\tDon't write a mount table entry.\n"
"\t-o option:\tOne of many filesystem options, listed below.\n"
"\t-r:\tMount the filesystem read-only.\n"
"\t-t filesystem-type:\tSpecify the filesystem type.\n"
"\t-w:\tMount for reading and writing (default).\n"
"\n"
"Options for use with the \"-o\" flag:\n"
"\tasync / sync:\tWrites are asynchronous / synchronous.\n"
"\tdev / nodev:\tAllow use of special device files / disallow them.\n"
"\texec / noexec:\tAllow use of executable files / disallow them.\n"
"\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n"
"\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n"
"\tro / rw: Mount for read-only / read-write.\n"
"\t"
"There are EVEN MORE flags that are specific to each filesystem.\n"
"You'll have to see the written documentation for those.\n";
struct mount_options {
const char * name;
unsigned long and;
unsigned long or;
};
static const struct mount_options mount_options[] = {
{ "async", ~MS_SYNCHRONOUS,0 },
{ "defaults", ~0, 0 },
{ "dev", ~MS_NODEV, 0 },
{ "exec", ~MS_NOEXEC, 0 },
{ "nodev", ~0, MS_NODEV },
{ "noexec", ~0, MS_NOEXEC },
{ "nosuid", ~0, MS_NOSUID },
{ "remount", ~0, MS_REMOUNT },
{ "ro", ~0, MS_RDONLY },
{ "rw", ~MS_RDONLY, 0 },
{ "suid", ~MS_NOSUID, 0 },
{ "sync", ~0, MS_SYNCHRONOUS },
{ 0, 0, 0 }
};
static void
show_flags(unsigned long flags, char * buffer)
{
const struct mount_options * f = mount_options;
while ( f->name ) {
if ( flags & f->and ) {
int length = strlen(f->name);
memcpy(buffer, f->name, length);
buffer += length;
*buffer++ = ',';
*buffer = '\0';
}
f++;
}
}
static void
one_option(
char * option
,unsigned long * flags
,char * data)
{
const struct mount_options * f = mount_options;
while ( f->name != 0 ) {
if ( strcasecmp(f->name, option) == 0 ) {
*flags &= f->and;
*flags |= f->or;
return;
}
f++;
}
if ( *data ) {
data += strlen(data);
*data++ = ',';
}
strcpy(data, option);
}
static void
parse_mount_options(
char * options
,unsigned long * flags
,char * data)
{
while ( *options ) {
char * comma = strchr(options, ',');
if ( comma )
*comma = '\0';
one_option(options, flags, data);
if ( comma ) {
*comma = ',';
options = ++comma;
}
else
break;
}
}
int
mount_one(
char * blockDevice
,char * directory
,char * filesystemType
,unsigned long flags
,char * string_flags
,int noMtab
,int fake)
{
int error = 0;
int status = 0;
char buf[255];
if (!fake) {
if (*filesystemType == 'a') { //Will fail on real FS starting with 'a'
FILE *f = fopen("/proc/filesystems", "r");
if (f == NULL) return 1;
while (fgets(buf, sizeof(buf), f) != NULL) {
filesystemType = buf;
if (*filesystemType == '\t') { // Not a nodev filesystem
while (*filesystemType && *filesystemType != '\n') filesystemType++;
*filesystemType = '\0';
filesystemType = buf;
filesystemType++; //hop past tab
status = mount(blockDevice, directory, filesystemType,
flags|MS_MGC_VAL ,string_flags);
error = errno;
if (status == 0) break;
}
}
fclose(f);
} else {
status = mount( blockDevice, directory, filesystemType,
flags|MS_MGC_VAL ,string_flags);
error = errno;
}
}
if ( status == 0 ) {
char * s = &string_flags[strlen(string_flags)];
FILE * mountTable;
if ( s != string_flags ) {
*s++ = ',';
show_flags(flags, s);
}
if ( !noMtab && (mountTable = setmntent("/etc/mtab", "a+")) ) {
int length = strlen(directory);
struct mntent m;
if ( length > 1 && directory[length - 1] == '/' )
directory[length - 1] = '\0';
if ( filesystemType == 0 ) {
struct mntent * p
= findMountPoint(blockDevice, "/proc/mounts");
if ( p && p->mnt_type )
filesystemType = p->mnt_type;
}
m.mnt_fsname = blockDevice;
m.mnt_dir = directory;
m.mnt_type = filesystemType ? filesystemType : "default";
if (*string_flags) {
m.mnt_opts = string_flags;
} else {
if ( (flags | MS_RDONLY) == flags )
m.mnt_opts = "ro";
else
m.mnt_opts = "rw";
}
m.mnt_freq = 0;
m.mnt_passno = 0;
addmntent(mountTable, &m);
endmntent(mountTable);
}
return 0;
} else {
fprintf(stderr, "Mount %s", blockDevice);
if ( filesystemType && *filesystemType )
fprintf(stderr, " (type %s)", filesystemType);
fprintf(
stderr
," on %s: "
,directory);
switch ( error ) {
case EPERM:
if (geteuid() == 0)
fprintf(
stderr
,"mount point %s is not a directory"
,blockDevice);
else
fprintf(
stderr
,"must be superuser to use mount");
break;
case EBUSY:
fprintf(
stderr
,"%s already mounted or %s busy"
,blockDevice
,directory);
break;
case ENOENT:
{
struct stat statbuf;
if ( stat(directory, &statbuf) != 0 )
fprintf(
stderr
,"directory %s does not exist"
,directory);
else if ( stat(blockDevice, &statbuf) != 0 )
fprintf(
stderr
,"block device %s does not exist"
,blockDevice);
else
fprintf(
stderr
,"%s is not mounted on %s, but the mount table says it is."
,blockDevice
,directory);
break;
}
case ENOTDIR:
fprintf(
stderr
,"%s is not a directory"
,directory);
break;
case EINVAL:
fprintf(
stderr
,"wrong filesystem type, or bad superblock on %s"
,blockDevice);
break;
case EMFILE:
fprintf(stderr, "mount table full");
break;
case EIO:
fprintf(
stderr
,"I/O error reading %s"
,blockDevice);
break;
case ENODEV:
{
FILE * f = fopen("/proc/filesystems", "r");
fprintf(
stderr
,"filesystem type %s not in kernel.\n"
,filesystemType);
fprintf(stderr, "Do you need to load a module?\n");
if ( f ) {
char buf[100];
fprintf(
stderr
,"Here are the filesystem types the kernel"
" can mount:\n");
while ( fgets(buf, sizeof(buf), f) != 0 )
fprintf(stderr, "\t%s", buf);
fclose(f);
}
break;
}
case ENOTBLK:
fprintf(
stderr
,"%s is not a block device"
,blockDevice);
break;
case ENXIO:
fprintf(
stderr
,"%s is not a valid block device"
,blockDevice);
break;
default:
fputs(strerror(errno), stderr);
}
putc('\n', stderr);
return -1;
}
}
extern int
mount_main(struct FileInfo * i, int argc, char * * argv)
{
char string_flags[1024];
unsigned long flags = 0;
char * filesystemType = "auto";
int fake = 0;
int noMtab = 0;
int all = 0;
*string_flags = '\0';
if ( argc == 1 ) {
FILE * mountTable;
if ( (mountTable = setmntent("/etc/mtab", "r")) ) {
struct mntent * m;
while ( (m = getmntent(mountTable)) != 0 ) {
printf(
"%s on %s type %s (%s)\n"
,m->mnt_fsname
,m->mnt_dir
,m->mnt_type
,m->mnt_opts);
}
endmntent(mountTable);
}
return 0;
}
while ( argc >= 2 && argv[1][0] == '-' ) {
switch ( argv[1][1] ) {
case 'f':
fake = 1;
break;
case 'n':
noMtab = 1;
break;
case 'o':
if ( argc < 3 ) {
usage(mount_usage);
return 1;
}
parse_mount_options(argv[2], &flags, string_flags);
argc--;
argv++;
break;
case 'r':
flags |= MS_RDONLY;
break;
case 't':
if ( argc < 3 ) {
usage(mount_usage);
return 1;
}
filesystemType = argv[2];
argc--;
argv++;
break;
case 'v':
break;
case 'w':
flags &= ~MS_RDONLY;
break;
case 'a':
all = 1;
break;
default:
usage(mount_usage);
return 1;
}
argc--;
argv++;
}
if (all == 1) {
struct mntent *m;
FILE *f = setmntent("/etc/fstab", "r");
if (f == NULL) {
return 1;
}
// FIXME: Combine read routine (make new function) with unmount_all to save space.
while ((m = getmntent(f)) != NULL) {
// If the file system isn't noauto, and isn't mounted on /, mount it
if ((!strstr(m->mnt_opts, "noauto")) && (m->mnt_dir[1] != '\0')
&& !((m->mnt_type[0] == 's') && (m->mnt_type[1] == 'w'))
&& !((m->mnt_type[0] == 'n') && (m->mnt_type[1] == 'f'))) {
mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type, flags, m->mnt_opts, noMtab, fake);
}
}
endmntent(f);
} else {
if ( argc >= 3 ) {
if ( mount_one( argv[1], argv[2], filesystemType, flags, string_flags, noMtab, fake) == 0 )
return 0;
else
return 1;
} else {
usage(mount_usage);
return 1;
}
}
return 0;
}

98
mt.c Normal file
View File

@ -0,0 +1,98 @@
#include "internal.h"
#include <stdio.h>
#include <sys/mtio.h>
#include <sys/fcntl.h>
const char mt_usage[] = "mt [-f device] opcode value\n";
struct mt_opcodes {
char * name;
short value;
};
/* missing: eod/seod, stoptions, stwrthreshold, densities */
static const struct mt_opcodes opcodes[] = {
{ "bsf", MTBSF },
{ "bsfm", MTBSFM },
{ "bsr", MTBSR },
{ "bss", MTBSS },
{ "datacompression", MTCOMPRESSION },
{ "eom", MTEOM },
{ "erase", MTERASE },
{ "fsf", MTFSF },
{ "fsfm", MTFSFM },
{ "fsr", MTFSR },
{ "fss", MTFSS },
{ "load", MTLOAD },
{ "lock", MTLOCK },
{ "mkpart", MTMKPART },
{ "nop", MTNOP },
{ "offline",MTOFFL },
{ "rewoffline",MTOFFL },
{ "ras1", MTRAS1 },
{ "ras2", MTRAS2 },
{ "ras3", MTRAS3 },
{ "reset", MTRESET },
{ "retension", MTRETEN },
{ "rew", MTREW },
{ "seek", MTSEEK },
{ "setblk", MTSETBLK },
{ "setdensity", MTSETDENSITY },
{ "drvbuffer", MTSETDRVBUFFER },
{ "setpart", MTSETPART },
{ "tell", MTTELL },
{ "wset", MTWSM },
{ "unload", MTUNLOAD },
{ "unlock", MTUNLOCK },
{ "eof", MTWEOF },
{ "weof", MTWEOF },
{ 0, 0 }
};
extern int
mt_main(struct FileInfo * i, int argc, char * * argv)
{
const char * file = "/dev/tape";
const struct mt_opcodes * code = opcodes;
struct mtop op;
int fd;
if ( strcmp(argv[1], "-f") == 0 ) {
if ( argc < 4 ) {
usage(mt_usage);
return 1;
}
file = argv[2];
argv += 2;
argc -= 2;
}
while ( code->name != 0 ) {
if ( strcmp(code->name, argv[1]) == 0 )
break;
code++;
}
if ( code->name == 0 ) {
fprintf(stderr, "mt: unrecognized opcode %s.\n", argv[1]);
return 1;
}
op.mt_op = code->value;
if ( argc >= 3 )
op.mt_count = atoi(argv[2]);
else
op.mt_count = 1; /* One, not zero, right? */
if ( (fd = open(file, O_RDONLY, 0)) < 0 ) {
name_and_error(file);
return 1;
}
if ( ioctl(fd, MTIOCTOP, &op) != 0 ) {
name_and_error(file);
return 1;
}
return 0;
}

38
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);
}

41
postprocess.c Normal file
View File

@ -0,0 +1,41 @@
#include "internal.h"
extern int
post_process(const struct FileInfo * i)
{
int status = 0;
if ( i->destination == 0 || *i->destination == 0 )
return 0;
if ( status == 0 && i->changeMode ) {
mode_t mode = i->stat.st_mode & 07777;
mode &= i->andWithMode;
mode |= i->orWithMode;
status = chmod(i->destination, mode);
if ( status != 0 && i->complainInPostProcess && !i->force ) {
name_and_error(i->destination);
return 1;
}
}
if ( i->changeUserID || i->changeGroupID ) {
uid_t uid = i->stat.st_uid;
gid_t gid = i->stat.st_gid;
if ( i->changeUserID )
uid = i->userID;
if ( i->changeGroupID )
gid = i->groupID;
status = chown(i->destination, uid, gid);
if ( status != 0 && i->complainInPostProcess && !i->force ) {
name_and_error(i->destination);
return 1;
}
}
return status;
}

531
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

140
procps/kill.c Normal file
View File

@ -0,0 +1,140 @@
#include "internal.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
const char kill_usage[] = "kill [-signal] process-id [process-id ...]\n";
struct signal_name {
const char * name;
int number;
};
const struct signal_name signames[] = {
{ "HUP", SIGHUP },
{ "INT", SIGINT },
{ "QUIT", SIGQUIT },
{ "ILL", SIGILL },
{ "TRAP", SIGTRAP },
{ "ABRT", SIGABRT },
#ifndef __alpha__
{ "IOT", SIGIOT },
#endif
#if defined(sparc) || defined(__alpha__)
{ "EMT", SIGEMT },
#else
{ "BUS", SIGBUS },
#endif
{ "FPE", SIGFPE },
{ "KILL", SIGKILL },
#if defined(sparc) || defined(__alpha__)
{ "BUS", SIGBUS },
#else
{ "USR1", SIGUSR1 },
#endif
{ "SEGV", SIGSEGV },
#if defined(sparc) || defined(__alpha__)
{ "SYS", SIGSYS },
#else
{ "USR2", SIGUSR2 },
#endif
{ "PIPE", SIGPIPE },
{ "ALRM", SIGALRM },
{ "TERM", SIGTERM },
#if defined(sparc) || defined(__alpha__)
{ "URG", SIGURG },
{ "STOP", SIGSTOP },
{ "TSTP", SIGTSTP },
{ "CONT", SIGCONT },
{ "CHLD", SIGCHLD },
{ "TTIN", SIGTTIN },
{ "TTOU", SIGTTOU },
{ "IO", SIGIO },
# ifndef __alpha__
{ "POLL", SIGIO },
# endif
{ "XCPU", SIGXCPU },
{ "XFSZ", SIGXFSZ },
{ "VTALRM", SIGVTALRM },
{ "PROF", SIGPROF },
{ "WINCH", SIGWINCH },
# ifdef __alpha__
{ "INFO", SIGINFO },
# else
{ "LOST", SIGLOST },
# endif
{ "USR1", SIGUSR1 },
{ "USR2", SIGUSR2 },
#else
{ "STKFLT", SIGSTKFLT },
{ "CHLD", SIGCHLD },
{ "CONT", SIGCONT },
{ "STOP", SIGSTOP },
{ "TSTP", SIGTSTP },
{ "TTIN", SIGTTIN },
{ "TTOU", SIGTTOU },
{ "URG", SIGURG },
{ "XCPU", SIGXCPU },
{ "XFSZ", SIGXFSZ },
{ "VTALRM", SIGVTALRM },
{ "PROF", SIGPROF },
{ "WINCH", SIGWINCH },
{ "IO", SIGIO },
{ "POLL", SIGPOLL },
{ "PWR", SIGPWR },
{ "UNUSED", SIGUNUSED },
#endif
{ 0, 0 }
};
extern int
kill_main(struct FileInfo * i, int argc, char * * argv)
{
int had_error = 0;
int sig = SIGTERM;
if ( argv[1][0] == '-' ) {
if ( argv[1][1] >= '0' && argv[1][1] <= '9' ) {
sig = atoi(&argv[1][1]);
if ( sig < 0 || sig >= NSIG ) {
usage(kill_usage);
exit(-1);
}
}
else {
const struct signal_name * s = signames;
for ( ; ; ) {
if ( strcmp(s->name, &argv[1][1]) == 0 ) {
sig = s->number;
break;
}
s++;
if ( s->name == 0 ) {
usage(kill_usage);
exit(-1);
}
}
}
argv++;
argc--;
}
while ( argc > 1 ) {
int pid;
if ( argv[1][0] < '0' || argv[1][0] > '9' ) {
usage(kill_usage);
exit(-1);
}
pid = atoi(argv[1]);
if ( kill(pid, sig) != 0 ) {
had_error = 1;
perror(argv[1]);
}
argv++;
argc--;
}
if ( had_error )
return -1;
else
return 0;
}

18
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;
}

12
reboot.c Normal file
View File

@ -0,0 +1,12 @@
#include "internal.h"
#include <signal.h>
const char reboot_usage[] = "reboot\n"
"\n\t"
"\treboot the system.\n";
extern int
reboot_main(struct FileInfo * i, int argc, char * * argv)
{
return kill(1, SIGUSR2);
}

30
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
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
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;
}

2
smtpout Normal file
View File

@ -0,0 +1,2 @@
echo '.' >smtpout echo 'QUIT' >smtpout
kjfjkjd

52
swapoff.c Normal file
View File

@ -0,0 +1,52 @@
#include <sys/swap.h>
#include <string.h>
#include <errno.h>
#include <mntent.h>
#include "internal.h"
const char swapoff_usage[] = "swapoff block-device\n"
"\n"
"\tStop swapping virtual memory pages on the given device.\n";
extern int
swapoff_fn(const struct FileInfo * i)
{
struct mntent entries[100];
int count = 0;
FILE * swapsTable = setmntent("/etc/swaps", "r");
struct mntent * m;
if (!(swapoff(i->source))) {
if ( swapsTable == 0 ) {
fprintf(stderr, "/etc/swaps: %s\n", strerror(errno));
return 1;
}
while ( (m = getmntent(swapsTable)) != 0 ) {
entries[count].mnt_fsname = strdup(m->mnt_fsname);
entries[count].mnt_dir = strdup(m->mnt_dir);
entries[count].mnt_type = strdup(m->mnt_type);
entries[count].mnt_opts = strdup(m->mnt_opts);
entries[count].mnt_freq = m->mnt_freq;
entries[count].mnt_passno = m->mnt_passno;
count++;
}
endmntent(swapsTable);
if ( (swapsTable = setmntent("/etc/swaps", "w")) ) {
int id;
for ( id = 0; id < count; id++ ) {
int result =
(strcmp(entries[id].mnt_fsname, i->source)==0
||strcmp(entries[id].mnt_dir, i->source)==0);
if ( result )
continue;
else
addmntent(swapsTable, &entries[id]);
}
endmntent(swapsTable);
}
else if ( errno != EROFS )
fprintf(stderr, "/etc/swaps: %s\n", strerror(errno));
return (0);
}
return (-1);
}

34
swapon.c Normal file
View File

@ -0,0 +1,34 @@
#include <stdio.h>
#include <mntent.h>
#include <sys/swap.h>
#include "internal.h"
const char swapon_usage[] = "swapon block-device\n"
"\n"
"\tSwap virtual memory pages on the given device.\n";
extern int
swapon_fn(const struct FileInfo * i)
{
FILE *swapsTable;
struct mntent m;
if (!(swapon(i->source, 0))) {
if ((swapsTable = setmntent("/etc/swaps", "a+"))) {
/* Needs the cast to avoid warning about conversion from
* const char* to just char*
*/
m.mnt_fsname = (char*)i->source;
m.mnt_dir = "none";
m.mnt_type = "swap";
m.mnt_opts = "sw";
m.mnt_freq = 0;
m.mnt_passno = 0;
addmntent(swapsTable, &m);
endmntent(swapsTable);
}
return (0);
}
return (-1);
}

11
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();
}

Some files were not shown because too many files have changed in this diff Show More