Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/miscutils


Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

Location:
branches/2.2.5/mindi-busybox/miscutils
Files:
6 added
2 deleted
20 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/miscutils/Config.in

    r821 r1765  
    66menu "Miscellaneous Utilities"
    77
    8 config CONFIG_ADJTIMEX
     8config ADJTIMEX
    99    bool "adjtimex"
    1010    default n
     
    1313      the Linux clock adjustment algorithm.
    1414
    15 config CONFIG_BBCONFIG
     15config BBCONFIG
    1616    bool "bbconfig"
    1717    default n
     
    2020      busybox was built.
    2121
    22 config CONFIG_CROND
     22config CHRT
     23    bool "chrt"
     24    default n
     25    help
     26      manipulate real-time attributes of a process.
     27      This requires sched_{g,s}etparam support in your libc.
     28
     29config CROND
    2330    bool "crond"
    2431    default n
    25     select CONFIG_FEATURE_SUID
     32    select FEATURE_SUID
     33    select FEATURE_SYSLOG
    2634    help
    2735      Crond is a background daemon that parses individual crontab
     
    3543      work properly.
    3644
    37 config CONFIG_DEBUG_CROND_OPTION
     45config DEBUG_CROND_OPTION
    3846    bool "Support debug option -d"
    39     depends on CONFIG_CROND
     47    depends on CROND
    4048    default n
    4149    help
    4250      Support option -d to enter debug mode.
    4351
    44 config CONFIG_FEATURE_CROND_CALL_SENDMAIL
     52config FEATURE_CROND_CALL_SENDMAIL
    4553    bool "Using /usr/sbin/sendmail?"
    4654    default n
    47     depends on CONFIG_CROND
     55    depends on CROND
    4856    help
    4957      Support calling /usr/sbin/sendmail for send cmd outputs.
    5058
    51 config CONFIG_CRONTAB
     59config CRONTAB
    5260    bool "crontab"
    5361    default n
    54     select CONFIG_FEATURE_SUID
     62    select FEATURE_SUID
    5563    help
    5664      Crontab manipulates the crontab for a particular user.  Only
    5765      the superuser may specify a different user and/or crontab directory.
    5866
    59 config CONFIG_DC
     67config DC
    6068    bool "dc"
    6169    default n
     
    6472      precision arithmetic.
    6573
    66 config CONFIG_DEVFSD
     74config DEVFSD
    6775    bool "devfsd (obsolete)"
    6876    default n
    69     help
    70       This is deprecated, and will be going away in a future release.
     77    select FEATURE_SYSLOG
     78    help
     79      This is deprecated, and will be removed at the end of 2008.
    7180
    7281      Provides compatibility with old device names on a devfs systems.
     
    7988       But only if they are written UPPERCASE!!!!!!!!
    8089
    81 config CONFIG_DEVFSD_MODLOAD
     90config DEVFSD_MODLOAD
    8291    bool "Adds support for MODLOAD keyword in devsfd.conf"
    8392    default n
    84     depends on CONFIG_DEVFSD
     93    depends on DEVFSD
    8594    help
    8695      This actually doesn't work with busybox modutils but needs
    8796      the external modutils.
    8897
    89 config CONFIG_DEVFSD_FG_NP
     98config DEVFSD_FG_NP
    9099    bool "Enables the -fg and -np options"
    91100    default n
    92     depends on CONFIG_DEVFSD
     101    depends on DEVFSD
    93102    help
    94103        -fg Run the daemon in the foreground.
    95104        -np Exit  after  parsing  the configuration file. Do not poll for events.
    96105
    97 config CONFIG_DEVFSD_VERBOSE
     106config DEVFSD_VERBOSE
    98107    bool "Increases logging (and size)"
    99108    default n
    100     depends on CONFIG_DEVFSD
     109    depends on DEVFSD
    101110    help
    102111      Increases logging to stderr or syslog.
    103112
    104 config CONFIG_FEATURE_DEVFS
     113config FEATURE_DEVFS
    105114    bool "  Use devfs names for all devices (obsolete)"
    106115    default n
    107116    help
     117      This is obsolete and will be going away at the end of 2008..
     118
    108119      This tells busybox to look for names like /dev/loop/0 instead of
    109120      /dev/loop0.  If your /dev directory has normal names instead of
    110121      devfs names, you don't want this.
    111122
    112       This is obsolete and will be going away someday.  Consider it
    113       deprecated.
    114 
    115 config CONFIG_EJECT
     123config EJECT
    116124    bool "eject"
    117125    default n
     
    119127      Used to eject cdroms.  (defaults to /dev/cdrom)
    120128
    121 config CONFIG_LAST
     129config LAST
    122130    bool "last"
    123131    default n
    124     select CONFIG_FEATURE_WTMP
     132    select FEATURE_WTMP
    125133    help
    126134      'last' displays a list of the last users that logged into the system.
    127135
    128 config CONFIG_LESS
     136config LESS
    129137    bool "less"
    130138    default n
     
    133141      a wide array of features, and is an improvement over 'more'.
    134142
    135 config CONFIG_FEATURE_LESS_BRACKETS
     143config FEATURE_LESS_MAXLINES
     144    int "Max number of input lines less will try to eat"
     145    default 9999999
     146    depends on LESS
     147
     148config FEATURE_LESS_BRACKETS
    136149    bool "Enable bracket searching"
    137150    default y
    138     depends on CONFIG_LESS
     151    depends on LESS
    139152    help
    140153      This option adds the capability to search for matching left and right
    141154      brackets, facilitating programming.
    142155
    143 config CONFIG_FEATURE_LESS_FLAGS
     156config FEATURE_LESS_FLAGS
    144157    bool "Enable extra flags"
    145158    default y
    146     depends on CONFIG_LESS
     159    depends on LESS
    147160    help
    148161      The extra flags provided do the following:
     
    151164      The -m flag enables a simpler status line with a percentage.
    152165
    153 config CONFIG_FEATURE_LESS_FLAGCS
     166config FEATURE_LESS_FLAGCS
    154167    bool "Enable flag changes"
    155168    default n
    156     depends on CONFIG_LESS
     169    depends on LESS
    157170    help
    158171      This enables the ability to change command-line flags within
    159172      less itself.
    160173
    161 config CONFIG_FEATURE_LESS_MARKS
     174config FEATURE_LESS_MARKS
    162175    bool "Enable marks"
    163176    default n
    164     depends on CONFIG_LESS
     177    depends on LESS
    165178    help
    166179      Marks enable positions in a file to be stored for easy reference.
    167180
    168 config CONFIG_FEATURE_LESS_REGEXP
     181config FEATURE_LESS_REGEXP
    169182    bool "Enable regular expressions"
    170183    default n
    171     depends on CONFIG_LESS
     184    depends on LESS
    172185    help
    173186      Enable regular expressions, allowing complex file searches.
    174187
    175 config CONFIG_HDPARM
     188config HDPARM
    176189    bool "hdparm"
    177190    default n
     
    179192      Get/Set hard drive parameters.  Primarily intended for ATA
    180193      drives.  Adds about 13k (or around 30k if you enable the
    181       CONFIG_FEATURE_HDPARM_GET_IDENTITY option)....
    182 
    183 config CONFIG_FEATURE_HDPARM_GET_IDENTITY
     194      FEATURE_HDPARM_GET_IDENTITY option)....
     195
     196config FEATURE_HDPARM_GET_IDENTITY
    184197    bool "Support obtaining detailed information directly from drives"
    185198    default y
    186     depends on CONFIG_HDPARM
     199    depends on HDPARM
    187200    help
    188201      Enables the -I and -i options to obtain detailed information
     
    191204      identify data from stdin. Enabling this option will add about 16k...
    192205
    193 config CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF
     206config FEATURE_HDPARM_HDIO_SCAN_HWIF
    194207    bool "Register an IDE interface (DANGEROUS)"
    195208    default n
    196     depends on CONFIG_HDPARM
     209    depends on HDPARM
    197210    help
    198211      Enables the 'hdparm -R' option to register an IDE interface.
    199212      This is dangerous stuff, so you should probably say N.
    200213
    201 config CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
     214config FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
    202215    bool "Un-register an IDE interface (DANGEROUS)"
    203216    default n
    204     depends on CONFIG_HDPARM
     217    depends on HDPARM
    205218    help
    206219      Enables the 'hdparm -U' option to un-register an IDE interface.
    207220      This is dangerous stuff, so you should probably say N.
    208221
    209 config CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET
     222config FEATURE_HDPARM_HDIO_DRIVE_RESET
    210223    bool "perform device reset (DANGEROUS)"
    211224    default n
    212     depends on CONFIG_HDPARM
     225    depends on HDPARM
    213226    help
    214227      Enables the 'hdparm -w' option to perform a device reset.
    215228      This is dangerous stuff, so you should probably say N.
    216229
    217 config CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
     230config FEATURE_HDPARM_HDIO_TRISTATE_HWIF
    218231    bool "tristate device for hotswap (DANGEROUS)"
    219232    default n
    220     depends on CONFIG_HDPARM
     233    depends on HDPARM
    221234    help
    222235      Enables the 'hdparm -x' option to tristate device for hotswap,
     
    224237      stuff, so you should probably say N.
    225238
    226 config CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA
     239config FEATURE_HDPARM_HDIO_GETSET_DMA
    227240    bool "get/set using_dma flag (DANGEROUS)"
    228241    default n
    229     depends on CONFIG_HDPARM
     242    depends on HDPARM
    230243    help
    231244      Enables the 'hdparm -d' option to get/set using_dma flag.
    232245      This is dangerous stuff, so you should probably say N.
    233246
    234 config CONFIG_MAKEDEVS
     247config MAKEDEVS
    235248    bool "makedevs"
    236249    default n
     
    245258      devices of a particluar type to be created per command.
    246259      e.g. /dev/hda[0-9]
    247           Device properties are passed as command line arguments.
     260      Device properties are passed as command line arguments.
    248261      .
    249262      'table' reads device properties from a file or stdin, allowing
    250263      a batch of unrelated devices to be made with one command.
    251           User/group names are allowed as an alternative to uid/gid.
     264      User/group names are allowed as an alternative to uid/gid.
    252265
    253266choice
    254267    prompt "Choose makedevs behaviour"
    255     depends CONFIG_MAKEDEVS
    256     default CONFIG_FEATURE_MAKEDEVS_TABLE
    257 
    258 config CONFIG_FEATURE_MAKEDEVS_LEAF
    259         bool "leaf"
    260 
    261 config CONFIG_FEATURE_MAKEDEVS_TABLE
     268    depends on MAKEDEVS
     269    default FEATURE_MAKEDEVS_TABLE
     270
     271config FEATURE_MAKEDEVS_LEAF
     272    bool "leaf"
     273
     274config FEATURE_MAKEDEVS_TABLE
    262275    bool "table"
    263276
    264277endchoice
    265278
    266 config CONFIG_MOUNTPOINT
     279config MOUNTPOINT
    267280    bool "mountpoint"
    268281    default n
     
    270283      mountpoint checks if the directory is a mountpoint.
    271284
    272 config CONFIG_MT
     285config MT
    273286    bool "mt"
    274287    default n
     
    278291      files on the tape.
    279292
    280 config CONFIG_RUNLEVEL
    281         bool "runlevel"
    282     default n
    283     help
    284       find the current and previous system runlevel.
     293config RAIDAUTORUN
     294    bool "raidautorun"
     295    default n
     296    help
     297      raidautorun tells the kernel md driver to
     298      search and start RAID arrays.
     299
     300config READAHEAD
     301    bool "readahead"
     302    default n
     303    depends on LFS
     304    help
     305      Preload the files listed on the command line into RAM cache so that
     306      subsequent reads on these files will not block on disk I/O.
     307
     308      This applet just calls the readahead(2) system call on each file.
     309      It is mainly useful in system startup scripts to preload files
     310      or executables before they are used.  When used at the right time
     311      (in particular when a CPU boundprocess is running) it can
     312      significantly speed up system startup.
     313
     314      As readahead(2) blocks until each file has been read, it is best to
     315      run this applet as a background job.
     316
     317config RUNLEVEL
     318    bool "runlevel"
     319    default n
     320    help
     321      find the current and previous system runlevel.
    285322
    286323      This applet uses utmp but does not rely on busybox supporing
    287324      utmp on purpose. It is used by e.g. emdebian via /etc/init.d/rc.
    288325
    289 config CONFIG_RX
    290         bool "rx"
    291     default n
    292     help
    293       Receive files using the Xmodem protocol.
    294 
    295 config CONFIG_STRINGS
     326config RX
     327    bool "rx"
     328    default n
     329    help
     330      Receive files using the Xmodem protocol.
     331
     332config STRINGS
    296333    bool "strings"
    297334    default n
     
    300337      specified.
    301338
    302 config CONFIG_SETSID
     339config SETSID
    303340    bool "setsid"
    304341    default n
     
    306343      setsid runs a program in a new session
    307344
    308 config CONFIG_TASKSET
     345config TASKSET
    309346    bool "taskset"
    310347    default n
    311348    help
    312       Retrieve or set a processes's CPU affinity
    313 
    314 config CONFIG_TASKSET
    315     bool "taskset"
    316     default n
    317     help
    318       Retrieve or set a processes's CPU affinity (on linux)
    319 
    320 config CONFIG_TIME
     349      Retrieve or set a processes's CPU affinity.
     350      This requires sched_{g,s}etaffinity support in your libc.
     351
     352config FEATURE_TASKSET_FANCY
     353    bool "fancy output"
     354    default y
     355    depends on TASKSET
     356    help
     357      Add code for fancy output. This merely silences a compiler-warning
     358      and adds about 135 Bytes. May be needed for machines with alot
     359      of CPUs.
     360
     361config TIME
    321362    bool "time"
    322363    default n
     
    326367      giving timing statistics about this program run.
    327368
    328 config CONFIG_WATCHDOG
     369config TTYSIZE
     370    bool "ttysize"
     371    default n
     372    help
     373      A replacement for "stty size". Unlike stty, can report only width,
     374      only height, or both, in any order. It also does not complain on error,
     375      but returns default 80x24. Usage in shell scripts: width=`ttysize w`.
     376
     377config WATCHDOG
    329378    bool "watchdog"
    330379    default n
  • branches/2.2.5/mindi-busybox/miscutils/adjtimex.c

    r821 r1765  
    1212 */
    1313
    14 #include "busybox.h"
    15 #include <stdio.h>
    16 #include <sys/types.h>
    17 #include <stdlib.h>
    18 #include <unistd.h>
     14#include "libbb.h"
    1915#include <sys/timex.h>
    2016
    21 static const struct {int bit; const char *name;} statlist[] = {
     17static const struct {
     18    int bit;
     19    const char *name;
     20} statlist[] = {
    2221    { STA_PLL,       "PLL"       },
    2322    { STA_PPSFREQ,   "PPSFREQ"   },
     
    3332    { STA_PPSERROR,  "PPSERROR"  },
    3433    { STA_CLOCKERR,  "CLOCKERR"  },
    35     { 0, NULL } };
     34    { 0, NULL }
     35};
    3636
    37 static const char * const ret_code_descript[] = {
     37static const char *const ret_code_descript[] = {
    3838    "clock synchronized",
    3939    "insert leap second",
     
    4141    "leap second in progress",
    4242    "leap second has occurred",
    43     "clock not synchronized" };
     43    "clock not synchronized"
     44};
    4445
     46int adjtimex_main(int argc, char **argv);
    4547int adjtimex_main(int argc, char **argv)
    4648{
     49    enum {
     50        OPT_quiet = 0x1
     51    };
     52    unsigned opt;
     53    char *opt_o, *opt_f, *opt_p, *opt_t;
    4754    struct timex txc;
    48     int quiet=0;
    49     int c, i, ret, sep;
     55    int i, ret, sep;
    5056    const char *descript;
    5157    txc.modes=0;
    52     for (;;) {
    53         c = getopt( argc, argv, "qo:f:p:t:");
    54         if (c == EOF) break;
    55         switch (c) {
    56             case 'q':
    57                 quiet=1;
    58                 break;
    59             case 'o':
    60                 txc.offset = atoi(optarg);
    61                 txc.modes |= ADJ_OFFSET_SINGLESHOT;
    62                 break;
    63             case 'f':
    64                 txc.freq = atoi(optarg);
    65                 txc.modes |= ADJ_FREQUENCY;
    66                 break;
    67             case 'p':
    68                 txc.constant = atoi(optarg);
    69                 txc.modes |= ADJ_TIMECONST;
    70                 break;
    71             case 't':
    72                 txc.tick = atoi(optarg);
    73                 txc.modes |= ADJ_TICK;
    74                 break;
    75             default:
    76                 bb_show_usage();
    77                 exit(1);
    78         }
     58
     59    opt = getopt32(argv, "qo:f:p:t:",
     60            &opt_o, &opt_f, &opt_p, &opt_t);
     61    //if (opt & 0x1) // -q
     62    if (opt & 0x2) { // -o
     63        txc.offset = xatol(opt_o);
     64        txc.modes |= ADJ_OFFSET_SINGLESHOT;
     65    }
     66    if (opt & 0x4) { // -f
     67        txc.freq = xatol(opt_f);
     68        txc.modes |= ADJ_FREQUENCY;
     69    }
     70    if (opt & 0x8) { // -p
     71        txc.constant = xatol(opt_p);
     72        txc.modes |= ADJ_TIMECONST;
     73    }
     74    if (opt & 0x10) { // -t
     75        txc.tick = xatol(opt_t);
     76        txc.modes |= ADJ_TICK;
    7977    }
    8078    if (argc != optind) { /* no valid non-option parameters */
    8179        bb_show_usage();
    82         exit(1);
    8380    }
    8481
     
    8784    if (ret < 0) perror("adjtimex");
    8885
    89     if (!quiet && ret>=0) {
     86    if (!(opt & OPT_quiet) && ret>=0) {
    9087        printf(
    9188            "    mode:         %d\n"
  • branches/2.2.5/mindi-busybox/miscutils/bbconfig.c

    r821 r1765  
    22/* This file was released into the public domain by Paul Fox.
    33 */
    4 #include "busybox.h"
     4#include "libbb.h"
    55#include "bbconfigopts.h"
    66
     7int bbconfig_main(int argc, char **argv);
    78int bbconfig_main(int argc, char **argv)
    89{
  • branches/2.2.5/mindi-busybox/miscutils/crond.c

    r821 r1765  
    66 *
    77 * Copyright 1994 Matthew Dillon (dillon@apollo.west.oic.com)
     8 * (version 2.3.2)
    89 * Vladimir Oleynik <dzo@simtreas.ru> (C) 2002
    910 *
     
    1112 */
    1213
    13 #define VERSION "2.3.2"
    14 
    15 #include "busybox.h"
    16 #include <stdio.h>
    17 #include <stdlib.h>
    18 #include <stdarg.h>
    19 #include <string.h>
    20 #include <errno.h>
    21 #include <time.h>
    22 #include <dirent.h>
    23 #include <fcntl.h>
    24 #include <unistd.h>
    25 #include <syslog.h>
    26 #include <signal.h>
    27 #include <getopt.h>
    28 #include <sys/ioctl.h>
    29 #include <sys/wait.h>
    30 #include <sys/stat.h>
    31 #include <sys/resource.h>
    32 
    33 #define arysize(ary)    (sizeof(ary)/sizeof((ary)[0]))
     14#include <sys/syslog.h>
     15#include "libbb.h"
    3416
    3517#ifndef CRONTABS
     
    4022#endif
    4123#ifndef SENDMAIL
    42 #define SENDMAIL        "/usr/sbin/sendmail"
     24#define SENDMAIL        "sendmail"
    4325#endif
    4426#ifndef SENDMAIL_ARGS
     
    8163
    8264#if ENABLE_DEBUG_CROND_OPTION
    83 static short DebugOpt;
    84 #endif
    85 
    86 static short LogLevel = 8;
     65static unsigned DebugOpt;
     66#endif
     67
     68static unsigned LogLevel = 8;
    8769static const char *LogFile;
    8870static const char *CDir = CRONTABS;
     
    130112            vsyslog(type, fmt, va);
    131113        } else {
     114#if !ENABLE_DEBUG_CROND_OPTION
    132115            int logfd = open(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600);
     116#else
     117            int logfd = open3_or_warn(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600);
     118#endif
    133119            if (logfd >= 0) {
    134120                vdprintf(logfd, fmt, va);
    135121                close(logfd);
    136 #if ENABLE_DEBUG_CROND_OPTION
    137             } else {
    138                 bb_perror_msg("Can't open log file");
    139 #endif
    140122            }
    141123        }
     
    147129}
    148130
     131int crond_main(int ac, char **av);
    149132int crond_main(int ac, char **av)
    150133{
    151     unsigned long opt;
     134    unsigned opt;
    152135    char *lopt, *Lopt, *copt;
    153 
    154 #if ENABLE_DEBUG_CROND_OPTION
    155     char *dopt;
    156 
    157     bb_opt_complementally = "f-b:b-f:S-L:L-S:d-l";
    158 #else
    159     bb_opt_complementally = "f-b:b-f:S-L:L-S";
    160 #endif
    161 
     136    USE_DEBUG_CROND_OPTION(char *dopt;)
     137
     138    opt_complementary = "f-b:b-f:S-L:L-S" USE_DEBUG_CROND_OPTION(":d-l");
    162139    opterr = 0;         /* disable getopt 'errors' message. */
    163     opt = bb_getopt_ulflags(ac, av, "l:L:fbSc:"
    164 #if ENABLE_DEBUG_CROND_OPTION
    165                             "d:"
    166 #endif
    167                             , &lopt, &Lopt, &copt
    168 #if ENABLE_DEBUG_CROND_OPTION
    169                             , &dopt
    170 #endif
    171         );
    172     if (opt & 1) {
    173         LogLevel = atoi(lopt);
    174     }
    175     if (opt & 2) {
    176         if (*Lopt != 0) {
     140    opt = getopt32(av, "l:L:fbSc:" USE_DEBUG_CROND_OPTION("d:"),
     141            &lopt, &Lopt, &copt USE_DEBUG_CROND_OPTION(, &dopt));
     142    if (opt & 1) /* -l */
     143        LogLevel = xatou(lopt);
     144    if (opt & 2) /* -L */
     145        if (*Lopt)
    177146            LogFile = Lopt;
    178         }
    179     }
    180     if (opt & 32) {
    181         if (*copt != 0) {
     147    if (opt & 32) /* -c */
     148        if (*copt)
    182149            CDir = copt;
    183         }
    184     }
    185 #if ENABLE_DEBUG_CROND_OPTION
    186     if (opt & 64) {
    187         DebugOpt = atoi(dopt);
     150#if ENABLE_DEBUG_CROND_OPTION
     151    if (opt & 64) { /* -d */
     152        DebugOpt = xatou(dopt);
    188153        LogLevel = 0;
    189154    }
    190155#endif
    191156
    192     /*
    193      * change directory
    194      */
    195 
    196     bb_xchdir(CDir);
    197     signal(SIGHUP, SIG_IGN);    /* hmm.. but, if kill -HUP original
    198                                  * version - his died. ;(
    199                                  */
    200     /*
    201      * close stdin and stdout, stderr.
     157    /* close stdin and stdout, stderr.
    202158     * close unused descriptors -  don't need.
    203159     * optional detach from controlling terminal
    204160     */
    205 
    206     if (!(opt & 4)) {
    207 #ifdef BB_NOMMU
    208         /* reexec for vfork() do continue parent */
    209         vfork_daemon_rexec(1, 0, ac, av, "-f");
    210 #else
    211         bb_xdaemon(1, 0);
    212 #endif
    213     }
    214 
    215     (void) startlogger();   /* need if syslog mode selected */
     161    if (!(opt & 4))
     162        bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, av);
     163
     164    xchdir(CDir);
     165    signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
     166
     167    startlogger();  /* need if syslog mode selected */
    216168
    217169    /*
     
    219171     *             of 1 second.
    220172     */
    221 
    222     crondlog("\011%s " VERSION " dillon, started, log level %d\n",
    223              bb_applet_name, LogLevel);
     173    crondlog("\011%s " BB_VER " started, log level %d\n",
     174             applet_name, LogLevel);
    224175
    225176    SynchronizeDir();
     
    232183        short sleep_time = 60;
    233184
     185        write_pidfile("/var/run/crond.pid");
    234186        for (;;) {
    235187            sleep((sleep_time + 1) - (short) (time(NULL) % sleep_time));
     
    280232        }
    281233    }
    282     bb_fflush_stdout_and_exit(EXIT_SUCCESS); /* not reached */
     234    return 0; /* not reached */
    283235}
    284236
     
    294246    if (pas == 0) {
    295247        crondlog("\011failed to get uid for %s", user);
    296         return (-1);
     248        return -1;
    297249    }
    298250    setenv("USER", pas->pw_name, 1);
     
    306258    if (err_msg) {
    307259        crondlog("\011%s for user %s", err_msg, user);
    308         return (-1);
     260        return -1;
    309261    }
    310262    if (chdir(pas->pw_dir) < 0) {
     
    312264        if (chdir(TMPDIR) < 0) {
    313265            crondlog("\011chdir failed: %s: %m", TMPDIR);
    314             return (-1);
    315         }
    316     }
    317     return (pas->pw_uid);
     266            return -1;
     267        }
     268    }
     269    return pas->pw_uid;
    318270}
    319271
     
    321273{
    322274    if (LogFile == 0) {
    323         openlog(bb_applet_name, LOG_CONS | LOG_PID, LOG_CRON);
     275        openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON);
    324276    }
    325277#if ENABLE_DEBUG_CROND_OPTION
     
    327279        int logfd;
    328280
    329         if ((logfd = open(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600)) >= 0) {
     281        logfd = open3_or_warn(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600);
     282        if (logfd >= 0) {
    330283            close(logfd);
    331         } else {
    332             bb_perror_msg("Failed to open log file '%s' reason", LogFile);
    333         }
    334     }
    335 #endif
    336 }
    337 
    338 
    339 static const char *const DowAry[] = {
    340     "sun",
    341     "mon",
    342     "tue",
    343     "wed",
    344     "thu",
    345     "fri",
    346     "sat",
    347 
    348     "Sun",
    349     "Mon",
    350     "Tue",
    351     "Wed",
    352     "Thu",
    353     "Fri",
    354     "Sat",
    355     NULL
    356 };
    357 
    358 static const char *const MonAry[] = {
    359     "jan",
    360     "feb",
    361     "mar",
    362     "apr",
    363     "may",
    364     "jun",
    365     "jul",
    366     "aug",
    367     "sep",
    368     "oct",
    369     "nov",
    370     "dec",
    371 
    372     "Jan",
    373     "Feb",
    374     "Mar",
    375     "Apr",
    376     "May",
    377     "Jun",
    378     "Jul",
    379     "Aug",
    380     "Sep",
    381     "Oct",
    382     "Nov",
    383     "Dec",
    384     NULL
    385 };
     284        }
     285    }
     286#endif
     287}
     288
     289
     290static const char DowAry[] ALIGN1 =
     291    "sun""mon""tue""wed""thu""fri""sat"
     292    /* "Sun""Mon""Tue""Wed""Thu""Fri""Sat" */
     293;
     294
     295static const char MonAry[] ALIGN1 =
     296    "jan""feb""mar""apr""may""jun""jul""aug""sep""oct""nov""dec"
     297    /* "Jan""Feb""Mar""Apr""May""Jun""Jul""Aug""Sep""Oct""Nov""Dec" */
     298;
    386299
    387300static char *ParseField(char *user, char *ary, int modvalue, int off,
    388                         const char *const *names, char *ptr)
     301                const char *names, char *ptr)
     302/* 'names' is a pointer to a set of 3-char abbreviations */
    389303{
    390304    char *base = ptr;
     
    393307
    394308    if (base == NULL) {
    395         return (NULL);
     309        return NULL;
    396310    }
    397311
     
    416330            int i;
    417331
    418             for (i = 0; names[i]; ++i) {
    419                 if (strncmp(ptr, names[i], strlen(names[i])) == 0) {
     332            for (i = 0; names[i]; i += 3) {
     333                /* was using strncmp before... */
     334                if (strncasecmp(ptr, &names[i], 3) == 0) {
     335                    ptr += 3;
     336                    if (n1 < 0) {
     337                        n1 = i / 3;
     338                    } else {
     339                        n2 = i / 3;
     340                    }
     341                    skip = 1;
    420342                    break;
    421343                }
    422             }
    423             if (names[i]) {
    424                 ptr += strlen(names[i]);
    425                 if (n1 < 0) {
    426                     n1 = i;
    427                 } else {
    428                     n2 = i;
    429                 }
    430                 skip = 1;
    431344            }
    432345        }
     
    436349        if (skip == 0) {
    437350            crondlog("\111failed user %s parsing %s\n", user, base);
    438             return (NULL);
     351            return NULL;
    439352        }
    440353        if (*ptr == '-' && n2 < 0) {
     
    476389            if (failsafe == 0) {
    477390                crondlog("\111failed user %s parsing %s\n", user, base);
    478                 return (NULL);
     391                return NULL;
    479392            }
    480393        }
     
    489402    if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n') {
    490403        crondlog("\111failed user %s parsing %s\n", user, base);
    491         return (NULL);
     404        return NULL;
    492405    }
    493406
     
    506419#endif
    507420
    508     return (ptr);
     421    return ptr;
    509422}
    510423
     
    515428    int daysUsed = 0;
    516429
    517     for (i = 0; i < (int)(arysize(line->cl_Dow)); ++i) {
     430    for (i = 0; i < (int)(ARRAY_SIZE(line->cl_Dow)); ++i) {
    518431        if (line->cl_Dow[i] == 0) {
    519432            weekUsed = 1;
     
    521434        }
    522435    }
    523     for (i = 0; i < (int)(arysize(line->cl_Days)); ++i) {
     436    for (i = 0; i < (int)(ARRAY_SIZE(line->cl_Days)); ++i) {
    524437        if (line->cl_Days[i] == 0) {
    525438            daysUsed = 1;
     
    558471
    559472            if (fstat(fileno(fi), &sbuf) == 0 && sbuf.st_uid == DaemonUid) {
    560                 CronFile *file = calloc(1, sizeof(CronFile));
     473                CronFile *file = xzalloc(sizeof(CronFile));
    561474                CronLine **pline;
    562475
     
    602515                    FixDayDow(&line);
    603516
    604                     *pline = calloc(1, sizeof(CronLine));
     517                    *pline = xzalloc(sizeof(CronLine));
    605518                    **pline = line;
    606519
     
    670583    remove(CRONUPDATE);
    671584    if (chdir(CDir) < 0) {
    672         crondlog("\311unable to find %s\n", CDir);
     585        crondlog("\311cannot find %s\n", CDir);
    673586    }
    674587    {
     
    689602            closedir(dir);
    690603        } else {
    691             crondlog("\311Unable to open current dir!\n");
     604            crondlog("\311cannot open current dir!\n");
    692605        }
    693606    }
     
    793706        }
    794707    }
    795     return (nJobs);
     708    return nJobs;
    796709}
    797710
     
    859772        nStillRunning += file->cf_Running;
    860773    }
    861     return (nStillRunning);
     774    return nStillRunning;
    862775}
    863776
     
    892805        }
    893806        execl(prog, prog, cmd, arg, NULL);
    894         crondlog("\024unable to exec, user %s cmd %s %s %s\n", user, prog, cmd, arg);
     807        crondlog("\024cannot exec, user %s cmd %s %s %s\n", user, prog, cmd, arg);
    895808        if (mailf) {
    896809            fdprintf(1, "Exec failed: %s -c %s\n", prog, arg);
     
    899812    } else if (pid < 0) {
    900813        /* FORK FAILED */
    901         crondlog("\024couldn't fork, user %s\n", user);
     814        crondlog("\024cannot fork, user %s\n", user);
    902815        line->cl_Pid = 0;
    903816        if (mailf) {
     
    940853        fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", user,
    941854            line->cl_Shell);
    942         line->cl_MailPos = lseek(mailFd, 0, 1);
     855        line->cl_MailPos = lseek(mailFd, 0, SEEK_CUR);
    943856    } else {
    944         crondlog("\024unable to create mail file user %s file %s, output to /dev/null\n", user, mailFile);
     857        crondlog("\024cannot create mail file user %s file %s, output to /dev/null\n", user, mailFile);
    945858    }
    946859
     
    989902    }
    990903
    991     if (fstat(mailFd, &sbuf) < 0 || sbuf.st_uid != DaemonUid || sbuf.st_nlink != 0 ||
    992         sbuf.st_size == line->cl_MailPos || !S_ISREG(sbuf.st_mode)) {
     904    if (fstat(mailFd, &sbuf) < 0 || sbuf.st_uid != DaemonUid
     905     || sbuf.st_nlink != 0 || sbuf.st_size == line->cl_MailPos
     906     || !S_ISREG(sbuf.st_mode)
     907    ) {
    993908        close(mailFd);
    994909        return;
     
    1019934
    1020935        execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_Shell, NULL);
    1021         crondlog("\024unable to exec, user %s cmd %s -c %s\n", user,
     936        crondlog("\024cannot exec, user %s cmd %s -c %s\n", user,
    1022937                 DEFAULT_SHELL, line->cl_Shell);
    1023938        exit(0);
    1024939    } else if (pid < 0) {
    1025940        /* FORK FAILED */
    1026         crondlog("\024couldn't fork, user %s\n", user);
     941        crondlog("\024cannot, user %s\n", user);
    1027942        pid = 0;
    1028943    }
  • branches/2.2.5/mindi-busybox/miscutils/crontab.c

    r821 r1765  
    1111 */
    1212
    13 #include "busybox.h"
    14 #include <stdio.h>
    15 #include <stdlib.h>
    16 #include <stdarg.h>
    17 #include <string.h>
    18 #include <errno.h>
    19 #include <time.h>
    20 #include <dirent.h>
    21 #include <fcntl.h>
    22 #include <unistd.h>
    23 #include <syslog.h>
    24 #include <signal.h>
    25 #include <getopt.h>
    26 #include <sys/ioctl.h>
    27 #include <sys/wait.h>
    28 #include <sys/stat.h>
    29 #include <sys/resource.h>
     13#include "libbb.h"
    3014
    3115#ifndef CRONTABS
     
    3923#endif
    4024#ifndef PATH_VI
    41 #define PATH_VI         "/bin/vi"   /* location of vi       */
     25#define PATH_VI         "/bin/vi"   /* location of vi */
    4226#endif
    4327
    44 static const char  *CDir = CRONTABS;
     28static const char *CDir = CRONTABS;
    4529
    4630static void EditFile(const char *user, const char *file);
    4731static int GetReplaceStream(const char *user, const char *file);
    48 static int  ChangeUser(const char *user, short dochdir);
    49 
    50 int
    51 crontab_main(int ac, char **av)
     32static int ChangeUser(const char *user, short dochdir);
     33
     34int crontab_main(int ac, char **av);
     35int crontab_main(int ac, char **av)
    5236{
    53     enum { NONE, EDIT, LIST, REPLACE, DELETE } option = NONE;
    54     const struct passwd *pas;
    55     const char *repFile = NULL;
    56     int repFd = 0;
    57     int i;
    58     char caller[256];           /* user that ran program */
    59     int   UserId;
    60 
    61     UserId = getuid();
    62     if ((pas = getpwuid(UserId)) == NULL)
    63     bb_perror_msg_and_die("getpwuid");
    64 
    65     safe_strncpy(caller, pas->pw_name, sizeof(caller));
    66 
    67     i = 1;
    68     if (ac > 1) {
    69     if (av[1][0] == '-' && av[1][1] == 0) {
    70         option = REPLACE;
    71         ++i;
    72     } else if (av[1][0] != '-') {
    73         option = REPLACE;
    74         ++i;
    75         repFile = av[1];
    76     }
    77     }
    78 
    79     for (; i < ac; ++i) {
    80     char *ptr = av[i];
    81 
    82     if (*ptr != '-')
    83         break;
    84     ptr += 2;
    85 
    86     switch(ptr[-1]) {
    87     case 'l':
    88         if (ptr[-1] == 'l')
    89         option = LIST;
    90         /* fall through */
    91     case 'e':
    92         if (ptr[-1] == 'e')
    93         option = EDIT;
    94         /* fall through */
    95     case 'd':
    96         if (ptr[-1] == 'd')
    97         option = DELETE;
    98         /* fall through */
    99     case 'u':
    100         if (i + 1 < ac && av[i+1][0] != '-') {
    101         ++i;
    102         if (getuid() == geteuid()) {
    103             pas = getpwnam(av[i]);
    104             if (pas) {
    105             UserId = pas->pw_uid;
    106             } else {
    107             bb_error_msg_and_die("user %s unknown", av[i]);
    108             }
    109         } else {
    110             bb_error_msg_and_die("only the superuser may specify a user");
    111         }
    112         }
    113         break;
    114     case 'c':
    115         if (getuid() == geteuid()) {
    116         CDir = (*ptr) ? ptr : av[++i];
    117         } else {
    118         bb_error_msg_and_die("-c option: superuser only");
    119         }
    120         break;
     37    enum { NONE, EDIT, LIST, REPLACE, DELETE } option = NONE;
     38    const struct passwd *pas;
     39    const char *repFile = NULL;
     40    int repFd = 0;
     41    int i;
     42    char caller[256];           /* user that ran program */
     43    char buf[1024];
     44    int UserId;
     45
     46    UserId = getuid();
     47    pas = getpwuid(UserId);
     48    if (pas == NULL)
     49        bb_perror_msg_and_die("getpwuid");
     50
     51    safe_strncpy(caller, pas->pw_name, sizeof(caller));
     52
     53    i = 1;
     54    if (ac > 1) {
     55        if (LONE_DASH(av[1])) {
     56            option = REPLACE;
     57            ++i;
     58        } else if (av[1][0] != '-') {
     59            option = REPLACE;
     60            ++i;
     61            repFile = av[1];
     62        }
     63    }
     64
     65    for (; i < ac; ++i) {
     66        char *ptr = av[i];
     67
     68        if (*ptr != '-')
     69            break;
     70        ptr += 2;
     71
     72        switch (ptr[-1]) {
     73        case 'l':
     74            if (ptr[-1] == 'l')
     75                option = LIST;
     76            /* fall through */
     77        case 'e':
     78            if (ptr[-1] == 'e')
     79                option = EDIT;
     80            /* fall through */
     81        case 'd':
     82            if (ptr[-1] == 'd')
     83                option = DELETE;
     84            /* fall through */
     85        case 'u':
     86            if (i + 1 < ac && av[i+1][0] != '-') {
     87                ++i;
     88                if (getuid() == geteuid()) {
     89                    pas = getpwnam(av[i]);
     90                    if (pas) {
     91                        UserId = pas->pw_uid;
     92                    } else {
     93                        bb_error_msg_and_die("user %s unknown", av[i]);
     94                    }
     95                } else {
     96                    bb_error_msg_and_die("only the superuser may specify a user");
     97                }
     98            }
     99            break;
     100        case 'c':
     101            if (getuid() == geteuid()) {
     102                CDir = (*ptr) ? ptr : av[++i];
     103            } else {
     104                bb_error_msg_and_die("-c option: superuser only");
     105            }
     106            break;
     107        default:
     108            i = ac;
     109            break;
     110        }
     111    }
     112    if (i != ac || option == NONE)
     113        bb_show_usage();
     114
     115    /*
     116     * Get password entry
     117     */
     118
     119    pas = getpwuid(UserId);
     120    if (pas == NULL)
     121        bb_perror_msg_and_die("getpwuid");
     122
     123    /*
     124     * If there is a replacement file, obtain a secure descriptor to it.
     125     */
     126
     127    if (repFile) {
     128        repFd = GetReplaceStream(caller, repFile);
     129        if (repFd < 0)
     130            bb_error_msg_and_die("cannot read replacement file");
     131    }
     132
     133    /*
     134     * Change directory to our crontab directory
     135     */
     136
     137    xchdir(CDir);
     138
     139    /*
     140     * Handle options as appropriate
     141     */
     142
     143    switch (option) {
     144    case LIST:
     145        {
     146            FILE *fi;
     147
     148            fi = fopen(pas->pw_name, "r");
     149            if (fi) {
     150                while (fgets(buf, sizeof(buf), fi) != NULL)
     151                    fputs(buf, stdout);
     152                fclose(fi);
     153            } else {
     154                bb_error_msg("no crontab for %s", pas->pw_name);
     155            }
     156        }
     157        break;
     158    case EDIT:
     159        {
     160/* FIXME: messy code here! we have file copying helpers for this! */
     161            FILE *fi;
     162            int fd;
     163            int n;
     164            char tmp[128];
     165
     166            snprintf(tmp, sizeof(tmp), TMPDIR "/crontab.%d", getpid());
     167            fd = xopen3(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600);
     168/* race, use fchown */
     169            chown(tmp, getuid(), getgid());
     170            fi = fopen(pas->pw_name, "r");
     171            if (fi) {
     172                while ((n = fread(buf, 1, sizeof(buf), fi)) > 0)
     173                    full_write(fd, buf, n);
     174            }
     175            EditFile(caller, tmp);
     176            remove(tmp);
     177            lseek(fd, 0L, SEEK_SET);
     178            repFd = fd;
     179        }
     180        option = REPLACE;
     181        /* fall through */
     182    case REPLACE:
     183        {
     184/* same here */
     185            char path[1024];
     186            int fd;
     187            int n;
     188
     189            snprintf(path, sizeof(path), "%s.new", pas->pw_name);
     190            fd = open(path, O_CREAT|O_TRUNC|O_APPEND|O_WRONLY, 0600);
     191            if (fd >= 0) {
     192                while ((n = read(repFd, buf, sizeof(buf))) > 0) {
     193                    full_write(fd, buf, n);
     194                }
     195                close(fd);
     196                rename(path, pas->pw_name);
     197            } else {
     198                bb_error_msg("cannot create %s/%s", CDir, path);
     199            }
     200            close(repFd);
     201        }
     202        break;
     203    case DELETE:
     204        remove(pas->pw_name);
     205        break;
     206    case NONE:
    121207    default:
    122         i = ac;
    123         break;
    124     }
    125     }
    126     if (i != ac || option == NONE)
    127     bb_show_usage();
    128 
    129     /*
    130      * Get password entry
    131      */
    132 
    133     if ((pas = getpwuid(UserId)) == NULL)
    134     bb_perror_msg_and_die("getpwuid");
    135 
    136     /*
    137      * If there is a replacement file, obtain a secure descriptor to it.
    138      */
    139 
    140     if (repFile) {
    141     repFd = GetReplaceStream(caller, repFile);
    142     if (repFd < 0)
    143         bb_error_msg_and_die("unable to read replacement file");
    144     }
    145 
    146     /*
    147      * Change directory to our crontab directory
    148      */
    149 
    150     bb_xchdir(CDir);
    151 
    152     /*
    153      * Handle options as appropriate
    154      */
    155 
    156     switch(option) {
    157     case LIST:
    158     {
    159         FILE *fi;
    160         char buf[1024];
    161 
    162         if ((fi = fopen(pas->pw_name, "r"))) {
    163         while (fgets(buf, sizeof(buf), fi) != NULL)
    164             fputs(buf, stdout);
    165         fclose(fi);
    166         } else {
    167         bb_error_msg("no crontab for %s", pas->pw_name);
    168         }
    169     }
    170     break;
    171     case EDIT:
    172     {
    173         FILE *fi;
    174         int fd;
    175         int n;
    176         char tmp[128];
    177         char buf[1024];
    178 
    179         snprintf(tmp, sizeof(tmp), TMPDIR "/crontab.%d", getpid());
    180         fd = bb_xopen3(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600);
    181         chown(tmp, getuid(), getgid());
    182         if ((fi = fopen(pas->pw_name, "r"))) {
    183         while ((n = fread(buf, 1, sizeof(buf), fi)) > 0)
    184             write(fd, buf, n);
    185         }
    186         EditFile(caller, tmp);
    187         remove(tmp);
    188         lseek(fd, 0L, 0);
    189         repFd = fd;
    190     }
    191     option = REPLACE;
    192     /* fall through */
    193     case REPLACE:
    194     {
    195         char buf[1024];
    196         char path[1024];
    197         int fd;
    198         int n;
    199 
    200         snprintf(path, sizeof(path), "%s.new", pas->pw_name);
    201         if ((fd = open(path, O_CREAT|O_TRUNC|O_APPEND|O_WRONLY, 0600)) >= 0) {
    202         while ((n = read(repFd, buf, sizeof(buf))) > 0) {
    203             write(fd, buf, n);
    204         }
    205         close(fd);
    206         rename(path, pas->pw_name);
    207         } else {
    208         bb_error_msg("unable to create %s/%s", CDir, path);
    209         }
    210         close(repFd);
    211     }
    212     break;
    213     case DELETE:
    214     remove(pas->pw_name);
    215     break;
    216     case NONE:
    217     default:
    218     break;
    219     }
    220 
    221     /*
    222      *  Bump notification file.  Handle window where crond picks file up
    223      *  before we can write our entry out.
    224      */
    225 
    226     if (option == REPLACE || option == DELETE) {
    227     FILE *fo;
    228     struct stat st;
    229 
    230     while ((fo = fopen(CRONUPDATE, "a"))) {
    231         fprintf(fo, "%s\n", pas->pw_name);
    232         fflush(fo);
    233         if (fstat(fileno(fo), &st) != 0 || st.st_nlink != 0) {
    234         fclose(fo);
    235208        break;
    236         }
    237         fclose(fo);
    238         /* loop */
    239     }
    240     if (fo == NULL) {
    241         bb_error_msg("unable to append to %s/%s", CDir, CRONUPDATE);
    242     }
    243     }
    244     return 0;
     209    }
     210
     211    /*
     212     *  Bump notification file.  Handle window where crond picks file up
     213     *  before we can write our entry out.
     214     */
     215
     216    if (option == REPLACE || option == DELETE) {
     217        FILE *fo;
     218        struct stat st;
     219
     220        while ((fo = fopen(CRONUPDATE, "a"))) {
     221            fprintf(fo, "%s\n", pas->pw_name);
     222            fflush(fo);
     223            if (fstat(fileno(fo), &st) != 0 || st.st_nlink != 0) {
     224                fclose(fo);
     225                break;
     226            }
     227            fclose(fo);
     228            /* loop */
     229        }
     230        if (fo == NULL) {
     231            bb_error_msg("cannot append to %s/%s", CDir, CRONUPDATE);
     232        }
     233    }
     234    return 0;
    245235}
    246236
    247 static int
    248 GetReplaceStream(const char *user, const char *file)
     237static int GetReplaceStream(const char *user, const char *file)
    249238{
    250     int filedes[2];
    251     int pid;
    252     int fd;
    253     int n;
    254     char buf[1024];
    255 
    256     if (pipe(filedes) < 0) {
    257     perror("pipe");
    258     return(-1);
    259     }
    260     if ((pid = fork()) < 0) {
    261     perror("fork");
    262     return(-1);
    263     }
    264     if (pid > 0) {
    265     /*
    266      * PARENT
    267      */
    268 
    269     close(filedes[1]);
    270     if (read(filedes[0], buf, 1) != 1) {
    271         close(filedes[0]);
    272         filedes[0] = -1;
    273     }
    274     return(filedes[0]);
    275     }
    276 
    277     /*
    278      * CHILD
    279      */
    280 
    281     close(filedes[0]);
    282 
    283     if (ChangeUser(user, 0) < 0)
     239    int filedes[2];
     240    int pid;
     241    int fd;
     242    int n;
     243    char buf[1024];
     244
     245    if (pipe(filedes) < 0) {
     246        perror("pipe");
     247        return -1;
     248    }
     249    pid = fork();
     250    if (pid < 0) {
     251        perror("fork");
     252        return -1;
     253    }
     254    if (pid > 0) {
     255        /*
     256         * PARENT
     257         */
     258
     259        close(filedes[1]);
     260        if (read(filedes[0], buf, 1) != 1) {
     261            close(filedes[0]);
     262            filedes[0] = -1;
     263        }
     264        return filedes[0];
     265    }
     266
     267    /*
     268     * CHILD
     269     */
     270
     271    close(filedes[0]);
     272
     273    if (ChangeUser(user, 0) < 0)
     274        exit(0);
     275
     276    xfunc_error_retval = 0;
     277    fd = xopen(file, O_RDONLY);
     278    buf[0] = 0;
     279    write(filedes[1], buf, 1);
     280    while ((n = read(fd, buf, sizeof(buf))) > 0) {
     281        write(filedes[1], buf, n);
     282    }
    284283    exit(0);
    285 
    286     bb_default_error_retval = 0;
    287     fd = bb_xopen3(file, O_RDONLY, 0);
    288     buf[0] = 0;
    289     write(filedes[1], buf, 1);
    290     while ((n = read(fd, buf, sizeof(buf))) > 0) {
    291     write(filedes[1], buf, n);
    292     }
    293     exit(0);
    294284}
    295285
    296 static void
    297 EditFile(const char *user, const char *file)
     286static void EditFile(const char *user, const char *file)
    298287{
    299     int pid;
    300 
    301     if ((pid = fork()) == 0) {
    302     /*
    303      * CHILD - change user and run editor
    304      */
    305     char *ptr;
    306     char visual[1024];
    307 
    308     if (ChangeUser(user, 1) < 0)
    309         exit(0);
    310     if ((ptr = getenv("VISUAL")) == NULL || strlen(ptr) > 256)
    311         ptr = PATH_VI;
    312 
    313     snprintf(visual, sizeof(visual), "%s %s", ptr, file);
    314     execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", visual, NULL);
    315     perror("exec");
    316     exit(0);
    317     }
    318     if (pid < 0) {
    319     /*
    320      * PARENT - failure
    321      */
    322     bb_perror_msg_and_die("fork");
    323     }
    324     wait4(pid, NULL, 0, NULL);
     288    int pid = fork();
     289
     290    if (pid == 0) {
     291        /*
     292         * CHILD - change user and run editor
     293         */
     294        const char *ptr;
     295
     296        if (ChangeUser(user, 1) < 0)
     297            exit(0);
     298        ptr = getenv("VISUAL");
     299        if (ptr == NULL)
     300            ptr = getenv("EDITOR");
     301        if (ptr == NULL)
     302            ptr = PATH_VI;
     303
     304        ptr = xasprintf("%s %s", ptr, file);
     305        execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", ptr, NULL);
     306        bb_perror_msg_and_die("exec");
     307    }
     308    if (pid < 0) {
     309        /*
     310         * PARENT - failure
     311         */
     312        bb_perror_msg_and_die("fork");
     313    }
     314    wait4(pid, NULL, 0, NULL);
    325315}
    326316
    327 static int
    328 ChangeUser(const char *user, short dochdir)
     317static int ChangeUser(const char *user, short dochdir)
    329318{
    330     struct passwd *pas;
    331 
    332     /*
    333     * Obtain password entry and change privileges
    334     */
    335 
    336     if ((pas = getpwnam(user)) == NULL) {
    337     bb_perror_msg_and_die("failed to get uid for %s", user);
    338     return(-1);
    339     }
    340     setenv("USER", pas->pw_name, 1);
    341     setenv("HOME", pas->pw_dir, 1);
    342     setenv("SHELL", DEFAULT_SHELL, 1);
    343 
    344     /*
    345     * Change running state to the user in question
    346     */
    347     change_identity(pas);
    348 
    349     if (dochdir) {
    350     if (chdir(pas->pw_dir) < 0) {
    351         bb_perror_msg("chdir failed: %s %s", user, pas->pw_dir);
    352         bb_xchdir(TMPDIR);
    353     }
    354     }
    355     return(pas->pw_uid);
     319    struct passwd *pas;
     320
     321    /*
     322    * Obtain password entry and change privileges
     323    */
     324
     325    pas = getpwnam(user);
     326    if (pas == NULL) {
     327        bb_perror_msg_and_die("failed to get uid for %s", user);
     328    }
     329    setenv("USER", pas->pw_name, 1);
     330    setenv("HOME", pas->pw_dir, 1);
     331    setenv("SHELL", DEFAULT_SHELL, 1);
     332
     333    /*
     334    * Change running state to the user in question
     335    */
     336    change_identity(pas);
     337
     338    if (dochdir) {
     339        if (chdir(pas->pw_dir) < 0) {
     340            bb_perror_msg("chdir(%s) by %s failed", pas->pw_dir, user);
     341            xchdir(TMPDIR);
     342        }
     343    }
     344    return pas->pw_uid;
    356345}
  • branches/2.2.5/mindi-busybox/miscutils/dc.c

    r821 r1765  
    11/* vi: set sw=4 ts=4: */
    2 #include "busybox.h"
    3 #include <ctype.h>
    4 #include <stdio.h>
    5 #include <stdlib.h>
    6 #include <string.h>
    7 #include <unistd.h>
     2/*
     3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     4 */
     5
     6#include "libbb.h"
    87#include <math.h>
    98
    109/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */
    1110
    12 static double stack[100];
     11enum { STACK_SIZE = COMMON_BUFSIZE / sizeof(double) };
     12
     13#define stack ((double*)&bb_common_bufsiz1)
    1314static unsigned int pointer;
    1415static unsigned char base;
     
    1617static void push(double a)
    1718{
    18     if (pointer >= (sizeof(stack) / sizeof(*stack)))
     19    if (pointer >= STACK_SIZE)
    1920        bb_error_msg_and_die("stack overflow");
    2021    stack[pointer++] = a;
     
    8889static void set_output_base(void)
    8990{
    90     base=(unsigned char)pop();
     91    base = (unsigned char)pop();
    9192    if ((base != 10) && (base != 16)) {
    92         fprintf(stderr, "Error: base = %d is not supported.\n", base);
    93         base=10;
     93        bb_error_msg("error, base %d is not supported", base);
     94        base = 10;
    9495    }
    9596}
     
    100101        printf("%x\n", (unsigned int)print);
    101102    else
    102     printf("%g\n", print);
     103        printf("%g\n", print);
    103104}
    104105
    105106static void print_stack_no_pop(void)
    106107{
    107     unsigned int i=pointer;
     108    unsigned int i = pointer;
    108109    while (i)
    109110        print_base(stack[--i]);
     
    116117
    117118struct op {
    118     const char *name;
     119    const char name[4];
    119120    void (*function) (void);
    120121};
     
    142143    {"f", print_stack_no_pop},
    143144    {"o", set_output_base},
    144     {0,    0}
     145    {"", 0}
    145146};
    146147
     
    161162    }
    162163
    163     while (o->name != 0) {
     164    while (o->name[0]) {
    164165        if (strcmp(o->name, argument) == 0) {
    165             (*(o->function)) ();
     166            o->function();
    166167            return;
    167168        }
    168169        o++;
    169170    }
    170     bb_error_msg_and_die("%s: syntax error.", argument);
     171    bb_error_msg_and_die("%s: syntax error", argument);
    171172}
    172173
     
    176177static char *get_token(char **buffer)
    177178{
    178     char *start   = NULL;
    179     char *current = *buffer;
    180 
    181     while (isspace(*current)) { current++; }
     179    char *start = NULL;
     180    char *current;
     181
     182    current = skip_whitespace(*buffer);
    182183    if (*current != 0) {
    183184        start = current;
    184         while (!isspace(*current) && *current != 0) { current++; }
     185        current = skip_non_whitespace(current);
    185186        *buffer = current;
    186187    }
     
    197198}
    198199
     200int dc_main(int argc, char **argv);
    199201int dc_main(int argc, char **argv)
    200202{
     
    205207        char *cursor = NULL;
    206208        char *token  = NULL;
    207         while ((line = bb_get_chomped_line_from_file(stdin))) {
     209        while ((line = xmalloc_getline(stdin))) {
    208210            cursor = line;
    209211            len = number_of_tokens(line);
     
    216218        }
    217219    } else {
    218         if (*argv[1]=='-')
     220        if (*argv[1] == '-')
    219221            bb_show_usage();
    220222        while (argc >= 2) {
  • branches/2.2.5/mindi-busybox/miscutils/devfsd.c

    r821 r1765  
     1/* vi: set sw=4 ts=4: */
     2/*
     3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     4 */
     5
    16/*
    27    devfsd implementation for busybox
     
    5055*/
    5156
    52 #include "busybox.h"
    53 #include "xregex.h"
    54 #include <unistd.h>
    55 #include <stdio.h>
    56 #include <stdlib.h>
    57 #include <stdarg.h>
    58 #include <string.h>
    59 #include <ctype.h>
    60 #include <sys/stat.h>
    61 #include <sys/types.h>
    62 #include <sys/wait.h>
    63 #include <sys/ioctl.h>
    64 #include <sys/socket.h>
     57//#include <sys/wait.h>
     58//#include <sys/ioctl.h>
     59//#include <sys/socket.h>
    6560#include <sys/un.h>
    6661#include <dirent.h>
    67 #include <fcntl.h>
    6862#include <syslog.h>
    69 #include <signal.h>
    70 #include <errno.h>
    7163#include <sys/sysmacros.h>
     64#include "libbb.h"
     65#include "xregex.h"
    7266
    7367
     
    165159struct permissions_type
    166160{
    167     mode_t mode;
    168     uid_t uid;
    169     gid_t gid;
     161    mode_t mode;
     162    uid_t uid;
     163    gid_t gid;
    170164};
    171165
    172166struct execute_type
    173167{
    174     char *argv[MAX_ARGS + 1];  /*  argv[0] must always be the programme  */
     168    char *argv[MAX_ARGS + 1];  /*  argv[0] must always be the programme  */
    175169};
    176170
    177171struct copy_type
    178172{
    179     const char *source;
    180     const char *destination;
     173    const char *source;
     174    const char *destination;
    181175};
    182176
    183177struct action_type
    184178{
    185     unsigned int what;
    186     unsigned int when;
     179    unsigned int what;
     180    unsigned int when;
    187181};
    188182
    189183struct config_entry_struct
    190184{
    191     struct action_type action;
    192     regex_t preg;
    193     union
    194     {
     185    struct action_type action;
     186    regex_t preg;
     187    union
     188    {
    195189    struct permissions_type permissions;
    196190    struct execute_type execute;
    197191    struct copy_type copy;
    198     }
    199     u;
    200     struct config_entry_struct *next;
     192    }
     193    u;
     194    struct config_entry_struct *next;
    201195};
    202196
    203197struct get_variable_info
    204198{
    205     const struct devfsd_notify_struct *info;
    206     const char *devname;
    207     char devpath[STRING_LENGTH];
     199    const struct devfsd_notify_struct *info;
     200    const char *devname;
     201    char devpath[STRING_LENGTH];
    208202};
    209203
    210 static void dir_operation(int , const char * , int,  unsigned long* );
     204static void dir_operation(int , const char * , int,  unsigned long*);
    211205static void service(struct stat statbuf, char *path);
    212 static int st_expr_expand(char *, unsigned, const char *, const char *(*) (const char *, void *), void *);
     206static int st_expr_expand(char *, unsigned, const char *, const char *(*)(const char *, void *), void *);
    213207static const char *get_old_name(const char *, unsigned, char *, unsigned, unsigned);
    214 static int mksymlink (const char *oldpath, const char *newpath);
    215 static void read_config_file (char *path, int optional, unsigned long *event_mask);
    216 static void process_config_line (const char *, unsigned long *);
    217 static int  do_servicing (int, unsigned long);
    218 static void service_name (const struct devfsd_notify_struct *);
    219 static void action_permissions (const struct devfsd_notify_struct *, const struct config_entry_struct *);
    220 static void action_execute (const struct devfsd_notify_struct *, const struct config_entry_struct *,
     208static int mksymlink(const char *oldpath, const char *newpath);
     209static void read_config_file(char *path, int optional, unsigned long *event_mask);
     210static void process_config_line(const char *, unsigned long *);
     211static int  do_servicing(int, unsigned long);
     212static void service_name(const struct devfsd_notify_struct *);
     213static void action_permissions(const struct devfsd_notify_struct *, const struct config_entry_struct *);
     214static void action_execute(const struct devfsd_notify_struct *, const struct config_entry_struct *,
    221215                            const regmatch_t *, unsigned);
    222 static void action_modload (const struct devfsd_notify_struct *info, const struct config_entry_struct *entry);
    223 static void action_copy (const struct devfsd_notify_struct *, const struct config_entry_struct *,
     216static void action_modload(const struct devfsd_notify_struct *info, const struct config_entry_struct *entry);
     217static void action_copy(const struct devfsd_notify_struct *, const struct config_entry_struct *,
    224218                         const regmatch_t *, unsigned);
    225 static void action_compat (const struct devfsd_notify_struct *, unsigned);
    226 static void free_config (void);
     219static void action_compat(const struct devfsd_notify_struct *, unsigned);
     220static void free_config(void);
    227221static void restore(char *spath, struct stat source_stat, int rootlen);
    228 static int copy_inode (const char *, const struct stat *, mode_t, const char *, const struct stat *);
    229 static mode_t get_mode (const char *);
    230 static void signal_handler (int);
    231 static const char *get_variable (const char *, void *);
    232 static int make_dir_tree (const char *);
     222static int copy_inode(const char *, const struct stat *, mode_t, const char *, const struct stat *);
     223static mode_t get_mode(const char *);
     224static void signal_handler(int);
     225static const char *get_variable(const char *, void *);
     226static int make_dir_tree(const char *);
    233227static int expand_expression(char *, unsigned, const char *, const char *(*)(const char *, void *), void *,
    234                              const char *, const regmatch_t *, unsigned );
    235 static void expand_regexp (char *, size_t, const char *, const char *, const regmatch_t *, unsigned );
     228                             const char *, const regmatch_t *, unsigned);
     229static void expand_regexp(char *, size_t, const char *, const char *, const regmatch_t *, unsigned);
    236230static const char *expand_variable( char *, unsigned, unsigned *, const char *,
    237                                     const char *(*) (const char *, void *), void * );
    238 static const char *get_variable_v2(const char *, const char *(*) (const char *, void *), void *);
    239 static char get_old_ide_name (unsigned , unsigned);
    240 static char *write_old_sd_name (char *, unsigned, unsigned, char *);
     231                                    const char *(*)(const char *, void *), void *);
     232static const char *get_variable_v2(const char *, const char *(*)(const char *, void *), void *);
     233static char get_old_ide_name(unsigned , unsigned);
     234static char *write_old_sd_name(char *, unsigned, unsigned, const char *);
    241235
    242236/* busybox functions */
    243 static void msg_logger(int pri, const char * fmt, ... )__attribute__ ((format (printf, 2, 3)));
    244 static void msg_logger_and_die(int pri, const char * fmt, ... )__attribute__ ((noreturn, format (printf, 2, 3)));
    245 static void do_ioctl_and_die(int fd, int request, unsigned long event_mask_flag);
    246 static void fork_and_execute(int die, char *arg0, char **arg );
    247 static int get_uid_gid ( int, const char *);
    248 static void safe_memcpy( char * dest, const char * src, int len);
    249 static unsigned int scan_dev_name_common(const char *d, unsigned int n, int addendum, char *ptr);
    250 static unsigned int scan_dev_name(const char *d, unsigned int n, char *ptr);
     237static int get_uid_gid(int flag, const char *string);
     238static void safe_memcpy(char * dest, const char * src, int len);
     239static unsigned int scan_dev_name_common(const char *d, unsigned int n, int addendum, const char *ptr);
     240static unsigned int scan_dev_name(const char *d, unsigned int n, const char *ptr);
    251241
    252242/* Structs and vars */
    253243static struct config_entry_struct *first_config = NULL;
    254244static struct config_entry_struct *last_config = NULL;
    255 static const char *mount_point = NULL;
     245static char *mount_point = NULL;
    256246static volatile int caught_signal = FALSE;
    257247static volatile int caught_sighup = FALSE;
    258 static struct initial_symlink_struct
    259 {
    260     char *dest;
    261     char *name;
    262 } initial_symlinks[] =
    263 {
    264     {"/proc/self/fd", "fd"},
    265     {"fd/0", "stdin"},
    266     {"fd/1", "stdout"},
    267     {"fd/2", "stderr"},
    268     {NULL, NULL},
     248static struct initial_symlink_struct {
     249    const char *dest;
     250    const char *name;
     251} initial_symlinks[] = {
     252    {"/proc/self/fd", "fd"},
     253    {"fd/0", "stdin"},
     254    {"fd/1", "stdout"},
     255    {"fd/2", "stderr"},
     256    {NULL, NULL},
    269257};
    270258
    271 static struct event_type
    272 {
    273     unsigned int type;        /*  The DEVFSD_NOTIFY_* value                  */
    274     const char *config_name;  /*  The name used in the config file           */
    275 } event_types[] =
    276 {
    277     {DEVFSD_NOTIFY_REGISTERED,   "REGISTER"},
    278     {DEVFSD_NOTIFY_UNREGISTERED, "UNREGISTER"},
    279     {DEVFSD_NOTIFY_ASYNC_OPEN,   "ASYNC_OPEN"},
    280     {DEVFSD_NOTIFY_CLOSE,        "CLOSE"},
    281     {DEVFSD_NOTIFY_LOOKUP,       "LOOKUP"},
    282     {DEVFSD_NOTIFY_CHANGE,       "CHANGE"},
    283     {DEVFSD_NOTIFY_CREATE,       "CREATE"},
    284     {DEVFSD_NOTIFY_DELETE,       "DELETE"},
    285     {0xffffffff,                 NULL}
     259static struct event_type {
     260    unsigned int type;        /*  The DEVFSD_NOTIFY_* value                  */
     261    const char *config_name;  /*  The name used in the config file           */
     262} event_types[] = {
     263    {DEVFSD_NOTIFY_REGISTERED,   "REGISTER"},
     264    {DEVFSD_NOTIFY_UNREGISTERED, "UNREGISTER"},
     265    {DEVFSD_NOTIFY_ASYNC_OPEN,   "ASYNC_OPEN"},
     266    {DEVFSD_NOTIFY_CLOSE,        "CLOSE"},
     267    {DEVFSD_NOTIFY_LOOKUP,       "LOOKUP"},
     268    {DEVFSD_NOTIFY_CHANGE,       "CHANGE"},
     269    {DEVFSD_NOTIFY_CREATE,       "CREATE"},
     270    {DEVFSD_NOTIFY_DELETE,       "DELETE"},
     271    {0xffffffff,                 NULL}
    286272};
    287273
    288274/* Busybox messages */
    289275
    290 static const char * const bb_msg_proto_rev          = "protocol revision";
    291 static const char * const bb_msg_bad_config     = "bad %s config file: %s";
    292 static const char * const bb_msg_small_buffer       = "buffer too small";
    293 static const char * const bb_msg_variable_not_found = "variable: %s not found";
    294 
    295 /* Busybox functions  */
    296 static void msg_logger(int pri, const char * fmt, ... )
    297 {
    298     va_list ap;
    299     int ret;
    300 
    301     va_start(ap, fmt);
    302     ret = access ("/dev/log", F_OK);
    303     if (ret == 0) {
    304         openlog(bb_applet_name, 0, LOG_DAEMON);
    305         vsyslog( pri , fmt, ap);
    306         /* Man: A trailing newline is added when needed. */
    307         closelog();
    308     }
    309     /* ENABLE_DEVFSD_VERBOSE is always enabled if msg_logger is used */
    310     if ((ENABLE_DEVFSD_VERBOSE && ret) || ENABLE_DEBUG) {
    311         bb_error_msg(fmt, ap);
    312     }
    313     va_end(ap);
    314 }
    315 
    316 static void msg_logger_and_die(int pri, const char* fmt, ...)
    317 {
    318     va_list ap;
    319 
    320     va_start(ap, fmt);
    321     msg_logger(pri, fmt, ap);
    322     va_end(ap);
    323     exit(EXIT_FAILURE);
    324 }
     276static const char bb_msg_proto_rev[] ALIGN1          = "protocol revision";
     277static const char bb_msg_bad_config[] ALIGN1         = "bad %s config file: %s";
     278static const char bb_msg_small_buffer[] ALIGN1       = "buffer too small";
     279static const char bb_msg_variable_not_found[] ALIGN1 = "variable: %s not found";
    325280
    326281/* Busybox stuff */
    327 #if defined(CONFIG_DEVFSD_VERBOSE) || defined(CONFIG_DEBUG)
    328 #define devfsd_error_msg(fmt, args...)                bb_error_msg(fmt, ## args)
    329 #define devfsd_perror_msg_and_die(fmt, args...)       bb_perror_msg_and_die(fmt, ## args)
    330 #define devfsd_error_msg_and_die(fmt, args...)        bb_error_msg_and_die(fmt, ## args)
    331 #if defined(CONFIG_DEBUG)
    332 #define debug_msg_logger(x, fmt, args...)             msg_logger(x, fmt, ## args)
     282#if ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG
     283#define info_logger(p, fmt, args...)                 bb_info_msg(fmt, ## args)
     284#define msg_logger(p, fmt, args...)                  bb_error_msg(fmt, ## args)
     285#define msg_logger_and_die(p, fmt, args...)          bb_error_msg_and_die(fmt, ## args)
     286#define error_logger(p, fmt, args...)                bb_perror_msg(fmt, ## args)
     287#define error_logger_and_die(p, fmt, args...)        bb_perror_msg_and_die(fmt, ## args)
    333288#else
    334 #define debug_msg_logger(x, fmt, args...)
    335 #endif
    336 #else
    337 #define debug_msg_logger(x, fmt, args...)
     289#define info_logger(p, fmt, args...)
    338290#define msg_logger(p, fmt, args...)
    339291#define msg_logger_and_die(p, fmt, args...)           exit(1)
    340 #define devfsd_perror_msg_and_die(fmt, args...)       exit(1)
    341 #define devfsd_error_msg_and_die(fmt, args...)        exit(1)
    342 #define devfsd_error_msg(fmt, args...)
     292#define error_logger(p, fmt, args...)
     293#define error_logger_and_die(p, fmt, args...)         exit(1)
    343294#endif
    344295
    345 static void do_ioctl_and_die(int fd, int request, unsigned long event_mask_flag)
    346 {
    347     if (ioctl (fd, request, event_mask_flag) == -1)
    348         msg_logger_and_die(LOG_ERR, "ioctl");
    349 }
    350 
    351 static void fork_and_execute(int die, char *arg0, char **arg )
    352 {
    353     switch ( fork () )
    354     {
    355     case 0:
    356         /*  Child  */
    357         break;
    358     case -1:
    359         /*  Parent: Error  : die or return */
    360         msg_logger(LOG_ERR,(char *) bb_msg_memory_exhausted);
    361         if(die)
    362             exit(EXIT_FAILURE);
    363         return;
    364     default:
    365         /*  Parent : ok : return or exit  */
    366         if(arg0 != NULL)
    367         {
    368             wait (NULL);
    369             return;
    370         }
    371         exit (EXIT_SUCCESS);
    372     }
    373      /* Child : if arg0 != NULL do execvp */
    374     if(arg0 != NULL )
    375     {
    376         execvp (arg0, arg);
    377         msg_logger_and_die(LOG_ERR, "execvp");
    378     }
    379 }
    380 
    381 static void safe_memcpy( char *dest, const char *src, int len)
    382 {
    383     memcpy (dest , src , len );
     296static void safe_memcpy(char *dest, const char *src, int len)
     297{
     298    memcpy(dest , src, len);
    384299    dest[len] = '\0';
    385300}
    386301
    387 static unsigned int scan_dev_name_common(const char *d, unsigned int n, int addendum, char *ptr)
    388 {
    389     if( d[n - 4]=='d' && d[n - 3]=='i' && d[n - 2]=='s' && d[n - 1]=='c')
    390         return (2 + addendum);
    391     else if( d[n - 2]=='c' && d[n - 1]=='d')
    392         return (3 + addendum);
    393     else if(ptr[0]=='p' && ptr[1]=='a' && ptr[2]=='r' && ptr[3]=='t')
    394         return (4 + addendum);
    395     else if( ptr[n - 2]=='m' && ptr[n - 1]=='t')
    396         return (5 + addendum);
    397     else
    398         return 0;
     302static unsigned int scan_dev_name_common(const char *d, unsigned int n, int addendum, const char *ptr)
     303{
     304    if (d[n - 4] == 'd' && d[n - 3] == 'i' && d[n - 2] == 's' && d[n - 1] == 'c')
     305        return 2 + addendum;
     306    if (d[n - 2] == 'c' && d[n - 1] == 'd')
     307        return 3 + addendum;
     308    if (ptr[0] == 'p' && ptr[1] == 'a' && ptr[2] == 'r' && ptr[3] == 't')
     309        return 4 + addendum;
     310    if (ptr[n - 2] == 'm' && ptr[n - 1] == 't')
     311        return 5 + addendum;
     312    return 0;
    399313}
    400314
    401 static unsigned int scan_dev_name(const char *d, unsigned int n, char *ptr)
    402 {
    403     if(d[0]=='s' && d[1]=='c' && d[2]=='s' && d[3]=='i' && d[4]=='/')
    404     {
    405         if( d[n - 7]=='g' && d[n - 6]=='e' && d[n - 5]=='n' &&
    406             d[n - 4]=='e' && d[n - 3]=='r' && d[n - 2]=='i' &&
    407             d[n - 1]=='c' )
     315static unsigned int scan_dev_name(const char *d, unsigned int n, const char *ptr)
     316{
     317    if (d[0] == 's' && d[1] == 'c' && d[2] == 's' && d[3] == 'i' && d[4] == '/') {
     318        if (d[n - 7] == 'g' && d[n - 6] == 'e' && d[n - 5] == 'n'
     319            && d[n - 4] == 'e' && d[n - 3] == 'r' && d[n - 2] == 'i' && d[n - 1] == 'c'
     320        )
    408321            return 1;
    409322        return scan_dev_name_common(d, n, 0, ptr);
    410323    }
    411     else if(d[0]=='i' && d[1]=='d' && d[2]=='e' && d[3]=='/' &&
    412             d[4]=='h' && d[5]=='o' && d[6]=='s' && d[7]=='t')
    413     {
     324    if (d[0] == 'i' && d[1] == 'd' && d[2] == 'e' && d[3] == '/'
     325        && d[4] == 'h' && d[5] == 'o' && d[6] == 's' && d[7] == 't'
     326    )
    414327        return scan_dev_name_common(d, n, 4, ptr);
    415     }
    416     else if(d[0]=='s' && d[1]=='b' && d[2]=='p' && d[3]=='/')
    417     {
     328    if (d[0] == 's' && d[1] == 'b' && d[2] == 'p' && d[3] == '/')
    418329        return 10;
    419     }
    420     else if(d[0]=='v' && d[1]=='c' && d[2]=='c' && d[3]=='/')
    421     {
     330    if (d[0] == 'v' && d[1] == 'c' && d[2] == 'c' && d[3] == '/')
    422331        return 11;
    423     }
    424     else if(d[0]=='p' && d[1]=='t' && d[2]=='y' && d[3]=='/')
    425     {
     332    if (d[0] == 'p' && d[1] == 't' && d[2] == 'y' && d[3] == '/')
    426333        return 12;
    427     }
    428334    return 0;
    429335}
     
    431337/*  Public functions follow  */
    432338
    433 int devfsd_main (int argc, char **argv)
     339int devfsd_main(int argc, char **argv);
     340int devfsd_main(int argc, char **argv)
    434341{
    435342    int print_version = FALSE;
     
    445352        bb_show_usage();
    446353
    447     for (count = 2; count < argc; ++count)
    448     {
    449         if(argv[count][0] == '-')
    450         {
    451             if(argv[count][1]=='v' && !argv[count][2]) /* -v */
    452                     print_version = TRUE;
    453             else if(ENABLE_DEVFSD_FG_NP && argv[count][1]=='f'
    454                     && argv[count][2]=='g' && !argv[count][3]) /* -fg */
    455                     do_daemon = FALSE;
    456             else if(ENABLE_DEVFSD_FG_NP && argv[count][1]=='n'
    457                     && argv[count][2]=='p' && !argv[count][3]) /* -np */
    458                     no_polling = TRUE;
     354    for (count = 2; count < argc; ++count) {
     355        if (argv[count][0] == '-') {
     356            if (argv[count][1] == 'v' && !argv[count][2]) /* -v */
     357                print_version = TRUE;
     358            else if (ENABLE_DEVFSD_FG_NP && argv[count][1] == 'f'
     359             && argv[count][2] == 'g' && !argv[count][3]) /* -fg */
     360                do_daemon = FALSE;
     361            else if (ENABLE_DEVFSD_FG_NP && argv[count][1] == 'n'
     362             && argv[count][2] == 'p' && !argv[count][3]) /* -np */
     363                no_polling = TRUE;
    459364            else
    460365                bb_show_usage();
     
    462367    }
    463368
    464     /* strip last / from mount point, so we don't need to check for it later */
    465     while( argv[1][1]!='\0' && argv[1][strlen(argv[1])-1] == '/' )
    466         argv[1][strlen(argv[1]) -1] = '\0';
    467 
    468     mount_point = argv[1];
    469 
    470     if (chdir (mount_point) != 0)
    471         devfsd_perror_msg_and_die(mount_point);
    472 
    473     fd = bb_xopen (".devfsd", O_RDONLY);
    474 
    475     if (fcntl (fd, F_SETFD, FD_CLOEXEC) != 0)
    476         devfsd_perror_msg_and_die("FD_CLOEXEC");
    477 
    478     if (ioctl (fd, DEVFSDIOC_GET_PROTO_REV, &proto_rev) == -1)
    479         msg_logger_and_die(LOG_ERR, "ioctl");
     369    mount_point = bb_simplify_path(argv[1]);
     370
     371    xchdir(mount_point);
     372
     373    fd = xopen(".devfsd", O_RDONLY);
     374
     375    if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0)
     376        bb_perror_msg_and_die("FD_CLOEXEC");
     377
     378    xioctl(fd, DEVFSDIOC_GET_PROTO_REV, &proto_rev);
    480379
    481380    /*setup initial entries */
    482     for (curr = initial_symlinks; curr->dest != NULL; ++curr)
    483         symlink (curr->dest, curr->name);
     381    for (curr = initial_symlinks; curr->dest != NULL; ++curr)
     382        symlink(curr->dest, curr->name);
    484383
    485384    /* NB: The check for CONFIG_FILE is done in read_config_file() */
    486385
    487     if ( print_version  || (DEVFSD_PROTOCOL_REVISION_DAEMON != proto_rev) )
    488     {
    489         bb_printf( "%s v%s\nDaemon %s:\t%d\nKernel-side %s:\t%d\n",
    490                      bb_applet_name,DEVFSD_VERSION,bb_msg_proto_rev,
    491                      DEVFSD_PROTOCOL_REVISION_DAEMON,bb_msg_proto_rev, proto_rev);
     386    if (print_version || (DEVFSD_PROTOCOL_REVISION_DAEMON != proto_rev)) {
     387        printf("%s v%s\nDaemon %s:\t%d\nKernel-side %s:\t%d\n",
     388                applet_name, DEVFSD_VERSION, bb_msg_proto_rev,
     389                DEVFSD_PROTOCOL_REVISION_DAEMON, bb_msg_proto_rev, proto_rev);
    492390        if (DEVFSD_PROTOCOL_REVISION_DAEMON != proto_rev)
    493             bb_error_msg_and_die( "%s mismatch!",bb_msg_proto_rev);
     391            bb_error_msg_and_die("%s mismatch!", bb_msg_proto_rev);
    494392        exit(EXIT_SUCCESS); /* -v */
    495393    }
    496     /*  Tell kernel we are special (i.e. we get to see hidden entries)  */
    497     do_ioctl_and_die(fd, DEVFSDIOC_SET_EVENT_MASK, 0);
    498 
    499     sigemptyset (&new_action.sa_mask);
     394    /*  Tell kernel we are special(i.e. we get to see hidden entries)  */
     395    xioctl(fd, DEVFSDIOC_SET_EVENT_MASK, 0);
     396
     397    sigemptyset(&new_action.sa_mask);
    500398    new_action.sa_flags = 0;
    501399
    502400    /*  Set up SIGHUP and SIGUSR1 handlers  */
    503401    new_action.sa_handler = signal_handler;
    504     if (sigaction (SIGHUP, &new_action, NULL) != 0 || sigaction (SIGUSR1, &new_action, NULL) != 0 )
    505         devfsd_error_msg_and_die( "sigaction");
    506 
    507     bb_printf("%s v%s  started for %s\n",bb_applet_name, DEVFSD_VERSION, mount_point);
     402    if (sigaction(SIGHUP, &new_action, NULL) != 0 || sigaction(SIGUSR1, &new_action, NULL) != 0)
     403        bb_error_msg_and_die("sigaction");
     404
     405    printf("%s v%s  started for %s\n",applet_name, DEVFSD_VERSION, mount_point);
    508406
    509407    /*  Set umask so that mknod(2), open(2) and mkdir(2) have complete control over permissions  */
    510     umask (0);
    511     read_config_file (CONFIG_FILE, FALSE, &event_mask);
     408    umask(0);
     409    read_config_file((char*)CONFIG_FILE, FALSE, &event_mask);
    512410    /*  Do the scan before forking, so that boot scripts see the finished product  */
    513     dir_operation(SERVICE,mount_point,0,NULL);
     411    dir_operation(SERVICE, mount_point, 0, NULL);
    514412
    515413    if (ENABLE_DEVFSD_FG_NP && no_polling)
    516         exit (0);
    517     if (do_daemon)
    518     {
     414        exit(0);
     415
     416    if (ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG)
     417        logmode = LOGMODE_BOTH;
     418    else if (do_daemon == TRUE)
     419        logmode = LOGMODE_SYSLOG;
     420    /* This is the default */
     421    /*else
     422        logmode = LOGMODE_STDIO; */
     423
     424    if (do_daemon) {
    519425        /*  Release so that the child can grab it  */
    520         do_ioctl_and_die(fd, DEVFSDIOC_RELEASE_EVENT_QUEUE, 0);
    521         fork_and_execute(DIE, NULL, NULL);
    522         setsid ();        /*  Prevent hangups and become pgrp leader         */
    523     } else if(ENABLE_DEVFSD_FG_NP) {
    524         setpgid (0, 0);  /*  Become process group leader                    */
    525     }
    526 
    527     while (TRUE)
    528     {
    529         do_scan = do_servicing (fd, event_mask);
    530 
    531         free_config ();
    532         read_config_file (CONFIG_FILE, FALSE, &event_mask);
     426        xioctl(fd, DEVFSDIOC_RELEASE_EVENT_QUEUE, 0);
     427        bb_daemonize_or_rexec(0, argv);
     428    } else if (ENABLE_DEVFSD_FG_NP) {
     429        setpgid(0, 0);  /*  Become process group leader                    */
     430    }
     431
     432    while (TRUE) {
     433        do_scan = do_servicing(fd, event_mask);
     434
     435        free_config();
     436        read_config_file((char*)CONFIG_FILE, FALSE, &event_mask);
    533437        if (do_scan)
    534             dir_operation(SERVICE,mount_point,0,NULL);
    535     }
     438            dir_operation(SERVICE, mount_point, 0, NULL);
     439    }
     440    if (ENABLE_FEATURE_CLEAN_UP) free(mount_point);
    536441}   /*  End Function main  */
    537442
     
    539444/*  Private functions follow  */
    540445
    541 static void read_config_file (char *path, int optional, unsigned long *event_mask)
     446static void read_config_file(char *path, int optional, unsigned long *event_mask)
    542447/*  [SUMMARY] Read a configuration database.
    543448    <path> The path to read the database from. If this is a directory, all
    544     entries in that directory will be read (except hidden entries).
     449    entries in that directory will be read(except hidden entries).
    545450    <optional> If TRUE, the routine will silently ignore a missing config file.
    546451    <event_mask> The event mask is written here. This is not initialised.
     
    551456    FILE *fp;
    552457    char buf[STRING_LENGTH];
    553     char *line=NULL;
    554 
    555     debug_msg_logger(LOG_INFO, "%s: %s", __FUNCTION__, path);
    556 
    557     if (stat (path, &statbuf) == 0 )
    558     {
     458    char *line = NULL;
     459    char *p;
     460
     461    if (stat(path, &statbuf) == 0) {
    559462        /* Don't read 0 length files: ignored */
    560         /*if( statbuf.st_size == 0 )
     463        /*if (statbuf.st_size == 0)
    561464                return;*/
    562         if ( S_ISDIR (statbuf.st_mode) )
    563         {
    564             /* strip last / from dirname so we don't need to check for it later */
    565             while( path  && path[1]!='\0' && path[strlen(path)-1] == '/')
    566                 path[strlen(path) -1] = '\0';
    567 
    568             dir_operation(READ_CONFIG, path, 0, event_mask);
     465        if (S_ISDIR(statbuf.st_mode)) {
     466            p = bb_simplify_path(path);
     467            dir_operation(READ_CONFIG, p, 0, event_mask);
     468            free(p);
    569469            return;
    570470        }
    571         if ( ( fp = fopen (path, "r") ) != NULL )
    572         {
    573             while (fgets (buf, STRING_LENGTH, fp) != NULL)
    574             {
     471        if ((fp = fopen(path, "r")) != NULL) {
     472            while (fgets(buf, STRING_LENGTH, fp) != NULL) {
    575473                /*  Skip whitespace  */
    576                 for (line = buf; isspace (*line); ++line)
    577                     /*VOID*/;
    578                 if (line[0] == '\0' || line[0] == '#' )
     474                line = buf;
     475                line = skip_whitespace(line);
     476                if (line[0] == '\0' || line[0] == '#')
    579477                    continue;
    580                 process_config_line (line, event_mask);
     478                process_config_line(line, event_mask);
    581479            }
    582             fclose (fp);
     480            fclose(fp);
    583481        } else {
    584482            goto read_config_file_err;
     
    586484    } else {
    587485read_config_file_err:
    588     if(optional ==  0  && errno == ENOENT)
    589         msg_logger_and_die(LOG_ERR, "read config file: %s: %m", path);
    590     }
    591     return;
     486        if (optional == 0 && errno == ENOENT)
     487            error_logger_and_die(LOG_ERR, "read config file: %s", path);
     488    }
    592489}   /*  End Function read_config_file   */
    593490
    594 static void process_config_line (const char *line, unsigned long *event_mask)
     491static void process_config_line(const char *line, unsigned long *event_mask)
    595492/*  [SUMMARY] Process a line from a configuration file.
    596493    <line> The configuration line.
     
    604501    char when[STRING_LENGTH], what[STRING_LENGTH];
    605502    char name[STRING_LENGTH];
    606     char * msg="";
     503    const char *msg = "";
    607504    char *ptr;
    608505    int i;
    609506
    610507    /* !!!! Only Uppercase Keywords in devsfd.conf */
    611     static const char *const options[] = {
    612         "CLEAR_CONFIG", "INCLUDE", "OPTIONAL_INCLUDE",
    613         "RESTORE", "PERMISSIONS", "MODLOAD", "EXECUTE",
    614         "COPY", "IGNORE", "MKOLDCOMPAT", "MKNEWCOMPAT",
    615         "RMOLDCOMPAT", "RMNEWCOMPAT", 0
    616     };
    617 
    618     debug_msg_logger(LOG_INFO, __FUNCTION__);
    619 
    620     for (count = 0; count < MAX_ARGS; ++count) p[count][0] = '\0';
    621     num_args = sscanf (line, "%s %s %s %s %s %s %s %s %s %s",
     508    static const char options[] ALIGN1 =
     509        "CLEAR_CONFIG\0""INCLUDE\0""OPTIONAL_INCLUDE\0"
     510        "RESTORE\0""PERMISSIONS\0""MODLOAD\0""EXECUTE\0"
     511        "COPY\0""IGNORE\0""MKOLDCOMPAT\0""MKNEWCOMPAT\0"
     512        "RMOLDCOMPAT\0""RMNEWCOMPAT\0";
     513
     514    for (count = 0; count < MAX_ARGS; ++count)
     515        p[count][0] = '\0';
     516    num_args = sscanf(line, "%s %s %s %s %s %s %s %s %s %s",
    622517            when, name, what,
    623518            p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
    624519
    625     i = compare_string_array(options, when );
    626 
    627     /*"CLEAR_CONFIG"*/
    628     if( i == 0)
    629     {
    630         free_config ();
     520    i = index_in_strings(options, when);
     521
     522    /* "CLEAR_CONFIG" */
     523    if (i == 0) {
     524        free_config();
    631525        *event_mask = 0;
    632526        return;
    633527    }
    634528
    635     if ( num_args < 2)
     529    if (num_args < 2)
    636530        goto process_config_line_err;
    637531
    638532    /* "INCLUDE" & "OPTIONAL_INCLUDE" */
    639     if( i == 1 || i == 2 )
    640     {
    641         st_expr_expand (name, STRING_LENGTH, name, get_variable, NULL );
    642         msg_logger(LOG_INFO, "%sinclude: %s",(toupper (when[0]) == 'I') ? "": "optional_", name);
    643         read_config_file (name, (toupper (when[0]) == 'I') ? FALSE : TRUE, event_mask);
     533    if (i == 1 || i == 2) {
     534        st_expr_expand(name, STRING_LENGTH, name, get_variable, NULL);
     535        info_logger(LOG_INFO, "%sinclude: %s", (toupper(when[0]) == 'I') ? "": "optional_", name);
     536        read_config_file(name, (toupper(when[0]) == 'I') ? FALSE : TRUE, event_mask);
    644537        return;
    645538    }
    646539    /* "RESTORE" */
    647     if( i == 3)
    648     {
    649         dir_operation(RESTORE,name, strlen (name),NULL);
     540    if (i == 3) {
     541        dir_operation(RESTORE, name, strlen(name),NULL);
    650542        return;
    651543    }
     
    653545        goto process_config_line_err;
    654546
    655     new = xmalloc (sizeof *new);
    656     memset (new, 0, sizeof *new);
    657 
    658     for (count = 0; event_types[count].config_name != NULL; ++count)
    659     {
    660         if (strcasecmp (when, event_types[count].config_name) != 0)
     547    new = xzalloc(sizeof *new);
     548
     549    for (count = 0; event_types[count].config_name != NULL; ++count) {
     550        if (strcasecmp(when, event_types[count].config_name) != 0)
    661551            continue;
    662552        new->action.when = event_types[count].type;
    663553        break;
    664554    }
    665     if (event_types[count].config_name == NULL)
    666     {
    667         msg="WHEN in";
     555    if (event_types[count].config_name == NULL) {
     556        msg = "WHEN in";
    668557        goto process_config_line_err;
    669558    }
    670559
    671     i = compare_string_array(options, what );
    672 
    673     switch(i)
    674     {
     560    i = index_in_strings(options, what);
     561
     562    switch (i) {
    675563        case 4: /* "PERMISSIONS" */
    676564            new->action.what = AC_PERMISSIONS;
    677565            /*  Get user and group  */
    678             if ( ( ptr = strchr (p[0], '.') ) == NULL )
    679             {
    680                 msg="UID.GID";
     566            if ((ptr = strchr(p[0], '.')) == NULL) {
     567                msg = "UID.GID";
    681568                goto process_config_line_err; /*"missing '.' in UID.GID"*/
    682569            }
    683570
    684571            *ptr++ = '\0';
    685             new->u.permissions.uid = get_uid_gid (UID, p[0]);
    686             new->u.permissions.gid = get_uid_gid (GID, ptr);
     572            new->u.permissions.uid = get_uid_gid(UID, p[0]);
     573            new->u.permissions.gid = get_uid_gid(GID, ptr);
    687574            /*  Get mode  */
    688             new->u.permissions.mode = get_mode (p[1]);
     575            new->u.permissions.mode = get_mode(p[1]);
    689576            break;
    690577        case 5: /*  MODLOAD */
    691             /*This  action will pass "/dev/$devname" (i.e. "/dev/" prefixed to
     578            /*This  action will pass "/dev/$devname"(i.e. "/dev/" prefixed to
    692579            the device name) to the module loading  facility.  In  addition,
    693580            the /etc/modules.devfs configuration file is used.*/
     
    700587
    701588            for (count = 0; count < num_args; ++count)
    702                 new->u.execute.argv[count] = bb_xstrdup (p[count]);
     589                new->u.execute.argv[count] = xstrdup(p[count]);
    703590
    704591            new->u.execute.argv[num_args] = NULL;
     
    710597                goto process_config_line_err; /* missing path and function in line */
    711598
    712             new->u.copy.source = bb_xstrdup (p[0]);
    713             new->u.copy.destination = bb_xstrdup (p[1]);
     599            new->u.copy.source = xstrdup(p[0]);
     600            new->u.copy.destination = xstrdup(p[1]);
    714601            break;
    715602        case 8: /* IGNORE */
     
    730617            break;
    731618        default:
    732             msg ="WHAT in";
     619            msg = "WHAT in";
    733620            goto process_config_line_err;
    734621        /*esac*/
    735622    } /* switch (i) */
    736623
    737     xregcomp( &new->preg, name, REG_EXTENDED);
     624    xregcomp(&new->preg, name, REG_EXTENDED);
    738625
    739626    *event_mask |= 1 << new->action.when;
     
    745632    last_config = new;
    746633    return;
    747 process_config_line_err:
     634
     635 process_config_line_err:
    748636    msg_logger_and_die(LOG_ERR, bb_msg_bad_config, msg , line);
    749637}  /*  End Function process_config_line   */
    750638
    751 static int do_servicing (int fd, unsigned long event_mask)
     639static int do_servicing(int fd, unsigned long event_mask)
    752640/*  [SUMMARY] Service devfs changes until a signal is received.
    753641    <fd> The open control file.
     
    758646    ssize_t bytes;
    759647    struct devfsd_notify_struct info;
    760     unsigned long tmp_event_mask;
    761 
    762     debug_msg_logger(LOG_INFO, __FUNCTION__);
    763 
    764     /*  Tell devfs what events we care about  */
    765     tmp_event_mask = event_mask;
    766     do_ioctl_and_die(fd, DEVFSDIOC_SET_EVENT_MASK, tmp_event_mask);
    767     while (!caught_signal)
    768     {
     648
     649    /* (void*) cast is only in order to match prototype */
     650    xioctl(fd, DEVFSDIOC_SET_EVENT_MASK, (void*)event_mask);
     651    while (!caught_signal) {
    769652        errno = 0;
    770         bytes = read (fd, (char *) &info, sizeof info);
     653        bytes = read(fd,(char *) &info, sizeof info);
    771654        if (caught_signal)
    772655            break;      /*  Must test for this first     */
     
    775658        if (bytes < 1)
    776659            break;
    777         service_name (&info);
    778     }
    779     if (caught_signal)
    780     {
     660        service_name(&info);
     661    }
     662    if (caught_signal) {
    781663        int c_sighup = caught_sighup;
    782664
    783665        caught_signal = FALSE;
    784666        caught_sighup = FALSE;
    785         return (c_sighup);
     667        return c_sighup;
    786668    }
    787669    msg_logger_and_die(LOG_ERR, "read error on control file");
    788670}   /*  End Function do_servicing  */
    789671
    790 static void service_name (const struct devfsd_notify_struct *info)
     672static void service_name(const struct devfsd_notify_struct *info)
    791673/*  [SUMMARY] Service a single devfs change.
    792674    <info> The devfs change.
     
    798680    struct config_entry_struct *entry;
    799681
    800     debug_msg_logger(LOG_INFO, __FUNCTION__);
    801682    if (ENABLE_DEBUG && info->overrun_count > 0)
    802         debug_msg_logger(LOG_ERR, "lost %u events", info->overrun_count);
     683        msg_logger(LOG_ERR, "lost %u events", info->overrun_count);
    803684
    804685    /*  Discard lookups on "/dev/log" and "/dev/initctl"  */
    805     if(   info->type == DEVFSD_NOTIFY_LOOKUP &&
    806         ((info->devname[0]=='l' && info->devname[1]=='o' &&
    807           info->devname[2]=='g' && !info->devname[3]) ||
    808         ( info->devname[0]=='i' && info->devname[1]=='n' &&
    809           info->devname[2]=='i' && info->devname[3]=='t' &&
    810           info->devname[4]=='c' && info->devname[5]=='t' &&
    811           info->devname[6]=='l' && !info->devname[7])))
    812             return;
    813     for (entry = first_config; entry != NULL; entry = entry->next)
    814     {
     686    if (info->type == DEVFSD_NOTIFY_LOOKUP
     687        && ((info->devname[0] == 'l' && info->devname[1] == 'o'
     688        && info->devname[2] == 'g' && !info->devname[3])
     689        || (info->devname[0] == 'i' && info->devname[1] == 'n'
     690        && info->devname[2] == 'i' && info->devname[3] == 't'
     691        && info->devname[4] == 'c' && info->devname[5] == 't'
     692        && info->devname[6] == 'l' && !info->devname[7]))
     693    )
     694        return;
     695
     696    for (entry = first_config; entry != NULL; entry = entry->next) {
    815697        /*  First check if action matches the type, then check if name matches */
    816         if (info->type != entry->action.when || regexec (&entry->preg, info->devname, MAX_SUBEXPR, mbuf, 0) != 0 )
     698        if (info->type != entry->action.when
     699        || regexec(&entry->preg, info->devname, MAX_SUBEXPR, mbuf, 0) != 0)
    817700            continue;
    818         for (n = 0; (n < MAX_SUBEXPR) && (mbuf[n].rm_so != -1); ++n)
     701        for (n = 0;(n < MAX_SUBEXPR) && (mbuf[n].rm_so != -1); ++n)
    819702            /* VOID */;
    820703
    821         debug_msg_logger(LOG_INFO, "%s: action.what %d", __FUNCTION__, entry->action.what);
    822 
    823         switch (entry->action.what)
    824         {
     704        switch (entry->action.what) {
    825705            case AC_PERMISSIONS:
    826                 action_permissions (info, entry);
     706                action_permissions(info, entry);
    827707                break;
    828708            case AC_MODLOAD:
    829                 if(ENABLE_DEVFSD_MODLOAD)
    830                     action_modload (info, entry);
     709                if (ENABLE_DEVFSD_MODLOAD)
     710                    action_modload(info, entry);
    831711                break;
    832712            case AC_EXECUTE:
    833                 action_execute (info, entry, mbuf, n);
     713                action_execute(info, entry, mbuf, n);
    834714                break;
    835715            case AC_COPY:
    836                 action_copy (info, entry, mbuf, n);
     716                action_copy(info, entry, mbuf, n);
    837717                break;
    838718            case AC_IGNORE:
     
    843723            case AC_RMOLDCOMPAT:
    844724            case AC_RMNEWCOMPAT:
    845                 action_compat (info, entry->action.what);
     725                action_compat(info, entry->action.what);
    846726                break;
    847727            default:
     
    851731}   /*  End Function service_name  */
    852732
    853 static void action_permissions (const struct devfsd_notify_struct *info,
     733static void action_permissions(const struct devfsd_notify_struct *info,
    854734                const struct config_entry_struct *entry)
    855735/*  [SUMMARY] Update permissions for a device entry.
     
    861741    struct stat statbuf;
    862742
    863     debug_msg_logger(LOG_INFO, __FUNCTION__);
    864 
    865     if ( stat (info->devname, &statbuf) != 0    ||
    866          chmod (info->devname,(statbuf.st_mode & S_IFMT) | (entry->u.permissions.mode & ~S_IFMT)) != 0 ||
    867          chown (info->devname, entry->u.permissions.uid, entry->u.permissions.gid) != 0)
    868     {
    869         msg_logger(LOG_ERR, "Can't chmod or chown: %s: %m",info->devname);
    870     }
     743    if (stat(info->devname, &statbuf) != 0
     744     || chmod(info->devname, (statbuf.st_mode & S_IFMT) | (entry->u.permissions.mode & ~S_IFMT)) != 0
     745     || chown(info->devname, entry->u.permissions.uid, entry->u.permissions.gid) != 0
     746    )
     747        error_logger(LOG_ERR, "Can't chmod or chown: %s", info->devname);
    871748}   /*  End Function action_permissions  */
    872749
    873 static void action_modload (const struct devfsd_notify_struct *info,
     750static void action_modload(const struct devfsd_notify_struct *info,
    874751                const struct config_entry_struct *entry ATTRIBUTE_UNUSED)
    875752/*  [SUMMARY] Load a module.
     
    880757{
    881758    char *argv[6];
    882     char device[STRING_LENGTH];
    883 
    884     argv[0] = MODPROBE;
    885     argv[1] = MODPROBE_SWITCH_1; /* "-k" */
    886     argv[2] = MODPROBE_SWITCH_2; /* "-C" */
    887     argv[3] = CONFIG_MODULES_DEVFS;
    888     argv[4] = device;
     759
     760    argv[0] = (char*)MODPROBE;
     761    argv[1] = (char*)MODPROBE_SWITCH_1; /* "-k" */
     762    argv[2] = (char*)MODPROBE_SWITCH_2; /* "-C" */
     763    argv[3] = (char*)CONFIG_MODULES_DEVFS;
     764    argv[4] = concat_path_file("/dev", info->devname); /* device */
    889765    argv[5] = NULL;
    890766
    891     snprintf (device, sizeof (device), "/dev/%s", info->devname);
    892     debug_msg_logger(LOG_INFO, "%s: %s %s %s %s %s",__FUNCTION__, argv[0],argv[1],argv[2],argv[3],argv[4]);
    893     fork_and_execute(DIE, argv[0], argv);
     767    wait4pid(xspawn(argv));
     768    free(argv[4]);
    894769}  /*  End Function action_modload  */
    895770
    896 static void action_execute (const struct devfsd_notify_struct *info,
     771static void action_execute(const struct devfsd_notify_struct *info,
    897772                const struct config_entry_struct *entry,
    898773                const regmatch_t *regexpr, unsigned int numexpr)
     
    900775    <info> The devfs change.
    901776    <entry> The config file entry.
    902     <regexpr> The number of subexpression (start, end) offsets within the
     777    <regexpr> The number of subexpression(start, end) offsets within the
    903778    device name.
    904779    <numexpr> The number of elements within <<regexpr>>.
     
    911786    char largv[MAX_ARGS + 1][STRING_LENGTH];
    912787
    913     debug_msg_logger(LOG_INFO ,__FUNCTION__);
    914788    gv_info.info = info;
    915789    gv_info.devname = info->devname;
    916     snprintf (gv_info.devpath, sizeof (gv_info.devpath), "%s/%s", mount_point, info->devname);
    917     for (count = 0; entry->u.execute.argv[count] != NULL; ++count)
    918     {
    919         expand_expression (largv[count], STRING_LENGTH,
     790    snprintf(gv_info.devpath, sizeof(gv_info.devpath), "%s/%s", mount_point, info->devname);
     791    for (count = 0; entry->u.execute.argv[count] != NULL; ++count) {
     792        expand_expression(largv[count], STRING_LENGTH,
    920793                entry->u.execute.argv[count],
    921794                get_variable, &gv_info,
    922                 gv_info.devname, regexpr, numexpr );
     795                gv_info.devname, regexpr, numexpr);
    923796        argv[count] = largv[count];
    924797    }
    925798    argv[count] = NULL;
    926     fork_and_execute(NO_DIE, argv[0], argv);
     799    wait4pid(spawn(argv));
    927800}   /*  End Function action_execute  */
    928801
    929802
    930 static void action_copy (const struct devfsd_notify_struct *info,
     803static void action_copy(const struct devfsd_notify_struct *info,
    931804             const struct config_entry_struct *entry,
    932805             const regmatch_t *regexpr, unsigned int numexpr)
     
    934807    <info> The devfs change.
    935808    <entry> The config file entry.
    936     <regexpr> This list of subexpression (start, end) offsets within the
     809    <regexpr> This list of subexpression(start, end) offsets within the
    937810    device name.
    938811    <numexpr> The number of elements in <<regexpr>>.
     
    946819    int ret = 0;
    947820
    948     debug_msg_logger(LOG_INFO, __FUNCTION__);
    949 
    950821    dest_stat.st_mode = 0;
    951822
    952     if ( (info->type == DEVFSD_NOTIFY_CHANGE) && S_ISLNK (info->mode) )
     823    if ((info->type == DEVFSD_NOTIFY_CHANGE) && S_ISLNK(info->mode))
    953824        return;
    954825    gv_info.info = info;
    955826    gv_info.devname = info->devname;
    956827
    957     snprintf (gv_info.devpath, sizeof (gv_info.devpath), "%s/%s", mount_point, info->devname);
    958     expand_expression (source, STRING_LENGTH, entry->u.copy.source,
     828    snprintf(gv_info.devpath, sizeof(gv_info.devpath), "%s/%s", mount_point, info->devname);
     829    expand_expression(source, STRING_LENGTH, entry->u.copy.source,
    959830                get_variable, &gv_info, gv_info.devname,
    960831                regexpr, numexpr);
    961832
    962     expand_expression (destination, STRING_LENGTH, entry->u.copy.destination,
     833    expand_expression(destination, STRING_LENGTH, entry->u.copy.destination,
    963834                get_variable, &gv_info, gv_info.devname,
    964835                regexpr, numexpr);
    965836
    966     if ( !make_dir_tree (destination) || lstat (source, &source_stat) != 0)
     837    if (!make_dir_tree(destination) || lstat(source, &source_stat) != 0)
    967838            return;
    968     lstat (destination, &dest_stat);
     839    lstat(destination, &dest_stat);
    969840    new_mode = source_stat.st_mode & ~S_ISVTX;
    970841    if (info->type == DEVFSD_NOTIFY_CREATE)
    971842        new_mode |= S_ISVTX;
    972     else if ( (info->type == DEVFSD_NOTIFY_CHANGE) && (dest_stat.st_mode & S_ISVTX) )
     843    else if ((info->type == DEVFSD_NOTIFY_CHANGE) &&(dest_stat.st_mode & S_ISVTX))
    973844        new_mode |= S_ISVTX;
    974     ret = copy_inode (destination, &dest_stat, new_mode, source, &source_stat);
     845    ret = copy_inode(destination, &dest_stat, new_mode, source, &source_stat);
    975846    if (ENABLE_DEBUG && ret && (errno != EEXIST))
    976         debug_msg_logger(LOG_ERR, "copy_inode: %s to %s: %m", source, destination);
    977     return;
     847        error_logger(LOG_ERR, "copy_inode: %s to %s", source, destination);
    978848}   /*  End Function action_copy  */
    979849
    980 static void action_compat (const struct devfsd_notify_struct *info, unsigned int action)
     850static void action_compat(const struct devfsd_notify_struct *info, unsigned int action)
    981851/*  [SUMMARY] Process a compatibility request.
    982852    <info> The devfs change.
     
    988858    const char *compat_name = NULL;
    989859    const char *dest_name = info->devname;
    990     char *ptr=NULL;
     860    const char *ptr;
    991861    char compat_buf[STRING_LENGTH], dest_buf[STRING_LENGTH];
    992862    int mode, host, bus, target, lun;
     
    1009879
    1010880    /*  First construct compatibility name  */
    1011     switch (action)
    1012     {
     881    switch (action) {
    1013882        case AC_MKOLDCOMPAT:
    1014883        case AC_RMOLDCOMPAT:
    1015             compat_name = get_old_name (info->devname, info->namelen, compat_buf, info->major, info->minor);
     884            compat_name = get_old_name(info->devname, info->namelen, compat_buf, info->major, info->minor);
    1016885            break;
    1017886        case AC_MKNEWCOMPAT:
    1018887        case AC_RMNEWCOMPAT:
    1019             ptr = strrchr (info->devname, '/') + 1;
    1020             i=scan_dev_name(info->devname, info->namelen, ptr);
    1021 
    1022             debug_msg_logger(LOG_INFO, "%s: scan_dev_name = %d", __FUNCTION__, i);
     888            ptr = bb_basename(info->devname);
     889            i = scan_dev_name(info->devname, info->namelen, ptr);
    1023890
    1024891            /* nothing found */
    1025             if(i==0 || i > 9)
     892            if (i == 0 || i > 9)
    1026893                return;
    1027894
    1028             sscanf (info->devname +((i<6)?5:4), "host%d/bus%d/target%d/lun%d/", &host, &bus, &target, &lun);
    1029             snprintf (dest_buf, sizeof (dest_buf), "../%s", info->devname + ((i>5)?4:0));
     895            sscanf(info->devname + ((i < 6) ? 5 : 4), "host%d/bus%d/target%d/lun%d/", &host, &bus, &target, &lun);
     896            snprintf(dest_buf, sizeof(dest_buf), "../%s", info->devname + (( i > 5) ? 4 : 0));
    1030897            dest_name = dest_buf;
    1031898            compat_name = compat_buf;
     
    1033900
    1034901            /* 1 == scsi/generic  2 == scsi/disc 3 == scsi/cd 6 == ide/host/disc 7 == ide/host/cd */
    1035             if( i == 1 || i == 2 || i == 3 || i == 6 || i ==7 )
    1036                 sprintf ( compat_buf, fmt[i], host, bus, target, lun);
     902            if (i == 1 || i == 2 || i == 3 || i == 6 || i ==7)
     903                sprintf(compat_buf, fmt[i], host, bus, target, lun);
    1037904
    1038905            /* 4 == scsi/part 8 == ide/host/part */
    1039             if( i == 4 || i == 8)
    1040                 sprintf ( compat_buf, fmt[i], host, bus, target, lun, atoi (ptr + 4) );
     906            if (i == 4 || i == 8)
     907                sprintf(compat_buf, fmt[i], host, bus, target, lun, atoi(ptr + 4));
    1041908
    1042909            /* 5 == scsi/mt */
    1043             if( i == 5)
    1044             {
     910            if (i == 5) {
    1045911                rewind_ = info->devname[info->namelen - 1];
    1046912                if (rewind_ != 'n')
    1047913                    rewind_ = '\0';
    1048914                mode=0;
    1049                 if(ptr[2] ==  'l' /*108*/ || ptr[2] == 'm'/*109*/)
     915                if (ptr[2] ==  'l' /*108*/ || ptr[2] == 'm'/*109*/)
    1050916                    mode = ptr[2] - 107; /* 1 or 2 */
    1051                 if(ptr[2] ==  'a')
     917                if (ptr[2] ==  'a')
    1052918                    mode = 3;
    1053                 sprintf (compat_buf, fmt [i], host, bus, target, lun, mode, rewind_);
     919                sprintf(compat_buf, fmt[i], host, bus, target, lun, mode, rewind_);
    1054920            }
    1055921
    1056922            /* 9 == ide/host/mt */
    1057             if( i ==  9 )
    1058                 snprintf (compat_buf, sizeof (compat_buf), fmt[i], host, bus, target, lun, ptr + 2);
     923            if (i ==  9)
     924                snprintf(compat_buf, sizeof(compat_buf), fmt[i], host, bus, target, lun, ptr + 2);
    1059925        /* esac */
    1060     } /* switch(action) */
    1061 
    1062     if(compat_name == NULL )
     926    } /* switch (action) */
     927
     928    if (compat_name == NULL)
    1063929        return;
    1064930
    1065     debug_msg_logger( LOG_INFO, "%s: %s", __FUNCTION__, compat_name);
    1066 
    1067931    /*  Now decide what to do with it  */
    1068     switch (action)
    1069     {
     932    switch (action) {
    1070933        case AC_MKOLDCOMPAT:
    1071934        case AC_MKNEWCOMPAT:
    1072             mksymlink (dest_name, compat_name);
     935            mksymlink(dest_name, compat_name);
    1073936            break;
    1074937        case AC_RMOLDCOMPAT:
    1075938        case AC_RMNEWCOMPAT:
    1076             ret = unlink (compat_name);
     939            ret = unlink(compat_name);
    1077940            if (ENABLE_DEBUG && ret)
    1078                 debug_msg_logger(LOG_ERR, "unlink: %s: %m", compat_name);
     941                error_logger(LOG_ERR, "unlink: %s", compat_name);
    1079942            break;
    1080943        /*esac*/
    1081     } /* switch(action) */
     944    } /* switch (action) */
    1082945}   /*  End Function action_compat  */
    1083946
    1084947static void restore(char *spath, struct stat source_stat, int rootlen)
    1085948{
    1086     char dpath[STRING_LENGTH];
     949    char *dpath;
    1087950    struct stat dest_stat;
    1088951
    1089     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1090 
    1091952    dest_stat.st_mode = 0;
    1092     snprintf (dpath, sizeof dpath, "%s%s", mount_point, spath + rootlen);
    1093     lstat (dpath, &dest_stat);
    1094 
    1095     if ( S_ISLNK (source_stat.st_mode) || (source_stat.st_mode & S_ISVTX) )
    1096         copy_inode (dpath, &dest_stat, (source_stat.st_mode & ~S_ISVTX) , spath, &source_stat);
    1097 
    1098     if ( S_ISDIR (source_stat.st_mode) )
     953    dpath = concat_path_file(mount_point, spath + rootlen);
     954    lstat(dpath, &dest_stat);
     955    free(dpath);
     956    if (S_ISLNK(source_stat.st_mode) || (source_stat.st_mode & S_ISVTX))
     957        copy_inode(dpath, &dest_stat,(source_stat.st_mode & ~S_ISVTX) , spath, &source_stat);
     958
     959    if (S_ISDIR(source_stat.st_mode))
    1099960        dir_operation(RESTORE, spath, rootlen,NULL);
    1100961}
    1101962
    1102963
    1103 static int copy_inode (const char *destpath, const struct stat *dest_stat,
     964static int copy_inode(const char *destpath, const struct stat *dest_stat,
    1104965            mode_t new_mode,
    1105966            const char *sourcepath, const struct stat *source_stat)
     
    1119980    char symlink_val[STRING_LENGTH];
    1120981
    1121     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1122 
    1123     if ( (source_stat->st_mode & S_IFMT) == (dest_stat->st_mode & S_IFMT) )
    1124     {
     982    if ((source_stat->st_mode & S_IFMT) ==(dest_stat->st_mode & S_IFMT)) {
    1125983        /*  Same type  */
    1126         if ( S_ISLNK (source_stat->st_mode) )
    1127         {
    1128             if (( source_len = readlink (sourcepath, source_link, STRING_LENGTH - 1) ) < 0 ||
    1129                 ( dest_len   = readlink (destpath  , dest_link  , STRING_LENGTH - 1) ) < 0 )
    1130                 return (FALSE);
     984        if (S_ISLNK(source_stat->st_mode)) {
     985            if ((source_len = readlink(sourcepath, source_link, STRING_LENGTH - 1)) < 0
     986                || (dest_len   = readlink(destpath  , dest_link  , STRING_LENGTH - 1)) < 0
     987            )
     988                return FALSE;
    1131989            source_link[source_len] = '\0';
    1132990            dest_link[dest_len] = '\0';
    1133             if ( (source_len != dest_len) || (strcmp (source_link, dest_link) != 0) )
    1134             {
    1135                 unlink (destpath);
    1136                 symlink (source_link, destpath);
     991            if ((source_len != dest_len) || (strcmp(source_link, dest_link) != 0)) {
     992                unlink(destpath);
     993                symlink(source_link, destpath);
    1137994            }
    1138             return (TRUE);
     995            return TRUE;
    1139996        }   /*  Else not a symlink  */
    1140         chmod (destpath, new_mode & ~S_IFMT);
    1141         chown (destpath, source_stat->st_uid, source_stat->st_gid);
    1142         return (TRUE);
     997        chmod(destpath, new_mode & ~S_IFMT);
     998        chown(destpath, source_stat->st_uid, source_stat->st_gid);
     999        return TRUE;
    11431000    }
    11441001    /*  Different types: unlink and create  */
    1145     unlink (destpath);
    1146     switch (source_stat->st_mode & S_IFMT)
    1147     {
     1002    unlink(destpath);
     1003    switch (source_stat->st_mode & S_IFMT) {
    11481004        case S_IFSOCK:
    1149             if ( ( fd = socket (AF_UNIX, SOCK_STREAM, 0) ) < 0 )
     1005            if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
    11501006                break;
    11511007            un_addr.sun_family = AF_UNIX;
    1152             snprintf (un_addr.sun_path, sizeof (un_addr.sun_path), "%s", destpath);
    1153             val = bind (fd, (struct sockaddr *) &un_addr, (int) sizeof un_addr);
    1154             close (fd);
    1155             if (val != 0 || chmod (destpath, new_mode & ~S_IFMT) != 0)
     1008            snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s", destpath);
     1009            val = bind(fd,(struct sockaddr *) &un_addr,(int) sizeof un_addr);
     1010            close(fd);
     1011            if (val != 0 || chmod(destpath, new_mode & ~S_IFMT) != 0)
    11561012                break;
    11571013            goto do_chown;
    11581014        case S_IFLNK:
    1159             if ( ( val = readlink (sourcepath, symlink_val, STRING_LENGTH - 1) ) < 0 )
     1015            if ((val = readlink(sourcepath, symlink_val, STRING_LENGTH - 1)) < 0)
    11601016                break;
    11611017            symlink_val[val] = '\0';
    1162             if (symlink (symlink_val, destpath) == 0)
    1163                 return (TRUE);
     1018            if (symlink(symlink_val, destpath) == 0)
     1019                return TRUE;
    11641020            break;
    11651021        case S_IFREG:
    1166             if ( ( fd = open (destpath, O_RDONLY | O_CREAT, new_mode & ~S_IFMT) ) < 0 )
     1022            if ((fd = open(destpath, O_RDONLY | O_CREAT, new_mode & ~S_IFMT)) < 0)
    11671023                break;
    1168             close (fd);
    1169             if (chmod (destpath, new_mode & ~S_IFMT) != 0)
     1024            close(fd);
     1025            if (chmod(destpath, new_mode & ~S_IFMT) != 0)
    11701026                break;
    11711027            goto do_chown;
     
    11731029        case S_IFCHR:
    11741030        case S_IFIFO:
    1175             if (mknod (destpath, new_mode, source_stat->st_rdev) != 0)
     1031            if (mknod(destpath, new_mode, source_stat->st_rdev) != 0)
    11761032                break;
    11771033            goto do_chown;
    11781034        case S_IFDIR:
    1179             if (mkdir (destpath, new_mode & ~S_IFMT) != 0)
     1035            if (mkdir(destpath, new_mode & ~S_IFMT) != 0)
    11801036                break;
    11811037do_chown:
    1182             if (chown (destpath, source_stat->st_uid, source_stat->st_gid) == 0)
    1183                 return (TRUE);
     1038            if (chown(destpath, source_stat->st_uid, source_stat->st_gid) == 0)
     1039                return TRUE;
    11841040        /*break;*/
    11851041    }
    1186     return (FALSE);
     1042    return FALSE;
    11871043}   /*  End Function copy_inode  */
    11881044
    1189 static void free_config (void)
     1045static void free_config(void)
    11901046/*  [SUMMARY] Free the configuration information.
    11911047    [RETURNS] Nothing.
     
    11951051    void *next;
    11961052
    1197     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1198 
    1199     for (c_entry = first_config; c_entry != NULL; c_entry = next)
    1200     {
     1053    for (c_entry = first_config; c_entry != NULL; c_entry = next) {
    12011054        unsigned int count;
    12021055
    12031056        next = c_entry->next;
    1204         regfree (&c_entry->preg);
    1205         if (c_entry->action.what == AC_EXECUTE)
    1206         {
    1207             for (count = 0; count < MAX_ARGS; ++count)
    1208             {
     1057        regfree(&c_entry->preg);
     1058        if (c_entry->action.what == AC_EXECUTE) {
     1059            for (count = 0; count < MAX_ARGS; ++count) {
    12091060                if (c_entry->u.execute.argv[count] == NULL)
    12101061                    break;
    1211                 free (c_entry->u.execute.argv[count]);
     1062                free(c_entry->u.execute.argv[count]);
    12121063            }
    12131064        }
    1214         free (c_entry);
     1065        free(c_entry);
    12151066    }
    12161067    first_config = NULL;
     
    12181069}   /*  End Function free_config  */
    12191070
    1220 static int get_uid_gid (int flag, const char *string)
     1071static int get_uid_gid(int flag, const char *string)
    12211072/*  [SUMMARY] Convert a string to a UID or GID value.
    12221073    <flag> "UID" or "GID".
     
    12271078    struct passwd *pw_ent;
    12281079    struct group *grp_ent;
    1229     static char *msg;
     1080    static const char *msg;
    12301081
    12311082    if (ENABLE_DEVFSD_VERBOSE)
    1232         msg="user";
    1233 
    1234     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1235 
    1236     if(ENABLE_DEBUG && flag != UID && flag != GID)
    1237         msg_logger_and_die(LOG_ERR,"%s: flag != UID && flag != GID", __FUNCTION__);
    1238 
    1239     if ( isdigit (string[0]) || ( (string[0] == '-') && isdigit (string[1]) ) )
    1240         return atoi (string);
    1241 
    1242     if ( flag == UID && ( pw_ent  = getpwnam (string) ) != NULL )
    1243         return (pw_ent->pw_uid);
    1244 
    1245     if ( flag == GID && ( grp_ent = getgrnam (string) ) != NULL )
    1246         return (grp_ent->gr_gid);
    1247     else if(ENABLE_DEVFSD_VERBOSE)
    1248         msg="group";
    1249 
    1250     if(ENABLE_DEVFSD_VERBOSE)
     1083        msg = "user";
     1084
     1085    if (isdigit(string[0]) ||((string[0] == '-') && isdigit(string[1])))
     1086        return atoi(string);
     1087
     1088    if (flag == UID && (pw_ent  = getpwnam(string)) != NULL)
     1089        return pw_ent->pw_uid;
     1090
     1091    if (flag == GID && (grp_ent = getgrnam(string)) != NULL)
     1092        return grp_ent->gr_gid;
     1093    else if (ENABLE_DEVFSD_VERBOSE)
     1094        msg = "group";
     1095
     1096    if (ENABLE_DEVFSD_VERBOSE)
    12511097        msg_logger(LOG_ERR,"unknown %s: %s, defaulting to %cid=0",  msg, string, msg[0]);
    1252     return (0);
     1098    return 0;
    12531099}/*  End Function get_uid_gid  */
    12541100
    1255 static mode_t get_mode (const char *string)
     1101static mode_t get_mode(const char *string)
    12561102/*  [SUMMARY] Convert a string to a mode value.
    12571103    <string> The string.
     
    12621108    int i;
    12631109
    1264     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1265 
    1266     if ( isdigit (string[0]) )
    1267         return strtoul (string, NULL, 8);
    1268     if (strlen (string) != 9)
     1110    if (isdigit(string[0]))
     1111        return strtoul(string, NULL, 8);
     1112    if (strlen(string) != 9)
    12691113        msg_logger_and_die(LOG_ERR, "bad mode: %s", string);
    12701114
    12711115    mode = 0;
    1272     i= S_IRUSR;
    1273     while(i>0)
    1274     {
    1275         if(string[0]=='r'||string[0]=='w'||string[0]=='x')
    1276             mode+=i;
    1277         i=i/2;
     1116    i = S_IRUSR;
     1117    while (i > 0) {
     1118        if (string[0] == 'r' || string[0] == 'w' || string[0] == 'x')
     1119            mode += i;
     1120        i = i / 2;
    12781121        string++;
    12791122    }
    1280     return (mode);
     1123    return mode;
    12811124}   /*  End Function get_mode  */
    12821125
    1283 static void signal_handler (int sig)
    1284 {
    1285     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1286 
     1126static void signal_handler(int sig)
     1127{
    12871128    caught_signal = TRUE;
    12881129    if (sig == SIGHUP)
    12891130        caught_sighup = TRUE;
    12901131
    1291     msg_logger(LOG_INFO, "Caught signal %d", sig);
     1132    info_logger(LOG_INFO, "Caught signal %d", sig);
    12921133}   /*  End Function signal_handler  */
    12931134
    1294 static const char *get_variable (const char *variable, void *info)
    1295 {
     1135static const char *get_variable(const char *variable, void *info)
     1136{
     1137    static char sbuf[sizeof(int)*3 + 2]; /* sign and NUL */
     1138
     1139    char hostname[STRING_LENGTH];
    12961140    struct get_variable_info *gv_info = info;
    1297     static char hostname[STRING_LENGTH], sbuf[STRING_LENGTH];
    1298     const char *field_names[] = { "hostname", "mntpt", "devpath", "devname",
    1299                                    "uid", "gid", "mode", hostname, mount_point,
    1300                                    gv_info->devpath, gv_info->devname, 0 };
     1141    const char *field_names[] = {
     1142            "hostname", "mntpt", "devpath", "devname",
     1143            "uid", "gid", "mode", hostname, mount_point,
     1144            gv_info->devpath, gv_info->devname, NULL
     1145    };
    13011146    int i;
    13021147
    1303     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1304 
    1305     if (gethostname (hostname, STRING_LENGTH - 1) != 0)
    1306         msg_logger_and_die(LOG_ERR, "gethostname: %m");
    1307 
     1148    if (gethostname(hostname, STRING_LENGTH - 1) != 0)
    13081149        /* Here on error we should do exit(RV_SYS_ERROR), instead we do exit(EXIT_FAILURE) */
    1309         hostname[STRING_LENGTH - 1] = '\0';
    1310 
    1311     /* compare_string_array returns i>=0  */
    1312     i=compare_string_array(field_names, variable);
    1313 
    1314     if ( i > 6 || i < 0 || (i > 1 && gv_info == NULL))
    1315             return (NULL);
    1316     if( i >= 0 && i <= 3)
    1317     {
    1318         debug_msg_logger(LOG_INFO, "%s: i=%d %s", __FUNCTION__, i ,field_names[i+7]);
    1319         return(field_names[i+7]);
    1320     }
    1321 
    1322     if(i == 4 )
    1323         sprintf (sbuf, "%u", gv_info->info->uid);
    1324     else if(i == 5)
    1325         sprintf (sbuf, "%u", gv_info->info->gid);
    1326     else if(i == 6)
    1327         sprintf (sbuf, "%o", gv_info->info->mode);
    1328 
    1329     debug_msg_logger(LOG_INFO, "%s: %s", __FUNCTION__, sbuf);
    1330 
    1331     return (sbuf);
     1150        error_logger_and_die(LOG_ERR, "gethostname");
     1151
     1152    hostname[STRING_LENGTH - 1] = '\0';
     1153
     1154    /* index_in_str_array returns i>=0  */
     1155    i = index_in_str_array(field_names, variable);
     1156
     1157    if (i > 6 || i < 0 || (i > 1 && gv_info == NULL))
     1158        return NULL;
     1159    if (i >= 0 && i <= 3)
     1160        return field_names[i + 7];
     1161
     1162    if (i == 4)
     1163        sprintf(sbuf, "%u", gv_info->info->uid);
     1164    else if (i == 5)
     1165        sprintf(sbuf, "%u", gv_info->info->gid);
     1166    else if (i == 6)
     1167        sprintf(sbuf, "%o", gv_info->info->mode);
     1168    return sbuf;
    13321169}   /*  End Function get_variable  */
    13331170
     
    13361173    struct devfsd_notify_struct info;
    13371174
    1338     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1339 
    1340     memset (&info, 0, sizeof info);
     1175    memset(&info, 0, sizeof info);
    13411176    info.type = DEVFSD_NOTIFY_REGISTERED;
    13421177    info.mode = statbuf.st_mode;
    1343     info.major = major (statbuf.st_rdev);
    1344     info.minor = minor (statbuf.st_rdev);
     1178    info.major = major(statbuf.st_rdev);
     1179    info.minor = minor(statbuf.st_rdev);
    13451180    info.uid = statbuf.st_uid;
    13461181    info.gid = statbuf.st_gid;
    1347     snprintf (info.devname, sizeof (info.devname), "%s", path + strlen (mount_point) + 1);
    1348     info.namelen = strlen (info.devname);
    1349     service_name (&info);
    1350     if ( S_ISDIR (statbuf.st_mode) )
    1351         dir_operation(SERVICE,path,0,NULL);
     1182    snprintf(info.devname, sizeof(info.devname), "%s", path + strlen(mount_point) + 1);
     1183    info.namelen = strlen(info.devname);
     1184    service_name(&info);
     1185    if (S_ISDIR(statbuf.st_mode))
     1186        dir_operation(SERVICE, path, 0, NULL);
    13521187}
    13531188
     
    13641199    DIR *dp;
    13651200    struct dirent *de;
    1366     char path[STRING_LENGTH];
    1367 
    1368     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1369 
    1370     if((dp = opendir( dir_name))==NULL)
    1371     {
    1372         debug_msg_logger(LOG_ERR, "opendir: %s: %m", dir_name);
     1201    char *path;
     1202
     1203    if ((dp = warn_opendir(dir_name)) == NULL)
    13731204        return;
    1374     }
    1375 
    1376     while ( (de = readdir (dp) ) != NULL )
    1377     {
    1378 
    1379         if(de->d_name && *de->d_name == '.' && (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2])))
     1205
     1206    while ((de = readdir(dp)) != NULL) {
     1207
     1208        if (de->d_name && DOT_OR_DOTDOT(de->d_name))
    13801209            continue;
    1381         snprintf (path, sizeof (path), "%s/%s", dir_name, de->d_name);
    1382         debug_msg_logger(LOG_ERR, "%s: %s", __FUNCTION__, path);
    1383 
    1384         if (lstat (path, &statbuf) != 0)
    1385         {
    1386             debug_msg_logger(LOG_ERR, "%s: %s: %m", __FUNCTION__, path);
    1387             continue;
     1210        path = concat_path_file(dir_name, de->d_name);
     1211        if (lstat(path, &statbuf) == 0) {
     1212            switch (type) {
     1213                case SERVICE:
     1214                    service(statbuf, path);
     1215                    break;
     1216                case RESTORE:
     1217                    restore(path, statbuf, var);
     1218                    break;
     1219                case READ_CONFIG:
     1220                    read_config_file(path, var, event_mask);
     1221                    break;
     1222            }
    13881223        }
    1389         switch(type)
    1390         {
    1391             case SERVICE:
    1392                 service(statbuf,path);
    1393                 break;
    1394             case RESTORE:
    1395                 restore(path, statbuf, var);
    1396                 break;
    1397             case READ_CONFIG:
    1398                 read_config_file (path, var, event_mask);
    1399                 break;
    1400         }
    1401     }
    1402     closedir (dp);
     1224        free(path);
     1225    }
     1226    closedir(dp);
    14031227}   /*  End Function do_scan_and_service  */
    14041228
    1405 static int mksymlink (const char *oldpath, const char *newpath)
     1229static int mksymlink(const char *oldpath, const char *newpath)
    14061230/*  [SUMMARY] Create a symlink, creating intervening directories as required.
    14071231    <oldpath> The string contained in the symlink.
     
    14101234*/
    14111235{
    1412     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1413 
    1414     if ( !make_dir_tree (newpath) )
    1415         return (-1);
    1416 
    1417     if (symlink (oldpath, newpath) != 0)
    1418     {
     1236    if (!make_dir_tree(newpath))
     1237        return -1;
     1238
     1239    if (symlink(oldpath, newpath) != 0) {
    14191240        if (errno != EEXIST)
    1420         {
    1421             debug_msg_logger(LOG_ERR, "%s: %s to %s: %m", __FUNCTION__, oldpath, newpath);
    1422             return (-1);
    1423         }
    1424     }
    1425     return (0);
     1241            return -1;
     1242    }
     1243    return 0;
    14261244}   /*  End Function mksymlink  */
    14271245
    14281246
    1429 static int make_dir_tree (const char *path)
     1247static int make_dir_tree(const char *path)
    14301248/*  [SUMMARY] Creating intervening directories for a path as required.
    1431     <path> The full pathname (including the leaf node).
     1249    <path> The full pathname(including the leaf node).
    14321250    [RETURNS] TRUE on success, else FALSE.
    14331251*/
    14341252{
    1435     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1436 
    1437     if (bb_make_directory( dirname((char *)path), -1, FILEUTILS_RECUR )==-1)
    1438     {
    1439         debug_msg_logger(LOG_ERR, "%s: %s: %m",__FUNCTION__, path);
    1440         return (FALSE);
    1441     }
    1442     return(TRUE);
     1253    if (bb_make_directory(dirname((char *)path), -1, FILEUTILS_RECUR) == -1)
     1254        return FALSE;
     1255    return TRUE;
    14431256} /*  End Function make_dir_tree  */
    14441257
     
    14661279    char temp[STRING_LENGTH];
    14671280
    1468     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1469 
    1470     if ( !st_expr_expand (temp, STRING_LENGTH, input, get_variable_func, info) )
    1471         return (FALSE);
    1472     expand_regexp (output, outsize, temp, devname, ex, numexp);
    1473     return (TRUE);
     1281    if (!st_expr_expand(temp, STRING_LENGTH, input, get_variable_func, info))
     1282        return FALSE;
     1283    expand_regexp(output, outsize, temp, devname, ex, numexp);
     1284    return TRUE;
    14741285}   /*  End Function expand_expression  */
    14751286
    1476 static void expand_regexp (char *output, size_t outsize, const char *input,
     1287static void expand_regexp(char *output, size_t outsize, const char *input,
    14771288               const char *devname,
    1478                const regmatch_t *ex, unsigned int numex )
     1289               const regmatch_t *ex, unsigned int numex)
    14791290/*  [SUMMARY] Expand all occurrences of the regular subexpressions \0 to \9.
    14801291    <output> The output expanded expression is written here.
     
    14951306    int c = -1;
    14961307
    1497     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1498 
    14991308    /*  Guarantee NULL termination by writing an explicit '\0' character into
    15001309    the very last byte  */
     
    15041313    and '\0' .. '\9' with subexpressions 0 .. 9, if they exist. Other \x
    15051314    codes are deleted  */
    1506     while ( (c != '\0') && (outsize != 0) )
    1507     {
     1315    while ((c != '\0') && (outsize != 0)) {
    15081316        c = *input;
    15091317        ++input;
    1510         if (c == '\\')
    1511         {
     1318        if (c == '\\') {
    15121319            c = *input;
    15131320            ++input;
    1514             if (c != '\\')
    1515             {
    1516                 if ((c >= '0') && (c <= last_exp))
    1517                 {
     1321            if (c != '\\') {
     1322                if ((c >= '0') && (c <= last_exp)) {
    15181323                    const regmatch_t *subexp = ex + (c - '0');
    15191324                    unsigned int sublen = subexp->rm_eo - subexp->rm_so;
     
    15221327                    if (sublen > outsize)
    15231328                        sublen = outsize;
    1524                     strncpy (output, devname + subexp->rm_so, sublen);
     1329                    strncpy(output, devname + subexp->rm_so, sublen);
    15251330                    output += sublen;
    15261331                    outsize -= sublen;
     
    15401345struct translate_struct
    15411346{
    1542     char *match;    /*  The string to match to (up to length)                */
    1543     char *format;   /*  Format of output, "%s" takes data past match string,
    1544             NULL is effectively "%s" (just more efficient)       */
     1347    const char *match;    /*  The string to match to(up to length)                */
     1348    const char *format;   /*  Format of output, "%s" takes data past match string,
     1349            NULL is effectively "%s"(just more efficient)       */
    15451350};
    15461351
     
    15781383};
    15791384
    1580 const char *get_old_name (const char *devname, unsigned int namelen,
     1385const char *get_old_name(const char *devname, unsigned int namelen,
    15811386              char *buffer, unsigned int major, unsigned int minor)
    15821387/*  [SUMMARY] Translate a kernel-supplied name into an old name.
     
    15901395{
    15911396    const char *compat_name = NULL;
    1592     char *ptr;
     1397    const char *ptr;
    15931398    struct translate_struct *trans;
    15941399    unsigned int i;
     
    16161421    };
    16171422
    1618     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1619 
    1620     for (trans = translate_table; trans->match != NULL; ++trans)
    1621     {
    1622          len = strlen (trans->match);
    1623 
    1624         if (strncmp (devname, trans->match, len) == 0)
    1625         {
     1423    for (trans = translate_table; trans->match != NULL; ++trans) {
     1424         len = strlen(trans->match);
     1425
     1426        if (strncmp(devname, trans->match, len) == 0) {
    16261427            if (trans->format == NULL)
    1627                 return (devname + len);
    1628             sprintf (buffer, trans->format, devname + len);
    1629             return (buffer);
     1428                return devname + len;
     1429            sprintf(buffer, trans->format, devname + len);
     1430            return buffer;
    16301431        }
    16311432    }
    16321433
    1633     ptr = (strrchr (devname, '/') + 1);
     1434    ptr = bb_basename(devname);
    16341435    i = scan_dev_name(devname, namelen, ptr);
    16351436
    1636     if( i > 0 && i < 13)
     1437    if (i > 0 && i < 13)
    16371438        compat_name = buffer;
    16381439    else
    16391440        return NULL;
    16401441
    1641     debug_msg_logger(LOG_INFO, "%s: scan_dev_name = %d", __FUNCTION__, i);
    1642 
    16431442    /* 1 == scsi/generic, 3 == scsi/cd, 10 == sbp/ */
    1644     if( i == 1 || i == 3 || i == 10 )
    1645         sprintf (buffer, fmt[i], minor);
     1443    if (i == 1 || i == 3 || i == 10)
     1444        sprintf(buffer, fmt[i], minor);
    16461445
    16471446    /* 2 ==scsi/disc, 4 == scsi/part */
    1648     if( i == 2 || i == 4)
    1649         compat_name = write_old_sd_name (buffer, major, minor,((i == 2)?"":(ptr + 4)));
     1447    if (i == 2 || i == 4)
     1448        compat_name = write_old_sd_name(buffer, major, minor,((i == 2) ? "" : (ptr + 4)));
    16501449
    16511450    /* 5 == scsi/mt */
    1652     if( i == 5)
    1653     {
     1451    if (i == 5) {
    16541452        mode = ptr[2];
    16551453        if (mode == 'n')
    16561454            mode = '\0';
    1657         sprintf (buffer, fmt[i], minor & 0x1f, mode);
     1455        sprintf(buffer, fmt[i], minor & 0x1f, mode);
    16581456        if (devname[namelen - 1] != 'n')
    16591457            ++compat_name;
    16601458    }
    16611459    /* 6 == ide/host/disc, 7 == ide/host/cd, 8 == ide/host/part */
    1662     if( i == 6 || i == 7 || i == 8 )
     1460    if (i == 6 || i == 7 || i == 8)
    16631461        /* last arg should be ignored for i == 6 or i== 7 */
    1664         sprintf (buffer, fmt[i] , get_old_ide_name (major, minor), ptr + 4);
     1462        sprintf(buffer, fmt[i] , get_old_ide_name(major, minor), ptr + 4);
    16651463
    16661464    /* 9 ==  ide/host/mt */
    1667     if( i == 9 )
    1668         sprintf (buffer, fmt[i], ptr + 2, minor & 0x7f);
     1465    if (i == 9)
     1466        sprintf(buffer, fmt[i], ptr + 2, minor & 0x7f);
    16691467
    16701468    /*  11 == vcc/ */
    1671     if( i == 11 )
    1672     {
    1673         sprintf (buffer, fmt[i], devname + 4);
     1469    if (i == 11) {
     1470        sprintf(buffer, fmt[i], devname + 4);
    16741471        if (buffer[3] == '0')
    16751472            buffer[3] = '\0';
    16761473    }
    16771474    /* 12 ==  pty/ */
    1678     if( i == 12 )
    1679     {
     1475    if (i == 12) {
    16801476        pty1 = "pqrstuvwxyzabcde";
    16811477        pty2 = "0123456789abcdef";
    1682         indexx = atoi (devname + 5);
    1683         sprintf (buffer, fmt[i], (devname[4] == 'm') ? 'p' : 't', pty1[indexx >> 4], pty2[indexx & 0x0f]);
    1684     }
    1685 
    1686     if(ENABLE_DEBUG && compat_name!=NULL)
    1687         msg_logger(LOG_INFO, "%s: compat_name  %s", __FUNCTION__, compat_name);
    1688 
    1689     return (compat_name);
     1478        indexx = atoi(devname + 5);
     1479        sprintf(buffer, fmt[i], (devname[4] == 'm') ? 'p' : 't', pty1[indexx >> 4], pty2[indexx & 0x0f]);
     1480    }
     1481    return compat_name;
    16901482}   /*  End Function get_old_name  */
    16911483
    1692 static char get_old_ide_name (unsigned int major, unsigned int minor)
     1484static char get_old_ide_name(unsigned int major, unsigned int minor)
    16931485/*  [SUMMARY] Get the old IDE name for a device.
    16941486    <major> The major number for the device.
     
    16971489*/
    16981490{
    1699     char letter='y';    /* 121 */
    1700     char c='a';     /*  97 */
    1701     int i=IDE0_MAJOR;
    1702 
    1703     debug_msg_logger(LOG_INFO, __FUNCTION__);
     1491    char letter = 'y';  /* 121 */
     1492    char c = 'a';       /*  97 */
     1493    int i = IDE0_MAJOR;
    17041494
    17051495    /* I hope it works like the previous code as it saves a few bytes. Tito ;P */
    17061496    do {
    1707         if( i==IDE0_MAJOR || i==IDE1_MAJOR || i==IDE2_MAJOR ||
    1708             i==IDE3_MAJOR || i==IDE4_MAJOR || i==IDE5_MAJOR ||
    1709             i==IDE6_MAJOR || i==IDE7_MAJOR || i==IDE8_MAJOR ||
    1710             i==IDE9_MAJOR )
    1711         {
    1712             if((unsigned int)i==major)
    1713             {
    1714                 letter=c;
     1497        if (i == IDE0_MAJOR || i == IDE1_MAJOR || i == IDE2_MAJOR
     1498         || i == IDE3_MAJOR || i == IDE4_MAJOR || i == IDE5_MAJOR
     1499         || i == IDE6_MAJOR || i == IDE7_MAJOR || i == IDE8_MAJOR
     1500         || i == IDE9_MAJOR
     1501        ) {
     1502            if ((unsigned int)i == major) {
     1503                letter = c;
    17151504                break;
    17161505            }
    1717             c+=2;
     1506            c += 2;
    17181507        }
    17191508        i++;
    1720     } while(i<=IDE9_MAJOR);
     1509    } while (i <= IDE9_MAJOR);
    17211510
    17221511    if (minor > 63)
    17231512        ++letter;
    1724     return (letter);
     1513    return letter;
    17251514}   /*  End Function get_old_ide_name  */
    17261515
    1727 static char *write_old_sd_name (char *buffer,
     1516static char *write_old_sd_name(char *buffer,
    17281517                unsigned int major, unsigned int minor,
    1729                 char *part)
     1518                const char *part)
    17301519/*  [SUMMARY] Write the old SCSI disc name to a buffer.
    17311520    <buffer> The buffer to write to.
     
    17381527    unsigned int disc_index;
    17391528
    1740     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1741 
    1742     if (major == 8)
    1743     {
    1744         sprintf (buffer, "sd%c%s", 'a' + (minor >> 4), part);
    1745         return (buffer);
    1746     }
    1747     if ( (major > 64) && (major < 72) )
    1748     {
    1749         disc_index = ( (major - 64) << 4 ) + (minor >> 4);
     1529    if (major == 8) {
     1530        sprintf(buffer, "sd%c%s", 'a' + (minor >> 4), part);
     1531        return buffer;
     1532    }
     1533    if ((major > 64) && (major < 72)) {
     1534        disc_index = ((major - 64) << 4) +(minor >> 4);
    17501535        if (disc_index < 26)
    1751             sprintf (buffer, "sd%c%s", 'a' + disc_index, part);
     1536            sprintf(buffer, "sd%c%s", 'a' + disc_index, part);
    17521537        else
    1753             sprintf (buffer, "sd%c%c%s", 'a' + (disc_index / 26) - 1, 'a' + disc_index % 26,part);
    1754         return (buffer);
    1755     }
    1756     return (NULL);
     1538            sprintf(buffer, "sd%c%c%s", 'a' +(disc_index / 26) - 1, 'a' + disc_index % 26, part);
     1539        return buffer;
     1540    }
     1541    return NULL;
    17571542}   /*  End Function write_old_sd_name  */
    17581543
     
    17621547/*EXPERIMENTAL_FUNCTION*/
    17631548
    1764 int st_expr_expand (char *output, unsigned int length, const char *input,
    1765              const char *(*get_variable_func) (const char *variable,
     1549int st_expr_expand(char *output, unsigned int length, const char *input,
     1550             const char *(*get_variable_func)(const char *variable,
    17661551                          void *info),
    17671552             void *info)
     
    17851570    char buffer[BUFFER_SIZE], tmp[STRING_LENGTH];
    17861571
    1787     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1788 
    17891572    if (length > BUFFER_SIZE)
    17901573        length = BUFFER_SIZE;
    1791     for (; TRUE; ++input)
    1792     {
    1793         switch (ch = *input)
    1794         {
     1574    for (; TRUE; ++input) {
     1575        switch (ch = *input) {
    17951576            case '$':
    17961577                /*  Variable expansion  */
    1797                 input = expand_variable (buffer, length, &out_pos, ++input, get_variable_func, info);
     1578                input = expand_variable(buffer, length, &out_pos, ++input, get_variable_func, info);
    17981579                if (input == NULL)
    1799                     return (FALSE);
     1580                    return FALSE;
    18001581                break;
    18011582            case '~':
    18021583                /*  Home directory expansion  */
    18031584                ch = input[1];
    1804                 if ( isspace (ch) || (ch == '/') || (ch == '\0') )
    1805                 {
     1585                if (isspace(ch) ||(ch == '/') ||(ch == '\0')) {
    18061586                    /* User's own home directory: leave separator for next time */
    1807                     if ( ( env = getenv ("HOME") ) == NULL )
    1808                     {
    1809                         msg_logger(LOG_INFO, bb_msg_variable_not_found, "HOME");
    1810                         return (FALSE);
     1587                    if ((env = getenv("HOME")) == NULL) {
     1588                        info_logger(LOG_INFO, bb_msg_variable_not_found, "HOME");
     1589                        return FALSE;
    18111590                    }
    1812                     len = strlen (env);
     1591                    len = strlen(env);
    18131592                    if (len + out_pos >= length)
    18141593                        goto st_expr_expand_out;
    1815                     memcpy (buffer + out_pos, env, len + 1);
     1594                    memcpy(buffer + out_pos, env, len + 1);
    18161595                    out_pos += len;
    18171596                    continue;
    18181597                }
    18191598                /*  Someone else's home directory  */
    1820                 for (ptr = ++input; !isspace (ch) && (ch != '/') && (ch != '\0'); ch = *++ptr)
    1821                     /* VOID */ ;
     1599                for (ptr = ++input; !isspace(ch) && (ch != '/') && (ch != '\0'); ch = *++ptr)
     1600                    /* VOID */;
    18221601                len = ptr - input;
    18231602                if (len >= sizeof tmp)
    18241603                    goto st_expr_expand_out;
    1825                 safe_memcpy (tmp, input, len);
     1604                safe_memcpy(tmp, input, len);
    18261605                input = ptr - 1;
    1827                 if ( ( pwent = getpwnam (tmp) ) == NULL )
    1828                 {
    1829                     msg_logger(LOG_INFO, "no pwent for: %s", tmp);
    1830                     return (FALSE);
     1606                if ((pwent = getpwnam(tmp)) == NULL) {
     1607                    info_logger(LOG_INFO, "no pwent for: %s", tmp);
     1608                    return FALSE;
    18311609                }
    1832                 len = strlen (pwent->pw_dir);
     1610                len = strlen(pwent->pw_dir);
    18331611                if (len + out_pos >= length)
    18341612                    goto st_expr_expand_out;
    1835                 memcpy (buffer + out_pos, pwent->pw_dir, len + 1);
     1613                memcpy(buffer + out_pos, pwent->pw_dir, len + 1);
    18361614                out_pos += len;
    18371615                break;
     
    18421620                    goto st_expr_expand_out;
    18431621                buffer[out_pos++] = ch;
    1844                 if (ch == '\0')
    1845                 {
    1846                     memcpy (output, buffer, out_pos);
    1847                     return (TRUE);
     1622                if (ch == '\0') {
     1623                    memcpy(output, buffer, out_pos);
     1624                    return TRUE;
    18481625                }
    18491626                break;
     
    18511628        }
    18521629    }
    1853     return (FALSE);
     1630    return FALSE;
    18541631st_expr_expand_out:
    1855     msg_logger(LOG_INFO, bb_msg_small_buffer);
    1856     return (FALSE);
     1632    info_logger(LOG_INFO, bb_msg_small_buffer);
     1633    return FALSE;
    18571634}   /*  End Function st_expr_expand  */
    18581635
     
    18601637/*  Private functions follow  */
    18611638
    1862 static const char *expand_variable (char *buffer, unsigned int length,
     1639static const char *expand_variable(char *buffer, unsigned int length,
    18631640                    unsigned int *out_pos, const char *input,
    1864                     const char *(*func) (const char *variable,
     1641                    const char *(*func)(const char *variable,
    18651642                             void *info),
    18661643                    void *info)
     
    18841661    char tmp[STRING_LENGTH];
    18851662
    1886     debug_msg_logger(LOG_INFO, __FUNCTION__);
    1887 
    18881663    ch = input[0];
    1889     if (ch == '$')
    1890     {
     1664    if (ch == '$') {
    18911665        /*  Special case for "$$": PID  */
    1892         sprintf ( tmp, "%d", (int) getpid () );
    1893         len = strlen (tmp);
     1666        sprintf(tmp, "%d",(int) getpid());
     1667        len = strlen(tmp);
    18941668        if (len + *out_pos >= length)
    18951669            goto expand_variable_out;
    18961670
    1897         memcpy (buffer + *out_pos, tmp, len + 1);
     1671        memcpy(buffer + *out_pos, tmp, len + 1);
    18981672        out_pos += len;
    1899         return (input);
     1673        return input;
    19001674    }
    19011675    /*  Ordinary variable expansion, possibly in braces  */
    1902     if (ch != '{')
    1903     {
     1676    if (ch != '{') {
    19041677        /*  Simple variable expansion  */
    1905         for (ptr = input; isalnum (ch) || (ch == '_') || (ch == ':');ch = *++ptr)
    1906             /* VOID */ ;
     1678        for (ptr = input; isalnum(ch) || (ch == '_') || (ch == ':'); ch = *++ptr)
     1679            /* VOID */;
    19071680        len = ptr - input;
    19081681        if ((size_t)len >= sizeof tmp)
    19091682            goto expand_variable_out;
    19101683
    1911         safe_memcpy (tmp, input, len);
     1684        safe_memcpy(tmp, input, len);
    19121685        input = ptr - 1;
    1913         if ( ( env = get_variable_v2 (tmp, func, info) ) == NULL )
    1914         {
    1915             msg_logger(LOG_INFO, bb_msg_variable_not_found, tmp);
    1916             return (NULL);
     1686        if ((env = get_variable_v2(tmp, func, info)) == NULL) {
     1687            info_logger(LOG_INFO, bb_msg_variable_not_found, tmp);
     1688            return NULL;
    19171689        }
    1918         len = strlen (env);
     1690        len = strlen(env);
    19191691        if (len + *out_pos >= length)
    19201692            goto expand_variable_out;
    19211693
    1922         memcpy (buffer + *out_pos, env, len + 1);
     1694        memcpy(buffer + *out_pos, env, len + 1);
    19231695        *out_pos += len;
    1924         return (input);
     1696        return input;
    19251697    }
    19261698    /*  Variable in braces: check for ':' tricks  */
    19271699    ch = *++input;
    1928     for (ptr = input; isalnum (ch) || (ch == '_'); ch = *++ptr)
     1700    for (ptr = input; isalnum(ch) || (ch == '_'); ch = *++ptr)
    19291701        /* VOID */;
    1930     if (ch == '}')
    1931     {
     1702    if (ch == '}') {
    19321703        /*  Must be simple variable expansion with "${var}"  */
    19331704        len = ptr - input;
     
    19351706            goto expand_variable_out;
    19361707
    1937         safe_memcpy (tmp, input, len);
    1938         ptr = expand_variable (buffer, length, out_pos, tmp, func, info );
     1708        safe_memcpy(tmp, input, len);
     1709        ptr = expand_variable(buffer, length, out_pos, tmp, func, info);
    19391710        if (ptr == NULL)
    1940             return (NULL);
    1941         return (input + len);
    1942     }
    1943     if (ch != ':' || ptr[1] != '-' )
    1944     {
    1945         msg_logger(LOG_INFO, "illegal char in var name");
    1946         return (NULL);
     1711            return NULL;
     1712        return input + len;
     1713    }
     1714    if (ch != ':' || ptr[1] != '-') {
     1715        info_logger(LOG_INFO, "illegal char in var name");
     1716        return NULL;
    19471717    }
    19481718    /*  It's that handy "${var:-word}" expression. Check if var is defined  */
     
    19511721        goto expand_variable_out;
    19521722
    1953     safe_memcpy (tmp, input, len);
     1723    safe_memcpy(tmp, input, len);
    19541724    /*  Move input pointer to ':'  */
    19551725    input = ptr;
     
    19571727    ptr += 2;
    19581728    ch = ptr[0];
    1959     for (open_braces = 1; open_braces > 0; ch = *++ptr)
    1960     {
    1961         switch (ch)
    1962         {
     1729    for (open_braces = 1; open_braces > 0; ch = *++ptr) {
     1730        switch (ch) {
    19631731            case '{':
    19641732                ++open_braces;
     
    19681736                break;
    19691737            case '\0':
    1970                 msg_logger(LOG_INFO,"\"}\" not found in: %s", input);
    1971                 return (NULL);
     1738                info_logger(LOG_INFO,"\"}\" not found in: %s", input);
     1739                return NULL;
    19721740            default:
    19731741                break;
     
    19761744    --ptr;
    19771745    /*  At this point ptr should point to closing brace of "${var:-word}"  */
    1978     if ( ( env = get_variable_v2 (tmp, func, info) ) != NULL )
    1979     {
     1746    if ((env = get_variable_v2(tmp, func, info)) != NULL) {
    19801747        /*  Found environment variable, so skip the input to the closing brace
    19811748            and return the variable  */
    19821749        input = ptr;
    1983         len = strlen (env);
     1750        len = strlen(env);
    19841751        if (len + *out_pos >= length)
    19851752            goto expand_variable_out;
    19861753
    1987         memcpy (buffer + *out_pos, env, len + 1);
     1754        memcpy(buffer + *out_pos, env, len + 1);
    19881755        *out_pos += len;
    1989         return (input);
     1756        return input;
    19901757    }
    19911758    /*  Environment variable was not found, so process word. Advance input
     
    19961763        goto expand_variable_out;
    19971764
    1998     safe_memcpy (tmp, input, len);
     1765    safe_memcpy(tmp, input, len);
    19991766    input = ptr;
    2000     if ( !st_expr_expand (tmp, STRING_LENGTH, tmp, func, info ) )
    2001         return (NULL);
    2002     len = strlen (tmp);
     1767    if (!st_expr_expand(tmp, STRING_LENGTH, tmp, func, info))
     1768        return NULL;
     1769    len = strlen(tmp);
    20031770    if (len + *out_pos >= length)
    20041771        goto expand_variable_out;
    20051772
    2006     memcpy (buffer + *out_pos, tmp, len + 1);
     1773    memcpy(buffer + *out_pos, tmp, len + 1);
    20071774    *out_pos += len;
    2008     return (input);
     1775    return input;
    20091776expand_variable_out:
    2010     msg_logger(LOG_INFO, bb_msg_small_buffer);
    2011     return (NULL);
     1777    info_logger(LOG_INFO, bb_msg_small_buffer);
     1778    return NULL;
    20121779}   /*  End Function expand_variable  */
    20131780
    20141781
    2015 static const char *get_variable_v2 (const char *variable,
    2016                   const char *(*func) (const char *variable, void *info),
     1782static const char *get_variable_v2(const char *variable,
     1783                  const char *(*func)(const char *variable, void *info),
    20171784                 void *info)
    20181785/*  [SUMMARY] Get a variable from the environment or .
     
    20261793    const char *value;
    20271794
    2028     debug_msg_logger(LOG_INFO, __FUNCTION__);
    2029 
    2030     if (func != NULL)
    2031     {
    2032         value = (*func) (variable, info);
     1795    if (func != NULL) {
     1796        value = (*func)(variable, info);
    20331797        if (value != NULL)
    2034             return (value);
    2035     }
    2036     return getenv (variable);
     1798            return value;
     1799    }
     1800    return getenv(variable);
    20371801}   /*  End Function get_variable  */
    20381802
  • branches/2.2.5/mindi-busybox/miscutils/eject.c

    r821 r1765  
    1414 */
    1515
    16 #include "busybox.h"
    17 #include <fcntl.h>
    18 #include <sys/ioctl.h>
    19 #include <unistd.h>
    20 #include <mntent.h>
     16#include "libbb.h"
    2117
    2218/* various defines swiped from linux/cdrom.h */
    2319#define CDROMCLOSETRAY            0x5319  /* pendant of CDROMEJECT  */
    2420#define CDROMEJECT                0x5309  /* Ejects the cdrom media */
    25 #define DEFAULT_CDROM             "/dev/cdrom"
     21#define CDROM_DRIVE_STATUS        0x5326  /* Get tray position, etc. */
     22/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
     23#define CDS_TRAY_OPEN        2
    2624
     25#define FLAG_CLOSE  1
     26#define FLAG_SMART  2
     27
     28int eject_main(int argc, char **argv);
    2729int eject_main(int argc, char **argv)
    2830{
    2931    unsigned long flags;
    30     char *device;
    31     struct mntent *m;
     32    const char *device;
     33    int dev, cmd;
    3234
    33     flags = bb_getopt_ulflags(argc, argv, "t");
    34     device = argv[optind] ? : DEFAULT_CDROM;
     35    opt_complementary = "?1:t--T:T--t";
     36    flags = getopt32(argv, "tT");
     37    device = argv[optind] ? : "/dev/cdrom";
    3538
    36     if ((m = find_mount_point(device, bb_path_mtab_file))) {
    37         if (umount(m->mnt_dir)) {
    38             bb_error_msg_and_die("Can't umount");
    39         } else if (ENABLE_FEATURE_MTAB_SUPPORT) {
    40             erase_mtab(m->mnt_fsname);
    41         }
    42     }
    43     if (ioctl(bb_xopen(device, (O_RDONLY | O_NONBLOCK)),
    44                 (flags ? CDROMCLOSETRAY : CDROMEJECT))) {
    45         bb_perror_msg_and_die("%s", device);
    46     }
    47     return (EXIT_SUCCESS);
     39    // We used to do "umount <device>" here, but it was buggy
     40    // if something was mounted OVER cdrom and
     41    // if cdrom is mounted many times.
     42    //
     43    // This works equally well (or better):
     44    // #!/bin/sh
     45    // umount /dev/cdrom
     46    // eject
     47
     48    dev = xopen(device, O_RDONLY|O_NONBLOCK);
     49    cmd = CDROMEJECT;
     50    if (flags & FLAG_CLOSE
     51     || (flags & FLAG_SMART && ioctl(dev, CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN))
     52        cmd = CDROMCLOSETRAY;
     53
     54    ioctl_or_perror_and_die(dev, cmd, NULL, "%s", device);
     55
     56    if (ENABLE_FEATURE_CLEAN_UP)
     57        close(dev);
     58
     59    return EXIT_SUCCESS;
    4860}
  • branches/2.2.5/mindi-busybox/miscutils/hdparm.c

    r902 r1765  
    1313 */
    1414
    15 #include "busybox.h"
    16 #include <string.h>
    17 #include <fcntl.h>
    18 #include <errno.h>
    19 #include <ctype.h>
    20 #include <sys/ioctl.h>
    21 #include <sys/sysmacros.h>
    22 #include <sys/times.h>
    23 #include <sys/mman.h>
    24 #include <linux/types.h>
     15#include "libbb.h"
    2516#include <linux/hdreg.h>
    26 
    27 #if BB_BIG_ENDIAN && !defined(__USE_XOPEN)
    28 # define __USE_XOPEN
    29 #endif
    30 #include <unistd.h>
    3117
    3218/* device types */
     
    5440#define START_MODEL     27  /* ASCII model number */
    5541#define LENGTH_MODEL        20  /* 20 words (40 bytes or characters) */
    56 #define SECTOR_XFER_MAX         47  /* r/w multiple: max sectors xfered */
     42#define SECTOR_XFER_MAX     47  /* r/w multiple: max sectors xfered */
    5743#define DWORD_IO        48  /* can do double-word IO (ATA-1 only) */
    5844#define CAPAB_0         49  /* capabilities */
     
    6349#define LCYLS_CUR       54  /* current logical cylinders */
    6450#define LHEADS_CUR      55  /* current logical heads */
    65 #define LSECTS_CUR          56  /* current logical sectors/track */
     51#define LSECTS_CUR      56  /* current logical sectors/track */
    6652#define CAPACITY_LSB        57  /* current capacity in sectors */
    6753#define CAPACITY_MSB        58
     
    142128#define CDROM 0x0005
    143129
    144 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
    145 static const char * const pkt_str[] = {
     130#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
     131static const char *const pkt_str[] = {
    146132    "Direct-access device",         /* word 0, bits 12-8 = 00 */
    147133    "Sequential-access device",     /* word 0, bits 12-8 = 01 */
     
    178164};
    179165
    180 static const char * const ata1_cfg_str[] = {            /* word 0 in ATA-1 mode */
     166static const char *const ata1_cfg_str[] = {         /* word 0 in ATA-1 mode */
    181167    "Reserved",             /* bit 0 */
    182168    "hard sectored",            /* bit 1 */
     
    215201
    216202/* word 49: capabilities 0 */
    217 #define STD_STBY        0x2000  /* 1=standard values supported (ATA);
    218                        0=vendor specific values */
     203#define STD_STBY        0x2000  /* 1=standard values supported (ATA); 0=vendor specific values */
    219204#define IORDY_SUP       0x0800  /* 1=support; 0=may be supported */
    220205#define IORDY_OFF       0x0400  /* 1=may be disabled */
     
    254239/* word 81: minor version number */
    255240#define MINOR_MAX       0x22
    256 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
    257 static const char *minor_str[MINOR_MAX+2] = {           /* word 81 value: */
    258     "Unspecified",                  /* 0x0000   */
    259     "ATA-1 X3T9.2 781D prior to rev.4", /* 0x0001   */
    260     "ATA-1 published, ANSI X3.221-1994",        /* 0x0002   */
    261     "ATA-1 X3T9.2 781D rev.4",          /* 0x0003   */
    262     "ATA-2 published, ANSI X3.279-1996",        /* 0x0004   */
    263     "ATA-2 X3T10 948D prior to rev.2k", /* 0x0005   */
    264     "ATA-3 X3T10 2008D rev.1",          /* 0x0006   */
    265     "ATA-2 X3T10 948D rev.2k",          /* 0x0007   */
    266     "ATA-3 X3T10 2008D rev.0",          /* 0x0008   */
    267     "ATA-2 X3T10 948D rev.3",           /* 0x0009   */
    268     "ATA-3 published, ANSI X3.298-199x",        /* 0x000a   */
    269     "ATA-3 X3T10 2008D rev.6",          /* 0x000b   */
    270     "ATA-3 X3T13 2008D rev.7 and 7a",       /* 0x000c   */
    271     "ATA/ATAPI-4 X3T13 1153D rev.6",        /* 0x000d   */
    272     "ATA/ATAPI-4 T13 1153D rev.13",     /* 0x000e   */
    273     "ATA/ATAPI-4 X3T13 1153D rev.7",        /* 0x000f   */
    274     "ATA/ATAPI-4 T13 1153D rev.18",     /* 0x0010   */
    275     "ATA/ATAPI-4 T13 1153D rev.15",     /* 0x0011   */
    276     "ATA/ATAPI-4 published, ANSI INCITS 317-1998",  /* 0x0012   */
    277     "ATA/ATAPI-5 T13 1321D rev.3",
    278     "ATA/ATAPI-4 T13 1153D rev.14",     /* 0x0014   */
    279     "ATA/ATAPI-5 T13 1321D rev.1",      /* 0x0015   */
    280     "ATA/ATAPI-5 published, ANSI INCITS 340-2000",  /* 0x0016   */
    281     "ATA/ATAPI-4 T13 1153D rev.17",     /* 0x0017   */
    282     "ATA/ATAPI-6 T13 1410D rev.0",      /* 0x0018   */
    283     "ATA/ATAPI-6 T13 1410D rev.3a",     /* 0x0019   */
    284     "ATA/ATAPI-7 T13 1532D rev.1",      /* 0x001a   */
    285     "ATA/ATAPI-6 T13 1410D rev.2",      /* 0x001b   */
    286     "ATA/ATAPI-6 T13 1410D rev.1",      /* 0x001c   */
    287     "ATA/ATAPI-7 published, ANSI INCITS 397-2005",  /* 0x001d   */
    288     "ATA/ATAPI-7 T13 1532D rev.0",      /* 0x001e   */
    289     "Reserved"                  /* 0x001f   */
    290     "Reserved"                  /* 0x0020   */
    291     "ATA/ATAPI-7 T13 1532D rev.4a",     /* 0x0021   */
    292     "ATA/ATAPI-6 published, ANSI INCITS 361-2002",  /* 0x0022   */
    293     "Reserved"                  /* 0x0023-0xfffe*/
     241#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
     242static const char *const minor_str[MINOR_MAX + 2] = {
     243    /* word 81 value: */
     244    "Unspecified",                                  /* 0x0000 */
     245    "ATA-1 X3T9.2 781D prior to rev.4",             /* 0x0001 */
     246    "ATA-1 published, ANSI X3.221-1994",            /* 0x0002 */
     247    "ATA-1 X3T9.2 781D rev.4",                      /* 0x0003 */
     248    "ATA-2 published, ANSI X3.279-1996",            /* 0x0004 */
     249    "ATA-2 X3T10 948D prior to rev.2k",             /* 0x0005 */
     250    "ATA-3 X3T10 2008D rev.1",                      /* 0x0006 */
     251    "ATA-2 X3T10 948D rev.2k",                      /* 0x0007 */
     252    "ATA-3 X3T10 2008D rev.0",                      /* 0x0008 */
     253    "ATA-2 X3T10 948D rev.3",                       /* 0x0009 */
     254    "ATA-3 published, ANSI X3.298-199x",            /* 0x000a */
     255    "ATA-3 X3T10 2008D rev.6",                      /* 0x000b */
     256    "ATA-3 X3T13 2008D rev.7 and 7a",               /* 0x000c */
     257    "ATA/ATAPI-4 X3T13 1153D rev.6",                /* 0x000d */
     258    "ATA/ATAPI-4 T13 1153D rev.13",                 /* 0x000e */
     259    "ATA/ATAPI-4 X3T13 1153D rev.7",                /* 0x000f */
     260    "ATA/ATAPI-4 T13 1153D rev.18",                 /* 0x0010 */
     261    "ATA/ATAPI-4 T13 1153D rev.15",                 /* 0x0011 */
     262    "ATA/ATAPI-4 published, ANSI INCITS 317-1998",  /* 0x0012 */
     263    "ATA/ATAPI-5 T13 1321D rev.3",                  /* 0x0013 */
     264    "ATA/ATAPI-4 T13 1153D rev.14",                 /* 0x0014 */
     265    "ATA/ATAPI-5 T13 1321D rev.1",                  /* 0x0015 */
     266    "ATA/ATAPI-5 published, ANSI INCITS 340-2000",  /* 0x0016 */
     267    "ATA/ATAPI-4 T13 1153D rev.17",                 /* 0x0017 */
     268    "ATA/ATAPI-6 T13 1410D rev.0",                  /* 0x0018 */
     269    "ATA/ATAPI-6 T13 1410D rev.3a",                 /* 0x0019 */
     270    "ATA/ATAPI-7 T13 1532D rev.1",                  /* 0x001a */
     271    "ATA/ATAPI-6 T13 1410D rev.2",                  /* 0x001b */
     272    "ATA/ATAPI-6 T13 1410D rev.1",                  /* 0x001c */
     273    "ATA/ATAPI-7 published, ANSI INCITS 397-2005",  /* 0x001d */
     274    "ATA/ATAPI-7 T13 1532D rev.0",                  /* 0x001e */
     275    "Reserved"                                      /* 0x001f */
     276    "Reserved"                                      /* 0x0020 */
     277    "ATA/ATAPI-7 T13 1532D rev.4a",                 /* 0x0021 */
     278    "ATA/ATAPI-6 published, ANSI INCITS 361-2002",  /* 0x0022 */
     279    "Reserved"                                      /* 0x0023-0xfffe */
    294280};
    295281#endif
    296 static const char actual_ver[MINOR_MAX+2] = {
    297             /* word 81 value: */
    298     0,      /* 0x0000   WARNING:    */
    299     1,      /* 0x0001   WARNING:    */
    300     1,      /* 0x0002   WARNING:    */
    301     1,      /* 0x0003   WARNING:    */
    302     2,      /* 0x0004   WARNING:   This array       */
    303     2,      /* 0x0005   WARNING:   corresponds      */
    304     3,      /* 0x0006   WARNING:   *exactly*        */
    305     2,      /* 0x0007   WARNING:   to the ATA/      */
    306     3,      /* 0x0008   WARNING:   ATAPI version    */
    307     2,      /* 0x0009   WARNING:   listed in        */
    308     3,      /* 0x000a   WARNING:   the          */
    309     3,      /* 0x000b   WARNING:   minor_str        */
    310     3,      /* 0x000c   WARNING:   array        */
    311     4,      /* 0x000d   WARNING:   above.       */
    312     4,      /* 0x000e   WARNING:            */
    313     4,      /* 0x000f   WARNING:   if you change    */
    314     4,      /* 0x0010   WARNING:   that one,        */
    315     4,      /* 0x0011   WARNING:   change this one  */
    316     4,      /* 0x0012   WARNING:   too!!!       */
    317     5,      /* 0x0013   WARNING:    */
    318     4,      /* 0x0014   WARNING:    */
    319     5,      /* 0x0015   WARNING:    */
    320     5,      /* 0x0016   WARNING:    */
    321     4,      /* 0x0017   WARNING:    */
    322     6,      /* 0x0018   WARNING:    */
    323     6,      /* 0x0019   WARNING:    */
    324     7,      /* 0x001a   WARNING:    */
    325     6,      /* 0x001b   WARNING:    */
    326     6,      /* 0x001c   WARNING:    */
    327     7,      /* 0x001d   WARNING:    */
    328     7,      /* 0x001e   WARNING:    */
    329     0,      /* 0x001f   WARNING:    */
    330     0,      /* 0x0020   WARNING:    */
    331     7,      /* 0x0021   WARNING:    */
    332     6,      /* 0x0022   WARNING:    */
    333     0       /* 0x0023-0xfffe        */
     282static const char actual_ver[MINOR_MAX + 2] ALIGN1 = {
     283       /* word 81 value: */
     284    0, /* 0x0000 WARNING: actual_ver[] array */
     285    1, /* 0x0001 WARNING: corresponds        */
     286    1, /* 0x0002 WARNING: *exactly*          */
     287    1, /* 0x0003 WARNING: to the ATA/        */
     288    2, /* 0x0004 WARNING: ATAPI version      */
     289    2, /* 0x0005 WARNING: listed in          */
     290    3, /* 0x0006 WARNING: the                */
     291    2, /* 0x0007 WARNING: minor_str          */
     292    3, /* 0x0008 WARNING: array              */
     293    2, /* 0x0009 WARNING: above.             */
     294    3, /* 0x000a WARNING:                    */
     295    3, /* 0x000b WARNING: If you change      */
     296    3, /* 0x000c WARNING: that one,          */
     297    4, /* 0x000d WARNING: change this one    */
     298    4, /* 0x000e WARNING: too!!!             */
     299    4, /* 0x000f */
     300    4, /* 0x0010 */
     301    4, /* 0x0011 */
     302    4, /* 0x0012 */
     303    5, /* 0x0013 */
     304    4, /* 0x0014 */
     305    5, /* 0x0015 */
     306    5, /* 0x0016 */
     307    4, /* 0x0017 */
     308    6, /* 0x0018 */
     309    6, /* 0x0019 */
     310    7, /* 0x001a */
     311    6, /* 0x001b */
     312    6, /* 0x001c */
     313    7, /* 0x001d */
     314    7, /* 0x001e */
     315    0, /* 0x001f */
     316    0, /* 0x0020 */
     317    7, /* 0x0021 */
     318    6, /* 0x0022 */
     319    0  /* 0x0023-0xfffe */
    334320};
    335321
     
    341327#define NUM_CMD_FEAT_STR    48
    342328
    343 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
    344 static const char * const cmd_feat_str[] = {
     329#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
     330static const char *const cmd_feat_str[] = {
    345331    "",                 /* word 82 bit 15: obsolete  */
    346332    "NOP cmd",              /* word 82 bit 14 */
     
    359345    "Security Mode feature set",        /* word 82 bit  1 */
    360346    "SMART feature set",            /* word 82 bit  0 */
    361                         /* --------------*/
     347                        /* -------------- */
    362348    "",                 /* word 83 bit 15: !valid bit */
    363349    "",                 /* word 83 bit 14:  valid bit */
    364     "FLUSH CACHE EXT cmd",      /* word 83 bit 13 */
    365     "Mandatory FLUSH CACHE cmd ",   /* word 83 bit 12 */
     350    "FLUSH CACHE EXT cmd",          /* word 83 bit 13 */
     351    "Mandatory FLUSH CACHE cmd ",       /* word 83 bit 12 */
    366352    "Device Configuration Overlay feature set ",
    367353    "48-bit Address feature set ",      /* word 83 bit 10 */
     
    372358    "Power-Up In Standby feature set",  /* word 83 bit  5 */
    373359    "Removable Media Status Notification feature set",
    374     "Adv. Power Management feature set",/* word 83 bit  3 */
     360    "Adv. Power Management feature set",    /* word 83 bit  3 */
    375361    "CFA feature set",          /* word 83 bit  2 */
    376362    "READ/WRITE DMA QUEUED",        /* word 83 bit  1 */
    377363    "DOWNLOAD MICROCODE cmd",       /* word 83 bit  0 */
    378                         /* --------------*/
     364                        /* -------------- */
    379365    "",                 /* word 84 bit 15: !valid bit */
    380366    "",                 /* word 84 bit 14:  valid bit */
     
    408394
    409395/* words 89, 90, SECU ERASE TIME */
    410 #define ERASE_BITS      0x00ff
     396#define ERASE_BITS      0x00ff
    411397
    412398/* word 92: master password revision */
     
    414400
    415401/* word 93: hw reset result */
    416 #define CBLID           0x2000  /* CBLID status */
    417 #define RST0            0x0001  /* 1=reset to device #0 */
    418 #define DEV_DET         0x0006  /* how device num determined */
    419 #define JUMPER_VAL      0x0002  /* device num determined by jumper */
    420 #define CSEL_VAL        0x0004  /* device num determined by CSEL_VAL */
     402#define CBLID           0x2000  /* CBLID status */
     403#define RST0            0x0001  /* 1=reset to device #0 */
     404#define DEV_DET         0x0006  /* how device num determined */
     405#define JUMPER_VAL      0x0002  /* device num determined by jumper */
     406#define CSEL_VAL        0x0004  /* device num determined by CSEL_VAL */
    421407
    422408/* word 127: removable media status notification feature set support */
    423 #define RM_STAT_BITS        0x0003
    424 #define RM_STAT_SUP     0x0001
     409#define RM_STAT_BITS    0x0003
     410#define RM_STAT_SUP     0x0001
    425411
    426412/* word 128: security */
    427 #define SECU_ENABLED    0x0002
    428 #define SECU_LEVEL      0x0010
    429 #define NUM_SECU_STR    6
    430 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
    431 static const char * const secu_str[] = {
     413#define SECU_ENABLED    0x0002
     414#define SECU_LEVEL      0x0010
     415#define NUM_SECU_STR    6
     416#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
     417static const char *const secu_str[] = {
    432418    "supported",            /* word 128, bit 0 */
    433419    "enabled",          /* word 128, bit 1 */
     
    440426
    441427/* word 160: CFA power mode */
    442 #define VALID_W160      0x8000  /* 1=word valid */
    443 #define PWR_MODE_REQ        0x2000  /* 1=CFA power mode req'd by some cmds*/
    444 #define PWR_MODE_OFF        0x1000  /* 1=CFA power moded disabled */
    445 #define MAX_AMPS        0x0fff  /* value = max current in ma */
     428#define VALID_W160              0x8000  /* 1=word valid */
     429#define PWR_MODE_REQ            0x2000  /* 1=CFA power mode req'd by some cmds*/
     430#define PWR_MODE_OFF            0x1000  /* 1=CFA power moded disabled */
     431#define MAX_AMPS                0x0fff  /* value = max current in ma */
    446432
    447433/* word 255: integrity */
    448 #define SIG         0x00ff  /* signature location */
    449 #define SIG_VAL         0x00A5  /* signature value */
    450 
    451 #define TIMING_MB       64
    452 #define TIMING_BUF_MB       1
    453 #define TIMING_BUF_BYTES    (TIMING_BUF_MB * 1024 * 1024)
    454 #define TIMING_BUF_COUNT    (timing_MB / TIMING_BUF_MB)
    455 #define BUFCACHE_FACTOR     2
    456 
    457 #undef DO_FLUSHCACHE        /* under construction: force cache flush on -W0 */
     434#define SIG                     0x00ff  /* signature location */
     435#define SIG_VAL                 0x00a5  /* signature value */
     436
     437#define TIMING_MB               64
     438#define TIMING_BUF_MB           1
     439#define TIMING_BUF_BYTES        (TIMING_BUF_MB * 1024 * 1024)
     440#define BUFCACHE_FACTOR         2
     441
     442#undef DO_FLUSHCACHE            /* under construction: force cache flush on -W0 */
    458443
    459444/* Busybox messages and functions */
    460 static int bb_ioctl(int fd, int request, void *argp, const char *string)
    461 {
    462     int e = ioctl(fd, request, argp);
    463     if (e && string)
    464         bb_perror_msg(" %s", string);
    465     return e;
    466 }
    467 
    468 static int bb_ioctl_alt(int fd, int cmd, unsigned char *args, int alt, const char *string)
     445#if ENABLE_IOCTL_HEX2STR_ERROR
     446static int ioctl_alt_func(int fd, int cmd, unsigned char *args, int alt, const char *string)
    469447{
    470448    if (!ioctl(fd, cmd, args))
    471449        return 0;
    472450    args[0] = alt;
    473     return bb_ioctl(fd, cmd, args, string);
    474 }
    475 
    476 static void on_off(unsigned int value);
    477 
    478 static void print_flag_on_off(unsigned long get_arg, const char *s, unsigned long arg)
    479 {
    480 
    481     if (get_arg)
    482     {
     451    return bb_ioctl_or_warn(fd, cmd, args, string);
     452}
     453#define ioctl_alt_or_warn(fd,cmd,args,alt) ioctl_alt_func(fd,cmd,args,alt,#cmd)
     454#else
     455static int ioctl_alt_func(int fd, int cmd, unsigned char *args, int alt)
     456{
     457    if (!ioctl(fd, cmd, args))
     458        return 0;
     459    args[0] = alt;
     460    return bb_ioctl_or_warn(fd, cmd, args);
     461}
     462#define ioctl_alt_or_warn(fd,cmd,args,alt) ioctl_alt_func(fd,cmd,args,alt)
     463#endif
     464
     465static void on_off(int value)
     466{
     467    puts(value ? " (on)" : " (off)");
     468}
     469
     470static void print_flag_on_off(int get_arg, const char *s, unsigned long arg)
     471{
     472    if (get_arg) {
    483473        printf(" setting %s to %ld", s, arg);
    484474        on_off(arg);
     
    486476}
    487477
    488 static void bb_ioctl_on_off(int fd, int request, void *argp, const char *string,
    489                              const char * str)
    490 {
    491     if (ioctl(fd, request, &argp) != 0)
    492         bb_perror_msg(" %s", string);
    493     else
    494     {
    495         printf(" %s\t= %2ld", str, (unsigned long) argp);
    496         on_off((unsigned long) argp);
    497     }
    498 }
    499 
    500 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
     478static void print_value_on_off(const char *str, unsigned long argp)
     479{
     480    printf(" %s\t= %2ld", str, argp);
     481    on_off(argp != 0);
     482}
     483
     484#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
    501485static void print_ascii(uint16_t *p, uint8_t length);
    502486
    503 static void xprint_ascii(uint16_t *val ,int i, char * string, int n)
    504 {
    505     if (val[i])
    506     {
    507         printf("\t%-20s",string);
     487static void xprint_ascii(uint16_t *val, int i, const char *string, int n)
     488{
     489    if (val[i]) {
     490        printf("\t%-20s", string);
    508491        print_ascii(&val[i], n);
    509492    }
    510493}
    511494#endif
    512 /* end of  busybox specific stuff */
    513 
    514 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
     495/* end of busybox specific stuff */
     496
     497#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
    515498static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode)
    516499{
     
    518501    uint8_t err_dma = 0;
    519502
    520     for (ii = 0; ii <= MODE_MAX; ii++)
    521     {
    522         if (mode_sel & 0x0001)
    523         {
    524             printf("*%cdma%u ",cc,ii);
     503    for (ii = 0; ii <= MODE_MAX; ii++) {
     504        if (mode_sel & 0x0001) {
     505            printf("*%cdma%u ", cc, ii);
    525506            if (*have_mode)
    526507                err_dma = 1;
    527508            *have_mode = 1;
    528         }
    529         else if (mode_sup & 0x0001)
    530             printf("%cdma%u ",cc,ii);
    531 
    532         mode_sup >>=1;
    533         mode_sel >>=1;
     509        } else if (mode_sup & 0x0001)
     510            printf("%cdma%u ", cc, ii);
     511
     512        mode_sup >>= 1;
     513        mode_sel >>= 1;
    534514    }
    535515    return err_dma;
    536516}
    537517
    538 static void print_ascii(uint16_t *p, uint8_t length) {
     518static void print_ascii(uint16_t *p, uint8_t length)
     519{
    539520    uint8_t ii;
    540521    char cl;
    541522
    542523    /* find first non-space & print it */
    543     for (ii = 0; ii< length; ii++)
    544     {
    545         if (((char) 0x00ff&((*p)>>8)) != ' ')
     524    for (ii = 0; ii < length; ii++) {
     525        if ((char)((*p)>>8) != ' ')
    546526            break;
    547         if ((cl = (char) 0x00ff&(*p)) != ' ')
    548         {
    549             if (cl != '\0') printf("%c",cl);
     527        cl = (char)(*p);
     528        if (cl != ' ') {
     529            if (cl != '\0')
     530                printf("%c", cl);
    550531            p++;
    551532            ii++;
     
    555536    }
    556537    /* print the rest */
    557     for (; ii< length; ii++)
    558     {
     538    for (; ii< length; ii++) {
    559539        if (!(*p))
    560540            break; /* some older devices have NULLs */
    561         printf("%c%c",(char)0x00ff&((*p)>>8),(char)(*p)&0x00ff);
     541        printf("%c%c", (char)((*p)>>8), (char)(*p));
    562542        p++;
    563543    }
    564     printf("\n");
     544    puts("");
    565545}
    566546
     
    584564        swab(id_supplied, buf, sizeof(buf));
    585565        val = buf;
    586     } else val = id_supplied;
     566    } else
     567        val = id_supplied;
    587568
    588569    chksum &= 0xff;
    589570
    590571    /* check if we recognise the device type */
    591     printf("\n");
    592     if(!(val[GEN_CONFIG] & NOT_ATA))
    593     {
     572    puts("");
     573    if (!(val[GEN_CONFIG] & NOT_ATA)) {
    594574        dev = ATA_DEV;
    595575        printf("ATA device, with ");
    596     }
    597     else if(val[GEN_CONFIG]==CFA_SUPPORT_VAL)
    598     {
     576    } else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) {
    599577        dev = ATA_DEV;
    600578        like_std = 4;
    601579        printf("CompactFlash ATA device, with ");
    602     }
    603     else if(!(val[GEN_CONFIG] & NOT_ATAPI))
    604     {
     580    } else if (!(val[GEN_CONFIG] & NOT_ATAPI)) {
    605581        dev = ATAPI_DEV;
    606582        eqpt = (val[GEN_CONFIG] & EQPT_TYPE) >> SHIFT_EQPT;
    607583        printf("ATAPI %s, with ", pkt_str[eqpt]);
    608584        like_std = 3;
    609     }
    610     else
     585    } else
    611586        /*"Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n"*/
    612         bb_error_msg_and_die("Unknown device type");
     587        bb_error_msg_and_die("unknown device type");
    613588
    614589    printf("%sremovable media\n", !(val[GEN_CONFIG] & MEDIA_REMOVABLE) ? "non-" : "");
     
    620595     * know yet what standard this device is using.
    621596     */
    622     if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL) ||
    623        (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL) )
    624     {
     597    if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)
     598     || (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL)
     599    ) {
    625600        like_std = 5;
    626         if((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL))
     601        if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL))
    627602            printf("powers-up in standby; SET FEATURES subcmd spins-up.\n");
    628         if(((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE))
     603        if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE))
    629604            printf("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n\n");
    630605    }
     
    640615     * defined until ATA-3 & the CDROM std uses different words.) */
    641616    printf("Standards:");
    642     if (eqpt != CDROM)
    643     {
    644         if (val[MINOR] && (val[MINOR] <= MINOR_MAX))
    645         {
    646             if(like_std < 3) like_std = 3;
     617    if (eqpt != CDROM) {
     618        if (val[MINOR] && (val[MINOR] <= MINOR_MAX)) {
     619            if (like_std < 3) like_std = 3;
    647620            std = actual_ver[val[MINOR]];
    648             if(std) printf("\n\tUsed: %s ",minor_str[val[MINOR]]);
     621            if (std) printf("\n\tUsed: %s ", minor_str[val[MINOR]]);
    649622
    650623        }
     
    652625         * thus, only the newest 4 issues need be supported. (That's
    653626         * what "kk" and "min_std" are all about.) */
    654         if (val[MAJOR] && (val[MAJOR] !=NOVAL_1))
    655         {
     627        if (val[MAJOR] && (val[MAJOR] != NOVAL_1)) {
    656628            printf("\n\tSupported: ");
    657629            jj = val[MAJOR] << 1;
    658630            kk = like_std >4 ? like_std-4: 0;
    659             for (ii = 14; (ii >0)&&(ii>kk); ii--)
    660             {
    661                 if (jj & 0x8000)
    662                 {
     631            for (ii = 14; (ii >0)&&(ii>kk); ii--) {
     632                if (jj & 0x8000) {
    663633                    printf("%u ", ii);
    664                     if (like_std < ii)
    665                     {
     634                    if (like_std < ii) {
    666635                        like_std = ii;
    667636                        kk = like_std >4 ? like_std-4: 0;
    668637                    }
    669                     if(min_std > ii) min_std = ii;
     638                    if (min_std > ii) min_std = ii;
    670639                }
    671640                jj <<= 1;
    672641            }
    673             if(like_std < 3) like_std = 3;
     642            if (like_std < 3) like_std = 3;
    674643        }
    675644        /* Figure out what standard the device is using if it hasn't told
     
    677646         * the words from the next level up.  It happens.
    678647         */
    679         if(like_std < std) like_std = std;
     648        if (like_std < std) like_std = std;
    680649
    681650        if (((std == 5) || (!std && (like_std < 6))) &&
     
    683652            ((  val[CMDS_SUPP_1] & CMDS_W83) > 0x00ff)) ||
    684653            ((( val[CMDS_SUPP_2] & VALID) == VALID_VAL) &&
    685             (   val[CMDS_SUPP_2] & CMDS_W84) ) ) )
    686         {
     654            (   val[CMDS_SUPP_2] & CMDS_W84) ) )
     655        ) {
    687656            like_std = 6;
    688         }
    689         else if (((std == 4) || (!std && (like_std < 5))) &&
     657        } else if (((std == 4) || (!std && (like_std < 5))) &&
    690658            ((((val[INTEGRITY]  & SIG) == SIG_VAL) && !chksum) ||
    691659            ((  val[HWRST_RSLT] & VALID) == VALID_VAL) ||
     
    694662        {
    695663            like_std = 5;
    696         }
    697         else if (((std == 3) || (!std && (like_std < 4))) &&
     664        } else if (((std == 3) || (!std && (like_std < 4))) &&
    698665                ((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
    699666                ((( val[CMDS_SUPP_1] & CMDS_W83) > 0x0000) ||
     
    701668                ((  val[CAPAB_1] & VALID) == VALID_VAL) ||
    702669                ((  val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) ||
    703                 ((  val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) ) )
    704         {
     670                ((  val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) )
     671        ) {
    705672            like_std = 4;
    706         }
    707         else if (((std == 2) || (!std && (like_std < 3))) &&
    708                ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) )
    709         {
     673        } else if (((std == 2) || (!std && (like_std < 3)))
     674         && ((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
     675        ) {
    710676            like_std = 3;
    711         }
    712         else if (((std == 1) || (!std && (like_std < 2))) &&
     677        } else if (((std == 1) || (!std && (like_std < 2))) &&
    713678                ((val[CAPAB_0] & (IORDY_SUP | IORDY_OFF)) ||
    714679                (val[WHATS_VALID] & OK_W64_70)) )
     
    716681            like_std = 2;
    717682        }
     683
    718684        if (!std)
    719             printf("\n\tLikely used: %u\n",like_std);
     685            printf("\n\tLikely used: %u\n", like_std);
    720686        else if (like_std > std)
    721             printf("& some of %u\n",like_std);
     687            printf("& some of %u\n", like_std);
    722688        else
    723             printf("\n");
    724     }
    725     else
    726     {
     689            puts("");
     690    } else {
    727691        /* TBD: do CDROM stuff more thoroughly.  For now... */
    728692        kk = 0;
    729         if (val[CDR_MINOR] == 9)
    730         {
     693        if (val[CDR_MINOR] == 9) {
    731694            kk = 1;
    732695            printf("\n\tUsed: ATAPI for CD-ROMs, SFF-8020i, r2.5");
    733696        }
    734         if (val[CDR_MAJOR] && (val[CDR_MAJOR] !=NOVAL_1))
    735         {
     697        if (val[CDR_MAJOR] && (val[CDR_MAJOR] !=NOVAL_1)) {
    736698            kk = 1;
    737699            printf("\n\tSupported: CD-ROM ATAPI");
    738700            jj = val[CDR_MAJOR] >> 1;
    739             for (ii = 1; ii <15; ii++)
    740             {
    741                 if(jj & 0x0001) printf("-%u ", ii);
     701            for (ii = 1; ii < 15; ii++) {
     702                if (jj & 0x0001) printf("-%u ", ii);
    742703                jj >>= 1;
    743704            }
    744705        }
    745         printf("%s\n", (!kk) ? "\n\tLikely used CD-ROM ATAPI-1" : "" );
     706        printf("%s\n", kk ? "" : "\n\tLikely used CD-ROM ATAPI-1");
    746707        /* the cdrom stuff is more like ATA-2 than anything else, so: */
    747708        like_std = 2;
     
    753714    printf("Configuration:\n");
    754715    /* more info from the general configuration word */
    755     if ((eqpt != CDROM) && (like_std == 1))
    756     {
     716    if ((eqpt != CDROM) && (like_std == 1)) {
    757717        jj = val[GEN_CONFIG] >> 1;
    758         for (ii = 1; ii < 15; ii++)
    759         {
    760             if(jj & 0x0001) printf("\t%s\n",ata1_cfg_str[ii]);
     718        for (ii = 1; ii < 15; ii++) {
     719            if (jj & 0x0001)
     720                printf("\t%s\n", ata1_cfg_str[ii]);
    761721            jj >>=1;
    762722        }
    763723    }
    764     if (dev == ATAPI_DEV)
    765     {
     724    if (dev == ATAPI_DEV) {
    766725        if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) ==  DRQ_3MS_VAL)
    767726            strng = "3ms";
     
    770729        else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) ==  DRQ_50US_VAL)
    771730            strng ="50us";
    772         else 
     731        else
    773732            strng = "Unknown";
    774733        printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */
     
    781740            strng = "Unknown";
    782741        puts(strng);
    783     }
    784     else
    785     {
     742    } else {
    786743        /* addressing...CHS? See section 6.2 of ATA specs 4 or 5 */
    787744        ll = (uint32_t)val[LBA_SECTS_MSB] << 16 | val[LBA_SECTS_LSB];
    788745        mm = 0; bbbig = 0;
    789         if ( (ll > 0x00FBFC10) && (!val[LCYLS]))
     746        if ((ll > 0x00FBFC10) && (!val[LCYLS]))
    790747            printf("\tCHS addressing not supported\n");
    791         else
    792         {
     748        else {
    793749            jj = val[WHATS_VALID] & OK_W54_58;
    794750            printf("\tLogical\t\tmax\tcurrent\n\tcylinders\t%u\t%u\n\theads\t\t%u\t%u\n\tsectors/track\t%u\t%u\n\t--\n",
     
    796752
    797753            if ((min_std == 1) && (val[TRACK_BYTES] || val[SECT_BYTES]))
    798                 printf("\tbytes/track: %u\tbytes/sector: %u\n",val[TRACK_BYTES], val[SECT_BYTES]);
    799 
    800             if (jj)
    801             {
     754                printf("\tbytes/track: %u\tbytes/sector: %u\n", val[TRACK_BYTES], val[SECT_BYTES]);
     755
     756            if (jj) {
    802757                mm = (uint32_t)val[CAPACITY_MSB] << 16 | val[CAPACITY_LSB];
    803                 if (like_std < 3)
    804                 {
    805                      /* check Endian of capacity bytes */
     758                if (like_std < 3) {
     759                    /* check Endian of capacity bytes */
    806760                    nn = val[LCYLS_CUR] * val[LHEADS_CUR] * val[LSECTS_CUR];
    807761                    oo = (uint32_t)val[CAPACITY_LSB] << 16 | val[CAPACITY_MSB];
     
    809763                        mm = oo;
    810764                }
    811                 printf("\tCHS current addressable sectors:%11u\n",mm);
     765                printf("\tCHS current addressable sectors:%11u\n", mm);
    812766            }
    813767        }
    814768        /* LBA addressing */
    815         printf("\tLBA    user addressable sectors:%11u\n",ll);
    816         if ( ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
    817              (val[CMDS_SUPP_1] & SUPPORT_48_BIT) )
    818         {
    819             bbbig = (uint64_t)val[LBA_64_MSB]   << 48 |
    820                     (uint64_t)val[LBA_48_MSB]   << 32 |
    821                     (uint64_t)val[LBA_MID]  << 16 |
    822                     val[LBA_LSB] ;
    823             printf("\tLBA48  user addressable sectors:%11"PRIu64"\n",bbbig);
     769        printf("\tLBA    user addressable sectors:%11u\n", ll);
     770        if (((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
     771         && (val[CMDS_SUPP_1] & SUPPORT_48_BIT)
     772        ) {
     773            bbbig = (uint64_t)val[LBA_64_MSB] << 48 |
     774                    (uint64_t)val[LBA_48_MSB] << 32 |
     775                    (uint64_t)val[LBA_MID] << 16 |
     776                    val[LBA_LSB];
     777            printf("\tLBA48  user addressable sectors:%11"PRIu64"\n", bbbig);
    824778        }
    825779
    826780        if (!bbbig)
    827781            bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */
    828         printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n",bbbig>>11);
    829         bbbig = (bbbig<<9)/1000000;
    830         printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ",bbbig);
     782        printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11);
     783        bbbig = (bbbig << 9) / 1000000;
     784        printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig);
    831785
    832786        if (bbbig > 1000)
    833787            printf("(%"PRIu64" GB)\n", bbbig/1000);
    834         else 
    835             printf("\n");
     788        else
     789            puts("");
    836790    }
    837791
     
    839793    printf("Capabilities:\n\t");
    840794
    841     if (dev == ATAPI_DEV)
    842     {
     795    if (dev == ATAPI_DEV) {
    843796        if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP)) printf("Cmd queuing, ");
    844797        if (val[CAPAB_0] & OVLP_SUP) printf("Cmd overlap, ");
     
    846799    if (val[CAPAB_0] & LBA_SUP) printf("LBA, ");
    847800
    848     if (like_std != 1)
    849     {
    850         printf("IORDY%s(can%s be disabled)\n",
    851                 !(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "",
     801    if (like_std != 1) {
     802        printf("IORDY%s(can%s be disabled)\n",
     803                !(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "",
    852804                (val[CAPAB_0] & IORDY_OFF) ? "" :"not");
    853     }
    854     else
     805    } else
    855806        printf("no IORDY\n");
    856807
    857     if ((like_std == 1) && val[BUF_TYPE])
    858     {
     808    if ((like_std == 1) && val[BUF_TYPE]) {
    859809        printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE],
    860                 (val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector", 
     810                (val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector",
    861811                (val[BUF_TYPE] > 2) ? " with read caching ability" : "");
    862812    }
    863813
    864     if ((min_std == 1) && (val[BUFFER__SIZE] && (val[BUFFER__SIZE] != NOVAL_1)))
    865     {
    866         printf("\tBuffer size: %.1fkB\n",(float)val[BUFFER__SIZE]/2);
    867     }
    868     if ((min_std < 4) && (val[RW_LONG]))
    869     {
    870         printf("\tbytes avail on r/w long: %u\n",val[RW_LONG]);
    871     }
    872     if ((eqpt != CDROM) && (like_std > 3))
    873     {
    874         printf("\tQueue depth: %u\n",(val[QUEUE_DEPTH] & DEPTH_BITS)+1);
    875     }
    876 
    877     if (dev == ATA_DEV)
    878     {
     814    if ((min_std == 1) && (val[BUFFER__SIZE] && (val[BUFFER__SIZE] != NOVAL_1))) {
     815        printf("\tBuffer size: %.1fkB\n", (float)val[BUFFER__SIZE]/2);
     816    }
     817    if ((min_std < 4) && (val[RW_LONG])) {
     818        printf("\tbytes avail on r/w long: %u\n", val[RW_LONG]);
     819    }
     820    if ((eqpt != CDROM) && (like_std > 3)) {
     821        printf("\tQueue depth: %u\n", (val[QUEUE_DEPTH] & DEPTH_BITS) + 1);
     822    }
     823
     824    if (dev == ATA_DEV) {
    879825        if (like_std == 1)
    880             printf("\tCan%s perform double-word IO\n",(!val[DWORD_IO]) ?"not":"");
    881         else
    882         {
     826            printf("\tCan%s perform double-word IO\n", (!val[DWORD_IO]) ? "not" : "");
     827        else {
    883828            printf("\tStandby timer values: spec'd by %s", (val[CAPAB_0] & STD_STBY) ? "Standard" : "Vendor");
    884829            if ((like_std > 3) && ((val[CAPAB_1] & VALID) == VALID_VAL))
    885                 printf(", %s device specific minimum\n",(val[CAPAB_1] & MIN_STANDBY_TIMER)?"with":"no");
     830                printf(", %s device specific minimum\n", (val[CAPAB_1] & MIN_STANDBY_TIMER) ? "with" : "no");
    886831            else
    887               printf("\n");
     832                puts("");
    888833        }
    889834        printf("\tR/W multiple sector transfer: ");
    890835        if ((like_std < 3) && !(val[SECTOR_XFER_MAX] & SECTOR_XFER))
    891836            printf("not supported\n");
    892         else
    893         {
    894             printf("Max = %u\tCurrent = ",val[SECTOR_XFER_MAX] & SECTOR_XFER);
     837        else {
     838            printf("Max = %u\tCurrent = ", val[SECTOR_XFER_MAX] & SECTOR_XFER);
    895839            if (val[SECTOR_XFER_CUR] & MULTIPLE_SETTING_VALID)
    896840                printf("%u\n", val[SECTOR_XFER_CUR] & SECTOR_XFER);
     
    898842                printf("?\n");
    899843        }
    900         if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008))
    901         {
     844        if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008)) {
    902845            /* We print out elsewhere whether the APM feature is enabled or
    903846               not.  If it's not enabled, let's not repeat the info; just print
    904847               nothing here. */
    905848            printf("\tAdvancedPM level: ");
    906             if ( (val[ADV_PWR] & 0xFF00) == 0x4000 )
    907             {
     849            if ((val[ADV_PWR] & 0xFF00) == 0x4000) {
    908850                uint8_t apm_level = val[ADV_PWR] & 0x00FF;
    909851                printf("%u (0x%x)\n", apm_level, apm_level);
     
    914856        if (like_std > 5 && val[ACOUSTIC]) {
    915857            printf("\tRecommended acoustic management value: %u, current value: %u\n",
    916                                     (val[ACOUSTIC] >> 8) & 0x00ff, val[ACOUSTIC] & 0x00ff);
    917         }
    918     }
    919     else
    920     {
     858                    (val[ACOUSTIC] >> 8) & 0x00ff, val[ACOUSTIC] & 0x00ff);
     859        }
     860    } else {
    921861         /* ATAPI */
    922862        if (eqpt != CDROM && (val[CAPAB_0] & SWRST_REQ))
    923863            printf("\tATA sw reset required\n");
    924864
    925         if (val[PKT_REL] || val[SVC_NBSY])
    926         {
     865        if (val[PKT_REL] || val[SVC_NBSY]) {
    927866            printf("\tOverlap support:");
    928             if (val[PKT_REL]) printf(" %uus to release bus.",val[PKT_REL]);
    929             if (val[SVC_NBSY]) printf(" %uus to clear BSY after SERVICE cmd.",val[SVC_NBSY]);
    930             printf("\n");
     867            if (val[PKT_REL]) printf(" %uus to release bus.", val[PKT_REL]);
     868            if (val[SVC_NBSY]) printf(" %uus to clear BSY after SERVICE cmd.", val[SVC_NBSY]);
     869            puts("");
    931870        }
    932871    }
     
    936875    if (!(val[CAPAB_0] & DMA_SUP))
    937876        printf("not supported\n");
    938     else
    939     {
     877    else {
    940878        if (val[DMA_MODE] && !val[SINGLE_DMA] && !val[MULTI_DMA])
    941             printf(" sdma%u\n",(val[DMA_MODE] & MODE) >> 8);
    942         if (val[SINGLE_DMA])
    943         {
     879            printf(" sdma%u\n", (val[DMA_MODE] & MODE) >> 8);
     880        if (val[SINGLE_DMA]) {
    944881            jj = val[SINGLE_DMA];
    945882            kk = val[SINGLE_DMA] >> 8;
    946             err_dma += mode_loop(jj,kk,'s',&have_mode);
    947         }
    948         if (val[MULTI_DMA])
    949         {
     883            err_dma += mode_loop(jj, kk, 's', &have_mode);
     884        }
     885        if (val[MULTI_DMA]) {
    950886            jj = val[MULTI_DMA];
    951887            kk = val[MULTI_DMA] >> 8;
    952             err_dma += mode_loop(jj,kk,'m',&have_mode);
    953         }
    954         if ((val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA])
    955         {
     888            err_dma += mode_loop(jj, kk, 'm', &have_mode);
     889        }
     890        if ((val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) {
    956891            jj = val[ULTRA_DMA];
    957892            kk = val[ULTRA_DMA] >> 8;
    958             err_dma += mode_loop(jj,kk,'u',&have_mode);
     893            err_dma += mode_loop(jj, kk, 'u', &have_mode);
    959894        }
    960895        if (err_dma || !have_mode) printf("(?)");
    961         printf("\n");
     896        puts("");
    962897
    963898        if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP))
    964899            printf("\t\tInterleaved DMA support\n");
    965900
    966         if ((val[WHATS_VALID] & OK_W64_70) &&
    967            (val[DMA_TIME_MIN] || val[DMA_TIME_NORM]))
    968         {
     901        if ((val[WHATS_VALID] & OK_W64_70)
     902         && (val[DMA_TIME_MIN] || val[DMA_TIME_NORM])
     903        ) {
    969904            printf("\t\tCycle time:");
    970             if (val[DMA_TIME_MIN]) printf(" min=%uns",val[DMA_TIME_MIN]);
    971             if (val[DMA_TIME_NORM]) printf(" recommended=%uns",val[DMA_TIME_NORM]);
    972             printf("\n");
     905            if (val[DMA_TIME_MIN]) printf(" min=%uns", val[DMA_TIME_MIN]);
     906            if (val[DMA_TIME_NORM]) printf(" recommended=%uns", val[DMA_TIME_NORM]);
     907            puts("");
    973908        }
    974909    }
     
    978913    /* If a drive supports mode n (e.g. 3), it also supports all modes less
    979914     * than n (e.g. 3, 2, 1 and 0).  Print all the modes. */
    980     if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP))
    981     {
     915    if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP)) {
    982916        jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007;
    983         for (ii = 0; ii <= PIO_MODE_MAX ; ii++)
    984         {
    985             if (jj & 0x0001) printf("pio%d ",ii);
     917        for (ii = 0; ii <= PIO_MODE_MAX; ii++) {
     918            if (jj & 0x0001) printf("pio%d ", ii);
    986919            jj >>=1;
    987920        }
    988         printf("\n");
    989     }
    990     else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE) )
    991     {
     921        puts("");
     922    } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) {
    992923        for (ii = 0; ii <= val[PIO_MODE]>>8; ii++)
    993             printf("pio%d ",ii);
    994         printf("\n");
    995     }
    996     else
     924            printf("pio%d ", ii);
     925        puts("");
     926    } else
    997927        printf("unknown\n");
    998928
    999     if (val[WHATS_VALID] & OK_W64_70)
    1000     {
    1001         if (val[PIO_NO_FLOW] || val[PIO_FLOW])
    1002         {
     929    if (val[WHATS_VALID] & OK_W64_70) {
     930        if (val[PIO_NO_FLOW] || val[PIO_FLOW]) {
    1003931            printf("\t\tCycle time:");
    1004932            if (val[PIO_NO_FLOW]) printf(" no flow control=%uns", val[PIO_NO_FLOW]);
    1005933            if (val[PIO_FLOW]) printf("  IORDY flow control=%uns", val[PIO_FLOW]);
    1006             printf("\n");
    1007         }
    1008     }
    1009 
    1010     if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
    1011     {
     934            puts("");
     935        }
     936    }
     937
     938    if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) {
    1012939        printf("Commands/features:\n\tEnabled\tSupported:\n");
    1013940        jj = val[CMDS_SUPP_0];
    1014941        kk = val[CMDS_EN_0];
    1015         for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++)
    1016         {
    1017             if ((jj & 0x8000) && (*cmd_feat_str[ii] != '\0'))
    1018             {
     942        for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) {
     943            if ((jj & 0x8000) && (*cmd_feat_str[ii] != '\0')) {
    1019944                printf("\t%s\t%s\n", (kk & 0x8000) ? "   *" : "", cmd_feat_str[ii]);
    1020945            }
    1021             jj <<=1; kk<<=1;
    1022             if (ii%16 == 15)
    1023             {
     946            jj <<= 1;
     947            kk <<= 1;
     948            if (ii % 16 == 15) {
    1024949                jj = val[CMDS_SUPP_0+1+(ii/16)];
    1025950                kk = val[CMDS_EN_0+1+(ii/16)];
    1026951            }
    1027             if (ii == 31)
    1028             {
     952            if (ii == 31) {
    1029953                if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL)
    1030954                    ii +=16;
     
    1033957    }
    1034958    /* Removable Media Status Notification feature set */
    1035     if((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP)
     959    if ((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP)
    1036960        printf("\t%s supported\n", cmd_feat_str[27]);
    1037961
    1038 
    1039962    /* security */
    1040     if ((eqpt != CDROM) && (like_std > 3) &&
    1041        (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME]))
    1042     {
     963    if ((eqpt != CDROM) && (like_std > 3)
     964     && (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME])
     965    ) {
    1043966        printf("Security:\n");
    1044967        if (val[PSWD_CODE] && (val[PSWD_CODE] != NOVAL_1))
    1045             printf("\tMaster password revision code = %u\n",val[PSWD_CODE]);
     968            printf("\tMaster password revision code = %u\n", val[PSWD_CODE]);
    1046969        jj = val[SECU_STATUS];
    1047         if (jj)
    1048         {
    1049             for (ii = 0; ii < NUM_SECU_STR; ii++)
    1050             {
     970        if (jj) {
     971            for (ii = 0; ii < NUM_SECU_STR; ii++) {
    1051972                printf("\t%s\t%s\n", (!(jj & 0x0001)) ? "not" : "",  secu_str[ii]);
    1052973                jj >>=1;
    1053974            }
    1054             if (val[SECU_STATUS] & SECU_ENABLED)
    1055             {
     975            if (val[SECU_STATUS] & SECU_ENABLED) {
    1056976                printf("\tSecurity level %s\n", (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high");
    1057977            }
     
    1059979        jj =  val[ERASE_TIME]     & ERASE_BITS;
    1060980        kk =  val[ENH_ERASE_TIME] & ERASE_BITS;
    1061         if (jj || kk)
    1062         {
     981        if (jj || kk) {
    1063982            printf("\t");
    1064983            if (jj) printf("%umin for %sSECURITY ERASE UNIT. ", jj==ERASE_BITS ? 508 : jj<<1, "");
    1065984            if (kk) printf("%umin for %sSECURITY ERASE UNIT. ", kk==ERASE_BITS ? 508 : kk<<1, "ENHANCED ");
    1066             printf("\n");
     985            puts("");
    1067986        }
    1068987    }
     
    1070989    /* reset result */
    1071990    jj = val[HWRST_RSLT];
    1072     if ((jj & VALID) == VALID_VAL)
    1073     {
     991    if ((jj & VALID) == VALID_VAL) {
    1074992        if (!(oo = (jj & RST0)))
    1075993            jj >>= 8;
     
    1078996        else if ((jj & DEV_DET) == CSEL_VAL)
    1079997            strng = " determined by CSEL";
    1080         else 
     998        else
    1081999            strng = "";
    1082         printf("HW reset results:\n\tCBLID- %s Vih\n\tDevice num = %i%s\n", 
     1000        printf("HW reset results:\n\tCBLID- %s Vih\n\tDevice num = %i%s\n",
    10831001                (val[HWRST_RSLT] & CBLID) ? "above" : "below", !(oo), strng);
    10841002    }
    10851003
    10861004    /* more stuff from std 5 */
    1087     if ((like_std > 4) && (eqpt != CDROM))
    1088     {
    1089         if (val[CFA_PWR_MODE] & VALID_W160)
    1090         {
     1005    if ((like_std > 4) && (eqpt != CDROM)) {
     1006        if (val[CFA_PWR_MODE] & VALID_W160) {
    10911007            printf("CFA power mode 1:\n\t%s%s\n", (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled",
    1092                                         (val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : "");
    1093 
    1094             if (val[CFA_PWR_MODE] & MAX_AMPS) printf("\tMaximum current = %uma\n",val[CFA_PWR_MODE] & MAX_AMPS);
    1095         }
    1096         if ((val[INTEGRITY] & SIG) == SIG_VAL)
    1097         {
     1008                    (val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : "");
     1009
     1010            if (val[CFA_PWR_MODE] & MAX_AMPS)
     1011                printf("\tMaximum current = %uma\n", val[CFA_PWR_MODE] & MAX_AMPS);
     1012        }
     1013        if ((val[INTEGRITY] & SIG) == SIG_VAL) {
    10981014            printf("Checksum: %scorrect\n", chksum ? "in" : "");
    10991015        }
     
    11041020#endif
    11051021
    1106 static int get_identity, get_geom;
    1107 static int do_flush;
    1108 static int do_ctimings, do_timings;
    1109 static unsigned long set_readahead, get_readahead, Xreadahead;
    1110 static unsigned long set_readonly, get_readonly, readonly;
    1111 static unsigned long set_unmask, get_unmask, unmask;
    1112 static unsigned long set_mult, get_mult, mult;
    1113 #ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA
    1114 static unsigned long set_dma, get_dma, dma;
    1115 #endif
    1116 static unsigned long set_dma_q, get_dma_q, dma_q;
    1117 static unsigned long set_nowerr, get_nowerr, nowerr;
    1118 static unsigned long set_keep, get_keep, keep;
    1119 static unsigned long set_io32bit, get_io32bit, io32bit;
    1120 static unsigned long set_piomode, noisy_piomode;
     1022static smallint get_identity, get_geom;
     1023static smallint do_flush;
     1024static smallint do_ctimings, do_timings;
     1025static smallint reread_partn;
     1026
     1027static smallint set_piomode, noisy_piomode;
     1028static smallint set_readahead, get_readahead;
     1029static smallint set_readonly, get_readonly;
     1030static smallint set_unmask, get_unmask;
     1031static smallint set_mult, get_mult;
     1032static smallint set_dma_q, get_dma_q;
     1033static smallint set_nowerr, get_nowerr;
     1034static smallint set_keep, get_keep;
     1035static smallint set_io32bit, get_io32bit;
    11211036static int piomode;
     1037static unsigned long Xreadahead;
     1038static unsigned long readonly;
     1039static unsigned long unmask;
     1040static unsigned long mult;
     1041static unsigned long dma_q;
     1042static unsigned long nowerr;
     1043static unsigned long keep;
     1044static unsigned long io32bit;
     1045#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
     1046static unsigned long dma;
     1047static smallint set_dma, get_dma;
     1048#endif
    11221049#ifdef HDIO_DRIVE_CMD
    1123 static unsigned long set_dkeep, get_dkeep, dkeep;
    1124 static unsigned long set_standby, get_standby, standby_requested;
    1125 static unsigned long set_xfermode, get_xfermode;
     1050static smallint set_xfermode, get_xfermode;
     1051static smallint set_dkeep, get_dkeep;
     1052static smallint set_standby, get_standby;
     1053static smallint set_lookahead, get_lookahead;
     1054static smallint set_prefetch, get_prefetch;
     1055static smallint set_defects, get_defects;
     1056static smallint set_wcache, get_wcache;
     1057static smallint set_doorlock, get_doorlock;
     1058static smallint set_seagate, get_seagate;
     1059static smallint set_standbynow, get_standbynow;
     1060static smallint set_sleepnow, get_sleepnow;
     1061static smallint get_powermode;
     1062static smallint set_apmmode, get_apmmode;
    11261063static int xfermode_requested;
    1127 static unsigned long set_lookahead, get_lookahead, lookahead;
    1128 static unsigned long set_prefetch, get_prefetch, prefetch;
    1129 static unsigned long set_defects, get_defects, defects;
    1130 static unsigned long set_wcache, get_wcache, wcache;
    1131 static unsigned long set_doorlock, get_doorlock, doorlock;
    1132 static unsigned long set_seagate, get_seagate;
    1133 static unsigned long set_standbynow, get_standbynow;
    1134 static unsigned long set_sleepnow, get_sleepnow;
    1135 static unsigned long get_powermode;
    1136 static unsigned long set_apmmode, get_apmmode, apmmode;
    1137 #endif
    1138 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
    1139 static int get_IDentity;
    1140 #endif
    1141 #ifdef CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
    1142 static unsigned long    unregister_hwif;
    1143 static unsigned long    hwif;
    1144 #endif
    1145 #ifdef CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF
    1146 static unsigned long scan_hwif;
     1064static unsigned long dkeep;
     1065static unsigned long standby_requested;
     1066static unsigned long lookahead;
     1067static unsigned long prefetch;
     1068static unsigned long defects;
     1069static unsigned long wcache;
     1070static unsigned long doorlock;
     1071static unsigned long apmmode;
     1072#endif
     1073USE_FEATURE_HDPARM_GET_IDENTITY(        static smallint get_IDentity;)
     1074USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static smallint set_busstate, get_busstate;)
     1075USE_FEATURE_HDPARM_HDIO_DRIVE_RESET(    static smallint perform_reset;)
     1076USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static smallint perform_tristate;)
     1077USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(static smallint unregister_hwif;)
     1078USE_FEATURE_HDPARM_HDIO_SCAN_HWIF(      static smallint scan_hwif;)
     1079USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static unsigned long busstate;)
     1080USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static unsigned long tristate;)
     1081USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(static unsigned long hwif;)
     1082#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
    11471083static unsigned long hwif_data;
    11481084static unsigned long hwif_ctrl;
    11491085static unsigned long hwif_irq;
    11501086#endif
    1151 #ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
    1152 static unsigned long    set_busstate, get_busstate, busstate;
    1153 #endif
    1154 static int  reread_partn;
    1155 
    1156 #ifdef CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET
    1157 static int  perform_reset;
    1158 #endif /* CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET */
    1159 #ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
    1160 static unsigned long    perform_tristate,   tristate;
    1161 #endif /* CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF */
    11621087
    11631088// Historically, if there was no HDIO_OBSOLETE_IDENTITY, then
     
    11721097// Too bad, really.
    11731098
    1174 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
    1175 static const char * const cfg_str[] =
    1176 {   "",      "HardSect",   "SoftSect",   "NotMFM",
     1099#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
     1100static const char *const cfg_str[] = {
     1101    "",      "HardSect",   "SoftSect",   "NotMFM",
    11771102    "HdSw>15uSec", "SpinMotCtl", "Fixed",     "Removeable",
    11781103    "DTR<=5Mbs",   "DTR>5Mbs",   "DTR>10Mbs", "RotSpdTol>.5%",
     
    11801105};
    11811106
    1182 static const char * const BuffType[] = {"Unknown", "1Sect", "DualPort", "DualPortCache"};
     1107static const char *const BuffType[] = {
     1108    "Unknown", "1Sect", "DualPort", "DualPortCache"
     1109};
    11831110
    11841111static void dump_identity(const struct hd_driveid *id)
    11851112{
    11861113    int i;
    1187     const unsigned short int *id_regs= (const void*) id;
     1114    const unsigned short int *id_regs = (const void*) id;
    11881115
    11891116    printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n Config={",
    11901117                id->model, id->fw_rev, id->serial_no);
    1191     for (i=0; i<=15; i++) {
     1118    for (i = 0; i <= 15; i++) {
    11921119        if (id->config & (1<<i))
    11931120            printf(" %s", cfg_str[i]);
    11941121    }
    1195     printf( " }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n"
     1122    printf(" }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n"
    11961123            " BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u",
    11971124                id->cyls, id->heads, id->sectors, id->track_bytes,
     
    11991126                id->buf_type, BuffType[(id->buf_type > 3) ? 0 :  id->buf_type],
    12001127                id->buf_size/2, id->max_multsect);
    1201     if (id->max_multsect)
    1202     {
     1128    if (id->max_multsect) {
    12031129        printf(", MultSect=");
    1204         if (!(id->multsect_valid&1))
     1130        if (!(id->multsect_valid & 1))
    12051131            printf("?%u?", id->multsect);
    12061132        else if (id->multsect)
     
    12091135            printf("off");
    12101136    }
    1211     printf("\n");
    1212 
    1213     if(!(id->field_valid&1))
     1137    puts("");
     1138
     1139    if (!(id->field_valid & 1))
    12141140        printf(" (maybe):");
    12151141
    1216     printf(" CurCHS=%u/%u/%u, CurSects=%lu, LBA=%s",id->cur_cyls, id->cur_heads,
    1217                                                     id->cur_sectors,
    1218                                                     (BB_BIG_ENDIAN) ?
    1219                                                     (long unsigned int)(id->cur_capacity0 << 16) | id->cur_capacity1 :
    1220                                                     (long unsigned int)(id->cur_capacity1 << 16) | id->cur_capacity0,
    1221                                                     ((id->capability&2) == 0) ? "no" : "yes");
    1222 
    1223     if (id->capability&2)
     1142    printf(" CurCHS=%u/%u/%u, CurSects=%lu, LBA=%s", id->cur_cyls, id->cur_heads,
     1143        id->cur_sectors,
     1144        (BB_BIG_ENDIAN) ?
     1145            (unsigned long)(id->cur_capacity0 << 16) | id->cur_capacity1 :
     1146            (unsigned long)(id->cur_capacity1 << 16) | id->cur_capacity0,
     1147            ((id->capability&2) == 0) ? "no" : "yes");
     1148
     1149    if (id->capability & 2)
    12241150        printf(", LBAsects=%u", id->lba_capacity);
    12251151
    1226     printf("\n IORDY=%s", (id->capability&8) ? (id->capability&4) ?  "on/off" : "yes" : "no");
    1227 
    1228     if (((id->capability&8) || (id->field_valid&2)) && id->field_valid&2)
     1152    printf("\n IORDY=%s", (id->capability & 8) ? (id->capability & 4) ?  "on/off" : "yes" : "no");
     1153
     1154    if (((id->capability & 8) || (id->field_valid & 2)) && (id->field_valid & 2))
    12291155        printf(", tPIO={min:%u,w/IORDY:%u}", id->eide_pio, id->eide_pio_iordy);
    1230    
    1231     if ((id->capability&1) && (id->field_valid&2))
     1156
     1157    if ((id->capability & 1) && (id->field_valid & 2))
    12321158        printf(", tDMA={min:%u,rec:%u}", id->eide_dma_min, id->eide_dma_time);
    12331159
    12341160    printf("\n PIO modes:  ");
    1235     if (id->tPIO <= 5)
    1236     {
     1161    if (id->tPIO <= 5) {
    12371162        printf("pio0 ");
    12381163        if (id->tPIO >= 1) printf("pio1 ");
    12391164        if (id->tPIO >= 2) printf("pio2 ");
    12401165    }
    1241     if (id->field_valid&2)
    1242     {
     1166    if (id->field_valid & 2) {
    12431167        if (id->eide_pio_modes & 1) printf("pio3 ");
    12441168        if (id->eide_pio_modes & 2) printf("pio4 ");
    12451169        if (id->eide_pio_modes &~3) printf("pio? ");
    12461170    }
    1247     if (id->capability&1)
    1248     {
    1249         if (id->dma_1word | id->dma_mword)
    1250         {
     1171    if (id->capability & 1) {
     1172        if (id->dma_1word | id->dma_mword) {
    12511173            printf("\n DMA modes:  ");
    12521174            if (id->dma_1word & 0x100) printf("*");
     
    12681190        }
    12691191    }
    1270     if (((id->capability&8) || (id->field_valid&2)) && id->field_valid&4)
    1271     {   
     1192    if (((id->capability & 8) || (id->field_valid & 2)) && id->field_valid & 4) {
    12721193        printf("\n UDMA modes: ");
    12731194        if (id->dma_ultra & 0x100) printf("*");
     
    12781199        if (id->dma_ultra & 0x004) printf("udma2 ");
    12791200#ifdef __NEW_HD_DRIVE_ID
    1280         if (id->hw_config & 0x2000)
    1281         {
     1201        if (id->hw_config & 0x2000) {
    12821202#else /* !__NEW_HD_DRIVE_ID */
    1283         if (id->word93 & 0x2000)
    1284         {
     1203        if (id->word93 & 0x2000) {
    12851204#endif /* __NEW_HD_DRIVE_ID */
    12861205            if (id->dma_ultra & 0x0800) printf("*");
     
    12961215        }
    12971216    }
    1298     printf("\n AdvancedPM=%s",((id_regs[83]&8)==0)?"no":"yes");
    1299     if (id_regs[83] & 8)
    1300     {
    1301         if (!(id_regs[86]&8))
     1217    printf("\n AdvancedPM=%s", (!(id_regs[83] & 8)) ? "no" : "yes");
     1218    if (id_regs[83] & 8) {
     1219        if (!(id_regs[86] & 8))
    13021220            printf(": disabled (255)");
    1303         else if ((id_regs[91]&0xFF00)!=0x4000)
     1221        else if ((id_regs[91] & 0xFF00) != 0x4000)
    13041222            printf(": unknown setting");
    13051223        else
    1306             printf(": mode=0x%02X (%u)",id_regs[91]&0xFF,id_regs[91]&0xFF);
    1307     }
    1308     if (id_regs[82]&0x20)
    1309         printf(" WriteCache=%s",(id_regs[85]&0x20) ? "enabled" : "disabled");
     1224            printf(": mode=0x%02X (%u)", id_regs[91] & 0xFF, id_regs[91] & 0xFF);
     1225    }
     1226    if (id_regs[82] & 0x20)
     1227        printf(" WriteCache=%s", (id_regs[85] & 0x20) ? "enabled" : "disabled");
    13101228#ifdef __NEW_HD_DRIVE_ID
    1311     if ((id->minor_rev_num && id->minor_rev_num <= 31) || (id->major_rev_num && id->minor_rev_num <= 31))
    1312     {
     1229    if ((id->minor_rev_num && id->minor_rev_num <= 31)
     1230     || (id->major_rev_num && id->minor_rev_num <= 31)
     1231    ) {
    13131232        printf("\n Drive conforms to: %s: ", (id->minor_rev_num <= 31) ? minor_str[id->minor_rev_num] : "Unknown");
    13141233        if (id->major_rev_num != 0x0000 &&  /* NOVAL_0 */
    13151234            id->major_rev_num != 0xFFFF) {  /* NOVAL_1 */
    1316             for (i=0; i <= 15; i++) {
     1235            for (i = 0; i <= 15; i++) {
    13171236                if (id->major_rev_num & (1<<i))
    13181237                        printf(" ATA/ATAPI-%u", i);
     
    13281247{
    13291248    fsync(fd);              /* flush buffers */
    1330     bb_ioctl(fd, BLKFLSBUF, NULL,"BLKFLSBUF" ) ;/* do it again, big time */
     1249    ioctl_or_warn(fd, BLKFLSBUF, NULL); /* do it again, big time */
    13311250#ifdef HDIO_DRIVE_CMD
    13321251    sleep(1);
    1333     if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) /* await completion */
    1334         bb_perror_msg("HDIO_DRIVE_CMD");
     1252    if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) {   /* await completion */
     1253        if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */
     1254            bb_perror_msg("HDIO_DRIVE_CMD");
     1255        else
     1256            bb_perror_msg("ioctl %#x failed", HDIO_DRIVE_CMD);
     1257    }
    13351258#endif
    13361259}
     
    13471270    int i;
    13481271
    1349     if ((i = read(fd, buf, TIMING_BUF_BYTES)) != TIMING_BUF_BYTES) {
     1272    i = read(fd, buf, TIMING_BUF_BYTES);
     1273    if (i != TIMING_BUF_BYTES) {
    13501274        bb_error_msg("read(%d bytes) failed (rc=%d)", TIMING_BUF_BYTES, i);
    13511275        return 1;
     
    13571281}
    13581282
    1359 static void print_timing(int t, double e)
    1360 {
    1361     if (t >= e)  /* more than 1MB/s */
    1362         printf("%2d MB in %5.2f seconds =%6.2f %cB/sec\n", t, e, t / e, 'M');
    1363     else
    1364         printf("%2d MB in %5.2f seconds =%6.2f %cB/sec\n", t, e, t / e * 1024, 'k');
    1365 }
    1366 
    1367 static int do_blkgetsize (int fd, unsigned long long *blksize64)
    1368 {
    1369     int     rc;
    1370     unsigned int    blksize32 = 0;
     1283static int do_blkgetsize(int fd, unsigned long long *blksize64)
     1284{
     1285    int rc;
     1286    unsigned blksize32 = 0;
    13711287
    13721288    if (0 == ioctl(fd, BLKGETSIZE64, blksize64)) {  // returns bytes
     
    13741290        return 0;
    13751291    }
    1376     rc = ioctl(fd, BLKGETSIZE, &blksize32); // returns sectors
    1377     if (rc)
    1378         bb_perror_msg("BLKGETSIZE");
     1292    rc = ioctl_or_warn(fd, BLKGETSIZE, &blksize32); // returns sectors
    13791293    *blksize64 = blksize32;
    13801294    return rc;
    13811295}
    13821296
     1297static void print_timing(unsigned t, double e)
     1298{
     1299    if (t >= e)  /* more than 1MB/s */
     1300        printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e, 'M');
     1301    else
     1302        printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e * 1024, 'k');
     1303}
     1304
    13831305static void do_time(int flag, int fd)
    1384 /*
    1385     flag = 0 time_cache
    1386     flag = 1 time_device
    1387 */
    1388 {
    1389     struct itimerval e1, e2;
    1390     double elapsed, elapsed2;
    1391     unsigned int max_iterations = 1024, total_MB, iterations;
     1306/* flag = 0 time_cache, 1 time_device */
     1307{
     1308    static const struct itimerval thousand = {{1000, 0}, {1000, 0}};
     1309
     1310    struct itimerval itv;
     1311    unsigned elapsed, elapsed2;
     1312    unsigned max_iterations, total_MB, iterations;
    13921313    unsigned long long blksize;
    13931314    RESERVE_CONFIG_BUFFER(buf, TIMING_BUF_BYTES);
     
    13981319    }
    13991320
     1321    max_iterations = 1024;
    14001322    if (0 == do_blkgetsize(fd, &blksize)) {
    14011323        max_iterations = blksize / (2 * 1024) / TIMING_BUF_MB;
     
    14041326    /* Clear out the device request queues & give them time to complete */
    14051327    sync();
    1406     sleep(3);
    1407 
    1408     setitimer(ITIMER_REAL, &(struct itimerval){{1000,0},{1000,0}}, NULL);
    1409 
    1410     if (flag  == 0) /* Time cache */
    1411     {
    1412         if (seek_to_zero (fd)) return;
    1413         if (read_big_block (fd, buf)) return;
    1414         printf(" Timing cached reads:   ");
    1415         fflush(stdout);
    1416    
    1417         /* Now do the timing */
    1418         iterations = 0;
    1419         getitimer(ITIMER_REAL, &e1);
     1328    sleep(2);
     1329    if (flag == 0) { /* Time cache */
     1330        if (seek_to_zero(fd))
     1331            goto quit;
     1332        if (read_big_block(fd, buf))
     1333            goto quit;
     1334        printf(" Timing buffer-cache reads:  ");
     1335    } else { /* Time device */
     1336        printf(" Timing buffered disk reads: ");
     1337    }
     1338    fflush(stdout);
     1339    iterations = 0;
     1340    /*
     1341     * getitimer() is used rather than gettimeofday() because
     1342     * it is much more consistent (on my machine, at least).
     1343     */
     1344    setitimer(ITIMER_REAL, &thousand, NULL);
     1345    /* Now do the timing */
     1346    do {
     1347        ++iterations;
     1348        if ((flag == 0) && seek_to_zero(fd))
     1349            goto quit;
     1350        if (read_big_block(fd, buf))
     1351            goto quit;
     1352        getitimer(ITIMER_REAL, &itv);
     1353        elapsed = (1000 - itv.it_value.tv_sec) * 1000000
     1354                - itv.it_value.tv_usec;
     1355    } while (elapsed < 3000000 && iterations < max_iterations);
     1356    total_MB = iterations * TIMING_BUF_MB;
     1357    if (flag == 0) {
     1358        /* Now remove the lseek() and getitimer() overheads from the elapsed time */
     1359        setitimer(ITIMER_REAL, &thousand, NULL);
    14201360        do {
    1421             ++iterations;
    1422             if (seek_to_zero (fd) || read_big_block (fd, buf))
     1361            if (seek_to_zero(fd))
    14231362                goto quit;
    1424             getitimer(ITIMER_REAL, &e2);
    1425             elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec)
    1426             + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0);
    1427         } while (elapsed < 2.0);
    1428         total_MB = iterations * TIMING_BUF_MB;
    1429 
    1430         /* Now remove the lseek() and getitimer() overheads from the elapsed time */
    1431         getitimer(ITIMER_REAL, &e1);
    1432         do {
    1433             if (seek_to_zero (fd))
    1434                 goto quit;
    1435             getitimer(ITIMER_REAL, &e2);
    1436             elapsed2 = (e1.it_value.tv_sec - e2.it_value.tv_sec)
    1437             + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0);
     1363            getitimer(ITIMER_REAL, &itv);
     1364            elapsed2 = (1000 - itv.it_value.tv_sec) * 1000000
     1365                    - itv.it_value.tv_usec;
    14381366        } while (--iterations);
    1439    
    14401367        elapsed -= elapsed2;
    1441         print_timing(BUFCACHE_FACTOR * total_MB, elapsed); 
     1368        total_MB *= BUFCACHE_FACTOR;
    14421369        flush_buffer_cache(fd);
    1443         sleep(1);
    1444     }
    1445     else /* Time device */
    1446     {
    1447         printf(" Timing buffered disk reads:  ");
    1448         fflush(stdout);
    1449         /*
    1450         * getitimer() is used rather than gettimeofday() because
    1451         * it is much more consistent (on my machine, at least).
    1452         */
    1453         /* Now do the timings for real */
    1454         iterations = 0;
    1455         getitimer(ITIMER_REAL, &e1);
    1456         do {
    1457             ++iterations;
    1458             if (read_big_block (fd, buf))
    1459                 goto quit;
    1460             getitimer(ITIMER_REAL, &e2);
    1461             elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec)
    1462             + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0);
    1463         } while (elapsed < 3.0 && iterations < max_iterations);
    1464    
    1465         total_MB = iterations * TIMING_BUF_MB;
    1466         print_timing(total_MB, elapsed);
    1467     }
    1468 quit:
     1370    }
     1371    print_timing(total_MB, elapsed / 1000000.0);
     1372 quit:
    14691373    munlock(buf, TIMING_BUF_BYTES);
    1470 quit2:
     1374 quit2:
    14711375    RELEASE_CONFIG_BUFFER(buf);
    14721376}
    14731377
    1474 static void on_off (unsigned int value)
    1475 {
    1476     printf(value ? " (on)\n" : " (off)\n");
    1477 }
    1478 
    1479 #ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
    1480 static void bus_state_value(unsigned int value)
     1378#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
     1379static void bus_state_value(unsigned value)
    14811380{
    14821381    if (value == BUSSTATE_ON)
     
    14921391
    14931392#ifdef HDIO_DRIVE_CMD
    1494 static void interpret_standby(unsigned int standby)
    1495 {
    1496     unsigned int t;
     1393static void interpret_standby(unsigned standby)
     1394{
     1395    unsigned t;
    14971396
    14981397    printf(" (");
     
    15071406    else if (standby == 255)
    15081407        printf("21 minutes + 15 seconds");
    1509     else {
    1510         if (standby <= 240) {
    1511             t = standby * 5;
    1512             printf("%u minutes + %u seconds", t / 60, t % 60);
    1513         } else if (standby <= 251) {
    1514             t = (standby - 240) * 30;
    1515             printf("%u hours + %u minutes", t / 60, t % 60);
    1516         } else
    1517             printf("illegal value");
    1518     }
     1408    else if (standby <= 240) {
     1409        t = standby * 5;
     1410        printf("%u minutes + %u seconds", t / 60, t % 60);
     1411    } else if (standby <= 251) {
     1412        t = (standby - 240) * 30;
     1413        printf("%u hours + %u minutes", t / 60, t % 60);
     1414    } else
     1415        printf("illegal value");
    15191416    printf(")\n");
    15201417}
    15211418
    1522 struct xfermode_entry {
    1523     int val;
    1524     const char *name;
     1419static const uint8_t xfermode_val[] ALIGN1 = {
     1420     8,      9,     10,     11,     12,     13,     14,     15,
     1421    16,     17,     18,     19,     20,     21,     22,     23,
     1422    32,     33,     34,     35,     36,     37,     38,     39,
     1423    64,     65,     66,     67,     68,     69,     70,     71
    15251424};
    1526 
    1527 static const struct xfermode_entry xfermode_table[] = {
    1528     { 8,    "pio0" },
    1529     { 9,    "pio1" },
    1530     { 10,   "pio2" },
    1531     { 11,   "pio3" },
    1532     { 12,   "pio4" },
    1533     { 13,   "pio5" },
    1534     { 14,   "pio6" },
    1535     { 15,   "pio7" },
    1536     { 16,   "sdma0" },
    1537     { 17,   "sdma1" },
    1538     { 18,   "sdma2" },
    1539     { 19,   "sdma3" },
    1540     { 20,   "sdma4" },
    1541     { 21,   "sdma5" },
    1542     { 22,   "sdma6" },
    1543     { 23,   "sdma7" },
    1544     { 32,   "mdma0" },
    1545     { 33,   "mdma1" },
    1546     { 34,   "mdma2" },
    1547     { 35,   "mdma3" },
    1548     { 36,   "mdma4" },
    1549     { 37,   "mdma5" },
    1550     { 38,   "mdma6" },
    1551     { 39,   "mdma7" },
    1552     { 64,   "udma0" },
    1553     { 65,   "udma1" },
    1554     { 66,   "udma2" },
    1555     { 67,   "udma3" },
    1556     { 68,   "udma4" },
    1557     { 69,   "udma5" },
    1558     { 70,   "udma6" },
    1559     { 71,   "udma7" },
    1560     { 0, NULL }
     1425/* NB: we save size by _not_ storing terninating NUL! */
     1426static const char xfermode_name[][5] ALIGN1 = {
     1427    "pio0", "pio1", "pio2", "pio3", "pio4", "pio5", "pio6", "pio7",
     1428    "sdma0","sdma1","sdma2","sdma3","sdma4","sdma5","sdma6","sdma7",
     1429    "mdma0","mdma1","mdma2","mdma3","mdma4","mdma5","mdma6","mdma7",
     1430    "udma0","udma1","udma2","udma3","udma4","udma5","udma6","udma7"
    15611431};
    15621432
    1563 static int translate_xfermode(char * name)
    1564 {
    1565     const struct xfermode_entry *tmp;
    1566     char *endptr;
    1567     int val = -1;
    1568 
    1569 
    1570     for (tmp = xfermode_table; tmp->name != NULL; ++tmp)
    1571     {
    1572         if (!strcmp(name, tmp->name))
    1573             return tmp->val;
    1574     }
    1575 
    1576     val = strtol(name, &endptr, 10);
    1577     if (*endptr == '\0')
     1433static int translate_xfermode(const char *name)
     1434{
     1435    int val, i;
     1436
     1437    for (i = 0; i < ARRAY_SIZE(xfermode_val); i++) {
     1438        if (!strncmp(name, xfermode_name[i], 5))
     1439            if (strlen(name) <= 5)
     1440                return xfermode_val[i];
     1441    }
     1442    /* Negative numbers are invalid and are caught later */
     1443    val = bb_strtoi(name, NULL, 10);
     1444    if (!errno)
    15781445        return val;
    1579 
    15801446    return -1;
    15811447}
    15821448
    1583 static void interpret_xfermode(unsigned int xfermode)
     1449static void interpret_xfermode(unsigned xfermode)
    15841450{
    15851451    printf(" (");
     
    15891455        printf("default PIO mode, disable IORDY");
    15901456    else if (xfermode >= 8 && xfermode <= 15)
    1591         printf("PIO flow control mode%u", xfermode-8);
     1457        printf("PIO flow control mode%u", xfermode - 8);
    15921458    else if (xfermode >= 16 && xfermode <= 23)
    1593         printf("singleword DMA mode%u", xfermode-16);
     1459        printf("singleword DMA mode%u", xfermode - 16);
    15941460    else if (xfermode >= 32 && xfermode <= 39)
    1595         printf("multiword DMA mode%u", xfermode-32);
     1461        printf("multiword DMA mode%u", xfermode - 32);
    15961462    else if (xfermode >= 64 && xfermode <= 71)
    1597         printf("UltraDMA mode%u", xfermode-64);
     1463        printf("UltraDMA mode%u", xfermode - 64);
    15981464    else
    15991465        printf("Unknown");
     
    16021468#endif /* HDIO_DRIVE_CMD */
    16031469
    1604 static void print_flag(unsigned long flag, char *s, unsigned long value)
    1605 {
    1606     if(flag)
     1470static void print_flag(int flag, const char *s, unsigned long value)
     1471{
     1472    if (flag)
    16071473        printf(" setting %s to %ld\n", s, value);
    16081474}
     
    16111477{
    16121478    int fd;
    1613     static long parm, multcount;
     1479    long parm, multcount;
    16141480#ifndef HDIO_DRIVE_CMD
    16151481    int force_operation = 0;
     
    16171483    /* Please restore args[n] to these values after each ioctl
    16181484       except for args[2] */
    1619     unsigned char args[4] = {WIN_SETFEATURES,0,0,0};
     1485    unsigned char args[4] = { WIN_SETFEATURES, 0, 0, 0 };
    16201486    const char *fmt = " %s\t= %2ld";
    16211487
    1622     fd = bb_xopen(devname, O_RDONLY|O_NONBLOCK);
     1488    fd = xopen(devname, O_RDONLY|O_NONBLOCK);
    16231489    printf("\n%s:\n", devname);
    16241490
    1625     if (set_readahead)
    1626     {
    1627         print_flag(get_readahead,"fs readahead", Xreadahead);
    1628         bb_ioctl(fd, BLKRASET,(int *)Xreadahead,"BLKRASET");
    1629     }
    1630 #ifdef CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
    1631     if (unregister_hwif)
    1632     {
     1491    if (set_readahead) {
     1492        print_flag(get_readahead, "fs readahead", Xreadahead);
     1493        ioctl_or_warn(fd, BLKRASET, (int *)Xreadahead);
     1494    }
     1495#if ENABLE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
     1496    if (unregister_hwif) {
    16331497        printf(" attempting to unregister hwif#%lu\n", hwif);
    1634         bb_ioctl(fd, HDIO_UNREGISTER_HWIF,(int *)(unsigned long)hwif,"HDIO_UNREGISTER_HWIF");
    1635     }
    1636 #endif
    1637 #ifdef CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF
    1638     if (scan_hwif)
    1639     {
     1498        ioctl_or_warn(fd, HDIO_UNREGISTER_HWIF, (int *)(unsigned long)hwif);
     1499    }
     1500#endif
     1501#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
     1502    if (scan_hwif) {
    16401503        printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq);
    16411504        args[0] = hwif_data;
    16421505        args[1] = hwif_ctrl;
    16431506        args[2] = hwif_irq;
    1644         bb_ioctl(fd, HDIO_SCAN_HWIF, args, "HDIO_SCAN_HWIF");
     1507        ioctl_or_warn(fd, HDIO_SCAN_HWIF, args);
    16451508        args[0] = WIN_SETFEATURES;
    16461509        args[1] = 0;
    16471510    }
    16481511#endif
    1649     if (set_piomode)
    1650     {
    1651         if (noisy_piomode)
    1652         {
     1512    if (set_piomode) {
     1513        if (noisy_piomode) {
    16531514            printf(" attempting to ");
    16541515            if (piomode == 255)
     
    16611522                printf("set UDMA mode to %d\n", (piomode-200));
    16621523        }
    1663         bb_ioctl(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode, "HDIO_SET_PIO_MODE");
    1664     }
    1665     if (set_io32bit)
    1666     {
    1667         print_flag(get_io32bit,"32-bit IO_support flag", io32bit);
    1668         bb_ioctl(fd, HDIO_SET_32BIT, (int *)io32bit, "HDIO_SET_32BIT");
    1669     }
    1670     if (set_mult)
    1671     {
     1524        ioctl_or_warn(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode);
     1525    }
     1526    if (set_io32bit) {
     1527        print_flag(get_io32bit, "32-bit IO_support flag", io32bit);
     1528        ioctl_or_warn(fd, HDIO_SET_32BIT, (int *)io32bit);
     1529    }
     1530    if (set_mult) {
    16721531        print_flag(get_mult, "multcount", mult);
    16731532#ifdef HDIO_DRIVE_CMD
    1674         bb_ioctl(fd, HDIO_SET_MULTCOUNT, &mult, "HDIO_SET_MULTCOUNT");
     1533        ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult);
    16751534#else
    1676         force_operation |= (!bb_ioctl(fd, HDIO_SET_MULTCOUNT, &mult, "HDIO_SET_MULTCOUNT"));
    1677 #endif
    1678     }
    1679     if (set_readonly)
    1680     {
    1681         print_flag_on_off(get_readonly,"readonly", readonly);
    1682         bb_ioctl(fd, BLKROSET, &readonly, "BLKROSET");
    1683     }
    1684     if (set_unmask)
    1685     {
    1686         print_flag_on_off(get_unmask,"unmaskirq", unmask);
    1687         bb_ioctl(fd, HDIO_SET_UNMASKINTR, (int *)unmask, "HDIO_SET_UNMASKINTR");
    1688     }
    1689 #ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA
    1690     if (set_dma)
    1691     {
     1535        force_operation |= (!ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult));
     1536#endif
     1537    }
     1538    if (set_readonly) {
     1539        print_flag_on_off(get_readonly, "readonly", readonly);
     1540        ioctl_or_warn(fd, BLKROSET, &readonly);
     1541    }
     1542    if (set_unmask) {
     1543        print_flag_on_off(get_unmask, "unmaskirq", unmask);
     1544        ioctl_or_warn(fd, HDIO_SET_UNMASKINTR, (int *)unmask);
     1545    }
     1546#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
     1547    if (set_dma) {
    16921548        print_flag_on_off(get_dma, "using_dma", dma);
    1693         bb_ioctl(fd, HDIO_SET_DMA, (int *)dma, "HDIO_SET_DMA");
    1694     }
    1695 #endif /* CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA */
    1696     if (set_dma_q)
    1697     {
    1698         print_flag_on_off(get_dma_q,"DMA queue_depth", dma_q);
    1699         bb_ioctl(fd, HDIO_SET_QDMA, (int *)dma_q, "HDIO_SET_QDMA");
    1700     }
    1701     if (set_nowerr)
    1702     {
    1703         print_flag_on_off(get_nowerr,"nowerr", nowerr);
    1704         bb_ioctl(fd, HDIO_SET_NOWERR, (int *)nowerr,"HDIO_SET_NOWERR");
    1705     }
    1706     if (set_keep)
    1707     {
    1708         print_flag_on_off(get_keep,"keep_settings", keep);
    1709         bb_ioctl(fd, HDIO_SET_KEEPSETTINGS, (int *)keep,"HDIO_SET_KEEPSETTINGS");
     1549        ioctl_or_warn(fd, HDIO_SET_DMA, (int *)dma);
     1550    }
     1551#endif /* FEATURE_HDPARM_HDIO_GETSET_DMA */
     1552    if (set_dma_q) {
     1553        print_flag_on_off(get_dma_q, "DMA queue_depth", dma_q);
     1554        ioctl_or_warn(fd, HDIO_SET_QDMA, (int *)dma_q);
     1555    }
     1556    if (set_nowerr) {
     1557        print_flag_on_off(get_nowerr, "nowerr", nowerr);
     1558        ioctl_or_warn(fd, HDIO_SET_NOWERR, (int *)nowerr);
     1559    }
     1560    if (set_keep) {
     1561        print_flag_on_off(get_keep, "keep_settings", keep);
     1562        ioctl_or_warn(fd, HDIO_SET_KEEPSETTINGS, (int *)keep);
    17101563    }
    17111564#ifdef HDIO_DRIVE_CMD
    1712     if (set_doorlock)
    1713     {
     1565    if (set_doorlock) {
    17141566        args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK;
    17151567        args[2] = 0;
    1716         print_flag_on_off(get_doorlock,"drive doorlock", doorlock);
    1717         bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(doorlock)");
     1568        print_flag_on_off(get_doorlock, "drive doorlock", doorlock);
     1569        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    17181570        args[0] = WIN_SETFEATURES;
    17191571    }
    1720     if (set_dkeep)
    1721     {
     1572    if (set_dkeep) {
    17221573        /* lock/unlock the drive's "feature" settings */
    1723         print_flag_on_off(get_dkeep,"drive keep features", dkeep);
     1574        print_flag_on_off(get_dkeep, "drive keep features", dkeep);
    17241575        args[2] = dkeep ? 0x66 : 0xcc;
    1725         bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(keepsettings)");
    1726     }
    1727     if (set_defects)
    1728     {
     1576        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
     1577    }
     1578    if (set_defects) {
    17291579        args[2] = defects ? 0x04 : 0x84;
    1730         print_flag(get_defects,"drive defect-mgmt", defects);
    1731         bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(defectmgmt)");
    1732     }
    1733     if (set_prefetch)
    1734     {
     1580        print_flag(get_defects, "drive defect-mgmt", defects);
     1581        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
     1582    }
     1583    if (set_prefetch) {
    17351584        args[1] = prefetch;
    17361585        args[2] = 0xab;
    1737         print_flag(get_prefetch,"drive prefetch", prefetch);
    1738         bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setprefetch)");
     1586        print_flag(get_prefetch, "drive prefetch", prefetch);
     1587        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    17391588        args[1] = 0;
    17401589    }
    1741     if (set_xfermode)
    1742     {
     1590    if (set_xfermode) {
    17431591        args[1] = xfermode_requested;
    17441592        args[2] = 3;
    1745         if (get_xfermode)
    1746         {
    1747             print_flag(1,"xfermode", xfermode_requested);
     1593        if (get_xfermode) {
     1594            print_flag(1, "xfermode", xfermode_requested);
    17481595            interpret_xfermode(xfermode_requested);
    17491596        }
    1750         bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(setxfermode)");
     1597        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    17511598        args[1] = 0;
    17521599    }
    1753     if (set_lookahead)
    1754     {
     1600    if (set_lookahead) {
    17551601        args[2] = lookahead ? 0xaa : 0x55;
    1756         print_flag_on_off(get_lookahead,"drive read-lookahead", lookahead);
    1757         bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setreadahead)");
    1758     }
    1759     if (set_apmmode)
    1760     {
     1602        print_flag_on_off(get_lookahead, "drive read-lookahead", lookahead);
     1603        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
     1604    }
     1605    if (set_apmmode) {
    17611606        args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */; /* feature register */
    17621607        args[1] = apmmode; /* sector count register 1-255 */
    17631608        if (get_apmmode)
    17641609            printf(" setting APM level to %s 0x%02lX (%ld)\n", (apmmode == 255) ? "disabled" : "", apmmode, apmmode);
    1765         bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD");
     1610        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    17661611        args[1] = 0;
    17671612    }
    1768     if (set_wcache)
    1769     {
     1613    if (set_wcache) {
    17701614#ifdef DO_FLUSHCACHE
    17711615#ifndef WIN_FLUSHCACHE
    17721616#define WIN_FLUSHCACHE 0xe7
    17731617#endif
    1774         static unsigned char flushcache[4] = {WIN_FLUSHCACHE,0,0,0};
     1618        static unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
    17751619#endif /* DO_FLUSHCACHE */
    17761620        args[2] = wcache ? 0x02 : 0x82;
    1777         print_flag_on_off(get_wcache,"drive write-caching", wcache);
     1621        print_flag_on_off(get_wcache, "drive write-caching", wcache);
    17781622#ifdef DO_FLUSHCACHE
    17791623        if (!wcache)
    1780             bb_ioctl(fd, HDIO_DRIVE_CMD, &flushcache, "HDIO_DRIVE_CMD(flushcache)");
     1624            ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
    17811625#endif /* DO_FLUSHCACHE */
    1782         bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setcache)");
     1626        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    17831627#ifdef DO_FLUSHCACHE
    17841628        if (!wcache)
    1785             bb_ioctl(fd, HDIO_DRIVE_CMD, &flushcache, "HDIO_DRIVE_CMD(flushcache)");
     1629            ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
    17861630#endif /* DO_FLUSHCACHE */
    17871631    }
     
    17911635    args[2] = 0;
    17921636
    1793     if (set_standbynow)
    1794     {
     1637    if (set_standbynow) {
    17951638#ifndef WIN_STANDBYNOW1
    17961639#define WIN_STANDBYNOW1 0xE0
     
    18011644        if (get_standbynow) printf(" issuing standby command\n");
    18021645        args[0] = WIN_STANDBYNOW1;
    1803         bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2, "HDIO_DRIVE_CMD(standby)");
    1804     }
    1805     if (set_sleepnow)
    1806     {
     1646        ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2);
     1647    }
     1648    if (set_sleepnow) {
    18071649#ifndef WIN_SLEEPNOW1
    18081650#define WIN_SLEEPNOW1 0xE6
     
    18131655        if (get_sleepnow) printf(" issuing sleep command\n");
    18141656        args[0] = WIN_SLEEPNOW1;
    1815         bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2, "HDIO_DRIVE_CMD(sleep)");
    1816     }
    1817     if (set_seagate)
    1818     {
     1657        ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2);
     1658    }
     1659    if (set_seagate) {
    18191660        args[0] = 0xfb;
    18201661        if (get_seagate) printf(" disabling Seagate auto powersaving mode\n");
    1821         bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(seagatepwrsave)");
    1822     }
    1823     if (set_standby)
    1824     {
     1662        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
     1663    }
     1664    if (set_standby) {
    18251665        args[0] = WIN_SETIDLE1;
    18261666        args[1] = standby_requested;
    1827         if (get_standby)
    1828         {
    1829             print_flag(1,"standby", standby_requested);
     1667        if (get_standby) {
     1668            print_flag(1, "standby", standby_requested);
    18301669            interpret_standby(standby_requested);
    18311670        }
    1832         bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setidle1)");
     1671        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    18331672        args[1] = 0;
    18341673    }
    18351674#else   /* HDIO_DRIVE_CMD */
    1836     if (force_operation)
    1837     {
     1675    if (force_operation) {
    18381676        char buf[512];
    18391677        flush_buffer_cache(fd);
     
    18431681#endif  /* HDIO_DRIVE_CMD */
    18441682
    1845     if (get_mult || get_identity)
    1846     {
     1683    if (get_mult || get_identity) {
    18471684        multcount = -1;
    1848         if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount))
    1849         {
    1850             if (get_mult)
     1685        if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) {
     1686            if (get_mult && ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn. */
    18511687                bb_perror_msg("HDIO_GET_MULTCOUNT");
    1852         }
    1853         else if (get_mult)
    1854         {
     1688            else
     1689                bb_perror_msg("ioctl %#x failed", HDIO_GET_MULTCOUNT);
     1690        } else if (get_mult) {
    18551691            printf(fmt, "multcount", multcount);
    1856             on_off(multcount);
    1857         }
    1858     }
    1859     if (get_io32bit)
    1860     {
    1861         if (!bb_ioctl(fd, HDIO_GET_32BIT, &parm, "HDIO_GET_32BIT"))
    1862         {
     1692            on_off(multcount != 0);
     1693        }
     1694    }
     1695    if (get_io32bit) {
     1696        if (!ioctl_or_warn(fd, HDIO_GET_32BIT, &parm)) {
    18631697            printf(" IO_support\t=%3ld (", parm);
    18641698            if (parm == 0)
     
    18761710        }
    18771711    }
    1878     if (get_unmask)
    1879     {
    1880         bb_ioctl_on_off(fd, HDIO_GET_UNMASKINTR,(unsigned long *)parm,
    1881                         "HDIO_GET_UNMASKINTR","unmaskirq");
    1882     }
    1883 
    1884 
    1885 #ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA
     1712    if (get_unmask) {
     1713        if(!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, (unsigned long *)parm))
     1714            print_value_on_off("unmaskirq", parm);
     1715    }
     1716
     1717
     1718#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
    18861719    if (get_dma) {
    1887         if (!bb_ioctl(fd, HDIO_GET_DMA, &parm, "HDIO_GET_DMA"))
    1888         {
     1720        if (!ioctl_or_warn(fd, HDIO_GET_DMA, &parm)) {
    18891721            printf(fmt, "using_dma", parm);
    18901722            if (parm == 8)
    18911723                printf(" (DMA-Assisted-PIO)\n");
    18921724            else
    1893                 on_off(parm);
    1894         }
    1895     }
    1896 #endif
    1897     if (get_dma_q)
    1898     {
    1899         bb_ioctl_on_off (fd, HDIO_GET_QDMA,(unsigned long *)parm,
    1900                           "HDIO_GET_QDMA","queue_depth");
    1901     }
    1902     if (get_keep)
    1903     {
    1904         bb_ioctl_on_off (fd, HDIO_GET_KEEPSETTINGS,(unsigned long *)parm,
    1905                             "HDIO_GET_KEEPSETTINGS","keepsettings");
    1906     }
    1907 
    1908     if (get_nowerr)
    1909     {
    1910         bb_ioctl_on_off  (fd, HDIO_GET_NOWERR,(unsigned long *)&parm,
    1911                             "HDIO_GET_NOWERR","nowerr");
    1912     }
    1913     if (get_readonly)
    1914     {
    1915         bb_ioctl_on_off(fd, BLKROGET,(unsigned long *)parm,
    1916                           "BLKROGET","readonly");
    1917     }
    1918     if (get_readahead)
    1919     {
    1920         bb_ioctl_on_off (fd, BLKRAGET, (unsigned long *) parm,
    1921                             "BLKRAGET","readahead");
    1922     }
    1923     if (get_geom)
    1924     {
    1925         if (!bb_ioctl(fd, BLKGETSIZE, &parm, "BLKGETSIZE"))
    1926         {
     1725                on_off(parm != 0);
     1726        }
     1727    }
     1728#endif
     1729    if (get_dma_q) {
     1730        if(!ioctl_or_warn(fd, HDIO_GET_QDMA, (unsigned long *)parm))
     1731            print_value_on_off("queue_depth", parm);
     1732    }
     1733    if (get_keep) {
     1734        if(!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, (unsigned long *)parm))
     1735            print_value_on_off("keepsettings", parm);
     1736    }
     1737
     1738    if (get_nowerr) {
     1739        if(!ioctl_or_warn(fd, HDIO_GET_NOWERR, (unsigned long *)parm))
     1740            print_value_on_off("nowerr", parm);
     1741    }
     1742    if (get_readonly) {
     1743        if(!ioctl_or_warn(fd, BLKROGET, (unsigned long *)parm))
     1744            print_value_on_off("readonly", parm);
     1745    }
     1746    if (get_readahead) {
     1747        if(!ioctl_or_warn(fd, BLKRAGET, (unsigned long *)parm))
     1748            print_value_on_off("readahead", parm);
     1749    }
     1750    if (get_geom) {
     1751        if (!ioctl_or_warn(fd, BLKGETSIZE, &parm)) {
    19271752            struct hd_geometry g;
    19281753
    1929             if (!bb_ioctl(fd, HDIO_GETGEO, &g, "HDIO_GETGEO"))
     1754            if (!ioctl_or_warn(fd, HDIO_GETGEO, &g))
    19301755                printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n",
    19311756                        g.cylinders, g.heads, g.sectors, parm, g.start);
     
    19331758    }
    19341759#ifdef HDIO_DRIVE_CMD
    1935     if (get_powermode)
    1936     {
     1760    if (get_powermode) {
    19371761#ifndef WIN_CHECKPOWERMODE1
    19381762#define WIN_CHECKPOWERMODE1 0xE5
     
    19441768
    19451769        args[0] = WIN_CHECKPOWERMODE1;
    1946         if (bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2, 0))
    1947         {
     1770        if (ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) {
    19481771            if (errno != EIO || args[0] != 0 || args[1] != 0)
    1949                 state = "Unknown";
     1772                state = "unknown";
    19501773            else
    19511774                state = "sleeping";
    1952         }
    1953         else
     1775        } else
    19541776            state = (args[2] == 255) ? "active/idle" : "standby";
    19551777        args[1] = args[2] = 0;
     
    19581780    }
    19591781#endif
    1960 #ifdef CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET
    1961     if (perform_reset)
    1962     {
    1963         bb_ioctl(fd, HDIO_DRIVE_RESET, NULL, "HDIO_DRIVE_RESET");
    1964     }
    1965 #endif /* CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET */
    1966 #ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
    1967     if (perform_tristate)
    1968     {
     1782#if ENABLE_FEATURE_HDPARM_HDIO_DRIVE_RESET
     1783    if (perform_reset) {
     1784        ioctl_or_warn(fd, HDIO_DRIVE_RESET, NULL);
     1785    }
     1786#endif /* FEATURE_HDPARM_HDIO_DRIVE_RESET */
     1787#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
     1788    if (perform_tristate) {
    19691789        args[0] = 0;
    19701790        args[1] = tristate;
    1971         bb_ioctl(fd, HDIO_TRISTATE_HWIF, &args, "HDIO_TRISTATE_HWIF");
    1972     }
    1973 #endif /* CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF */
    1974 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
    1975     if (get_identity)
    1976     {
    1977         static struct hd_driveid id;
    1978 
    1979         if (!ioctl(fd, HDIO_GET_IDENTITY, &id))
    1980         {
    1981             if (multcount != -1)
    1982             {
     1791        ioctl_or_warn(fd, HDIO_TRISTATE_HWIF, &args);
     1792    }
     1793#endif /* FEATURE_HDPARM_HDIO_TRISTATE_HWIF */
     1794#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
     1795    if (get_identity) {
     1796        struct hd_driveid id;
     1797
     1798        if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) {
     1799            if (multcount != -1) {
    19831800                id.multsect = multcount;
    19841801                id.multsect_valid |= 1;
    1985             }
    1986             else
     1802            } else
    19871803                id.multsect_valid &= ~1;
    19881804            dump_identity(&id);
    1989         }
    1990         else if (errno == -ENOMSG)
     1805        } else if (errno == -ENOMSG)
    19911806            printf(" no identification info available\n");
     1807        else if (ENABLE_IOCTL_HEX2STR_ERROR)  /* To be coherent with ioctl_or_warn */
     1808            bb_perror_msg("HDIO_GET_IDENTITY");
    19921809        else
    1993             bb_perror_msg("HDIO_GET_IDENTITY");
    1994     }
    1995 
    1996     if (get_IDentity)
    1997     {
     1810            bb_perror_msg("ioctl %#x failed", HDIO_GET_IDENTITY);
     1811    }
     1812
     1813    if (get_IDentity) {
    19981814        unsigned char args1[4+512]; /* = { ... } will eat 0.5k of rodata! */
    19991815
     
    20011817        args1[0] = WIN_IDENTIFY;
    20021818        args1[3] = 1;
    2003         if (!bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY, "HDIO_DRIVE_CMD(identify)"))
     1819        if (!ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY))
    20041820            identify((void *)(args1 + 4));
    20051821    }
    20061822#endif
    2007 #ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
    2008     if (set_busstate)
    2009     {
    2010         if (get_busstate)
    2011         {
     1823#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
     1824    if (set_busstate) {
     1825        if (get_busstate) {
    20121826            print_flag(1, "bus state", busstate);
    20131827            bus_state_value(busstate);
    20141828        }
    2015         bb_ioctl(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate, "HDIO_SET_BUSSTATE");
    2016     }
    2017     if (get_busstate)
    2018     {
    2019         if (!bb_ioctl(fd, HDIO_GET_BUSSTATE, &parm, "HDIO_GET_BUSSTATE"))
    2020         {
     1829        ioctl_or_warn(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate);
     1830    }
     1831    if (get_busstate) {
     1832        if (!ioctl_or_warn(fd, HDIO_GET_BUSSTATE, &parm)) {
    20211833            printf(fmt, "bus state", parm);
    20221834            bus_state_value(parm);
     
    20251837#endif
    20261838    if (reread_partn)
    2027         bb_ioctl(fd, BLKRRPART, NULL, "BLKRRPART");
    2028 
     1839        ioctl_or_warn(fd, BLKRRPART, NULL);
    20291840
    20301841    if (do_ctimings)
    2031         do_time(0,fd);      /*time cache */
     1842        do_time(0, fd); /* time cache */
    20321843    if (do_timings)
    2033         do_time(1,fd);      /*time device */
     1844        do_time(1, fd); /* time device */
    20341845    if (do_flush)
    20351846        flush_buffer_cache(fd);
     
    20371848}
    20381849
    2039 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
     1850#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
    20401851static int fromhex(unsigned char c)
    20411852{
     1853    if (isdigit(c))
     1854        return (c - '0');
    20421855    if (c >= 'a' && c <= 'f')
    2043         return 10 + (c - 'a');
    2044     if (c >= '0' && c <= '9')
    2045         return (c - '0');
     1856        return (c - ('a' - 10));
    20461857    bb_error_msg_and_die("bad char: '%c' 0x%02x", c, c);
    20471858}
     
    20501861{
    20511862    uint16_t sbuf[256];
    2052     unsigned char  buf[1280], *b = (unsigned char *)buf;
    2053     int i, count = read(0, buf, 1280);
    2054 
    2055     if (count != 1280)
    2056         bb_error_msg_and_die("read(%d bytes) failed (rc=%d)", 1280, count);
     1863    unsigned char buf[1280];
     1864    unsigned char *b = (unsigned char *)buf;
     1865    int i;
     1866
     1867    xread(0, buf, 1280);
    20571868
    20581869    // Convert the newline-separated hex data into an identify block.
    20591870
    2060     for (i = 0; i<256; i++)
    2061     {
     1871    for (i = 0; i < 256; i++) {
    20621872        int j;
    2063         for(j=0;j<4;j++) sbuf[i] = (sbuf[i] <<4) + fromhex(*(b++));
     1873        for (j = 0; j < 4; j++)
     1874            sbuf[i] = (sbuf[i] << 4) + fromhex(*(b++));
    20641875    }
    20651876
     
    20711882
    20721883/* busybox specific stuff */
    2073 static void parse_opts(unsigned long *get, unsigned long *set, unsigned long *value, int min, int max)
    2074 {
    2075         if (get) {
    2076             *get = 1;
    2077         }
    2078         if (optarg) {
    2079             *set = 1;
    2080             *value = bb_xgetlarg(optarg, 10, min, max);
    2081         }
    2082 }
    2083 
    2084 static void parse_xfermode(int flag, unsigned long *get, unsigned long *set, int *value)
     1884static void parse_opts(smallint *get, smallint *set, unsigned long *value, int min, int max)
     1885{
     1886    if (get) {
     1887        *get = 1;
     1888    }
     1889    if (optarg) {
     1890        *set = 1;
     1891        *value = xatol_range(optarg, min, max);
     1892    }
     1893}
     1894
     1895static void parse_xfermode(int flag, smallint *get, smallint *set, int *value)
    20851896{
    20861897    if (flag) {
    20871898        *get = 1;
    20881899        if (optarg) {
    2089             *set = ((*value = translate_xfermode(optarg)) > -1);
     1900            *value = translate_xfermode(optarg);
     1901            *set = (*value > -1);
    20901902        }
    20911903    }
     
    20931905
    20941906/*------- getopt short options --------*/
    2095 static const char hdparm_options[]= "gfu::n::p:r::m::c::k::a::B:tTh"\
     1907static const char hdparm_options[] ALIGN1 =
     1908    "gfu::n::p:r::m::c::k::a::B:tTh"
    20961909    USE_FEATURE_HDPARM_GET_IDENTITY("iI")
    20971910    USE_FEATURE_HDPARM_HDIO_GETSET_DMA("d::")
    20981911#ifdef HDIO_DRIVE_CMD
    2099                                     "S:D:P:X:K:A:L:W:CyYzZ"
     1912    "S:D:P:X:K:A:L:W:CyYzZ"
    21001913#endif
    21011914    USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:")
    21021915#ifdef HDIO_GET_QDMA
    21031916#ifdef HDIO_SET_QDMA
    2104                                     "Q:"
     1917    "Q:"
    21051918#else
    2106                                     "Q"
     1919    "Q"
    21071920#endif
    21081921#endif
     
    21131926
    21141927/* our main() routine: */
    2115 int hdparm_main(int argc, char **argv) ATTRIBUTE_NORETURN;
     1928int hdparm_main(int argc, char **argv);
    21161929int hdparm_main(int argc, char **argv)
    21171930{
     
    21291942        USE_FEATURE_HDPARM_HDIO_GETSET_DMA(if (c == 'd') parse_opts(&get_dma, &set_dma, &dma, 0, 9));
    21301943        if (c == 'n') parse_opts(&get_nowerr, &set_nowerr, &nowerr, 0, 1);
    2131         parse_xfermode((c == 'p'),&noisy_piomode, &set_piomode, &piomode);
     1944        parse_xfermode((c == 'p'), &noisy_piomode, &set_piomode, &piomode);
    21321945        if (c == 'r') parse_opts(&get_readonly, &set_readonly, &readonly, 0, 1);
    21331946        if (c == 'm') parse_opts(&get_mult, &set_mult, &mult, 0, INT_MAX /*32*/);
     
    21391952        do_flush |= do_ctimings |= (c == 'T');
    21401953#ifdef HDIO_DRIVE_CMD
    2141         if (c == 'S') parse_opts(&get_standby, &set_standby, &standby_requested, 0, INT_MAX);   
     1954        if (c == 'S') parse_opts(&get_standby, &set_standby, &standby_requested, 0, INT_MAX);
    21421955        if (c == 'D') parse_opts(&get_defects, &set_defects, &defects, 0, INT_MAX);
    21431956        if (c == 'P') parse_opts(&get_prefetch, &set_prefetch, &prefetch, 0, INT_MAX);
     
    21531966        get_seagate = set_seagate |= (c == 'Z');
    21541967#endif
    2155         USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') parse_opts(NULL, &unregister_hwif, &hwif, 0, INT_MAX));   
     1968        USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') parse_opts(NULL, &unregister_hwif, &hwif, 0, INT_MAX));
    21561969#ifdef HDIO_GET_QDMA
    21571970        if (c == 'Q') {
     
    21591972            parse_opts(&get_dma_q, &set_dma_q, &dma_q, 0, INT_MAX);
    21601973#else
    2161             parse_opts(&get_dma_q, NULL, NULL, 0, 0);   
    2162 #endif
    2163         }
    2164 #endif     
     1974            parse_opts(&get_dma_q, NULL, NULL, 0, 0);
     1975#endif
     1976        }
     1977#endif
    21651978        USE_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r'));
    2166         USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') parse_opts(NULL, &perform_tristate, &tristate, 0, 1)); 
    2167         USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') parse_opts(&get_busstate, &set_busstate, &busstate, 0, 2)); 
     1979        USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') parse_opts(NULL, &perform_tristate, &tristate, 0, 1));
     1980        USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') parse_opts(&get_busstate, &set_busstate, &busstate, 0, 2));
    21681981#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
    21691982        if (c == 'R') {
    2170             parse_opts(NULL, &scan_hwif, &hwif_data, 0, INT_MAX);   
    2171             hwif_ctrl =  bb_xgetlarg((argv[optind]) ? argv[optind] : "", 10, 0, INT_MAX);
    2172             hwif_irq  =  bb_xgetlarg((argv[optind+1]) ? argv[optind+1] : "", 10, 0, INT_MAX);
     1983            parse_opts(NULL, &scan_hwif, &hwif_data, 0, INT_MAX);
     1984            hwif_ctrl = xatoi_u((argv[optind]) ? argv[optind] : "");
     1985            hwif_irq  = xatoi_u((argv[optind+1]) ? argv[optind+1] : "");
    21731986            /* Move past the 2 additional arguments */
    21741987            argv += 2;
     
    21781991    }
    21791992    /* When no flags are given (flagcount = 0), -acdgkmnru is assumed. */
    2180     if (!flagcount){
     1993    if (!flagcount) {
    21811994        get_mult = get_io32bit = get_unmask = get_keep = get_readonly = get_readahead = get_geom = 1;
    21821995        USE_FEATURE_HDPARM_HDIO_GETSET_DMA(get_dma = 1);
    21831996    }
    2184     argc -= optind;
    21851997    argv += optind;
    21861998
    2187     if (argc < 1) {
     1999    if (!*argv) {
    21882000        if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO))
    21892001            identify_from_stdin(); /* EXIT */
     
    21912003    }
    21922004
    2193     while (argc--) {
    2194         process_dev(*argv);
    2195         argv++;
    2196     }
    2197     exit(EXIT_SUCCESS);
    2198 }
     2005    do {
     2006        process_dev(*argv++);
     2007    } while (*argv);
     2008
     2009    return EXIT_SUCCESS;
     2010}
  • branches/2.2.5/mindi-busybox/miscutils/last.c

    r821 r1765  
    55 * Copyright (C) 2003-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     7 * Licensed under the GPL version 2, see the file LICENSE in this tarball.
    88 */
    99
    10 #include "busybox.h"
    11 #include <sys/types.h>
    12 #include <fcntl.h>
    13 #include <unistd.h>
    14 #include <stdlib.h>
     10#include "libbb.h"
    1511#include <utmp.h>
    16 #include <sys/stat.h>
    17 #include <errno.h>
    18 #include <string.h>
    19 #include <time.h>
    2012
    2113#ifndef SHUTDOWN_TIME
     
    3527#endif
    3628
     29int last_main(int argc, char **argv);
    3730int last_main(int argc, char **argv)
    3831{
     
    4437        bb_show_usage();
    4538    }
    46     file = bb_xopen(bb_path_wtmp_file, O_RDONLY);
     39    file = xopen(bb_path_wtmp_file, O_RDONLY);
    4740
    4841    printf("%-10s %-14s %-18s %-12.12s %s\n", "USER", "TTY", "HOST", "LOGIN", "TIME");
     
    5346        }
    5447
    55         if (strncmp(ut.ut_line, "~", 1) == 0) {
     48        if (ut.ut_line[0] == '~') {
    5649            if (strncmp(ut.ut_user, "shutdown", 8) == 0)
    5750                ut.ut_type = SHUTDOWN_TIME;
     
    9689    }
    9790
    98     bb_fflush_stdout_and_exit(EXIT_SUCCESS);
     91    fflush_stdout_and_exit(EXIT_SUCCESS);
    9992}
  • branches/2.2.5/mindi-busybox/miscutils/less.c

    r821 r1765  
    99
    1010/*
    11  *      This program needs a lot of development, so consider it in a beta stage
    12  *      at best.
     11 * TODO:
     12 * - Add more regular expression support - search modifiers, certain matches, etc.
     13 * - Add more complex bracket searching - currently, nested brackets are
     14 *   not considered.
     15 * - Add support for "F" as an input. This causes less to act in
     16 *   a similar way to tail -f.
     17 * - Allow horizontal scrolling.
    1318 *
    14  *      TODO:
    15  *      - Add more regular expression support - search modifiers, certain matches, etc.
    16  *      - Add more complex bracket searching - currently, nested brackets are
    17  *      not considered.
    18  *      - Add support for "F" as an input. This causes less to act in
    19  *      a similar way to tail -f.
    20  *      - Check for binary files, and prompt the user if a binary file
    21  *      is detected.
    22  *      - Allow horizontal scrolling. Currently, lines simply continue onto
    23  *      the next line, per the terminal's discretion
    24  *
    25  *      Notes:
    26  *      - filename is an array and not a pointer because that avoids all sorts
    27  *      of complications involving the fact that something that is pointed to
    28  *      will be changed if the pointer is changed.
    29  *      - the inp file pointer is used so that keyboard input works after
    30  *      redirected input has been read from stdin
    31 */
    32 
    33 #include "busybox.h"
    34 #include <stdio.h>
    35 #include <stdlib.h>
    36 #include <string.h>
    37 #include <termios.h>
    38 #include <unistd.h>
    39 #include <ctype.h>
    40 
    41 #ifdef CONFIG_FEATURE_LESS_REGEXP
     19 * Notes:
     20 * - the inp file pointer is used so that keyboard input works after
     21 *   redirected input has been read from stdin
     22 */
     23
     24#include <sched.h>  /* sched_yield() */
     25
     26#include "libbb.h"
     27#if ENABLE_FEATURE_LESS_REGEXP
    4228#include "xregex.h"
    4329#endif
    4430
    45 
    46 /* These are the escape sequences corresponding to special keys */
    47 #define REAL_KEY_UP 'A'
    48 #define REAL_KEY_DOWN 'B'
    49 #define REAL_KEY_RIGHT 'C'
    50 #define REAL_KEY_LEFT 'D'
    51 #define REAL_PAGE_UP '5'
    52 #define REAL_PAGE_DOWN '6'
    53 
    54 /* These are the special codes assigned by this program to the special keys */
    55 #define PAGE_UP 20
    56 #define PAGE_DOWN 21
    57 #define KEY_UP 22
    58 #define KEY_DOWN 23
    59 #define KEY_RIGHT 24
    60 #define KEY_LEFT 25
     31/* FIXME: currently doesn't work right */
     32#undef ENABLE_FEATURE_LESS_FLAGCS
     33#define ENABLE_FEATURE_LESS_FLAGCS 0
    6134
    6235/* The escape codes for highlighted and normal text */
    6336#define HIGHLIGHT "\033[7m"
    6437#define NORMAL "\033[0m"
    65 
    6638/* The escape code to clear the screen */
    6739#define CLEAR "\033[H\033[J"
    68 
    69 /* Maximum number of lines in a file */
    70 #define MAXLINES 10000
    71 
    72 static int height;
    73 static int width;
    74 static char **files;
    75 static char filename[256];
    76 static char **buffer;
    77 static char **flines;
    78 static int current_file = 1;
    79 static int line_pos;
    80 static int num_flines;
    81 static int num_files = 1;
    82 static int past_eof;
     40/* The escape code to clear to end of line */
     41#define CLEAR_2_EOL "\033[K"
     42
     43/* These are the escape sequences corresponding to special keys */
     44enum {
     45    REAL_KEY_UP = 'A',
     46    REAL_KEY_DOWN = 'B',
     47    REAL_KEY_RIGHT = 'C',
     48    REAL_KEY_LEFT = 'D',
     49    REAL_PAGE_UP = '5',
     50    REAL_PAGE_DOWN = '6',
     51    REAL_KEY_HOME = '7', // vt100? linux vt? or what?
     52    REAL_KEY_END = '8',
     53    REAL_KEY_HOME_ALT = '1', // ESC [1~ (vt100? linux vt? or what?)
     54    REAL_KEY_END_ALT = '4', // ESC [4~
     55    REAL_KEY_HOME_XTERM = 'H',
     56    REAL_KEY_END_XTERM = 'F',
     57
     58/* These are the special codes assigned by this program to the special keys */
     59    KEY_UP = 20,
     60    KEY_DOWN = 21,
     61    KEY_RIGHT = 22,
     62    KEY_LEFT = 23,
     63    PAGE_UP = 24,
     64    PAGE_DOWN = 25,
     65    KEY_HOME = 26,
     66    KEY_END = 27,
     67
     68/* Absolute max of lines eaten */
     69    MAXLINES = CONFIG_FEATURE_LESS_MAXLINES,
     70
     71/* This many "after the end" lines we will show (at max) */
     72    TILDES = 1,
     73};
    8374
    8475/* Command line options */
    85 static unsigned long flags;
    86 #define FLAG_E 1
    87 #define FLAG_M (1<<1)
    88 #define FLAG_m (1<<2)
    89 #define FLAG_N (1<<3)
    90 #define FLAG_TILDE (1<<4)
    91 
    92 /* This is needed so that program behaviour changes when input comes from
    93    stdin */
    94 static int inp_stdin;
    95 
    96 #ifdef CONFIG_FEATURE_LESS_MARKS
    97 static int mark_lines[15][2];
    98 static int num_marks;
    99 #endif
    100 
    101 #ifdef CONFIG_FEATURE_LESS_REGEXP
    102 static int match_found;
    103 static int *match_lines;
    104 static int match_pos;
    105 static int num_matches;
    106 static int match_backwards;
    107 static regex_t old_pattern;
    108 #endif
    109 
    110 /* Needed termios structures */
    111 static struct termios term_orig, term_vi;
    112 
    113 /* File pointer to get input from */
    114 static FILE *inp;
     76enum {
     77    FLAG_E = 1,
     78    FLAG_M = 1 << 1,
     79    FLAG_m = 1 << 2,
     80    FLAG_N = 1 << 3,
     81    FLAG_TILDE = 1 << 4,
     82/* hijack command line options variable for internal state vars */
     83    LESS_STATE_MATCH_BACKWARDS = 1 << 15,
     84};
     85
     86#if !ENABLE_FEATURE_LESS_REGEXP
     87enum { pattern_valid = 0 };
     88#endif
     89
     90struct globals {
     91    int cur_fline; /* signed */
     92    int kbd_fd;  /* fd to get input from */
     93/* last position in last line, taking into account tabs */
     94    size_t linepos;
     95    unsigned max_displayed_line;
     96    unsigned max_fline;
     97    unsigned max_lineno; /* this one tracks linewrap */
     98    unsigned width;
     99    ssize_t eof_error; /* eof if 0, error if < 0 */
     100    size_t readpos;
     101    size_t readeof;
     102    const char **buffer;
     103    const char **flines;
     104    const char *empty_line_marker;
     105    unsigned num_files;
     106    unsigned current_file;
     107    char *filename;
     108    char **files;
     109#if ENABLE_FEATURE_LESS_MARKS
     110    unsigned num_marks;
     111    unsigned mark_lines[15][2];
     112#endif
     113#if ENABLE_FEATURE_LESS_REGEXP
     114    unsigned *match_lines;
     115    int match_pos; /* signed! */
     116    unsigned num_matches;
     117    regex_t pattern;
     118    smallint pattern_valid;
     119#endif
     120    smallint terminated;
     121    struct termios term_orig, term_less;
     122};
     123#define G (*ptr_to_globals)
     124#define cur_fline           (G.cur_fline         )
     125#define kbd_fd              (G.kbd_fd            )
     126#define linepos             (G.linepos           )
     127#define max_displayed_line  (G.max_displayed_line)
     128#define max_fline           (G.max_fline         )
     129#define max_lineno          (G.max_lineno        )
     130#define width               (G.width             )
     131#define eof_error           (G.eof_error         )
     132#define readpos             (G.readpos           )
     133#define readeof             (G.readeof           )
     134#define buffer              (G.buffer            )
     135#define flines              (G.flines            )
     136#define empty_line_marker   (G.empty_line_marker )
     137#define num_files           (G.num_files         )
     138#define current_file        (G.current_file      )
     139#define filename            (G.filename          )
     140#define files               (G.files             )
     141#define num_marks           (G.num_marks         )
     142#define mark_lines          (G.mark_lines        )
     143#if ENABLE_FEATURE_LESS_REGEXP
     144#define match_lines         (G.match_lines       )
     145#define match_pos           (G.match_pos         )
     146#define num_matches         (G.num_matches       )
     147#define pattern             (G.pattern           )
     148#define pattern_valid       (G.pattern_valid     )
     149#endif
     150#define terminated          (G.terminated        )
     151#define term_orig           (G.term_orig         )
     152#define term_less           (G.term_less         )
     153#define INIT_G() do { \
     154        PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
     155        empty_line_marker = "~"; \
     156        num_files = 1; \
     157        current_file = 1; \
     158        eof_error = 1; \
     159        terminated = 1; \
     160    } while (0)
    115161
    116162/* Reset terminal input to normal */
     
    118164{
    119165    fflush(stdout);
    120     tcsetattr(fileno(inp), TCSANOW, &term_orig);
    121 }
    122 
    123 /* Set terminal input to raw mode  (taken from vi.c) */
    124 static void set_tty_raw(void)
    125 {
    126     tcsetattr(fileno(inp), TCSANOW, &term_vi);
     166    tcsetattr(kbd_fd, TCSANOW, &term_orig);
    127167}
    128168
    129169/* Exit the program gracefully */
    130 static void tless_exit(int code)
     170static void less_exit(int code)
    131171{
    132172    /* TODO: We really should save the terminal state when we start,
    133          and restore it when we exit. Less does this with the
    134          "ti" and "te" termcap commands; can this be done with
    135          only termios.h? */
    136 
     173     * and restore it when we exit. Less does this with the
     174     * "ti" and "te" termcap commands; can this be done with
     175     * only termios.h? */
    137176    putchar('\n');
    138     exit(code);
    139 }
    140 
    141 /* Grab a character from input without requiring the return key. If the
    142    character is ASCII \033, get more characters and assign certain sequences
    143    special return codes. Note that this function works best with raw input. */
    144 static int tless_getch(void)
    145 {
    146     int input;
    147 
    148     set_tty_raw();
    149 
    150     input = getc(inp);
    151     /* Detect escape sequences (i.e. arrow keys) and handle
    152        them accordingly */
    153 
    154     if (input == '\033' && getc(inp) == '[') {
    155         input = getc(inp);
    156         set_tty_cooked();
    157         if (input == REAL_KEY_UP)
    158             return KEY_UP;
    159         else if (input == REAL_KEY_DOWN)
    160             return KEY_DOWN;
    161         else if (input == REAL_KEY_RIGHT)
    162             return KEY_RIGHT;
    163         else if (input == REAL_KEY_LEFT)
    164             return KEY_LEFT;
    165         else if (input == REAL_PAGE_UP)
    166             return PAGE_UP;
    167         else if (input == REAL_PAGE_DOWN)
    168             return PAGE_DOWN;
    169     }
    170     /* The input is a normal ASCII value */
    171     else {
    172         set_tty_cooked();
    173         return input;
    174     }
    175     return 0;
     177    fflush_stdout_and_exit(code);
    176178}
    177179
    178180/* Move the cursor to a position (x,y), where (0,0) is the
    179181   top-left corner of the console */
    180 static void move_cursor(int x, int y)
    181 {
    182     printf("\033[%i;%iH", x, y);
     182static void move_cursor(int line, int row)
     183{
     184    printf("\033[%u;%uH", line, row);
    183185}
    184186
    185187static void clear_line(void)
    186188{
    187     move_cursor(height, 0);
    188     printf("\033[K");
    189 }
    190 
    191 /* This adds line numbers to every line, as the -N flag necessitates */
    192 static void add_linenumbers(void)
    193 {
    194     char current_line[256];
    195     int i;
    196 
    197     for (i = 0; i <= num_flines; i++) {
    198         safe_strncpy(current_line, flines[i], 256);
    199         flines[i] = bb_xasprintf("%5d %s", i + 1, current_line);
    200     }
    201 }
    202 
    203 static void data_readlines(void)
    204 {
    205     int i;
    206     char current_line[256];
    207     FILE *fp;
    208 
    209     fp = (inp_stdin) ? stdin : bb_xfopen(filename, "r");
    210     flines = NULL;
    211     for (i = 0; (feof(fp)==0) && (i <= MAXLINES); i++) {
    212         strcpy(current_line, "");
    213         fgets(current_line, 256, fp);
    214         if (fp != stdin)
    215             bb_xferror(fp, filename);
    216         flines = xrealloc(flines, (i+1) * sizeof(char *));
    217         flines[i] = bb_xstrdup(current_line);
    218     }
    219     num_flines = i - 2;
    220 
    221     /* Reset variables for a new file */
    222 
    223     line_pos = 0;
    224     past_eof = 0;
    225 
    226     fclose(fp);
    227 
    228     if (inp == NULL)
    229         inp = (inp_stdin) ? bb_xfopen(CURRENT_TTY, "r") : stdin;
    230 
    231     if (flags & FLAG_N)
    232         add_linenumbers();
    233 }
    234 
    235 #ifdef CONFIG_FEATURE_LESS_FLAGS
    236 
    237 /* Interestingly, writing calc_percent as a function and not a prototype saves around 32 bytes
     189    printf("\033[%u;0H" CLEAR_2_EOL, max_displayed_line + 2);
     190}
     191
     192static void print_hilite(const char *str)
     193{
     194    printf(HIGHLIGHT"%s"NORMAL, str);
     195}
     196
     197static void print_statusline(const char *str)
     198{
     199    clear_line();
     200    printf(HIGHLIGHT"%.*s"NORMAL, width - 1, str);
     201}
     202
     203#if ENABLE_FEATURE_LESS_REGEXP
     204static void fill_match_lines(unsigned pos);
     205#else
     206#define fill_match_lines(pos) ((void)0)
     207#endif
     208
     209/* Devilishly complex routine.
     210 *
     211 * Has to deal with EOF and EPIPE on input,
     212 * with line wrapping, with last line not ending in '\n'
     213 * (possibly not ending YET!), with backspace and tabs.
     214 * It reads input again if last time we got an EOF (thus supporting
     215 * growing files) or EPIPE (watching output of slow process like make).
     216 *
     217 * Variables used:
     218 * flines[] - array of lines already read. Linewrap may cause
     219 *      one source file line to occupy several flines[n].
     220 * flines[max_fline] - last line, possibly incomplete.
     221 * terminated - 1 if flines[max_fline] is 'terminated'
     222 *      (if there was '\n' [which isn't stored itself, we just remember
     223 *      that it was seen])
     224 * max_lineno - last line's number, this one doesn't increment
     225 *      on line wrap, only on "real" new lines.
     226 * readbuf[0..readeof-1] - small preliminary buffer.
     227 * readbuf[readpos] - next character to add to current line.
     228 * linepos - screen line position of next char to be read
     229 *      (takes into account tabs and backspaces)
     230 * eof_error - < 0 error, == 0 EOF, > 0 not EOF/error
     231 */
     232static void read_lines(void)
     233{
     234#define readbuf bb_common_bufsiz1
     235    char *current_line, *p;
     236    USE_FEATURE_LESS_REGEXP(unsigned old_max_fline = max_fline;)
     237    int w = width;
     238    char last_terminated = terminated;
     239
     240    if (option_mask32 & FLAG_N)
     241        w -= 8;
     242
     243    current_line = xmalloc(w);
     244    p = current_line;
     245    max_fline += last_terminated;
     246    if (!last_terminated) {
     247        const char *cp = flines[max_fline];
     248        if (option_mask32 & FLAG_N)
     249            cp += 8;
     250        strcpy(current_line, cp);
     251        p += strlen(current_line);
     252        /* linepos is still valid from previous read_lines() */
     253    } else {
     254        linepos = 0;
     255    }
     256
     257    while (1) {
     258 again:
     259        *p = '\0';
     260        terminated = 0;
     261        while (1) {
     262            char c;
     263            /* if no unprocessed chars left, eat more */
     264            if (readpos >= readeof) {
     265                smallint yielded = 0;
     266
     267                ndelay_on(0);
     268 read_again:
     269                eof_error = safe_read(0, readbuf, sizeof(readbuf));
     270                readpos = 0;
     271                readeof = eof_error;
     272                if (eof_error < 0) {
     273                    if (errno == EAGAIN && !yielded) {
     274            /* We can hit EAGAIN while searching for regexp match.
     275             * Yield is not 100% reliable solution in general,
     276             * but for less it should be good enough -
     277             * we give stdin supplier some CPU time to produce
     278             * more input. We do it just once.
     279             * Currently, we do not stop when we found the Nth
     280             * occurrence we were looking for. We read till end
     281             * (or double EAGAIN). TODO? */
     282                        sched_yield();
     283                        yielded = 1;
     284                        goto read_again;
     285                    }
     286                    readeof = 0;
     287                    if (errno != EAGAIN)
     288                        print_statusline("read error");
     289                }
     290                ndelay_off(0);
     291
     292                if (eof_error <= 0) {
     293                    goto reached_eof;
     294                }
     295            }
     296            c = readbuf[readpos];
     297            /* backspace? [needed for manpages] */
     298            /* <tab><bs> is (a) insane and */
     299            /* (b) harder to do correctly, so we refuse to do it */
     300            if (c == '\x8' && linepos && p[-1] != '\t') {
     301                readpos++; /* eat it */
     302                linepos--;
     303            /* was buggy (p could end up <= current_line)... */
     304                *--p = '\0';
     305                continue;
     306            }
     307            {
     308                size_t new_linepos = linepos + 1;
     309                if (c == '\t') {
     310                    new_linepos += 7;
     311                    new_linepos &= (~7);
     312                }
     313                if (new_linepos >= w)
     314                    break;
     315                linepos = new_linepos;
     316            }
     317            /* ok, we will eat this char */
     318            readpos++;
     319            if (c == '\n') {
     320                terminated = 1;
     321                linepos = 0;
     322                break;
     323            }
     324            /* NUL is substituted by '\n'! */
     325            if (c == '\0') c = '\n';
     326            *p++ = c;
     327            *p = '\0';
     328        }
     329        /* Corner case: linewrap with only "" wrapping to next line */
     330        /* Looks ugly on screen, so we do not store this empty line */
     331        if (!last_terminated && !current_line[0]) {
     332            last_terminated = 1;
     333            max_lineno++;
     334            goto again;
     335        }
     336 reached_eof:
     337        last_terminated = terminated;
     338        flines = xrealloc(flines, (max_fline+1) * sizeof(char *));
     339        if (option_mask32 & FLAG_N) {
     340            /* Width of 7 preserves tab spacing in the text */
     341            flines[max_fline] = xasprintf(
     342                (max_lineno <= 9999999) ? "%7u %s" : "%07u %s",
     343                max_lineno % 10000000, current_line);
     344            free(current_line);
     345            if (terminated)
     346                max_lineno++;
     347        } else {
     348            flines[max_fline] = xrealloc(current_line, strlen(current_line)+1);
     349        }
     350        if (max_fline >= MAXLINES) {
     351            eof_error = 0; /* Pretend we saw EOF */
     352            break;
     353        }
     354        if (max_fline > cur_fline + max_displayed_line)
     355            break;
     356        if (eof_error <= 0) {
     357            if (eof_error < 0 && errno == EAGAIN) {
     358                /* not yet eof or error, reset flag (or else
     359                 * we will hog CPU - select() will return
     360                 * immediately */
     361                eof_error = 1;
     362            }
     363            break;
     364        }
     365        max_fline++;
     366        current_line = xmalloc(w);
     367        p = current_line;
     368        linepos = 0;
     369    }
     370    fill_match_lines(old_max_fline);
     371#undef readbuf
     372}
     373
     374#if ENABLE_FEATURE_LESS_FLAGS
     375/* Interestingly, writing calc_percent as a function saves around 32 bytes
    238376 * on my build. */
    239377static int calc_percent(void)
    240378{
    241     return ((100 * (line_pos + height - 2) / num_flines) + 1);
     379    unsigned p = (100 * (cur_fline+max_displayed_line+1) + max_fline/2) / (max_fline+1);
     380    return p <= 100 ? p : 100;
    242381}
    243382
     
    247386    int percentage;
    248387
    249     if (!past_eof) {
    250         if (!line_pos) {
    251             if (num_files > 1)
    252                 printf("%s%s %s%i%s%i%s%i-%i/%i ", HIGHLIGHT, filename, "(file ", current_file, " of ", num_files, ") lines ", line_pos + 1, line_pos + height - 1, num_flines + 1);
    253             else {
    254                 printf("%s%s lines %i-%i/%i ", HIGHLIGHT, filename, line_pos + 1, line_pos + height - 1, num_flines + 1);
    255             }
    256         }
    257         else {
    258             printf("%s %s lines %i-%i/%i ", HIGHLIGHT, filename, line_pos + 1, line_pos + height - 1, num_flines + 1);
    259         }
    260 
    261         if (line_pos == num_flines - height + 2) {
    262             printf("(END) %s", NORMAL);
    263             if ((num_files > 1) && (current_file != num_files))
    264                 printf("%s- Next: %s%s", HIGHLIGHT, files[current_file], NORMAL);
    265         }
    266         else {
    267             percentage = calc_percent();
    268             printf("%i%% %s", percentage, NORMAL);
    269         }
    270     }
    271     else {
    272         printf("%s%s lines %i-%i/%i (END) ", HIGHLIGHT, filename, line_pos + 1, num_flines + 1, num_flines + 1);
    273         if ((num_files > 1) && (current_file != num_files))
    274             printf("- Next: %s", files[current_file]);
    275         printf("%s", NORMAL);
    276     }
    277 }
    278 
    279 /* Print a status line if -m was specified */
    280 static void medium_status_print(void)
    281 {
    282     int percentage;
     388    clear_line();
     389    printf(HIGHLIGHT"%s", filename);
     390    if (num_files > 1)
     391        printf(" (file %i of %i)", current_file, num_files);
     392    printf(" lines %i-%i/%i ",
     393            cur_fline + 1, cur_fline + max_displayed_line + 1,
     394            max_fline + 1);
     395    if (cur_fline >= max_fline - max_displayed_line) {
     396        printf("(END)"NORMAL);
     397        if (num_files > 1 && current_file != num_files)
     398            printf(HIGHLIGHT" - next: %s"NORMAL, files[current_file]);
     399        return;
     400    }
    283401    percentage = calc_percent();
    284 
    285     if (!line_pos)
    286         printf("%s%s %i%%%s", HIGHLIGHT, filename, percentage, NORMAL);
    287     else if (line_pos == num_flines - height + 2)
    288         printf("%s(END)%s", HIGHLIGHT, NORMAL);
    289     else
    290         printf("%s%i%%%s", HIGHLIGHT, percentage, NORMAL);
     402    printf("%i%%"NORMAL, percentage);
    291403}
    292404#endif
     
    295407static void status_print(void)
    296408{
     409    const char *p;
     410
    297411    /* Change the status if flags have been set */
    298 #ifdef CONFIG_FEATURE_LESS_FLAGS
    299     if (flags & FLAG_M)
     412#if ENABLE_FEATURE_LESS_FLAGS
     413    if (option_mask32 & (FLAG_M|FLAG_m)) {
    300414        m_status_print();
    301     else if (flags & FLAG_m)
    302         medium_status_print();
     415        return;
     416    }
    303417    /* No flags set */
    304     else {
    305 #endif
    306         if (!line_pos) {
    307             printf("%s%s %s", HIGHLIGHT, filename, NORMAL);
    308             if (num_files > 1)
    309                 printf("%s%s%i%s%i%s%s", HIGHLIGHT, "(file ", current_file, " of ", num_files, ")", NORMAL);
     418#endif
     419
     420    clear_line();
     421    if (cur_fline && cur_fline < max_fline - max_displayed_line) {
     422        putchar(':');
     423        return;
     424    }
     425    p = "(END)";
     426    if (!cur_fline)
     427        p = filename;
     428    if (num_files > 1) {
     429        printf(HIGHLIGHT"%s (file %i of %i)"NORMAL,
     430                p, current_file, num_files);
     431        return;
     432    }
     433    print_hilite(p);
     434}
     435
     436static void cap_cur_fline(int nlines)
     437{
     438    int diff;
     439    if (cur_fline < 0)
     440        cur_fline = 0;
     441    if (cur_fline + max_displayed_line > max_fline + TILDES) {
     442        cur_fline -= nlines;
     443        if (cur_fline < 0)
     444            cur_fline = 0;
     445        diff = max_fline - (cur_fline + max_displayed_line) + TILDES;
     446        /* As the number of lines requested was too large, we just move
     447        to the end of the file */
     448        if (diff > 0)
     449            cur_fline += diff;
     450    }
     451}
     452
     453static const char controls[] ALIGN1 =
     454    /* NUL: never encountered; TAB: not converted */
     455    /**/"\x01\x02\x03\x04\x05\x06\x07\x08"  "\x0a\x0b\x0c\x0d\x0e\x0f"
     456    "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
     457    "\x7f\x9b"; /* DEL and infamous Meta-ESC :( */
     458static const char ctrlconv[] ALIGN1 =
     459    /* '\n': it's a former NUL - subst with '@', not 'J' */
     460    "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f"
     461    "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f";
     462
     463#if ENABLE_FEATURE_LESS_REGEXP
     464static void print_found(const char *line)
     465{
     466    int match_status;
     467    int eflags;
     468    char *growline;
     469    regmatch_t match_structs;
     470
     471    char buf[width];
     472    const char *str = line;
     473    char *p = buf;
     474    size_t n;
     475
     476    while (*str) {
     477        n = strcspn(str, controls);
     478        if (n) {
     479            if (!str[n]) break;
     480            memcpy(p, str, n);
     481            p += n;
     482            str += n;
    310483        }
    311         else if (line_pos == num_flines - height + 2) {
    312             printf("%s%s %s", HIGHLIGHT, "(END)", NORMAL);
    313             if ((num_files > 1) && (current_file != num_files))
    314                 printf("%s%s%s%s", HIGHLIGHT, "- Next: ", files[current_file], NORMAL);
     484        n = strspn(str, controls);
     485        memset(p, '.', n);
     486        p += n;
     487        str += n;
     488    }
     489    strcpy(p, str);
     490
     491    /* buf[] holds quarantined version of str */
     492
     493    /* Each part of the line that matches has the HIGHLIGHT
     494       and NORMAL escape sequences placed around it.
     495       NB: we regex against line, but insert text
     496       from quarantined copy (buf[]) */
     497    str = buf;
     498    growline = NULL;
     499    eflags = 0;
     500    goto start;
     501
     502    while (match_status == 0) {
     503        char *new = xasprintf("%s%.*s"HIGHLIGHT"%.*s"NORMAL,
     504                growline ? : "",
     505                match_structs.rm_so, str,
     506                match_structs.rm_eo - match_structs.rm_so,
     507                        str + match_structs.rm_so);
     508        free(growline); growline = new;
     509        str += match_structs.rm_eo;
     510        line += match_structs.rm_eo;
     511        eflags = REG_NOTBOL;
     512 start:
     513        /* Most of the time doesn't find the regex, optimize for that */
     514        match_status = regexec(&pattern, line, 1, &match_structs, eflags);
     515    }
     516
     517    if (!growline) {
     518        printf(CLEAR_2_EOL"%s\n", str);
     519        return;
     520    }
     521    printf(CLEAR_2_EOL"%s%s\n", growline, str);
     522    free(growline);
     523}
     524#else
     525void print_found(const char *line);
     526#endif
     527
     528static void print_ascii(const char *str)
     529{
     530    char buf[width];
     531    char *p;
     532    size_t n;
     533
     534    printf(CLEAR_2_EOL);
     535    while (*str) {
     536        n = strcspn(str, controls);
     537        if (n) {
     538            if (!str[n]) break;
     539            printf("%.*s", (int) n, str);
     540            str += n;
    315541        }
    316         else {
    317             putchar(':');
    318         }
    319 #ifdef CONFIG_FEATURE_LESS_FLAGS
    320     }
    321 #endif
     542        n = strspn(str, controls);
     543        p = buf;
     544        do {
     545            if (*str == 0x7f)
     546                *p++ = '?';
     547            else if (*str == (char)0x9b)
     548            /* VT100's CSI, aka Meta-ESC. Who's inventor? */
     549            /* I want to know who committed this sin */
     550                *p++ = '{';
     551            else
     552                *p++ = ctrlconv[(unsigned char)*str];
     553            str++;
     554        } while (--n);
     555        *p = '\0';
     556        print_hilite(buf);
     557    }
     558    puts(str);
    322559}
    323560
     
    327564    int i;
    328565
    329     printf("%s", CLEAR);
    330     if (num_flines >= height - 2) {
    331         for (i = 0; i < height - 1; i++)
    332             printf("%s", buffer[i]);
    333     }
    334     else {
    335         for (i = 1; i < (height - 1 - num_flines); i++)
    336             putchar('\n');
    337         for (i = 0; i < height - 1; i++)
    338             printf("%s", buffer[i]);
    339     }
    340 
     566    move_cursor(0, 0);
     567    for (i = 0; i <= max_displayed_line; i++)
     568        if (pattern_valid)
     569            print_found(buffer[i]);
     570        else
     571            print_ascii(buffer[i]);
    341572    status_print();
    342573}
    343574
    344 /* Initialise the buffer */
    345 static void buffer_init(void)
     575static void buffer_fill_and_print(void)
    346576{
    347577    int i;
    348 
    349     if (buffer == NULL) {
    350         /* malloc the number of lines needed for the buffer */
    351         buffer = xrealloc(buffer, height * sizeof(char *));
    352     } else {
    353         for (i = 0; i < (height - 1); i++)
    354             free(buffer[i]);
    355     }
    356 
    357     /* Fill the buffer until the end of the file or the
    358        end of the buffer is reached */
    359     for (i = 0; (i < (height - 1)) && (i <= num_flines); i++) {
    360         buffer[i] = bb_xstrdup(flines[i]);
    361     }
    362 
    363     /* If the buffer still isn't full, fill it with blank lines */
    364     for (; i < (height - 1); i++) {
    365         buffer[i] = bb_xstrdup("");
    366     }
     578    for (i = 0; i <= max_displayed_line && cur_fline + i <= max_fline; i++) {
     579        buffer[i] = flines[cur_fline + i];
     580    }
     581    for (; i <= max_displayed_line; i++) {
     582        buffer[i] = empty_line_marker;
     583    }
     584    buffer_print();
    367585}
    368586
     
    370588static void buffer_down(int nlines)
    371589{
     590    cur_fline += nlines;
     591    read_lines();
     592    cap_cur_fline(nlines);
     593    buffer_fill_and_print();
     594}
     595
     596static void buffer_up(int nlines)
     597{
     598    cur_fline -= nlines;
     599    if (cur_fline < 0) cur_fline = 0;
     600    read_lines();
     601    buffer_fill_and_print();
     602}
     603
     604static void buffer_line(int linenum)
     605{
     606    if (linenum < 0)
     607        linenum = 0;
     608    cur_fline = linenum;
     609    read_lines();
     610    if (linenum + max_displayed_line > max_fline)
     611        linenum = max_fline - max_displayed_line + TILDES;
     612    if (linenum < 0)
     613        linenum = 0;
     614    cur_fline = linenum;
     615    buffer_fill_and_print();
     616}
     617
     618static void open_file_and_read_lines(void)
     619{
     620    if (filename) {
     621        int fd = xopen(filename, O_RDONLY);
     622        dup2(fd, 0);
     623        if (fd) close(fd);
     624    } else {
     625        /* "less" with no arguments in argv[] */
     626        /* For status line only */
     627        filename = xstrdup(bb_msg_standard_input);
     628    }
     629    readpos = 0;
     630    readeof = 0;
     631    linepos = 0;
     632    terminated = 1;
     633    read_lines();
     634}
     635
     636/* Reinitialize everything for a new file - free the memory and start over */
     637static void reinitialize(void)
     638{
    372639    int i;
    373640
    374     if (!past_eof) {
    375         if (line_pos + (height - 3) + nlines < num_flines) {
    376             line_pos += nlines;
    377             for (i = 0; i < (height - 1); i++) {
    378                 free(buffer[i]);
    379                 buffer[i] = bb_xstrdup(flines[line_pos + i]);
    380             }
     641    if (flines) {
     642        for (i = 0; i <= max_fline; i++)
     643            free((void*)(flines[i]));
     644        free(flines);
     645        flines = NULL;
     646    }
     647
     648    max_fline = -1;
     649    cur_fline = 0;
     650    max_lineno = 0;
     651    open_file_and_read_lines();
     652    buffer_fill_and_print();
     653}
     654
     655static void getch_nowait(char* input, int sz)
     656{
     657    ssize_t rd;
     658    fd_set readfds;
     659 again:
     660    fflush(stdout);
     661
     662    /* NB: select returns whenever read will not block. Therefore:
     663     * (a) with O_NONBLOCK'ed fds select will return immediately
     664     * (b) if eof is reached, select will also return
     665     *     because read will immediately return 0 bytes.
     666     * Even if select says that input is available, read CAN block
     667     * (switch fd into O_NONBLOCK'ed mode to avoid it)
     668     */
     669    FD_ZERO(&readfds);
     670    if (max_fline <= cur_fline + max_displayed_line
     671     && eof_error > 0 /* did NOT reach eof yet */
     672    ) {
     673        /* We are interested in stdin */
     674        FD_SET(0, &readfds);
     675    }
     676    FD_SET(kbd_fd, &readfds);
     677    tcsetattr(kbd_fd, TCSANOW, &term_less);
     678    select(kbd_fd + 1, &readfds, NULL, NULL, NULL);
     679
     680    input[0] = '\0';
     681    ndelay_on(kbd_fd);
     682    rd = read(kbd_fd, input, sz);
     683    ndelay_off(kbd_fd);
     684    if (rd < 0) {
     685        /* No keyboard input, but we have input on stdin! */
     686        if (errno != EAGAIN) /* Huh?? */
     687            return;
     688        read_lines();
     689        buffer_fill_and_print();
     690        goto again;
     691    }
     692}
     693
     694/* Grab a character from input without requiring the return key. If the
     695 * character is ASCII \033, get more characters and assign certain sequences
     696 * special return codes. Note that this function works best with raw input. */
     697static int less_getch(void)
     698{
     699    char input[16];
     700    unsigned i;
     701 again:
     702    memset(input, 0, sizeof(input));
     703    getch_nowait(input, sizeof(input));
     704
     705    /* Detect escape sequences (i.e. arrow keys) and handle
     706     * them accordingly */
     707    if (input[0] == '\033' && input[1] == '[') {
     708        set_tty_cooked();
     709        i = input[2] - REAL_KEY_UP;
     710        if (i < 4)
     711            return 20 + i;
     712        i = input[2] - REAL_PAGE_UP;
     713        if (i < 4)
     714            return 24 + i;
     715        if (input[2] == REAL_KEY_HOME_XTERM)
     716            return KEY_HOME;
     717        if (input[2] == REAL_KEY_HOME_ALT)
     718            return KEY_HOME;
     719        if (input[2] == REAL_KEY_END_XTERM)
     720            return KEY_END;
     721        if (input[2] == REAL_KEY_END_ALT)
     722            return KEY_END;
     723        return 0;
     724    }
     725    /* Reject almost all control chars */
     726    i = input[0];
     727    if (i < ' ' && i != 0x0d && i != 8) goto again;
     728    set_tty_cooked();
     729    return i;
     730}
     731
     732static char* less_gets(int sz)
     733{
     734    char c;
     735    int i = 0;
     736    char *result = xzalloc(1);
     737    while (1) {
     738        fflush(stdout);
     739
     740        /* I be damned if I know why is it needed *repeatedly*,
     741         * but it is needed. Is it because of stdio? */
     742        tcsetattr(kbd_fd, TCSANOW, &term_less);
     743
     744        c = '\0';
     745        read(kbd_fd, &c, 1);
     746        if (c == 0x0d)
     747            return result;
     748        if (c == 0x7f)
     749            c = 8;
     750        if (c == 8 && i) {
     751            printf("\x8 \x8");
     752            i--;
    381753        }
    382         else {
    383             /* As the number of lines requested was too large, we just move
    384             to the end of the file */
    385             while (line_pos + (height - 3) + 1 < num_flines) {
    386                 line_pos += 1;
    387                 for (i = 0; i < (height - 1); i++) {
    388                     free(buffer[i]);
    389                     buffer[i] = bb_xstrdup(flines[line_pos + i]);
    390                 }
    391             }
    392         }
    393 
    394         /* We exit if the -E flag has been set */
    395         if ((flags & FLAG_E) && (line_pos + (height - 2) == num_flines))
    396             tless_exit(0);
    397     }
    398 }
    399 
    400 static void buffer_up(int nlines)
    401 {
    402     int i;
    403     int tilde_line;
    404 
    405     if (!past_eof) {
    406         if (line_pos - nlines >= 0) {
    407             line_pos -= nlines;
    408             for (i = 0; i < (height - 1); i++) {
    409                 free(buffer[i]);
    410                 buffer[i] = bb_xstrdup(flines[line_pos + i]);
    411             }
    412         }
    413         else {
    414         /* As the requested number of lines to move was too large, we
    415            move one line up at a time until we can't. */
    416             while (line_pos != 0) {
    417                 line_pos -= 1;
    418                 for (i = 0; i < (height - 1); i++) {
    419                     free(buffer[i]);
    420                     buffer[i] = bb_xstrdup(flines[line_pos + i]);
    421                 }
    422             }
    423         }
    424     }
    425     else {
    426         /* Work out where the tildes start */
    427         tilde_line = num_flines - line_pos + 3;
    428 
    429         line_pos -= nlines;
    430         /* Going backwards nlines lines has taken us to a point where
    431            nothing is past the EOF, so we revert to normal. */
    432         if (line_pos < num_flines - height + 3) {
    433             past_eof = 0;
    434             buffer_up(nlines);
    435         }
    436         else {
    437             /* We only move part of the buffer, as the rest
    438             is past the EOF */
    439             for (i = 0; i < (height - 1); i++) {
    440                 free(buffer[i]);
    441                 if (i < tilde_line - nlines + 1)
    442                     buffer[i] = bb_xstrdup(flines[line_pos + i]);
    443                 else {
    444                     if (line_pos >= num_flines - height + 2)
    445                         buffer[i] = bb_xstrdup("~\n");
    446                 }
    447             }
    448         }
    449     }
    450 }
    451 
    452 static void buffer_line(int linenum)
    453 {
    454     int i;
    455     past_eof = 0;
    456 
    457     if (linenum < 0 || linenum > num_flines) {
    458         clear_line();
    459         printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum + 1, NORMAL);
    460     }
    461     else if (linenum < (num_flines - height - 2)) {
    462         for (i = 0; i < (height - 1); i++) {
    463             free(buffer[i]);
    464             buffer[i] = bb_xstrdup(flines[linenum + i]);
    465         }
    466         line_pos = linenum;
    467         buffer_print();
    468     }
    469     else {
    470         for (i = 0; i < (height - 1); i++) {
    471             free(buffer[i]);
    472             if (linenum + i < num_flines + 2)
    473                 buffer[i] = bb_xstrdup(flines[linenum + i]);
    474             else
    475                 buffer[i] = bb_xstrdup((flags & FLAG_TILDE) ? "\n" : "~\n");
    476         }
    477         line_pos = linenum;
    478         /* Set past_eof so buffer_down and buffer_up act differently */
    479         past_eof = 1;
    480         buffer_print();
    481     }
    482 }
    483 
    484 /* Reinitialise everything for a new file - free the memory and start over */
    485 static void reinitialise(void)
    486 {
    487     int i;
    488 
    489     for (i = 0; i <= num_flines; i++)
    490         free(flines[i]);
    491     free(flines);
    492 
    493     data_readlines();
    494     buffer_init();
    495     buffer_print();
     754        if (c < ' ')
     755            continue;
     756        if (i >= width - sz - 1)
     757            continue; /* len limit */
     758        putchar(c);
     759        result[i++] = c;
     760        result = xrealloc(result, i+1);
     761        result[i] = '\0';
     762    }
    496763}
    497764
    498765static void examine_file(void)
    499766{
    500     int newline_offset;
    501 
    502     clear_line();
    503     printf("Examine: ");
    504     fgets(filename, 256, inp);
    505 
    506     /* As fgets adds a newline to the end of an input string, we
    507        need to remove it */
    508     newline_offset = strlen(filename) - 1;
    509     filename[newline_offset] = '\0';
    510 
    511     files[num_files] = bb_xstrdup(filename);
     767    print_statusline("Examine: ");
     768    free(filename);
     769    filename = less_gets(sizeof("Examine: ")-1);
     770    /* files start by = argv. why we assume that argv is infinitely long??
     771    files[num_files] = filename;
    512772    current_file = num_files + 1;
    513     num_files++;
    514 
    515     inp_stdin = 0;
    516     reinitialise();
     773    num_files++; */
     774    files[0] = filename;
     775    num_files = current_file = 1;
     776    reinitialize();
    517777}
    518778
     
    520780 * -1: go back one file
    521781 *  0: go to the first file
    522  *  1: go forward one file
    523 */
     782 *  1: go forward one file */
    524783static void change_file(int direction)
    525784{
    526785    if (current_file != ((direction > 0) ? num_files : 1)) {
    527786        current_file = direction ? current_file + direction : 1;
    528         strcpy(filename, files[current_file - 1]);
    529         reinitialise();
    530     }
    531     else {
    532         clear_line();
    533         printf("%s%s%s", HIGHLIGHT, (direction > 0) ? "No next file" : "No previous file", NORMAL);
     787        free(filename);
     788        filename = xstrdup(files[current_file - 1]);
     789        reinitialize();
     790    } else {
     791        print_statusline(direction > 0 ? "No next file" : "No previous file");
    534792    }
    535793}
     
    538796{
    539797    int i;
     798
     799    if (num_files < 2)
     800        return;
    540801
    541802    if (current_file != 1) {
     
    544805            files[i - 2] = files[i - 1];
    545806        num_files--;
    546         buffer_print();
    547     }
    548     else {
     807    } else {
    549808        change_file(1);
    550809        for (i = 2; i <= num_files; i++)
     
    552811        num_files--;
    553812        current_file--;
    554         buffer_print();
    555813    }
    556814}
     
    561819
    562820    /* Clear the current line and print a prompt */
    563     clear_line();
    564     printf(" :");
    565 
    566     keypress = tless_getch();
     821    print_statusline(" :");
     822
     823    keypress = less_getch();
    567824    switch (keypress) {
    568         case 'd':
    569             remove_current_file();
    570             break;
    571         case 'e':
    572             examine_file();
    573             break;
    574 #ifdef CONFIG_FEATURE_LESS_FLAGS
    575         case 'f':
    576             clear_line();
    577             m_status_print();
    578             break;
    579 #endif
    580         case 'n':
    581             change_file(1);
    582             break;
    583         case 'p':
    584             change_file(-1);
    585             break;
    586         case 'q':
    587             tless_exit(0);
    588             break;
    589         case 'x':
    590             change_file(0);
    591             break;
    592         default:
    593             break;
    594     }
    595 }
    596 
    597 #ifdef CONFIG_FEATURE_LESS_REGEXP
    598 /* The below two regular expression handler functions NEED development. */
    599 
    600 /* Get a regular expression from the user, and then go through the current
    601    file line by line, running a processing regex function on each one. */
    602 
    603 static char *process_regex_on_line(char *line, regex_t *pattern, int action)
    604 {
    605     /* This function takes the regex and applies it to the line.
    606        Each part of the line that matches has the HIGHLIGHT
    607        and NORMAL escape sequences placed around it by
    608        insert_highlights if action = 1, or has the escape sequences
    609        removed if action = 0, and then the line is returned. */
    610     int match_status;
    611     char *line2 = (char *) xmalloc((sizeof(char) * (strlen(line) + 1)) + 64);
    612     char *growline = "";
    613     regmatch_t match_structs;
    614 
    615     line2 = bb_xstrdup(line);
    616 
    617     match_found = 0;
    618     match_status = regexec(pattern, line2, 1, &match_structs, 0);
    619    
    620     while (match_status == 0) {
    621         if (match_found == 0)
    622             match_found = 1;
    623        
    624         if (action) {
    625             growline = bb_xasprintf("%s%.*s%s%.*s%s", growline, match_structs.rm_so, line2, HIGHLIGHT, match_structs.rm_eo - match_structs.rm_so, line2 + match_structs.rm_so, NORMAL);
     825    case 'd':
     826        remove_current_file();
     827        break;
     828    case 'e':
     829        examine_file();
     830        break;
     831#if ENABLE_FEATURE_LESS_FLAGS
     832    case 'f':
     833        m_status_print();
     834        break;
     835#endif
     836    case 'n':
     837        change_file(1);
     838        break;
     839    case 'p':
     840        change_file(-1);
     841        break;
     842    case 'q':
     843        less_exit(0);
     844        break;
     845    case 'x':
     846        change_file(0);
     847        break;
     848    }
     849}
     850
     851#if ENABLE_FEATURE_LESS_REGEXP
     852static void normalize_match_pos(int match)
     853{
     854    if (match >= num_matches)
     855        match = num_matches - 1;
     856    if (match < 0)
     857        match = 0;
     858    match_pos = match;
     859}
     860
     861static void goto_match(int match)
     862{
     863    int sv;
     864
     865    if (!pattern_valid)
     866        return;
     867    if (match < 0)
     868        match = 0;
     869    sv = cur_fline;
     870    /* Try to find next match if eof isn't reached yet */
     871    if (match >= num_matches && eof_error > 0) {
     872        cur_fline = MAXLINES; /* look as far as needed */
     873        read_lines();
     874    }
     875    if (num_matches) {
     876        cap_cur_fline(cur_fline);
     877        normalize_match_pos(match);
     878        buffer_line(match_lines[match_pos]);
     879    } else {
     880        cur_fline = sv;
     881        print_statusline("No matches found");
     882    }
     883}
     884
     885static void fill_match_lines(unsigned pos)
     886{
     887    if (!pattern_valid)
     888        return;
     889    /* Run the regex on each line of the current file */
     890    while (pos <= max_fline) {
     891        /* If this line matches */
     892        if (regexec(&pattern, flines[pos], 0, NULL, 0) == 0
     893        /* and we didn't match it last time */
     894         && !(num_matches && match_lines[num_matches-1] == pos)
     895        ) {
     896            match_lines = xrealloc(match_lines, (num_matches+1) * sizeof(int));
     897            match_lines[num_matches++] = pos;
    626898        }
    627         else {
    628             growline = bb_xasprintf("%s%.*s%.*s", growline, match_structs.rm_so - 4, line2, match_structs.rm_eo - match_structs.rm_so, line2 + match_structs.rm_so);
    629         }
    630        
    631         line2 += match_structs.rm_eo;
    632         match_status = regexec(pattern, line2, 1, &match_structs, REG_NOTBOL);
    633     }
    634    
    635     growline = bb_xasprintf("%s%s", growline, line2);
    636    
    637     return (match_found ? growline : line);
    638    
    639     free(growline);
    640     free(line2);
    641 }
    642 
    643 static void goto_match(int match)
    644 {
    645     /* This goes to a specific match - all line positions of matches are
    646        stored within the match_lines[] array. */
    647     if ((match < num_matches) && (match >= 0)) {
    648         buffer_line(match_lines[match]);
    649         match_pos = match;
     899        pos++;
    650900    }
    651901}
     
    653903static void regex_process(void)
    654904{
    655     char uncomp_regex[100];
    656     char *current_line;
    657     int i;
    658     int j = 0;
    659     regex_t pattern;
     905    char *uncomp_regex, *err;
     906
     907    /* Reset variables */
     908    free(match_lines);
     909    match_lines = NULL;
     910    match_pos = 0;
     911    num_matches = 0;
     912    if (pattern_valid) {
     913        regfree(&pattern);
     914        pattern_valid = 0;
     915    }
     916
    660917    /* Get the uncompiled regular expression from the user */
    661918    clear_line();
    662     putchar((match_backwards) ? '?' : '/');
    663     uncomp_regex[0] = 0;
    664     fgets(uncomp_regex, sizeof(uncomp_regex), inp);
    665    
    666     if (strlen(uncomp_regex) == 1) {
    667         if (num_matches)
    668             goto_match(match_backwards ? match_pos - 1 : match_pos + 1);
    669         else
    670             buffer_print();
     919    putchar((option_mask32 & LESS_STATE_MATCH_BACKWARDS) ? '?' : '/');
     920    uncomp_regex = less_gets(1);
     921    if (!uncomp_regex[0]) {
     922        free(uncomp_regex);
     923        buffer_print();
    671924        return;
    672925    }
    673     uncomp_regex[strlen(uncomp_regex) - 1] = '\0';
    674    
     926
    675927    /* Compile the regex and check for errors */
    676     xregcomp(&pattern, uncomp_regex, 0);
    677 
    678     if (num_matches) {
    679         /* Get rid of all the highlights we added previously */
    680         for (i = 0; i <= num_flines; i++) {
    681             current_line = process_regex_on_line(flines[i], &old_pattern, 0);
    682             flines[i] = bb_xstrdup(current_line);
    683         }
    684     }
    685     old_pattern = pattern;
    686    
    687     /* Reset variables */
    688     match_lines = xrealloc(match_lines, sizeof(int));
    689     match_lines[0] = -1;
     928    err = regcomp_or_errmsg(&pattern, uncomp_regex, 0);
     929    free(uncomp_regex);
     930    if (err) {
     931        print_statusline(err);
     932        free(err);
     933        return;
     934    }
     935
     936    pattern_valid = 1;
    690937    match_pos = 0;
    691     num_matches = 0;
    692     match_found = 0;
    693     /* Run the regex on each line of the current file here */
    694     for (i = 0; i <= num_flines; i++) {
    695         current_line = process_regex_on_line(flines[i], &pattern, 1);
    696         flines[i] = bb_xstrdup(current_line);
    697         if (match_found) {
    698             match_lines = xrealloc(match_lines, (j + 1) * sizeof(int));
    699             match_lines[j] = i;
    700             j++;
    701         }
    702     }
    703    
    704     num_matches = j;
    705     if ((match_lines[0] != -1) && (num_flines > height - 2)) {
    706         if (match_backwards) {
    707             for (i = 0; i < num_matches; i++) {
    708                 if (match_lines[i] > line_pos) {
    709                     match_pos = i - 1;
    710                     buffer_line(match_lines[match_pos]);
    711                     break;
    712                 }
    713             }
    714         }
    715         else
    716             buffer_line(match_lines[0]);
    717     }
    718     else
    719         buffer_init();
     938    fill_match_lines(0);
     939    while (match_pos < num_matches) {
     940        if (match_lines[match_pos] > cur_fline)
     941            break;
     942        match_pos++;
     943    }
     944    if (option_mask32 & LESS_STATE_MATCH_BACKWARDS)
     945        match_pos--;
     946
     947    /* It's possible that no matches are found yet.
     948     * goto_match() will read input looking for match,
     949     * if needed */
     950    goto_match(match_pos);
    720951}
    721952#endif
     
    725956    int i = 1;
    726957    int num;
    727     char num_input[80];
     958    char num_input[sizeof(int)*4]; /* more than enough */
    728959    char keypress;
    729     char *endptr;
    730960
    731961    num_input[0] = first_digit;
     
    735965    printf(":%c", first_digit);
    736966
    737     /* Receive input until a letter is given (max 80 chars)*/
    738     while((i < 80) && (num_input[i] = tless_getch()) && isdigit(num_input[i])) {
     967    /* Receive input until a letter is given */
     968    while (i < sizeof(num_input)-1) {
     969        num_input[i] = less_getch();
     970        if (!num_input[i] || !isdigit(num_input[i]))
     971            break;
    739972        putchar(num_input[i]);
    740973        i++;
     
    744977    keypress = num_input[i];
    745978    num_input[i] = '\0';
    746     num = strtol(num_input, &endptr, 10);
    747     if (endptr==num_input || *endptr!='\0' || num < 1 || num > MAXLINES) {
     979    num = bb_strtou(num_input, NULL, 10);
     980    /* on format error, num == -1 */
     981    if (num < 1 || num > MAXLINES) {
    748982        buffer_print();
    749983        return;
     
    752986    /* We now know the number and the letter entered, so we process them */
    753987    switch (keypress) {
    754         case KEY_DOWN: case 'z': case 'd': case 'e': case ' ': case '\015':
    755             buffer_down(num);
    756             break;
    757         case KEY_UP: case 'b': case 'w': case 'y': case 'u':
    758             buffer_up(num);
    759             break;
    760         case 'g': case '<': case 'G': case '>':
    761             if (num_flines >= height - 2)
    762                 buffer_line(num - 1);
    763             break;
    764         case 'p': case '%':
    765             buffer_line(((num / 100) * num_flines) - 1);
    766             break;
    767 #ifdef CONFIG_FEATURE_LESS_REGEXP
    768         case 'n':
    769             goto_match(match_pos + num);
    770             break;
    771         case '/':
    772             match_backwards = 0;
    773             regex_process();
    774             break;
    775         case '?':
    776             match_backwards = 1;
    777             regex_process();
    778             break;
    779 #endif
    780         default:
    781             break;
    782     }
    783 }
    784 
    785 #ifdef CONFIG_FEATURE_LESS_FLAGCS
     988    case KEY_DOWN: case 'z': case 'd': case 'e': case ' ': case '\015':
     989        buffer_down(num);
     990        break;
     991    case KEY_UP: case 'b': case 'w': case 'y': case 'u':
     992        buffer_up(num);
     993        break;
     994    case 'g': case '<': case 'G': case '>':
     995        cur_fline = num + max_displayed_line;
     996        read_lines();
     997        buffer_line(num - 1);
     998        break;
     999    case 'p': case '%':
     1000        num = num * (max_fline / 100); /* + max_fline / 2; */
     1001        cur_fline = num + max_displayed_line;
     1002        read_lines();
     1003        buffer_line(num);
     1004        break;
     1005#if ENABLE_FEATURE_LESS_REGEXP
     1006    case 'n':
     1007        goto_match(match_pos + num);
     1008        break;
     1009    case '/':
     1010        option_mask32 &= ~LESS_STATE_MATCH_BACKWARDS;
     1011        regex_process();
     1012        break;
     1013    case '?':
     1014        option_mask32 |= LESS_STATE_MATCH_BACKWARDS;
     1015        regex_process();
     1016        break;
     1017#endif
     1018    }
     1019}
     1020
     1021#if ENABLE_FEATURE_LESS_FLAGCS
    7861022static void flag_change(void)
    7871023{
     
    7901026    clear_line();
    7911027    putchar('-');
    792     keypress = tless_getch();
     1028    keypress = less_getch();
    7931029
    7941030    switch (keypress) {
    795         case 'M':
    796             flags ^= FLAG_M;
    797             break;
    798         case 'm':
    799             flags ^= FLAG_m;
    800             break;
    801         case 'E':
    802             flags ^= FLAG_E;
    803             break;
    804         case '~':
    805             flags ^= FLAG_TILDE;
    806             break;
    807         default:
    808             break;
     1031    case 'M':
     1032        option_mask32 ^= FLAG_M;
     1033        break;
     1034    case 'm':
     1035        option_mask32 ^= FLAG_m;
     1036        break;
     1037    case 'E':
     1038        option_mask32 ^= FLAG_E;
     1039        break;
     1040    case '~':
     1041        option_mask32 ^= FLAG_TILDE;
     1042        break;
    8091043    }
    8101044}
     
    8171051    clear_line();
    8181052    putchar('_');
    819     keypress = tless_getch();
     1053    keypress = less_getch();
    8201054
    8211055    switch (keypress) {
    822         case 'M':
    823             flag_val = flags & FLAG_M;
    824             break;
    825         case 'm':
    826             flag_val = flags & FLAG_m;
    827             break;
    828         case '~':
    829             flag_val = flags & FLAG_TILDE;
    830             break;
    831         case 'N':
    832             flag_val = flags & FLAG_N;
    833             break;
    834         case 'E':
    835             flag_val = flags & FLAG_E;
    836             break;
    837         default:
    838             flag_val = 0;
    839             break;
     1056    case 'M':
     1057        flag_val = option_mask32 & FLAG_M;
     1058        break;
     1059    case 'm':
     1060        flag_val = option_mask32 & FLAG_m;
     1061        break;
     1062    case '~':
     1063        flag_val = option_mask32 & FLAG_TILDE;
     1064        break;
     1065    case 'N':
     1066        flag_val = option_mask32 & FLAG_N;
     1067        break;
     1068    case 'E':
     1069        flag_val = option_mask32 & FLAG_E;
     1070        break;
     1071    default:
     1072        flag_val = 0;
     1073        break;
    8401074    }
    8411075
    8421076    clear_line();
    843     printf("%s%s%i%s", HIGHLIGHT, "The status of the flag is: ", flag_val != 0, NORMAL);
    844 }
    845 #endif
    846 
    847 static void full_repaint(void)
    848 {
    849     int temp_line_pos = line_pos;
    850     data_readlines();
    851     buffer_init();
    852     buffer_line(temp_line_pos);
    853 }
    854 
     1077    printf(HIGHLIGHT"The status of the flag is: %u"NORMAL, flag_val != 0);
     1078}
     1079#endif
    8551080
    8561081static void save_input_to_file(void)
    8571082{
    858     char current_line[256];
     1083    const char *msg = "";
     1084    char *current_line;
    8591085    int i;
    8601086    FILE *fp;
    8611087
    862     clear_line();
    863     printf("Log file: ");
    864     fgets(current_line, 256, inp);
    865     current_line[strlen(current_line) - 1] = '\0';
    866     if (strlen(current_line) > 1) {
    867         fp = bb_xfopen(current_line, "w");
    868         for (i = 0; i < num_flines; i++)
    869             fprintf(fp, "%s", flines[i]);
     1088    print_statusline("Log file: ");
     1089    current_line = less_gets(sizeof("Log file: ")-1);
     1090    if (strlen(current_line) > 0) {
     1091        fp = fopen(current_line, "w");
     1092        if (!fp) {
     1093            msg = "Error opening log file";
     1094            goto ret;
     1095        }
     1096        for (i = 0; i <= max_fline; i++)
     1097            fprintf(fp, "%s\n", flines[i]);
    8701098        fclose(fp);
    871         buffer_print();
    872     }
    873     else
    874         printf("%sNo log file%s", HIGHLIGHT, NORMAL);
    875 }
    876 
    877 #ifdef CONFIG_FEATURE_LESS_MARKS
     1099        msg = "Done";
     1100    }
     1101 ret:
     1102    print_statusline(msg);
     1103    free(current_line);
     1104}
     1105
     1106#if ENABLE_FEATURE_LESS_MARKS
    8781107static void add_mark(void)
    8791108{
    8801109    int letter;
    881     int mark_line;
    882 
    883     clear_line();
    884     printf("Mark: ");
    885     letter = tless_getch();
     1110
     1111    print_statusline("Mark: ");
     1112    letter = less_getch();
    8861113
    8871114    if (isalpha(letter)) {
    888         mark_line = line_pos;
    889 
    8901115        /* If we exceed 15 marks, start overwriting previous ones */
    8911116        if (num_marks == 14)
     
    8931118
    8941119        mark_lines[num_marks][0] = letter;
    895         mark_lines[num_marks][1] = line_pos;
     1120        mark_lines[num_marks][1] = cur_fline;
    8961121        num_marks++;
    897     }
    898     else {
    899         clear_line();
    900         printf("%s%s%s", HIGHLIGHT, "Invalid mark letter", NORMAL);
     1122    } else {
     1123        print_statusline("Invalid mark letter");
    9011124    }
    9021125}
     
    9071130    int i;
    9081131
    909     clear_line();
    910     printf("Go to mark: ");
    911     letter = tless_getch();
     1132    print_statusline("Go to mark: ");
     1133    letter = less_getch();
    9121134    clear_line();
    9131135
     
    9181140                break;
    9191141            }
    920         if ((num_marks == 14) && (letter != mark_lines[14][0]))
    921             printf("%s%s%s", HIGHLIGHT, "Mark not set", NORMAL);
    922     }
    923     else
    924         printf("%s%s%s", HIGHLIGHT, "Invalid mark letter", NORMAL);
    925 }
    926 #endif
    927 
    928 
    929 #ifdef CONFIG_FEATURE_LESS_BRACKETS
    930 
     1142        if (num_marks == 14 && letter != mark_lines[14][0])
     1143            print_statusline("Mark not set");
     1144    } else
     1145        print_statusline("Invalid mark letter");
     1146}
     1147#endif
     1148
     1149#if ENABLE_FEATURE_LESS_BRACKETS
    9311150static char opp_bracket(char bracket)
    9321151{
    9331152    switch (bracket) {
    934         case '{': case '[':
    935             return bracket + 2;
    936             break;
    937         case '(':
    938             return ')';
    939             break;
    940         case '}': case ']':
    941             return bracket - 2;
    942             break;
    943         case ')':
    944             return '(';
    945             break;
    946         default:
    947             return 0;
    948             break;
    949     }
     1153    case '{': case '[':
     1154        return bracket + 2;
     1155    case '(':
     1156        return ')';
     1157    case '}': case ']':
     1158        return bracket - 2;
     1159    case ')':
     1160        return '(';
     1161    }
     1162    return 0;
    9501163}
    9511164
     
    9551168    int i;
    9561169
    957     clear_line();
    958 
    959     if (strchr(flines[line_pos], bracket) == NULL)
    960         printf("%s%s%s", HIGHLIGHT, "No bracket in top line", NORMAL);
    961     else {
    962         for (i = line_pos + 1; i < num_flines; i++) {
    963             if (strchr(flines[i], opp_bracket(bracket)) != NULL) {
    964                 bracket_line = i;
    965                 break;
    966             }
     1170    if (strchr(flines[cur_fline], bracket) == NULL) {
     1171        print_statusline("No bracket in top line");
     1172        return;
     1173    }
     1174    for (i = cur_fline + 1; i < max_fline; i++) {
     1175        if (strchr(flines[i], opp_bracket(bracket)) != NULL) {
     1176            bracket_line = i;
     1177            break;
    9671178        }
    968 
    969         if (bracket_line == -1)
    970             printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL);
    971 
    972         buffer_line(bracket_line - height + 2);
    973     }
     1179    }
     1180    if (bracket_line == -1)
     1181        print_statusline("No matching bracket found");
     1182    buffer_line(bracket_line - max_displayed_line);
    9741183}
    9751184
     
    9791188    int i;
    9801189
    981     clear_line();
    982 
    983     if (strchr(flines[line_pos + height - 2], bracket) == NULL) {
    984         printf("%s%s%s", HIGHLIGHT, "No bracket in bottom line", NORMAL);
    985         printf("%s", flines[line_pos + height]);
    986         sleep(4);
    987     }
    988     else {
    989         for (i = line_pos + height - 2; i >= 0; i--) {
    990             if (strchr(flines[i], opp_bracket(bracket)) != NULL) {
    991                 bracket_line = i;
    992                 break;
    993             }
     1190    if (strchr(flines[cur_fline + max_displayed_line], bracket) == NULL) {
     1191        print_statusline("No bracket in bottom line");
     1192        return;
     1193    }
     1194
     1195    for (i = cur_fline + max_displayed_line; i >= 0; i--) {
     1196        if (strchr(flines[i], opp_bracket(bracket)) != NULL) {
     1197            bracket_line = i;
     1198            break;
    9941199        }
    995 
    996         if (bracket_line == -1)
    997             printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL);
    998 
    999         buffer_line(bracket_line);
    1000     }
    1001 }
    1002 
    1003 #endif  /* CONFIG_FEATURE_LESS_BRACKETS */
     1200    }
     1201    if (bracket_line == -1)
     1202        print_statusline("No matching bracket found");
     1203    buffer_line(bracket_line);
     1204}
     1205#endif  /* FEATURE_LESS_BRACKETS */
    10041206
    10051207static void keypress_process(int keypress)
    10061208{
    10071209    switch (keypress) {
    1008         case KEY_DOWN: case 'e': case 'j': case '\015':
    1009             buffer_down(1);
    1010             buffer_print();
    1011             break;
    1012         case KEY_UP: case 'y': case 'k':
    1013             buffer_up(1);
    1014             buffer_print();
    1015             break;
    1016         case PAGE_DOWN: case ' ': case 'z':
    1017             buffer_down(height - 1);
    1018             buffer_print();
    1019             break;
    1020         case PAGE_UP: case 'w': case 'b':
    1021             buffer_up(height - 1);
    1022             buffer_print();
    1023             break;
    1024         case 'd':
    1025             buffer_down((height - 1) / 2);
    1026             buffer_print();
    1027             break;
    1028         case 'u':
    1029             buffer_up((height - 1) / 2);
    1030             buffer_print();
    1031             break;
    1032         case 'g': case 'p': case '<': case '%':
    1033             buffer_line(0);
    1034             break;
    1035         case 'G': case '>':
    1036             buffer_line(num_flines - height + 2);
    1037             break;
    1038         case 'q': case 'Q':
    1039             tless_exit(0);
    1040             break;
    1041 #ifdef CONFIG_FEATURE_LESS_MARKS
    1042         case 'm':
    1043             add_mark();
    1044             buffer_print();
    1045             break;
    1046         case '\'':
    1047             goto_mark();
    1048             buffer_print();
    1049             break;
    1050 #endif
    1051         case 'r':
    1052             buffer_print();
    1053             break;
    1054         case 'R':
    1055             full_repaint();
    1056             break;
    1057         case 's':
    1058             if (inp_stdin)
    1059                 save_input_to_file();
    1060             break;
    1061         case 'E':
    1062             examine_file();
    1063             break;
    1064 #ifdef CONFIG_FEATURE_LESS_FLAGS
    1065         case '=':
    1066             clear_line();
    1067             m_status_print();
    1068             break;
    1069 #endif
    1070 #ifdef CONFIG_FEATURE_LESS_REGEXP
    1071         case '/':
    1072             match_backwards = 0;
    1073             regex_process();
    1074             break;
    1075         case 'n':
    1076             goto_match(match_pos + 1);
    1077             break;
    1078         case 'N':
    1079             goto_match(match_pos - 1);
    1080             break;
    1081         case '?':
    1082             match_backwards = 1;
    1083             regex_process();
    1084             break;
    1085 #endif
    1086 #ifdef CONFIG_FEATURE_LESS_FLAGCS
    1087         case '-':
    1088             flag_change();
    1089             buffer_print();
    1090             break;
    1091         case '_':
    1092             show_flag_status();
    1093             break;
    1094 #endif
    1095 #ifdef CONFIG_FEATURE_LESS_BRACKETS
    1096         case '{': case '(': case '[':
    1097             match_right_bracket(keypress);
    1098             break;
    1099         case '}': case ')': case ']':
    1100             match_left_bracket(keypress);
    1101             break;
    1102 #endif
    1103         case ':':
    1104             colon_process();
    1105             break;
    1106         default:
    1107             break;
     1210    case KEY_DOWN: case 'e': case 'j': case 0x0d:
     1211        buffer_down(1);
     1212        break;
     1213    case KEY_UP: case 'y': case 'k':
     1214        buffer_up(1);
     1215        break;
     1216    case PAGE_DOWN: case ' ': case 'z':
     1217        buffer_down(max_displayed_line + 1);
     1218        break;
     1219    case PAGE_UP: case 'w': case 'b':
     1220        buffer_up(max_displayed_line + 1);
     1221        break;
     1222    case 'd':
     1223        buffer_down((max_displayed_line + 1) / 2);
     1224        break;
     1225    case 'u':
     1226        buffer_up((max_displayed_line + 1) / 2);
     1227        break;
     1228    case KEY_HOME: case 'g': case 'p': case '<': case '%':
     1229        buffer_line(0);
     1230        break;
     1231    case KEY_END: case 'G': case '>':
     1232        cur_fline = MAXLINES;
     1233        read_lines();
     1234        buffer_line(cur_fline);
     1235        break;
     1236    case 'q': case 'Q':
     1237        less_exit(0);
     1238        break;
     1239#if ENABLE_FEATURE_LESS_MARKS
     1240    case 'm':
     1241        add_mark();
     1242        buffer_print();
     1243        break;
     1244    case '\'':
     1245        goto_mark();
     1246        buffer_print();
     1247        break;
     1248#endif
     1249    case 'r': case 'R':
     1250        buffer_print();
     1251        break;
     1252    /*case 'R':
     1253        full_repaint();
     1254        break;*/
     1255    case 's':
     1256        save_input_to_file();
     1257        break;
     1258    case 'E':
     1259        examine_file();
     1260        break;
     1261#if ENABLE_FEATURE_LESS_FLAGS
     1262    case '=':
     1263        m_status_print();
     1264        break;
     1265#endif
     1266#if ENABLE_FEATURE_LESS_REGEXP
     1267    case '/':
     1268        option_mask32 &= ~LESS_STATE_MATCH_BACKWARDS;
     1269        regex_process();
     1270        break;
     1271    case 'n':
     1272        goto_match(match_pos + 1);
     1273        break;
     1274    case 'N':
     1275        goto_match(match_pos - 1);
     1276        break;
     1277    case '?':
     1278        option_mask32 |= LESS_STATE_MATCH_BACKWARDS;
     1279        regex_process();
     1280        break;
     1281#endif
     1282#if ENABLE_FEATURE_LESS_FLAGCS
     1283    case '-':
     1284        flag_change();
     1285        buffer_print();
     1286        break;
     1287    case '_':
     1288        show_flag_status();
     1289        break;
     1290#endif
     1291#if ENABLE_FEATURE_LESS_BRACKETS
     1292    case '{': case '(': case '[':
     1293        match_right_bracket(keypress);
     1294        break;
     1295    case '}': case ')': case ']':
     1296        match_left_bracket(keypress);
     1297        break;
     1298#endif
     1299    case ':':
     1300        colon_process();
     1301        break;
    11081302    }
    11091303
     
    11121306}
    11131307
    1114 int less_main(int argc, char **argv) {
    1115 
     1308static void sig_catcher(int sig ATTRIBUTE_UNUSED)
     1309{
     1310    set_tty_cooked();
     1311    exit(1);
     1312}
     1313
     1314int less_main(int argc, char **argv);
     1315int less_main(int argc, char **argv)
     1316{
    11161317    int keypress;
    11171318
    1118     flags = bb_getopt_ulflags(argc, argv, "EMmN~");
    1119 
     1319    INIT_G();
     1320
     1321    /* TODO: -x: do not interpret backspace, -xx: tab also */
     1322    /* -xxx: newline also */
     1323    /* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */
     1324    getopt32(argv, "EMmN~");
    11201325    argc -= optind;
    11211326    argv += optind;
     1327    num_files = argc;
    11221328    files = argv;
    1123     num_files = argc;
     1329
     1330    /* Another popular pager, most, detects when stdout
     1331     * is not a tty and turns into cat. This makes sense. */
     1332    if (!isatty(STDOUT_FILENO))
     1333        return bb_cat(argv);
     1334    kbd_fd = open(CURRENT_TTY, O_RDONLY);
     1335    if (kbd_fd < 0)
     1336        return bb_cat(argv);
    11241337
    11251338    if (!num_files) {
    1126         if (ttyname(STDIN_FILENO) == NULL)
    1127             inp_stdin = 1;
    1128         else {
    1129             bb_error_msg("Missing filename");
     1339        if (isatty(STDIN_FILENO)) {
     1340            /* Just "less"? No args and no redirection? */
     1341            bb_error_msg("missing filename");
    11301342            bb_show_usage();
    11311343        }
    1132     }
    1133 
    1134     strcpy(filename, (inp_stdin) ? bb_msg_standard_input : files[0]);
    1135     get_terminal_width_height(0, &width, &height);
    1136     data_readlines();
    1137     tcgetattr(fileno(inp), &term_orig);
    1138     term_vi = term_orig;
    1139     term_vi.c_lflag &= (~ICANON & ~ECHO);
    1140     term_vi.c_iflag &= (~IXON & ~ICRNL);
    1141     term_vi.c_oflag &= (~ONLCR);
    1142     term_vi.c_cc[VMIN] = 1;
    1143     term_vi.c_cc[VTIME] = 0;
    1144     buffer_init();
    1145     buffer_print();
    1146 
     1344    } else
     1345        filename = xstrdup(files[0]);
     1346
     1347    get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
     1348    /* 20: two tabstops + 4 */
     1349    if (width < 20 || max_displayed_line < 3)
     1350        bb_error_msg_and_die("too narrow here");
     1351    max_displayed_line -= 2;
     1352
     1353    buffer = xmalloc((max_displayed_line+1) * sizeof(char *));
     1354    if (option_mask32 & FLAG_TILDE)
     1355        empty_line_marker = "";
     1356
     1357    tcgetattr(kbd_fd, &term_orig);
     1358    signal(SIGTERM, sig_catcher);
     1359    signal(SIGINT, sig_catcher);
     1360    term_less = term_orig;
     1361    term_less.c_lflag &= ~(ICANON | ECHO);
     1362    term_less.c_iflag &= ~(IXON | ICRNL);
     1363    /*term_less.c_oflag &= ~ONLCR;*/
     1364    term_less.c_cc[VMIN] = 1;
     1365    term_less.c_cc[VTIME] = 0;
     1366
     1367    /* Want to do it just once, but it doesn't work, */
     1368    /* so we are redoing it (see code above). Mystery... */
     1369    /*tcsetattr(kbd_fd, TCSANOW, &term_less);*/
     1370
     1371    reinitialize();
    11471372    while (1) {
    1148         keypress = tless_getch();
     1373        keypress = less_getch();
    11491374        keypress_process(keypress);
    11501375    }
  • branches/2.2.5/mindi-busybox/miscutils/makedevs.c

    r821 r1765  
    88 */
    99
    10 #include "busybox.h"
    11 #include <stdio.h>
    12 #include <stdlib.h>
    13 #include <string.h>
    14 #include <fcntl.h>
    15 #include <time.h>
    16 #include <ctype.h>
    17 #include <unistd.h>
    18 #include <sys/types.h>
    19 #include <sys/sysmacros.h>     /* major() and minor() */
    20 
    21 #ifdef CONFIG_FEATURE_MAKEDEVS_LEAF
     10#include "libbb.h"
     11
     12#if ENABLE_FEATURE_MAKEDEVS_LEAF
     13int makedevs_main(int argc, char **argv);
    2214int makedevs_main(int argc, char **argv)
    2315{
     
    3123    basedev = argv[1];
    3224    type = argv[2];
    33     Smajor = atoi(argv[3]);
    34     Sminor = atoi(argv[4]);
    35     S = atoi(argv[5]);
    36     E = atoi(argv[6]);
     25    Smajor = xatoi_u(argv[3]);
     26    Sminor = xatoi_u(argv[4]);
     27    S = xatoi_u(argv[5]);
     28    E = xatoi_u(argv[6]);
    3729    nodname = argc == 8 ? basedev : buf;
    3830
     
    5749
    5850        sz = snprintf(buf, sizeof(buf), "%s%d", basedev, S);
    59         if(sz<0 || sz>=sizeof(buf))  /* libc different */
     51        if (sz < 0 || sz >= sizeof(buf))  /* libc different */
    6052            bb_error_msg_and_die("%s too large", basedev);
    6153
     
    6355
    6456        if (mknod(nodname, mode, makedev(Smajor, Sminor)))
    65             bb_error_msg("Failed to create: %s", nodname);
     57            bb_error_msg("failed to create: %s", nodname);
    6658
    6759        if (nodname == basedev) /* ex. /dev/hda - to /dev/hda1 ... */
     
    7466}
    7567
    76 #elif defined CONFIG_FEATURE_MAKEDEVS_TABLE
     68#elif ENABLE_FEATURE_MAKEDEVS_TABLE
    7769
    7870/* Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */
    7971
     72int makedevs_main(int argc, char **argv);
    8073int makedevs_main(int argc, char **argv)
    8174{
     
    8679    int ret = EXIT_SUCCESS;
    8780
    88     unsigned long flags;
    89     flags = bb_getopt_ulflags(argc, argv, "d:", &line);
     81    getopt32(argv, "d:", &line);
    9082    if (line)
    91         table = bb_xfopen(line, "r");
     83        table = xfopen(line, "r");
    9284
    9385    if (optind >= argc || (rootdir=argv[optind])==NULL) {
     
    9587    }
    9688
    97     bb_xchdir(rootdir);
     89    xchdir(rootdir);
    9890
    9991    umask(0);
     
    10698    }
    10799
    108     while ((line = bb_get_chomped_line_from_file(table))) {
     100    while ((line = xmalloc_getline(table))) {
    109101        char type;
    110102        unsigned int mode = 0755;
     
    130122            if (*line=='\0' || *line=='#' || isspace(*line))
    131123                continue;
    132             bb_error_msg("line %d invalid: '%s'\n", linenum, line);
     124            bb_error_msg("line %d invalid: '%s'", linenum, line);
    133125            ret = EXIT_FAILURE;
    134126            continue;
     
    138130        }
    139131
    140         gid = (*group) ? get_ug_id(group, bb_xgetgrnam) : getgid();
    141         uid = (*user) ? get_ug_id(user, bb_xgetpwnam) : getuid();
     132        gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid();
     133        uid = (*user) ? get_ug_id(user, xuname2uid) : getuid();
    142134        full_name = concat_path_file(rootdir, name);
    143135
     
    171163                goto loop;
    172164            }
    173         } else
    174         {
     165        } else {
    175166            dev_t rdev;
    176167
     
    196187                for (i = start; i < count; i++) {
    197188                    sprintf(full_name_inc, "%s%d", full_name, i);
    198                     rdev = (major << 8) + minor + (i * increment - start);
     189                    rdev = makedev(major, minor + (i * increment - start));
    199190                    if (mknod(full_name_inc, mode, rdev) == -1) {
    200                         bb_perror_msg("line %d: could not create node %s", linenum, full_name_inc);
     191                        bb_perror_msg("line %d: cannot create node %s", linenum, full_name_inc);
    201192                        ret = EXIT_FAILURE;
    202193                    }
     
    212203                free(full_name_inc);
    213204            } else {
    214                 rdev = (major << 8) + minor;
     205                rdev = makedev(major, minor);
    215206                if (mknod(full_name, mode, rdev) == -1) {
    216                     bb_perror_msg("line %d: could not create node %s", linenum, full_name);
     207                    bb_perror_msg("line %d: cannot create node %s", linenum, full_name);
    217208                    ret = EXIT_FAILURE;
    218209                }
  • branches/2.2.5/mindi-busybox/miscutils/mountpoint.c

    r821 r1765  
    1010 */
    1111
    12 #include "busybox.h"
    13 #include <sys/stat.h>
    14 #include <errno.h> /* errno */
    15 #include <string.h> /* strerror */
    16 #include <getopt.h> /* optind */
     12#include "libbb.h"
    1713
     14int mountpoint_main(int argc, char **argv);
    1815int mountpoint_main(int argc, char **argv)
    1916{
    20     int opt = bb_getopt_ulflags(argc, argv, "qdx");
     17    struct stat st;
     18    char *arg;
     19    int opt = getopt32(argv, "qdx");
    2120#define OPT_q (1)
    2221#define OPT_d (2)
     
    2524    if (optind != argc - 1)
    2625        bb_show_usage();
    27     {
    28         char *arg = argv[optind];
    29         struct stat st;
    3026
    31         if ( (opt & OPT_x && stat(arg, &st) == 0) || (lstat(arg, &st) == 0) ) {
    32             if (opt & OPT_x) {
    33                 if (S_ISBLK(st.st_mode))
    34                 {
    35                     bb_printf("%u:%u\n", major(st.st_rdev),
    36                                 minor(st.st_rdev));
    37                     return EXIT_SUCCESS;
    38                 } else {
    39                     if (opt & OPT_q)
    40                         putchar('\n');
    41                     else
    42                         bb_error_msg("%s: not a block device", arg);
    43                 }
    44                 return EXIT_FAILURE;
    45             } else
    46             if (S_ISDIR(st.st_mode)) {
    47                 dev_t st_dev = st.st_dev;
    48                 ino_t st_ino = st.st_ino;
    49                 char *p = bb_xasprintf("%s/..", arg);
     27    arg = argv[optind];
    5028
    51                 if (stat(p, &st) == 0) {
    52                     short ret = (st_dev != st.st_dev) ||
    53                         (st_dev == st.st_dev && st_ino == st.st_ino);
    54                     if (opt & OPT_d)
    55                         bb_printf("%u:%u\n", major(st_dev), minor(st_dev));
    56                     else if (!(opt & OPT_q))
    57                         bb_printf("%s is %sa mountpoint\n", arg, ret?"":"not ");
    58                     return !ret;
    59                 }
     29    if ( (opt & OPT_x && stat(arg, &st) == 0) || (lstat(arg, &st) == 0) ) {
     30        if (opt & OPT_x) {
     31            if (S_ISBLK(st.st_mode)) {
     32                printf("%u:%u\n", major(st.st_rdev),
     33                            minor(st.st_rdev));
     34                return EXIT_SUCCESS;
    6035            } else {
    61                 if (!(opt & OPT_q))
    62                     bb_error_msg("%s: not a directory", arg);
    63                 return EXIT_FAILURE;
     36                if (opt & OPT_q)
     37                    putchar('\n');
     38                else
     39                    bb_error_msg("%s: not a block device", arg);
    6440            }
     41            return EXIT_FAILURE;
     42        } else
     43        if (S_ISDIR(st.st_mode)) {
     44            dev_t st_dev = st.st_dev;
     45            ino_t st_ino = st.st_ino;
     46            char *p = xasprintf("%s/..", arg);
     47
     48            if (stat(p, &st) == 0) {
     49                int ret = (st_dev != st.st_dev) ||
     50                    (st_dev == st.st_dev && st_ino == st.st_ino);
     51                if (opt & OPT_d)
     52                    printf("%u:%u\n", major(st_dev), minor(st_dev));
     53                else if (!(opt & OPT_q))
     54                    printf("%s is %sa mountpoint\n", arg, ret?"":"not ");
     55                return !ret;
     56            }
     57        } else {
     58            if (!(opt & OPT_q))
     59                bb_error_msg("%s: not a directory", arg);
     60            return EXIT_FAILURE;
    6561        }
    66         if (!(opt & OPT_q))
    67             bb_perror_msg("%s", arg);
    68         return EXIT_FAILURE;
    6962    }
     63    if (!(opt & OPT_q))
     64        bb_perror_msg("%s", arg);
     65    return EXIT_FAILURE;
    7066}
  • branches/2.2.5/mindi-busybox/miscutils/mt.c

    r821 r1765  
    11/* vi: set sw=4 ts=4: */
    2 #include "busybox.h"
    3 #include <stdio.h>
    4 #include <stdlib.h>
    5 #include <string.h>
     2/*
     3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     4 */
     5
     6#include "libbb.h"
    67#include <sys/mtio.h>
    7 #include <fcntl.h>
    88
    99struct mt_opcodes {
    10     char *name;
     10    const char *name;
    1111    short value;
    1212};
     
    5151};
    5252
     53int mt_main(int argc, char **argv);
    5354int mt_main(int argc, char **argv)
    5455{
     
    7980
    8081    if (code->name == 0) {
    81         bb_error_msg("unrecognized opcode %s.", argv[1]);
     82        bb_error_msg("unrecognized opcode %s", argv[1]);
    8283        return EXIT_FAILURE;
    8384    }
     
    8586    op.mt_op = code->value;
    8687    if (argc >= 3)
    87         op.mt_count = atoi(argv[2]);
     88        op.mt_count = xatoi_u(argv[2]);
    8889    else
    8990        op.mt_count = 1;        /* One, not zero, right? */
     
    102103    }
    103104
    104     fd = bb_xopen3(file, mode, 0);
     105    fd = xopen(file, mode);
    105106
    106107    switch (code->value) {
    107108        case MTTELL:
    108             if (ioctl(fd, MTIOCPOS, &position) < 0)
    109                 bb_perror_msg_and_die("%s", file);
    110             printf ("At block %d.\n", (int) position.mt_blkno);
     109            ioctl_or_perror_and_die(fd, MTIOCPOS, &position, "%s", file);
     110            printf("At block %d.\n", (int) position.mt_blkno);
    111111            break;
    112112
    113113        default:
    114             if (ioctl(fd, MTIOCTOP, &op) != 0)
    115                 bb_perror_msg_and_die("%s", file);
     114            ioctl_or_perror_and_die(fd, MTIOCTOP, &op, "%s", file);
    116115            break;
    117116    }
  • branches/2.2.5/mindi-busybox/miscutils/runlevel.c

    r821 r1765  
    1313 */
    1414
    15 #include "busybox.h"
    16 #include <stdio.h>
    1715#include <utmp.h>
    18 #include <time.h>
    19 #include <stdlib.h>
     16#include "libbb.h"
    2017
    21 int runlevel_main(int argc, char *argv[])
     18int runlevel_main(int argc, char **argv);
     19int runlevel_main(int argc, char **argv)
    2220{
    23   struct utmp *ut;
    24   char prev;
     21    struct utmp *ut;
     22    char prev;
    2523
    26   if (argc > 1) utmpname(argv[1]);
     24    if (argc > 1) utmpname(argv[1]);
    2725
    28   setutent();
    29   while ((ut = getutent()) != NULL) {
    30     if (ut->ut_type == RUN_LVL) {
    31         prev = ut->ut_pid / 256;
    32         if (prev == 0) prev = 'N';
    33         printf("%c %c\n", prev, ut->ut_pid % 256);
     26    setutent();
     27    while ((ut = getutent()) != NULL) {
     28        if (ut->ut_type == RUN_LVL) {
     29            prev = ut->ut_pid / 256;
     30            if (prev == 0) prev = 'N';
     31            printf("%c %c\n", prev, ut->ut_pid % 256);
     32            if (ENABLE_FEATURE_CLEAN_UP)
     33                endutent();
     34            return 0;
     35        }
     36    }
     37
     38    puts("unknown");
     39
     40    if (ENABLE_FEATURE_CLEAN_UP)
    3441        endutent();
    35         return (0);
    36     }
    37   }
    38 
    39   printf("unknown\n");
    40   endutent();
    41   return (1);
     42    return 1;
    4243}
    43 
  • branches/2.2.5/mindi-busybox/miscutils/rx.c

    r821 r1765  
    22/*-------------------------------------------------------------------------
    33 * Filename:      xmodem.c
    4  * Version:       $Id: rx.c,v 1.2 2004/03/15 08:28:46 andersen Exp $
    54 * Copyright:     Copyright (C) 2001, Hewlett-Packard Company
    65 * Author:        Christopher Hoover <ch@hpl.hp.com>
     
    2120 */
    2221
    23 #include "busybox.h"
    24 #include <stdlib.h>
    25 #include <stdarg.h>
    26 #include <stdio.h>
    27 #include <unistd.h>
    28 #include <errno.h>
    29 #include <termios.h>
    30 #include <signal.h>
    31 #include <sys/types.h>
    32 #include <sys/stat.h>
    33 #include <fcntl.h>
    34 #include <string.h>
    35 
     22#include "libbb.h"
    3623
    3724#define SOH 0x01
     
    5744#define MAXERRORS 10
    5845
    59 static int read_byte(int fd, unsigned int timeout) {
     46static int read_byte(int fd, unsigned int timeout)
     47{
    6048    char buf[1];
    6149    int n;
     
    213201        length += blockLength;
    214202
    215         if (bb_full_write(filefd, blockBuf, blockLength) < 0) {
     203        if (full_write(filefd, blockBuf, blockLength) < 0) {
    216204            note_error("write to file failed: %m");
    217205            goto fatal;
     
    262250}
    263251
     252int rx_main(int argc, char **argv);
    264253int rx_main(int argc, char **argv)
    265254{
     
    275264
    276265    fn = argv[1];
    277     ttyfd = bb_xopen3(CURRENT_TTY, O_RDWR, 0);
    278     filefd = bb_xopen3(fn, O_RDWR|O_CREAT|O_TRUNC, 0666);
     266    ttyfd = xopen(CURRENT_TTY, O_RDWR);
     267    filefd = xopen(fn, O_RDWR|O_CREAT|O_TRUNC);
    279268
    280269    if (tcgetattr(ttyfd, &tty) < 0)
    281             bb_error_msg_and_die("%s: tcgetattr failed: %m\n", argv[0]);
     270            bb_perror_msg_and_die("tcgetattr");
    282271
    283272    orig_tty = tty;
     
    297286
    298287    if (n < 0)
    299             bb_error_msg_and_die("\n%s: receive failed:\n  %s\n",
    300                                argv[0], error_buf);
    301 
    302     bb_fflush_stdout_and_exit(EXIT_SUCCESS);
    303 }
     288        bb_error_msg_and_die("\nreceive failed:\n  %s", error_buf);
     289
     290    fflush_stdout_and_exit(EXIT_SUCCESS);
     291}
  • branches/2.2.5/mindi-busybox/miscutils/setsid.c

    r821 r1765  
    1515 */
    1616
    17 #include "busybox.h"
    18 #include <stdio.h>
    19 #include <unistd.h>
    20 #include <stdlib.h>
     17#include "libbb.h"
    2118
    22 int setsid_main(int argc, char *argv[])
     19int setsid_main(int argc, char **argv);
     20int setsid_main(int argc, char **argv)
    2321{
    2422    if (argc < 2)
    2523        bb_show_usage();
    2624
    27     if (getpgrp() == getpid()) {
    28         switch(fork()){
    29         case -1:
    30             bb_perror_msg_and_die("fork");
    31         case 0:
    32             break;
    33         default:    /* parent */
    34             exit(0);
    35         }
    36         /* child falls through */
    37     }
     25    /* Comment why is this necessary? */
     26    if (getpgrp() == getpid())
     27        forkexit_or_rexec(argv);
    3828
    3929    setsid();  /* no error possible */
    4030
    41     execvp(argv[1], argv + 1);
    42 
     31    BB_EXECVP(argv[1], argv + 1);
    4332    bb_perror_msg_and_die("%s", argv[1]);
    4433}
  • branches/2.2.5/mindi-busybox/miscutils/strings.c

    r821 r1765  
    33 * strings implementation for busybox
    44 *
    5  * Copyright (c) 1980, 1987
    6  *  The Regents of the University of California.  All rights reserved.
     5 * Copyright Tito Ragusa <farmatito@tiscali.it>
    76 *
    87 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
    9  *
    10  * Original copyright notice is retained at the end of this file.
    11  *
    12  * Modified for BusyBox by Erik Andersen <andersen@codepoet.org>
    13  * Badly hacked by Tito Ragusa <farmatito@tiscali.it>
    148 */
    159
    16 #include "busybox.h"
    17 #include <stdio.h>
    18 #include <stdlib.h>
    1910#include <getopt.h>
    20 #include <ctype.h>
     11
     12#include "libbb.h"
    2113
    2214#define WHOLE_FILE      1
     
    2517#define SIZE            8
    2618
     19int strings_main(int argc, char **argv);
    2720int strings_main(int argc, char **argv)
    2821{
    29     int n, c, i = 0, status = EXIT_SUCCESS;
    30     unsigned long opt;
    31     unsigned long count;
     22    int n, c, status = EXIT_SUCCESS;
     23    unsigned opt;
     24    unsigned count;
     25    off_t offset;
    3226    FILE *file = stdin;
    3327    char *string;
    3428    const char *fmt = "%s: ";
    35     char *n_arg = "4";
     29    const char *n_arg = "4";
    3630
    37     opt = bb_getopt_ulflags(argc, argv, "afon:", &n_arg);
     31    opt = getopt32(argv, "afon:", &n_arg);
    3832    /* -a is our default behaviour */
    39 
    40     argc -= optind;
     33    /*argc -= optind;*/
    4134    argv += optind;
    4235
    43     n = bb_xgetlarg(n_arg, 10, 1, INT_MAX);
     36    n = xatou_range(n_arg, 1, INT_MAX);
    4437    string = xzalloc(n + 1);
    4538    n--;
    4639
    47     if (argc == 0) {
     40    if (!*argv) {
    4841        fmt = "{%s}: ";
    49         *argv = (char *)bb_msg_standard_input;
     42        *--argv = (char *)bb_msg_standard_input;
    5043        goto PIPE;
    5144    }
    5245
    5346    do {
    54         if ((file = bb_wfopen(*argv, "r"))) {
    55 PIPE:
    56             count = 0;
    57             do {
    58                 c = fgetc(file);
    59                 if (isprint(c) || c == '\t') {
    60                     if (i <= n) {
    61                         string[i] = c;
    62                     } else {
    63                         putchar(c);
    64                     }
    65                     if (i == n) {
     47        file = fopen_or_warn(*argv, "r");
     48        if (!file) {
     49            status = EXIT_FAILURE;
     50            continue;
     51        }
     52 PIPE:
     53        offset = 0;
     54        count = 0;
     55        do {
     56            c = fgetc(file);
     57            if (isprint(c) || c == '\t') {
     58                if (count > n) {
     59                    putchar(c);
     60                } else {
     61                    string[count] = c;
     62                    if (count == n) {
    6663                        if (opt & PRINT_NAME) {
    6764                            printf(fmt, *argv);
    6865                        }
    6966                        if (opt & PRINT_OFFSET) {
    70                             printf("%7lo ", count - n);
     67                            printf("%7"OFF_FMT"o ", offset - n);
    7168                        }
    72                         printf("%s", string);
     69                        fputs(string, stdout);
    7370                    }
    74                     i++;
    75                 } else {
    76                     if (i > n) {
    77                         putchar('\n');
    78                     }
    79                     i = 0;
     71                    count++;
    8072                }
    81                 count++;
    82             } while (c != EOF);
    83             bb_fclose_nonstdin(file);
    84         } else {
    85             status = EXIT_FAILURE;
    86         }
    87     } while (--argc > 0);
     73            } else {
     74                if (count > n) {
     75                    putchar('\n');
     76                }
     77                count = 0;
     78            }
     79            offset++;
     80        } while (c != EOF);
     81        fclose_if_not_stdin(file);
     82    } while (*++argv);
    8883
    8984    if (ENABLE_FEATURE_CLEAN_UP)
    9085        free(string);
    9186
    92     bb_fflush_stdout_and_exit(status);
     87    fflush_stdout_and_exit(status);
    9388}
    94 
    95 /*
    96  * Copyright (c) 1980, 1987
    97  *  The Regents of the University of California.  All rights reserved.
    98  *
    99  * Redistribution and use in source and binary forms, with or without
    100  * modification, are permitted provided that the following conditions
    101  * are met:
    102  * 1. Redistributions of source code must retain the above copyright
    103  *    notice, this list of conditions and the following disclaimer.
    104  * 2. Redistributions in binary form must reproduce the above copyright
    105  *    notice, this list of conditions and the following disclaimer in the
    106  *    documentation and/or other materials provided with the distribution.
    107  *
    108  * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
    109  *      ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
    110  *
    111  * 4. Neither the name of the University nor the names of its contributors
    112  *    may be used to endorse or promote products derived from this software
    113  *    without specific prior written permission.
    114  *
    115  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    116  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    117  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    118  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    119  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    120  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    121  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    122  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    123  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    124  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    125  * SUCH DAMAGE.
    126  */
  • branches/2.2.5/mindi-busybox/miscutils/time.c

    r821 r1765  
    33   Copyright (C) 1990, 91, 92, 93, 96 Free Software Foundation, Inc.
    44
    5    Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     5   Licensed under GPL version 2, see file LICENSE in this tarball for details.
    66*/
    77/* Originally written by David Keppel <pardo@cs.washington.edu>.
     
    1010*/
    1111
    12 #include "busybox.h"
    13 #include <stdlib.h>
    14 #include <stdio.h>
    15 #include <signal.h>
    16 #include <errno.h>
    17 #include <getopt.h>
    18 #include <string.h>
    19 #include <limits.h>
    20 #include <unistd.h>
    21 #include <sys/types.h>  /* For pid_t. */
    22 #include <sys/wait.h>
    23 #include <sys/param.h>  /* For getpagesize, maybe.  */
    24 
    25 #define TV_MSEC tv_usec / 1000
    26 #include <sys/resource.h>
     12#include "libbb.h"
    2713
    2814/* Information on the resources used by a child process.  */
     
    3016    int waitstatus;
    3117    struct rusage ru;
    32     struct timeval start, elapsed;  /* Wallclock time of process.  */
     18    unsigned elapsed_ms;    /* Wallclock time of process.  */
    3319} resource_t;
    3420
     
    3622   usec = microseconds = 1/1,000,000 (1*10e-6) second.  */
    3723
    38 #ifndef TICKS_PER_SEC
    39 #define TICKS_PER_SEC 100
    40 #endif
    41 
    42 /* The number of milliseconds in one `tick' used by the `rusage' structure.  */
    43 #define MSEC_PER_TICK (1000 / TICKS_PER_SEC)
    44 
    45 /* Return the number of clock ticks that occur in M milliseconds.  */
    46 #define MSEC_TO_TICKS(m) ((m) / MSEC_PER_TICK)
    47 
    4824#define UL unsigned long
    4925
    50 static const char *const default_format = "real\t%E\nuser\t%u\nsys\t%T";
     26static const char default_format[] ALIGN1 = "real\t%E\nuser\t%u\nsys\t%T";
    5127
    5228/* The output format for the -p option .*/
    53 static const char *const posix_format = "real %e\nuser %U\nsys %S";
     29static const char posix_format[] ALIGN1 = "real %e\nuser %U\nsys %S";
    5430
    5531
    5632/* Format string for printing all statistics verbosely.
    5733   Keep this output to 24 lines so users on terminals can see it all.*/
    58 static const char *const long_format =
     34static const char long_format[] ALIGN1 =
    5935    "\tCommand being timed: \"%C\"\n"
    6036    "\tUser time (seconds): %U\n"
     
    7854    "\tSocket messages received: %r\n"
    7955    "\tSignals delivered: %k\n"
    80     "\tPage size (bytes): %Z\n" "\tExit status: %x";
    81 
    82 
    83   /* Wait for and fill in data on child process PID.
    84      Return 0 on error, 1 if ok.  */
     56    "\tPage size (bytes): %Z\n"
     57    "\tExit status: %x";
     58
     59
     60/* Wait for and fill in data on child process PID.
     61   Return 0 on error, 1 if ok.  */
    8562
    8663/* pid_t is short on BSDI, so don't try to promote it.  */
     
    8865{
    8966    int status;
    90 
    9167    pid_t caught;
    9268
     
    9773            return 0;
    9874    }
    99 
    100     gettimeofday(&resp->elapsed, (struct timezone *) 0);
    101     resp->elapsed.tv_sec -= resp->start.tv_sec;
    102     if (resp->elapsed.tv_usec < resp->start.tv_usec) {
    103         /* Manually carry a one from the seconds field.  */
    104         resp->elapsed.tv_usec += 1000000;
    105         --resp->elapsed.tv_sec;
    106     }
    107     resp->elapsed.tv_usec -= resp->start.tv_usec;
    108 
     75    resp->elapsed_ms = (monotonic_us() / 1000) - resp->elapsed_ms;
    10976    resp->waitstatus = status;
    110 
    11177    return 1;
    11278}
    11379
    114 /* Print ARGV to FP, with each entry in ARGV separated by FILLER.  */
    115 static void fprintargv(FILE * fp, char *const *argv, const char *filler)
    116 {
    117     char *const *av;
    118 
    119     av = argv;
    120     fputs(*av, fp);
    121     while (*++av) {
    122         fputs(filler, fp);
    123         fputs(*av, fp);
    124     }
    125     if (ferror(fp))
    126         bb_error_msg_and_die(bb_msg_write_error);
     80/* Print ARGV, with each entry in ARGV separated by FILLER.  */
     81static void printargv(char *const *argv, const char *filler)
     82{
     83    fputs(*argv, stdout);
     84    while (*++argv) {
     85        fputs(filler, stdout);
     86        fputs(*argv, stdout);
     87    }
    12788}
    12889
     
    13798static unsigned long ptok(unsigned long pages)
    13899{
    139     static unsigned long ps = 0;
     100    static unsigned long ps;
    140101    unsigned long tmp;
    141     static long size = LONG_MAX;
    142102
    143103    /* Initialization.  */
    144104    if (ps == 0)
    145         ps = (long) getpagesize();
     105        ps = getpagesize();
    146106
    147107    /* Conversion.  */
    148108    if (pages > (LONG_MAX / ps)) {  /* Could overflow.  */
    149109        tmp = pages / 1024; /* Smaller first, */
    150         size = tmp * ps;    /* then larger.  */
    151     } else {            /* Could underflow.  */
    152         tmp = pages * ps;   /* Larger first, */
    153         size = tmp / 1024;  /* then smaller.  */
    154     }
    155     return size;
     110        return tmp * ps;    /* then larger.  */
     111    }
     112    /* Could underflow.  */
     113    tmp = pages * ps;   /* Larger first, */
     114    return tmp / 1024;  /* then smaller.  */
    156115}
    157116
    158117/* summarize: Report on the system use of a command.
    159118
    160    Copy the FMT argument to FP except that `%' sequences
     119   Print the FMT argument except that `%' sequences
    161120   have special meaning, and `\n' and `\t' are translated into
    162121   newline and tab, respectively, and `\\' is translated into `\'.
     
    196155   and dividing by elapsed real time.
    197156
    198    FP is the stream to print to.
    199157   FMT is the format string, interpreted as described above.
    200158   COMMAND is the command and args that are being summarized.
    201159   RESP is resource information on the command.  */
    202160
    203 static void summarize(FILE * fp, const char *fmt, char **command,
    204                       resource_t * resp)
    205 {
    206     unsigned long r;    /* Elapsed real milliseconds.  */
    207     unsigned long v;    /* Elapsed virtual (CPU) milliseconds.  */
     161#ifndef TICKS_PER_SEC
     162#define TICKS_PER_SEC 100
     163#endif
     164
     165static void summarize(const char *fmt, char **command, resource_t * resp)
     166{
     167    unsigned vv_ms;     /* Elapsed virtual (CPU) milliseconds */
     168    unsigned cpu_ticks; /* Same, in "CPU ticks" */
    208169
    209170    if (WIFSTOPPED(resp->waitstatus))
    210         fprintf(fp, "Command stopped by signal %d\n",
     171        printf("Command stopped by signal %u\n",
    211172                WSTOPSIG(resp->waitstatus));
    212173    else if (WIFSIGNALED(resp->waitstatus))
    213         fprintf(fp, "Command terminated by signal %d\n",
     174        printf("Command terminated by signal %u\n",
    214175                WTERMSIG(resp->waitstatus));
    215176    else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus))
    216         fprintf(fp, "Command exited with non-zero status %d\n",
     177        printf("Command exited with non-zero status %u\n",
    217178                WEXITSTATUS(resp->waitstatus));
    218179
    219     /* Convert all times to milliseconds.  Occasionally, one of these values
    220        comes out as zero.  Dividing by zero causes problems, so we first
    221        check the time value.  If it is zero, then we take `evasive action'
    222        instead of calculating a value.  */
    223 
    224     r = resp->elapsed.tv_sec * 1000 + resp->elapsed.tv_usec / 1000;
    225 
    226     v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC +
    227         resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC;
     180    vv_ms = (resp->ru.ru_utime.tv_sec + resp->ru.ru_stime.tv_sec) * 1000
     181          + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000;
     182
     183#if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000
     184    /* 1000 is exactly divisible by TICKS_PER_SEC */
     185    cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC);
     186#else
     187    cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000;
     188#endif
     189    if (!cpu_ticks) cpu_ticks = 1; /* we divide by it, must be nonzero */
     190
     191    /* putchar() != putc(stdout) in glibc! */
    228192
    229193    while (*fmt) {
     194        /* Handle leading literal part */
     195        int n = strcspn(fmt, "%\\");
     196        if (n) {
     197            printf("%.*s", n, fmt);
     198            fmt += n;
     199            continue;
     200        }
     201
    230202        switch (*fmt) {
     203#ifdef NOT_NEEDED
     204        /* Handle literal char */
     205        /* Usually we optimize for size, but there is a limit
     206         * for everything. With this we do a lot of 1-byte writes */
     207        default:
     208            putc(*fmt, stdout);
     209            break;
     210#endif
     211
    231212        case '%':
    232213            switch (*++fmt) {
    233             case '%':   /* Literal '%'.  */
    234                 putc('%', fp);
    235                 break;
     214#ifdef NOT_NEEDED_YET
     215        /* Our format strings do not have these */
     216        /* and we do not take format str from user */
     217            default:
     218                putc('%', stdout);
     219                /*FALLTHROUGH*/
     220            case '%':
     221                if (!*fmt) goto ret;
     222                putc(*fmt, stdout);
     223                break;
     224#endif
    236225            case 'C':   /* The command that got timed.  */
    237                 fprintargv(fp, command, " ");
     226                printargv(command, " ");
    238227                break;
    239228            case 'D':   /* Average unshared data size.  */
    240                 fprintf(fp, "%lu",
    241                         MSEC_TO_TICKS(v) == 0 ? 0 :
    242                         ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
    243                         ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
    244                 break;
    245             case 'E':   /* Elapsed real (wall clock) time.  */
    246                 if (resp->elapsed.tv_sec >= 3600)   /* One hour -> h:m:s.  */
    247                     fprintf(fp, "%ldh %ldm %02lds",
    248                             resp->elapsed.tv_sec / 3600,
    249                             (resp->elapsed.tv_sec % 3600) / 60,
    250                             resp->elapsed.tv_sec % 60);
     229                printf("%lu",
     230                        ptok((UL) resp->ru.ru_idrss) / cpu_ticks +
     231                        ptok((UL) resp->ru.ru_isrss) / cpu_ticks);
     232                break;
     233            case 'E': { /* Elapsed real (wall clock) time.  */
     234                unsigned seconds = resp->elapsed_ms / 1000;
     235                if (seconds >= 3600)    /* One hour -> h:m:s.  */
     236                    printf("%uh %um %02us",
     237                            seconds / 3600,
     238                            (seconds % 3600) / 60,
     239                            seconds % 60);
    251240                else
    252                     fprintf(fp, "%ldm %ld.%02lds",  /* -> m:s.  */
    253                             resp->elapsed.tv_sec / 60,
    254                             resp->elapsed.tv_sec % 60,
    255                             resp->elapsed.tv_usec / 10000);
    256                 break;
     241                    printf("%um %u.%02us",  /* -> m:s.  */
     242                            seconds / 60,
     243                            seconds % 60,
     244                            (unsigned)(resp->elapsed_ms / 10) % 100);
     245                break;
     246            }
    257247            case 'F':   /* Major page faults.  */
    258                 fprintf(fp, "%ld", resp->ru.ru_majflt);
     248                printf("%lu", resp->ru.ru_majflt);
    259249                break;
    260250            case 'I':   /* Inputs.  */
    261                 fprintf(fp, "%ld", resp->ru.ru_inblock);
     251                printf("%lu", resp->ru.ru_inblock);
    262252                break;
    263253            case 'K':   /* Average mem usage == data+stack+text.  */
    264                 fprintf(fp, "%lu",
    265                         MSEC_TO_TICKS(v) == 0 ? 0 :
    266                         ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
    267                         ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v) +
    268                         ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
     254                printf("%lu",
     255                        ptok((UL) resp->ru.ru_idrss) / cpu_ticks +
     256                        ptok((UL) resp->ru.ru_isrss) / cpu_ticks +
     257                        ptok((UL) resp->ru.ru_ixrss) / cpu_ticks);
    269258                break;
    270259            case 'M':   /* Maximum resident set size.  */
    271                 fprintf(fp, "%lu", ptok((UL) resp->ru.ru_maxrss));
     260                printf("%lu", ptok((UL) resp->ru.ru_maxrss));
    272261                break;
    273262            case 'O':   /* Outputs.  */
    274                 fprintf(fp, "%ld", resp->ru.ru_oublock);
     263                printf("%lu", resp->ru.ru_oublock);
    275264                break;
    276265            case 'P':   /* Percent of CPU this job got.  */
    277266                /* % cpu is (total cpu time)/(elapsed time).  */
    278                 if (r > 0)
    279                     fprintf(fp, "%lu%%", (v * 100 / r));
     267                if (resp->elapsed_ms > 0)
     268                    printf("%u%%", (unsigned)(vv_ms * 100 / resp->elapsed_ms));
    280269                else
    281                     fprintf(fp, "?%%");
     270                    printf("?%%");
    282271                break;
    283272            case 'R':   /* Minor page faults (reclaims).  */
    284                 fprintf(fp, "%ld", resp->ru.ru_minflt);
     273                printf("%lu", resp->ru.ru_minflt);
    285274                break;
    286275            case 'S':   /* System time.  */
    287                 fprintf(fp, "%ld.%02ld",
    288                         resp->ru.ru_stime.tv_sec,
    289                         resp->ru.ru_stime.TV_MSEC / 10);
     276                printf("%u.%02u",
     277                        (unsigned)resp->ru.ru_stime.tv_sec,
     278                        (unsigned)(resp->ru.ru_stime.tv_usec / 10000));
    290279                break;
    291280            case 'T':   /* System time.  */
    292281                if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s.  */
    293                     fprintf(fp, "%ldh %ldm %02lds",
    294                             resp->ru.ru_stime.tv_sec / 3600,
    295                             (resp->ru.ru_stime.tv_sec % 3600) / 60,
    296                             resp->ru.ru_stime.tv_sec % 60);
     282                    printf("%uh %um %02us",
     283                            (unsigned)(resp->ru.ru_stime.tv_sec / 3600),
     284                            (unsigned)(resp->ru.ru_stime.tv_sec % 3600) / 60,
     285                            (unsigned)(resp->ru.ru_stime.tv_sec % 60));
    297286                else
    298                     fprintf(fp, "%ldm %ld.%02lds",  /* -> m:s.  */
    299                             resp->ru.ru_stime.tv_sec / 60,
    300                             resp->ru.ru_stime.tv_sec % 60,
    301                             resp->ru.ru_stime.tv_usec / 10000);
     287                    printf("%um %u.%02us",  /* -> m:s.  */
     288                            (unsigned)(resp->ru.ru_stime.tv_sec / 60),
     289                            (unsigned)(resp->ru.ru_stime.tv_sec % 60),
     290                            (unsigned)(resp->ru.ru_stime.tv_usec / 10000));
    302291                break;
    303292            case 'U':   /* User time.  */
    304                 fprintf(fp, "%ld.%02ld",
    305                         resp->ru.ru_utime.tv_sec,
    306                         resp->ru.ru_utime.TV_MSEC / 10);
     293                printf("%u.%02u",
     294                        (unsigned)resp->ru.ru_utime.tv_sec,
     295                        (unsigned)(resp->ru.ru_utime.tv_usec / 10000));
    307296                break;
    308297            case 'u':   /* User time.  */
    309298                if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s.  */
    310                     fprintf(fp, "%ldh %ldm %02lds",
    311                             resp->ru.ru_utime.tv_sec / 3600,
    312                             (resp->ru.ru_utime.tv_sec % 3600) / 60,
    313                             resp->ru.ru_utime.tv_sec % 60);
     299                    printf("%uh %um %02us",
     300                            (unsigned)(resp->ru.ru_utime.tv_sec / 3600),
     301                            (unsigned)(resp->ru.ru_utime.tv_sec % 3600) / 60,
     302                            (unsigned)(resp->ru.ru_utime.tv_sec % 60));
    314303                else
    315                     fprintf(fp, "%ldm %ld.%02lds",  /* -> m:s.  */
    316                             resp->ru.ru_utime.tv_sec / 60,
    317                             resp->ru.ru_utime.tv_sec % 60,
    318                             resp->ru.ru_utime.tv_usec / 10000);
     304                    printf("%um %u.%02us",  /* -> m:s.  */
     305                            (unsigned)(resp->ru.ru_utime.tv_sec / 60),
     306                            (unsigned)(resp->ru.ru_utime.tv_sec % 60),
     307                            (unsigned)(resp->ru.ru_utime.tv_usec / 10000));
    319308                break;
    320309            case 'W':   /* Times swapped out.  */
    321                 fprintf(fp, "%ld", resp->ru.ru_nswap);
     310                printf("%lu", resp->ru.ru_nswap);
    322311                break;
    323312            case 'X':   /* Average shared text size.  */
    324                 fprintf(fp, "%lu",
    325                         MSEC_TO_TICKS(v) == 0 ? 0 :
    326                         ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
     313                printf("%lu", ptok((UL) resp->ru.ru_ixrss) / cpu_ticks);
    327314                break;
    328315            case 'Z':   /* Page size.  */
    329                 fprintf(fp, "%d", getpagesize());
     316                printf("%u", getpagesize());
    330317                break;
    331318            case 'c':   /* Involuntary context switches.  */
    332                 fprintf(fp, "%ld", resp->ru.ru_nivcsw);
     319                printf("%lu", resp->ru.ru_nivcsw);
    333320                break;
    334321            case 'e':   /* Elapsed real time in seconds.  */
    335                 fprintf(fp, "%ld.%02ld",
    336                         resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000);
     322                printf("%u.%02u",
     323                        (unsigned)resp->elapsed_ms / 1000,
     324                        (unsigned)(resp->elapsed_ms / 10) % 100);
    337325                break;
    338326            case 'k':   /* Signals delivered.  */
    339                 fprintf(fp, "%ld", resp->ru.ru_nsignals);
     327                printf("%lu", resp->ru.ru_nsignals);
    340328                break;
    341329            case 'p':   /* Average stack segment.  */
    342                 fprintf(fp, "%lu",
    343                         MSEC_TO_TICKS(v) == 0 ? 0 :
    344                         ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
     330                printf("%lu", ptok((UL) resp->ru.ru_isrss) / cpu_ticks);
    345331                break;
    346332            case 'r':   /* Incoming socket messages received.  */
    347                 fprintf(fp, "%ld", resp->ru.ru_msgrcv);
     333                printf("%lu", resp->ru.ru_msgrcv);
    348334                break;
    349335            case 's':   /* Outgoing socket messages sent.  */
    350                 fprintf(fp, "%ld", resp->ru.ru_msgsnd);
     336                printf("%lu", resp->ru.ru_msgsnd);
    351337                break;
    352338            case 't':   /* Average resident set size.  */
    353                 fprintf(fp, "%lu",
    354                         MSEC_TO_TICKS(v) == 0 ? 0 :
    355                         ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v));
     339                printf("%lu", ptok((UL) resp->ru.ru_idrss) / cpu_ticks);
    356340                break;
    357341            case 'w':   /* Voluntary context switches.  */
    358                 fprintf(fp, "%ld", resp->ru.ru_nvcsw);
     342                printf("%lu", resp->ru.ru_nvcsw);
    359343                break;
    360344            case 'x':   /* Exit status.  */
    361                 fprintf(fp, "%d", WEXITSTATUS(resp->waitstatus));
    362                 break;
    363             case '\0':
    364                 putc('?', fp);
    365                 return;
    366             default:
    367                 putc('?', fp);
    368                 putc(*fmt, fp);
     345                printf("%u", WEXITSTATUS(resp->waitstatus));
     346                break;
    369347            }
    370             ++fmt;
    371348            break;
    372349
     350#ifdef NOT_NEEDED_YET
    373351        case '\\':      /* Format escape.  */
    374352            switch (*++fmt) {
     353            default:
     354                putc('\\', stdout);
     355                /*FALLTHROUGH*/
     356            case '\\':
     357                if (!*fmt) goto ret;
     358                putc(*fmt, stdout);
     359                break;
    375360            case 't':
    376                 putc('\t', fp);
     361                putc('\t', stdout);
    377362                break;
    378363            case 'n':
    379                 putc('\n', fp);
    380                 break;
    381             case '\\':
    382                 putc('\\', fp);
    383                 break;
    384             default:
    385                 putc('?', fp);
    386                 putc('\\', fp);
    387                 putc(*fmt, fp);
     364                putc('\n', stdout);
     365                break;
    388366            }
    389             ++fmt;
    390367            break;
    391 
    392         default:
    393             putc(*fmt++, fp);
     368#endif
    394369        }
    395 
    396         if (ferror(fp))
    397             bb_error_msg_and_die(bb_msg_write_error);
    398     }
    399     putc('\n', fp);
    400 
    401     if (ferror(fp))
    402         bb_error_msg_and_die(bb_msg_write_error);
     370        ++fmt;
     371    }
     372 /* ret: */
     373    putc('\n', stdout);
    403374}
    404375
     
    410381    __sighandler_t interrupt_signal, quit_signal;
    411382
    412     gettimeofday(&resp->start, (struct timezone *) 0);
     383    resp->elapsed_ms = monotonic_us() / 1000;
    413384    pid = vfork();      /* Run CMD as child process.  */
    414385    if (pid < 0)
     
    417388        /* Don't cast execvp arguments; that causes errors on some systems,
    418389           versus merely warnings if the cast is left off.  */
    419         execvp(cmd[0], cmd);
     390        BB_EXECVP(cmd[0], cmd);
    420391        bb_error_msg("cannot run %s", cmd[0]);
    421392        _exit(errno == ENOENT ? 127 : 126);
     
    434405}
    435406
     407int time_main(int argc, char **argv);
    436408int time_main(int argc, char **argv)
    437409{
    438     int gotone;
    439410    resource_t res;
    440411    const char *output_format = default_format;
    441 
    442     argc--;
    443     argv++;
     412    char c;
     413
     414    goto next;
    444415    /* Parse any options  -- don't use getopt() here so we don't
    445416     * consume the args of our client application... */
    446     while (argc > 0 && **argv == '-') {
    447         gotone = 0;
    448         while (gotone == 0 && *++(*argv)) {
    449             switch (**argv) {
     417    while (argc > 0 && argv[0][0] == '-') {
     418        while ((c = *++*argv)) {
     419            switch (c) {
    450420            case 'v':
    451421                output_format = long_format;
     
    457427                bb_show_usage();
    458428            }
    459             argc--;
    460             argv++;
    461             gotone = 1;
    462429        }
    463     }
    464 
    465     if (argv == NULL || *argv == NULL)
    466         bb_show_usage();
     430 next:
     431        argv++;
     432        argc--;
     433        if (!argc)
     434            bb_show_usage();
     435    }
    467436
    468437    run_command(argv, &res);
    469     summarize(stderr, output_format, argv, &res);
    470     fflush(stderr);
     438
     439    /* Cheat. printf's are shorter :) */
     440    stdout = stderr;
     441    dup2(2, 1); /* just in case libc does something silly :( */
     442    summarize(output_format, argv, &res);
    471443
    472444    if (WIFSTOPPED(res.waitstatus))
    473         exit(WSTOPSIG(res.waitstatus));
    474     else if (WIFSIGNALED(res.waitstatus))
    475         exit(WTERMSIG(res.waitstatus));
    476     else if (WIFEXITED(res.waitstatus))
    477         exit(WEXITSTATUS(res.waitstatus));
    478     return 0;
    479 }
     445        return WSTOPSIG(res.waitstatus);
     446    if (WIFSIGNALED(res.waitstatus))
     447        return WTERMSIG(res.waitstatus);
     448    if (WIFEXITED(res.waitstatus))
     449        return WEXITSTATUS(res.waitstatus);
     450    fflush_stdout_and_exit(0);
     451}
  • branches/2.2.5/mindi-busybox/miscutils/watchdog.c

    r821 r1765  
    99 */
    1010
    11 #include "busybox.h"
    12 #include <stdio.h>
    13 #include <fcntl.h>
    14 #include <unistd.h>
    15 #include <stdlib.h>
    16 #include <signal.h>
     11#include "libbb.h"
    1712
    1813#define OPT_FOREGROUND 0x01
    1914#define OPT_TIMER      0x02
    2015
    21 /* Watchdog file descriptor */
    22 static int fd;
    23 
    24 static void watchdog_shutdown(int ATTRIBUTE_UNUSED unused)
     16static void watchdog_shutdown(int ATTRIBUTE_UNUSED sig) ATTRIBUTE_NORETURN;
     17static void watchdog_shutdown(int ATTRIBUTE_UNUSED sig)
    2518{
    26     write(fd, "V", 1);  /* Magic, see watchdog-api.txt in kernel */
    27     close(fd);
     19    write(3, "V", 1);   /* Magic, see watchdog-api.txt in kernel */
     20    if (ENABLE_FEATURE_CLEAN_UP)
     21        close(3);
    2822    exit(0);
    2923}
    3024
     25int watchdog_main(int argc, char **argv);
    3126int watchdog_main(int argc, char **argv)
    3227{
    33     unsigned long opts;
    34     unsigned long timer_duration = 30; /* Userspace timer duration, in seconds */
     28    unsigned opts;
     29    unsigned timer_duration = 30; /* Userspace timer duration, in seconds */
    3530    char *t_arg;
    3631
    37     opts = bb_getopt_ulflags(argc, argv, "Ft:", &t_arg);
     32    opt_complementary = "=1"; /* must have 1 argument */
     33    opts = getopt32(argv, "Ft:", &t_arg);
    3834
    3935    if (opts & OPT_TIMER)
    40         timer_duration = bb_xgetlarg(t_arg, 10, 0, INT_MAX);
     36        timer_duration = xatou(t_arg);
    4137
    42     /* We're only interested in the watchdog device .. */
    43     if (optind < argc - 1 || argc == 1)
    44         bb_show_usage();
    45 
    46 #ifdef BB_NOMMU
    47     if (!(opts & OPT_FOREGROUND))
    48         vfork_daemon_rexec(0, 1, argc, argv, "-F");
    49 #else
    50     bb_xdaemon(0, 1);
    51 #endif
     38    if (!(opts & OPT_FOREGROUND)) {
     39        bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
     40    }
    5241
    5342    signal(SIGHUP, watchdog_shutdown);
    5443    signal(SIGINT, watchdog_shutdown);
    5544
    56     fd = bb_xopen(argv[argc - 1], O_WRONLY);
     45    /* Use known fd # - avoid needing global 'int fd' */
     46    xmove_fd(xopen(argv[argc - 1], O_WRONLY), 3);
    5747
    5848    while (1) {
     
    6151         * is undefined at this point -- PFM
    6252         */
    63         write(fd, "\0", 1);
     53        write(3, "", 1);
    6454        sleep(timer_duration);
    6555    }
    6656
    6757    watchdog_shutdown(0);
    68 
    69     return EXIT_SUCCESS;
     58    /* return EXIT_SUCCESS; */
    7059}
Note: See TracChangeset for help on using the changeset viewer.