mirror of
https://github.com/troglobit/finit.git
synced 2026-10-18 10:59:34 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccfea59cb3 | ||
|
|
7b315364ca | ||
|
|
e9e28ece1c | ||
|
|
c1f9b4e1f6 | ||
|
|
6ebb23e0f0 | ||
|
|
026c229005 | ||
|
|
4d05bf9359 | ||
|
|
289247dab9 | ||
|
|
e44dfde54e | ||
|
|
35b200d3a9 | ||
|
|
5badf4d376 | ||
|
|
24f274c126 | ||
|
|
1abd43384b | ||
|
|
70a1acc210 | ||
|
|
6af0446490 | ||
|
|
ecaf111a4b | ||
|
|
32ec25b070 | ||
|
|
305ad302f2 | ||
|
|
d6390244ad | ||
|
|
790a316607 | ||
|
|
77aa941e84 | ||
|
|
e0a65f67c9 | ||
|
|
3ed291789c | ||
|
|
774a24cdd8 | ||
|
|
6011f91f22 | ||
|
|
07a364e570 | ||
|
|
5b9d99011b | ||
|
|
f4f773b4c7 | ||
|
|
9d949c4186 | ||
|
|
1434561a46 | ||
|
|
cf3d3f6f8e | ||
|
|
621da582c2 | ||
|
|
9167d9255d | ||
|
|
c71bafd495 | ||
|
|
b3b7a33252 | ||
|
|
d1efc60c84 | ||
|
|
9a24dfd98d | ||
|
|
0e3fe5e3bf | ||
|
|
224f42c344 | ||
|
|
e60eb94810 | ||
|
|
464bc831a5 | ||
|
|
e84911fe52 | ||
|
|
4bcfd606b4 | ||
|
|
fe27ed17eb | ||
|
|
b3ea23ed26 | ||
|
|
439699ef52 | ||
|
|
f20936dae0 | ||
|
|
d5bea7eeeb | ||
|
|
5da0a460fe | ||
|
|
63033d7dcf | ||
|
|
2857dafaf4 | ||
|
|
8355c37285 | ||
|
|
dc49b523d1 | ||
|
|
bf863673c8 |
No files matched your search
+2
-5
@@ -5,9 +5,6 @@ language: c
|
|||||||
# Use docker for quicker builds, it now allows https://docs.travis-ci.com/user/apt/
|
# Use docker for quicker builds, it now allows https://docs.travis-ci.com/user/apt/
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
# Use non-docker builds atm. to install libuEv and libite from source
|
|
||||||
#sudo: true
|
|
||||||
|
|
||||||
# Test build with both GCC and Clang (LLVM)
|
# Test build with both GCC and Clang (LLVM)
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
@@ -30,7 +27,7 @@ addons:
|
|||||||
name: "troglobit/finit"
|
name: "troglobit/finit"
|
||||||
description: "finit | Fast & Extensible init for Linux"
|
description: "finit | Fast & Extensible init for Linux"
|
||||||
notification_email: troglobit@gmail.com
|
notification_email: troglobit@gmail.com
|
||||||
build_command_prepend: "./autogen.sh && ./configure --prefix=/tmp"
|
build_command_prepend: "./autogen.sh && ./configure --prefix=/tmp --disable-doc --disable-contrib --enable-watchdog --enable-fallback-shell"
|
||||||
build_command: "make"
|
build_command: "make"
|
||||||
branch_pattern: dev
|
branch_pattern: dev
|
||||||
|
|
||||||
@@ -48,7 +45,7 @@ script:
|
|||||||
- ./configure --prefix=/tmp --enable-static
|
- ./configure --prefix=/tmp --enable-static
|
||||||
- make clean
|
- make clean
|
||||||
- make V=1 -j5
|
- make V=1 -j5
|
||||||
- ./configure --prefix=/tmp --enable-x11-common-plugin --enable-fallback-shell --enable-watchdog --enable-logit
|
- ./configure --prefix=/tmp --enable-x11-common-plugin --enable-fallback-shell --enable-watchdog
|
||||||
- cat config.log
|
- cat config.log
|
||||||
- make clean
|
- make clean
|
||||||
- make V=1 -j5
|
- make V=1 -j5
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Major Contributors:
|
|||||||
* Mattias Walström <mattias.walstrom@westermo.se>
|
* Mattias Walström <mattias.walstrom@westermo.se>
|
||||||
* Jonas Johansson <jonas.johansson@westermo.se>
|
* Jonas Johansson <jonas.johansson@westermo.se>
|
||||||
* Jacques de Laval <jacques@de-laval.se>
|
* Jacques de Laval <jacques@de-laval.se>
|
||||||
|
* Magnus Malm <magnusmalm@gmail.com>
|
||||||
|
|
||||||
Original Author(s):
|
Original Author(s):
|
||||||
* Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ Finit is a simple alternative to [SysV init][4] and [systemd][6]. It
|
|||||||
was reverse engineered from the [EeePC fastinit][] over ten years ago
|
was reverse engineered from the [EeePC fastinit][] over ten years ago
|
||||||
by [Claudio Matsuoka][] — "gaps filled with frog DNA …"
|
by [Claudio Matsuoka][] — "gaps filled with frog DNA …"
|
||||||
|
|
||||||
|

