mirror of
https://github.com/troglobit/finit.git
synced 2026-11-06 15:51:03 +00:00
Fix I/O plugin watcher, load plugins earlier to enable a new early hook!
Restructure start by calling the plugin loader earlier. This makes it
possible to run hooks even earlier. This also adds a new hook:
HOOK_ROOTFS_UP which runs as soon as the system root (/) is available.
Another very notable change is the slow refactor of helpers.c into a finit
helper library called libite.so (-lite). This is a light-weight
Also, lots of misc. fixes all over the place. Signal handling still really
needs to be looked into once more!
Makefile:
Add dependency handling for parallell build
Add libite library
ChangeLog:
Update with new 1.4 release. There is a lot of fixes!
libite/:
Collection of utility functions and C library extensions for
finit & its plugins
reboot.c:
New reboot tool. Simply sends SIGINT to PID 1
finit.h:
Cleanup old LISTEN_INITCTL define, code is in an optional plugin now
finit.c:
Let mdev/udev run *after* cls()
Add useful debug statement for /proc/cmdline
Earlier plugin load => new early hook point
Show OK/FAIL for total plugin load, not for each plugin => speedup
helpers.h:
Rename syslog macros to prevent common name clashes (DEBUG/ERROR)
Add __FILE__ to _e(), _d() and _pe() macros
helpers.c:
In ifconfig() the addr and mask arguments are now optional
The copyfile() has been moved to libite.so
Temporarily remove const directive from some functions to build
Use DFLSIG() macro in run_getty() to simplify code
plugin.h:
Add new HOOK_ROOTFS_UP hook
plugin.c:
Fix init_plugins() to actually register the plugin's I/O fd
Skip verbose listing of all plugins in plugin_load_all()
svc.c:
svc_start(): Dito
plugins/Makefile:
Inherit CFLAGS and LDFLAGS, but make sure to filter out -rdynamic
from LDFLAGS, it's used by the daemon, only
plugins/initctl.c:
New includes after helpers.h refactor
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
1 parent
c002b5301f
commit
65c9e7ebc6
22 files changed
+1324
-111
No files matched your search
@@ -1,3 +1,15 @@
|
|||||||
|
1.4 (20121002)
|
||||||
|
- Fix I/O plugin watcher and load plugins earlier for a new hook
|
||||||
|
- Start refactoring helpers.c into a libite.so (-lite). This
|
||||||
|
means other user space applications/daemons can make use of
|
||||||
|
the neat toolbox available in finit
|
||||||
|
- Use short-form -s/-w -u to work with BusyBox hwclock as well
|
||||||
|
- Use RTLD_GLOBAL flag to tell dynamic loader to load dependent
|
||||||
|
.so files as well. Lets other plugins use global symbols.
|
||||||
|
- Greatly simplify svc hook for external plugins and cleanup
|
||||||
|
the plugin API.
|
||||||
|
- And more... see the GIT log for more details.
|
||||||
|
|
||||||
1.3 (20120928)
|
1.3 (20120928)
|
||||||
- Cleanup public plugin API a bit and add new pid/pidfile funcs
|
- Cleanup public plugin API a bit and add new pid/pidfile funcs
|
||||||
- Add plugin hook to end of service startup
|
- Add plugin hook to end of service startup
|
||||||
|
|||||||
@@ -26,14 +26,15 @@
|
|||||||
uninstall-exec uninstall-data uninstall-dev
|
uninstall-exec uninstall-data uninstall-dev
|
||||||
|
|
||||||
# Top directory for building complete system, fall back to this directory
|
# Top directory for building complete system, fall back to this directory
|
||||||
ROOTDIR ?= $(shell pwd)
|
ROOTDIR = $(shell pwd)
|
||||||
|
|
||||||
#VERSION ?= $(shell git tag -l | tail -1)
|
#VERSION ?= $(shell git tag -l | tail -1)
|
||||||
VERSION ?= 1.4
|
VERSION ?= 1.4
|
||||||
EXEC = finit
|
NAME = finit
|
||||||
PKG = $(EXEC)-$(VERSION)
|
PKG = $(NAME)-$(VERSION)
|
||||||
DEV = $(EXEC)-dev
|
DEV = $(NAME)-dev
|
||||||
ARCHIVE = $(PKG).tar.xz
|
ARCHIVE = $(PKG).tar.xz
|
||||||
|
EXEC = finit reboot
|
||||||
HEADERS = plugin.h svc.h helpers.h
|
HEADERS = plugin.h svc.h helpers.h
|
||||||
DISTFILES = LICENSE README ChangeLog finit.conf services
|
DISTFILES = LICENSE README ChangeLog finit.conf services
|
||||||
OBJS = finit.o conf.o helpers.o sig.o svc.o plugin.o
|
OBJS = finit.o conf.o helpers.o sig.o svc.o plugin.o
|
||||||
@@ -45,7 +46,8 @@ DEPS = $(addprefix .,$(SRCS:.c=.d))
|
|||||||
prefix ?= /usr
|
prefix ?= /usr
|
||||||
sysconfdir ?= /etc
|
sysconfdir ?= /etc
|
||||||
sbindir ?= /sbin
|
sbindir ?= /sbin
|
||||||
plugindir ?= /lib/finit/plugins
|
libdir ?= /lib
|
||||||
|
plugindir ?= $(libdir)/finit/plugins
|
||||||
incdir = $(prefix)/include/finit
|
incdir = $(prefix)/include/finit
|
||||||
datadir = $(prefix)/share/doc/finit
|
datadir = $(prefix)/share/doc/finit
|
||||||
mandir = $(prefix)/share/man/man8
|
mandir = $(prefix)/share/man/man8
|
||||||
@@ -58,22 +60,28 @@ FINIT_RCSD ?= $(sysconfdir)/finit.d
|
|||||||
CFLAGS += -W -Wall -Werror -Os
|
CFLAGS += -W -Wall -Werror -Os
|
||||||
# Disable annoying gcc warning for "warn_unused_result", see GIT 37af997
|
# Disable annoying gcc warning for "warn_unused_result", see GIT 37af997
|
||||||
CPPFLAGS += -U_FORTIFY_SOURCE
|
CPPFLAGS += -U_FORTIFY_SOURCE
|
||||||
CPPFLAGS += -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE
|
CPPFLAGS += -Ilibite -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE
|
||||||
CPPFLAGS += -DVERSION=\"$(VERSION)\" -DWHOAMI=\"`whoami`@`hostname`\"
|
CPPFLAGS += -DVERSION=\"$(VERSION)\" -DWHOAMI=\"`whoami`@`hostname`\"
|
||||||
CPPFLAGS += -DFINIT_FIFO=\"$(FINIT_FIFO)\" -DFINIT_CONF=\"$(FINIT_CONF)\"
|
CPPFLAGS += -DFINIT_FIFO=\"$(FINIT_FIFO)\" -DFINIT_CONF=\"$(FINIT_CONF)\"
|
||||||
CPPFLAGS += -DFINIT_RCSD=\"$(FINIT_RCSD)\" -DPLUGIN_PATH=\"$(plugindir)\"
|
CPPFLAGS += -DFINIT_RCSD=\"$(FINIT_RCSD)\" -DPLUGIN_PATH=\"$(plugindir)\"
|
||||||
LDFLAGS += -rdynamic
|
LDFLAGS += -rdynamic -L$(ROOTDIR)/libite
|
||||||
LDLIBS += -ldl
|
DEPLIBS = libite/libite.so
|
||||||
|
LDLIBS += -ldl -lite
|
||||||
|
|
||||||
include common.mk
|
include common.mk
|
||||||
export plugindir ROOTDIR CPPFLAGS
|
export libdir plugindir incdir ROOTDIR CPPFLAGS LDFLAGS LDLIBS
|
||||||
|
|
||||||
all: Makefile $(EXEC)
|
all: $(DEPLIBS) $(EXEC)
|
||||||
$(MAKE) -C plugins $@
|
$(MAKE) -C plugins $@
|
||||||
|
|
||||||
|
$(DEPLIBS): Makefile
|
||||||
|
$(MAKE) -C libite all
|
||||||
|
|
||||||
$(OBJS): Makefile
|
$(OBJS): Makefile
|
||||||
|
|
||||||
$(EXEC): $(OBJS)
|
finit: $(OBJS) $(DEPLIBS)
|
||||||
|
|
||||||
|
reboot: reboot.o $(DEPLIBS)
|
||||||
|
|
||||||
install-exec: all
|
install-exec: all
|
||||||
@$(INSTALL) -d $(DESTDIR)$(FINIT_RCSD)
|
@$(INSTALL) -d $(DESTDIR)$(FINIT_RCSD)
|
||||||
@@ -82,6 +90,7 @@ install-exec: all
|
|||||||
printf " INSTALL $(DESTDIR)$(sbindir)/$$file\n"; \
|
printf " INSTALL $(DESTDIR)$(sbindir)/$$file\n"; \
|
||||||
$(STRIPINST) $$file $(DESTDIR)$(sbindir)/$$file; \
|
$(STRIPINST) $$file $(DESTDIR)$(sbindir)/$$file; \
|
||||||
done
|
done
|
||||||
|
$(MAKE) -C libite install-exec
|
||||||
$(MAKE) -C plugins install
|
$(MAKE) -C plugins install
|
||||||
|
|
||||||
install-data:
|
install-data:
|
||||||
@@ -98,6 +107,7 @@ install-dev:
|
|||||||
printf " INSTALL $(DESTDIR)$(incdir)/$$file\n"; \
|
printf " INSTALL $(DESTDIR)$(incdir)/$$file\n"; \
|
||||||
$(INSTALL) -m 0644 $$file $(DESTDIR)$(incdir)/$$file; \
|
$(INSTALL) -m 0644 $$file $(DESTDIR)$(incdir)/$$file; \
|
||||||
done
|
done
|
||||||
|
$(MAKE) -C libite install-dev install-exec
|
||||||
|
|
||||||
install: install-exec install-data install-dev
|
install: install-exec install-data install-dev
|
||||||
|
|
||||||
@@ -108,6 +118,7 @@ uninstall-exec:
|
|||||||
done
|
done
|
||||||
-@rmdir $(DESTDIR)$(sbindir) 2>/dev/null
|
-@rmdir $(DESTDIR)$(sbindir) 2>/dev/null
|
||||||
-@rmdir $(DESTDIR)$(FINIT_RCSD) 2>/dev/null
|
-@rmdir $(DESTDIR)$(FINIT_RCSD) 2>/dev/null
|
||||||
|
$(MAKE) -C libite uninstall
|
||||||
$(MAKE) -C plugins uninstall
|
$(MAKE) -C plugins uninstall
|
||||||
|
|
||||||
uninstall-data:
|
uninstall-data:
|
||||||
@@ -119,20 +130,18 @@ uninstall-data:
|
|||||||
-@rmdir $(DESTDIR)$(datadir)
|
-@rmdir $(DESTDIR)$(datadir)
|
||||||
|
|
||||||
uninstall-dev:
|
uninstall-dev:
|
||||||
-@for file in $(HEADERS); do \
|
-@$(RM) -rf $(DESTDIR)$(incdir)
|
||||||
printf " REMOVE $(DESTDIR)$(incdir)/$$file\n"; \
|
|
||||||
rm $(DESTDIR)$(incdir)/$$file 2>/dev/null; \
|
|
||||||
done
|
|
||||||
-@rmdir $(DESTDIR)$(incdir)
|
|
||||||
|
|
||||||
uninstall: uninstall-exec uninstall-data uninstall-dev
|
uninstall: uninstall-exec uninstall-data uninstall-dev
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-@$(RM) $(OBJS) $(DEPS) $(EXEC)
|
-@$(RM) $(OBJS) $(DEPS) $(EXEC)
|
||||||
|
$(MAKE) -C libite $@
|
||||||
$(MAKE) -C plugins $@
|
$(MAKE) -C plugins $@
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
-@$(RM) $(JUNK) unittest *.o
|
-@$(RM) $(JUNK) unittest *.o .*.d
|
||||||
|
$(MAKE) -C libite $@
|
||||||
$(MAKE) -C plugins $@
|
$(MAKE) -C plugins $@
|
||||||
|
|
||||||
dist:
|
dist:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
JUNK = *~ *.bak *.aux *.dvi *.idx *.ind *.log *.ps *.map .*.d DEADJOE semantic.cache *.gdb *.elf core core.*
|
JUNK = *~ *.bak *.aux *.dvi *.idx *.ind *.log *.ps *.map .*.d DEADJOE semantic.cache *.gdb *.elf core core.*
|
||||||
MAKE := @$(MAKE)
|
MAKE := @$(MAKE)
|
||||||
MAKEFLAGS = --no-print-directory --silent
|
MAKEFLAGS = --no-print-directory --silent
|
||||||
INSTALL := install -b
|
INSTALL := install --backup=off
|
||||||
STRIPINST := $(INSTALL) -s --strip-program=$(CROSS)strip -m 0755
|
STRIPINST := $(INSTALL) -s --strip-program=$(CROSS)strip -m 0755
|
||||||
|
|
||||||
# Smart autodependecy generation via GCC -M.
|
# Smart autodependecy generation via GCC -M.
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ static void parse_kernel_cmdline(void)
|
|||||||
|
|
||||||
if ((fp = fopen("/proc/cmdline", "r")) != NULL) {
|
if ((fp = fopen("/proc/cmdline", "r")) != NULL) {
|
||||||
fgets(line, sizeof(line), fp);
|
fgets(line, sizeof(line), fp);
|
||||||
|
_d("Kernel command line: %s", line);
|
||||||
|
|
||||||
if (strstr(line, "finit_debug") || strstr(line, "--debug"))
|
if (strstr(line, "finit_debug") || strstr(line, "--debug"))
|
||||||
debug = 1;
|
debug = 1;
|
||||||
@@ -91,15 +92,6 @@ int main(int UNUSED(args), char *argv[])
|
|||||||
mount("none", "/dev/shm", "tmpfs", 0, NULL);
|
mount("none", "/dev/shm", "tmpfs", 0, NULL);
|
||||||
umask(022);
|
umask(022);
|
||||||
|
|
||||||
/*
|
|
||||||
* Populate /dev and prepare for runtime events from kernel.
|
|
||||||
*/
|
|
||||||
#if defined(USE_UDEV)
|
|
||||||
run_interactive("udevd --daemon", "Populating device tree");
|
|
||||||
#elif defined (MDEV)
|
|
||||||
run_interactive(MDEV "-s", "Populating device tree");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse kernel parameters
|
* Parse kernel parameters
|
||||||
*/
|
*/
|
||||||
@@ -108,11 +100,28 @@ int main(int UNUSED(args), char *argv[])
|
|||||||
cls();
|
cls();
|
||||||
echo("finit " VERSION " (built " __DATE__ " " __TIME__ " by " WHOAMI ")");
|
echo("finit " VERSION " (built " __DATE__ " " __TIME__ " by " WHOAMI ")");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Populate /dev and prepare for runtime events from kernel.
|
||||||
|
*/
|
||||||
|
#if defined(USE_UDEV)
|
||||||
|
run_interactive("udevd --daemon", "Populating device tree");
|
||||||
|
#elif defined (MDEV)
|
||||||
|
run_interactive(MDEV " -s", "Populating device tree");
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse configuration file
|
* Parse configuration file
|
||||||
*/
|
*/
|
||||||
parse_finit_conf(FINIT_CONF);
|
parse_finit_conf(FINIT_CONF);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load plugins. Must run after finit.conf has registered
|
||||||
|
* all services, or service plugins won't have anything to
|
||||||
|
* hook on to.
|
||||||
|
*/
|
||||||
|
print_desc("", "Loading plugins");
|
||||||
|
print_result(plugin_load_all(PLUGIN_PATH));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mount filesystems
|
* Mount filesystems
|
||||||
*/
|
*/
|
||||||
@@ -124,6 +133,9 @@ int main(int UNUSED(args), char *argv[])
|
|||||||
#ifdef SYSROOT
|
#ifdef SYSROOT
|
||||||
run(SYSROOT, "/", NULL, MS_MOVE, NULL);
|
run(SYSROOT, "/", NULL, MS_MOVE, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
_d("Root FS up, calling hooks ...");
|
||||||
|
plugin_run_hooks(HOOK_ROOTFS_UP);
|
||||||
|
|
||||||
umask(0);
|
umask(0);
|
||||||
run("/bin/mount -na");
|
run("/bin/mount -na");
|
||||||
run("/sbin/swapon -ea");
|
run("/sbin/swapon -ea");
|
||||||
@@ -137,13 +149,7 @@ int main(int UNUSED(args), char *argv[])
|
|||||||
*/
|
*/
|
||||||
sig_setup();
|
sig_setup();
|
||||||
|
|
||||||
/*
|
_d("Base FS up, calling hooks ...");
|
||||||
* Load plugins and run first level hooks.
|
|
||||||
*/
|
|
||||||
_d("Loading plugins ...");
|
|
||||||
plugin_load_all(PLUGIN_PATH);
|
|
||||||
|
|
||||||
_d("Running first level hooks ...");
|
|
||||||
plugin_run_hooks(HOOK_BASEFS_UP);
|
plugin_run_hooks(HOOK_BASEFS_UP);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -39,14 +39,12 @@
|
|||||||
# define CONSOLE "/dev/console"
|
# define CONSOLE "/dev/console"
|
||||||
# define MDEV "/sbin/mdev"
|
# define MDEV "/sbin/mdev"
|
||||||
# define GETTY "/sbin/getty -L 115200 ttyS0 vt100"
|
# define GETTY "/sbin/getty -L 115200 ttyS0 vt100"
|
||||||
# define LISTEN_INITCTL
|
|
||||||
#else /* Debian/Ubuntu based distributions */
|
#else /* Debian/Ubuntu based distributions */
|
||||||
# define RANDOMSEED "/var/lib/urandom/random-seed"
|
# define RANDOMSEED "/var/lib/urandom/random-seed"
|
||||||
# define CONSOLE "/dev/tty1"
|
# define CONSOLE "/dev/tty1"
|
||||||
# define GETTY "/sbin/getty -8 38400 tty1"
|
# define GETTY "/sbin/getty -8 38400 tty1"
|
||||||
# define REMOUNT_ROOTFS_RW
|
# define REMOUNT_ROOTFS_RW
|
||||||
# define RUNLEVEL 2
|
# define RUNLEVEL 2
|
||||||
# define LISTEN_INITCTL
|
|
||||||
# define USE_UDEV
|
# define USE_UDEV
|
||||||
# define USE_MESSAGE_BUS
|
# define USE_MESSAGE_BUS
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
|
#include "lite.h"
|
||||||
|
|
||||||
#define NUM_ARGS 16
|
#define NUM_ARGS 16
|
||||||
#define NUM_SCRIPTS 128 /* ought to be enough for anyone */
|
#define NUM_SCRIPTS 128 /* ought to be enough for anyone */
|
||||||
@@ -93,10 +94,14 @@ void ifconfig(char *ifname, char *addr, char *mask, int up)
|
|||||||
ifr.ifr_addr.sa_family = AF_INET;
|
ifr.ifr_addr.sa_family = AF_INET;
|
||||||
|
|
||||||
if (up) {
|
if (up) {
|
||||||
inet_aton(addr, &a->sin_addr);
|
if (addr) {
|
||||||
ioctl(sock, SIOCSIFADDR, &ifr);
|
inet_aton(addr, &a->sin_addr);
|
||||||
inet_aton(mask, &a->sin_addr);
|
ioctl(sock, SIOCSIFADDR, &ifr);
|
||||||
ioctl(sock, SIOCSIFNETMASK, &ifr);
|
}
|
||||||
|
if (mask) {
|
||||||
|
inet_aton(mask, &a->sin_addr);
|
||||||
|
ioctl(sock, SIOCSIFNETMASK, &ifr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ioctl(sock, SIOCGIFFLAGS, &ifr);
|
ioctl(sock, SIOCGIFFLAGS, &ifr);
|
||||||
@@ -112,30 +117,6 @@ void ifconfig(char *ifname, char *addr, char *mask, int up)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void copyfile(char *src, char *dst, int size)
|
|
||||||
{
|
|
||||||
char buffer[BUF_SIZE];
|
|
||||||
int s, d, n;
|
|
||||||
|
|
||||||
/* Size == 0 means copy entire file */
|
|
||||||
if (size == 0)
|
|
||||||
size = INT_MAX;
|
|
||||||
|
|
||||||
if ((s = open(src, O_RDONLY)) >= 0) {
|
|
||||||
if ((d = open(dst, O_WRONLY | O_CREAT, 0644)) >= 0) {
|
|
||||||
do {
|
|
||||||
int csize = size > BUF_SIZE ? BUF_SIZE : size;
|
|
||||||
|
|
||||||
if ((n = read(s, buffer, csize)) > 0)
|
|
||||||
write(d, buffer, n);
|
|
||||||
size -= csize;
|
|
||||||
} while (size > 0 && n == BUF_SIZE);
|
|
||||||
close(d);
|
|
||||||
}
|
|
||||||
close(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pidfile_read - Reads a PID value from a pidfile.
|
* pidfile_read - Reads a PID value from a pidfile.
|
||||||
* @pidfile: File containing PID, usually in /var/run/<PROC>.pid
|
* @pidfile: File containing PID, usually in /var/run/<PROC>.pid
|
||||||
@@ -148,7 +129,7 @@ void copyfile(char *src, char *dst, int size)
|
|||||||
* be translated this function returns zero (0), on success this function returns
|
* be translated this function returns zero (0), on success this function returns
|
||||||
* a PID value greater than one. PID 1 is reserved for the system init process.
|
* a PID value greater than one. PID 1 is reserved for the system init process.
|
||||||
*/
|
*/
|
||||||
pid_t pidfile_read(const char *pidfile)
|
pid_t pidfile_read(char *pidfile)
|
||||||
{
|
{
|
||||||
pid_t pid = 0;
|
pid_t pid = 0;
|
||||||
char buf[16];
|
char buf[16];
|
||||||
@@ -189,7 +170,7 @@ pid_t pidfile_read(const char *pidfile)
|
|||||||
* Returns:
|
* Returns:
|
||||||
* The PID read from @path, or zero on timeout.
|
* The PID read from @path, or zero on timeout.
|
||||||
*/
|
*/
|
||||||
pid_t pidfile_poll(char *cmd, const char *path)
|
pid_t pidfile_poll(char *cmd, char *path)
|
||||||
{
|
{
|
||||||
pid_t pid = 0;
|
pid_t pid = 0;
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
@@ -275,7 +256,7 @@ char *pid_get_name(pid_t pid, char *name, size_t len)
|
|||||||
* @name: New name of process
|
* @name: New name of process
|
||||||
* @args: The process' argv[] vector.
|
* @args: The process' argv[] vector.
|
||||||
*/
|
*/
|
||||||
void procname_set(const char *name, char *args[])
|
void procname_set(char *name, char *args[])
|
||||||
{
|
{
|
||||||
size_t len = strlen(args[0]) + 1; /* Include terminating '\0' */
|
size_t len = strlen(args[0]) + 1; /* Include terminating '\0' */
|
||||||
|
|
||||||
@@ -296,7 +277,7 @@ void procname_set(const char *name, char *args[])
|
|||||||
* Returns:
|
* Returns:
|
||||||
* Number of signals sent, i.e. number of processes who have received the signal.
|
* Number of signals sent, i.e. number of processes who have received the signal.
|
||||||
*/
|
*/
|
||||||
int procname_kill (const char *name, int signo)
|
int procname_kill (char *name, int signo)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
char path[32], line[64];
|
char path[32], line[64];
|
||||||
@@ -327,7 +308,7 @@ int procname_kill (const char *name, int signo)
|
|||||||
int error = errno;
|
int error = errno;
|
||||||
|
|
||||||
if (kill(atoi(entry->d_name), signo)) {
|
if (kill(atoi(entry->d_name), signo)) {
|
||||||
ERROR("Failed signalling(%d) %s: %s!", signo, name, strerror(error));
|
FLOG_ERROR("Failed signalling(%d) %s: %s!", signo, name, strerror(error));
|
||||||
} else {
|
} else {
|
||||||
result++; /* Track number of processes we deliver the signal to. */
|
result++; /* Track number of processes we deliver the signal to. */
|
||||||
}
|
}
|
||||||
@@ -547,15 +528,13 @@ pid_t run_getty(char *cmd, char *argv[])
|
|||||||
if (open(CONSOLE, O_RDWR) != 0)
|
if (open(CONSOLE, O_RDWR) != 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
sigemptyset(&sa.sa_mask);
|
|
||||||
sa.sa_handler = SIG_DFL;
|
|
||||||
|
|
||||||
sigemptyset(&nmask);
|
sigemptyset(&nmask);
|
||||||
sigaddset(&nmask, SIGCHLD);
|
sigaddset(&nmask, SIGCHLD);
|
||||||
sigprocmask(SIG_UNBLOCK, &nmask, NULL);
|
sigprocmask(SIG_UNBLOCK, &nmask, NULL);
|
||||||
|
|
||||||
for (i = 1; i < NSIG; i++)
|
/* Reset signal handlers that were set by the parent process */
|
||||||
sigaction(i, &sa, NULL);
|
for (i = 1; i < NSIG; i++)
|
||||||
|
DFLSIG(sa, i, 0);
|
||||||
|
|
||||||
dup2(0, STDIN_FILENO);
|
dup2(0, STDIN_FILENO);
|
||||||
dup2(0, STDOUT_FILENO);
|
dup2(0, STDOUT_FILENO);
|
||||||
|
|||||||
@@ -27,17 +27,18 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h> /* access() */
|
|
||||||
|
|
||||||
#define DO_LOG(level, fmt, args...) \
|
#define DO_LOG(level, fmt, args...) \
|
||||||
{ \
|
{ \
|
||||||
openlog("finit", LOG_CONS | LOG_PID, LOG_DAEMON); \
|
openlog("finit", LOG_CONS | LOG_PID, LOG_DAEMON); \
|
||||||
syslog(LOG_DEBUG, fmt, ##args); \
|
syslog(level, fmt, ##args); \
|
||||||
closelog(); \
|
closelog(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEBUG(fmt, args...) DO_LOG(LOG_DEBUG, fmt, ##args)
|
#define FLOG_DEBUG(fmt, args...) DO_LOG(LOG_DEBUG, fmt, ##args)
|
||||||
#define ERROR(fmt, args...) DO_LOG(LOG_CRIT, fmt, ##args)
|
#define FLOG_ERROR(fmt, args...) DO_LOG(LOG_CRIT, fmt, ##args)
|
||||||
|
#define FLOG_PERROR(fmt, args...) DO_LOG(LOG_CRIT, fmt ". Error %d: %s", ##args, errno, strerror(errno))
|
||||||
|
|
||||||
|
|
||||||
#ifndef touch
|
#ifndef touch
|
||||||
# define touch(x) mknod((x), S_IFREG|0644, 0)
|
# define touch(x) mknod((x), S_IFREG|0644, 0)
|
||||||
@@ -48,34 +49,30 @@
|
|||||||
#ifndef blkdev
|
#ifndef blkdev
|
||||||
# define blkdev(x,m,maj,min) mknod((x), S_IFBLK|(m), makedev((maj),(min)))
|
# define blkdev(x,m,maj,min) mknod((x), S_IFBLK|(m), makedev((maj),(min)))
|
||||||
#endif
|
#endif
|
||||||
#ifndef fexist
|
|
||||||
# define fexist(x) (access(x, F_OK) != -1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef UNUSED
|
#ifndef UNUSED
|
||||||
#define UNUSED(x) UNUSED_ ## x __attribute__ ((unused))
|
#define UNUSED(x) UNUSED_ ## x __attribute__ ((unused))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define echo(fmt, args...) do { if (verbose) { fprintf(stderr, fmt "\n", ##args); } } while (0)
|
#define echo(fmt, args...) do { if (verbose) { fprintf(stderr, fmt "\n", ##args); } } while (0)
|
||||||
#define _d(fmt, args...) do { if (debug) { fprintf(stderr, "finit:%s() - " fmt "\n", __func__, ##args); } } while (0)
|
#define _d(fmt, args...) do { if (debug) { fprintf(stderr, "finit:%s() - " fmt "\n", __func__, ##args); } } while (0)
|
||||||
#define _e(fmt, args...) do { fprintf(stderr, "finit:%s() - " fmt "\n", __func__, ##args); } while (0)
|
#define _e(fmt, args...) do { fprintf(stderr, "finit:%s:%s() - " fmt "\n", __FILE__, __func__, ##args); } while (0)
|
||||||
#define _pe(fmt, args...) do { fprintf(stderr, "finit:%s() - " fmt ". Error %d: %s\n", __func__, ##args, errno, strerror(errno)); } while (0)
|
#define _pe(fmt, args...) do { fprintf(stderr, "finit:%s:%s() - " fmt ". Error %d: %s\n", __FILE__, __func__, ##args, errno, strerror(errno)); } while (0)
|
||||||
|
|
||||||
extern int debug;
|
extern int debug;
|
||||||
extern int verbose;
|
extern int verbose;
|
||||||
|
|
||||||
int makepath (char *path);
|
int makepath (char *path);
|
||||||
void ifconfig (char *ifname, char *addr, char *mask, int up);
|
void ifconfig (char *ifname, char *addr, char *mask, int up);
|
||||||
void copyfile (char *src, char *dst, int size);
|
|
||||||
|
|
||||||
pid_t pidfile_read (const char *pidfile);
|
pid_t pidfile_read (char *pidfile);
|
||||||
pid_t pidfile_poll (char *cmd, const char *path);
|
pid_t pidfile_poll (char *cmd, char *path);
|
||||||
|
|
||||||
int pid_alive (pid_t pid);
|
int pid_alive (pid_t pid);
|
||||||
char *pid_get_name (pid_t pid, char *name, size_t len);
|
char *pid_get_name (pid_t pid, char *name, size_t len);
|
||||||
|
|
||||||
void procname_set (const char *name, char *args[]);
|
void procname_set (char *name, char *args[]);
|
||||||
int procname_kill (const char *name, int signo);
|
int procname_kill (char *name, int signo);
|
||||||
|
|
||||||
void print_desc (char *action, char *desc);
|
void print_desc (char *action, char *desc);
|
||||||
int print_result (int fail);
|
int print_result (int fail);
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# Finit libite -- Light-weight utility functions and C-library extensions
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
|
||||||
|
.EXPORT_ALL_VARIABLES:
|
||||||
|
.PHONY: all install clean
|
||||||
|
|
||||||
|
include ../common.mk
|
||||||
|
|
||||||
|
CFLAGS += -fPIC
|
||||||
|
HEADERS = lite.h
|
||||||
|
OBJS := copyfile.o dir.o fexist.o fisdir.o fmode.o rsync.o
|
||||||
|
DEPS := $(addprefix ., $(OBJS:.o=.d))
|
||||||
|
|
||||||
|
VER = 0
|
||||||
|
LIBNAME = libite
|
||||||
|
TARGET = $(LIBNAME).so
|
||||||
|
VERLIB = $(TARGET).$(VER)
|
||||||
|
STATICLIB = $(LIBNAME).a
|
||||||
|
|
||||||
|
CHECK_FLAGS = $(CFLAGS) $(CPPFLAGS)
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(OBJS): Makefile
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS)
|
||||||
|
@printf " LINK %s\n" $@
|
||||||
|
# @$(AR) $(ARFLAGS) $(STATICLIB) $(OBJS)
|
||||||
|
@$(CC) $(LDFLAGS) -shared $(OBJS) -lrt -lcrypt -Wl,-soname,$@ -o $@
|
||||||
|
@ln -sf $@ $(VERLIB)
|
||||||
|
|
||||||
|
install-exec: all
|
||||||
|
@install -d $(DESTDIR)$(libdir)
|
||||||
|
@echo " INSTALL $(DESTDIR)$(libdir)/$(TARGET)"
|
||||||
|
@$(STRIPINST) $(TARGET) $(DESTDIR)$(libdir)/$(TARGET)
|
||||||
|
@ln -sf $(TARGET) $(DESTDIR)$(libdir)/$(VERLIB)
|
||||||
|
|
||||||
|
install-dev:
|
||||||
|
@for file in $(HEADERS); do \
|
||||||
|
printf " INSTALL $(DESTDIR)$(incdir)/$$file\n"; \
|
||||||
|
$(INSTALL) -m 0644 $$file $(DESTDIR)$(incdir)/$$file; \
|
||||||
|
done
|
||||||
|
|
||||||
|
install: install-dev install-exec
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
-@$(RM) $(DESTDIR)$(libdir)/$(VERLIB)
|
||||||
|
-@$(RM) $(DESTDIR)$(libdir)/$(TARGET)
|
||||||
|
|
||||||
|
clean: uninstall
|
||||||
|
-@$(RM) $(OBJS) $(DEPS) $(TARGET) $(VERLIB) $(STATICLIB)
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
-@$(RM) $(JUNK) unittest *.o .*.d *.unittest
|
||||||
|
|
||||||
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
|
ifneq ($(MAKECMDGOALS),distclean)
|
||||||
|
-include $(DEPS)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
@@ -0,0 +1,317 @@
|
|||||||
|
/* Fastinit (finit) copyfile() implementation.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 Claudio Matsuoka <http://helllabs.org/finit/>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/param.h> /* MAX(), isset(), setbit(), TRUE, FALSE, et consortes. :-) */
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lite.h"
|
||||||
|
|
||||||
|
static int __isdir_and_append_filename(char *src, char **dst);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copyfile - Copy a file to another.
|
||||||
|
* @src: Source file.
|
||||||
|
* @dst: Target file.
|
||||||
|
* @len: Number of bytes to copy, zero (0) for entire file.
|
||||||
|
*
|
||||||
|
* This is a C implementation of the command line cp(1) utility. It is one
|
||||||
|
* of the classic missing links in the UNIX C library. This version is from
|
||||||
|
* the finit project, http://helllabs.org/finit/, which is a reimplementation
|
||||||
|
* of fastinit for the Asus EeePC.
|
||||||
|
*
|
||||||
|
* Only some small changes to save stack space have been introduced.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The number of bytes copied, zero may be error (check errno!), but it
|
||||||
|
* may also indicate that @src was empty. If @src is a directory errno
|
||||||
|
* will be set to %EISDIR since copyfile() is not recursive.
|
||||||
|
*/
|
||||||
|
ssize_t copyfile(char *src, char *dst, int len)
|
||||||
|
{
|
||||||
|
char *buffer;
|
||||||
|
int s, d, n, isdir = 0, saved_errno = 0;
|
||||||
|
ssize_t size = 0;
|
||||||
|
|
||||||
|
errno = 0; /* Reset before leaving this function. */
|
||||||
|
// fprintf (stderr, "%s() src: %s, dst: %s, len: %d\n", __func__, src, dst, len);
|
||||||
|
|
||||||
|
buffer = malloc(BUFSIZ);
|
||||||
|
if (!buffer)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (fisdir(src)) {
|
||||||
|
errno = EISDIR; /* Error: source is a directory */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if target is a directory, then append the src base filename. */
|
||||||
|
isdir = __isdir_and_append_filename(src, &dst);
|
||||||
|
|
||||||
|
/* Len == 0 means copy entire file */
|
||||||
|
if (len == 0) {
|
||||||
|
/* XXX: This feels a bit unsafe, but 2047 MiB may be sufficient for us.
|
||||||
|
* --Jocke 2008-08-11 */
|
||||||
|
len = INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((s = open(src, O_RDONLY)) >= 0) {
|
||||||
|
if ((d =
|
||||||
|
open(dst, O_WRONLY | O_CREAT | O_TRUNC,
|
||||||
|
fmode(src))) >= 0) {
|
||||||
|
do {
|
||||||
|
int clen = len > BUFSIZ ? BUFSIZ : len;
|
||||||
|
|
||||||
|
if ((n = read(s, buffer, clen)) > 0) {
|
||||||
|
size += write(d, buffer, n);
|
||||||
|
}
|
||||||
|
len -= clen;
|
||||||
|
}
|
||||||
|
while (len > 0 && n == BUFSIZ);
|
||||||
|
|
||||||
|
close(d);
|
||||||
|
} else {
|
||||||
|
saved_errno = errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(s);
|
||||||
|
} else {
|
||||||
|
saved_errno = errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
if (isdir)
|
||||||
|
free(dst);
|
||||||
|
errno = saved_errno;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* movefile - Move a file to another location
|
||||||
|
* @src: Source file.
|
||||||
|
* @dst: Target file, or location.
|
||||||
|
*
|
||||||
|
* This is a C implementation of the command line mv(1) utility.
|
||||||
|
* Usually the rename() API is sufficient, but not when moving across
|
||||||
|
* file system boundaries.
|
||||||
|
*
|
||||||
|
* The @src argument must include the full path to the source file,
|
||||||
|
* whereas the @dst argument may only be a directory, in which case the
|
||||||
|
* same file name from @src is used.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* POSIX OK(0), or non-zero with errno set.
|
||||||
|
*/
|
||||||
|
int movefile(char *src, char *dst)
|
||||||
|
{
|
||||||
|
int isdir, result = 0;
|
||||||
|
|
||||||
|
/* Check if target is a directory, then append the src base filename. */
|
||||||
|
isdir = __isdir_and_append_filename(src, &dst);
|
||||||
|
|
||||||
|
if (rename(src, dst)) {
|
||||||
|
if (errno == EXDEV) {
|
||||||
|
errno = 0;
|
||||||
|
copyfile(src, dst, 0);
|
||||||
|
if (errno)
|
||||||
|
result = 1;
|
||||||
|
else
|
||||||
|
result = remove(src);
|
||||||
|
} else {
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isdir)
|
||||||
|
free(dst);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy_filep - Copy between FILE *fp.
|
||||||
|
* @src: Source FILE.
|
||||||
|
* @dst: Destination FILE.
|
||||||
|
*
|
||||||
|
* Function takes signals into account and will restart the syscalls as long
|
||||||
|
* as error is %EINTR.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* POSIX OK(0), or non-zero with errno set on error.
|
||||||
|
*/
|
||||||
|
int copy_filep(FILE *src, FILE *dst)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
char *buf = (char *)malloc(BUFSIZ);
|
||||||
|
|
||||||
|
if (!src || !dst)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (!fgets(buf, BUFSIZ, src)) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
clearerr(src);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (feof(src))
|
||||||
|
break;
|
||||||
|
|
||||||
|
result = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
while (EOF == fputs(buf, dst)) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
clearerr(dst);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
free(buf);
|
||||||
|
return errno = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tests if dst is a directory, if so, reallocates dst and appends src filename returning 1 */
|
||||||
|
static int __isdir_and_append_filename(char *src, char **dst)
|
||||||
|
{
|
||||||
|
int isdir = 0;
|
||||||
|
|
||||||
|
if (fisdir(*dst)) {
|
||||||
|
int slash = 0;
|
||||||
|
char *tmp, *ptr = strrchr(src, '/');
|
||||||
|
|
||||||
|
if (!ptr)
|
||||||
|
ptr = src;
|
||||||
|
else
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
// fprintf (stderr, "Yes %s is a dir --> add %s\n", *dst, ptr);
|
||||||
|
tmp = malloc(strlen(*dst) + strlen(ptr) + 2);
|
||||||
|
if (!tmp) {
|
||||||
|
errno = EISDIR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
isdir = 1; /* Free dst before exit! */
|
||||||
|
slash = fisslashdir(*dst);
|
||||||
|
|
||||||
|
sprintf(tmp, "%s%s%s", *dst, slash ? "" : "/", ptr);
|
||||||
|
*dst = tmp;
|
||||||
|
// fprintf (stderr, "NEW DST:%s\n", *dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNITTEST
|
||||||
|
#include <stdio.h>
|
||||||
|
/* XXX: Make a real set of unit tests ... */
|
||||||
|
#if 0
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (argc < 3) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Usage: %s <src> <dst>\nCopies the <src> file to the <dst> file.\n",
|
||||||
|
argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Copying file %s to %s\n", argv[1], argv[2]);
|
||||||
|
|
||||||
|
return copyfile(argv[1], argv[2], 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
char *files[] = {
|
||||||
|
"/etc/passwd", "/tmp/tok", "/tmp/tok",
|
||||||
|
"/etc/passwd", "/tmp/", "/tmp/passwd",
|
||||||
|
"/etc/passwd", "/tmp", "/tmp/passwd",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
FILE *src, *dst;
|
||||||
|
|
||||||
|
fprintf(stderr, "\n=>Start testing copy_filep()\n");
|
||||||
|
while (files[i]) {
|
||||||
|
fprintf(stderr, "copy_filep(%s, %s)\t", files[i],
|
||||||
|
files[i + 1]);
|
||||||
|
src = fopen(files[i], "r");
|
||||||
|
dst = fopen(files[i + 1], "w");
|
||||||
|
if (copy_filep(src, dst))
|
||||||
|
perror("Failed");
|
||||||
|
|
||||||
|
if (src)
|
||||||
|
fclose(src);
|
||||||
|
if (dst)
|
||||||
|
fclose(dst);
|
||||||
|
|
||||||
|
if (fexist(files[i + 2]))
|
||||||
|
fprintf(stderr, "OK => %s\n", files[i + 2]);
|
||||||
|
|
||||||
|
remove(files[i + 2]);
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n\n=>Start testing copyfile()\n");
|
||||||
|
i = 0;
|
||||||
|
while (files[i]) {
|
||||||
|
fprintf(stderr, "copyfile(%s, %s)\t", files[i], files[i + 1]);
|
||||||
|
if (!copyfile(files[i], files[i + 1], 0))
|
||||||
|
perror("Failed");
|
||||||
|
|
||||||
|
if (fexist(files[i + 2]))
|
||||||
|
fprintf(stderr, "OK => %s\n", files[i + 2]);
|
||||||
|
|
||||||
|
remove(files[i + 2]);
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* UNITTEST */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* compile-command: "gcc -g -I../include -o unittest -DUNITTEST copyfile.c && ./unittest"
|
||||||
|
* version-control: t
|
||||||
|
* kept-new-versions: 2
|
||||||
|
* c-file-style: "ellemtel"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
+228
@@ -0,0 +1,228 @@
|
|||||||
|
/* Functions for operating on files in directories.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const char *matcher_type = NULL;
|
||||||
|
static int (*matcher_filter) (const char *file) = NULL;
|
||||||
|
static int matcher(const struct dirent *entry)
|
||||||
|
{
|
||||||
|
char *pos = strrchr(entry->d_name, '.');
|
||||||
|
|
||||||
|
if (matcher_filter && !matcher_filter(entry->d_name))
|
||||||
|
/* User matcher overrides the rest. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Skip current dir "." from list of files. */
|
||||||
|
if ((1 == strlen(entry->d_name) && entry->d_name[0] == '.') ||
|
||||||
|
(2 == strlen(entry->d_name) && !strcmp(entry->d_name, "..")))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* filetype == "" */
|
||||||
|
if (matcher_type[0] == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Entry has no "." */
|
||||||
|
if (!pos)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return !strcmp(pos, matcher_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dir - List all files of a certain type in the given directory.
|
||||||
|
* @dir: Base directory for dir operation.
|
||||||
|
* @type: File type suffix, e.g. ".cfg".
|
||||||
|
* @filter: Optional file name filter.
|
||||||
|
* @list: Pointer to an array of file names.
|
||||||
|
* @strip: Flag, if set dir() strips the file type.
|
||||||
|
*
|
||||||
|
* This function returns a @list of files, matching the @type suffix,
|
||||||
|
* in the given directory @dir.
|
||||||
|
*
|
||||||
|
* The @list argument is a pointer to where to store the dynamically
|
||||||
|
* allocated list of file names. This list should be free'd by first
|
||||||
|
* calling free() on each file name and then on the list itself.
|
||||||
|
*
|
||||||
|
* If @filter is not %NULL it will be called for each file found. If
|
||||||
|
* @filter returns non-zero the @file argument will be included in the
|
||||||
|
* resulting @list. If @filter returns zero for given @file it will
|
||||||
|
* be discarded.
|
||||||
|
*
|
||||||
|
* If the @strip flag is set the resulting @list of files has their
|
||||||
|
* file type stripped, including the dot. So a match "config0.cfg"
|
||||||
|
* would be returned as "config0".
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Number of files in @list, zero if no matching files of @type.
|
||||||
|
*/
|
||||||
|
int dir(const char *dir, const char *type, int (*filter) (const char *file), char ***list, int strip)
|
||||||
|
{
|
||||||
|
int i, n, num = 0;
|
||||||
|
char **files;
|
||||||
|
struct dirent **namelist;
|
||||||
|
|
||||||
|
assert(list);
|
||||||
|
|
||||||
|
if (!dir)
|
||||||
|
/* Assuming current directory */
|
||||||
|
dir = ".";
|
||||||
|
if (!type)
|
||||||
|
/* Assuming all files. */
|
||||||
|
type = "";
|
||||||
|
|
||||||
|
matcher_type = type;
|
||||||
|
matcher_filter = filter;
|
||||||
|
n = scandir(dir, &namelist, matcher, alphasort);
|
||||||
|
if (n < 0) {
|
||||||
|
perror("scandir");
|
||||||
|
} else {
|
||||||
|
files = (char **)malloc(n * sizeof(char *));
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (files) {
|
||||||
|
char *name = namelist[i]->d_name;
|
||||||
|
char *type = strrchr(name, '.');
|
||||||
|
|
||||||
|
if (type && strip)
|
||||||
|
*type = 0;
|
||||||
|
|
||||||
|
files[i] = strdup(name);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
free(namelist[i]);
|
||||||
|
}
|
||||||
|
free(namelist);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num)
|
||||||
|
*list = files;
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNITTEST
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include "otn/c.h"
|
||||||
|
|
||||||
|
#define DIR_TYPE_IMAGE ".img"
|
||||||
|
#define DIR_TYPE_SYSLOG ""
|
||||||
|
#define DIR_TYPE_CONFIG ".cfg"
|
||||||
|
#define STARTUP_CONFIG "startup-config.cfg"
|
||||||
|
|
||||||
|
int simulate_files(int creat)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *files[] =
|
||||||
|
{ "config0.cfg", "config1.cfg", "config2.cfg", "config3.cfg",
|
||||||
|
"rr109.img", "rx100.img", "rx107.img", "rm957.img", "messages"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_ELEMENTS(files); i++) {
|
||||||
|
if (creat)
|
||||||
|
touch(files[i]);
|
||||||
|
else
|
||||||
|
remove(files[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (creat)
|
||||||
|
symlink("config2.cfg", STARTUP_CONFIG);
|
||||||
|
else
|
||||||
|
remove(STARTUP_CONFIG);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cfg_dir_filter(const char *file)
|
||||||
|
{
|
||||||
|
/* Skip the STARTUP_CONFIG file, it is a symbolic link to the
|
||||||
|
* current startup configuration. */
|
||||||
|
return ! !strcmp(file, STARTUP_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int i, num;
|
||||||
|
char *type = DIR_TYPE_CONFIG;
|
||||||
|
char **files;
|
||||||
|
int once = 1;
|
||||||
|
|
||||||
|
int is_startup_config(const char *entry) {
|
||||||
|
static char file[80];
|
||||||
|
|
||||||
|
if (once) {
|
||||||
|
int len = readlink(STARTUP_CONFIG, file, sizeof(file));
|
||||||
|
|
||||||
|
if (len == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
file[len] = 0;
|
||||||
|
once = 0; /* Only once per call to dir() */
|
||||||
|
}
|
||||||
|
//printf ("Comparing link %s with entry %s\n", file, entry);
|
||||||
|
return !strcmp(file, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
simulate_files(1);
|
||||||
|
|
||||||
|
if (argc >= 2) {
|
||||||
|
if (!strcasecmp("CONFIG", argv[1])) {
|
||||||
|
type = DIR_TYPE_CONFIG;
|
||||||
|
system("ls -l *" DIR_TYPE_CONFIG);
|
||||||
|
}
|
||||||
|
if (!strcasecmp("IMAGE", argv[1])) {
|
||||||
|
type = DIR_TYPE_IMAGE;
|
||||||
|
system("ls -l *" DIR_TYPE_IMAGE);
|
||||||
|
}
|
||||||
|
if (!strcasecmp("SYSLOG", argv[1])) {
|
||||||
|
type = DIR_TYPE_SYSLOG;
|
||||||
|
system("ls -l *");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
num = dir(NULL, type, cfg_dir_filter, &files, 0);
|
||||||
|
if (num) {
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
printf("%s", files[i]);
|
||||||
|
if (is_startup_config(files[i]))
|
||||||
|
printf(" --> startup-config");
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
free(files[i]);
|
||||||
|
}
|
||||||
|
free(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
simulate_files(0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* UNITTEST */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* compile-command: "gcc -g -DUNITTEST -o unittest dir.c"
|
||||||
|
* version-control: t
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/* Check if file exists
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 Claudio Matsuoka <http://helllabs.org/finit/>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fexist - Check if a file exists in the file system.
|
||||||
|
* @file: File to look for, with full path.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* %TRUE(1) if the file exists, otherwise %FALSE(0).
|
||||||
|
*/
|
||||||
|
int fexist(char *file)
|
||||||
|
{
|
||||||
|
if (!file) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return 0; /* Doesn't exist ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-1 == access(file, F_OK))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* version-control: t
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/* Check if directory exists
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 Claudio Matsuoka <http://helllabs.org/finit/>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fexist - Check if a file exists and is a directory.
|
||||||
|
* @file: File to look for, with full path.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* %TRUE(1) if the file exists and is a directory, otherwise %FALSE(0).
|
||||||
|
*/
|
||||||
|
int fisdir(char *file)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (!stat(file, &sb) && S_ISDIR(sb.st_mode))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* version-control: t
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/* File mode bit operations
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 Claudio Matsuoka <http://helllabs.org/finit/>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fmode - Return a file's mode bits.
|
||||||
|
* @file: File to look for, with full path.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The mode bits or zero when @file does not exist and errno set to %ENOENT.
|
||||||
|
*/
|
||||||
|
mode_t fmode(char *file)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return 0; /* Doesn't exist ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stat(file, &sb))
|
||||||
|
return sb.st_mode;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* version-control: t
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/* Collection of utility funcs and C library extensions for finit & its plugins
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
|
* Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FINIT_LITE_H_
|
||||||
|
#define FINIT_LITE_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int fexist (char *file);
|
||||||
|
int fisdir (char *file);
|
||||||
|
mode_t fmode (char *file);
|
||||||
|
|
||||||
|
ssize_t copyfile (char *src, char *dst, int len);
|
||||||
|
int movefile (char *src, char *dst);
|
||||||
|
int copy_filep (FILE *src, FILE *dst);
|
||||||
|
|
||||||
|
int dir (const char *dir, const char *type, int (*filter) (const char *file), char ***list, int strip);
|
||||||
|
int rsync (char *src, char *dst, int delete, int (*filter) (const char *file));
|
||||||
|
|
||||||
|
static inline int fisslashdir(char *dir)
|
||||||
|
{
|
||||||
|
if (!dir) return 0;
|
||||||
|
if (strlen (dir) > 0) return dir[strlen (dir) - 1] == '/';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FINIT_LITE_H_ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* version-control: t
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
|
|
||||||
+280
@@ -0,0 +1,280 @@
|
|||||||
|
/* Micro "rsync" implementation.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, 2012 Joachim Nilsson <troglobit@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h> /* NULL, free() */
|
||||||
|
#include <string.h> /* strlen() */
|
||||||
|
#include <strings.h> /* rindex() */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/param.h> /* MAX(), isset(), setbit(), TRUE, FALSE, et consortes. :-) */
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "lite.h"
|
||||||
|
#include "../helpers.h"
|
||||||
|
|
||||||
|
static int makedir(char *buf, size_t buf_len, char *dir, char *name, mode_t mode);
|
||||||
|
static int prune(char *dst, char **new_files, int new_num);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rsync - Synchronize contents and optionally remove non-existing backups
|
||||||
|
* @src: Source directory
|
||||||
|
* @dst: Destination directory
|
||||||
|
* @delete: Prune files from @dst that no longer exist in @src.
|
||||||
|
* @filter: Optional filtering function for source directory.
|
||||||
|
*
|
||||||
|
* This is a miniature implementation of the famous rsync for local use only.
|
||||||
|
* In fact, it is not even a true rsync since it copies all files from @src
|
||||||
|
* to @dst. The @delete option is useful for creating backups, when set all
|
||||||
|
* files removed from src since last backup are pruned from the destination
|
||||||
|
* (backup) directory.
|
||||||
|
*
|
||||||
|
* The filter callback, @filter, if provided, is used to determine what files to
|
||||||
|
* include from the source directory when backing up. If a file is to be skipped
|
||||||
|
* the callback should simply return zero.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* POSIX OK(0), or non-zero with @errno set on error.
|
||||||
|
*/
|
||||||
|
int rsync(char *src, char *dst, int delete, int (*filter) (const char *file))
|
||||||
|
{
|
||||||
|
char source[256];
|
||||||
|
char dest[256];
|
||||||
|
int i = 0, num = 0, result = 0;
|
||||||
|
char **files; /* Array of file names. */
|
||||||
|
|
||||||
|
void copy(char *src, char *dst)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
copyfile(src, dst, 0);
|
||||||
|
if (errno) result++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fisdir(dst))
|
||||||
|
mkdir(dst, 0755);
|
||||||
|
|
||||||
|
if (!fisdir(src)) {
|
||||||
|
if (!fexist(src))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
copy(src, dst);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy dir as well? */
|
||||||
|
if (!fisslashdir(src)) {
|
||||||
|
char *ptr = rindex(src, '/');
|
||||||
|
|
||||||
|
if (!ptr)
|
||||||
|
ptr = src;
|
||||||
|
else
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
if (makedir(dest, sizeof(dest), dst, ptr, fmode(src)))
|
||||||
|
return 1;
|
||||||
|
dst = dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
num = dir(src, "", filter, &files, 0);
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
/* Recursively copy sub-directries */
|
||||||
|
snprintf(source, sizeof(source), "%s%s%s", src, fisslashdir(src) ? "" : "/", files[i]);
|
||||||
|
if (fisdir(source)) {
|
||||||
|
char dst2[256];
|
||||||
|
|
||||||
|
strcat(source, "/");
|
||||||
|
if (makedir (dst2, sizeof(dst2), dst, files[i], fmode(source))) {
|
||||||
|
result++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rsync(source, dst2, delete, filter);
|
||||||
|
continue; /* Next file/dir in @src to copy... */
|
||||||
|
}
|
||||||
|
copy(source, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We ignore any errors from the pruning, that phase albeit useful is only
|
||||||
|
* cosmetic. --Jocke 2011-03-24 */
|
||||||
|
if (delete)
|
||||||
|
prune(dst, files, num);
|
||||||
|
|
||||||
|
if (num) {
|
||||||
|
for (i = 0; i < num; i++)
|
||||||
|
free(files[i]);
|
||||||
|
free(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Creates dir/name @mode ... skipping / if dir already ends so. */
|
||||||
|
static int makedir(char *buf, size_t buf_len, char *dir, char *name, mode_t mode)
|
||||||
|
{
|
||||||
|
snprintf(buf, buf_len, "%s%s%s/", dir, fisslashdir(dir) ? "" : "/", name);
|
||||||
|
if (mkdir(buf, mode))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prune old files, no longer existing on source, from destination directory. */
|
||||||
|
static int prune(char *dst, char **new_files, int new_num)
|
||||||
|
{
|
||||||
|
int i, num, result = 0;
|
||||||
|
char **files;
|
||||||
|
|
||||||
|
int find(char *file) {
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (n = 0; n < new_num; n++)
|
||||||
|
if (!strncmp (new_files[n], file, MAX(strlen(new_files[n]), strlen(file))))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
num = dir(dst, "", NULL, &files, 0);
|
||||||
|
if (num) {
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
if (!find(files[i])) {
|
||||||
|
char *name;
|
||||||
|
size_t len = strlen(files[i]) + 2 + strlen(dst);
|
||||||
|
|
||||||
|
name = malloc(len);
|
||||||
|
if (name) {
|
||||||
|
snprintf(name, len, "%s%s%s", dst, fisslashdir(dst) ? "" : "/", files[i]);
|
||||||
|
if (remove(name))
|
||||||
|
result++;
|
||||||
|
free(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(files[i]);
|
||||||
|
}
|
||||||
|
free(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNITTEST
|
||||||
|
#define BASE "/tmp/.unittest/"
|
||||||
|
#define SRC BASE "src/"
|
||||||
|
#define DST BASE "dst/"
|
||||||
|
|
||||||
|
char *files[] = {
|
||||||
|
SRC "sub1/1.tst",
|
||||||
|
SRC "sub1/2.tst",
|
||||||
|
SRC "sub1/3.tst",
|
||||||
|
SRC "sub2/4.tst",
|
||||||
|
SRC "sub2/5.tst",
|
||||||
|
SRC "sub2/6.tst",
|
||||||
|
SRC "sub3/7.tst",
|
||||||
|
SRC "sub3/8.tst",
|
||||||
|
SRC "sub3/9.tst",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
void cleanup_test(void)
|
||||||
|
{
|
||||||
|
system("rm -rf " BASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_test(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char cmd[256];
|
||||||
|
mode_t dir_modes[] = { 755, 700 };
|
||||||
|
mode_t file_modes[] = { 644, 600 };
|
||||||
|
|
||||||
|
cleanup_test();
|
||||||
|
|
||||||
|
mkdir(BASE, 0755);
|
||||||
|
mkdir(SRC, 0755);
|
||||||
|
mkdir(DST, 0755);
|
||||||
|
|
||||||
|
for (i = 0; files[i]; i++) {
|
||||||
|
snprintf(cmd, sizeof(cmd), "mkdir -m %d -p `dirname %s`",
|
||||||
|
dir_modes[i % 2], files[i]);
|
||||||
|
system(cmd);
|
||||||
|
|
||||||
|
snprintf(cmd, sizeof(cmd), "touch %s; chmod %d %s", files[i],
|
||||||
|
file_modes[i % 2], files[i]);
|
||||||
|
system(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_test()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
setup_test();
|
||||||
|
puts("Before:");
|
||||||
|
system("tree -np " BASE);
|
||||||
|
|
||||||
|
rsync(SRC, DST, 0, NULL);
|
||||||
|
puts("After:");
|
||||||
|
system("tree -np " BASE);
|
||||||
|
cleanup_test();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
setup_test();
|
||||||
|
rsync(BASE "src", DST, 0, NULL);
|
||||||
|
puts("Only partial rsync of src <-- No slash!");
|
||||||
|
system("tree -np " BASE);
|
||||||
|
#if 0
|
||||||
|
cleanup_test();
|
||||||
|
setup_test();
|
||||||
|
rsync(BASE "src/sub1", BASE "dst", 0, NULL);
|
||||||
|
puts("Only partial rsync of src/sub1 <-- No slashes!!");
|
||||||
|
system("tree -np " BASE);
|
||||||
|
|
||||||
|
cleanup_test();
|
||||||
|
setup_test();
|
||||||
|
rsync(BASE "src/sub1/", DST, 0, NULL);
|
||||||
|
puts("Only partial rsync of src/sub1/");
|
||||||
|
system("tree -np " BASE);
|
||||||
|
|
||||||
|
cleanup_test();
|
||||||
|
setup_test();
|
||||||
|
rsync(BASE "src/sub1", DST, 0, NULL);
|
||||||
|
puts("Only partial rsync of src/sub1 <-- No slash!");
|
||||||
|
system("tree -np " BASE);
|
||||||
|
|
||||||
|
rsync("/etc", "/var/tmp", 0, NULL);
|
||||||
|
puts("Real life test:");
|
||||||
|
system("tree -np /var/tmp");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
atexit(cleanup_test);
|
||||||
|
|
||||||
|
return run_test();
|
||||||
|
}
|
||||||
|
#endif /* UNITTEST */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* compile-command: "make -f rsync.mk"
|
||||||
|
* version-control: t
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Unittest makefile for rsync.c
|
||||||
|
.PHONY: clean
|
||||||
|
|
||||||
|
SRC = rsync.c
|
||||||
|
OBJS = dir.o copyfile.o fexist.o fisdir.o fmode.o
|
||||||
|
UNIT = rsync.unittest
|
||||||
|
#CPPFLAGS = -DDEBUG -I../../.. -I../../include
|
||||||
|
|
||||||
|
all: build run
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f $(OBJS) $(UNIT)
|
||||||
|
|
||||||
|
# This rule also forces a cleanup of built objects to not leave any object files
|
||||||
|
# lingering in the tree to interfere with cross builds.
|
||||||
|
build: clean $(OBJS)
|
||||||
|
$(CC) $(CFLAGS) $(CPPFLAGS) -o $(UNIT) -DUNITTEST $(SRC) $(OBJS)
|
||||||
|
@rm -f $(OBJS)
|
||||||
|
|
||||||
|
run:
|
||||||
|
@./$(UNIT)
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ int plugin_register(plugin_t *plugin)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!inuse) {
|
if (!inuse) {
|
||||||
_e("No service \"%s\" loaded, and no I/O or finit hooks, skipping plugin.", basename(plugin->name));
|
_d("No service \"%s\" loaded, and no I/O or finit hooks, skipping plugin.", basename(plugin->name));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,15 +173,16 @@ static void init_plugins(void)
|
|||||||
PLUGIN_ITERATOR(p) {
|
PLUGIN_ITERATOR(p) {
|
||||||
if (is_io_plugin(p)) {
|
if (is_io_plugin(p)) {
|
||||||
_d("Initializing plugin %s for I/O", basename(p->name));
|
_d("Initializing plugin %s for I/O", basename(p->name));
|
||||||
fds[i].revents = 0;
|
fds[i].revents = 0;
|
||||||
fds[i].events = p->io.flags;
|
fds[i].events = p->io.flags;
|
||||||
fds[num_fds++].fd = p->io.fd;
|
fds[i++].fd = p->io.fd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int plugin_load_all(char *path)
|
int plugin_load_all(char *path)
|
||||||
{
|
{
|
||||||
|
int fail = 0;
|
||||||
DIR *dp = opendir(path);
|
DIR *dp = opendir(path);
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
|
|
||||||
@@ -194,25 +195,28 @@ int plugin_load_all(char *path)
|
|||||||
char *ext = entry->d_name + strlen(entry->d_name) - 3;
|
char *ext = entry->d_name + strlen(entry->d_name) - 3;
|
||||||
|
|
||||||
if (!strcmp(ext, ".so")) {
|
if (!strcmp(ext, ".so")) {
|
||||||
|
int result = 0;
|
||||||
void *handle;
|
void *handle;
|
||||||
char plugin[1024];
|
char plugin[1024];
|
||||||
|
|
||||||
snprintf(plugin, sizeof(plugin), "%s/%s", path, entry->d_name);
|
snprintf(plugin, sizeof(plugin), "%s/%s", path, entry->d_name);
|
||||||
print_desc(" Loading plugin ", basename(plugin));
|
// print_desc(" Loading plugin ", basename(plugin));
|
||||||
handle = dlopen(plugin, RTLD_LAZY | RTLD_GLOBAL);
|
handle = dlopen(plugin, RTLD_LAZY | RTLD_GLOBAL);
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
_d("Failed loading plugin %s: %s", plugin, dlerror());
|
_d("Failed loading plugin %s: %s", plugin, dlerror());
|
||||||
print_result(1);
|
result = 1;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
print_result(0);
|
if (result)
|
||||||
|
fail++;
|
||||||
|
|
||||||
|
// print_result(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
init_plugins();
|
init_plugins();
|
||||||
|
|
||||||
return 0;
|
return fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -40,7 +40,8 @@
|
|||||||
* Predefined hook points for easier plugin debugging
|
* Predefined hook points for easier plugin debugging
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HOOK_BASEFS_UP = 0,
|
HOOK_ROOTFS_UP = 0,
|
||||||
|
HOOK_BASEFS_UP,
|
||||||
HOOK_NETWORK_UP,
|
HOOK_NETWORK_UP,
|
||||||
HOOK_SYSTEM_UP,
|
HOOK_SYSTEM_UP,
|
||||||
HOOK_SVC_UP,
|
HOOK_SVC_UP,
|
||||||
|
|||||||
+3
-2
@@ -1,7 +1,8 @@
|
|||||||
# Plugin based services architecture for finit -*-Makefile-*-
|
# Plugin based services architecture for finit -*-Makefile-*-
|
||||||
CFLAGS = -fPIC -g -Os
|
CFLAGS += -fPIC -Os
|
||||||
CPPFLAGS += -I..
|
CPPFLAGS += -I..
|
||||||
LDFLAGS = -shared
|
LDFLAGS := $(filter-out -rdynamic, $(LDFLAGS))
|
||||||
|
LDFLAGS += -shared
|
||||||
PLUGINS ?= initctl.so alsa-utils.so bootmisc.so dbus.so hwclock.so \
|
PLUGINS ?= initctl.so alsa-utils.so bootmisc.so dbus.so hwclock.so \
|
||||||
resolvconf.so urandom.so x11-common.so
|
resolvconf.so urandom.so x11-common.so
|
||||||
DEPS = $(addprefix .,$(PLUGINS:.so=.d))
|
DEPS = $(addprefix .,$(PLUGINS:.so=.d))
|
||||||
|
|||||||
@@ -26,9 +26,11 @@
|
|||||||
#include <fcntl.h> /* O_RDONLY et al */
|
#include <fcntl.h> /* O_RDONLY et al */
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h> /* read() */
|
||||||
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "sig.h"
|
||||||
|
|
||||||
#define INIT_MAGIC 0x03091969
|
#define INIT_MAGIC 0x03091969
|
||||||
#define INIT_CMD_RUNLVL 1
|
#define INIT_CMD_RUNLVL 1
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* reboot for finit
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2012 Joachim Nilsson <troglobit@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
return !!kill(1, SIGINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* version-control: t
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
|
#include "lite.h"
|
||||||
#include "svc.h"
|
#include "svc.h"
|
||||||
|
|
||||||
/* The registered services are kept in shared memory for easy read-only access
|
/* The registered services are kept in shared memory for easy read-only access
|
||||||
@@ -269,6 +270,7 @@ int svc_start(svc_t *svc)
|
|||||||
{
|
{
|
||||||
int respawn = svc->pid != 0;
|
int respawn = svc->pid != 0;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
sigset_t nmask, omask;
|
||||||
char *args[MAX_NUM_SVC_ARGS];
|
char *args[MAX_NUM_SVC_ARGS];
|
||||||
|
|
||||||
/* Ignore if finit is SIGSTOP'ed */
|
/* Ignore if finit is SIGSTOP'ed */
|
||||||
@@ -278,12 +280,22 @@ int svc_start(svc_t *svc)
|
|||||||
if (!respawn)
|
if (!respawn)
|
||||||
print_desc("Starting ", svc->desc);
|
print_desc("Starting ", svc->desc);
|
||||||
|
|
||||||
|
/* Block sigchild while forking. */
|
||||||
|
sigemptyset(&nmask);
|
||||||
|
sigaddset(&nmask, SIGCHLD);
|
||||||
|
sigprocmask(SIG_BLOCK, &nmask, &omask);
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int uid = getuser(svc->username);
|
int uid = getuser(svc->username);
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
|
sigemptyset(&nmask);
|
||||||
|
sigaddset(&nmask, SIGCHLD);
|
||||||
|
sigprocmask(SIG_UNBLOCK, &nmask, NULL);
|
||||||
|
|
||||||
/* Reset signal handlers that were set by the parent process */
|
/* Reset signal handlers that were set by the parent process */
|
||||||
for (i = 1; i < NSIG; i++)
|
for (i = 1; i < NSIG; i++)
|
||||||
DFLSIG(sa, i, 0);
|
DFLSIG(sa, i, 0);
|
||||||
@@ -298,16 +310,23 @@ int svc_start(svc_t *svc)
|
|||||||
args[i] = NULL;
|
args[i] = NULL;
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
int fd = open (CONSOLE, O_WRONLY | O_APPEND);
|
int fd;
|
||||||
|
char buf[256] = "";
|
||||||
|
|
||||||
|
fd = open (CONSOLE, O_WRONLY | O_APPEND);
|
||||||
if (-1 != fd) {
|
if (-1 != fd) {
|
||||||
dup2(STDOUT_FILENO, fd);
|
dup2(STDOUT_FILENO, fd);
|
||||||
dup2(STDERR_FILENO, fd);
|
dup2(STDERR_FILENO, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
_e("%starting %s ", respawn ? "Res" : "S", svc->cmd);
|
for (i = 0; args[i] && i < MAX_NUM_SVC_ARGS; i++) {
|
||||||
for (i = 0; args[i] && i < MAX_NUM_SVC_ARGS; i++)
|
char arg[MAX_ARG_LEN];
|
||||||
_e("%s ", args[i]);
|
|
||||||
_e("");
|
snprintf(arg, sizeof(arg), "%s ", args[i]);
|
||||||
|
if ((sizeof(buf) - strlen(buf)) < strlen(arg))
|
||||||
|
strcat(buf, arg);
|
||||||
|
}
|
||||||
|
_e("%starting %s: %s", respawn ? "Res" : "S", svc->cmd, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
execvp(svc->cmd, args);
|
execvp(svc->cmd, args);
|
||||||
@@ -383,9 +402,9 @@ void svc_start_all(void)
|
|||||||
|
|
||||||
for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
|
for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
|
||||||
cmd = svc_enabled(svc, 0, NULL);
|
cmd = svc_enabled(svc, 0, NULL);
|
||||||
if (cmd == SVC_START || (cmd == SVC_RELOAD && svc->pid == 0))
|
if (SVC_START == cmd || (SVC_RELOAD == cmd && svc->pid == 0))
|
||||||
svc_start(svc);
|
svc_start(svc);
|
||||||
else if (cmd == SVC_RELOAD)
|
else if (SVC_RELOAD == cmd)
|
||||||
svc_reload(svc);
|
svc_reload(svc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user