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/networking/ifupdown.c

    r1765 r2725  
    22/*
    33 *  ifupdown for busybox
    4  *  Copyright (c) 2002 Glenn McGrath <bug1@iinet.net.au>
     4 *  Copyright (c) 2002 Glenn McGrath
    55 *  Copyright (c) 2003-2004 Erik Andersen <andersen@codepoet.org>
    66 *
     
    1515 *  configuration.
    1616 *
    17  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     17 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1818 */
    1919
     20#include "libbb.h"
     21/* After libbb.h, since it needs sys/types.h on some systems */
    2022#include <sys/utsname.h>
    2123#include <fnmatch.h>
    22 #include <getopt.h>
    23 
    24 #include "libbb.h"
    2524
    2625#define MAX_OPT_DEPTH 10
     
    3332#endif
    3433
     34#define UDHCPC_CMD_OPTIONS CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS
     35
    3536#define debug_noise(args...) /*fprintf(stderr, args)*/
    3637
     
    4243struct method_t {
    4344    const char *name;
    44     int (*up)(struct interface_defn_t *ifd, execfn *e);
    45     int (*down)(struct interface_defn_t *ifd, execfn *e);
     45    int (*up)(struct interface_defn_t *ifd, execfn *e) FAST_FUNC;
     46    int (*down)(struct interface_defn_t *ifd, execfn *e) FAST_FUNC;
    4647};
    4748
     
    8788};
    8889
    89 #define OPTION_STR "anvf" USE_FEATURE_IFUPDOWN_MAPPING("m") "i:"
     90
     91#define OPTION_STR "anvf" IF_FEATURE_IFUPDOWN_MAPPING("m") "i:"
    9092enum {
    91     OPT_do_all = 0x1,
    92     OPT_no_act = 0x2,
    93     OPT_verbose = 0x4,
    94     OPT_force = 0x8,
     93    OPT_do_all      = 0x1,
     94    OPT_no_act      = 0x2,
     95    OPT_verbose     = 0x4,
     96    OPT_force       = 0x8,
    9597    OPT_no_mappings = 0x10,
    9698};
    97 #define DO_ALL (option_mask32 & OPT_do_all)
    98 #define NO_ACT (option_mask32 & OPT_no_act)
    99 #define VERBOSE (option_mask32 & OPT_verbose)
    100 #define FORCE (option_mask32 & OPT_force)
     99#define DO_ALL      (option_mask32 & OPT_do_all)
     100#define NO_ACT      (option_mask32 & OPT_no_act)
     101#define VERBOSE     (option_mask32 & OPT_verbose)
     102#define FORCE       (option_mask32 & OPT_force)
    101103#define NO_MAPPINGS (option_mask32 & OPT_no_mappings)
    102104
    103 static char **my_environ;
    104 
    105 static const char *startup_PATH;
     105
     106struct globals {
     107    char **my_environ;
     108    const char *startup_PATH;
     109} FIX_ALIASING;
     110#define G (*(struct globals*)&bb_common_bufsiz1)
     111#define INIT_G() do { } while (0)
     112
    106113
    107114#if ENABLE_FEATURE_IFUPDOWN_IPV4 || ENABLE_FEATURE_IFUPDOWN_IPV6
     
    126133
    127134    if (i == 0)
    128         return -r[llen];
     135        return - (unsigned char)r[llen];
    129136    return i;
    130137}
     
    135142
    136143    if (strncmpz(id, "iface", idlen) == 0) {
    137         char *result;
    138         static char label_buf[20];
    139         safe_strncpy(label_buf, ifd->iface, sizeof(label_buf));
    140         result = strchr(label_buf, ':');
    141         if (result) {
    142             *result = '\0';
    143         }
    144         return label_buf;
     144        // ubuntu's ifup doesn't do this:
     145        //static char *label_buf;
     146        //char *result;
     147        //free(label_buf);
     148        //label_buf = xstrdup(ifd->iface);
     149        // Remove virtual iface suffix
     150        //result = strchrnul(label_buf, ':');
     151        //*result = '\0';
     152        //return label_buf;
     153
     154        return ifd->iface;
    145155    }
    146156    if (strncmpz(id, "label", idlen) == 0) {
     
    155165}
    156166
    157 #if ENABLE_FEATURE_IFUPDOWN_IP
     167# if ENABLE_FEATURE_IFUPDOWN_IP
    158168static int count_netmask_bits(const char *dotted_quad)
    159169{
     
    186196    return result;
    187197}
    188 #endif
     198# endif
    189199
    190200static char *parse(const char *command, struct interface_defn_t *ifd)
     
    249259
    250260                if (varvalue) {
     261# if ENABLE_FEATURE_IFUPDOWN_IP
     262                    /* "hwaddress <class> <address>":
     263                     * unlike ifconfig, ip doesnt want <class>
     264                     * (usually "ether" keyword). Skip it. */
     265                    if (strncmp(command, "hwaddress", 9) == 0) {
     266                        varvalue = skip_whitespace(skip_non_whitespace(varvalue));
     267                    }
     268# endif
    251269                    addstr(&result, varvalue, strlen(varvalue));
    252270                } else {
    253 #if ENABLE_FEATURE_IFUPDOWN_IP
     271# if ENABLE_FEATURE_IFUPDOWN_IP
    254272                    /* Sigh...  Add a special case for 'ip' to convert from
    255273                     * dotted quad to bit count style netmasks.  */
     
    267285                        }
    268286                    }
    269 #endif
     287# endif
    270288                    okay[opt_depth - 1] = 0;
    271289                }
     
    312330    return 1;
    313331}
    314 #endif
     332
     333#endif /* FEATURE_IFUPDOWN_IPV4 || FEATURE_IFUPDOWN_IPV6 */
     334
    315335
    316336#if ENABLE_FEATURE_IFUPDOWN_IPV6
    317 static int loopback_up6(struct interface_defn_t *ifd, execfn *exec)
    318 {
    319 #if ENABLE_FEATURE_IFUPDOWN_IP
     337
     338static int FAST_FUNC loopback_up6(struct interface_defn_t *ifd, execfn *exec)
     339{
     340# if ENABLE_FEATURE_IFUPDOWN_IP
    320341    int result;
    321342    result = execute("ip addr add ::1 dev %iface%", ifd, exec);
    322343    result += execute("ip link set %iface% up", ifd, exec);
    323344    return ((result == 2) ? 2 : 0);
    324 #else
     345# else
    325346    return execute("ifconfig %iface% add ::1", ifd, exec);
    326 #endif
    327 }
    328 
    329 static int loopback_down6(struct interface_defn_t *ifd, execfn *exec)
    330 {
    331 #if ENABLE_FEATURE_IFUPDOWN_IP
     347# endif
     348}
     349
     350static int FAST_FUNC loopback_down6(struct interface_defn_t *ifd, execfn *exec)
     351{
     352# if ENABLE_FEATURE_IFUPDOWN_IP
    332353    return execute("ip link set %iface% down", ifd, exec);
    333 #else
     354# else
    334355    return execute("ifconfig %iface% del ::1", ifd, exec);
    335 #endif
    336 }
    337 
    338 static int static_up6(struct interface_defn_t *ifd, execfn *exec)
     356# endif
     357}
     358
     359static int FAST_FUNC manual_up_down6(struct interface_defn_t *ifd UNUSED_PARAM, execfn *exec UNUSED_PARAM)
     360{
     361    return 1;
     362}
     363
     364static int FAST_FUNC static_up6(struct interface_defn_t *ifd, execfn *exec)
    339365{
    340366    int result;
    341 #if ENABLE_FEATURE_IFUPDOWN_IP
     367# if ENABLE_FEATURE_IFUPDOWN_IP
    342368    result = execute("ip addr add %address%/%netmask% dev %iface%[[ label %label%]]", ifd, exec);
    343     result += execute("ip link set[[ mtu %mtu%]][[ address %hwaddress%]] %iface% up", ifd, exec);
     369    result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec);
    344370    /* Was: "[[ ip ....%gateway% ]]". Removed extra spaces w/o checking */
    345371    result += execute("[[ip route add ::/0 via %gateway%]]", ifd, exec);
    346 #else
     372# else
    347373    result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec);
    348374    result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec);
    349375    result += execute("[[route -A inet6 add ::/0 gw %gateway%]]", ifd, exec);
    350 #endif
     376# endif
    351377    return ((result == 3) ? 3 : 0);
    352378}
    353379
    354 static int static_down6(struct interface_defn_t *ifd, execfn *exec)
    355 {
    356 #if ENABLE_FEATURE_IFUPDOWN_IP
     380static int FAST_FUNC static_down6(struct interface_defn_t *ifd, execfn *exec)
     381{
     382# if ENABLE_FEATURE_IFUPDOWN_IP
    357383    return execute("ip link set %iface% down", ifd, exec);
    358 #else
     384# else
    359385    return execute("ifconfig %iface% down", ifd, exec);
    360 #endif
    361 }
    362 
    363 #if ENABLE_FEATURE_IFUPDOWN_IP
    364 static int v4tunnel_up(struct interface_defn_t *ifd, execfn *exec)
     386# endif
     387}
     388
     389# if ENABLE_FEATURE_IFUPDOWN_IP
     390static int FAST_FUNC v4tunnel_up(struct interface_defn_t *ifd, execfn *exec)
    365391{
    366392    int result;
     
    373399}
    374400
    375 static int v4tunnel_down(struct interface_defn_t * ifd, execfn * exec)
     401static int FAST_FUNC v4tunnel_down(struct interface_defn_t * ifd, execfn * exec)
    376402{
    377403    return execute("ip tunnel del %iface%", ifd, exec);
    378404}
    379 #endif
     405# endif
    380406
    381407static const struct method_t methods6[] = {
    382 #if ENABLE_FEATURE_IFUPDOWN_IP
    383     { "v4tunnel", v4tunnel_up, v4tunnel_down, },
    384 #endif
    385     { "static", static_up6, static_down6, },
    386     { "loopback", loopback_up6, loopback_down6, },
     408# if ENABLE_FEATURE_IFUPDOWN_IP
     409    { "v4tunnel" , v4tunnel_up     , v4tunnel_down   , },
     410# endif
     411    { "static"   , static_up6      , static_down6    , },
     412    { "manual"   , manual_up_down6 , manual_up_down6 , },
     413    { "loopback" , loopback_up6    , loopback_down6  , },
    387414};
    388415
     
    392419    methods6
    393420};
     421
    394422#endif /* FEATURE_IFUPDOWN_IPV6 */
    395423
     424
    396425#if ENABLE_FEATURE_IFUPDOWN_IPV4
    397 static int loopback_up(struct interface_defn_t *ifd, execfn *exec)
    398 {
    399 #if ENABLE_FEATURE_IFUPDOWN_IP
     426
     427static int FAST_FUNC loopback_up(struct interface_defn_t *ifd, execfn *exec)
     428{
     429# if ENABLE_FEATURE_IFUPDOWN_IP
    400430    int result;
    401431    result = execute("ip addr add 127.0.0.1/8 dev %iface%", ifd, exec);
    402432    result += execute("ip link set %iface% up", ifd, exec);
    403433    return ((result == 2) ? 2 : 0);
    404 #else
     434# else
    405435    return execute("ifconfig %iface% 127.0.0.1 up", ifd, exec);
    406 #endif
    407 }
    408 
    409 static int loopback_down(struct interface_defn_t *ifd, execfn *exec)
    410 {
    411 #if ENABLE_FEATURE_IFUPDOWN_IP
     436# endif
     437}
     438
     439static int FAST_FUNC loopback_down(struct interface_defn_t *ifd, execfn *exec)
     440{
     441# if ENABLE_FEATURE_IFUPDOWN_IP
    412442    int result;
    413443    result = execute("ip addr flush dev %iface%", ifd, exec);
    414444    result += execute("ip link set %iface% down", ifd, exec);
    415445    return ((result == 2) ? 2 : 0);
    416 #else
     446# else
    417447    return execute("ifconfig %iface% 127.0.0.1 down", ifd, exec);
    418 #endif
    419 }
    420 
    421 static int static_up(struct interface_defn_t *ifd, execfn *exec)
     448# endif
     449}
     450
     451static int FAST_FUNC static_up(struct interface_defn_t *ifd, execfn *exec)
    422452{
    423453    int result;
    424 #if ENABLE_FEATURE_IFUPDOWN_IP
     454# if ENABLE_FEATURE_IFUPDOWN_IP
    425455    result = execute("ip addr add %address%/%bnmask%[[ broadcast %broadcast%]] "
    426456            "dev %iface%[[ peer %pointopoint%]][[ label %label%]]", ifd, exec);
    427     result += execute("ip link set[[ mtu %mtu%]][[ address %hwaddress%]] %iface% up", ifd, exec);
     457    result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec);
    428458    result += execute("[[ip route add default via %gateway% dev %iface%]]", ifd, exec);
    429459    return ((result == 3) ? 3 : 0);
    430 #else
     460# else
    431461    /* ifconfig said to set iface up before it processes hw %hwaddress%,
    432462     * which then of course fails. Thus we run two separate ifconfig */
     
    438468    result += execute("[[route add default gw %gateway% %iface%]]", ifd, exec);
    439469    return ((result == 3) ? 3 : 0);
    440 #endif
    441 }
    442 
    443 static int static_down(struct interface_defn_t *ifd, execfn *exec)
     470# endif
     471}
     472
     473static int FAST_FUNC static_down(struct interface_defn_t *ifd, execfn *exec)
    444474{
    445475    int result;
    446 #if ENABLE_FEATURE_IFUPDOWN_IP
     476# if ENABLE_FEATURE_IFUPDOWN_IP
    447477    result = execute("ip addr flush dev %iface%", ifd, exec);
    448478    result += execute("ip link set %iface% down", ifd, exec);
    449 #else
    450     result = execute("[[route del default gw %gateway% %iface%]]", ifd, exec);
     479# else
     480    /* result = execute("[[route del default gw %gateway% %iface%]]", ifd, exec); */
     481    /* Bringing the interface down deletes the routes in itself.
     482       Otherwise this fails if we reference 'gateway' when using this from dhcp_down */
     483    result = 1;
    451484    result += execute("ifconfig %iface% down", ifd, exec);
    452 #endif
     485# endif
    453486    return ((result == 2) ? 2 : 0);
    454487}
    455488
    456 #if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP
    457 struct dhcp_client_t
    458 {
     489# if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP
     490struct dhcp_client_t {
    459491    const char *name;
    460492    const char *startcmd;
     
    464496static const struct dhcp_client_t ext_dhcp_clients[] = {
    465497    { "dhcpcd",
    466         "dhcpcd[[ -h %hostname%]][[ -i %vendor%]][[ -I %clientid%]][[ -l %leasetime%]] %iface%",
     498        "dhcpcd[[ -h %hostname%]][[ -i %vendor%]][[ -I %client%]][[ -l %leasetime%]] %iface%",
    467499        "dhcpcd -k %iface%",
    468500    },
     
    476508    },
    477509    { "udhcpc",
    478         "udhcpc -R -n -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]]",
     510        "udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -H %hostname%]][[ -c %client%]]"
     511                "[[ -s %script%]][[ %udhcpc_opts%]]",
    479512        "kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null",
    480513    },
    481514};
    482 #endif /* ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCPC */
    483 
    484 static int dhcp_up(struct interface_defn_t *ifd, execfn *exec)
    485 {
    486 #if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP
    487     int i;
    488 #if ENABLE_FEATURE_IFUPDOWN_IP
     515# endif /* FEATURE_IFUPDOWN_EXTERNAL_DHCPC */
     516
     517# if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP
     518static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd, execfn *exec)
     519{
     520    unsigned i;
     521#  if ENABLE_FEATURE_IFUPDOWN_IP
    489522    /* ip doesn't up iface when it configures it (unlike ifconfig) */
    490     if (!execute("ip link set %iface% up", ifd, exec))
     523    if (!execute("ip link set[[ addr %hwaddress%]] %iface% up", ifd, exec))
    491524        return 0;
    492 #endif
     525#  else
     526    /* needed if we have hwaddress on dhcp iface */
     527    if (!execute("ifconfig %iface%[[ hw %hwaddress%]] up", ifd, exec))
     528        return 0;
     529#  endif
    493530    for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) {
    494531        if (exists_execable(ext_dhcp_clients[i].name))
     
    497534    bb_error_msg("no dhcp clients found");
    498535    return 0;
    499 #elif ENABLE_APP_UDHCPC
    500 #if ENABLE_FEATURE_IFUPDOWN_IP
     536}
     537# elif ENABLE_UDHCPC
     538static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd, execfn *exec)
     539{
     540#  if ENABLE_FEATURE_IFUPDOWN_IP
    501541    /* ip doesn't up iface when it configures it (unlike ifconfig) */
    502     if (!execute("ip link set %iface% up", ifd, exec))
     542    if (!execute("ip link set[[ addr %hwaddress%]] %iface% up", ifd, exec))
    503543        return 0;
    504 #endif
    505     return execute("udhcpc -R -n -p /var/run/udhcpc.%iface%.pid "
    506             "-i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]]",
     544#  else
     545    /* needed if we have hwaddress on dhcp iface */
     546    if (!execute("ifconfig %iface%[[ hw %hwaddress%]] up", ifd, exec))
     547        return 0;
     548#  endif
     549    return execute("udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid "
     550            "-i %iface%[[ -H %hostname%]][[ -c %client%]][[ -s %script%]][[ %udhcpc_opts%]]",
    507551            ifd, exec);
    508 #else
     552}
     553# else
     554static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd UNUSED_PARAM,
     555        execfn *exec UNUSED_PARAM)
     556{
    509557    return 0; /* no dhcp support */
    510 #endif
    511 }
    512 
    513 static int dhcp_down(struct interface_defn_t *ifd, execfn *exec)
    514 {
    515 #if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP
    516     int i;
     558}
     559# endif
     560
     561# if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP
     562static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec)
     563{
     564    int result = 0;
     565    unsigned i;
     566
    517567    for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) {
    518         if (exists_execable(ext_dhcp_clients[i].name))
    519             return execute(ext_dhcp_clients[i].stopcmd, ifd, exec);
    520     }
    521     bb_error_msg("no dhcp clients found, using static interface shutdown");
    522     return static_down(ifd, exec);
    523 #elif ENABLE_APP_UDHCPC
    524     return execute("kill "
    525                    "`cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec);
    526 #else
     568        if (exists_execable(ext_dhcp_clients[i].name)) {
     569            result = execute(ext_dhcp_clients[i].stopcmd, ifd, exec);
     570            if (result)
     571                break;
     572        }
     573    }
     574
     575    if (!result)
     576        bb_error_msg("warning: no dhcp clients found and stopped");
     577
     578    /* Sleep a bit, otherwise static_down tries to bring down interface too soon,
     579       and it may come back up because udhcpc is still shutting down */
     580    usleep(100000);
     581    result += static_down(ifd, exec);
     582    return ((result == 3) ? 3 : 0);
     583}
     584# elif ENABLE_UDHCPC
     585static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec)
     586{
     587    int result;
     588    result = execute(
     589        "test -f /var/run/udhcpc.%iface%.pid && "
     590        "kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null",
     591        ifd, exec);
     592    /* Also bring the hardware interface down since
     593       killing the dhcp client alone doesn't do it.
     594       This enables consecutive ifup->ifdown->ifup */
     595    /* Sleep a bit, otherwise static_down tries to bring down interface too soon,
     596       and it may come back up because udhcpc is still shutting down */
     597    usleep(100000);
     598    result += static_down(ifd, exec);
     599    return ((result == 3) ? 3 : 0);
     600}
     601# else
     602static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd UNUSED_PARAM,
     603        execfn *exec UNUSED_PARAM)
     604{
    527605    return 0; /* no dhcp support */
    528 #endif
    529 }
    530 
    531 static int manual_up_down(struct interface_defn_t *ifd, execfn *exec)
     606}
     607# endif
     608
     609static int FAST_FUNC manual_up_down(struct interface_defn_t *ifd UNUSED_PARAM, execfn *exec UNUSED_PARAM)
    532610{
    533611    return 1;
    534612}
    535613
    536 static int bootp_up(struct interface_defn_t *ifd, execfn *exec)
     614static int FAST_FUNC bootp_up(struct interface_defn_t *ifd, execfn *exec)
    537615{
    538616    return execute("bootpc[[ --bootfile %bootfile%]] --dev %iface%"
     
    541619}
    542620
    543 static int ppp_up(struct interface_defn_t *ifd, execfn *exec)
     621static int FAST_FUNC ppp_up(struct interface_defn_t *ifd, execfn *exec)
    544622{
    545623    return execute("pon[[ %provider%]]", ifd, exec);
    546624}
    547625
    548 static int ppp_down(struct interface_defn_t *ifd, execfn *exec)
     626static int FAST_FUNC ppp_down(struct interface_defn_t *ifd, execfn *exec)
    549627{
    550628    return execute("poff[[ %provider%]]", ifd, exec);
    551629}
    552630
    553 static int wvdial_up(struct interface_defn_t *ifd, execfn *exec)
     631static int FAST_FUNC wvdial_up(struct interface_defn_t *ifd, execfn *exec)
    554632{
    555633    return execute("start-stop-daemon --start -x wvdial "
     
    557635}
    558636
    559 static int wvdial_down(struct interface_defn_t *ifd, execfn *exec)
     637static int FAST_FUNC wvdial_down(struct interface_defn_t *ifd, execfn *exec)
    560638{
    561639    return execute("start-stop-daemon --stop -x wvdial "
     
    564642
    565643static const struct method_t methods[] = {
    566     { "manual", manual_up_down, manual_up_down, },
    567     { "wvdial", wvdial_up, wvdial_down, },
    568     { "ppp", ppp_up, ppp_down, },
    569     { "static", static_up, static_down, },
    570     { "bootp", bootp_up, static_down, },
    571     { "dhcp", dhcp_up, dhcp_down, },
    572     { "loopback", loopback_up, loopback_down, },
     644    { "manual"  , manual_up_down, manual_up_down, },
     645    { "wvdial"  , wvdial_up     , wvdial_down   , },
     646    { "ppp"     , ppp_up        , ppp_down      , },
     647    { "static"  , static_up     , static_down   , },
     648    { "bootp"   , bootp_up      , static_down   , },
     649    { "dhcp"    , dhcp_up       , dhcp_down     , },
     650    { "loopback", loopback_up   , loopback_down , },
    573651};
    574652
     
    579657};
    580658
    581 #endif  /* if ENABLE_FEATURE_IFUPDOWN_IPV4 */
    582 
     659#endif  /* FEATURE_IFUPDOWN_IPV4 */
     660
     661
     662/* Returns pointer to the next word, or NULL.
     663 * In 1st case, advances *buf to the word after this one.
     664 */
    583665static char *next_word(char **buf)
    584666{
    585     unsigned short length;
     667    unsigned length;
    586668    char *word;
    587 
    588     if (!buf || !*buf || !**buf) {
    589         return NULL;
    590     }
    591669
    592670    /* Skip over leading whitespace */
    593671    word = skip_whitespace(*buf);
    594672
    595     /* Skip over comments */
    596     if (*word == '#') {
     673    /* Stop on EOL */
     674    if (*word == '\0')
    597675        return NULL;
    598     }
    599 
    600     /* Find the length of this word */
     676
     677    /* Find the length of this word (can't be 0) */
    601678    length = strcspn(word, " \t\n");
    602     if (length == 0) {
    603         return NULL;
    604     }
    605     *buf = word + length;
    606     /*DBU:[dave@cray.com] if we are already at EOL dont't increment beyond it */
    607     if (**buf) {
    608         **buf = '\0';
    609         (*buf)++;
    610     }
     679
     680    /* Unless we are already at NUL, store NUL and advance */
     681    if (word[length] != '\0')
     682        word[length++] = '\0';
     683
     684    *buf = skip_whitespace(word + length);
    611685
    612686    return word;
     
    634708    if (!name)
    635709        return NULL;
    636 
     710    /* TODO: use index_in_str_array() */
    637711    for (i = 0; i < af->n_methods; i++) {
    638712        if (strcmp(af->method[i].name, name) == 0) {
     
    643717}
    644718
    645 static const llist_t *find_list_string(const llist_t *list, const char *string)
    646 {
    647     if (string == NULL)
    648         return NULL;
    649 
    650     while (list) {
    651         if (strcmp(list->data, string) == 0) {
    652             return list;
    653         }
    654         list = list->link;
    655     }
    656     return NULL;
    657 }
    658 
    659719static struct interfaces_file_t *read_interfaces(const char *filename)
    660720{
     721    /* Let's try to be compatible.
     722     *
     723     * "man 5 interfaces" says:
     724     * Lines starting with "#" are ignored. Note that end-of-line
     725     * comments are NOT supported, comments must be on a line of their own.
     726     * A line may be extended across multiple lines by making
     727     * the last character a backslash.
     728     *
     729     * Seen elsewhere in example config file:
     730     * A first non-blank "#" character makes the rest of the line
     731     * be ignored. Blank lines are ignored. Lines may be indented freely.
     732     * A "\" character at the very end of the line indicates the next line
     733     * should be treated as a continuation of the current one.
     734     */
    661735#if ENABLE_FEATURE_IFUPDOWN_MAPPING
    662736    struct mapping_defn_t *currmap = NULL;
     
    665739    struct interfaces_file_t *defn;
    666740    FILE *f;
    667     char *firstword;
    668741    char *buf;
    669 
     742    char *first_word;
     743    char *rest_of_line;
    670744    enum { NONE, IFACE, MAPPING } currently_processing = NONE;
    671745
    672     defn = xzalloc(sizeof(struct interfaces_file_t));
    673 
    674     f = xfopen(filename, "r");
    675 
    676     while ((buf = xmalloc_getline(f)) != NULL) {
    677         char *buf_ptr = buf;
    678 
    679         firstword = next_word(&buf_ptr);
    680         if (firstword == NULL) {
     746    defn = xzalloc(sizeof(*defn));
     747    f = xfopen_for_read(filename);
     748
     749    while ((buf = xmalloc_fgetline(f)) != NULL) {
     750#if ENABLE_DESKTOP
     751        /* Trailing "\" concatenates lines */
     752        char *p;
     753        while ((p = last_char_is(buf, '\\')) != NULL) {
     754            *p = '\0';
     755            rest_of_line = xmalloc_fgetline(f);
     756            if (!rest_of_line)
     757                break;
     758            p = xasprintf("%s%s", buf, rest_of_line);
    681759            free(buf);
    682             continue;   /* blank line */
    683         }
    684 
    685         if (strcmp(firstword, "mapping") == 0) {
     760            free(rest_of_line);
     761            buf = p;
     762        }
     763#endif
     764        rest_of_line = buf;
     765        first_word = next_word(&rest_of_line);
     766        if (!first_word || *first_word == '#') {
     767            free(buf);
     768            continue; /* blank/comment line */
     769        }
     770
     771        if (strcmp(first_word, "mapping") == 0) {
    686772#if ENABLE_FEATURE_IFUPDOWN_MAPPING
    687             currmap = xzalloc(sizeof(struct mapping_defn_t));
    688 
    689             while ((firstword = next_word(&buf_ptr)) != NULL) {
    690                 if (currmap->max_matches == currmap->n_matches) {
    691                     currmap->max_matches = currmap->max_matches * 2 + 1;
    692                     currmap->match = xrealloc(currmap->match, sizeof(currmap->match) * currmap->max_matches);
    693                 }
    694 
    695                 currmap->match[currmap->n_matches++] = xstrdup(firstword);
    696             }
    697             currmap->max_mappings = 0;
    698             currmap->n_mappings = 0;
    699             currmap->mapping = NULL;
    700             currmap->script = NULL;
     773            currmap = xzalloc(sizeof(*currmap));
     774
     775            while ((first_word = next_word(&rest_of_line)) != NULL) {
     776                currmap->match = xrealloc_vector(currmap->match, 4, currmap->n_matches);
     777                currmap->match[currmap->n_matches++] = xstrdup(first_word);
     778            }
     779            /*currmap->max_mappings = 0; - done by xzalloc */
     780            /*currmap->n_mappings = 0;*/
     781            /*currmap->mapping = NULL;*/
     782            /*currmap->script = NULL;*/
    701783            {
    702784                struct mapping_defn_t **where = &defn->mappings;
     
    705787                }
    706788                *where = currmap;
    707                 currmap->next = NULL;
     789                /*currmap->next = NULL;*/
    708790            }
    709791            debug_noise("Added mapping\n");
    710792#endif
    711793            currently_processing = MAPPING;
    712         } else if (strcmp(firstword, "iface") == 0) {
     794        } else if (strcmp(first_word, "iface") == 0) {
    713795            static const struct address_family_t *const addr_fams[] = {
    714796#if ENABLE_FEATURE_IFUPDOWN_IPV4
     
    720802                NULL
    721803            };
    722 
    723804            char *iface_name;
    724805            char *address_family_name;
     
    726807            llist_t *iface_list;
    727808
    728             currif = xzalloc(sizeof(struct interface_defn_t));
    729             iface_name = next_word(&buf_ptr);
    730             address_family_name = next_word(&buf_ptr);
    731             method_name = next_word(&buf_ptr);
    732 
    733             if (buf_ptr == NULL) {
    734                 bb_error_msg("too few parameters for line \"%s\"", buf);
    735                 return NULL;
    736             }
     809            currif = xzalloc(sizeof(*currif));
     810            iface_name = next_word(&rest_of_line);
     811            address_family_name = next_word(&rest_of_line);
     812            method_name = next_word(&rest_of_line);
     813
     814            if (method_name == NULL)
     815                bb_error_msg_and_die("too few parameters for line \"%s\"", buf);
    737816
    738817            /* ship any trailing whitespace */
    739             buf_ptr = skip_whitespace(buf_ptr);
    740 
    741             if (buf_ptr[0] != '\0') {
    742                 bb_error_msg("too many parameters \"%s\"", buf);
    743                 return NULL;
    744             }
     818            rest_of_line = skip_whitespace(rest_of_line);
     819
     820            if (rest_of_line[0] != '\0' /* && rest_of_line[0] != '#' */)
     821                bb_error_msg_and_die("too many parameters \"%s\"", buf);
    745822
    746823            currif->iface = xstrdup(iface_name);
    747824
    748825            currif->address_family = get_address_family(addr_fams, address_family_name);
    749             if (!currif->address_family) {
    750                 bb_error_msg("unknown address type \"%s\"", address_family_name);
    751                 return NULL;
    752             }
     826            if (!currif->address_family)
     827                bb_error_msg_and_die("unknown address type \"%s\"", address_family_name);
    753828
    754829            currif->method = get_method(currif->address_family, method_name);
    755             if (!currif->method) {
    756                 bb_error_msg("unknown method \"%s\"", method_name);
    757                 return NULL;
    758             }
     830            if (!currif->method)
     831                bb_error_msg_and_die("unknown method \"%s\"", method_name);
    759832
    760833            for (iface_list = defn->ifaces; iface_list; iface_list = iface_list->link) {
    761834                struct interface_defn_t *tmp = (struct interface_defn_t *) iface_list->data;
    762                 if ((strcmp(tmp->iface, currif->iface) == 0) &&
    763                     (tmp->address_family == currif->address_family)) {
    764                     bb_error_msg("duplicate interface \"%s\"", tmp->iface);
    765                     return NULL;
     835                if ((strcmp(tmp->iface, currif->iface) == 0)
     836                 && (tmp->address_family == currif->address_family)
     837                ) {
     838                    bb_error_msg_and_die("duplicate interface \"%s\"", tmp->iface);
    766839                }
    767840            }
     
    770843            debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name);
    771844            currently_processing = IFACE;
    772         } else if (strcmp(firstword, "auto") == 0) {
    773             while ((firstword = next_word(&buf_ptr)) != NULL) {
     845        } else if (strcmp(first_word, "auto") == 0) {
     846            while ((first_word = next_word(&rest_of_line)) != NULL) {
    774847
    775848                /* Check the interface isnt already listed */
    776                 if (find_list_string(defn->autointerfaces, firstword)) {
     849                if (llist_find_str(defn->autointerfaces, first_word)) {
    777850                    bb_perror_msg_and_die("interface declared auto twice \"%s\"", buf);
    778851                }
    779852
    780853                /* Add the interface to the list */
    781                 llist_add_to_end(&(defn->autointerfaces), xstrdup(firstword));
    782                 debug_noise("\nauto %s\n", firstword);
     854                llist_add_to_end(&(defn->autointerfaces), xstrdup(first_word));
     855                debug_noise("\nauto %s\n", first_word);
    783856            }
    784857            currently_processing = NONE;
     
    786859            switch (currently_processing) {
    787860            case IFACE:
    788                 {
     861                if (rest_of_line[0] == '\0')
     862                    bb_error_msg_and_die("option with empty value \"%s\"", buf);
     863
     864                if (strcmp(first_word, "up") != 0
     865                 && strcmp(first_word, "down") != 0
     866                 && strcmp(first_word, "pre-up") != 0
     867                 && strcmp(first_word, "post-down") != 0
     868                ) {
    789869                    int i;
    790 
    791                     if (strlen(buf_ptr) == 0) {
    792                         bb_error_msg("option with empty value \"%s\"", buf);
    793                         return NULL;
     870                    for (i = 0; i < currif->n_options; i++) {
     871                        if (strcmp(currif->option[i].name, first_word) == 0)
     872                            bb_error_msg_and_die("duplicate option \"%s\"", buf);
    794873                    }
    795 
    796                     if (strcmp(firstword, "up") != 0
    797                             && strcmp(firstword, "down") != 0
    798                             && strcmp(firstword, "pre-up") != 0
    799                             && strcmp(firstword, "post-down") != 0) {
    800                         for (i = 0; i < currif->n_options; i++) {
    801                             if (strcmp(currif->option[i].name, firstword) == 0) {
    802                                 bb_error_msg("duplicate option \"%s\"", buf);
    803                                 return NULL;
    804                             }
    805                         }
    806                     }
    807874                }
    808875                if (currif->n_options >= currif->max_options) {
    809                     struct variable_t *opt;
    810 
    811                     currif->max_options = currif->max_options + 10;
    812                     opt = xrealloc(currif->option, sizeof(*opt) * currif->max_options);
    813                     currif->option = opt;
    814                 }
    815                 currif->option[currif->n_options].name = xstrdup(firstword);
    816                 currif->option[currif->n_options].value = xstrdup(buf_ptr);
    817                 if (!currif->option[currif->n_options].name) {
    818                     perror(filename);
    819                     return NULL;
    820                 }
    821                 if (!currif->option[currif->n_options].value) {
    822                     perror(filename);
    823                     return NULL;
    824                 }
    825                 debug_noise("\t%s=%s\n", currif->option[currif->n_options].name,
    826                         currif->option[currif->n_options].value);
     876                    currif->max_options += 10;
     877                    currif->option = xrealloc(currif->option,
     878                        sizeof(*currif->option) * currif->max_options);
     879                }
     880                debug_noise("\t%s=%s\n", first_word, rest_of_line);
     881                currif->option[currif->n_options].name = xstrdup(first_word);
     882                currif->option[currif->n_options].value = xstrdup(rest_of_line);
    827883                currif->n_options++;
    828884                break;
    829885            case MAPPING:
    830886#if ENABLE_FEATURE_IFUPDOWN_MAPPING
    831                 if (strcmp(firstword, "script") == 0) {
    832                     if (currmap->script != NULL) {
    833                         bb_error_msg("duplicate script in mapping \"%s\"", buf);
    834                         return NULL;
    835                     } else {
    836                         currmap->script = xstrdup(next_word(&buf_ptr));
     887                if (strcmp(first_word, "script") == 0) {
     888                    if (currmap->script != NULL)
     889                        bb_error_msg_and_die("duplicate script in mapping \"%s\"", buf);
     890                    currmap->script = xstrdup(next_word(&rest_of_line));
     891                } else if (strcmp(first_word, "map") == 0) {
     892                    if (currmap->n_mappings >= currmap->max_mappings) {
     893                        currmap->max_mappings = currmap->max_mappings * 2 + 1;
     894                        currmap->mapping = xrealloc(currmap->mapping,
     895                            sizeof(char *) * currmap->max_mappings);
    837896                    }
    838                 } else if (strcmp(firstword, "map") == 0) {
    839                     if (currmap->max_mappings == currmap->n_mappings) {
    840                         currmap->max_mappings = currmap->max_mappings * 2 + 1;
    841                         currmap->mapping = xrealloc(currmap->mapping, sizeof(char *) * currmap->max_mappings);
    842                     }
    843                     currmap->mapping[currmap->n_mappings] = xstrdup(next_word(&buf_ptr));
     897                    currmap->mapping[currmap->n_mappings] = xstrdup(next_word(&rest_of_line));
    844898                    currmap->n_mappings++;
    845899                } else {
    846                     bb_error_msg("misplaced option \"%s\"", buf);
    847                     return NULL;
     900                    bb_error_msg_and_die("misplaced option \"%s\"", buf);
    848901                }
    849902#endif
     
    851904            case NONE:
    852905            default:
    853                 bb_error_msg("misplaced option \"%s\"", buf);
    854                 return NULL;
     906                bb_error_msg_and_die("misplaced option \"%s\"", buf);
    855907            }
    856908        }
    857909        free(buf);
    858     }
     910    } /* while (fgets) */
     911
    859912    if (ferror(f) != 0) {
    860913        /* ferror does NOT set errno! */
     
    869922{
    870923    char *result;
    871     char *here;
    872     char *there;
     924    char *dst;
     925    char *src;
     926    char c;
    873927
    874928    result = xasprintf(format, name, value);
    875929
    876     for (here = there = result; *there != '=' && *there; there++) {
    877         if (*there == '-')
    878             *there = '_';
    879         if (isalpha(*there))
    880             *there = toupper(*there);
    881 
    882         if (isalnum(*there) || *there == '_') {
    883             *here = *there;
    884             here++;
    885         }
    886     }
    887     memmove(here, there, strlen(there) + 1);
     930    for (dst = src = result; (c = *src) != '=' && c; src++) {
     931        if (c == '-')
     932            c = '_';
     933        if (c >= 'a' && c <= 'z')
     934            c -= ('a' - 'A');
     935        if (isalnum(c) || c == '_')
     936            *dst++ = c;
     937    }
     938    overlapping_strcpy(dst, src);
    888939
    889940    return result;
     
    892943static void set_environ(struct interface_defn_t *iface, const char *mode)
    893944{
    894     char **environend;
    895945    int i;
    896     const int n_env_entries = iface->n_options + 5;
    897     char **ppch;
    898 
    899     if (my_environ != NULL) {
    900         for (ppch = my_environ; *ppch; ppch++) {
    901             free(*ppch);
    902             *ppch = NULL;
    903         }
    904         free(my_environ);
    905     }
    906     my_environ = xzalloc(sizeof(char *) * (n_env_entries + 1 /* for final NULL */ ));
    907     environend = my_environ;
     946    char **pp;
     947
     948    if (G.my_environ != NULL) {
     949        for (pp = G.my_environ; *pp; pp++) {
     950            free(*pp);
     951        }
     952        free(G.my_environ);
     953    }
     954
     955    /* note: last element will stay NULL: */
     956    G.my_environ = xzalloc(sizeof(char *) * (iface->n_options + 6));
     957    pp = G.my_environ;
    908958
    909959    for (i = 0; i < iface->n_options; i++) {
     
    915965            continue;
    916966        }
    917         *(environend++) = setlocalenv("IF_%s=%s", iface->option[i].name, iface->option[i].value);
    918     }
    919 
    920     *(environend++) = setlocalenv("%s=%s", "IFACE", iface->iface);
    921     *(environend++) = setlocalenv("%s=%s", "ADDRFAM", iface->address_family->name);
    922     *(environend++) = setlocalenv("%s=%s", "METHOD", iface->method->name);
    923     *(environend++) = setlocalenv("%s=%s", "MODE", mode);
    924     *(environend++) = setlocalenv("%s=%s", "PATH", startup_PATH);
     967        *pp++ = setlocalenv("IF_%s=%s", iface->option[i].name, iface->option[i].value);
     968    }
     969
     970    *pp++ = setlocalenv("%s=%s", "IFACE", iface->iface);
     971    *pp++ = setlocalenv("%s=%s", "ADDRFAM", iface->address_family->name);
     972    *pp++ = setlocalenv("%s=%s", "METHOD", iface->method->name);
     973    *pp++ = setlocalenv("%s=%s", "MODE", mode);
     974    if (G.startup_PATH)
     975        *pp++ = setlocalenv("%s=%s", "PATH", G.startup_PATH);
    925976}
    926977
     
    934985        int status;
    935986
    936         fflush(NULL);
    937         child = fork();
     987        fflush_all();
     988        child = vfork();
    938989        switch (child) {
    939990        case -1: /* failure */
    940991            return 0;
    941992        case 0: /* child */
    942             execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, my_environ);
    943             exit(127);
    944         }
    945         waitpid(child, &status, 0);
     993            execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, (char *) NULL, G.my_environ);
     994            _exit(127);
     995        }
     996        safe_waitpid(child, &status, 0);
    946997        if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
    947998            return 0;
     
    9941045
    9951046#if ENABLE_FEATURE_IFUPDOWN_MAPPING
    996 static int popen2(FILE **in, FILE **out, char *command, ...)
    997 {
    998     va_list ap;
    999     char *argv[11] = { command };
    1000     int argc;
    1001     int infd[2], outfd[2];
     1047static int popen2(FILE **in, FILE **out, char *command, char *param)
     1048{
     1049    char *argv[3] = { command, param, NULL };
     1050    struct fd_pair infd, outfd;
    10021051    pid_t pid;
    10031052
    1004     argc = 1;
    1005     va_start(ap, command);
    1006     while ((argc < 10) && (argv[argc] = va_arg(ap, char *))) {
    1007         argc++;
    1008     }
    1009     argv[argc] = NULL;  /* make sure */
    1010     va_end(ap);
    1011 
    1012     if (pipe(infd) != 0) {
    1013         return 0;
    1014     }
    1015 
    1016     if (pipe(outfd) != 0) {
    1017         close(infd[0]);
    1018         close(infd[1]);
    1019         return 0;
    1020     }
    1021 
    1022     fflush(NULL);
    1023     switch (pid = fork()) {
    1024     case -1:            /* failure */
    1025         close(infd[0]);
    1026         close(infd[1]);
    1027         close(outfd[0]);
    1028         close(outfd[1]);
    1029         return 0;
    1030     case 0:         /* child */
    1031         dup2(infd[0], 0);
    1032         dup2(outfd[1], 1);
    1033         close(infd[0]);
    1034         close(infd[1]);
    1035         close(outfd[0]);
    1036         close(outfd[1]);
    1037         BB_EXECVP(command, argv);
    1038         exit(127);
    1039     default:            /* parent */
    1040         *in = fdopen(infd[1], "w");
    1041         *out = fdopen(outfd[0], "r");
    1042         close(infd[0]);
    1043         close(outfd[1]);
    1044         return pid;
    1045     }
    1046     /* unreached */
    1047 }
    1048 
    1049 static char *run_mapping(char *physical, struct mapping_defn_t * map)
     1053    xpiped_pair(infd);
     1054    xpiped_pair(outfd);
     1055
     1056    fflush_all();
     1057    pid = xvfork();
     1058
     1059    if (pid == 0) {
     1060        /* Child */
     1061        /* NB: close _first_, then move fds! */
     1062        close(infd.wr);
     1063        close(outfd.rd);
     1064        xmove_fd(infd.rd, 0);
     1065        xmove_fd(outfd.wr, 1);
     1066        BB_EXECVP_or_die(argv);
     1067    }
     1068    /* parent */
     1069    close(infd.rd);
     1070    close(outfd.wr);
     1071    *in = xfdopen_for_write(infd.wr);
     1072    *out = xfdopen_for_read(outfd.rd);
     1073    return pid;
     1074}
     1075
     1076static char *run_mapping(char *physical, struct mapping_defn_t *map)
    10501077{
    10511078    FILE *in, *out;
     
    10551082    char *logical = xstrdup(physical);
    10561083
    1057     /* Run the mapping script. */
    1058     pid = popen2(&in, &out, map->script, physical, NULL);
    1059 
    1060     /* popen2() returns 0 on failure. */
    1061     if (pid == 0)
    1062         return logical;
     1084    /* Run the mapping script. Never fails. */
     1085    pid = popen2(&in, &out, map->script, physical);
    10631086
    10641087    /* Write mappings to stdin of mapping script. */
     
    10671090    }
    10681091    fclose(in);
    1069     waitpid(pid, &status, 0);
     1092    safe_waitpid(pid, &status, 0);
    10701093
    10711094    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
     
    10731096         * grab a line of output and use that as the name of the
    10741097         * logical interface. */
    1075         char *new_logical = xmalloc(MAX_INTERFACE_LENGTH);
    1076 
    1077         if (fgets(new_logical, MAX_INTERFACE_LENGTH, out)) {
     1098        char *new_logical = xmalloc_fgetline(out);
     1099
     1100        if (new_logical) {
    10781101            /* If we are able to read a line of output from the script,
    10791102             * remove any trailing whitespace and use this value
     
    10861109            free(logical);
    10871110            logical = new_logical;
    1088         } else {
    1089             /* If we are UNABLE to read a line of output, discard our
    1090              * freshly allocated memory. */
    1091             free(new_logical);
    10921111        }
    10931112    }
     
    11011120static llist_t *find_iface_state(llist_t *state_list, const char *iface)
    11021121{
    1103     unsigned short iface_len = strlen(iface);
     1122    unsigned iface_len = strlen(iface);
    11041123    llist_t *search = state_list;
    11051124
    11061125    while (search) {
    11071126        if ((strncmp(search->data, iface, iface_len) == 0)
    1108          && (search->data[iface_len] == '=')) {
     1127         && (search->data[iface_len] == '=')
     1128        ) {
    11091129            return search;
    11101130        }
     
    11181138{
    11191139    llist_t *state_list = NULL;
    1120     FILE *state_fp = fopen(CONFIG_IFUPDOWN_IFSTATE_PATH, "r");
     1140    FILE *state_fp = fopen_for_read(CONFIG_IFUPDOWN_IFSTATE_PATH);
    11211141
    11221142    if (state_fp) {
     
    11341154
    11351155
    1136 int ifupdown_main(int argc, char **argv);
    1137 int ifupdown_main(int argc, char **argv)
    1138 {
    1139     int (*cmds)(struct interface_defn_t *) = NULL;
     1156int ifupdown_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     1157int ifupdown_main(int argc UNUSED_PARAM, char **argv)
     1158{
     1159    int (*cmds)(struct interface_defn_t *);
    11401160    struct interfaces_file_t *defn;
    11411161    llist_t *target_list = NULL;
     
    11431163    bool any_failures = 0;
    11441164
     1165    INIT_G();
     1166
     1167    G.startup_PATH = getenv("PATH");
     1168
    11451169    cmds = iface_down;
    11461170    if (applet_name[2] == 'u') {
     
    11501174
    11511175    getopt32(argv, OPTION_STR, &interfaces);
    1152     if (argc - optind > 0) {
     1176    argv += optind;
     1177    if (argv[0]) {
    11531178        if (DO_ALL) bb_show_usage();
    11541179    } else {
     
    11591184    defn = read_interfaces(interfaces);
    11601185    debug_noise("\ndone reading %s\n\n", interfaces);
    1161 
    1162     if (!defn) {
    1163         return EXIT_FAILURE;
    1164     }
    1165 
    1166     startup_PATH = getenv("PATH");
    1167     if (!startup_PATH) startup_PATH = "";
    11681186
    11691187    /* Create a list of interfaces to work on */
     
    11711189        target_list = defn->autointerfaces;
    11721190    } else {
    1173         llist_add_to_end(&target_list, argv[optind]);
     1191        llist_add_to_end(&target_list, argv[0]);
    11741192    }
    11751193
     
    11821200        char *pch;
    11831201        bool okay = 0;
    1184         unsigned cmds_ret;
     1202        int cmds_ret;
    11851203
    11861204        iface = xstrdup(target_list->data);
     
    12601278        }
    12611279        if (VERBOSE) {
    1262             puts("");
     1280            bb_putchar('\n');
    12631281        }
    12641282
     
    12881306
    12891307            /* Actually write the new state */
    1290             state_fp = xfopen(CONFIG_IFUPDOWN_IFSTATE_PATH, "w");
     1308            state_fp = xfopen_for_write(CONFIG_IFUPDOWN_IFSTATE_PATH);
    12911309            state = state_list;
    12921310            while (state) {
Note: See TracChangeset for help on using the changeset viewer.