Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/runit


Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
Location:
branches/2.2.9/mindi-busybox/runit
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/runit/Config.in

    r1765 r2725  
     1# DO NOT EDIT. This file is generated from Config.src
    12#
    23# For a description of the syntax of this configuration file,
     
    67menu "Runit Utilities"
    78
     9
     10
    811config RUNSV
    912    bool "runsv"
    10     default n
     13    default y
    1114    help
    1215      runsv starts and monitors a service and optionally an appendant log
     
    1518config RUNSVDIR
    1619    bool "runsvdir"
    17     default n
     20    default y
    1821    help
    1922      runsvdir starts a runsv process for each subdirectory, or symlink to
     
    2124      subdirectories, and restarts a runsv process if it terminates.
    2225
     26config FEATURE_RUNSVDIR_LOG
     27    bool "Enable scrolling argument log"
     28    depends on RUNSVDIR
     29    default n
     30    help
     31      Enable feature where second parameter of runsvdir holds last error
     32      message (viewable via top/ps). Otherwise (feature is off
     33      or no parameter), error messages go to stderr only.
     34
    2335config SV
    2436    bool "sv"
    25     default n
     37    default y
    2638    help
    2739      sv reports the current status and controls the state of services
    2840      monitored by the runsv supervisor.
    2941
     42config SV_DEFAULT_SERVICE_DIR
     43    string "Default directory for services"
     44    default "/var/service"
     45    depends on SV
     46    help
     47      Default directory for services.
     48      Defaults to "/var/service"
     49
    3050config SVLOGD
    3151    bool "svlogd"
    32     default n
     52    default y
    3353    help
    3454      svlogd continuously reads log data from its standard input, optionally
     
    3858config CHPST
    3959    bool "chpst"
    40     default n
     60    default y
    4161    help
    4262      chpst changes the process state according to the given options, and
     
    4565config SETUIDGID
    4666    bool "setuidgid"
     67    default y
    4768    help
    4869      Sets soft resource limits as specified by options
     
    5071config ENVUIDGID
    5172    bool "envuidgid"
     73    default y
    5274    help
    5375      Sets $UID to account's uid and $GID to account's gid
     
    5577config ENVDIR
    5678    bool "envdir"
     79    default y
    5780    help
    5881      Sets various environment variables as specified by files
     
    6184config SOFTLIMIT
    6285    bool "softlimit"
     86    default y
    6387    help
    6488      Sets soft resource limits as specified by options
  • branches/2.2.9/mindi-busybox/runit/Kbuild

    r1765 r2725  
     1# DO NOT EDIT. This file is generated from Kbuild.src
    12# Makefile for busybox
    23#
    34# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
    45#
    5 # Licensed under the GPL v2, see the file LICENSE in this tarball.
     6# Licensed under GPLv2, see file LICENSE in this source tree.
    67
    78lib-y:=
    8 lib-$(CONFIG_RUNSV) += runsv.o runit_lib.o
    9 lib-$(CONFIG_RUNSVDIR) += runsvdir.o runit_lib.o
    10 lib-$(CONFIG_SV) += sv.o runit_lib.o
    11 lib-$(CONFIG_SVLOGD) += svlogd.o runit_lib.o
     9
     10
     11
     12lib-$(CONFIG_RUNSV) += runsv.o
     13lib-$(CONFIG_RUNSVDIR) += runsvdir.o
     14lib-$(CONFIG_SV) += sv.o
     15lib-$(CONFIG_SVLOGD) += svlogd.o
    1216lib-$(CONFIG_CHPST) += chpst.o
    1317
  • branches/2.2.9/mindi-busybox/runit/chpst.c

    r1765 r2725  
    2626*/
    2727
    28 /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
     28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
    2929/* Dependencies on runit_lib.c removed */
    3030
    3131#include "libbb.h"
    3232
    33 #include <dirent.h>
    34 
    35 // Must match constants in chpst_main!
    36 #define OPT_verbose  (option_mask32 & 0x2000)
    37 #define OPT_pgrp     (option_mask32 & 0x4000)
    38 #define OPT_nostdin  (option_mask32 & 0x8000)
    39 #define OPT_nostdout (option_mask32 & 0x10000)
    40 #define OPT_nostderr (option_mask32 & 0x20000)
    41 
    42 static char *set_user;
    43 static char *env_user;
    44 static const char *env_dir;
    45 static long limitd = -2;
    46 static long limits = -2;
    47 static long limitl = -2;
    48 static long limita = -2;
    49 static long limito = -2;
    50 static long limitp = -2;
    51 static long limitf = -2;
    52 static long limitc = -2;
    53 static long limitr = -2;
    54 static long limitt = -2;
    55 static int nicelvl;
    56 static const char *root;
    57 
    58 static void suidgid(char *user)
    59 {
    60     struct bb_uidgid_t ugid;
    61 
    62     if (!get_uidgid(&ugid, user, 1)) {
    63         bb_error_msg_and_die("unknown user/group: %s", user);
    64     }
    65     if (setgroups(1, &ugid.gid) == -1)
    66         bb_perror_msg_and_die("setgroups");
    67     xsetgid(ugid.gid);
    68     xsetuid(ugid.uid);
    69 }
    70 
    71 static void euidgid(char *user)
    72 {
    73     struct bb_uidgid_t ugid;
    74 
    75     if (!get_uidgid(&ugid, user, 1)) {
    76         bb_error_msg_and_die("unknown user/group: %s", user);
    77     }
    78     xsetenv("GID", utoa(ugid.gid));
    79     xsetenv("UID", utoa(ugid.uid));
    80 }
    81 
    82 static void edir(const char *directory_name)
     33/*
     34Five applets here: chpst, envdir, envuidgid, setuidgid, softlimit.
     35
     36Only softlimit and chpst are taking options:
     37
     38# common
     39-o N            Limit number of open files per process
     40-p N            Limit number of processes per uid
     41-m BYTES        Same as -d BYTES -s BYTES -l BYTES [-a BYTES]
     42-d BYTES        Limit data segment
     43-f BYTES        Limit output file sizes
     44-c BYTES        Limit core file size
     45# softlimit
     46-a BYTES        Limit total size of all segments
     47-s BYTES        Limit stack segment
     48-l BYTES        Limit locked memory size
     49-r BYTES        Limit resident set size
     50-t N            Limit CPU time
     51# chpst
     52-u USER[:GRP]   Set uid and gid
     53-U USER[:GRP]   Set $UID and $GID in environment
     54-e DIR          Set environment variables as specified by files in DIR
     55-/ DIR          Chroot to DIR
     56-n NICE         Add NICE to nice value
     57-v              Verbose
     58-P              Create new process group
     59-0 -1 -2        Close fd 0,1,2
     60
     61Even though we accept all these options for both softlimit and chpst,
     62they are not to be advertised on their help texts.
     63We have enough problems with feature creep in other people's
     64software, don't want to add our own.
     65
     66envdir, envuidgid, setuidgid take no options, but they reuse code which
     67handles -e, -U and -u.
     68*/
     69
     70enum {
     71    OPT_a = (1 << 0) * ENABLE_SOFTLIMIT,
     72    OPT_c = (1 << 1) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
     73    OPT_d = (1 << 2) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
     74    OPT_f = (1 << 3) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
     75    OPT_l = (1 << 4) * ENABLE_SOFTLIMIT,
     76    OPT_m = (1 << 5) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
     77    OPT_o = (1 << 6) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
     78    OPT_p = (1 << 7) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
     79    OPT_r = (1 << 8) * ENABLE_SOFTLIMIT,
     80    OPT_s = (1 << 9) * ENABLE_SOFTLIMIT,
     81    OPT_t = (1 << 10) * ENABLE_SOFTLIMIT,
     82    OPT_u = (1 << 11) * (ENABLE_CHPST || ENABLE_SETUIDGID),
     83    OPT_U = (1 << 12) * (ENABLE_CHPST || ENABLE_ENVUIDGID),
     84    OPT_e = (1 << 13) * (ENABLE_CHPST || ENABLE_ENVDIR),
     85    OPT_root = (1 << 14) * ENABLE_CHPST,
     86    OPT_n = (1 << 15) * ENABLE_CHPST,
     87    OPT_v = (1 << 16) * ENABLE_CHPST,
     88    OPT_P = (1 << 17) * ENABLE_CHPST,
     89    OPT_0 = (1 << 18) * ENABLE_CHPST,
     90    OPT_1 = (1 << 19) * ENABLE_CHPST,
     91    OPT_2 = (1 << 20) * ENABLE_CHPST,
     92};
     93
     94/* TODO: use recursive_action? */
     95static NOINLINE void edir(const char *directory_name)
    8396{
    8497    int wdir;
     
    89102    wdir = xopen(".", O_RDONLY | O_NDELAY);
    90103    xchdir(directory_name);
    91     dir = opendir(".");
    92     if (!dir)
    93         bb_perror_msg_and_die("opendir %s", directory_name);
     104    dir = xopendir(".");
    94105    for (;;) {
     106        char buf[256];
     107        char *tail;
     108        int size;
     109
    95110        errno = 0;
    96111        d = readdir(dir);
     
    101116            break;
    102117        }
    103         if (d->d_name[0] == '.') continue;
     118        if (d->d_name[0] == '.')
     119            continue;
    104120        fd = open(d->d_name, O_RDONLY | O_NDELAY);
    105121        if (fd < 0) {
    106             if ((errno == EISDIR) && env_dir) {
    107                 if (OPT_verbose)
     122            if ((errno == EISDIR) && directory_name) {
     123                if (option_mask32 & OPT_v)
    108124                    bb_perror_msg("warning: %s/%s is a directory",
    109                         directory_name, d->d_name);
    110                 continue;
    111             } else
    112                 bb_perror_msg_and_die("open %s/%s",
    113125                        directory_name, d->d_name);
    114         }
    115         if (fd >= 0) {
    116             char buf[256];
    117             char *tail;
    118             int size;
    119 
    120             size = safe_read(fd, buf, sizeof(buf)-1);
    121             if (size < 0)
    122                 bb_perror_msg_and_die("read %s/%s",
    123                         directory_name, d->d_name);
    124             if (size == 0) {
    125                 unsetenv(d->d_name);
    126126                continue;
    127127            }
    128             buf[size] = '\n';
    129             tail = memchr(buf, '\n', sizeof(buf));
    130             /* skip trailing whitespace */;
    131             while (1) {
    132                 if (tail[0]==' ') tail[0] = '\0';
    133                 if (tail[0]=='\t') tail[0] = '\0';
    134                 if (tail[0]=='\n') tail[0] = '\0';
    135                 if (tail == buf) break;
    136                 tail--;
    137             }
    138             xsetenv(d->d_name, buf);
    139         }
     128            bb_perror_msg_and_die("open %s/%s",
     129                        directory_name, d->d_name);
     130        }
     131        size = full_read(fd, buf, sizeof(buf)-1);
     132        close(fd);
     133        if (size < 0)
     134            bb_perror_msg_and_die("read %s/%s",
     135                    directory_name, d->d_name);
     136        if (size == 0) {
     137            unsetenv(d->d_name);
     138            continue;
     139        }
     140        buf[size] = '\n';
     141        tail = strchr(buf, '\n');
     142        /* skip trailing whitespace */
     143        while (1) {
     144            *tail = '\0';
     145            tail--;
     146            if (tail < buf || !isspace(*tail))
     147                break;
     148        }
     149        xsetenv(d->d_name, buf);
    140150    }
    141151    closedir(dir);
    142     if (fchdir(wdir) == -1) bb_perror_msg_and_die("fchdir");
     152    if (fchdir(wdir) == -1)
     153        bb_perror_msg_and_die("fchdir");
    143154    close(wdir);
    144155}
     
    148159    struct rlimit r;
    149160
    150     if (getrlimit(what, &r) == -1) bb_perror_msg_and_die("getrlimit");
     161    /* Never fails under Linux (except if you pass it bad arguments) */
     162    getrlimit(what, &r);
    151163    if ((l < 0) || (l > r.rlim_max))
    152164        r.rlim_cur = r.rlim_max;
    153165    else
    154166        r.rlim_cur = l;
    155     if (setrlimit(what, &r) == -1) bb_perror_msg_and_die("setrlimit");
     167    if (setrlimit(what, &r) == -1)
     168        bb_perror_msg_and_die("setrlimit");
    156169}
    157170
    158 static void slimit(void)
     171int chpst_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     172int chpst_main(int argc UNUSED_PARAM, char **argv)
    159173{
    160     if (limitd >= -1) {
     174    struct bb_uidgid_t ugid;
     175    char *set_user = set_user; /* for compiler */
     176    char *env_user = env_user;
     177    char *env_dir = env_dir;
     178    char *root;
     179    char *nicestr;
     180    unsigned limita;
     181    unsigned limitc;
     182    unsigned limitd;
     183    unsigned limitf;
     184    unsigned limitl;
     185    unsigned limitm;
     186    unsigned limito;
     187    unsigned limitp;
     188    unsigned limitr;
     189    unsigned limits;
     190    unsigned limitt;
     191    unsigned opt;
     192
     193    if ((ENABLE_CHPST && applet_name[0] == 'c')
     194     || (ENABLE_SOFTLIMIT && applet_name[1] == 'o')
     195    ) {
     196        // FIXME: can we live with int-sized limits?
     197        // can we live with 40000 days?
     198        // if yes -> getopt converts strings to numbers for us
     199        opt_complementary = "-1:a+:c+:d+:f+:l+:m+:o+:p+:r+:s+:t+";
     200        opt = getopt32(argv, "+a:c:d:f:l:m:o:p:r:s:t:u:U:e:"
     201            IF_CHPST("/:n:vP012"),
     202            &limita, &limitc, &limitd, &limitf, &limitl,
     203            &limitm, &limito, &limitp, &limitr, &limits, &limitt,
     204            &set_user, &env_user, &env_dir
     205            IF_CHPST(, &root, &nicestr));
     206        argv += optind;
     207        if (opt & OPT_m) { // -m means -asld
     208            limita = limits = limitl = limitd = limitm;
     209            opt |= (OPT_s | OPT_l | OPT_a | OPT_d);
     210        }
     211    } else {
     212        option_mask32 = opt = 0;
     213        argv++;
     214        if (!*argv)
     215            bb_show_usage();
     216    }
     217
     218    // envdir?
     219    if (ENABLE_ENVDIR && applet_name[3] == 'd') {
     220        env_dir = *argv++;
     221        opt |= OPT_e;
     222    }
     223
     224    // setuidgid?
     225    if (ENABLE_SETUIDGID && applet_name[1] == 'e') {
     226        set_user = *argv++;
     227        opt |= OPT_u;
     228    }
     229
     230    // envuidgid?
     231    if (ENABLE_ENVUIDGID && applet_name[0] == 'e' && applet_name[3] == 'u') {
     232        env_user = *argv++;
     233        opt |= OPT_U;
     234    }
     235
     236    // we must have PROG [ARGS]
     237    if (!*argv)
     238        bb_show_usage();
     239
     240    // set limits
     241    if (opt & OPT_d) {
    161242#ifdef RLIMIT_DATA
    162243        limit(RLIMIT_DATA, limitd);
    163244#else
    164         if (OPT_verbose) bb_error_msg("system does not support %s",
    165                 "RLIMIT_DATA");
    166 #endif
    167     }
    168     if (limits >= -1) {
     245        if (opt & OPT_v)
     246            bb_error_msg("system does not support RLIMIT_%s",
     247                "DATA");
     248#endif
     249    }
     250    if (opt & OPT_s) {
    169251#ifdef RLIMIT_STACK
    170252        limit(RLIMIT_STACK, limits);
    171253#else
    172         if (OPT_verbose) bb_error_msg("system does not support %s",
    173                 "RLIMIT_STACK");
    174 #endif
    175     }
    176     if (limitl >= -1) {
     254        if (opt & OPT_v)
     255            bb_error_msg("system does not support RLIMIT_%s",
     256                "STACK");
     257#endif
     258    }
     259    if (opt & OPT_l) {
    177260#ifdef RLIMIT_MEMLOCK
    178261        limit(RLIMIT_MEMLOCK, limitl);
    179262#else
    180         if (OPT_verbose) bb_error_msg("system does not support %s",
    181                 "RLIMIT_MEMLOCK");
    182 #endif
    183     }
    184     if (limita >= -1) {
     263        if (opt & OPT_v)
     264            bb_error_msg("system does not support RLIMIT_%s",
     265                "MEMLOCK");
     266#endif
     267    }
     268    if (opt & OPT_a) {
    185269#ifdef RLIMIT_VMEM
    186270        limit(RLIMIT_VMEM, limita);
     
    189273        limit(RLIMIT_AS, limita);
    190274#else
    191         if (OPT_verbose)
    192             bb_error_msg("system does not support %s",
    193                 "RLIMIT_VMEM");
    194 #endif
    195 #endif
    196     }
    197     if (limito >= -1) {
     275        if (opt & OPT_v)
     276            bb_error_msg("system does not support RLIMIT_%s",
     277                "VMEM");
     278#endif
     279#endif
     280    }
     281    if (opt & OPT_o) {
    198282#ifdef RLIMIT_NOFILE
    199283        limit(RLIMIT_NOFILE, limito);
     
    202286        limit(RLIMIT_OFILE, limito);
    203287#else
    204         if (OPT_verbose)
    205             bb_error_msg("system does not support %s",
    206                 "RLIMIT_NOFILE");
    207 #endif
    208 #endif
    209     }
    210     if (limitp >= -1) {
     288        if (opt & OPT_v)
     289            bb_error_msg("system does not support RLIMIT_%s",
     290                "NOFILE");
     291#endif
     292#endif
     293    }
     294    if (opt & OPT_p) {
    211295#ifdef RLIMIT_NPROC
    212296        limit(RLIMIT_NPROC, limitp);
    213297#else
    214         if (OPT_verbose) bb_error_msg("system does not support %s",
    215                 "RLIMIT_NPROC");
    216 #endif
    217     }
    218     if (limitf >= -1) {
     298        if (opt & OPT_v)
     299            bb_error_msg("system does not support RLIMIT_%s",
     300                "NPROC");
     301#endif
     302    }
     303    if (opt & OPT_f) {
    219304#ifdef RLIMIT_FSIZE
    220305        limit(RLIMIT_FSIZE, limitf);
    221306#else
    222         if (OPT_verbose) bb_error_msg("system does not support %s",
    223                 "RLIMIT_FSIZE");
    224 #endif
    225     }
    226     if (limitc >= -1) {
     307        if (opt & OPT_v)
     308            bb_error_msg("system does not support RLIMIT_%s",
     309                "FSIZE");
     310#endif
     311    }
     312    if (opt & OPT_c) {
    227313#ifdef RLIMIT_CORE
    228314        limit(RLIMIT_CORE, limitc);
    229315#else
    230         if (OPT_verbose) bb_error_msg("system does not support %s",
    231                 "RLIMIT_CORE");
    232 #endif
    233     }
    234     if (limitr >= -1) {
     316        if (opt & OPT_v)
     317            bb_error_msg("system does not support RLIMIT_%s",
     318                "CORE");
     319#endif
     320    }
     321    if (opt & OPT_r) {
    235322#ifdef RLIMIT_RSS
    236323        limit(RLIMIT_RSS, limitr);
    237324#else
    238         if (OPT_verbose) bb_error_msg("system does not support %s",
    239                 "RLIMIT_RSS");
    240 #endif
    241     }
    242     if (limitt >= -1) {
     325        if (opt & OPT_v)
     326            bb_error_msg("system does not support RLIMIT_%s",
     327                "RSS");
     328#endif
     329    }
     330    if (opt & OPT_t) {
    243331#ifdef RLIMIT_CPU
    244332        limit(RLIMIT_CPU, limitt);
    245333#else
    246         if (OPT_verbose) bb_error_msg("system does not support %s",
    247                 "RLIMIT_CPU");
    248 #endif
    249     }
     334        if (opt & OPT_v)
     335            bb_error_msg("system does not support RLIMIT_%s",
     336                "CPU");
     337#endif
     338    }
     339
     340    if (opt & OPT_P)
     341        setsid();
     342
     343    if (opt & OPT_e)
     344        edir(env_dir);
     345
     346    // FIXME: chrooted jail must have /etc/passwd if we move this after chroot!
     347    // OTOH chroot fails for non-roots!
     348    // SOLUTION: cache uid/gid before chroot, apply uid/gid after
     349    if (opt & OPT_U) {
     350        xget_uidgid(&ugid, env_user);
     351        xsetenv("GID", utoa(ugid.gid));
     352        xsetenv("UID", utoa(ugid.uid));
     353    }
     354
     355    if (opt & OPT_u) {
     356        xget_uidgid(&ugid, set_user);
     357    }
     358
     359    if (opt & OPT_root) {
     360        xchdir(root);
     361        xchroot(".");
     362    }
     363
     364    if (opt & OPT_u) {
     365        if (setgroups(1, &ugid.gid) == -1)
     366            bb_perror_msg_and_die("setgroups");
     367        xsetgid(ugid.gid);
     368        xsetuid(ugid.uid);
     369    }
     370
     371    if (opt & OPT_n) {
     372        errno = 0;
     373        if (nice(xatoi(nicestr)) == -1)
     374            bb_perror_msg_and_die("nice");
     375    }
     376
     377    if (opt & OPT_0)
     378        close(STDIN_FILENO);
     379    if (opt & OPT_1)
     380        close(STDOUT_FILENO);
     381    if (opt & OPT_2)
     382        close(STDERR_FILENO);
     383
     384    BB_EXECVP_or_die(argv);
    250385}
    251 
    252 /* argv[0] */
    253 static void setuidgid(int, char **);
    254 static void envuidgid(int, char **);
    255 static void envdir(int, char **);
    256 static void softlimit(int, char **);
    257 
    258 int chpst_main(int argc, char **argv);
    259 int chpst_main(int argc, char **argv)
    260 {
    261     if (applet_name[3] == 'd') envdir(argc, argv);
    262     if (applet_name[1] == 'o') softlimit(argc, argv);
    263     if (applet_name[0] == 's') setuidgid(argc, argv);
    264     if (applet_name[0] == 'e') envuidgid(argc, argv);
    265     // otherwise we are chpst
    266 
    267     {
    268         char *m,*d,*o,*p,*f,*c,*r,*t,*n;
    269         getopt32(argv, "+u:U:e:m:d:o:p:f:c:r:t:/:n:vP012",
    270                 &set_user,&env_user,&env_dir,
    271                 &m,&d,&o,&p,&f,&c,&r,&t,&root,&n);
    272         // if (option_mask32 & 0x1) // -u
    273         // if (option_mask32 & 0x2) // -U
    274         // if (option_mask32 & 0x4) // -e
    275         if (option_mask32 & 0x8) limits = limitl = limita = limitd = xatoul(m); // -m
    276         if (option_mask32 & 0x10) limitd = xatoul(d); // -d
    277         if (option_mask32 & 0x20) limito = xatoul(o); // -o
    278         if (option_mask32 & 0x40) limitp = xatoul(p); // -p
    279         if (option_mask32 & 0x80) limitf = xatoul(f); // -f
    280         if (option_mask32 & 0x100) limitc = xatoul(c); // -c
    281         if (option_mask32 & 0x200) limitr = xatoul(r); // -r
    282         if (option_mask32 & 0x400) limitt = xatoul(t); // -t
    283         // if (option_mask32 & 0x800) // -/
    284         if (option_mask32 & 0x1000) nicelvl = xatoi(n); // -n
    285         // The below consts should match #defines at top!
    286         //if (option_mask32 & 0x2000) OPT_verbose = 1; // -v
    287         //if (option_mask32 & 0x4000) OPT_pgrp = 1; // -P
    288         //if (option_mask32 & 0x8000) OPT_nostdin = 1; // -0
    289         //if (option_mask32 & 0x10000) OPT_nostdout = 1; // -1
    290         //if (option_mask32 & 0x20000) OPT_nostderr = 1; // -2
    291     }
    292     argv += optind;
    293     if (!argv || !*argv) bb_show_usage();
    294 
    295     if (OPT_pgrp) setsid();
    296     if (env_dir) edir(env_dir);
    297     if (root) {
    298         xchdir(root);
    299         if (chroot(".") == -1)
    300             bb_perror_msg_and_die("chroot");
    301     }
    302     slimit();
    303     if (nicelvl) {
    304         errno = 0;
    305         if (nice(nicelvl) == -1)
    306             bb_perror_msg_and_die("nice");
    307     }
    308     if (env_user) euidgid(env_user);
    309     if (set_user) suidgid(set_user);
    310     if (OPT_nostdin) close(0);
    311     if (OPT_nostdout) close(1);
    312     if (OPT_nostderr) close(2);
    313     BB_EXECVP(argv[0], argv);
    314     bb_perror_msg_and_die("exec %s", argv[0]);
    315 }
    316 
    317 static void setuidgid(int argc, char **argv)
    318 {
    319     const char *account;
    320 
    321     account = *++argv;
    322     if (!account) bb_show_usage();
    323     if (!*++argv) bb_show_usage();
    324     suidgid((char*)account);
    325     BB_EXECVP(argv[0], argv);
    326     bb_perror_msg_and_die("exec %s", argv[0]);
    327 }
    328 
    329 static void envuidgid(int argc, char **argv)
    330 {
    331     const char *account;
    332 
    333     account = *++argv;
    334     if (!account) bb_show_usage();
    335     if (!*++argv) bb_show_usage();
    336     euidgid((char*)account);
    337     BB_EXECVP(argv[0], argv);
    338     bb_perror_msg_and_die("exec %s", argv[0]);
    339 }
    340 
    341 static void envdir(int argc, char **argv)
    342 {
    343     const char *dir;
    344 
    345     dir = *++argv;
    346     if (!dir) bb_show_usage();
    347     if (!*++argv) bb_show_usage();
    348     edir(dir);
    349     BB_EXECVP(argv[0], argv);
    350     bb_perror_msg_and_die("exec %s", argv[0]);
    351 }
    352 
    353 static void softlimit(int argc, char **argv)
    354 {
    355     char *a,*c,*d,*f,*l,*m,*o,*p,*r,*s,*t;
    356     getopt32(argv, "+a:c:d:f:l:m:o:p:r:s:t:",
    357             &a,&c,&d,&f,&l,&m,&o,&p,&r,&s,&t);
    358     if (option_mask32 & 0x001) limita = xatoul(a); // -a
    359     if (option_mask32 & 0x002) limitc = xatoul(c); // -c
    360     if (option_mask32 & 0x004) limitd = xatoul(d); // -d
    361     if (option_mask32 & 0x008) limitf = xatoul(f); // -f
    362     if (option_mask32 & 0x010) limitl = xatoul(l); // -l
    363     if (option_mask32 & 0x020) limits = limitl = limita = limitd = xatoul(m); // -m
    364     if (option_mask32 & 0x040) limito = xatoul(o); // -o
    365     if (option_mask32 & 0x080) limitp = xatoul(p); // -p
    366     if (option_mask32 & 0x100) limitr = xatoul(r); // -r
    367     if (option_mask32 & 0x200) limits = xatoul(s); // -s
    368     if (option_mask32 & 0x400) limitt = xatoul(t); // -t
    369     argv += optind;
    370     if (!argv[0]) bb_show_usage();
    371     slimit();
    372     BB_EXECVP(argv[0], argv);
    373     bb_perror_msg_and_die("exec %s", argv[0]);
    374 }
  • branches/2.2.9/mindi-busybox/runit/runit_lib.h

    r1765 r2725  
    2626*/
    2727
    28 extern unsigned byte_chr(char *s,unsigned n,int c);
    29 
    30 extern int coe(int);
    31 
    32 #define direntry struct dirent
    33 
    34 //struct tai {
    35 //  uint64_t x;
    36 //};
    37 //
    38 //#define tai_unix(t,u) ((void) ((t)->x = 0x400000000000000aULL + (uint64_t) (u)))
    39 //
    40 //#define TAI_PACK 8
    41 //extern void tai_unpack(const char *,struct tai *);
    42 //
    43 //extern void tai_uint(struct tai *,unsigned);
    44 //
    45 //struct taia {
    46 //  struct tai sec;
    47 //  unsigned long nano; /* 0...999999999 */
    48 //  unsigned long atto; /* 0...999999999 */
    49 //};
    50 //
    51 //extern void taia_now(struct taia *);
    52 //
    53 //extern void taia_add(struct taia *,const struct taia *,const struct taia *);
    54 //extern void taia_addsec(struct taia *,const struct taia *,int);
    55 //extern void taia_sub(struct taia *,const struct taia *,const struct taia *);
    56 //extern void taia_half(struct taia *,const struct taia *);
    57 //extern int taia_less(const struct taia *,const struct taia *);
    58 //
    59 //#define TAIA_PACK 16
    60 //extern void taia_pack(char *,const struct taia *);
    61 //
    62 //extern void taia_uint(struct taia *,unsigned);
    63 //
    64 //typedef struct pollfd iopause_fd;
    65 //#define IOPAUSE_READ POLLIN
    66 //#define IOPAUSE_WRITE POLLOUT
    67 //
    68 //extern void iopause(iopause_fd *,unsigned,struct taia *,struct taia *);
    69 
    70 extern int lock_ex(int);
    71 extern int lock_un(int);
    72 extern int lock_exnb(int);
    73 
    74 extern int open_read(const char *);
    75 extern int open_excl(const char *);
    76 extern int open_append(const char *);
    77 extern int open_trunc(const char *);
    78 extern int open_write(const char *);
    79 
    80 extern unsigned pmatch(const char *, const char *, unsigned);
    81 
    82 #define str_diff(s,t) strcmp((s), (t))
    83 #define str_equal(s,t) (!strcmp((s), (t)))
     28PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
    8429
    8530/*
     
    8732 */
    8833typedef struct svstatus_t {
    89     uint64_t time_be64 ATTRIBUTE_PACKED;
    90     uint32_t time_nsec_be32 ATTRIBUTE_PACKED;
    91     uint32_t pid_le32 ATTRIBUTE_PACKED;
     34    uint64_t time_be64 PACKED;
     35    uint32_t time_nsec_be32 PACKED;
     36    uint32_t pid_le32 PACKED;
    9237    uint8_t  paused;
    93     uint8_t  want;
     38    uint8_t  want; /* 'u' or 'd' */
    9439    uint8_t  got_term;
    9540    uint8_t  run_or_finish;
     
    9843    char ERR_svstatus_must_be_20_bytes[sizeof(svstatus_t) == 20 ? 1 : -1];
    9944};
     45
     46POP_SAVED_FUNCTION_VISIBILITY
  • branches/2.2.9/mindi-busybox/runit/runsv.c

    r1765 r2725  
    2626*/
    2727
    28 /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
     28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
    2929/* TODO: depends on runit_lib.c - review and reduce/eliminate */
    3030
     
    6161/* Compare possibly overflowing unsigned counters */
    6262#define LESS(a,b) ((int)((unsigned)(b) - (unsigned)(a)) > 0)
    63 
    64 static int selfpipe[2];
    6563
    6664/* state */
     
    8179    smallint state;
    8280    smallint ctrl;
    83     smallint want;
     81    smallint sd_want;
    8482    smallint islog;
    8583    struct timespec start;
     
    8785    int fdcontrol;
    8886    int fdcontrolwrite;
     87    int wstat;
    8988};
    9089
    91 static struct svdir svd[2];
    92 static smallint sigterm;
    93 static smallint haslog;
    94 static smallint pidchanged = 1;
    95 static int logpipe[2];
    96 static char *dir;
     90struct globals {
     91    smallint haslog;
     92    smallint sigterm;
     93    smallint pidchanged;
     94    struct fd_pair selfpipe;
     95    struct fd_pair logpipe;
     96    char *dir;
     97    struct svdir svd[2];
     98} FIX_ALIASING;
     99#define G (*(struct globals*)&bb_common_bufsiz1)
     100#define haslog       (G.haslog      )
     101#define sigterm      (G.sigterm     )
     102#define pidchanged   (G.pidchanged  )
     103#define selfpipe     (G.selfpipe    )
     104#define logpipe      (G.logpipe     )
     105#define dir          (G.dir         )
     106#define svd          (G.svd         )
     107#define INIT_G() do { \
     108    pidchanged = 1; \
     109} while (0)
    97110
    98111static void fatal2_cannot(const char *m1, const char *m2)
     
    116129}
    117130
    118 static void s_child(int sig_no)
    119 {
    120     write(selfpipe[1], "", 1);
    121 }
    122 
    123 static void s_term(int sig_no)
     131static void s_child(int sig_no UNUSED_PARAM)
     132{
     133    write(selfpipe.wr, "", 1);
     134}
     135
     136static void s_term(int sig_no UNUSED_PARAM)
    124137{
    125138    sigterm = 1;
    126     write(selfpipe[1], "", 1); /* XXX */
    127 }
    128 
    129 static char *add_str(char *p, const char *to_add)
     139    write(selfpipe.wr, "", 1); /* XXX */
     140}
     141
     142/* libbb candidate */
     143static char *bb_stpcpy(char *p, const char *to_add)
    130144{
    131145    while ((*p = *to_add) != '\0') {
     
    138152static int open_trunc_or_warn(const char *name)
    139153{
    140     int fd = open_trunc(name);
     154    /* Why O_NDELAY? */
     155    int fd = open(name, O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT, 0644);
    141156    if (fd < 0)
    142157        bb_perror_msg("%s: warning: cannot open %s",
    143158                dir, name);
    144159    return fd;
    145 }
    146 
    147 static int rename_or_warn(const char *old, const char *new)
    148 {
    149     if (rename(old, new) == -1) {
    150         bb_perror_msg("%s: warning: cannot rename %s to %s",
    151                 dir, old, new);
    152         return -1;
    153     }
    154     return 0;
    155160}
    156161
     
    188193        switch (s->state) {
    189194        case S_DOWN:
    190             p = add_str(p, "down");
     195            p = bb_stpcpy(p, "down");
    191196            break;
    192197        case S_RUN:
    193             p = add_str(p, "run");
     198            p = bb_stpcpy(p, "run");
    194199            break;
    195200        case S_FINISH:
    196             p = add_str(p, "finish");
     201            p = bb_stpcpy(p, "finish");
    197202            break;
    198203        }
    199         if (s->ctrl & C_PAUSE) p = add_str(p, ", paused");
    200         if (s->ctrl & C_TERM) p = add_str(p, ", got TERM");
     204        if (s->ctrl & C_PAUSE)
     205            p = bb_stpcpy(p, ", paused");
     206        if (s->ctrl & C_TERM)
     207            p = bb_stpcpy(p, ", got TERM");
    201208        if (s->state != S_DOWN)
    202             switch (s->want) {
     209            switch (s->sd_want) {
    203210            case W_DOWN:
    204                 p = add_str(p, ", want down");
     211                p = bb_stpcpy(p, ", want down");
    205212                break;
    206213            case W_EXIT:
    207                 p = add_str(p, ", want exit");
     214                p = bb_stpcpy(p, ", want exit");
    208215                break;
    209216            }
     
    223230    if (s->ctrl & C_PAUSE)
    224231        status.paused = 1;
    225     if (s->want == W_UP)
     232    if (s->sd_want == W_UP)
    226233        status.want = 'u';
    227234    else
     
    246253static unsigned custom(struct svdir *s, char c)
    247254{
    248     int pid;
     255    pid_t pid;
    249256    int w;
    250257    char a[10];
    251258    struct stat st;
    252     char *prog[2];
    253 
    254     if (s->islog) return 0;
     259
     260    if (s->islog)
     261        return 0;
    255262    strcpy(a, "control/?");
    256     a[8] = c;
     263    a[8] = c; /* replace '?' */
    257264    if (stat(a, &st) == 0) {
    258265        if (st.st_mode & S_IXUSR) {
    259             pid = fork();
     266            pid = vfork();
    260267            if (pid == -1) {
    261                 warn_cannot("fork for control/?");
     268                warn_cannot("vfork for control/?");
    262269                return 0;
    263270            }
    264             if (!pid) {
    265                 if (haslog && dup2(logpipe[1], 1) == -1)
     271            if (pid == 0) {
     272                /* child */
     273                if (haslog && dup2(logpipe.wr, 1) == -1)
    266274                    warn_cannot("setup stdout for control/?");
    267                 prog[0] = a;
    268                 prog[1] = NULL;
    269                 execve(a, prog, environ);
     275                execl(a, a, (char *) NULL);
    270276                fatal_cannot("run control/?");
    271277            }
    272             while (wait_pid(&w, pid) == -1) {
    273                 if (errno == EINTR) continue;
     278            /* parent */
     279            if (safe_waitpid(pid, &w, 0) == -1) {
    274280                warn_cannot("wait for child control/?");
    275281                return 0;
    276282            }
    277             return !wait_exitcode(w);
     283            return WEXITSTATUS(w) == 0;
    278284        }
    279285    } else {
     
    291297        update_status(s);
    292298    }
    293     if (s->want == W_DOWN) {
     299    if (s->sd_want == W_DOWN) {
    294300        kill(s->pid, SIGCONT);
    295301        custom(s, 'd');
    296302        return;
    297303    }
    298     if (s->want == W_EXIT) {
     304    if (s->sd_want == W_EXIT) {
    299305        kill(s->pid, SIGCONT);
    300306        custom(s, 'x');
     
    305311{
    306312    int p;
    307     char *run[2];
    308 
    309     if (s->state == S_FINISH)
    310         run[0] = (char*)"./finish";
    311     else {
    312         run[0] = (char*)"./run";
     313    const char *arg[4];
     314    char exitcode[sizeof(int)*3 + 2];
     315
     316    if (s->state == S_FINISH) {
     317/* Two arguments are given to ./finish. The first one is ./run exit code,
     318 * or -1 if ./run didnt exit normally. The second one is
     319 * the least significant byte of the exit status as determined by waitpid;
     320 * for instance it is 0 if ./run exited normally, and the signal number
     321 * if ./run was terminated by a signal. If runsv cannot start ./run
     322 * for some reason, the exit code is 111 and the status is 0.
     323 */
     324        arg[0] = "./finish";
     325        arg[1] = "-1";
     326        if (WIFEXITED(s->wstat)) {
     327            *utoa_to_buf(WEXITSTATUS(s->wstat), exitcode, sizeof(exitcode)) = '\0';
     328            arg[1] = exitcode;
     329        }
     330        //arg[2] = "0";
     331        //if (WIFSIGNALED(s->wstat)) {
     332            arg[2] = utoa(WTERMSIG(s->wstat));
     333        //}
     334        arg[3] = NULL;
     335    } else {
     336        arg[0] = "./run";
     337        arg[1] = NULL;
    313338        custom(s, 'u');
    314339    }
    315     run[1] = NULL;
    316340
    317341    if (s->pid != 0)
    318342        stopservice(s); /* should never happen */
    319     while ((p = fork()) == -1) {
    320         warn_cannot("fork, sleeping");
     343    while ((p = vfork()) == -1) {
     344        warn_cannot("vfork, sleeping");
    321345        sleep(5);
    322346    }
     
    324348        /* child */
    325349        if (haslog) {
     350            /* NB: bug alert! right order is close, then dup2 */
    326351            if (s->islog) {
    327                 xdup2(logpipe[0], 0);
    328                 close(logpipe[1]);
    329352                xchdir("./log");
     353                close(logpipe.wr);
     354                xdup2(logpipe.rd, 0);
    330355            } else {
    331                 xdup2(logpipe[1], 1);
    332                 close(logpipe[0]);
    333             }
    334         }
    335         signal(SIGCHLD, SIG_DFL);
    336         signal(SIGTERM, SIG_DFL);
     356                close(logpipe.rd);
     357                xdup2(logpipe.wr, 1);
     358            }
     359        }
     360        /* Non-ignored signals revert to SIG_DFL on exec anyway */
     361        /*bb_signals(0
     362            + (1 << SIGCHLD)
     363            + (1 << SIGTERM)
     364            , SIG_DFL);*/
    337365        sig_unblock(SIGCHLD);
    338366        sig_unblock(SIGTERM);
    339         execvp(*run, run);
    340         fatal2_cannot(s->islog ? "start log/" : "start ", *run);
    341     }
     367        execv(arg[0], (char**) arg);
     368        fatal2_cannot(s->islog ? "start log/" : "start ", arg[0]);
     369    }
     370    /* parent */
    342371    if (s->state != S_FINISH) {
    343372        gettimeofday_ns(&s->start);
     
    356385    switch (c) {
    357386    case 'd': /* down */
    358         s->want = W_DOWN;
     387        s->sd_want = W_DOWN;
    359388        update_status(s);
    360389        if (s->pid && s->state != S_FINISH)
     
    362391        break;
    363392    case 'u': /* up */
    364         s->want = W_UP;
     393        s->sd_want = W_UP;
    365394        update_status(s);
    366395        if (s->pid == 0)
     
    370399        if (s->islog)
    371400            break;
    372         s->want = W_EXIT;
     401        s->sd_want = W_EXIT;
    373402        update_status(s);
    374403        /* FALLTHROUGH */
     
    391420        if (s->pid && !custom(s, c))
    392421            kill(s->pid, SIGCONT);
    393         if (s->ctrl & C_PAUSE)
    394             s->ctrl &= ~C_PAUSE;
     422        s->ctrl &= ~C_PAUSE;
    395423        update_status(s);
    396424        break;
    397425    case 'o': /* once */
    398         s->want = W_DOWN;
     426        s->sd_want = W_DOWN;
    399427        update_status(s);
    400428        if (!s->pid)
     
    427455}
    428456
    429 int runsv_main(int argc, char **argv);
    430 int runsv_main(int argc, char **argv)
     457int runsv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     458int runsv_main(int argc UNUSED_PARAM, char **argv)
    431459{
    432460    struct stat s;
     
    435463    char buf[256];
    436464
    437     if (!argv[1] || argv[2])
    438         bb_show_usage();
    439     dir = argv[1];
    440 
    441     xpipe(selfpipe);
    442     coe(selfpipe[0]);
    443     coe(selfpipe[1]);
    444     ndelay_on(selfpipe[0]);
    445     ndelay_on(selfpipe[1]);
     465    INIT_G();
     466
     467    dir = single_argv(argv);
     468
     469    xpiped_pair(selfpipe);
     470    close_on_exec_on(selfpipe.rd);
     471    close_on_exec_on(selfpipe.wr);
     472    ndelay_on(selfpipe.rd);
     473    ndelay_on(selfpipe.wr);
    446474
    447475    sig_block(SIGCHLD);
    448     sig_catch(SIGCHLD, s_child);
     476    bb_signals_recursive_norestart(1 << SIGCHLD, s_child);
    449477    sig_block(SIGTERM);
    450     sig_catch(SIGTERM, s_term);
     478    bb_signals_recursive_norestart(1 << SIGTERM, s_term);
    451479
    452480    xchdir(dir);
     
    454482    if (S_DOWN) svd[0].state = S_DOWN; /* otherwise already 0 (bss) */
    455483    if (C_NOOP) svd[0].ctrl = C_NOOP;
    456     if (W_UP) svd[0].want = W_UP;
     484    if (W_UP) svd[0].sd_want = W_UP;
    457485    /* bss: svd[0].islog = 0; */
    458486    /* bss: svd[1].pid = 0; */
    459487    gettimeofday_ns(&svd[0].start);
    460     if (stat("down", &s) != -1) svd[0].want = W_DOWN;
     488    if (stat("down", &s) != -1)
     489        svd[0].sd_want = W_DOWN;
    461490
    462491    if (stat("log", &s) == -1) {
     
    471500            svd[1].state = S_DOWN;
    472501            svd[1].ctrl = C_NOOP;
    473             svd[1].want = W_UP;
     502            svd[1].sd_want = W_UP;
    474503            svd[1].islog = 1;
    475504            gettimeofday_ns(&svd[1].start);
    476505            if (stat("log/down", &s) != -1)
    477                 svd[1].want = W_DOWN;
    478             xpipe(logpipe);
    479             coe(logpipe[0]);
    480             coe(logpipe[1]);
     506                svd[1].sd_want = W_DOWN;
     507            xpiped_pair(logpipe);
     508            close_on_exec_on(logpipe.rd);
     509            close_on_exec_on(logpipe.wr);
    481510        }
    482511    }
     
    496525    svd[0].fdlock = xopen3("log/supervise/lock"+4,
    497526            O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
    498     if (lock_exnb(svd[0].fdlock) == -1)
     527    if (flock(svd[0].fdlock, LOCK_EX | LOCK_NB) == -1)
    499528        fatal_cannot("lock supervise/lock");
    500     coe(svd[0].fdlock);
     529    close_on_exec_on(svd[0].fdlock);
    501530    if (haslog) {
    502531        if (mkdir("log/supervise", 0700) == -1) {
     
    520549        svd[1].fdlock = xopen3("log/supervise/lock",
    521550                O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
    522         if (lock_ex(svd[1].fdlock) == -1)
     551        if (flock(svd[1].fdlock, LOCK_EX) == -1)
    523552            fatal_cannot("lock log/supervise/lock");
    524         coe(svd[1].fdlock);
     553        close_on_exec_on(svd[1].fdlock);
    525554    }
    526555
    527556    mkfifo("log/supervise/control"+4, 0600);
    528557    svd[0].fdcontrol = xopen("log/supervise/control"+4, O_RDONLY|O_NDELAY);
    529     coe(svd[0].fdcontrol);
     558    close_on_exec_on(svd[0].fdcontrol);
    530559    svd[0].fdcontrolwrite = xopen("log/supervise/control"+4, O_WRONLY|O_NDELAY);
    531     coe(svd[0].fdcontrolwrite);
     560    close_on_exec_on(svd[0].fdcontrolwrite);
    532561    update_status(&svd[0]);
    533562    if (haslog) {
    534563        mkfifo("log/supervise/control", 0600);
    535564        svd[1].fdcontrol = xopen("log/supervise/control", O_RDONLY|O_NDELAY);
    536         coe(svd[1].fdcontrol);
     565        close_on_exec_on(svd[1].fdcontrol);
    537566        svd[1].fdcontrolwrite = xopen("log/supervise/control", O_WRONLY|O_NDELAY);
    538         coe(svd[1].fdcontrolwrite);
     567        close_on_exec_on(svd[1].fdcontrolwrite);
    539568        update_status(&svd[1]);
    540569    }
    541570    mkfifo("log/supervise/ok"+4, 0600);
    542571    fd = xopen("log/supervise/ok"+4, O_RDONLY|O_NDELAY);
    543     coe(fd);
     572    close_on_exec_on(fd);
    544573    if (haslog) {
    545574        mkfifo("log/supervise/ok", 0600);
    546575        fd = xopen("log/supervise/ok", O_RDONLY|O_NDELAY);
    547         coe(fd);
     576        close_on_exec_on(fd);
    548577    }
    549578    for (;;) {
     
    553582
    554583        if (haslog)
    555             if (!svd[1].pid && svd[1].want == W_UP)
     584            if (!svd[1].pid && svd[1].sd_want == W_UP)
    556585                startservice(&svd[1]);
    557586        if (!svd[0].pid)
    558             if (svd[0].want == W_UP || svd[0].state == S_FINISH)
     587            if (svd[0].sd_want == W_UP || svd[0].state == S_FINISH)
    559588                startservice(&svd[0]);
    560589
    561         x[0].fd = selfpipe[0];
     590        x[0].fd = selfpipe.rd;
    562591        x[0].events = POLLIN;
    563592        x[1].fd = svd[0].fdcontrol;
     
    572601        sig_block(SIGCHLD);
    573602
    574         while (read(selfpipe[0], &ch, 1) == 1)
     603        while (read(selfpipe.rd, &ch, 1) == 1)
    575604            continue;
    576605
    577606        for (;;) {
    578             int child;
     607            pid_t child;
    579608            int wstat;
    580609
    581             child = wait_nohang(&wstat);
     610            child = wait_any_nohang(&wstat);
    582611            if (!child)
    583612                break;
     
    585614                break;
    586615            if (child == svd[0].pid) {
     616                svd[0].wstat = wstat;
    587617                svd[0].pid = 0;
    588618                pidchanged = 1;
    589                 svd[0].ctrl &=~ C_TERM;
     619                svd[0].ctrl &= ~C_TERM;
    590620                if (svd[0].state != S_FINISH) {
    591                     fd = open_read("finish");
     621                    fd = open("finish", O_RDONLY|O_NDELAY);
    592622                    if (fd != -1) {
    593623                        close(fd);
     
    606636            if (haslog) {
    607637                if (child == svd[1].pid) {
     638                    svd[0].wstat = wstat;
    608639                    svd[1].pid = 0;
    609640                    pidchanged = 1;
     
    617648                }
    618649            }
    619         }
     650        } /* for (;;) */
    620651        if (read(svd[0].fdcontrol, &ch, 1) == 1)
    621652            ctrl(&svd[0], ch);
     
    629660        }
    630661
    631         if (svd[0].want == W_EXIT && svd[0].state == S_DOWN) {
     662        if (svd[0].sd_want == W_EXIT && svd[0].state == S_DOWN) {
    632663            if (svd[1].pid == 0)
    633                 _exit(0);
    634             if (svd[1].want != W_EXIT) {
    635                 svd[1].want = W_EXIT;
     664                _exit(EXIT_SUCCESS);
     665            if (svd[1].sd_want != W_EXIT) {
     666                svd[1].sd_want = W_EXIT;
    636667                /* stopservice(&svd[1]); */
    637668                update_status(&svd[1]);
    638                 close(logpipe[1]);
    639                 close(logpipe[0]);
    640             }
    641         }
    642     }
     669                close(logpipe.wr);
     670                close(logpipe.rd);
     671            }
     672        }
     673    } /* for (;;) */
    643674    /* not reached */
    644675    return 0;
  • branches/2.2.9/mindi-busybox/runit/runsvdir.c

    r1765 r2725  
    2626*/
    2727
    28 /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
     28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
    2929/* TODO: depends on runit_lib.c - review and reduce/eliminate */
    3030
     
    3636#define MAXSERVICES 1000
    3737
     38/* Should be not needed - all dirs are on same FS, right? */
     39#define CHECK_DEVNO_TOO 0
     40
    3841struct service {
     42#if CHECK_DEVNO_TOO
    3943    dev_t dev;
     44#endif
    4045    ino_t ino;
    4146    pid_t pid;
     
    4348};
    4449
    45 struct service *sv;
    46 static char *svdir;
    47 static int svnum;
    48 static char *rplog;
    49 static int rploglen;
    50 static int logpipe[2];
    51 static struct pollfd pfd[1];
    52 static unsigned stamplog;
    53 static smallint check = 1;
    54 static smallint exitsoon;
    55 static smallint set_pgrp;
     50struct globals {
     51    struct service *sv;
     52    char *svdir;
     53    int svnum;
     54#if ENABLE_FEATURE_RUNSVDIR_LOG
     55    char *rplog;
     56    int rploglen;
     57    struct fd_pair logpipe;
     58    struct pollfd pfd[1];
     59    unsigned stamplog;
     60#endif
     61} FIX_ALIASING;
     62#define G (*(struct globals*)&bb_common_bufsiz1)
     63#define sv          (G.sv          )
     64#define svdir       (G.svdir       )
     65#define svnum       (G.svnum       )
     66#define rplog       (G.rplog       )
     67#define rploglen    (G.rploglen    )
     68#define logpipe     (G.logpipe     )
     69#define pfd         (G.pfd         )
     70#define stamplog    (G.stamplog    )
     71#define INIT_G() do { \
     72} while (0)
    5673
    5774static void fatal2_cannot(const char *m1, const char *m2)
    5875{
    59     bb_perror_msg_and_die("%s: fatal: cannot %s%s", svdir, m1, m2);
     76    bb_perror_msg_and_die("%s: fatal: can't %s%s", svdir, m1, m2);
    6077    /* was exiting 100 */
    6178}
     
    6683static void warn2_cannot(const char *m1, const char *m2)
    6784{
    68     warn3x("cannot ", m1, m2);
    69 }
     85    warn3x("can't ", m1, m2);
     86}
     87#if ENABLE_FEATURE_RUNSVDIR_LOG
    7088static void warnx(const char *m1)
    7189{
    7290    warn3x(m1, "", "");
    7391}
    74 
    75 static void s_term(int sig_no)
    76 {
    77     exitsoon = 1;
    78 }
    79 static void s_hangup(int sig_no)
    80 {
    81     exitsoon = 2;
    82 }
    83 
    84 static void runsv(int no, const char *name)
     92#endif
     93
     94/* inlining + vfork -> bigger code */
     95static NOINLINE pid_t runsv(const char *name)
    8596{
    8697    pid_t pid;
    87     char *prog[3];
    88 
    89     prog[0] = (char*)"runsv";
    90     prog[1] = (char*)name;
    91     prog[2] = NULL;
     98
     99    /* If we got signaled, stop spawning children at once! */
     100    if (bb_got_signal)
     101        return 0;
    92102
    93103    pid = vfork();
    94 
    95104    if (pid == -1) {
    96105        warn2_cannot("vfork", "");
    97         return;
     106        return 0;
    98107    }
    99108    if (pid == 0) {
    100109        /* child */
    101         if (set_pgrp)
     110        if (option_mask32 & 1) /* -P option? */
    102111            setsid();
    103         signal(SIGHUP, SIG_DFL);
    104         signal(SIGTERM, SIG_DFL);
    105         execvp(prog[0], prog);
     112/* man execv:
     113 * "Signals set to be caught by the calling process image
     114 *  shall be set to the default action in the new process image."
     115 * Therefore, we do not need this: */
     116#if 0
     117        bb_signals(0
     118            | (1 << SIGHUP)
     119            | (1 << SIGTERM)
     120            , SIG_DFL);
     121#endif
     122        execlp("runsv", "runsv", name, (char *) NULL);
    106123        fatal2_cannot("start runsv ", name);
    107124    }
    108     sv[no].pid = pid;
    109 }
    110 
    111 static void runsvdir(void)
     125    return pid;
     126}
     127
     128/* gcc 4.3.0 does better with NOINLINE */
     129static NOINLINE int do_rescan(void)
    112130{
    113131    DIR *dir;
    114     direntry *d;
     132    struct dirent *d;
    115133    int i;
    116134    struct stat s;
     135    int need_rescan = 0;
    117136
    118137    dir = opendir(".");
    119138    if (!dir) {
    120139        warn2_cannot("open directory ", svdir);
    121         return;
     140        return 1; /* need to rescan again soon */
    122141    }
    123142    for (i = 0; i < svnum; i++)
    124143        sv[i].isgone = 1;
    125     errno = 0;
    126     while ((d = readdir(dir))) {
     144
     145    while (1) {
     146        errno = 0;
     147        d = readdir(dir);
     148        if (!d)
     149            break;
    127150        if (d->d_name[0] == '.')
    128151            continue;
    129152        if (stat(d->d_name, &s) == -1) {
    130153            warn2_cannot("stat ", d->d_name);
    131             errno = 0;
    132154            continue;
    133155        }
    134156        if (!S_ISDIR(s.st_mode))
    135157            continue;
     158        /* Do we have this service listed already? */
    136159        for (i = 0; i < svnum; i++) {
    137             if ((sv[i].ino == s.st_ino) && (sv[i].dev == s.st_dev)) {
    138                 sv[i].isgone = 0;
    139                 if (!sv[i].pid)
    140                     runsv(i, d->d_name);
    141                 break;
    142             }
    143         }
    144         if (i == svnum) {
    145             /* new service */
     160            if ((sv[i].ino == s.st_ino)
     161#if CHECK_DEVNO_TOO
     162             && (sv[i].dev == s.st_dev)
     163#endif
     164            ) {
     165                if (sv[i].pid == 0) /* restart if it has died */
     166                    goto run_ith_sv;
     167                sv[i].isgone = 0; /* "we still see you" */
     168                goto next_dentry;
     169            }
     170        }
     171        { /* Not found, make new service */
    146172            struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
    147173            if (!svnew) {
    148                 warn3x("cannot start runsv ", d->d_name,
    149                         " too many services");
     174                warn2_cannot("start runsv ", d->d_name);
     175                need_rescan = 1;
    150176                continue;
    151177            }
    152178            sv = svnew;
    153179            svnum++;
    154             memset(&sv[i], 0, sizeof(sv[i]));
     180#if CHECK_DEVNO_TOO
     181            sv[i].dev = s.st_dev;
     182#endif
    155183            sv[i].ino = s.st_ino;
    156             sv[i].dev = s.st_dev;
    157             /*sv[i].pid = 0;*/
    158             /*sv[i].isgone = 0;*/
    159             runsv(i, d->d_name);
    160             check = 1;
    161         }
    162     }
    163     if (errno) {
     184 run_ith_sv:
     185            sv[i].pid = runsv(d->d_name);
     186            sv[i].isgone = 0;
     187        }
     188 next_dentry: ;
     189    }
     190    i = errno;
     191    closedir(dir);
     192    if (i) { /* readdir failed */
    164193        warn2_cannot("read directory ", svdir);
    165         closedir(dir);
    166         check = 1;
    167         return;
    168     }
    169     closedir(dir);
    170 
    171     /* SIGTERM removed runsv's */
     194        return 1; /* need to rescan again soon */
     195    }
     196
     197    /* Send SIGTERM to runsv whose directories
     198     * were no longer found (-> must have been removed) */
    172199    for (i = 0; i < svnum; i++) {
    173200        if (!sv[i].isgone)
     
    175202        if (sv[i].pid)
    176203            kill(sv[i].pid, SIGTERM);
    177         sv[i] = sv[--svnum];
    178         check = 1;
    179     }
    180 }
    181 
    182 static int setup_log(void)
    183 {
    184     rploglen = strlen(rplog);
    185     if (rploglen < 7) {
    186         warnx("log must have at least seven characters");
    187         return 0;
    188     }
    189     if (pipe(logpipe)) {
    190         warnx("cannot create pipe for log");
    191         return -1;
    192     }
    193     coe(logpipe[1]);
    194     coe(logpipe[0]);
    195     ndelay_on(logpipe[0]);
    196     ndelay_on(logpipe[1]);
    197     if (dup2(logpipe[1], 2) == -1) {
    198         warnx("cannot set filedescriptor for log");
    199         return -1;
    200     }
    201     pfd[0].fd = logpipe[0];
    202     pfd[0].events = POLLIN;
    203     stamplog = monotonic_sec();
    204     return 1;
    205 }
    206 
    207 int runsvdir_main(int argc, char **argv);
    208 int runsvdir_main(int argc, char **argv)
     204        svnum--;
     205        sv[i] = sv[svnum];
     206        i--; /* so that we don't skip new sv[i] (bug was here!) */
     207    }
     208    return need_rescan;
     209}
     210
     211int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     212int runsvdir_main(int argc UNUSED_PARAM, char **argv)
    209213{
    210214    struct stat s;
     
    214218    int wstat;
    215219    int curdir;
    216     int pid;
     220    pid_t pid;
    217221    unsigned deadline;
    218222    unsigned now;
    219223    unsigned stampcheck;
    220     char ch;
    221224    int i;
    222 
    223     argv++;
    224     if (!*argv)
    225         bb_show_usage();
    226     if (argv[0][0] == '-') {
    227         switch (argv[0][1]) {
    228         case 'P': set_pgrp = 1;
    229         case '-': ++argv;
    230         }
    231         if (!*argv)
    232             bb_show_usage();
    233     }
    234 
    235     sig_catch(SIGTERM, s_term);
    236     sig_catch(SIGHUP, s_hangup);
     225    int need_rescan = 1;
     226    char *opt_s_argv[3];
     227
     228    INIT_G();
     229
     230    opt_complementary = "-1";
     231    opt_s_argv[0] = NULL;
     232    opt_s_argv[2] = NULL;
     233    getopt32(argv, "Ps:", &opt_s_argv[0]);
     234    argv += optind;
     235
     236    bb_signals(0
     237        | (1 << SIGTERM)
     238        | (1 << SIGHUP)
     239        /* For busybox's init, SIGTERM == reboot,
     240         * SIGUSR1 == halt
     241         * SIGUSR2 == poweroff
     242         * so we need to intercept SIGUSRn too.
     243         * Note that we do not implement actual reboot
     244         * (killall(TERM) + umount, etc), we just pause
     245         * respawing and avoid exiting (-> making kernel oops).
     246         * The user is responsible for the rest. */
     247        | (getpid() == 1 ? ((1 << SIGUSR1) | (1 << SIGUSR2)) : 0)
     248        , record_signo);
    237249    svdir = *argv++;
    238     if (argv && *argv) {
     250
     251#if ENABLE_FEATURE_RUNSVDIR_LOG
     252    /* setup log */
     253    if (*argv) {
    239254        rplog = *argv;
    240         if (setup_log() != 1) {
    241             rplog = 0;
    242             warnx("log service disabled");
    243         }
    244     }
    245     curdir = open_read(".");
     255        rploglen = strlen(rplog);
     256        if (rploglen < 7) {
     257            warnx("log must have at least seven characters");
     258        } else if (piped_pair(logpipe)) {
     259            warnx("can't create pipe for log");
     260        } else {
     261            close_on_exec_on(logpipe.rd);
     262            close_on_exec_on(logpipe.wr);
     263            ndelay_on(logpipe.rd);
     264            ndelay_on(logpipe.wr);
     265            if (dup2(logpipe.wr, 2) == -1) {
     266                warnx("can't set filedescriptor for log");
     267            } else {
     268                pfd[0].fd = logpipe.rd;
     269                pfd[0].events = POLLIN;
     270                stamplog = monotonic_sec();
     271                goto run;
     272            }
     273        }
     274        rplog = NULL;
     275        warnx("log service disabled");
     276    }
     277 run:
     278#endif
     279    curdir = open(".", O_RDONLY|O_NDELAY);
    246280    if (curdir == -1)
    247281        fatal2_cannot("open current directory", "");
    248     coe(curdir);
     282    close_on_exec_on(curdir);
    249283
    250284    stampcheck = monotonic_sec();
     
    253287        /* collect children */
    254288        for (;;) {
    255             pid = wait_nohang(&wstat);
     289            pid = wait_any_nohang(&wstat);
    256290            if (pid <= 0)
    257291                break;
    258292            for (i = 0; i < svnum; i++) {
    259293                if (pid == sv[i].pid) {
    260                     /* runsv has gone */
     294                    /* runsv has died */
    261295                    sv[i].pid = 0;
    262                     check = 1;
    263                     break;
     296                    need_rescan = 1;
    264297                }
    265298            }
     
    272305
    273306            if (stat(svdir, &s) != -1) {
    274                 if (check || s.st_mtime != last_mtime
     307                if (need_rescan || s.st_mtime != last_mtime
    275308                 || s.st_ino != last_ino || s.st_dev != last_dev
    276309                ) {
     
    280313                        last_dev = s.st_dev;
    281314                        last_ino = s.st_ino;
    282                         check = 0;
    283                         //if (now <= mtime)
    284                         //  sleep(1);
    285                         runsvdir();
     315                        /* if the svdir changed this very second, wait until the
     316                         * next second, because we won't be able to detect more
     317                         * changes within this second */
     318                        while (time(NULL) == last_mtime)
     319                            usleep(100000);
     320                        need_rescan = do_rescan();
    286321                        while (fchdir(curdir) == -1) {
    287322                            warn2_cannot("change directory, pausing", "");
    288323                            sleep(5);
    289324                        }
    290                     } else
     325                    } else {
    291326                        warn2_cannot("change directory to ", svdir);
     327                    }
    292328                }
    293             } else
     329            } else {
    294330                warn2_cannot("stat ", svdir);
    295         }
    296 
     331            }
     332        }
     333
     334#if ENABLE_FEATURE_RUNSVDIR_LOG
    297335        if (rplog) {
    298336            if ((int)(now - stamplog) >= 0) {
    299                 write(logpipe[1], ".", 1);
     337                write(logpipe.wr, ".", 1);
    300338                stamplog = now + 900;
    301339            }
    302340        }
    303 
    304341        pfd[0].revents = 0;
     342#endif
     343        deadline = (need_rescan ? 1 : 5);
    305344        sig_block(SIGCHLD);
    306         deadline = (check ? 1 : 5);
     345#if ENABLE_FEATURE_RUNSVDIR_LOG
    307346        if (rplog)
    308347            poll(pfd, 1, deadline*1000);
    309348        else
     349#endif
    310350            sleep(deadline);
    311351        sig_unblock(SIGCHLD);
    312352
     353#if ENABLE_FEATURE_RUNSVDIR_LOG
    313354        if (pfd[0].revents & POLLIN) {
    314             while (read(logpipe[0], &ch, 1) > 0) {
    315                 if (ch) {
    316                     for (i = 6; i < rploglen; i++)
    317                         rplog[i-1] = rplog[i];
    318                     rplog[rploglen-1] = ch;
    319                 }
    320             }
    321         }
    322 
    323         switch (exitsoon) {
    324         case 1:
    325             _exit(0);
    326         case 2:
     355            char ch;
     356            while (read(logpipe.rd, &ch, 1) > 0) {
     357                if (ch < ' ')
     358                    ch = ' ';
     359                for (i = 6; i < rploglen; i++)
     360                    rplog[i-1] = rplog[i];
     361                rplog[rploglen-1] = ch;
     362            }
     363        }
     364#endif
     365        if (!bb_got_signal)
     366            continue;
     367
     368        /* -s SCRIPT: useful if we are init.
     369         * In this case typically script never returns,
     370         * it halts/powers off/reboots the system. */
     371        if (opt_s_argv[0]) {
     372            /* Single parameter: signal# */
     373            opt_s_argv[1] = utoa(bb_got_signal);
     374            pid = spawn(opt_s_argv);
     375            if (pid > 0) {
     376                /* Remembering to wait for _any_ children,
     377                 * not just pid */
     378                while (wait(NULL) != pid)
     379                    continue;
     380            }
     381        }
     382
     383        if (bb_got_signal == SIGHUP) {
    327384            for (i = 0; i < svnum; i++)
    328385                if (sv[i].pid)
    329386                    kill(sv[i].pid, SIGTERM);
    330             _exit(111);
    331         }
    332     }
    333     /* not reached */
    334     return 0;
    335 }
     387        }
     388        /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */
     389        /* Exit unless we are init */
     390        if (getpid() != 1)
     391            return (SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS;
     392
     393        /* init continues to monitor services forever */
     394        bb_got_signal = 0;
     395    } /* for (;;) */
     396}
  • branches/2.2.9/mindi-busybox/runit/sv.c

    r1765 r2725  
    151151*/
    152152
    153 /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
     153/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
    154154/* TODO: depends on runit_lib.c - review and reduce/eliminate */
    155155
     
    159159#include "runit_lib.h"
    160160
    161 static const char *acts;
    162 static char **service;
    163 static unsigned rc;
     161struct globals {
     162    const char *acts;
     163    char **service;
     164    unsigned rc;
    164165/* "Bernstein" time format: unix + 0x400000000000000aULL */
    165 static uint64_t tstart, tnow;
    166 svstatus_t svstatus;
    167 
    168 
    169 static void fatal_cannot(const char *m1) ATTRIBUTE_NORETURN;
     166    uint64_t tstart, tnow;
     167    svstatus_t svstatus;
     168} FIX_ALIASING;
     169#define G (*(struct globals*)&bb_common_bufsiz1)
     170#define acts         (G.acts        )
     171#define service      (G.service     )
     172#define rc           (G.rc          )
     173#define tstart       (G.tstart      )
     174#define tnow         (G.tnow        )
     175#define svstatus     (G.svstatus    )
     176#define INIT_G() do { } while (0)
     177
     178
     179#define str_equal(s,t) (!strcmp((s), (t)))
     180
     181
     182static void fatal_cannot(const char *m1) NORETURN;
    170183static void fatal_cannot(const char *m1)
    171184{
    172     bb_perror_msg("fatal: cannot %s", m1);
     185    bb_perror_msg("fatal: can't %s", m1);
    173186    _exit(151);
    174187}
     
    180193        printf(": %s", strerror(errno));
    181194    }
    182     puts(""); /* will also flush the output */
     195    bb_putchar('\n'); /* will also flush the output */
    183196}
    184197
     
    212225    int fd, r;
    213226
    214     fd = open_write("supervise/ok");
     227    fd = open("supervise/ok", O_WRONLY|O_NDELAY);
    215228    if (fd == -1) {
    216229        if (errno == ENODEV) {
     
    219232            return 0;
    220233        }
    221         warn("cannot open supervise/ok");
     234        warn("can't open supervise/ok");
    222235        return -1;
    223236    }
    224237    close(fd);
    225     fd = open_read("supervise/status");
     238    fd = open("supervise/status", O_RDONLY|O_NDELAY);
    226239    if (fd == -1) {
    227         warn("cannot open supervise/status");
     240        warn("can't open supervise/status");
    228241        return -1;
    229242    }
     
    234247        break;
    235248    case -1:
    236         warn("cannot read supervise/status");
     249        warn("can't read supervise/status");
    237250        return -1;
    238251    default:
    239252        errno = 0;
    240         warn("cannot read supervise/status: bad format");
     253        warn("can't read supervise/status: bad format");
    241254        return -1;
    242255    }
     
    254267    if (stat("down", &s) == -1) {
    255268        if (errno != ENOENT) {
    256             bb_perror_msg(WARN"cannot stat %s/down", *service);
     269            bb_perror_msg(WARN"can't stat %s/down", *service);
    257270            return 0;
    258271        }
     
    284297}
    285298
    286 static int status(const char *unused)
     299static int status(const char *unused UNUSED_PARAM)
    287300{
    288301    int r;
    289302
    290     r = svstatus_get();
    291     switch (r) { case -1: case 0: return 0; }
     303    if (svstatus_get() <= 0)
     304        return 0;
    292305
    293306    r = svstatus_print(*service);
    294307    if (chdir("log") == -1) {
    295308        if (errno != ENOENT) {
    296             printf("; log: "WARN"cannot change to log service directory: %s",
     309            printf("; log: "WARN"can't change to log service directory: %s",
    297310                    strerror(errno));
    298311        }
     
    301314        svstatus_print("log");
    302315    }
    303     puts(""); /* will also flush the output */
     316    bb_putchar('\n'); /* will also flush the output */
    304317    return r;
    305318}
     
    313326    if (stat("check", &s) == -1) {
    314327        if (errno == ENOENT) return 1;
    315         bb_perror_msg(WARN"cannot stat %s/check", *service);
     328        bb_perror_msg(WARN"can't stat %s/check", *service);
    316329        return 0;
    317330    }
     
    321334    pid = spawn(prog);
    322335    if (pid <= 0) {
    323         bb_perror_msg(WARN"cannot %s child %s/check", "run", *service);
     336        bb_perror_msg(WARN"can't %s child %s/check", "run", *service);
    324337        return 0;
    325338    }
    326     while (wait_pid(&w, pid) == -1) {
    327         if (errno == EINTR) continue;
    328         bb_perror_msg(WARN"cannot %s child %s/check", "wait for", *service);
     339    while (safe_waitpid(pid, &w, 0) == -1) {
     340        bb_perror_msg(WARN"can't %s child %s/check", "wait for", *service);
    329341        return 0;
    330342    }
    331     return !wait_exitcode(w);
     343    return WEXITSTATUS(w) == 0;
    332344}
    333345
     
    335347{
    336348    int r;
    337     unsigned pid;
     349    unsigned pid_le32;
    338350    uint64_t timestamp;
    339351
     
    346358        return -1;
    347359    }
    348     pid = SWAP_LE32(svstatus.pid_le32);
     360    pid_le32 = svstatus.pid_le32;
    349361    switch (*a) {
    350362    case 'x':
    351363        return 0;
    352364    case 'u':
    353         if (!pid || svstatus.run_or_finish != 1) return 0;
     365        if (!pid_le32 || svstatus.run_or_finish != 1) return 0;
    354366        if (!checkscript()) return 0;
    355367        break;
    356368    case 'd':
    357         if (pid) return 0;
     369        if (pid_le32) return 0;
    358370        break;
    359371    case 'c':
    360         if (pid && !checkscript()) return 0;
     372        if (pid_le32 && !checkscript()) return 0;
    361373        break;
    362374    case 't':
    363         if (!pid && svstatus.want == 'd') break;
     375        if (!pid_le32 && svstatus.want == 'd') break;
    364376        timestamp = SWAP_BE64(svstatus.time_be64);
    365         if ((tstart > timestamp) || !pid || svstatus.got_term || !checkscript())
     377        if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript())
    366378            return 0;
    367379        break;
    368380    case 'o':
    369381        timestamp = SWAP_BE64(svstatus.time_be64);
    370         if ((!pid && tstart > timestamp) || (pid && svstatus.want != 'd'))
     382        if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd'))
    371383            return 0;
    372384    }
    373385    printf(OK);
    374386    svstatus_print(*service);
    375     puts(""); /* will also flush the output */
     387    bb_putchar('\n'); /* will also flush the output */
    376388    return 1;
    377389}
     
    379391static int control(const char *a)
    380392{
    381     int fd, r;
    382 
     393    int fd, r, l;
     394
     395/* Is it an optimization?
     396   It causes problems with "sv o SRV; ...; sv d SRV"
     397   ('d' is not passed to SRV because its .want == 'd'):
    383398    if (svstatus_get() <= 0)
    384399        return -1;
    385400    if (svstatus.want == *a)
    386401        return 0;
    387     fd = open_write("supervise/control");
     402*/
     403    fd = open("supervise/control", O_WRONLY|O_NDELAY);
    388404    if (fd == -1) {
    389405        if (errno != ENODEV)
    390             warn("cannot open supervise/control");
     406            warn("can't open supervise/control");
    391407        else
    392408            *a == 'x' ? ok("runsv not running") : failx("runsv not running");
    393409        return -1;
    394410    }
    395     r = write(fd, a, strlen(a));
     411    l = strlen(a);
     412    r = write(fd, a, l);
    396413    close(fd);
    397     if (r != strlen(a)) {
    398         warn("cannot write to supervise/control");
     414    if (r != l) {
     415        warn("can't write to supervise/control");
    399416        return -1;
    400417    }
     
    402419}
    403420
    404 int sv_main(int argc, char **argv);
    405 int sv_main(int argc, char **argv)
     421int sv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     422int sv_main(int argc UNUSED_PARAM, char **argv)
    406423{
    407424    unsigned opt;
    408     unsigned i, want_exit;
    409425    char *x;
    410426    char *action;
    411     const char *varservice = "/var/service/";
    412     unsigned services;
    413     char **servicex;
     427    const char *varservice = CONFIG_SV_DEFAULT_SERVICE_DIR;
    414428    unsigned waitsec = 7;
    415429    smallint kll = 0;
    416     smallint verbose = 0;
     430    int verbose = 0;
    417431    int (*act)(const char*);
    418432    int (*cbk)(const char*);
    419433    int curdir;
     434
     435    INIT_G();
    420436
    421437    xfunc_error_retval = 100;
     
    426442    if (x) waitsec = xatou(x);
    427443
    428     opt = getopt32(argv, "w:v", &x);
    429     if (opt & 1) waitsec = xatou(x); // -w
    430     if (opt & 2) verbose = 1; // -v
    431     argc -= optind;
     444    opt_complementary = "w+:vv"; /* -w N, -v is a counter */
     445    opt = getopt32(argv, "w:v", &waitsec, &verbose);
    432446    argv += optind;
    433447    action = *argv++;
    434448    if (!action || !*argv) bb_show_usage();
    435     service = argv;
    436     services = argc - 1;
    437 
    438     tnow = time(0) + 0x400000000000000aULL;
     449
     450    tnow = time(NULL) + 0x400000000000000aULL;
    439451    tstart = tnow;
    440     curdir = open_read(".");
     452    curdir = open(".", O_RDONLY|O_NDELAY);
    441453    if (curdir == -1)
    442454        fatal_cannot("open current directory");
     
    525537    }
    526538
    527     servicex = service;
    528     for (i = 0; i < services; ++i) {
    529         if ((**service != '/') && (**service != '.')) {
     539    service = argv;
     540    while ((x = *service) != NULL) {
     541        if (x[0] != '/' && x[0] != '.') {
    530542            if (chdir(varservice) == -1)
    531543                goto chdir_failed_0;
    532544        }
    533         if (chdir(*service) == -1) {
     545        if (chdir(x) == -1) {
    534546 chdir_failed_0:
    535             fail("cannot change to service directory");
     547            fail("can't change to service directory");
    536548            goto nullify_service_0;
    537549        }
    538550        if (act && (act(acts) == -1)) {
    539551 nullify_service_0:
    540             *service = NULL;
     552            *service = (char*) -1L; /* "dead" */
    541553        }
    542554        if (fchdir(curdir) == -1)
     
    546558
    547559    if (cbk) while (1) {
     560        int want_exit;
    548561        int diff;
    549562
    550563        diff = tnow - tstart;
    551         service = servicex;
     564        service = argv;
    552565        want_exit = 1;
    553         for (i = 0; i < services; ++i, ++service) {
    554             if (!*service)
    555                 continue;
    556             if ((**service != '/') && (**service != '.')) {
     566        while ((x = *service) != NULL) {
     567            if (x == (char*) -1L) /* "dead" */
     568                goto next;
     569            if (x[0] != '/' && x[0] != '.') {
    557570                if (chdir(varservice) == -1)
    558571                    goto chdir_failed;
    559572            }
    560             if (chdir(*service) == -1) {
     573            if (chdir(x) == -1) {
    561574 chdir_failed:
    562                 fail("cannot change to service directory");
     575                fail("can't change to service directory");
    563576                goto nullify_service;
    564577            }
     
    569582                printf(kll ? "kill: " : "timeout: ");
    570583                if (svstatus_get() > 0) {
    571                     svstatus_print(*service);
     584                    svstatus_print(x);
    572585                    ++rc;
    573586                }
    574                 puts(""); /* will also flush the output */
     587                bb_putchar('\n'); /* will also flush the output */
    575588                if (kll)
    576589                    control("k");
    577590 nullify_service:
    578                 *service = NULL;
     591                *service = (char*) -1L; /* "dead" */
    579592            }
    580593            if (fchdir(curdir) == -1)
    581594                fatal_cannot("change to original directory");
     595 next:
     596            service++;
    582597        }
    583598        if (want_exit) break;
    584599        usleep(420000);
    585         tnow = time(0) + 0x400000000000000aULL;
     600        tnow = time(NULL) + 0x400000000000000aULL;
    586601    }
    587602    return rc > 99 ? 99 : rc;
  • branches/2.2.9/mindi-busybox/runit/svlogd.c

    r1765 r2725  
    2626*/
    2727
    28 /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
     28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
    2929/* TODO: depends on runit_lib.c - review and reduce/eliminate */
     30
     31/*
     32Config files
     33
     34On startup, and after receiving a HUP signal, svlogd checks for each
     35log directory log if the configuration file log/config exists,
     36and if so, reads the file line by line and adjusts configuration
     37for log as follows:
     38
     39If the line is empty, or starts with a #, it is ignored. A line
     40of the form
     41
     42ssize
     43    sets the maximum file size of current when svlogd should rotate
     44    the current log file to size bytes. Default is 1000000.
     45    If size is zero, svlogd doesnt rotate log files
     46    You should set size to at least (2 * len).
     47nnum
     48    sets the number of old log files svlogd should maintain to num.
     49    If svlogd sees more that num old log files in log after log file
     50    rotation, it deletes the oldest one. Default is 10.
     51    If num is zero, svlogd doesnt remove old log files.
     52Nmin
     53    sets the minimum number of old log files svlogd should maintain
     54    to min. min must be less than num. If min is set, and svlogd
     55    cannot write to current because the filesystem is full,
     56    and it sees more than min old log files, it deletes the oldest one.
     57ttimeout
     58    sets the maximum age of the current log file when svlogd should
     59    rotate the current log file to timeout seconds. If current
     60    is timeout seconds old, and is not empty, svlogd forces log file rotation.
     61!processor
     62    tells svlogd to feed each recent log file through processor
     63    (see above) on log file rotation. By default log files are not processed.
     64ua.b.c.d[:port]
     65    tells svlogd to transmit the first len characters of selected
     66    log messages to the IP address a.b.c.d, port number port.
     67    If port isnt set, the default port for syslog is used (514).
     68    len can be set through the -l option, see below. If svlogd
     69    has trouble sending udp packets, it writes error messages
     70    to the log directory. Attention: logging through udp is unreliable,
     71    and should be used in private networks only.
     72Ua.b.c.d[:port]
     73    is the same as the u line above, but the log messages are no longer
     74    written to the log directory, but transmitted through udp only.
     75    Error messages from svlogd concerning sending udp packages still go
     76    to the log directory.
     77pprefix
     78    tells svlogd to prefix each line to be written to the log directory,
     79    to standard error, or through UDP, with prefix.
     80
     81If a line starts with a -, +, e, or E, svlogd matches the first len characters
     82of each log message against pattern and acts accordingly:
     83
     84-pattern
     85    the log message is deselected.
     86+pattern
     87    the log message is selected.
     88epattern
     89    the log message is selected to be printed to standard error.
     90Epattern
     91    the log message is deselected to be printed to standard error.
     92
     93Initially each line is selected to be written to log/current. Deselected
     94log messages are discarded from log. Initially each line is deselected
     95to be written to standard err. Log messages selected for standard error
     96are written to standard error.
     97
     98Pattern Matching
     99
     100svlogd matches a log message against the string pattern as follows:
     101
     102pattern is applied to the log message one character by one, starting
     103with the first. A character not a star (*) and not a plus (+) matches itself.
     104A plus matches the next character in pattern in the log message one
     105or more times. A star before the end of pattern matches any string
     106in the log message that does not include the next character in pattern.
     107A star at the end of pattern matches any string.
     108
     109Timestamps optionally added by svlogd are not considered part
     110of the log message.
     111
     112An svlogd pattern is not a regular expression. For example consider
     113a log message like this
     114
     1152005-12-18_09:13:50.97618 tcpsvd: info: pid 1977 from 10.4.1.14
     116
     117The following pattern doesnt match
     118
     119-*pid*
     120
     121because the first star matches up to the first p in tcpsvd,
     122and then the match fails because i is not s. To match this
     123log message, you can use a pattern like this instead
     124
     125-*: *: pid *
     126*/
    30127
    31128#include <sys/poll.h>
     
    38135#define FMT_PTIME 30
    39136
    40 static unsigned verbose;
    41 static int linemax = 1000;
    42 ////static int buflen = 1024;
    43 static int linelen;
    44 
    45 static char **fndir;
    46 static int fdwdir;
    47 static int wstat;
    48 static unsigned nearest_rotate;
    49 
    50 static char *line;
    51 static smallint exitasap;
    52 static smallint rotateasap;
    53 static smallint reopenasap;
    54 static smallint linecomplete = 1;
    55 
    56 static smallint tmaxflag;
    57 
    58 static char repl;
    59 static const char *replace = "";
    60 
    61 static sigset_t *blocked_sigset;
    62 static int fl_flag_0;
    63 
    64 static struct logdir {
     137struct logdir {
    65138    ////char *btmp;
    66139    /* pattern list to match, in "aa\0bb\0\cc\0\0" form */
     
    82155    char match;
    83156    char matcherr;
    84 } *dir;
    85 static unsigned dirn;
     157};
     158
     159
     160struct globals {
     161    struct logdir *dir;
     162    unsigned verbose;
     163    int linemax;
     164    ////int buflen;
     165    int linelen;
     166
     167    int fdwdir;
     168    char **fndir;
     169    int wstat;
     170    unsigned nearest_rotate;
     171
     172    void* (*memRchr)(const void *, int, size_t);
     173
     174    smallint exitasap;
     175    smallint rotateasap;
     176    smallint reopenasap;
     177    smallint linecomplete;
     178    smallint tmaxflag;
     179
     180    char repl;
     181    const char *replace;
     182    int fl_flag_0;
     183    unsigned dirn;
     184
     185    sigset_t blocked_sigset;
     186};
     187#define G (*ptr_to_globals)
     188#define dir            (G.dir           )
     189#define verbose        (G.verbose       )
     190#define linemax        (G.linemax       )
     191#define buflen         (G.buflen        )
     192#define linelen        (G.linelen       )
     193#define fndir          (G.fndir         )
     194#define fdwdir         (G.fdwdir        )
     195#define wstat          (G.wstat         )
     196#define memRchr        (G.memRchr       )
     197#define nearest_rotate (G.nearest_rotate)
     198#define exitasap       (G.exitasap      )
     199#define rotateasap     (G.rotateasap    )
     200#define reopenasap     (G.reopenasap    )
     201#define linecomplete   (G.linecomplete  )
     202#define tmaxflag       (G.tmaxflag      )
     203#define repl           (G.repl          )
     204#define replace        (G.replace       )
     205#define blocked_sigset (G.blocked_sigset)
     206#define fl_flag_0      (G.fl_flag_0     )
     207#define dirn           (G.dirn          )
     208#define INIT_G() do { \
     209    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
     210    linemax = 1000; \
     211    /*buflen = 1024;*/ \
     212    linecomplete = 1; \
     213    replace = ""; \
     214} while (0)
     215
     216#define line bb_common_bufsiz1
     217
    86218
    87219#define FATAL "fatal: "
     
    90222#define INFO "info: "
    91223
    92 #define usage() bb_show_usage()
    93224static void fatalx(const char *m0)
    94225{
     
    114245static void pause1cannot(const char *m0)
    115246{
    116     bb_perror_msg(PAUSE"cannot %s", m0);
     247    bb_perror_msg(PAUSE"can't %s", m0);
    117248    sleep(3);
    118249}
    119250static void pause2cannot(const char *m0, const char *m1)
    120251{
    121     bb_perror_msg(PAUSE"cannot %s %s", m0, m1);
     252    bb_perror_msg(PAUSE"can't %s %s", m0, m1);
    122253    sleep(3);
    123254}
     
    131262}
    132263
     264static unsigned pmatch(const char *p, const char *s, unsigned len)
     265{
     266    for (;;) {
     267        char c = *p++;
     268        if (!c) return !len;
     269        switch (c) {
     270        case '*':
     271            c = *p;
     272            if (!c) return 1;
     273            for (;;) {
     274                if (!len) return 0;
     275                if (*s == c) break;
     276                ++s;
     277                --len;
     278            }
     279            continue;
     280        case '+':
     281            c = *p++;
     282            if (c != *s) return 0;
     283            for (;;) {
     284                if (!len) return 1;
     285                if (*s != c) break;
     286                ++s;
     287                --len;
     288            }
     289            continue;
     290            /*
     291        case '?':
     292            if (*p == '?') {
     293                if (*s != '?') return 0;
     294                ++p;
     295            }
     296            ++s; --len;
     297            continue;
     298            */
     299        default:
     300            if (!len) return 0;
     301            if (*s != c) return 0;
     302            ++s;
     303            --len;
     304            continue;
     305        }
     306    }
     307    return 0;
     308}
     309
    133310/*** ex fmt_ptime.[ch] ***/
    134311
     
    136313static void fmt_time_human_30nul(char *s)
    137314{
    138     struct tm *t;
     315    struct tm *ptm;
    139316    struct timeval tv;
    140317
    141318    gettimeofday(&tv, NULL);
    142     t = gmtime(&(tv.tv_sec));
     319    ptm = gmtime(&tv.tv_sec);
    143320    sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%06u000",
    144         (unsigned)(1900 + t->tm_year),
    145         (unsigned)(t->tm_mon + 1),
    146         (unsigned)(t->tm_mday),
    147         (unsigned)(t->tm_hour),
    148         (unsigned)(t->tm_min),
    149         (unsigned)(t->tm_sec),
     321        (unsigned)(1900 + ptm->tm_year),
     322        (unsigned)(ptm->tm_mon + 1),
     323        (unsigned)(ptm->tm_mday),
     324        (unsigned)(ptm->tm_hour),
     325        (unsigned)(ptm->tm_min),
     326        (unsigned)(ptm->tm_sec),
    150327        (unsigned)(tv.tv_usec)
    151328    );
     
    175352}
    176353
    177 static unsigned processorstart(struct logdir *ld)
    178 {
     354static void processorstart(struct logdir *ld)
     355{
     356    char sv_ch;
    179357    int pid;
    180358
    181     if (!ld->processor) return 0;
     359    if (!ld->processor) return;
    182360    if (ld->ppid) {
    183361        warnx("processor already running", ld->name);
    184         return 0;
    185     }
    186     while ((pid = fork()) == -1)
    187         pause2cannot("fork for processor", ld->name);
     362        return;
     363    }
     364
     365    /* vfork'ed child trashes this byte, save... */
     366    sv_ch = ld->fnsave[26];
     367
     368    while ((pid = vfork()) == -1)
     369        pause2cannot("vfork for processor", ld->name);
    188370    if (!pid) {
    189         char *prog[4];
    190371        int fd;
    191372
    192373        /* child */
    193         signal(SIGTERM, SIG_DFL);
    194         signal(SIGALRM, SIG_DFL);
    195         signal(SIGHUP, SIG_DFL);
     374        /* Non-ignored signals revert to SIG_DFL on exec anyway */
     375        /*bb_signals(0
     376            + (1 << SIGTERM)
     377            + (1 << SIGALRM)
     378            + (1 << SIGHUP)
     379            , SIG_DFL);*/
    196380        sig_unblock(SIGTERM);
    197381        sig_unblock(SIGALRM);
     
    202386        fd = xopen(ld->fnsave, O_RDONLY|O_NDELAY);
    203387        xmove_fd(fd, 0);
    204         ld->fnsave[26] = 't';
     388        ld->fnsave[26] = 't'; /* <- that's why we need sv_ch! */
    205389        fd = xopen(ld->fnsave, O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT);
    206390        xmove_fd(fd, 1);
    207         fd = open_read("state");
     391        fd = open("state", O_RDONLY|O_NDELAY);
    208392        if (fd == -1) {
    209393            if (errno != ENOENT)
    210                 bb_perror_msg_and_die(FATAL"cannot %s processor %s", "open state for", ld->name);
     394                bb_perror_msg_and_die(FATAL"can't %s processor %s", "open state for", ld->name);
    211395            close(xopen("state", O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT));
    212396            fd = xopen("state", O_RDONLY|O_NDELAY);
     
    217401
    218402// getenv("SHELL")?
    219         prog[0] = (char*)"sh";
    220         prog[1] = (char*)"-c";
    221         prog[2] = ld->processor;
    222         prog[3] = NULL;
    223         execve("/bin/sh", prog, environ);
    224         bb_perror_msg_and_die(FATAL"cannot %s processor %s", "run", ld->name);
    225     }
     403        execl(DEFAULT_SHELL, DEFAULT_SHELL_SHORT_NAME, "-c", ld->processor, (char*) NULL);
     404        bb_perror_msg_and_die(FATAL"can't %s processor %s", "run", ld->name);
     405    }
     406    ld->fnsave[26] = sv_ch; /* ...restore */
    226407    ld->ppid = pid;
    227     return 1;
    228408}
    229409
     
    234414    if (ld->ppid) {
    235415        sig_unblock(SIGHUP);
    236         while (wait_pid(&wstat, ld->ppid) == -1)
     416        while (safe_waitpid(ld->ppid, &wstat, 0) == -1)
    237417            pause2cannot("wait for processor", ld->name);
    238418        sig_block(SIGHUP);
    239419        ld->ppid = 0;
    240420    }
    241     if (ld->fddir == -1) return 1;
     421    if (ld->fddir == -1)
     422        return 1;
    242423    while (fchdir(ld->fddir) == -1)
    243424        pause2cannot("change directory, want processor", ld->name);
    244     if (wait_exitcode(wstat) != 0) {
     425    if (WEXITSTATUS(wstat) != 0) {
    245426        warnx("processor failed, restart", ld->name);
    246427        ld->fnsave[26] = 't';
     
    262443    ld->fnsave[26] = 'u';
    263444    if (unlink(ld->fnsave) == -1)
    264         bb_error_msg(WARNING"cannot unlink: %s/%s", ld->name, ld->fnsave);
     445        bb_error_msg(WARNING"can't unlink: %s/%s", ld->name, ld->fnsave);
    265446    while (rename("newstate", "state") == -1)
    266447        pause2cannot("rename state", ld->name);
     
    287468            if (f->d_name[26] == 't') {
    288469                if (unlink(f->d_name) == -1)
    289                     warn2("cannot unlink processor leftover", f->d_name);
     470                    warn2("can't unlink processor leftover", f->d_name);
    290471            } else {
    291472                ++n;
     
    297478    }
    298479    if (errno)
    299         warn2("cannot read directory", ld->name);
     480        warn2("can't read directory", ld->name);
    300481    closedir(d);
    301482
     
    304485            bb_error_msg(INFO"delete: %s/%s", ld->name, oldest);
    305486        if ((*oldest == '@') && (unlink(oldest) == -1))
    306             warn2("cannot unlink oldest logfile", ld->name);
     487            warn2("can't unlink oldest logfile", ld->name);
    307488    }
    308489}
     
    359540        while ((ld->fdcur = open("current", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600)) == -1)
    360541            pause2cannot("create new current", ld->name);
    361         /* we presume this cannot fail */
    362         ld->filecur = fdopen(ld->fdcur, "a"); ////
     542        while ((ld->filecur = fdopen(ld->fdcur, "a")) == NULL) ////
     543            pause2cannot("create new current", ld->name); /* very unlikely */
    363544        setvbuf(ld->filecur, NULL, _IOFBF, linelen); ////
    364         coe(ld->fdcur);
     545        close_on_exec_on(ld->fdcur);
    365546        ld->size = 0;
    366547        while (fchmod(ld->fdcur, 0644) == -1)
    367548            pause2cannot("set mode of current", ld->name);
     549
    368550        rmoldest(ld);
    369551        processorstart(ld);
     
    413595                        memcpy(oldest, f->d_name, 27);
    414596                }
    415             if (errno) warn2("cannot read directory, want remove old logfile",
     597            if (errno) warn2("can't read directory, want remove old logfile",
    416598                    ld->name);
    417599            closedir(d);
     
    423605                    errno = 0;
    424606                    if (unlink(oldest) == -1) {
    425                         warn2("cannot unlink oldest logfile", ld->name);
     607                        warn2("can't unlink oldest logfile", ld->name);
    426608                        errno = ENOSPC;
    427609                    }
     
    468650}
    469651
    470 static unsigned logdir_open(struct logdir *ld, const char *fn)
     652static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn)
    471653{
    472654    char buf[128];
     
    480662    ld->fddir = open(fn, O_RDONLY|O_NDELAY);
    481663    if (ld->fddir == -1) {
    482         warn2("cannot open log directory", (char*)fn);
     664        warn2("can't open log directory", (char*)fn);
    483665        return 0;
    484666    }
    485     coe(ld->fddir);
     667    close_on_exec_on(ld->fddir);
    486668    if (fchdir(ld->fddir) == -1) {
    487669        logdir_close(ld);
    488         warn2("cannot change directory", (char*)fn);
     670        warn2("can't change directory", (char*)fn);
    489671        return 0;
    490672    }
    491673    ld->fdlock = open("lock", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
    492674    if ((ld->fdlock == -1)
    493      || (lock_exnb(ld->fdlock) == -1)
     675     || (flock(ld->fdlock, LOCK_EX | LOCK_NB) == -1)
    494676    ) {
    495677        logdir_close(ld);
    496         warn2("cannot lock directory", (char*)fn);
     678        warn2("can't lock directory", (char*)fn);
    497679        while (fchdir(fdwdir) == -1)
    498680            pause1cannot("change to initial working directory");
    499681        return 0;
    500682    }
    501     coe(ld->fdlock);
     683    close_on_exec_on(ld->fdlock);
    502684
    503685    ld->size = 0;
     
    512694
    513695    /* read config */
    514     i = open_read_close("config", buf, sizeof(buf));
     696    i = open_read_close("config", buf, sizeof(buf) - 1);
    515697    if (i < 0 && errno != ENOENT)
    516698        bb_perror_msg(WARNING"%s/config", ld->name);
    517699    if (i > 0) {
     700        buf[i] = '\0';
    518701        if (verbose)
    519702            bb_error_msg(INFO"read: %s/config", ld->name);
     
    528711            case 'e':
    529712            case 'E':
     713                /* Filtering requires one-line buffering,
     714                 * resetting the "find newline" function
     715                 * accordingly */
     716                memRchr = memchr;
    530717                /* Add '\n'-terminated line to ld->inst */
    531718                while (1) {
    532                     int l = asprintf(&new, "%s%s\n", ld->inst ? : "", s);
     719                    int l = asprintf(&new, "%s%s\n", ld->inst ? ld->inst : "", s);
    533720                    if (l >= 0 && new)
    534721                        break;
     
    542729                    { "k", 1024 },
    543730                    { "m", 1024*1024 },
    544                     { }
     731                    { "", 0 }
    545732                };
    546733                ld->sizemax = xatou_sfx(&s[1], km_suffixes);
     
    548735            }
    549736            case 'n':
    550                 ld->nmax = xatoi_u(&s[1]);
     737                ld->nmax = xatoi_positive(&s[1]);
    551738                break;
    552739            case 'N':
    553                 ld->nmin = xatoi_u(&s[1]);
     740                ld->nmin = xatoi_positive(&s[1]);
    554741                break;
    555742            case 't': {
     
    558745                    { "h", 60*60 },
    559746                    /*{ "d", 24*60*60 },*/
    560                     { }
     747                    { "", 0 }
    561748                };
    562749                ld->rotate_period = xatou_sfx(&s[1], mh_suffixes);
     
    613800        if (errno != ENOENT) {
    614801            logdir_close(ld);
    615             warn2("cannot stat current", ld->name);
     802            warn2("can't stat current", ld->name);
    616803            while (fchdir(fdwdir) == -1)
    617804                pause1cannot("change to initial working directory");
     
    621808    while ((ld->fdcur = open("current", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600)) == -1)
    622809        pause2cannot("open current", ld->name);
    623     /* we presume this cannot fail */
    624     ld->filecur = fdopen(ld->fdcur, "a"); ////
     810    while ((ld->filecur = fdopen(ld->fdcur, "a")) == NULL)
     811        pause2cannot("open current", ld->name); ////
    625812    setvbuf(ld->filecur, NULL, _IOFBF, linelen); ////
    626813
    627     coe(ld->fdcur);
     814    close_on_exec_on(ld->fdcur);
    628815    while (fchmod(ld->fdcur, 0644) == -1)
    629816        pause2cannot("set mode of current", ld->name);
     
    666853
    667854/* Used for reading stdin */
    668 static int buffer_pread(int fd, char *s, unsigned len)
     855static int buffer_pread(/*int fd, */char *s, unsigned len)
    669856{
    670857    unsigned now;
     
    672859    int i;
    673860
    674     input.fd = 0;
     861    input.fd = STDIN_FILENO;
    675862    input.events = POLLIN;
    676863
     
    701888        }
    702889
    703         sigprocmask(SIG_UNBLOCK, blocked_sigset, NULL);
     890        sigprocmask(SIG_UNBLOCK, &blocked_sigset, NULL);
    704891        i = nearest_rotate - now;
    705892        if (i > 1000000)
     
    708895            i = 1;
    709896        poll(&input, 1, i * 1000);
    710         sigprocmask(SIG_BLOCK, blocked_sigset, NULL);
    711 
    712         i = ndelay_read(fd, s, len);
     897        sigprocmask(SIG_BLOCK, &blocked_sigset, NULL);
     898
     899        i = ndelay_read(STDIN_FILENO, s, len);
    713900        if (i >= 0)
    714901            break;
     
    716903            continue;
    717904        if (errno != EAGAIN) {
    718             warn("cannot read standard input");
     905            warn("can't read standard input");
    719906            break;
    720907        }
     
    750937}
    751938
    752 static void sig_term_handler(int sig_no)
     939static void sig_term_handler(int sig_no UNUSED_PARAM)
    753940{
    754941    if (verbose)
     
    757944}
    758945
    759 static void sig_child_handler(int sig_no)
    760 {
    761     int pid, l;
     946static void sig_child_handler(int sig_no UNUSED_PARAM)
     947{
     948    pid_t pid;
     949    int l;
    762950
    763951    if (verbose)
    764952        bb_error_msg(INFO"sig%s received", "child");
    765     while ((pid = wait_nohang(&wstat)) > 0) {
     953    while ((pid = wait_any_nohang(&wstat)) > 0) {
    766954        for (l = 0; l < dirn; ++l) {
    767955            if (dir[l].ppid == pid) {
     
    774962}
    775963
    776 static void sig_alarm_handler(int sig_no)
     964static void sig_alarm_handler(int sig_no UNUSED_PARAM)
    777965{
    778966    if (verbose)
     
    781969}
    782970
    783 static void sig_hangup_handler(int sig_no)
     971static void sig_hangup_handler(int sig_no UNUSED_PARAM)
    784972{
    785973    if (verbose)
     
    8121000}
    8131001
    814 int svlogd_main(int argc, char **argv);
     1002int svlogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    8151003int svlogd_main(int argc, char **argv)
    8161004{
    817     sigset_t ss;
    818     char *r,*l,*b;
     1005    char *r, *l, *b;
    8191006    ssize_t stdin_cnt = 0;
    8201007    int i;
    8211008    unsigned opt;
    8221009    unsigned timestamp = 0;
    823     void* (*memRchr)(const void *, int, size_t) = memchr;
    824 
    825 #define line bb_common_bufsiz1
     1010
     1011    INIT_G();
    8261012
    8271013    opt_complementary = "tt:vv";
     
    8301016    if (opt & 1) { // -r
    8311017        repl = r[0];
    832         if (!repl || r[1]) usage();
     1018        if (!repl || r[1])
     1019            bb_show_usage();
    8331020    }
    8341021    if (opt & 2) if (!repl) repl = '_'; // -R
    8351022    if (opt & 4) { // -l
    8361023        linemax = xatou_range(l, 0, BUFSIZ-26);
    837         if (linemax == 0) linemax = BUFSIZ-26;
    838         if (linemax < 256) linemax = 256;
     1024        if (linemax == 0)
     1025            linemax = BUFSIZ-26;
     1026        if (linemax < 256)
     1027            linemax = 256;
    8391028    }
    8401029    ////if (opt & 8) { // -b
    841     ////    buflen = xatoi_u(b);
     1030    ////    buflen = xatoi_positive(b);
    8421031    ////    if (buflen == 0) buflen = 1024;
    8431032    ////}
     
    8491038
    8501039    dirn = argc;
    851     if (dirn <= 0) usage();
    852     ////if (buflen <= linemax) usage();
     1040    if (dirn <= 0)
     1041        bb_show_usage();
     1042    ////if (buflen <= linemax) bb_show_usage();
    8531043    fdwdir = xopen(".", O_RDONLY|O_NDELAY);
    854     coe(fdwdir);
    855     dir = xzalloc(dirn * sizeof(struct logdir));
     1044    close_on_exec_on(fdwdir);
     1045    dir = xzalloc(dirn * sizeof(dir[0]));
    8561046    for (i = 0; i < dirn; ++i) {
    8571047        dir[i].fddir = -1;
     
    8671057    fl_flag_0 = fcntl(0, F_GETFL);
    8681058
    869     blocked_sigset = &ss;
    870     sigemptyset(&ss);
    871     sigaddset(&ss, SIGTERM);
    872     sigaddset(&ss, SIGCHLD);
    873     sigaddset(&ss, SIGALRM);
    874     sigaddset(&ss, SIGHUP);
    875     sigprocmask(SIG_BLOCK, &ss, NULL);
    876     sig_catch(SIGTERM, sig_term_handler);
    877     sig_catch(SIGCHLD, sig_child_handler);
    878     sig_catch(SIGALRM, sig_alarm_handler);
    879     sig_catch(SIGHUP, sig_hangup_handler);
    880 
    881     logdirs_reopen();
     1059    sigemptyset(&blocked_sigset);
     1060    sigaddset(&blocked_sigset, SIGTERM);
     1061    sigaddset(&blocked_sigset, SIGCHLD);
     1062    sigaddset(&blocked_sigset, SIGALRM);
     1063    sigaddset(&blocked_sigset, SIGHUP);
     1064    sigprocmask(SIG_BLOCK, &blocked_sigset, NULL);
     1065    bb_signals_recursive_norestart(1 << SIGTERM, sig_term_handler);
     1066    bb_signals_recursive_norestart(1 << SIGCHLD, sig_child_handler);
     1067    bb_signals_recursive_norestart(1 << SIGALRM, sig_alarm_handler);
     1068    bb_signals_recursive_norestart(1 << SIGHUP, sig_hangup_handler);
    8821069
    8831070    /* Without timestamps, we don't have to print each line
    8841071     * separately, so we can look for _last_ newline, not first,
    885      * thus batching writes */
    886     if (!timestamp)
    887         memRchr = memrchr;
     1072     * thus batching writes. If filtering is enabled in config,
     1073     * logdirs_reopen resets it to memchr.
     1074     */
     1075    memRchr = (timestamp ? memchr : memrchr);
     1076
     1077    logdirs_reopen();
    8881078
    8891079    setvbuf(stderr, NULL, _IOFBF, linelen);
     
    9101100            i = linemax - stdin_cnt; /* avail. bytes at tail */
    9111101            if (i >= 128) {
    912                 i = buffer_pread(0, lineptr + stdin_cnt, i);
     1102                i = buffer_pread(/*0, */lineptr + stdin_cnt, i);
    9131103                if (i <= 0) /* EOF or error on stdin */
    9141104                    exitasap = 1;
     
    9251115        linelen = stdin_cnt;
    9261116        if (np) {
    927  print_to_nl:       /* NB: starting from here lineptr may point
     1117 print_to_nl:
     1118            /* NB: starting from here lineptr may point
    9281119             * farther out into line[] */
    9291120            linelen = np - lineptr + 1;
     
    9531144        for (i = 0; i < dirn; ++i) {
    9541145            struct logdir *ld = &dir[i];
    955             if (ld->fddir == -1) continue;
     1146            if (ld->fddir == -1)
     1147                continue;
    9561148            if (ld->inst)
    9571149                logmatch(ld);
    958             if (ld->matcherr == 'e')
    959                 ////full_write(2, printptr, printlen);
    960                 fwrite(lineptr, 1, linelen, stderr);
    961             if (ld->match != '+') continue;
     1150            if (ld->matcherr == 'e') {
     1151                /* runit-1.8.0 compat: if timestamping, do it on stderr too */
     1152                ////full_write(STDERR_FILENO, printptr, printlen);
     1153                fwrite(printptr, 1, printlen, stderr);
     1154            }
     1155            if (ld->match != '+')
     1156                continue;
    9621157            buffer_pwrite(i, printptr, printlen);
    9631158        }
     
    9671162        while (ch != '\n') {
    9681163            /* lineptr is emptied now, safe to use as buffer */
    969             stdin_cnt = exitasap ? -1 : buffer_pread(0, lineptr, linemax);
     1164            stdin_cnt = exitasap ? -1 : buffer_pread(/*0, */lineptr, linemax);
    9701165            if (stdin_cnt <= 0) { /* EOF or error on stdin */
    9711166                exitasap = 1;
     
    9821177            /* linelen == no of chars incl. '\n' (or == stdin_cnt) */
    9831178            for (i = 0; i < dirn; ++i) {
    984                 if (dir[i].fddir == -1) continue;
    985                 if (dir[i].matcherr == 'e')
    986                     ////full_write(2, lineptr, linelen);
     1179                if (dir[i].fddir == -1)
     1180                    continue;
     1181                if (dir[i].matcherr == 'e') {
     1182                    ////full_write(STDERR_FILENO, lineptr, linelen);
    9871183                    fwrite(lineptr, 1, linelen, stderr);
    988                 if (dir[i].match != '+') continue;
     1184                }
     1185                if (dir[i].match != '+')
     1186                    continue;
    9891187                buffer_pwrite(i, lineptr, linelen);
    9901188            }
     
    10021200            memmove((timestamp ? line+26 : line), lineptr, stdin_cnt);
    10031201        }
    1004         fflush(NULL);////
     1202        fflush_all();////
    10051203    }
    10061204
     
    10081206        if (dir[i].ppid)
    10091207            while (!processorstop(&dir[i]))
    1010                 /* repeat */;
     1208                continue;
    10111209        logdir_close(&dir[i]);
    10121210    }
Note: See TracChangeset for help on using the changeset viewer.