From 8e2707b81b0c90295c9fdf92a576925442d22147 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 20 Aug 2014 21:11:13 +0200 Subject: add sash, simpleinit and a uclibc config for nonmmu case --- mk/image.mk | 8 + package/busybox/config/init/Config.in | 3 + package/busybox/config/shell/Config.in | 2 +- package/sash/Makefile | 25 + package/sash/files/rc | 47 ++ package/sash/src/Makefile | 38 ++ package/sash/src/README | 6 + package/sash/src/cmd_uclinux.c | 127 ++++ package/sash/src/cmds.c | 899 +++++++++++++++++++++++++ package/sash/src/cp.c | 27 + package/sash/src/date.c | 54 ++ package/sash/src/df.c | 55 ++ package/sash/src/free.c | 44 ++ package/sash/src/hexdump.c | 127 ++++ package/sash/src/hostname.c | 24 + package/sash/src/libsash/Makefile | 20 + package/sash/src/libsash/utils.c | 706 ++++++++++++++++++++ package/sash/src/ls.c | 311 +++++++++ package/sash/src/ps.c | 317 +++++++++ package/sash/src/reboot.c | 93 +++ package/sash/src/sash.c | 1118 ++++++++++++++++++++++++++++++++ package/sash/src/sash.h | 70 ++ package/sash/src/shutdown.c | 75 +++ package/simpleinit/Makefile | 30 + package/simpleinit/files/rc | 47 ++ package/simpleinit/src/pathnames.h | 37 ++ package/simpleinit/src/simpleinit.c | 1046 ++++++++++++++++++++++++++++++ target/config/Config.in | 2 + target/config/Config.in.runtime | 16 +- target/m68k/uclibc-ng.config | 5 +- target/m68k/uclibc.config | 81 +-- 31 files changed, 5416 insertions(+), 44 deletions(-) create mode 100644 package/sash/Makefile create mode 100755 package/sash/files/rc create mode 100644 package/sash/src/Makefile create mode 100644 package/sash/src/README create mode 100644 package/sash/src/cmd_uclinux.c create mode 100644 package/sash/src/cmds.c create mode 100644 package/sash/src/cp.c create mode 100644 package/sash/src/date.c create mode 100644 package/sash/src/df.c create mode 100644 package/sash/src/free.c create mode 100644 package/sash/src/hexdump.c create mode 100644 package/sash/src/hostname.c create mode 100644 package/sash/src/libsash/Makefile create mode 100644 package/sash/src/libsash/utils.c create mode 100644 package/sash/src/ls.c create mode 100644 package/sash/src/ps.c create mode 100644 package/sash/src/reboot.c create mode 100644 package/sash/src/sash.c create mode 100644 package/sash/src/sash.h create mode 100644 package/sash/src/shutdown.c create mode 100644 package/simpleinit/Makefile create mode 100755 package/simpleinit/files/rc create mode 100644 package/simpleinit/src/pathnames.h create mode 100644 package/simpleinit/src/simpleinit.c diff --git a/mk/image.mk b/mk/image.mk index 321794f76..e47a82ac1 100644 --- a/mk/image.mk +++ b/mk/image.mk @@ -6,6 +6,8 @@ ifeq (${ADK_BINSH_ASH},y) BINSH:=ash else ifeq (${ADK_BINSH_BASH},y) BINSH:=bash +else ifeq (${ADK_BINSH_SASH},y) +BINSH:=sash else ifeq (${ADK_BINSH_HUSH},y) BINSH:=hush else ifeq (${ADK_BINSH_MKSH},y) @@ -21,6 +23,8 @@ ifeq (${ADK_ROOTSH_ASH},y) ROOTSH:=/bin/ash else ifeq (${ADK_ROOTSH_BASH},y) ROOTSH:=/bin/bash +else ifeq (${ADK_ROOTSH_SASH},y) +ROOTSH:=/bin/sash else ifeq (${ADK_ROOTSH_HUSH},y) ROOTSH:=/bin/hush else ifeq (${ADK_ROOTSH_MKSH},y) @@ -54,9 +58,13 @@ image-prepare-post: mkfontdir ${TARGET_DIR}/usr/share/fonts/X11/$${i}; \ done; \ fi +ifeq (${ADK_ROOTSH_SASH},) $(SED) '/^root:/s!:/bin/sh$$!:${ROOTSH}!' ${TARGET_DIR}/etc/passwd +endif +ifeq (${ADK_BINSH_SASH},) -rm -f ${TARGET_DIR}/bin/sh ln -sf ${BINSH} ${TARGET_DIR}/bin/sh +endif test -z $(GIT) || \ $(GIT) log -1|head -1|sed -e 's#commit ##' \ > $(TARGET_DIR)/etc/.adkversion diff --git a/package/busybox/config/init/Config.in b/package/busybox/config/init/Config.in index d8b4a449e..58ab4bca4 100644 --- a/package/busybox/config/init/Config.in +++ b/package/busybox/config/init/Config.in @@ -44,6 +44,7 @@ config BUSYBOX_FEATURE_BOOTCHARTD_CONFIG_FILE help Enable reading and parsing of $PWD/bootchartd.conf and /etc/bootchartd.conf files. + config BUSYBOX_HALT bool "poweroff, halt, and reboot" default y @@ -69,9 +70,11 @@ config BUSYBOX_TELINIT_PATH When busybox halt and friends have to call external telinit to facilitate proper shutdown, this path is to be used when locating telinit executable. + config BUSYBOX_INIT bool "init" default y + depends on !ADK_TARGET_UCLINUX select BUSYBOX_FEATURE_SYSLOG help init is the first program run when the system boots. diff --git a/package/busybox/config/shell/Config.in b/package/busybox/config/shell/Config.in index b1b8ad4b2..dd396b015 100644 --- a/package/busybox/config/shell/Config.in +++ b/package/busybox/config/shell/Config.in @@ -299,7 +299,7 @@ config BUSYBOX_MSH choice prompt "Choose which shell is aliased to 'sh' name" - default FEATURE_SH_IS_ASH + default FEATURE_SH_IS_NONE help Choose which shell you want to be executed by 'sh' alias. The ash shell is the most bash compatible and full featured one. diff --git a/package/sash/Makefile b/package/sash/Makefile new file mode 100644 index 000000000..16a767a70 --- /dev/null +++ b/package/sash/Makefile @@ -0,0 +1,25 @@ +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include ${ADK_TOPDIR}/rules.mk + +PKG_NAME:= sash +PKG_VERSION:= 1.0 +PKG_RELEASE:= 1 +PKG_DESCR:= standalone shell +PKG_SECTION:= base/shells + +NO_DISTFILES:= 1 + +include ${ADK_TOPDIR}/mk/package.mk + +$(eval $(call PKG_template,SASH,sash,${PKG_VERSION}-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) + +CONFIG_STYLE:= manual +INSTALL_STYLE:= manual + +do-install: + ${INSTALL_DIR} ${IDIR_SASH}/bin + ${INSTALL_BIN} ${WRKBUILD}/sh ${IDIR_SASH}/bin/sh + +include ${ADK_TOPDIR}/mk/pkg-bottom.mk diff --git a/package/sash/files/rc b/package/sash/files/rc new file mode 100755 index 000000000..33d60a4b6 --- /dev/null +++ b/package/sash/files/rc @@ -0,0 +1,47 @@ +#!/bin/sh +set -x +export PATH=/bin:/sbin:/usr/bin:/usr/sbin +ln -s /proc/self/fd/2 /dev/stderr +: ${rcquiet=0} +if [ $rcquiet -ne 1 ];then + echo "System initialization ..." +fi + +# remount /dev with smaller size +mount -o remount,nosuid,size=128k,mode=0755 -t tmpfs mdev /dev + +# start mdev dynamic device node management +echo >/dev/mdev.seq +if [ -f /proc/sys/kernel/hotplug ];then + echo "/sbin/mdev" >/proc/sys/kernel/hotplug +fi +# creates f.e. /dev/root +mdev -s + +# seed some random +cat /etc/.rnd >/dev/urandom 2>&1 + +# setup cfgfs +[ -x /sbin/cfgfs ] && { + cfgfs setup + mount -o remount,ro / +} + +# remount /tmp with smaller size +size=$(cat /etc/tmpfs 2>/dev/null) +[ -z $size ] && size=2048 +mount -o remount,nosuid,nodev,mode=1777,size=${size}k -t tmpfs tmpfs /tmp + +# create some useful directories in tmpfs +mkdir -p /var/log +mkdir -p /var/run +mkdir -p /var/tmp +touch /var/log/lastlog +touch /var/log/wtmp + +HOSTNAME= +[[ -s /etc/hostname ]] && HOSTNAME=$(cat /etc/hostname) +HOSTNAME=${HOSTNAME%%.*} +echo ${HOSTNAME:=openadk} >/proc/sys/kernel/hostname + +chown 0:0 /tmp; chmod 1777 /tmp diff --git a/package/sash/src/Makefile b/package/sash/src/Makefile new file mode 100644 index 000000000..90d6adf99 --- /dev/null +++ b/package/sash/src/Makefile @@ -0,0 +1,38 @@ + +SH = sh +SHOBJS = sash.o cmds.o cmd_uclinux.o ls.o hexdump.o df.o free.o \ + hostname.o date.o + +SHUTDOWN = shutdown +SHUTDOWNOBJS = shutdown.o + +REBOOT = reboot +REBOOTOBJS = reboot.o + +SHOBJS += ps.o +CFLAGS += -DCONFIG_USER_SASH_PS + +LIBSASH = libsash/libsash.a + +CFLAGS += -DCOMMAND_HISTORY + +all: $(SH) $(SHUTDOWN) $(REBOOT) + +$(SH): $(SHOBJS) $(LIBSASH) + $(CC) $(LDFLAGS) -o $@ $(SHOBJS) $(LIBSASH) $(LDLIBS$(LDLIBS_$@)) + +$(SHUTDOWN): $(SHUTDOWNOBJS) $(LIBSASH) + $(CC) $(LDFLAGS) -o $@ $(SHUTDOWNOBJS) $(LIBSASH) $(LDLIBS) + +$(REBOOT): $(REBOOTOBJS) $(LIBSASH) + $(CC) $(LDFLAGS) -o $@ $(REBOOTOBJS) $(LIBSASH) $(LDLIBS$(LDLIBS_$@)) + +dummy_target: + +$(LIBSASH): dummy_target + $(MAKE) -C libsash + +clean: + -rm -f $(SH) $(SHUTDOWN) $(REBOOT) *.elf *.gdb *.o + $(MAKE) -C libsash clean + diff --git a/package/sash/src/README b/package/sash/src/README new file mode 100644 index 000000000..191c7de63 --- /dev/null +++ b/package/sash/src/README @@ -0,0 +1,6 @@ + + + This shell is an adaption of David Bell's "sash", the stand-along shell, +with some adaptions (and truncations) for our environment. It also includes +a few utilities (like reboot and ps) that weren't part of the original sash. + diff --git a/package/sash/src/cmd_uclinux.c b/package/sash/src/cmd_uclinux.c new file mode 100644 index 000000000..bf66c4529 --- /dev/null +++ b/package/sash/src/cmd_uclinux.c @@ -0,0 +1,127 @@ + +#include "sash.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#if 0 +char psbuf[256]; +char name[40]; +int pid, state; +char statec; + +void +do_ps(argc, argv) + char **argv; +{ + int i; + int h; + int max; + FILE * f; + DIR * d; + struct dirent * de; + int l; + + printf(" PID TTY STAT TIME COMMAND\n"); + + + d = opendir("/proc"); + if (!d) + return; + + while (de = readdir(d)) { + for(i=0;id_name);i++) + if (!isdigit(de->d_name[i])) + goto next; + + sprintf(psbuf, "/proc/%s/stat", de->d_name); + h = open(psbuf, O_RDONLY); + + if (h==-1) + continue; + + l = read(h, psbuf, 255); + if (l<=0) { + perror("Unable to read status"); + close(h); + continue; + } + + psbuf[l] = '\0'; + psbuf[255] = '\0'; + + + if (sscanf(psbuf, + "%d %s %c", + &pid, name, &statec)<3) + { + perror("Unable to parse status"); + close(h); + continue; + } + + state = statec; + + close(h); + + sprintf(psbuf, "/proc/%s/cmdline", de->d_name); + h = open(psbuf, O_RDONLY); + + if (h == -1) { + perror("Unable to open cmdline"); + continue; + } + + l = read(h, psbuf, 255); + if (l < 0) { + perror("Unable to read cmdline"); + close(h); + continue; + } + + close(h); + + psbuf[255] = psbuf[l] = '\0'; + + printf("%5d %3s %c --:-- %s\n", pid, "", state, psbuf); + next: + } + + closedir(d); +} +#endif + +void +do_cat(argc, argv) + char **argv; +{ + int fd; + char *name; + size_t l; + char buf[256]; + + while (argc-- > 1) { + if (intflag) { + return; + } + name = *(++argv); + + fd = open(name, O_RDONLY); + if (fd < 0) { + perror(name); + return; + } + + while ((l = read(fd, buf, sizeof(buf))) > 0) { + fwrite(buf, 1, l, stdout); + } + close(fd); + } +} diff --git a/package/sash/src/cmds.c b/package/sash/src/cmds.c new file mode 100644 index 000000000..d822d9f6d --- /dev/null +++ b/package/sash/src/cmds.c @@ -0,0 +1,899 @@ +/* + * Modifications for uClinux + * Copyright (C) 1998 Kenneth Albanowski + * + * Original code + * Copyright (c) 1993 by David I. Bell + * Permission is granted to use, distribute, or modify this source, + * provided that this copyright notice remains intact. + * + * Most simple built-in commands are here. + */ + +#include "sash.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef EMBED +#include +#endif + +void +do_echo(argc, argv) + char **argv; +{ + BOOL first; + + first = TRUE; + while (argc-- > 1) { + if (!first) + fputc(' ', stdout); + first = FALSE; + fputs(*++argv, stdout); + } + fputc('\n', stdout); +} + + +void +do_pwd(argc, argv) + char **argv; +{ + char buf[PATHLEN]; + + if (getcwd(buf, PATHLEN) == NULL) { + fprintf(stderr, "Cannot get current directory\n"); + return; + } + + printf("%s\n", buf); +} + +void +do_time(argc, argv) + char ** argv; +{ + struct timeval tv; + gettimeofday(&tv, 0); + printf("Time of day = %d.%6.6d seconds\n", tv.tv_sec, tv.tv_usec); +} + +void +do_cd(argc, argv) + char **argv; +{ + char *path; + + if (argc > 1) + path = argv[1]; + else { + path = getenv("HOME"); + if (path == NULL) { + fprintf(stderr, "No HOME environment variable\n"); + return; + } + } + + if (chdir(path) < 0) + perror(path); +} + + +void +do_mkdir(argc, argv) + char **argv; +{ + int state = 0, mode = -1; + + while (argc-- > 1) { + if (state == 0) { + if (strcmp(argv[1], "-m") == 0) + state = 1; + else if (mkdir(argv[1], 0777) < 0) + perror(argv[1]); + else if (mode != -1 && chmod(argv[1], mode) < 0) + perror(argv[1]); + } else if (state == 1) { + mode = strtol(argv[1], NULL, 8); + state = 0; + } + argv++; + } +} + +void +do_sleep(argc, argv) + char **argv; +{ + if (argc > 1) + sleep(atoi(argv[1])); +} + +void +do_mknod(argc, argv) + char **argv; +{ + char *cp; + int mode; + int major; + int minor; + + mode = 0666; + + if (strcmp(argv[2], "b") == 0) + mode |= S_IFBLK; + else if (strcmp(argv[2], "c") == 0) + mode |= S_IFCHR; + else { + fprintf(stderr, "Bad device type\n"); + return; + } + + major = 0; + cp = argv[3]; + while (isdecimal(*cp)) + major = major * 10 + *cp++ - '0'; + + if (*cp || (major < 0) || (major > 255)) { + fprintf(stderr, "Bad major number\n"); + return; + } + + minor = 0; + cp = argv[4]; + while (isdecimal(*cp)) + minor = minor * 10 + *cp++ - '0'; + + if (*cp || (minor < 0) || (minor > 255)) { + fprintf(stderr, "Bad minor number\n"); + return; + } + + if (mknod(argv[1], mode, major * 256 + minor) < 0) + perror(argv[1]); +} + + +void +do_rmdir(argc, argv) + char **argv; +{ + while (argc-- > 1) { + if (rmdir(argv[1]) < 0) + perror(argv[1]); + argv++; + } +} + + +void +do_sync(argc, argv) + char **argv; +{ +#ifdef CONFIG_USER_FLATFSD_FLATFSD + system("exec flatfsd -s"); +#endif + sync(); +} + + +void +do_rm(argc, argv) + char **argv; +{ + while (argc-- > 1) { + if (unlink(argv[1]) < 0) + perror(argv[1]); + argv++; + } +} + + +void +do_chmod(argc, argv) + char **argv; +{ + char *cp; + int mode; + + mode = 0; + cp = argv[1]; + while (isoctal(*cp)) + mode = mode * 8 + (*cp++ - '0'); + + if (*cp) { + fprintf(stderr, "Mode must be octal\n"); + return; + } + argc--; + argv++; + + while (argc-- > 1) { + if (chmod(argv[1], mode) < 0) + perror(argv[1]); + argv++; + } +} + + +void +do_chown(argc, argv) + char **argv; +{ + char *cp; + int uid; + struct passwd *pwd; + struct stat statbuf; + + cp = argv[1]; + if (isdecimal(*cp)) { + uid = 0; + while (isdecimal(*cp)) + uid = uid * 10 + (*cp++ - '0'); + + if (*cp) { + fprintf(stderr, "Bad uid value\n"); + return; + } + } else { + pwd = getpwnam(cp); + if (pwd == NULL) { + fprintf(stderr, "Unknown user name\n"); + return; + } + + uid = pwd->pw_uid; + } + + argc--; + argv++; + + while (argc-- > 1) { + argv++; + if ((stat(*argv, &statbuf) < 0) || + (chown(*argv, uid, statbuf.st_gid) < 0)) + perror(*argv); + } +} + + +void +do_chgrp(argc, argv) + char **argv; +{ + char *cp; + int gid; + struct group *grp; + struct stat statbuf; + + 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; + } + } else { + grp = getgrnam(cp); + if (grp == NULL) { + fprintf(stderr, "Unknown group name\n"); + return; + } + + gid = grp->gr_gid; + } + + argc--; + argv++; + + while (argc-- > 1) { + argv++; + if ((stat(*argv, &statbuf) < 0) || + (chown(*argv, statbuf.st_uid, gid) < 0)) + perror(*argv); + } +} + + +void +do_touch(argc, argv) + char **argv; +{ + char *name; + int fd; + struct utimbuf now; + + time(&now.actime); + now.modtime = now.actime; + + while (argc-- > 1) { + name = *(++argv); + + if (utime(name, &now) <0) + { + fd = open(name, O_CREAT | O_WRONLY | O_EXCL, 0666); + if (fd >= 0) + { + close(fd); + continue; + } + perror(name); + } + } +} + + +void +do_mv(argc, argv) + char **argv; +{ + int dirflag; + char *srcname; + char *destname; + char *lastarg; + + lastarg = argv[argc - 1]; + + dirflag = isadir(lastarg); + + if ((argc > 3) && !dirflag) { + fprintf(stderr, "%s: not a directory\n", lastarg); + return; + } + + while (argc-- > 2) { + srcname = *(++argv); + if (access(srcname, 0) < 0) { + perror(srcname); + continue; + } + + destname = lastarg; + if (dirflag) + destname = buildname(destname, srcname); + + if (rename(srcname, destname) >= 0) + continue; + + if (errno != EXDEV) { + perror(destname); + continue; + } + + if (!copyfile(srcname, destname, TRUE)) + continue; + + if (unlink(srcname) < 0) + perror(srcname); + } +} + + +void +do_ln(argc, argv) + char **argv; +{ + int dirflag; + char *srcname; + char *destname; + char *lastarg; + + if (argv[1][0] == '-') { + if (strcmp(argv[1], "-s")) { + fprintf(stderr, "Unknown option\n"); + return; + } + + if (argc != 4) { + fprintf(stderr, "Wrong number of arguments for symbolic link\n"); + return; + } + +#ifdef S_ISLNK + if (symlink(argv[2], argv[3]) < 0) + perror(argv[3]); +#else + fprintf(stderr, "Symbolic links are not allowed\n"); +#endif + return; + } + + /* + * Here for normal hard links. + */ + lastarg = argv[argc - 1]; + dirflag = isadir(lastarg); + + if ((argc > 3) && !dirflag) { + fprintf(stderr, "%s: not a directory\n", lastarg); + return; + } + + while (argc-- > 2) { + srcname = *(++argv); + if (access(srcname, 0) < 0) { + perror(srcname); + continue; + } + + destname = lastarg; + if (dirflag) + destname = buildname(destname, srcname); + + if (link(srcname, destname) < 0) { + perror(destname); + continue; + } + } +} + + +void +do_cp(argc, argv) + char **argv; +{ + BOOL dirflag; + char *srcname; + char *destname; + char *lastarg; + + lastarg = argv[argc - 1]; + + dirflag = isadir(lastarg); + + if ((argc > 3) && !dirflag) { + fprintf(stderr, "%s: not a directory\n", lastarg); + return; + } + + while (argc-- > 2) { + destname = lastarg; + srcname = *++argv; + if (dirflag) + destname = buildname(destname, srcname); + + (void) copyfile(srcname, destname, FALSE); + } +} + + +void +do_mount(argc, argv) + char **argv; +{ + char *str; + char *type; + + argc--; + argv++; + type = "minix"; + + while ((argc > 0) && (**argv == '-')) { + argc--; + str = *argv++ ; + + while (*++str) switch (*str) { + case 't': + if ((argc <= 0) || (**argv == '-')) { + fprintf(stderr, "Missing file system type\n"); + return; + } + + type = *argv++; + argc--; + break; + + default: + fprintf(stderr, "Unknown option\n"); + return; + } + } + + if (argc != 2) { + fprintf(stderr, "Wrong number of arguments for mount\n"); + return; + } + + if (mount(argv[0], argv[1], type, 0, 0) < 0) + perror("mount failed"); +} + + +void +do_umount(argc, argv) + char **argv; +{ + if (umount(argv[1]) < 0) + perror(argv[1]); +} + + +void +do_cmp(argc, argv) + char **argv; +{ + int fd1; + int fd2; + int cc1; + int cc2; + long pos; + char *srcname; + char *destname; + char *lastarg; + char *bp1; + char *bp2; + char *buf1; + char *buf2; + struct stat statbuf1; + struct stat statbuf2; + + if (stat(argv[1], &statbuf1) < 0) { + perror(argv[1]); + return; + } + + if (stat(argv[2], &statbuf2) < 0) { + perror(argv[2]); + return; + } + + if ((statbuf1.st_dev == statbuf2.st_dev) && + (statbuf1.st_ino == statbuf2.st_ino)) + { + printf("Files are links to each other\n"); + return; + } + + if (statbuf1.st_size != statbuf2.st_size) { + printf("Files are different sizes\n"); + return; + } + + fd1 = open(argv[1], 0); + if (fd1 < 0) { + perror(argv[1]); + return; + } + + fd2 = open(argv[2], 0); + if (fd2 < 0) { + perror(argv[2]); + close(fd1); + return; + } + + buf1 = malloc(8192-16); + buf2 = malloc(8192-16); + + pos = 0; + while (TRUE) { + if (intflag) + goto closefiles; + + cc1 = read(fd1, buf1, 8192-16); + if (cc1 < 0) { + perror(argv[1]); + goto closefiles; + } + + cc2 = read(fd2, buf2, 8192-16); + if (cc2 < 0) { + perror(argv[2]); + goto closefiles; + } + + if ((cc1 == 0) && (cc2 == 0)) { + printf("Files are identical\n"); + goto closefiles; + } + + if (cc1 < cc2) { + printf("First file is shorter than second\n"); + goto closefiles; + } + + if (cc1 > cc2) { + printf("Second file is shorter than first\n"); + goto closefiles; + } + + if (memcmp(buf1, buf2, cc1) == 0) { + pos += cc1; + continue; + } + + bp1 = buf1; + bp2 = buf2; + while (*bp1++ == *bp2++) + pos++; + + printf("Files differ at byte position %ld\n", pos); + goto closefiles; + } + +closefiles: + close(fd1); + close(fd2); + free(buf1); + free(buf2); +} + + +void +do_more(argc, argv) + char **argv; +{ + FILE *fp; + char *name; + int ch; + int line; + int col; + char buf[80]; + + while (argc-- > 1) { + name = *(++argv); + + fp = fopen(name, "r"); + if (fp == NULL) { + perror(name); + return; + } + + printf("<< %s >>\n", name); + line = 1; + col = 0; + + while (fp && ((ch = fgetc(fp)) != EOF)) { + switch (ch) { + case '\r': + col = 0; + break; + + case '\n': + line++; + col = 0; + break; + + case '\t': + col = ((col + 1) | 0x07) + 1; + break; + + case '\b': + if (col > 0) + col--; + break; + + default: + col++; + } + + putchar(ch); + if (col >= 80) { + col -= 80; + line++; + } + + if (line < 24) + continue; + + if (col > 0) + putchar('\n'); + + printf("--More--"); + fflush(stdout); + + if (intflag || (read(0, buf, sizeof(buf)) < 0)) { + if (fp) + fclose(fp); + return; + } + + ch = buf[0]; + if (ch == ':') + ch = buf[1]; + + switch (ch) { + case 'N': + case 'n': + fclose(fp); + fp = NULL; + break; + + case 'Q': + case 'q': + fclose(fp); + return; + } + + col = 0; + line = 1; + } + if (fp) + fclose(fp); + } +} + + +void +do_exit(argc, argv) + char **argv; +{ + exit(0); +} + + +void +do_setenv(argc, argv) + char **argv; +{ + setenv(argv[1], argv[2], 1); +} + + +void +do_printenv(argc, argv) + char **argv; +{ + char **env; + extern char **environ; + int len; + + env = environ; + + if (argc == 1) { + while (*env) + printf("%s\n", *env++); + return; + } + + len = strlen(argv[1]); + while (*env) { + if ((strlen(*env) > len) && (env[0][len] == '=') && + (memcmp(argv[1], *env, len) == 0)) + { + printf("%s\n", &env[0][len+1]); + return; + } + env++; + } +} + + +void +do_umask(argc, argv) + char **argv; +{ + char *cp; + int mask; + + if (argc <= 1) { + mask = umask(0); + umask(mask); + printf("%03o\n", mask); + return; + } + + mask = 0; + cp = argv[1]; + while (isoctal(*cp)) + mask = mask * 8 + *cp++ - '0'; + + if (*cp || (mask & ~0777)) { + fprintf(stderr, "Bad umask value\n"); + return; + } + + umask(mask); +} + + +void +do_kill(argc, argv) + char **argv; +{ + char *cp; + int sig; + int pid; + + sig = SIGTERM; + + if (argv[1][0] == '-') { + cp = &argv[1][1]; + if (strcmp(cp, "HUP") == 0) + sig = SIGHUP; + else if (strcmp(cp, "INT") == 0) + sig = SIGINT; + else if (strcmp(cp, "QUIT") == 0) + sig = SIGQUIT; + else if (strcmp(cp, "ILL") == 0) + sig = SIGILL; + else if (strcmp(cp, "TRAP") == 0) + sig = SIGTRAP; + else if (strcmp(cp, "ABRT") == 0) + sig = SIGABRT; + else if (strcmp(cp, "IOT") == 0) + sig = SIGIOT; + else if (strcmp(cp, "BUS") == 0) + sig = SIGBUS; + else if (strcmp(cp, "FPE") == 0) + sig = SIGFPE; + else if (strcmp(cp, "KILL") == 0) + sig = SIGKILL; + else if (strcmp(cp, "USR1") == 0) + sig = SIGUSR1; + else if (strcmp(cp, "SEGV") == 0) + sig = SIGSEGV; + else if (strcmp(cp, "USR2") == 0) + sig = SIGUSR2; + else if (strcmp(cp, "PIPE") == 0) + sig = SIGPIPE; + else if (strcmp(cp, "ALRM") == 0) + sig = SIGALRM; + else if (strcmp(cp, "TERM") == 0) + sig = SIGTERM; +#ifdef SIGSTKFLT + else if (strcmp(cp, "STKFLT") == 0) + sig = SIGSTKFLT; +#endif + else if (strcmp(cp, "CHLD") == 0) + sig = SIGCHLD; + else if (strcmp(cp, "CONT") == 0) + sig = SIGCONT; + else if (strcmp(cp, "STOP") == 0) + sig = SIGSTOP; + else if (strcmp(cp, "TSTP") == 0) + sig = SIGTSTP; + else if (strcmp(cp, "TTIN") == 0) + sig = SIGTTIN; + else if (strcmp(cp, "TTOU") == 0) + sig = SIGTTOU; + else if (strcmp(cp, "URG") == 0) + sig = SIGURG; + else if (strcmp(cp, "PWR") == 0) + sig = SIGPWR; + else { + sig = 0; + while (isdecimal(*cp)) + sig = sig * 10 + *cp++ - '0'; + + if (*cp) { + fprintf(stderr, "Unknown signal\n"); + exit_code = 1; + return; + } + } + argc--; + argv++; + } + + while (argc-- > 1) { + cp = *++argv; + pid = 0; + while (isdecimal(*cp)) + pid = pid * 10 + *cp++ - '0'; + + if (*cp) { + fprintf(stderr, "Non-numeric pid\n"); + exit_code = 1; + return; + } + + if (kill(pid, sig) < 0) { + perror(*argv); + exit_code = 1; + } + } +} + +/* END CODE */ diff --git a/package/sash/src/cp.c b/package/sash/src/cp.c new file mode 100644 index 000000000..11d03f74c --- /dev/null +++ b/package/sash/src/cp.c @@ -0,0 +1,27 @@ + +void +do_cp(argc, argv) + char **argv; +{ + BOOL dirflag; + char *srcname; + char *destname; + char *lastarg; + + lastarg = argv[argc - 1]; + + dirflag = isadir(lastarg); + + if ((argc > 3) && !dirflag) { + fprintf(stderr, "%s: not a directory\n", lastarg); + return; + } + + while (argc-- > 2) { + destname = lastarg; + if (dirflag) + destname = buildname(destname, srcname); + + (void) copyfile(*++argv, destname, FALSE); + } +} diff --git a/package/sash/src/date.c b/package/sash/src/date.c new file mode 100644 index 000000000..c7317998b --- /dev/null +++ b/package/sash/src/date.c @@ -0,0 +1,54 @@ +/* date.c bradkemp@indusriver.com */ + +#include +#include + +static const char invalid_date[] = "Invalid date %s\n"; +int do_date(int argc, char * argv[]) +{ + + time_t tm; + struct tm tm_time; + time(&tm); + memcpy(&tm_time, localtime(&tm), sizeof(tm_time)); + + if (argc > 1) { + int nr; + + nr = sscanf(argv[1], "%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, invalid_date, argv[1]); + return(0); + } + + /* 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; + + if((tm = mktime(&tm_time)) < 0) { + fprintf(stderr, invalid_date, argv[1]); + return(0); + } + + if(stime(&tm) < 0) { + fprintf(stderr, "Unable to set date\n"); + return(0); + } + + return (0); + + } + printf("%s\n",asctime(&tm_time)); + + return(0); +} + + + diff --git a/package/sash/src/df.c b/package/sash/src/df.c new file mode 100644 index 000000000..99ac2217e --- /dev/null +++ b/package/sash/src/df.c @@ -0,0 +1,55 @@ +/* df.c: + * + * Copyright (C) 1998 Kenneth Albanowski , + * + * 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. + */ + +#include "sash.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef __UC_LIBC__ +#include +#endif +#include +#include +#include + +void +do_df(int argc, char * argv[]) +{ + char * name; + struct statfs stbuf; + +#if 0 + fclose(stdin); +#endif + + if (argc<2) + name = "/"; + else + name = argv[1]; + + if (statfs(name, &stbuf) == -1) { + printf("Unable to get disk space of %s: %s\n", name, strerror(errno)); + return; + } + + printf("Total Kbytes: %ld\n", (stbuf.f_bsize / 256) * (stbuf.f_blocks / 4)); + printf("Free Kbytes: %ld\n", (stbuf.f_bsize / 256) * (stbuf.f_bfree / 4)); + printf("Total nodes: %ld\n", stbuf.f_files); + printf("Free nodes: %ld\n", stbuf.f_ffree); +} + diff --git a/package/sash/src/free.c b/package/sash/src/free.c new file mode 100644 index 000000000..281f10995 --- /dev/null +++ b/package/sash/src/free.c @@ -0,0 +1,44 @@ +/* free.c: + * + * Copyright (C) 1998 Kenneth Albanowski , + * + * 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. + */ + +#include "sash.h" + +#include +#include + +#include +#include +#include +#include +#include + +void +do_free(argc, argv) + char **argv; +{ + int i; + FILE * f; + char buf[256]; + + f = fopen("/proc/meminfo", "r"); + + if (!f) { + perror("Unable to open /proc/meminfo: "); + return; + } + + for(i=0;i<3;i++) { + fgets(buf, 250, f); + fputs(buf, stdout); + } + + fclose(f); +} + diff --git a/package/sash/src/hexdump.c b/package/sash/src/hexdump.c new file mode 100644 index 000000000..f12f62494 --- /dev/null +++ b/package/sash/src/hexdump.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1993 by David I. Bell + * Permission is granted to use, distribute, or modify this source, + * provided that this copyright notice remains intact. + * + * Most simple built-in commands are here. + */ + +#include "sash.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void +do_hexdump(argc, argv) + int argc; + char **argv; +{ + FILE *fp; + int count; + int c; + char text[17]; + unsigned char buf[130]; + + char *name = 0; + unsigned long pos = 0; + char *myname = argv[0]; + + if ( (argc > 2) && !strcmp(argv[1],"-s") ) { + pos = strtoul(argv[2], 0, 0); + argc -= 2; + argv += 2; + } + + if (argc <= 1) { + fprintf(stderr, "No filename provided\n"); + return; + } + + name = argv[1]; + fp = fopen(name, "r"); + if (!fp) { + fprintf(stderr, "Failed to open file '%s': %s\n", + name, strerror(errno)); + return; + } + + if (pos) + fseek(fp, pos, SEEK_SET); + + c = 0; + + text[16] = 0; + + while(!feof(fp)) { + + strcmp(text, " "); + + while (c < (pos & 0xf)) { + if (c == 0) + printf("%4X:", pos & 0xfffffff0); + printf( (c == 8) ? "- " : " "); + text[c] = ' '; + c++; + } + + { + int p = 0; + count = fread(buf, 1, 128 - (pos % 16), fp); + + if (count <= 0) + break; + + while (p < count) { + c = (pos & 0xf); + + if (c == 0) + printf("%4X:", pos & 0xfffffff0); + + if ((buf[p] < 32) || (buf[p]>126)) + text[c] = '.'; + else + text[c] = buf[p]; + + printf( (c==15) ? " %02.2X" : (c == 8) ? "-%02.2X" : " %02.2X", buf[p]); + + if (c == 15) + printf(" %s\n", text); + + pos++; + p++; + } + } + + if (c = (pos & 0x0f)) { + + while (c < 16) { + printf( (c == 8) ? "- " : " "); + text[c] = ' '; + c++; + } + + printf(" %s\n", text); + } + + if (feof(fp)) + break; + + printf("--more--"); + fflush(stdout); + + fgets(buf, 80, stdin); + if (toupper(buf[0]) == 'Q') + break; + } + + if (fp != stdin) + fclose(fp); +} + diff --git a/package/sash/src/hostname.c b/package/sash/src/hostname.c new file mode 100644 index 000000000..8841e7fa3 --- /dev/null +++ b/package/sash/src/hostname.c @@ -0,0 +1,24 @@ +/* hostname.c - poe@daimi.aau.dk */ + +#include "sash.h" + +#include +#include +#include +#include + +void do_hostname(int argc, char **argv) +{ + char hn[PATHLEN + 1]; + + if(argc >= 2) { + if(strlen(argv[1]) > PATHLEN) { + printf("That name is too long.\n"); + } else { + sethostname(argv[1], strlen(argv[1])); + } + } else { + gethostname(hn, PATHLEN); + printf("%s\n", hn); + } +} diff --git a/package/sash/src/libsash/Makefile b/package/sash/src/libsash/Makefile new file mode 100644 index 000000000..03a2fafae --- /dev/null +++ b/package/sash/src/libsash/Makefile @@ -0,0 +1,20 @@ + +LIB = libsash.a +CHOPSRC = utils.c +LIBOBJS = intflag.o modestring.o timestring.o isadir.o copyfile.o \ + buildname.o expandwildcards.o namesort.o match.o makeargs.o \ + makestring.o chunks.o expandenvvar.o + +CFLAGS += -I../ + + +all: $(EXEC) $(LIB) + +$(LIBOBJS): $(CHOPSRC) + $(CC) $(CFLAGS) -DL_$(basename $*) -o $(basename $*).o -c $^ + +$(LIB): $(LIB)($(LIBOBJS)) + $(RANLIB) $(LIB) + +clean: + rm -f $(LIB) $(EXEC) *.o diff --git a/package/sash/src/libsash/utils.c b/package/sash/src/libsash/utils.c new file mode 100644 index 000000000..a05b33aee --- /dev/null +++ b/package/sash/src/libsash/utils.c @@ -0,0 +1,706 @@ +/* + * Copyright (c) 1993 by David I. Bell + * Permission is granted to use, distribute, or modify this source, + * provided that this copyright notice remains intact. + * + * Utility routines. + */ + +#include "sash.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef L_intflag + +int intflag; + +#endif + +#ifdef L_modestring + +/* + * Return the standard ls-like mode string from a file mode. + * This is static and so is overwritten on each call. + */ +char * +modestring(mode) +{ + static char buf[12]; + + strcpy(buf, "----------"); + + /* + * Fill in the file type. + */ + if (S_ISDIR(mode)) + buf[0] = 'd'; + if (S_ISCHR(mode)) + buf[0] = 'c'; + if (S_ISBLK(mode)) + buf[0] = 'b'; + if (S_ISFIFO(mode)) + buf[0] = 'p'; +#ifdef S_ISLNK + if (S_ISLNK(mode)) + buf[0] = 'l'; +#endif +#ifdef S_ISSOCK + if (S_ISSOCK(mode)) + buf[0] = 's'; +#endif + + /* + * Now fill in the normal file permissions. + */ + if (mode & S_IRUSR) + buf[1] = 'r'; + if (mode & S_IWUSR) + buf[2] = 'w'; + if (mode & S_IXUSR) + buf[3] = 'x'; + if (mode & S_IRGRP) + buf[4] = 'r'; + if (mode & S_IWGRP) + buf[5] = 'w'; + if (mode & S_IXGRP) + buf[6] = 'x'; + if (mode & S_IROTH) + buf[7] = 'r'; + if (mode & S_IWOTH) + buf[8] = 'w'; + if (mode & S_IXOTH) + buf[9] = 'x'; + + /* + * Finally fill in magic stuff like suid and sticky text. + */ + if (mode & S_ISUID) + buf[3] = ((mode & S_IXUSR) ? 's' : 'S'); + if (mode & S_ISGID) + buf[6] = ((mode & S_IXGRP) ? 's' : 'S'); + if (mode & S_ISVTX) + buf[9] = ((mode & S_IXOTH) ? 't' : 'T'); + + return buf; +} + +#endif + +#ifdef L_timestring + +/* + * Get the time to be used for a file. + * This is down to the minute for new files, but only the date for old files. + * The string is returned from a static buffer, and so is overwritten for + * each call. + */ +char * +timestring(t) + long t; +{ + long now; + char *str; + static char buf[26]; + + time(&now); + + str = ctime(&t); + + strcpy(buf, &str[4]); + buf[12] = '\0'; + + if ((t > now) || (t < now - 365*24*60*60L)) { + strcpy(&buf[7], &str[20]); + buf[11] = '\0'; + } + + return buf; +} + +#endif + +#ifdef L_isadir + +/* + * Return TRUE if a filename is a directory. + * Nonexistant files return FALSE. + */ +BOOL +isadir(name) + char *name; +{ + struct stat statbuf; + + if (stat(name, &statbuf) < 0) + return FALSE; + + return S_ISDIR(statbuf.st_mode); +} + +#endif + +#ifdef L_copyfile + +/* + * Copy one file to another, while possibly preserving its modes, times, + * and modes. Returns TRUE if successful, or FALSE on a failure with an + * error message output. (Failure is not indicted if the attributes cannot + * be set.) + */ +BOOL +copyfile(srcname, destname, setmodes) + char *srcname; + char *destname; + BOOL setmodes; +{ + int rfd; + int wfd; + int rcc; + int wcc; + char *bp; + struct stat statbuf1; + struct stat statbuf2; + struct utimbuf times; + int len = 8192-16; + char * buf = 0; + + if (stat(srcname, &statbuf1) < 0) { + perror(srcname); + return FALSE; + } + + if (stat(destname, &statbuf2) < 0) { + statbuf2.st_ino = -1; + statbuf2.st_dev = -1; + } + + if (S_ISREG(statbuf1.st_mode) && + (statbuf1.st_dev == statbuf2.st_dev) && + (statbuf1.st_ino == statbuf2.st_ino)) + { + fprintf(stderr, "Copying file \"%s\" to itself\n", srcname); + return FALSE; + } + + rfd = open(srcname, 0); + if (rfd < 0) { + perror(srcname); + return FALSE; + } + + wfd = open(destname, O_WRONLY|O_CREAT|O_TRUNC, statbuf1.st_mode); + if (wfd < 0) { + perror(destname); + close(rfd); + return FALSE; + } + + buf = malloc(len); + if (!buf) { + fprintf(stderr,"Unable to allocate buffer of %d bytes\n", len); + return FALSE; + } + + while ((rcc = read(rfd, buf, len)) > 0) { + if (intflag) { + close(rfd); + close(wfd); + free(buf); + return FALSE; + } + + bp = buf; + while (rcc > 0) { + wcc = write(wfd, bp, rcc); + if (wcc < 0) { + perror(destname); + free(buf); + goto error_exit; + } + bp += wcc; + rcc -= wcc; + } + } + + free(buf); + + if (rcc < 0) { + perror(srcname); + goto error_exit; + } + + close(rfd); + if (close(wfd) < 0) { + perror(destname); + return FALSE; + } + + if (setmodes) { + (void) chmod(destname, statbuf1.st_mode); + + (void) chown(destname, statbuf1.st_uid, statbuf1.st_gid); + + times.actime = statbuf1.st_atime; + times.modtime = statbuf1.st_mtime; + + (void) utime(destname, ×); + } + + return TRUE; + + +error_exit: + close(rfd); + close(wfd); + + return FALSE; +} + +#endif + +#ifdef L_buildname + +/* + * Build a path name from the specified directory name and file name. + * If the directory name is NULL, then the original filename is returned. + * The built path is in a static area, and is overwritten for each call. + */ +char * +buildname(dirname, filename) + char *dirname; + char *filename; +{ + char *cp; + static char buf[PATHLEN]; + + if ((dirname == NULL) || (*dirname == '\0')) + return filename; + + cp = strrchr(filename, '/'); + if (cp) + filename = cp + 1; + + strcpy(buf, dirname); + strcat(buf, "/"); + strcat(buf, filename); + + return buf; +} + +#endif + +#ifdef L_expandwildcards + +/* + * Expand the wildcards in a filename, if any. + * Returns an argument list with matching filenames in sorted order. + * The expanded names are stored in memory chunks which can later all + * be freed at once. Returns zero if the name is not a wildcard, or + * returns the count of matched files if the name is a wildcard and + * there was at least one match, or returns -1 if too many filenames + * matched (with an error output). + * If the name is a wildcard and no names match, returns 0 as + * if the name were not a wildcard. + */ +int +expandwildcards(name, maxargc, retargv) + char *name; + int maxargc; + char *retargv[]; +{ + char *last; + char *cp1, *cp2, *cp3; + DIR *dirp; + struct dirent *dp; + int dirlen; + int matches; + char dirname[PATHLEN]; + + last = strrchr(name, '/'); + if (last) + last++; + else + last = name; + + cp1 = strchr(name, '*'); + cp2 = strchr(name, '?'); + cp3 = strchr(name, '['); + + if ((cp1 == NULL) && (cp2 == NULL) && (cp3 == NULL)) + return 0; + + if ((cp1 && (cp1 < last)) || (cp2 && (cp2 < last)) || + (cp3 && (cp3 < last))) + { + fprintf(stderr, "Wildcards only implemented for last filename component\n"); + return -1; + } + + dirname[0] = '.'; + dirname[1] = '\0'; + + if (last != name) { + memcpy(dirname, name, last - name); + dirname[last - name - 1] = '\0'; + if (dirname[0] == '\0') { + dirname[0] = '/'; + dirname[1] = '\0'; + } + } + + dirp = opendir(dirname); + if (dirp == NULL) { + perror(dirname); + return -1; + } + + dirlen = strlen(dirname); + if (last == name) { + dirlen = 0; + dirname[0] = '\0'; + } else if (dirname[dirlen - 1] != '/') { + dirname[dirlen++] = '/'; + dirname[dirlen] = '\0'; + } + + matches = 0; + + while ((dp = readdir(dirp)) != NULL) { + if ((strcmp(dp->d_name, ".") == 0) || + (strcmp(dp->d_name, "..") == 0)) + continue; + + if (!match(dp->d_name, last)) + continue; + + if (matches >= maxargc) { + fprintf(stderr, "Too many filename matches\n"); + closedir(dirp); + return -1; + } + + cp1 = getchunk(dirlen + strlen(dp->d_name) + 1); + if (cp1 == NULL) { + fprintf(stderr, "No memory for filename\n"); + closedir(dirp); + return -1; + } + + if (dirlen) + memcpy(cp1, dirname, dirlen); + strcpy(cp1 + dirlen, dp->d_name); + + retargv[matches++] = cp1; + } + + closedir(dirp); + + if (matches == 0) { + return 0; + } + + qsort((char *) retargv, matches, sizeof(char *), namesort); + + return matches; +} + +#endif + +#ifdef L_namesort + +/* + * Sort routine for list of filenames. + */ +int +namesort(p1, p2) + char **p1; + char **p2; +{ + return strcmp(*p1, *p2); +} + +#endif + +#ifdef L_match + +/* + * Routine to see if a text string is matched by a wildcard pattern. + * Returns TRUE if the text is matched, or FALSE if it is not matched + * or if the pattern is invalid. + * * matches zero or more characters + * ? matches a single character + * [abc] matches 'a', 'b' or 'c' + * \c quotes character c + * Adapted from code written by Ingo Wilken. + */ +BOOL +match(text, pattern) + char *text; + char *pattern; +{ + return fnmatch(pattern, text, 0) == 0; +} +#endif + +#ifdef L_makeargs + +/* + * Take a command string, and break it up into an argc, argv list. + * The returned argument list and strings are in static memory, and so + * are overwritten on each call. The argument array is ended with an + * extra NULL pointer for convenience. Returns TRUE if successful, + * or FALSE on an error with a message already output. + * + * Note that leading quotes are *not* removed at this point, but + * trailing quotes are. + */ +BOOL +makeargs(cmd, argcptr, argvptr) + char *cmd; + int *argcptr; + char ***argvptr; +{ + char *cp; + int argc; + static char strings[CMDLEN+1]; + static char *argtable[MAXARGS+1]; + static char quoted[MAXARGS+1]; + + /* + * Copy the command string and then break it apart + * into separate arguments. + */ + strcpy(strings, cmd); + argc = 0; + cp = strings; + + while (*cp) { + if (argc >= MAXARGS) { + fprintf(stderr, "Too many arguments\n"); + return FALSE; + } + + quoted[argc] = 0; + argtable[argc++] = cp; + + while (*cp && !isblank(*cp)) { + if (*cp == '"' || *cp == '\'') { + char *sp = cp++; + + while (*cp && *cp != *sp) + cp++; + + if (*cp == *sp) { + /* Chop off the trailing quote, but leave the leading quote + * so that later processing will know the argument is quoted + */ + *cp++ = 0; + } + } else + cp++; + } + + while (isblank(*cp)) + *cp++ = '\0'; + } + + argtable[argc] = NULL; + + *argcptr = argc; + *argvptr = argtable; + + return TRUE; +} + +#endif + +#ifdef L_makestring + +/* + * Make a NULL-terminated string out of an argc, argv pair. + * Returns TRUE if successful, or FALSE if the string is too long, + * with an error message given. This does not handle spaces within + * arguments correctly. + */ +BOOL +makestring(argc, argv, buf, buflen) + char **argv; + char *buf; +{ + int len; + + while (argc-- > 0) { + len = strlen(*argv); + if (len >= buflen) { + fprintf(stderr, "Argument string too long\n"); + return FALSE; + } + + strcpy(buf, *argv++); + + buf += len; + buflen -= len; + + if (argc) + *buf++ = ' '; + buflen--; + } + + *buf = '\0'; + + return TRUE; +} + +#endif + +#ifdef L_chunks + +typedef struct chunk CHUNK; +#define CHUNKINITSIZE 4 +struct chunk { + CHUNK *next; + char data[CHUNKINITSIZE]; /* actually of varying length */ +}; + + +static CHUNK * chunklist; + + +/* + * Allocate a chunk of memory (like malloc). + * The difference, though, is that the memory allocated is put on a + * list of chunks which can be freed all at one time. You CAN NOT free + * an individual chunk. + */ +char * +getchunk(size) +{ + CHUNK *chunk; + + if (size < CHUNKINITSIZE) + size = CHUNKINITSIZE; + + chunk = (CHUNK *) malloc(size + sizeof(CHUNK) - CHUNKINITSIZE); + if (chunk == NULL) + return NULL; + + chunk->next = chunklist; + chunklist = chunk; + + return chunk->data; +} + + +/* + * Free all chunks of memory that had been allocated since the last + * call to this routine. + */ +void +freechunks() +{ + CHUNK *chunk; + + while (chunklist) { + chunk = chunklist; + chunklist = chunk->next; + free((char *) chunk); + } +} + +#endif + + +#ifdef L_expandenvvar + +/* Expand environment variables + * Variable names must use a-z, A-Z, 0-9, or _ + * Backslashes are also interpreted to preserve the literal value of the + * next character. + * Returns NULL if there is an error, otherwise returns a pointer + * to a static buffer containing the expand command line. + * + * Makes a lame attempt to not expand inside single quotes. + */ +char * +expandenvvar(cmd) + char *cmd; +{ + static char newcmd[CMDLEN+1]; + char* newp = newcmd; + int freelength = CMDLEN; /* Don't include final terminator */ + char varname[CMDLEN+1]; + char* varp; + char* value; + int valuelength; + int quoted = 0; + + if (cmd == NULL) { + return NULL; + } + + if (strlen(cmd) > freelength) { + fprintf(stderr, "Variable expansion too long\n"); + return NULL; + } + + while (*cmd) { + int copy = 1; + + switch (*cmd) { + case '$': + if (!quoted) { + copy = 0; + cmd++; + varp = varname; + while (isalnum(*cmd) || (*cmd == '_') || (*cmd == '?')) { + *varp++ = *cmd++; + } + *varp = '\0'; + if ((*varname) && (value = getenv(varname))) { + valuelength = strlen(value); + if (valuelength > freelength) { + fprintf(stderr, "Variable expansion too long\n"); + return NULL; + } + strncpy(newp, value, valuelength); + newp += valuelength; + freelength -= valuelength; + } + } + break; + + case '\'': + quoted = !quoted; + break; + + case '\\': + cmd++; + break; + } + + if (copy) { + if (freelength < 1) { + fprintf(stderr, "Variable expansion too long\n"); + return NULL; + } + *newp++ = *cmd++; + freelength--; + } + } + + *newp = '\0'; + + return newcmd; +} + +#endif + + +/* END CODE */ diff --git a/package/sash/src/ls.c b/package/sash/src/ls.c new file mode 100644 index 000000000..9b337aeaa --- /dev/null +++ b/package/sash/src/ls.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 1993 by David I. Bell + * Permission is granted to use, distribute, or modify this source, + * provided that this copyright notice remains intact. + * + * The "ls" built-in command. + */ + +#include "sash.h" + +#include +#include +#include +#include +#include +#include +#include + +#define LISTSIZE 256 + +#define COLWIDTH 20 + +#ifdef S_ISLNK +#define LSTAT lstat +#else +#define LSTAT stat +#endif + + +/* + * Flags for the LS command. + */ +#define LSF_LONG 0x01 +#define LSF_DIR 0x02 +#define LSF_INODE 0x04 +#define LSF_MULT 0x08 +#define LSF_ALL 0x10 +#define LSF_COMPACT 0x20 + + +static char **list; +static int listsize; +static int listused; +static int linelen = 0; + + +static void lsfile(); + + +void +do_ls(argc, argv) + int argc; + char **argv; +{ + char *cp; + char *name; + int flags; + int i; + DIR *dirp; + BOOL endslash; + char **newlist; + struct dirent *dp; + char fullname[PATHLEN]; + struct stat statbuf; + static char *def[2]; + + if (listsize == 0) { + list = (char **) malloc(LISTSIZE * sizeof(char *)); + if (list == NULL) { + fprintf(stderr, "No memory for ls buffer\n"); + return; + } + listsize = LISTSIZE; + } + listused = 0; + + flags = 0; + if ((argc > 1) && (argv[1][0] == '-')) + { + argc--; + cp = *(++argv) + 1; + + while (*cp) switch (*cp++) { + case 'l': flags |= LSF_LONG; break; + case 'd': flags |= LSF_DIR; break; + case 'i': flags |= LSF_INODE; break; + case 'a': flags |= LSF_ALL; break; + case 'C': flags |= LSF_COMPACT; break; + default: + fprintf(stderr, "Unknown option -%c\n", cp[-1]); + return; + } + } + + if ((flags & LSF_COMPACT) && (flags & ~LSF_COMPACT)) { + fprintf(stderr, "Cannot do compact list with other options\n"); + return; + } + + if (argc <= 1) { + argc = 2; + argv = def; + argv[0] = "ls"; + argv[1] = "."; + } + + if (argc > 2) + flags |= LSF_MULT; + + while (argc-- > 1) { + name = *(++argv); + endslash = (*name && (name[strlen(name) - 1] == '/')); + + if (LSTAT(name, &statbuf) < 0) { + perror(name); + continue; + } + + if ((flags & LSF_DIR) || (!S_ISDIR(statbuf.st_mode))) { + lsfile(name, &statbuf, flags); + continue; + } + + /* + * Do all the files in a directory. + */ + dirp = opendir(name); + if (dirp == NULL) { + perror(name); + continue; + } + + if (flags & LSF_MULT) + printf("\n%s:\n", name); + + while ((dp = readdir(dirp)) != NULL) { + + if ((dp->d_name[0] == '.') && !(flags & LSF_ALL)) + continue; + + fullname[0] = '\0'; + + if ((*name != '.') || (name[1] != '\0')) { + strcpy(fullname, name); + if (!endslash) + strcat(fullname, "/"); + } + + strcat(fullname, dp->d_name); + + if (listused >= listsize) { + newlist = malloc((sizeof(char **)) * (listsize + LISTSIZE)); + if (newlist == NULL) { + fprintf(stderr, "No memory for ls buffer\n"); + break; + } + memcpy(newlist, list, sizeof(char**) * listsize); + free(list); + listsize += LISTSIZE; + } + + list[listused] = strdup(fullname); + if (list[listused] == NULL) { + fprintf(stderr, "No memory for filenames\n"); + break; + } + listused++; + } + + closedir(dirp); + + /* + * Sort the files. + */ + qsort((char *) list, listused, sizeof(char *), namesort); + + /* + * Now finally list the filenames. + */ + for (i = 0; i < listused; i++) { + name = list[i]; + + if (LSTAT(name, &statbuf) < 0) { + perror(name); + free(name); + continue; + } + + cp = strrchr(name, '/'); + if (cp) + cp++; + else + cp = name; + + lsfile(cp, &statbuf, flags); + + free(name); + } + + listused = 0; + } + + if (linelen) + fputc('\n', stdout); +} + + +/* + * Do an LS of a particular file name according to the flags. + */ +static void +lsfile(name, statbuf, flags) + char *name; + struct stat *statbuf; +{ + char *cp; + struct passwd *pwd; + struct group *grp; + int len; + char buf[PATHLEN]; + static char username[12]; + static int userid; + static BOOL useridknown; + static char groupname[12]; + static int groupid; + static BOOL groupidknown; + + cp = buf; + *cp = '\0'; + + if (flags & LSF_INODE) { + sprintf(cp, "%5d ", statbuf->st_ino); + cp += strlen(cp); + } + + if (flags & LSF_LONG) { + strcpy(cp, modestring(statbuf->st_mode)); + cp += strlen(cp); + + sprintf(cp, "%3d ", statbuf->st_nlink); + cp += strlen(cp); + + if (!useridknown || (statbuf->st_uid != userid)) { + /*pwd = getpwuid(statbuf->st_uid); + if (pwd) + strcpy(username, pwd->pw_name); + else*/ + sprintf(username, "%d", statbuf->st_uid); + userid = statbuf->st_uid; + useridknown = TRUE; + } + + sprintf(cp, "%-8s ", username); + cp += strlen(cp); + + if (!groupidknown || (statbuf->st_gid != groupid)) { + /*grp = getgrgid(statbuf->st_gid); + if (grp) + strcpy(groupname, grp->gr_name); + else*/ + sprintf(groupname, "%d", statbuf->st_gid); + groupid = statbuf->st_gid; + groupidknown = TRUE; + } + + sprintf(cp, "%-8s ", groupname); + cp += strlen(cp); + + if (S_ISBLK(statbuf->st_mode) || S_ISCHR(statbuf->st_mode)) + sprintf(cp, "%3d, %3d ", major(statbuf->st_rdev), + minor(statbuf->st_rdev)); + else + sprintf(cp, "%8d ", statbuf->st_size); + cp += strlen(cp); + + sprintf(cp, " %-12s ", timestring(statbuf->st_mtime)); + } + + fputs(buf, stdout); + fputs(name, stdout); + +#ifdef S_ISLNK + if ((flags & LSF_LONG) && S_ISLNK(statbuf->st_mode)) { + len = readlink(name, buf, PATHLEN - 1); + if (len >= 0) { + buf[len] = '\0'; + printf(" -> %s", buf); + } + } +#endif + + if (flags & LSF_COMPACT) { + len = strlen(name); + if (len < COLWIDTH) { + for (; (len < COLWIDTH); len++) + fputc(' ', stdout); + linelen += COLWIDTH; + } else { + linelen = 80; + } + + if (linelen >= 80) { + fputc('\n', stdout); + linelen = 0; + } + } else { + fputc('\n', stdout); + } +} + +/* END CODE */ diff --git a/package/sash/src/ps.c b/package/sash/src/ps.c new file mode 100644 index 000000000..ed4226cc9 --- /dev/null +++ b/package/sash/src/ps.c @@ -0,0 +1,317 @@ +/* ps.c: + * + * Copyright (C) 1998 Kenneth Albanowski , + * + * 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. + */ + +#include "sash.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef __UC_LIBC_ +#include +#endif +#include +#include +#ifdef __UC_LIBC__ +#include +#endif + +char psbuf[256]; +char name[40]; +int pid, state; +char statec; +int ppid, pgrp, session; +dev_t tty; +char tty_name[10]; + +char master[] = "pqrstuvwxyzabcde"; + +#define MAJOR(x) ((x) >> 8) +#define MINOR(x) ((x) & 0xff) + +int port_xlate[16] = {1, 3, 5, 7,9 ,11,13,15, + 2, 4, 6, 8,10,12,14,16}; + +void dev_to_name(dev_t dev, char * ttyname) +{ + strcpy(ttyname, ""); + if (MAJOR(dev) == 75) + sprintf(ttyname,"X%d", MINOR(dev)); + else if (MAJOR(dev) == TTY_MAJOR) + sprintf(ttyname,"S%d", MINOR(dev)-64); + else if (MAJOR(dev) == PTY_SLAVE_MAJOR) + sprintf(ttyname,"%c%x", master[MINOR(dev) / 16], MINOR(dev) & 0xf); +} + +void +do_ps(argc, argv) + char **argv; +{ + int i; + int h; + int max; + FILE * f; + DIR * d; + unsigned long bytes, sbytes; + struct dirent * de; + char *ext; + int l; + time_t time_now; + long uptime_secs; + float idle_secs; + float seconds, start, total_time; + int utime, stime, start_time; + int pcpu; + /*extern int _vfprintf_fp_ref, _vfscanf_fp_ref;*/ + +#if 0 + fclose(stdin); +#endif + + printf(" PID PORT STAT SIZE SHARED %%CPU COMMAND\n"/*, _vfprintf_fp_ref, _vfscanf_fp_ref*/); + + h = open("/proc/uptime", O_RDONLY); + + if (h==-1) { + perror("Unable to open /proc/uptime\n"); + return; + } + + l = read(h, psbuf, 255); + + close(h); + + + if (l<=0) { + perror("Unable to read uptime"); + return; + } + + + psbuf[l] = '\0'; + psbuf[255] = '\0'; + + ext = psbuf; + + + uptime_secs = atol(ext); + + + time_now = time(0); + + d = opendir("/proc"); + if (!d) + return; + + while (de = readdir(d)) { + + + for(i=0;id_name);i++) + if (!isdigit(de->d_name[i])) + goto next; + + sprintf(psbuf, "/proc/%s/stat", de->d_name); + + h = open(psbuf, O_RDONLY); + + if (h==-1) + continue; + + l = read(h, psbuf, 255); + if (l<=0) { + perror("Unable to read status"); + close(h); + continue; + } + + psbuf[l] = '\0'; + psbuf[255] = '\0'; + + ext = strrchr(psbuf, ')'); + ext[0] = '\0'; + + statec = ext[2]; + + ext += 4; + + ppid = atoi(ext); + ext = strchr(ext, ' ')+1; + + pgrp = atoi(ext); + ext = strchr(ext, ' ')+1; + + session = atoi(ext); + ext = strchr(ext, ' ')+1; + + tty = atoi(ext); + ext = strchr(ext, ' ')+1; + + //printf("1|%s\n", ext); + //tpgid + ext = strchr(ext, ' ')+1; + + //printf("2|%s\n", ext); + //flags + ext = strchr(ext, ' ')+1; + + //printf("3|%s\n", ext); + //min_flt + ext = strchr(ext, ' ')+1; + + //printf("4|%s\n", ext); + //cmin_flt + ext = strchr(ext, ' ')+1; + + //printf("5|%s\n", ext); + //maj_flt + ext = strchr(ext, ' ')+1; + + //printf("6|%s\n", ext); + //cmaj_flt + ext = strchr(ext, ' ')+1; + + //printf("7|%s\n", ext); + utime = atoi(ext); + ext = strchr(ext, ' ')+1; + + //printf("8|%s\n", ext); + stime = atoi(ext); + ext = strchr(ext, ' ')+1; + + //printf("9|%s\n", ext); + //cutime + ext = strchr(ext, ' ')+1; + + //printf("10|%s\n", ext); + //cstime + ext = strchr(ext, ' ')+1; + + //priority + ext = strchr(ext, ' ')+1; + + //nice + ext = strchr(ext, ' ')+1; + + //timeout + ext = strchr(ext, ' ')+1; + + //it_real_value + ext = strchr(ext, ' ')+1; + + start_time = atoi(ext); + + ext = strchr(psbuf, '('); + ext++; + strcpy(name, ext); + + pid = atoi(psbuf); + + + state = statec; + + close(h); + + dev_to_name(tty, tty_name); + + bytes = 0; + sbytes = 0; + sprintf(psbuf, "/proc/%s/status", de->d_name); + + f = fopen(psbuf, "r"); + + if (f) { + while (fgets(psbuf, 250, f)) { + if (strncmp(psbuf, "Mem:", 4) == 0) { + bytes = atol(psbuf+5); + bytes /= 1024; + } else if (strncmp(psbuf, "Shared:", 7) == 0) { + sbytes = atol(psbuf+8); + sbytes /= 1024; + } else if (strncmp(psbuf, "VmSize:", 7) == 0) { + bytes = atol(psbuf+8); + } + } + fclose(f); + } + + + seconds = ((uptime_secs * (long)HZ) - start_time) / HZ; + + /*printf("seconds=%s\n", gcvt(seconds, 15, psbuf));*/ + + start = time_now - seconds; + + /* + printf("1\n"); + + gcvt(start, 15, psbuf); + + printf("2\n"); + + printf("start=%s\n", psbuf); + + printf("utime=%d, stime=%d. start_time=%d\n", utime, stime, start_time); + */ + + total_time = (utime + stime); + + /*printf("total_time=%s\n", gcvt(total_time, 15, psbuf));*/ + + pcpu = seconds ? + (total_time * 10.0f * 100.0f / (float)HZ) / seconds : + 0; + if (pcpu > 999) pcpu = 999; + + + sprintf(psbuf, "/proc/%s/cmdline", de->d_name); + h = open(psbuf, O_RDONLY); + + if (h == -1) { + perror("Unable to open cmdline"); + continue; + } + + l = read(h, psbuf, 255); + if (l < 0) { + perror("Unable to read cmdline"); + close(h); + continue; + } + + close(h); + + /* + * the args are NUL separated, substitute spaces instead + */ + psbuf[l] = '\0'; + i=l; + while(psbuf[i] == '\0') + i--; /* Don't bother with trailing NULs */ + while(--i > 0) + if (psbuf[i] == '\0') + psbuf[i] = ' '; + + printf("%5d %4s %c %4ldK %3ldK %2u.%u %s\n", pid, tty_name, state, + bytes, sbytes, + pcpu / 10, pcpu % 10, + /*(int)seconds / 60, (int)seconds % 60,*/ + l ? psbuf : name); + next: + ; + } + + closedir(d); +} + diff --git a/package/sash/src/reboot.c b/package/sash/src/reboot.c new file mode 100644 index 000000000..8342ec992 --- /dev/null +++ b/package/sash/src/reboot.c @@ -0,0 +1,93 @@ +/* shutdown.c: + * + * Copyright (C) 1998 Kenneth Albanowski , + * + * 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. + * + * JUN/99 -- copied from shutdown.c to make new reboot command. + * (gerg@snapgear.com) + * AUG/99 -- added delay option to reboot + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#if __GNU_LIBRARY__ > 5 +#include +#endif + +int main(int argc, char *argv[]) +{ + int delay = 0; /* delay in seconds before rebooting */ + int rc; + int force = 0; + + while ((rc = getopt(argc, argv, "h?d:f")) > 0) { + switch (rc) { + case 'd': + delay = atoi(optarg); + break; + case 'f': + force = 1; + break; + case 'h': + case '?': + default: + printf("usage: reboot [-h] [-d ] [-f]\n"); + exit(0); + break; + } + } + + if(delay > 0) + sleep(delay); +#ifdef CONFIG_DISKtel + printf("unmounting /home\n"); + if(umount("/home") != 0){ + printf("unmounting failed!!!\n"); + } +#endif + +#ifdef CONFIG_USER_FLATFSD_FLATFSD + if (!force) { + /* Ask flatfsd to reboot us safely */ + execlp("flatfsd", "flatfsd", "-b", NULL); + /* if this returns, then force a reboot */ + } +#endif + + kill(1, SIGTSTP); + sync(); + signal(SIGTERM,SIG_IGN); + signal(SIGHUP,SIG_IGN); + setpgrp(); + kill(-1, SIGTERM); + sleep(1); + kill(-1, SIGHUP); + sleep(1); + sync(); + sleep(1); +#if __GNU_LIBRARY__ > 5 + reboot(0x01234567); +#else + reboot(0xfee1dead, 672274793, 0x01234567); +#endif + exit(0); /* Shrug */ +} + diff --git a/package/sash/src/sash.c b/package/sash/src/sash.c new file mode 100644 index 000000000..24fbddbf7 --- /dev/null +++ b/package/sash/src/sash.c @@ -0,0 +1,1118 @@ +/* + * Copyright (c) 1993 by David I. Bell + * Permission is granted to use, distribute, or modify this source, + * provided that this copyright notice remains intact. + * + * Stand-alone shell for system maintainance for Linux. + * This program should NOT be built using shared libraries. + * + * 1.1.1, hacked to re-allow cmd line invocation of script file + * Pat Adamo, padamo@unix.asb.com + */ + +#include "sash.h" + +#ifndef CMD_HELP +#define CMD_HELP +#endif +#undef INTERNAL_PATH_EXPANSION +#define FAVOUR_EXTERNAL_COMMANDS + +#include +#include +#include +#include +#include +#include +#include + +static char version[] = "1.1.1"; + +extern int intflag; + +extern void do_test(); + +typedef struct { + char name[10]; + char usage[30]; + void (*func)(); + int minargs; + int maxargs; +} CMDTAB; + + +CMDTAB cmdtab[] = { +/* + "alias", "[name [command]]", do_alias, + 1, MAXARGS, +*/ + "cd", "[dirname]", do_cd, + 1, 2, + + "sleep", "seconds", do_sleep, + 1, 2, + + "chgrp", "gid filename ...", do_chgrp, + 3, MAXARGS, + + "chmod", "mode filename ...", do_chmod, + 3, MAXARGS, + + "chown", "uid filename ...", do_chown, + 3, MAXARGS, + + "cmp", "filename1 filename2", do_cmp, + 3, 3, + + "cp", "srcname ... destname", do_cp, + 3, MAXARGS, + +/* + "dd", "if=name of=name [bs=n] [count=n] [skip=n] [seek=n]", do_dd, + 3, MAXARGS, +*/ + "df", "[file-system]", do_df, + 1, 2, + + "echo", "[args] ...", do_echo, + 1, MAXARGS, + +/* + "ed", "[filename]", do_ed, + 1, 2, +*/ + + "exec", "filename [args]", do_exec, + 2, MAXARGS, + + "exit", "", do_exit, + 1, 1, + + "free", "", do_free, + 1, 1, + +/* + "-grep", "[-in] word filename ...", do_grep, + 3, MAXARGS, +*/ + +#ifdef CMD_HELP + "help", "", do_help, + 1, MAXARGS, +#endif + + "hexdump", "[-s pos] filename", do_hexdump, + 1, 4, + + "hostname", "[hostname]", do_hostname, + 1, 2, + + "kill", "[-sig] pid ...", do_kill, + 2, MAXARGS, + + "ln", "[-s] srcname ... destname", do_ln, + 3, MAXARGS, + + "ls", "[-lidC] filename ...", do_ls, + 1, MAXARGS, + + "mkdir", "dirname ...", do_mkdir, + 2, MAXARGS, + + "mknod", "filename type major minor", do_mknod, + 5, 5, + + "more", "filename ...", do_more, + 2, MAXARGS, + + "mount", "[-t type] devname dirname", do_mount, + 3, MAXARGS, + + "mv", "srcname ... destname", do_mv, + 3, MAXARGS, + + "printenv", "[name]", do_printenv, + 1, 2, + + "pwd", "", do_pwd, + 1, 1, + + "pid", "", do_pid, + 1, 1, + + "quit", "", do_exit, + 1, 1, + + "rm", "filename ...", do_rm, + 2, MAXARGS, + + "rmdir", "dirname ...", do_rmdir, + 2, MAXARGS, + + "setenv", "name value", do_setenv, + 3, 3, + + "source", "filename", do_source, + 2, 2, + + "sync", "", do_sync, + 1, 1, + +/* "time", "", do_time, + 1, 1, +*/ +/* + "tar", "[xtv]f devname filename ...", do_tar, + 2, MAXARGS, +*/ + "touch", "filename ...", do_touch, + 2, MAXARGS, + + "umask", "[mask]", do_umask, + 1, 2, + + "umount", "filename", do_umount, + 2, 2, + +/* + "unalias", "name", do_unalias, + 2, 2, +*/ +#ifdef CONFIG_USER_SASH_PS + "ps", "", do_ps, + 1, MAXARGS, +#endif + +/* "reboot", "", do_reboot, + 1, MAXARGS, +*/ + "cat", "filename ...", do_cat, + 2, MAXARGS, + + "date", "date [MMDDhhmm[YYYY]]", do_date, + 1, 2, + + 0, 0, 0, + 0, 0 +}; + + +typedef struct { + char *name; + char *value; +} ALIAS; + + +static ALIAS *aliastable; +static int aliascount; + +static FILE *sourcefiles[MAXSOURCE]; +static int sourcecount; + +volatile static BOOL intcrlf = TRUE; + + +static void catchint(); +static void catchquit(); +static void catchchild(); +static void readfile(); +static void command(); +#ifdef COMMAND_HISTORY +#define do_command(c,h) command(c,h) +#else +#define do_command(c,h) command(c) +#endif +static void runcmd(); +static void showprompt(); +static BOOL trybuiltin(); +static BOOL command_in_path(); +static ALIAS *findalias(); + +extern char ** environ; + +/* +char text1[] = "Text"; +char * text2 = text1; +char ** text3 = &text2; +*/ + +char buf[CMDLEN]; +int exit_code = 0; + +main(argc, argv, env) + char **argv; + char *env[]; +{ + struct sigaction act; + char *cp; +/* char buf[PATHLEN];*/ + int dofile = 0; + + if ((argc > 1) && !strcmp(argv[1], "-c")) { + /* We are that fancy a shell */ + buf[0] = '\0'; + for (dofile = 2; dofile < argc; dofile++) { + strncat(buf, argv[dofile], sizeof(buf)); + if (dofile + 1 < argc) + strncat(buf, " ", sizeof(buf)); + } + do_command(buf, FALSE); + exit(exit_code); + } + + //;'pa990523 + + if ((argc > 1) && strcmp(argv[1], "-t")) + { + dofile++; + printf("Shell invoked to run file: %s\n",argv[1]); + } + else + printf("\nSash command shell (version %s)\n", version); + fflush(stdout); + + signal(SIGINT, catchint); + signal(SIGQUIT, catchquit); + + memset(&act, 0, sizeof(act)); + act.sa_handler = catchchild; + act.sa_flags = SA_RESTART; + sigaction(SIGCHLD, &act, NULL); + + if (getenv("PATH") == NULL) + putenv("PATH=/bin:/usr/bin:/etc:/sbin:/usr/sbin"); + +/* cp = getenv("HOME"); + if (cp) { + strcpy(buf, cp); + strcat(buf, "/"); + strcat(buf, ".aliasrc"); + + if ((access(buf, 0) == 0) || (errno != ENOENT)) + readfile(buf); + } +*/ + //;'pa990523 -1/+ + //readfile(NULL); + if (dofile) + { + //open the file for reading! + readfile(argv[1]); + } + else + { + readfile(NULL); //no arguments! + } //end if arguments supplied + exit(exit_code); +} + + +/* + * Read commands from the specified file. + * A null name pointer indicates to read from stdin. + */ +static void +readfile(name) + char *name; +{ + FILE *fp; + int cc; + BOOL ttyflag; + char *ptr; + + if (sourcecount >= MAXSOURCE) { + fprintf(stderr, "Too many source files\n"); + return; + } + + fp = stdin; + if (name) { + fp = fopen(name, "r"); + if (fp == NULL) { + perror(name); + return; + } + } + sourcefiles[sourcecount++] = fp; + + ttyflag = isatty(fileno(fp)); + + while (TRUE) { + fflush(stdout); + //;'pa990523 -1/+1 + //if (1) + if (fp == stdin) //using terminal, so show prompt + showprompt(); + + if (intflag && !ttyflag && (fp != stdin)) { + fclose(fp); + sourcecount--; + return; + } + + if (fgets(buf, CMDLEN - 1, fp) == NULL) { + if (ferror(fp) && (errno == EINTR)) { + clearerr(fp); + continue; + } + break; + } + + cc = strlen(buf); + + while ((cc > 0) && isspace(buf[cc - 1])) + cc--; + buf[cc] = '\0'; + /* remove leading spaces and look for a '#' */ + ptr = &buf[0]; + while (*ptr == ' ') { + ptr++; + } + if (*ptr != '#') { + //;'pa990523 + + if (fp != stdin) { + //taking commands from file - echo + printf("Command: %s\n",buf); + } //end if (fp != stdin) + + do_command(buf, fp == stdin); + } + } + + + + if (ferror(fp)) { + perror("Reading command line"); + if (fp == stdin) + exit(1); + } + + clearerr(fp); + if (fp != stdin) + {//;'pa990523 added braces and printf + fclose(fp); + printf("Execution Finished, Exiting\n"); + } //end if (fp != stdin) + + sourcecount--; +} + + +/* + * Parse and execute one null-terminated command line string. + * This breaks the command line up into words, checks to see if the + * command is an alias, and expands wildcards. + */ +static void +#ifdef COMMAND_HISTORY +command(cmd, do_history) + int do_history; +#else +command(cmd) +#endif + char *cmd; +{ + ALIAS *alias; + char **argv; + int argc; + int bg; + char *c; + + char last_exit_code[10]; + + sprintf(last_exit_code, "%d", exit_code); + + intflag = FALSE; + exit_code = 0; + + freechunks(); + + while (isblank(*cmd)) + cmd++; + +#ifdef COMMAND_HISTORY + if (do_history) { + int i; + static char *history[HISTORY_SIZE]; + + if (*cmd == '!') { + if (cmd[1] == '!') + i = 0; + else { + i = atoi(cmd+1) - 1; + if (i < 0 || i >= HISTORY_SIZE) { + printf("%s: Out of range\n", cmd); + return; + } + } + if (history[i] == NULL) { + printf("%s: Null entry\n", cmd); + return; + } + strcpy(cmd, history[i]); + } else if (*cmd == 'h' && cmd[1] == '\0') { + for (i=0; i0; i--) + history[i] = history[i-1]; + history[0] = strdup(cmd); + } + } +#endif + if (c = strchr(cmd, '&')) { + *c = '\0'; + bg = 1; + } else + bg = 0; + + /* Set the last exit code */ + setenv("?", last_exit_code, 1); + + if ((cmd = expandenvvar(cmd)) == NULL) + return; + + if ((*cmd == '\0') || !makeargs(cmd, &argc, &argv)) + return; + + /* + * Search for the command in the alias table. + * If it is found, then replace the command name with + * the alias, and append any other arguments to it. + */ + alias = findalias(argv[0]); + if (alias) { + cmd = buf; + strcpy(cmd, alias->value); + + while (--argc > 0) { + strcat(cmd, " "); + strcat(cmd, *++argv); + } + + if (!makeargs(cmd, &argc, &argv)) + return; + } + + /* + * BASH-style variable setting + */ + if (argc == 1) { + c = index(argv[0], '='); + if (c > argv[0]) { + *c++ = '\0'; + setenv(argv[0], c, 1); + return; + } + } + + /* + * Now look for the command in the builtin table, and execute + * the command if found. + */ +#ifdef FAVOUR_EXTERNAL_COMMANDS + if (!command_in_path(argv[0])) +#endif + if (trybuiltin(argc, argv)) + return; + + /* + * Not found, run the program along the PATH list. + */ + runcmd(cmd, bg, argc, argv); +} + + +#ifdef FAVOUR_EXTERNAL_COMMANDS +/* + * return true if we find this command in our + * path. + */ +static BOOL +command_in_path(char *cmd) +{ + struct stat stat_buf; + + if (strchr(cmd, '/') == 0) { + char * path; + static char path_copy[PATHLEN]; + + /* Search path for binary */ + for (path = getenv("PATH"); path && *path; ) { + char * p2; + + strcpy(path_copy, path); + if (p2 = strchr(path_copy, ':')) { + *p2 = '\0'; + } + + if (strlen(path_copy)) + strcat(path_copy, "/"); + strcat(path_copy, cmd); + + if (!stat(path_copy, &stat_buf) && (stat_buf.st_mode & 0111)) + return(TRUE); + + p2 = strchr(path, ':'); + if (p2) + path = p2 + 1; + else + path = 0; + } + } else if (!stat(cmd, &stat_buf) && (stat_buf.st_mode & 0111)) + return(TRUE); + return(FALSE); +} +#endif /* FAVOUR_EXTERNAL_COMMANDS */ + + +/* + * Try to execute a built-in command. + * Returns TRUE if the command is a built in, whether or not the + * command succeeds. Returns FALSE if this is not a built-in command. + */ +static BOOL +trybuiltin(argc, argv) + char **argv; +{ + CMDTAB *cmdptr; + int oac; + int newargc; + int matches; + int i; + char *newargv[MAXARGS]; + char *nametable[MAXARGS]; + + cmdptr = cmdtab - 1; + do { + cmdptr++; + if (cmdptr->name[0] == 0) + return FALSE; + + } while (strcmp(argv[0], cmdptr->name)); + + /* + * Give a usage string if the number of arguments is too large + * or too small. + */ + if ((argc < cmdptr->minargs) || (argc > cmdptr->maxargs)) { + fprintf(stderr, "usage: %s %s\n", + cmdptr->name, cmdptr->usage); + fflush(stderr); + + return TRUE; + } + + /* + * Check here for several special commands which do not + * have wildcarding done for them. + */ + +/* if (cmdptr->func == do_prompt) { + (*cmdptr->func)(argc, argv); + return TRUE; + } +*/ + + /* + * Now for each command argument, see if it is a wildcard, and if + * so, replace the argument with the list of matching filenames. + */ + newargv[0] = argv[0]; + newargc = 1; + oac = 0; + + while (++oac < argc) { + if (argv[oac][0] == '"' || argv[oac][0] == '\'') { + argv[oac]++; + matches = 0; + } + else { + matches = expandwildcards(argv[oac], MAXARGS, nametable); + if (matches < 0) + return TRUE; + } + + if ((newargc + matches) >= MAXARGS) { + fprintf(stderr, "Too many arguments\n"); + return TRUE; + } + + if (matches == 0) + newargv[newargc++] = argv[oac]; + + for (i = 0; i < matches; i++) + newargv[newargc++] = nametable[i]; + } + + (*cmdptr->func)(newargc, newargv); + + return TRUE; +} + + +/* + * Execute the specified command. + */ +static void +runcmd(cmd, bg, argc, argv) + char *cmd; + int bg; + int argc; + char **argv; +{ + register char * cp; + BOOL magic; + int pid; + int status; + int oac; + int newargc; + int matches; + int i; + char *newargv[MAXARGS]; + char *nametable[MAXARGS]; + struct sigaction act; + + newargv[0] = argv[0]; + +#ifdef INTERNAL_PATH_EXPANSION + if (strchr(argv[0], '/') == 0) { + char * path; + struct stat stat_buf; + static char path_copy[PATHLEN]; + + /* Search path for binary */ + for (path = getenv("PATH"); path && *path; ) { + char * p2; + strncpy(path_copy, path, sizeof(path_copy - 1)); + if (p2 = strchr(path_copy, ':')) { + *p2 = '\0'; + } + + if (strlen(path_copy)) + strncat(path_copy, "/", sizeof(path_copy)); + strncat(path_copy, argv[0], sizeof(path_copy)); + + if (!stat(path_copy, &stat_buf) && (stat_buf.st_mode & 0111)) { + newargv[0] = path_copy; + break; + } + + p2 = strchr(path, ':'); + if (p2) + path = p2 + 1; + else + path = 0; + } + } +#endif + + /* + * Now for each command argument, see if it is a wildcard, and if + * so, replace the argument with the list of matching filenames. + */ + newargc = 1; + oac = 0; + + while (++oac < argc) { + if (argv[oac][0] == '"' || argv[oac][0] == '\'') { + argv[oac]++; + matches = 0; + } + else { + matches = expandwildcards(argv[oac], MAXARGS, nametable); + if (matches < 0) + return; + } + + if ((newargc + matches) >= MAXARGS) { + fprintf(stderr, "Too many arguments\n"); + return; + } + + if (matches == 0) + newargv[newargc++] = argv[oac]; + + for (i = 0; i < matches; i++) + newargv[newargc++] = nametable[i]; + } + + newargv[newargc] = 0; + + magic = FALSE; + + /* + for (cp = cmd; *cp; cp++) { + if ((*cp >= 'a') && (*cp <= 'z')) + continue; + if ((*cp >= 'A') && (*cp <= 'Z')) + continue; + if (isdecimal(*cp)) + continue; + if (isblank(*cp)) + continue; + + if ((*cp == '.') || (*cp == '/') || (*cp == '-') || + (*cp == '+') || (*cp == '=') || (*cp == '_') || + (*cp == ':') || (*cp == ',')) + continue; + + magic = TRUE; + } + */ + + if (magic) { + printf("%s: no such file or directory\n", cmd); + system(cmd); + return; + } + + if (!bg) + signal(SIGCHLD, SIG_DFL); + + /* + * No magic characters in the expanded command, so do the fork and + * exec ourself. If this fails with ENOEXEC, then run the + * shell anyway since it might be a shell script. + */ + if (!(pid = vfork())) { + int ci; + + /* + * We are the child, so run the program. + * First close any extra file descriptors we have opened. + * be sure not to modify any globals after the vfork ! + */ + + for (ci = 0; ci < sourcecount; ci++) + if (sourcefiles[ci] != stdin) + close(fileno(sourcefiles[ci])); + + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + execvp(newargv[0], newargv); + + printf("%s: %s\n", newargv[0], (errno == ENOENT) ? "Bad command or file name" : strerror(errno)); + + _exit(0); + } + + if (pid < 0) { + memset(&act, 0, sizeof(act)); + act.sa_handler = catchchild; + act.sa_flags = SA_RESTART; + sigaction(SIGCHLD, &act, NULL); + + perror("vfork failed"); + return; + } + + if (bg) { + printf("[%d]\n", pid); + return; + } + + if (pid) { + int cpid; + status = 0; + intcrlf = FALSE; + + for (;;) { + cpid = wait4(pid, &status, 0, 0); + if ((cpid < 0) && (errno == EINTR)) + continue; + if (cpid < 0) + break; + if (cpid != pid) { + fprintf(stderr, "sh %d: child %d died\n", getpid(), cpid); + continue; + } + } + + act.sa_handler = catchchild; + memset(&act.sa_mask, 0, sizeof(act.sa_mask)); + act.sa_flags = SA_RESTART; + sigaction(SIGCHLD, &act, NULL); + + intcrlf = TRUE; + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == 0) + return; + exit_code = WEXITSTATUS(status); + } else + exit_code = 1; + + return; + } + + perror(argv[0]); + exit(1); +} + +#ifdef CMD_HELP +void +do_help(argc, argv) + char **argv; +{ + CMDTAB *cmdptr; + + for (cmdptr = cmdtab; cmdptr->name && cmdptr->name[0]; cmdptr++) + printf("%-10s %s\n", cmdptr->name, cmdptr->usage); +} +#endif /* CMD_HELP */ + +#ifdef CMD_ALIAS +void +do_alias(argc, argv) + char **argv; +{ + char *name; + char *value; + ALIAS *alias; + int count; + char buf[CMDLEN]; + + if (argc < 2) { + count = aliascount; + for (alias = aliastable; count-- > 0; alias++) + printf("%s\t%s\n", alias->name, alias->value); + return; + } + + name = argv[1]; + if (argc == 2) { + alias = findalias(name); + if (alias) + printf("%s\n", alias->value); + else + fprintf(stderr, "Alias \"%s\" is not defined\n", name); + return; + } + + if (strcmp(name, "alias") == 0) { + fprintf(stderr, "Cannot alias \"alias\"\n"); + return; + } + + if (!makestring(argc - 2, argv + 2, buf, CMDLEN)) + return; + + value = malloc(strlen(buf) + 1); + + if (value == NULL) { + fprintf(stderr, "No memory for alias value\n"); + return; + } + + strcpy(value, buf); + + alias = findalias(name); + if (alias) { + free(alias->value); + alias->value = value; + return; + } + + if ((aliascount % ALIASALLOC) == 0) { + count = aliascount + ALIASALLOC; + + if (aliastable) + alias = (ALIAS *) realloc(aliastable, + sizeof(ALIAS *) * count); + else + alias = (ALIAS *) malloc(sizeof(ALIAS *) * count); + + if (alias == NULL) { + free(value); + fprintf(stderr, "No memory for alias table\n"); + return; + } + + aliastable = alias; + } + + alias = &aliastable[aliascount]; + + alias->name = malloc(strlen(name) + 1); + + if (alias->name == NULL) { + free(value); + fprintf(stderr, "No memory for alias name\n"); + return; + } + + strcpy(alias->name, name); + alias->value = value; + aliascount++; +} +#endif /* CMD_ALIAS */ + +/* + * Look up an alias name, and return a pointer to it. + * Returns NULL if the name does not exist. + */ +static ALIAS * +findalias(name) + char *name; +{ + ALIAS *alias; + int count; + + count = aliascount; + for (alias = aliastable; count-- > 0; alias++) { + if (strcmp(name, alias->name) == 0) + return alias; + } + + return NULL; +} + + +void +do_source(argc, argv) + char **argv; +{ + readfile(argv[1]); +} + +/*void +do_cd(argc, argv) + char **argv; +{ + char *name; + + name = argv[1]; + + if (chdir(name)) + perror("Unable to chdir to %s"); + +}*/ + +void +do_pid(argc, argv) +{ + printf("%d\n", getpid()); +} + +void +do_exec(argc, argv) + char **argv; +{ + while (--sourcecount >= 0) { + if (sourcefiles[sourcecount] != stdin) + fclose(sourcefiles[sourcecount]); + } + + argv[argc] = NULL; + execvp(argv[1], &argv[1]); + + perror(argv[1]); + exit(1); +} + +/*void +do_exit(argc, argv) + char **argv; +{ + if (argc>1) + exit(atoi(argv[1])); + else + exit(0); +}*/ + + +#ifdef CMD_ALIAS +void +do_unalias(argc, argv) + char **argv; +{ + ALIAS *alias; + + while (--argc > 0) { + alias = findalias(*++argv); + if (alias == NULL) + continue; + + free(alias->name); + free(alias->value); + aliascount--; + alias->name = aliastable[aliascount].name; + alias->value = aliastable[aliascount].value; + } +} +#endif /* CMD_ALIAS */ + +/* + * Display the prompt string. + */ +static void +showprompt() +{ + char *cp; + //;'pa990523 changed from 6... + char buf[60]; + + if ((cp = getenv("PS1")) != NULL) { + printf("%s", cp); + } + else { + *buf = '\0'; + getcwd(buf, sizeof(buf) - 1); + printf("%s> ", buf); + } + fflush(stdout); +} + + +static void +catchint() +{ + signal(SIGINT, catchint); + + intflag = TRUE; + + if (intcrlf) + write(STDOUT, "\n", 1); +} + + +static void +catchquit() +{ + signal(SIGQUIT, catchquit); + + intflag = TRUE; + + if (intcrlf) + write(STDOUT, "\n", 1); +} + +static void +catchchild() +{ + char buf[40]; + pid_t pid; + int status; + + /*signal(SIGCHLD, catchchild);*/ /* Unneeded */ + + pid = wait4(-1, &status, WUNTRACED, 0); + if (WIFSTOPPED(status)) + sprintf(buf, "sh %d: Child %d stopped\n", getpid(), pid); + else + sprintf(buf, "sh %d: Child %d died\n", getpid(), pid); + + if (intcrlf) + write(STDOUT, "\n", 1); + + write(STDOUT, buf, strlen(buf)); +} + +/* END CODE */ diff --git a/package/sash/src/sash.h b/package/sash/src/sash.h new file mode 100644 index 000000000..eb2321fa0 --- /dev/null +++ b/package/sash/src/sash.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1993 by David I. Bell + * Permission is granted to use, distribute, or modify this source, + * provided that this copyright notice remains intact. + * + * Definitions for stand-alone shell for system maintainance for Linux. + */ + +#include +#include +#include +#include +#include + +#define PATHLEN 256 +#define CMDLEN 1024 +#define MAXARGS 50 +#define ALIASALLOC 20 +#define STDIN 0 +#define STDOUT 1 +#define MAXSOURCE 10 +#ifdef COMMAND_HISTORY +#define HISTORY_SIZE 20 /* Number of entries in command history */ +#endif + +#ifndef isblank +#define isblank(ch) (((ch) == ' ') || ((ch) == '\t')) +#endif + +#define isquote(ch) (((ch) == '"') || ((ch) == '\'')) +#define isdecimal(ch) (((ch) >= '0') && ((ch) <= '9')) +#define isoctal(ch) (((ch) >= '0') && ((ch) <= '7')) + + +typedef int BOOL; + +#define FALSE ((BOOL) 0) +#define TRUE ((BOOL) 1) + + +extern void do_alias(), do_cd(), do_exec(), do_exit(), do_prompt(); +extern void do_source(), do_umask(), do_unalias(), do_help(), do_ln(); +extern void do_cp(), do_mv(), do_rm(), do_chmod(), do_mkdir(), do_rmdir(); +extern void do_mknod(), do_chown(), do_chgrp(), do_sync(), do_printenv(); +extern void do_more(), do_cmp(), do_touch(), do_ls(), do_dd(), do_tar(); +extern void do_mount(), do_umount(), do_setenv(), do_pwd(), do_echo(); +extern void do_kill(), do_grep(), do_ed(), do_hexdump(), do_pid(); +extern void do_df(), do_ps(), do_reboot(), do_cat(), do_time(), do_free(); +extern void do_hostname(), do_sleep(); +extern void do_date(); + + +extern char *buildname(); +extern char *modestring(); +extern char *timestring(); +extern BOOL isadir(); +extern BOOL copyfile(); +extern BOOL match(); +extern BOOL makestring(); +extern BOOL makeargs(); +extern int expandwildcards(); +extern int namesort(); +extern char *getchunk(); +extern void freechunks(); +extern char *expandenvvar(); + +extern BOOL intflag; +extern int exit_code; + +/* END CODE */ diff --git a/package/sash/src/shutdown.c b/package/sash/src/shutdown.c new file mode 100644 index 000000000..444326483 --- /dev/null +++ b/package/sash/src/shutdown.c @@ -0,0 +1,75 @@ +/* shutdown.c: + * + * Copyright (C) 1998 Kenneth Albanowski , + * + * 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. + */ + +#include "sash.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if __GNU_LIBRARY__ > 5 +#include +#endif + +int +main(argc, argv) + int argc; + char **argv; +{ + char *progname = argv[0]; + + if (argc > 2 && strcmp(argv[1], "-d") == 0) { + sleep(atoi(argv[2])); + argc -= 2; + } + if ((argc != 3) || (strcmp(argv[1], "-h") && strcmp(argv[1], "-r")) || strcmp(argv[2], "now")) { + printf("Usage: %s [-d delay] -h|-r now\n", progname); + exit(0); + } + + kill(1, SIGTSTP); + sync(); + signal(SIGTERM,SIG_IGN); + setpgrp(); + kill(-1, SIGTERM); + sleep(1); + kill(-1, SIGHUP); /* Force PPPD's down, too */ + sleep(1); + kill(-1, SIGKILL); + sync(); + sleep(1); + + if (strcmp(argv[1], "-h")==0) { +#if __GNU_LIBRARY__ > 5 + reboot(0xCDEF0123); +#else + reboot(0xfee1dead, 672274793, 0xCDEF0123); +#endif + } else { +#if __GNU_LIBRARY__ > 5 + reboot(0x01234567); +#else + reboot(0xfee1dead, 672274793, 0x01234567); +#endif + } + + exit(0); /* Shrug */ +} + diff --git a/package/simpleinit/Makefile b/package/simpleinit/Makefile new file mode 100644 index 000000000..aeeedfc08 --- /dev/null +++ b/package/simpleinit/Makefile @@ -0,0 +1,30 @@ +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include ${ADK_TOPDIR}/rules.mk + +PKG_NAME:= simpleinit +PKG_VERSION:= 1.0 +PKG_RELEASE:= 1 +PKG_DESCR:= simple init for systems without mmu +PKG_SECTION:= base/apps + +NO_DISTFILES:= 1 + +include ${ADK_TOPDIR}/mk/package.mk + +$(eval $(call PKG_template,SIMPLEINIT,simpleinit,${PKG_VERSION}-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) + +CONFIG_STYLE:= manual +BUILD_STYLE:= manual +INSTALL_STYLE:= manual + +do-build: + ${TARGET_CC} ${TARGET_CPPFLAGS} ${TARGET_CFLAGS} ${TARGET_LDFLAGS} \ + -o ${WRKBUILD}/simpleinit ${WRKBUILD}/simpleinit.c + +do-install: + ${INSTALL_DIR} ${IDIR_SIMPLEINIT}/sbin + ${INSTALL_BIN} ${WRKBUILD}/simpleinit ${IDIR_SIMPLEINIT}/sbin/init + +include ${ADK_TOPDIR}/mk/pkg-bottom.mk diff --git a/package/simpleinit/files/rc b/package/simpleinit/files/rc new file mode 100755 index 000000000..33d60a4b6 --- /dev/null +++ b/package/simpleinit/files/rc @@ -0,0 +1,47 @@ +#!/bin/sh +set -x +export PATH=/bin:/sbin:/usr/bin:/usr/sbin +ln -s /proc/self/fd/2 /dev/stderr +: ${rcquiet=0} +if [ $rcquiet -ne 1 ];then + echo "System initialization ..." +fi + +# remount /dev with smaller size +mount -o remount,nosuid,size=128k,mode=0755 -t tmpfs mdev /dev + +# start mdev dynamic device node management +echo >/dev/mdev.seq +if [ -f /proc/sys/kernel/hotplug ];then + echo "/sbin/mdev" >/proc/sys/kernel/hotplug +fi +# creates f.e. /dev/root +mdev -s + +# seed some random +cat /etc/.rnd >/dev/urandom 2>&1 + +# setup cfgfs +[ -x /sbin/cfgfs ] && { + cfgfs setup + mount -o remount,ro / +} + +# remount /tmp with smaller size +size=$(cat /etc/tmpfs 2>/dev/null) +[ -z $size ] && size=2048 +mount -o remount,nosuid,nodev,mode=1777,size=${size}k -t tmpfs tmpfs /tmp + +# create some useful directories in tmpfs +mkdir -p /var/log +mkdir -p /var/run +mkdir -p /var/tmp +touch /var/log/lastlog +touch /var/log/wtmp + +HOSTNAME= +[[ -s /etc/hostname ]] && HOSTNAME=$(cat /etc/hostname) +HOSTNAME=${HOSTNAME%%.*} +echo ${HOSTNAME:=openadk} >/proc/sys/kernel/hostname + +chown 0:0 /tmp; chmod 1777 /tmp diff --git a/package/simpleinit/src/pathnames.h b/package/simpleinit/src/pathnames.h new file mode 100644 index 000000000..92b7d0302 --- /dev/null +++ b/package/simpleinit/src/pathnames.h @@ -0,0 +1,37 @@ +/* + * @(#)pathnames.h 5.3 (Berkeley) 5/9/89 + * + * Heavily modified by poe@daimi.aau.dk for Linux + */ + +#include + +#ifndef __STDC__ +# error "we need an ANSI compiler" +#endif + +#ifndef SBINDIR +# define SBINDIR "/sbin" +#endif + +#define _PATH_BSHELL "/bin/sh" +#define _PATH_CSHELL "/bin/csh" +#define _PATH_TTY "/dev/tty" +#define TTYTYPES "/etc/ttytype" +#define SECURETTY "/etc/securetty" + +#define _PATH_HUSHLOGIN ".hushlogin" +#define _PATH_MOTDFILE "/etc/motd" +#define _PATH_NOLOGIN "/etc/nologin" + +#define _PATH_LOGIN "/bin/login" +#define _PATH_INITTAB "/etc/inittab" +#define _PATH_RC "/etc/rc" +#define _PATH_REBOOT "/bin/reboot" +#define _PATH_SINGLE "/etc/singleboot" +#define _PATH_SECURE "/etc/securesingle" +#define _PATH_USERTTY "/etc/usertty" + +#define _PATH_CONFIGRC "/etc/config/start" +#define _PATH_CONFIGTAB "/etc/config/inittab" +#define _PATH_FIREWALL "/bin/firewall" diff --git a/package/simpleinit/src/simpleinit.c b/package/simpleinit/src/simpleinit.c new file mode 100644 index 000000000..291f88f47 --- /dev/null +++ b/package/simpleinit/src/simpleinit.c @@ -0,0 +1,1046 @@ +/* simpleinit.c - poe@daimi.aau.dk */ +/* Version 1.21 */ + +/* gerg@snapgear.com -- modified for direct console support DEC/1999 */ +/* davidm@snapgear.com -- modified for init.conf SEP/2004 */ +/* toby@snapgear.com -- allow the array of commands to grow as needed OCT/2004 */ +/* davidm@snapgear.com -- use dynamically allocated tables APR/2005 */ + +#define _GNU_SOURCE /* For crypt() and termios defines */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SHADOW_PWD +#include +#endif + +#if __GNU_LIBRARY__ > 5 +#include +#endif + +#include "pathnames.h" + +#define BUF_SIZ 100 /* max size of a line in inittab */ +#define NUMCMD 30 /* step size when realloc more space for the commands */ +#define NUMTOK 20 /* max number of tokens in inittab command */ + +/* Threshold time for detecting "fast" spawning processes */ +static int testtime = 90; +/* Number of rapid respawns that counts as too fast */ +static int maxspawn = 5; +/* Maximum delay between runs */ +static int maxdelay = 595; +/* Time between successive runs of a process */ +static int delaytime = 5; + +#define MAXTRIES 3 /* number of tries allowed when giving the password */ + +#define RUN_RC /* Use a console if possible */ + +#ifndef CTRL +#define CTRL(X) ((X)&037) +#endif + +#ifdef INCLUDE_TIMEZONE +char tzone[BUF_SIZ]; +#endif +/* #define DEBUGGING */ + +/* Define this if you want init to ignore the termcap field in inittab for + console ttys. */ +/* #define SPECIAL_CONSOLE_TERM */ + +struct initline { + pid_t pid; + time_t lastrun; + time_t nextrun; + char **toks; + short delay; + char tty[10]; + char termcap[30]; + char *line; + char *fullline; + unsigned char xcnt; +}; + +struct initline *inittab; +/* How many struct initline's will fit in the memory pointed to by inittab */ +int inittab_size = 0; +int numcmd; +int stopped = 0; /* are we stopped */ +int reload = 0; /* are we stopped */ +int run_sigint_processing = 0; + +extern void spawn(int); +extern void hup_handler(); +extern void reload_inittab(); +extern void read_inittab(void); +static int read_initfile(const char *); +extern void tstp_handler(); +extern void int_handler(); +extern void sigint_processing(); +extern void cont_handler(); +extern void set_tz(void); +extern void write_wtmp(void); +extern void make_ascii_tty(void); +extern void make_console(const char *); +extern int boot_single(int singlearg, int argc, char *argv[]); +#ifdef CONFIG_USER_INIT_CONF +extern void load_init_conf(void); +#endif + +/* Keep track of console device, if any... */ +#if LINUX_VERSION_CODE < 0x020100 +char *console_device = NULL; +int console_baud = -1; +#else +int have_console = 0; +#endif + + +static void err(const char *s) +{ + struct iovec output[2]; +#if LINUX_VERSION_CODE < 0x020100 + int fd; +#endif + output[0].iov_base = "init: "; + output[0].iov_len = 6; + output[1].iov_base = (void *)s; + output[1].iov_len = strlen(s); +#if LINUX_VERSION_CODE < 0x020100 + if (console_device == NULL) return; + if((fd = open(console_device, O_WRONLY)) < 0) return; + writev(fd, output, 2); + close(fd); +#else + if (have_console) + writev(1, output, 2); +#endif +} + +void +add_tok(struct initline *p, char *tok) +{ + int i; + for (i = 0; p->toks && p->toks[i]; i++) + ; + + /* allocate space for new entry and terminating NULL */ + p->toks = (char **) realloc(p->toks, (i + 2) * sizeof(char *)); + if (!p->toks) { + err("malloc failed\n"); + _exit(1); + } + p->toks[i++] = tok; + p->toks[i] = NULL; +} + +static void enter_single(void) +{ + pid_t pid; + char *av[2]; + + err("Booting to single user mode\n"); + av[0] = _PATH_BSHELL; + av[1] = NULL; + if((pid = vfork()) == 0) { + extern char **environ; + /* the child */ + execve(_PATH_BSHELL, av, environ); + err("exec of single user shell failed\n"); + _exit(0); + } else if(pid > 0) { + int i; + while(wait(&i) != pid) /* nothing */; + } else if(pid < 0) { + err("fork of single user shell failed\n"); + } + unlink(_PATH_SINGLE); +} + + +#if LINUX_VERSION_CODE < 0x020100 +static void +set_console_baud(int baud) +{ + switch (baud) { + case 50: console_baud = B50; break; + case 75: console_baud = B75; break; + case 110: console_baud = B110; break; + case 134: console_baud = B134; break; + case 150: console_baud = B150; break; + case 200: console_baud = B200; break; + case 300: console_baud = B300; break; + case 600: console_baud = B600; break; + case 1200: console_baud = B1200; break; + case 1800: console_baud = B1800; break; + case 2400: console_baud = B2400; break; + case 4800: console_baud = B4800; break; + default: + case 9600: console_baud = B9600; break; + case 19200: console_baud = B19200; break; + case 38400: console_baud = B38400; break; + case 57600: console_baud = B57600; break; + case 115200: console_baud = B115200; break; + case 230400: console_baud = B230400; break; + case 460800: console_baud = B460800; break; + } +} +#endif + +static int do_command(const char *path, const char *filename, int dowait) +{ + pid_t pid, wpid; + int stat, st; + + if((pid = vfork()) == 0) { + /* the child */ + char *argv[3]; +#ifdef INCLUDE_TIMEZONE + char tz[BUF_SIZ]; +#endif + char *env[3]; + + /* Use /dev/null for stdin */ + close(0); + open("/dev/null", O_RDONLY); + + argv[0] = (char *)path; + argv[1] = (char *)filename; + argv[2] = NULL; + + env[0] = "PATH=/bin:/usr/bin:/etc:/sbin:/usr/sbin"; +#ifdef INCLUDE_TIMEZONE + strcpy(tz, "TZ="); + strcat(tz, tzone); + env[1] = tz; + env[2] = NULL; +#else + env[1] = NULL; +#endif + + execve(path, argv, env); + + err("exec rc failed\n"); + _exit(2); + } else if(pid > 0) { + if (!dowait) + stat = 0; + else { + /* parent, wait till rc process dies before spawning */ + while ((wpid = wait(&stat)) != pid) + if (wpid == -1 && errno == ECHILD) { /* see wait(2) manpage */ + stat = 0; + break; + } + } + } else if(pid < 0) { + err("fork of rc shell failed\n"); + stat = -1; + } + st = WEXITSTATUS(stat); + return st; +} + +/* + * run /etc/rc. The environment is passed to the script, so the RC environment + * variable can be used to decide what to do. RC may be set from LILO. + */ +static int do_rc(void) +{ + int rc; + + rc = do_command(_PATH_BSHELL, _PATH_RC, 1); + if (rc) + return(rc); +#ifdef CONFIG_USER_INIT_RUN_FIREWALL + rc = do_command(_PATH_FIREWALL, "-i", 1); + if (rc) + err(_PATH_FIREWALL " failed!"); +#endif +#ifdef CONFIG_USER_FLATFSD_FLATFSD + rc = do_command(_PATH_BSHELL, _PATH_CONFIGRC, 1); + if (rc) + err(_PATH_CONFIGRC " failed!"); +#endif +#ifdef CONFIG_USER_INIT_RUN_FIREWALL + rc = do_command(_PATH_FIREWALL, NULL, 0); + if (rc) + err(_PATH_FIREWALL " failed!"); +#endif +#ifdef INCLUDE_TIMEZONE + /* We read the timezone file here, because the flat file system + * has probably been created by now. + */ + set_tz(); +#endif + return(0); +} + +void respawn_children(int signo) { + int i, delta = -1; + time_t now; + alarm(0); + if ((now = time(NULL)) == 0) now = 1; + for(i = 0; i < numcmd; i++) { + if(inittab[i].pid < 0) { /* Start jobs */ + if(stopped) + inittab[i].pid = -1; + /* + ** Do not spawn child from signal handler ! + ** SIGALRM would be blocked for the child + */ + else if (signo == 0) + spawn(i); + } + /* Check for naughty jobs */ + if (inittab[i].nextrun > now) { + int d; + d = inittab[i].nextrun - now; + if (delta < 0 || d < delta) + delta = d; + } + } + if (delta > 0) { + alarm(delta); + } +} + +int main(int argc, char *argv[]) +{ + int i; + struct sigaction sa; + + /* + * setup all the signal handlers here + */ + + memset(&sa, 0, sizeof(sa)); + /* sa.sa_flags = SA_RESETHAND we want to keep the handlers armed */ + + sa.sa_handler = tstp_handler; + sigaction(SIGTSTP, &sa, NULL); + + sa.sa_handler = cont_handler; + sigaction(SIGCONT, &sa, NULL); + + sa.sa_handler = int_handler; + sigaction(SIGINT, &sa, NULL); + + sa.sa_handler = respawn_children; + sigaction(SIGALRM, &sa, NULL); + + sa.sa_handler = hup_handler; + sigaction(SIGHUP, &sa, NULL); + +#if defined(CONSOLE_BAUD_RATE) && LINUX_VERSION_CODE < 0x020100 + set_console_baud(CONSOLE_BAUD_RATE); +#endif + + /* + * start up in single user mode if /etc/singleboot exists or if + * argv[1] is "single". + */ + if(boot_single(0, argc, argv)) enter_single(); + +#ifdef RUN_RC + /* Register console if defined by boot */ +#if LINUX_VERSION_CODE < 0x020100 + if ((console_device = getenv("CONSOLE"))) { + char *sp; + unsetenv("CONSOLE"); + if ((sp = strchr(console_device, ','))) { + *sp++ = 0; + set_console_baud(atoi(sp)); + } + } + + make_ascii_tty(); +#else +{ + struct stat st; + + if (isatty(1)) { + have_console = 1; + make_ascii_tty(); + } else if (fstat(1, &st) == -1 && errno == EBADF) { + /* No stdout, so send everything to /dev/null */ + close(0); close(1); close(2); + open("/dev/null", O_RDWR); + dup(0); + dup(0); + } +} +#endif + + /*If we get a SIGTSTP before multi-user mode, do nothing*/ + while(stopped) + pause(); + if(do_rc() != 0 && boot_single(1, argc, argv) && !stopped) + enter_single(); + while(stopped) /*Also if /etc/rc fails & we get SIGTSTP*/ + pause(); +#endif + + /* initialize the array of commands */ + inittab = (struct initline *)malloc(NUMCMD * sizeof(struct initline)); + inittab_size = NUMCMD; + + if (!inittab) { + /* failure case - what do you do if init fails? */ + err("malloc failed"); + _exit(1); + } + + write_wtmp(); /* write boottime record */ + read_inittab(); + +#ifdef DEBUGGING + for(i = 0; i < numcmd; i++) { + char **p = inittab[i].toks; + printf("toks= %s %s %s %s\n",p[0], p[1], p[2], p[3]); + printf("tty= %s\n", inittab[i].tty); + printf("termcap= %s\n", inittab[i].termcap); + } + /*exit(0);*/ +#endif + +#if LINUX_VERSION_CODE < 0x020100 + for(i = 0; i < getdtablesize(); i++) close(i); +#else + /* Always leave 0, 1, and 2 connected (to /dev/null) for the child process */ + for(i = 3; i < getdtablesize(); i++) close(i); +#endif + + for (;;) { + pid_t pid; + int vec; + + if (run_sigint_processing) { + run_sigint_processing = 0; + sigint_processing(); + } + + respawn_children(0); + + if (reload) { + reload = 0; + reload_inittab(); + continue; /* process all reloads before waiting */ + } + + pid = wait(&vec); + alarm(0); + + /* clear utmp entry, and append to wtmp if possible */ +#if 0 /* DAVIDM */ + { + struct utmp *ut; + int ut_fd; + + utmpname(_PATH_UTMP); + setutent(); + while((ut = getutent())) { + if(ut->ut_pid == pid) { + time(&ut->ut_time); + bzero(&ut->ut_user, UT_NAMESIZE); + bzero(&ut->ut_host, sizeof(ut->ut_host)); + ut->ut_type = DEAD_PROCESS; + ut->ut_pid = 0; + ut->ut_addr = 0; + endutent(); + pututline(ut); + if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) { + flock(ut_fd, LOCK_EX|LOCK_NB); + write(ut_fd, (const void *)ut, sizeof(struct utmp)); + flock(ut_fd, LOCK_UN|LOCK_NB); + close(ut_fd); + } + break; + } + } + endutent(); + } +#endif + + for(i = 0; i < numcmd; i++) { + if(pid == inittab[i].pid) { + inittab[i].pid = -1; + } + } + } +} + + +/* + * return true if we should boot up in singleuser mode. If argv[i] is + * "single" or the file /etc/singleboot exists, then singleuser mode should + * be entered. If /etc/securesingle exists ask for root password first. + */ +int boot_single(int singlearg, int argc, char *argv[]) +{ + char *pass, *rootpass = NULL; + struct passwd *pwd; + int i; + + for(i = 1; i < argc; i++) { + if(argv[i] && !strcmp(argv[i], "single")) singlearg = 1; + } + return 0; +} + +void spawn(int i) +{ + pid_t pid; + int j; + time_t t; + struct initline *it; + char buf[150]; + + it = inittab + i; + + t = time(NULL); + /* Check for held process */ + if ((unsigned long)(it->nextrun - t - 1) < maxdelay) + return; + if (it->lastrun + testtime > t) { /* Respawning quickly */ + if (it->xcnt < 0xff) + it->xcnt++; + } else { /* Normal respawning */ + it->xcnt = 0; + it->lastrun = t; + it->delay = delaytime; + } + if (it->xcnt >= maxspawn) { /* Too many too quickly */ + strcpy(buf, it->toks[0]); + strcat(buf, " respawning too fast\n"); + err(buf); + it->pid = -1; + if (it->delay >= maxdelay) + it->delay = maxdelay; + else if (it->delay < delaytime) + it->delay = delaytime; + else if((it->delay *= 2) > maxdelay) + it->delay = maxdelay; + it->nextrun = t + it->delay; + /* Fiddle with the tracking vars to ensure that only + * one attempt is made to run this next time around. + */ + it->lastrun = it->nextrun; + it->xcnt -= 2; + return; + } + it->nextrun = t + delaytime; + + if((pid = vfork()) < 0) { + it->pid = -1; + err("fork failed\n"); + return; + } + if(pid) { + /* this is the parent */ + it->pid = pid; + return; + } else { + /* this is the child */ + char term[40]; + char *prog; +#ifdef INCLUDE_TIMEZONE + char tz[BUF_SIZ]; +#endif + char *env[4]; + + setsid(); + + /* Close everything other than 0, 1 and 2 */ + for(j = 3; j < getdtablesize(); j++) { + close(j); + } + /* Now set up 0, 1 and 2 */ + make_console(it->tty); + + strcpy(term, "TERM="); + strcat(term, it->termcap); + env[0] = term; + env[1] = "PATH=/bin:/usr/bin:/etc:/sbin:/usr/sbin"; +#ifdef INCLUDE_TIMEZONE + strcpy(tz, "TZ="); + strcat(tz, tzone); + env[2] = tz; + env[3] = NULL; +#else + env[2] = NULL; +#endif + + prog = it->toks[0]; + if (*prog == '-' && *(prog+1)) + prog++; + execve(prog, it->toks, env); + strcpy(buf, it->toks[0]); + strcat(buf, " exec failed\n"); + err(buf); + _exit(1); + } +} + +static void init_itab(struct initline *p) { + bzero(p, sizeof(struct initline)); + p->pid = -1; + p->nextrun = time(NULL); +} + +static void clear_itab(struct initline *p) { + if (p->line) + free(p->line); + if (p->fullline) + free(p->fullline); + if (p->toks) + free(p->toks); + init_itab(p); +} + +void read_inittab(void) +{ + int i; + + /* + * free any old data and start again + */ + for (i = 0; i < numcmd; i++) + clear_itab(&inittab[i]); + numcmd = 0; + + /* Fake an inittab entry if boot console defined */ +#ifdef CONFIG_USER_INIT_CONSOLE_SH +#if LINUX_VERSION_CODE < 0x020100 + if (console_device && strcmp(console_device, "/dev/null")) +#else + if (have_console) +#endif + { + struct initline *p; + p = inittab + numcmd++; + init_itab(p); + p->fullline = strdup("console"); + strcpy(p->tty, "console"); + strcpy(p->termcap, "linux"); + add_tok(p, "-/bin/sh"); + } +#endif + + i = 0; + if (read_initfile(_PATH_INITTAB) == 0) + i++; + +#ifdef CONFIG_USER_FLATFSD_FLATFSD + if (read_initfile(_PATH_CONFIGTAB) == 0) + i++; +#endif + + if (i == 0) { + err("Failed to open " _PATH_INITTAB +#ifdef CONFIG_USER_FLATFSD_FLATFSD + " or " _PATH_CONFIGTAB +#endif + "." + ); + } + +#ifdef CONFIG_USER_INIT_CONF + load_init_conf(); +#endif + + /* if needed, shrink the array using realloc - + * must be done here so that we include the results of all init files + * when calculating number of commands */ + if ((numcmd + 2) < (inittab_size - NUMCMD)) { + /* round up from numcmd to the nearest multiple of NUMCMD */ + inittab_size = ((numcmd + 2) / NUMCMD + 1) * NUMCMD; + inittab = realloc(inittab, inittab_size * sizeof(struct initline)); + if (!inittab) { + /* failure case - what do you do if init fails? */ + err("malloc failed"); + _exit(1); + } + } + + if (numcmd == 0) + _exit(1); +} + +static int +read_initfile(const char *initfile) +{ + struct initline *p; + FILE *f; + char *buf = NULL; + size_t buf_len = 0; + int i,j,k; + char *ptr, *getty; +#ifdef SPECIAL_CONSOLE_TERM + char tty[50]; + struct stat stb; + char *termenv; + + termenv = getenv("TERM"); /* set by kernel */ +#endif + + i = numcmd; + + if (!(f = fopen(initfile, "r"))) + return 1; + + while(!feof(f)) { + if (i+2 == inittab_size) { + /* need to realloc inittab */ + inittab_size += NUMCMD; + inittab = realloc(inittab, inittab_size * sizeof(struct initline)); + if (!inittab) { + /* failure case - what do you do if init fails? */ + err("malloc failed"); + _exit(1); + } + } + if (getline(&buf, &buf_len, f) == -1) break; + + for(k = 0; k < buf_len && buf[k]; k++) { + if(buf[k] == '#') { + buf[k] = '\0'; break; + } + } + + if(buf[0] == '\0' || buf[0] == '\n') continue; + + p = inittab + i; + init_itab(p); + p->line = strdup(buf); + p->fullline = strdup(buf); + if (!p->line || !p->fullline) { + err("Not memory to allocate inittab entry"); + clear_itab(p); + continue; + } + ptr = strtok(p->line, ":"); + if (!ptr) { + err("Missing TTY/ID field in inittab"); + clear_itab(p); + continue; + } + strncpy(p->tty, ptr, 9); + //p->tty[9] = '\0'; + ptr = strtok(NULL, ":"); + if (!ptr) { + err("Missing TERMTYPE field in inittab"); + clear_itab(p); + continue; + } + strncpy(p->termcap, ptr, 29); + //p->termcap[29] = '\0'; + + getty = strtok(NULL, " \t\n"); + if (!getty) { + err("Missing PROCESS field in inittab"); + clear_itab(p); + continue; + } + add_tok(p, getty); + j = 1; + while((ptr = strtok(NULL, " \t\n"))) + add_tok(p, ptr); + +#ifdef SPECIAL_CONSOLE_TERM + /* special-case termcap for the console ttys */ + strcpy(tty, "/dev/"); + strcat(tty, p->tty); + if(!termenv || stat(tty, &stb) < 0) { + err("no TERM or cannot stat tty\n"); + } else { + /* is it a console tty? */ + if(major(stb.st_rdev) == 4 && minor(stb.st_rdev) < 64) { + strncpy(p->termcap, termenv, 30); + p->termcap[29] = 0; + } + } +#endif + + i++; + } + + if (buf) + free(buf); + + fclose(f); + + numcmd = i; + return 0; +} + +void hup_handler() +{ + reload = 1; +} + +void reload_inittab() +{ + int i; + int oldnum; + char ** saveline = (char **) malloc(inittab_size * sizeof(char *)); + pid_t * savepid = (pid_t*) malloc(inittab_size * sizeof(pid_t)); + + if (!saveline || !savepid) { + /* another failure case - what DO you do if init fails */ + err("malloc failed"); + _exit(1); + } + + for (i=0; i 1) + kill(savepid[i], SIGTERM); + free(saveline[i]); + } + + free(saveline); + free(savepid); +} + +void tstp_handler() +{ + stopped++; +} + +void cont_handler() +{ + stopped = 0; +} + +void int_handler() +{ + run_sigint_processing = 1; +} + +void sigint_processing() +{ + /* + * After Linux 0.96b PL1, we get a SIGINT when + * the user presses Ctrl-Alt-Del... + */ + + int pid; + + sync(); + sync(); + if((pid = vfork()) == 0) { + char *av[2]; + extern char **environ; + /* reboot properly... */ + av[0] = _PATH_REBOOT; + av[1] = NULL; + + execve(_PATH_REBOOT, av, environ); +#if __GNU_LIBRARY__ > 5 + reboot(0x1234567); +#else + reboot(0xfee1dead, 672274793, 0x1234567); +#endif + _exit(2); + } else if(pid < 0) { + /* fork failed, try the hard way... */ +#if __GNU_LIBRARY__ > 5 + reboot(0x1234567); +#else + reboot(0xfee1dead, 672274793, 0x1234567); +#endif + } +} + +#ifdef INCLUDE_TIMEZONE +void set_tz(void) +{ + FILE *f; + int len; + + if((f = fopen("/etc/config/TZ", "r")) == NULL && + (f = fopen("/etc/TZ", "r")) == NULL) + return; + fgets(tzone, BUF_SIZ-2, f); + fclose(f); + if((len=strlen(tzone)) < 2) + return; + tzone[len-1] = 0; /* get rid of the '\n' */ + setenv("TZ", tzone, 0); +} +#endif + +#ifdef CONFIG_USER_INIT_CONF +void load_init_conf(void) +{ + char line[BUF_SIZ]; + FILE *f; + + if ((f = fopen("/etc/config/init.conf", "r")) == NULL && + (f = fopen("/etc/init.conf", "r")) == NULL) + return; + while (fgets(line, sizeof(line) - 2, f)) { + if (strncasecmp(line, "delaytime=", 10) == 0) + delaytime = atoi(line + 10); + if (strncasecmp(line, "maxdelay=", 9) == 0) + maxdelay = atoi(line + 9); + if (strncasecmp(line, "maxspawn=", 9) == 0) + maxspawn = atoi(line + 9); + if (strncasecmp(line, "testtime=", 9) == 0) + testtime = atoi(line + 9); + } + fclose(f); +} +#endif + +void write_wtmp(void) +{ +#if 0 + int fd; + struct utmp ut; + + bzero((char *)&ut, sizeof(ut)); + strcpy(ut.ut_line, "~"); + bzero(ut.ut_name, sizeof(ut.ut_name)); + time(&ut.ut_time); + ut.ut_type = BOOT_TIME; + + if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND)) >= 0) { + flock(fd, LOCK_EX|LOCK_NB); /* make sure init won't hang */ + write(fd, (char *)&ut, sizeof(ut)); + flock(fd, LOCK_UN|LOCK_NB); + close(fd); + } +#endif +} + +void make_ascii_tty(void) +{ + struct termios tty; + const char *pt; + + if (tcgetattr(0, &tty) < 0) + return; + + tty.c_iflag &= ~(INLCR|IGNCR|IUCLC); + tty.c_iflag |= ICRNL; + tty.c_oflag &= ~(OCRNL|OLCUC|ONOCR|ONLRET|OFILL); + tty.c_oflag |= OPOST|ONLCR; + tty.c_cflag |= CLOCAL; + tty.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE; +#ifdef IEXTEN + tty.c_lflag |= IEXTEN; +#endif + +#if LINUX_VERSION_CODE < 0x020100 + if (console_baud != -1) + cfsetospeed(&tty, console_baud); +#endif + + tty.c_cc[VINTR] = CTRL('C'); + tty.c_cc[VQUIT] = CTRL('\\'); + tty.c_cc[VERASE] = CTRL('H'); /*127*/ + tty.c_cc[VKILL] = CTRL('U'); /*Changed from non-standard ^X*/ + tty.c_cc[VEOF] = CTRL('D'); + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 1; + tty.c_cc[VSTART] = CTRL('Q'); + tty.c_cc[VSTOP] = CTRL('S'); + tty.c_cc[VSUSP] = CTRL('Z'); +#ifdef VWERASE + tty.c_cc[VWERASE] = CTRL('W'); +#endif + /* Pick up simple environment setting of VERASE. + * Useful for setting on kernel command line. + * e.g. TTYERASE=^? + */ + pt = getenv("TTYERASE"); + if (pt && pt[0] == '^' && pt[1]) { + tty.c_cc[VERASE] = (pt[1] == '?') ? 127 : CTRL(pt[1]); + } + + tcsetattr(0, TCSANOW, &tty); +} + +void make_console(const char *tty) +{ + char devname[32]; + + close(0); close(1); close(2); + + if (tty && *tty) { +#if LINUX_VERSION_CODE < 0x020100 + /* + * until we get proper console support under 2.0 + */ + if (strcmp(tty, "console") == 0) { + strcpy(devname, console_device); + } + else +#endif + { + strcpy(devname, "/dev/"); + strcat(devname, tty); + } + + /* Try to open the specified console */ + if (open(devname, O_RDWR|O_NONBLOCK) >= 0) { + fcntl(0, F_SETFL, 0); + dup(0); + dup(0); + make_ascii_tty(); + ioctl(0, TIOCSCTTY, (char*)0); + return; + } + } + + /* No go, so send to /dev/null */ + open("/dev/null", O_RDWR|O_NONBLOCK); + dup(0); + dup(0); +} diff --git a/target/config/Config.in b/target/config/Config.in index 38f8090dd..3982b9cc9 100644 --- a/target/config/Config.in +++ b/target/config/Config.in @@ -16,6 +16,8 @@ config ADK_TARGET_TOOLCHAIN config ADK_TARGET_UCLINUX select ADK_TARGET_USE_STATIC_LIBS + select ADK_PACKAGE_SASH + select ADK_PACKAGE_SIMPLEINIT boolean config ADK_TARGET_QEMU diff --git a/target/config/Config.in.runtime b/target/config/Config.in.runtime index 845786a45..2caec15ec 100644 --- a/target/config/Config.in.runtime +++ b/target/config/Config.in.runtime @@ -150,7 +150,7 @@ config ADK_RUNTIME_KBD_LAYOUT choice prompt "initial login shell for the root user" -default ADK_ROOTSH_HUSH if ADK_TARGET_UCLINUX +default ADK_ROOTSH_SASH if ADK_TARGET_UCLINUX default ADK_ROOTSH_MKSH config ADK_ROOTSH_MKSH @@ -160,6 +160,12 @@ config ADK_ROOTSH_MKSH Use mksh (a Korn Shell variant) as standard login shell for the superuser. +config ADK_ROOTSH_SASH + select ADK_PACKAGE_SASH if !ADK_TOOLCHAIN_ONLY + bool "sash (Shell compatible with non-MMU systems)" + help + standalone shell. + config ADK_ROOTSH_HUSH select ADK_PACKAGE_HUSH if !ADK_TOOLCHAIN_ONLY bool "hush (Shell compatible with non-MMU systems)" @@ -197,7 +203,7 @@ endchoice choice prompt "system /bin/sh (POSIX script shell)" -default ADK_BINSH_HUSH if ADK_TARGET_UCLINUX +default ADK_BINSH_SASH if ADK_TARGET_UCLINUX default ADK_BINSH_MKSH config ADK_BINSH_MKSH @@ -207,6 +213,12 @@ config ADK_BINSH_MKSH Use mksh (a Korn Shell variant) as system shell, which is both small and powerful, so quite suited for this task. +config ADK_BINSH_SASH + select ADK_PACKAGE_SASH if !ADK_TOOLCHAIN_ONLY + bool "sash (Standalone Shell)" + help + hush shell. + config ADK_BINSH_HUSH select ADK_PACKAGE_HUSH if !ADK_TOOLCHAIN_ONLY bool "hush (busybox)" diff --git a/target/m68k/uclibc-ng.config b/target/m68k/uclibc-ng.config index c3225505d..2ca37cc90 100644 --- a/target/m68k/uclibc-ng.config +++ b/target/m68k/uclibc-ng.config @@ -54,9 +54,8 @@ UCLIBC_HAS_THREADS=y # PTHREADS_DEBUG_SUPPORT is not set UCLIBC_HAS_SYSLOG=y UCLIBC_HAS_LFS=y -MALLOC=y -# MALLOC_SIMPLE is not set -MALLOC_GLIBC_COMPAT=y +MALLOC_SIMPLE=y +# MALLOC_GLIBC_COMPAT is not set UCLIBC_HAS_OBSTACK=y UCLIBC_DYNAMIC_ATEXIT=y UCLIBC_SUSV2_LEGACY=y diff --git a/target/m68k/uclibc.config b/target/m68k/uclibc.config index 54e6f6322..2612dfe40 100644 --- a/target/m68k/uclibc.config +++ b/target/m68k/uclibc.config @@ -1,19 +1,32 @@ # -# Automatically generated file; DO NOT EDIT. -# uClibc-ng 1.0.0 C Library Configuration +# Automatically generated make config: don't edit +# Version: 0.9.33.2 +# Mon Aug 18 18:48:15 2014 # # TARGET_alpha is not set -# TARGET_arc is not set # TARGET_arm is not set +# TARGET_avr32 is not set # TARGET_bfin is not set +# TARGET_c6x is not set +# TARGET_cris is not set +# TARGET_e1 is not set +# TARGET_frv is not set +# TARGET_h8300 is not set +# TARGET_hppa is not set # TARGET_i386 is not set +# TARGET_i960 is not set +# TARGET_ia64 is not set TARGET_m68k=y -# TARGET_metag is not set # TARGET_microblaze is not set # TARGET_mips is not set +# TARGET_nios is not set +# TARGET_nios2 is not set # TARGET_powerpc is not set # TARGET_sh is not set +# TARGET_sh64 is not set # TARGET_sparc is not set +# TARGET_v850 is not set +# TARGET_vax is not set # TARGET_x86_64 is not set # TARGET_xtensa is not set @@ -23,58 +36,48 @@ TARGET_m68k=y TARGET_ARCH="m68k" FORCE_OPTIONS_FOR_ARCH=y TARGET_SUBARCH="" - -# -# Using ELF file format -# -ARCH_HAS_DEPRECATED_SYSCALLS=y +# UCLIBC_FORMAT_ELF is not set +# UCLIBC_FORMAT_FDPIC_ELF is not set +# UCLIBC_FORMAT_DSBT_ELF is not set +# UCLIBC_FORMAT_FLAT is not set +UCLIBC_FORMAT_FLAT_SEP_DATA=y +# UCLIBC_FORMAT_SHARED_FLAT is not set ARCH_BIG_ENDIAN=y # # Using Big Endian # -ARCH_HAS_MMU=y -ARCH_USE_MMU=y +# ARCH_HAS_MMU is not set UCLIBC_HAS_FLOATS=y -UCLIBC_HAS_FPU=y +# UCLIBC_HAS_FPU is not set +UCLIBC_HAS_SOFT_FLOAT=y DO_C99_MATH=y # DO_XSI_MATH is not set UCLIBC_HAS_FENV=y UCLIBC_HAS_LONG_DOUBLE_MATH=y KERNEL_HEADERS="" +UCLIBC_UCLINUX_BROKEN_MUNMAP=y HAVE_DOT_CONFIG=y # # General Library Settings # DOPIC=y -HAVE_SHARED=y -# FORCE_SHAREABLE_TEXT_SEGMENTS is not set -LDSO_LDD_SUPPORT=y -LDSO_CACHE_SUPPORT=y -LDSO_PRELOAD_ENV_SUPPORT=y -# LDSO_PRELOAD_FILE_SUPPORT is not set -LDSO_BASE_FILENAME="ld.so" -# LDSO_STANDALONE_SUPPORT is not set -# LDSO_PRELINK_SUPPORT is not set -UCLIBC_STATIC_LDCONFIG=y -LDSO_RUNPATH=y -LDSO_SAFE_RUNPATH=y -LDSO_SEARCH_INTERP_PATH=y -LDSO_LD_LIBRARY_PATH=y -# LDSO_NO_CLEANUP is not set -# LDSO_GNU_HASH_SUPPORT is not set +ARCH_HAS_NO_SHARED=y +ARCH_HAS_NO_LDSO=y +UCLIBC_CTOR_DTOR=y HAS_NO_THREADS=y +# LINUXTHREADS_OLD is not set +# LINUXTHREADS_NEW is not set # UCLIBC_HAS_THREADS_NATIVE is not set UCLIBC_HAS_SYSLOG=y UCLIBC_HAS_LFS=y -# MALLOC is not set +MALLOC=y # MALLOC_SIMPLE is not set -MALLOC_STANDARD=y +# MALLOC_STANDARD is not set MALLOC_GLIBC_COMPAT=y -UCLIBC_HAS_OBSTACK=y UCLIBC_DYNAMIC_ATEXIT=y -UCLIBC_SUSV2_LEGACY=y +# COMPAT_ATEXIT is not set UCLIBC_SUSV3_LEGACY=y # UCLIBC_SUSV3_LEGACY_MACROS is not set UCLIBC_SUSV4_LEGACY=y @@ -104,6 +107,8 @@ UCLIBC_GRP_BUFFER_SIZE=256 # # Support various families of functions # +UCLIBC_LINUX_MODULE_26=y +# UCLIBC_LINUX_MODULE_24 is not set UCLIBC_LINUX_SPECIFIC=y UCLIBC_HAS_GNU_ERROR=y UCLIBC_BSD_SPECIFIC=y @@ -125,6 +130,7 @@ UCLIBC_HAS_NETWORK_SUPPORT=y UCLIBC_HAS_SOCKET=y UCLIBC_HAS_IPV4=y UCLIBC_HAS_IPV6=y +# UCLIBC_HAS_RPC is not set UCLIBC_USE_NETLINK=y UCLIBC_SUPPORT_AI_ADDRCONFIG=y UCLIBC_HAS_BSD_RES_CLOSE=y @@ -149,6 +155,8 @@ UCLIBC_HAS_WCHAR=y UCLIBC_HAS_HEXADECIMAL_FLOATS=y UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9 +# UCLIBC_HAS_SCANF_GLIBC_A_FLAG is not set +# UCLIBC_HAS_STDIO_BUFSIZ_NONE is not set # UCLIBC_HAS_STDIO_BUFSIZ_256 is not set # UCLIBC_HAS_STDIO_BUFSIZ_512 is not set # UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set @@ -178,7 +186,9 @@ UCLIBC_HAS_GNU_GETSUBOPT=y # Big and Tall # UCLIBC_HAS_REGEX=y +# UCLIBC_HAS_REGEX_OLD is not set UCLIBC_HAS_FNMATCH=y +# UCLIBC_HAS_FNMATCH_OLD is not set UCLIBC_HAS_WORDEXP=y UCLIBC_HAS_NFTW=y UCLIBC_HAS_FTW=y @@ -199,10 +209,7 @@ HARDWIRED_ABSPATH=y # Security options # UCLIBC_HAS_ARC4RANDOM=y -# ARC4RANDOM_USES_NODEV is not set # UCLIBC_HAS_SSP is not set -UCLIBC_BUILD_RELRO=y -# UCLIBC_BUILD_NOW is not set UCLIBC_BUILD_NOEXECSTACK=y # @@ -213,10 +220,8 @@ UCLIBC_EXTRA_CFLAGS="" # DODEBUG is not set # DOSTRIP is not set # DOASSERTS is not set -# SUPPORT_LD_DEBUG is not set -# SUPPORT_LD_DEBUG_EARLY is not set # UCLIBC_MALLOC_DEBUGGING is not set -# UCLIBC_HAS_BACKTRACE is not set WARNINGS="-Wall" EXTRA_WARNINGS=y # DOMULTI is not set +# UCLIBC_MJN3_ONLY is not set -- cgit v1.2.3