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


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
File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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 }
Note: See TracChangeset for help on using the changeset viewer.