|
||||||
|
*Figure 1: Screenshot showing Finit booting [Alpine Linux](https://www.alpinelinux.org/).*
|
||||||
|
|
||||||
Focus is on small and embedded systems, although Finit is fully usable
|
Focus is on small and embedded systems, although Finit is fully usable
|
||||||
on server and desktop systems as well. For working examples, see the
|
on server and desktop systems as well. For working examples, see the
|
||||||
[contrib/](contrib/) section with tutorials for:
|
[contrib/](contrib/) section with tutorials for:
|
||||||
@@ -34,9 +37,6 @@ on server and desktop systems as well. For working examples, see the
|
|||||||
* [Alpine Linux](contrib/alpine/), and
|
* [Alpine Linux](contrib/alpine/), and
|
||||||
* [Debian GNU/Linux](contrib/debian/)
|
* [Debian GNU/Linux](contrib/debian/)
|
||||||
|
|
||||||

|
|
||||||
The screenshot shows [Alpine Linux](https://www.alpinelinux.org/).
|
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
@@ -348,11 +348,15 @@ Finit also implements a modern API to query status, and start/stop
|
|||||||
services, called `initctl`. Unlike `telinit` the `initctl` tool does
|
services, called `initctl`. Unlike `telinit` the `initctl` tool does
|
||||||
not return until the given command has fully completed.
|
not return until the given command has fully completed.
|
||||||
|
|
||||||
```shell
|
```
|
||||||
~ $ initctl -h
|
alpine:~# initctl help
|
||||||
Usage: initctl [OPTIONS] [COMMAND]
|
Usage: initctl [OPTIONS] [COMMAND]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
-b, --batch Batch mode, no screen size probing
|
||||||
|
-c, --create Create missing paths (and files) as needed
|
||||||
|
-f, --force Ignore missing files and arguments, never prompt
|
||||||
|
-t, --no-heading Skip table headings
|
||||||
-v, --verbose Verbose output
|
-v, --verbose Verbose output
|
||||||
-h, --help This help text
|
-h, --help This help text
|
||||||
|
|
||||||
@@ -360,29 +364,34 @@ Commands:
|
|||||||
debug Toggle Finit (daemon) debug
|
debug Toggle Finit (daemon) debug
|
||||||
help This help text
|
help This help text
|
||||||
version Show Finit version
|
version Show Finit version
|
||||||
|
|
||||||
list List all .conf in /etc/finit.d/
|
ls | list List all .conf in /etc/finit.d
|
||||||
enable <CONF> Enable .conf in /etc/finit.d/available/
|
create <CONF> Create .conf in /etc/finit.d/available
|
||||||
disable <CONF> Disable .conf in /etc/finit.d/[enabled/]
|
delete <CONF> Delete .conf in /etc/finit.d/available
|
||||||
touch <CONF> Mark .conf in /etc/finit.d/ for reload
|
show <CONF> Show .conf in /etc/finit.d/available
|
||||||
reload Reload *.conf in /etc/finit.d/ (activates changes)
|
edit <CONF> Edit .conf in /etc/finit.d/available
|
||||||
|
touch <CONF> Change .conf in /etc/finit.d/available
|
||||||
|
enable <CONF> Enable .conf in /etc/finit.d/available
|
||||||
|
disable <CONF> Disable .conf in /etc/finit.d/enabled
|
||||||
|
reload Reload *.conf in /etc/finit.d (activate changes)
|
||||||
|
|
||||||
cond show Show condition status
|
cond show Show condition status
|
||||||
cond dump Dump all conditions and their status
|
cond dump Dump all conditions and their status
|
||||||
|
|
||||||
log [NAME] Show ten last Finit, or NAME, messages from syslog
|
log [NAME] Show ten last Finit, or NAME, messages from syslog
|
||||||
start <JOB|NAME>[:ID] Start service by job# or name, with optional ID
|
start <NAME>[:ID] Start service by name, with optional ID
|
||||||
stop <JOB|NAME>[:ID] Stop/Pause a running service by job# or name
|
stop <NAME>[:ID] Stop/Pause a running service by name
|
||||||
restart <JOB|NAME>[:ID] Restart (stop/start) service by job# or name
|
restart <NAME>[:ID] Restart (stop/start) service by name
|
||||||
status <JOB|NAME>[:ID] Show service status, by job# or name
|
status <NAME>[:ID] Show service status, by name
|
||||||
status | show Show status of services, default command
|
status Show status of services, default command
|
||||||
|
|
||||||
|
ps List processes based on cgroups
|
||||||
|
|
||||||
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
|
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
|
||||||
reboot Reboot system
|
reboot Reboot system
|
||||||
halt Halt system
|
halt Halt system
|
||||||
poweroff Halt and power off system
|
poweroff Halt and power off system
|
||||||
|
suspend Suspend system
|
||||||
utmp show Raw dump of UTMP/WTMP db
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For services *not* supporting `SIGHUP` the `<!>` notation in the .conf
|
For services *not* supporting `SIGHUP` the `<!>` notation in the .conf
|
||||||
@@ -395,18 +404,31 @@ the current runlevel these services will not be respawned automatically
|
|||||||
by Finit if they exit (crash). Hence, if the runlevel is 2, the below
|
by Finit if they exit (crash). Hence, if the runlevel is 2, the below
|
||||||
Dropbear SSH service will not be restarted if it is killed or exits.
|
Dropbear SSH service will not be restarted if it is killed or exits.
|
||||||
|
|
||||||
```shell
|
|
||||||
~ $ initctl status -v
|
|
||||||
1 running 476 [S12345] /sbin/watchdog -T 16 -t 2 -F /dev/watchdog
|
|
||||||
2 running 477 [S12345] /sbin/syslogd -n -b 3 -D
|
|
||||||
3 running 478 [S12345] /sbin/klogd -n
|
|
||||||
4:1 inetd 0 [2345] internal time allow *:37,!eth0
|
|
||||||
4:2 inetd 0 [2345] internal time allow eth0:3737
|
|
||||||
5:1 inetd 0 [2345] /sbin/telnetd allow *:23 deny eth0,eth1
|
|
||||||
5:2 inetd 0 [2345] /sbin/telnetd allow eth0:2323,eth2:2323,eth1:2323
|
|
||||||
6:1 inetd 0 [345] /sbin/dropbear allow eth0:222
|
|
||||||
6:2 inetd 0 [345] /sbin/dropbear allow *:22 deny eth0
|
|
||||||
```
|
```
|
||||||
|
alpine:~# initctl
|
||||||
|
PID IDENT STATUS RUNLEVELS DESCRIPTION
|
||||||
|
======================================================================
|
||||||
|
1506 acpid running [--2345----] ACPI daemon
|
||||||
|
1509 crond running [--2345----] Cron daemon
|
||||||
|
1489 dropbear running [--2345----] Dropbear SSH daemon
|
||||||
|
1511 klogd running [S12345----] Kernel log daemon
|
||||||
|
1512 ntpd running [--2345----] NTP daemon
|
||||||
|
1473 syslogd running [S12345----] Syslog daemon
|
||||||
|
|
||||||
|
alpine:~# initctl -v
|
||||||
|
PID IDENT STATUS RUNLEVELS COMMAND
|
||||||
|
======================================================================
|
||||||
|
1506 acpid running [--2345----] acpid -f
|
||||||
|
1509 crond running [--2345----] crond -f -S $CRON_OPTS
|
||||||
|
1489 dropbear running [--2345----] dropbear -R -F $DROPBEAR_OPTS
|
||||||
|
1511 klogd running [S12345----] klogd -n $KLOGD_OPTS
|
||||||
|
1512 ntpd running [--2345----] ntpd -n $NTPD_OPTS
|
||||||
|
1473 syslogd running [S12345----] syslogd -n
|
||||||
|
```
|
||||||
|
|
||||||
|
The environment variables to each of the services above are read from,
|
||||||
|
in the case of Alpine Linux, `/etc/conf.d/`. Other distributions may
|
||||||
|
have other directories, e.g., Debian use `/etc/default/`.
|
||||||
|
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
@@ -473,6 +495,6 @@ and proposed extensions.
|
|||||||
[License]: https://en.wikipedia.org/wiki/MIT_License
|
[License]: https://en.wikipedia.org/wiki/MIT_License
|
||||||
[License Badge]: https://img.shields.io/badge/License-MIT-teal.svg
|
[License Badge]: https://img.shields.io/badge/License-MIT-teal.svg
|
||||||
[Travis]: https://travis-ci.org/troglobit/finit
|
[Travis]: https://travis-ci.org/troglobit/finit
|
||||||
[Travis Status]: https://travis-ci.org/troglobit/finit.png?branch=master
|
[Travis Status]: https://travis-ci.org/troglobit/finit.svg?branch=master
|
||||||
[Coverity Scan]: https://scan.coverity.com/projects/3545
|
[Coverity Scan]: https://scan.coverity.com/projects/3545
|
||||||
[Coverity Status]: https://scan.coverity.com/projects/3545/badge.svg
|
[Coverity Status]: https://scan.coverity.com/projects/3545/badge.svg
|
||||||
+6
-4
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT(Finit, 4.0-rc1, https://github.com/troglobit/finit/issues, finit, https://troglobit.com/finit.html)
|
AC_INIT(Finit, 4.0-rc2, https://github.com/troglobit/finit/issues, finit, https://troglobit.com/finit.html)
|
||||||
AC_CONFIG_AUX_DIR(aux)
|
AC_CONFIG_AUX_DIR(aux)
|
||||||
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
|
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
@@ -32,7 +32,7 @@ AC_PROG_MKDIR_P
|
|||||||
|
|
||||||
# Configuration.
|
# Configuration.
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
AC_CHECK_HEADERS([fstaby.h termios.h])
|
AC_CHECK_HEADERS([fstaby.h termios.h sys/ioctl.h])
|
||||||
AC_CHECK_FUNCS([strstr getopt getfsenty])
|
AC_CHECK_FUNCS([strstr getopt getfsenty])
|
||||||
|
|
||||||
# Check for uint[8,16,32]_t
|
# Check for uint[8,16,32]_t
|
||||||
@@ -89,11 +89,11 @@ AC_ARG_ENABLE(contrib,
|
|||||||
enable_all_plugins=auto
|
enable_all_plugins=auto
|
||||||
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
|
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
|
||||||
AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus])
|
AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus])
|
||||||
AC_PLUGIN([hotplug], [yes], [Setup and start udev or mdev hotplug daemon])
|
|
||||||
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
|
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
|
||||||
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
|
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
|
||||||
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
|
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
|
||||||
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
|
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
|
||||||
|
AC_PLUGIN([hotplug], [yes], [Setup and start udev or mdev hotplug daemon])
|
||||||
|
|
||||||
# Check for extra arguments or packages
|
# Check for extra arguments or packages
|
||||||
AC_ARG_WITH(heading,
|
AC_ARG_WITH(heading,
|
||||||
@@ -113,7 +113,7 @@ AC_ARG_WITH(rc-local,
|
|||||||
[rclocal=$withval], [rclocal=yes])
|
[rclocal=$withval], [rclocal=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(sysconfig,
|
AC_ARG_WITH(sysconfig,
|
||||||
AS_HELP_STRING([--with-sysconfig=DIR], [System environment, default /etc/default & /etc/conf.d]),
|
AS_HELP_STRING([--with-sysconfig=DIR], [System environment directory, sourced by .conf files, default /etc/default & /etc/conf.d]),
|
||||||
[sysconfig=$withval], [sysconfig=default])
|
[sysconfig=$withval], [sysconfig=default])
|
||||||
|
|
||||||
AC_ARG_WITH(hostname,
|
AC_ARG_WITH(hostname,
|
||||||
@@ -153,6 +153,8 @@ AS_IF([test "x$enable_logit" != "xno"], [
|
|||||||
AS_IF([test "x$enable_logrotate" != "xno"], [
|
AS_IF([test "x$enable_logrotate" != "xno"], [
|
||||||
AC_DEFINE(LOGROTATE_ENABLED, 1, [Enable built-in rotation of /var/log/wtmp et al.])])
|
AC_DEFINE(LOGROTATE_ENABLED, 1, [Enable built-in rotation of /var/log/wtmp et al.])])
|
||||||
|
|
||||||
|
AM_CONDITIONAL(LOGROTATE, [test "x$enable_logrotate" = "xyes"])
|
||||||
|
|
||||||
### With features ##############################################################################
|
### With features ##############################################################################
|
||||||
AS_IF([test "x$with_config" != "xno"], [
|
AS_IF([test "x$with_config" != "xno"], [
|
||||||
AS_IF([test "x$conf" = "xyes"], [
|
AS_IF([test "x$conf" = "xyes"], [
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ The current state depends on the two following conditions:
|
|||||||
|
|
||||||
A service may be stopped, or blocked, for several reasons:
|
A service may be stopped, or blocked, for several reasons:
|
||||||
|
|
||||||
- The user has manually stopped the service using `initctl stop JOB`
|
- The user has manually stopped the service using `initctl stop NAME`
|
||||||
- The program exits immediately. I.e. keeps crashing (make sure to use
|
- The program exits immediately. I.e. keeps crashing (make sure to use
|
||||||
the 'run this service in the foreground' command line option)
|
the 'run this service in the foreground' command line option)
|
||||||
- The binary is missing in the filesystem
|
- The binary is missing in the filesystem
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 7.6 KiB |
+75
-40
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <net/if.h> /* IFNAMSIZ */
|
#include <net/if.h> /* IFNAMSIZ */
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@@ -48,7 +49,7 @@ static int nlmsg_validate(struct nlmsghdr *nh, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nl_route(struct nlmsghdr *nlmsg)
|
static void nl_route(struct nlmsghdr *nlmsg, ssize_t len)
|
||||||
{
|
{
|
||||||
struct rtmsg *r;
|
struct rtmsg *r;
|
||||||
struct rtattr *a;
|
struct rtattr *a;
|
||||||
@@ -63,8 +64,14 @@ static void nl_route(struct nlmsghdr *nlmsg)
|
|||||||
r = NLMSG_DATA(nlmsg);
|
r = NLMSG_DATA(nlmsg);
|
||||||
a = RTM_RTA(r);
|
a = RTM_RTA(r);
|
||||||
la = RTM_PAYLOAD(nlmsg);
|
la = RTM_PAYLOAD(nlmsg);
|
||||||
|
if (la >= len) {
|
||||||
|
_e("Packet too large!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (RTA_OK(a, la)) {
|
while (RTA_OK(a, la)) {
|
||||||
void *data = RTA_DATA(a);
|
void *data = RTA_DATA(a);
|
||||||
|
|
||||||
switch (a->rta_type) {
|
switch (a->rta_type) {
|
||||||
case RTA_GATEWAY:
|
case RTA_GATEWAY:
|
||||||
gw = *((int *)data);
|
gw = *((int *)data);
|
||||||
@@ -105,7 +112,27 @@ static void net_cond_set(char *ifname, char *cond, int set)
|
|||||||
cond_clear(msg);
|
cond_clear(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nl_link(struct nlmsghdr *nlmsg)
|
static int validate_ifname(const char *ifname)
|
||||||
|
{
|
||||||
|
if (!ifname || !ifname[0])
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (strlen(ifname) >= IFNAMSIZ)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (strstr(ifname, ".."))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
while (*ifname) {
|
||||||
|
if (*ifname == '/' || isspace(*ifname))
|
||||||
|
return 1;
|
||||||
|
ifname++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
||||||
{
|
{
|
||||||
int la;
|
int la;
|
||||||
char ifname[IFNAMSIZ + 1];
|
char ifname[IFNAMSIZ + 1];
|
||||||
@@ -120,53 +147,61 @@ static void nl_link(struct nlmsghdr *nlmsg)
|
|||||||
i = NLMSG_DATA(nlmsg);
|
i = NLMSG_DATA(nlmsg);
|
||||||
a = (struct rtattr *)((char *)i + NLMSG_ALIGN(sizeof(struct ifinfomsg)));
|
a = (struct rtattr *)((char *)i + NLMSG_ALIGN(sizeof(struct ifinfomsg)));
|
||||||
la = NLMSG_PAYLOAD(nlmsg, sizeof(struct ifinfomsg));
|
la = NLMSG_PAYLOAD(nlmsg, sizeof(struct ifinfomsg));
|
||||||
|
if (la >= len) {
|
||||||
|
_e("Packet too large!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (RTA_OK(a, la)) {
|
for (; RTA_OK(a, la); a = RTA_NEXT(a, la)) {
|
||||||
if (a->rta_type == IFLA_IFNAME) {
|
if (a->rta_type != IFLA_IFNAME)
|
||||||
strlcpy(ifname, RTA_DATA(a), sizeof(ifname));
|
continue;
|
||||||
switch (nlmsg->nlmsg_type) {
|
|
||||||
case RTM_NEWLINK:
|
|
||||||
/*
|
|
||||||
* New interface has appeared, or interface flags has changed.
|
|
||||||
* Check ifi_flags here to see if the interface is UP/DOWN
|
|
||||||
*/
|
|
||||||
_d("%s: New link, flags 0x%x, change 0x%x", ifname, i->ifi_flags, i->ifi_change);
|
|
||||||
net_cond_set(ifname, "exist", 1);
|
|
||||||
net_cond_set(ifname, "up", i->ifi_flags & IFF_UP);
|
|
||||||
net_cond_set(ifname, "running", i->ifi_flags & IFF_RUNNING);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RTM_DELLINK:
|
strlcpy(ifname, RTA_DATA(a), sizeof(ifname));
|
||||||
/* NOTE: Interface has disappeared, not link down ... */
|
if (validate_ifname(ifname)) {
|
||||||
_d("%s: Delete link", ifname);
|
_d("Invalid interface name '%s', skipping ...", ifname);
|
||||||
net_cond_set(ifname, "exist", 0);
|
continue;
|
||||||
net_cond_set(ifname, "up", 0);
|
|
||||||
net_cond_set(ifname, "running", 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RTM_NEWADDR:
|
|
||||||
_d("%s: New Address", ifname);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RTM_DELADDR:
|
|
||||||
_d("%s: Deconfig Address", ifname);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
_d("%s: Msg 0x%x", ifname, nlmsg->nlmsg_type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a = RTA_NEXT(a, la);
|
switch (nlmsg->nlmsg_type) {
|
||||||
|
case RTM_NEWLINK:
|
||||||
|
/*
|
||||||
|
* New interface has appeared, or interface flags has changed.
|
||||||
|
* Check ifi_flags here to see if the interface is UP/DOWN
|
||||||
|
*/
|
||||||
|
_d("%s: New link, flags 0x%x, change 0x%x", ifname, i->ifi_flags, i->ifi_change);
|
||||||
|
net_cond_set(ifname, "exist", 1);
|
||||||
|
net_cond_set(ifname, "up", i->ifi_flags & IFF_UP);
|
||||||
|
net_cond_set(ifname, "running", i->ifi_flags & IFF_RUNNING);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTM_DELLINK:
|
||||||
|
/* NOTE: Interface has disappeared, not link down ... */
|
||||||
|
_d("%s: Delete link", ifname);
|
||||||
|
net_cond_set(ifname, "exist", 0);
|
||||||
|
net_cond_set(ifname, "up", 0);
|
||||||
|
net_cond_set(ifname, "running", 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTM_NEWADDR:
|
||||||
|
_d("%s: New Address", ifname);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTM_DELADDR:
|
||||||
|
_d("%s: Deconfig Address", ifname);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_d("%s: Msg 0x%x", ifname, nlmsg->nlmsg_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nl_callback(void *arg, int sd, int events)
|
static void nl_callback(void *arg, int sd, int events)
|
||||||
{
|
{
|
||||||
ssize_t len;
|
|
||||||
static char buf[4096];
|
static char buf[4096];
|
||||||
struct nlmsghdr *nh;
|
struct nlmsghdr *nh;
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
len = recv(sd, buf, sizeof(buf), 0);
|
len = recv(sd, buf, sizeof(buf), 0);
|
||||||
@@ -179,9 +214,9 @@ static void nl_callback(void *arg, int sd, int events)
|
|||||||
for (nh = (struct nlmsghdr *)buf; !nlmsg_validate(nh, len); nh = NLMSG_NEXT(nh, len)) {
|
for (nh = (struct nlmsghdr *)buf; !nlmsg_validate(nh, len); nh = NLMSG_NEXT(nh, len)) {
|
||||||
//_d("Well formed netlink message received. type %d ...", nh->nlmsg_type);
|
//_d("Well formed netlink message received. type %d ...", nh->nlmsg_type);
|
||||||
if (nh->nlmsg_type == RTM_NEWROUTE || nh->nlmsg_type == RTM_DELROUTE)
|
if (nh->nlmsg_type == RTM_NEWROUTE || nh->nlmsg_type == RTM_DELROUTE)
|
||||||
nl_route(nh);
|
nl_route(nh, len);
|
||||||
else
|
else
|
||||||
nl_link(nh);
|
nl_link(nh, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-4
@@ -151,7 +151,8 @@ static void pidfile_callback(void *arg, int fd, int events)
|
|||||||
{
|
{
|
||||||
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
|
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
|
||||||
struct inotify_event *ev;
|
struct inotify_event *ev;
|
||||||
ssize_t sz, off;
|
ssize_t sz;
|
||||||
|
size_t off;
|
||||||
|
|
||||||
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
if (sz <= 0) {
|
if (sz <= 0) {
|
||||||
@@ -160,10 +161,16 @@ static void pidfile_callback(void *arg, int fd, int events)
|
|||||||
}
|
}
|
||||||
ev_buf[sz] = 0;
|
ev_buf[sz] = 0;
|
||||||
|
|
||||||
for (off = 0; off < sz; off += sizeof(*ev) + ev->len) {
|
for (off = 0; off < (size_t)sz; off += sizeof(*ev) + ev->len) {
|
||||||
struct iwatch_path *iwp;
|
struct iwatch_path *iwp;
|
||||||
|
|
||||||
|
if (off + sizeof(*ev) > (size_t)sz)
|
||||||
|
break;
|
||||||
|
|
||||||
ev = (struct inotify_event *)&ev_buf[off];
|
ev = (struct inotify_event *)&ev_buf[off];
|
||||||
|
if (off + sizeof(*ev) + ev->len > (size_t)sz)
|
||||||
|
break;
|
||||||
|
|
||||||
if (!ev->mask)
|
if (!ev->mask)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -235,8 +242,11 @@ static void pidfile_init(void *arg)
|
|||||||
*/
|
*/
|
||||||
path = realpath(_PATH_VARRUN, NULL);
|
path = realpath(_PATH_VARRUN, NULL);
|
||||||
if (!path) {
|
if (!path) {
|
||||||
_pe("Failed ");
|
path = realpath("/run", NULL);
|
||||||
return;
|
if (!path) {
|
||||||
|
_e("System does not have %s or /run, aborting.", _PATH_VARRUN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pidfile_add_path(&iw_pidfile, path))
|
if (pidfile_add_path(&iw_pidfile, path))
|
||||||
|
|||||||
+36
-21
@@ -53,33 +53,48 @@ static void setup(void)
|
|||||||
_pe("Failed starting TTY watcher");
|
_pe("Failed starting TTY watcher");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void do_tty(char *tty, size_t len, int creat)
|
||||||
|
{
|
||||||
|
char name[len + 6];
|
||||||
|
struct tty *entry;
|
||||||
|
|
||||||
|
snprintf(name, sizeof(name), "/dev/%s", tty);
|
||||||
|
entry = tty_find(name);
|
||||||
|
if (entry && tty_enabled(entry)) {
|
||||||
|
if (creat)
|
||||||
|
tty_start(entry);
|
||||||
|
else if (entry->pid)
|
||||||
|
tty_stop(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void watcher(void *arg, int fd, int events)
|
static void watcher(void *arg, int fd, int events)
|
||||||
{
|
{
|
||||||
char buf[EVENT_SIZE];
|
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
|
||||||
int len = 0;
|
struct inotify_event *ev;
|
||||||
|
ssize_t sz;
|
||||||
|
size_t off;
|
||||||
|
|
||||||
while ((len = read(fd, buf, sizeof(buf)))) {
|
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
struct inotify_event *notified = (struct inotify_event *)buf;
|
if (sz <= 0) {
|
||||||
char name[notified->len + 6];
|
_pe("invalid inotify event");
|
||||||
struct tty *entry;
|
return;
|
||||||
|
}
|
||||||
|
ev_buf[sz] = 0;
|
||||||
|
|
||||||
if (-1 == len) {
|
for (off = 0; off < (size_t)sz; off += sizeof(*ev) + ev->len) {
|
||||||
if (errno == EINVAL)
|
if (off + sizeof(*ev) > (size_t)sz)
|
||||||
setup();
|
break;
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
break; /* Likely EAGAIN */
|
ev = (struct inotify_event *)&ev_buf[off];
|
||||||
}
|
if (off + sizeof(*ev) + ev->len > (size_t)sz)
|
||||||
|
break;
|
||||||
|
|
||||||
snprintf(name, sizeof(name), "/dev/%s", notified->name);
|
if (!ev->mask)
|
||||||
entry = tty_find(name);
|
continue;
|
||||||
if (entry && tty_enabled(entry)) {
|
|
||||||
if (notified->mask & IN_CREATE)
|
_d("tty %s, event: 0x%08x", ev->name, ev->mask);
|
||||||
tty_start(entry);
|
do_tty(ev->name, ev->len, ev->mask & IN_CREATE);
|
||||||
else if (entry->pid)
|
|
||||||
tty_stop(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-3
@@ -1,6 +1,5 @@
|
|||||||
EXTRA_DIST = cgreaper.sh rescue.conf sample.conf
|
EXTRA_DIST = cgreaper.sh rescue.conf sample.conf
|
||||||
AM_CPPFLAGS = -U_FORTIFY_SOURCE
|
AM_CPPFLAGS = -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE -D_DEFAULT_SOURCE
|
||||||
AM_CPPFLAGS += -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE -D_DEFAULT_SOURCE
|
|
||||||
if STATIC
|
if STATIC
|
||||||
AM_CPPFLAGS += -DENABLE_STATIC
|
AM_CPPFLAGS += -DENABLE_STATIC
|
||||||
AM_LDFLAGS = -static-libtool-libs
|
AM_LDFLAGS = -static-libtool-libs
|
||||||
@@ -20,8 +19,10 @@ endif
|
|||||||
|
|
||||||
if LOGIT
|
if LOGIT
|
||||||
pkglibexec_PROGRAMS = logit
|
pkglibexec_PROGRAMS = logit
|
||||||
logit_SOURCES = logit.c
|
logit_SOURCES = logit.c logrotate.c
|
||||||
logit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
logit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
||||||
|
logit_CFLAGS += $(lite_CFLAGS)
|
||||||
|
logit_LDADD = $(lite_LIBS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
finit_SOURCES = api.c cgroup.c cgroup.h \
|
finit_SOURCES = api.c cgroup.c cgroup.h \
|
||||||
@@ -43,6 +44,10 @@ finit_SOURCES = api.c cgroup.c cgroup.h \
|
|||||||
tty.c tty.h \
|
tty.c tty.h \
|
||||||
util.c util.h \
|
util.c util.h \
|
||||||
utmp-api.c utmp-api.h
|
utmp-api.c utmp-api.h
|
||||||
|
if LOGROTATE
|
||||||
|
finit_SOURCES += logrotate.c
|
||||||
|
endif
|
||||||
|
|
||||||
pkginclude_HEADERS = cond.h finit.h helpers.h log.h plugin.h svc.h
|
pkginclude_HEADERS = cond.h finit.h helpers.h log.h plugin.h svc.h
|
||||||
|
|
||||||
finit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
finit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ ev_t ev_list[] = {
|
|||||||
|
|
||||||
static void send_svc(int sd, svc_t *svc)
|
static void send_svc(int sd, svc_t *svc)
|
||||||
{
|
{
|
||||||
svc_t empty;
|
svc_t empty = { 0 };
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (!svc) {
|
if (!svc) {
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ BASE=/sys/fs/cgroup/finit
|
|||||||
PROC=`basename $1`
|
PROC=`basename $1`
|
||||||
DIR="$BASE$1"
|
DIR="$BASE$1"
|
||||||
|
|
||||||
/libexec/finit/logit -p daemon.info -t finit "$PROC stopped, cleaning up control group $DIR"
|
#/libexec/finit/logit -p daemon.info -t finit "$PROC stopped, cleaning up control group $DIR"
|
||||||
rmdir $DIR
|
rmdir $DIR
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
+15
-10
@@ -27,6 +27,7 @@
|
|||||||
#include <lite/lite.h>
|
#include <lite/lite.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
|
|
||||||
|
#include "finit.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ void cgroup_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Skip first line, header */
|
/* Skip first line, header */
|
||||||
fgets(buf, sizeof(buf), fp);
|
(void)fgets(buf, sizeof(buf), fp);
|
||||||
while (fgets(buf, sizeof(buf), fp)) {
|
while (fgets(buf, sizeof(buf), fp)) {
|
||||||
char *cgroup;
|
char *cgroup;
|
||||||
char rc[80];
|
char rc[80];
|
||||||
@@ -70,27 +71,27 @@ void cgroup_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Default cgroups for process monitoring */
|
/* Default cgroups for process monitoring */
|
||||||
if (mkdir("/sys/fs/cgroup/finit", 0755) && EEXIST != errno)
|
if (mkdir(FINIT_CGPATH, 0755) && EEXIST != errno)
|
||||||
goto fail;
|
goto fail;
|
||||||
if (mount("none", "/sys/fs/cgroup/finit", "cgroup", opts, "none,name=finit")) {
|
if (mount("none", FINIT_CGPATH, "cgroup", opts, "none,name=finit")) {
|
||||||
_pe("Failed mounting Finit cgroup hierarchy");
|
_pe("Failed mounting Finit cgroup hierarchy");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up reaper and enable callbacks */
|
/* Set up reaper and enable callbacks */
|
||||||
echo("/sys/fs/cgroup/finit/release_agent", 0, FINIT_LIBPATH_ "/cgreaper.sh");
|
echo(FINIT_CGPATH "/release_agent", 0, FINIT_LIBPATH_ "/cgreaper.sh");
|
||||||
echo("/sys/fs/cgroup/finit/notify_on_release", 0, "1");
|
echo(FINIT_CGPATH "/notify_on_release", 0, "1");
|
||||||
|
|
||||||
/* Default groups, PID 1, services, and user/login processes */
|
/* Default groups, PID 1, services, and user/login processes */
|
||||||
if (mkdir("/sys/fs/cgroup/finit/init", 0755) && EEXIST != errno)
|
if (mkdir(FINIT_CGPATH "/init", 0755) && EEXIST != errno)
|
||||||
goto fail;
|
goto fail;
|
||||||
if (mkdir("/sys/fs/cgroup/finit/system", 0755) && EEXIST != errno)
|
if (mkdir(FINIT_CGPATH "/system", 0755) && EEXIST != errno)
|
||||||
goto fail;
|
goto fail;
|
||||||
if (mkdir("/sys/fs/cgroup/finit/user", 0755) && EEXIST != errno)
|
if (mkdir(FINIT_CGPATH "/user", 0755) && EEXIST != errno)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* Move ourselves to init */
|
/* Move ourselves to init */
|
||||||
echo("/sys/fs/cgroup/finit/init/cgroup.procs", 0, "1");
|
echo(FINIT_CGPATH "/init/cgroup.procs", 0, "1");
|
||||||
|
|
||||||
/* We have signal, main screen turn on! */
|
/* We have signal, main screen turn on! */
|
||||||
cg_init = 1;
|
cg_init = 1;
|
||||||
@@ -102,7 +103,11 @@ static int move_pid(char *group, char *name, char *id, int pid)
|
|||||||
{
|
{
|
||||||
char path[256];
|
char path[256];
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/sys/fs/cgroup/%s/%s:%s", group, name, id);
|
snprintf(path, sizeof(path), "/sys/fs/cgroup/%s/%s", group, name);
|
||||||
|
if (id && strlen(id)) {
|
||||||
|
strlcat(path, ":", sizeof(path));
|
||||||
|
strlcat(path, id, sizeof(path));
|
||||||
|
}
|
||||||
if (mkdir(path, 0755) && errno != EEXIST)
|
if (mkdir(path, 0755) && errno != EEXIST)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|||||||
@@ -162,26 +162,6 @@ int cond_set_path(const char *path, enum cond_state new)
|
|||||||
return new != old;
|
return new != old;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Has condition in configuration and cond is allowed? */
|
|
||||||
static int svc_has_cond(svc_t *svc)
|
|
||||||
{
|
|
||||||
if (!svc->cond[0])
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
switch (svc->type) {
|
|
||||||
case SVC_TYPE_SERVICE:
|
|
||||||
case SVC_TYPE_TASK:
|
|
||||||
case SVC_TYPE_RUN:
|
|
||||||
case SVC_TYPE_SYSV:
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cond_update(const char *name)
|
static void cond_update(const char *name)
|
||||||
{
|
{
|
||||||
svc_t *svc, *iter = NULL;
|
svc_t *svc, *iter = NULL;
|
||||||
|
|||||||
+35
-21
@@ -47,6 +47,7 @@
|
|||||||
int logfile_size_max = 200000; /* 200 kB */
|
int logfile_size_max = 200000; /* 200 kB */
|
||||||
int logfile_count_max = 5;
|
int logfile_count_max = 5;
|
||||||
|
|
||||||
|
struct rlimit initial_rlimit[RLIMIT_NLIMITS];
|
||||||
struct rlimit global_rlimit[RLIMIT_NLIMITS];
|
struct rlimit global_rlimit[RLIMIT_NLIMITS];
|
||||||
|
|
||||||
struct conf_change {
|
struct conf_change {
|
||||||
@@ -78,14 +79,14 @@ static void hide_args(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_bool(char *ptr, int default_value)
|
int get_bool(char *arg, int default_value)
|
||||||
{
|
{
|
||||||
if (!ptr)
|
if (!arg)
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
|
||||||
if (string_compare(ptr, "true") || string_compare(ptr, "on") || string_compare(ptr, "1"))
|
if (string_compare(arg, "true") || string_compare(arg, "on") || string_compare(arg, "1"))
|
||||||
return 1;
|
return 1;
|
||||||
if (string_compare(ptr, "false") || string_compare(ptr, "off") || string_compare(ptr, "0"))
|
if (string_compare(arg, "false") || string_compare(arg, "off") || string_compare(arg, "0"))
|
||||||
return 0;
|
return 0;
|
||||||
fallback:
|
fallback:
|
||||||
return default_value;
|
return default_value;
|
||||||
@@ -97,19 +98,24 @@ fallback:
|
|||||||
*/
|
*/
|
||||||
static void parse_finit_opts(char *opt)
|
static void parse_finit_opts(char *opt)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *arg;
|
||||||
|
|
||||||
ptr = strchr(opt, '=');
|
arg = strchr(opt, '=');
|
||||||
if (ptr)
|
if (arg)
|
||||||
*ptr++ = 0;
|
*arg++ = 0;
|
||||||
|
|
||||||
if (string_compare(opt, "debug")) {
|
if (string_compare(opt, "debug")) {
|
||||||
debug = get_bool(ptr, 1);
|
debug = get_bool(arg, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string_compare(opt, "status_style")) {
|
if (string_compare(opt, "status_style")) {
|
||||||
if (string_compare(ptr, "old") || string_compare(ptr, "classic"))
|
if (!arg) {
|
||||||
|
_e("status_style option requires an argument, skipping.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string_compare(arg, "old") || string_compare(arg, "classic"))
|
||||||
show_progress(PROGRESS_CLASSIC);
|
show_progress(PROGRESS_CLASSIC);
|
||||||
else
|
else
|
||||||
show_progress(PROGRESS_MODERN);
|
show_progress(PROGRESS_MODERN);
|
||||||
@@ -117,7 +123,7 @@ static void parse_finit_opts(char *opt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (string_compare(opt, "show_status")) {
|
if (string_compare(opt, "show_status")) {
|
||||||
show_progress(get_bool(ptr, 1) ? PROGRESS_DEFAULT : PROGRESS_SILENT);
|
show_progress(get_bool(arg, 1) ? PROGRESS_DEFAULT : PROGRESS_SILENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -620,12 +626,9 @@ int conf_reload(void)
|
|||||||
tty_mark();
|
tty_mark();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get current global limits, which may be overridden from both
|
* Reset global rlimit to bootstrap values from conf_init().
|
||||||
* finit.conf, for Finit and its services like getty+watchdogd,
|
|
||||||
* and *.conf in finit.d/, for each service(s) listed there.
|
|
||||||
*/
|
*/
|
||||||
for (int i = 0; i < RLIMIT_NLIMITS; i++)
|
memcpy(global_rlimit, initial_rlimit, sizeof(global_rlimit));
|
||||||
getrlimit(i, &global_rlimit[i]);
|
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
int rc;
|
int rc;
|
||||||
@@ -694,6 +697,8 @@ int conf_reload(void)
|
|||||||
|
|
||||||
globfree(&gl);
|
globfree(&gl);
|
||||||
|
|
||||||
|
/* Mark any reverse deps as chenaged. */
|
||||||
|
service_update_rdeps();
|
||||||
done:
|
done:
|
||||||
/* Drop record of all .conf changes */
|
/* Drop record of all .conf changes */
|
||||||
drop_changes();
|
drop_changes();
|
||||||
@@ -716,7 +721,6 @@ static struct conf_change *conf_find(char *file)
|
|||||||
struct conf_change *node, *tmp;
|
struct conf_change *node, *tmp;
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(node, &conf_change_list, link, tmp) {
|
TAILQ_FOREACH_SAFE(node, &conf_change_list, link, tmp) {
|
||||||
_d("file: %s vs changed file: %s", file, node->name);
|
|
||||||
if (string_compare(node->name, file))
|
if (string_compare(node->name, file))
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@@ -801,7 +805,8 @@ static void conf_cb(uev_t *w, void *arg, int events)
|
|||||||
{
|
{
|
||||||
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
|
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
|
||||||
struct inotify_event *ev;
|
struct inotify_event *ev;
|
||||||
ssize_t sz, off;
|
ssize_t sz;
|
||||||
|
size_t off;
|
||||||
|
|
||||||
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
|
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
if (sz <= 0) {
|
if (sz <= 0) {
|
||||||
@@ -810,10 +815,16 @@ static void conf_cb(uev_t *w, void *arg, int events)
|
|||||||
}
|
}
|
||||||
ev_buf[sz] = 0;
|
ev_buf[sz] = 0;
|
||||||
|
|
||||||
for (off = 0; off < sz; off += sizeof(*ev) + ev->len) {
|
for (off = 0; off < (size_t)sz; off += sizeof(*ev) + ev->len) {
|
||||||
struct iwatch_path *iwp;
|
struct iwatch_path *iwp;
|
||||||
|
|
||||||
|
if (off + sizeof(*ev) > (size_t)sz)
|
||||||
|
break;
|
||||||
|
|
||||||
ev = (struct inotify_event *)&ev_buf[off];
|
ev = (struct inotify_event *)&ev_buf[off];
|
||||||
|
if (off + sizeof(*ev) + ev->len > (size_t)sz)
|
||||||
|
break;
|
||||||
|
|
||||||
if (!ev->mask)
|
if (!ev->mask)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -883,8 +894,11 @@ int conf_init(uev_ctx_t *ctx)
|
|||||||
* finit.conf, for Finit and its services like getty+watchdogd,
|
* finit.conf, for Finit and its services like getty+watchdogd,
|
||||||
* and *.conf in finit.d/, for each service(s) listed there.
|
* and *.conf in finit.d/, for each service(s) listed there.
|
||||||
*/
|
*/
|
||||||
for (int i = 0; i < RLIMIT_NLIMITS; i++)
|
for (int i = 0; i < RLIMIT_NLIMITS; i++) {
|
||||||
getrlimit(i, &global_rlimit[i]);
|
if (getrlimit(i, &initial_rlimit[i]))
|
||||||
|
logit(LOG_WARNING, "rlimit: Failed reading setting %s: %s",
|
||||||
|
rlim2str(i), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
/* prepare /etc watcher */
|
/* prepare /etc watcher */
|
||||||
fd = iwatch_init(&iw_conf);
|
fd = iwatch_init(&iw_conf);
|
||||||
|
|||||||
+18
-10
@@ -179,7 +179,8 @@ static void fs_remount_root(int fsckerr)
|
|||||||
* XXX: Untested, in the initramfs age we should
|
* XXX: Untested, in the initramfs age we should
|
||||||
* probably use switch_root instead.
|
* probably use switch_root instead.
|
||||||
*/
|
*/
|
||||||
rc = mount(SYSROOT, "/", NULL, MS_MOVE, NULL);
|
if (mount(SYSROOT, "/", NULL, MS_MOVE, NULL))
|
||||||
|
_pe("Failed %s / MS_MOVE");
|
||||||
}
|
}
|
||||||
#endif /* SYSROOT */
|
#endif /* SYSROOT */
|
||||||
|
|
||||||
@@ -206,6 +207,9 @@ static void fs_mount(void)
|
|||||||
* for early multi-console, and /sys for the cgroups support. Any
|
* for early multi-console, and /sys for the cgroups support. Any
|
||||||
* occurrence of these file systems in /etc/fstab will replace these
|
* occurrence of these file systems in /etc/fstab will replace these
|
||||||
* mounts later in fs_mount()
|
* mounts later in fs_mount()
|
||||||
|
*
|
||||||
|
* Ignore any mount errors with EBUSY, kernel likely alread mounted
|
||||||
|
* the filesystem for us automatically, e.g., CONFIG_DEVTMPFS_MOUNT.
|
||||||
*/
|
*/
|
||||||
static void fs_init(void)
|
static void fs_init(void)
|
||||||
{
|
{
|
||||||
@@ -218,8 +222,13 @@ static void fs_init(void)
|
|||||||
};
|
};
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < NELEMS(fs); i++)
|
for (i = 0; i < NELEMS(fs); i++) {
|
||||||
mount(fs[i].spec, fs[i].file, fs[i].type, 0, NULL);
|
int rc;
|
||||||
|
|
||||||
|
rc = mount(fs[i].spec, fs[i].file, fs[i].type, 0, NULL);
|
||||||
|
if (rc && errno != EBUSY)
|
||||||
|
_pe("Failed mounting %s on %s", fs[i].spec, fs[i].file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -475,13 +484,10 @@ int main(int argc, char *argv[])
|
|||||||
setenv("PATH", _PATH_STDPATH, 1);
|
setenv("PATH", _PATH_STDPATH, 1);
|
||||||
setenv("SHELL", _PATH_BSHELL, 1);
|
setenv("SHELL", _PATH_BSHELL, 1);
|
||||||
|
|
||||||
chdir("/");
|
if (chdir("/"))
|
||||||
|
_pe("Failed cd /");
|
||||||
umask(0);
|
umask(0);
|
||||||
|
|
||||||
/* Set up canvas */
|
|
||||||
if (!rescue && !debug)
|
|
||||||
screen_init();
|
|
||||||
|
|
||||||
/* Allow progress, if enabled */
|
/* Allow progress, if enabled */
|
||||||
enable_progress(1);
|
enable_progress(1);
|
||||||
|
|
||||||
@@ -490,8 +496,10 @@ int main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
emergency_shell();
|
emergency_shell();
|
||||||
|
|
||||||
/* Load plugins early, the first hook is in banner(), so we
|
/*
|
||||||
* need plugins loaded before calling it. */
|
* Load plugins early, the first hook is in banner(), so we
|
||||||
|
* need plugins loaded before calling it.
|
||||||
|
*/
|
||||||
plugin_init(&loop);
|
plugin_init(&loop);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+6
-2
@@ -38,11 +38,15 @@
|
|||||||
|
|
||||||
/* just in case */
|
/* just in case */
|
||||||
#ifndef _PATH_STDPATH
|
#ifndef _PATH_STDPATH
|
||||||
#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
|
#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _PATH_VARRUN
|
#ifndef _PATH_VARRUN
|
||||||
#define _PATH_VARRUN "/var/run/"
|
#define _PATH_VARRUN "/var/run/"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FINIT_CGPATH
|
||||||
|
#define FINIT_CGPATH "/sys/fs/cgroup/finit"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LOGIT_PATH FINIT_LIBPATH_ "/logit"
|
#define LOGIT_PATH FINIT_LIBPATH_ "/logit"
|
||||||
|
|||||||
+15
-7
@@ -121,7 +121,7 @@ static void add_console(char *cons)
|
|||||||
num_cons++;
|
num_cons++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void console_init(void)
|
static void find_active_consoles(void)
|
||||||
{
|
{
|
||||||
char *cons, *ptr, *tok;
|
char *cons, *ptr, *tok;
|
||||||
char buf[512];
|
char buf[512];
|
||||||
@@ -148,6 +148,12 @@ void console_init(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void console_init(void)
|
||||||
|
{
|
||||||
|
find_active_consoles();
|
||||||
|
screen_init();
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t cprintf(const char *fmt, ...)
|
ssize_t cprintf(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
const size_t len = strlen(fmt) * 2;
|
const size_t len = strlen(fmt) * 2;
|
||||||
@@ -426,14 +432,14 @@ void set_hostname(char **hostname)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fgets(*hostname, st.st_size, fp);
|
if (fgets(*hostname, st.st_size, fp))
|
||||||
chomp(*hostname);
|
chomp(*hostname);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (*hostname)
|
if (*hostname)
|
||||||
sethostname(*hostname, strlen(*hostname));
|
(void)sethostname(*hostname, strlen(*hostname));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -557,10 +563,12 @@ int ismnt(char *file, char *dir, char *mode)
|
|||||||
|
|
||||||
while ((mnt = getmntent(fp))) {
|
while ((mnt = getmntent(fp))) {
|
||||||
if (!strcmp(mnt->mnt_dir, dir)) {
|
if (!strcmp(mnt->mnt_dir, dir)) {
|
||||||
if (mode && hasopt(mnt->mnt_opts, mode))
|
if (mode) {
|
||||||
found = 1;
|
if (hasopt(mnt->mnt_opts, mode))
|
||||||
else
|
found = 1;
|
||||||
|
} else
|
||||||
found = 1;
|
found = 1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+171
-105
@@ -26,6 +26,7 @@
|
|||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <ftw.h>
|
#include <ftw.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -43,6 +44,11 @@
|
|||||||
|
|
||||||
#define _PATH_COND _PATH_VARRUN "finit/cond/"
|
#define _PATH_COND _PATH_VARRUN "finit/cond/"
|
||||||
|
|
||||||
|
#define NONE " "
|
||||||
|
#define PIPE plain ? "|" : "│"
|
||||||
|
#define FORK plain ? "|-" : "├─"
|
||||||
|
#define END plain ? "`-" : "└─"
|
||||||
|
|
||||||
struct command {
|
struct command {
|
||||||
char *cmd;
|
char *cmd;
|
||||||
int (*cb)(char *arg);
|
int (*cb)(char *arg);
|
||||||
@@ -51,8 +57,8 @@ struct command {
|
|||||||
int icreate = 0;
|
int icreate = 0;
|
||||||
int iforce = 0;
|
int iforce = 0;
|
||||||
int heading = 1;
|
int heading = 1;
|
||||||
int numeric = 0;
|
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
|
int plain = 0;
|
||||||
int runlevel = 0;
|
int runlevel = 0;
|
||||||
int iw, pw;
|
int iw, pw;
|
||||||
|
|
||||||
@@ -72,11 +78,7 @@ static void col_widths(void)
|
|||||||
for (svc = client_svc_iterator(1); svc; svc = client_svc_iterator(0)) {
|
for (svc = client_svc_iterator(1); svc; svc = client_svc_iterator(0)) {
|
||||||
int w, p;
|
int w, p;
|
||||||
|
|
||||||
if (!numeric)
|
svc_ident(svc, ident, sizeof(ident));
|
||||||
svc_ident(svc, ident, sizeof(ident));
|
|
||||||
else
|
|
||||||
svc_jobid(svc, ident, sizeof(ident));
|
|
||||||
|
|
||||||
w = (int)strlen(ident);
|
w = (int)strlen(ident);
|
||||||
if (w > iw)
|
if (w > iw)
|
||||||
iw = w;
|
iw = w;
|
||||||
@@ -143,10 +145,9 @@ static int do_runlevel(char *arg)
|
|||||||
struct init_request rq = {
|
struct init_request rq = {
|
||||||
.magic = INIT_MAGIC,
|
.magic = INIT_MAGIC,
|
||||||
.cmd = INIT_CMD_RUNLVL,
|
.cmd = INIT_CMD_RUNLVL,
|
||||||
.runlevel = (int)arg[0],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!rq.runlevel) {
|
if (!arg) {
|
||||||
int prevlevel = 0;
|
int prevlevel = 0;
|
||||||
int runlevel;
|
int runlevel;
|
||||||
char prev;
|
char prev;
|
||||||
@@ -165,6 +166,9 @@ static int do_runlevel(char *arg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* set runlevel */
|
||||||
|
rq.runlevel = (int)arg[0];
|
||||||
|
|
||||||
return client_send(&rq, sizeof(rq));
|
return client_send(&rq, sizeof(rq));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,10 +199,17 @@ static int do_startstop(int cmd, char *arg)
|
|||||||
.cmd = INIT_CMD_SVC_QUERY
|
.cmd = INIT_CMD_SVC_QUERY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!arg || !arg[0])
|
||||||
|
errx(1, "missing argument to %s", (cmd == INIT_CMD_START_SVC
|
||||||
|
? "start"
|
||||||
|
: (cmd == INIT_CMD_STOP_SVC
|
||||||
|
? "stop"
|
||||||
|
: "restart")));
|
||||||
|
|
||||||
strlcpy(rq.data, arg, sizeof(rq.data));
|
strlcpy(rq.data, arg, sizeof(rq.data));
|
||||||
if (client_send(&rq, sizeof(rq))) {
|
if (client_send(&rq, sizeof(rq))) {
|
||||||
fprintf(stderr, "No such job(s) or service(s): %s\n\n", rq.data);
|
fprintf(stderr, "No such task or service(s): %s\n\n", arg);
|
||||||
fprintf(stderr, "Usage: initctl %s <JOB|NAME>[:ID]\n",
|
fprintf(stderr, "Usage: initctl %s <NAME>[:ID]\n",
|
||||||
cmd == INIT_CMD_START_SVC ? "start" :
|
cmd == INIT_CMD_START_SVC ? "start" :
|
||||||
(cmd == INIT_CMD_STOP_SVC ? "stop" : "restart"));
|
(cmd == INIT_CMD_STOP_SVC ? "stop" : "restart"));
|
||||||
return 1;
|
return 1;
|
||||||
@@ -314,11 +325,7 @@ static int do_cond_show(char *arg)
|
|||||||
|
|
||||||
cond = cond_get_agg(svc->cond);
|
cond = cond_get_agg(svc->cond);
|
||||||
|
|
||||||
if (!numeric)
|
svc_ident(svc, ident, sizeof(ident));
|
||||||
svc_ident(svc, ident, sizeof(ident));
|
|
||||||
else
|
|
||||||
svc_jobid(svc, ident, sizeof(ident));
|
|
||||||
|
|
||||||
printf("%-*d %-*s ", pw, svc->pid, iw, ident);
|
printf("%-*d %-*s ", pw, svc->pid, iw, ident);
|
||||||
|
|
||||||
if (cond == COND_ON)
|
if (cond == COND_ON)
|
||||||
@@ -343,6 +350,9 @@ static int do_cond(char *cmd)
|
|||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!cmd)
|
||||||
|
goto fallback;
|
||||||
|
|
||||||
arg = strpbrk(cmd, " \0");
|
arg = strpbrk(cmd, " \0");
|
||||||
if (arg)
|
if (arg)
|
||||||
*arg++ = 0;
|
*arg++ = 0;
|
||||||
@@ -352,6 +362,7 @@ static int do_cond(char *cmd)
|
|||||||
return command[c].cb(arg);
|
return command[c].cb(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fallback:
|
||||||
return do_cond_show(NULL);
|
return do_cond_show(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,9 +489,24 @@ char *runlevel_string(int runlevel, int levels)
|
|||||||
return lvl;
|
return lvl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *svc_command(svc_t *svc, char *cmd, size_t len)
|
||||||
|
{
|
||||||
|
strlcpy(cmd, svc->cmd, len);
|
||||||
|
for (int i = 1; i < MAX_NUM_SVC_ARGS; i++) {
|
||||||
|
if (!svc->args[i][0])
|
||||||
|
break;
|
||||||
|
|
||||||
|
strlcat(cmd, " ", len);
|
||||||
|
strlcat(cmd, svc->args[i], len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
static int show_status(char *arg)
|
static int show_status(char *arg)
|
||||||
{
|
{
|
||||||
char ident[MAX_IDENT_LEN];
|
char ident[MAX_IDENT_LEN];
|
||||||
|
char cmd[512];
|
||||||
svc_t *svc;
|
svc_t *svc;
|
||||||
|
|
||||||
runlevel = runlevel_get(NULL);
|
runlevel = runlevel_get(NULL);
|
||||||
@@ -493,11 +519,11 @@ static int show_status(char *arg)
|
|||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
printf("Job : %d\n", svc->job);
|
|
||||||
printf("Service : %s\n", svc->cmd);
|
|
||||||
printf("Description : %s\n", svc->desc);
|
|
||||||
printf("Identity : %s\n", svc_ident(svc, ident, sizeof(ident)));
|
printf("Identity : %s\n", svc_ident(svc, ident, sizeof(ident)));
|
||||||
|
printf("Description : %s\n", svc->desc);
|
||||||
|
printf("Origin : %s\n", svc->file[0] ? svc->file : "built-in");
|
||||||
printf("Environment : %s\n", svc->env);
|
printf("Environment : %s\n", svc->env);
|
||||||
|
printf("Command : %s\n", svc_command(svc, cmd, sizeof(cmd)));
|
||||||
printf("PID : %d\n", svc->pid);
|
printf("PID : %d\n", svc->pid);
|
||||||
printf("Uptime : %s\n", svc->pid ? uptime(now - svc->start_time, buf, sizeof(buf)) : buf);
|
printf("Uptime : %s\n", svc->pid ? uptime(now - svc->start_time, buf, sizeof(buf)) : buf);
|
||||||
printf("Runlevels : %s\n", runlevel_string(runlevel, svc->runlevels));
|
printf("Runlevels : %s\n", runlevel_string(runlevel, svc->runlevels));
|
||||||
@@ -523,15 +549,10 @@ static int show_status(char *arg)
|
|||||||
|
|
||||||
for (svc = client_svc_iterator(1); svc; svc = client_svc_iterator(0)) {
|
for (svc = client_svc_iterator(1); svc; svc = client_svc_iterator(0)) {
|
||||||
char *lvls;
|
char *lvls;
|
||||||
int i;
|
|
||||||
|
|
||||||
printf("%-*d ", pw, svc->pid);
|
printf("%-*d ", pw, svc->pid);
|
||||||
|
|
||||||
if (!numeric)
|
svc_ident(svc, ident, sizeof(ident));
|
||||||
svc_ident(svc, ident, sizeof(ident));
|
|
||||||
else
|
|
||||||
svc_jobid(svc, ident, sizeof(ident));
|
|
||||||
|
|
||||||
printf("%-*s %-8s ", iw, ident, svc_status(svc));
|
printf("%-*s %-8s ", iw, ident, svc_status(svc));
|
||||||
|
|
||||||
lvls = runlevel_string(runlevel, svc->runlevels);
|
lvls = runlevel_string(runlevel, svc->runlevels);
|
||||||
@@ -540,89 +561,124 @@ static int show_status(char *arg)
|
|||||||
else
|
else
|
||||||
printf("%-12.12s ", lvls);
|
printf("%-12.12s ", lvls);
|
||||||
|
|
||||||
if (!verbose) {
|
if (!verbose)
|
||||||
printf("%s\n", svc->desc);
|
puts(svc->desc);
|
||||||
} else {
|
else
|
||||||
char args[CMD_SIZE] = "";
|
puts(svc_command(svc, cmd, sizeof(cmd)));
|
||||||
|
|
||||||
for (i = 1; i < MAX_NUM_SVC_ARGS; i++) {
|
|
||||||
if (strlen(svc->args[i]) == 0)
|
|
||||||
continue;
|
|
||||||
if (args[0])
|
|
||||||
strlcat(args, " ", sizeof(args));
|
|
||||||
strlcat(args, svc->args[i], sizeof(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s %s\n", svc->cmd, args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dump_cgroup(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf)
|
static int cgroup_filter(const struct dirent *entry)
|
||||||
{
|
{
|
||||||
|
/* Skip current dir ".", and prev 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;
|
||||||
|
|
||||||
|
if (entry->d_name[0] == '.')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (entry->d_type != DT_DIR)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dump_cgroup(char *path, char *pfx)
|
||||||
|
{
|
||||||
|
struct dirent **namelist = NULL;
|
||||||
|
struct stat st;
|
||||||
|
char buf[512];
|
||||||
|
int rc = 0;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *group;
|
int i, n;
|
||||||
char path[256];
|
int num;
|
||||||
char buf[256];
|
|
||||||
int user = 0;
|
|
||||||
int num = 0;
|
|
||||||
|
|
||||||
if (tflag == FTW_F)
|
if (-1 == lstat(path, &st))
|
||||||
return 0;
|
return 1;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/cgroup.procs", fpath);
|
if ((st.st_mode & S_IFMT) != S_IFDIR) {
|
||||||
fp = fopen(path, "r");
|
errno = ENOTDIR;
|
||||||
if (!fp)
|
return -1;
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (strstr(fpath, "finit/user"))
|
|
||||||
user = 1;
|
|
||||||
|
|
||||||
group = strrchr(fpath, '/');
|
|
||||||
if (!group)
|
|
||||||
goto err;
|
|
||||||
group++;
|
|
||||||
|
|
||||||
while (fgets(buf, sizeof(buf), fp)) {
|
|
||||||
FILE *cfp;
|
|
||||||
int pid;
|
|
||||||
|
|
||||||
if (num == 0)
|
|
||||||
printf("%c :- %s/", user ? ' ' : '|', group);
|
|
||||||
num++;
|
|
||||||
|
|
||||||
pid = atoi(chomp(buf));
|
|
||||||
snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
|
|
||||||
cfp = fopen(path, "r");
|
|
||||||
if (!cfp)
|
|
||||||
continue;
|
|
||||||
fgets(buf, sizeof(buf), cfp);
|
|
||||||
fclose(cfp);
|
|
||||||
|
|
||||||
printf("\n%c :- %d %s", user ? ' ' : '|', pid, buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err:
|
fp = fopenf("r", "%s/cgroup.procs", path);
|
||||||
fclose(fp);
|
if (!fp)
|
||||||
if (num)
|
return -1;
|
||||||
printf("\r%c\n", user ? ' ' : '|');
|
num = 0;
|
||||||
|
while (fgets(buf, sizeof(buf), fp))
|
||||||
|
num++;
|
||||||
|
|
||||||
return 0;
|
if (!pfx) {
|
||||||
|
pfx = "";
|
||||||
|
puts(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
n = scandir(path, &namelist, cgroup_filter, alphasort);
|
||||||
|
if (n > 0) {
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
char *nm = namelist[i]->d_name;
|
||||||
|
char dir[80];
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%s/%s", path, nm);
|
||||||
|
|
||||||
|
if (i + 1 == n) {
|
||||||
|
printf("%s%s ", pfx, END);
|
||||||
|
snprintf(dir, sizeof(dir), "%s ", pfx);
|
||||||
|
} else {
|
||||||
|
printf("%s%s ", pfx, FORK);
|
||||||
|
snprintf(dir, sizeof(dir), "%s%s ", pfx, PIPE);
|
||||||
|
}
|
||||||
|
puts(nm);
|
||||||
|
|
||||||
|
rc += dump_cgroup(buf, dir);
|
||||||
|
|
||||||
|
free(namelist[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(namelist);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num > 0) {
|
||||||
|
rewind(fp);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (fgets(buf, sizeof(buf), fp)) {
|
||||||
|
FILE *cfp;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
pid = atoi(chomp(buf));
|
||||||
|
cfp = fopenf("r", "/proc/%d/cmdline", pid);
|
||||||
|
if (!cfp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fgets(buf, sizeof(buf), cfp))
|
||||||
|
printf("%s%s %d %s\n", pfx, ++i == num ? END : FORK, pid, buf);
|
||||||
|
fclose(cfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int show_cgroup(char *arg)
|
static int show_cgroup(char *arg)
|
||||||
{
|
{
|
||||||
puts("finit/");
|
char path[512];
|
||||||
puts("|- init/");
|
|
||||||
nftw("/sys/fs/cgroup/finit/init", dump_cgroup, 20, 0);
|
|
||||||
puts("|- system/");
|
|
||||||
nftw("/sys/fs/cgroup/finit/system", dump_cgroup, 20, 0);
|
|
||||||
puts("`- user/");
|
|
||||||
nftw("/sys/fs/cgroup/finit/user", dump_cgroup, 20, 0);
|
|
||||||
|
|
||||||
return 0;
|
if (!arg)
|
||||||
|
arg = FINIT_CGPATH;
|
||||||
|
else if (arg[0] != '/') {
|
||||||
|
paste(path, sizeof(path), FINIT_CGPATH, arg);
|
||||||
|
arg = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dump_cgroup(arg, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int transform(char *nm)
|
static int transform(char *nm)
|
||||||
@@ -669,7 +725,6 @@ static int usage(int rc)
|
|||||||
" -b, --batch Batch mode, no screen size probing\n"
|
" -b, --batch Batch mode, no screen size probing\n"
|
||||||
" -c, --create Create missing paths (and files) as needed\n"
|
" -c, --create Create missing paths (and files) as needed\n"
|
||||||
" -f, --force Ignore missing files and arguments, never prompt\n"
|
" -f, --force Ignore missing files and arguments, never prompt\n"
|
||||||
" -n, --numeric Show JOB:ID instead of NAME:ID\n"
|
|
||||||
" -t, --no-heading Skip table headings\n"
|
" -t, --no-heading Skip table headings\n"
|
||||||
" -v, --verbose Verbose output\n"
|
" -v, --verbose Verbose output\n"
|
||||||
" -h, --help This help text\n"
|
" -h, --help This help text\n"
|
||||||
@@ -685,9 +740,14 @@ static int usage(int rc)
|
|||||||
" ls | list List all .conf in " FINIT_RCSD "\n"
|
" ls | list List all .conf in " FINIT_RCSD "\n"
|
||||||
" create <CONF> Create .conf in %s\n"
|
" create <CONF> Create .conf in %s\n"
|
||||||
" delete <CONF> Delete .conf in %s\n"
|
" delete <CONF> Delete .conf in %s\n"
|
||||||
|
" show <CONF> Show .conf in %s\n"
|
||||||
" edit <CONF> Edit .conf in %s\n"
|
" edit <CONF> Edit .conf in %s\n"
|
||||||
" touch <CONF> Change .conf in %s\n",
|
" touch <CONF> Change .conf in %s\n",
|
||||||
avail, avail, avail, avail);
|
avail, avail, avail, avail, avail);
|
||||||
|
else
|
||||||
|
fprintf(stderr,
|
||||||
|
" show Show %s\n", FINIT_CONF);
|
||||||
|
|
||||||
if (has_ena)
|
if (has_ena)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
" enable <CONF> Enable .conf in %s\n", avail);
|
" enable <CONF> Enable .conf in %s\n", avail);
|
||||||
@@ -702,17 +762,17 @@ static int usage(int rc)
|
|||||||
" reload Reload " FINIT_CONF " (activate changes)\n");
|
" reload Reload " FINIT_CONF " (activate changes)\n");
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
// " reload <JOB|NAME>[:ID] Reload (SIGHUP) service by job# or name\n"
|
// " reload <NAME>[:ID] Reload (SIGHUP) service by name\n"
|
||||||
"\n"
|
"\n"
|
||||||
" cond show Show condition status\n"
|
" cond show Show condition status\n"
|
||||||
" cond dump Dump all conditions and their status\n"
|
" cond dump Dump all conditions and their status\n"
|
||||||
"\n"
|
"\n"
|
||||||
" log [NAME] Show ten last Finit, or NAME, messages from syslog\n"
|
" log [NAME] Show ten last Finit, or NAME, messages from syslog\n"
|
||||||
" start <JOB|NAME>[:ID] Start service by job# or name, with optional ID\n"
|
" start <NAME>[:ID] Start service by name, with optional ID\n"
|
||||||
" stop <JOB|NAME>[:ID] Stop/Pause a running service by job# or name\n"
|
" stop <NAME>[:ID] Stop/Pause a running service by name\n"
|
||||||
" restart <JOB|NAME>[:ID] Restart (stop/start) service by job# or name\n"
|
" restart <NAME>[:ID] Restart (stop/start) service by name\n"
|
||||||
" status <JOB|NAME>[:ID] Show service status, by job# or name\n"
|
" status <NAME>[:ID] Show service status, by name\n"
|
||||||
" status | show Show status of services, default command\n"
|
" status Show status of services, default command\n"
|
||||||
"\n"
|
"\n"
|
||||||
" ps List processes based on cgroups\n"
|
" ps List processes based on cgroups\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -733,6 +793,15 @@ static int usage(int rc)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_devel(char *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
printf("Screen %dx%d\n", screen_cols, screen_rows);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_help(char *arg)
|
static int do_help(char *arg)
|
||||||
{
|
{
|
||||||
return usage(0);
|
return usage(0);
|
||||||
@@ -742,6 +811,7 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
struct command command[] = {
|
struct command command[] = {
|
||||||
{ "debug", toggle_debug },
|
{ "debug", toggle_debug },
|
||||||
|
{ "devel", do_devel },
|
||||||
{ "help", do_help },
|
{ "help", do_help },
|
||||||
{ "version", show_version },
|
{ "version", show_version },
|
||||||
|
|
||||||
@@ -750,6 +820,7 @@ int main(int argc, char *argv[])
|
|||||||
{ "enable", serv_enable },
|
{ "enable", serv_enable },
|
||||||
{ "disable", serv_disable },
|
{ "disable", serv_disable },
|
||||||
{ "touch", serv_touch },
|
{ "touch", serv_touch },
|
||||||
|
{ "show", serv_show },
|
||||||
{ "edit", serv_edit },
|
{ "edit", serv_edit },
|
||||||
{ "create", serv_creat },
|
{ "create", serv_creat },
|
||||||
{ "delete", serv_delete },
|
{ "delete", serv_delete },
|
||||||
@@ -762,7 +833,7 @@ int main(int argc, char *argv[])
|
|||||||
{ "stop", do_stop },
|
{ "stop", do_stop },
|
||||||
{ "restart", do_restart },
|
{ "restart", do_restart },
|
||||||
{ "status", show_status },
|
{ "status", show_status },
|
||||||
{ "show", show_status }, /* Convenience alias */
|
{ "show", show_status }, /* Convenience alias, for now */
|
||||||
|
|
||||||
{ "ps", show_cgroup },
|
{ "ps", show_cgroup },
|
||||||
|
|
||||||
@@ -780,7 +851,6 @@ int main(int argc, char *argv[])
|
|||||||
{ "create", 0, NULL, 'c' },
|
{ "create", 0, NULL, 'c' },
|
||||||
{ "force", 0, NULL, 'f' },
|
{ "force", 0, NULL, 'f' },
|
||||||
{ "help", 0, NULL, 'h' },
|
{ "help", 0, NULL, 'h' },
|
||||||
{ "numeric", 0, NULL, 'n' },
|
|
||||||
{ "no-heading", 0, NULL, 't' },
|
{ "no-heading", 0, NULL, 't' },
|
||||||
{ "verbose", 0, NULL, 'v' },
|
{ "verbose", 0, NULL, 'v' },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
@@ -791,7 +861,7 @@ int main(int argc, char *argv[])
|
|||||||
if (transform(progname(argv[0])))
|
if (transform(progname(argv[0])))
|
||||||
return reboot_main(argc, argv);
|
return reboot_main(argc, argv);
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "bcfh?ntv", long_options, NULL)) != EOF) {
|
while ((c = getopt_long(argc, argv, "bcfh?tv", long_options, NULL)) != EOF) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
interactive = 0;
|
interactive = 0;
|
||||||
@@ -809,10 +879,6 @@ int main(int argc, char *argv[])
|
|||||||
case '?':
|
case '?':
|
||||||
return usage(0);
|
return usage(0);
|
||||||
|
|
||||||
case 'n':
|
|
||||||
numeric = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
heading = 0;
|
heading = 0;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <sched.h> /* sched_yield() */
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <lite/lite.h>
|
#include <lite/lite.h>
|
||||||
@@ -50,15 +49,13 @@ void log_exit(void)
|
|||||||
* Unless in debug mode at shutdown, Reinitialize screen,
|
* Unless in debug mode at shutdown, Reinitialize screen,
|
||||||
* terminal may have been resized at runtime
|
* terminal may have been resized at runtime
|
||||||
*/
|
*/
|
||||||
if (debug)
|
if (!debug)
|
||||||
screen_exit();
|
|
||||||
else
|
|
||||||
screen_init();
|
screen_init();
|
||||||
|
|
||||||
enable_progress(1);
|
enable_progress(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_open(void)
|
static void log_open(void)
|
||||||
{
|
{
|
||||||
int opts = LOG_PID;
|
int opts = LOG_PID;
|
||||||
|
|
||||||
@@ -79,7 +76,6 @@ void log_debug(void)
|
|||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
loglevel = LOG_DEBUG;
|
loglevel = LOG_DEBUG;
|
||||||
screen_exit();
|
|
||||||
} else {
|
} else {
|
||||||
loglevel = LOG_NOTICE;
|
loglevel = LOG_NOTICE;
|
||||||
screen_init();
|
screen_init();
|
||||||
@@ -103,11 +99,12 @@ void logit(int prio, const char *fmt, ...)
|
|||||||
if (up || fexist("/dev/log")) {
|
if (up || fexist("/dev/log")) {
|
||||||
if (!up)
|
if (!up)
|
||||||
log_open();
|
log_open();
|
||||||
|
|
||||||
vsyslog(prio, fmt, ap);
|
vsyslog(prio, fmt, ap);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!debug && prio > loglevel)
|
if (prio > loglevel)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
fp = fopen("/dev/kmsg", "w");
|
fp = fopen("/dev/kmsg", "w");
|
||||||
|
|||||||
+2
-65
@@ -30,75 +30,12 @@
|
|||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <lite/lite.h>
|
||||||
|
|
||||||
static const char version_info[] = PACKAGE_NAME " v" PACKAGE_VERSION;
|
static const char version_info[] = PACKAGE_NAME " v" PACKAGE_VERSION;
|
||||||
|
extern int logrotate(char *file, int num, off_t sz);
|
||||||
|
|
||||||
|
|
||||||
static int create(char *path, mode_t mode, uid_t uid, gid_t gid)
|
|
||||||
{
|
|
||||||
return mknod(path, S_IFREG | mode, 0) || chown(path, uid, gid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function triggers a log rotates of @file when size >= @sz bytes
|
|
||||||
* At most @num old versions are kept and by default it starts gzipping
|
|
||||||
* .2 and older log files. If gzip is not available in $PATH then @num
|
|
||||||
* files are kept uncompressed.
|
|
||||||
*/
|
|
||||||
static int logrotate(char *file, int num, off_t sz)
|
|
||||||
{
|
|
||||||
int cnt;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (stat(file, &st))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (sz > 0 && S_ISREG(st.st_mode) && st.st_size > sz) {
|
|
||||||
if (num > 0) {
|
|
||||||
size_t len = strlen(file) + 10 + 1;
|
|
||||||
char ofile[len];
|
|
||||||
char nfile[len];
|
|
||||||
|
|
||||||
/* First age zipped log files */
|
|
||||||
for (cnt = num; cnt > 2; cnt--) {
|
|
||||||
snprintf(ofile, len, "%s.%d.gz", file, cnt - 1);
|
|
||||||
snprintf(nfile, len, "%s.%d.gz", file, cnt);
|
|
||||||
|
|
||||||
/* May fail because ofile doesn't exist yet, ignore. */
|
|
||||||
(void)rename(ofile, nfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (cnt = num; cnt > 0; cnt--) {
|
|
||||||
snprintf(ofile, len, "%s.%d", file, cnt - 1);
|
|
||||||
snprintf(nfile, len, "%s.%d", file, cnt);
|
|
||||||
|
|
||||||
/* May fail because ofile doesn't exist yet, ignore. */
|
|
||||||
(void)rename(ofile, nfile);
|
|
||||||
|
|
||||||
if (cnt == 2 && !access(nfile, F_OK)) {
|
|
||||||
size_t len = 5 + strlen(nfile) + 1;
|
|
||||||
char cmd[len];
|
|
||||||
|
|
||||||
snprintf(cmd, len, "gzip %s", nfile);
|
|
||||||
system(cmd);
|
|
||||||
|
|
||||||
remove(nfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rename(file, nfile))
|
|
||||||
(void)truncate(file, 0);
|
|
||||||
else
|
|
||||||
create(file, st.st_mode, st.st_uid, st.st_gid);
|
|
||||||
} else {
|
|
||||||
if (truncate(file, 0))
|
|
||||||
syslog(LOG_ERR | LOG_PERROR, "Failed truncating %s during logrotate: %s", file, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int checksz(FILE *fp, off_t sz)
|
static int checksz(FILE *fp, off_t sz)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|||||||
+102
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2021 Joachim Wiberg <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 <lite/lite.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static int recreate(char *path, mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
if (mknod(path, S_IFREG | mode, 0) || chown(path, uid, gid)) {
|
||||||
|
syslog(LOG_ERR, "Failed recreating %s: %s", path, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function triggers a log rotates of @file when size >= @sz bytes
|
||||||
|
* At most @num old versions are kept and by default it starts gzipping
|
||||||
|
* .2 and older log files. If gzip is not available in $PATH then @num
|
||||||
|
* files are kept uncompressed.
|
||||||
|
*/
|
||||||
|
int logrotate(char *file, int num, off_t sz)
|
||||||
|
{
|
||||||
|
int cnt;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (stat(file, &st))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (sz > 0 && S_ISREG(st.st_mode) && st.st_size > sz) {
|
||||||
|
if (num > 0) {
|
||||||
|
size_t len = strlen(file) + 10 + 1;
|
||||||
|
char ofile[len];
|
||||||
|
char nfile[len];
|
||||||
|
|
||||||
|
/* First age zipped log files */
|
||||||
|
for (cnt = num; cnt > 2; cnt--) {
|
||||||
|
snprintf(ofile, len, "%s.%d.gz", file, cnt - 1);
|
||||||
|
snprintf(nfile, len, "%s.%d.gz", file, cnt);
|
||||||
|
|
||||||
|
/* May fail because ofile doesn't exist yet, ignore. */
|
||||||
|
if (rename(ofile, nfile) && errno != ENOENT)
|
||||||
|
syslog(LOG_ERR, "Failed logrotate %s: %s",
|
||||||
|
ofile, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cnt = num; cnt > 0; cnt--) {
|
||||||
|
snprintf(ofile, len, "%s.%d", file, cnt - 1);
|
||||||
|
snprintf(nfile, len, "%s.%d", file, cnt);
|
||||||
|
|
||||||
|
/* May fail because ofile doesn't exist yet, ignore. */
|
||||||
|
if (rename(ofile, nfile) && errno != ENOENT) {
|
||||||
|
syslog(LOG_ERR, "Failed logrotate %s: %s",
|
||||||
|
ofile, strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cnt == 2 && fexist(nfile)) {
|
||||||
|
if (systemf("gzip %s", nfile))
|
||||||
|
continue; /* no gzip, probably */
|
||||||
|
|
||||||
|
(void)remove(nfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rename(file, nfile))
|
||||||
|
goto fallback;
|
||||||
|
recreate(file, st.st_mode, st.st_uid, st.st_gid);
|
||||||
|
} else {
|
||||||
|
fallback:
|
||||||
|
if (truncate(file, 0))
|
||||||
|
syslog(LOG_ERR, "Failed truncating %s during logrotate: %s",
|
||||||
|
file, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+26
-4
@@ -58,7 +58,9 @@ static void do_list(const char *path)
|
|||||||
glob_t gl;
|
glob_t gl;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
chdir(path);
|
if (chdir(path))
|
||||||
|
return;
|
||||||
|
|
||||||
if (glob("*.conf", 0, NULL, &gl))
|
if (glob("*.conf", 0, NULL, &gl))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -138,6 +140,11 @@ static char *conf(char *path, size_t len, char *name, int creat)
|
|||||||
{
|
{
|
||||||
char corr[40];
|
char corr[40];
|
||||||
|
|
||||||
|
if (!name || !name[0]) {
|
||||||
|
strlcpy(path, FINIT_CONF, len);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strstr(name, ".conf")) {
|
if (!strstr(name, ".conf")) {
|
||||||
snprintf(corr, sizeof(corr), "%s.conf", name);
|
snprintf(corr, sizeof(corr), "%s.conf", name);
|
||||||
name = corr;
|
name = corr;
|
||||||
@@ -208,7 +215,7 @@ int do_disable(char *arg, int check)
|
|||||||
|
|
||||||
if (chdir(FINIT_RCSD))
|
if (chdir(FINIT_RCSD))
|
||||||
err(1, "failed cd %s", FINIT_RCSD);
|
err(1, "failed cd %s", FINIT_RCSD);
|
||||||
chdir("enabled"); /* System *may* have enabled/ dir. */
|
(void)chdir("enabled"); /* System *may* have enabled/ dir. */
|
||||||
|
|
||||||
if (check && stat(arg, &st))
|
if (check && stat(arg, &st))
|
||||||
errx(1, "%s not (an) enabled (service).", arg);
|
errx(1, "%s not (an) enabled (service).", arg);
|
||||||
@@ -250,6 +257,20 @@ int serv_touch(char *arg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int serv_show(char *arg)
|
||||||
|
{
|
||||||
|
char path[256];
|
||||||
|
char *fn;
|
||||||
|
|
||||||
|
fn = conf(path, sizeof(path), arg, 0);
|
||||||
|
if (!fexist(fn)) {
|
||||||
|
warnx("Cannot find %s", arg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return systemf("cat %s", fn);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to open an editor for the given file, if creat is given we
|
* Try to open an editor for the given file, if creat is given we
|
||||||
* create a new file based on /lib/finit/sample.conf
|
* create a new file based on /lib/finit/sample.conf
|
||||||
@@ -270,7 +291,7 @@ static int do_edit(char *arg, int creat)
|
|||||||
char *editor[] = {
|
char *editor[] = {
|
||||||
"sensible-editor",
|
"sensible-editor",
|
||||||
"editor",
|
"editor",
|
||||||
"${VISUAL:-${EDITOR:-$(command -v mg vi | head -1)}}"
|
"${VISUAL:-${EDITOR:-$(command -v mg || command -v vi)}}"
|
||||||
};
|
};
|
||||||
char path[256];
|
char path[256];
|
||||||
char *fn;
|
char *fn;
|
||||||
@@ -358,7 +379,8 @@ int serv_delete(char *arg)
|
|||||||
|
|
||||||
if (iforce || yorn("Remove file and symlink(s) to %s (y/N)? ", fn)) {
|
if (iforce || yorn("Remove file and symlink(s) to %s (y/N)? ", fn)) {
|
||||||
do_disable(arg, 0);
|
do_disable(arg, 0);
|
||||||
remove(fn);
|
if (remove(fn))
|
||||||
|
err(1, "Failed removing %s", fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ int serv_list (char *arg);
|
|||||||
int serv_enable (char *arg);
|
int serv_enable (char *arg);
|
||||||
int serv_disable (char *arg);
|
int serv_disable (char *arg);
|
||||||
int serv_touch (char *arg);
|
int serv_touch (char *arg);
|
||||||
|
int serv_show (char *arg);
|
||||||
int serv_edit (char *arg);
|
int serv_edit (char *arg);
|
||||||
int serv_creat (char *arg);
|
int serv_creat (char *arg);
|
||||||
int serv_delete (char *arg);
|
int serv_delete (char *arg);
|
||||||
|
|||||||
+76
-9
@@ -464,17 +464,18 @@ static int service_start(svc_t *svc)
|
|||||||
|
|
||||||
/* Set desired user+group */
|
/* Set desired user+group */
|
||||||
if (gid >= 0)
|
if (gid >= 0)
|
||||||
setgid(gid);
|
(void)setgid(gid);
|
||||||
|
|
||||||
if (uid >= 0) {
|
if (uid >= 0) {
|
||||||
setuid(uid);
|
(void)setuid(uid);
|
||||||
|
|
||||||
/* Set default path for regular users */
|
/* Set default path for regular users */
|
||||||
if (uid > 0)
|
if (uid > 0)
|
||||||
setenv("PATH", _PATH_DEFPATH, 1);
|
setenv("PATH", _PATH_DEFPATH, 1);
|
||||||
if (home) {
|
if (home) {
|
||||||
setenv("HOME", home, 1);
|
setenv("HOME", home, 1);
|
||||||
chdir(home);
|
if (chdir(home))
|
||||||
|
(void)chdir("/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -918,24 +919,56 @@ static void parse_name(svc_t *svc, char *arg)
|
|||||||
*/
|
*/
|
||||||
static void parse_cmdline_args(svc_t *svc, char *cmd)
|
static void parse_cmdline_args(svc_t *svc, char *cmd)
|
||||||
{
|
{
|
||||||
int i;
|
char sep = 0;
|
||||||
char *arg;
|
char *arg;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
strlcpy(svc->args[0], cmd, sizeof(svc->args[0]));
|
strlcpy(svc->args[i++], cmd, sizeof(svc->args[0]));
|
||||||
|
|
||||||
|
while (i < MAX_NUM_SVC_ARGS)
|
||||||
|
svc->args[i++][0] = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy supplied args. Stop at MAX_NUM_SVC_ARGS-1 to allow the args
|
* Copy supplied args. Stop at MAX_NUM_SVC_ARGS-1 to allow the args
|
||||||
* array to be zero-terminated.
|
* array to be zero-terminated.
|
||||||
*/
|
*/
|
||||||
for (i = 1; (arg = strtok(NULL, " ")) && i < (MAX_NUM_SVC_ARGS - 1); i++)
|
for (i = 1; (arg = strtok(NULL, " ")) && i < (MAX_NUM_SVC_ARGS - 1);) {
|
||||||
strlcpy(svc->args[i], arg, sizeof(svc->args[0]));
|
char ch = arg[0];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
/* XXX: ugly string arg re-concatenation, fixme */
|
||||||
|
if (ch == '"' || ch == '\'')
|
||||||
|
sep = ch;
|
||||||
|
else if (sep)
|
||||||
|
strlcat(svc->args[i], " ", sizeof(svc->args[0]));
|
||||||
|
|
||||||
|
strlcat(svc->args[i], arg, sizeof(svc->args[0]));
|
||||||
|
|
||||||
|
/* string arg contained already? */
|
||||||
|
len = strlen(arg);
|
||||||
|
if (sep && len >= 1) {
|
||||||
|
ch = arg[len - 1];
|
||||||
|
if (ch != sep)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sep = 0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear remaining args in case they were set earlier.
|
* Clear remaining args in case they were set earlier.
|
||||||
* This also zero-terminates the args array.
|
* This also zero-terminates the args array.
|
||||||
*/
|
*/
|
||||||
for (; i < MAX_NUM_SVC_ARGS; i++)
|
while (i < MAX_NUM_SVC_ARGS)
|
||||||
svc->args[i][0] = 0;
|
svc->args[i++][0] = 0;
|
||||||
|
#if 0
|
||||||
|
for (i = 0; i < MAX_NUM_SVC_ARGS; i++) {
|
||||||
|
if (!svc->args[i][0])
|
||||||
|
break;
|
||||||
|
_d("%s ", svc->args[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1130,6 +1163,8 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
strlcpy(svc->desc, desc, sizeof(svc->desc));
|
strlcpy(svc->desc, desc, sizeof(svc->desc));
|
||||||
if (env)
|
if (env)
|
||||||
parse_env(svc, env);
|
parse_env(svc, env);
|
||||||
|
if (file)
|
||||||
|
strlcpy(svc->file, file, sizeof(svc->file));
|
||||||
|
|
||||||
/* Set configured limits */
|
/* Set configured limits */
|
||||||
memcpy(svc->rlimit, rlimit, sizeof(svc->rlimit));
|
memcpy(svc->rlimit, rlimit, sizeof(svc->rlimit));
|
||||||
@@ -1215,6 +1250,38 @@ void service_monitor(pid_t lost, int status)
|
|||||||
sm_step(&sm);
|
sm_step(&sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void svc_mark_affected(char *cond)
|
||||||
|
{
|
||||||
|
svc_t *svc, *iter = NULL;
|
||||||
|
|
||||||
|
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
||||||
|
if (!svc_has_cond(svc))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cond_affects(cond, svc->cond))
|
||||||
|
svc_mark_dirty(svc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called on conf_reload() to update service reverse dependencies.
|
||||||
|
* E.g., if ospfd depends on zebra and the zebra Finit conf has
|
||||||
|
* changed, we need to mark the ospfd Finit conf as changed too.
|
||||||
|
*/
|
||||||
|
void service_update_rdeps(void)
|
||||||
|
{
|
||||||
|
svc_t *svc, *iter = NULL;
|
||||||
|
|
||||||
|
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
||||||
|
char cond[MAX_COND_LEN];
|
||||||
|
|
||||||
|
if (!svc_is_changed(svc))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
svc_mark_affected(mkcond(svc, cond, sizeof(cond)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void service_retry(svc_t *svc)
|
static void service_retry(svc_t *svc)
|
||||||
{
|
{
|
||||||
int timeout;
|
int timeout;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ void service_unregister (svc_t *svc);
|
|||||||
|
|
||||||
void service_runtask_clean (void);
|
void service_runtask_clean (void);
|
||||||
void service_reload_dynamic (void);
|
void service_reload_dynamic (void);
|
||||||
|
void service_update_rdeps (void);
|
||||||
|
|
||||||
int service_step (svc_t *svc);
|
int service_step (svc_t *svc);
|
||||||
void service_step_all (int types);
|
void service_step_all (int types);
|
||||||
|
|||||||
@@ -86,9 +86,8 @@ typedef enum {
|
|||||||
typedef struct svc {
|
typedef struct svc {
|
||||||
TAILQ_ENTRY(svc) link;
|
TAILQ_ENTRY(svc) link;
|
||||||
|
|
||||||
/* Instance specifics */
|
/* Origin of service */
|
||||||
int job; /* JOB: */
|
char file[MAX_ARG_LEN];
|
||||||
char id[MAX_ID_LEN]; /* :ID */
|
|
||||||
|
|
||||||
/* Limits and scoping */
|
/* Limits and scoping */
|
||||||
struct rlimit rlimit[RLIMIT_NLIMITS];
|
struct rlimit rlimit[RLIMIT_NLIMITS];
|
||||||
@@ -110,7 +109,11 @@ typedef struct svc {
|
|||||||
int sighup; /* This service supports SIGHUP :) */
|
int sighup; /* This service supports SIGHUP :) */
|
||||||
svc_block_t block; /* Reason that this service is currently stopped */
|
svc_block_t block; /* Reason that this service is currently stopped */
|
||||||
char cond[MAX_COND_LEN];
|
char cond[MAX_COND_LEN];
|
||||||
|
|
||||||
|
/* Instance specifics */
|
||||||
|
int job; /* For intenal use only, canonical ref is NAME:ID */
|
||||||
char name[MAX_ARG_LEN];
|
char name[MAX_ARG_LEN];
|
||||||
|
char id[MAX_ID_LEN]; /* :ID */
|
||||||
|
|
||||||
/* Counters */
|
/* Counters */
|
||||||
char once; /* run/task, (at least) once per runlevel */
|
char once; /* run/task, (at least) once per runlevel */
|
||||||
@@ -205,6 +208,26 @@ static inline void svc_missing (svc_t *svc) { if (svc) svc->block = SVC_BLOC
|
|||||||
static inline void svc_restarting (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_RESTARTING; }
|
static inline void svc_restarting (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_RESTARTING; }
|
||||||
static inline void svc_crashing (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_CRASHING; }
|
static inline void svc_crashing (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_CRASHING; }
|
||||||
|
|
||||||
|
/* Has condition in configuration and cond is allowed? */
|
||||||
|
static inline int svc_has_cond(svc_t *svc)
|
||||||
|
{
|
||||||
|
if (!svc->cond[0])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (svc->type) {
|
||||||
|
case SVC_TYPE_SERVICE:
|
||||||
|
case SVC_TYPE_TASK:
|
||||||
|
case SVC_TYPE_RUN:
|
||||||
|
case SVC_TYPE_SYSV:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline char *svc_status(svc_t *svc)
|
static inline char *svc_status(svc_t *svc)
|
||||||
{
|
{
|
||||||
if (!svc)
|
if (!svc)
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
#include <lite/queue.h> /* BSD sys/queue.h API */
|
#include <lite/queue.h> /* BSD sys/queue.h API */
|
||||||
|
|
||||||
#define TTY_MAX_ARGS 16
|
#define TTY_MAX_ARGS 16
|
||||||
#define EVENT_SIZE ((sizeof(struct inotify_event) + NAME_MAX + 1))
|
|
||||||
|
|
||||||
struct tty {
|
struct tty {
|
||||||
LIST_ENTRY(tty) link;
|
LIST_ENTRY(tty) link;
|
||||||
|
|||||||
+62
-15
@@ -28,9 +28,15 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_TERMIOS_H
|
||||||
|
# include <termios.h>
|
||||||
|
#endif
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <utmp.h>
|
#include <utmp.h>
|
||||||
|
#ifdef HAVE_SYS_IOCTL_H
|
||||||
|
# include <sys/ioctl.h>
|
||||||
|
#endif
|
||||||
#include <sys/sysinfo.h> /* sysinfo() */
|
#include <sys/sysinfo.h> /* sysinfo() */
|
||||||
#include <lite/lite.h> /* strlcat() */
|
#include <lite/lite.h> /* strlcat() */
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@@ -202,25 +208,66 @@ char *sanitize(char *arg, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called at boot, and shutdown, to (re)initialize the
|
* Called by initctl, and by finit at boot and shutdown, to
|
||||||
* screen size for print() et al.
|
* (re)initialize the screen size for print() et al.
|
||||||
*/
|
*/
|
||||||
void screen_init(void)
|
int screen_init(void)
|
||||||
{
|
{
|
||||||
if (!isatty(STDOUT_FILENO))
|
#ifdef HAVE_TERMIOS_H
|
||||||
return;
|
struct pollfd fd = { STDIN_FILENO, POLLIN, 0 };
|
||||||
|
struct winsize ws = { 0 };
|
||||||
|
struct termios tc, saved;
|
||||||
|
|
||||||
initscr(&screen_rows, &screen_cols);
|
/*
|
||||||
}
|
* Basic TTY init, CLOCaL is important or TIOCWINSZ will block
|
||||||
|
* until DCD is asserted, and we won't ever get it.
|
||||||
|
*/
|
||||||
|
tcgetattr(STDERR_FILENO, &tc);
|
||||||
|
saved = tc;
|
||||||
|
tc.c_cflag |= (CLOCAL | CREAD);
|
||||||
|
tc.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
||||||
|
tcsetattr(STDERR_FILENO, TCSANOW, &tc);
|
||||||
|
|
||||||
/*
|
/* 1. Try TIOCWINSZ to query window size from kernel */
|
||||||
* Called when debug mode is enabled to revert back
|
if (!ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws)) {
|
||||||
* to old-school safe defaults.
|
screen_rows = ws.ws_row;
|
||||||
*/
|
screen_cols = ws.ws_col;
|
||||||
void screen_exit(void)
|
|
||||||
{
|
/* Likely doesn't work in PID 1 after kernel starts us ... */
|
||||||
screen_rows = 24;
|
if (!ws.ws_row && !ws.ws_col)
|
||||||
screen_cols = 80;
|
goto fallback;
|
||||||
|
} else if (!isatty(STDOUT_FILENO)) {
|
||||||
|
/* 2. We may be running under watch(1) */
|
||||||
|
screen_cols = atonum(getenv("COLUMNS"));
|
||||||
|
screen_rows = atonum(getenv("LINES"));
|
||||||
|
} else {
|
||||||
|
fallback:
|
||||||
|
/* 3. ANSI goto + query cursor position trick as fallback */
|
||||||
|
fprintf(stderr, "\e7\e[r\e[999;999H\e[6n");
|
||||||
|
|
||||||
|
if (poll(&fd, 1, 300) > 0) {
|
||||||
|
int row, col;
|
||||||
|
|
||||||
|
if (scanf("\e[%d;%dR", &row, &col) == 2) {
|
||||||
|
screen_cols = col;
|
||||||
|
screen_rows = row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Jump back to where we started (\e7) */
|
||||||
|
fprintf(stderr, "\e8");
|
||||||
|
}
|
||||||
|
|
||||||
|
tcsetattr(STDERR_FILENO, TCSANOW, &saved);
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
if (screen_cols <= 0)
|
||||||
|
screen_cols = 80;
|
||||||
|
if (screen_rows <= 0)
|
||||||
|
screen_rows = 24;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return screen_cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-3
@@ -55,9 +55,7 @@ char *uptime (long secs, char *buf, size_t len);
|
|||||||
|
|
||||||
char *sanitize (char *arg, size_t len);
|
char *sanitize (char *arg, size_t len);
|
||||||
|
|
||||||
void screen_init (void);
|
int screen_init (void);
|
||||||
void screen_exit (void);
|
|
||||||
int screen_width (void);
|
|
||||||
|
|
||||||
static inline char *strterm(char *str, size_t len)
|
static inline char *strterm(char *str, size_t len)
|
||||||
{
|
{
|
||||||
|
|||||||
+5
-61
@@ -35,6 +35,9 @@
|
|||||||
#define MAX_NO 5
|
#define MAX_NO 5
|
||||||
#define MAX_SZ 100 * 1024
|
#define MAX_SZ 100 * 1024
|
||||||
|
|
||||||
|
extern int logrotate(char *file, int num, off_t sz);
|
||||||
|
|
||||||
|
|
||||||
static void utmp_strncpy(char *dst, const char *src, size_t dlen)
|
static void utmp_strncpy(char *dst, const char *src, size_t dlen)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
@@ -46,65 +49,6 @@ static void utmp_strncpy(char *dst, const char *src, size_t dlen)
|
|||||||
dst[i] = 0;
|
dst[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOGROTATE_ENABLED
|
|
||||||
/*
|
|
||||||
* This function triggers a log rotates of @file when size >= @sz bytes
|
|
||||||
* At most @num old versions are kept and by default it starts gzipping
|
|
||||||
* .2 and older log files. If gzip is not available in $PATH then @num
|
|
||||||
* files are kept uncompressed.
|
|
||||||
*/
|
|
||||||
static int logrotate(char *file, int num, off_t sz)
|
|
||||||
{
|
|
||||||
int cnt;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (stat(file, &st))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (sz > 0 && S_ISREG(st.st_mode) && st.st_size > sz) {
|
|
||||||
if (num > 0) {
|
|
||||||
size_t len = strlen(file) + 10 + 1;
|
|
||||||
char ofile[len];
|
|
||||||
char nfile[len];
|
|
||||||
|
|
||||||
/* First age zipped log files */
|
|
||||||
for (cnt = num; cnt > 2; cnt--) {
|
|
||||||
snprintf(ofile, len, "%s.%d.gz", file, cnt - 1);
|
|
||||||
snprintf(nfile, len, "%s.%d.gz", file, cnt);
|
|
||||||
|
|
||||||
/* May fail because ofile doesn't exist yet, ignore. */
|
|
||||||
(void)rename(ofile, nfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (cnt = num; cnt > 0; cnt--) {
|
|
||||||
snprintf(ofile, len, "%s.%d", file, cnt - 1);
|
|
||||||
snprintf(nfile, len, "%s.%d", file, cnt);
|
|
||||||
|
|
||||||
/* May fail because ofile doesn't exist yet, ignore. */
|
|
||||||
(void)rename(ofile, nfile);
|
|
||||||
|
|
||||||
if (cnt == 2 && fexist(nfile)) {
|
|
||||||
size_t len = 5 + strlen(nfile) + 1;
|
|
||||||
char cmd[len];
|
|
||||||
|
|
||||||
snprintf(cmd, len, "gzip %s", nfile);
|
|
||||||
run(cmd);
|
|
||||||
|
|
||||||
remove(nfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)rename(file, nfile);
|
|
||||||
create(file, st.st_mode, st.st_uid, st.st_gid);
|
|
||||||
} else {
|
|
||||||
truncate(file, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* LOGROTATE_ENABLED */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rotate /var/log/wtmp (+ btmp?) and /run/utmp
|
* Rotate /var/log/wtmp (+ btmp?) and /run/utmp
|
||||||
*
|
*
|
||||||
@@ -194,13 +138,13 @@ static int set_getty(int type, char *tty, char *id, char *user)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!tty)
|
if (!tty)
|
||||||
line = "";
|
line = NULL;
|
||||||
else if (!strncmp(tty, "/dev/", 5))
|
else if (!strncmp(tty, "/dev/", 5))
|
||||||
line = tty + 5;
|
line = tty + 5;
|
||||||
else
|
else
|
||||||
line = tty;
|
line = tty;
|
||||||
|
|
||||||
if (!id) {
|
if (!id && line) {
|
||||||
id = line;
|
id = line;
|
||||||
if (!strncmp(id, "pts/", 4))
|
if (!strncmp(id, "pts/", 4))
|
||||||
id += 4;
|
id += 4;
|
||||||
|
|||||||
Reference in new issue
Block a user