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


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

Legend:

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

    r1765 r2725  
     1# DO NOT EDIT. This file is generated from Config.src
    12#
    23# For a description of the syntax of this configuration file,
     
    89config BASENAME
    910    bool "basename"
     11    default y
     12    help
     13      basename is used to strip the directory and suffix from filenames,
     14      leaving just the filename itself. Enable this option if you wish
     15      to enable the 'basename' utility.
     16config CAT
     17    bool "cat"
     18    default y
     19    help
     20      cat is used to concatenate files and print them to the standard
     21      output. Enable this option if you wish to enable the 'cat' utility.
     22config DATE
     23    bool "date"
     24    default y
     25    help
     26      date is used to set the system date or display the
     27      current time in the given format.
     28
     29config FEATURE_DATE_ISOFMT
     30    bool "Enable ISO date format output (-I)"
     31    default y
     32    depends on DATE
     33    help
     34      Enable option (-I) to output an ISO-8601 compliant
     35      date/time string.
     36
     37# defaults to "no": stat's nanosecond field is a bit non-portable
     38config FEATURE_DATE_NANO
     39    bool "Support %[num]N nanosecond format specifier"
    1040    default n
    11     help
    12       basename is used to strip the directory and suffix from filenames,
    13       leaving just the filename itself.  Enable this option if you wish
    14       to enable the 'basename' utility.
     41    depends on DATE && PLATFORM_LINUX # syscall(__NR_clock_gettime)
     42    help
     43      Support %[num]N format specifier. Adds ~250 bytes of code.
     44
     45config FEATURE_DATE_COMPAT
     46    bool "Support weird 'date MMDDhhmm[[YY]YY][.ss]' format"
     47    default y
     48    depends on DATE
     49    help
     50      System time can be set by 'date -s DATE' and simply 'date DATE',
     51      but formats of DATE string are different. 'date DATE' accepts
     52      a rather weird MMDDhhmm[[YY]YY][.ss] format with completely
     53      unnatural placement of year between minutes and seconds.
     54      date -s (and other commands like touch -d) use more sensible
     55      formats (for one, ISO format YYYY-MM-DD hh:mm:ss.ssssss).
     56
     57      With this option off, 'date DATE' is 'date -s DATE' support
     58      the same format. With it on, 'date DATE' additionally supports
     59      MMDDhhmm[[YY]YY][.ss] format.
     60config TEST
     61    bool "test"
     62    default y
     63    help
     64      test is used to check file types and compare values,
     65      returning an appropriate exit code. The bash shell
     66      has test built in, ash can build it in optionally.
     67
     68config FEATURE_TEST_64
     69    bool "Extend test to 64 bit"
     70    default y
     71    depends on TEST || ASH_BUILTIN_TEST || HUSH
     72    help
     73      Enable 64-bit support in test.
     74config TR
     75    bool "tr"
     76    default y
     77    help
     78      tr is used to squeeze, and/or delete characters from standard
     79      input, writing to standard output.
     80
     81config FEATURE_TR_CLASSES
     82    bool "Enable character classes (such as [:upper:])"
     83    default y
     84    depends on TR
     85    help
     86      Enable character classes, enabling commands such as:
     87      tr [:upper:] [:lower:] to convert input into lowercase.
     88
     89config FEATURE_TR_EQUIV
     90    bool "Enable equivalence classes"
     91    default y
     92    depends on TR
     93    help
     94      Enable equivalence classes, which essentially add the enclosed
     95      character to the current set. For instance, tr [=a=] xyz would
     96      replace all instances of 'a' with 'xyz'. This option is mainly
     97      useful for cases when no other way of expressing a character
     98      is possible.
     99config BASE64
     100    bool "base64"
     101    default y
     102    help
     103      Base64 encode and decode
    15104
    16105config CAL
    17106    bool "cal"
    18     default n
     107    default y
    19108    help
    20109      cal is used to display a monthly calender.
    21 
    22 config CAT
    23     bool "cat"
    24     default n
    25     help
    26       cat is used to concatenate files and print them to the standard
    27       output.  Enable this option if you wish to enable the 'cat' utility.
    28110
    29111config CATV
    30112    bool "catv"
    31     default n
     113    default y
    32114    help
    33115      Display nonprinting characters as escape sequences (like some
     
    36118config CHGRP
    37119    bool "chgrp"
    38     default n
     120    default y
    39121    help
    40122      chgrp is used to change the group ownership of files.
     
    42124config CHMOD
    43125    bool "chmod"
    44     default n
     126    default y
    45127    help
    46128      chmod is used to change the access permission of files.
     
    48130config CHOWN
    49131    bool "chown"
    50     default n
     132    default y
    51133    help
    52134      chown is used to change the user and/or group ownership
    53135      of files.
    54136
     137config FEATURE_CHOWN_LONG_OPTIONS
     138    bool "Enable long options"
     139    default y
     140    depends on CHOWN && LONG_OPTS
     141    help
     142      Enable use of long options
     143
    55144config CHROOT
    56145    bool "chroot"
    57     default n
     146    default y
    58147    help
    59148      chroot is used to change the root directory and run a command.
     
    62151config CKSUM
    63152    bool "cksum"
    64     default n
     153    default y
    65154    help
    66155      cksum is used to calculate the CRC32 checksum of a file.
     
    68157config COMM
    69158    bool "comm"
    70     default n
     159    default y
    71160    help
    72161      comm is used to compare two files line by line and return
     
    75164config CP
    76165    bool "cp"
    77     default n
     166    default y
    78167    help
    79168      cp is used to copy files and directories.
     169
     170config FEATURE_CP_LONG_OPTIONS
     171    bool "Enable long options for cp"
     172    default y
     173    depends on CP && LONG_OPTS
     174    help
     175      Enable long options for cp.
     176      Also add support for --parents option.
    80177
    81178config CUT
    82179    bool "cut"
    83     default n
     180    default y
    84181    help
    85182      cut is used to print selected parts of lines from
    86183      each file to stdout.
    87184
    88 config DATE
    89     bool "date"
    90     default n
    91     help
    92       date is used to set the system date or display the
    93       current time in the given format.
    94 
    95 config FEATURE_DATE_ISOFMT
    96     bool "Enable ISO date format output (-I)"
    97     default y
    98     depends on DATE
    99     help
    100       Enable option (-I) to output an ISO-8601 compliant
    101       date/time string.
    102 
    103185config DD
    104186    bool "dd"
    105     default n
     187    default y
    106188    help
    107189      dd copies a file (from standard input to standard output,
     
    114196    depends on DD
    115197    help
    116       sending a SIGUSR1 signal to a running `dd' process makes it
     198      Sending a SIGUSR1 signal to a running `dd' process makes it
    117199      print to standard error the number of records read and written
    118200      so far, then to resume copying.
    119201
    120       $ dd if=/dev/zero of=/dev/null& pid=$! $ kill -USR1 $pid; sleep 1; kill $pid
    121       10899206+0 records in 10899206+0 records out
     202      $ dd if=/dev/zero of=/dev/null&
     203      $ pid=$! kill -USR1 $pid; sleep 1; kill $pid
     204      10899206+0 records in
     205      10899206+0 records out
     206
     207config FEATURE_DD_THIRD_STATUS_LINE
     208    bool "Enable the third status line upon signal"
     209    default y
     210    depends on DD && FEATURE_DD_SIGNAL_HANDLING
     211    help
     212      Displays a coreutils-like third status line with transferred bytes,
     213      elapsed time and speed.
    122214
    123215config FEATURE_DD_IBS_OBS
    124216    bool "Enable ibs, obs and conv options"
    125     default n
     217    default y
    126218    depends on DD
    127219    help
     
    131223config DF
    132224    bool "df"
    133     default n
     225    default y
    134226    help
    135227      df reports the amount of disk space used and available
    136228      on filesystems.
    137229
     230config FEATURE_DF_FANCY
     231    bool "Enable -a, -i, -B"
     232    default y
     233    depends on DF
     234    help
     235      This option enables -a, -i and -B.
     236
     237        -a Show all filesystems
     238        -i Inodes
     239        -B <SIZE> Blocksize
     240
    138241config DIRNAME
    139242    bool "dirname"
    140     default n
     243    default y
    141244    help
    142245      dirname is used to strip a non-directory suffix from
     
    145248config DOS2UNIX
    146249    bool "dos2unix/unix2dos"
    147     default n
     250    default y
    148251    help
    149252      dos2unix is used to convert a text file from DOS format to
     
    160263config DU
    161264    bool "du (default blocksize of 512 bytes)"
    162     default n
     265    default y
    163266    help
    164267      du is used to report the amount of disk space used
     
    174277config ECHO
    175278    bool "echo (basic SuSv3 version taking no options)"
    176     default n
     279    default y
    177280    help
    178281      echo is used to print a specified string to stdout.
     
    182285    bool "Enable echo options (-n and -e)"
    183286    default y
    184     depends on ECHO
     287    depends on ECHO || ASH_BUILTIN_ECHO || HUSH
    185288    help
    186289      This adds options (-n and -e) to echo.
     
    188291config ENV
    189292    bool "env"
    190     default n
     293    default y
    191294    help
    192295      env is used to set an environment variable and run
     
    196299config FEATURE_ENV_LONG_OPTIONS
    197300    bool "Enable long options"
    198     default n
    199     depends on ENV && GETOPT_LONG
     301    default y
     302    depends on ENV && LONG_OPTS
    200303    help
    201304      Support long options for the env applet.
     
    203306config EXPAND
    204307    bool "expand"
    205     default n
     308    default y
    206309    help
    207310      By default, convert all tabs to spaces.
     
    209312config FEATURE_EXPAND_LONG_OPTIONS
    210313    bool "Enable long options"
    211     default n
    212     depends on EXPAND && GETOPT_LONG
     314    default y
     315    depends on EXPAND && LONG_OPTS
    213316    help
    214317      Support long options for the expand applet.
     
    216319config EXPR
    217320    bool "expr"
    218     default n
     321    default y
    219322    help
    220323      expr is used to calculate numbers and print the result
     
    223326config EXPR_MATH_SUPPORT_64
    224327    bool "Extend Posix numbers support to 64 bit"
    225     default n
     328    default y
    226329    depends on EXPR
    227330    help
    228       Enable 64-bit math support in the expr applet.  This will make
     331      Enable 64-bit math support in the expr applet. This will make
    229332      the applet slightly larger, but will allow computation with very
    230333      large numbers.
     
    232335config FALSE
    233336    bool "false"
    234     default n
     337    default y
    235338    help
    236339      false returns an exit code of FALSE (1).
     
    238341config FOLD
    239342    bool "fold"
    240     default n
     343    default y
    241344    help
    242345      Wrap text to fit a specific width.
     346
     347config FSYNC
     348    bool "fsync"
     349    default y
     350    help
     351      fsync is used to flush file-related cached blocks to disk.
    243352
    244353config HEAD
    245354    bool "head"
    246     default n
     355    default y
    247356    help
    248357      head is used to print the first specified number of lines
     
    251360config FEATURE_FANCY_HEAD
    252361    bool "Enable head options (-c, -q, and -v)"
    253     default n
     362    default y
    254363    depends on HEAD
    255364    help
     
    258367config HOSTID
    259368    bool "hostid"
    260     default n
     369    default y
    261370    help
    262371      hostid prints the numeric identifier (in hexadecimal) for
     
    265374config ID
    266375    bool "id"
    267     default n
     376    default y
    268377    help
    269378      id displays the current user and group ID names.
     
    271380config INSTALL
    272381    bool "install"
    273     default n
     382    default y
    274383    help
    275384      Copy files and set attributes.
     
    277386config FEATURE_INSTALL_LONG_OPTIONS
    278387    bool "Enable long options"
    279     default n
    280     depends on INSTALL && GETOPT_LONG
     388    default y
     389    depends on INSTALL && LONG_OPTS
    281390    help
    282391      Support long options for the install applet.
     
    284393config LENGTH
    285394    bool "length"
    286     default n
     395    default y
    287396    help
    288397      length is used to print out the length of a specified string.
     
    290399config LN
    291400    bool "ln"
    292     default n
     401    default y
    293402    help
    294403      ln is used to create hard or soft links between files.
     
    296405config LOGNAME
    297406    bool "logname"
    298     default n
     407    default y
    299408    help
    300409      logname is used to print the current user's login name.
     
    302411config LS
    303412    bool "ls"
    304     default n
     413    default y
    305414    help
    306415      ls is used to list the contents of directories.
     
    351460    bool "Allow use of color to identify file types"
    352461    default y
    353     depends on LS && GETOPT_LONG
     462    depends on LS && LONG_OPTS
    354463    help
    355464      This enables the --color option to ls.
     
    357466config FEATURE_LS_COLOR_IS_DEFAULT
    358467    bool "Produce colored ls output by default"
    359     default n
     468    default y
    360469    depends on FEATURE_LS_COLOR
    361470    help
     
    368477config MD5SUM
    369478    bool "md5sum"
    370     default n
     479    default y
    371480    help
    372481      md5sum is used to print or check MD5 checksums.
     
    374483config MKDIR
    375484    bool "mkdir"
    376     default n
     485    default y
    377486    help
    378487      mkdir is used to create directories with the specified names.
     
    380489config FEATURE_MKDIR_LONG_OPTIONS
    381490    bool "Enable long options"
    382     default n
    383     depends on MKDIR && GETOPT_LONG
     491    default y
     492    depends on MKDIR && LONG_OPTS
    384493    help
    385494      Support long options for the mkdir applet.
     
    387496config MKFIFO
    388497    bool "mkfifo"
    389     default n
     498    default y
    390499    help
    391500      mkfifo is used to create FIFOs (named pipes).
     
    394503config MKNOD
    395504    bool "mknod"
    396     default n
     505    default y
    397506    help
    398507      mknod is used to create FIFOs or block/character special
     
    401510config MV
    402511    bool "mv"
    403     default n
     512    default y
    404513    help
    405514      mv is used to move or rename files or directories.
     
    407516config FEATURE_MV_LONG_OPTIONS
    408517    bool "Enable long options"
    409     default n
    410     depends on MV && GETOPT_LONG
     518    default y
     519    depends on MV && LONG_OPTS
    411520    help
    412521      Support long options for the mv applet.
     
    414523config NICE
    415524    bool "nice"
    416     default n
     525    default y
    417526    help
    418527      nice runs a program with modified scheduling priority.
     
    420529config NOHUP
    421530    bool "nohup"
    422     default n
     531    default y
    423532    help
    424533      run a command immune to hangups, with output to a non-tty.
     
    426535config OD
    427536    bool "od"
    428     default n
     537    default y
    429538    help
    430539      od is used to dump binary files in octal and other formats.
     
    432541config PRINTENV
    433542    bool "printenv"
    434     default n
     543    default y
    435544    help
    436545      printenv is used to print all or part of environment.
     
    438547config PRINTF
    439548    bool "printf"
    440     default n
     549    default y
    441550    help
    442551      printf is used to format and print specified strings.
     
    445554config PWD
    446555    bool "pwd"
    447     default n
     556    default y
    448557    help
    449558      pwd is used to print the current directory.
     
    451560config READLINK
    452561    bool "readlink"
    453     default n
     562    default y
    454563    help
    455564      This program reads a symbolic link and returns the name
     
    458567config FEATURE_READLINK_FOLLOW
    459568    bool "Enable canonicalization by following all symlinks (-f)"
    460     default n
     569    default y
    461570    depends on READLINK
    462571    help
     
    465574config REALPATH
    466575    bool "realpath"
    467     default n
     576    default y
    468577    help
    469578      Return the canonicalized absolute pathname.
     
    472581config RM
    473582    bool "rm"
    474     default n
     583    default y
    475584    help
    476585      rm is used to remove files or directories.
     
    478587config RMDIR
    479588    bool "rmdir"
    480     default n
     589    default y
    481590    help
    482591      rmdir is used to remove empty directories.
     592
     593config FEATURE_RMDIR_LONG_OPTIONS
     594    bool "Enable long options"
     595    default y
     596    depends on RMDIR && LONG_OPTS
     597    help
     598      Support long options for the rmdir applet, including
     599      --ignore-fail-on-non-empty for compatibility with GNU rmdir.
    483600
    484601config SEQ
    485602    bool "seq"
    486     default n
     603    default y
    487604    help
    488605      print a sequence of numbers
     
    490607config SHA1SUM
    491608    bool "sha1sum"
    492     default n
     609    default y
    493610    help
    494611      Compute and check SHA1 message digest
    495612
     613config SHA256SUM
     614    bool "sha256sum"
     615    default y
     616    help
     617      Compute and check SHA256 message digest
     618
     619config SHA512SUM
     620    bool "sha512sum"
     621    default y
     622    help
     623      Compute and check SHA512 message digest
     624
    496625config SLEEP
    497     bool "sleep (single integer arg with no suffix)"
    498     default n
    499     help
    500       sleep is used to pause for a specified number of seconds,
     626    bool "sleep"
     627    default y
     628    help
     629      sleep is used to pause for a specified number of seconds.
     630      It comes in 3 versions:
     631      - small: takes one integer parameter
     632      - fancy: takes multiple integer arguments with suffixes:
     633        sleep 1d 2h 3m 15s
     634      - fancy with fractional numbers:
     635        sleep 2.3s 4.5h sleeps for 16202.3 seconds
     636      Last one is "the most compatible" with coreutils sleep,
     637      but it adds around 1k of code.
    501638
    502639config FEATURE_FANCY_SLEEP
    503     bool "Enable multiple integer args and optional time suffixes"
    504     default n
     640    bool "Enable multiple arguments and s/m/h/d suffixes"
     641    default y
    505642    depends on SLEEP
    506643    help
    507644      Allow sleep to pause for specified minutes, hours, and days.
     645
     646config FEATURE_FLOAT_SLEEP
     647    bool "Enable fractional arguments"
     648    default y
     649    depends on FEATURE_FANCY_SLEEP
     650    help
     651      Allow for fractional numeric parameters.
    508652
    509653config SORT
    510654    bool "sort"
    511     default n
     655    default y
    512656    help
    513657      sort is used to sort lines of text in specified files.
    514658
    515659config FEATURE_SORT_BIG
    516     bool "full SuSv3 compliant sort (Support -ktcsbdfiozgM)"
     660    bool "Full SuSv3 compliant sort (support -ktcsbdfiozgM)"
    517661    default y
    518662    depends on SORT
    519663    help
    520       Without this, sort only supports  -r, -u, and an integer version
    521       of -n.  Selecting this adds sort keys, floating point support, and
    522       more.  This adds a little over 3k to a nonstatic build on x86.
     664      Without this, sort only supports -r, -u, and an integer version
     665      of -n. Selecting this adds sort keys, floating point support, and
     666      more. This adds a little over 3k to a nonstatic build on x86.
    523667
    524668      The SuSv3 sort standard is available at:
     
    527671config SPLIT
    528672    bool "split"
    529     default n
     673    default y
    530674    help
    531675      split a file into pieces.
    532676
    533677config FEATURE_SPLIT_FANCY
    534     bool "fancy extensions"
    535     default n
     678    bool "Fancy extensions"
     679    default y
    536680    depends on SPLIT
    537681    help
     
    542686config STAT
    543687    bool "stat"
    544     default n
     688    default y
     689    depends on PLATFORM_LINUX # statfs()
    545690    help
    546691      display file or filesystem status.
     
    548693config FEATURE_STAT_FORMAT
    549694    bool "Enable custom formats (-c)"
    550     default n
     695    default y
    551696    depends on STAT
    552697    help
    553698      Without this, stat will not support the '-c format' option where
    554       users can pass a custom format string for output.  This adds about
     699      users can pass a custom format string for output. This adds about
    555700      7k to a nonstatic build on amd64.
    556701
    557702config STTY
    558703    bool "stty"
    559     default n
     704    default y
    560705    help
    561706      stty is used to change and print terminal line settings.
     
    563708config SUM
    564709    bool "sum"
    565     default n
     710    default y
    566711    help
    567712      checksum and count the blocks in a file
     
    569714config SYNC
    570715    bool "sync"
    571     default n
     716    default y
    572717    help
    573718      sync is used to flush filesystem buffers.
     719
     720config TAC
     721    bool "tac"
     722    default y
     723    help
     724      tac is used to concatenate and print files in reverse.
    574725
    575726config TAIL
    576727    bool "tail"
    577     default n
     728    default y
    578729    help
    579730      tail is used to print the last specified number of lines
     
    581732
    582733config FEATURE_FANCY_TAIL
    583     bool "Enable extra tail options (-q, -s, and -v)"
     734    bool "Enable extra tail options (-q, -s, -v, and -F)"
    584735    default y
    585736    depends on TAIL
     
    588739      are not specific in the SUSv3 standard.
    589740
     741        -q      Never output headers giving file names
     742        -s SEC  Wait SEC seconds between reads with -f
     743        -v      Always output headers giving file names
     744
    590745config TEE
    591746    bool "tee"
    592     default n
     747    default y
    593748    help
    594749      tee is used to read from standard input and write
     
    596751
    597752config FEATURE_TEE_USE_BLOCK_IO
    598     bool "Enable block i/o (larger/faster) instead of byte i/o."
    599     default n
     753    bool "Enable block I/O (larger/faster) instead of byte I/O"
     754    default y
    600755    depends on TEE
    601756    help
    602757      Enable this option for a faster tee, at expense of size.
    603 
    604 config TEST
    605     bool "test"
    606     default n
    607     help
    608       test is used to check file types and compare values,
    609       returning an appropriate exit code.  The bash shell
    610       has test built in, ash can build it in optionally.
    611 
    612 config FEATURE_TEST_64
    613     bool "Extend test to 64 bit"
    614     default n
    615     depends on TEST
    616     help
    617       Enable 64-bit support in test.
    618758
    619759config TOUCH
    620760    bool "touch"
    621     default n
     761    default y
    622762    help
    623763      touch is used to create or change the access and/or
    624764      modification timestamp of specified files.
    625765
    626 config TR
    627     bool "tr"
    628     default n
    629     help
    630       tr is used to squeeze, and/or delete characters from standard
    631       input, writing to standard output.
    632 
    633 config FEATURE_TR_CLASSES
    634     bool "Enable character classes (such as [:upper:])"
    635     default n
    636     depends on TR
    637     help
    638       Enable character classes, enabling commands such as:
    639       tr [:upper:] [:lower:] to convert input into lowercase.
    640 
    641 config FEATURE_TR_EQUIV
    642     bool "Enable equivalence classes"
    643     default n
    644     depends on TR
    645     help
    646       Enable equivalence classes, which essentially add the enclosed
    647       character to the current set. For instance, tr [=a=] xyz would
    648       replace all instances of 'a' with 'xyz'. This option is mainly
    649       useful for cases when no other way of expressing a character
    650       is possible.
    651 
    652766config TRUE
    653767    bool "true"
    654     default n
     768    default y
    655769    help
    656770      true returns an exit code of TRUE (0).
     
    658772config TTY
    659773    bool "tty"
    660     default n
     774    default y
    661775    help
    662776      tty is used to print the name of the current terminal to
     
    665779config UNAME
    666780    bool "uname"
    667     default n
     781    default y
    668782    help
    669783      uname is used to print system information.
     
    671785config UNEXPAND
    672786    bool "unexpand"
    673     default n
     787    default y
    674788    help
    675789      By default, convert only leading sequences of blanks to tabs.
     
    677791config FEATURE_UNEXPAND_LONG_OPTIONS
    678792    bool "Enable long options"
    679     default n
    680     depends on UNEXPAND && GETOPT_LONG
     793    default y
     794    depends on UNEXPAND && LONG_OPTS
    681795    help
    682796      Support long options for the unexpand applet.
     
    684798config UNIQ
    685799    bool "uniq"
    686     default n
     800    default y
    687801    help
    688802      uniq is used to remove duplicate lines from a sorted file.
     
    690804config USLEEP
    691805    bool "usleep"
    692     default n
     806    default y
    693807    help
    694808      usleep is used to pause for a specified number of microseconds.
     
    696810config UUDECODE
    697811    bool "uudecode"
    698     default n
     812    default y
    699813    help
    700814      uudecode is used to decode a uuencoded file.
     
    702816config UUENCODE
    703817    bool "uuencode"
    704     default n
     818    default y
    705819    help
    706820      uuencode is used to uuencode a file.
     
    708822config WC
    709823    bool "wc"
    710     default n
     824    default y
    711825    help
    712826      wc is used to print the number of bytes, words, and lines,
     
    715829config FEATURE_WC_LARGE
    716830    bool "Support very large files in wc"
    717     default n
     831    default y
    718832    depends on WC
    719833    help
    720       Use "unsigned long long" in wc for count variables
     834      Use "unsigned long long" in wc for counter variables.
    721835
    722836config WHO
    723837    bool "who"
    724     default n
    725     select FEATURE_UTMP
     838    default y
     839    depends on FEATURE_UTMP
    726840    help
    727841      who is used to show who is logged on.
     
    729843config WHOAMI
    730844    bool "whoami"
    731     default n
     845    default y
    732846    help
    733847      whoami is used to print the username of the current
     
    736850config YES
    737851    bool "yes"
    738     default n
     852    default y
    739853    help
    740854      yes is used to repeatedly output a specific string, or
     
    746860config FEATURE_PRESERVE_HARDLINKS
    747861    bool "Preserve hard links"
    748     default n
     862    default y
    749863    depends on CP || MV
    750864    help
     
    770884config FEATURE_HUMAN_READABLE
    771885    bool "Support for human readable output (example 13k, 23M, 235G)"
    772     default n
     886    default y
    773887    depends on DF || DU || LS
    774888    help
    775889      Allow df, du, and ls to have human readable output.
    776890
    777 comment "Common options for md5sum, sha1sum"
    778     depends on MD5SUM || SHA1SUM
     891comment "Common options for md5sum, sha1sum, sha256sum, sha512sum"
     892    depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM
    779893
    780894config FEATURE_MD5_SHA1_SUM_CHECK
    781895    bool "Enable -c, -s and -w options"
    782     default n
    783     depends on MD5SUM || SHA1SUM
     896    default y
     897    depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM
    784898    help
    785899      Enabling the -c options allows files to be checked
  • branches/2.2.9/mindi-busybox/coreutils/Kbuild

    r1765 r2725  
     1# DO NOT EDIT. This file is generated from Kbuild.src
    12# Makefile for busybox
    23#
    34# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
    45#
    5 # Licensed under the GPL v2, see the file LICENSE in this tarball.
     6# Licensed under GPLv2, see file LICENSE in this source tree.
    67
    78libs-y          += libcoreutils/
    89
    910lib-y:=
    10 lib-$(CONFIG_BASENAME)  += basename.o
     11
     12lib-$(CONFIG_BASENAME) += basename.o
     13lib-$(CONFIG_CAT)     += cat.o
     14lib-$(CONFIG_MORE)    += cat.o # more uses it if stdout isn't a tty
     15lib-$(CONFIG_LESS)    += cat.o # less too
     16lib-$(CONFIG_CRONTAB) += cat.o # crontab -l
     17lib-$(CONFIG_DATE) += date.o
     18lib-$(CONFIG_TEST)      += test.o test_ptr_hack.o
     19lib-$(CONFIG_ASH)       += test.o test_ptr_hack.o
     20lib-$(CONFIG_HUSH)      += test.o test_ptr_hack.o
     21lib-$(CONFIG_TR) += tr.o
     22lib-$(CONFIG_BASE64) += uudecode.o
    1123lib-$(CONFIG_CAL)       += cal.o
    12 lib-$(CONFIG_CAT)       += cat.o
    13 lib-$(CONFIG_MORE)      += cat.o # more uses it if stdout isn't a tty
    14 lib-$(CONFIG_LESS)      += cat.o # less too
    1524lib-$(CONFIG_CATV)      += catv.o
    1625lib-$(CONFIG_CHGRP)     += chgrp.o chown.o
    1726lib-$(CONFIG_CHMOD)     += chmod.o
    1827lib-$(CONFIG_CHOWN)     += chown.o
     28lib-$(CONFIG_ADDUSER)   += chown.o # used by adduser
     29lib-$(CONFIG_ADDGROUP)  += chown.o # used by adduser
    1930lib-$(CONFIG_CHROOT)    += chroot.o
    2031lib-$(CONFIG_CKSUM)     += cksum.o
     
    2233lib-$(CONFIG_CP)        += cp.o
    2334lib-$(CONFIG_CUT)       += cut.o
    24 lib-$(CONFIG_DATE)      += date.o
    2535lib-$(CONFIG_DD)        += dd.o
    2636lib-$(CONFIG_DF)        += df.o
     
    3040lib-$(CONFIG_ECHO)      += echo.o
    3141lib-$(CONFIG_ASH)       += echo.o # used by ash
     42lib-$(CONFIG_HUSH)      += echo.o # used by hush
    3243lib-$(CONFIG_ENV)       += env.o
    3344lib-$(CONFIG_EXPR)      += expr.o
     
    3546lib-$(CONFIG_FALSE)     += false.o
    3647lib-$(CONFIG_FOLD)      += fold.o
     48lib-$(CONFIG_FSYNC)     += fsync.o
    3749lib-$(CONFIG_HEAD)      += head.o
    3850lib-$(CONFIG_HOSTID)    += hostid.o
     
    4355lib-$(CONFIG_LOGNAME)   += logname.o
    4456lib-$(CONFIG_LS)        += ls.o
     57lib-$(CONFIG_FTPD)      += ls.o
    4558lib-$(CONFIG_MD5SUM)    += md5_sha1_sum.o
    4659lib-$(CONFIG_MKDIR)     += mkdir.o
     
    5366lib-$(CONFIG_PRINTENV)  += printenv.o
    5467lib-$(CONFIG_PRINTF)    += printf.o
     68lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o
    5569lib-$(CONFIG_PWD)       += pwd.o
    5670lib-$(CONFIG_READLINK)  += readlink.o
     
    6074lib-$(CONFIG_SEQ)       += seq.o
    6175lib-$(CONFIG_SHA1SUM)   += md5_sha1_sum.o
     76lib-$(CONFIG_SHA256SUM) += md5_sha1_sum.o
     77lib-$(CONFIG_SHA512SUM) += md5_sha1_sum.o
    6278lib-$(CONFIG_SLEEP)     += sleep.o
    6379lib-$(CONFIG_SPLIT)     += split.o
     
    6783lib-$(CONFIG_SUM)       += sum.o
    6884lib-$(CONFIG_SYNC)      += sync.o
     85lib-$(CONFIG_TAC)       += tac.o
    6986lib-$(CONFIG_TAIL)      += tail.o
    7087lib-$(CONFIG_TEE)       += tee.o
    71 lib-$(CONFIG_TEST)      += test.o
    72 lib-$(CONFIG_ASH)       += test.o # used by ash
    7388lib-$(CONFIG_TOUCH)     += touch.o
    74 lib-$(CONFIG_TR)        += tr.o
    7589lib-$(CONFIG_TRUE)      += true.o
    7690lib-$(CONFIG_TTY)       += tty.o
  • branches/2.2.9/mindi-busybox/coreutils/basename.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
    8  *
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    98 */
    10 
    11 /* BB_AUDIT SUSv3 compliant */
    12 /* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */
    13 
    149
    1510/* Mar 16, 2003      Manuel Novoa III   (mjn3@codepoet.org)
     
    2116 */
    2217
     18/* BB_AUDIT SUSv3 compliant */
     19/* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */
     20
     21//kbuild:lib-$(CONFIG_BASENAME) += basename.o
     22
     23//config:config BASENAME
     24//config:   bool "basename"
     25//config:   default y
     26//config:   help
     27//config:     basename is used to strip the directory and suffix from filenames,
     28//config:     leaving just the filename itself. Enable this option if you wish
     29//config:     to enable the 'basename' utility.
     30
    2331#include "libbb.h"
    2432
    2533/* This is a NOFORK applet. Be very careful! */
    2634
    27 int basename_main(int argc, char **argv);
     35int basename_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    2836int basename_main(int argc, char **argv)
    2937{
     
    3139    char *s;
    3240
    33     if (((unsigned int)(argc-2)) >= 2) {
     41    if ((unsigned)(argc-2) >= 2) {
    3442        bb_show_usage();
    3543    }
    3644
    37     s = bb_get_last_path_component(*++argv);
     45    /* It should strip slash: /abc/def/ -> def */
     46    s = bb_get_last_path_component_strip(*++argv);
    3847
     48    m = strlen(s);
    3949    if (*++argv) {
    4050        n = strlen(*argv);
    41         m = strlen(s);
    42         if ((m > n) && ((strcmp)(s+m-n, *argv) == 0)) {
    43             s[m-n] = '\0';
     51        if ((m > n) && (strcmp(s+m-n, *argv) == 0)) {
     52            m -= n;
     53            /*s[m] = '\0'; - redundant */
    4454        }
    4555    }
    4656
    47     puts(s);
    48 
    49     return fflush(stdout);
     57    /* puts(s) will do, but we can do without stdio this way: */
     58    s[m++] = '\n';
     59    /* NB: != is correct here: */
     60    return full_write(STDOUT_FILENO, s, m) != (ssize_t)m;
    5061}
  • branches/2.2.9/mindi-busybox/coreutils/cal.c

    r1765 r2725  
    55 * See original copyright at the end of this file
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1717 * Major size reduction... over 50% (>1.5k) on i386.
    1818 */
    19 
    2019#include "libbb.h"
     20#include "unicode.h"
    2121
    2222/* We often use "unsigned" intead of "int", it's easier to div on most CPUs */
     
    4141};
    4242
    43 static unsigned julian;
     43/* Set to 0 or 1 in main */
     44#define julian ((unsigned)option_mask32)
    4445
    4546/* leap year -- account for Gregorian reformation in 1752 */
     
    7677#define HEAD_SEP    2       /* spaces between day headings */
    7778
    78 int cal_main(int argc, char **argv);
    79 int cal_main(int argc, char **argv)
    80 {
    81     struct tm *local_time;
     79int cal_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     80int cal_main(int argc UNUSED_PARAM, char **argv)
     81{
    8282    struct tm zero_tm;
    8383    time_t now;
    8484    unsigned month, year, flags, i;
    8585    char *month_names[12];
    86     char day_headings[28];  /* 28 for julian, 21 for nonjulian */
     86    /* normal heading: */
     87    /* "Su Mo Tu We Th Fr Sa" */
     88    /* -j heading: */
     89    /* " Su  Mo  Tu  We  Th  Fr  Sa" */
     90    char day_headings[ENABLE_UNICODE_SUPPORT ? 28 * 6 : 28];
     91    IF_UNICODE_SUPPORT(char *hp = day_headings;)
    8792    char buf[40];
    8893
     94    init_unicode();
     95
    8996    flags = getopt32(argv, "jy");
    90     julian = flags & 1;
     97    /* This sets julian = flags & 1: */
     98    option_mask32 &= 1;
    9199    month = 0;
    92100    argv += optind;
    93     argc -= optind;
    94 
    95     if (argc > 2) {
    96         bb_show_usage();
    97     }
    98 
    99     if (!argc) {
     101
     102    if (!argv[0]) {
     103        struct tm *ptm;
     104
    100105        time(&now);
    101         local_time = localtime(&now);
    102         year = local_time->tm_year + 1900;
    103         if (!(flags & 2)) {
    104             month = local_time->tm_mon + 1;
     106        ptm = localtime(&now);
     107        year = ptm->tm_year + 1900;
     108        if (!(flags & 2)) { /* no -y */
     109            month = ptm->tm_mon + 1;
    105110        }
    106111    } else {
    107         if (argc == 2) {
    108             month = xatou_range(*argv++, 1, 12);
     112        if (argv[1]) {
     113            if (argv[2]) {
     114                bb_show_usage();
     115            }
     116            if (!(flags & 2)) { /* no -y */
     117                month = xatou_range(*argv, 1, 12);
     118            }
     119            argv++;
    109120        }
    110121        year = xatou_range(*argv, 1, 9999);
     
    116127    do {
    117128        zero_tm.tm_mon = i;
     129        /* full month name according to locale */
    118130        strftime(buf, sizeof(buf), "%B", &zero_tm);
    119131        month_names[i] = xstrdup(buf);
     
    121133        if (i < 7) {
    122134            zero_tm.tm_wday = i;
     135            /* abbreviated weekday name according to locale */
    123136            strftime(buf, sizeof(buf), "%a", &zero_tm);
     137#if ENABLE_UNICODE_SUPPORT
     138            if (julian)
     139                *hp++ = ' ';
     140            {
     141                char *two_wchars = unicode_conv_to_printable_fixedwidth(NULL, buf, 2);
     142                strcpy(hp, two_wchars);
     143                free(two_wchars);
     144            }
     145            hp += strlen(hp);
     146            *hp++ = ' ';
     147#else
    124148            strncpy(day_headings + i * (3+julian) + julian, buf, 2);
     149#endif
    125150        }
    126151    } while (++i < 12);
     152    IF_UNICODE_SUPPORT(hp[-1] = '\0';)
    127153
    128154    if (month) {
     
    146172        char lineout[80];
    147173
    148         sprintf(lineout, "%d", year);
     174        sprintf(lineout, "%u", year);
    149175        center(lineout,
    150176               (WEEK_LEN * 3 + HEAD_SEP * 2)
     
    168194                printf("%*s%s", HEAD_SEP, "", day_headings);
    169195            }
    170             putchar('\n');
     196            bb_putchar('\n');
    171197            for (row = 0; row < (6*7); row += 7) {
    172198                for (which_cal = 0; which_cal < 3-julian; which_cal++) {
     
    180206    }
    181207
    182     fflush_stdout_and_exit(0);
     208    fflush_stdout_and_exit(EXIT_SUCCESS);
    183209}
    184210
     
    261287    while (p != s) {
    262288        --p;
    263         if (!(isspace)(*p)) {   /* We want the function... not the inline. */
     289        if (!isspace(*p)) {
    264290            p[1] = '\0';
    265291            break;
  • branches/2.2.9/mindi-busybox/coreutils/cat.c

    r1765 r2725  
    55 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2, see file License in this tarball for details.
     7 * Licensed under GPLv2, see file LICENSE in this source tree.
    88 */
    99
    1010/* BB_AUDIT SUSv3 compliant */
    1111/* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */
     12
     13//kbuild:lib-$(CONFIG_CAT)     += cat.o
     14//kbuild:lib-$(CONFIG_MORE)    += cat.o # more uses it if stdout isn't a tty
     15//kbuild:lib-$(CONFIG_LESS)    += cat.o # less too
     16//kbuild:lib-$(CONFIG_CRONTAB) += cat.o # crontab -l
     17
     18//config:config CAT
     19//config:   bool "cat"
     20//config:   default y
     21//config:   help
     22//config:     cat is used to concatenate files and print them to the standard
     23//config:     output. Enable this option if you wish to enable the 'cat' utility.
    1224
    1325#include "libbb.h"
     
    1830int bb_cat(char **argv)
    1931{
    20     static const char *const argv_dash[] = { "-", NULL };
    21 
    2232    int fd;
    2333    int retval = EXIT_SUCCESS;
    2434
    2535    if (!*argv)
    26         argv = (char**) &argv_dash;
     36        argv = (char**) &bb_argv_dash;
    2737
    2838    do {
    29         fd = STDIN_FILENO;
    30         if (!LONE_DASH(*argv))
    31             fd = open_or_warn(*argv, O_RDONLY);
     39        fd = open_or_warn_stdin(*argv);
    3240        if (fd >= 0) {
    33             /* This is not an xfunc - never exits */
     41            /* This is not a xfunc - never exits */
    3442            off_t r = bb_copyfd_eof(fd, STDOUT_FILENO);
    3543            if (fd != STDIN_FILENO)
     
    4452}
    4553
    46 int cat_main(int argc, char **argv);
    47 int cat_main(int argc, char **argv)
     54int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     55int cat_main(int argc UNUSED_PARAM, char **argv)
    4856{
    4957    getopt32(argv, "u");
  • branches/2.2.9/mindi-busybox/coreutils/catv.c

    r1765 r2725  
    55 * Copyright (C) 2006 Rob Landley <rob@landley.net>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1313#include "libbb.h"
    1414
    15 int catv_main(int argc, char **argv);
    16 int catv_main(int argc, char **argv)
     15int catv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     16int catv_main(int argc UNUSED_PARAM, char **argv)
    1717{
    1818    int retval = EXIT_SUCCESS;
     
    2828
    2929    /* Read from stdin if there's nothing else to do. */
    30     fd = 0;
    31     if (!argv[0]) {
    32         argv--;
    33         goto jump_in;
    34     }
     30    if (!argv[0])
     31        *--argv = (char*)"-";
    3532    do {
    36         fd = open_or_warn(*argv, O_RDONLY);
     33        fd = open_or_warn_stdin(*argv);
    3734        if (fd < 0) {
    3835            retval = EXIT_FAILURE;
    3936            continue;
    4037        }
    41  jump_in:
    4238        for (;;) {
    4339            int i, res;
     
    6359                    if (c == 10) {
    6460                        if (flags & CATV_OPT_e)
    65                             putchar('$');
     61                            bb_putchar('$');
    6662                    } else if (flags & (c==9 ? CATV_OPT_t : CATV_OPT_v)) {
    6763                        printf("^%c", c+'@');
     
    6965                    }
    7066                }
    71                 putchar(c);
     67                bb_putchar(c);
    7268            }
    7369        }
  • branches/2.2.9/mindi-busybox/coreutils/chgrp.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1717
    1818
    19 int chgrp_main(int argc, char **argv);
     19int chgrp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    2020int chgrp_main(int argc, char **argv)
    2121{
  • branches/2.2.9/mindi-busybox/coreutils/chmod.c

    r1765 r2725  
    88 *  to correctly parse '-rwxgoa'
    99 *
    10  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     10 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1111 */
    1212
     
    2121
    2222#define OPT_RECURSE (option_mask32 & 1)
    23 #define OPT_VERBOSE (USE_DESKTOP(option_mask32 & 2) SKIP_DESKTOP(0))
    24 #define OPT_CHANGED (USE_DESKTOP(option_mask32 & 4) SKIP_DESKTOP(0))
    25 #define OPT_QUIET   (USE_DESKTOP(option_mask32 & 8) SKIP_DESKTOP(0))
    26 #define OPT_STR     "R" USE_DESKTOP("vcf")
     23#define OPT_VERBOSE (IF_DESKTOP(option_mask32 & 2) IF_NOT_DESKTOP(0))
     24#define OPT_CHANGED (IF_DESKTOP(option_mask32 & 4) IF_NOT_DESKTOP(0))
     25#define OPT_QUIET   (IF_DESKTOP(option_mask32 & 8) IF_NOT_DESKTOP(0))
     26#define OPT_STR     "R" IF_DESKTOP("vcf")
    2727
    2828/* coreutils:
     
    3535 */
    3636
    37 static int fileAction(const char *fileName, struct stat *statbuf, void* param, int depth)
     37static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf, void* param, int depth)
    3838{
    3939    mode_t newmode;
     
    5151
    5252    if (!bb_parse_mode((char *)param, &newmode))
    53         bb_error_msg_and_die("invalid mode: %s", (char *)param);
     53        bb_error_msg_and_die("invalid mode '%s'", (char *)param);
    5454
    5555    if (chmod(fileName, newmode) == 0) {
     
    6464 err:
    6565    if (!OPT_QUIET)
    66         bb_perror_msg("%s", fileName);
     66        bb_simple_perror_msg(fileName);
    6767    return FALSE;
    6868}
    6969
    70 int chmod_main(int argc, char **argv);
    71 int chmod_main(int argc, char **argv)
     70int chmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     71int chmod_main(int argc UNUSED_PARAM, char **argv)
    7272{
    7373    int retval = EXIT_SUCCESS;
  • branches/2.2.9/mindi-busybox/coreutils/chown.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
    1010/* BB_AUDIT SUSv3 defects - none? */
    11 /* BB_AUDIT GNU defects - unsupported long options. */
    1211/* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */
    1312
     
    1716
    1817
    19 #define OPT_STR     ("Rh" USE_DESKTOP("vcfLHP"))
     18#define OPT_STR     ("Rh" IF_DESKTOP("vcfLHP"))
    2019#define BIT_RECURSE 1
    21 #define OPT_RECURSE (option_mask32 & 1)
    22 #define OPT_NODEREF (option_mask32 & 2)
    23 #define OPT_VERBOSE (USE_DESKTOP(option_mask32 & 0x04) SKIP_DESKTOP(0))
    24 #define OPT_CHANGED (USE_DESKTOP(option_mask32 & 0x08) SKIP_DESKTOP(0))
    25 #define OPT_QUIET   (USE_DESKTOP(option_mask32 & 0x10) SKIP_DESKTOP(0))
     20#define OPT_RECURSE (opt & 1)
     21#define OPT_NODEREF (opt & 2)
     22#define OPT_VERBOSE (IF_DESKTOP(opt & 0x04) IF_NOT_DESKTOP(0))
     23#define OPT_CHANGED (IF_DESKTOP(opt & 0x08) IF_NOT_DESKTOP(0))
     24#define OPT_QUIET   (IF_DESKTOP(opt & 0x10) IF_NOT_DESKTOP(0))
    2625/* POSIX options
    2726 * -L traverse every symbolic link to a directory encountered
     
    3332/* -L */
    3433#define BIT_TRAVERSE 0x20
    35 #define OPT_TRAVERSE (USE_DESKTOP(option_mask32 & BIT_TRAVERSE) SKIP_DESKTOP(0))
     34#define OPT_TRAVERSE (IF_DESKTOP(opt & BIT_TRAVERSE) IF_NOT_DESKTOP(0))
    3635/* -H or -L */
    3736#define BIT_TRAVERSE_TOP (0x20|0x40)
    38 #define OPT_TRAVERSE_TOP (USE_DESKTOP(option_mask32 & BIT_TRAVERSE_TOP) SKIP_DESKTOP(0))
     37#define OPT_TRAVERSE_TOP (IF_DESKTOP(opt & BIT_TRAVERSE_TOP) IF_NOT_DESKTOP(0))
     38
     39#if ENABLE_FEATURE_CHOWN_LONG_OPTIONS
     40static const char chown_longopts[] ALIGN1 =
     41    "recursive\0"        No_argument   "R"
     42    "dereference\0"      No_argument   "\xff"
     43    "no-dereference\0"   No_argument   "h"
     44# if ENABLE_DESKTOP
     45    "changes\0"          No_argument   "c"
     46    "silent\0"           No_argument   "f"
     47    "quiet\0"            No_argument   "f"
     48    "verbose\0"          No_argument   "v"
     49# endif
     50    ;
     51#endif
    3952
    4053typedef int (*chown_fptr)(const char *, uid_t, gid_t);
    4154
    42 static struct bb_uidgid_t ugid = { -1, -1 };
     55struct param_t {
     56    struct bb_uidgid_t ugid;
     57    chown_fptr chown_func;
     58};
    4359
    44 static int fileAction(const char *fileName, struct stat *statbuf,
    45         void *cf, int depth)
     60static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf,
     61        void *vparam, int depth UNUSED_PARAM)
    4662{
    47     uid_t u = (ugid.uid == (uid_t)-1) ? statbuf->st_uid : ugid.uid;
    48     gid_t g = (ugid.gid == (gid_t)-1) ? statbuf->st_gid : ugid.gid;
     63#define param  (*(struct param_t*)vparam)
     64#define opt option_mask32
     65    uid_t u = (param.ugid.uid == (uid_t)-1L) ? statbuf->st_uid : param.ugid.uid;
     66    gid_t g = (param.ugid.gid == (gid_t)-1L) ? statbuf->st_gid : param.ugid.gid;
    4967
    50     if (!((chown_fptr)cf)(fileName, u, g)) {
     68    if (param.chown_func(fileName, u, g) == 0) {
    5169        if (OPT_VERBOSE
    5270         || (OPT_CHANGED && (statbuf->st_uid != u || statbuf->st_gid != g))
     
    5876    }
    5977    if (!OPT_QUIET)
    60         bb_perror_msg("%s", fileName);  /* A filename can have % in it... */
     78        bb_simple_perror_msg(fileName);
    6179    return FALSE;
     80#undef opt
     81#undef param
    6282}
    6383
    64 int chown_main(int argc, char **argv);
    65 int chown_main(int argc, char **argv)
     84int chown_main(int argc UNUSED_PARAM, char **argv)
    6685{
    6786    int retval = EXIT_SUCCESS;
    68     int flags;
    69     chown_fptr chown_func;
     87    int opt, flags;
     88    struct param_t param;
    7089
     90    /* Just -1 might not work: uid_t may be unsigned long */
     91    param.ugid.uid = -1L;
     92    param.ugid.gid = -1L;
     93
     94#if ENABLE_FEATURE_CHOWN_LONG_OPTIONS
     95    applet_long_options = chown_longopts;
     96#endif
    7197    opt_complementary = "-2";
    72     getopt32(argv, OPT_STR);
     98    opt = getopt32(argv, OPT_STR);
    7399    argv += optind;
    74100
    75101    /* This matches coreutils behavior (almost - see below) */
    76     chown_func = chown;
     102    param.chown_func = chown;
    77103    if (OPT_NODEREF
    78104        /* || (OPT_RECURSE && !OPT_TRAVERSE_TOP): */
    79         USE_DESKTOP( || (option_mask32 & (BIT_RECURSE|BIT_TRAVERSE_TOP)) == BIT_RECURSE)
     105        IF_DESKTOP( || (opt & (BIT_RECURSE|BIT_TRAVERSE_TOP)) == BIT_RECURSE)
    80106    ) {
    81         chown_func = lchown;
     107        param.chown_func = lchown;
    82108    }
    83109
     
    90116        flags |= ACTION_FOLLOWLINKS; /* follow links if -L */
    91117
    92     parse_chown_usergroup_or_die(&ugid, argv[0]);
     118    parse_chown_usergroup_or_die(&param.ugid, argv[0]);
    93119
    94120    /* Ok, ready to do the deed now */
    95     argv++;
    96     do {
     121    while (*++argv) {
    97122        if (!recursive_action(*argv,
    98123                flags,          /* flags */
    99124                fileAction,     /* file action */
    100125                fileAction,     /* dir action */
    101                 chown_func,     /* user data */
     126                &param,         /* user data */
    102127                0)              /* depth */
    103128        ) {
    104129            retval = EXIT_FAILURE;
    105130        }
    106     } while (*++argv);
     131    }
    107132
    108133    return retval;
  • branches/2.2.9/mindi-busybox/coreutils/chroot.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1212#include "libbb.h"
    1313
    14 int chroot_main(int argc, char **argv);
    15 int chroot_main(int argc, char **argv)
     14int chroot_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     15int chroot_main(int argc UNUSED_PARAM, char **argv)
    1616{
    17     if (argc < 2) {
     17    ++argv;
     18    if (!*argv)
    1819        bb_show_usage();
    19     }
    20 
    21     ++argv;
    22     if (chroot(*argv)) {
    23         bb_perror_msg_and_die("cannot change root directory to %s", *argv);
    24     }
     20    xchroot(*argv);
    2521    xchdir("/");
    2622
    2723    ++argv;
    28     if (argc == 2) {
     24    if (!*argv) { /* no 2nd param (PROG), use shell */
    2925        argv -= 2;
    3026        argv[0] = getenv("SHELL");
     
    3531    }
    3632
    37     BB_EXECVP(*argv, argv);
    38     bb_perror_msg_and_die("cannot execute %s", *argv);
     33    BB_EXECVP_or_die(argv);
    3934}
  • branches/2.2.9/mindi-busybox/coreutils/cksum.c

    r1765 r2725  
    55 * Copyright (C) 2006 by Rob Sullivan, with ideas from code by Walter Harms
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */
    8 
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
     8 */
    99#include "libbb.h"
    1010
    11 int cksum_main(int argc, char **argv);
    12 int cksum_main(int argc, char **argv)
     11/* This is a NOEXEC applet. Be very careful! */
     12
     13int cksum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     14int cksum_main(int argc UNUSED_PARAM, char **argv)
    1315{
    1416    uint32_t *crc32_table = crc32_filltable(NULL, 1);
     17    uint32_t crc;
     18    off_t length, filesize;
     19    int bytes_read;
     20    int exit_code = EXIT_SUCCESS;
    1521
    16     FILE *fp;
    17     uint32_t crc;
    18     long length, filesize;
    19     int bytes_read;
    20     char *cp;
    21 
    22     int inp_stdin = (argc == optind) ? 1 : 0;
     22#if ENABLE_DESKTOP
     23    getopt32(argv, ""); /* coreutils 6.9 compat */
     24    argv += optind;
     25#else
     26    argv++;
     27#endif
    2328
    2429    do {
    25         fp = fopen_or_warn_stdin((inp_stdin) ? bb_msg_standard_input : *++argv);
     30        int fd = open_or_warn_stdin(*argv ? *argv : bb_msg_standard_input);
    2631
     32        if (fd < 0) {
     33            exit_code = EXIT_FAILURE;
     34            continue;
     35        }
    2736        crc = 0;
    2837        length = 0;
    2938
    3039#define read_buf bb_common_bufsiz1
    31         while ((bytes_read = fread(read_buf, 1, BUFSIZ, fp)) > 0) {
    32             cp = read_buf;
    33             length += bytes_read;
    34             while (bytes_read--)
    35                 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ (*cp++)) & 0xffL];
     40        while ((bytes_read = safe_read(fd, read_buf, sizeof(read_buf))) > 0) {
     41            crc = crc32_block_endian1(crc, read_buf, bytes_read, crc32_table);
    3642        }
     43        close(fd);
    3744
    3845        filesize = length;
    3946
    40         for (; length; length >>= 8)
    41             crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ length) & 0xffL];
    42         crc ^= 0xffffffffL;
     47        while (length) {
     48            crc = (crc << 8) ^ crc32_table[(uint8_t)(crc >> 24) ^ (uint8_t)length];
     49            /* must ensure that shift is unsigned! */
     50            if (sizeof(length) <= sizeof(unsigned))
     51                length = (unsigned)length >> 8;
     52            else if (sizeof(length) <= sizeof(unsigned long))
     53                length = (unsigned long)length >> 8;
     54            else
     55                length = (unsigned long long)length >> 8;
     56        }
     57        crc = ~crc;
    4358
    44         if (inp_stdin) {
    45             printf("%" PRIu32 " %li\n", crc, filesize);
    46             break;
    47         }
     59        printf((*argv ? "%"PRIu32" %"OFF_FMT"i %s\n" : "%"PRIu32" %"OFF_FMT"i\n"),
     60                crc, filesize, *argv);
     61    } while (*argv && *++argv);
    4862
    49         printf("%" PRIu32 " %li %s\n", crc, filesize, *argv);
    50         fclose(fp);
    51     } while (*(argv + 1));
    52 
    53     fflush_stdout_and_exit(EXIT_SUCCESS);
     63    fflush_stdout_and_exit(exit_code);
    5464}
  • branches/2.2.9/mindi-busybox/coreutils/comm.c

    r1765 r2725  
    55 * Copyright (C) 2005 by Robert Sullivan <cogito.ergo.cogito@gmail.com>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1515
    1616/* writeline outputs the input given, appropriately aligned according to class */
    17 static void writeline(char *line, int class, int flags)
     17static void writeline(char *line, int class)
    1818{
     19    int flags = option_mask32;
    1920    if (class == 0) {
    2021        if (flags & COMM_OPT_1)
     
    3334            putchar('\t');
    3435    }
    35     fputs(line, stdout);
     36    puts(line);
    3637}
    3738
    38 int comm_main(int argc, char **argv);
    39 int comm_main(int argc, char **argv)
     39int comm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     40int comm_main(int argc UNUSED_PARAM, char **argv)
    4041{
    41 #define LINE_LEN 100
    42 #define BB_EOF_0 0x1
    43 #define BB_EOF_1 0x2
    44     char thisline[2][LINE_LEN];
    45     FILE *streams[2];
     42    char *thisline[2];
     43    FILE *stream[2];
    4644    int i;
    47     unsigned flags;
     45    int order;
    4846
    4947    opt_complementary = "=2";
    50     flags = getopt32(argv, "123");
     48    getopt32(argv, "123");
    5149    argv += optind;
    5250
    5351    for (i = 0; i < 2; ++i) {
    54         streams[i] = (argv[i][0] == '-' && !argv[i][1]) ? stdin : xfopen(argv[i], "r");
    55         fgets(thisline[i], LINE_LEN, streams[i]);
     52        stream[i] = xfopen_stdin(argv[i]);
    5653    }
    5754
    58     /* This is the real core of the program - lines are compared here */
    59 
    60     while (*thisline[0] || *thisline[1]) {
    61         int order = 0;
    62 
    63         i = 0;
    64         if (feof(streams[0])) i |= BB_EOF_0;
    65         if (feof(streams[1])) i |= BB_EOF_1;
    66 
    67         if (!*thisline[0])
    68             order = 1;
    69         else if (!*thisline[1])
    70             order = -1;
    71         else {
    72             int tl0_len, tl1_len;
    73             tl0_len = strlen(thisline[0]);
    74             tl1_len = strlen(thisline[1]);
    75             order = memcmp(thisline[0], thisline[1], tl0_len < tl1_len ? tl0_len : tl1_len);
    76             if (!order)
    77                 order = tl0_len < tl1_len ? -1 : tl0_len != tl1_len;
     55    order = 0;
     56    thisline[1] = thisline[0] = NULL;
     57    while (1) {
     58        if (order <= 0) {
     59            free(thisline[0]);
     60            thisline[0] = xmalloc_fgetline(stream[0]);
     61        }
     62        if (order >= 0) {
     63            free(thisline[1]);
     64            thisline[1] = xmalloc_fgetline(stream[1]);
    7865        }
    7966
    80         if (order == 0 && !i)
    81             writeline(thisline[1], 2, flags);
    82         else if (order > 0 && !(i & BB_EOF_1))
    83             writeline(thisline[1], 1, flags);
    84         else if (order < 0 && !(i & BB_EOF_0))
    85             writeline(thisline[0], 0, flags);
     67        i = !thisline[0] + (!thisline[1] << 1);
     68        if (i)
     69            break;
     70        order = strcmp(thisline[0], thisline[1]);
    8671
    87         if (i & BB_EOF_0 & BB_EOF_1) {
    88             break;
     72        if (order >= 0)
     73            writeline(thisline[1], order ? 1 : 2);
     74        else
     75            writeline(thisline[0], 0);
     76    }
    8977
    90         } else if (i) {
    91             i = (i & BB_EOF_0 ? 1 : 0);
    92             while (!feof(streams[i])) {
    93                 if ((order < 0 && i) || (order > 0 && !i))
    94                     writeline(thisline[i], i, flags);
    95                 fgets(thisline[i], LINE_LEN, streams[i]);
    96             }
    97             break;
    98 
    99         } else {
    100             if (order >= 0)
    101                 fgets(thisline[1], LINE_LEN, streams[1]);
    102             if (order <= 0)
    103                 fgets(thisline[0], LINE_LEN, streams[0]);
     78    /* EOF at least on one of the streams */
     79    i &= 1;
     80    if (thisline[i]) {
     81        /* stream[i] is not at EOF yet */
     82        /* we did not print thisline[i] yet */
     83        char *p = thisline[i];
     84        writeline(p, i);
     85        while (1) {
     86            free(p);
     87            p = xmalloc_fgetline(stream[i]);
     88            if (!p)
     89                break;
     90            writeline(p, i);
    10491        }
    10592    }
    10693
    10794    if (ENABLE_FEATURE_CLEAN_UP) {
    108         fclose(streams[0]);
    109         fclose(streams[1]);
     95        fclose(stream[0]);
     96        fclose(stream[1]);
    11097    }
    11198
  • branches/2.2.9/mindi-busybox/coreutils/cp.c

    r1765 r2725  
    66 * SELinux support by Yuichi Nakamura <ynakam@hitachisoft.jp>
    77 *
    8  * Licensed under GPL v2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
     
    2121/* This is a NOEXEC applet. Be very careful! */
    2222
    23 
    24 int cp_main(int argc, char **argv);
     23int cp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    2524int cp_main(int argc, char **argv)
    2625{
     
    3231    int d_flags;
    3332    int flags;
    34     int status = 0;
     33    int status;
    3534    enum {
    3635        OPT_a = 1 << (sizeof(FILEUTILS_CP_OPTSTR)-1),
    3736        OPT_r = 1 << (sizeof(FILEUTILS_CP_OPTSTR)),
    3837        OPT_P = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+1),
    39         OPT_H = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+2),
    40         OPT_L = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+3),
     38        OPT_v = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+2),
     39#if ENABLE_FEATURE_CP_LONG_OPTIONS
     40        OPT_parents = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+3),
     41#endif
    4142    };
    4243
    43     // Soft- and hardlinking don't mix
     44    // Need at least two arguments
     45    // Soft- and hardlinking doesn't mix
    4446    // -P and -d are the same (-P is POSIX, -d is GNU)
    4547    // -r and -R are the same
     48    // -R (and therefore -r) turns on -d (coreutils does this)
    4649    // -a = -pdR
    47     opt_complementary = "l--s:s--l:Pd:rR:apdR";
    48     flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPHL");
    49     /* Default behavior of cp is to dereference, so we don't have to do
    50      * anything special when we are given -L.
    51      * The behavior of -H is *almost* like -L, but not quite, so let's
    52      * just ignore it too for fun.
    53     if (flags & OPT_L) ...
    54     if (flags & OPT_H) ... // deref command-line params only
    55     */
     50    opt_complementary = "-2:l--s:s--l:Pd:rRd:Rd:apdR";
     51#if ENABLE_FEATURE_CP_LONG_OPTIONS
     52    applet_long_options =
     53        "archive\0"        No_argument "a"
     54        "force\0"          No_argument "f"
     55        "interactive\0"    No_argument "i"
     56        "link\0"           No_argument "l"
     57        "dereference\0"    No_argument "L"
     58        "no-dereference\0" No_argument "P"
     59        "recursive\0"      No_argument "R"
     60        "symbolic-link\0"  No_argument "s"
     61        "verbose\0"        No_argument "v"
     62        "parents\0"        No_argument "\xff"
     63        ;
     64#endif
     65    // -v (--verbose) is ignored
     66    flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPv");
     67    /* Options of cp from GNU coreutils 6.10:
     68     * -a, --archive
     69     * -f, --force
     70     * -i, --interactive
     71     * -l, --link
     72     * -L, --dereference
     73     * -P, --no-dereference
     74     * -R, -r, --recursive
     75     * -s, --symbolic-link
     76     * -v, --verbose
     77     * -H   follow command-line symbolic links in SOURCE
     78     * -d   same as --no-dereference --preserve=links
     79     * -p   same as --preserve=mode,ownership,timestamps
     80     * -c   same as --preserve=context
     81     * --parents
     82     *  use full source file name under DIRECTORY
     83     * NOT SUPPORTED IN BBOX:
     84     * --backup[=CONTROL]
     85     *  make a backup of each existing destination file
     86     * -b   like --backup but does not accept an argument
     87     * --copy-contents
     88     *  copy contents of special files when recursive
     89     * --preserve[=ATTR_LIST]
     90     *  preserve attributes (default: mode,ownership,timestamps),
     91     *  if possible additional attributes: security context,links,all
     92     * --no-preserve=ATTR_LIST
     93     * --remove-destination
     94     *  remove  each existing destination file before attempting to open
     95     * --sparse=WHEN
     96     *  control creation of sparse files
     97     * --strip-trailing-slashes
     98     *  remove any trailing slashes from each SOURCE argument
     99     * -S, --suffix=SUFFIX
     100     *  override the usual backup suffix
     101     * -t, --target-directory=DIRECTORY
     102     *  copy all SOURCE arguments into DIRECTORY
     103     * -T, --no-target-directory
     104     *  treat DEST as a normal file
     105     * -u, --update
     106     *  copy only when the SOURCE file is newer than the destination
     107     *  file or when the destination file is missing
     108     * -x, --one-file-system
     109     *  stay on this file system
     110     * -Z, --context=CONTEXT
     111     *  (SELinux) set SELinux security context of copy to CONTEXT
     112     */
     113    argc -= optind;
     114    argv += optind;
     115    /* Reverse this bit. If there is -d, bit is not set: */
     116    flags ^= FILEUTILS_DEREFERENCE;
     117    /* coreutils 6.9 compat:
     118     * by default, "cp" derefs symlinks (creates regular dest files),
     119     * but "cp -R" does not. We switch off deref if -r or -R (see above).
     120     * However, "cp -RL" must still deref symlinks: */
     121    if (flags & FILEUTILS_DEREF_SOFTLINK) /* -L */
     122        flags |= FILEUTILS_DEREFERENCE;
    56123
    57124#if ENABLE_SELINUX
     
    61128#endif
    62129
    63     flags ^= FILEUTILS_DEREFERENCE;     /* The sense of this flag was reversed. */
    64 
    65     if (optind + 2 > argc) {
    66         bb_show_usage();
    67     }
    68 
     130    status = EXIT_SUCCESS;
    69131    last = argv[argc - 1];
    70     argv += optind;
    71 
    72132    /* If there are only two arguments and...  */
    73     if (optind + 2 == argc) {
     133    if (argc == 2) {
    74134        s_flags = cp_mv_stat2(*argv, &source_stat,
    75                       (flags & FILEUTILS_DEREFERENCE) ? stat : lstat);
     135                (flags & FILEUTILS_DEREFERENCE) ? stat : lstat);
    76136        if (s_flags < 0)
    77137            return EXIT_FAILURE;
     
    80140            return EXIT_FAILURE;
    81141
    82         /* ...if neither is a directory or...  */
    83         if ( !((s_flags | d_flags) & 2) ||
    84             /* ...recursing, the 1st is a directory, and the 2nd doesn't exist... */
    85             ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags)
     142#if ENABLE_FEATURE_CP_LONG_OPTIONS
     143        if (flags & OPT_parents) {
     144            if (!(d_flags & 2)) {
     145                bb_error_msg_and_die("with --parents, the destination must be a directory");
     146            }
     147        }
     148#endif
     149
     150        /* ...if neither is a directory...  */
     151        if (!((s_flags | d_flags) & 2)
     152            /* ...or: recursing, the 1st is a directory, and the 2nd doesn't exist... */
     153         || ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags)
    86154        ) {
    87             /* ...do a simple copy. */
    88             dest = xstrdup(last);
    89             goto DO_COPY; /* Note: optind+2==argc implies argv[1]==last below. */
     155            /* Do a simple copy */
     156            dest = last;
     157            goto DO_COPY; /* NB: argc==2 -> *++argv==last */
    90158        }
    91159    }
    92160
    93     do {
    94         dest = concat_path_file(last, bb_get_last_path_component(*argv));
     161    while (1) {
     162#if ENABLE_FEATURE_CP_LONG_OPTIONS
     163        if (flags & OPT_parents) {
     164            char *dest_dup;
     165            char *dest_dir;
     166            dest = concat_path_file(last, *argv);
     167            dest_dup = xstrdup(dest);
     168            dest_dir = dirname(dest_dup);
     169            if (bb_make_directory(dest_dir, -1, FILEUTILS_RECUR)) {
     170                return EXIT_FAILURE;
     171            }
     172            free(dest_dup);
     173            goto DO_COPY;
     174        }
     175#endif
     176        dest = concat_path_file(last, bb_get_last_path_component_strip(*argv));
    95177 DO_COPY:
    96178        if (copy_file(*argv, dest, flags) < 0) {
    97             status = 1;
     179            status = EXIT_FAILURE;
    98180        }
     181        if (*++argv == last) {
     182            /* possibly leaking dest... */
     183            break;
     184        }
     185        /* don't move up: dest may be == last and not malloced! */
    99186        free((void*)dest);
    100     } while (*++argv != last);
     187    }
    101188
     189    /* Exit. We are NOEXEC, not NOFORK. We do exit at the end of main() */
    102190    return status;
    103191}
  • branches/2.2.9/mindi-busybox/coreutils/cut.c

    r1765 r2725  
    55 * Copyright (C) 1999,2000,2001 by Lineo, inc.
    66 * Written by Mark Whitley <markw@codepoet.org>
    7  * debloated by Bernhard Fischer
     7 * debloated by Bernhard Reutner-Fischer
    88 *
    9  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1010 */
    1111
     
    1717/* option vars */
    1818static const char optstring[] ALIGN1 = "b:c:f:d:sn";
    19 #define CUT_OPT_BYTE_FLGS   (1<<0)
    20 #define CUT_OPT_CHAR_FLGS   (1<<1)
    21 #define CUT_OPT_FIELDS_FLGS (1<<2)
    22 #define CUT_OPT_DELIM_FLGS  (1<<3)
    23 #define CUT_OPT_SUPPRESS_FLGS (1<<4)
    24 
    25 static char delim = '\t';   /* delimiter, default is tab */
     19#define CUT_OPT_BYTE_FLGS     (1 << 0)
     20#define CUT_OPT_CHAR_FLGS     (1 << 1)
     21#define CUT_OPT_FIELDS_FLGS   (1 << 2)
     22#define CUT_OPT_DELIM_FLGS    (1 << 3)
     23#define CUT_OPT_SUPPRESS_FLGS (1 << 4)
    2624
    2725struct cut_list {
     
    3634};
    3735
    38 /* growable array holding a series of lists */
    39 static struct cut_list *cut_lists;
    40 static unsigned int nlists; /* number of elements in above list */
    41 
    42 
    4336static int cmpfunc(const void *a, const void *b)
    4437{
    4538    return (((struct cut_list *) a)->startpos -
    4639            ((struct cut_list *) b)->startpos);
    47 
    4840}
    4941
    50 static void cut_file(FILE * file)
     42static void cut_file(FILE *file, char delim, const struct cut_list *cut_lists, unsigned nlists)
    5143{
    52     char *line = NULL;
    53     unsigned int linenum = 0;   /* keep these zero-based to be consistent */
     44    char *line;
     45    unsigned linenum = 0;   /* keep these zero-based to be consistent */
    5446
    5547    /* go through every line in the file */
    56     while ((line = xmalloc_getline(file)) != NULL) {
     48    while ((line = xmalloc_fgetline(file)) != NULL) {
    5749
    5850        /* set up a list so we can keep track of what's been printed */
    59         char * printed = xzalloc(strlen(line) * sizeof(char));
    60         char * orig_line = line;
    61         unsigned int cl_pos = 0;
     51        int linelen = strlen(line);
     52        char *printed = xzalloc(linelen + 1);
     53        char *orig_line = line;
     54        unsigned cl_pos = 0;
    6255        int spos;
    6356
     
    6760            for (; cl_pos < nlists; cl_pos++) {
    6861                spos = cut_lists[cl_pos].startpos;
    69                 while (spos < strlen(line)) {
     62                while (spos < linelen) {
    7063                    if (!printed[spos]) {
    7164                        printed[spos] = 'X';
     
    7467                    spos++;
    7568                    if (spos > cut_lists[cl_pos].endpos
    76                         || cut_lists[cl_pos].endpos == NON_RANGE)
     69                    /* NON_RANGE is -1, so if below is true,
     70                     * the above was true too (spos is >= 0) */
     71                    /* || cut_lists[cl_pos].endpos == NON_RANGE */
     72                    ) {
    7773                        break;
     74                    }
    7875                }
    7976            }
     
    8380            /* get out if we have no more lists to process or if the lines
    8481             * are lower than what we're interested in */
    85             if (linenum < spos || cl_pos >= nlists)
     82            if (((int)linenum < spos) || (cl_pos >= nlists))
    8683                goto next_line;
    8784
    8885            /* if the line we're looking for is lower than the one we were
    8986             * passed, it means we displayed it already, so move on */
    90             while (spos < linenum) {
     87            while (spos < (int)linenum) {
    9188                spos++;
    9289                /* go to the next list if we're at the end of this one */
    9390                if (spos > cut_lists[cl_pos].endpos
    94                     || cut_lists[cl_pos].endpos == NON_RANGE) {
     91                 || cut_lists[cl_pos].endpos == NON_RANGE
     92                ) {
    9593                    cl_pos++;
    9694                    /* get out if there's no more lists to process */
     
    10098                    /* get out if the current line is lower than the one
    10199                     * we just became interested in */
    102                     if (linenum < spos)
     100                    if ((int)linenum < spos)
    103101                        goto next_line;
    104102                }
     
    113111            int nfields_printed = 0;
    114112            char *field = NULL;
    115             const char delimiter[2] = { delim, 0 };
     113            char delimiter[2];
     114
     115            delimiter[0] = delim;
     116            delimiter[1] = 0;
    116117
    117118            /* does this line contain any delimiters? */
     
    151152                     * list */
    152153                } while (spos <= cut_lists[cl_pos].endpos && line
    153                          && cut_lists[cl_pos].endpos != NON_RANGE);
     154                        && cut_lists[cl_pos].endpos != NON_RANGE);
    154155            }
    155156        }
     
    164165}
    165166
    166 static const char _op_on_field[] ALIGN1 = " only when operating on fields";
    167 
    168 int cut_main(int argc, char **argv);
    169 int cut_main(int argc, char **argv)
     167int cut_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     168int cut_main(int argc UNUSED_PARAM, char **argv)
    170169{
     170    /* growable array holding a series of lists */
     171    struct cut_list *cut_lists = NULL;
     172    unsigned nlists = 0;    /* number of elements in above list */
     173    char delim = '\t';  /* delimiter, default is tab */
    171174    char *sopt, *ltok;
     175    unsigned opt;
    172176
    173177    opt_complementary = "b--bcf:c--bcf:f--bcf";
    174     getopt32(argv, optstring, &sopt, &sopt, &sopt, &ltok);
     178    opt = getopt32(argv, optstring, &sopt, &sopt, &sopt, &ltok);
    175179//  argc -= optind;
    176180    argv += optind;
    177     if (!(option_mask32 & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS)))
     181    if (!(opt & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS)))
    178182        bb_error_msg_and_die("expected a list of bytes, characters, or fields");
    179183
    180     if (option_mask32 & CUT_OPT_DELIM_FLGS) {
    181         if (strlen(ltok) > 1) {
     184    if (opt & CUT_OPT_DELIM_FLGS) {
     185        if (ltok[0] && ltok[1]) { /* more than 1 char? */
    182186            bb_error_msg_and_die("the delimiter must be a single character");
    183187        }
     
    186190
    187191    /*  non-field (char or byte) cutting has some special handling */
    188     if (!(option_mask32 & CUT_OPT_FIELDS_FLGS)) {
    189         if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) {
     192    if (!(opt & CUT_OPT_FIELDS_FLGS)) {
     193        static const char _op_on_field[] ALIGN1 = " only when operating on fields";
     194
     195        if (opt & CUT_OPT_SUPPRESS_FLGS) {
    190196            bb_error_msg_and_die
    191197                ("suppressing non-delimited lines makes sense%s",
     
    207213        int s = 0, e = 0;
    208214
    209         /* take apart the lists, one by one (they are separated with commas */
     215        /* take apart the lists, one by one (they are separated with commas) */
    210216        while ((ltok = strsep(&sopt, ",")) != NULL) {
    211217
    212218            /* it's actually legal to pass an empty list */
    213             if (strlen(ltok) == 0)
     219            if (!ltok[0])
    214220                continue;
    215221
    216222            /* get the start pos */
    217223            ntok = strsep(&ltok, "-");
    218             if (ntok == NULL) {
    219                 bb_error_msg
    220                     ("internal error: ntok is null for start pos!?\n");
    221             } else if (strlen(ntok) == 0) {
     224            if (!ntok[0]) {
    222225                s = BOL;
    223226            } else {
    224                 s = xatoi_u(ntok);
     227                s = xatoi_positive(ntok);
    225228                /* account for the fact that arrays are zero based, while
    226229                 * the user expects the first char on the line to be char #1 */
     
    230233
    231234            /* get the end pos */
    232             ntok = strsep(&ltok, "-");
    233             if (ntok == NULL) {
     235            if (ltok == NULL) {
    234236                e = NON_RANGE;
    235             } else if (strlen(ntok) == 0) {
     237            } else if (!ltok[0]) {
    236238                e = EOL;
    237239            } else {
    238                 e = xatoi_u(ntok);
    239                 /* if the user specified and end position of 0, that means "til the
    240                  * end of the line */
     240                e = xatoi_positive(ltok);
     241                /* if the user specified and end position of 0,
     242                 * that means "til the end of the line" */
    241243                if (e == 0)
    242244                    e = EOL;
     
    246248            }
    247249
    248             /* if there's something left to tokenize, the user passed
    249              * an invalid list */
    250             if (ltok)
    251                 bb_error_msg_and_die("invalid byte or field list");
    252 
    253250            /* add the new list */
    254             cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
    255             cut_lists[nlists-1].startpos = s;
    256             cut_lists[nlists-1].endpos = e;
     251            cut_lists = xrealloc_vector(cut_lists, 4, nlists);
     252            /* NB: startpos is always >= 0,
     253             * while endpos may be = NON_RANGE (-1) */
     254            cut_lists[nlists].startpos = s;
     255            cut_lists[nlists].endpos = e;
     256            nlists++;
    257257        }
    258258
     
    264264         * easier on us when it comes time to print the chars / fields / lines
    265265         */
    266         qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc);
    267     }
    268 
    269     /* argv[0..argc-1] should be names of file to process. If no
    270      * files were specified or '-' was specified, take input from stdin.
    271      * Otherwise, we process all the files specified. */
    272     if (argv[0] == NULL || LONE_DASH(argv[0])) {
    273         cut_file(stdin);
    274     } else {
    275         FILE *file;
     266        qsort(cut_lists, nlists, sizeof(cut_lists[0]), cmpfunc);
     267    }
     268
     269    {
     270        int retval = EXIT_SUCCESS;
     271
     272        if (!*argv)
     273            *--argv = (char *)"-";
    276274
    277275        do {
    278             file = fopen_or_warn(argv[0], "r");
    279             if (file) {
    280                 cut_file(file);
    281                 fclose(file);
    282             }
     276            FILE *file = fopen_or_warn_stdin(*argv);
     277            if (!file) {
     278                retval = EXIT_FAILURE;
     279                continue;
     280            }
     281            cut_file(file, delim, cut_lists, nlists);
     282            fclose_if_not_stdin(file);
    283283        } while (*++argv);
    284     }
    285     if (ENABLE_FEATURE_CLEAN_UP)
    286         free(cut_lists);
    287     return EXIT_SUCCESS;
     284
     285        if (ENABLE_FEATURE_CLEAN_UP)
     286            free(cut_lists);
     287        fflush_stdout_and_exit(retval);
     288    }
    288289}
  • branches/2.2.9/mindi-busybox/coreutils/date.c

    r1765 r2725  
    66 *
    77 * iso-format handling added by Robert Griebl <griebl@gmx.de>
    8  * bugfixes and cleanup by Bernhard Fischer
     8 * bugfixes and cleanup by Bernhard Reutner-Fischer
    99 *
    10  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     10 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1111*/
    12 
    13 #include "libbb.h"
    1412
    1513/* This 'date' command supports only 2 time setting formats,
     
    2220   much as possible, missed out a lot of bounds checking */
    2321
    24 /* Default input handling to save surprising some people */
    25 
    26 
    27 #define DATE_OPT_RFC2822    0x01
    28 #define DATE_OPT_SET        0x02
    29 #define DATE_OPT_UTC        0x04
    30 #define DATE_OPT_DATE       0x08
    31 #define DATE_OPT_REFERENCE  0x10
    32 #define DATE_OPT_TIMESPEC   0x20
    33 #define DATE_OPT_HINT       0x40
     22//applet:IF_DATE(APPLET(date, _BB_DIR_BIN, _BB_SUID_DROP))
     23
     24//kbuild:lib-$(CONFIG_DATE) += date.o
     25
     26//config:config DATE
     27//config:   bool "date"
     28//config:   default y
     29//config:   help
     30//config:     date is used to set the system date or display the
     31//config:     current time in the given format.
     32//config:
     33//config:config FEATURE_DATE_ISOFMT
     34//config:   bool "Enable ISO date format output (-I)"
     35//config:   default y
     36//config:   depends on DATE
     37//config:   help
     38//config:     Enable option (-I) to output an ISO-8601 compliant
     39//config:     date/time string.
     40//config:
     41//config:# defaults to "no": stat's nanosecond field is a bit non-portable
     42//config:config FEATURE_DATE_NANO
     43//config:   bool "Support %[num]N nanosecond format specifier"
     44//config:   default n
     45//config:   depends on DATE && PLATFORM_LINUX # syscall(__NR_clock_gettime)
     46//config:   help
     47//config:     Support %[num]N format specifier. Adds ~250 bytes of code.
     48//config:
     49//config:config FEATURE_DATE_COMPAT
     50//config:   bool "Support weird 'date MMDDhhmm[[YY]YY][.ss]' format"
     51//config:   default y
     52//config:   depends on DATE
     53//config:   help
     54//config:     System time can be set by 'date -s DATE' and simply 'date DATE',
     55//config:     but formats of DATE string are different. 'date DATE' accepts
     56//config:     a rather weird MMDDhhmm[[YY]YY][.ss] format with completely
     57//config:     unnatural placement of year between minutes and seconds.
     58//config:     date -s (and other commands like touch -d) use more sensible
     59//config:     formats (for one, ISO format YYYY-MM-DD hh:mm:ss.ssssss).
     60//config:
     61//config:     With this option off, 'date DATE' is 'date -s DATE' support
     62//config:     the same format. With it on, 'date DATE' additionally supports
     63//config:     MMDDhhmm[[YY]YY][.ss] format.
     64
     65/* GNU coreutils 6.9 man page:
     66 * date [OPTION]... [+FORMAT]
     67 * date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
     68 * -d, --date=STRING
     69 *      display time described by STRING, not `now'
     70 * -f, --file=DATEFILE
     71 *      like --date once for each line of DATEFILE
     72 * -r, --reference=FILE
     73 *      display the last modification time of FILE
     74 * -R, --rfc-2822
     75 *      output date and time in RFC 2822 format.
     76 *      Example: Mon, 07 Aug 2006 12:34:56 -0600
     77 * --rfc-3339=TIMESPEC
     78 *      output date and time in RFC 3339 format.
     79 *      TIMESPEC='date', 'seconds', or 'ns'
     80 *      Date and time components are separated by a single space:
     81 *      2006-08-07 12:34:56-06:00
     82 * -s, --set=STRING
     83 *      set time described by STRING
     84 * -u, --utc, --universal
     85 *      print or set Coordinated Universal Time
     86 *
     87 * Busybox:
     88 * long options are not supported
     89 * -f is not supported
     90 * -I seems to roughly match --rfc-3339, but -I has _optional_ param
     91 *    (thus "-I seconds" doesn't work, only "-Iseconds"),
     92 *    and does not support -Ins
     93 * -D FMT is a bbox extension for _input_ conversion of -d DATE
     94 */
     95
     96//usage:#define date_trivial_usage
     97//usage:       "[OPTIONS] [+FMT] [TIME]"
     98//usage:#define date_full_usage "\n\n"
     99//usage:       "Display time (using +FMT), or set time\n"
     100//usage:     "\nOptions:"
     101//usage:    IF_NOT_LONG_OPTS(
     102//usage:     "\n    [-s] TIME   Set time to TIME"
     103//usage:     "\n    -u      Work in UTC (don't convert to local time)"
     104//usage:     "\n    -R      Output RFC-2822 compliant date string"
     105//usage:    ) IF_LONG_OPTS(
     106//usage:     "\n    [-s,--set] TIME Set time to TIME"
     107//usage:     "\n    -u,--utc    Work in UTC (don't convert to local time)"
     108//usage:     "\n    -R,--rfc-2822   Output RFC-2822 compliant date string"
     109//usage:    )
     110//usage:    IF_FEATURE_DATE_ISOFMT(
     111//usage:     "\n    -I[SPEC]    Output ISO-8601 compliant date string"
     112//usage:     "\n            SPEC='date' (default) for date only,"
     113//usage:     "\n            'hours', 'minutes', or 'seconds' for date and"
     114//usage:     "\n            time to the indicated precision"
     115//usage:    )
     116//usage:    IF_NOT_LONG_OPTS(
     117//usage:     "\n    -r FILE     Display last modification time of FILE"
     118//usage:     "\n    -d TIME     Display TIME, not 'now'"
     119//usage:    ) IF_LONG_OPTS(
     120//usage:     "\n    -r,--reference FILE Display last modification time of FILE"
     121//usage:     "\n    -d,--date TIME  Display TIME, not 'now'"
     122//usage:    )
     123//usage:    IF_FEATURE_DATE_ISOFMT(
     124//usage:     "\n    -D FMT      Use FMT for -d TIME conversion"
     125//usage:    )
     126//usage:     "\n"
     127//usage:     "\nRecognized TIME formats:"
     128//usage:     "\n    hh:mm[:ss]"
     129//usage:     "\n    [YYYY.]MM.DD-hh:mm[:ss]"
     130//usage:     "\n    YYYY-MM-DD hh:mm[:ss]"
     131//usage:     "\n    [[[[[YY]YY]MM]DD]hh]mm[.ss]"
     132//usage:
     133//usage:#define date_example_usage
     134//usage:       "$ date\n"
     135//usage:       "Wed Apr 12 18:52:41 MDT 2000\n"
     136
     137#include "libbb.h"
     138#if ENABLE_FEATURE_DATE_NANO
     139# include <sys/syscall.h>
     140#endif
     141
     142enum {
     143    OPT_RFC2822   = (1 << 0), /* R */
     144    OPT_SET       = (1 << 1), /* s */
     145    OPT_UTC       = (1 << 2), /* u */
     146    OPT_DATE      = (1 << 3), /* d */
     147    OPT_REFERENCE = (1 << 4), /* r */
     148    OPT_TIMESPEC  = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */
     149    OPT_HINT      = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */
     150};
    34151
    35152static void maybe_set_utc(int opt)
    36153{
    37     if (opt & DATE_OPT_UTC)
     154    if (opt & OPT_UTC)
    38155        putenv((char*)"TZ=UTC0");
    39156}
    40157
    41 int date_main(int argc, char **argv);
    42 int date_main(int argc, char **argv)
     158#if ENABLE_LONG_OPTS
     159static const char date_longopts[] ALIGN1 =
     160        "rfc-822\0"   No_argument       "R"
     161        "rfc-2822\0"  No_argument       "R"
     162        "set\0"       Required_argument "s"
     163        "utc\0"       No_argument       "u"
     164    /*  "universal\0" No_argument       "u" */
     165        "date\0"      Required_argument "d"
     166        "reference\0" Required_argument "r"
     167        ;
     168#endif
     169
     170int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     171int date_main(int argc UNUSED_PARAM, char **argv)
    43172{
    44     time_t tm;
     173    struct timespec ts;
    45174    struct tm tm_time;
     175    char buf_fmt_dt2str[64];
    46176    unsigned opt;
    47177    int ifmt = -1;
    48     char *date_str = NULL;
    49     char *date_fmt = NULL;
    50     char *filename = NULL;
    51     char *isofmt_arg;
    52     char *hintfmt_arg;
     178    char *date_str;
     179    char *fmt_dt2str;
     180    char *fmt_str2dt;
     181    char *filename;
     182    char *isofmt_arg = NULL;
    53183
    54184    opt_complementary = "d--s:s--d"
    55         USE_FEATURE_DATE_ISOFMT(":R--I:I--R");
     185        IF_FEATURE_DATE_ISOFMT(":R--I:I--R");
     186    IF_LONG_OPTS(applet_long_options = date_longopts;)
    56187    opt = getopt32(argv, "Rs:ud:r:"
    57             USE_FEATURE_DATE_ISOFMT("I::D:"),
     188            IF_FEATURE_DATE_ISOFMT("I::D:"),
    58189            &date_str, &date_str, &filename
    59             USE_FEATURE_DATE_ISOFMT(, &isofmt_arg, &hintfmt_arg));
     190            IF_FEATURE_DATE_ISOFMT(, &isofmt_arg, &fmt_str2dt));
     191    argv += optind;
    60192    maybe_set_utc(opt);
    61193
    62     if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_TIMESPEC)) {
    63         if (!isofmt_arg) {
    64             ifmt = 0; /* default is date */
    65         } else {
    66             static const char *const isoformats[] = {
    67                 "date", "hours", "minutes", "seconds"
    68             };
    69 
    70             for (ifmt = 0; ifmt < 4; ifmt++)
    71                 if (!strcmp(isofmt_arg, isoformats[ifmt]))
    72                     goto found;
    73             /* parse error */
    74             bb_show_usage();
    75  found: ;
    76         }
    77     }
    78 
    79     /* XXX, date_fmt == NULL from this always */
    80     if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) {
    81         date_fmt = &argv[optind][1];    /* Skip over the '+' */
    82     } else if (date_str == NULL) {
    83         opt |= DATE_OPT_SET;
    84         date_str = argv[optind];
    85     }
     194    if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_TIMESPEC)) {
     195        ifmt = 0; /* default is date */
     196        if (isofmt_arg) {
     197            static const char isoformats[] ALIGN1 =
     198                "date\0""hours\0""minutes\0""seconds\0"; /* ns? */
     199            ifmt = index_in_substrings(isoformats, isofmt_arg);
     200            if (ifmt < 0)
     201                bb_show_usage();
     202        }
     203    }
     204
     205    fmt_dt2str = NULL;
     206    if (argv[0] && argv[0][0] == '+') {
     207        fmt_dt2str = &argv[0][1]; /* skip over the '+' */
     208        argv++;
     209    }
     210    if (!(opt & (OPT_SET | OPT_DATE))) {
     211        opt |= OPT_SET;
     212        date_str = argv[0]; /* can be NULL */
     213        if (date_str) {
     214#if ENABLE_FEATURE_DATE_COMPAT
     215            int len = strspn(date_str, "0123456789");
     216            if (date_str[len] == '\0'
     217             || (date_str[len] == '.'
     218                && isdigit(date_str[len+1])
     219                && isdigit(date_str[len+2])
     220                && date_str[len+3] == '\0'
     221                )
     222            ) {
     223                /* Dreaded MMDDhhmm[[CC]YY][.ss] format!
     224                 * It does not match -d or -s format.
     225                 * Some users actually do use it.
     226                 */
     227                len -= 8;
     228                if (len < 0 || len > 4 || (len & 1))
     229                    bb_error_msg_and_die(bb_msg_invalid_date, date_str);
     230                if (len != 0) { /* move YY or CCYY to front */
     231                    char buf[4];
     232                    memcpy(buf, date_str + 8, len);
     233                    memmove(date_str + len, date_str, 8);
     234                    memcpy(date_str, buf, len);
     235                }
     236            }
     237#endif
     238            argv++;
     239        }
     240    }
     241    if (*argv)
     242        bb_show_usage();
    86243
    87244    /* Now we have parsed all the information except the date format
    88        which depends on whether the clock is being set or read */
    89 
    90     if (filename) {
     245     * which depends on whether the clock is being set or read */
     246
     247    if (opt & OPT_REFERENCE) {
    91248        struct stat statbuf;
    92249        xstat(filename, &statbuf);
    93         tm = statbuf.st_mtime;
    94     } else
    95         time(&tm);
    96     memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
    97     /* Zero out fields - take her back to midnight! */
     250        ts.tv_sec = statbuf.st_mtime;
     251#if ENABLE_FEATURE_DATE_NANO
     252        ts.tv_nsec = statbuf.st_mtim.tv_nsec;
     253        /* some toolchains use .st_mtimensec instead of st_mtim.tv_nsec */
     254#endif
     255    } else {
     256#if ENABLE_FEATURE_DATE_NANO
     257        /* libc has incredibly messy way of doing this,
     258         * typically requiring -lrt. We just skip all this mess */
     259        syscall(__NR_clock_gettime, CLOCK_REALTIME, &ts);
     260#else
     261        time(&ts.tv_sec);
     262#endif
     263    }
     264    localtime_r(&ts.tv_sec, &tm_time);
     265
     266    /* If date string is given, update tm_time, and maybe set date */
    98267    if (date_str != NULL) {
     268        /* Zero out fields - take her back to midnight! */
    99269        tm_time.tm_sec = 0;
    100270        tm_time.tm_min = 0;
     
    102272
    103273        /* Process any date input to UNIX time since 1 Jan 1970 */
    104         if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_HINT)) {
    105             strptime(date_str, hintfmt_arg, &tm_time);
    106         } else if (strchr(date_str, ':') != NULL) {
    107             /* Parse input and assign appropriately to tm_time */
    108 
    109             if (sscanf(date_str, "%d:%d:%d", &tm_time.tm_hour, &tm_time.tm_min,
    110                                  &tm_time.tm_sec) == 3) {
    111                 /* no adjustments needed */
    112             } else if (sscanf(date_str, "%d:%d", &tm_time.tm_hour,
    113                                         &tm_time.tm_min) == 2) {
    114                 /* no adjustments needed */
    115             } else if (sscanf(date_str, "%d.%d-%d:%d:%d", &tm_time.tm_mon,
    116                                 &tm_time.tm_mday, &tm_time.tm_hour,
    117                                 &tm_time.tm_min, &tm_time.tm_sec) == 5) {
    118                 /* Adjust dates from 1-12 to 0-11 */
    119                 tm_time.tm_mon -= 1;
    120             } else if (sscanf(date_str, "%d.%d-%d:%d", &tm_time.tm_mon,
    121                                 &tm_time.tm_mday,
    122                                 &tm_time.tm_hour, &tm_time.tm_min) == 4) {
    123                 /* Adjust dates from 1-12 to 0-11 */
    124                 tm_time.tm_mon -= 1;
    125             } else if (sscanf(date_str, "%d.%d.%d-%d:%d:%d", &tm_time.tm_year,
    126                                 &tm_time.tm_mon, &tm_time.tm_mday,
    127                                 &tm_time.tm_hour, &tm_time.tm_min,
    128                                     &tm_time.tm_sec) == 6) {
    129                 tm_time.tm_year -= 1900;    /* Adjust years */
    130                 tm_time.tm_mon -= 1;    /* Adjust dates from 1-12 to 0-11 */
    131             } else if (sscanf(date_str, "%d.%d.%d-%d:%d", &tm_time.tm_year,
    132                                 &tm_time.tm_mon, &tm_time.tm_mday,
    133                                 &tm_time.tm_hour, &tm_time.tm_min) == 5) {
    134                 tm_time.tm_year -= 1900;    /* Adjust years */
    135                 tm_time.tm_mon -= 1;    /* Adjust dates from 1-12 to 0-11 */
    136             } else {
     274        if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_HINT)) {
     275            if (strptime(date_str, fmt_str2dt, &tm_time) == NULL)
    137276                bb_error_msg_and_die(bb_msg_invalid_date, date_str);
    138             }
    139277        } else {
    140             int nr;
    141             char *cp;
    142 
    143             nr = sscanf(date_str, "%2d%2d%2d%2d%d", &tm_time.tm_mon,
    144                         &tm_time.tm_mday, &tm_time.tm_hour, &tm_time.tm_min,
    145                         &tm_time.tm_year);
    146 
    147             if (nr < 4 || nr > 5) {
    148                 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
    149             }
    150 
    151             cp = strchr(date_str, '.');
    152             if (cp) {
    153                 nr = sscanf(cp + 1, "%2d", &tm_time.tm_sec);
    154                 if (nr != 1) {
    155                     bb_error_msg_and_die(bb_msg_invalid_date, date_str);
    156                 }
    157             }
    158 
    159             /* correct for century  - minor Y2K problem here? */
    160             if (tm_time.tm_year >= 1900) {
    161                 tm_time.tm_year -= 1900;
    162             }
    163             /* adjust date */
    164             tm_time.tm_mon -= 1;
     278            parse_datestr(date_str, &tm_time);
    165279        }
    166280
    167281        /* Correct any day of week and day of year etc. fields */
    168         tm_time.tm_isdst = -1;  /* Be sure to recheck dst. */
    169         tm = mktime(&tm_time);
    170         if (tm < 0) {
    171             bb_error_msg_and_die(bb_msg_invalid_date, date_str);
    172         }
     282        tm_time.tm_isdst = -1;  /* Be sure to recheck dst */
     283        ts.tv_sec = validate_tm_time(date_str, &tm_time);
     284
    173285        maybe_set_utc(opt);
    174286
    175287        /* if setting time, set it */
    176         if ((opt & DATE_OPT_SET) && stime(&tm) < 0) {
    177             bb_perror_msg("cannot set date");
     288        if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) {
     289            bb_perror_msg("can't set date");
    178290        }
    179291    }
     
    182294
    183295    /* Deal with format string */
    184 
    185     if (date_fmt == NULL) {
     296    if (fmt_dt2str == NULL) {
    186297        int i;
    187         date_fmt = xzalloc(32);
     298        fmt_dt2str = buf_fmt_dt2str;
    188299        if (ENABLE_FEATURE_DATE_ISOFMT && ifmt >= 0) {
    189             strcpy(date_fmt, "%Y-%m-%d");
    190             if (ifmt > 0) {
    191                 i = 8;
    192                 date_fmt[i++] = 'T';
    193                 date_fmt[i++] = '%';
    194                 date_fmt[i++] = 'H';
    195                 if (ifmt > 1) {
    196                     date_fmt[i++] = ':';
    197                     date_fmt[i++] = '%';
    198                     date_fmt[i++] = 'M';
    199                 }
    200                 if (ifmt > 2) {
    201                     date_fmt[i++] = ':';
    202                     date_fmt[i++] = '%';
    203                     date_fmt[i++] = 'S';
    204                 }
     300            /* -I[SPEC]: 0:date 1:hours 2:minutes 3:seconds */
     301            strcpy(fmt_dt2str, "%Y-%m-%dT%H:%M:%S");
     302            i = 8 + 3 * ifmt;
     303            if (ifmt != 0) {
     304                /* TODO: if (ifmt==4) i += sprintf(&fmt_dt2str[i], ",%09u", nanoseconds); */
    205305 format_utc:
    206                 date_fmt[i++] = '%';
    207                 date_fmt[i] = (opt & DATE_OPT_UTC) ? 'Z' : 'z';
    208             }
    209         } else if (opt & DATE_OPT_RFC2822) {
    210             /* Undo busybox.c for date -R */
     306                fmt_dt2str[i++] = '%';
     307                fmt_dt2str[i++] = (opt & OPT_UTC) ? 'Z' : 'z';
     308            }
     309            fmt_dt2str[i] = '\0';
     310        } else if (opt & OPT_RFC2822) {
     311            /* -R. undo busybox.c setlocale */
    211312            if (ENABLE_LOCALE_SUPPORT)
    212313                setlocale(LC_TIME, "C");
    213             strcpy(date_fmt, "%a, %d %b %Y %H:%M:%S ");
    214             i = 22;
     314            strcpy(fmt_dt2str, "%a, %d %b %Y %H:%M:%S ");
     315            i = sizeof("%a, %d %b %Y %H:%M:%S ")-1;
    215316            goto format_utc;
    216         } else /* default case */
    217             date_fmt = (char*)"%a %b %e %H:%M:%S %Z %Y";
    218     }
     317        } else { /* default case */
     318            fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y";
     319        }
     320    }
     321#if ENABLE_FEATURE_DATE_NANO
     322    else {
     323        /* User-specified fmt_dt2str */
     324        /* Search for and process "%N" */
     325        char *p = fmt_dt2str;
     326        while ((p = strchr(p, '%')) != NULL) {
     327            int n, m;
     328            unsigned pres, scale;
     329
     330            p++;
     331            if (*p == '%') {
     332                p++;
     333                continue;
     334            }
     335            n = strspn(p, "0123456789");
     336            if (p[n] != 'N') {
     337                p += n;
     338                continue;
     339            }
     340            /* We have "%[nnn]N" */
     341            p[-1] = '\0';
     342            p[n] = '\0';
     343            scale = 1;
     344            pres = 9;
     345            if (n) {
     346                pres = xatoi_positive(p);
     347                if (pres == 0)
     348                    pres = 9;
     349                m = 9 - pres;
     350                while (--m >= 0)
     351                    scale *= 10;
     352            }
     353
     354            m = p - fmt_dt2str;
     355            p += n + 1;
     356            fmt_dt2str = xasprintf("%s%0*u%s", fmt_dt2str, pres, (unsigned)ts.tv_nsec / scale, p);
     357            p = fmt_dt2str + m;
     358        }
     359    }
     360#endif
    219361
    220362#define date_buf bb_common_bufsiz1
    221     if (*date_fmt == '\0') {
     363    if (*fmt_dt2str == '\0') {
    222364        /* With no format string, just print a blank line */
    223365        date_buf[0] = '\0';
    224366    } else {
    225367        /* Handle special conversions */
    226 
    227         if (strncmp(date_fmt, "%f", 2) == 0) {
    228             date_fmt = (char*)"%Y.%m.%d-%H:%M:%S";
    229         }
    230 
     368        if (strncmp(fmt_dt2str, "%f", 2) == 0) {
     369            fmt_dt2str = (char*)"%Y.%m.%d-%H:%M:%S";
     370        }
    231371        /* Generate output string */
    232         strftime(date_buf, sizeof(date_buf), date_fmt, &tm_time);
     372        strftime(date_buf, sizeof(date_buf), fmt_dt2str, &tm_time);
    233373    }
    234374    puts(date_buf);
  • branches/2.2.9/mindi-busybox/coreutils/dd.c

    r1765 r2725  
    66 * Copyright (C) 2000,2001  Matt Kraai
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
    11 #include <signal.h>  /* For FEATURE_DD_SIGNAL_HANDLING */
    1211#include "libbb.h"
    1312
    1413/* This is a NOEXEC applet. Be very careful! */
    1514
     15
     16enum {
     17    ifd = STDIN_FILENO,
     18    ofd = STDOUT_FILENO,
     19};
    1620
    1721static const struct suffix_mult dd_suffixes[] = {
     
    2125    { "kD", 1000 },
    2226    { "k", 1024 },
    23     { "K", 1024 },  /* compat with coreutils dd */
     27    { "K", 1024 },  /* compat with coreutils dd */
    2428    { "MD", 1000000 },
    2529    { "M", 1048576 },
    2630    { "GD", 1000000000 },
    2731    { "G", 1073741824 },
    28     { }
     32    { "", 0 }
    2933};
    3034
    3135struct globals {
    3236    off_t out_full, out_part, in_full, in_part;
    33 };
     37#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
     38    unsigned long long total_bytes;
     39    unsigned long long begin_time_us;
     40#endif
     41} FIX_ALIASING;
    3442#define G (*(struct globals*)&bb_common_bufsiz1)
    35 /* We have to zero it out because of NOEXEC */
    36 #define INIT_G() memset(&G, 0, sizeof(G))
    37 
    38 
    39 static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal)
     43#define INIT_G() do { \
     44    /* we have to zero it out because of NOEXEC */ \
     45    memset(&G, 0, sizeof(G)); \
     46} while (0)
     47
     48
     49static void dd_output_status(int UNUSED_PARAM cur_signal)
    4050{
     51#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
     52    double seconds;
     53    unsigned long long bytes_sec;
     54    unsigned long long now_us = monotonic_us(); /* before fprintf */
     55#endif
     56
    4157    /* Deliberately using %u, not %d */
    4258    fprintf(stderr, "%"OFF_FMT"u+%"OFF_FMT"u records in\n"
     
    4460            G.in_full, G.in_part,
    4561            G.out_full, G.out_part);
     62
     63#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
     64    fprintf(stderr, "%llu bytes (%sB) copied, ",
     65            G.total_bytes,
     66            /* show fractional digit, use suffixes */
     67            make_human_readable_str(G.total_bytes, 1, 0)
     68    );
     69    /* Corner cases:
     70     * ./busybox dd </dev/null >/dev/null
     71     * ./busybox dd bs=1M count=2000 </dev/zero >/dev/null
     72     * (echo DONE) | ./busybox dd >/dev/null
     73     * (sleep 1; echo DONE) | ./busybox dd >/dev/null
     74     */
     75    seconds = (now_us - G.begin_time_us) / 1000000.0;
     76    bytes_sec = G.total_bytes / seconds;
     77    fprintf(stderr, "%f seconds, %sB/s\n",
     78            seconds,
     79            /* show fractional digit, use suffixes */
     80            make_human_readable_str(bytes_sec, 1, 0)
     81    );
     82#endif
    4683}
    4784
    48 static ssize_t full_write_or_warn(int fd, const void *buf, size_t len,
     85static ssize_t full_write_or_warn(const void *buf, size_t len,
    4986    const char *const filename)
    5087{
    51     ssize_t n = full_write(fd, buf, len);
     88    ssize_t n = full_write(ofd, buf, len);
    5289    if (n < 0)
    5390        bb_perror_msg("writing '%s'", filename);
     
    5592}
    5693
    57 static bool write_and_stats(int fd, const void *buf, size_t len, size_t obs,
     94static bool write_and_stats(const void *buf, size_t len, size_t obs,
    5895    const char *filename)
    5996{
    60     ssize_t n = full_write_or_warn(fd, buf, len, filename);
     97    ssize_t n = full_write_or_warn(buf, len, filename);
    6198    if (n < 0)
    6299        return 1;
    63     if (n == obs)
     100    if ((size_t)n == obs)
    64101        G.out_full++;
    65102    else if (n) /* > 0 */
    66103        G.out_part++;
     104#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
     105    G.total_bytes += n;
     106#endif
    67107    return 0;
    68108}
    69109
    70110#if ENABLE_LFS
    71 #define XATOU_SFX xatoull_sfx
     111# define XATOU_SFX xatoull_sfx
    72112#else
    73 #define XATOU_SFX xatoul_sfx
    74 #endif
    75 
    76 int dd_main(int argc, char **argv);
    77 int dd_main(int argc, char **argv)
     113# define XATOU_SFX xatoul_sfx
     114#endif
     115
     116int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     117int dd_main(int argc UNUSED_PARAM, char **argv)
    78118{
    79119    enum {
    80         FLAG_SYNC    = 1 << 0,
    81         FLAG_NOERROR = 1 << 1,
    82         FLAG_NOTRUNC = 1 << 2,
    83         FLAG_TWOBUFS = 1 << 3,
    84         FLAG_COUNT   = 1 << 4,
     120        /* Must be in the same order as OP_conv_XXX! */
     121        /* (see "flags |= (1 << what)" below) */
     122        FLAG_NOTRUNC = 1 << 0,
     123        FLAG_SYNC    = 1 << 1,
     124        FLAG_NOERROR = 1 << 2,
     125        FLAG_FSYNC   = 1 << 3,
     126        /* end of conv flags */
     127        FLAG_TWOBUFS = 1 << 4,
     128        FLAG_COUNT   = 1 << 5,
    85129    };
    86130    static const char keywords[] ALIGN1 =
    87         "bs=\0""count=\0""seek=\0""skip=\0""if=\0""of=\0"
     131        "bs\0""count\0""seek\0""skip\0""if\0""of\0"
    88132#if ENABLE_FEATURE_DD_IBS_OBS
    89         "ibs=\0""obs=\0""conv=\0""notrunc\0""sync\0""noerror\0"
     133        "ibs\0""obs\0""conv\0"
    90134#endif
    91135        ;
     136#if ENABLE_FEATURE_DD_IBS_OBS
     137    static const char conv_words[] ALIGN1 =
     138        "notrunc\0""sync\0""noerror\0""fsync\0";
     139#endif
    92140    enum {
    93         OP_bs = 1,
     141        OP_bs = 0,
    94142        OP_count,
    95143        OP_seek,
     
    101149        OP_obs,
    102150        OP_conv,
    103         OP_conv_notrunc,
     151        /* Must be in the same order as FLAG_XXX! */
     152        OP_conv_notrunc = 0,
    104153        OP_conv_sync,
    105154        OP_conv_noerror,
     155        OP_conv_fsync,
     156    /* Unimplemented conv=XXX: */
     157    //nocreat       do not create the output file
     158    //excl          fail if the output file already exists
     159    //fdatasync     physically write output file data before finishing
     160    //swab          swap every pair of input bytes
     161    //lcase         change upper case to lower case
     162    //ucase         change lower case to upper case
     163    //block         pad newline-terminated records with spaces to cbs-size
     164    //unblock       replace trailing spaces in cbs-size records with newline
     165    //ascii         from EBCDIC to ASCII
     166    //ebcdic        from ASCII to EBCDIC
     167    //ibm           from ASCII to alternate EBCDIC
    106168#endif
    107169    };
     170    int exitcode = EXIT_FAILURE;
    108171    size_t ibs = 512, obs = 512;
    109172    ssize_t n, w;
     
    112175    struct {
    113176        int flags;
    114         int ifd, ofd;
    115177        size_t oc;
    116178        off_t count;
    117179        off_t seek, skip;
    118180        const char *infile, *outfile;
    119 #if ENABLE_FEATURE_DD_SIGNAL_HANDLING
    120         struct sigaction sigact;
    121 #endif
    122181    } Z;
    123182#define flags   (Z.flags  )
    124 #define ifd     (Z.ifd    )
    125 #define ofd     (Z.ofd    )
    126183#define oc      (Z.oc     )
    127184#define count   (Z.count  )
     
    130187#define infile  (Z.infile )
    131188#define outfile (Z.outfile)
    132 #define sigact  (Z.sigact )
    133189
    134190    memset(&Z, 0, sizeof(Z));
    135191    INIT_G();
    136 
    137 #if ENABLE_FEATURE_DD_SIGNAL_HANDLING
    138     sigact.sa_handler = dd_output_status;
    139     sigact.sa_flags = SA_RESTART;
    140     sigemptyset(&sigact.sa_mask);
    141     sigaction(SIGUSR1, &sigact, NULL);
    142 #endif
    143 
    144     for (n = 1; n < argc; n++) {
    145         smalluint key_len;
    146         smalluint what;
    147         char *key;
     192    //fflush_all(); - is this needed because of NOEXEC?
     193
     194    for (n = 1; argv[n]; n++) {
     195        int what;
     196        char *val;
    148197        char *arg = argv[n];
    149198
    150 //XXX:FIXME: we reject plain "dd --" This would cost ~20 bytes, so..
    151 //if (*arg == '-' && *++arg == '-' && !*++arg) continue;
    152         key = strstr(arg, "=");
    153         if (key == NULL)
     199#if ENABLE_DESKTOP
     200        /* "dd --". NB: coreutils 6.9 will complain if they see
     201         * more than one of them. We wouldn't. */
     202        if (arg[0] == '-' && arg[1] == '-' && arg[2] == '\0')
     203            continue;
     204#endif
     205        val = strchr(arg, '=');
     206        if (val == NULL)
    154207            bb_show_usage();
    155         key_len = key - arg + 1;
    156         key = xstrndup(arg, key_len);
    157         what = index_in_strings(keywords, key) + 1;
    158         if (ENABLE_FEATURE_CLEAN_UP)
    159             free(key);
    160         if (what == 0)
     208        *val = '\0';
     209        what = index_in_strings(keywords, arg);
     210        if (what < 0)
    161211            bb_show_usage();
    162         arg += key_len;
    163         /* Must fit into positive ssize_t */
     212        /* *val = '='; - to preserve ps listing? */
     213        val++;
    164214#if ENABLE_FEATURE_DD_IBS_OBS
    165             if (what == OP_ibs) {
    166                 ibs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes);
    167                 continue;
     215        if (what == OP_ibs) {
     216            /* Must fit into positive ssize_t */
     217            ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);
     218            /*continue;*/
     219        }
     220        if (what == OP_obs) {
     221            obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);
     222            /*continue;*/
     223        }
     224        if (what == OP_conv) {
     225            while (1) {
     226                /* find ',', replace them with NUL so we can use val for
     227                 * index_in_strings() without copying.
     228                 * We rely on val being non-null, else strchr would fault.
     229                 */
     230                arg = strchr(val, ',');
     231                if (arg)
     232                    *arg = '\0';
     233                what = index_in_strings(conv_words, val);
     234                if (what < 0)
     235                    bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv");
     236                flags |= (1 << what);
     237                if (!arg) /* no ',' left, so this was the last specifier */
     238                    break;
     239                /* *arg = ','; - to preserve ps listing? */
     240                val = arg + 1; /* skip this keyword and ',' */
    168241            }
    169             if (what == OP_obs) {
    170                 obs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes);
    171                 continue;
    172             }
    173             if (what == OP_conv) {
    174                 while (1) {
    175                     /* find ',', replace them with nil so we can use arg for
    176                      * index_in_strings() without copying.
    177                      * We rely on arg being non-null, else strchr would fault.
    178                      */
    179                     key = strchr(arg, ',');
    180                     if (key)
    181                         *key = '\0';
    182                     what = index_in_strings(keywords, arg) + 1;
    183                     if (what < OP_conv_notrunc)
    184                         bb_error_msg_and_die(bb_msg_invalid_arg, arg, "conv");
    185                     if (what == OP_conv_notrunc)
    186                         flags |= FLAG_NOTRUNC;
    187                     if (what == OP_conv_sync)
    188                         flags |= FLAG_SYNC;
    189                     if (what == OP_conv_noerror)
    190                         flags |= FLAG_NOERROR;
    191                     if (!key) /* no ',' left, so this was the last specifier */
    192                         break;
    193                     arg = key + 1; /* skip this keyword and ',' */
    194                 }
    195                 continue;
    196             }
     242            continue; /* we trashed 'what', can't fall through */
     243        }
    197244#endif
    198245        if (what == OP_bs) {
    199             ibs = obs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes);
    200             continue;
     246            ibs = obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);
     247            /*continue;*/
    201248        }
    202249        /* These can be large: */
    203250        if (what == OP_count) {
    204251            flags |= FLAG_COUNT;
    205             count = XATOU_SFX(arg, dd_suffixes);
    206             continue;
     252            count = XATOU_SFX(val, dd_suffixes);
     253            /*continue;*/
    207254        }
    208255        if (what == OP_seek) {
    209             seek = XATOU_SFX(arg, dd_suffixes);
    210             continue;
     256            seek = XATOU_SFX(val, dd_suffixes);
     257            /*continue;*/
    211258        }
    212259        if (what == OP_skip) {
    213             skip = XATOU_SFX(arg, dd_suffixes);
    214             continue;
     260            skip = XATOU_SFX(val, dd_suffixes);
     261            /*continue;*/
    215262        }
    216263        if (what == OP_if) {
    217             infile = arg;
    218             continue;
    219         }
    220         if (what == OP_of)
    221             outfile = arg;
    222     }
     264            infile = val;
     265            /*continue;*/
     266        }
     267        if (what == OP_of) {
     268            outfile = val;
     269            /*continue;*/
     270        }
     271    } /* end of "for (argv[n])" */
     272
    223273//XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever
    224274    ibuf = obuf = xmalloc(ibs);
     
    227277        obuf = xmalloc(obs);
    228278    }
     279
     280#if ENABLE_FEATURE_DD_SIGNAL_HANDLING
     281    signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status);
     282#endif
     283#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
     284    G.begin_time_us = monotonic_us();
     285#endif
     286
    229287    if (infile != NULL)
    230         ifd = xopen(infile, O_RDONLY);
     288        xmove_fd(xopen(infile, O_RDONLY), ifd);
    231289    else {
    232         /* ifd = STDIN_FILENO; - it's zero and it's already there */
    233290        infile = bb_msg_standard_input;
    234291    }
     
    239296            oflag |= O_TRUNC;
    240297
    241         ofd = xopen(outfile, oflag);
     298        xmove_fd(xopen(outfile, oflag), ofd);
    242299
    243300        if (seek && !(flags & FLAG_NOTRUNC)) {
     
    245302                struct stat st;
    246303
    247                 if (fstat(ofd, &st) < 0 || S_ISREG(st.st_mode) ||
    248                         S_ISDIR(st.st_mode))
     304                if (fstat(ofd, &st) < 0
     305                 || S_ISREG(st.st_mode)
     306                 || S_ISDIR(st.st_mode)
     307                ) {
    249308                    goto die_outfile;
     309                }
    250310            }
    251311        }
    252312    } else {
    253         ofd = STDOUT_FILENO;
    254313        outfile = bb_msg_standard_output;
    255314    }
     
    271330
    272331    while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) {
    273         if (flags & FLAG_NOERROR) /* Pre-zero the buffer if conv=noerror */
    274             memset(ibuf, 0, ibs);
    275332        n = safe_read(ifd, ibuf, ibs);
    276333        if (n == 0)
    277334            break;
    278335        if (n < 0) {
    279             if (flags & FLAG_NOERROR) {
    280                 n = ibs;
    281                 bb_perror_msg("%s", infile);
    282             } else
     336            /* "Bad block" */
     337            if (!(flags & FLAG_NOERROR))
    283338                goto die_infile;
     339            bb_simple_perror_msg(infile);
     340            /* GNU dd with conv=noerror skips over bad blocks */
     341            xlseek(ifd, ibs, SEEK_CUR);
     342            /* conv=noerror,sync writes NULs,
     343             * conv=noerror just ignores input bad blocks */
     344            n = 0;
    284345        }
    285346        if ((size_t)n == ibs)
     
    288349            G.in_part++;
    289350            if (flags & FLAG_SYNC) {
    290                 memset(ibuf + n, '\0', ibs - n);
     351                memset(ibuf + n, 0, ibs - n);
    291352                n = ibs;
    292353            }
     
    297358                size_t d = obs - oc;
    298359
    299                 if (d > n)
     360                if (d > (size_t)n)
    300361                    d = n;
    301362                memcpy(obuf + oc, tmp, d);
     
    304365                oc += d;
    305366                if (oc == obs) {
    306                     if (write_and_stats(ofd, obuf, obs, obs, outfile))
     367                    if (write_and_stats(obuf, obs, obs, outfile))
    307368                        goto out_status;
    308369                    oc = 0;
    309370                }
    310371            }
    311         } else if (write_and_stats(ofd, ibuf, n, obs, outfile))
     372        } else if (write_and_stats(ibuf, n, obs, outfile))
    312373            goto out_status;
     374
     375        if (flags & FLAG_FSYNC) {
     376            if (fsync(ofd) < 0)
     377                goto die_outfile;
     378        }
    313379    }
    314380
    315381    if (ENABLE_FEATURE_DD_IBS_OBS && oc) {
    316         w = full_write_or_warn(ofd, obuf, oc, outfile);
     382        w = full_write_or_warn(obuf, oc, outfile);
    317383        if (w < 0) goto out_status;
    318         if (w > 0)
    319             G.out_part++;
     384        if (w > 0) G.out_part++;
    320385    }
    321386    if (close(ifd) < 0) {
    322387 die_infile:
    323         bb_perror_msg_and_die("%s", infile);
     388        bb_simple_perror_msg_and_die(infile);
    324389    }
    325390
    326391    if (close(ofd) < 0) {
    327392 die_outfile:
    328         bb_perror_msg_and_die("%s", outfile);
    329     }
     393        bb_simple_perror_msg_and_die(outfile);
     394    }
     395
     396    exitcode = EXIT_SUCCESS;
    330397 out_status:
    331398    dd_output_status(0);
    332399
    333     return EXIT_SUCCESS;
     400    return exitcode;
    334401}
  • branches/2.2.9/mindi-busybox/coreutils/df.c

    r1765 r2725  
    66 * based on original code by (I think) Bruce Perens <bruce@pixar.com>.
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
    11 /* BB_AUDIT SUSv3 _NOT_ compliant -- options -P and -t missing.  Also blocksize. */
     11/* BB_AUDIT SUSv3 _NOT_ compliant -- option -t missing. */
    1212/* http://www.opengroup.org/onlinepubs/007904975/utilities/df.html */
    1313
     
    1717 * on output.  Output stats on 0-sized filesystems if specifically listed on
    1818 * the command line.  Properly round *-blocks, Used, and Available quantities.
     19 *
     20 * Aug 28, 2008      Bernhard Reutner-Fischer
     21 *
     22 * Implement -P and -B; better coreutils compat; cleanup
    1923 */
    2024
     
    2226#include <sys/vfs.h>
    2327#include "libbb.h"
     28#include "unicode.h"
    2429
    2530#if !ENABLE_FEATURE_HUMAN_READABLE
     
    3035#endif
    3136
    32 int df_main(int argc, char **argv);
    33 int df_main(int argc, char **argv)
     37int df_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     38int df_main(int argc UNUSED_PARAM, char **argv)
    3439{
    3540    unsigned long blocks_used;
    3641    unsigned blocks_percent_used;
    37 #if ENABLE_FEATURE_HUMAN_READABLE
    38     unsigned df_disp_hr = 1024;
    39 #endif
     42    unsigned long df_disp_hr = 1024;
    4043    int status = EXIT_SUCCESS;
    4144    unsigned opt;
     
    4346    struct mntent *mount_entry;
    4447    struct statfs s;
    45     /* default display is kilobytes */
    46     const char *disp_units_hdr = "1k-blocks";
    47 
    48 #if ENABLE_FEATURE_HUMAN_READABLE
    49     opt_complementary = "h-km:k-hm:m-hk";
    50     opt = getopt32(argv, "hmk");
    51     if (opt & 1) {
     48
     49    enum {
     50        OPT_KILO  = (1 << 0),
     51        OPT_POSIX = (1 << 1),
     52        OPT_ALL   = (1 << 2) * ENABLE_FEATURE_DF_FANCY,
     53        OPT_INODE = (1 << 3) * ENABLE_FEATURE_DF_FANCY,
     54        OPT_BSIZE = (1 << 4) * ENABLE_FEATURE_DF_FANCY,
     55        OPT_HUMAN = (1 << (2 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE,
     56        OPT_MEGA  = (1 << (3 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE,
     57    };
     58    const char *disp_units_hdr = NULL;
     59    char *chp;
     60
     61    init_unicode();
     62
     63#if ENABLE_FEATURE_HUMAN_READABLE && ENABLE_FEATURE_DF_FANCY
     64    opt_complementary = "k-mB:m-Bk:B-km";
     65#elif ENABLE_FEATURE_HUMAN_READABLE
     66    opt_complementary = "k-m:m-k";
     67#endif
     68    opt = getopt32(argv, "kP"
     69            IF_FEATURE_DF_FANCY("aiB:")
     70            IF_FEATURE_HUMAN_READABLE("hm")
     71            IF_FEATURE_DF_FANCY(, &chp));
     72    if (opt & OPT_MEGA)
     73        df_disp_hr = 1024*1024;
     74
     75    if (opt & OPT_BSIZE)
     76        df_disp_hr = xatoul_range(chp, 1, ULONG_MAX); /* disallow 0 */
     77
     78    /* From the manpage of df from coreutils-6.10:
     79       Disk space is shown in 1K blocks by default, unless the environment
     80       variable POSIXLY_CORRECT is set, in which case 512-byte blocks are used.
     81    */
     82    if (getenv("POSIXLY_CORRECT")) /* TODO - a new libbb function? */
     83        df_disp_hr = 512;
     84
     85    if (opt & OPT_HUMAN) {
    5286        df_disp_hr = 0;
    5387        disp_units_hdr = "     Size";
    5488    }
    55     if (opt & 2) {
    56         df_disp_hr = 1024*1024;
    57         disp_units_hdr = "1M-blocks";
    58     }
     89    if (opt & OPT_INODE)
     90        disp_units_hdr = "   Inodes";
     91
     92    if (disp_units_hdr == NULL) {
     93#if ENABLE_FEATURE_HUMAN_READABLE
     94        disp_units_hdr = xasprintf("%s-blocks",
     95            /* print df_disp_hr, show no fractionals,
     96             * use suffixes if OPT_POSIX is set in opt */
     97            make_human_readable_str(df_disp_hr, 0, !!(opt & OPT_POSIX))
     98        );
    5999#else
    60     opt = getopt32(argv, "k");
    61 #endif
    62 
    63     printf("Filesystem%11s%-15sUsed Available Use%% Mounted on\n",
    64               "", disp_units_hdr);
     100        disp_units_hdr = xasprintf("%lu-blocks", df_disp_hr);
     101#endif
     102    }
     103    printf("Filesystem           %-15sUsed Available %s Mounted on\n",
     104            disp_units_hdr, (opt & OPT_POSIX) ? "Capacity" : "Use%");
    65105
    66106    mount_table = NULL;
    67107    argv += optind;
    68     if (optind >= argc) {
     108    if (!argv[0]) {
    69109        mount_table = setmntent(bb_path_mtab_file, "r");
    70         if (!mount_table) {
     110        if (!mount_table)
    71111            bb_perror_msg_and_die(bb_path_mtab_file);
    72         }
    73112    }
    74113
     
    85124        } else {
    86125            mount_point = *argv++;
    87             if (!mount_point) {
     126            if (!mount_point)
    88127                break;
    89             }
    90             mount_entry = find_mount_point(mount_point, bb_path_mtab_file);
     128            mount_entry = find_mount_point(mount_point, 1);
    91129            if (!mount_entry) {
    92130                bb_error_msg("%s: can't find mount point", mount_point);
    93  SET_ERROR:
     131 set_error:
    94132                status = EXIT_FAILURE;
    95133                continue;
     
    101139
    102140        if (statfs(mount_point, &s) != 0) {
    103             bb_perror_msg("%s", mount_point);
    104             goto SET_ERROR;
     141            bb_simple_perror_msg(mount_point);
     142            goto set_error;
    105143        }
    106144
    107         if ((s.f_blocks > 0) || !mount_table){
     145        if ((s.f_blocks > 0) || !mount_table || (opt & OPT_ALL)) {
     146            if (opt & OPT_INODE) {
     147                s.f_blocks = s.f_files;
     148                s.f_bavail = s.f_bfree = s.f_ffree;
     149                s.f_bsize = 1;
     150
     151                if (df_disp_hr)
     152                    df_disp_hr = 1;
     153            }
    108154            blocks_used = s.f_blocks - s.f_bfree;
    109155            blocks_percent_used = 0;
     
    114160            }
    115161
    116             if (strcmp(device, "rootfs") == 0) {
     162            /* GNU coreutils 6.10 skips certain mounts, try to be compatible.  */
     163            if (strcmp(device, "rootfs") == 0)
    117164                continue;
    118             } else if (strcmp(device, "/dev/root") == 0) {
     165
     166#ifdef WHY_WE_DO_IT_FOR_DEV_ROOT_ONLY
     167            if (strcmp(device, "/dev/root") == 0) {
    119168                /* Adjusts device to be the real root device,
    120                 * or leaves device alone if it can't find it */
     169                 * or leaves device alone if it can't find it */
    121170                device = find_block_device("/");
    122171                if (!device) {
    123                     goto SET_ERROR;
     172                    goto set_error;
    124173                }
    125174            }
    126 
     175#endif
     176
     177#if ENABLE_UNICODE_SUPPORT
     178            {
     179                uni_stat_t uni_stat;
     180                char *uni_dev = unicode_conv_to_printable(&uni_stat, device);
     181                if (uni_stat.unicode_width > 20) {
     182                    printf("%s\n%20s", uni_dev, "");
     183                } else {
     184                    printf("%s%*s", uni_dev, 20 - (int)uni_stat.unicode_width, "");
     185                }
     186                free(uni_dev);
     187            }
     188#else
    127189            if (printf("\n%-20s" + 1, device) > 20)
    128190                    printf("\n%-20s", "");
     191#endif
     192
    129193#if ENABLE_FEATURE_HUMAN_READABLE
    130194            printf(" %9s ",
     195                /* f_blocks x f_bsize / df_disp_hr, show one fractional,
     196                 * use suffixes if df_disp_hr == 0 */
    131197                make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr));
    132198
    133199            printf(" %9s " + 1,
     200                /* EXPR x f_bsize / df_disp_hr, show one fractional,
     201                 * use suffixes if df_disp_hr == 0 */
    134202                make_human_readable_str((s.f_blocks - s.f_bfree),
    135203                        s.f_bsize, df_disp_hr));
    136204
    137205            printf("%9s %3u%% %s\n",
    138                     make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr),
    139                     blocks_percent_used, mount_point);
     206                /* f_bavail x f_bsize / df_disp_hr, show one fractional,
     207                 * use suffixes if df_disp_hr == 0 */
     208                make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr),
     209                blocks_percent_used, mount_point);
    140210#else
    141211            printf(" %9lu %9lu %9lu %3u%% %s\n",
    142                     kscale(s.f_blocks, s.f_bsize),
    143                     kscale(s.f_blocks-s.f_bfree, s.f_bsize),
    144                     kscale(s.f_bavail, s.f_bsize),
    145                     blocks_percent_used, mount_point);
     212                kscale(s.f_blocks, s.f_bsize),
     213                kscale(s.f_blocks - s.f_bfree, s.f_bsize),
     214                kscale(s.f_bavail, s.f_bsize),
     215                blocks_percent_used, mount_point);
    146216#endif
    147217        }
    148218    }
    149219
    150     fflush_stdout_and_exit(status);
     220    return status;
    151221}
  • branches/2.2.9/mindi-busybox/coreutils/dirname.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1515/* This is a NOFORK applet. Be very careful! */
    1616
    17 int dirname_main(int argc, char **argv);
    18 int dirname_main(int argc, char **argv)
     17int dirname_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     18int dirname_main(int argc UNUSED_PARAM, char **argv)
    1919{
    20     if (argc != 2) {
    21         bb_show_usage();
    22     }
    23 
    24     puts(dirname(argv[1]));
    25 
    26     return fflush(stdout);
     20    puts(dirname(single_argv(argv)));
     21    return fflush_all();
    2722}
  • branches/2.2.9/mindi-busybox/coreutils/dos2unix.c

    r1765 r2725  
    1010 * dos2unix filters reading input from stdin and writing output to stdout.
    1111 *
    12  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     12 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1313*/
    1414
    1515#include "libbb.h"
     16
     17/* This is a NOEXEC applet. Be very careful! */
    1618
    1719enum {
     
    2123
    2224/* if fn is NULL then input is stdin and output is stdout */
    23 static int convert(char *fn, int conv_type)
     25static void convert(char *fn, int conv_type)
    2426{
    2527    FILE *in, *out;
    2628    int i;
    27 #define name_buf bb_common_bufsiz1
     29    char *temp_fn = temp_fn; /* for compiler */
     30    char *resolved_fn = resolved_fn;
    2831
    2932    in = stdin;
    3033    out = stdout;
    3134    if (fn != NULL) {
    32         in = xfopen(fn, "rw");
    33         /*
    34            The file is then created with mode read/write and
    35            permissions 0666 for glibc 2.0.6 and earlier or
    36            0600 for glibc 2.0.7 and later.
    37          */
    38         snprintf(name_buf, sizeof(name_buf), "%sXXXXXX", fn);
    39         i = mkstemp(&name_buf[0]);
    40         if (i == -1 || chmod(name_buf, 0600) == -1) {
    41             bb_perror_nomsg_and_die();
    42         }
    43         out = fdopen(i, "w+");
    44         if (!out) {
    45             close(i);
    46             remove(name_buf);
    47             return -2;
    48         }
     35        struct stat st;
     36
     37        resolved_fn = xmalloc_follow_symlinks(fn);
     38        if (resolved_fn == NULL)
     39            bb_simple_perror_msg_and_die(fn);
     40        in = xfopen_for_read(resolved_fn);
     41        fstat(fileno(in), &st);
     42
     43        temp_fn = xasprintf("%sXXXXXX", resolved_fn);
     44        i = xmkstemp(temp_fn);
     45        if (fchmod(i, st.st_mode) == -1)
     46            bb_simple_perror_msg_and_die(temp_fn);
     47
     48        out = xfdopen_for_write(i);
    4949    }
    5050
     
    5252        if (i == '\r')
    5353            continue;
    54         if (i == '\n') {
     54        if (i == '\n')
    5555            if (conv_type == CT_UNIX2DOS)
    5656                fputc('\r', out);
    57             fputc('\n', out);
    58             continue;
    59         }
    6057        fputc(i, out);
    6158    }
     
    6360    if (fn != NULL) {
    6461        if (fclose(in) < 0 || fclose(out) < 0) {
    65             bb_perror_nomsg();
    66             remove(name_buf);
    67             return -2;
     62            unlink(temp_fn);
     63            bb_perror_nomsg_and_die();
    6864        }
    69         /* Assume they are both on the same filesystem (which
    70          * should be true since we put them into the same directory
    71          * so we _should_ be ok, but you never know... */
    72         if (rename(name_buf, fn) < 0) {
    73             bb_perror_msg("cannot rename '%s' as '%s'", name_buf, fn);
    74             return -1;
    75         }
     65        xrename(temp_fn, resolved_fn);
     66        free(temp_fn);
     67        free(resolved_fn);
    7668    }
    77 
    78     return 0;
    7969}
    8070
    81 int dos2unix_main(int argc, char **argv);
    82 int dos2unix_main(int argc, char **argv)
     71int dos2unix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     72int dos2unix_main(int argc UNUSED_PARAM, char **argv)
    8373{
    8474    int o, conv_type;
    8575
    8676    /* See if we are supposed to be doing dos2unix or unix2dos */
     77    conv_type = CT_UNIX2DOS;
    8778    if (applet_name[0] == 'd') {
    88         conv_type = CT_DOS2UNIX;    /* 2 */
    89     } else {
    90         conv_type = CT_UNIX2DOS;    /* 1 */
     79        conv_type = CT_DOS2UNIX;
    9180    }
    9281
     
    10089        conv_type = o;
    10190
     91    argv += optind;
    10292    do {
    10393        /* might be convert(NULL) if there is no filename given */
    104         o = convert(argv[optind], conv_type);
    105         if (o < 0)
    106             break;
    107         optind++;
    108     } while (optind < argc);
     94        convert(*argv, conv_type);
     95    } while (*argv && *++argv);
    10996
    110     return o;
     97    return 0;
    11198}
  • branches/2.2.9/mindi-busybox/coreutils/du.c

    r1765 r2725  
    77 * Copyright (C) 2002  Edward Betts <edward@debian.org>
    88 *
    9  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1010 */
    1111
     
    2626#include "libbb.h"
    2727
    28 #if ENABLE_FEATURE_HUMAN_READABLE
    29 # if ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
    30 static unsigned long disp_hr = 1024;
    31 # else
    32 static unsigned long disp_hr = 512;
    33 # endif
    34 #elif ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
    35 static unsigned disp_k = 1;
    36 #else
    37 static unsigned disp_k; /* bss inits to 0 */
    38 #endif
    39 
    40 static int max_print_depth = INT_MAX;
    41 static nlink_t count_hardlinks = 1;
    42 
    43 static int status;
    44 static int print_files;
    45 static int slink_depth;
    46 static int du_depth;
    47 static int one_file_system;
    48 static dev_t dir_dev;
    49 
    50 
    51 static void print(long size, const char *const filename)
     28enum {
     29    OPT_a_files_too    = (1 << 0),
     30    OPT_H_follow_links = (1 << 1),
     31    OPT_k_kbytes       = (1 << 2),
     32    OPT_L_follow_links = (1 << 3),
     33    OPT_s_total_norecurse = (1 << 4),
     34    OPT_x_one_FS       = (1 << 5),
     35    OPT_d_maxdepth     = (1 << 6),
     36    OPT_l_hardlinks    = (1 << 7),
     37    OPT_c_total        = (1 << 8),
     38    OPT_h_for_humans   = (1 << 9),
     39    OPT_m_mbytes       = (1 << 10),
     40};
     41
     42struct globals {
     43#if ENABLE_FEATURE_HUMAN_READABLE
     44    unsigned long disp_hr;
     45#else
     46    unsigned disp_k;
     47#endif
     48    int max_print_depth;
     49    bool status;
     50    int slink_depth;
     51    int du_depth;
     52    dev_t dir_dev;
     53} FIX_ALIASING;
     54#define G (*(struct globals*)&bb_common_bufsiz1)
     55
     56
     57static void print(unsigned long size, const char *filename)
    5258{
    5359    /* TODO - May not want to defer error checking here. */
    5460#if ENABLE_FEATURE_HUMAN_READABLE
    55     printf("%s\t%s\n", make_human_readable_str(size, 512, disp_hr),
     61    printf("%s\t%s\n",
     62            /* size x 512 / G.disp_hr, show one fractional,
     63             * use suffixes if G.disp_hr == 0 */
     64            make_human_readable_str(size, 512, G.disp_hr),
    5665            filename);
    5766#else
    58     if (disp_k) {
     67    if (G.disp_k) {
    5968        size++;
    6069        size >>= 1;
    6170    }
    62     printf("%ld\t%s\n", size, filename);
     71    printf("%lu\t%s\n", size, filename);
    6372#endif
    6473}
    6574
    6675/* tiny recursive du */
    67 static long du(const char *const filename)
     76static unsigned long du(const char *filename)
    6877{
    6978    struct stat statbuf;
    70     long sum;
     79    unsigned long sum;
    7180
    7281    if (lstat(filename, &statbuf) != 0) {
    73         bb_perror_msg("%s", filename);
    74         status = EXIT_FAILURE;
     82        bb_simple_perror_msg(filename);
     83        G.status = EXIT_FAILURE;
    7584        return 0;
    7685    }
    7786
    78     if (one_file_system) {
    79         if (du_depth == 0) {
    80             dir_dev = statbuf.st_dev;
    81         } else if (dir_dev != statbuf.st_dev) {
     87    if (option_mask32 & OPT_x_one_FS) {
     88        if (G.du_depth == 0) {
     89            G.dir_dev = statbuf.st_dev;
     90        } else if (G.dir_dev != statbuf.st_dev) {
    8291            return 0;
    8392        }
     
    8796
    8897    if (S_ISLNK(statbuf.st_mode)) {
    89         if (slink_depth > du_depth) {   /* -H or -L */
     98        if (G.slink_depth > G.du_depth) { /* -H or -L */
    9099            if (stat(filename, &statbuf) != 0) {
    91                 bb_perror_msg("%s", filename);
    92                 status = EXIT_FAILURE;
     100                bb_simple_perror_msg(filename);
     101                G.status = EXIT_FAILURE;
    93102                return 0;
    94103            }
    95104            sum = statbuf.st_blocks;
    96             if (slink_depth == 1) {
    97                 slink_depth = INT_MAX;  /* Convert -H to -L. */
     105            if (G.slink_depth == 1) {
     106                /* Convert -H to -L */
     107                G.slink_depth = INT_MAX;
    98108            }
    99109        }
    100110    }
    101111
    102     if (statbuf.st_nlink > count_hardlinks) {
     112    if (!(option_mask32 & OPT_l_hardlinks)
     113     && statbuf.st_nlink > 1
     114    ) {
    103115        /* Add files/directories with links only once */
    104116        if (is_in_ino_dev_hashtable(&statbuf)) {
     
    115127        dir = warn_opendir(filename);
    116128        if (!dir) {
    117             status = EXIT_FAILURE;
     129            G.status = EXIT_FAILURE;
    118130            return sum;
    119131        }
    120132
    121         newfile = last_char_is(filename, '/');
    122         if (newfile)
    123             *newfile = '\0';
    124 
    125133        while ((entry = readdir(dir))) {
    126             char *name = entry->d_name;
    127 
    128             newfile = concat_subpath_file(filename, name);
     134            newfile = concat_subpath_file(filename, entry->d_name);
    129135            if (newfile == NULL)
    130136                continue;
    131             ++du_depth;
     137            ++G.du_depth;
    132138            sum += du(newfile);
    133             --du_depth;
     139            --G.du_depth;
    134140            free(newfile);
    135141        }
    136142        closedir(dir);
    137     } else if (du_depth > print_files) {
    138         return sum;
    139     }
    140     if (du_depth <= max_print_depth) {
     143    } else {
     144        if (!(option_mask32 & OPT_a_files_too) && G.du_depth != 0)
     145            return sum;
     146    }
     147    if (G.du_depth <= G.max_print_depth) {
    141148        print(sum, filename);
    142149    }
     
    144151}
    145152
    146 int du_main(int argc, char **argv);
    147 int du_main(int argc, char **argv)
     153int du_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     154int du_main(int argc UNUSED_PARAM, char **argv)
    148155{
    149     long total;
     156    unsigned long total;
    150157    int slink_depth_save;
    151     int print_final_total;
    152     char *smax_print_depth;
    153158    unsigned opt;
    154159
    155 #if ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
    156     if (getenv("POSIXLY_CORRECT")) {    /* TODO - a new libbb function? */
    157 #if ENABLE_FEATURE_HUMAN_READABLE
    158         disp_hr = 512;
    159 #else
    160         disp_k = 0;
    161 #endif
    162     }
    163 #endif
     160#if ENABLE_FEATURE_HUMAN_READABLE
     161    IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 1024;)
     162    IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 512;)
     163    if (getenv("POSIXLY_CORRECT"))  /* TODO - a new libbb function? */
     164        G.disp_hr = 512;
     165#else
     166    IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 1;)
     167    /* IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 0;) - G is pre-zeroed */
     168#endif
     169    G.max_print_depth = INT_MAX;
    164170
    165171    /* Note: SUSv3 specifies that -a and -s options cannot be used together
     
    170176     */
    171177#if ENABLE_FEATURE_HUMAN_READABLE
    172     opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s";
    173     opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &smax_print_depth);
    174     if (opt & (1 << 9)) {
    175         /* -h opt */
    176         disp_hr = 0;
    177     }
    178     if (opt & (1 << 10)) {
    179         /* -m opt */
    180         disp_hr = 1024*1024;
    181     }
    182     if (opt & (1 << 2)) {
    183         /* -k opt */
    184         disp_hr = 1024;
    185     }
    186 #else
    187     opt_complementary = "H-L:L-H:s-d:d-s";
    188     opt = getopt32(argv, "aHkLsx" "d:" "lc", &smax_print_depth);
     178    opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s:d+";
     179    opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &G.max_print_depth);
     180    argv += optind;
     181    if (opt & OPT_h_for_humans) {
     182        G.disp_hr = 0;
     183    }
     184    if (opt & OPT_m_mbytes) {
     185        G.disp_hr = 1024*1024;
     186    }
     187    if (opt & OPT_k_kbytes) {
     188        G.disp_hr = 1024;
     189    }
     190#else
     191    opt_complementary = "H-L:L-H:s-d:d-s:d+";
     192    opt = getopt32(argv, "aHkLsx" "d:" "lc", &G.max_print_depth);
     193    argv += optind;
    189194#if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
    190     if (opt & (1 << 2)) {
    191         /* -k opt */
    192         disp_k = 1;
    193     }
    194 #endif
    195 #endif
    196     if (opt & (1 << 0)) {
    197         /* -a opt */
    198         print_files = INT_MAX;
    199     }
    200     if (opt & (1 << 1)) {
    201         /* -H opt */
    202         slink_depth = 1;
    203     }
    204     if (opt & (1 << 3)) {
    205         /* -L opt */
    206         slink_depth = INT_MAX;
    207     }
    208     if (opt & (1 << 4)) {
    209         /* -s opt */
    210         max_print_depth = 0;
    211     }
    212     one_file_system = opt & (1 << 5); /* -x opt */
    213     if (opt & (1 << 6)) {
    214         /* -d opt */
    215         max_print_depth = xatoi_u(smax_print_depth);
    216     }
    217     if (opt & (1 << 7)) {
    218         /* -l opt */
    219         count_hardlinks = MAXINT(nlink_t);
    220     }
    221     print_final_total = opt & (1 << 8); /* -c opt */
     195    if (opt & OPT_k_kbytes) {
     196        G.disp_k = 1;
     197    }
     198#endif
     199#endif
     200    if (opt & OPT_H_follow_links) {
     201        G.slink_depth = 1;
     202    }
     203    if (opt & OPT_L_follow_links) {
     204        G.slink_depth = INT_MAX;
     205    }
     206    if (opt & OPT_s_total_norecurse) {
     207        G.max_print_depth = 0;
     208    }
    222209
    223210    /* go through remaining args (if any) */
    224     argv += optind;
    225     if (optind >= argc) {
     211    if (!*argv) {
    226212        *--argv = (char*)".";
    227         if (slink_depth == 1) {
    228             slink_depth = 0;
    229         }
    230     }
    231 
    232     slink_depth_save = slink_depth;
     213        if (G.slink_depth == 1) {
     214            G.slink_depth = 0;
     215        }
     216    }
     217
     218    slink_depth_save = G.slink_depth;
    233219    total = 0;
    234220    do {
    235221        total += du(*argv);
    236         slink_depth = slink_depth_save;
     222        /* otherwise du /dir /dir won't show /dir twice: */
     223        reset_ino_dev_hashtable();
     224        G.slink_depth = slink_depth_save;
    237225    } while (*++argv);
    238     if (ENABLE_FEATURE_CLEAN_UP)
    239         reset_ino_dev_hashtable();
    240     if (print_final_total) {
     226
     227    if (opt & OPT_c_total)
    241228        print(total, "total");
    242     }
    243 
    244     fflush_stdout_and_exit(status);
     229
     230    fflush_stdout_and_exit(G.status);
    245231}
  • branches/2.2.9/mindi-busybox/coreutils/echo.c

    r1765 r2725  
    66 *  The Regents of the University of California.  All rights reserved.
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 *
    1010 * Original copyright notice is retained at the end of this file.
     
    2626#include "libbb.h"
    2727
    28 int bb_echo(char **argv)
     28/* This is a NOFORK applet. Be very careful! */
     29
     30/* NB: can be used by shell even if not enabled as applet */
     31
     32int echo_main(int argc UNUSED_PARAM, char **argv)
    2933{
    3034    const char *arg;
     
    3438        nflag = 1,  /* 1 -- print '\n' */
    3539    };
     40
     41    /* We must check that stdout is not closed.
     42     * The reason for this is highly non-obvious.
     43     * echo_main is used from shell. Shell must correctly handle "echo foo"
     44     * if stdout is closed. With stdio, output gets shoveled into
     45     * stdout buffer, and even fflush cannot clear it out. It seems that
     46     * even if libc receives EBADF on write attempts, it feels determined
     47     * to output data no matter what. So it will try later,
     48     * and possibly will clobber future output. Not good. */
     49// TODO: check fcntl() & O_ACCMODE == O_WRONLY or O_RDWR?
     50    if (fcntl(1, F_GETFL) == -1)
     51        return 1; /* match coreutils 6.10 (sans error msg to stderr) */
     52    //if (dup2(1, 1) != 1) - old way
     53    //  return 1;
     54
    3655    arg = *++argv;
    3756    if (!arg)
     
    4160    char nflag = 1;
    4261    char eflag = 0;
     62
     63    /* We must check that stdout is not closed. */
     64    if (fcntl(1, F_GETFL) == -1)
     65        return 1;
    4366
    4467    while (1) {
     
    89112#if !ENABLE_FEATURE_FANCY_ECHO
    90113                /* SUSv3 specifies that octal escapes must begin with '0'. */
    91                 if ( (((unsigned char)*arg) - '1') >= 7)
     114                if ( ((int)(unsigned char)(*arg) - '0') >= 8) /* '8' or bigger */
    92115#endif
    93116                {
    94117                    /* Since SUSv3 mandates a first digit of 0, 4-digit octals
    95118                    * of the form \0### are accepted. */
    96                     if (*arg == '0' && ((unsigned char)(arg[1]) - '0') < 8) {
    97                         arg++;
     119                    if (*arg == '0') {
     120                        /* NB: don't turn "...\0" into "...\" */
     121                        if (arg[1] && ((unsigned char)(arg[1]) - '0') < 8) {
     122                            arg++;
     123                        }
    98124                    }
    99                     /* bb_process_escape_sequence can handle nul correctly */
     125                    /* bb_process_escape_sequence handles NUL correctly
     126                     * ("...\" case). */
    100127                    c = bb_process_escape_sequence(&arg);
    101128                }
    102129            }
    103             putchar(c);
     130            bb_putchar(c);
    104131        }
    105132
     
    107134        if (!arg)
    108135            break;
    109         putchar(' ');
     136        bb_putchar(' ');
    110137    }
    111138
    112139 newline_ret:
    113140    if (nflag) {
    114         putchar('\n');
     141        bb_putchar('\n');
    115142    }
    116143 ret:
    117     return fflush(stdout);
    118 }
    119 
    120 /* This is a NOFORK applet. Be very careful! */
    121 
    122 int echo_main(int argc, char** argv);
    123 int echo_main(int argc, char** argv)
    124 {
    125     return bb_echo(argv);
     144    return fflush_all();
    126145}
    127146
     
    164183 *  @(#)echo.c  8.1 (Berkeley) 5/31/93
    165184 */
     185
     186#ifdef VERSION_WITH_WRITEV
     187/* We can't use stdio.
     188 * The reason for this is highly non-obvious.
     189 * echo_main is used from shell. Shell must correctly handle "echo foo"
     190 * if stdout is closed. With stdio, output gets shoveled into
     191 * stdout buffer, and even fflush cannot clear it out. It seems that
     192 * even if libc receives EBADF on write attempts, it feels determined
     193 * to output data no matter what. So it will try later,
     194 * and possibly will clobber future output. Not good.
     195 *
     196 * Using writev instead, with 'direct' conversion of argv vector.
     197 */
     198
     199int echo_main(int argc, char **argv)
     200{
     201    struct iovec io[argc];
     202    struct iovec *cur_io = io;
     203    char *arg;
     204    char *p;
     205#if !ENABLE_FEATURE_FANCY_ECHO
     206    enum {
     207        eflag = '\\',
     208        nflag = 1,  /* 1 -- print '\n' */
     209    };
     210    arg = *++argv;
     211    if (!arg)
     212        goto newline_ret;
     213#else
     214    char nflag = 1;
     215    char eflag = 0;
     216
     217    while (1) {
     218        arg = *++argv;
     219        if (!arg)
     220            goto newline_ret;
     221        if (*arg != '-')
     222            break;
     223
     224        /* If it appears that we are handling options, then make sure
     225         * that all of the options specified are actually valid.
     226         * Otherwise, the string should just be echoed.
     227         */
     228        p = arg + 1;
     229        if (!*p)    /* A single '-', so echo it. */
     230            goto just_echo;
     231
     232        do {
     233            if (!strrchr("neE", *p))
     234                goto just_echo;
     235        } while (*++p);
     236
     237        /* All of the options in this arg are valid, so handle them. */
     238        p = arg + 1;
     239        do {
     240            if (*p == 'n')
     241                nflag = 0;
     242            if (*p == 'e')
     243                eflag = '\\';
     244        } while (*++p);
     245    }
     246 just_echo:
     247#endif
     248
     249    while (1) {
     250        /* arg is already == *argv and isn't NULL */
     251        int c;
     252
     253        cur_io->iov_base = p = arg;
     254
     255        if (!eflag) {
     256            /* optimization for very common case */
     257            p += strlen(arg);
     258        } else while ((c = *arg++)) {
     259            if (c == eflag) {   /* Check for escape seq. */
     260                if (*arg == 'c') {
     261                    /* '\c' means cancel newline and
     262                     * ignore all subsequent chars. */
     263                    cur_io->iov_len = p - (char*)cur_io->iov_base;
     264                    cur_io++;
     265                    goto ret;
     266                }
     267#if !ENABLE_FEATURE_FANCY_ECHO
     268                /* SUSv3 specifies that octal escapes must begin with '0'. */
     269                if ( (((unsigned char)*arg) - '1') >= 7)
     270#endif
     271                {
     272                    /* Since SUSv3 mandates a first digit of 0, 4-digit octals
     273                    * of the form \0### are accepted. */
     274                    if (*arg == '0' && ((unsigned char)(arg[1]) - '0') < 8) {
     275                        arg++;
     276                    }
     277                    /* bb_process_escape_sequence can handle nul correctly */
     278                    c = bb_process_escape_sequence( (void*) &arg);
     279                }
     280            }
     281            *p++ = c;
     282        }
     283
     284        arg = *++argv;
     285        if (arg)
     286            *p++ = ' ';
     287        cur_io->iov_len = p - (char*)cur_io->iov_base;
     288        cur_io++;
     289        if (!arg)
     290            break;
     291    }
     292
     293 newline_ret:
     294    if (nflag) {
     295        cur_io->iov_base = (char*)"\n";
     296        cur_io->iov_len = 1;
     297        cur_io++;
     298    }
     299 ret:
     300    /* TODO: implement and use full_writev? */
     301    return writev(1, io, (cur_io - io)) >= 0;
     302}
     303#endif
  • branches/2.2.9/mindi-busybox/coreutils/env.c

    r1765 r2725  
    44 *
    55 * Copyright (c) 1988, 1993, 1994
    6  *  The Regents of the University of California.  All rights reserved.
     6 * The Regents of the University of California.  All rights reserved.
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 *
    1010 * Original copyright notice is retained at the end of this file.
     
    3030 */
    3131
    32 #include <getopt.h> /* struct option */
    33 extern char **environ;
     32/* This is a NOEXEC applet. Be very careful! */
    3433
    3534#include "libbb.h"
     
    4241#endif
    4342
    44 int env_main(int argc, char** argv);
    45 int env_main(int argc, char** argv)
     43int env_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     44int env_main(int argc UNUSED_PARAM, char **argv)
    4645{
    47     /* cleanenv was static - why? */
    48     char *cleanenv[1];
    49     char **ep;
    50     unsigned opt;
     46    unsigned opts;
    5147    llist_t *unset_env = NULL;
    5248
     
    5551    applet_long_options = env_longopts;
    5652#endif
    57     opt = getopt32(argv, "+iu:", &unset_env);
     53    opts = getopt32(argv, "+iu:", &unset_env);
    5854    argv += optind;
    59     if (*argv && LONE_DASH(argv[0])) {
    60         opt |= 1;
     55    if (argv[0] && LONE_DASH(argv[0])) {
     56        opts |= 1;
    6157        ++argv;
    6258    }
    63     if (opt & 1) {
    64         cleanenv[0] = NULL;
    65         environ = cleanenv;
    66     } else {
    67         while (unset_env) {
    68             unsetenv(unset_env->data);
    69             unset_env = unset_env->link;
    70         }
     59    if (opts & 1) {
     60        clearenv();
     61    }
     62    while (unset_env) {
     63        char *var = llist_pop(&unset_env);
     64        /* This does not handle -uVAR=VAL
     65         * (coreutils _sets_ the variable in that case): */
     66        /*unsetenv(var);*/
     67        /* This does, but uses somewhan undocumented feature that
     68         * putenv("name_without_equal_sign") unsets the variable: */
     69        putenv(var);
    7170    }
    7271
     
    7877    }
    7978
    80     if (*argv) {
    81         BB_EXECVP(*argv, argv);
    82         /* SUSv3-mandated exit codes. */
    83         xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
    84         bb_perror_msg_and_die("%s", *argv);
     79    if (argv[0]) {
     80        BB_EXECVP_or_die(argv);
    8581    }
    8682
    87     for (ep = environ; *ep; ep++) {
    88         puts(*ep);
     83    if (environ) { /* clearenv() may set environ == NULL! */
     84        char **ep;
     85        for (ep = environ; *ep; ep++) {
     86            puts(*ep);
     87        }
    8988    }
    9089
    91     fflush_stdout_and_exit(0);
     90    fflush_stdout_and_exit(EXIT_SUCCESS);
    9291}
    9392
     
    105104 *    documentation and/or other materials provided with the distribution.
    106105 *
    107  * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
    108  *      ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
     106 * 3. BSD Advertising Clause omitted per the July 22, 1999 licensing change
     107 *    ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
    109108 *
    110109 * 4. Neither the name of the University nor the names of its contributors
     
    124123 * SUCH DAMAGE.
    125124 */
    126 
    127 
  • branches/2.2.9/mindi-busybox/coreutils/expand.c

    r1765 r2725  
    44 * Copyright (C) 89, 91, 1995-2006 Free Software Foundation, Inc.
    55 *
    6  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    77 *
    88 * David MacKenzie <djm@gnu.ai.mit.edu>
     
    2121 *  Caveat: this versions of expand and unexpand don't accept tab lists.
    2222 */
    23 
    2423#include "libbb.h"
     24#include "unicode.h"
    2525
    2626enum {
     
    3030};
    3131
    32 static void xputchar(char c)
    33 {
    34     if (putchar(c) < 0)
    35         bb_error_msg_and_die(bb_msg_write_error);
    36 }
    37 
    3832#if ENABLE_EXPAND
    3933static void expand(FILE *file, unsigned tab_size, unsigned opt)
    4034{
    4135    char *line;
    42     char *ptr;
    43     int convert;
    44     int pos;
    45 
    46     /* Increment tab_size by 1 locally.*/
    47     tab_size++;
    4836
    4937    while ((line = xmalloc_fgets(file)) != NULL) {
    50         convert = 1;
    51         pos = 0;
    52         ptr = line;
    53         while (*line) {
    54             pos++;
    55             if (*line == '\t' && convert) {
    56                 for (; pos < tab_size; pos++) {
    57                     xputchar(' ');
     38        unsigned char c;
     39        char *ptr;
     40        char *ptr_strbeg;
     41
     42        ptr = ptr_strbeg = line;
     43        while ((c = *ptr) != '\0') {
     44            if ((opt & OPT_INITIAL) && !isblank(c)) {
     45                /* not space or tab */
     46                break;
     47            }
     48            if (c == '\t') {
     49                unsigned len;
     50                *ptr = '\0';
     51# if ENABLE_UNICODE_SUPPORT
     52                {
     53                    uni_stat_t uni_stat;
     54                    printable_string(&uni_stat, ptr_strbeg);
     55                    len = uni_stat.unicode_width;
    5856                }
    59             } else {
    60                 if ((opt & OPT_INITIAL) && !isblank(*line)) {
    61                     convert = 0;
    62                 }
    63                 xputchar(*line);
    64             }
    65             if (pos == tab_size) {
    66                 pos = 0;
    67             }
    68             line++;
    69         }
    70         free(ptr);
     57# else
     58                len = ptr - ptr_strbeg;
     59# endif
     60                len = tab_size - (len % tab_size);
     61                /*while (ptr[1] == '\t') { ptr++; len += tab_size; } - can handle many tabs at once */
     62                printf("%s%*s", ptr_strbeg, len, "");
     63                ptr_strbeg = ptr + 1;
     64            }
     65            ptr++;
     66        }
     67        fputs(ptr_strbeg, stdout);
     68        free(line);
    7169    }
    7270}
     
    7472
    7573#if ENABLE_UNEXPAND
    76 static void unexpand(FILE *file, unsigned int tab_size, unsigned opt)
     74static void unexpand(FILE *file, unsigned tab_size, unsigned opt)
    7775{
    7876    char *line;
    79     char *ptr;
    80     int convert;
    81     int pos;
    82     int i = 0;
    83     int column = 0;
    8477
    8578    while ((line = xmalloc_fgets(file)) != NULL) {
    86         convert = 1;
    87         pos = 0;
    88         ptr = line;
    89         while (*line) {
    90             while ((*line == ' ' || *line == '\t') && convert) {
    91                 pos += (*line == ' ') ? 1 : tab_size;
    92                 line++;
    93                 column++;
    94                 if ((opt & OPT_ALL) && column == tab_size) {
    95                     column = 0;
    96                     goto put_tab;
    97                 }
    98             }
    99             if (pos) {
    100                 i = pos / tab_size;
    101                 if (i) {
    102                     for (; i > 0; i--) {
    103  put_tab:
    104                         xputchar('\t');
    105                     }
    106                 } else {
    107                     for (i = pos % tab_size; i > 0; i--) {
    108                         xputchar(' ');
    109                     }
    110                 }
    111                 pos = 0;
    112             } else {
    113                 if (opt & OPT_INITIAL) {
    114                     convert = 0;
    115                 }
    116                 if (opt & OPT_ALL) {
    117                     column++;
    118                 }
    119                 xputchar(*line);
    120                 line++;
    121             }
    122         }
    123         free(ptr);
     79        char *ptr = line;
     80        unsigned column = 0;
     81
     82        while (*ptr) {
     83            unsigned n;
     84            unsigned len = 0;
     85
     86            while (*ptr == ' ') {
     87                ptr++;
     88                len++;
     89            }
     90            column += len;
     91            if (*ptr == '\t') {
     92                column += tab_size - (column % tab_size);
     93                ptr++;
     94                continue;
     95            }
     96
     97            n = column / tab_size;
     98            if (n) {
     99                len = column = column % tab_size;
     100                while (n--)
     101                    putchar('\t');
     102            }
     103
     104            if ((opt & OPT_INITIAL) && ptr != line) {
     105                printf("%*s%s", len, "", ptr);
     106                break;
     107            }
     108            n = strcspn(ptr, "\t ");
     109            printf("%*s%.*s", len, "", n, ptr);
     110# if ENABLE_UNICODE_SUPPORT
     111            {
     112                char c;
     113                uni_stat_t uni_stat;
     114                c = ptr[n];
     115                ptr[n] = '\0';
     116                printable_string(&uni_stat, ptr);
     117                len = uni_stat.unicode_width;
     118                ptr[n] = c;
     119            }
     120# else
     121            len = n;
     122# endif
     123            ptr += n;
     124            column = (column + len) % tab_size;
     125        }
     126        free(line);
    124127    }
    125128}
    126129#endif
    127130
    128 int expand_main(int argc, char **argv);
    129 int expand_main(int argc, char **argv)
     131int expand_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     132int expand_main(int argc UNUSED_PARAM, char **argv)
    130133{
    131134    /* Default 8 spaces for 1 tab */
     
    151154    ;
    152155#endif
     156    init_unicode();
    153157
    154158    if (ENABLE_EXPAND && (!ENABLE_UNEXPAND || applet_name[0] == 'e')) {
    155         USE_FEATURE_EXPAND_LONG_OPTIONS(applet_long_options = expand_longopts);
     159        IF_FEATURE_EXPAND_LONG_OPTIONS(applet_long_options = expand_longopts);
    156160        opt = getopt32(argv, "it:", &opt_t);
    157     } else if (ENABLE_UNEXPAND) {
    158         USE_FEATURE_UNEXPAND_LONG_OPTIONS(applet_long_options = unexpand_longopts);
     161    } else {
     162        IF_FEATURE_UNEXPAND_LONG_OPTIONS(applet_long_options = unexpand_longopts);
    159163        /* -t NUM sets also -a */
    160164        opt_complementary = "ta";
     
    167171    argv += optind;
    168172
    169     /* If no args are given, read from stdin */
    170173    if (!*argv) {
    171174        *--argv = (char*)bb_msg_standard_input;
    172         goto use_stdin;
    173     }
    174 
     175    }
    175176    do {
    176         if (NOT_LONE_CHAR(*argv, '-')) {
    177             file = fopen_or_warn(*argv, "r");
    178             if (!file) {
    179                 exit_status = EXIT_FAILURE;
    180                 continue;
    181             }
    182         } else {
    183  use_stdin:
    184             file = stdin;
     177        file = fopen_or_warn_stdin(*argv);
     178        if (!file) {
     179            exit_status = EXIT_FAILURE;
     180            continue;
    185181        }
    186182
    187183        if (ENABLE_EXPAND && (!ENABLE_UNEXPAND || applet_name[0] == 'e'))
    188             USE_EXPAND(expand(file, tab_size, opt));
    189         else if (ENABLE_UNEXPAND)
    190             USE_UNEXPAND(unexpand(file, tab_size, opt));
     184            IF_EXPAND(expand(file, tab_size, opt));
     185        else
     186            IF_UNEXPAND(unexpand(file, tab_size, opt));
    191187
    192188        /* Check and close the file */
    193         /* We do want all of them to execute, thus | instead of || */
    194         if (ferror(file) | fclose_if_not_stdin(file)) {
    195             bb_perror_msg("%s", *argv);
     189        if (fclose_if_not_stdin(file)) {
     190            bb_simple_perror_msg(*argv);
    196191            exit_status = EXIT_FAILURE;
    197192        }
  • branches/2.2.9/mindi-busybox/coreutils/expr.c

    r1765 r2725  
    1212 *  - 64 math support
    1313 *
    14  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     14 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1515 */
    1616
     
    2929#include "xregex.h"
    3030
    31 /* The kinds of value we can have.  */
    32 enum valtype {
    33     integer,
    34     string
    35 };
    36 typedef enum valtype TYPE;
    37 
    3831#if ENABLE_EXPR_MATH_SUPPORT_64
    3932typedef int64_t arith_t;
     
    5245/* TODO: use bb_strtol[l]? It's easier to check for errors... */
    5346
     47/* The kinds of value we can have.  */
     48enum {
     49    INTEGER,
     50    STRING
     51};
     52
    5453/* A value is.... */
    5554struct valinfo {
    56     TYPE type;          /* Which kind. */
    57     union {             /* The value itself. */
     55    smallint type;                  /* Which kind. */
     56    union {                         /* The value itself. */
    5857        arith_t i;
    5958        char *s;
     
    6564struct globals {
    6665    char **args;
    67 };
     66} FIX_ALIASING;
    6867#define G (*(struct globals*)&bb_common_bufsiz1)
    6968
     
    7877    VALUE *v;
    7978
    80     v = xmalloc(sizeof(VALUE));
    81     v->type = integer;
     79    v = xzalloc(sizeof(VALUE));
     80    if (INTEGER) /* otherwise xzaaloc did it already */
     81        v->type = INTEGER;
    8282    v->u.i = i;
    8383    return v;
     
    9090    VALUE *v;
    9191
    92     v = xmalloc(sizeof(VALUE));
    93     v->type = string;
     92    v = xzalloc(sizeof(VALUE));
     93    if (STRING) /* otherwise xzaaloc did it already */
     94        v->type = STRING;
    9495    v->u.s = xstrdup(s);
    9596    return v;
     
    9899/* Free VALUE V, including structure components.  */
    99100
    100 static void freev(VALUE * v)
    101 {
    102     if (v->type == string)
     101static void freev(VALUE *v)
     102{
     103    if (v->type == STRING)
    103104        free(v->u.s);
    104105    free(v);
     
    107108/* Return nonzero if V is a null-string or zero-number.  */
    108109
    109 static int null(VALUE * v)
    110 {
    111     if (v->type == integer)
     110static int null(VALUE *v)
     111{
     112    if (v->type == INTEGER)
    112113        return v->u.i == 0;
    113     /* string: */
     114    /* STRING: */
    114115    return v->u.s[0] == '\0' || LONE_CHAR(v->u.s, '0');
    115116}
    116117
    117 /* Coerce V to a string value (can't fail).  */
    118 
    119 static void tostring(VALUE * v)
    120 {
    121     if (v->type == integer) {
     118/* Coerce V to a STRING value (can't fail).  */
     119
     120static void tostring(VALUE *v)
     121{
     122    if (v->type == INTEGER) {
    122123        v->u.s = xasprintf("%" PF_REZ "d", PF_REZ_TYPE v->u.i);
    123         v->type = string;
    124     }
    125 }
    126 
    127 /* Coerce V to an integer value.  Return 1 on success, 0 on failure.  */
    128 
    129 static bool toarith(VALUE * v)
    130 {
    131     if (v->type == string) {
     124        v->type = STRING;
     125    }
     126}
     127
     128/* Coerce V to an INTEGER value.  Return 1 on success, 0 on failure.  */
     129
     130static bool toarith(VALUE *v)
     131{
     132    if (v->type == STRING) {
    132133        arith_t i;
    133134        char *e;
     
    140141        free(v->u.s);
    141142        v->u.i = i;
    142         v->type = integer;
     143        v->type = INTEGER;
    143144    }
    144145    return 1;
    145146}
    146147
    147 /* Return nonzero if the next token matches STR exactly.
     148/* Return str[0]+str[1] if the next token matches STR exactly.
    148149   STR must not be NULL.  */
    149150
    150 static bool nextarg(const char *str)
    151 {
    152     if (*G.args == NULL)
     151static int nextarg(const char *str)
     152{
     153    if (*G.args == NULL || strcmp(*G.args, str) != 0)
    153154        return 0;
    154     return strcmp(*G.args, str) == 0;
     155    return (unsigned char)str[0] + (unsigned char)str[1];
    155156}
    156157
    157158/* The comparison operator handling functions.  */
    158159
    159 static int cmp_common(VALUE * l, VALUE * r, int op)
    160 {
    161     int cmpval;
    162 
    163     if (l->type == string || r->type == string) {
     160static int cmp_common(VALUE *l, VALUE *r, int op)
     161{
     162    arith_t ll, rr;
     163
     164    ll = l->u.i;
     165    rr = r->u.i;
     166    if (l->type == STRING || r->type == STRING) {
    164167        tostring(l);
    165168        tostring(r);
    166         cmpval = strcmp(l->u.s, r->u.s);
    167     } else
    168         cmpval = l->u.i - r->u.i;
     169        ll = strcmp(l->u.s, r->u.s);
     170        rr = 0;
     171    }
     172    /* calculating ll - rr and checking the result is prone to overflows.
     173     * We'll do it differently: */
    169174    if (op == '<')
    170         return cmpval < 0;
    171     if (op == ('L' + 'E'))
    172         return cmpval <= 0;
    173     if (op == '=')
    174         return cmpval == 0;
    175     if (op == '!')
    176         return cmpval != 0;
     175        return ll < rr;
     176    if (op == ('<' + '='))
     177        return ll <= rr;
     178    if (op == '=' || (op == '=' + '='))
     179        return ll == rr;
     180    if (op == '!' + '=')
     181        return ll != rr;
    177182    if (op == '>')
    178         return cmpval > 0;
     183        return ll > rr;
    179184    /* >= */
    180     return cmpval >= 0;
     185    return ll >= rr;
    181186}
    182187
    183188/* The arithmetic operator handling functions.  */
    184189
    185 static arith_t arithmetic_common(VALUE * l, VALUE * r, int op)
     190static arith_t arithmetic_common(VALUE *l, VALUE *r, int op)
    186191{
    187192    arith_t li, ri;
     
    191196    li = l->u.i;
    192197    ri = r->u.i;
    193     if ((op == '/' || op == '%') && ri == 0)
    194         bb_error_msg_and_die("division by zero");
    195198    if (op == '+')
    196199        return li + ri;
    197     else if (op == '-')
     200    if (op == '-')
    198201        return li - ri;
    199     else if (op == '*')
     202    if (op == '*')
    200203        return li * ri;
    201     else if (op == '/')
     204    if (ri == 0)
     205        bb_error_msg_and_die("division by zero");
     206    if (op == '/')
    202207        return li / ri;
    203     else
    204         return li % ri;
     208    return li % ri;
    205209}
    206210
     
    209213   PV is the VALUE for the rhs (the pattern).  */
    210214
    211 static VALUE *docolon(VALUE * sv, VALUE * pv)
    212 {
     215static VALUE *docolon(VALUE *sv, VALUE *pv)
     216{
     217    enum { NMATCH = 2 };
    213218    VALUE *v;
    214219    regex_t re_buffer;
    215     const int NMATCH = 2;
    216220    regmatch_t re_regs[NMATCH];
    217221
     
    220224
    221225    if (pv->u.s[0] == '^') {
    222         bb_error_msg("\
    223 warning: unportable BRE: `%s': using `^' as the first character\n\
    224 of a basic regular expression is not portable; it is being ignored", pv->u.s);
     226        bb_error_msg(
     227"warning: '%s': using '^' as the first character\n"
     228"of a basic regular expression is not portable; it is ignored", pv->u.s);
    225229    }
    226230
    227231    memset(&re_buffer, 0, sizeof(re_buffer));
    228     memset(re_regs, 0, sizeof(*re_regs));
     232    memset(re_regs, 0, sizeof(re_regs));
    229233    xregcomp(&re_buffer, pv->u.s, 0);
    230234
    231235    /* expr uses an anchored pattern match, so check that there was a
    232236     * match and that the match starts at offset 0. */
    233     if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH &&
    234         re_regs[0].rm_so == 0) {
     237    if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH
     238     && re_regs[0].rm_so == 0
     239    ) {
    235240        /* Were \(...\) used? */
    236         if (re_buffer.re_nsub > 0) {
     241        if (re_buffer.re_nsub > 0 && re_regs[1].rm_so >= 0) {
    237242            sv->u.s[re_regs[1].rm_eo] = '\0';
    238243            v = str_value(sv->u.s + re_regs[1].rm_so);
    239         } else
     244        } else {
    240245            v = int_value(re_regs[0].rm_eo);
     246        }
    241247    } else {
    242248        /* Match failed -- return the right kind of null.  */
     
    246252            v = int_value(0);
    247253    }
    248 //FIXME: sounds like here is a bit missing: regfree(&re_buffer);
     254    regfree(&re_buffer);
    249255    return v;
    250256}
     
    328334        else {
    329335            v = xmalloc(sizeof(VALUE));
    330             v->type = string;
     336            v->type = STRING;
    331337            v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
    332338        }
     
    336342    }
    337343    return v;
    338 
    339344}
    340345
     
    368373    l = eval5();
    369374    while (1) {
    370         if (nextarg("*"))
    371             op = '*';
    372         else if (nextarg("/"))
    373             op = '/';
    374         else if (nextarg("%"))
    375             op = '%';
    376         else
    377             return l;
     375        op = nextarg("*");
     376        if (!op) { op = nextarg("/");
     377         if (!op) { op = nextarg("%");
     378          if (!op) return l;
     379        }}
    378380        G.args++;
    379381        r = eval5();
     
    395397    l = eval4();
    396398    while (1) {
    397         if (nextarg("+"))
    398             op = '+';
    399         else if (nextarg("-"))
    400             op = '-';
    401         else
    402             return l;
     399        op = nextarg("+");
     400        if (!op) {
     401            op = nextarg("-");
     402            if (!op) return l;
     403        }
    403404        G.args++;
    404405        r = eval4();
     
    420421    l = eval3();
    421422    while (1) {
    422         if (nextarg("<"))
    423             op = '<';
    424         else if (nextarg("<="))
    425             op = 'L' + 'E';
    426         else if (nextarg("=") || nextarg("=="))
    427             op = '=';
    428         else if (nextarg("!="))
    429             op = '!';
    430         else if (nextarg(">="))
    431             op = 'G' + 'E';
    432         else if (nextarg(">"))
    433             op = '>';
    434         else
    435             return l;
     423        op = nextarg("<");
     424        if (!op) { op = nextarg("<=");
     425         if (!op) { op = nextarg("=");
     426          if (!op) { op = nextarg("==");
     427           if (!op) { op = nextarg("!=");
     428            if (!op) { op = nextarg(">=");
     429             if (!op) { op = nextarg(">");
     430              if (!op) return l;
     431        }}}}}}
    436432        G.args++;
    437433        r = eval3();
     
    484480}
    485481
    486 int expr_main(int argc, char **argv);
    487 int expr_main(int argc, char **argv)
     482int expr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     483int expr_main(int argc UNUSED_PARAM, char **argv)
    488484{
    489485    VALUE *v;
    490486
    491     if (argc == 1) {
     487    xfunc_error_retval = 2; /* coreutils compat */
     488    G.args = argv + 1;
     489    if (*G.args == NULL) {
    492490        bb_error_msg_and_die("too few arguments");
    493491    }
    494 
    495     G.args = argv + 1;
    496 
    497492    v = eval();
    498493    if (*G.args)
    499494        bb_error_msg_and_die("syntax error");
    500 
    501     if (v->type == integer)
     495    if (v->type == INTEGER)
    502496        printf("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i);
    503497    else
    504498        puts(v->u.s);
    505 
    506499    fflush_stdout_and_exit(null(v));
    507500}
  • branches/2.2.9/mindi-busybox/coreutils/false.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
    1010/* BB_AUDIT SUSv3 compliant */
    11 /* http://www.opengroup.org/onlinepubs/007904975/utilities/false.html */
     11/* http://www.opengroup.org/onlinepubs/000095399/utilities/false.html */
    1212
    1313#include "libbb.h"
     
    1515/* This is a NOFORK applet. Be very careful! */
    1616
    17 int false_main(int ATTRIBUTE_UNUSED argc, char ATTRIBUTE_UNUSED **argv);
    18 int false_main(int ATTRIBUTE_UNUSED argc, char ATTRIBUTE_UNUSED **argv)
     17int false_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     18int false_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
    1919{
    2020    return EXIT_FAILURE;
  • branches/2.2.9/mindi-busybox/coreutils/fold.c

    r1765 r2725  
    66
    77   Modified for busybox based on coreutils v 5.0
    8    Copyright (C) 2003 Glenn McGrath <bug1@iinet.net.au>
     8   Copyright (C) 2003 Glenn McGrath
    99
    10    Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     10   Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1111*/
     12#include "libbb.h"
     13#include "unicode.h"
    1214
    13 #include "libbb.h"
     15/* This is a NOEXEC applet. Be very careful! */
    1416
    15 static unsigned long flags;
    16 #define FLAG_COUNT_BYTES    1
    17 #define FLAG_BREAK_SPACES   2
    18 #define FLAG_WIDTH          4
     17/* Must match getopt32 call */
     18#define FLAG_COUNT_BYTES        1
     19#define FLAG_BREAK_SPACES       2
     20#define FLAG_WIDTH              4
    1921
    2022/* Assuming the current column is COLUMN, return the column that
    2123   printing C will move the cursor to.
    2224   The first column is 0. */
     25static int adjust_column(unsigned column, char c)
     26{
     27    if (option_mask32 & FLAG_COUNT_BYTES)
     28        return ++column;
    2329
    24 static int adjust_column(int column, char c)
    25 {
    26     if (!(flags & FLAG_COUNT_BYTES)) {
    27         if (c == '\b') {
    28             if (column > 0)
    29                 column--;
    30         } else if (c == '\r')
     30    if (c == '\t')
     31        return column + 8 - column % 8;
     32
     33    if (c == '\b') {
     34        if ((int)--column < 0)
    3135            column = 0;
    32         else if (c == '\t')
    33             column = column + 8 - column % 8;
    34         else            /* if (isprint (c)) */
     36    }
     37    else if (c == '\r')
     38        column = 0;
     39    else { /* just a printable char */
     40        if (unicode_status != UNICODE_ON /* every byte is a new char */
     41         || (c & 0xc0) != 0x80 /* it isn't a 2nd+ byte of a Unicode char */
     42        ) {
    3543            column++;
    36     } else
    37         column++;
     44        }
     45    }
    3846    return column;
    3947}
    4048
    41 int fold_main(int argc, char **argv);
    42 int fold_main(int argc, char **argv)
     49/* Note that this function can write NULs, unlike fputs etc. */
     50static void write2stdout(const void *buf, unsigned size)
     51{
     52    fwrite(buf, 1, size, stdout);
     53}
     54
     55int fold_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     56int fold_main(int argc UNUSED_PARAM, char **argv)
    4357{
    4458    char *line_out = NULL;
    45     int allocated_out = 0;
    46     char *w_opt;
    47     int width = 80;
    48     int i;
    49     int errs = 0;
     59    const char *w_opt = "80";
     60    unsigned width;
     61    smallint exitcode = EXIT_SUCCESS;
     62
     63    init_unicode();
    5064
    5165    if (ENABLE_INCLUDE_SUSv2) {
    5266        /* Turn any numeric options into -w options.  */
    53         for (i = 1; i < argc; i++) {
    54             char const *a = argv[i];
    55 
    56             if (*a++ == '-') {
    57                 if (*a == '-' && !a[1])
     67        int i;
     68        for (i = 1; argv[i]; i++) {
     69            const char *a = argv[i];
     70            if (*a == '-') {
     71                a++;
     72                if (*a == '-' && !a[1]) /* "--" */
    5873                    break;
    59                 if (isdigit(*a)) {
     74                if (isdigit(*a))
    6075                    argv[i] = xasprintf("-w%s", a);
    61                 }
    6276            }
    6377        }
    6478    }
    6579
    66     flags = getopt32(argv, "bsw:", &w_opt);
    67     if (flags & FLAG_WIDTH)
    68         width = xatoul_range(w_opt, 1, 10000);
     80    getopt32(argv, "bsw:", &w_opt);
     81    width = xatou_range(w_opt, 1, 10000);
    6982
    7083    argv += optind;
    71     if (!*argv) {
     84    if (!*argv)
    7285        *--argv = (char*)"-";
    73     }
    7486
    7587    do {
    7688        FILE *istream = fopen_or_warn_stdin(*argv);
    7789        int c;
    78         int column = 0;     /* Screen column where next char will go. */
    79         int offset_out = 0; /* Index in `line_out' for next char. */
     90        unsigned column = 0;     /* Screen column where next char will go */
     91        unsigned offset_out = 0; /* Index in 'line_out' for next char */
    8092
    8193        if (istream == NULL) {
    82             errs |= EXIT_FAILURE;
     94            exitcode = EXIT_FAILURE;
    8395            continue;
    8496        }
    8597
    8698        while ((c = getc(istream)) != EOF) {
    87             if (offset_out + 1 >= allocated_out) {
    88                 allocated_out += 1024;
    89                 line_out = xrealloc(line_out, allocated_out);
     99            /* We grow line_out in chunks of 0x1000 bytes */
     100            if ((offset_out & 0xfff) == 0) {
     101                line_out = xrealloc(line_out, offset_out + 0x1000);
    90102            }
    91 
     103 rescan:
     104            line_out[offset_out] = c;
    92105            if (c == '\n') {
    93                 line_out[offset_out++] = c;
    94                 fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
     106                write2stdout(line_out, offset_out + 1);
    95107                column = offset_out = 0;
    96108                continue;
    97109            }
    98  rescan:
    99110            column = adjust_column(column, c);
    100 
    101             if (column > width) {
    102                 /* This character would make the line too long.
    103                    Print the line plus a newline, and make this character
    104                    start the next line. */
    105                 if (flags & FLAG_BREAK_SPACES) {
    106                     /* Look for the last blank. */
    107                     int logical_end;
    108 
    109                     for (logical_end = offset_out - 1; logical_end >= 0; logical_end--) {
    110                         if (isblank(line_out[logical_end])) {
    111                             break;
    112                         }
    113                     }
    114                     if (logical_end >= 0) {
    115                         /* Found a blank.  Don't output the part after it. */
    116                         logical_end++;
    117                         fwrite(line_out, sizeof(char), (size_t) logical_end, stdout);
    118                         putchar('\n');
    119                         /* Move the remainder to the beginning of the next line.
    120                            The areas being copied here might overlap. */
    121                         memmove(line_out, line_out + logical_end, offset_out - logical_end);
    122                         offset_out -= logical_end;
    123                         for (column = i = 0; i < offset_out; i++) {
    124                             column = adjust_column(column, line_out[i]);
    125                         }
    126                         goto rescan;
    127                     }
    128                 } else {
    129                     if (offset_out == 0) {
    130                         line_out[offset_out++] = c;
    131                         continue;
    132                     }
    133                 }
    134                 line_out[offset_out++] = '\n';
    135                 fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
    136                 column = offset_out = 0;
    137                 goto rescan;
     111            if (column <= width || offset_out == 0) {
     112                /* offset_out == 0 case happens
     113                 * with small width (say, 1) and tabs.
     114                 * The very first tab already goes to column 8,
     115                 * but we must not wrap it */
     116                offset_out++;
     117                continue;
    138118            }
    139119
    140             line_out[offset_out++] = c;
     120            /* This character would make the line too long.
     121             * Print the line plus a newline, and make this character
     122             * start the next line */
     123            if (option_mask32 & FLAG_BREAK_SPACES) {
     124                unsigned i;
     125                unsigned logical_end;
     126
     127                /* Look for the last blank. */
     128                for (logical_end = offset_out - 1; (int)logical_end >= 0; logical_end--) {
     129                    if (!isblank(line_out[logical_end]))
     130                        continue;
     131
     132                    /* Found a space or tab.
     133                     * Output up to and including it, and start a new line */
     134                    logical_end++;
     135                    /*line_out[logical_end] = '\n'; - NO! this nukes one buffered character */
     136                    write2stdout(line_out, logical_end);
     137                    putchar('\n');
     138                    /* Move the remainder to the beginning of the next line.
     139                     * The areas being copied here might overlap. */
     140                    memmove(line_out, line_out + logical_end, offset_out - logical_end);
     141                    offset_out -= logical_end;
     142                    for (column = i = 0; i < offset_out; i++) {
     143                        column = adjust_column(column, line_out[i]);
     144                    }
     145                    goto rescan;
     146                }
     147                /* No blank found, wrap will split the overlong word */
     148            }
     149            /* Output what we accumulated up to now, and start a new line */
     150            line_out[offset_out] = '\n';
     151            write2stdout(line_out, offset_out + 1);
     152            column = offset_out = 0;
     153            goto rescan;
     154        } /* while (not EOF) */
     155
     156        if (offset_out) {
     157            write2stdout(line_out, offset_out);
    141158        }
    142159
    143         if (offset_out) {
    144             fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
    145         }
    146 
    147         if (ferror(istream) || fclose_if_not_stdin(istream)) {
    148             bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
    149             errs |= EXIT_FAILURE;
     160        if (fclose_if_not_stdin(istream)) {
     161            bb_simple_perror_msg(*argv);
     162            exitcode = EXIT_FAILURE;
    150163        }
    151164    } while (*++argv);
    152165
    153     fflush_stdout_and_exit(errs);
     166    fflush_stdout_and_exit(exitcode);
    154167}
  • branches/2.2.9/mindi-busybox/coreutils/head.c

    r1765 r2725  
    55 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1414#include "libbb.h"
    1515
     16/* This is a NOEXEC applet. Be very careful! */
     17
    1618static const char head_opts[] ALIGN1 =
    1719    "n:"
     
    2123    ;
    2224
    23 #if ENABLE_FEATURE_FANCY_HEAD
    2425static const struct suffix_mult head_suffixes[] = {
    2526    { "b", 512 },
    2627    { "k", 1024 },
    2728    { "m", 1024*1024 },
    28     { }
     29    { "", 0 }
    2930};
    30 #endif
    3131
    32 static const char header_fmt_str[] ALIGN1 = "\n==> %s <==\n";
     32#define header_fmt_str "\n==> %s <==\n"
    3333
    34 int head_main(int argc, char **argv);
     34int head_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    3535int head_main(int argc, char **argv)
    3636{
     
    4141    int header_threshhold = 1;
    4242#endif
    43 
    4443    FILE *fp;
    4544    const char *fmt;
     
    5150#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
    5251    /* Allow legacy syntax of an initial numeric option without -n. */
    53     if (argc > 1 && argv[1][0] == '-'
     52    if (argv[1] && argv[1][0] == '-'
    5453     && isdigit(argv[1][1])
    5554    ) {
     
    8079 GET_COUNT:
    8180#endif
    82 
    83 #if !ENABLE_FEATURE_FANCY_HEAD
    84             count = xatoul(p);
    85 #else
    8681            count = xatoul_sfx(p, head_suffixes);
    87 #endif
    8882            break;
    8983        default:
     
    9286    }
    9387
     88    argc -= optind;
    9489    argv += optind;
    95     if (!*argv) {
     90    if (!*argv)
    9691        *--argv = (char*)"-";
    97     }
    9892
    9993    fmt = header_fmt_str + 1;
    10094#if ENABLE_FEATURE_FANCY_HEAD
    101     if (argc - optind <= header_threshhold) {
     95    if (argc <= header_threshhold) {
    10296        header_threshhold = 0;
    10397    }
    10498#else
    105     if (argc <= optind + 1) {
    106         fmt += 11;
     99    if (argc <= 1) {
     100        fmt += 11; /* "" */
    107101    }
    108102    /* Now define some things here to avoid #ifdefs in the code below.
     
    129123            }
    130124            if (fclose_if_not_stdin(fp)) {
    131                 bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
     125                bb_simple_perror_msg(*argv);
    132126                retval = EXIT_FAILURE;
    133127            }
    134128            die_if_ferror_stdout();
     129        } else {
     130            retval = EXIT_FAILURE;
    135131        }
    136132        fmt = header_fmt_str;
  • branches/2.2.9/mindi-busybox/coreutils/hostid.c

    r1765 r2725  
    55 * Copyright (C) 2000  Edward Betts <edward@debian.org>.
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1414/* This is a NOFORK applet. Be very careful! */
    1515
    16 int hostid_main(int argc, char ATTRIBUTE_UNUSED **argv);
    17 int hostid_main(int argc, char ATTRIBUTE_UNUSED **argv)
     16int hostid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     17int hostid_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
    1818{
    19     if (argc > 1) {
     19    if (argv[1]) {
    2020        bb_show_usage();
    2121    }
     
    2323    printf("%lx\n", gethostid());
    2424
    25     return fflush(stdout);
     25    return fflush_all();
    2626}
  • branches/2.2.9/mindi-busybox/coreutils/id.c

    r1765 r2725  
    44 *
    55 * Copyright (C) 2000 by Randolph Chung <tausq@debian.org>
     6 * Copyright (C) 2008 by Tito Ragusa <farmatito@tiscali.it>
    67 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    89 */
    910
    10 /* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */
    11 /* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to
    12  * be more similar to GNU id.
     11/* BB_AUDIT SUSv3 compliant. */
     12/* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever
     13 * length and to be more similar to GNU id.
    1314 * -Z option support: by Yuichi Nakamura <ynakam@hitachisoft.jp>
     15 * Added -G option Tito Ragusa (C) 2008 for SUSv3.
    1416 */
    1517
    1618#include "libbb.h"
    1719
    18 #define PRINT_REAL        1
    19 #define NAME_NOT_NUMBER   2
    20 #define JUST_USER         4
    21 #define JUST_GROUP        8
    22 #if ENABLE_SELINUX
    23 #define JUST_CONTEXT     16
    24 #endif
    25 
    26 static int printf_full(unsigned int id, const char *arg, const char prefix)
    27 {
    28     const char *fmt = "%cid=%u";
    29     int status = EXIT_FAILURE;
    30 
    31     if (arg) {
    32         fmt = "%cid=%u(%s)";
    33         status = EXIT_SUCCESS;
    34     }
    35     printf(fmt, prefix, id, arg);
    36     return status;
    37 }
    38 
    39 int id_main(int argc, char **argv);
    40 int id_main(int argc, char **argv)
    41 {
    42     struct passwd *p;
    43     uid_t uid;
    44     gid_t gid;
    45     unsigned long flags;
    46     short status;
    47 #if ENABLE_SELINUX
    48     security_context_t scontext;
    49 #endif
    50     /* Don't allow -n -r -nr -ug -rug -nug -rnug */
     20/* This is a NOEXEC applet. Be very careful! */
     21
     22#if !ENABLE_USE_BB_PWD_GRP
     23#if defined(__UCLIBC_MAJOR__) && (__UCLIBC_MAJOR__ == 0)
     24#if (__UCLIBC_MINOR__ < 9) || (__UCLIBC_MINOR__ == 9 &&  __UCLIBC_SUBLEVEL__ < 30)
     25#error "Sorry, you need at least uClibc version 0.9.30 for id applet to build"
     26#endif
     27#endif
     28#endif
     29
     30enum {
     31    PRINT_REAL      = (1 << 0),
     32    NAME_NOT_NUMBER = (1 << 1),
     33    JUST_USER       = (1 << 2),
     34    JUST_GROUP      = (1 << 3),
     35    JUST_ALL_GROUPS = (1 << 4),
     36#if ENABLE_SELINUX
     37    JUST_CONTEXT    = (1 << 5),
     38#endif
     39};
     40
     41static int print_common(unsigned id, const char *name, const char *prefix)
     42{
     43    if (prefix) {
     44        printf("%s", prefix);
     45    }
     46    if (!(option_mask32 & NAME_NOT_NUMBER) || !name) {
     47        printf("%u", id);
     48    }
     49    if (!option_mask32 || (option_mask32 & NAME_NOT_NUMBER)) {
     50        if (name) {
     51            printf(option_mask32 ? "%s" : "(%s)", name);
     52        } else {
     53            /* Don't set error status flag in default mode */
     54            if (option_mask32) {
     55                if (ENABLE_DESKTOP)
     56                    bb_error_msg("unknown ID %u", id);
     57                return EXIT_FAILURE;
     58            }
     59        }
     60    }
     61    return EXIT_SUCCESS;
     62}
     63
     64static int print_group(gid_t id, const char *prefix)
     65{
     66    return print_common(id, gid2group(id), prefix);
     67}
     68
     69static int print_user(uid_t id, const char *prefix)
     70{
     71    return print_common(id, uid2uname(id), prefix);
     72}
     73
     74/* On error set *n < 0 and return >= 0
     75 * If *n is too small, update it and return < 0
     76 *  (ok to trash groups[] in both cases)
     77 * Otherwise fill in groups[] and return >= 0
     78 */
     79static int get_groups(const char *username, gid_t rgid, gid_t *groups, int *n)
     80{
     81    int m;
     82
     83    if (username) {
     84        /* If the user is a member of more than
     85         * *n groups, then -1 is returned. Otherwise >= 0.
     86         * (and no defined way of detecting errors?!) */
     87        m = getgrouplist(username, rgid, groups, n);
     88        /* I guess *n < 0 might indicate error. Anyway,
     89         * malloc'ing -1 bytes won't be good, so: */
     90        //if (*n < 0)
     91        //  return 0;
     92        //return m;
     93        //commented out here, happens below anyway
     94    } else {
     95        /* On error -1 is returned, which ends up in *n */
     96        int nn = getgroups(*n, groups);
     97        /* 0: nn <= *n, groups[] was big enough; -1 otherwise */
     98        m = - (nn > *n);
     99        *n = nn;
     100    }
     101    if (*n < 0)
     102        return 0; /* error, don't return < 0! */
     103    return m;
     104}
     105
     106int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     107int id_main(int argc UNUSED_PARAM, char **argv)
     108{
     109    uid_t ruid;
     110    gid_t rgid;
     111    uid_t euid;
     112    gid_t egid;
     113    unsigned opt;
     114    int i;
     115    int status = EXIT_SUCCESS;
     116    const char *prefix;
     117    const char *username;
     118#if ENABLE_SELINUX
     119    security_context_t scontext = NULL;
     120#endif
     121    /* Don't allow -n -r -nr -ug -rug -nug -rnug -uZ -gZ -GZ*/
    51122    /* Don't allow more than one username */
    52     opt_complementary = "?1:u--g:g--u:r?ug:n?ug" USE_SELINUX(":u--Z:Z--u:g--Z:Z--g");
    53     flags = getopt32(argv, "rnug" USE_SELINUX("Z"));
    54 
    55     /* This values could be overwritten later */
    56     uid = geteuid();
    57     gid = getegid();
    58     if (flags & PRINT_REAL) {
    59         uid = getuid();
    60         gid = getgid();
    61     }
    62 
    63     if (argv[optind]) {
    64         p = getpwnam(argv[optind]);
    65         /* xuname2uid is needed because it exits on failure */
    66         uid = xuname2uid(argv[optind]);
    67         gid = p->pw_gid;
    68         /* in this case PRINT_REAL is the same */
    69     }
    70 
    71     if (flags & (JUST_GROUP | JUST_USER USE_SELINUX(| JUST_CONTEXT))) {
    72         /* JUST_GROUP and JUST_USER are mutually exclusive */
    73         if (flags & NAME_NOT_NUMBER) {
    74             /* bb_getXXXid(-1) exit on failure, puts cannot segfault */
    75             puts((flags & JUST_USER) ? bb_getpwuid(NULL, -1, uid) : bb_getgrgid(NULL, -1, gid));
     123    opt_complementary = "?1:u--g:g--u:G--u:u--G:g--G:G--g:r?ugG:n?ugG"
     124             IF_SELINUX(":u--Z:Z--u:g--Z:Z--g:G--Z:Z--G");
     125    opt = getopt32(argv, "rnugG" IF_SELINUX("Z"));
     126
     127    username = argv[optind];
     128    if (username) {
     129        struct passwd *p = xgetpwnam(username);
     130        euid = ruid = p->pw_uid;
     131        egid = rgid = p->pw_gid;
     132    } else {
     133        egid = getegid();
     134        rgid = getgid();
     135        euid = geteuid();
     136        ruid = getuid();
     137    }
     138    /* JUST_ALL_GROUPS ignores -r PRINT_REAL flag even if man page for */
     139    /* id says: print the real ID instead of the effective ID, with -ugG */
     140    /* in fact in this case egid is always printed if egid != rgid */
     141    if (!opt || (opt & JUST_ALL_GROUPS)) {
     142        gid_t *groups;
     143        int n;
     144
     145        if (!opt) {
     146            /* Default Mode */
     147            status |= print_user(ruid, "uid=");
     148            status |= print_group(rgid, " gid=");
     149            if (euid != ruid)
     150                status |= print_user(euid, " euid=");
     151            if (egid != rgid)
     152                status |= print_group(egid, " egid=");
    76153        } else {
    77             if (flags & JUST_USER) {
    78                 printf("%u\n", uid);
     154            /* JUST_ALL_GROUPS */
     155            status |= print_group(rgid, NULL);
     156            if (egid != rgid)
     157                status |= print_group(egid, " ");
     158        }
     159        /* We are supplying largish buffer, trying
     160         * to not run get_groups() twice. That might be slow
     161         * ("user database in remote SQL server" case) */
     162        groups = xmalloc(64 * sizeof(gid_t));
     163        n = 64;
     164        if (get_groups(username, rgid, groups, &n) < 0) {
     165            /* Need bigger buffer after all */
     166            groups = xrealloc(groups, n * sizeof(gid_t));
     167            get_groups(username, rgid, groups, &n);
     168        }
     169        if (n > 0) {
     170            /* Print the list */
     171            prefix = " groups=";
     172            for (i = 0; i < n; i++) {
     173                if (opt && (groups[i] == rgid || groups[i] == egid))
     174                    continue;
     175                status |= print_group(groups[i], opt ? " " : prefix);
     176                prefix = ",";
    79177            }
    80             if (flags & JUST_GROUP) {
    81                 printf("%u\n", gid);
    82             }
    83         }
    84 
    85 #if ENABLE_SELINUX
    86         if (flags & JUST_CONTEXT) {
    87             selinux_or_die();
    88             if (argc - optind == 1) {
    89                 bb_error_msg_and_die("user name can't be passed with -Z");
    90             }
    91 
    92             if (getcon(&scontext)) {
    93                 bb_error_msg_and_die("can't get process context");
    94             }
    95             printf("%s\n", scontext);
    96         }
    97 #endif
    98         /* exit */
    99         fflush_stdout_and_exit(EXIT_SUCCESS);
    100     }
    101 
    102     /* Print full info like GNU id */
    103     /* bb_getpwuid(0) doesn't exit on failure (returns NULL) */
    104     status = printf_full(uid, bb_getpwuid(NULL, 0, uid), 'u');
    105     putchar(' ');
    106     status |= printf_full(gid, bb_getgrgid(NULL, 0, gid), 'g');
    107 
    108 #if ENABLE_SELINUX
    109     if (is_selinux_enabled()) {
    110         security_context_t mysid;
    111         const char *context;
    112 
    113         context = "unknown";
    114         getcon(&mysid);
    115         if (mysid) {
    116             context = alloca(strlen(mysid) + 1);
    117             strcpy((char*)context, mysid);
    118             freecon(mysid);
    119         }
    120         printf(" context=%s", context);
    121     }
    122 #endif
    123 
    124     putchar('\n');
     178        } else if (n < 0) { /* error in get_groups() */
     179            if (!ENABLE_DESKTOP)
     180                bb_error_msg_and_die("can't get groups");
     181            else
     182                return EXIT_FAILURE;
     183        }
     184        if (ENABLE_FEATURE_CLEAN_UP)
     185            free(groups);
     186#if ENABLE_SELINUX
     187        if (is_selinux_enabled()) {
     188            if (getcon(&scontext) == 0)
     189                printf(" context=%s", scontext);
     190        }
     191#endif
     192    } else if (opt & PRINT_REAL) {
     193        euid = ruid;
     194        egid = rgid;
     195    }
     196
     197    if (opt & JUST_USER)
     198        status |= print_user(euid, NULL);
     199    else if (opt & JUST_GROUP)
     200        status |= print_group(egid, NULL);
     201#if ENABLE_SELINUX
     202    else if (opt & JUST_CONTEXT) {
     203        selinux_or_die();
     204        if (username || getcon(&scontext)) {
     205            bb_error_msg_and_die("can't get process context%s",
     206                username ? " for a different user" : "");
     207        }
     208        fputs(scontext, stdout);
     209    }
     210    /* freecon(NULL) seems to be harmless */
     211    if (ENABLE_FEATURE_CLEAN_UP)
     212        freecon(scontext);
     213#endif
     214    bb_putchar('\n');
    125215    fflush_stdout_and_exit(status);
    126216}
  • branches/2.2.9/mindi-busybox/coreutils/install.c

    r1765 r2725  
    44 * SELinux support: by Yuichi Nakamura <ynakam@hitachisoft.jp>
    55 *
    6  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
    7  *
    8  * TODO: -d option, need a way of recursively making directories and changing
    9  *           owner/group, will probably modify bb_make_directory(...)
     6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    107 */
    11 
    12 #include <libgen.h>
    13 #include <getopt.h> /* struct option */
    148
    159#include "libbb.h"
     
    2115    "preserve-timestamps\0" No_argument       "p"
    2216    "strip\0"               No_argument       "s"
    23     "group\0"               No_argument      "g"
    24     "mode\0"                No_argument      "m"
    25     "owner\0"               No_argument      "o"
     17    "group\0"               Required_argument "g"
     18    "mode\0"                Required_argument "m"
     19    "owner\0"               Required_argument "o"
    2620/* autofs build insists of using -b --suffix=.orig */
    2721/* TODO? (short option for --suffix is -S) */
     
    5751    if (lsetfilecon(path, scontext) < 0) {
    5852        if (errno != ENOTSUP) {
    59             bb_perror_msg("warning: failed to change context of %s to %s", path, scontext);
     53            bb_perror_msg("warning: can't change context"
     54                    " of %s to %s", path, scontext);
    6055        }
    6156    }
     
    6762#endif
    6863
    69 int install_main(int argc, char **argv);
     64int install_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    7065int install_main(int argc, char **argv)
    7166{
     
    7974    const char *mode_str;
    8075    int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE;
    81     int flags;
     76    int opts;
     77    int min_args = 1;
    8278    int ret = EXIT_SUCCESS;
    83     int isdir;
     79    int isdir = 0;
    8480#if ENABLE_SELINUX
    8581    security_context_t scontext;
     
    9086        OPT_v             = 1 << 1,
    9187        OPT_b             = 1 << 2,
    92         OPT_DIRECTORY     = 1 << 3,
    93         OPT_PRESERVE_TIME = 1 << 4,
    94         OPT_STRIP         = 1 << 5,
    95         OPT_GROUP         = 1 << 6,
    96         OPT_MODE          = 1 << 7,
    97         OPT_OWNER         = 1 << 8,
    98 #if ENABLE_SELINUX
    99         OPT_SET_SECURITY_CONTEXT = 1 << 9,
    100         OPT_PRESERVE_SECURITY_CONTEXT = 1 << 10,
     88        OPT_MKDIR_LEADING = 1 << 3,
     89        OPT_DIRECTORY     = 1 << 4,
     90        OPT_PRESERVE_TIME = 1 << 5,
     91        OPT_STRIP         = 1 << 6,
     92        OPT_GROUP         = 1 << 7,
     93        OPT_MODE          = 1 << 8,
     94        OPT_OWNER         = 1 << 9,
     95#if ENABLE_SELINUX
     96        OPT_SET_SECURITY_CONTEXT = 1 << 10,
     97        OPT_PRESERVE_SECURITY_CONTEXT = 1 << 11,
    10198#endif
    10299    };
     
    105102    applet_long_options = install_longopts;
    106103#endif
    107     opt_complementary = "s--d:d--s" USE_SELINUX(":Z--\xff:\xff--Z");
     104    opt_complementary = "s--d:d--s" IF_FEATURE_INSTALL_LONG_OPTIONS(IF_SELINUX(":Z--\xff:\xff--Z"));
    108105    /* -c exists for backwards compatibility, it's needed */
    109106    /* -v is ignored ("print name of each created directory") */
    110107    /* -b is ignored ("make a backup of each existing destination file") */
    111     flags = getopt32(argv, "cvb" "dpsg:m:o:" USE_SELINUX("Z:"),
    112             &gid_str, &mode_str, &uid_str USE_SELINUX(, &scontext));
     108    opts = getopt32(argv, "cvb" "Ddpsg:m:o:" IF_SELINUX("Z:"),
     109            &gid_str, &mode_str, &uid_str IF_SELINUX(, &scontext));
    113110    argc -= optind;
    114111    argv += optind;
    115112
    116113#if ENABLE_SELINUX
    117     if (flags & (OPT_PRESERVE_SECURITY_CONTEXT|OPT_SET_SECURITY_CONTEXT)) {
     114    if (opts & (OPT_PRESERVE_SECURITY_CONTEXT|OPT_SET_SECURITY_CONTEXT)) {
    118115        selinux_or_die();
    119116        use_default_selinux_context = 0;
    120         if (flags & OPT_PRESERVE_SECURITY_CONTEXT) {
     117        if (opts & OPT_PRESERVE_SECURITY_CONTEXT) {
    121118            copy_flags |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
    122119        }
    123         if (flags & OPT_SET_SECURITY_CONTEXT) {
     120        if (opts & OPT_SET_SECURITY_CONTEXT) {
    124121            setfscreatecon_or_die(scontext);
    125122            copy_flags |= FILEUTILS_SET_SECURITY_CONTEXT;
     
    128125#endif
    129126
    130     /* preserve access and modification time, this is GNU behaviour, BSD only preserves modification time */
    131     if (flags & OPT_PRESERVE_TIME) {
     127    /* preserve access and modification time, this is GNU behaviour,
     128     * BSD only preserves modification time */
     129    if (opts & OPT_PRESERVE_TIME) {
    132130        copy_flags |= FILEUTILS_PRESERVE_STATUS;
    133131    }
    134     mode = 0666;
    135     if (flags & OPT_MODE)
     132    mode = 0755; /* GNU coreutils 6.10 compat */
     133    if (opts & OPT_MODE)
    136134        bb_parse_mode(mode_str, &mode);
    137     uid = (flags & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid();
    138     gid = (flags & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid();
    139     if (flags & (OPT_OWNER|OPT_GROUP))
    140         umask(0);
    141 
    142     /* Create directories
    143      * don't use bb_make_directory() as it can't change uid or gid
    144      * perhaps bb_make_directory() should be improved.
    145      */
    146     if (flags & OPT_DIRECTORY) {
    147         while ((arg = *argv++) != NULL) {
    148             char *slash = arg;
    149             while (1) {
    150                 slash = strchr(slash + 1, '/');
    151                 if (slash)
    152                     *slash = '\0';
    153                 if (mkdir(arg, mode | 0111) == -1) {
    154                     if (errno != EEXIST) {
    155                         bb_perror_msg("cannot create %s", arg);
    156                         ret = EXIT_FAILURE;
    157                         break;
    158                     }
    159                 } /* dir was created, chown? */
    160                 else if ((flags & (OPT_OWNER|OPT_GROUP))
    161                  && lchown(arg, uid, gid) == -1
    162                 ) {
    163                     bb_perror_msg("cannot change ownership of %s", arg);
    164                     ret = EXIT_FAILURE;
    165                     break;
    166                 }
    167                 if (!slash)
    168                     break;
    169                 *slash = '/';
    170             }
    171         }
    172         return ret;
    173     }
    174 
    175     if (argc < 2)
     135    uid = (opts & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid();
     136    gid = (opts & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid();
     137
     138    last = argv[argc - 1];
     139    if (!(opts & OPT_DIRECTORY)) {
     140        argv[argc - 1] = NULL;
     141        min_args++;
     142
     143        /* coreutils install resolves link in this case, don't use lstat */
     144        isdir = stat(last, &statbuf) < 0 ? 0 : S_ISDIR(statbuf.st_mode);
     145    }
     146
     147    if (argc < min_args)
    176148        bb_show_usage();
    177 
    178     last = argv[argc - 1];
    179     argv[argc - 1] = NULL;
    180     /* coreutils install resolves link in this case, don't use lstat */
    181     isdir = stat(last, &statbuf) < 0 ? 0 : S_ISDIR(statbuf.st_mode);
    182149
    183150    while ((arg = *argv++) != NULL) {
    184151        char *dest = last;
    185         if (isdir)
    186             dest = concat_path_file(last, basename(arg));
    187         if (copy_file(arg, dest, copy_flags)) {
    188             /* copy is not made */
    189             ret = EXIT_FAILURE;
    190             goto next;
    191         }
    192 
    193         /* Set the file mode */
    194         if ((flags & OPT_MODE) && chmod(dest, mode) == -1) {
    195             bb_perror_msg("cannot change permissions of %s", dest);
     152        if (opts & OPT_DIRECTORY) {
     153            dest = arg;
     154            /* GNU coreutils 6.9 does not set uid:gid
     155             * on intermediate created directories
     156             * (only on last one) */
     157            if (bb_make_directory(dest, 0755, FILEUTILS_RECUR)) {
     158                ret = EXIT_FAILURE;
     159                goto next;
     160            }
     161        } else {
     162            if (opts & OPT_MKDIR_LEADING) {
     163                char *ddir = xstrdup(dest);
     164                bb_make_directory(dirname(ddir), 0755, FILEUTILS_RECUR);
     165                /* errors are not checked. copy_file
     166                 * will fail if dir is not created. */
     167                free(ddir);
     168            }
     169            if (isdir)
     170                dest = concat_path_file(last, bb_basename(arg));
     171            if (copy_file(arg, dest, copy_flags) != 0) {
     172                /* copy is not made */
     173                ret = EXIT_FAILURE;
     174                goto next;
     175            }
     176            if (opts & OPT_STRIP) {
     177                char *args[4];
     178                args[0] = (char*)"strip";
     179                args[1] = (char*)"-p"; /* -p --preserve-dates */
     180                args[2] = dest;
     181                args[3] = NULL;
     182                if (spawn_and_wait(args)) {
     183                    bb_perror_msg("strip");
     184                    ret = EXIT_FAILURE;
     185                }
     186            }
     187        }
     188
     189        /* Set the file mode (always, not only with -m).
     190         * GNU coreutils 6.10 is not affected by umask. */
     191        if (chmod(dest, mode) == -1) {
     192            bb_perror_msg("can't change %s of %s", "permissions", dest);
    196193            ret = EXIT_FAILURE;
    197194        }
     
    201198#endif
    202199        /* Set the user and group id */
    203         if ((flags & (OPT_OWNER|OPT_GROUP))
     200        if ((opts & (OPT_OWNER|OPT_GROUP))
    204201         && lchown(dest, uid, gid) == -1
    205202        ) {
    206             bb_perror_msg("cannot change ownership of %s", dest);
     203            bb_perror_msg("can't change %s of %s", "ownership", dest);
    207204            ret = EXIT_FAILURE;
    208         }
    209         if (flags & OPT_STRIP) {
    210             char *args[3];
    211             args[0] = (char*)"strip";
    212             args[1] = dest;
    213             args[2] = NULL;
    214             if (spawn_and_wait(args)) {
    215                 bb_perror_msg("strip");
    216                 ret = EXIT_FAILURE;
    217             }
    218205        }
    219206 next:
  • branches/2.2.9/mindi-busybox/coreutils/length.c

    r1765 r2725  
    11/* vi: set sw=4 ts=4: */
     2/*
     3 * Licensed under GPLv2, see file LICENSE in this source tree.
     4 */
    25
    36/* BB_AUDIT SUSv3 N/A -- Apparently a busybox (obsolete?) extension. */
     
    710/* This is a NOFORK applet. Be very careful! */
    811
    9 int length_main(int argc, char **argv);
     12int length_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    1013int length_main(int argc, char **argv)
    1114{
     
    1619    printf("%u\n", (unsigned)strlen(*argv));
    1720
    18     return fflush(stdout);
     21    return fflush_all();
    1922}
  • branches/2.2.9/mindi-busybox/coreutils/libcoreutils/Kbuild

    r1765 r2725  
     1# DO NOT EDIT. This file is generated from Kbuild.src
    12# Makefile for busybox
    23#
    34# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    45#
    5 # Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     6# Licensed under GPLv2 or later, see file LICENSE in this source tree.
    67
    78lib-y:=
     9
     10
    811lib-$(CONFIG_MKFIFO)    += getopt_mk_fifo_nod.o
    912lib-$(CONFIG_MKNOD) += getopt_mk_fifo_nod.o
  • branches/2.2.9/mindi-busybox/coreutils/libcoreutils/coreutils.h

    r1765 r2725  
    11/* vi: set sw=4 ts=4: */
    22/*
    3  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    44 */
    55
    66#ifndef COREUTILS_H
    7 #define COREUTILS_H     1
     7#define COREUTILS_H 1
     8
     9PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
    810
    911typedef int (*stat_func)(const char *fn, struct stat *ps);
    1012
    11 int cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf);
    12 int cp_mv_stat(const char *fn, struct stat *fn_stat);
     13int cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf) FAST_FUNC;
     14int cp_mv_stat(const char *fn, struct stat *fn_stat) FAST_FUNC;
    1315
    14 mode_t getopt_mk_fifo_nod(int argc, char **argv);
     16mode_t getopt_mk_fifo_nod(char **argv) FAST_FUNC;
     17
     18POP_SAVED_FUNCTION_VISIBILITY
    1519
    1620#endif
  • branches/2.2.9/mindi-busybox/coreutils/libcoreutils/cp_mv_stat.c

    r1765 r2725  
    2424#include "coreutils.h"
    2525
    26 int cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf)
     26int FAST_FUNC cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf)
    2727{
    2828    if (sf(fn, fn_stat) < 0) {
    2929        if (errno != ENOENT) {
    30             bb_perror_msg("cannot stat '%s'", fn);
     30#if ENABLE_FEATURE_VERBOSE_CP_MESSAGE
     31            if (errno == ENOTDIR) {
     32                bb_error_msg("can't stat '%s': Path has non-directory component", fn);
     33                return -1;
     34            }
     35#endif
     36            bb_perror_msg("can't stat '%s'", fn);
    3137            return -1;
    3238        }
    3339        return 0;
    34     } else if (S_ISDIR(fn_stat->st_mode)) {
     40    }
     41    if (S_ISDIR(fn_stat->st_mode)) {
    3542        return 3;
    3643    }
     
    3845}
    3946
    40 int cp_mv_stat(const char *fn, struct stat *fn_stat)
     47int FAST_FUNC cp_mv_stat(const char *fn, struct stat *fn_stat)
    4148{
    4249    return cp_mv_stat2(fn, fn_stat, stat);
  • branches/2.2.9/mindi-busybox/coreutils/libcoreutils/getopt_mk_fifo_nod.c

    r1765 r2725  
    2424#include "coreutils.h"
    2525
    26 mode_t getopt_mk_fifo_nod(int argc, char **argv)
     26mode_t FAST_FUNC getopt_mk_fifo_nod(char **argv)
    2727{
    2828    mode_t mode = 0666;
     
    3232#endif
    3333    int opt;
    34     opt = getopt32(argv, "m:" USE_SELINUX("Z:"), &smode USE_SELINUX(,&scontext));
     34    opt = getopt32(argv, "m:" IF_SELINUX("Z:"), &smode IF_SELINUX(,&scontext));
    3535    if (opt & 1) {
    3636        if (bb_parse_mode(smode, &mode))
  • branches/2.2.9/mindi-busybox/coreutils/ln.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    2323#define LN_SUFFIX           16
    2424
    25 int ln_main(int argc, char **argv);
     25int ln_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    2626int ln_main(int argc, char **argv)
    2727{
    2828    int status = EXIT_SUCCESS;
    29     int flag;
     29    int opts;
    3030    char *last;
    3131    char *src_name;
     
    3535    int (*link_func)(const char *, const char *);
    3636
    37     flag = getopt32(argv, "sfnbS:", &suffix);
    38 
    39     if (argc == optind) {
    40         bb_show_usage();
    41     }
     37    opt_complementary = "-1"; /* min one arg */
     38    opts = getopt32(argv, "sfnbS:", &suffix);
    4239
    4340    last = argv[argc - 1];
     
    4643    if (argc == optind + 1) {
    4744        *--argv = last;
    48         last = bb_get_last_path_component(xstrdup(last));
     45        last = bb_get_last_path_component_strip(xstrdup(last));
    4946    }
    5047
     
    5451
    5552        if (is_directory(src,
    56                         (flag & LN_NODEREFERENCE) ^ LN_NODEREFERENCE,
     53                        (opts & LN_NODEREFERENCE) ^ LN_NODEREFERENCE,
    5754                        NULL)
    5855        ) {
    5956            src_name = xstrdup(*argv);
    60             src = concat_path_file(src, bb_get_last_path_component(src_name));
     57            src = concat_path_file(src, bb_get_last_path_component_strip(src_name));
    6158            free(src_name);
    6259            src_name = src;
    6360        }
    64         if (!(flag & LN_SYMLINK) && stat(*argv, &statbuf)) {
     61        if (!(opts & LN_SYMLINK) && stat(*argv, &statbuf)) {
    6562            // coreutils: "ln dangling_symlink new_hardlink" works
    6663            if (lstat(*argv, &statbuf) || !S_ISLNK(statbuf.st_mode)) {
    67                 bb_perror_msg("%s", *argv);
     64                bb_simple_perror_msg(*argv);
    6865                status = EXIT_FAILURE;
    6966                free(src_name);
     
    7269        }
    7370
    74         if (flag & LN_BACKUP) {
     71        if (opts & LN_BACKUP) {
    7572            char *backup;
    7673            backup = xasprintf("%s%s", src, suffix);
    7774            if (rename(src, backup) < 0 && errno != ENOENT) {
    78                 bb_perror_msg("%s", src);
     75                bb_simple_perror_msg(src);
    7976                status = EXIT_FAILURE;
    8077                free(backup);
     
    8885             */
    8986            unlink(src);
    90         } else if (flag & LN_FORCE) {
     87        } else if (opts & LN_FORCE) {
    9188            unlink(src);
    9289        }
    9390
    9491        link_func = link;
    95         if (flag & LN_SYMLINK) {
     92        if (opts & LN_SYMLINK) {
    9693            link_func = symlink;
    9794        }
    9895
    9996        if (link_func(*argv, src) != 0) {
    100             bb_perror_msg("%s", src);
     97            bb_simple_perror_msg(src);
    10198            status = EXIT_FAILURE;
    10299        }
  • branches/2.2.9/mindi-busybox/coreutils/logname.c

    r1765 r2725  
    55 * Copyright (C) 2000  Edward Betts <edward@debian.org>.
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    2525/* This is a NOFORK applet. Be very careful! */
    2626
    27 int logname_main(int argc, char ATTRIBUTE_UNUSED **argv);
    28 int logname_main(int argc, char ATTRIBUTE_UNUSED **argv)
     27int logname_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     28int logname_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
    2929{
    30     char buf[128];
     30    char buf[64];
    3131
    32     if (argc > 1) {
     32    if (argv[1]) {
    3333        bb_show_usage();
    3434    }
     
    3737    if (getlogin_r(buf, sizeof(buf)) == 0) {
    3838        puts(buf);
    39         return fflush(stdout);
     39        return fflush_all();
    4040    }
    4141
  • branches/2.2.9/mindi-busybox/coreutils/ls.c

    r1765 r2725  
    44 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com>
    55 *
    6  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    77 */
    88
    9 /*
     9/* [date unknown. Perhaps before year 2000]
    1010 * To achieve a small memory footprint, this version of 'ls' doesn't do any
    1111 * file sorting, and only has the most essential command line switches
     
    1818 *
    1919 * KNOWN BUGS:
    20  * 1. ls -l of a directory doesn't give "total <blocks>" header
    21  * 2. ls of a symlink to a directory doesn't list directory contents
    22  * 3. hidden files can make column width too large
     20 * 1. hidden files can make column width too large
    2321 *
    2422 * NON-OPTIMAL BEHAVIOUR:
     
    2826 * PORTABILITY:
    2927 * 1. requires lstat (BSD) - how do you do it without?
     28 *
     29 * [2009-03]
     30 * ls sorts listing now, and supports almost all options.
    3031 */
    31 
    32 #include <getopt.h>
    3332#include "libbb.h"
     33#include "unicode.h"
     34
    3435
    3536/* This is a NOEXEC applet. Be very careful! */
    3637
    3738
     39#if ENABLE_FTPD
     40/* ftpd uses ls, and without timestamps Mozilla won't understand
     41 * ftpd's LIST output.
     42 */
     43# undef CONFIG_FEATURE_LS_TIMESTAMPS
     44# undef ENABLE_FEATURE_LS_TIMESTAMPS
     45# undef IF_FEATURE_LS_TIMESTAMPS
     46# undef IF_NOT_FEATURE_LS_TIMESTAMPS
     47# define CONFIG_FEATURE_LS_TIMESTAMPS 1
     48# define ENABLE_FEATURE_LS_TIMESTAMPS 1
     49# define IF_FEATURE_LS_TIMESTAMPS(...) __VA_ARGS__
     50# define IF_NOT_FEATURE_LS_TIMESTAMPS(...)
     51#endif
     52
     53
    3854enum {
    39 
    4055TERMINAL_WIDTH  = 80,           /* use 79 if terminal has linefold bug */
    4156COLUMN_GAP      = 2,            /* includes the file type char */
     
    5772LIST_CONTEXT    = 1 << 6,
    5873LIST_SIZE       = 1 << 7,
    59 LIST_DEV        = 1 << 8,
     74//LIST_DEV        = 1 << 8, - unused, synonym to LIST_SIZE
    6075LIST_DATE_TIME  = 1 << 9,
    6176LIST_FULLTIME   = 1 << 10,
     
    105120SPLIT_FILE      = 0,
    106121SPLIT_SUBDIR    = 2,
    107 
    108122};
    109123
    110 #define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
    111 #define TYPECHAR(mode)  ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
    112 #define APPCHAR(mode)   ("\0|\0\0/\0\0\0\0\0@\0=\0\0\0" [TYPEINDEX(mode)])
    113 #define COLOR(mode) ("\000\043\043\043\042\000\043\043"\
    114              "\000\000\044\000\043\000\000\040" [TYPEINDEX(mode)])
    115 #define ATTR(mode)  ("\00\00\01\00\01\00\01\00"\
    116              "\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)])
    117 
    118 /* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */
    119 #if ENABLE_FEATURE_LS_COLOR
    120 static smallint show_color;
    121 /* long option entry used only for --color, which has no short option
    122  * equivalent */
    123 static const char ls_color_opt[] ALIGN1 =
    124     "color\0" Optional_argument "\xff" /* no short equivalent */
     124/* "[-]Cadil1", POSIX mandated options, busybox always supports */
     125/* "[-]gnsx", POSIX non-mandated options, busybox always supports */
     126/* "[-]Q" GNU option? busybox always supports */
     127/* "[-]Ak" GNU options, busybox always supports */
     128/* "[-]FLRctur", POSIX mandated options, busybox optionally supports */
     129/* "[-]p", POSIX non-mandated options, busybox optionally supports */
     130/* "[-]SXvThw", GNU options, busybox optionally supports */
     131/* "[-]K", SELinux mandated options, busybox optionally supports */
     132/* "[-]e", I think we made this one up */
     133static const char ls_options[] ALIGN1 =
     134    "Cadil1gnsxQAk" /* 13 opts, total 13 */
     135    IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */
     136    IF_FEATURE_LS_SORTFILES("SXrv")  /* 4, 21 */
     137    IF_FEATURE_LS_FILETYPES("Fp")    /* 2, 23 */
     138    IF_FEATURE_LS_FOLLOWLINKS("L")   /* 1, 24 */
     139    IF_FEATURE_LS_RECURSIVE("R")     /* 1, 25 */
     140    IF_FEATURE_HUMAN_READABLE("h")   /* 1, 26 */
     141    IF_SELINUX("KZ") /* 2, 28 */
     142    IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 30 */
    125143    ;
    126 #else
    127 enum { show_color = 0 };
    128 #endif
     144enum {
     145    //OPT_C = (1 << 0),
     146    //OPT_a = (1 << 1),
     147    //OPT_d = (1 << 2),
     148    //OPT_i = (1 << 3),
     149    //OPT_l = (1 << 4),
     150    //OPT_1 = (1 << 5),
     151    OPT_g = (1 << 6),
     152    //OPT_n = (1 << 7),
     153    //OPT_s = (1 << 8),
     154    //OPT_x = (1 << 9),
     155    OPT_Q = (1 << 10),
     156    //OPT_A = (1 << 11),
     157    //OPT_k = (1 << 12),
     158    OPTBIT_color = 13
     159        + 4 * ENABLE_FEATURE_LS_TIMESTAMPS
     160        + 4 * ENABLE_FEATURE_LS_SORTFILES
     161        + 2 * ENABLE_FEATURE_LS_FILETYPES
     162        + 1 * ENABLE_FEATURE_LS_FOLLOWLINKS
     163        + 1 * ENABLE_FEATURE_LS_RECURSIVE
     164        + 1 * ENABLE_FEATURE_HUMAN_READABLE
     165        + 2 * ENABLE_SELINUX
     166        + 2 * ENABLE_FEATURE_AUTOWIDTH,
     167    OPT_color = 1 << OPTBIT_color,
     168};
     169
     170enum {
     171    LIST_MASK_TRIGGER   = 0,
     172    STYLE_MASK_TRIGGER  = STYLE_MASK,
     173    DISP_MASK_TRIGGER   = DISP_ROWS,
     174    SORT_MASK_TRIGGER   = SORT_MASK,
     175};
     176
     177/* TODO: simple toggles may be stored as OPT_xxx bits instead */
     178static const unsigned opt_flags[] = {
     179    LIST_SHORT | STYLE_COLUMNS, /* C */
     180    DISP_HIDDEN | DISP_DOT,     /* a */
     181    DISP_NOLIST,                /* d */
     182    LIST_INO,                   /* i */
     183    LIST_LONG | STYLE_LONG,     /* l - remember LS_DISP_HR in mask! */
     184    LIST_SHORT | STYLE_SINGLE,  /* 1 */
     185    0,                          /* g (don't show owner) - handled via OPT_g */
     186    LIST_ID_NUMERIC,            /* n */
     187    LIST_BLOCKS,                /* s */
     188    DISP_ROWS,                  /* x */
     189    0,                          /* Q (quote filename) - handled via OPT_Q */
     190    DISP_HIDDEN,                /* A */
     191    ENABLE_SELINUX * LIST_CONTEXT, /* k (ignored if !SELINUX) */
     192#if ENABLE_FEATURE_LS_TIMESTAMPS
     193    TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME),   /* c */
     194    LIST_FULLTIME,              /* e */
     195    ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME,   /* t */
     196    TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME),   /* u */
     197#endif
     198#if ENABLE_FEATURE_LS_SORTFILES
     199    SORT_SIZE,                  /* S */
     200    SORT_EXT,                   /* X */
     201    SORT_REVERSE,               /* r */
     202    SORT_VERSION,               /* v */
     203#endif
     204#if ENABLE_FEATURE_LS_FILETYPES
     205    LIST_FILETYPE | LIST_EXEC,  /* F */
     206    LIST_FILETYPE,              /* p */
     207#endif
     208#if ENABLE_FEATURE_LS_FOLLOWLINKS
     209    FOLLOW_LINKS,               /* L */
     210#endif
     211#if ENABLE_FEATURE_LS_RECURSIVE
     212    DISP_RECURSIVE,             /* R */
     213#endif
     214#if ENABLE_FEATURE_HUMAN_READABLE
     215    LS_DISP_HR,                 /* h */
     216#endif
     217#if ENABLE_SELINUX
     218    LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */
     219#endif
     220#if ENABLE_SELINUX
     221    LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */
     222#endif
     223    (1U<<31)
     224    /* options after Z are not processed through opt_flags:
     225     * T, w - ignored
     226     */
     227};
     228
    129229
    130230/*
    131231 * a directory entry and its stat info are stored here
    132232 */
    133 struct dnode {                  /* the basic node */
    134     const char *name;             /* the dir entry name */
    135     const char *fullname;         /* the dir entry name */
    136     int   allocated;
     233struct dnode {
     234    const char *name;       /* the dir entry name */
     235    const char *fullname;   /* the dir entry name */
     236    struct dnode *next;     /* point at the next node */
     237    smallint fname_allocated;
    137238    struct stat dstat;      /* the file stat info */
    138     USE_SELINUX(security_context_t sid;)
    139     struct dnode *next;     /* point at the next node */
     239    IF_SELINUX(security_context_t sid;)
    140240};
    141 typedef struct dnode dnode_t;
    142 
    143 static struct dnode **list_dir(const char *);
    144 static struct dnode **dnalloc(int);
    145 static int list_single(struct dnode *);
    146 
    147 static unsigned all_fmt;
    148 
     241
     242struct globals {
     243#if ENABLE_FEATURE_LS_COLOR
     244    smallint show_color;
     245#endif
     246    smallint exit_code;
     247    unsigned all_fmt;
    149248#if ENABLE_FEATURE_AUTOWIDTH
    150 static unsigned tabstops = COLUMN_GAP;
    151 static unsigned terminal_width = TERMINAL_WIDTH;
     249    unsigned tabstops; // = COLUMN_GAP;
     250    unsigned terminal_width; // = TERMINAL_WIDTH;
     251#endif
     252#if ENABLE_FEATURE_LS_TIMESTAMPS
     253    /* Do time() just once. Saves one syscall per file for "ls -l" */
     254    time_t current_time_t;
     255#endif
     256} FIX_ALIASING;
     257#define G (*(struct globals*)&bb_common_bufsiz1)
     258#if ENABLE_FEATURE_LS_COLOR
     259# define show_color     (G.show_color    )
     260#else
     261enum { show_color = 0 };
     262#endif
     263#define exit_code       (G.exit_code     )
     264#define all_fmt         (G.all_fmt       )
     265#if ENABLE_FEATURE_AUTOWIDTH
     266# define tabstops       (G.tabstops      )
     267# define terminal_width (G.terminal_width)
    152268#else
    153269enum {
     
    156272};
    157273#endif
    158 
    159 static int status = EXIT_SUCCESS;
     274#define current_time_t (G.current_time_t)
     275#define INIT_G() do { \
     276    /* we have to zero it out because of NOEXEC */ \
     277    memset(&G, 0, sizeof(G)); \
     278    IF_FEATURE_AUTOWIDTH(tabstops = COLUMN_GAP;) \
     279    IF_FEATURE_AUTOWIDTH(terminal_width = TERMINAL_WIDTH;) \
     280    IF_FEATURE_LS_TIMESTAMPS(time(&current_time_t);) \
     281} while (0)
     282
    160283
    161284static struct dnode *my_stat(const char *fullname, const char *name, int force_follow)
     
    163286    struct stat dstat;
    164287    struct dnode *cur;
    165     USE_SELINUX(security_context_t sid = NULL;)
     288    IF_SELINUX(security_context_t sid = NULL;)
    166289
    167290    if ((all_fmt & FOLLOW_LINKS) || force_follow) {
     
    172295#endif
    173296        if (stat(fullname, &dstat)) {
    174             bb_perror_msg("%s", fullname);
    175             status = EXIT_FAILURE;
     297            bb_simple_perror_msg(fullname);
     298            exit_code = EXIT_FAILURE;
    176299            return 0;
    177300        }
     
    183306#endif
    184307        if (lstat(fullname, &dstat)) {
    185             bb_perror_msg("%s", fullname);
    186             status = EXIT_FAILURE;
     308            bb_simple_perror_msg(fullname);
     309            exit_code = EXIT_FAILURE;
    187310            return 0;
    188311        }
    189312    }
    190313
    191     cur = xmalloc(sizeof(struct dnode));
     314    cur = xmalloc(sizeof(*cur));
    192315    cur->fullname = fullname;
    193316    cur->name = name;
    194317    cur->dstat = dstat;
    195     USE_SELINUX(cur->sid = sid;)
     318    IF_SELINUX(cur->sid = sid;)
    196319    return cur;
    197320}
    198321
     322/* FYI type values: 1:fifo 2:char 4:dir 6:blk 8:file 10:link 12:socket
     323 * (various wacky OSes: 13:Sun door 14:BSD whiteout 5:XENIX named file
     324 *  3/7:multiplexed char/block device)
     325 * and we use 0 for unknown and 15 for executables (see below) */
     326#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
     327#define TYPECHAR(mode)  ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
     328#define APPCHAR(mode)   ("\0|\0\0/\0\0\0\0\0@\0=\0\0\0" [TYPEINDEX(mode)])
     329/* 036 black foreground              050 black background
     330   037 red foreground                051 red background
     331   040 green foreground              052 green background
     332   041 brown foreground              053 brown background
     333   042 blue foreground               054 blue background
     334   043 magenta (purple) foreground   055 magenta background
     335   044 cyan (light blue) foreground  056 cyan background
     336   045 gray foreground               057 white background
     337*/
     338#define COLOR(mode) ( \
     339    /*un  fi  chr     dir     blk     file    link    sock        exe */ \
     340    "\037\043\043\045\042\045\043\043\000\045\044\045\043\045\045\040" \
     341    [TYPEINDEX(mode)])
     342/* Select normal (0) [actually "reset all"] or bold (1)
     343 * (other attributes are 2:dim 4:underline 5:blink 7:reverse,
     344 *  let's use 7 for "impossible" types, just for fun)
     345 * Note: coreutils 6.9 uses inverted red for setuid binaries.
     346 */
     347#define ATTR(mode) ( \
     348    /*un fi chr   dir   blk   file  link  sock     exe */ \
     349    "\01\00\01\07\01\07\01\07\00\07\01\07\01\07\07\01" \
     350    [TYPEINDEX(mode)])
     351
    199352#if ENABLE_FEATURE_LS_COLOR
     353/* mode of zero is interpreted as "unknown" (stat failed) */
    200354static char fgcolor(mode_t mode)
    201355{
    202     /* Check wheter the file is existing (if so, color it red!) */
    203     if (errno == ENOENT)
    204         return '\037';
    205356    if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
    206357        return COLOR(0xF000);   /* File is executable ... */
    207358    return COLOR(mode);
    208359}
    209 
    210 static char bgcolor(mode_t mode)
     360static char bold(mode_t mode)
    211361{
    212362    if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
     
    231381#endif
    232382
    233 #define countdirs(A, B) count_dirs((A), (B), 1)
    234 #define countsubdirs(A, B) count_dirs((A), (B), 0)
    235 static int count_dirs(struct dnode **dn, int nfiles, int notsubdirs)
    236 {
    237     int i, dirs;
     383static unsigned count_dirs(struct dnode **dn, int which)
     384{
     385    unsigned dirs, all;
    238386
    239387    if (!dn)
    240388        return 0;
    241     dirs = 0;
    242     for (i = 0; i < nfiles; i++) {
     389
     390    dirs = all = 0;
     391    for (; *dn; dn++) {
    243392        const char *name;
    244         if (!S_ISDIR(dn[i]->dstat.st_mode))
     393
     394        all++;
     395        if (!S_ISDIR((*dn)->dstat.st_mode))
    245396            continue;
    246         name = dn[i]->name;
    247         if (notsubdirs
    248          || name[0]!='.' || (name[1] && (name[1]!='.' || name[2]))
     397        name = (*dn)->name;
     398        if (which != SPLIT_SUBDIR /* if not requested to skip . / .. */
     399         /* or if it's not . or .. */
     400         || name[0] != '.' || (name[1] && (name[1] != '.' || name[2]))
    249401        ) {
    250402            dirs++;
    251403        }
    252404    }
    253     return dirs;
    254 }
    255 
    256 static int countfiles(struct dnode **dnp)
    257 {
    258     int nfiles;
    259     struct dnode *cur;
    260 
    261     if (dnp == NULL)
    262         return 0;
    263     nfiles = 0;
    264     for (cur = dnp[0]; cur->next; cur = cur->next)
    265         nfiles++;
    266     nfiles++;
    267     return nfiles;
     405    return which != SPLIT_FILE ? dirs : all - dirs;
    268406}
    269407
    270408/* get memory to hold an array of pointers */
    271 static struct dnode **dnalloc(int num)
     409static struct dnode **dnalloc(unsigned num)
    272410{
    273411    if (num < 1)
    274412        return NULL;
    275413
     414    num++; /* so that we have terminating NULL */
    276415    return xzalloc(num * sizeof(struct dnode *));
    277416}
    278417
    279418#if ENABLE_FEATURE_LS_RECURSIVE
    280 static void dfree(struct dnode **dnp, int nfiles)
    281 {
    282     int i;
     419static void dfree(struct dnode **dnp)
     420{
     421    unsigned i;
    283422
    284423    if (dnp == NULL)
    285424        return;
    286425
    287     for (i = 0; i < nfiles; i++) {
     426    for (i = 0; dnp[i]; i++) {
    288427        struct dnode *cur = dnp[i];
    289         if (cur->allocated)
    290             free((char*)cur->fullname); /* free the filename */
    291         free(cur);      /* free the dnode */
    292     }
    293     free(dnp);          /* free the array holding the dnode pointers */
     428        if (cur->fname_allocated)
     429            free((char*)cur->fullname);
     430        free(cur);
     431    }
     432    free(dnp);
    294433}
    295434#else
     
    297436#endif
    298437
    299 static struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which)
    300 {
    301     int dncnt, i, d;
     438/* Returns NULL-terminated malloced vector of pointers (or NULL) */
     439static struct dnode **splitdnarray(struct dnode **dn, int which)
     440{
     441    unsigned dncnt, d;
    302442    struct dnode **dnp;
    303443
    304     if (dn == NULL || nfiles < 1)
     444    if (dn == NULL)
    305445        return NULL;
    306446
    307     /* count how many dirs and regular files there are */
    308     if (which == SPLIT_SUBDIR)
    309         dncnt = countsubdirs(dn, nfiles);
    310     else {
    311         dncnt = countdirs(dn, nfiles);  /* assume we are looking for dirs */
    312         if (which == SPLIT_FILE)
    313             dncnt = nfiles - dncnt; /* looking for files */
    314     }
     447    /* count how many dirs or files there are */
     448    dncnt = count_dirs(dn, which);
    315449
    316450    /* allocate a file array and a dir array */
     
    318452
    319453    /* copy the entrys into the file or dir array */
    320     for (d = i = 0; i < nfiles; i++) {
    321         if (S_ISDIR(dn[i]->dstat.st_mode)) {
     454    for (d = 0; *dn; dn++) {
     455        if (S_ISDIR((*dn)->dstat.st_mode)) {
    322456            const char *name;
     457
    323458            if (!(which & (SPLIT_DIR|SPLIT_SUBDIR)))
    324459                continue;
    325             name = dn[i]->name;
     460            name = (*dn)->name;
    326461            if ((which & SPLIT_DIR)
    327462             || name[0]!='.' || (name[1] && (name[1]!='.' || name[2]))
    328463            ) {
    329                 dnp[d++] = dn[i];
     464                dnp[d++] = *dn;
    330465            }
    331466        } else if (!(which & (SPLIT_DIR|SPLIT_SUBDIR))) {
    332             dnp[d++] = dn[i];
     467            dnp[d++] = *dn;
    333468        }
    334469    }
     
    342477    struct dnode *d2 = *(struct dnode **)b;
    343478    unsigned sort_opts = all_fmt & SORT_MASK;
    344     int dif;
     479    off_t dif;
    345480
    346481    dif = 0; /* assume SORT_NAME */
     
    348483    // instead of branch forest
    349484    if (sort_opts == SORT_SIZE) {
    350         dif = (int) (d2->dstat.st_size - d1->dstat.st_size);
     485        dif = (d2->dstat.st_size - d1->dstat.st_size);
    351486    } else if (sort_opts == SORT_ATIME) {
    352         dif = (int) (d2->dstat.st_atime - d1->dstat.st_atime);
     487        dif = (d2->dstat.st_atime - d1->dstat.st_atime);
    353488    } else if (sort_opts == SORT_CTIME) {
    354         dif = (int) (d2->dstat.st_ctime - d1->dstat.st_ctime);
     489        dif = (d2->dstat.st_ctime - d1->dstat.st_ctime);
    355490    } else if (sort_opts == SORT_MTIME) {
    356         dif = (int) (d2->dstat.st_mtime - d1->dstat.st_mtime);
     491        dif = (d2->dstat.st_mtime - d1->dstat.st_mtime);
    357492    } else if (sort_opts == SORT_DIR) {
    358493        dif = S_ISDIR(d2->dstat.st_mode) - S_ISDIR(d1->dstat.st_mode);
     
    360495        /* } else if (sort_opts == SORT_EXT) { */
    361496    }
    362 
    363497    if (dif == 0) {
    364         /* sort by name - may be a tie_breaker for time or size cmp */
    365         if (ENABLE_LOCALE_SUPPORT) dif = strcoll(d1->name, d2->name);
    366         else dif = strcmp(d1->name, d2->name);
    367     }
    368 
    369     if (all_fmt & SORT_REVERSE) {
    370         dif = -dif;
    371     }
    372     return dif;
     498        /* sort by name, or tie_breaker for other sorts */
     499        if (ENABLE_LOCALE_SUPPORT)
     500            dif = strcoll(d1->name, d2->name);
     501        else
     502            dif = strcmp(d1->name, d2->name);
     503    }
     504
     505    /* Make dif fit into an int */
     506    if (sizeof(dif) > sizeof(int)) {
     507        enum { BITS_TO_SHIFT = 8 * (sizeof(dif) - sizeof(int)) };
     508        /* shift leaving only "int" worth of bits */
     509        if (dif != 0) {
     510            dif = 1 | (int)((uoff_t)dif >> BITS_TO_SHIFT);
     511        }
     512    }
     513
     514    return (all_fmt & SORT_REVERSE) ? -(int)dif : (int)dif;
    373515}
    374516
     
    382524
    383525
    384 static void showfiles(struct dnode **dn, int nfiles)
    385 {
    386     int i, ncols, nrows, row, nc;
    387     int column = 0;
    388     int nexttab = 0;
    389     int column_width = 0; /* for STYLE_LONG and STYLE_SINGLE not used */
    390 
    391     if (dn == NULL || nfiles < 1)
    392         return;
    393 
    394     if (all_fmt & STYLE_LONG) {
     526static unsigned calc_name_len(const char *name)
     527{
     528    unsigned len;
     529    uni_stat_t uni_stat;
     530
     531    // TODO: quote tab as \t, etc, if -Q
     532    name = printable_string(&uni_stat, name);
     533
     534    if (!(option_mask32 & OPT_Q)) {
     535        return uni_stat.unicode_width;
     536    }
     537
     538    len = 2 + uni_stat.unicode_width;
     539    while (*name) {
     540        if (*name == '"' || *name == '\\') {
     541            len++;
     542        }
     543        name++;
     544    }
     545    return len;
     546}
     547
     548
     549/* Return the number of used columns.
     550 * Note that only STYLE_COLUMNS uses return value.
     551 * STYLE_SINGLE and STYLE_LONG don't care.
     552 * coreutils 7.2 also supports:
     553 * ls -b (--escape) = octal escapes (although it doesn't look like working)
     554 * ls -N (--literal) = not escape at all
     555 */
     556static unsigned print_name(const char *name)
     557{
     558    unsigned len;
     559    uni_stat_t uni_stat;
     560
     561    // TODO: quote tab as \t, etc, if -Q
     562    name = printable_string(&uni_stat, name);
     563
     564    if (!(option_mask32 & OPT_Q)) {
     565        fputs(name, stdout);
     566        return uni_stat.unicode_width;
     567    }
     568
     569    len = 2 + uni_stat.unicode_width;
     570    putchar('"');
     571    while (*name) {
     572        if (*name == '"' || *name == '\\') {
     573            putchar('\\');
     574            len++;
     575        }
     576        putchar(*name);
     577        name++;
     578    }
     579    putchar('"');
     580    return len;
     581}
     582
     583/* Return the number of used columns.
     584 * Note that only STYLE_COLUMNS uses return value,
     585 * STYLE_SINGLE and STYLE_LONG don't care.
     586 */
     587static NOINLINE unsigned list_single(const struct dnode *dn)
     588{
     589    unsigned column = 0;
     590    char *lpath = lpath; /* for compiler */
     591#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR
     592    struct stat info;
     593    char append;
     594#endif
     595
     596    /* Never happens:
     597    if (dn->fullname == NULL)
     598        return 0;
     599    */
     600
     601#if ENABLE_FEATURE_LS_FILETYPES
     602    append = append_char(dn->dstat.st_mode);
     603#endif
     604
     605    /* Do readlink early, so that if it fails, error message
     606     * does not appear *inside* the "ls -l" line */
     607    if (all_fmt & LIST_SYMLINK)
     608        if (S_ISLNK(dn->dstat.st_mode))
     609            lpath = xmalloc_readlink_or_warn(dn->fullname);
     610
     611    if (all_fmt & LIST_INO)
     612        column += printf("%7llu ", (long long) dn->dstat.st_ino);
     613    if (all_fmt & LIST_BLOCKS)
     614        column += printf("%4"OFF_FMT"u ", (off_t) (dn->dstat.st_blocks >> 1));
     615    if (all_fmt & LIST_MODEBITS)
     616        column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
     617    if (all_fmt & LIST_NLINKS)
     618        column += printf("%4lu ", (long) dn->dstat.st_nlink);
     619#if ENABLE_FEATURE_LS_USERNAME
     620    if (all_fmt & LIST_ID_NAME) {
     621        if (option_mask32 & OPT_g) {
     622            column += printf("%-8.8s ",
     623                get_cached_groupname(dn->dstat.st_gid));
     624        } else {
     625            column += printf("%-8.8s %-8.8s ",
     626                get_cached_username(dn->dstat.st_uid),
     627                get_cached_groupname(dn->dstat.st_gid));
     628        }
     629    }
     630#endif
     631    if (all_fmt & LIST_ID_NUMERIC) {
     632        if (option_mask32 & OPT_g)
     633            column += printf("%-8u ", (int) dn->dstat.st_gid);
     634        else
     635            column += printf("%-8u %-8u ",
     636                    (int) dn->dstat.st_uid,
     637                    (int) dn->dstat.st_gid);
     638    }
     639    if (all_fmt & (LIST_SIZE /*|LIST_DEV*/ )) {
     640        if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) {
     641            column += printf("%4u, %3u ",
     642                    (int) major(dn->dstat.st_rdev),
     643                    (int) minor(dn->dstat.st_rdev));
     644        } else {
     645            if (all_fmt & LS_DISP_HR) {
     646                column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ",
     647                    /* print st_size, show one fractional, use suffixes */
     648                    make_human_readable_str(dn->dstat.st_size, 1, 0)
     649                );
     650            } else {
     651                column += printf("%9"OFF_FMT"u ", (off_t) dn->dstat.st_size);
     652            }
     653        }
     654    }
     655#if ENABLE_FEATURE_LS_TIMESTAMPS
     656    if (all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) {
     657        char *filetime;
     658        time_t ttime = dn->dstat.st_mtime;
     659        if (all_fmt & TIME_ACCESS)
     660            ttime = dn->dstat.st_atime;
     661        if (all_fmt & TIME_CHANGE)
     662            ttime = dn->dstat.st_ctime;
     663        filetime = ctime(&ttime);
     664        /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */
     665        if (all_fmt & LIST_FULLTIME)
     666            column += printf("%.24s ", filetime);
     667        else { /* LIST_DATE_TIME */
     668            /* current_time_t ~== time(NULL) */
     669            time_t age = current_time_t - ttime;
     670            printf("%.6s ", filetime + 4); /* "Jun 30" */
     671            if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) {
     672                /* hh:mm if less than 6 months old */
     673                printf("%.5s ", filetime + 11);
     674            } else { /* year. buggy if year > 9999 ;) */
     675                printf(" %.4s ", filetime + 20);
     676            }
     677            column += 13;
     678        }
     679    }
     680#endif
     681#if ENABLE_SELINUX
     682    if (all_fmt & LIST_CONTEXT) {
     683        column += printf("%-32s ", dn->sid ? dn->sid : "unknown");
     684        freecon(dn->sid);
     685    }
     686#endif
     687    if (all_fmt & LIST_FILENAME) {
     688#if ENABLE_FEATURE_LS_COLOR
     689        if (show_color) {
     690            info.st_mode = 0; /* for fgcolor() */
     691            lstat(dn->fullname, &info);
     692            printf("\033[%u;%um", bold(info.st_mode),
     693                    fgcolor(info.st_mode));
     694        }
     695#endif
     696        column += print_name(dn->name);
     697        if (show_color) {
     698            printf("\033[0m");
     699        }
     700    }
     701    if (all_fmt & LIST_SYMLINK) {
     702        if (S_ISLNK(dn->dstat.st_mode) && lpath) {
     703            printf(" -> ");
     704#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR
     705#if ENABLE_FEATURE_LS_COLOR
     706            info.st_mode = 0; /* for fgcolor() */
     707#endif
     708            if (stat(dn->fullname, &info) == 0) {
     709                append = append_char(info.st_mode);
     710            }
     711#endif
     712#if ENABLE_FEATURE_LS_COLOR
     713            if (show_color) {
     714                printf("\033[%u;%um", bold(info.st_mode),
     715                       fgcolor(info.st_mode));
     716            }
     717#endif
     718            column += print_name(lpath) + 4;
     719            if (show_color) {
     720                printf("\033[0m");
     721            }
     722            free(lpath);
     723        }
     724    }
     725#if ENABLE_FEATURE_LS_FILETYPES
     726    if (all_fmt & LIST_FILETYPE) {
     727        if (append) {
     728            putchar(append);
     729            column++;
     730        }
     731    }
     732#endif
     733
     734    return column;
     735}
     736
     737static void showfiles(struct dnode **dn, unsigned nfiles)
     738{
     739    unsigned i, ncols, nrows, row, nc;
     740    unsigned column = 0;
     741    unsigned nexttab = 0;
     742    unsigned column_width = 0; /* used only by STYLE_COLUMNS */
     743
     744    if (all_fmt & STYLE_LONG) { /* STYLE_LONG or STYLE_SINGLE */
    395745        ncols = 1;
    396746    } else {
    397747        /* find the longest file name, use that as the column width */
    398         for (i = 0; i < nfiles; i++) {
    399             int len = strlen(dn[i]->name);
     748        for (i = 0; dn[i]; i++) {
     749            int len = calc_name_len(dn[i]->name);
    400750            if (column_width < len)
    401751                column_width = len;
    402752        }
    403753        column_width += tabstops +
    404             USE_SELINUX( ((all_fmt & LIST_CONTEXT) ? 33 : 0) + )
    405                          ((all_fmt & LIST_INO) ? 8 : 0) +
    406                          ((all_fmt & LIST_BLOCKS) ? 5 : 0);
     754            IF_SELINUX( ((all_fmt & LIST_CONTEXT) ? 33 : 0) + )
     755                ((all_fmt & LIST_INO) ? 8 : 0) +
     756                ((all_fmt & LIST_BLOCKS) ? 5 : 0);
    407757        ncols = (int) (terminal_width / column_width);
    408758    }
     
    420770        for (nc = 0; nc < ncols; nc++) {
    421771            /* reach into the array based on the column and row */
    422             i = (nc * nrows) + row; /* assume display by column */
    423772            if (all_fmt & DISP_ROWS)
    424773                i = (row * ncols) + nc; /* display across row */
     774            else
     775                i = (nc * nrows) + row; /* display by column */
    425776            if (i < nfiles) {
    426777                if (column > 0) {
     
    439790
    440791
    441 static void showdirs(struct dnode **dn, int ndirs, int first)
    442 {
    443     int i, nfiles;
     792#if ENABLE_DESKTOP
     793/* http://www.opengroup.org/onlinepubs/9699919799/utilities/ls.html
     794 * If any of the -l, -n, -s options is specified, each list
     795 * of files within the directory shall be preceded by a
     796 * status line indicating the number of file system blocks
     797 * occupied by files in the directory in 512-byte units if
     798 * the -k option is not specified, or 1024-byte units if the
     799 * -k option is specified, rounded up to the next integral
     800 * number of units.
     801 */
     802/* by Jorgen Overgaard (jorgen AT antistaten.se) */
     803static off_t calculate_blocks(struct dnode **dn)
     804{
     805    uoff_t blocks = 1;
     806    if (dn) {
     807        while (*dn) {
     808            /* st_blocks is in 512 byte blocks */
     809            blocks += (*dn)->dstat.st_blocks;
     810            dn++;
     811        }
     812    }
     813
     814    /* Even though standard says use 512 byte blocks, coreutils use 1k */
     815    /* Actually, we round up by calculating (blocks + 1) / 2,
     816     * "+ 1" was done when we initialized blocks to 1 */
     817    return blocks >> 1;
     818}
     819#endif
     820
     821
     822static struct dnode **list_dir(const char *, unsigned *);
     823
     824static void showdirs(struct dnode **dn, int first)
     825{
     826    unsigned nfiles;
     827    unsigned dndirs;
    444828    struct dnode **subdnp;
    445     int dndirs;
    446829    struct dnode **dnd;
    447830
    448     if (dn == NULL || ndirs < 1)
     831    /* Never happens:
     832    if (dn == NULL || ndirs < 1) {
    449833        return;
    450 
    451     for (i = 0; i < ndirs; i++) {
     834    }
     835    */
     836
     837    for (; *dn; dn++) {
    452838        if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) {
    453839            if (!first)
    454                 puts("");
     840                bb_putchar('\n');
    455841            first = 0;
    456             printf("%s:\n", dn[i]->fullname);
    457         }
    458         subdnp = list_dir(dn[i]->fullname);
    459         nfiles = countfiles(subdnp);
     842            printf("%s:\n", (*dn)->fullname);
     843        }
     844        subdnp = list_dir((*dn)->fullname, &nfiles);
     845#if ENABLE_DESKTOP
     846        if ((all_fmt & STYLE_MASK) == STYLE_LONG)
     847            printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp));
     848#endif
    460849        if (nfiles > 0) {
    461850            /* list all files at this level */
    462851            dnsort(subdnp, nfiles);
    463852            showfiles(subdnp, nfiles);
    464             if (ENABLE_FEATURE_LS_RECURSIVE) {
    465                 if (all_fmt & DISP_RECURSIVE) {
    466                     /* recursive- list the sub-dirs */
    467                     dnd = splitdnarray(subdnp, nfiles, SPLIT_SUBDIR);
    468                     dndirs = countsubdirs(subdnp, nfiles);
    469                     if (dndirs > 0) {
    470                         dnsort(dnd, dndirs);
    471                         showdirs(dnd, dndirs, 0);
    472                         /* free the array of dnode pointers to the dirs */
    473                         free(dnd);
    474                     }
     853            if (ENABLE_FEATURE_LS_RECURSIVE
     854             && (all_fmt & DISP_RECURSIVE)
     855            ) {
     856                /* recursive - list the sub-dirs */
     857                dnd = splitdnarray(subdnp, SPLIT_SUBDIR);
     858                dndirs = count_dirs(subdnp, SPLIT_SUBDIR);
     859                if (dndirs > 0) {
     860                    dnsort(dnd, dndirs);
     861                    showdirs(dnd, 0);
     862                    /* free the array of dnode pointers to the dirs */
     863                    free(dnd);
    475864                }
    476                 /* free the dnodes and the fullname mem */
    477                 dfree(subdnp, nfiles);
    478865            }
    479         }
    480     }
    481 }
    482 
    483 
    484 static struct dnode **list_dir(const char *path)
     866            /* free the dnodes and the fullname mem */
     867            dfree(subdnp);
     868        }
     869    }
     870}
     871
     872
     873/* Returns NULL-terminated malloced vector of pointers (or NULL) */
     874static struct dnode **list_dir(const char *path, unsigned *nfiles_p)
    485875{
    486876    struct dnode *dn, *cur, **dnp;
    487877    struct dirent *entry;
    488878    DIR *dir;
    489     int i, nfiles;
    490 
     879    unsigned i, nfiles;
     880
     881    /* Never happens:
    491882    if (path == NULL)
    492883        return NULL;
    493 
     884    */
     885
     886    *nfiles_p = 0;
     887    dir = warn_opendir(path);
     888    if (dir == NULL) {
     889        exit_code = EXIT_FAILURE;
     890        return NULL;    /* could not open the dir */
     891    }
    494892    dn = NULL;
    495893    nfiles = 0;
    496     dir = warn_opendir(path);
    497     if (dir == NULL) {
    498         status = EXIT_FAILURE;
    499         return NULL;    /* could not open the dir */
    500     }
    501894    while ((entry = readdir(dir)) != NULL) {
    502895        char *fullname;
     
    518911            continue;
    519912        }
    520         cur->allocated = 1;
     913        cur->fname_allocated = 1;
    521914        cur->next = dn;
    522915        dn = cur;
     
    525918    closedir(dir);
    526919
     920    if (dn == NULL)
     921        return NULL;
     922
    527923    /* now that we know how many files there are
    528924     * allocate memory for an array to hold dnode pointers
    529925     */
    530     if (dn == NULL)
    531         return NULL;
     926    *nfiles_p = nfiles;
    532927    dnp = dnalloc(nfiles);
    533     for (i = 0, cur = dn; i < nfiles; i++) {
    534         dnp[i] = cur;   /* save pointer to node in array */
    535         cur = cur->next;
     928    for (i = 0; /* i < nfiles - detected via !dn below */; i++) {
     929        dnp[i] = dn;    /* save pointer to node in array */
     930        dn = dn->next;
     931        if (!dn)
     932            break;
    536933    }
    537934
     
    540937
    541938
    542 #if ENABLE_FEATURE_LS_TIMESTAMPS
    543 /* Do time() just once. Saves one syscall per file for "ls -l" */
    544 /* Initialized in main() */
    545 static time_t current_time_t;
    546 #endif
    547 
    548 static int list_single(struct dnode *dn)
    549 {
    550     int i, column = 0;
    551 
    552 #if ENABLE_FEATURE_LS_TIMESTAMPS
    553     char *filetime;
    554     time_t ttime, age;
    555 #endif
    556 #if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR
    557     struct stat info;
    558     char append;
    559 #endif
    560 
    561     if (dn->fullname == NULL)
    562         return 0;
    563 
    564 #if ENABLE_FEATURE_LS_TIMESTAMPS
    565     ttime = dn->dstat.st_mtime; /* the default time */
    566     if (all_fmt & TIME_ACCESS)
    567         ttime = dn->dstat.st_atime;
    568     if (all_fmt & TIME_CHANGE)
    569         ttime = dn->dstat.st_ctime;
    570     filetime = ctime(&ttime);
    571 #endif
    572 #if ENABLE_FEATURE_LS_FILETYPES
    573     append = append_char(dn->dstat.st_mode);
    574 #endif
    575 
    576     for (i = 0; i <= 31; i++) {
    577         switch (all_fmt & (1 << i)) {
    578         case LIST_INO:
    579             column += printf("%7ld ", (long) dn->dstat.st_ino);
    580             break;
    581         case LIST_BLOCKS:
    582             column += printf("%4"OFF_FMT"d ", (off_t) dn->dstat.st_blocks >> 1);
    583             break;
    584         case LIST_MODEBITS:
    585             column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
    586             break;
    587         case LIST_NLINKS:
    588             column += printf("%4ld ", (long) dn->dstat.st_nlink);
    589             break;
    590         case LIST_ID_NAME:
    591 #if ENABLE_FEATURE_LS_USERNAME
    592             printf("%-8.8s %-8.8s",
    593                 get_cached_username(dn->dstat.st_uid),
    594                 get_cached_groupname(dn->dstat.st_gid));
    595             column += 17;
    596             break;
    597 #endif
    598         case LIST_ID_NUMERIC:
    599             column += printf("%-8d %-8d", dn->dstat.st_uid, dn->dstat.st_gid);
    600             break;
    601         case LIST_SIZE:
    602         case LIST_DEV:
    603             if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) {
    604                 column += printf("%4d, %3d ", (int) major(dn->dstat.st_rdev),
    605                        (int) minor(dn->dstat.st_rdev));
    606             } else {
    607                 if (all_fmt & LS_DISP_HR) {
    608                     column += printf("%9s ",
    609                         make_human_readable_str(dn->dstat.st_size, 1, 0));
    610                 } else {
    611                     column += printf("%9"OFF_FMT"d ", (off_t) dn->dstat.st_size);
    612                 }
    613             }
    614             break;
    615 #if ENABLE_FEATURE_LS_TIMESTAMPS
    616         case LIST_FULLTIME:
    617             printf("%24.24s ", filetime);
    618             column += 25;
    619             break;
    620         case LIST_DATE_TIME:
    621             if ((all_fmt & LIST_FULLTIME) == 0) {
    622                 /* current_time_t ~== time(NULL) */
    623                 age = current_time_t - ttime;
    624                 printf("%6.6s ", filetime + 4);
    625                 if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) {
    626                     /* hh:mm if less than 6 months old */
    627                     printf("%5.5s ", filetime + 11);
    628                 } else {
    629                     printf(" %4.4s ", filetime + 20);
    630                 }
    631                 column += 13;
    632             }
    633             break;
    634 #endif
    635 #if ENABLE_SELINUX
    636         case LIST_CONTEXT:
    637             {
    638                 char context[80];
    639                 int len = 0;
    640 
    641                 if (dn->sid) {
    642                     /* I assume sid initilized with NULL */
    643                     len = strlen(dn->sid) + 1;
    644                     safe_strncpy(context, dn->sid, len);
    645                     freecon(dn->sid);
    646                 } else {
    647                     safe_strncpy(context, "unknown", 8);
    648                 }
    649                 printf("%-32s ", context);
    650                 column += MAX(33, len);
    651             }
    652             break;
    653 #endif
    654         case LIST_FILENAME:
    655             errno = 0;
    656 #if ENABLE_FEATURE_LS_COLOR
    657             if (show_color && !lstat(dn->fullname, &info)) {
    658                 printf("\033[%d;%dm", bgcolor(info.st_mode),
    659                         fgcolor(info.st_mode));
    660             }
    661 #endif
    662             column += printf("%s", dn->name);
    663             if (show_color) {
    664                 printf("\033[0m");
    665             }
    666             break;
    667         case LIST_SYMLINK:
    668             if (S_ISLNK(dn->dstat.st_mode)) {
    669                 char *lpath = xmalloc_readlink_or_warn(dn->fullname);
    670                 if (!lpath) break;
    671                 printf(" -> ");
    672 #if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR
    673                 if (!stat(dn->fullname, &info)) {
    674                     append = append_char(info.st_mode);
    675                 }
    676 #endif
    677 #if ENABLE_FEATURE_LS_COLOR
    678                 if (show_color) {
    679                     errno = 0;
    680                     printf("\033[%d;%dm", bgcolor(info.st_mode),
    681                            fgcolor(info.st_mode));
    682                 }
    683 #endif
    684                 column += printf("%s", lpath) + 4;
    685                 if (show_color) {
    686                     printf("\033[0m");
    687                 }
    688                 free(lpath);
    689             }
    690             break;
    691 #if ENABLE_FEATURE_LS_FILETYPES
    692         case LIST_FILETYPE:
    693             if (append) {
    694                 putchar(append);
    695                 column++;
    696             }
    697             break;
    698 #endif
    699         }
    700     }
    701 
    702     return column;
    703 }
    704 
    705 /* "[-]Cadil1", POSIX mandated options, busybox always supports */
    706 /* "[-]gnsx", POSIX non-mandated options, busybox always supports */
    707 /* "[-]Ak" GNU options, busybox always supports */
    708 /* "[-]FLRctur", POSIX mandated options, busybox optionally supports */
    709 /* "[-]p", POSIX non-mandated options, busybox optionally supports */
    710 /* "[-]SXvThw", GNU options, busybox optionally supports */
    711 /* "[-]K", SELinux mandated options, busybox optionally supports */
    712 /* "[-]e", I think we made this one up */
    713 static const char ls_options[] ALIGN1 =
    714     "Cadil1gnsxAk"
    715     USE_FEATURE_LS_TIMESTAMPS("cetu")
    716     USE_FEATURE_LS_SORTFILES("SXrv")
    717     USE_FEATURE_LS_FILETYPES("Fp")
    718     USE_FEATURE_LS_FOLLOWLINKS("L")
    719     USE_FEATURE_LS_RECURSIVE("R")
    720     USE_FEATURE_HUMAN_READABLE("h")
    721     USE_SELINUX("K")
    722     USE_FEATURE_AUTOWIDTH("T:w:")
    723     USE_SELINUX("Z");
    724 
    725 enum {
    726     LIST_MASK_TRIGGER   = 0,
    727     STYLE_MASK_TRIGGER  = STYLE_MASK,
    728     DISP_MASK_TRIGGER   = DISP_ROWS,
    729     SORT_MASK_TRIGGER   = SORT_MASK,
    730 };
    731 
    732 static const unsigned opt_flags[] = {
    733     LIST_SHORT | STYLE_COLUMNS, /* C */
    734     DISP_HIDDEN | DISP_DOT,     /* a */
    735     DISP_NOLIST,                /* d */
    736     LIST_INO,                   /* i */
    737     LIST_LONG | STYLE_LONG,     /* l - remember LS_DISP_HR in mask! */
    738     LIST_SHORT | STYLE_SINGLE,  /* 1 */
    739     0,                          /* g - ingored */
    740     LIST_ID_NUMERIC,            /* n */
    741     LIST_BLOCKS,                /* s */
    742     DISP_ROWS,                  /* x */
    743     DISP_HIDDEN,                /* A */
    744     ENABLE_SELINUX * LIST_CONTEXT, /* k (ignored if !SELINUX) */
    745 #if ENABLE_FEATURE_LS_TIMESTAMPS
    746     TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME),   /* c */
    747     LIST_FULLTIME,              /* e */
    748     ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME,   /* t */
    749     TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME),   /* u */
    750 #endif
    751 #if ENABLE_FEATURE_LS_SORTFILES
    752     SORT_SIZE,                  /* S */
    753     SORT_EXT,                   /* X */
    754     SORT_REVERSE,               /* r */
    755     SORT_VERSION,               /* v */
    756 #endif
    757 #if ENABLE_FEATURE_LS_FILETYPES
    758     LIST_FILETYPE | LIST_EXEC,  /* F */
    759     LIST_FILETYPE,              /* p */
    760 #endif
    761 #if ENABLE_FEATURE_LS_FOLLOWLINKS
    762     FOLLOW_LINKS,               /* L */
    763 #endif
    764 #if ENABLE_FEATURE_LS_RECURSIVE
    765     DISP_RECURSIVE,             /* R */
    766 #endif
    767 #if ENABLE_FEATURE_HUMAN_READABLE
    768     LS_DISP_HR,                 /* h */
    769 #endif
    770 #if ENABLE_SELINUX
    771     LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */
    772 #endif
    773 #if ENABLE_FEATURE_AUTOWIDTH
    774     0, 0,                       /* T, w - ignored */
    775 #endif
    776 #if ENABLE_SELINUX
    777     LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */
    778 #endif
    779     (1U<<31)
    780 };
    781 
    782 
    783 /* THIS IS A "SAFE" APPLET, main() MAY BE CALLED INTERNALLY FROM SHELL */
    784 /* BE CAREFUL! */
    785 
    786 int ls_main(int argc, char **argv);
    787 int ls_main(int argc, char **argv)
     939int ls_main(int argc UNUSED_PARAM, char **argv)
    788940{
    789941    struct dnode **dnd;
     
    793945    struct dnode *cur;
    794946    unsigned opt;
    795     int nfiles = 0;
    796     int dnfiles;
    797     int dndirs;
    798     int oi;
    799     int ac;
    800     int i;
    801     char **av;
    802     USE_FEATURE_AUTOWIDTH(char *tabstops_str = NULL;)
    803     USE_FEATURE_AUTOWIDTH(char *terminal_width_str = NULL;)
    804     USE_FEATURE_LS_COLOR(char *color_opt;)
    805 
    806 #if ENABLE_FEATURE_LS_TIMESTAMPS
    807     time(&current_time_t);
    808 #endif
     947    unsigned nfiles;
     948    unsigned dnfiles;
     949    unsigned dndirs;
     950    unsigned i;
     951#if ENABLE_FEATURE_LS_COLOR
     952    /* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */
     953    /* coreutils 6.10:
     954     * # ls --color=BOGUS
     955     * ls: invalid argument 'BOGUS' for '--color'
     956     * Valid arguments are:
     957     * 'always', 'yes', 'force'
     958     * 'never', 'no', 'none'
     959     * 'auto', 'tty', 'if-tty'
     960     * (and substrings: "--color=alwa" work too)
     961     */
     962    static const char ls_longopts[] ALIGN1 =
     963        "color\0" Optional_argument "\xff"; /* no short equivalent */
     964    static const char color_str[] ALIGN1 =
     965        "always\0""yes\0""force\0"
     966        "auto\0""tty\0""if-tty\0";
     967    /* need to initialize since --color has _an optional_ argument */
     968    const char *color_opt = color_str; /* "always" */
     969#endif
     970
     971    INIT_G();
     972
     973    init_unicode();
    809974
    810975    all_fmt = LIST_SHORT |
     
    812977
    813978#if ENABLE_FEATURE_AUTOWIDTH
    814     /* Obtain the terminal width */
     979    /* obtain the terminal width */
    815980    get_terminal_width_height(STDIN_FILENO, &terminal_width, NULL);
    816     /* Go one less... */
     981    /* go one less... */
    817982    terminal_width--;
    818983#endif
    819984
    820985    /* process options */
    821     USE_FEATURE_LS_COLOR(applet_long_options = ls_color_opt;)
     986    IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;)
    822987#if ENABLE_FEATURE_AUTOWIDTH
    823     opt = getopt32(argv, ls_options, &tabstops_str, &terminal_width_str
    824                 USE_FEATURE_LS_COLOR(, &color_opt));
    825     if (tabstops_str)
    826         tabstops = xatou(tabstops_str);
    827     if (terminal_width_str)
    828         terminal_width = xatou(terminal_width_str);
     988    opt_complementary = "T+:w+"; /* -T N, -w N */
     989    opt = getopt32(argv, ls_options, &tabstops, &terminal_width
     990                IF_FEATURE_LS_COLOR(, &color_opt));
    829991#else
    830     opt = getopt32(argv, ls_options USE_FEATURE_LS_COLOR(, &color_opt));
     992    opt = getopt32(argv, ls_options IF_FEATURE_LS_COLOR(, &color_opt));
    831993#endif
    832994    for (i = 0; opt_flags[i] != (1U<<31); i++) {
     
    8581020        char *p = getenv("LS_COLORS");
    8591021        /* LS_COLORS is unset, or (not empty && not "none") ? */
    860         if (!p || (p[0] && strcmp(p, "none")))
     1022        if (!p || (p[0] && strcmp(p, "none") != 0))
    8611023            show_color = 1;
    8621024    }
    863     if (opt & (1 << i)) {  /* next flag after short options */
    864         if (!color_opt || !strcmp("always", color_opt))
    865             show_color = 1;
    866         else if (color_opt && !strcmp("never", color_opt))
     1025    if (opt & OPT_color) {
     1026        if (color_opt[0] == 'n')
    8671027            show_color = 0;
    868         else if (color_opt && !strcmp("auto", color_opt) && isatty(STDOUT_FILENO))
    869             show_color = 1;
     1028        else switch (index_in_substrings(color_str, color_opt)) {
     1029        case 3:
     1030        case 4:
     1031        case 5:
     1032            if (isatty(STDOUT_FILENO)) {
     1033        case 0:
     1034        case 1:
     1035        case 2:
     1036                show_color = 1;
     1037            }
     1038        }
    8701039    }
    8711040#endif
     
    8901059        all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE);
    8911060
    892     /*
    893      * when there are no cmd line args we have to supply a default "." arg.
    894      * we will create a second argv array, "av" that will hold either
    895      * our created "." arg, or the real cmd line args.  The av array
    896      * just holds the pointers- we don't move the date the pointers
    897      * point to.
    898      */
    899     ac = argc - optind; /* how many cmd line args are left */
    900     if (ac < 1) {
    901         static const char *const dotdir[] = { "." };
    902 
    903         av = (char **) dotdir;
    904         ac = 1;
    905     } else {
    906         av = argv + optind;
    907     }
    908 
    909     /* now, everything is in the av array */
    910     if (ac > 1)
    911         all_fmt |= DISP_DIRNAME;    /* 2 or more items? label directories */
     1061    argv += optind;
     1062    if (!argv[0])
     1063        *--argv = (char*)".";
     1064
     1065    if (argv[1])
     1066        all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */
    9121067
    9131068    /* stuff the command line file names into a dnode array */
    9141069    dn = NULL;
    915     for (oi = 0; oi < ac; oi++) {
    916         /* ls w/o -l follows links on command line */
    917         cur = my_stat(av[oi], av[oi], !(all_fmt & STYLE_LONG));
     1070    nfiles = 0;
     1071    do {
     1072        /* NB: follow links on command line unless -l or -s */
     1073        cur = my_stat(*argv, *argv, !(all_fmt & (STYLE_LONG|LIST_BLOCKS)));
     1074        argv++;
    9181075        if (!cur)
    9191076            continue;
    920         cur->allocated = 0;
     1077        cur->fname_allocated = 0;
    9211078        cur->next = dn;
    9221079        dn = cur;
    9231080        nfiles++;
    924     }
     1081    } while (*argv);
     1082
     1083    /* nfiles _may_ be 0 here - try "ls doesnt_exist" */
     1084    if (nfiles == 0)
     1085        return exit_code;
    9251086
    9261087    /* now that we know how many files there are
     
    9281089     */
    9291090    dnp = dnalloc(nfiles);
    930     for (i = 0, cur = dn; i < nfiles; i++) {
    931         dnp[i] = cur;   /* save pointer to node in array */
    932         cur = cur->next;
     1091    for (i = 0; /* i < nfiles - detected via !dn below */; i++) {
     1092        dnp[i] = dn;    /* save pointer to node in array */
     1093        dn = dn->next;
     1094        if (!dn)
     1095            break;
    9331096    }
    9341097
    9351098    if (all_fmt & DISP_NOLIST) {
    9361099        dnsort(dnp, nfiles);
    937         if (nfiles > 0)
    938             showfiles(dnp, nfiles);
     1100        showfiles(dnp, nfiles);
    9391101    } else {
    940         dnd = splitdnarray(dnp, nfiles, SPLIT_DIR);
    941         dnf = splitdnarray(dnp, nfiles, SPLIT_FILE);
    942         dndirs = countdirs(dnp, nfiles);
     1102        dnd = splitdnarray(dnp, SPLIT_DIR);
     1103        dnf = splitdnarray(dnp, SPLIT_FILE);
     1104        dndirs = count_dirs(dnp, SPLIT_DIR);
    9431105        dnfiles = nfiles - dndirs;
    9441106        if (dnfiles > 0) {
     
    9501112        if (dndirs > 0) {
    9511113            dnsort(dnd, dndirs);
    952             showdirs(dnd, dndirs, dnfiles == 0);
     1114            showdirs(dnd, dnfiles == 0);
    9531115            if (ENABLE_FEATURE_CLEAN_UP)
    9541116                free(dnd);
     
    9561118    }
    9571119    if (ENABLE_FEATURE_CLEAN_UP)
    958         dfree(dnp, nfiles);
    959     return status;
    960 }
     1120        dfree(dnp);
     1121    return exit_code;
     1122}
  • branches/2.2.9/mindi-busybox/coreutils/md5_sha1_sum.c

    r1765 r2725  
    44 *  Copyright (C) 2003-2004 Erik Andersen
    55 *
    6  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    77 */
    88
    99#include "libbb.h"
    1010
    11 typedef enum { HASH_SHA1, HASH_MD5 } hash_algo_t;
     11/* This is a NOEXEC applet. Be very careful! */
    1212
    13 #define FLAG_SILENT 1
    14 #define FLAG_CHECK  2
    15 #define FLAG_WARN   4
     13enum {
     14    /* 4th letter of applet_name is... */
     15    HASH_MD5 = 's', /* "md5>s<um" */
     16    HASH_SHA1 = '1',
     17    HASH_SHA256 = '2',
     18    HASH_SHA512 = '5',
     19};
     20
     21#define FLAG_SILENT  1
     22#define FLAG_CHECK   2
     23#define FLAG_WARN    4
    1624
    1725/* This might be useful elsewhere */
     
    2230    char *hex_value = xzalloc((hash_length * 2) + 1);
    2331    bin2hex(hex_value, (char*)hash_value, hash_length);
    24     return hex_value;
     32    return (unsigned char *)hex_value;
    2533}
    2634
    27 static uint8_t *hash_file(const char *filename, hash_algo_t hash_algo)
     35static uint8_t *hash_file(const char *filename)
    2836{
    2937    int src_fd, hash_len, count;
    3038    union _ctx_ {
     39        sha512_ctx_t sha512;
     40        sha256_ctx_t sha256;
    3141        sha1_ctx_t sha1;
    3242        md5_ctx_t md5;
     
    3444    uint8_t *hash_value = NULL;
    3545    RESERVE_CONFIG_UBUFFER(in_buf, 4096);
    36     void (*update)(const void*, size_t, void*);
    37     void (*final)(void*, void*);
     46    void FAST_FUNC (*update)(void*, const void*, size_t);
     47    void FAST_FUNC (*final)(void*, void*);
     48    char hash_algo;
    3849
    39     src_fd = STDIN_FILENO;
    40     if (NOT_LONE_DASH(filename)) {
    41         src_fd = open_or_warn(filename, O_RDONLY);
    42         if (src_fd < 0) {
    43             return NULL;
    44         }
     50    src_fd = open_or_warn_stdin(filename);
     51    if (src_fd < 0) {
     52        return NULL;
    4553    }
    4654
     55    hash_algo = applet_name[3];
     56
    4757    /* figure specific hash algorithims */
    48     if (ENABLE_MD5SUM && hash_algo==HASH_MD5) {
     58    if (ENABLE_MD5SUM && hash_algo == HASH_MD5) {
    4959        md5_begin(&context.md5);
    50         update = (void (*)(const void*, size_t, void*))md5_hash;
    51         final = (void (*)(void*, void*))md5_end;
     60        update = (void*)md5_hash;
     61        final = (void*)md5_end;
    5262        hash_len = 16;
    53     } else if (ENABLE_SHA1SUM && hash_algo==HASH_SHA1) {
     63    } else if (ENABLE_SHA1SUM && hash_algo == HASH_SHA1) {
    5464        sha1_begin(&context.sha1);
    55         update = (void (*)(const void*, size_t, void*))sha1_hash;
    56         final = (void (*)(void*, void*))sha1_end;
     65        update = (void*)sha1_hash;
     66        final = (void*)sha1_end;
    5767        hash_len = 20;
     68    } else if (ENABLE_SHA256SUM && hash_algo == HASH_SHA256) {
     69        sha256_begin(&context.sha256);
     70        update = (void*)sha256_hash;
     71        final = (void*)sha256_end;
     72        hash_len = 32;
     73    } else if (ENABLE_SHA512SUM && hash_algo == HASH_SHA512) {
     74        sha512_begin(&context.sha512);
     75        update = (void*)sha512_hash;
     76        final = (void*)sha512_end;
     77        hash_len = 64;
    5878    } else {
    59         bb_error_msg_and_die("algorithm not supported");
     79        xfunc_die(); /* can't reach this */
    6080    }
    6181
    62     while (0 < (count = safe_read(src_fd, in_buf, 4096))) {
    63         update(in_buf, count, &context);
     82    while ((count = safe_read(src_fd, in_buf, 4096)) > 0) {
     83        update(&context, in_buf, count);
    6484    }
    6585
    6686    if (count == 0) {
    67         final(in_buf, &context);
     87        final(&context, in_buf);
    6888        hash_value = hash_bin_to_hex(in_buf, hash_len);
    6989    }
     
    7898}
    7999
    80 int md5_sha1_sum_main(int argc, char **argv);
    81 int md5_sha1_sum_main(int argc, char **argv)
     100int md5_sha1_sum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     101int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv)
    82102{
    83103    int return_value = EXIT_SUCCESS;
    84     uint8_t *hash_value;
    85104    unsigned flags;
    86     hash_algo_t hash_algo = ENABLE_MD5SUM
    87         ? (ENABLE_SHA1SUM ? (applet_name[0] == 'm' ? HASH_MD5 : HASH_SHA1) : HASH_MD5)
    88         : HASH_SHA1;
    89105
    90     if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK)
    91         flags = getopt32(argv, "scw");
    92     else optind = 1;
     106    if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK) {
     107        /* -b "binary", -t "text" are ignored (shaNNNsum compat) */
     108        flags = getopt32(argv, "scwbt");
     109        argv += optind;
     110        //argc -= optind;
     111    } else {
     112        argv += 1;
     113        //argc -= 1;
     114    }
     115    if (!*argv)
     116        *--argv = (char*)"-";
    93117
    94118    if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && !(flags & FLAG_CHECK)) {
    95119        if (flags & FLAG_SILENT) {
    96             bb_error_msg_and_die
    97                 ("-%c is meaningful only when verifying checksums", 's');
    98         } else if (flags & FLAG_WARN) {
    99             bb_error_msg_and_die
    100                 ("-%c is meaningful only when verifying checksums", 'w');
     120            bb_error_msg_and_die("-%c is meaningful only with -c", 's');
    101121        }
    102     }
    103 
    104     if (argc == optind) {
    105         argv[argc++] = (char*)"-";
     122        if (flags & FLAG_WARN) {
     123            bb_error_msg_and_die("-%c is meaningful only with -c", 'w');
     124        }
    106125    }
    107126
     
    110129        int count_total = 0;
    111130        int count_failed = 0;
    112         char *file_ptr = argv[optind];
    113131        char *line;
    114132
    115         if (optind + 1 != argc) {
    116             bb_error_msg_and_die
    117                 ("only one argument may be specified when using -c");
     133        if (argv[1]) {
     134            bb_error_msg_and_die("only one argument may be specified with -c");
    118135        }
    119136
    120         pre_computed_stream = stdin;
    121         if (NOT_LONE_DASH(file_ptr)) {
    122             pre_computed_stream = xfopen(file_ptr, "r");
    123         }
     137        pre_computed_stream = xfopen_stdin(argv[0]);
    124138
    125         while ((line = xmalloc_getline(pre_computed_stream)) != NULL) {
     139        while ((line = xmalloc_fgetline(pre_computed_stream)) != NULL) {
     140            uint8_t *hash_value;
    126141            char *filename_ptr;
    127142
     
    144159            filename_ptr += 2;
    145160
    146             hash_value = hash_file(filename_ptr, hash_algo);
     161            hash_value = hash_file(filename_ptr);
    147162
    148163            if (hash_value && (strcmp((char*)hash_value, line) == 0)) {
     
    165180        /*
    166181        if (fclose_if_not_stdin(pre_computed_stream) == EOF) {
    167             bb_perror_msg_and_die("cannot close file %s", file_ptr);
     182            bb_perror_msg_and_die("can't close file %s", file_ptr);
    168183        }
    169184        */
    170185    } else {
    171         while (optind < argc) {
    172             char *file_ptr = argv[optind++];
    173 
    174             hash_value = hash_file(file_ptr, hash_algo);
     186        do {
     187            uint8_t *hash_value = hash_file(*argv);
    175188            if (hash_value == NULL) {
    176189                return_value = EXIT_FAILURE;
    177190            } else {
    178                 printf("%s  %s\n", hash_value, file_ptr);
     191                printf("%s  %s\n", hash_value, *argv);
    179192                free(hash_value);
    180193            }
    181         }
     194        } while (*++argv);
    182195    }
    183196    return return_value;
  • branches/2.2.9/mindi-busybox/coreutils/mkdir.c

    r1765 r2725  
    55 * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    2020 */
    2121
    22 #include <getopt.h> /* struct option */
    2322#include "libbb.h"
    2423
     
    3534#endif
    3635
    37 int mkdir_main(int argc, char **argv);
    38 int mkdir_main(int argc, char **argv)
     36int mkdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     37int mkdir_main(int argc UNUSED_PARAM, char **argv)
    3938{
    4039    mode_t mode = (mode_t)(-1);
     
    5049    applet_long_options = mkdir_longopts;
    5150#endif
    52     opt = getopt32(argv, "m:p" USE_SELINUX("Z:"), &smode USE_SELINUX(,&scontext));
     51    opt = getopt32(argv, "m:p" IF_SELINUX("Z:"), &smode IF_SELINUX(,&scontext));
    5352    if (opt & 1) {
    5453        mode = 0777;
     
    6665#endif
    6766
    68     if (optind == argc) {
     67    argv += optind;
     68    if (!argv[0])
    6969        bb_show_usage();
    70     }
    71 
    72     argv += optind;
    7370
    7471    do {
  • branches/2.2.9/mindi-busybox/coreutils/mkfifo.c

    r1765 r2725  
    55 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1414#include "libcoreutils/coreutils.h"
    1515
    16 int mkfifo_main(int argc, char **argv);
    17 int mkfifo_main(int argc, char **argv)
     16/* This is a NOEXEC applet. Be very careful! */
     17
     18int mkfifo_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     19int mkfifo_main(int argc UNUSED_PARAM, char **argv)
    1820{
    1921    mode_t mode;
    2022    int retval = EXIT_SUCCESS;
    2123
    22     mode = getopt_mk_fifo_nod(argc, argv);
     24    mode = getopt_mk_fifo_nod(argv);
    2325
    2426    argv += optind;
     
    2931    do {
    3032        if (mkfifo(*argv, mode) < 0) {
    31             bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
     33            bb_simple_perror_msg(*argv);  /* Avoid multibyte problems. */
    3234            retval = EXIT_FAILURE;
    3335        }
  • branches/2.2.9/mindi-busybox/coreutils/mknod.c

    r1765 r2725  
    55 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1515#include "libcoreutils/coreutils.h"
    1616
     17/* This is a NOEXEC applet. Be very careful! */
     18
    1719static const char modes_chars[] ALIGN1 = { 'p', 'c', 'u', 'b', 0, 1, 1, 2 };
    1820static const mode_t modes_cubp[] = { S_IFIFO, S_IFCHR, S_IFBLK };
    1921
    20 int mknod_main(int argc, char **argv);
     22int mknod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    2123int mknod_main(int argc, char **argv)
    2224{
     
    2527    const char *name;
    2628
    27     mode = getopt_mk_fifo_nod(argc, argv);
     29    mode = getopt_mk_fifo_nod(argv);
    2830    argv += optind;
    2931    argc -= optind;
    3032
    31     if ((argc >= 2) && ((name = strchr(modes_chars, argv[1][0])) != NULL)) {
    32         mode |= modes_cubp[(int)(name[4])];
     33    if (argc >= 2) {
     34        name = strchr(modes_chars, argv[1][0]);
     35        if (name != NULL) {
     36            mode |= modes_cubp[(int)(name[4])];
    3337
    34         dev = 0;
    35         if ((*name != 'p') && ((argc -= 2) == 2)) {
    36             /* Autodetect what the system supports; these macros should
    37              * optimize out to two constants. */
    38             dev = makedev(xatoul_range(argv[2], 0, major(UINT_MAX)),
    39                           xatoul_range(argv[3], 0, minor(UINT_MAX)));
    40         }
     38            dev = 0;
     39            if (*name != 'p') {
     40                argc -= 2;
     41                if (argc == 2) {
     42                    /* Autodetect what the system supports; these macros should
     43                     * optimize out to two constants. */
     44                    dev = makedev(xatoul_range(argv[2], 0, major(UINT_MAX)),
     45                                  xatoul_range(argv[3], 0, minor(UINT_MAX)));
     46                }
     47            }
    4148
    42         if (argc == 2) {
    43             name = *argv;
    44             if (mknod(name, mode, dev) == 0) {
    45                 return EXIT_SUCCESS;
     49            if (argc == 2) {
     50                name = *argv;
     51                if (mknod(name, mode, dev) == 0) {
     52                    return EXIT_SUCCESS;
     53                }
     54                bb_simple_perror_msg_and_die(name);
    4655            }
    47             bb_perror_msg_and_die("%s", name);
    4856        }
    4957    }
  • branches/2.2.9/mindi-busybox/coreutils/mv.c

    r1765 r2725  
    66 * SELinux support by Yuichi Nakamura <ynakam@hitachisoft.jp>
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
     
    1414 */
    1515
    16 #include <sys/types.h>
    17 #include <sys/stat.h>
    18 #include <dirent.h>
    19 #include <getopt.h> /* struct option */
    2016#include "libbb.h"
    2117#include "libcoreutils/coreutils.h"
     18
     19//usage:#define mv_trivial_usage
     20//usage:       "[-fin] SOURCE DEST\n"
     21//usage:       "or: mv [-fin] SOURCE... DIRECTORY"
     22//usage:#define mv_full_usage "\n\n"
     23//usage:       "Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY\n"
     24//usage:     "\nOptions:"
     25//usage:     "\n    -f  Don't prompt before overwriting"
     26//usage:     "\n    -i  Interactive, prompt before overwrite"
     27//usage:     "\n    -n  Don't overwrite an existing file"
     28//usage:
     29//usage:#define mv_example_usage
     30//usage:       "$ mv /tmp/foo /bin/bar\n"
    2231
    2332#if ENABLE_FEATURE_MV_LONG_OPTIONS
     
    2534    "interactive\0" No_argument "i"
    2635    "force\0"       No_argument "f"
     36    "no-clobber\0"  No_argument "n"
    2737    ;
    2838#endif
     
    3040#define OPT_FILEUTILS_FORCE       1
    3141#define OPT_FILEUTILS_INTERACTIVE 2
     42#define OPT_FILEUTILS_NOCLOBBER   4
    3243
    33 static const char fmt[] ALIGN1 =
    34     "cannot overwrite %sdirectory with %sdirectory";
    35 
    36 int mv_main(int argc, char **argv);
     44int mv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    3745int mv_main(int argc, char **argv)
    3846{
     
    4048    const char *last;
    4149    const char *dest;
    42     unsigned long flags;
     50    unsigned flags;
    4351    int dest_exists;
    4452    int status = 0;
     
    4856    applet_long_options = mv_longopts;
    4957#endif
    50     opt_complementary = "f-i:i-f";
    51     flags = getopt32(argv, "fi");
    52     if (optind + 2 > argc) {
    53         bb_show_usage();
    54     }
     58    /* Need at least two arguments.
     59     * If more than one of -f, -i, -n is specified , only the final one
     60     * takes effect (it unsets previous options). */
     61    opt_complementary = "-2:f-in:i-fn:n-fi";
     62    flags = getopt32(argv, "fin");
     63    argc -= optind;
     64    argv += optind;
     65    last = argv[argc - 1];
    5566
    56     last = argv[argc - 1];
    57     argv += optind;
    58 
    59     if (optind + 2 == argc) {
     67    if (argc == 2) {
    6068        dest_exists = cp_mv_stat(last, &dest_stat);
    6169        if (dest_exists < 0) {
    62             return 1;
     70            return EXIT_FAILURE;
    6371        }
    6472
    65         if (!(dest_exists & 2)) {
     73        if (!(dest_exists & 2)) { /* last is not a directory */
    6674            dest = last;
    6775            goto DO_MOVE;
     
    7078
    7179    do {
    72         dest = concat_path_file(last, bb_get_last_path_component(*argv));
     80        dest = concat_path_file(last, bb_get_last_path_component_strip(*argv));
    7381        dest_exists = cp_mv_stat(dest, &dest_stat);
    7482        if (dest_exists < 0) {
     
    7684        }
    7785
    78 DO_MOVE:
    79 
    80         if (dest_exists && !(flags & OPT_FILEUTILS_FORCE) &&
    81             ((access(dest, W_OK) < 0 && isatty(0)) ||
    82             (flags & OPT_FILEUTILS_INTERACTIVE))) {
    83             if (fprintf(stderr, "mv: overwrite '%s'? ", dest) < 0) {
    84                 goto RET_1; /* Ouch! fprintf failed! */
    85             }
    86             if (!bb_ask_confirmation()) {
     86 DO_MOVE:
     87        if (dest_exists) {
     88            if (flags & OPT_FILEUTILS_NOCLOBBER)
    8789                goto RET_0;
     90            if (!(flags & OPT_FILEUTILS_FORCE)
     91             && ((access(dest, W_OK) < 0 && isatty(0))
     92                || (flags & OPT_FILEUTILS_INTERACTIVE))
     93            ) {
     94                if (fprintf(stderr, "mv: overwrite '%s'? ", dest) < 0) {
     95                    goto RET_1;  /* Ouch! fprintf failed! */
     96                }
     97                if (!bb_ask_confirmation()) {
     98                    goto RET_0;
     99                }
    88100            }
    89101        }
     102
    90103        if (rename(*argv, dest) < 0) {
    91104            struct stat source_stat;
    92105            int source_exists;
    93106
    94             if (errno != EXDEV ||
    95                 (source_exists = cp_mv_stat(*argv, &source_stat)) < 1) {
    96                 bb_perror_msg("cannot rename '%s'", *argv);
     107            if (errno != EXDEV
     108             || (source_exists = cp_mv_stat2(*argv, &source_stat, lstat)) < 1
     109            ) {
     110                bb_perror_msg("can't rename '%s'", *argv);
    97111            } else {
     112                static const char fmt[] ALIGN1 =
     113                    "can't overwrite %sdirectory with %sdirectory";
     114
    98115                if (dest_exists) {
    99116                    if (dest_exists == 3) {
     
    109126                    }
    110127                    if (unlink(dest) < 0) {
    111                         bb_perror_msg("cannot remove '%s'", dest);
     128                        bb_perror_msg("can't remove '%s'", dest);
    112129                        goto RET_1;
    113130                    }
    114131                }
     132                /* FILEUTILS_RECUR also prevents nasties like
     133                 * "read from device and write contents to dst"
     134                 * instead of "create same device node" */
    115135                copy_flag = FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS;
    116136#if ENABLE_SELINUX
    117137                copy_flag |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
    118138#endif
    119                 if ((copy_file(*argv, dest, copy_flag) >= 0) &&
    120                     (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)) {
     139                if ((copy_file(*argv, dest, copy_flag) >= 0)
     140                 && (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)
     141                ) {
    121142                    goto RET_0;
    122143                }
    123144            }
    124 RET_1:
     145 RET_1:
    125146            status = 1;
    126147        }
    127 RET_0:
     148 RET_0:
    128149        if (dest != last) {
    129150            free((void *) dest);
  • branches/2.2.9/mindi-busybox/coreutils/nice.c

    r1765 r2725  
    55 * Copyright (C) 2005  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1111#include "libbb.h"
    1212
    13 int nice_main(int argc, char **argv);
     13int nice_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    1414int nice_main(int argc, char **argv)
    1515{
     
    1818    old_priority = getpriority(PRIO_PROCESS, 0);
    1919
    20     if (!*++argv) { /* No args, so (GNU) output current nice value. */
     20    if (!*++argv) { /* No args, so (GNU) output current nice value. */
    2121        printf("%d\n", old_priority);
    2222        fflush_stdout_and_exit(EXIT_SUCCESS);
    2323    }
    2424
    25     adjustment = 10;            /* Set default adjustment. */
     25    adjustment = 10;  /* Set default adjustment. */
    2626
    2727    if (argv[0][0] == '-') {
     
    3333            argv[0] += 1; argv--; argc++;
    3434        }
    35         if (argc < 4) {         /* Missing priority and/or utility! */
     35        if (argc < 4) {  /* Missing priority and/or utility! */
    3636            bb_show_usage();
    3737        }
     
    4848    }
    4949
    50     BB_EXECVP(*argv, argv);     /* Now exec the desired program. */
    51 
    52     /* The exec failed... */
    53     xfunc_error_retval = (errno == ENOENT) ? 127 : 126; /* SUSv3 */
    54     bb_perror_msg_and_die("%s", *argv);
     50    BB_EXECVP_or_die(argv);
    5551}
  • branches/2.2.9/mindi-busybox/coreutils/nohup.c

    r1765 r2725  
    66 *
    77 * Copyright 2006 Rob Landley <rob@landley.net>
    8  * Copyright 2006 Bernhard Fischer
     8 * Copyright 2006 Bernhard Reutner-Fischer
    99 *
    10  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     10 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1111 */
    1212
    1313#include "libbb.h"
    1414
    15 int nohup_main(int argc, char **argv);
    16 int nohup_main(int argc, char **argv)
     15/* Compat info: nohup (GNU coreutils 6.8) does this:
     16# nohup true
     17nohup: ignoring input and appending output to `nohup.out'
     18# nohup true 1>/dev/null
     19nohup: ignoring input and redirecting stderr to stdout
     20# nohup true 2>zz
     21# cat zz
     22nohup: ignoring input and appending output to `nohup.out'
     23# nohup true 2>zz 1>/dev/null
     24# cat zz
     25nohup: ignoring input
     26# nohup true </dev/null 1>/dev/null
     27nohup: redirecting stderr to stdout
     28# nohup true </dev/null 2>zz 1>/dev/null
     29# cat zz
     30  (nothing)
     31#
     32*/
     33
     34int nohup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     35int nohup_main(int argc UNUSED_PARAM, char **argv)
    1736{
    18     int nullfd;
    1937    const char *nohupout;
    20     char *home = NULL;
     38    char *home;
    2139
    2240    xfunc_error_retval = 127;
    2341
    24     if (argc < 2) bb_show_usage();
     42    if (!argv[1]) {
     43        bb_show_usage();
     44    }
    2545
    26     nullfd = xopen(bb_dev_null, O_WRONLY|O_APPEND);
    2746    /* If stdin is a tty, detach from it. */
    28     if (isatty(STDIN_FILENO))
    29         dup2(nullfd, STDIN_FILENO);
     47    if (isatty(STDIN_FILENO)) {
     48        /* bb_error_msg("ignoring input"); */
     49        close(STDIN_FILENO);
     50        xopen(bb_dev_null, O_RDONLY); /* will be fd 0 (STDIN_FILENO) */
     51    }
    3052
    3153    nohupout = "nohup.out";
     
    3860                nohupout = concat_path_file(home, nohupout);
    3961                xopen3(nohupout, O_CREAT|O_WRONLY|O_APPEND, S_IRUSR|S_IWUSR);
     62            } else {
     63                xopen(bb_dev_null, O_RDONLY); /* will be fd 1 */
    4064            }
    4165        }
    42     } else dup2(nullfd, STDOUT_FILENO);
     66        bb_error_msg("appending output to %s", nohupout);
     67    }
    4368
    44     /* If we have a tty on stderr, announce filename and redirect to stdout.
    45      * Else redirect to /dev/null.
    46      */
     69    /* If we have a tty on stderr, redirect to stdout. */
    4770    if (isatty(STDERR_FILENO)) {
    48         bb_error_msg("appending to %s", nohupout);
     71        /* if (stdout_wasnt_a_tty)
     72            bb_error_msg("redirecting stderr to stdout"); */
    4973        dup2(STDOUT_FILENO, STDERR_FILENO);
    50     } else dup2(nullfd, STDERR_FILENO);
     74    }
    5175
    52     if (nullfd > 2)
    53         close(nullfd);
    5476    signal(SIGHUP, SIG_IGN);
    5577
    56     BB_EXECVP(argv[1], argv+1);
    57     if (ENABLE_FEATURE_CLEAN_UP && home)
    58         free((char*)nohupout);
    59     bb_perror_msg_and_die("%s", argv[1]);
     78    argv++;
     79    BB_EXECVP_or_die(argv);
    6080}
  • branches/2.2.9/mindi-busybox/coreutils/od.c

    r1765 r2725  
    55 *
    66 * Copyright (c) 1990
    7  *  The Regents of the University of California.  All rights reserved.
    8  *
    9  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * The Regents of the University of California.  All rights reserved.
     8 *
     9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1010 *
    1111 * Original copyright notice is retained at the end of this file.
     
    1818#include "od_bloaty.c"
    1919#else
    20 #include <getopt.h>
    2120
    2221#include "dump.h"
    2322
    24 #define isdecdigit(c) isdigit(c)
    25 #define ishexdigit(c) (isxdigit)(c)
    26 
    2723static void
    28 odoffset(int argc, char ***argvp)
     24odoffset(dumper_t *dumper, int argc, char ***argvp)
    2925{
    3026    char *num, *p;
     
    5349    if ((*p != '+')
    5450        && (argc < 2
    55             || (!isdecdigit(p[0])
    56                 && ((p[0] != 'x') || !ishexdigit(p[1])))))
     51            || (!isdigit(p[0])
     52                && ((p[0] != 'x') || !isxdigit(p[1])))))
    5753        return;
    5854
    5955    base = 0;
    6056    /*
    61      * bb_dump_skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
     57     * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
    6258     * set base.
    6359     */
    6460    if (p[0] == '+')
    6561        ++p;
    66     if (p[0] == 'x' && ishexdigit(p[1])) {
     62    if (p[0] == 'x' && isxdigit(p[1])) {
    6763        ++p;
    6864        base = 16;
     
    7268    }
    7369
    74     /* bb_dump_skip over the number */
     70    /* skip over the number */
    7571    if (base == 16)
    76         for (num = p; ishexdigit(*p); ++p);
     72        for (num = p; isxdigit(*p); ++p)
     73            continue;
    7774    else
    78         for (num = p; isdecdigit(*p); ++p);
     75        for (num = p; isdigit(*p); ++p)
     76            continue;
    7977
    8078    /* check for no number */
     
    8987    }
    9088
    91     bb_dump_skip = strtol(num, &end, base ? base : 8);
     89    dumper->dump_skip = strtol(num, &end, base ? base : 8);
    9290
    9391    /* if end isn't the same as p, we got a non-octal digit */
    9492    if (end != p)
    95         bb_dump_skip = 0;
     93        dumper->dump_skip = 0;
    9694    else {
    9795        if (*p) {
    9896            if (*p == 'b') {
    99                 bb_dump_skip *= 512;
     97                dumper->dump_skip *= 512;
    10098                ++p;
    10199            } else if (*p == 'B') {
    102                 bb_dump_skip *= 1024;
     100                dumper->dump_skip *= 1024;
    103101                ++p;
    104102            }
    105103        }
    106104        if (*p)
    107             bb_dump_skip = 0;
     105            dumper->dump_skip = 0;
    108106        else {
    109107            ++*argvp;
     
    113111             * but it's easy.
    114112             */
    115 #define TYPE_OFFSET 7
     113#define TYPE_OFFSET 7
    116114            {
    117115                char x_or_d;
     
    122120                if (base == 10) {
    123121                    x_or_d = 'd';
    124                 DO_X_OR_D:
    125                     bb_dump_fshead->nextfu->fmt[TYPE_OFFSET]
    126                         = bb_dump_fshead->nextfs->nextfu->fmt[TYPE_OFFSET]
     122 DO_X_OR_D:
     123                    dumper->fshead->nextfu->fmt[TYPE_OFFSET]
     124                        = dumper->fshead->nextfs->nextfu->fmt[TYPE_OFFSET]
    127125                        = x_or_d;
    128126                }
     
    133131
    134132static const char *const add_strings[] = {
    135     "16/1 \"%3_u \" \"\\n\"",               /* a */
    136     "8/2 \" %06o \" \"\\n\"",               /* B, o */
    137     "16/1 \"%03o \" \"\\n\"",               /* b */
    138     "16/1 \"%3_c \" \"\\n\"",               /* c */
    139     "8/2 \"  %05u \" \"\\n\"",              /* d */
    140     "4/4 \"     %010u \" \"\\n\"",          /* D */
    141     "2/8 \"          %21.14e \" \"\\n\"",   /* e (undocumented in od), F */
    142     "4/4 \" %14.7e \" \"\\n\"",             /* f */
    143     "4/4 \"       %08x \" \"\\n\"",         /* H, X */
    144     "8/2 \"   %04x \" \"\\n\"",             /* h, x */
    145     "4/4 \"    %11d \" \"\\n\"",            /* I, L, l */
    146     "8/2 \" %6d \" \"\\n\"",                /* i */
    147     "4/4 \"    %011o \" \"\\n\"",           /* O */
     133    "16/1 \"%3_u \" \"\\n\"",              /* a */
     134    "8/2 \" %06o \" \"\\n\"",              /* B, o */
     135    "16/1 \"%03o \" \"\\n\"",              /* b */
     136    "16/1 \"%3_c \" \"\\n\"",              /* c */
     137    "8/2 \"  %05u \" \"\\n\"",             /* d */
     138    "4/4 \"     %010u \" \"\\n\"",         /* D */
     139    "2/8 \"          %21.14e \" \"\\n\"",  /* e (undocumented in od), F */
     140    "4/4 \" %14.7e \" \"\\n\"",            /* f */
     141    "4/4 \"       %08x \" \"\\n\"",        /* H, X */
     142    "8/2 \"   %04x \" \"\\n\"",            /* h, x */
     143    "4/4 \"    %11d \" \"\\n\"",           /* I, L, l */
     144    "8/2 \" %6d \" \"\\n\"",               /* i */
     145    "4/4 \"    %011o \" \"\\n\"",          /* O */
    148146};
    149147
     
    157155};
    158156
    159 int od_main(int argc, char **argv);
     157int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    160158int od_main(int argc, char **argv)
    161159{
     
    163161    int first = 1;
    164162    char *p;
    165     bb_dump_vflag = FIRST;
    166     bb_dump_length = -1;
     163    dumper_t *dumper = alloc_dumper();
    167164
    168165    while ((ch = getopt(argc, argv, od_opts)) > 0) {
    169166        if (ch == 'v') {
    170             bb_dump_vflag = ALL;
     167            dumper->dump_vflag = ALL;
    171168        } else if (((p = strchr(od_opts, ch)) != NULL) && (*p != '\0')) {
    172169            if (first) {
    173170                first = 0;
    174                 bb_dump_add("\"%07.7_Ao\n\"");
    175                 bb_dump_add("\"%07.7_ao  \"");
     171                bb_dump_add(dumper, "\"%07.7_Ao\n\"");
     172                bb_dump_add(dumper, "\"%07.7_ao  \"");
    176173            } else {
    177                 bb_dump_add("\"         \"");
     174                bb_dump_add(dumper, "\"         \"");
    178175            }
    179             bb_dump_add(add_strings[(int)od_o2si[(p-od_opts)]]);
    180         } else {    /* P, p, s, w, or other unhandled */
     176            bb_dump_add(dumper, add_strings[(int)od_o2si[(p - od_opts)]]);
     177        } else {  /* P, p, s, w, or other unhandled */
    181178            bb_show_usage();
    182179        }
    183180    }
    184     if (!bb_dump_fshead) {
    185         bb_dump_add("\"%07.7_Ao\n\"");
    186         bb_dump_add("\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
     181    if (!dumper->fshead) {
     182        bb_dump_add(dumper, "\"%07.7_Ao\n\"");
     183        bb_dump_add(dumper, "\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
    187184    }
    188185
     
    190187    argv += optind;
    191188
    192     odoffset(argc, &argv);
    193 
    194     return bb_dump_dump(argv);
     189    odoffset(dumper, argc, &argv);
     190
     191    return bb_dump_dump(dumper, argv);
    195192}
    196193#endif /* ENABLE_DESKTOP */
  • branches/2.2.9/mindi-busybox/coreutils/od_bloaty.c

    r1765 r2725  
    1818/* Written by Jim Meyering.  */
    1919
    20 /* Busyboxed by Denis Vlasenko
     20/* Busyboxed by Denys Vlasenko
    2121
    2222Based on od.c from coreutils-5.2.1
     
    5151
    5252#include "libbb.h"
    53 #include <getopt.h>
    5453
    5554#define assert(a) ((void)0)
     
    182181   the number of bytes to skip.  */
    183182static off_t pseudo_offset;
    184 /* The number of input bytes to skip before formatting and writing.  */
    185 static off_t n_bytes_to_skip;
    186183/* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
    187184   input is formatted.  */
    188 /* The maximum number of bytes that will be formatted.  */
    189 static off_t max_bytes_to_format;
    190 /* The offset of the first byte after the last byte to be formatted.  */
    191 static off_t end_offset;
    192185
    193186/* The number of input bytes formatted per output line.  It must be
     
    195188   the specified output types.  It should be as large as possible, but
    196189   no larger than 16 -- unless specified with the -w option.  */
    197 static size_t bytes_per_block;
    198 
    199 /* Human-readable representation of *file_list (for error messages).
    200    It differs from *file_list only when *file_list is "-".  */
    201 static char const *input_filename;
     190static unsigned bytes_per_block = 32; /* have to use unsigned, not size_t */
    202191
    203192/* A NULL-terminated list of the file-arguments from the command line.  */
    204 static char const *const *file_list;
    205 
    206 /* Initializer for file_list if no file-arguments
    207    were specified on the command line.  */
    208 static char const *const default_file_list[] = { "-", NULL };
     193static const char *const *file_list;
    209194
    210195/* The input stream associated with the current file.  */
     
    212197
    213198#define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t)
    214 static unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] ALIGN1 = {
     199static const unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] ALIGN1 = {
    215200    [sizeof(char)] = CHAR,
    216201#if USHRT_MAX != UCHAR_MAX
     
    229214
    230215#define MAX_FP_TYPE_SIZE sizeof(longdouble_t)
    231 static unsigned char fp_type_size[MAX_FP_TYPE_SIZE + 1] ALIGN1 = {
     216static const unsigned char fp_type_size[MAX_FP_TYPE_SIZE + 1] ALIGN1 = {
    232217    /* gcc seems to allow repeated indexes. Last one stays */
    233218    [sizeof(longdouble_t)] = FLOAT_LONG_DOUBLE,
     
    375360
    376361/* print_[named]_ascii are optimized for speed.
    377  * Remember, someday you may want to pump gigabytes thru this thing.
     362 * Remember, someday you may want to pump gigabytes through this thing.
    378363 * Saving a dozen of .text bytes here is counter-productive */
    379364
    380365static void
    381366print_named_ascii(size_t n_bytes, const char *block,
    382         const char *unused_fmt_string ATTRIBUTE_UNUSED)
     367        const char *unused_fmt_string UNUSED_PARAM)
    383368{
    384369    /* Names for some non-printing characters.  */
     
    420405static void
    421406print_ascii(size_t n_bytes, const char *block,
    422         const char *unused_fmt_string ATTRIBUTE_UNUSED)
     407        const char *unused_fmt_string UNUSED_PARAM)
    423408{
    424409    // buf[N] pos:  01234 56789
     
    482467{
    483468    while (1) {
    484         input_filename = *file_list;
    485         if (!input_filename)
     469        if (!*file_list)
    486470            return;
    487         file_list++;
    488         in_stream = fopen_or_warn_stdin(input_filename);
     471        in_stream = fopen_or_warn_stdin(*file_list++);
    489472        if (in_stream) {
    490             if (in_stream == stdin)
    491                 input_filename = bb_msg_standard_input;
    492473            break;
    493474        }
     
    511492    if (in_stream) {
    512493        if (ferror(in_stream))  {
    513             bb_error_msg("%s: read error", input_filename);
     494            bb_error_msg("%s: read error", (in_stream == stdin)
     495                    ? bb_msg_standard_input
     496                    : file_list[-1]
     497            );
    514498            ioerror = 1;
    515499        }
     
    519503
    520504    if (ferror(stdout)) {
    521         bb_error_msg("write error");
     505        bb_error_msg(bb_msg_write_error);
    522506        ioerror = 1;
    523507    }
     
    525509
    526510/* If S points to a single valid modern od format string, put
    527    a description of that format in *TSPEC, make *NEXT point at the
    528    character following the just-decoded format (if *NEXT is non-NULL),
    529    and return zero.  For example, if S were "d4afL"
    530    *NEXT would be set to "afL" and *TSPEC would be
     511   a description of that format in *TSPEC, return pointer to
     512   character following the just-decoded format.
     513   For example, if S were "d4afL", we will return a rtp to "afL"
     514   and *TSPEC would be
    531515    {
    532516        fmt = SIGNED_DECIMAL;
     
    538522   string argument. */
    539523
    540 static void
    541 decode_one_format(const char *s_orig, const char *s, const char **next,
    542                        struct tspec *tspec)
     524static NOINLINE const char *
     525decode_one_format(const char *s_orig, const char *s, struct tspec *tspec)
    543526{
    544527    enum size_spec size_spec;
     
    553536    int pos;
    554537
    555     assert(tspec != NULL);
    556538
    557539    switch (*s) {
     
    564546        c = *s++;
    565547        p = strchr(CSIL, *s);
    566         if (!p) {
     548        /* if *s == NUL, p != NULL! Testcase: "od -tx" */
     549        if (!p || *p == '\0') {
    567550            size = sizeof(int);
    568551            if (isdigit(s[0])) {
     
    579562            }
    580563        } else {
    581             static const uint8_t CSIL_sizeof[] = {
     564            static const uint8_t CSIL_sizeof[4] = {
    582565                sizeof(char),
    583566                sizeof(short),
     
    586569            };
    587570            size = CSIL_sizeof[p - CSIL];
     571            s++; /* skip C/S/I/L */
    588572        }
    589573
     
    733717        s++;
    734718
    735     if (next != NULL)
    736         *next = s;
     719    return s;
    737720}
    738721
    739722/* Decode the modern od format string S.  Append the decoded
    740723   representation to the global array SPEC, reallocating SPEC if
    741    necessary.  Return zero if S is valid, nonzero otherwise.  */
     724   necessary.  */
    742725
    743726static void
     
    750733        const char *next;
    751734
    752         decode_one_format(s_orig, s, &next, &tspec);
     735        next = decode_one_format(s_orig, s, &tspec);
    753736
    754737        assert(s != next);
    755738        s = next;
     739        spec = xrealloc_vector(spec, 4, n_specs);
     740        memcpy(&spec[n_specs], &tspec, sizeof(spec[0]));
    756741        n_specs++;
    757         spec = xrealloc(spec, n_specs * sizeof(*spec));
    758         memcpy(&spec[n_specs-1], &tspec, sizeof *spec);
    759742    }
    760743}
     
    792775               decrement n_skip and go on to the next file.  */
    793776        if (fstat(fileno(in_stream), &file_stats) == 0
    794          && S_ISREG(file_stats.st_mode) && file_stats.st_size >= 0
     777         && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
    795778        ) {
    796779            if (file_stats.st_size < n_skip) {
    797780                n_skip -= file_stats.st_size;
    798                 /* take check&close / open_next route */
     781                /* take "check & close / open_next" route */
    799782            } else {
    800783                if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
     
    803786            }
    804787        } else {
    805             /* If it's not a regular file with nonnegative size,
     788            /* If it's not a regular file with positive size,
    806789               position the file pointer by reading.  */
    807             char buf[BUFSIZ];
    808             size_t n_bytes_read, n_bytes_to_read = BUFSIZ;
     790            char buf[1024];
     791            size_t n_bytes_to_read = 1024;
     792            size_t n_bytes_read;
    809793
    810794            while (n_skip > 0) {
     
    825809
    826810    if (n_skip)
    827         bb_error_msg_and_die("cannot skip past end of combined input");
     811        bb_error_msg_and_die("can't skip past end of combined input");
    828812}
    829813
     
    832816
    833817static void
    834 format_address_none(off_t address ATTRIBUTE_UNUSED, char c ATTRIBUTE_UNUSED)
     818format_address_none(off_t address UNUSED_PARAM, char c UNUSED_PARAM)
    835819{
    836820}
     
    850834}
    851835
    852 #if ENABLE_GETOPT_LONG
     836#if ENABLE_LONG_OPTS
    853837/* only used with --traditional */
    854838static void
     
    971955}
    972956
    973 #if ENABLE_GETOPT_LONG
     957#if ENABLE_LONG_OPTS
    974958/* If S is a valid traditional offset specification with an optional
    975959   leading '+' return nonzero and set *OFFSET to the offset it denotes.  */
     
    981965        { "B", 1024 },
    982966        { "b", 512 },
    983         { }
     967        { "", 0 }
    984968    };
    985969    char *p;
     
    1015999   multiple of all format spec sizes.  Write the final block.  Finally,
    10161000   write on a line by itself the offset of the byte after the last byte
    1017    read.  Accumulate return values from calls to read_block and
    1018    check_and_close, and if any was nonzero, return nonzero.
    1019    Otherwise, return zero.  */
    1020 
    1021 static void
    1022 dump(void)
     1001   read.  */
     1002
     1003static void
     1004dump(off_t current_offset, off_t end_offset)
    10231005{
    10241006    char *block[2];
    1025     off_t current_offset;
    10261007    int idx;
    10271008    size_t n_bytes_read;
     
    10291010    block[0] = xmalloc(2*bytes_per_block);
    10301011    block[1] = block[0] + bytes_per_block;
    1031 
    1032     current_offset = n_bytes_to_skip;
    10331012
    10341013    idx = 0;
     
    10961075   Then try to read a byte from the newly opened file.  Repeat if
    10971076   necessary until EOF is reached for the last file in FILE_LIST, then
    1098    set *C to EOF and return.  Subsequent calls do likewise.  The return
    1099    value is nonzero if any errors occured, zero otherwise.  */
     1077   set *C to EOF and return.  Subsequent calls do likewise.  */
    11001078
    11011079static void
     
    11301108   graphic (or formatting) characters terminated by a null.
    11311109   Based on a function written by Richard Stallman for a
    1132    traditional version of od.  Return nonzero if an error
    1133    occurs.  Otherwise, return zero.  */
    1134 
    1135 static void
    1136 dump_strings(void)
     1110   traditional version of od.  */
     1111
     1112static void
     1113dump_strings(off_t address, off_t end_offset)
    11371114{
    11381115    size_t bufsize = MAX(100, string_min);
    11391116    char *buf = xmalloc(bufsize);
    1140     off_t address = n_bytes_to_skip;
    11411117
    11421118    while (1) {
     
    11701146            goto tryline;
    11711147
    1172         /* If we get here, the string is all printable and null-terminated,
     1148        /* If we get here, the string is all printable and NUL-terminated,
    11731149         * so print it.  It is all in 'buf' and 'i' is its length.  */
    11741150        buf[i] = 0;
     
    11841160            case '\t': fputs("\\t", stdout); break;
    11851161            case '\v': fputs("\\v", stdout); break;
    1186             default: putc(c, stdout);
     1162            default: putchar(c);
    11871163            }
    11881164        }
     
    11971173}
    11981174
    1199 int od_main(int argc, char **argv);
     1175int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    12001176int od_main(int argc, char **argv)
    12011177{
     
    12041180        { "k", 1024 },
    12051181        { "m", 1024*1024 },
    1206         { }
     1182        { "", 0 }
    12071183    };
    1208     unsigned opt;
    1209     int l_c_m;
    1210     /* The old-style 'pseudo starting address' to be printed in parentheses
    1211        after any true address.  */
    1212     off_t pseudo_start = 0; // only for gcc
    12131184    enum {
    12141185        OPT_A = 1 << 0,
     
    12301201        OPT_S = 1 << 16,
    12311202        OPT_w = 1 << 17,
    1232         OPT_traditional = (1 << 18) * ENABLE_GETOPT_LONG,
     1203        OPT_traditional = (1 << 18) * ENABLE_LONG_OPTS,
    12331204    };
    1234 #if ENABLE_GETOPT_LONG
     1205#if ENABLE_LONG_OPTS
    12351206    static const char od_longopts[] ALIGN1 =
    12361207        "skip-bytes\0"        Required_argument "j"
     
    12451216#endif
    12461217    char *str_A, *str_N, *str_j, *str_S;
    1247     char *str_w = NULL;
    12481218    llist_t *lst_t = NULL;
     1219    unsigned opt;
     1220    int l_c_m;
     1221    /* The old-style 'pseudo starting address' to be printed in parentheses
     1222       after any true address.  */
     1223    off_t pseudo_start = pseudo_start; // for gcc
     1224    /* The number of input bytes to skip before formatting and writing.  */
     1225    off_t n_bytes_to_skip = 0;
     1226    /* The offset of the first byte after the last byte to be formatted.  */
     1227    off_t end_offset = 0;
     1228    /* The maximum number of bytes that will be formatted.  */
     1229    off_t max_bytes_to_format = 0;
    12491230
    12501231    spec = NULL;
     
    12551236
    12561237    /* Parse command line */
    1257     opt_complementary = "t::"; // list
    1258 #if ENABLE_GETOPT_LONG
     1238    opt_complementary = "w+:t::"; /* -w N, -t is a list */
     1239#if ENABLE_LONG_OPTS
    12591240    applet_long_options = od_longopts;
    12601241#endif
     
    12641245        // but in coreutils 6.3 it was renamed and now has
    12651246        // _mandatory_ parameter
    1266         &str_A, &str_N, &str_j, &lst_t, &str_S, &str_w);
     1247        &str_A, &str_N, &str_j, &lst_t, &str_S, &bytes_per_block);
    12671248    argc -= optind;
    12681249    argv += optind;
     
    13021283    //if (opt & OPT_t)...
    13031284    while (lst_t) {
    1304         decode_format_string(lst_t->data);
    1305         lst_t = lst_t->link;
     1285        decode_format_string(llist_pop(&lst_t));
    13061286    }
    13071287    if (opt & OPT_v) verbose = 1;
     
    13281308     * traditional syntax even if --traditional is not given.  */
    13291309
    1330 #if ENABLE_GETOPT_LONG
     1310#if ENABLE_LONG_OPTS
    13311311    if (opt & OPT_traditional) {
    13321312        off_t o1, o2;
     
    14001380       set the global pointer FILE_LIST so that it
    14011381       references the null-terminated list of one name: "-".  */
    1402     file_list = default_file_list;
     1382    file_list = bb_argv_dash;
    14031383    if (argc > 0) {
    14041384        /* Set the global pointer FILE_LIST so that it
     
    14121392    skip(n_bytes_to_skip);
    14131393    if (!in_stream)
    1414         return 1;
     1394        return EXIT_FAILURE;
    14151395
    14161396    pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0);
     
    14201400
    14211401    if (opt & OPT_w) { /* -w: width */
    1422         bytes_per_block = 32;
    1423         if (str_w)
    1424             bytes_per_block = xatou(str_w);
    14251402        if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
    1426             bb_error_msg("warning: invalid width %zu; using %d instead",
    1427                     bytes_per_block, l_c_m);
     1403            bb_error_msg("warning: invalid width %u; using %d instead",
     1404                    (unsigned)bytes_per_block, l_c_m);
    14281405            bytes_per_block = l_c_m;
    14291406        }
     
    14421419
    14431420    if (flag_dump_strings)
    1444         dump_strings();
     1421        dump_strings(n_bytes_to_skip, end_offset);
    14451422    else
    1446         dump();
     1423        dump(n_bytes_to_skip, end_offset);
    14471424
    14481425    if (fclose(stdin) == EOF)
  • branches/2.2.9/mindi-busybox/coreutils/printenv.c

    r1765 r2725  
    66 * Copyright (C) 2005 by Mike Frysinger <vapier@gentoo.org>
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
    1111#include "libbb.h"
    12 extern char **environ;
    1312
    14 int printenv_main(int argc, char **argv);
    15 int printenv_main(int argc, char **argv)
     13/* This is a NOFORK applet. Be very careful! */
     14
     15int printenv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     16int printenv_main(int argc UNUSED_PARAM, char **argv)
    1617{
     18    int exit_code = EXIT_SUCCESS;
     19
    1720    /* no variables specified, show whole env */
    18     if (argc == 1) {
     21    if (!argv[1]) {
    1922        int e = 0;
    2023        while (environ[e])
     
    2831            if (env)
    2932                puts(env);
     33            else
     34                exit_code = EXIT_FAILURE;
    3035        }
    3136    }
    3237
    33     fflush_stdout_and_exit(0);
     38    fflush_stdout_and_exit(exit_code);
    3439}
  • branches/2.2.9/mindi-busybox/coreutils/printf.c

    r1765 r2725  
    55   Portions copyright (C) 1990-1996 Free Software Foundation, Inc.
    66
    7    Licensed under GPL v2 or later, see file LICENSE in this tarball for details.
     7   Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88*/
    99
     
    3434   to convert all of the given arguments.
    3535
    36    David MacKenzie <djm@gnu.ai.mit.edu> */
    37 
     36   David MacKenzie <djm@gnu.ai.mit.edu>
     37*/
    3838
    3939//   19990508 Busy Boxed! Dave Cinege
     
    4141#include "libbb.h"
    4242
    43 typedef void (*converter)(const char *arg, void *result);
    44 
    45 static void multiconvert(const char *arg, void *result, converter convert)
    46 {
    47     char s[sizeof(int)*3 + 2];
    48 
     43/* A note on bad input: neither bash 3.2 nor coreutils 6.10 stop on it.
     44 * They report it:
     45 *  bash: printf: XXX: invalid number
     46 *  printf: XXX: expected a numeric value
     47 *  bash: printf: 123XXX: invalid number
     48 *  printf: 123XXX: value not completely converted
     49 * but then they use 0 (or partially converted numeric prefix) as a value
     50 * and continue. They exit with 1 in this case.
     51 * Both accept insane field width/precision (e.g. %9999999999.9999999999d).
     52 * Both print error message and assume 0 if %*.*f width/precision is "bad"
     53 *  (but negative numbers are not "bad").
     54 * Both accept negative numbers for %u specifier.
     55 *
     56 * We try to be compatible.
     57 */
     58
     59typedef void FAST_FUNC (*converter)(const char *arg, void *result);
     60
     61static int multiconvert(const char *arg, void *result, converter convert)
     62{
    4963    if (*arg == '"' || *arg == '\'') {
    50         sprintf(s, "%d", (unsigned char)arg[1]);
    51         arg = s;
    52     }
     64        arg = utoa((unsigned char)arg[1]);
     65    }
     66    errno = 0;
    5367    convert(arg, result);
    54     /* if there was conversion error, print unconverted string */
    55     if (errno)
    56         fputs(arg, stderr);
    57 }
    58 
    59 static void conv_strtoul(const char *arg, void *result)
    60 {
    61     *(unsigned long*)result = bb_strtoul(arg, NULL, 0);
    62 }
    63 static void conv_strtol(const char *arg, void *result)
    64 {
    65     *(long*)result = bb_strtol(arg, NULL, 0);
    66 }
    67 static void conv_strtod(const char *arg, void *result)
     68    if (errno) {
     69        bb_error_msg("invalid number '%s'", arg);
     70        return 1;
     71    }
     72    return 0;
     73}
     74
     75static void FAST_FUNC conv_strtoull(const char *arg, void *result)
     76{
     77    *(unsigned long long*)result = bb_strtoull(arg, NULL, 0);
     78    /* both coreutils 6.10 and bash 3.2:
     79     * $ printf '%x\n' -2
     80     * fffffffffffffffe
     81     * Mimic that:
     82     */
     83    if (errno) {
     84        *(unsigned long long*)result = bb_strtoll(arg, NULL, 0);
     85    }
     86}
     87static void FAST_FUNC conv_strtoll(const char *arg, void *result)
     88{
     89    *(long long*)result = bb_strtoll(arg, NULL, 0);
     90}
     91static void FAST_FUNC conv_strtod(const char *arg, void *result)
    6892{
    6993    char *end;
    70     /* Well, this one allows leading whitespace... so what */
    71     /* What I like much less is that "-" is accepted too! :( */
     94    /* Well, this one allows leading whitespace... so what? */
     95    /* What I like much less is that "-" accepted too! :( */
    7296    *(double*)result = strtod(arg, &end);
    73     if (end[0]) errno = ERANGE;
    74 }
    75 
    76 static unsigned long my_xstrtoul(const char *arg)
    77 {
    78     unsigned long result;
    79     multiconvert(arg, &result, conv_strtoul);
     97    if (end[0]) {
     98        errno = ERANGE;
     99        *(double*)result = 0;
     100    }
     101}
     102
     103/* Callers should check errno to detect errors */
     104static unsigned long long my_xstrtoull(const char *arg)
     105{
     106    unsigned long long result;
     107    if (multiconvert(arg, &result, conv_strtoull))
     108        result = 0;
    80109    return result;
    81110}
    82 
    83 static long my_xstrtol(const char *arg)
    84 {
    85     long result;
    86     multiconvert(arg, &result, conv_strtol);
     111static long long my_xstrtoll(const char *arg)
     112{
     113    long long result;
     114    if (multiconvert(arg, &result, conv_strtoll))
     115        result = 0;
    87116    return result;
    88117}
    89 
    90118static double my_xstrtod(const char *arg)
    91119{
     
    95123}
    96124
    97 static void print_esc_string(char *str)
    98 {
    99     for (; *str; str++) {
    100         if (*str == '\\') {
    101             str++;
    102             putchar(bb_process_escape_sequence((const char **)&str));
    103         } else {
    104             putchar(*str);
    105         }
    106 
    107     }
    108 }
    109 
    110 static void print_direc(char *start, size_t length, int field_width, int precision,
     125static void print_esc_string(const char *str)
     126{
     127    char c;
     128    while ((c = *str) != '\0') {
     129        str++;
     130        if (c == '\\')
     131            c = bb_process_escape_sequence(&str);
     132        putchar(c);
     133    }
     134}
     135
     136static void print_direc(char *format, unsigned fmt_length,
     137        int field_width, int precision,
    111138        const char *argument)
    112139{
    113     char *p;        /* Null-terminated copy of % directive. */
    114 
    115     p = xmalloc((unsigned) (length + 1));
    116     strncpy(p, start, length);
    117     p[length] = 0;
    118 
    119     switch (p[length - 1]) {
     140    long long llv;
     141    double dv;
     142    char saved;
     143    char *have_prec, *have_width;
     144
     145    saved = format[fmt_length];
     146    format[fmt_length] = '\0';
     147
     148    have_prec = strstr(format, ".*");
     149    have_width = strchr(format, '*');
     150    if (have_width - 1 == have_prec)
     151        have_width = NULL;
     152
     153    errno = 0;
     154
     155    switch (format[fmt_length - 1]) {
     156    case 'c':
     157        printf(format, *argument);
     158        break;
    120159    case 'd':
    121160    case 'i':
    122         if (field_width < 0) {
    123             if (precision < 0)
    124                 printf(p, my_xstrtol(argument));
     161        llv = my_xstrtoll(argument);
     162 print_long:
     163        if (!have_width) {
     164            if (!have_prec)
     165                printf(format, llv);
    125166            else
    126                 printf(p, precision, my_xstrtol(argument));
     167                printf(format, precision, llv);
    127168        } else {
    128             if (precision < 0)
    129                 printf(p, field_width, my_xstrtol(argument));
     169            if (!have_prec)
     170                printf(format, field_width, llv);
    130171            else
    131                 printf(p, field_width, precision, my_xstrtol(argument));
     172                printf(format, field_width, precision, llv);
    132173        }
    133174        break;
     
    136177    case 'x':
    137178    case 'X':
    138         if (field_width < 0) {
    139             if (precision < 0)
    140                 printf(p, my_xstrtoul(argument));
    141             else
    142                 printf(p, precision, my_xstrtoul(argument));
     179        llv = my_xstrtoull(argument);
     180        /* cheat: unsigned long and long have same width, so... */
     181        goto print_long;
     182    case 's':
     183        /* Are char* and long long the same? */
     184        if (sizeof(argument) == sizeof(llv)) {
     185            llv = (long long)(ptrdiff_t)argument;
     186            goto print_long;
    143187        } else {
    144             if (precision < 0)
    145                 printf(p, field_width, my_xstrtoul(argument));
    146             else
    147                 printf(p, field_width, precision, my_xstrtoul(argument));
     188            /* Hope compiler will optimize it out by moving call
     189             * instruction after the ifs... */
     190            if (!have_width) {
     191                if (!have_prec)
     192                    printf(format, argument, /*unused:*/ argument, argument);
     193                else
     194                    printf(format, precision, argument, /*unused:*/ argument);
     195            } else {
     196                if (!have_prec)
     197                    printf(format, field_width, argument, /*unused:*/ argument);
     198                else
     199                    printf(format, field_width, precision, argument);
     200            }
     201            break;
    148202        }
    149         break;
    150203    case 'f':
    151204    case 'e':
     
    153206    case 'g':
    154207    case 'G':
    155         if (field_width < 0) {
    156             if (precision < 0)
    157                 printf(p, my_xstrtod(argument));
     208        dv = my_xstrtod(argument);
     209        if (!have_width) {
     210            if (!have_prec)
     211                printf(format, dv);
    158212            else
    159                 printf(p, precision, my_xstrtod(argument));
     213                printf(format, precision, dv);
    160214        } else {
    161             if (precision < 0)
    162                 printf(p, field_width, my_xstrtod(argument));
     215            if (!have_prec)
     216                printf(format, field_width, dv);
    163217            else
    164                 printf(p, field_width, precision, my_xstrtod(argument));
     218                printf(format, field_width, precision, dv);
    165219        }
    166220        break;
    167     case 'c':
    168         printf(p, *argument);
    169         break;
    170     case 's':
    171         if (field_width < 0) {
    172             if (precision < 0)
    173                 printf(p, argument);
    174             else
    175                 printf(p, precision, argument);
    176         } else {
    177             if (precision < 0)
    178                 printf(p, field_width, argument);
    179             else
    180                 printf(p, field_width, precision, argument);
    181         }
    182         break;
    183     }
    184 
    185     free(p);
    186 }
    187 
    188 /* Print the text in FORMAT, using ARGV (with ARGC elements) for
    189    arguments to any '%' directives.
    190    Return the number of elements of ARGV used.  */
    191 
    192 static int print_formatted(char *format, int argc, char **argv)
    193 {
    194     int save_argc = argc;   /* Preserve original value.  */
    195     char *f;                /* Pointer into 'format'.  */
     221    } /* switch */
     222
     223    format[fmt_length] = saved;
     224}
     225
     226/* Handle params for "%*.*f". Negative numbers are ok (compat). */
     227static int get_width_prec(const char *str)
     228{
     229    int v = bb_strtoi(str, NULL, 10);
     230    if (errno) {
     231        bb_error_msg("invalid number '%s'", str);
     232        v = 0;
     233    }
     234    return v;
     235}
     236
     237/* Print the text in FORMAT, using ARGV for arguments to any '%' directives.
     238   Return advanced ARGV.  */
     239static char **print_formatted(char *f, char **argv, int *conv_err)
     240{
    196241    char *direc_start;      /* Start of % directive.  */
    197     size_t direc_length;    /* Length of % directive.  */
    198     int field_width;        /* Arg to first '*', or -1 if none.  */
    199     int precision;          /* Arg to second '*', or -1 if none.  */
    200 
    201     for (f = format; *f; ++f) {
     242    unsigned direc_length;  /* Length of % directive.  */
     243    int field_width;        /* Arg to first '*' */
     244    int precision;          /* Arg to second '*' */
     245    char **saved_argv = argv;
     246
     247    for (; *f; ++f) {
    202248        switch (*f) {
    203249        case '%':
    204250            direc_start = f++;
    205251            direc_length = 1;
    206             field_width = precision = -1;
     252            field_width = precision = 0;
    207253            if (*f == '%') {
    208                 putchar('%');
     254                bb_putchar('%');
    209255                break;
    210256            }
    211257            if (*f == 'b') {
    212                 if (argc > 0) {
     258                if (*argv) {
    213259                    print_esc_string(*argv);
    214260                    ++argv;
    215                     --argc;
    216261                }
    217262                break;
     
    224269                ++f;
    225270                ++direc_length;
    226                 if (argc > 0) {
    227                     field_width = my_xstrtoul(*argv);
    228                     ++argv;
    229                     --argc;
    230                 } else
    231                     field_width = 0;
     271                if (*argv)
     272                    field_width = get_width_prec(*argv++);
    232273            } else {
    233274                while (isdigit(*f)) {
     
    242283                    ++f;
    243284                    ++direc_length;
    244                     if (argc > 0) {
    245                         precision = my_xstrtoul(*argv);
    246                         ++argv;
    247                         --argc;
    248                     } else
    249                         precision = 0;
    250                 } else
     285                    if (*argv)
     286                        precision = get_width_prec(*argv++);
     287                } else {
    251288                    while (isdigit(*f)) {
    252289                        ++f;
    253290                        ++direc_length;
    254291                    }
    255             }
    256             if (*f == 'l' || *f == 'L' || *f == 'h') {
    257                 ++f;
     292                }
     293            }
     294
     295            /* Remove "lLhz" size modifiers, repeatedly.
     296             * bash does not like "%lld", but coreutils
     297             * happily takes even "%Llllhhzhhzd"!
     298             * We are permissive like coreutils */
     299            while ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') {
     300                overlapping_strcpy(f, f + 1);
     301            }
     302            /* Add "ll" if integer modifier, then print */
     303            {
     304                static const char format_chars[] ALIGN1 = "diouxXfeEgGcs";
     305                char *p = strchr(format_chars, *f);
     306                /* needed - try "printf %" without it */
     307                if (p == NULL) {
     308                    bb_error_msg("%s: invalid format", direc_start);
     309                    /* causes main() to exit with error */
     310                    return saved_argv - 1;
     311                }
    258312                ++direc_length;
    259             }
    260             /*
    261             if (!strchr ("diouxXfeEgGcs", *f))
    262             fprintf(stderr, "%%%c: invalid directive", *f);
    263             */
    264             ++direc_length;
    265             if (argc > 0) {
    266                 print_direc(direc_start, direc_length, field_width,
    267                             precision, *argv);
    268                 ++argv;
    269                 --argc;
    270             } else
    271                 print_direc(direc_start, direc_length, field_width,
    272                             precision, "");
     313                if (p - format_chars <= 5) {
     314                    /* it is one of "diouxX" */
     315                    p = xmalloc(direc_length + 3);
     316                    memcpy(p, direc_start, direc_length);
     317                    p[direc_length + 1] = p[direc_length - 1];
     318                    p[direc_length - 1] = 'l';
     319                    p[direc_length] = 'l';
     320                    //bb_error_msg("<%s>", p);
     321                    direc_length += 2;
     322                    direc_start = p;
     323                } else {
     324                    p = NULL;
     325                }
     326                if (*argv) {
     327                    print_direc(direc_start, direc_length, field_width,
     328                                precision, *argv++);
     329                } else {
     330                    print_direc(direc_start, direc_length, field_width,
     331                                precision, "");
     332                }
     333                *conv_err |= errno;
     334                free(p);
     335            }
    273336            break;
    274337        case '\\':
    275             if (*++f == 'c')
    276                 exit(0);
    277             putchar(bb_process_escape_sequence((const char **)&f));
     338            if (*++f == 'c') {
     339                return saved_argv; /* causes main() to exit */
     340            }
     341            bb_putchar(bb_process_escape_sequence((const char **)&f));
    278342            f--;
    279343            break;
     
    283347    }
    284348
    285     return save_argc - argc;
    286 }
    287 
    288 int printf_main(int argc, char **argv);
    289 int printf_main(int argc, char **argv)
    290 {
     349    return argv;
     350}
     351
     352int printf_main(int argc UNUSED_PARAM, char **argv)
     353{
     354    int conv_err;
    291355    char *format;
    292     int args_used;
    293 
    294     if (argc <= 1 || argv[1][0] == '-') {
     356    char **argv2;
     357
     358    /* We must check that stdout is not closed.
     359     * The reason for this is highly non-obvious.
     360     * printf_main is used from shell.
     361     * Shell must correctly handle 'printf "%s" foo'
     362     * if stdout is closed. With stdio, output gets shoveled into
     363     * stdout buffer, and even fflush cannot clear it out. It seems that
     364     * even if libc receives EBADF on write attempts, it feels determined
     365     * to output data no matter what. So it will try later,
     366     * and possibly will clobber future output. Not good. */
     367// TODO: check fcntl() & O_ACCMODE == O_WRONLY or O_RDWR?
     368    if (fcntl(1, F_GETFL) == -1)
     369        return 1; /* match coreutils 6.10 (sans error msg to stderr) */
     370    //if (dup2(1, 1) != 1) - old way
     371    //  return 1;
     372
     373    /* bash builtin errors out on "printf '-%s-\n' foo",
     374     * coreutils-6.9 works. Both work with "printf -- '-%s-\n' foo".
     375     * We will mimic coreutils. */
     376    if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && !argv[1][2])
     377        argv++;
     378    if (!argv[1]) {
     379        if (ENABLE_ASH_BUILTIN_PRINTF
     380         && applet_name[0] != 'p'
     381        ) {
     382            bb_error_msg("usage: printf FORMAT [ARGUMENT...]");
     383            return 2; /* bash compat */
     384        }
    295385        bb_show_usage();
    296386    }
    297387
    298388    format = argv[1];
    299     argc -= 2;
    300     argv += 2;
    301 
     389    argv2 = argv + 2;
     390
     391    conv_err = 0;
    302392    do {
    303         args_used = print_formatted(format, argc, argv);
    304         argc -= args_used;
    305         argv += args_used;
    306     } while (args_used > 0 && argc > 0);
    307 
    308 /*  if (argc > 0)
     393        argv = argv2;
     394        argv2 = print_formatted(format, argv, &conv_err);
     395    } while (argv2 > argv && *argv2);
     396
     397    /* coreutils compat (bash doesn't do this):
     398    if (*argv)
    309399        fprintf(stderr, "excess args ignored");
    310 */
    311 
    312     return EXIT_SUCCESS;
    313 }
     400    */
     401
     402    return (argv2 < argv) /* if true, print_formatted errored out */
     403        || conv_err; /* print_formatted saw invalid number */
     404}
  • branches/2.2.9/mindi-busybox/coreutils/pwd.c

    r1765 r2725  
    55 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1212/* This is a NOFORK applet. Be very careful! */
    1313
    14 int pwd_main(int argc, char **argv);
    15 int pwd_main(int argc, char **argv)
     14int pwd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     15int pwd_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
    1616{
    1717    char *buf;
     
    2121        puts(buf);
    2222        free(buf);
    23         return fflush(stdout);
     23        return fflush_all();
    2424    }
    2525
  • branches/2.2.9/mindi-busybox/coreutils/readlink.c

    r1765 r2725  
    55 * Copyright (C) 2000,2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>
    66 *
    7  * Licensed under GPL v2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
     8 */
     9#include "libbb.h"
     10
     11/*
     12 * # readlink --version
     13 * readlink (GNU coreutils) 6.10
     14 * # readlink --help
     15 *   -f, --canonicalize
     16 *      canonicalize by following every symlink in
     17 *      every component of the given name recursively;
     18 *      all but the last component must exist
     19 *   -e, --canonicalize-existing
     20 *      canonicalize by following every symlink in
     21 *      every component of the given name recursively,
     22 *      all components must exist
     23 *   -m, --canonicalize-missing
     24 *      canonicalize by following every symlink in
     25 *      every component of the given name recursively,
     26 *      without requirements on components existence
     27 *   -n, --no-newline              do not output the trailing newline
     28 *   -q, --quiet, -s, --silent     suppress most error messages
     29 *   -v, --verbose                 report error messages
     30 *
     31 * bbox supports: -f -n -v (fully), -q -s (accepts but ignores)
    832 */
    933
    10 #include <getopt.h>
    11 
    12 #include "libbb.h"
    13 
    14 int readlink_main(int argc, char **argv);
    15 int readlink_main(int argc, char **argv)
     34int readlink_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     35int readlink_main(int argc UNUSED_PARAM, char **argv)
    1636{
    1737    char *buf;
    1838    char *fname;
    1939
    20     USE_FEATURE_READLINK_FOLLOW(
     40    IF_FEATURE_READLINK_FOLLOW(
    2141        unsigned opt;
    2242        /* We need exactly one non-option argument.  */
    2343        opt_complementary = "=1";
    24         opt = getopt32(argv, "f");
     44        opt = getopt32(argv, "fnvsq");
    2545        fname = argv[optind];
    2646    )
    27     SKIP_FEATURE_READLINK_FOLLOW(
     47    IF_NOT_FEATURE_READLINK_FOLLOW(
    2848        const unsigned opt = 0;
    2949        if (argc != 2) bb_show_usage();
     
    3252
    3353    /* compat: coreutils readlink reports errors silently via exit code */
    34     logmode = LOGMODE_NONE;
     54    if (!(opt & 4)) /* not -v */
     55        logmode = LOGMODE_NONE;
    3556
    36     if (opt) {
    37         buf = realpath(fname, bb_common_bufsiz1);
     57    if (opt & 1) { /* -f */
     58        buf = xmalloc_realpath(fname);
    3859    } else {
    3960        buf = xmalloc_readlink_or_warn(fname);
     
    4263    if (!buf)
    4364        return EXIT_FAILURE;
    44     puts(buf);
     65    printf((opt & 2) ? "%s" : "%s\n", buf);
    4566
    46     if (ENABLE_FEATURE_CLEAN_UP && !opt)
     67    if (ENABLE_FEATURE_CLEAN_UP)
    4768        free(buf);
    4869
  • branches/2.2.9/mindi-busybox/coreutils/realpath.c

    r1765 r2725  
    88 * if one or more paths cannot be resolved.
    99 *
    10  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     10 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1111 */
    1212
    1313#include "libbb.h"
    1414
    15 int realpath_main(int argc, char **argv);
    16 int realpath_main(int argc, char **argv)
     15int realpath_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     16int realpath_main(int argc UNUSED_PARAM, char **argv)
    1717{
    1818    int retval = EXIT_SUCCESS;
    1919
    20 #if PATH_MAX > (BUFSIZ+1)
    21     RESERVE_CONFIG_BUFFER(resolved_path, PATH_MAX);
    22 # define resolved_path_MUST_FREE 1
    23 #else
    24 #define resolved_path bb_common_bufsiz1
    25 # define resolved_path_MUST_FREE 0
    26 #endif
    27 
    28     if (--argc == 0) {
     20    if (!*++argv) {
    2921        bb_show_usage();
    3022    }
    3123
    3224    do {
    33         argv++;
    34         if (realpath(*argv, resolved_path) != NULL) {
     25        char *resolved_path = xmalloc_realpath(*argv);
     26        if (resolved_path != NULL) {
    3527            puts(resolved_path);
     28            free(resolved_path);
    3629        } else {
    3730            retval = EXIT_FAILURE;
    38             bb_perror_msg("%s", *argv);
     31            bb_simple_perror_msg(*argv);
    3932        }
    40     } while (--argc);
    41 
    42 #if ENABLE_FEATURE_CLEAN_UP && resolved_path_MUST_FREE
    43     RELEASE_CONFIG_BUFFER(resolved_path);
    44 #endif
     33    } while (*++argv);
    4534
    4635    fflush_stdout_and_exit(retval);
  • branches/2.2.9/mindi-busybox/coreutils/rm.c

    r1765 r2725  
    55 * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    2020/* This is a NOFORK applet. Be very careful! */
    2121
    22 int rm_main(int argc, char **argv);
    23 int rm_main(int argc, char **argv)
     22int rm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     23int rm_main(int argc UNUSED_PARAM, char **argv)
    2424{
    2525    int status = 0;
     
    2828
    2929    opt_complementary = "f-i:i-f";
    30     opt = getopt32(argv, "fiRr");
     30    /* -v (verbose) is ignored */
     31    opt = getopt32(argv, "fiRrv");
    3132    argv += optind;
    3233    if (opt & 1)
     
    3435    if (opt & 2)
    3536        flags |= FILEUTILS_INTERACTIVE;
    36     if (opt & 12)
     37    if (opt & (8|4))
    3738        flags |= FILEUTILS_RECUR;
    3839
    3940    if (*argv != NULL) {
    4041        do {
    41             const char *base = bb_get_last_path_component(*argv);
     42            const char *base = bb_get_last_path_component_strip(*argv);
    4243
    4344            if (DOT_OR_DOTDOT(base)) {
    44                 bb_error_msg("cannot remove '.' or '..'");
     45                bb_error_msg("can't remove '.' or '..'");
    4546            } else if (remove_file(*argv, flags) >= 0) {
    4647                continue;
  • branches/2.2.9/mindi-busybox/coreutils/rmdir.c

    r1765 r2725  
    55 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1111/* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */
    1212
    13 #include <libgen.h>
    1413#include "libbb.h"
    1514
     
    1716
    1817
    19 int rmdir_main(int argc, char **argv);
    20 int rmdir_main(int argc, char **argv)
     18#define PARENTS 0x01
     19#define IGNORE_NON_EMPTY 0x02
     20
     21int rmdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     22int rmdir_main(int argc UNUSED_PARAM, char **argv)
    2123{
    2224    int status = EXIT_SUCCESS;
    2325    int flags;
    24     int do_dot;
    2526    char *path;
    2627
     28#if ENABLE_FEATURE_RMDIR_LONG_OPTIONS
     29    static const char rmdir_longopts[] ALIGN1 =
     30        "parents\0"                  No_argument "p"
     31        /* Debian etch: many packages fail to be purged or installed
     32         * because they desperately want this option: */
     33        "ignore-fail-on-non-empty\0" No_argument "\xff"
     34        ;
     35    applet_long_options = rmdir_longopts;
     36#endif
    2737    flags = getopt32(argv, "p");
    2838    argv += optind;
     
    3545        path = *argv;
    3646
    37         /* Record if the first char was a '.' so we can use dirname later. */
    38         do_dot = (*path == '.');
    39 
    4047        while (1) {
    4148            if (rmdir(path) < 0) {
    42                 bb_perror_msg("'%s'", path);    /* Match gnu rmdir msg. */
     49#if ENABLE_FEATURE_RMDIR_LONG_OPTIONS
     50                if ((flags & IGNORE_NON_EMPTY) && errno == ENOTEMPTY)
     51                    break;
     52#endif
     53                bb_perror_msg("'%s'", path);  /* Match gnu rmdir msg. */
    4354                status = EXIT_FAILURE;
    44             } else if (flags) {
    45                 /* Note: path was not empty or null since rmdir succeeded. */
     55            } else if (flags & PARENTS) {
     56                /* Note: path was not "" since rmdir succeeded. */
    4657                path = dirname(path);
    47                 /* Path is now just the parent component.  Note that dirname
    48                  * returns "." if there are no parents.  We must distinguish
    49                  * this from the case of the original path starting with '.'.
     58                /* Path is now just the parent component.  Dirname
     59                 * returns "." if there are no parents.
    5060                 */
    51                 if (do_dot || (*path != '.') || path[1]) {
     61                if (NOT_LONE_CHAR(path, '.')) {
    5262                    continue;
    5363                }
     
    5565            break;
    5666        }
    57 
    5867    } while (*++argv);
    5968
  • branches/2.2.9/mindi-busybox/coreutils/seq.c

    r1765 r2725  
    55 * Copyright (C) 2004, Glenn McGrath
    66 *
    7  * Licensed under the GPL v2, see the file LICENSE in this tarball.
     7 * Licensed under GPLv2, see file LICENSE in this source tree.
    88 */
    9 
    109#include "libbb.h"
    1110
    1211/* This is a NOFORK applet. Be very careful! */
    1312
    14 
    15 int seq_main(int argc, char **argv);
     13int seq_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    1614int seq_main(int argc, char **argv)
    1715{
    18     double last, increment, i;
     16    enum {
     17        OPT_w = (1 << 0),
     18        OPT_s = (1 << 1),
     19    };
     20    double first, last, increment, v;
     21    unsigned n;
     22    unsigned width;
     23    unsigned frac_part;
     24    const char *sep, *opt_s = "\n";
     25    unsigned opt;
    1926
    20     i = increment = 1;
     27#if ENABLE_LOCALE_SUPPORT
     28    /* Undo busybox.c: on input, we want to use dot
     29     * as fractional separator, regardless of current locale */
     30    setlocale(LC_NUMERIC, "C");
     31#endif
     32
     33    opt = getopt32(argv, "+ws:", &opt_s);
     34    argc -= optind;
     35    argv += optind;
     36    first = increment = 1;
     37    errno = 0;
    2138    switch (argc) {
    22         case 4:
    23             increment = atof(argv[2]);
     39            char *pp;
    2440        case 3:
    25             i = atof(argv[1]);
     41            increment = strtod(argv[1], &pp);
     42            errno |= *pp;
    2643        case 2:
    27             last = atof(argv[argc-1]);
    28             break;
     44            first = strtod(argv[0], &pp);
     45            errno |= *pp;
     46        case 1:
     47            last = strtod(argv[argc-1], &pp);
     48            if (!errno && *pp == '\0')
     49                break;
    2950        default:
    3051            bb_show_usage();
    3152    }
    3253
    33     /* You should note that this is pos-5.0.91 semantics, -- FK. */
    34     while ((increment > 0 && i <= last) || (increment < 0 && i >= last)) {
    35         printf("%g\n", i);
    36         i += increment;
     54#if ENABLE_LOCALE_SUPPORT
     55    setlocale(LC_NUMERIC, "");
     56#endif
     57
     58    /* Last checked to be compatible with: coreutils-6.10 */
     59    width = 0;
     60    frac_part = 0;
     61    while (1) {
     62        char *dot = strchrnul(*argv, '.');
     63        int w = (dot - *argv);
     64        int f = strlen(dot);
     65        if (width < w)
     66            width = w;
     67        argv++;
     68        if (!*argv)
     69            break;
     70        /* Why do the above _before_ frac check below?
     71         * Try "seq 1 2.0" and "seq 1.0 2.0":
     72         * coreutils never pay attention to the number
     73         * of fractional digits in last arg. */
     74        if (frac_part < f)
     75            frac_part = f;
    3776    }
     77    if (frac_part) {
     78        frac_part--;
     79        if (frac_part)
     80            width += frac_part + 1;
     81    }
     82    if (!(opt & OPT_w))
     83        width = 0;
    3884
    39     return fflush(stdout);
     85    sep = "";
     86    v = first;
     87    n = 0;
     88    while (increment >= 0 ? v <= last : v >= last) {
     89        if (printf("%s%0*.*f", sep, width, frac_part, v) < 0)
     90            break; /* I/O error, bail out (yes, this really happens) */
     91        sep = opt_s;
     92        /* v += increment; - would accumulate floating point errors */
     93        n++;
     94        v = first + n * increment;
     95    }
     96    if (n) /* if while loop executed at least once */
     97        bb_putchar('\n');
     98
     99    return fflush_all();
    40100}
  • branches/2.2.9/mindi-busybox/coreutils/sleep.c

    r1765 r2725  
    55 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    2121#include "libbb.h"
    2222
    23 /* This is a NOFORK applet. Be very careful! */
     23/* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells */
    2424
    2525
    26 #if ENABLE_FEATURE_FANCY_SLEEP
     26#if ENABLE_FEATURE_FANCY_SLEEP || ENABLE_FEATURE_FLOAT_SLEEP
    2727static const struct suffix_mult sfx[] = {
    2828    { "s", 1 },
     
    3030    { "h", 60*60 },
    3131    { "d", 24*60*60 },
    32     { }
     32    { "", 0 }
    3333};
    3434#endif
    3535
    36 int sleep_main(int argc, char **argv);
    37 int sleep_main(int argc, char **argv)
     36int sleep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     37int sleep_main(int argc UNUSED_PARAM, char **argv)
    3838{
     39#if ENABLE_FEATURE_FLOAT_SLEEP
     40    double duration;
     41    struct timespec ts;
     42#else
    3943    unsigned duration;
    40 
    41 #if ENABLE_FEATURE_FANCY_SLEEP
    42 
    43     if (argc < 2) {
    44         bb_show_usage();
    45     }
     44#endif
    4645
    4746    ++argv;
     47    if (!*argv)
     48        bb_show_usage();
     49
     50#if ENABLE_FEATURE_FLOAT_SLEEP
     51
     52# if ENABLE_LOCALE_SUPPORT
     53    /* undo busybox.c setlocale */
     54    setlocale(LC_NUMERIC, "C");
     55# endif
    4856    duration = 0;
    4957    do {
    50         duration += xatoul_range_sfx(*argv, 0, UINT_MAX-duration, sfx);
     58        char *arg = *argv;
     59        if (strchr(arg, '.')) {
     60            double d;
     61            char *pp;
     62            int len = strspn(arg, "0123456789.");
     63            char sv = arg[len];
     64            arg[len] = '\0';
     65            errno = 0;
     66            d = strtod(arg, &pp);
     67            if (errno || *pp)
     68                bb_show_usage();
     69            arg += len;
     70            *arg-- = sv;
     71            sv = *arg;
     72            *arg = '1';
     73            duration += d * xatoul_sfx(arg, sfx);
     74            *arg = sv;
     75        } else {
     76            duration += xatoul_sfx(arg, sfx);
     77        }
    5178    } while (*++argv);
    5279
    53 #else  /* FEATURE_FANCY_SLEEP */
     80    ts.tv_sec = MAXINT(typeof(ts.tv_sec));
     81    ts.tv_nsec = 0;
     82    if (duration >= 0 && duration < ts.tv_sec) {
     83        ts.tv_sec = duration;
     84        ts.tv_nsec = (duration - ts.tv_sec) * 1000000000;
     85    }
     86    do {
     87        errno = 0;
     88        nanosleep(&ts, &ts);
     89    } while (errno == EINTR);
    5490
    55     if (argc != 2) {
    56         bb_show_usage();
    57     }
     91#elif ENABLE_FEATURE_FANCY_SLEEP
    5892
    59     duration = xatou(argv[1]);
     93    duration = 0;
     94    do {
     95        duration += xatou_range_sfx(*argv, 0, UINT_MAX - duration, sfx);
     96    } while (*++argv);
     97    sleep(duration);
    6098
    61 #endif /* FEATURE_FANCY_SLEEP */
     99#else /* simple */
    62100
    63     if (sleep(duration)) {
    64         bb_perror_nomsg_and_die();
    65     }
     101    duration = xatou(*argv);
     102    sleep(duration);
     103    // Off. If it's really needed, provide example why
     104    //if (sleep(duration)) {
     105    //  bb_perror_nomsg_and_die();
     106    //}
     107
     108#endif
    66109
    67110    return EXIT_SUCCESS;
  • branches/2.2.9/mindi-busybox/coreutils/sort.c

    r1765 r2725  
    77 * MAINTAINER: Rob Landley <rob@landley.net>
    88 *
    9  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1010 *
    1111 * See SuS3 sort standard at:
     
    3333    FLAG_c  = 0x10,         /* Check: no output, exit(!ordered) */
    3434    FLAG_s  = 0x20,         /* Stable sort, no ascii fallback at end */
    35     FLAG_z  = 0x40,         /* Input is null terminated, not \n */
     35    FLAG_z  = 0x40,         /* Input and output is NUL terminated, not \n */
    3636/* These can be applied to search keys, the previous four can't */
    3737    FLAG_b  = 0x80,         /* Ignore leading blanks */
     
    5353
    5454static struct sort_key {
    55     struct sort_key *next_key;  /* linked list */
    56     unsigned range[4];  /* start word, start char, end word, end char */
     55    struct sort_key *next_key;  /* linked list */
     56    unsigned range[4];          /* start word, start char, end word, end char */
    5757    unsigned flags;
    5858} *key_list;
     
    6060static char *get_key(char *str, struct sort_key *key, int flags)
    6161{
    62     int start = 0, end = 0, len, i, j;
     62    int start = 0, end = 0, len, j;
     63    unsigned i;
    6364
    6465    /* Special case whole string, so we don't have to make a copy */
     
    128129    if (flags & FLAG_i) {
    129130        for (start = end = 0; str[end]; end++)
    130             if (isprint(str[end]))
     131            if (isprint_asciionly(str[end]))
    131132                str[start++] = str[end];
    132133        str[start] = '\0';
     
    151152    ((option_mask32 & FLAG_z) \
    152153    ? bb_get_chunk_from_file(fp, NULL) \
    153     : xmalloc_getline(fp))
     154    : xmalloc_fgetline(fp))
    154155#else
    155 #define GET_LINE(fp) xmalloc_getline(fp)
     156#define GET_LINE(fp) xmalloc_fgetline(fp)
    156157#endif
    157158
     
    275276#endif
    276277
    277 int sort_main(int argc, char **argv);
    278 int sort_main(int argc, char **argv)
     278int sort_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     279int sort_main(int argc UNUSED_PARAM, char **argv)
    279280{
    280     FILE *fp, *outfile = stdout;
    281     char *line, **lines = NULL;
     281    char *line, **lines;
    282282    char *str_ignored, *str_o, *str_t;
    283283    llist_t *lst_k = NULL;
    284284    int i, flag;
    285     int linecount = 0;
     285    int linecount;
     286    unsigned opts;
    286287
    287288    xfunc_error_retval = 2;
     
    289290    /* Parse command line options */
    290291    /* -o and -t can be given at most once */
    291     opt_complementary = "o--o:t--t:" /* -t, -o: maximum one of each */
     292    opt_complementary = "o--o:t--t:" /* -t, -o: at most one of each */
    292293            "k::"; /* -k takes list */
    293     getopt32(argv, OPT_STR, &str_ignored, &str_ignored, &str_o, &lst_k, &str_t);
    294 #if ENABLE_FEATURE_SORT_BIG
    295     if (option_mask32 & FLAG_o) outfile = xfopen(str_o, "w");
    296     if (option_mask32 & FLAG_t) {
     294    opts = getopt32(argv, OPT_STR, &str_ignored, &str_ignored, &str_o, &lst_k, &str_t);
     295    /* global b strips leading and trailing spaces */
     296    if (opts & FLAG_b)
     297        option_mask32 |= FLAG_bb;
     298#if ENABLE_FEATURE_SORT_BIG
     299    if (opts & FLAG_t) {
    297300        if (!str_t[0] || str_t[1])
    298301            bb_error_msg_and_die("bad -t parameter");
    299302        key_separator = str_t[0];
    300303    }
     304    /* note: below this point we use option_mask32, not opts,
     305     * since that reduces register pressure and makes code smaller */
     306
    301307    /* parse sort key */
    302308    while (lst_k) {
     
    314320        };
    315321        struct sort_key *key = add_key();
    316         char *str_k = lst_k->data;
    317         const char *temp2;
     322        char *str_k = llist_pop(&lst_k);
    318323
    319324        i = 0; /* i==0 before comma, 1 after (-k3,6) */
     
    327332            }
    328333            while (*str_k) {
     334                const char *temp2;
     335
    329336                if (*str_k == ',' && !i++) {
    330337                    str_k++;
    331338                    break;
    332339                } /* no else needed: fall through to syntax error
    333                      because comma isn't in OPT_STR */
     340                    because comma isn't in OPT_STR */
    334341                temp2 = strchr(OPT_STR, *str_k);
    335342                if (!temp2)
     
    339346                    bb_error_msg_and_die("unknown sort type");
    340347                /* b after ',' means strip _trailing_ space */
    341                 if (i && flag == FLAG_b) flag = FLAG_bb;
     348                if (i && flag == FLAG_b)
     349                    flag = FLAG_bb;
    342350                key->flags |= flag;
    343351                str_k++;
    344352            }
    345353        }
    346         /* leaking lst_k... */
    347         lst_k = lst_k->link;
    348     }
    349 #endif
    350     /* global b strips leading and trailing spaces */
    351     if (option_mask32 & FLAG_b) option_mask32 |= FLAG_bb;
     354    }
     355#endif
    352356
    353357    /* Open input files and read data */
    354     for (i = argv[optind] ? optind : optind-1; argv[i]; i++) {
    355         fp = stdin;
    356         if (i >= optind && NOT_LONE_DASH(argv[i]))
    357             fp = xfopen(argv[i], "r");
     358    argv += optind;
     359    if (!*argv)
     360        *--argv = (char*)"-";
     361    linecount = 0;
     362    lines = NULL;
     363    do {
     364        /* coreutils 6.9 compat: abort on first open error,
     365         * do not continue to next file: */
     366        FILE *fp = xfopen_stdin(*argv);
    358367        for (;;) {
    359368            line = GET_LINE(fp);
    360             if (!line) break;
    361             if (!(linecount & 63))
    362                 lines = xrealloc(lines, sizeof(char *) * (linecount + 64));
     369            if (!line)
     370                break;
     371            lines = xrealloc_vector(lines, 6, linecount);
    363372            lines[linecount++] = line;
    364373        }
    365         fclose(fp);
    366     }
     374        fclose_if_not_stdin(fp);
     375    } while (*++argv);
     376
    367377#if ENABLE_FEATURE_SORT_BIG
    368378    /* if no key, perform alphabetic sort */
     
    372382    if (option_mask32 & FLAG_c) {
    373383        int j = (option_mask32 & FLAG_u) ? -1 : 0;
    374         for (i = 1; i < linecount; i++)
     384        for (i = 1; i < linecount; i++) {
    375385            if (compare_keys(&lines[i-1], &lines[i]) > j) {
    376                 fprintf(stderr, "Check line %d\n", i);
    377                 return 1;
     386                fprintf(stderr, "Check line %u\n", i);
     387                return EXIT_FAILURE;
    378388            }
    379         return 0;
     389        }
     390        return EXIT_SUCCESS;
    380391    }
    381392#endif
    382393    /* Perform the actual sort */
    383     qsort(lines, linecount, sizeof(char *), compare_keys);
     394    qsort(lines, linecount, sizeof(lines[0]), compare_keys);
    384395    /* handle -u */
    385396    if (option_mask32 & FLAG_u) {
     
    389400        option_mask32 |= FLAG_s;
    390401        for (i = 1; i < linecount; i++) {
    391             if (!compare_keys(&lines[flag], &lines[i]))
     402            if (compare_keys(&lines[flag], &lines[i]) == 0)
    392403                free(lines[i]);
    393404            else
    394405                lines[++flag] = lines[i];
    395406        }
    396         if (linecount) linecount = flag+1;
    397     }
     407        if (linecount)
     408            linecount = flag+1;
     409    }
     410
    398411    /* Print it */
     412#if ENABLE_FEATURE_SORT_BIG
     413    /* Open output file _after_ we read all input ones */
     414    if (option_mask32 & FLAG_o)
     415        xmove_fd(xopen(str_o, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO);
     416#endif
     417    flag = (option_mask32 & FLAG_z) ? '\0' : '\n';
    399418    for (i = 0; i < linecount; i++)
    400         fprintf(outfile, "%s\n", lines[i]);
     419        printf("%s%c", lines[i], flag);
    401420
    402421    fflush_stdout_and_exit(EXIT_SUCCESS);
  • branches/2.2.9/mindi-busybox/coreutils/split.c

    r1765 r2725  
    22/*
    33 * split - split a file into pieces
    4  * Copyright (c) 2007 Bernhard Fischer
     4 * Copyright (c) 2007 Bernhard Reutner-Fischer
    55 *
    6  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    77 */
    88/* BB_AUDIT: SUSv3 compliant
     
    2121    { "g", 1024*1024*1024 },
    2222#endif
    23     { }
     23    { "", 0 }
    2424};
    2525
     
    5656#define SPLIT_OPT_a (1<<2)
    5757
    58 int split_main(int argc, char **argv);
    59 int split_main(int argc, char **argv)
     58int split_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     59int split_main(int argc UNUSED_PARAM, char **argv)
    6060{
    6161    unsigned suffix_len = 2;
     
    6969    char *src;
    7070
    71     opt_complementary = "?2";
    72     opt = getopt32(argv, "l:b:a:", &count_p, &count_p, &sfx);
     71    opt_complementary = "?2:a+"; /* max 2 args; -a N */
     72    opt = getopt32(argv, "l:b:a:", &count_p, &count_p, &suffix_len);
    7373
    7474    if (opt & SPLIT_OPT_l)
    75         cnt = xatoul(count_p);
    76     if (opt & SPLIT_OPT_b)
    77         cnt = xatoul_sfx(count_p, split_suffices);
    78     if (opt & SPLIT_OPT_a)
    79         suffix_len = xatou(sfx);
     75        cnt = XATOOFF(count_p);
     76    if (opt & SPLIT_OPT_b) // FIXME: also needs XATOOFF
     77        cnt = xatoull_sfx(count_p, split_suffices);
    8078    sfx = "x";
    8179
    8280    argv += optind;
    8381    if (argv[0]) {
     82        int fd;
    8483        if (argv[1])
    8584            sfx = argv[1];
    86         xmove_fd(xopen(argv[0], O_RDONLY), 0);
     85        fd = xopen_stdin(argv[0]);
     86        xmove_fd(fd, STDIN_FILENO);
    8787    } else {
    8888        argv[0] = (char *) bb_msg_standard_input;
     
    101101
    102102    while (1) {
    103         bytes_read = safe_read(0, read_buffer, READ_BUFFER_SIZE);
     103        bytes_read = safe_read(STDIN_FILENO, read_buffer, READ_BUFFER_SIZE);
    104104        if (!bytes_read)
    105105            break;
    106106        if (bytes_read < 0)
    107             bb_perror_msg_and_die("%s", argv[0]);
     107            bb_simple_perror_msg_and_die(argv[0]);
    108108        src = read_buffer;
    109109        do {
     
    133133            }
    134134
    135             xwrite(1, src, to_write);
     135            xwrite(STDOUT_FILENO, src, to_write);
    136136            bytes_read -= to_write;
    137137            src += to_write;
    138138        } while (bytes_read);
    139139    }
    140     return 0;
     140    return EXIT_SUCCESS;
    141141}
  • branches/2.2.9/mindi-busybox/coreutils/stat.c

    r1765 r2725  
    1111 * Taken from coreutils and turned into a busybox applet by Mike Frysinger
    1212 *
    13  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     13 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1414 */
    15 
    1615#include "libbb.h"
    1716
    18 /* vars to control behavior */
    19 #define OPT_FILESYS     (1<<0)
    20 #define OPT_TERSE       (1<<1)
    21 #define OPT_DEREFERENCE (1<<2)
    22 #define OPT_SELINUX     (1<<3)
    23 
    24 static char buf[sizeof("YYYY-MM-DD HH:MM:SS.000000000")] ALIGN1;
    25 
    26 static char const * file_type(struct stat const *st)
     17#define OPT_FILESYS     (1 << 0)
     18#define OPT_TERSE       (1 << 1)
     19#define OPT_DEREFERENCE (1 << 2)
     20#define OPT_SELINUX     (1 << 3)
     21
     22#if ENABLE_FEATURE_STAT_FORMAT
     23typedef bool (*statfunc_ptr)(const char *, const char *);
     24#else
     25typedef bool (*statfunc_ptr)(const char *);
     26#endif
     27
     28static const char *file_type(const struct stat *st)
    2729{
    2830    /* See POSIX 1003.1-2001 XCU Table 4-8 lines 17093-17107
     
    4749}
    4850
    49 static char const *human_time(time_t t)
     51static const char *human_time(time_t t)
    5052{
    5153    /* Old
     
    5759    /* coreutils 6.3 compat: */
    5860
     61    /*static char buf[sizeof("YYYY-MM-DD HH:MM:SS.000000000")] ALIGN1;*/
     62#define buf bb_common_bufsiz1
     63
    5964    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000000000", localtime(&t));
    6065    return buf;
     66#undef buf
    6167}
    6268
     
    6672 * Still others have neither and have to get by with f_type (Linux).
    6773 */
    68 static char const *human_fstype(long f_type)
    69 {
    70     int i;
     74static const char *human_fstype(uint32_t f_type)
     75{
    7176    static const struct types {
    72         long type;
     77        uint32_t type;
    7378        const char *const fs;
    7479    } humantypes[] = {
     
    110115        { 0, "UNKNOWN" }
    111116    };
     117
     118    int i;
     119
    112120    for (i = 0; humantypes[i].type; ++i)
    113121        if (humantypes[i].type == f_type)
     
    116124}
    117125
     126/* "man statfs" says that statfsbuf->f_fsid is a mess */
     127/* coreutils treats it as an array of ints, most significant first */
     128static unsigned long long get_f_fsid(const struct statfs *statfsbuf)
     129{
     130    const unsigned *p = (const void*) &statfsbuf->f_fsid;
     131    unsigned sz = sizeof(statfsbuf->f_fsid) / sizeof(unsigned);
     132    unsigned long long r = 0;
     133
     134    do
     135        r = (r << (sizeof(unsigned)*8)) | *p++;
     136    while (--sz > 0);
     137    return r;
     138}
     139
    118140#if ENABLE_FEATURE_STAT_FORMAT
     141static void strcatc(char *str, char c)
     142{
     143    int len = strlen(str);
     144    str[len++] = c;
     145    str[len] = '\0';
     146}
     147
     148static void printfs(char *pformat, const char *msg)
     149{
     150    strcatc(pformat, 's');
     151    printf(pformat, msg);
     152}
     153
    119154/* print statfs info */
    120 static void print_statfs(char *pformat, const size_t buf_len, const char m,
    121              const char *const filename, void const *data
    122              USE_SELINUX(, security_context_t scontext))
    123 {
    124     struct statfs const *statfsbuf = data;
     155static void FAST_FUNC print_statfs(char *pformat, const char m,
     156        const char *const filename, const void *data
     157        IF_SELINUX(, security_context_t scontext))
     158{
     159    const struct statfs *statfsbuf = data;
    125160    if (m == 'n') {
    126         strncat(pformat, "s", buf_len);
    127         printf(pformat, filename);
     161        printfs(pformat, filename);
    128162    } else if (m == 'i') {
    129         strncat(pformat, "Lx", buf_len);
    130         printf(pformat, statfsbuf->f_fsid);
     163        strcat(pformat, "llx");
     164        printf(pformat, get_f_fsid(statfsbuf));
    131165    } else if (m == 'l') {
    132         strncat(pformat, "lu", buf_len);
    133         printf(pformat, statfsbuf->f_namelen);
     166        strcat(pformat, "lu");
     167        printf(pformat, (unsigned long) statfsbuf->f_namelen);
    134168    } else if (m == 't') {
    135         strncat(pformat, "lx", buf_len);
    136         printf(pformat, (unsigned long) (statfsbuf->f_type)); /* no equiv */
     169        strcat(pformat, "lx");
     170        printf(pformat, (unsigned long) statfsbuf->f_type); /* no equiv */
    137171    } else if (m == 'T') {
    138         strncat(pformat, "s", buf_len);
    139         printf(pformat, human_fstype(statfsbuf->f_type));
     172        printfs(pformat, human_fstype(statfsbuf->f_type));
    140173    } else if (m == 'b') {
    141         strncat(pformat, "jd", buf_len);
    142         printf(pformat, (intmax_t) (statfsbuf->f_blocks));
     174        strcat(pformat, "llu");
     175        printf(pformat, (unsigned long long) statfsbuf->f_blocks);
    143176    } else if (m == 'f') {
    144         strncat(pformat, "jd", buf_len);
    145         printf(pformat, (intmax_t) (statfsbuf->f_bfree));
     177        strcat(pformat, "llu");
     178        printf(pformat, (unsigned long long) statfsbuf->f_bfree);
    146179    } else if (m == 'a') {
    147         strncat(pformat, "jd", buf_len);
    148         printf(pformat, (intmax_t) (statfsbuf->f_bavail));
     180        strcat(pformat, "llu");
     181        printf(pformat, (unsigned long long) statfsbuf->f_bavail);
    149182    } else if (m == 's' || m == 'S') {
    150         strncat(pformat, "lu", buf_len);
    151         printf(pformat, (unsigned long) (statfsbuf->f_bsize));
     183        strcat(pformat, "lu");
     184        printf(pformat, (unsigned long) statfsbuf->f_bsize);
    152185    } else if (m == 'c') {
    153         strncat(pformat, "jd", buf_len);
    154         printf(pformat, (intmax_t) (statfsbuf->f_files));
     186        strcat(pformat, "llu");
     187        printf(pformat, (unsigned long long) statfsbuf->f_files);
    155188    } else if (m == 'd') {
    156         strncat(pformat, "jd", buf_len);
    157         printf(pformat, (intmax_t) (statfsbuf->f_ffree));
    158 #if ENABLE_SELINUX
     189        strcat(pformat, "llu");
     190        printf(pformat, (unsigned long long) statfsbuf->f_ffree);
     191# if ENABLE_SELINUX
    159192    } else if (m == 'C' && (option_mask32 & OPT_SELINUX)) {
    160         strncat(pformat, "s", buf_len);
    161         printf(scontext);
    162 #endif
     193        printfs(pformat, scontext);
     194# endif
    163195    } else {
    164         strncat(pformat, "c", buf_len);
     196        strcatc(pformat, 'c');
    165197        printf(pformat, m);
    166198    }
     
    168200
    169201/* print stat info */
    170 static void print_stat(char *pformat, const size_t buf_len, const char m,
    171                const char *const filename, void const *data
    172                USE_SELINUX(, security_context_t scontext))
     202static void FAST_FUNC print_stat(char *pformat, const char m,
     203        const char *const filename, const void *data
     204        IF_SELINUX(, security_context_t scontext))
    173205{
    174206#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
     
    178210
    179211    if (m == 'n') {
    180         strncat(pformat, "s", buf_len);
    181         printf(pformat, filename);
     212        printfs(pformat, filename);
    182213    } else if (m == 'N') {
    183         strncat(pformat, "s", buf_len);
     214        strcatc(pformat, 's');
    184215        if (S_ISLNK(statbuf->st_mode)) {
    185216            char *linkname = xmalloc_readlink_or_warn(filename);
    186             if (linkname == NULL) {
    187                 bb_perror_msg("cannot read symbolic link '%s'", filename);
     217            if (linkname == NULL)
    188218                return;
    189             }
    190             /*printf("\"%s\" -> \"%s\"", filename, linkname); */
    191             printf(pformat, filename);
    192             printf(" -> ");
    193             printf(pformat, linkname);
     219            printf("'%s' -> '%s'", filename, linkname);
     220            free(linkname);
    194221        } else {
    195222            printf(pformat, filename);
    196223        }
    197224    } else if (m == 'd') {
    198         strncat(pformat, "ju", buf_len);
    199         printf(pformat, (uintmax_t) statbuf->st_dev);
     225        strcat(pformat, "llu");
     226        printf(pformat, (unsigned long long) statbuf->st_dev);
    200227    } else if (m == 'D') {
    201         strncat(pformat, "jx", buf_len);
    202         printf(pformat, (uintmax_t) statbuf->st_dev);
     228        strcat(pformat, "llx");
     229        printf(pformat, (unsigned long long) statbuf->st_dev);
    203230    } else if (m == 'i') {
    204         strncat(pformat, "ju", buf_len);
    205         printf(pformat, (uintmax_t) statbuf->st_ino);
     231        strcat(pformat, "llu");
     232        printf(pformat, (unsigned long long) statbuf->st_ino);
    206233    } else if (m == 'a') {
    207         strncat(pformat, "lo", buf_len);
     234        strcat(pformat, "lo");
    208235        printf(pformat, (unsigned long) (statbuf->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)));
    209236    } else if (m == 'A') {
    210         strncat(pformat, "s", buf_len);
    211         printf(pformat, bb_mode_string(statbuf->st_mode));
     237        printfs(pformat, bb_mode_string(statbuf->st_mode));
    212238    } else if (m == 'f') {
    213         strncat(pformat, "lx", buf_len);
     239        strcat(pformat, "lx");
    214240        printf(pformat, (unsigned long) statbuf->st_mode);
    215241    } else if (m == 'F') {
    216         strncat(pformat, "s", buf_len);
    217         printf(pformat, file_type(statbuf));
     242        printfs(pformat, file_type(statbuf));
    218243    } else if (m == 'h') {
    219         strncat(pformat, "lu", buf_len);
     244        strcat(pformat, "lu");
    220245        printf(pformat, (unsigned long) statbuf->st_nlink);
    221246    } else if (m == 'u') {
    222         strncat(pformat, "lu", buf_len);
     247        strcat(pformat, "lu");
    223248        printf(pformat, (unsigned long) statbuf->st_uid);
    224249    } else if (m == 'U') {
    225         strncat(pformat, "s", buf_len);
    226         setpwent();
    227250        pw_ent = getpwuid(statbuf->st_uid);
    228         printf(pformat, (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN");
     251        printfs(pformat, (pw_ent != NULL) ? pw_ent->pw_name : "UNKNOWN");
    229252    } else if (m == 'g') {
    230         strncat(pformat, "lu", buf_len);
     253        strcat(pformat, "lu");
    231254        printf(pformat, (unsigned long) statbuf->st_gid);
    232255    } else if (m == 'G') {
    233         strncat(pformat, "s", buf_len);
    234         setgrent();
    235256        gw_ent = getgrgid(statbuf->st_gid);
    236         printf(pformat, (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
     257        printfs(pformat, (gw_ent != NULL) ? gw_ent->gr_name : "UNKNOWN");
    237258    } else if (m == 't') {
    238         strncat(pformat, "lx", buf_len);
     259        strcat(pformat, "lx");
    239260        printf(pformat, (unsigned long) major(statbuf->st_rdev));
    240261    } else if (m == 'T') {
    241         strncat(pformat, "lx", buf_len);
     262        strcat(pformat, "lx");
    242263        printf(pformat, (unsigned long) minor(statbuf->st_rdev));
    243264    } else if (m == 's') {
    244         strncat(pformat, "ju", buf_len);
    245         printf(pformat, (uintmax_t) (statbuf->st_size));
     265        strcat(pformat, "llu");
     266        printf(pformat, (unsigned long long) statbuf->st_size);
    246267    } else if (m == 'B') {
    247         strncat(pformat, "lu", buf_len);
     268        strcat(pformat, "lu");
    248269        printf(pformat, (unsigned long) 512); //ST_NBLOCKSIZE
    249270    } else if (m == 'b') {
    250         strncat(pformat, "ju", buf_len);
    251         printf(pformat, (uintmax_t) statbuf->st_blocks);
     271        strcat(pformat, "llu");
     272        printf(pformat, (unsigned long long) statbuf->st_blocks);
    252273    } else if (m == 'o') {
    253         strncat(pformat, "lu", buf_len);
     274        strcat(pformat, "lu");
    254275        printf(pformat, (unsigned long) statbuf->st_blksize);
    255276    } else if (m == 'x') {
    256         strncat(pformat, "s", buf_len);
    257         printf(pformat, human_time(statbuf->st_atime));
     277        printfs(pformat, human_time(statbuf->st_atime));
    258278    } else if (m == 'X') {
    259         strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len);
    260         printf(pformat, (unsigned long) statbuf->st_atime);
     279        strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
     280        /* note: (unsigned long) would be wrong:
     281         * imagine (unsigned long64)int32 */
     282        printf(pformat, (long) statbuf->st_atime);
    261283    } else if (m == 'y') {
    262         strncat(pformat, "s", buf_len);
    263         printf(pformat, human_time(statbuf->st_mtime));
     284        printfs(pformat, human_time(statbuf->st_mtime));
    264285    } else if (m == 'Y') {
    265         strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len);
    266         printf(pformat, (unsigned long) statbuf->st_mtime);
     286        strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
     287        printf(pformat, (long) statbuf->st_mtime);
    267288    } else if (m == 'z') {
    268         strncat(pformat, "s", buf_len);
    269         printf(pformat, human_time(statbuf->st_ctime));
     289        printfs(pformat, human_time(statbuf->st_ctime));
    270290    } else if (m == 'Z') {
    271         strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len);
    272         printf(pformat, (unsigned long) statbuf->st_ctime);
    273 #if ENABLE_SELINUX
     291        strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
     292        printf(pformat, (long) statbuf->st_ctime);
     293# if ENABLE_SELINUX
    274294    } else if (m == 'C' && (option_mask32 & OPT_SELINUX)) {
    275         strncat(pformat, "s", buf_len);
    276         printf(pformat, scontext);
    277 #endif
     295        printfs(pformat, scontext);
     296# endif
    278297    } else {
    279         strncat(pformat, "c", buf_len);
     298        strcatc(pformat, 'c');
    280299        printf(pformat, m);
    281300    }
    282301}
    283302
    284 static void print_it(char const *masterformat, char const *filename,
    285              void (*print_func) (char *, size_t, char, char const *, void const *
    286                                  USE_SELINUX(, security_context_t scontext)),
    287                      void const *data USE_SELINUX(, security_context_t scontext) )
    288 {
    289     char *b;
    290 
    291     /* create a working copy of the format string */
     303static void print_it(const char *masterformat,
     304        const char *filename,
     305        void FAST_FUNC (*print_func)(char*, char, const char*, const void* IF_SELINUX(, security_context_t scontext)),
     306        const void *data
     307        IF_SELINUX(, security_context_t scontext))
     308{
     309    /* Create a working copy of the format string */
    292310    char *format = xstrdup(masterformat);
    293 
    294311    /* Add 2 to accomodate our conversion of the stat '%s' format string
    295312     * to the printf '%llu' one.  */
    296     size_t n_alloc = strlen(format) + 2 + 1;
    297     char *dest = xmalloc(n_alloc);
     313    char *dest = xmalloc(strlen(format) + 2 + 1);
     314    char *b;
    298315
    299316    b = format;
    300317    while (b) {
     318        /* Each iteration finds next %spec,
     319         * prints preceding string and handles found %spec
     320         */
    301321        size_t len;
    302322        char *p = strchr(b, '%');
    303323        if (!p) {
    304             /* coreutils 6.3 always print <cr> at the end */
     324            /* coreutils 6.3 always prints newline at the end */
    305325            /*fputs(b, stdout);*/
    306326            puts(b);
    307327            break;
    308328        }
    309         *p++ = '\0';
     329
     330        /* dest = "%<modifiers>" */
     331        len = 1 + strspn(p + 1, "#-+.I 0123456789");
     332        memcpy(dest, p, len);
     333        dest[len] = '\0';
     334
     335        /* print preceding string */
     336        *p = '\0';
    310337        fputs(b, stdout);
    311338
    312         len = strspn(p, "#-+.I 0123456789");
    313         dest[0] = '%';
    314         memcpy(dest + 1, p, len);
    315         dest[1 + len] = 0;
    316339        p += len;
    317 
    318340        b = p + 1;
    319341        switch (*p) {
     
    322344            /* fall through */
    323345        case '%':
    324             putchar('%');
     346            bb_putchar('%');
    325347            break;
    326348        default:
    327             print_func(dest, n_alloc, *p, filename, data USE_SELINUX(,scontext));
     349            /* Completes "%<modifiers>" with specifier and printfs */
     350            print_func(dest, *p, filename, data IF_SELINUX(,scontext));
    328351            break;
    329352        }
     
    333356    free(dest);
    334357}
    335 #endif
     358#endif  /* FEATURE_STAT_FORMAT */
    336359
    337360/* Stat the file system and print what we find.  */
    338 static bool do_statfs(char const *filename, char const *format)
     361#if !ENABLE_FEATURE_STAT_FORMAT
     362#define do_statfs(filename, format) do_statfs(filename)
     363#endif
     364static bool do_statfs(const char *filename, const char *format)
    339365{
    340366    struct statfs statfsbuf;
     367#if !ENABLE_FEATURE_STAT_FORMAT
     368    const char *format;
     369#endif
    341370#if ENABLE_SELINUX
    342371    security_context_t scontext = NULL;
     
    354383#endif
    355384    if (statfs(filename, &statfsbuf) != 0) {
    356         bb_perror_msg("cannot read file system information for '%s'", filename);
     385        bb_perror_msg("can't read file system information for '%s'", filename);
    357386        return 0;
    358387    }
    359388
    360389#if ENABLE_FEATURE_STAT_FORMAT
    361     if (format == NULL)
    362 #if !ENABLE_SELINUX
     390    if (format == NULL) {
     391# if !ENABLE_SELINUX
    363392        format = (option_mask32 & OPT_TERSE
    364393            ? "%n %i %l %t %s %b %f %a %c %d\n"
     
    368397              "Blocks: Total: %-10b Free: %-10f Available: %a\n"
    369398              "Inodes: Total: %-10c Free: %d");
    370     print_it(format, filename, print_statfs, &statfsbuf USE_SELINUX(, scontext));
    371 #else
    372     format = (option_mask32 & OPT_TERSE
     399# else
     400        format = (option_mask32 & OPT_TERSE
    373401            ? (option_mask32 & OPT_SELINUX ? "%n %i %l %t %s %b %f %a %c %d %C\n":
    374402            "%n %i %l %t %s %b %f %a %c %d\n")
     
    386414            "Inodes: Total: %-10c Free: %d\n")
    387415            );
    388     print_it(format, filename, print_statfs, &statfsbuf USE_SELINUX(, scontext));
    389 #endif /* SELINUX */
     416# endif /* SELINUX */
     417    }
     418    print_it(format, filename, print_statfs, &statfsbuf IF_SELINUX(, scontext));
    390419#else /* FEATURE_STAT_FORMAT */
    391420    format = (option_mask32 & OPT_TERSE
    392421        ? "%s %llx %lu "
    393422        : "  File: \"%s\"\n"
    394           "    ID: %-8Lx Namelen: %-7lu ");
     423          "    ID: %-8llx Namelen: %-7lu ");
    395424    printf(format,
    396425           filename,
    397            statfsbuf.f_fsid,
     426           get_f_fsid(&statfsbuf),
    398427           statfsbuf.f_namelen);
    399428
    400429    if (option_mask32 & OPT_TERSE)
    401         printf("%lx ", (unsigned long) (statfsbuf.f_type));
     430        printf("%lx ", (unsigned long) statfsbuf.f_type);
    402431    else
    403432        printf("Type: %s\n", human_fstype(statfsbuf.f_type));
    404433
    405 #if !ENABLE_SELINUX
     434# if !ENABLE_SELINUX
    406435    format = (option_mask32 & OPT_TERSE
    407         ? "%lu %ld %ld %ld %ld %ld\n"
     436        ? "%lu %llu %llu %llu %llu %llu\n"
    408437        : "Block size: %-10lu\n"
    409           "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
    410           "Inodes: Total: %-10jd Free: %jd\n");
     438          "Blocks: Total: %-10llu Free: %-10llu Available: %llu\n"
     439          "Inodes: Total: %-10llu Free: %llu\n");
    411440    printf(format,
    412            (unsigned long) (statfsbuf.f_bsize),
    413            (intmax_t) (statfsbuf.f_blocks),
    414            (intmax_t) (statfsbuf.f_bfree),
    415            (intmax_t) (statfsbuf.f_bavail),
    416            (intmax_t) (statfsbuf.f_files),
    417            (intmax_t) (statfsbuf.f_ffree));
    418 #else
     441           (unsigned long) statfsbuf.f_bsize,
     442           (unsigned long long) statfsbuf.f_blocks,
     443           (unsigned long long) statfsbuf.f_bfree,
     444           (unsigned long long) statfsbuf.f_bavail,
     445           (unsigned long long) statfsbuf.f_files,
     446           (unsigned long long) statfsbuf.f_ffree);
     447# else
    419448    format = (option_mask32 & OPT_TERSE
    420         ? (option_mask32 & OPT_SELINUX ? "%lu %ld %ld %ld %ld %ld %C\n":
    421         "%lu %ld %ld %ld %ld %ld\n")
    422         : (option_mask32 & OPT_SELINUX ?
    423         "Block size: %-10lu\n"
    424         "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
    425         "Inodes: Total: %-10jd Free: %jd"
    426         "S_context: %C\n":
    427         "Block size: %-10lu\n"
    428         "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
    429         "Inodes: Total: %-10jd Free: %jd\n"));
     449        ? (option_mask32 & OPT_SELINUX ? "%lu %llu %llu %llu %llu %llu %C\n" : "%lu %llu %llu %llu %llu %llu\n")
     450        : (option_mask32 & OPT_SELINUX
     451            ?   "Block size: %-10lu\n"
     452                "Blocks: Total: %-10llu Free: %-10llu Available: %llu\n"
     453                "Inodes: Total: %-10llu Free: %llu"
     454                "S_context: %C\n"
     455            :   "Block size: %-10lu\n"
     456                "Blocks: Total: %-10llu Free: %-10llu Available: %llu\n"
     457                "Inodes: Total: %-10llu Free: %llu\n"
     458            )
     459        );
    430460    printf(format,
    431            (unsigned long) (statfsbuf.f_bsize),
    432            (intmax_t) (statfsbuf.f_blocks),
    433            (intmax_t) (statfsbuf.f_bfree),
    434            (intmax_t) (statfsbuf.f_bavail),
    435            (intmax_t) (statfsbuf.f_files),
    436            (intmax_t) (statfsbuf.f_ffree),
     461        (unsigned long) statfsbuf.f_bsize,
     462        (unsigned long long) statfsbuf.f_blocks,
     463        (unsigned long long) statfsbuf.f_bfree,
     464        (unsigned long long) statfsbuf.f_bavail,
     465        (unsigned long long) statfsbuf.f_files,
     466        (unsigned long long) statfsbuf.f_ffree,
    437467        scontext);
    438468
    439469    if (scontext)
    440470        freecon(scontext);
    441 #endif
    442 #endif  /* FEATURE_STAT_FORMAT */
     471# endif
     472#endif  /* FEATURE_STAT_FORMAT */
    443473    return 1;
    444474}
    445475
    446476/* stat the file and print what we find */
    447 static bool do_stat(char const *filename, char const *format)
     477#if !ENABLE_FEATURE_STAT_FORMAT
     478#define do_stat(filename, format) do_stat(filename)
     479#endif
     480static bool do_stat(const char *filename, const char *format)
    448481{
    449482    struct stat statbuf;
     
    463496#endif
    464497    if ((option_mask32 & OPT_DEREFERENCE ? stat : lstat) (filename, &statbuf) != 0) {
    465         bb_perror_msg("cannot stat '%s'", filename);
     498        bb_perror_msg("can't stat '%s'", filename);
    466499        return 0;
    467500    }
     
    469502#if ENABLE_FEATURE_STAT_FORMAT
    470503    if (format == NULL) {
    471 #if !ENABLE_SELINUX
     504# if !ENABLE_SELINUX
    472505        if (option_mask32 & OPT_TERSE) {
    473506            format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o";
     
    475508            if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode)) {
    476509                format =
    477                     "  File: \"%N\"\n"
     510                    "  File: %N\n"
    478511                    "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
    479512                    "Device: %Dh/%dd\tInode: %-10i  Links: %-5h"
     
    483516            } else {
    484517                format =
    485                     "  File: \"%N\"\n"
     518                    "  File: %N\n"
    486519                    "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
    487520                    "Device: %Dh/%dd\tInode: %-10i  Links: %h\n"
     
    490523            }
    491524        }
    492 #else
     525# else
    493526        if (option_mask32 & OPT_TERSE) {
    494527            format = (option_mask32 & OPT_SELINUX ?
     
    498531            if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode)) {
    499532                format = (option_mask32 & OPT_SELINUX ?
    500                       "  File: \"%N\"\n"
     533                      "  File: %N\n"
    501534                      "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
    502535                      "Device: %Dh/%dd\tInode: %-10i  Links: %-5h"
     
    505538                      "   S_Context: %C\n"
    506539                      "Access: %x\n" "Modify: %y\n" "Change: %z\n":
    507                       "  File: \"%N\"\n"
     540                      "  File: %N\n"
    508541                      "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
    509542                      "Device: %Dh/%dd\tInode: %-10i  Links: %-5h"
     
    513546            } else {
    514547                format = (option_mask32 & OPT_SELINUX ?
    515                       "  File: \"%N\"\n"
     548                      "  File: %N\n"
    516549                      "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
    517550                      "Device: %Dh/%dd\tInode: %-10i  Links: %h\n"
     
    519552                      "S_Context: %C\n"
    520553                      "Access: %x\n" "Modify: %y\n" "Change: %z\n":
    521                       "  File: \"%N\"\n"
     554                      "  File: %N\n"
    522555                      "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
    523556                      "Device: %Dh/%dd\tInode: %-10i  Links: %h\n"
     
    526559            }
    527560        }
    528 #endif
    529     }
    530     print_it(format, filename, print_stat, &statbuf USE_SELINUX(, scontext));
     561# endif
     562    }
     563    print_it(format, filename, print_stat, &statbuf IF_SELINUX(, scontext));
    531564#else   /* FEATURE_STAT_FORMAT */
    532565    if (option_mask32 & OPT_TERSE) {
    533         printf("%s %ju %ju %lx %lu %lu %jx %ju %lu %lx %lx %lu %lu %lu %lu"
    534                SKIP_SELINUX("\n"),
     566        printf("%s %llu %llu %lx %lu %lu %llx %llu %lu %lx %lx %lu %lu %lu %lu"
     567               IF_NOT_SELINUX("\n"),
    535568               filename,
    536                (uintmax_t) (statbuf.st_size),
    537                (uintmax_t) statbuf.st_blocks,
     569               (unsigned long long) statbuf.st_size,
     570               (unsigned long long) statbuf.st_blocks,
    538571               (unsigned long) statbuf.st_mode,
    539572               (unsigned long) statbuf.st_uid,
    540573               (unsigned long) statbuf.st_gid,
    541                (uintmax_t) statbuf.st_dev,
    542                (uintmax_t) statbuf.st_ino,
     574               (unsigned long long) statbuf.st_dev,
     575               (unsigned long long) statbuf.st_ino,
    543576               (unsigned long) statbuf.st_nlink,
    544577               (unsigned long) major(statbuf.st_rdev),
     
    549582               (unsigned long) statbuf.st_blksize
    550583        );
    551 #if ENABLE_SELINUX
     584# if ENABLE_SELINUX
    552585        if (option_mask32 & OPT_SELINUX)
    553586            printf(" %lc\n", *scontext);
    554587        else
    555             putchar('\n');
    556 #endif
     588            bb_putchar('\n');
     589# endif
    557590    } else {
    558591        char *linkname = NULL;
    559 
    560592        struct passwd *pw_ent;
    561593        struct group *gw_ent;
    562         setgrent();
     594
    563595        gw_ent = getgrgid(statbuf.st_gid);
    564         setpwent();
    565596        pw_ent = getpwuid(statbuf.st_uid);
    566597
    567598        if (S_ISLNK(statbuf.st_mode))
    568599            linkname = xmalloc_readlink_or_warn(filename);
    569         if (linkname)
    570             printf("  File: \"%s\" -> \"%s\"\n", filename, linkname);
    571         else
    572             printf("  File: \"%s\"\n", filename);
    573 
    574         printf("  Size: %-10ju\tBlocks: %-10ju IO Block: %-6lu %s\n"
    575                "Device: %jxh/%jud\tInode: %-10ju  Links: %-5lu",
    576                (uintmax_t) (statbuf.st_size),
    577                (uintmax_t) statbuf.st_blocks,
     600        if (linkname) {
     601            printf("  File: '%s' -> '%s'\n", filename, linkname);
     602            free(linkname);
     603        } else {
     604            printf("  File: '%s'\n", filename);
     605        }
     606
     607        printf("  Size: %-10llu\tBlocks: %-10llu IO Block: %-6lu %s\n"
     608               "Device: %llxh/%llud\tInode: %-10llu  Links: %-5lu",
     609               (unsigned long long) statbuf.st_size,
     610               (unsigned long long) statbuf.st_blocks,
    578611               (unsigned long) statbuf.st_blksize,
    579612               file_type(&statbuf),
    580                (uintmax_t) statbuf.st_dev,
    581                (uintmax_t) statbuf.st_dev,
    582                (uintmax_t) statbuf.st_ino,
     613               (unsigned long long) statbuf.st_dev,
     614               (unsigned long long) statbuf.st_dev,
     615               (unsigned long long) statbuf.st_ino,
    583616               (unsigned long) statbuf.st_nlink);
    584617        if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode))
     
    587620                   (unsigned long) minor(statbuf.st_rdev));
    588621        else
    589             putchar('\n');
     622            bb_putchar('\n');
    590623        printf("Access: (%04lo/%10.10s)  Uid: (%5lu/%8s)   Gid: (%5lu/%8s)\n",
    591624               (unsigned long) (statbuf.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)),
    592625               bb_mode_string(statbuf.st_mode),
    593626               (unsigned long) statbuf.st_uid,
    594                (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN",
     627               (pw_ent != NULL) ? pw_ent->pw_name : "UNKNOWN",
    595628               (unsigned long) statbuf.st_gid,
    596                (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
     629               (gw_ent != NULL) ? gw_ent->gr_name : "UNKNOWN");
     630# if ENABLE_SELINUX
     631        printf("   S_Context: %lc\n", *scontext);
     632# endif
     633        printf("Access: %s\n", human_time(statbuf.st_atime));
     634        printf("Modify: %s\n", human_time(statbuf.st_mtime));
     635        printf("Change: %s\n", human_time(statbuf.st_ctime));
     636    }
     637#endif  /* FEATURE_STAT_FORMAT */
     638    return 1;
     639}
     640
     641int stat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     642int stat_main(int argc UNUSED_PARAM, char **argv)
     643{
     644    IF_FEATURE_STAT_FORMAT(char *format = NULL;)
     645    int i;
     646    int ok;
     647    unsigned opts;
     648    statfunc_ptr statfunc = do_stat;
     649
     650    opt_complementary = "-1"; /* min one arg */
     651    opts = getopt32(argv, "ftL"
     652        IF_SELINUX("Z")
     653        IF_FEATURE_STAT_FORMAT("c:", &format)
     654    );
     655    if (opts & OPT_FILESYS) /* -f */
     656        statfunc = do_statfs;
    597657#if ENABLE_SELINUX
    598         printf("   S_Context: %lc\n", *scontext);
    599 #endif
    600         printf("Access: %s\n" "Modify: %s\n" "Change: %s\n",
    601                human_time(statbuf.st_atime),
    602                human_time(statbuf.st_mtime),
    603                human_time(statbuf.st_ctime));
    604     }
    605 #endif  /* FEATURE_STAT_FORMAT */
    606     return 1;
    607 }
    608 
    609 int stat_main(int argc, char **argv);
    610 int stat_main(int argc, char **argv)
    611 {
    612     char *format = NULL;
    613     int i;
    614     int ok = 1;
    615     bool (*statfunc)(char const *, char const *) = do_stat;
    616 
    617     getopt32(argv, "ftL"
    618         USE_SELINUX("Z")
    619         USE_FEATURE_STAT_FORMAT("c:", &format)
    620     );
    621 
    622     if (option_mask32 & OPT_FILESYS) /* -f */
    623         statfunc = do_statfs;
    624     if (argc == optind)           /* files */
    625         bb_show_usage();
    626 
    627 #if ENABLE_SELINUX
    628     if (option_mask32 & OPT_SELINUX) {
     658    if (opts & OPT_SELINUX) {
    629659        selinux_or_die();
    630660    }
    631 #endif  /* ENABLE_SELINUX */
    632     for (i = optind; i < argc; ++i)
    633         ok &= statfunc(argv[i], format);
     661#endif
     662    ok = 1;
     663    argv += optind;
     664    for (i = 0; argv[i]; ++i)
     665        ok &= statfunc(argv[i] IF_FEATURE_STAT_FORMAT(, format));
    634666
    635667    return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
  • branches/2.2.9/mindi-busybox/coreutils/stty.c

    r1765 r2725  
    33   Copyright (C) 1990-1999 Free Software Foundation, Inc.
    44
    5    Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     5   Licensed under GPLv2 or later, see file LICENSE in this source tree.
    66*/
    77/* Usage: stty [-ag] [-F device] [setting...]
     
    114114#if defined(VSTATUS) && !defined(CSTATUS)
    115115# define CSTATUS Control('t')
     116#endif
     117
     118/* Save us from #ifdef forest plague */
     119#ifndef BSDLY
     120# define BSDLY 0
     121#endif
     122#ifndef CIBAUD
     123# define CIBAUD 0
     124#endif
     125#ifndef CRDLY
     126# define CRDLY 0
     127#endif
     128#ifndef CRTSCTS
     129# define CRTSCTS 0
     130#endif
     131#ifndef ECHOCTL
     132# define ECHOCTL 0
     133#endif
     134#ifndef ECHOKE
     135# define ECHOKE 0
     136#endif
     137#ifndef ECHOPRT
     138# define ECHOPRT 0
     139#endif
     140#ifndef FFDLY
     141# define FFDLY 0
     142#endif
     143#ifndef IEXTEN
     144# define IEXTEN 0
     145#endif
     146#ifndef IMAXBEL
     147# define IMAXBEL 0
     148#endif
     149#ifndef IUCLC
     150# define IUCLC 0
     151#endif
     152#ifndef IXANY
     153# define IXANY 0
     154#endif
     155#ifndef NLDLY
     156# define NLDLY 0
     157#endif
     158#ifndef OCRNL
     159# define OCRNL 0
     160#endif
     161#ifndef OFDEL
     162# define OFDEL 0
     163#endif
     164#ifndef OFILL
     165# define OFILL 0
     166#endif
     167#ifndef OLCUC
     168# define OLCUC 0
     169#endif
     170#ifndef ONLCR
     171# define ONLCR 0
     172#endif
     173#ifndef ONLRET
     174# define ONLRET 0
     175#endif
     176#ifndef ONOCR
     177# define ONOCR 0
     178#endif
     179#ifndef OXTABS
     180# define OXTABS 0
     181#endif
     182#ifndef TABDLY
     183# define TABDLY 0
     184#endif
     185#ifndef TAB1
     186# define TAB1 0
     187#endif
     188#ifndef TAB2
     189# define TAB2 0
     190#endif
     191#ifndef TOSTOP
     192# define TOSTOP 0
     193#endif
     194#ifndef VDSUSP
     195# define VDSUSP 0
     196#endif
     197#ifndef VEOL2
     198# define VEOL2 0
     199#endif
     200#ifndef VFLUSHO
     201# define VFLUSHO 0
     202#endif
     203#ifndef VLNEXT
     204# define VLNEXT 0
     205#endif
     206#ifndef VREPRINT
     207# define VREPRINT 0
     208#endif
     209#ifndef VSTATUS
     210# define VSTATUS 0
     211#endif
     212#ifndef VSWTCH
     213# define VSWTCH 0
     214#endif
     215#ifndef VTDLY
     216# define VTDLY 0
     217#endif
     218#ifndef VWERASE
     219# define VWERASE 0
     220#endif
     221#ifndef XCASE
     222# define XCASE 0
    116223#endif
    117224
     
    128235};
    129236
    130 static const char evenp     [] ALIGN1 = "evenp";
    131 static const char raw       [] ALIGN1 = "raw";
    132 static const char stty_min  [] ALIGN1 = "min";
    133 static const char stty_time [] ALIGN1 = "time";
    134 static const char stty_swtch[] ALIGN1 = "swtch";
    135 static const char stty_eol  [] ALIGN1 = "eol";
    136 static const char stty_eof  [] ALIGN1 = "eof";
    137 static const char parity    [] ALIGN1 = "parity";
    138 static const char stty_oddp [] ALIGN1 = "oddp";
    139 static const char stty_nl   [] ALIGN1 = "nl";
    140 static const char stty_ek   [] ALIGN1 = "ek";
    141 static const char stty_sane [] ALIGN1 = "sane";
    142 static const char cbreak    [] ALIGN1 = "cbreak";
    143 static const char stty_pass8[] ALIGN1 = "pass8";
    144 static const char litout    [] ALIGN1 = "litout";
    145 static const char cooked    [] ALIGN1 = "cooked";
    146 static const char decctlq   [] ALIGN1 = "decctlq";
    147 static const char stty_tabs [] ALIGN1 = "tabs";
    148 static const char stty_lcase[] ALIGN1 = "lcase";
    149 static const char stty_LCASE[] ALIGN1 = "LCASE";
    150 static const char stty_crt  [] ALIGN1 = "crt";
    151 static const char stty_dec  [] ALIGN1 = "dec";
    152 
    153237/* Flags for 'struct mode_info' */
    154238#define SANE_SET 1              /* Set in 'sane' mode                  */
     
    157241#define OMIT 8                  /* Don't display value                 */
    158242
    159 /* Each mode */
     243
     244/* Each mode.
     245 * This structure should be kept as small as humanly possible.
     246 */
    160247struct mode_info {
    161     const char *const name;      /* Name given on command line           */
    162     const unsigned char type;     /* Which structure element to change    */
    163     const unsigned char flags;    /* Setting and display options          */
    164     /* were using short here, but ppc32 was unhappy: */
     248    const uint8_t type;           /* Which structure element to change    */
     249    const uint8_t flags;          /* Setting and display options          */
     250    /* only these values are ever used, so... */
     251#if   (CSIZE | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY) < 0x100
     252    const uint8_t mask;
     253#elif (CSIZE | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY) < 0x10000
     254    const uint16_t mask;
     255#else
    165256    const tcflag_t mask;          /* Other bits to turn off for this mode */
     257#endif
     258    /* was using short here, but ppc32 was unhappy */
    166259    const tcflag_t bits;          /* Bits to set for this mode            */
    167260};
    168261
    169 /* We can optimize it further by using name[8] instead of char *name */
    170 /* but beware of "if (info->name == evenp)" checks! */
    171 /* Need to replace them with "if (info == &mode_info[EVENP_INDX])" */
    172 
    173 #define MI_ENTRY(N,T,F,B,M) { N, T, F, M, B }
     262enum {
     263    /* Must match mode_name[] and mode_info[] order! */
     264    IDX_evenp = 0,
     265    IDX_parity,
     266    IDX_oddp,
     267    IDX_nl,
     268    IDX_ek,
     269    IDX_sane,
     270    IDX_cooked,
     271    IDX_raw,
     272    IDX_pass8,
     273    IDX_litout,
     274    IDX_cbreak,
     275    IDX_crt,
     276    IDX_dec,
     277#if IXANY
     278    IDX_decctlq,
     279#endif
     280#if TABDLY || OXTABS
     281    IDX_tabs,
     282#endif
     283#if XCASE && IUCLC && OLCUC
     284    IDX_lcase,
     285    IDX_LCASE,
     286#endif
     287};
     288
     289#define MI_ENTRY(N,T,F,B,M) N "\0"
     290
     291/* Mode names given on command line */
     292static const char mode_name[] =
     293    MI_ENTRY("evenp",    combination, REV        | OMIT, 0,          0 )
     294    MI_ENTRY("parity",   combination, REV        | OMIT, 0,          0 )
     295    MI_ENTRY("oddp",     combination, REV        | OMIT, 0,          0 )
     296    MI_ENTRY("nl",       combination, REV        | OMIT, 0,          0 )
     297    MI_ENTRY("ek",       combination, OMIT,              0,          0 )
     298    MI_ENTRY("sane",     combination, OMIT,              0,          0 )
     299    MI_ENTRY("cooked",   combination, REV        | OMIT, 0,          0 )
     300    MI_ENTRY("raw",      combination, REV        | OMIT, 0,          0 )
     301    MI_ENTRY("pass8",    combination, REV        | OMIT, 0,          0 )
     302    MI_ENTRY("litout",   combination, REV        | OMIT, 0,          0 )
     303    MI_ENTRY("cbreak",   combination, REV        | OMIT, 0,          0 )
     304    MI_ENTRY("crt",      combination, OMIT,              0,          0 )
     305    MI_ENTRY("dec",      combination, OMIT,              0,          0 )
     306#if IXANY
     307    MI_ENTRY("decctlq",  combination, REV        | OMIT, 0,          0 )
     308#endif
     309#if TABDLY || OXTABS
     310    MI_ENTRY("tabs",     combination, REV        | OMIT, 0,          0 )
     311#endif
     312#if XCASE && IUCLC && OLCUC
     313    MI_ENTRY("lcase",    combination, REV        | OMIT, 0,          0 )
     314    MI_ENTRY("LCASE",    combination, REV        | OMIT, 0,          0 )
     315#endif
     316    MI_ENTRY("parenb",   control,     REV,               PARENB,     0 )
     317    MI_ENTRY("parodd",   control,     REV,               PARODD,     0 )
     318    MI_ENTRY("cs5",      control,     0,                 CS5,     CSIZE)
     319    MI_ENTRY("cs6",      control,     0,                 CS6,     CSIZE)
     320    MI_ENTRY("cs7",      control,     0,                 CS7,     CSIZE)
     321    MI_ENTRY("cs8",      control,     0,                 CS8,     CSIZE)
     322    MI_ENTRY("hupcl",    control,     REV,               HUPCL,      0 )
     323    MI_ENTRY("hup",      control,     REV        | OMIT, HUPCL,      0 )
     324    MI_ENTRY("cstopb",   control,     REV,               CSTOPB,     0 )
     325    MI_ENTRY("cread",    control,     SANE_SET   | REV,  CREAD,      0 )
     326    MI_ENTRY("clocal",   control,     REV,               CLOCAL,     0 )
     327#if CRTSCTS
     328    MI_ENTRY("crtscts",  control,     REV,               CRTSCTS,    0 )
     329#endif
     330    MI_ENTRY("ignbrk",   input,       SANE_UNSET | REV,  IGNBRK,     0 )
     331    MI_ENTRY("brkint",   input,       SANE_SET   | REV,  BRKINT,     0 )
     332    MI_ENTRY("ignpar",   input,       REV,               IGNPAR,     0 )
     333    MI_ENTRY("parmrk",   input,       REV,               PARMRK,     0 )
     334    MI_ENTRY("inpck",    input,       REV,               INPCK,      0 )
     335    MI_ENTRY("istrip",   input,       REV,               ISTRIP,     0 )
     336    MI_ENTRY("inlcr",    input,       SANE_UNSET | REV,  INLCR,      0 )
     337    MI_ENTRY("igncr",    input,       SANE_UNSET | REV,  IGNCR,      0 )
     338    MI_ENTRY("icrnl",    input,       SANE_SET   | REV,  ICRNL,      0 )
     339    MI_ENTRY("ixon",     input,       REV,               IXON,       0 )
     340    MI_ENTRY("ixoff",    input,       SANE_UNSET | REV,  IXOFF,      0 )
     341    MI_ENTRY("tandem",   input,       REV        | OMIT, IXOFF,      0 )
     342#if IUCLC
     343    MI_ENTRY("iuclc",    input,       SANE_UNSET | REV,  IUCLC,      0 )
     344#endif
     345#if IXANY
     346    MI_ENTRY("ixany",    input,       SANE_UNSET | REV,  IXANY,      0 )
     347#endif
     348#if IMAXBEL
     349    MI_ENTRY("imaxbel",  input,       SANE_SET   | REV,  IMAXBEL,    0 )
     350#endif
     351    MI_ENTRY("opost",    output,      SANE_SET   | REV,  OPOST,      0 )
     352#if OLCUC
     353    MI_ENTRY("olcuc",    output,      SANE_UNSET | REV,  OLCUC,      0 )
     354#endif
     355#if OCRNL
     356    MI_ENTRY("ocrnl",    output,      SANE_UNSET | REV,  OCRNL,      0 )
     357#endif
     358#if ONLCR
     359    MI_ENTRY("onlcr",    output,      SANE_SET   | REV,  ONLCR,      0 )
     360#endif
     361#if ONOCR
     362    MI_ENTRY("onocr",    output,      SANE_UNSET | REV,  ONOCR,      0 )
     363#endif
     364#if ONLRET
     365    MI_ENTRY("onlret",   output,      SANE_UNSET | REV,  ONLRET,     0 )
     366#endif
     367#if OFILL
     368    MI_ENTRY("ofill",    output,      SANE_UNSET | REV,  OFILL,      0 )
     369#endif
     370#if OFDEL
     371    MI_ENTRY("ofdel",    output,      SANE_UNSET | REV,  OFDEL,      0 )
     372#endif
     373#if NLDLY
     374    MI_ENTRY("nl1",      output,      SANE_UNSET,        NL1,     NLDLY)
     375    MI_ENTRY("nl0",      output,      SANE_SET,          NL0,     NLDLY)
     376#endif
     377#if CRDLY
     378    MI_ENTRY("cr3",      output,      SANE_UNSET,        CR3,     CRDLY)
     379    MI_ENTRY("cr2",      output,      SANE_UNSET,        CR2,     CRDLY)
     380    MI_ENTRY("cr1",      output,      SANE_UNSET,        CR1,     CRDLY)
     381    MI_ENTRY("cr0",      output,      SANE_SET,          CR0,     CRDLY)
     382#endif
     383
     384#if TABDLY
     385    MI_ENTRY("tab3",     output,      SANE_UNSET,        TAB3,   TABDLY)
     386# if TAB2
     387    MI_ENTRY("tab2",     output,      SANE_UNSET,        TAB2,   TABDLY)
     388# endif
     389# if TAB1
     390    MI_ENTRY("tab1",     output,      SANE_UNSET,        TAB1,   TABDLY)
     391# endif
     392    MI_ENTRY("tab0",     output,      SANE_SET,          TAB0,   TABDLY)
     393#else
     394# if OXTABS
     395    MI_ENTRY("tab3",     output,      SANE_UNSET,        OXTABS,     0 )
     396# endif
     397#endif
     398
     399#if BSDLY
     400    MI_ENTRY("bs1",      output,      SANE_UNSET,        BS1,     BSDLY)
     401    MI_ENTRY("bs0",      output,      SANE_SET,          BS0,     BSDLY)
     402#endif
     403#if VTDLY
     404    MI_ENTRY("vt1",      output,      SANE_UNSET,        VT1,     VTDLY)
     405    MI_ENTRY("vt0",      output,      SANE_SET,          VT0,     VTDLY)
     406#endif
     407#if FFDLY
     408    MI_ENTRY("ff1",      output,      SANE_UNSET,        FF1,     FFDLY)
     409    MI_ENTRY("ff0",      output,      SANE_SET,          FF0,     FFDLY)
     410#endif
     411    MI_ENTRY("isig",     local,       SANE_SET   | REV,  ISIG,       0 )
     412    MI_ENTRY("icanon",   local,       SANE_SET   | REV,  ICANON,     0 )
     413#if IEXTEN
     414    MI_ENTRY("iexten",   local,       SANE_SET   | REV,  IEXTEN,     0 )
     415#endif
     416    MI_ENTRY("echo",     local,       SANE_SET   | REV,  ECHO,       0 )
     417    MI_ENTRY("echoe",    local,       SANE_SET   | REV,  ECHOE,      0 )
     418    MI_ENTRY("crterase", local,       REV        | OMIT, ECHOE,      0 )
     419    MI_ENTRY("echok",    local,       SANE_SET   | REV,  ECHOK,      0 )
     420    MI_ENTRY("echonl",   local,       SANE_UNSET | REV,  ECHONL,     0 )
     421    MI_ENTRY("noflsh",   local,       SANE_UNSET | REV,  NOFLSH,     0 )
     422#if XCASE
     423    MI_ENTRY("xcase",    local,       SANE_UNSET | REV,  XCASE,      0 )
     424#endif
     425#if TOSTOP
     426    MI_ENTRY("tostop",   local,       SANE_UNSET | REV,  TOSTOP,     0 )
     427#endif
     428#if ECHOPRT
     429    MI_ENTRY("echoprt",  local,       SANE_UNSET | REV,  ECHOPRT,    0 )
     430    MI_ENTRY("prterase", local,       REV | OMIT,        ECHOPRT,    0 )
     431#endif
     432#if ECHOCTL
     433    MI_ENTRY("echoctl",  local,       SANE_SET   | REV,  ECHOCTL,    0 )
     434    MI_ENTRY("ctlecho",  local,       REV        | OMIT, ECHOCTL,    0 )
     435#endif
     436#if ECHOKE
     437    MI_ENTRY("echoke",   local,       SANE_SET   | REV,  ECHOKE,     0 )
     438    MI_ENTRY("crtkill",  local,       REV        | OMIT, ECHOKE,     0 )
     439#endif
     440    ;
     441
     442#undef MI_ENTRY
     443#define MI_ENTRY(N,T,F,B,M) { T, F, M, B },
    174444
    175445static const struct mode_info mode_info[] = {
    176     MI_ENTRY("parenb",   control,     REV,               PARENB,     0 ),
    177     MI_ENTRY("parodd",   control,     REV,               PARODD,     0 ),
    178     MI_ENTRY("cs5",      control,     0,                 CS5,     CSIZE),
    179     MI_ENTRY("cs6",      control,     0,                 CS6,     CSIZE),
    180     MI_ENTRY("cs7",      control,     0,                 CS7,     CSIZE),
    181     MI_ENTRY("cs8",      control,     0,                 CS8,     CSIZE),
    182     MI_ENTRY("hupcl",    control,     REV,               HUPCL,      0 ),
    183     MI_ENTRY("hup",      control,     REV        | OMIT, HUPCL,      0 ),
    184     MI_ENTRY("cstopb",   control,     REV,               CSTOPB,     0 ),
    185     MI_ENTRY("cread",    control,     SANE_SET   | REV,  CREAD,      0 ),
    186     MI_ENTRY("clocal",   control,     REV,               CLOCAL,     0 ),
    187 #ifdef CRTSCTS
    188     MI_ENTRY("crtscts",  control,     REV,               CRTSCTS,    0 ),
    189 #endif
    190     MI_ENTRY("ignbrk",   input,       SANE_UNSET | REV,  IGNBRK,     0 ),
    191     MI_ENTRY("brkint",   input,       SANE_SET   | REV,  BRKINT,     0 ),
    192     MI_ENTRY("ignpar",   input,       REV,               IGNPAR,     0 ),
    193     MI_ENTRY("parmrk",   input,       REV,               PARMRK,     0 ),
    194     MI_ENTRY("inpck",    input,       REV,               INPCK,      0 ),
    195     MI_ENTRY("istrip",   input,       REV,               ISTRIP,     0 ),
    196     MI_ENTRY("inlcr",    input,       SANE_UNSET | REV,  INLCR,      0 ),
    197     MI_ENTRY("igncr",    input,       SANE_UNSET | REV,  IGNCR,      0 ),
    198     MI_ENTRY("icrnl",    input,       SANE_SET   | REV,  ICRNL,      0 ),
    199     MI_ENTRY("ixon",     input,       REV,               IXON,       0 ),
    200     MI_ENTRY("ixoff",    input,       SANE_UNSET | REV,  IXOFF,      0 ),
    201     MI_ENTRY("tandem",   input,       REV        | OMIT, IXOFF,      0 ),
    202 #ifdef IUCLC
    203     MI_ENTRY("iuclc",    input,       SANE_UNSET | REV,  IUCLC,      0 ),
    204 #endif
    205 #ifdef IXANY
    206     MI_ENTRY("ixany",    input,       SANE_UNSET | REV,  IXANY,      0 ),
    207 #endif
    208 #ifdef IMAXBEL
    209     MI_ENTRY("imaxbel",  input,       SANE_SET   | REV,  IMAXBEL,    0 ),
    210 #endif
    211     MI_ENTRY("opost",    output,      SANE_SET   | REV,  OPOST,      0 ),
    212 #ifdef OLCUC
    213     MI_ENTRY("olcuc",    output,      SANE_UNSET | REV,  OLCUC,      0 ),
    214 #endif
    215 #ifdef OCRNL
    216     MI_ENTRY("ocrnl",    output,      SANE_UNSET | REV,  OCRNL,      0 ),
    217 #endif
    218 #ifdef ONLCR
    219     MI_ENTRY("onlcr",    output,      SANE_SET   | REV,  ONLCR,      0 ),
    220 #endif
    221 #ifdef ONOCR
    222     MI_ENTRY("onocr",    output,      SANE_UNSET | REV,  ONOCR,      0 ),
    223 #endif
    224 #ifdef ONLRET
    225     MI_ENTRY("onlret",   output,      SANE_UNSET | REV,  ONLRET,     0 ),
    226 #endif
    227 #ifdef OFILL
    228     MI_ENTRY("ofill",    output,      SANE_UNSET | REV,  OFILL,      0 ),
    229 #endif
    230 #ifdef OFDEL
    231     MI_ENTRY("ofdel",    output,      SANE_UNSET | REV,  OFDEL,      0 ),
    232 #endif
    233 #ifdef NLDLY
    234     MI_ENTRY("nl1",      output,      SANE_UNSET,        NL1,     NLDLY),
    235     MI_ENTRY("nl0",      output,      SANE_SET,          NL0,     NLDLY),
    236 #endif
    237 #ifdef CRDLY
    238     MI_ENTRY("cr3",      output,      SANE_UNSET,        CR3,     CRDLY),
    239     MI_ENTRY("cr2",      output,      SANE_UNSET,        CR2,     CRDLY),
    240     MI_ENTRY("cr1",      output,      SANE_UNSET,        CR1,     CRDLY),
    241     MI_ENTRY("cr0",      output,      SANE_SET,          CR0,     CRDLY),
    242 #endif
    243 
    244 #ifdef TABDLY
    245     MI_ENTRY("tab3",     output,      SANE_UNSET,        TAB3,   TABDLY),
    246     MI_ENTRY("tab2",     output,      SANE_UNSET,        TAB2,   TABDLY),
    247     MI_ENTRY("tab1",     output,      SANE_UNSET,        TAB1,   TABDLY),
    248     MI_ENTRY("tab0",     output,      SANE_SET,          TAB0,   TABDLY),
     446    /* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */
     447    MI_ENTRY("evenp",    combination, REV        | OMIT, 0,          0 )
     448    MI_ENTRY("parity",   combination, REV        | OMIT, 0,          0 )
     449    MI_ENTRY("oddp",     combination, REV        | OMIT, 0,          0 )
     450    MI_ENTRY("nl",       combination, REV        | OMIT, 0,          0 )
     451    MI_ENTRY("ek",       combination, OMIT,              0,          0 )
     452    MI_ENTRY("sane",     combination, OMIT,              0,          0 )
     453    MI_ENTRY("cooked",   combination, REV        | OMIT, 0,          0 )
     454    MI_ENTRY("raw",      combination, REV        | OMIT, 0,          0 )
     455    MI_ENTRY("pass8",    combination, REV        | OMIT, 0,          0 )
     456    MI_ENTRY("litout",   combination, REV        | OMIT, 0,          0 )
     457    MI_ENTRY("cbreak",   combination, REV        | OMIT, 0,          0 )
     458    MI_ENTRY("crt",      combination, OMIT,              0,          0 )
     459    MI_ENTRY("dec",      combination, OMIT,              0,          0 )
     460#if IXANY
     461    MI_ENTRY("decctlq",  combination, REV        | OMIT, 0,          0 )
     462#endif
     463#if TABDLY || OXTABS
     464    MI_ENTRY("tabs",     combination, REV        | OMIT, 0,          0 )
     465#endif
     466#if XCASE && IUCLC && OLCUC
     467    MI_ENTRY("lcase",    combination, REV        | OMIT, 0,          0 )
     468    MI_ENTRY("LCASE",    combination, REV        | OMIT, 0,          0 )
     469#endif
     470    MI_ENTRY("parenb",   control,     REV,               PARENB,     0 )
     471    MI_ENTRY("parodd",   control,     REV,               PARODD,     0 )
     472    MI_ENTRY("cs5",      control,     0,                 CS5,     CSIZE)
     473    MI_ENTRY("cs6",      control,     0,                 CS6,     CSIZE)
     474    MI_ENTRY("cs7",      control,     0,                 CS7,     CSIZE)
     475    MI_ENTRY("cs8",      control,     0,                 CS8,     CSIZE)
     476    MI_ENTRY("hupcl",    control,     REV,               HUPCL,      0 )
     477    MI_ENTRY("hup",      control,     REV        | OMIT, HUPCL,      0 )
     478    MI_ENTRY("cstopb",   control,     REV,               CSTOPB,     0 )
     479    MI_ENTRY("cread",    control,     SANE_SET   | REV,  CREAD,      0 )
     480    MI_ENTRY("clocal",   control,     REV,               CLOCAL,     0 )
     481#if CRTSCTS
     482    MI_ENTRY("crtscts",  control,     REV,               CRTSCTS,    0 )
     483#endif
     484    MI_ENTRY("ignbrk",   input,       SANE_UNSET | REV,  IGNBRK,     0 )
     485    MI_ENTRY("brkint",   input,       SANE_SET   | REV,  BRKINT,     0 )
     486    MI_ENTRY("ignpar",   input,       REV,               IGNPAR,     0 )
     487    MI_ENTRY("parmrk",   input,       REV,               PARMRK,     0 )
     488    MI_ENTRY("inpck",    input,       REV,               INPCK,      0 )
     489    MI_ENTRY("istrip",   input,       REV,               ISTRIP,     0 )
     490    MI_ENTRY("inlcr",    input,       SANE_UNSET | REV,  INLCR,      0 )
     491    MI_ENTRY("igncr",    input,       SANE_UNSET | REV,  IGNCR,      0 )
     492    MI_ENTRY("icrnl",    input,       SANE_SET   | REV,  ICRNL,      0 )
     493    MI_ENTRY("ixon",     input,       REV,               IXON,       0 )
     494    MI_ENTRY("ixoff",    input,       SANE_UNSET | REV,  IXOFF,      0 )
     495    MI_ENTRY("tandem",   input,       REV        | OMIT, IXOFF,      0 )
     496#if IUCLC
     497    MI_ENTRY("iuclc",    input,       SANE_UNSET | REV,  IUCLC,      0 )
     498#endif
     499#if IXANY
     500    MI_ENTRY("ixany",    input,       SANE_UNSET | REV,  IXANY,      0 )
     501#endif
     502#if IMAXBEL
     503    MI_ENTRY("imaxbel",  input,       SANE_SET   | REV,  IMAXBEL,    0 )
     504#endif
     505    MI_ENTRY("opost",    output,      SANE_SET   | REV,  OPOST,      0 )
     506#if OLCUC
     507    MI_ENTRY("olcuc",    output,      SANE_UNSET | REV,  OLCUC,      0 )
     508#endif
     509#if OCRNL
     510    MI_ENTRY("ocrnl",    output,      SANE_UNSET | REV,  OCRNL,      0 )
     511#endif
     512#if ONLCR
     513    MI_ENTRY("onlcr",    output,      SANE_SET   | REV,  ONLCR,      0 )
     514#endif
     515#if ONOCR
     516    MI_ENTRY("onocr",    output,      SANE_UNSET | REV,  ONOCR,      0 )
     517#endif
     518#if ONLRET
     519    MI_ENTRY("onlret",   output,      SANE_UNSET | REV,  ONLRET,     0 )
     520#endif
     521#if OFILL
     522    MI_ENTRY("ofill",    output,      SANE_UNSET | REV,  OFILL,      0 )
     523#endif
     524#if OFDEL
     525    MI_ENTRY("ofdel",    output,      SANE_UNSET | REV,  OFDEL,      0 )
     526#endif
     527#if NLDLY
     528    MI_ENTRY("nl1",      output,      SANE_UNSET,        NL1,     NLDLY)
     529    MI_ENTRY("nl0",      output,      SANE_SET,          NL0,     NLDLY)
     530#endif
     531#if CRDLY
     532    MI_ENTRY("cr3",      output,      SANE_UNSET,        CR3,     CRDLY)
     533    MI_ENTRY("cr2",      output,      SANE_UNSET,        CR2,     CRDLY)
     534    MI_ENTRY("cr1",      output,      SANE_UNSET,        CR1,     CRDLY)
     535    MI_ENTRY("cr0",      output,      SANE_SET,          CR0,     CRDLY)
     536#endif
     537
     538#if TABDLY
     539    MI_ENTRY("tab3",     output,      SANE_UNSET,        TAB3,   TABDLY)
     540# if TAB2
     541    MI_ENTRY("tab2",     output,      SANE_UNSET,        TAB2,   TABDLY)
     542# endif
     543# if TAB1
     544    MI_ENTRY("tab1",     output,      SANE_UNSET,        TAB1,   TABDLY)
     545# endif
     546    MI_ENTRY("tab0",     output,      SANE_SET,          TAB0,   TABDLY)
    249547#else
    250 # ifdef OXTABS
    251     MI_ENTRY("tab3",     output,      SANE_UNSET,        OXTABS,     0 ),
     548# if OXTABS
     549    MI_ENTRY("tab3",     output,      SANE_UNSET,        OXTABS,     0 )
    252550# endif
    253551#endif
    254552
    255 #ifdef BSDLY
    256     MI_ENTRY("bs1",      output,      SANE_UNSET,        BS1,     BSDLY),
    257     MI_ENTRY("bs0",      output,      SANE_SET,          BS0,     BSDLY),
    258 #endif
    259 #ifdef VTDLY
    260     MI_ENTRY("vt1",      output,      SANE_UNSET,        VT1,     VTDLY),
    261     MI_ENTRY("vt0",      output,      SANE_SET,          VT0,     VTDLY),
    262 #endif
    263 #ifdef FFDLY
    264     MI_ENTRY("ff1",      output,      SANE_UNSET,        FF1,     FFDLY),
    265     MI_ENTRY("ff0",      output,      SANE_SET,          FF0,     FFDLY),
    266 #endif
    267     MI_ENTRY("isig",     local,       SANE_SET   | REV,  ISIG,       0 ),
    268     MI_ENTRY("icanon",   local,       SANE_SET   | REV,  ICANON,     0 ),
    269 #ifdef IEXTEN
    270     MI_ENTRY("iexten",   local,       SANE_SET   | REV,  IEXTEN,     0 ),
    271 #endif
    272     MI_ENTRY("echo",     local,       SANE_SET   | REV,  ECHO,       0 ),
    273     MI_ENTRY("echoe",    local,       SANE_SET   | REV,  ECHOE,      0 ),
    274     MI_ENTRY("crterase", local,       REV        | OMIT, ECHOE,      0 ),
    275     MI_ENTRY("echok",    local,       SANE_SET   | REV,  ECHOK,      0 ),
    276     MI_ENTRY("echonl",   local,       SANE_UNSET | REV,  ECHONL,     0 ),
    277     MI_ENTRY("noflsh",   local,       SANE_UNSET | REV,  NOFLSH,     0 ),
    278 #ifdef XCASE
    279     MI_ENTRY("xcase",    local,       SANE_UNSET | REV,  XCASE,      0 ),
    280 #endif
    281 #ifdef TOSTOP
    282     MI_ENTRY("tostop",   local,       SANE_UNSET | REV,  TOSTOP,     0 ),
    283 #endif
    284 #ifdef ECHOPRT
    285     MI_ENTRY("echoprt",  local,       SANE_UNSET | REV,  ECHOPRT,    0 ),
    286     MI_ENTRY("prterase", local,       REV | OMIT,        ECHOPRT,    0 ),
    287 #endif
    288 #ifdef ECHOCTL
    289     MI_ENTRY("echoctl",  local,       SANE_SET   | REV,  ECHOCTL,    0 ),
    290     MI_ENTRY("ctlecho",  local,       REV        | OMIT, ECHOCTL,    0 ),
    291 #endif
    292 #ifdef ECHOKE
    293     MI_ENTRY("echoke",   local,       SANE_SET   | REV,  ECHOKE,     0 ),
    294     MI_ENTRY("crtkill",  local,       REV        | OMIT, ECHOKE,     0 ),
    295 #endif
    296     MI_ENTRY(evenp,      combination, REV        | OMIT, 0,          0 ),
    297     MI_ENTRY(parity,     combination, REV        | OMIT, 0,          0 ),
    298     MI_ENTRY(stty_oddp,  combination, REV        | OMIT, 0,          0 ),
    299     MI_ENTRY(stty_nl,    combination, REV        | OMIT, 0,          0 ),
    300     MI_ENTRY(stty_ek,    combination, OMIT,              0,          0 ),
    301     MI_ENTRY(stty_sane,  combination, OMIT,              0,          0 ),
    302     MI_ENTRY(cooked,     combination, REV        | OMIT, 0,          0 ),
    303     MI_ENTRY(raw,        combination, REV        | OMIT, 0,          0 ),
    304     MI_ENTRY(stty_pass8, combination, REV        | OMIT, 0,          0 ),
    305     MI_ENTRY(litout,     combination, REV        | OMIT, 0,          0 ),
    306     MI_ENTRY(cbreak,     combination, REV        | OMIT, 0,          0 ),
    307 #ifdef IXANY
    308     MI_ENTRY(decctlq,    combination, REV        | OMIT, 0,          0 ),
    309 #endif
    310 #if defined(TABDLY) || defined(OXTABS)
    311     MI_ENTRY(stty_tabs,  combination, REV        | OMIT, 0,          0 ),
    312 #endif
    313 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
    314     MI_ENTRY(stty_lcase, combination, REV        | OMIT, 0,          0 ),
    315     MI_ENTRY(stty_LCASE, combination, REV        | OMIT, 0,          0 ),
    316 #endif
    317     MI_ENTRY(stty_crt,   combination, OMIT,              0,          0 ),
    318     MI_ENTRY(stty_dec,   combination, OMIT,              0,          0 ),
     553#if BSDLY
     554    MI_ENTRY("bs1",      output,      SANE_UNSET,        BS1,     BSDLY)
     555    MI_ENTRY("bs0",      output,      SANE_SET,          BS0,     BSDLY)
     556#endif
     557#if VTDLY
     558    MI_ENTRY("vt1",      output,      SANE_UNSET,        VT1,     VTDLY)
     559    MI_ENTRY("vt0",      output,      SANE_SET,          VT0,     VTDLY)
     560#endif
     561#if FFDLY
     562    MI_ENTRY("ff1",      output,      SANE_UNSET,        FF1,     FFDLY)
     563    MI_ENTRY("ff0",      output,      SANE_SET,          FF0,     FFDLY)
     564#endif
     565    MI_ENTRY("isig",     local,       SANE_SET   | REV,  ISIG,       0 )
     566    MI_ENTRY("icanon",   local,       SANE_SET   | REV,  ICANON,     0 )
     567#if IEXTEN
     568    MI_ENTRY("iexten",   local,       SANE_SET   | REV,  IEXTEN,     0 )
     569#endif
     570    MI_ENTRY("echo",     local,       SANE_SET   | REV,  ECHO,       0 )
     571    MI_ENTRY("echoe",    local,       SANE_SET   | REV,  ECHOE,      0 )
     572    MI_ENTRY("crterase", local,       REV        | OMIT, ECHOE,      0 )
     573    MI_ENTRY("echok",    local,       SANE_SET   | REV,  ECHOK,      0 )
     574    MI_ENTRY("echonl",   local,       SANE_UNSET | REV,  ECHONL,     0 )
     575    MI_ENTRY("noflsh",   local,       SANE_UNSET | REV,  NOFLSH,     0 )
     576#if XCASE
     577    MI_ENTRY("xcase",    local,       SANE_UNSET | REV,  XCASE,      0 )
     578#endif
     579#if TOSTOP
     580    MI_ENTRY("tostop",   local,       SANE_UNSET | REV,  TOSTOP,     0 )
     581#endif
     582#if ECHOPRT
     583    MI_ENTRY("echoprt",  local,       SANE_UNSET | REV,  ECHOPRT,    0 )
     584    MI_ENTRY("prterase", local,       REV | OMIT,        ECHOPRT,    0 )
     585#endif
     586#if ECHOCTL
     587    MI_ENTRY("echoctl",  local,       SANE_SET   | REV,  ECHOCTL,    0 )
     588    MI_ENTRY("ctlecho",  local,       REV        | OMIT, ECHOCTL,    0 )
     589#endif
     590#if ECHOKE
     591    MI_ENTRY("echoke",   local,       SANE_SET   | REV,  ECHOKE,     0 )
     592    MI_ENTRY("crtkill",  local,       REV        | OMIT, ECHOKE,     0 )
     593#endif
    319594};
    320595
     
    323598};
    324599
    325 /* Control character settings */
     600
     601/* Control characters */
    326602struct control_info {
    327     const char *const name;               /* Name given on command line */
    328     const unsigned char saneval;          /* Value to set for 'stty sane' */
    329     const unsigned char offset;           /* Offset in c_cc */
     603    const uint8_t saneval;  /* Value to set for 'stty sane' */
     604    const uint8_t offset;   /* Offset in c_cc */
    330605};
    331606
    332 /* Control characters */
     607enum {
     608    /* Must match control_name[] and control_info[] order! */
     609    CIDX_intr = 0,
     610    CIDX_quit,
     611    CIDX_erase,
     612    CIDX_kill,
     613    CIDX_eof,
     614    CIDX_eol,
     615#if VEOL2
     616    CIDX_eol2,
     617#endif
     618#if VSWTCH
     619    CIDX_swtch,
     620#endif
     621    CIDX_start,
     622    CIDX_stop,
     623    CIDX_susp,
     624#if VDSUSP
     625    CIDX_dsusp,
     626#endif
     627#if VREPRINT
     628    CIDX_rprnt,
     629#endif
     630#if VWERASE
     631    CIDX_werase,
     632#endif
     633#if VLNEXT
     634    CIDX_lnext,
     635#endif
     636#if VFLUSHO
     637    CIDX_flush,
     638#endif
     639#if VSTATUS
     640    CIDX_status,
     641#endif
     642    CIDX_min,
     643    CIDX_time,
     644};
     645
     646#define CI_ENTRY(n,s,o) n "\0"
     647
     648/* Name given on command line */
     649static const char control_name[] =
     650    CI_ENTRY("intr",     CINTR,   VINTR   )
     651    CI_ENTRY("quit",     CQUIT,   VQUIT   )
     652    CI_ENTRY("erase",    CERASE,  VERASE  )
     653    CI_ENTRY("kill",     CKILL,   VKILL   )
     654    CI_ENTRY("eof",      CEOF,    VEOF    )
     655    CI_ENTRY("eol",      CEOL,    VEOL    )
     656#if VEOL2
     657    CI_ENTRY("eol2",     CEOL2,   VEOL2   )
     658#endif
     659#if VSWTCH
     660    CI_ENTRY("swtch",    CSWTCH,  VSWTCH  )
     661#endif
     662    CI_ENTRY("start",    CSTART,  VSTART  )
     663    CI_ENTRY("stop",     CSTOP,   VSTOP   )
     664    CI_ENTRY("susp",     CSUSP,   VSUSP   )
     665#if VDSUSP
     666    CI_ENTRY("dsusp",    CDSUSP,  VDSUSP  )
     667#endif
     668#if VREPRINT
     669    CI_ENTRY("rprnt",    CRPRNT,  VREPRINT)
     670#endif
     671#if VWERASE
     672    CI_ENTRY("werase",   CWERASE, VWERASE )
     673#endif
     674#if VLNEXT
     675    CI_ENTRY("lnext",    CLNEXT,  VLNEXT  )
     676#endif
     677#if VFLUSHO
     678    CI_ENTRY("flush",    CFLUSHO, VFLUSHO )
     679#endif
     680#if VSTATUS
     681    CI_ENTRY("status",   CSTATUS, VSTATUS )
     682#endif
     683    /* These must be last because of the display routines */
     684    CI_ENTRY("min",      1,       VMIN    )
     685    CI_ENTRY("time",     0,       VTIME   )
     686    ;
     687
     688#undef CI_ENTRY
     689#define CI_ENTRY(n,s,o) { s, o },
    333690
    334691static const struct control_info control_info[] = {
    335     {"intr",     CINTR,   VINTR},
    336     {"quit",     CQUIT,   VQUIT},
    337     {"erase",    CERASE,  VERASE},
    338     {"kill",     CKILL,   VKILL},
    339     {stty_eof,   CEOF,    VEOF},
    340     {stty_eol,   CEOL,    VEOL},
    341 #ifdef VEOL2
    342     {"eol2",     CEOL2,   VEOL2},
    343 #endif
    344 #ifdef VSWTCH
    345     {stty_swtch, CSWTCH,  VSWTCH},
    346 #endif
    347     {"start",    CSTART,  VSTART},
    348     {"stop",     CSTOP,   VSTOP},
    349     {"susp",     CSUSP,   VSUSP},
    350 #ifdef VDSUSP
    351     {"dsusp",    CDSUSP,  VDSUSP},
    352 #endif
    353 #ifdef VREPRINT
    354     {"rprnt",    CRPRNT,  VREPRINT},
    355 #endif
    356 #ifdef VWERASE
    357     {"werase",   CWERASE, VWERASE},
    358 #endif
    359 #ifdef VLNEXT
    360     {"lnext",    CLNEXT,  VLNEXT},
    361 #endif
    362 #ifdef VFLUSHO
    363     {"flush",    CFLUSHO, VFLUSHO},
    364 #endif
    365 #ifdef VSTATUS
    366     {"status",   CSTATUS, VSTATUS},
     692    /* This should be verbatim cut-n-paste copy of the above CI_ENTRYs */
     693    CI_ENTRY("intr",     CINTR,   VINTR   )
     694    CI_ENTRY("quit",     CQUIT,   VQUIT   )
     695    CI_ENTRY("erase",    CERASE,  VERASE  )
     696    CI_ENTRY("kill",     CKILL,   VKILL   )
     697    CI_ENTRY("eof",      CEOF,    VEOF    )
     698    CI_ENTRY("eol",      CEOL,    VEOL    )
     699#if VEOL2
     700    CI_ENTRY("eol2",     CEOL2,   VEOL2   )
     701#endif
     702#if VSWTCH
     703    CI_ENTRY("swtch",    CSWTCH,  VSWTCH  )
     704#endif
     705    CI_ENTRY("start",    CSTART,  VSTART  )
     706    CI_ENTRY("stop",     CSTOP,   VSTOP   )
     707    CI_ENTRY("susp",     CSUSP,   VSUSP   )
     708#if VDSUSP
     709    CI_ENTRY("dsusp",    CDSUSP,  VDSUSP  )
     710#endif
     711#if VREPRINT
     712    CI_ENTRY("rprnt",    CRPRNT,  VREPRINT)
     713#endif
     714#if VWERASE
     715    CI_ENTRY("werase",   CWERASE, VWERASE )
     716#endif
     717#if VLNEXT
     718    CI_ENTRY("lnext",    CLNEXT,  VLNEXT  )
     719#endif
     720#if VFLUSHO
     721    CI_ENTRY("flush",    CFLUSHO, VFLUSHO )
     722#endif
     723#if VSTATUS
     724    CI_ENTRY("status",   CSTATUS, VSTATUS )
    367725#endif
    368726    /* These must be last because of the display routines */
    369     {stty_min,   1,       VMIN},
    370     {stty_time,  0,       VTIME},
     727    CI_ENTRY("min",      1,       VMIN    )
     728    CI_ENTRY("time",     0,       VTIME   )
    371729};
    372730
     
    375733};
    376734
    377 /* The width of the screen, for output wrapping */
    378 unsigned max_col = 80; /* default */
    379735
    380736struct globals {
     737    const char *device_name;
     738    /* The width of the screen, for output wrapping */
     739    unsigned max_col;
    381740    /* Current position, to know when to wrap */
    382741    unsigned current_col;
    383742    char buf[10];
    384 };
     743} FIX_ALIASING;
    385744#define G (*(struct globals*)&bb_common_bufsiz1)
    386 
    387 static const char *device_name = bb_msg_standard_input;
     745#define INIT_G() do { \
     746    G.device_name = bb_msg_standard_input; \
     747    G.max_col = 80; \
     748} while (0)
     749
    388750
    389751/* Return a string that is the printable representation of character CH */
     
    418780static tcflag_t *mode_type_flag(unsigned type, const struct termios *mode)
    419781{
    420     static const unsigned char tcflag_offsets[] ALIGN1 = {
     782    static const uint8_t tcflag_offsets[] ALIGN1 = {
    421783        offsetof(struct termios, c_cflag), /* control */
    422784        offsetof(struct termios, c_iflag), /* input */
     
    431793}
    432794
    433 static void set_speed_or_die(enum speed_setting type, const char *const arg,
    434                     struct termios * const mode)
     795static void set_speed_or_die(enum speed_setting type, const char *arg,
     796                    struct termios *mode)
    435797{
    436798    speed_t baud;
     
    446808}
    447809
    448 static ATTRIBUTE_NORETURN void perror_on_device_and_die(const char *fmt)
    449 {
    450     bb_perror_msg_and_die(fmt, device_name);
     810static NORETURN void perror_on_device_and_die(const char *fmt)
     811{
     812    bb_perror_msg_and_die(fmt, G.device_name);
    451813}
    452814
    453815static void perror_on_device(const char *fmt)
    454816{
    455     bb_perror_msg(fmt, device_name);
     817    bb_perror_msg(fmt, G.device_name);
    456818}
    457819
     
    463825    char buf[128];
    464826    va_list args;
    465     int buflen;
     827    unsigned buflen;
    466828
    467829    va_start(args, message);
     
    475837        G.current_col++;
    476838        if (buf[0] != '\n') {
    477             if (G.current_col + buflen >= max_col) {
    478                 putchar('\n');
     839            if (G.current_col + buflen >= G.max_col) {
     840                bb_putchar('\n');
    479841                G.current_col = 0;
    480842            } else
    481                 putchar(' ');
     843                bb_putchar(' ');
    482844        }
    483845    }
     
    488850}
    489851
    490 static void set_window_size(const int rows, const int cols)
    491 {
    492     struct winsize win = { 0, 0, 0, 0};
     852static void newline(void)
     853{
     854    if (G.current_col != 0)
     855        wrapf("\n");
     856}
     857
     858#ifdef TIOCGWINSZ
     859static void set_window_size(int rows, int cols)
     860{
     861    struct winsize win = { 0, 0, 0, 0 };
    493862
    494863    if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win)) {
     
    508877        perror_on_device("%s");
    509878}
    510 
    511 static void display_window_size(const int fancy)
     879#endif
     880
     881static void display_window_size(int fancy)
    512882{
    513883    const char *fmt_str = "%s\0%s: no size information for this device";
     
    519889        }
    520890    } else {
    521         wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n",
     891        wrapf(fancy ? "rows %u; columns %u;" : "%u %u\n",
    522892                height, width);
    523893    }
     
    528898    { "k", 1024 },
    529899    { "B", 1024 },
    530     { }
     900    { "", 0 }
    531901};
    532902
    533903static const struct mode_info *find_mode(const char *name)
    534904{
    535     int i;
    536     for (i = 0; i < NUM_mode_info; ++i)
    537         if (!strcmp(name, mode_info[i].name))
    538             return &mode_info[i];
    539     return 0;
     905    int i = index_in_strings(mode_name, name);
     906    return i >= 0 ? &mode_info[i] : NULL;
    540907}
    541908
    542909static const struct control_info *find_control(const char *name)
    543910{
    544     int i;
    545     for (i = 0; i < NUM_control_info; ++i)
    546         if (!strcmp(name, control_info[i].name))
    547             return &control_info[i];
    548     return 0;
     911    int i = index_in_strings(control_name, name);
     912    return i >= 0 ? &control_info[i] : NULL;
    549913}
    550914
     
    561925};
    562926
    563 static int find_param(const char *const name)
     927static int find_param(const char *name)
    564928{
    565929    static const char params[] ALIGN1 =
     
    611975
    612976static void display_recoverable(const struct termios *mode,
    613                 int ATTRIBUTE_UNUSED dummy)
     977                int UNUSED_PARAM dummy)
    614978{
    615979    int i;
     
    619983    for (i = 0; i < NCCS; ++i)
    620984        printf(":%x", (unsigned int) mode->c_cc[i]);
    621     putchar('\n');
     985    bb_putchar('\n');
    622986}
    623987
    624988static void display_speed(const struct termios *mode, int fancy)
    625989{
    626                          //01234567 8 9
     990    //____________________ 01234567 8 9
    627991    const char *fmt_str = "%lu %lu\n\0ispeed %lu baud; ospeed %lu baud;";
    628992    unsigned long ispeed, ospeed;
     
    631995    if (ispeed == 0 || ispeed == (ospeed = cfgetospeed(mode))) {
    632996        ispeed = ospeed;                /* in case ispeed was 0 */
    633                  //0123 4 5 6 7 8 9
     997        //________ 0123 4 5 6 7 8 9
    634998        fmt_str = "%lu\n\0\0\0\0\0speed %lu baud;";
    635999    }
     
    6381002}
    6391003
    640 static void do_display(const struct termios *mode, const int all)
     1004static void do_display(const struct termios *mode, int all)
    6411005{
    6421006    int i;
     
    6491013        display_window_size(1);
    6501014#ifdef HAVE_C_LINE
    651     wrapf("line = %d;\n", mode->c_line);
     1015    wrapf("line = %u;\n", mode->c_line);
    6521016#else
    653     wrapf("\n");
    654 #endif
    655 
    656     for (i = 0; control_info[i].name != stty_min; ++i) {
     1017    newline();
     1018#endif
     1019
     1020    for (i = 0; i != CIDX_min; ++i) {
    6571021        /* If swtch is the same as susp, don't print both */
    6581022#if VSWTCH == VSUSP
    659         if (control_info[i].name == stty_swtch)
     1023        if (i == CIDX_swtch)
    6601024            continue;
    6611025#endif
    6621026        /* If eof uses the same slot as min, only print whichever applies */
    6631027#if VEOF == VMIN
    664         if ((mode->c_lflag & ICANON) == 0
    665             && (control_info[i].name == stty_eof
    666                 || control_info[i].name == stty_eol)) continue;
    667 #endif
    668         wrapf("%s = %s;", control_info[i].name,
     1028        if (!(mode->c_lflag & ICANON)
     1029         && (i == CIDX_eof || i == CIDX_eol)
     1030        ) {
     1031            continue;
     1032        }
     1033#endif
     1034        wrapf("%s = %s;", nth_string(control_name, i),
    6691035              visible(mode->c_cc[control_info[i].offset]));
    6701036    }
     
    6721038    if ((mode->c_lflag & ICANON) == 0)
    6731039#endif
    674         wrapf("min = %d; time = %d;", mode->c_cc[VMIN], mode->c_cc[VTIME]);
    675     if (G.current_col) wrapf("\n");
     1040        wrapf("min = %u; time = %u;", mode->c_cc[VMIN], mode->c_cc[VTIME]);
     1041    newline();
    6761042
    6771043    for (i = 0; i < NUM_mode_info; ++i) {
     
    6791045            continue;
    6801046        if (mode_info[i].type != prev_type) {
    681             /* wrapf("\n"); */
    682             if (G.current_col) wrapf("\n");
     1047            newline();
    6831048            prev_type = mode_info[i].type;
    6841049        }
     
    6881053        if ((*bitsp & mask) == mode_info[i].bits) {
    6891054            if (all || (mode_info[i].flags & SANE_UNSET))
    690                 wrapf("%s", mode_info[i].name);
     1055                wrapf("-%s"+1, nth_string(mode_name, i));
    6911056        } else {
    692             if ((all && mode_info[i].flags & REV) ||
    693                  (!all &&
    694                   (mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV)))
    695                 wrapf("-%s", mode_info[i].name);
    696         }
    697     }
    698     if (G.current_col) wrapf("\n");
     1057            if ((all && mode_info[i].flags & REV)
     1058             || (!all && (mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
     1059            ) {
     1060                wrapf("-%s", nth_string(mode_name, i));
     1061            }
     1062        }
     1063    }
     1064    newline();
    6991065}
    7001066
     
    7061072    for (i = 0; i < NUM_control_info; ++i) {
    7071073#if VMIN == VEOF
    708         if (control_info[i].name == stty_min)
     1074        if (i == CIDX_min)
    7091075            break;
    7101076#endif
     
    7251091}
    7261092
    727 /* Save set_mode from #ifdef forest plague */
    728 #ifndef ONLCR
    729 #define ONLCR 0
    730 #endif
    731 #ifndef OCRNL
    732 #define OCRNL 0
    733 #endif
    734 #ifndef ONLRET
    735 #define ONLRET 0
    736 #endif
    737 #ifndef XCASE
    738 #define XCASE 0
    739 #endif
    740 #ifndef IXANY
    741 #define IXANY 0
    742 #endif
    743 #ifndef TABDLY
    744 #define TABDLY 0
    745 #endif
    746 #ifndef OXTABS
    747 #define OXTABS 0
    748 #endif
    749 #ifndef IUCLC
    750 #define IUCLC 0
    751 #endif
    752 #ifndef OLCUC
    753 #define OLCUC 0
    754 #endif
    755 #ifndef ECHOCTL
    756 #define ECHOCTL 0
    757 #endif
    758 #ifndef ECHOKE
    759 #define ECHOKE 0
    760 #endif
    761 
    7621093static void set_mode(const struct mode_info *info, int reversed,
    7631094                    struct termios *mode)
     
    7761107
    7771108    /* Combination mode */
    778     if (info->name == evenp || info->name == parity) {
     1109    if (info == &mode_info[IDX_evenp] || info == &mode_info[IDX_parity]) {
    7791110        if (reversed)
    7801111            mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
    7811112        else
    782             mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
    783     } else if (info->name == stty_oddp) {
     1113            mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
     1114    } else if (info == &mode_info[IDX_oddp]) {
    7841115        if (reversed)
    7851116            mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
    7861117        else
    787             mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
    788     } else if (info->name == stty_nl) {
     1118            mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
     1119    } else if (info == &mode_info[IDX_nl]) {
    7891120        if (reversed) {
    7901121            mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
    791             mode->c_oflag = (mode->c_oflag | ONLCR) & ~OCRNL & ~ONLRET;
     1122            mode->c_oflag = (mode->c_oflag | ONLCR) & ~OCRNL & ~ONLRET;
    7921123        } else {
    7931124            mode->c_iflag = mode->c_iflag & ~ICRNL;
    7941125            if (ONLCR) mode->c_oflag = mode->c_oflag & ~ONLCR;
    7951126        }
    796     } else if (info->name == stty_ek) {
     1127    } else if (info == &mode_info[IDX_ek]) {
    7971128        mode->c_cc[VERASE] = CERASE;
    7981129        mode->c_cc[VKILL] = CKILL;
    799     } else if (info->name == stty_sane) {
     1130    } else if (info == &mode_info[IDX_sane]) {
    8001131        sane_mode(mode);
    801     }
    802     else if (info->name == cbreak) {
     1132    } else if (info == &mode_info[IDX_cbreak]) {
    8031133        if (reversed)
    8041134            mode->c_lflag |= ICANON;
    8051135        else
    8061136            mode->c_lflag &= ~ICANON;
    807     } else if (info->name == stty_pass8) {
     1137    } else if (info == &mode_info[IDX_pass8]) {
    8081138        if (reversed) {
    8091139            mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
     
    8131143            mode->c_iflag &= ~ISTRIP;
    8141144        }
    815     } else if (info->name == litout) {
     1145    } else if (info == &mode_info[IDX_litout]) {
    8161146        if (reversed) {
    8171147            mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
     
    8231153            mode->c_oflag &= ~OPOST;
    8241154        }
    825     } else if (info->name == raw || info->name == cooked) {
    826         if ((info->name[0] == 'r' && reversed)
    827             || (info->name[0] == 'c' && !reversed)) {
     1155    } else if (info == &mode_info[IDX_raw] || info == &mode_info[IDX_cooked]) {
     1156        if ((info == &mode_info[IDX_raw] && reversed)
     1157         || (info == &mode_info[IDX_cooked] && !reversed)
     1158        ) {
    8281159            /* Cooked mode */
    8291160            mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
     
    8451176        }
    8461177    }
    847     else if (IXANY && info->name == decctlq) {
     1178#if IXANY
     1179    else if (info == &mode_info[IDX_decctlq]) {
    8481180        if (reversed)
    8491181            mode->c_iflag |= IXANY;
     
    8511183            mode->c_iflag &= ~IXANY;
    8521184    }
    853     else if (TABDLY && info->name == stty_tabs) {
     1185#endif
     1186#if TABDLY
     1187    else if (info == &mode_info[IDX_tabs]) {
    8541188        if (reversed)
    8551189            mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
     
    8571191            mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
    8581192    }
    859     else if (OXTABS && info->name == stty_tabs) {
     1193#endif
     1194#if OXTABS
     1195    else if (info == &mode_info[IDX_tabs]) {
    8601196        if (reversed)
    8611197            mode->c_oflag |= OXTABS;
     
    8631199            mode->c_oflag &= ~OXTABS;
    8641200    }
    865     else if (XCASE && IUCLC && OLCUC
    866     && (info->name == stty_lcase || info->name == stty_LCASE)) {
     1201#endif
     1202#if XCASE && IUCLC && OLCUC
     1203    else if (info==&mode_info[IDX_lcase] || info==&mode_info[IDX_LCASE]) {
    8671204        if (reversed) {
    8681205            mode->c_lflag &= ~XCASE;
     
    8751212        }
    8761213    }
    877     else if (info->name == stty_crt) {
     1214#endif
     1215    else if (info == &mode_info[IDX_crt]) {
    8781216        mode->c_lflag |= ECHOE | ECHOCTL | ECHOKE;
    879     }
    880     else if (info->name == stty_dec) {
     1217    } else if (info == &mode_info[IDX_dec]) {
    8811218        mode->c_cc[VINTR] = 3; /* ^C */
    8821219        mode->c_cc[VERASE] = 127; /* DEL */
     
    8921229    unsigned char value;
    8931230
    894     if (info->name == stty_min || info->name == stty_time)
     1231    if (info == &control_info[CIDX_min] || info == &control_info[CIDX_time])
    8951232        value = xatoul_range_sfx(arg, 0, 0xff, stty_suffixes);
    8961233    else if (arg[0] == '\0' || arg[1] == '\0')
    8971234        value = arg[0];
    898     else if (!strcmp(arg, "^-") || !strcmp(arg, "undef"))
     1235    else if (strcmp(arg, "^-") == 0 || strcmp(arg, "undef") == 0)
    8991236        value = _POSIX_VDISABLE;
    9001237    else if (arg[0] == '^') { /* Ignore any trailing junk (^Cjunk) */
     
    9071244}
    9081245
    909 #define STTY_require_set_attr   (1<<0)
    910 #define STTY_speed_was_set      (1<<1)
    911 #define STTY_verbose_output     (1<<2)
    912 #define STTY_recoverable_output (1<<3)
    913 #define STTY_noargs             (1<<4)
    914 int stty_main(int argc, char **argv);
    915 int stty_main(int argc, char **argv)
     1246#define STTY_require_set_attr   (1 << 0)
     1247#define STTY_speed_was_set      (1 << 1)
     1248#define STTY_verbose_output     (1 << 2)
     1249#define STTY_recoverable_output (1 << 3)
     1250#define STTY_noargs             (1 << 4)
     1251
     1252int stty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     1253int stty_main(int argc UNUSED_PARAM, char **argv)
    9161254{
    9171255    struct termios mode;
    918     void (*output_func)(const struct termios *, const int);
     1256    void (*output_func)(const struct termios *, int);
    9191257    const char *file_name = NULL;
    9201258    int display_all = 0;
    9211259    int stty_state;
    9221260    int k;
     1261
     1262    INIT_G();
    9231263
    9241264    stty_state = STTY_noargs;
     
    9661306                            bb_error_msg_and_die(bb_msg_requires_arg, "-F");
    9671307                        /* remove -F param from arg[vc] */
    968                         --argc;
    969                         while (argv[p]) { argv[p] = argv[p+1]; ++p; }
     1308                        while (argv[p]) {
     1309                            argv[p] = argv[p+1];
     1310                            ++p;
     1311                        }
    9701312                    }
    9711313                    goto end_option;
     
    10421384        bb_error_msg_and_die("verbose and stty-readable output styles are mutually exclusive");
    10431385    /* Specifying -a or -g with non-options is an error */
    1044     if (!(stty_state & STTY_noargs) &&
    1045         (stty_state & (STTY_verbose_output | STTY_recoverable_output)))
     1386    if (!(stty_state & STTY_noargs)
     1387     && (stty_state & (STTY_verbose_output | STTY_recoverable_output))
     1388    ) {
    10461389        bb_error_msg_and_die("modes may not be set when specifying an output style");
     1390    }
    10471391
    10481392    /* Now it is safe to start doing things */
    10491393    if (file_name) {
    1050         int fd, fdflags;
    1051         device_name = file_name;
    1052         fd = xopen(device_name, O_RDONLY | O_NONBLOCK);
    1053         if (fd != STDIN_FILENO) {
    1054             dup2(fd, STDIN_FILENO);
    1055             close(fd);
    1056         }
    1057         fdflags = fcntl(STDIN_FILENO, F_GETFL);
    1058         if (fdflags < 0 ||
    1059             fcntl(STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
    1060             perror_on_device_and_die("%s: cannot reset non-blocking mode");
     1394        G.device_name = file_name;
     1395        xmove_fd(xopen_nonblocking(G.device_name), STDIN_FILENO);
     1396        ndelay_off(STDIN_FILENO);
    10611397    }
    10621398
     
    10681404
    10691405    if (stty_state & (STTY_verbose_output | STTY_recoverable_output | STTY_noargs)) {
    1070         get_terminal_width_height(STDOUT_FILENO, &max_col, NULL);
     1406        get_terminal_width_height(STDOUT_FILENO, &G.max_col, NULL);
    10711407        output_func(&mode, display_all);
    10721408        return EXIT_SUCCESS;
     
    11211457#ifdef TIOCGWINSZ
    11221458        case param_cols:
     1459        case param_columns:
    11231460            set_window_size(-1, xatoul_sfx(argnext, stty_suffixes));
    11241461            break;
     
    11721509
    11731510        if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) {
    1174 #ifdef CIBAUD
     1511#if CIBAUD
    11751512            /* SunOS 4.1.3 (at least) has the problem that after this sequence,
    11761513               tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
  • branches/2.2.9/mindi-busybox/coreutils/sum.c

    r1765 r2725  
    1111 * Taken from coreutils and turned into a busybox applet by Mike Frysinger
    1212 *
    13  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     13 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1414 */
    1515
     
    2222/* SYSV: calculate and print the checksum and the size in 512-byte blocks */
    2323/* Return 1 if successful.  */
    24 static unsigned sum_file(const char *file, const unsigned type)
     24static unsigned sum_file(const char *file, unsigned type)
    2525{
    2626#define buf bb_common_bufsiz1
    27     uintmax_t total_bytes = 0;
    28     int fd = 0, r;
    29 
     27    unsigned long long total_bytes = 0;
     28    int fd, r;
    3029    /* The sum of all the input bytes, modulo (UINT_MAX + 1).  */
    3130    unsigned s = 0;
    3231
    33     if (NOT_LONE_DASH(file)) {
    34         fd = open(file, O_RDONLY);
    35         if (fd == -1)
    36             goto ret_bad;
    37     }
     32    fd = open_or_warn_stdin(file);
     33    if (fd == -1)
     34        return 0;
    3835
    3936    while (1) {
     
    4542                /* no error */
    4643                break;
    47  ret_bad:
    48             bb_perror_msg(file);
     44            bb_simple_perror_msg(file);
    4945            return 0;
    5046        }
     
    6864        r = (s & 0xffff) + ((s & 0xffffffff) >> 16);
    6965        s = (r & 0xffff) + (r >> 16);
    70         printf("%d %ju %s\n", s, (total_bytes+511)/512, file);
     66        printf("%d %llu %s\n", s, (total_bytes + 511) / 512, file);
    7167    } else
    72         printf("%05d %5ju %s\n", s, (total_bytes+1023)/1024, file);
     68        printf("%05d %5llu %s\n", s, (total_bytes + 1023) / 1024, file);
    7369    return 1;
    7470#undef buf
    7571}
    7672
    77 int sum_main(int argc, char **argv);
    78 int sum_main(int argc, char **argv)
     73int sum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     74int sum_main(int argc UNUSED_PARAM, char **argv)
    7975{
    8076    unsigned n;
     
    8278
    8379    n = getopt32(argv, "sr");
     80    argv += optind;
    8481    if (n & 1) type = SUM_SYSV;
    8582    /* give the bsd priority over sysv func */
    8683    if (n & 2) type = SUM_BSD;
    8784
    88     if (argc == optind) {
     85    if (!argv[0]) {
    8986        /* Do not print the name */
    9087        n = sum_file("-", type);
     
    9390           - more than one file given
    9491           - doing sysv */
    95         type += argc - 1 > optind || type == SUM_SYSV;
    96         for (n = 1; optind < argc; optind++)
    97             n &= sum_file(argv[optind], type);
     92        type += (argv[1] || type == SUM_SYSV);
     93        n = 1;
     94        do {
     95            n &= sum_file(*argv, type);
     96        } while (*++argv);
    9897    }
    9998    return !n;
  • branches/2.2.9/mindi-busybox/coreutils/sync.c

    r1765 r2725  
    55 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1414/* This is a NOFORK applet. Be very careful! */
    1515
    16 int sync_main(int argc, char **argv);
    17 int sync_main(int argc, char **argv)
     16int sync_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     17int sync_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM))
    1818{
    19     bb_warn_ignoring_args(argc - 1);
     19    /* coreutils-6.9 compat */
     20    bb_warn_ignoring_args(argv[1]);
    2021
    2122    sync();
  • branches/2.2.9/mindi-busybox/coreutils/tail.c

    r1772 r2725  
    55 * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    3131    { "k", 1024 },
    3232    { "m", 1024*1024 },
    33     { }
     33    { "", 0 }
    3434};
    3535
    3636struct globals {
    3737    bool status;
    38 };
     38} FIX_ALIASING;
    3939#define G (*(struct globals*)&bb_common_bufsiz1)
    4040
     
    5151    struct stat sbuf;
    5252
    53     /* (A good comment is missing here) */
    54     current = lseek(fd, 0, SEEK_CUR);
    5553    /* /proc files report zero st_size, don't lseek them. */
    56     if (fstat(fd, &sbuf) == 0 && sbuf.st_size)
     54    if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) {
     55        current = lseek(fd, 0, SEEK_CUR);
    5756        if (sbuf.st_size < current)
    58             lseek(fd, 0, SEEK_SET);
    59 
    60     r = safe_read(fd, buf, count);
     57            xlseek(fd, 0, SEEK_SET);
     58    }
     59
     60    r = full_read(fd, buf, count);
    6161    if (r < 0) {
    6262        bb_perror_msg(bb_msg_read_error);
     
    6767}
    6868
    69 static const char header_fmt[] ALIGN1 = "\n==> %s <==\n";
     69#define header_fmt_str "\n==> %s <==\n"
    7070
    7171static unsigned eat_num(const char *p)
     
    7575    else if (*p == '+') {
    7676        p++;
    77         G.status = EXIT_FAILURE;
     77        G.status = 1; /* mark that we saw "+" */
    7878    }
    7979    return xatou_sfx(p, tail_suffixes);
    8080}
    8181
    82 int tail_main(int argc, char **argv);
     82int tail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    8383int tail_main(int argc, char **argv)
    8484{
     
    8686    unsigned sleep_period = 1;
    8787    bool from_top;
    88     int header_threshhold = 1;
    8988    const char *str_c, *str_n;
    90     USE_FEATURE_FANCY_TAIL(const char *str_s;)
    9189
    9290    char *tailbuf;
    9391    size_t tailbufsize;
    94     int taillen = 0;
    95     int newline = 0;
    96     int nfiles, nread, nwrite, seen, i, opt;
     92    unsigned header_threshhold = 1;
     93    unsigned nfiles;
     94    int i, opt;
    9795
    9896    int *fds;
    99     char *s, *buf;
    10097    const char *fmt;
    10198
    10299#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL
    103100    /* Allow legacy syntax of an initial numeric option without -n. */
    104     if (argc >= 2 && (argv[1][0] == '+' || argv[1][0] == '-')
     101    if (argv[1] && (argv[1][0] == '+' || argv[1][0] == '-')
    105102     && isdigit(argv[1][1])
    106103    ) {
    107         /* replacing arg[0] with "-n" can segfault, so... */
    108         argv[1] = xasprintf("-n%s", argv[1]);
    109 #if 0 /* If we ever decide to make tail NOFORK */
    110         char *s = alloca(strlen(argv[1]) + 3);
    111         sprintf(s, "-n%s", argv[1]);
    112         argv[1] = s;
     104        count = eat_num(argv[1]);
     105        argv++;
     106        argc--;
     107    }
    113108#endif
    114     }
    115 #endif
    116 
    117     opt = getopt32(argv, "fc:n:" USE_FEATURE_FANCY_TAIL("qs:v"),
    118             &str_c, &str_n USE_FEATURE_FANCY_TAIL(,&str_s));
     109
     110    /* -s NUM, -F imlies -f */
     111    IF_FEATURE_FANCY_TAIL(opt_complementary = "s+:Ff";)
     112    opt = getopt32(argv, "fc:n:" IF_FEATURE_FANCY_TAIL("qs:vF"),
     113            &str_c, &str_n IF_FEATURE_FANCY_TAIL(,&sleep_period));
    119114#define FOLLOW (opt & 0x1)
    120115#define COUNT_BYTES (opt & 0x2)
     
    123118    if (opt & 0x4) count = eat_num(str_n); // -n
    124119#if ENABLE_FEATURE_FANCY_TAIL
    125     if (opt & 0x8) header_threshhold = INT_MAX; // -q
    126     if (opt & 0x10) sleep_period = xatou(str_s); // -s
     120    /* q: make it impossible for nfiles to be > header_threshhold */
     121    if (opt & 0x8) header_threshhold = UINT_MAX; // -q
     122    //if (opt & 0x10) // -s
    127123    if (opt & 0x20) header_threshhold = 0; // -v
     124# define FOLLOW_RETRY (opt & 0x40)
     125#else
     126# define FOLLOW_RETRY 0
    128127#endif
    129128    argc -= optind;
    130129    argv += optind;
    131     from_top = G.status;
     130    from_top = G.status; /* 1 if there was "-c +N" or "-n +N" */
     131    G.status = EXIT_SUCCESS;
    132132
    133133    /* open all the files */
    134     fds = xmalloc(sizeof(int) * (argc + 1));
     134    fds = xmalloc(sizeof(fds[0]) * (argc + 1));
     135    if (!argv[0]) {
     136        struct stat statbuf;
     137
     138        if (fstat(STDIN_FILENO, &statbuf) == 0
     139         && S_ISFIFO(statbuf.st_mode)
     140        ) {
     141            opt &= ~1; /* clear FOLLOW */
     142        }
     143        argv[0] = (char *) bb_msg_standard_input;
     144    }
    135145    nfiles = i = 0;
    136     G.status = EXIT_SUCCESS;
    137     if (argc == 0) {
    138         struct stat statbuf;
    139 
    140         if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) {
    141             opt &= ~1; /* clear FOLLOW */
    142         }
    143         *argv = (char *) bb_msg_standard_input;
    144     }
    145146    do {
    146         FILE* fil = fopen_or_warn_stdin(argv[i]);
    147         if (!fil) {
     147        int fd = open_or_warn_stdin(argv[i]);
     148        if (fd < 0 && !FOLLOW_RETRY) {
    148149            G.status = EXIT_FAILURE;
    149150            continue;
    150151        }
    151         fds[nfiles] = fileno(fil);
     152        fds[nfiles] = fd;
    152153        argv[nfiles++] = argv[i];
    153154    } while (++i < argc);
     
    156157        bb_error_msg_and_die("no files");
    157158
     159    /* prepare the buffer */
    158160    tailbufsize = BUFSIZ;
     161    if (!from_top && COUNT_BYTES) {
     162        if (tailbufsize < count + BUFSIZ) {
     163            tailbufsize = count + BUFSIZ;
     164        }
     165    }
     166    tailbuf = xmalloc(tailbufsize);
    159167
    160168    /* tail the files */
    161     if (!from_top && COUNT_BYTES) {
    162         if (tailbufsize < count) {
    163             tailbufsize = count + BUFSIZ;
    164         }
    165     }
    166 
    167     buf = tailbuf = xmalloc(tailbufsize);
    168 
    169     fmt = header_fmt + 1;   /* Skip header leading newline on first output. */
     169    fmt = header_fmt_str + 1; /* skip header leading newline on first output */
    170170    i = 0;
    171171    do {
    172         /* Be careful.  It would be possible to optimize the count-bytes
    173          * case if the file is seekable.  If you do though, remember that
    174          * starting file position may not be the beginning of the file.
    175          * Beware of backing up too far.  See example in wc.c.
    176          */
    177         if (!(count | from_top) && lseek(fds[i], 0, SEEK_END) >= 0) {
    178             continue;
    179         }
     172        char *buf;
     173        int taillen;
     174        int newlines_seen;
     175        unsigned seen;
     176        int nread;
     177        int fd = fds[i];
     178
     179        if (ENABLE_FEATURE_FANCY_TAIL && fd < 0)
     180            continue; /* may happen with -E */
    180181
    181182        if (nfiles > header_threshhold) {
    182183            tail_xprint_header(fmt, argv[i]);
    183             fmt = header_fmt;
     184            fmt = header_fmt_str;
     185        }
     186
     187        if (!from_top) {
     188            off_t current = lseek(fd, 0, SEEK_END);
     189            if (current > 0) {
     190                unsigned off;
     191                if (COUNT_BYTES) {
     192                /* Optimizing count-bytes case if the file is seekable.
     193                 * Beware of backing up too far.
     194                 * Also we exclude files with size 0 (because of /proc/xxx) */
     195                    if (count == 0)
     196                        continue; /* showing zero bytes is easy :) */
     197                    current -= count;
     198                    if (current < 0)
     199                        current = 0;
     200                    xlseek(fd, current, SEEK_SET);
     201                    bb_copyfd_size(fd, STDOUT_FILENO, count);
     202                    continue;
     203                }
     204#if 1 /* This is technically incorrect for *LONG* strings, but very useful */
     205                /* Optimizing count-lines case if the file is seekable.
     206                 * We assume the lines are <64k.
     207                 * (Users complain that tail takes too long
     208                 * on multi-gigabyte files) */
     209                off = (count | 0xf); /* for small counts, be more paranoid */
     210                if (off > (INT_MAX / (64*1024)))
     211                    off = (INT_MAX / (64*1024));
     212                current -= off * (64*1024);
     213                if (current < 0)
     214                    current = 0;
     215                xlseek(fd, current, SEEK_SET);
     216#endif
     217            }
    184218        }
    185219
    186220        buf = tailbuf;
    187221        taillen = 0;
     222        /* "We saw 1st line/byte".
     223         * Used only by +N code ("start from Nth", 1-based): */
    188224        seen = 1;
    189         newline = 0;
    190 
    191         while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {
     225        newlines_seen = 0;
     226        while ((nread = tail_read(fd, buf, tailbufsize-taillen)) > 0) {
    192227            if (from_top) {
    193                 nwrite = nread;
     228                int nwrite = nread;
    194229                if (seen < count) {
     230                    /* We need to skip a few more bytes/lines */
    195231                    if (COUNT_BYTES) {
    196232                        nwrite -= (count - seen);
    197233                        seen = count;
    198234                    } else {
    199                         s = buf;
     235                        char *s = buf;
    200236                        do {
    201237                            --nwrite;
     
    206242                    }
    207243                }
    208                 xwrite(STDOUT_FILENO, buf + nread - nwrite, nwrite);
     244                if (nwrite > 0)
     245                    xwrite(STDOUT_FILENO, buf + nread - nwrite, nwrite);
    209246            } else if (count) {
    210247                if (COUNT_BYTES) {
    211248                    taillen += nread;
    212                     if (taillen > count) {
     249                    if (taillen > (int)count) {
    213250                        memmove(tailbuf, tailbuf + taillen - count, count);
    214251                        taillen = count;
     
    216253                } else {
    217254                    int k = nread;
    218                     int nbuf = 0;
    219 
    220                     while (k) {
    221                         --k;
     255                    int newlines_in_buf = 0;
     256
     257                    do { /* count '\n' in last read */
     258                        k--;
    222259                        if (buf[k] == '\n') {
    223                             ++nbuf;
     260                            newlines_in_buf++;
    224261                        }
    225                     }
    226 
    227                     if (newline + nbuf < count) {
    228                         newline += nbuf;
     262                    } while (k);
     263
     264                    if (newlines_seen + newlines_in_buf < (int)count) {
     265                        newlines_seen += newlines_in_buf;
    229266                        taillen += nread;
    230267                    } else {
    231                         int extra = 0;
    232 
    233                         if (buf[nread-1] != '\n')
    234                             extra = 1;
    235                         k = newline + nbuf + extra - count;
     268                        int extra = (buf[nread-1] != '\n');
     269                        char *s;
     270
     271                        k = newlines_seen + newlines_in_buf + extra - count;
    236272                        s = tailbuf;
    237273                        while (k) {
    238274                            if (*s == '\n') {
    239                                 --k;
     275                                k--;
    240276                            }
    241                             ++s;
     277                            s++;
    242278                        }
    243279                        taillen += nread - (s - tailbuf);
    244280                        memmove(tailbuf, s, taillen);
    245                         newline = count - extra;
    246                     }
    247                     if (tailbufsize < taillen + BUFSIZ) {
     281                        newlines_seen = count - extra;
     282                    }
     283                    if (tailbufsize < (size_t)taillen + BUFSIZ) {
    248284                        tailbufsize = taillen + BUFSIZ;
    249285                        tailbuf = xrealloc(tailbuf, tailbufsize);
     
    252288                buf = tailbuf + taillen;
    253289            }
    254         }
    255 
     290        } /* while (tail_read() > 0) */
    256291        if (!from_top) {
    257292            xwrite(STDOUT_FILENO, tailbuf, taillen);
    258293        }
    259 
    260         taillen = 0;
    261294    } while (++i < nfiles);
    262295
    263     buf = xrealloc(tailbuf, BUFSIZ);
     296    tailbuf = xrealloc(tailbuf, BUFSIZ);
    264297
    265298    fmt = NULL;
     
    267300    if (FOLLOW) while (1) {
    268301        sleep(sleep_period);
     302
    269303        i = 0;
    270304        do {
     305            int nread;
     306            const char *filename = argv[i];
     307            int fd = fds[i];
     308
     309            if (FOLLOW_RETRY) {
     310                struct stat sbuf, fsbuf;
     311
     312                if (fd < 0
     313                 || fstat(fd, &fsbuf) < 0
     314                 || stat(filename, &sbuf) < 0
     315                 || fsbuf.st_dev != sbuf.st_dev
     316                 || fsbuf.st_ino != sbuf.st_ino
     317                ) {
     318                    int new_fd;
     319
     320                    if (fd >= 0)
     321                        close(fd);
     322                    new_fd = open(filename, O_RDONLY);
     323                    if (new_fd >= 0) {
     324                        bb_error_msg("%s has %s; following end of new file",
     325                            filename, (fd < 0) ? "appeared" : "been replaced"
     326                        );
     327                    } else if (fd >= 0) {
     328                        bb_perror_msg("%s has become inaccessible", filename);
     329                    }
     330                    fds[i] = fd = new_fd;
     331                }
     332            }
     333            if (ENABLE_FEATURE_FANCY_TAIL && fd < 0)
     334                continue;
    271335            if (nfiles > header_threshhold) {
    272                 fmt = header_fmt;
    273             }
    274             while ((nread = tail_read(fds[i], buf, sizeof(buf))) > 0) {
     336                fmt = header_fmt_str;
     337            }
     338            while ((nread = tail_read(fd, tailbuf, BUFSIZ)) > 0) {
    275339                if (fmt) {
    276                     tail_xprint_header(fmt, argv[i]);
     340                    tail_xprint_header(fmt, filename);
    277341                    fmt = NULL;
    278342                }
    279                 xwrite(STDOUT_FILENO, buf, nread);
     343                xwrite(STDOUT_FILENO, tailbuf, nread);
    280344            }
    281345        } while (++i < nfiles);
     
    283347    if (ENABLE_FEATURE_CLEAN_UP) {
    284348        free(fds);
     349        free(tailbuf);
    285350    }
    286351    return G.status;
  • branches/2.2.9/mindi-busybox/coreutils/tee.c

    r1765 r2725  
    55 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1212
    1313#include "libbb.h"
    14 #include <signal.h>
    1514
    16 int tee_main(int argc, char **argv);
     15int tee_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    1716int tee_main(int argc, char **argv)
    1817{
     
    2322    char **np;
    2423    char retval;
     24//TODO: make unconditional
    2525#if ENABLE_FEATURE_TEE_USE_BLOCK_IO
    2626    ssize_t c;
     
    3636
    3737    if (retval & 1) {
    38         signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction. */
     38        signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction. (why?) */
    3939    }
    4040    retval = EXIT_SUCCESS;
    4141    /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
    4242     * that doesn't consume all its input.  Good idea... */
    43     signal(SIGPIPE, SIG_IGN);   /* TODO - switch to sigaction. */
     43    signal(SIGPIPE, SIG_IGN);
    4444
    45     /* Allocate an array of FILE *'s, with one extra for a sentinal. */
     45    /* Allocate an array of FILE *'s, with one extra for a sentinel. */
    4646    fp = files = xzalloc(sizeof(FILE *) * (argc + 2));
    4747    np = names = argv - 1;
     
    5050    goto GOT_NEW_FILE;
    5151    do {
    52         *fp = fopen_or_warn(*argv, mode);
    53         if (*fp == NULL) {
    54             retval = EXIT_FAILURE;
    55             continue;
     52        *fp = stdout;
     53        if (NOT_LONE_DASH(*argv)) {
     54            *fp = fopen_or_warn(*argv, mode);
     55            if (*fp == NULL) {
     56                retval = EXIT_FAILURE;
     57                argv++;
     58                continue;
     59            }
    5660        }
    5761        *np = *argv++;
    5862 GOT_NEW_FILE:
    59         setbuf(*fp++, NULL);    /* tee must not buffer output. */
     63        setbuf(*fp, NULL);  /* tee must not buffer output. */
     64        fp++;
    6065        np++;
    6166    } while (*argv);
     
    6368
    6469#if ENABLE_FEATURE_TEE_USE_BLOCK_IO
    65     while ((c = safe_read(STDIN_FILENO, buf, BUFSIZ)) > 0) {
     70    while ((c = safe_read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
    6671        fp = files;
    6772        do
    68             fwrite(buf, 1, c, *fp++);
    69         while (*fp);
     73            fwrite(buf, 1, c, *fp);
     74        while (*++fp);
    7075    }
    7176    if (c < 0) {        /* Make sure read errors are signaled. */
     
    7782        fp = files;
    7883        do
    79             putc(c, *fp++);
    80         while (*fp);
     84            putc(c, *fp);
     85        while (*++fp);
    8186    }
    8287#endif
  • branches/2.2.9/mindi-busybox/coreutils/test.c

    r1765 r2725  
    1313 *     modified by Erik Andersen <andersen@codepoet.org> to be used
    1414 *     in busybox.
    15  *     modified by Bernhard Fischer to be useable (i.e. a bit less bloaty).
     15 *     modified by Bernhard Reutner-Fischer to be useable (i.e. a bit less bloaty).
    1616 *
    17  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     17 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1818 *
    1919 * Original copyright notice states:
     
    2121 */
    2222
     23//kbuild:lib-$(CONFIG_TEST)      += test.o test_ptr_hack.o
     24//kbuild:lib-$(CONFIG_ASH)       += test.o test_ptr_hack.o
     25//kbuild:lib-$(CONFIG_HUSH)      += test.o test_ptr_hack.o
     26
     27//config:config TEST
     28//config:   bool "test"
     29//config:   default y
     30//config:   help
     31//config:     test is used to check file types and compare values,
     32//config:     returning an appropriate exit code. The bash shell
     33//config:     has test built in, ash can build it in optionally.
     34//config:
     35//config:config FEATURE_TEST_64
     36//config:   bool "Extend test to 64 bit"
     37//config:   default y
     38//config:   depends on TEST || ASH_BUILTIN_TEST || HUSH
     39//config:   help
     40//config:     Enable 64-bit support in test.
     41
    2342#include "libbb.h"
    2443#include <setjmp.h>
    2544
    26 /* This is a NOEXEC applet. Be very careful! */
    27 
     45/* This is a NOFORK applet. Be very careful! */
     46
     47/* test_main() is called from shells, and we need to be extra careful here.
     48 * This is true regardless of PREFER_APPLETS and STANDALONE_SHELL
     49 * state. */
    2850
    2951/* test(1) accepts the following grammar:
    30     oexpr   ::= aexpr | aexpr "-o" oexpr ;
    31     aexpr   ::= nexpr | nexpr "-a" aexpr ;
    32     nexpr   ::= primary | "!" primary
     52    oexpr   ::= aexpr | aexpr "-o" oexpr ;
     53    aexpr   ::= nexpr | nexpr "-a" aexpr ;
     54    nexpr   ::= primary | "!" primary
    3355    primary ::= unary-operator operand
    3456        | operand binary-operator operand
     
    4466*/
    4567
     68/* TODO: handle [[ expr ]] bashism bash-compatibly.
     69 * [[ ]] is meant to be a "better [ ]", with less weird syntax
     70 * and without the risk of variables and quoted strings misinterpreted
     71 * as operators.
     72 * This will require support from shells - we need to know quote status
     73 * of each parameter (see below).
     74 *
     75 * Word splitting and pathname expansion should NOT be performed:
     76 *      # a="a b"; [[ $a = "a b" ]] && echo YES
     77 *      YES
     78 *      # [[ /bin/m* ]] && echo YES
     79 *      YES
     80 *
     81 * =~ should do regexp match
     82 * = and == should do pattern match against right side:
     83 *      # [[ *a* == bab ]] && echo YES
     84 *      # [[ bab == *a* ]] && echo YES
     85 *      YES
     86 * != does the negated == (i.e., also with pattern matching).
     87 * Pattern matching is quotation-sensitive:
     88 *      # [[ bab == "b"a* ]] && echo YES
     89 *      YES
     90 *      # [[ bab == b"a*" ]] && echo YES
     91 *
     92 * Conditional operators such as -f must be unquoted literals to be recognized:
     93 *      # [[ -e /bin ]] && echo YES
     94 *      YES
     95 *      # [[ '-e' /bin ]] && echo YES
     96 *      bash: conditional binary operator expected...
     97 *      # A='-e'; [[ $A /bin ]] && echo YES
     98 *      bash: conditional binary operator expected...
     99 *
     100 * || and && should work as -o and -a work in [ ]
     101 * -a and -o aren't recognized (&& and || are to be used instead)
     102 * ( and ) do not need to be quoted unlike in [ ]:
     103 *      # [[ ( abc ) && '' ]] && echo YES
     104 *      # [[ ( abc ) || '' ]] && echo YES
     105 *      YES
     106 *      # [[ ( abc ) -o '' ]] && echo YES
     107 *      bash: syntax error in conditional expression...
     108 *
     109 * Apart from the above, [[ expr ]] should work as [ expr ]
     110 */
     111
     112#define TEST_DEBUG 0
     113
    46114enum token {
    47115    EOI,
    48     FILRD,
     116
     117    FILRD, /* file access */
    49118    FILWR,
    50119    FILEX,
     120
    51121    FILEXIST,
    52     FILREG,
     122
     123    FILREG, /* file type */
    53124    FILDIR,
    54125    FILCDEV,
     
    56127    FILFIFO,
    57128    FILSOCK,
     129
    58130    FILSYM,
    59131    FILGZ,
    60132    FILTT,
    61     FILSUID,
     133
     134    FILSUID, /* file bit */
    62135    FILSGID,
    63136    FILSTCK,
    64     FILNT,
     137
     138    FILNT, /* file ops */
    65139    FILOT,
    66140    FILEQ,
     141
    67142    FILUID,
    68143    FILGID,
    69     STREZ,
     144
     145    STREZ, /* str ops */
    70146    STRNZ,
    71147    STREQ,
     
    73149    STRLT,
    74150    STRGT,
    75     INTEQ,
     151
     152    INTEQ, /* int ops */
    76153    INTNE,
    77154    INTGE,
     
    79156    INTLE,
    80157    INTLT,
     158
    81159    UNOT,
    82160    BAND,
     
    86164    OPERAND
    87165};
    88 #define is_int_op(a) (((unsigned char)((a) - INTEQ)) <= 5)
    89 #define is_str_op(a) (((unsigned char)((a) - STREZ)) <= 5)
    90 #define is_file_op(a) (((unsigned char)((a) - FILNT)) <= 2)
     166#define is_int_op(a)      (((unsigned char)((a) - INTEQ)) <= 5)
     167#define is_str_op(a)      (((unsigned char)((a) - STREZ)) <= 5)
     168#define is_file_op(a)     (((unsigned char)((a) - FILNT)) <= 2)
    91169#define is_file_access(a) (((unsigned char)((a) - FILRD)) <= 2)
    92 #define is_file_type(a) (((unsigned char)((a) - FILREG)) <= 5)
    93 #define is_file_bit(a) (((unsigned char)((a) - FILSUID)) <= 2)
    94 enum token_types {
     170#define is_file_type(a)   (((unsigned char)((a) - FILREG)) <= 5)
     171#define is_file_bit(a)    (((unsigned char)((a) - FILSUID)) <= 2)
     172
     173#if TEST_DEBUG
     174int depth;
     175#define nest_msg(...) do { \
     176    depth++; \
     177    fprintf(stderr, "%*s", depth*2, ""); \
     178    fprintf(stderr, __VA_ARGS__); \
     179} while (0)
     180#define unnest_msg(...) do { \
     181    fprintf(stderr, "%*s", depth*2, ""); \
     182    fprintf(stderr, __VA_ARGS__); \
     183    depth--; \
     184} while (0)
     185#define dbg_msg(...) do { \
     186    fprintf(stderr, "%*s", depth*2, ""); \
     187    fprintf(stderr, __VA_ARGS__); \
     188} while (0)
     189#define unnest_msg_and_return(expr, ...) do { \
     190    number_t __res = (expr); \
     191    fprintf(stderr, "%*s", depth*2, ""); \
     192    fprintf(stderr, __VA_ARGS__, res); \
     193    depth--; \
     194    return __res; \
     195} while (0)
     196static const char *const TOKSTR[] = {
     197    "EOI",
     198    "FILRD",
     199    "FILWR",
     200    "FILEX",
     201    "FILEXIST",
     202    "FILREG",
     203    "FILDIR",
     204    "FILCDEV",
     205    "FILBDEV",
     206    "FILFIFO",
     207    "FILSOCK",
     208    "FILSYM",
     209    "FILGZ",
     210    "FILTT",
     211    "FILSUID",
     212    "FILSGID",
     213    "FILSTCK",
     214    "FILNT",
     215    "FILOT",
     216    "FILEQ",
     217    "FILUID",
     218    "FILGID",
     219    "STREZ",
     220    "STRNZ",
     221    "STREQ",
     222    "STRNE",
     223    "STRLT",
     224    "STRGT",
     225    "INTEQ",
     226    "INTNE",
     227    "INTGE",
     228    "INTGT",
     229    "INTLE",
     230    "INTLT",
     231    "UNOT",
     232    "BAND",
     233    "BOR",
     234    "LPAREN",
     235    "RPAREN",
     236    "OPERAND"
     237};
     238#else
     239#define nest_msg(...)   ((void)0)
     240#define unnest_msg(...) ((void)0)
     241#define dbg_msg(...)    ((void)0)
     242#define unnest_msg_and_return(expr, ...) return expr
     243#endif
     244
     245enum {
    95246    UNOP,
    96247    BINOP,
     
    100251};
    101252
    102 static const struct t_op {
    103     char op_text[4];
     253struct operator_t {
    104254    unsigned char op_num, op_type;
    105 } ops[] = {
    106     { "-r", FILRD   , UNOP   },
    107     { "-w", FILWR   , UNOP   },
    108     { "-x", FILEX   , UNOP   },
    109     { "-e", FILEXIST, UNOP   },
    110     { "-f", FILREG  , UNOP   },
    111     { "-d", FILDIR  , UNOP   },
    112     { "-c", FILCDEV , UNOP   },
    113     { "-b", FILBDEV , UNOP   },
    114     { "-p", FILFIFO , UNOP   },
    115     { "-u", FILSUID , UNOP   },
    116     { "-g", FILSGID , UNOP   },
    117     { "-k", FILSTCK , UNOP   },
    118     { "-s", FILGZ   , UNOP   },
    119     { "-t", FILTT   , UNOP   },
    120     { "-z", STREZ   , UNOP   },
    121     { "-n", STRNZ   , UNOP   },
    122     { "-h", FILSYM  , UNOP   },    /* for backwards compat */
    123 
    124     { "-O" , FILUID , UNOP   },
    125     { "-G" , FILGID , UNOP   },
    126     { "-L" , FILSYM , UNOP   },
    127     { "-S" , FILSOCK, UNOP   },
    128     { "="  , STREQ  , BINOP  },
    129     { "==" , STREQ  , BINOP  },
    130     { "!=" , STRNE  , BINOP  },
    131     { "<"  , STRLT  , BINOP  },
    132     { ">"  , STRGT  , BINOP  },
    133     { "-eq", INTEQ  , BINOP  },
    134     { "-ne", INTNE  , BINOP  },
    135     { "-ge", INTGE  , BINOP  },
    136     { "-gt", INTGT  , BINOP  },
    137     { "-le", INTLE  , BINOP  },
    138     { "-lt", INTLT  , BINOP  },
    139     { "-nt", FILNT  , BINOP  },
    140     { "-ot", FILOT  , BINOP  },
    141     { "-ef", FILEQ  , BINOP  },
    142     { "!"  , UNOT   , BUNOP  },
    143     { "-a" , BAND   , BBINOP },
    144     { "-o" , BOR    , BBINOP },
    145     { "("  , LPAREN , PAREN  },
    146     { ")"  , RPAREN , PAREN  },
    147255};
    148256
     257static const struct operator_t ops_table[] = {
     258    { /* "-r" */ FILRD   , UNOP   },
     259    { /* "-w" */ FILWR   , UNOP   },
     260    { /* "-x" */ FILEX   , UNOP   },
     261    { /* "-e" */ FILEXIST, UNOP   },
     262    { /* "-f" */ FILREG  , UNOP   },
     263    { /* "-d" */ FILDIR  , UNOP   },
     264    { /* "-c" */ FILCDEV , UNOP   },
     265    { /* "-b" */ FILBDEV , UNOP   },
     266    { /* "-p" */ FILFIFO , UNOP   },
     267    { /* "-u" */ FILSUID , UNOP   },
     268    { /* "-g" */ FILSGID , UNOP   },
     269    { /* "-k" */ FILSTCK , UNOP   },
     270    { /* "-s" */ FILGZ   , UNOP   },
     271    { /* "-t" */ FILTT   , UNOP   },
     272    { /* "-z" */ STREZ   , UNOP   },
     273    { /* "-n" */ STRNZ   , UNOP   },
     274    { /* "-h" */ FILSYM  , UNOP   },    /* for backwards compat */
     275
     276    { /* "-O" */ FILUID  , UNOP   },
     277    { /* "-G" */ FILGID  , UNOP   },
     278    { /* "-L" */ FILSYM  , UNOP   },
     279    { /* "-S" */ FILSOCK , UNOP   },
     280    { /* "="  */ STREQ   , BINOP  },
     281    { /* "==" */ STREQ   , BINOP  },
     282    { /* "!=" */ STRNE   , BINOP  },
     283    { /* "<"  */ STRLT   , BINOP  },
     284    { /* ">"  */ STRGT   , BINOP  },
     285    { /* "-eq"*/ INTEQ   , BINOP  },
     286    { /* "-ne"*/ INTNE   , BINOP  },
     287    { /* "-ge"*/ INTGE   , BINOP  },
     288    { /* "-gt"*/ INTGT   , BINOP  },
     289    { /* "-le"*/ INTLE   , BINOP  },
     290    { /* "-lt"*/ INTLT   , BINOP  },
     291    { /* "-nt"*/ FILNT   , BINOP  },
     292    { /* "-ot"*/ FILOT   , BINOP  },
     293    { /* "-ef"*/ FILEQ   , BINOP  },
     294    { /* "!"  */ UNOT    , BUNOP  },
     295    { /* "-a" */ BAND    , BBINOP },
     296    { /* "-o" */ BOR     , BBINOP },
     297    { /* "("  */ LPAREN  , PAREN  },
     298    { /* ")"  */ RPAREN  , PAREN  },
     299};
     300/* Please keep these two tables in sync */
     301static const char ops_texts[] ALIGN1 =
     302    "-r"  "\0"
     303    "-w"  "\0"
     304    "-x"  "\0"
     305    "-e"  "\0"
     306    "-f"  "\0"
     307    "-d"  "\0"
     308    "-c"  "\0"
     309    "-b"  "\0"
     310    "-p"  "\0"
     311    "-u"  "\0"
     312    "-g"  "\0"
     313    "-k"  "\0"
     314    "-s"  "\0"
     315    "-t"  "\0"
     316    "-z"  "\0"
     317    "-n"  "\0"
     318    "-h"  "\0"
     319
     320    "-O"  "\0"
     321    "-G"  "\0"
     322    "-L"  "\0"
     323    "-S"  "\0"
     324    "="   "\0"
     325    "=="  "\0"
     326    "!="  "\0"
     327    "<"   "\0"
     328    ">"   "\0"
     329    "-eq" "\0"
     330    "-ne" "\0"
     331    "-ge" "\0"
     332    "-gt" "\0"
     333    "-le" "\0"
     334    "-lt" "\0"
     335    "-nt" "\0"
     336    "-ot" "\0"
     337    "-ef" "\0"
     338    "!"   "\0"
     339    "-a"  "\0"
     340    "-o"  "\0"
     341    "("   "\0"
     342    ")"   "\0"
     343;
     344
    149345
    150346#if ENABLE_FEATURE_TEST_64
    151 typedef int64_t arith_t;
     347typedef int64_t number_t;
    152348#else
    153 typedef int arith_t;
     349typedef int number_t;
    154350#endif
    155351
    156 /* Cannot eliminate these static data (do the G trick)
    157  * because of test_main usage from other applets */
    158 static char **t_wp;
    159 static struct t_op const *t_wp_op;
    160 static gid_t *group_array;
    161 static int ngroups;
    162 static jmp_buf leaving;
    163 
    164 static enum token t_lex(char *s);
    165 static arith_t oexpr(enum token n);
    166 static arith_t aexpr(enum token n);
    167 static arith_t nexpr(enum token n);
    168 static int binop(void);
    169 static arith_t primary(enum token n);
    170 static int filstat(char *nm, enum token mode);
    171 static arith_t getn(const char *s);
    172 /* UNUSED
    173 static int newerf(const char *f1, const char *f2);
    174 static int olderf(const char *f1, const char *f2);
    175 static int equalf(const char *f1, const char *f2);
    176 */
    177 static int test_eaccess(char *path, int mode);
    178 static int is_a_group_member(gid_t gid);
    179 static void initialize_group_array(void);
    180 
    181 int test_main(int argc, char **argv)
    182 {
    183     int res;
    184     const char *arg0;
    185     bool _off;
    186 
    187     arg0 = bb_basename(argv[0]);
    188     if (arg0[0] == '[') {
    189         --argc;
    190         if (!arg0[1]) { /* "[" ? */
    191             if (NOT_LONE_CHAR(argv[argc], ']')) {
    192                 bb_error_msg("missing ]");
    193                 return 2;
    194             }
    195         } else { /* assuming "[[" */
    196             if (strcmp(argv[argc], "]]") != 0) {
    197                 bb_error_msg("missing ]]");
    198                 return 2;
    199             }
    200         }
    201         argv[argc] = NULL;
    202     }
    203 
    204     res = setjmp(leaving);
    205     if (res)
    206         return res;
    207 
    208     /* resetting ngroups is probably unnecessary.  it will
    209      * force a new call to getgroups(), which prevents using
    210      * group data fetched during a previous call.  but the
    211      * only way the group data could be stale is if there's
    212      * been an intervening call to setgroups(), and this
    213      * isn't likely in the case of a shell.  paranoia
    214      * prevails...
    215      */
    216     ngroups = 0;
    217 
    218     /* Implement special cases from POSIX.2, section 4.62.4 */
    219     if (argc == 1)
    220         return 1;
    221     if (argc == 2)
    222         return *argv[1] == '\0';
    223 //assert(argc);
    224     /* remember if we saw argc==4 which wants *no* '!' test */
    225     _off = argc - 4;
    226     if (_off ?
    227         (LONE_CHAR(argv[1], '!'))
    228         : (argv[1][0] != '!' || argv[1][1] != '\0'))
    229     {
    230         if (argc == 3)
    231             return *argv[2] != '\0';
    232 
    233         t_lex(argv[2 + _off]);
    234         if (t_wp_op && t_wp_op->op_type == BINOP) {
    235             t_wp = &argv[1 + _off];
    236             return binop() == _off;
    237         }
    238     }
    239     t_wp = &argv[1];
    240     res = !oexpr(t_lex(*t_wp));
    241 
    242     if (*t_wp != NULL && *++t_wp != NULL) {
    243         bb_error_msg("%s: unknown operand", *t_wp);
    244         return 2;
    245     }
    246     return res;
    247 }
    248 
    249 static void syntax(const char *op, const char *msg) ATTRIBUTE_NORETURN;
     352
     353/* We try to minimize both static and stack usage. */
     354struct test_statics {
     355    char **args;
     356    /* set only by check_operator(), either to bogus struct
     357     * or points to matching operator_t struct. Never NULL. */
     358    const struct operator_t *last_operator;
     359    gid_t *group_array;
     360    int ngroups;
     361    jmp_buf leaving;
     362};
     363
     364/* See test_ptr_hack.c */
     365extern struct test_statics *const test_ptr_to_statics;
     366
     367#define S (*test_ptr_to_statics)
     368#define args            (S.args         )
     369#define last_operator   (S.last_operator)
     370#define group_array     (S.group_array  )
     371#define ngroups         (S.ngroups      )
     372#define leaving         (S.leaving      )
     373
     374#define INIT_S() do { \
     375    (*(struct test_statics**)&test_ptr_to_statics) = xzalloc(sizeof(S)); \
     376    barrier(); \
     377} while (0)
     378#define DEINIT_S() do { \
     379    free(test_ptr_to_statics); \
     380} while (0)
     381
     382static number_t primary(enum token n);
     383
     384static void syntax(const char *op, const char *msg) NORETURN;
    250385static void syntax(const char *op, const char *msg)
    251386{
     
    258393}
    259394
    260 static arith_t oexpr(enum token n)
    261 {
    262     arith_t res;
    263 
    264     res = aexpr(n);
    265     if (t_lex(*++t_wp) == BOR) {
    266         return oexpr(t_lex(*++t_wp)) || res;
    267     }
    268     t_wp--;
    269     return res;
    270 }
    271 
    272 static arith_t aexpr(enum token n)
    273 {
    274     arith_t res;
    275 
    276     res = nexpr(n);
    277     if (t_lex(*++t_wp) == BAND)
    278         return aexpr(t_lex(*++t_wp)) && res;
    279     t_wp--;
    280     return res;
    281 }
    282 
    283 static arith_t nexpr(enum token n)
    284 {
    285     if (n == UNOT)
    286         return !nexpr(t_lex(*++t_wp));
    287     return primary(n);
    288 }
    289 
    290 static arith_t primary(enum token n)
    291 {
    292     arith_t res;
    293 
    294     if (n == EOI) {
    295         syntax(NULL, "argument expected");
    296     }
    297     if (n == LPAREN) {
    298         res = oexpr(t_lex(*++t_wp));
    299         if (t_lex(*++t_wp) != RPAREN)
    300             syntax(NULL, "closing paren expected");
    301         return res;
    302     }
    303     if (t_wp_op && t_wp_op->op_type == UNOP) {
    304         /* unary expression */
    305         if (*++t_wp == NULL)
    306             syntax(t_wp_op->op_text, "argument expected");
    307         if (n == STREZ)
    308             return t_wp[0][0] == '\0';
    309         if (n == STRNZ)
    310             return t_wp[0][0] != '\0';
    311         if (n == FILTT)
    312             return isatty(getn(*t_wp));
    313         return filstat(*t_wp, n);
    314     }
    315 
    316     t_lex(t_wp[1]);
    317     if (t_wp_op && t_wp_op->op_type == BINOP) {
    318         return binop();
    319     }
    320 
    321     return t_wp[0][0] != '\0';
    322 }
     395/* atoi with error detection */
     396//XXX: FIXME: duplicate of existing libbb function?
     397static number_t getn(const char *s)
     398{
     399    char *p;
     400#if ENABLE_FEATURE_TEST_64
     401    long long r;
     402#else
     403    long r;
     404#endif
     405
     406    errno = 0;
     407#if ENABLE_FEATURE_TEST_64
     408    r = strtoll(s, &p, 10);
     409#else
     410    r = strtol(s, &p, 10);
     411#endif
     412
     413    if (errno != 0)
     414        syntax(s, "out of range");
     415
     416    if (p == s || *(skip_whitespace(p)) != '\0')
     417        syntax(s, "bad number");
     418
     419    return r;
     420}
     421
     422/* UNUSED
     423static int newerf(const char *f1, const char *f2)
     424{
     425    struct stat b1, b2;
     426
     427    return (stat(f1, &b1) == 0 &&
     428            stat(f2, &b2) == 0 && b1.st_mtime > b2.st_mtime);
     429}
     430
     431static int olderf(const char *f1, const char *f2)
     432{
     433    struct stat b1, b2;
     434
     435    return (stat(f1, &b1) == 0 &&
     436            stat(f2, &b2) == 0 && b1.st_mtime < b2.st_mtime);
     437}
     438
     439static int equalf(const char *f1, const char *f2)
     440{
     441    struct stat b1, b2;
     442
     443    return (stat(f1, &b1) == 0 &&
     444            stat(f2, &b2) == 0 &&
     445            b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino);
     446}
     447*/
     448
     449
     450static enum token check_operator(const char *s)
     451{
     452    static const struct operator_t no_op = {
     453        .op_num = -1,
     454        .op_type = -1
     455    };
     456    int n;
     457
     458    last_operator = &no_op;
     459    if (s == NULL)
     460        return EOI;
     461    n = index_in_strings(ops_texts, s);
     462    if (n < 0)
     463        return OPERAND;
     464    last_operator = &ops_table[n];
     465    return ops_table[n].op_num;
     466}
     467
    323468
    324469static int binop(void)
    325470{
    326471    const char *opnd1, *opnd2;
    327     struct t_op const *op;
    328     arith_t val1, val2;
    329 
    330     opnd1 = *t_wp;
    331     (void) t_lex(*++t_wp);
    332     op = t_wp_op;
    333 
    334     opnd2 = *++t_wp;
     472    const struct operator_t *op;
     473    number_t val1, val2;
     474
     475    opnd1 = *args;
     476    check_operator(*++args);
     477    op = last_operator;
     478
     479    opnd2 = *++args;
    335480    if (opnd2 == NULL)
    336         syntax(op->op_text, "argument expected");
     481        syntax(args[-1], "argument expected");
    337482
    338483    if (is_int_op(op->op_num)) {
     
    349494        if (op->op_num == INTLE)
    350495            return val1 <= val2;
    351         if (op->op_num == INTLT)
    352             return val1 <  val2;
     496        /*if (op->op_num == INTLT)*/
     497        return val1 <  val2;
    353498    }
    354499    if (is_str_op(op->op_num)) {
     
    360505        if (op->op_num == STRLT)
    361506            return val1 < 0;
    362         if (op->op_num == STRGT)
    363             return val1 > 0;
     507        /*if (op->op_num == STRGT)*/
     508        return val1 > 0;
    364509    }
    365510    /* We are sure that these three are by now the only binops we didn't check
     
    376521        if (op->op_num == FILOT)
    377522            return b1.st_mtime < b2.st_mtime;
    378         if (op->op_num == FILEQ)
    379             return b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino;
    380     }
    381     return 1; /* NOTREACHED */
    382 }
     523        /*if (op->op_num == FILEQ)*/
     524        return b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino;
     525    }
     526    /*return 1; - NOTREACHED */
     527}
     528
     529
     530static void initialize_group_array(void)
     531{
     532    int n;
     533
     534    /* getgroups may be expensive, try to use it only once */
     535    ngroups = 32;
     536    do {
     537        /* FIXME: ash tries so hard to not die on OOM,
     538         * and we spoil it with just one xrealloc here */
     539        /* We realloc, because test_main can be entered repeatedly by shell.
     540         * Testcase (ash): 'while true; do test -x some_file; done'
     541         * and watch top. (some_file must have owner != you) */
     542        n = ngroups;
     543        group_array = xrealloc(group_array, n * sizeof(gid_t));
     544        ngroups = getgroups(n, group_array);
     545    } while (ngroups > n);
     546}
     547
     548
     549/* Return non-zero if GID is one that we have in our groups list. */
     550//XXX: FIXME: duplicate of existing libbb function?
     551// see toplevel TODO file:
     552// possible code duplication ingroup() and is_a_group_member()
     553static int is_a_group_member(gid_t gid)
     554{
     555    int i;
     556
     557    /* Short-circuit if possible, maybe saving a call to getgroups(). */
     558    if (gid == getgid() || gid == getegid())
     559        return 1;
     560
     561    if (ngroups == 0)
     562        initialize_group_array();
     563
     564    /* Search through the list looking for GID. */
     565    for (i = 0; i < ngroups; i++)
     566        if (gid == group_array[i])
     567            return 1;
     568
     569    return 0;
     570}
     571
     572
     573/* Do the same thing access(2) does, but use the effective uid and gid,
     574   and don't make the mistake of telling root that any file is
     575   executable. */
     576static int test_eaccess(char *path, int mode)
     577{
     578    struct stat st;
     579    unsigned int euid = geteuid();
     580
     581    if (stat(path, &st) < 0)
     582        return -1;
     583
     584    if (euid == 0) {
     585        /* Root can read or write any file. */
     586        if (mode != X_OK)
     587            return 0;
     588
     589        /* Root can execute any file that has any one of the execute
     590           bits set. */
     591        if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
     592            return 0;
     593    }
     594
     595    if (st.st_uid == euid)  /* owner */
     596        mode <<= 6;
     597    else if (is_a_group_member(st.st_gid))
     598        mode <<= 3;
     599
     600    if (st.st_mode & mode)
     601        return 0;
     602
     603    return -1;
     604}
     605
    383606
    384607static int filstat(char *nm, enum token mode)
    385608{
    386609    struct stat s;
    387     int i = i; /* gcc 3.x thinks it can be used uninitialized */
     610    unsigned i = i; /* gcc 3.x thinks it can be used uninitialized */
    388611
    389612    if (mode == FILSYM) {
     
    454677}
    455678
    456 static enum token t_lex(char *s)
    457 {
    458     const struct t_op *op;
    459 
    460     t_wp_op = NULL;
    461     if (s == NULL) {
    462         return EOI;
    463     }
    464 
    465     op = ops;
    466     do {
    467         if (strcmp(s, op->op_text) == 0) {
    468             t_wp_op = op;
    469             return op->op_num;
     679
     680static number_t nexpr(enum token n)
     681{
     682    number_t res;
     683
     684    nest_msg(">nexpr(%s)\n", TOKSTR[n]);
     685    if (n == UNOT) {
     686        n = check_operator(*++args);
     687        if (n == EOI) {
     688            /* special case: [ ! ], [ a -a ! ] are valid */
     689            /* IOW, "! ARG" may miss ARG */
     690            unnest_msg("<nexpr:1 (!EOI)\n");
     691            return 1;
    470692        }
    471         op++;
    472     } while (op < ops + ARRAY_SIZE(ops));
    473 
    474     return OPERAND;
    475 }
    476 
    477 /* atoi with error detection */
    478 //XXX: FIXME: duplicate of existing libbb function?
    479 static arith_t getn(const char *s)
    480 {
    481     char *p;
    482 #if ENABLE_FEATURE_TEST_64
    483     long long r;
     693        res = !nexpr(n);
     694        unnest_msg("<nexpr:%lld\n", res);
     695        return res;
     696    }
     697    res = primary(n);
     698    unnest_msg("<nexpr:%lld\n", res);
     699    return res;
     700}
     701
     702
     703static number_t aexpr(enum token n)
     704{
     705    number_t res;
     706
     707    nest_msg(">aexpr(%s)\n", TOKSTR[n]);
     708    res = nexpr(n);
     709    dbg_msg("aexpr: nexpr:%lld, next args:%s\n", res, args[1]);
     710    if (check_operator(*++args) == BAND) {
     711        dbg_msg("aexpr: arg is AND, next args:%s\n", args[1]);
     712        res = aexpr(check_operator(*++args)) && res;
     713        unnest_msg("<aexpr:%lld\n", res);
     714        return res;
     715    }
     716    args--;
     717    unnest_msg("<aexpr:%lld, args:%s\n", res, args[0]);
     718    return res;
     719}
     720
     721
     722static number_t oexpr(enum token n)
     723{
     724    number_t res;
     725
     726    nest_msg(">oexpr(%s)\n", TOKSTR[n]);
     727    res = aexpr(n);
     728    dbg_msg("oexpr: aexpr:%lld, next args:%s\n", res, args[1]);
     729    if (check_operator(*++args) == BOR) {
     730        dbg_msg("oexpr: next arg is OR, next args:%s\n", args[1]);
     731        res = oexpr(check_operator(*++args)) || res;
     732        unnest_msg("<oexpr:%lld\n", res);
     733        return res;
     734    }
     735    args--;
     736    unnest_msg("<oexpr:%lld, args:%s\n", res, args[0]);
     737    return res;
     738}
     739
     740
     741static number_t primary(enum token n)
     742{
     743#if TEST_DEBUG
     744    number_t res = res; /* for compiler */
    484745#else
    485     long r;
     746    number_t res;
    486747#endif
    487 
    488     errno = 0;
    489 #if ENABLE_FEATURE_TEST_64
    490     r = strtoll(s, &p, 10);
    491 #else
    492     r = strtol(s, &p, 10);
     748    const struct operator_t *args0_op;
     749
     750    nest_msg(">primary(%s)\n", TOKSTR[n]);
     751    if (n == EOI) {
     752        syntax(NULL, "argument expected");
     753    }
     754    if (n == LPAREN) {
     755        res = oexpr(check_operator(*++args));
     756        if (check_operator(*++args) != RPAREN)
     757            syntax(NULL, "closing paren expected");
     758        unnest_msg("<primary:%lld\n", res);
     759        return res;
     760    }
     761
     762    /* coreutils 6.9 checks "is args[1] binop and args[2] exist?" first,
     763     * do the same */
     764    args0_op = last_operator;
     765    /* last_operator = operator at args[1] */
     766    if (check_operator(args[1]) != EOI) { /* if args[1] != NULL */
     767        if (args[2]) {
     768            // coreutils also does this:
     769            // if (args[3] && args[0]="-l" && args[2] is BINOP)
     770            //  return binop(1 /* prepended by -l */);
     771            if (last_operator->op_type == BINOP)
     772                unnest_msg_and_return(binop(), "<primary: binop:%lld\n");
     773        }
     774    }
     775    /* check "is args[0] unop?" second */
     776    if (args0_op->op_type == UNOP) {
     777        /* unary expression */
     778        if (args[1] == NULL)
     779//          syntax(args0_op->op_text, "argument expected");
     780            goto check_emptiness;
     781        args++;
     782        if (n == STREZ)
     783            unnest_msg_and_return(args[0][0] == '\0', "<primary:%lld\n");
     784        if (n == STRNZ)
     785            unnest_msg_and_return(args[0][0] != '\0', "<primary:%lld\n");
     786        if (n == FILTT)
     787            unnest_msg_and_return(isatty(getn(*args)), "<primary: isatty(%s)%lld\n", *args);
     788        unnest_msg_and_return(filstat(*args, n), "<primary: filstat(%s):%lld\n", *args);
     789    }
     790
     791    /*check_operator(args[1]); - already done */
     792    if (last_operator->op_type == BINOP) {
     793        /* args[2] is known to be NULL, isn't it bound to fail? */
     794        unnest_msg_and_return(binop(), "<primary:%lld\n");
     795    }
     796 check_emptiness:
     797    unnest_msg_and_return(args[0][0] != '\0', "<primary:%lld\n");
     798}
     799
     800
     801int test_main(int argc, char **argv)
     802{
     803    int res;
     804    const char *arg0;
     805//  bool negate = 0;
     806
     807    arg0 = bb_basename(argv[0]);
     808    if (arg0[0] == '[') {
     809        --argc;
     810        if (!arg0[1]) { /* "[" ? */
     811            if (NOT_LONE_CHAR(argv[argc], ']')) {
     812                bb_error_msg("missing ]");
     813                return 2;
     814            }
     815        } else { /* assuming "[[" */
     816            if (strcmp(argv[argc], "]]") != 0) {
     817                bb_error_msg("missing ]]");
     818                return 2;
     819            }
     820        }
     821        argv[argc] = NULL;
     822    }
     823
     824    /* We must do DEINIT_S() prior to returning */
     825    INIT_S();
     826
     827    res = setjmp(leaving);
     828    if (res)
     829        goto ret;
     830
     831    /* resetting ngroups is probably unnecessary.  it will
     832     * force a new call to getgroups(), which prevents using
     833     * group data fetched during a previous call.  but the
     834     * only way the group data could be stale is if there's
     835     * been an intervening call to setgroups(), and this
     836     * isn't likely in the case of a shell.  paranoia
     837     * prevails...
     838     */
     839    /*ngroups = 0; - done by INIT_S() */
     840
     841    //argc--;
     842    argv++;
     843
     844    /* Implement special cases from POSIX.2, section 4.62.4 */
     845    if (!argv[0]) { /* "test" */
     846        res = 1;
     847        goto ret;
     848    }
     849#if 0
     850// Now it's fixed in the parser and should not be needed
     851    if (LONE_CHAR(argv[0], '!') && argv[1]) {
     852        negate = 1;
     853        //argc--;
     854        argv++;
     855    }
     856    if (!argv[1]) { /* "test [!] arg" */
     857        res = (*argv[0] == '\0');
     858        goto ret;
     859    }
     860    if (argv[2] && !argv[3]) {
     861        check_operator(argv[1]);
     862        if (last_operator->op_type == BINOP) {
     863            /* "test [!] arg1 <binary_op> arg2" */
     864            args = argv;
     865            res = (binop() == 0);
     866            goto ret;
     867        }
     868    }
     869
     870    /* Some complex expression. Undo '!' removal */
     871    if (negate) {
     872        negate = 0;
     873        //argc++;
     874        argv--;
     875    }
    493876#endif
    494 
    495     if (errno != 0)
    496         syntax(s, "out of range");
    497 
    498     if (*(skip_whitespace(p)))
    499         syntax(s, "bad number");
    500 
    501     return r;
    502 }
    503 
    504 /* UNUSED
    505 static int newerf(const char *f1, const char *f2)
    506 {
    507     struct stat b1, b2;
    508 
    509     return (stat(f1, &b1) == 0 &&
    510             stat(f2, &b2) == 0 && b1.st_mtime > b2.st_mtime);
    511 }
    512 
    513 static int olderf(const char *f1, const char *f2)
    514 {
    515     struct stat b1, b2;
    516 
    517     return (stat(f1, &b1) == 0 &&
    518             stat(f2, &b2) == 0 && b1.st_mtime < b2.st_mtime);
    519 }
    520 
    521 static int equalf(const char *f1, const char *f2)
    522 {
    523     struct stat b1, b2;
    524 
    525     return (stat(f1, &b1) == 0 &&
    526             stat(f2, &b2) == 0 &&
    527             b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino);
    528 }
    529 */
    530 
    531 /* Do the same thing access(2) does, but use the effective uid and gid,
    532    and don't make the mistake of telling root that any file is
    533    executable. */
    534 static int test_eaccess(char *path, int mode)
    535 {
    536     struct stat st;
    537     unsigned int euid = geteuid();
    538 
    539     if (stat(path, &st) < 0)
    540         return -1;
    541 
    542     if (euid == 0) {
    543         /* Root can read or write any file. */
    544         if (mode != X_OK)
    545             return 0;
    546 
    547         /* Root can execute any file that has any one of the execute
    548            bits set. */
    549         if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
    550             return 0;
    551     }
    552 
    553     if (st.st_uid == euid)  /* owner */
    554         mode <<= 6;
    555     else if (is_a_group_member(st.st_gid))
    556         mode <<= 3;
    557 
    558     if (st.st_mode & mode)
    559         return 0;
    560 
    561     return -1;
    562 }
    563 
    564 static void initialize_group_array(void)
    565 {
    566     ngroups = getgroups(0, NULL);
    567     if (ngroups > 0) {
    568         /* FIXME: ash tries so hard to not die on OOM,
    569          * and we spoil it with just one xrealloc here */
    570         /* We realloc, because test_main can be entered repeatedly by shell.
    571          * Testcase (ash): 'while true; do test -x some_file; done'
    572          * and watch top. (some_file must have owner != you) */
    573         group_array = xrealloc(group_array, ngroups * sizeof(gid_t));
    574         getgroups(ngroups, group_array);
    575     }
    576 }
    577 
    578 /* Return non-zero if GID is one that we have in our groups list. */
    579 //XXX: FIXME: duplicate of existing libbb function?
    580 // see toplevel TODO file:
    581 // possible code duplication ingroup() and is_a_group_member()
    582 static int is_a_group_member(gid_t gid)
    583 {
    584     int i;
    585 
    586     /* Short-circuit if possible, maybe saving a call to getgroups(). */
    587     if (gid == getgid() || gid == getegid())
    588         return 1;
    589 
    590     if (ngroups == 0)
    591         initialize_group_array();
    592 
    593     /* Search through the list looking for GID. */
    594     for (i = 0; i < ngroups; i++)
    595         if (gid == group_array[i])
    596             return 1;
    597 
    598     return 0;
    599 }
     877    args = argv;
     878    res = !oexpr(check_operator(*args));
     879
     880    if (*args != NULL && *++args != NULL) {
     881        /* TODO: example when this happens? */
     882        bb_error_msg("%s: unknown operand", *args);
     883        res = 2;
     884    }
     885 ret:
     886    DEINIT_S();
     887//  return negate ? !res : res;
     888    return res;
     889}
  • branches/2.2.9/mindi-busybox/coreutils/touch.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    2222/* This is a NOFORK applet. Be very careful! */
    2323
    24 int touch_main(int argc, char **argv);
    25 int touch_main(int argc, char **argv)
     24/* coreutils implements:
     25 * -a   change only the access time
     26 * -c, --no-create
     27 *      do not create any files
     28 * -d, --date=STRING
     29 *      parse STRING and use it instead of current time
     30 * -f   (ignored, BSD compat)
     31 * -m   change only the modification time
     32 * -r, --reference=FILE
     33 *      use this file's times instead of current time
     34 * -t STAMP
     35 *      use [[CC]YY]MMDDhhmm[.ss] instead of current time
     36 * --time=WORD
     37 *      change the specified time: WORD is access, atime, or use
     38 */
     39
     40int touch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     41int touch_main(int argc UNUSED_PARAM, char **argv)
    2642{
    2743    int fd;
    2844    int status = EXIT_SUCCESS;
    29     int flags = getopt32(argv, "c");
     45    int opts;
     46#if ENABLE_DESKTOP
     47# if ENABLE_LONG_OPTS
     48    static const char touch_longopts[] ALIGN1 =
     49        /* name, has_arg, val */
     50        "no-create\0"         No_argument       "c"
     51        "reference\0"         Required_argument "r"
     52        "date\0"              Required_argument "d"
     53    ;
     54# endif
     55    char *reference_file = NULL;
     56    char *date_str = NULL;
     57    struct timeval timebuf[2];
     58    timebuf[1].tv_usec = timebuf[0].tv_usec = 0;
     59#else
     60# define reference_file NULL
     61# define date_str       NULL
     62# define timebuf        ((struct timeval*)NULL)
     63#endif
    3064
     65#if ENABLE_DESKTOP && ENABLE_LONG_OPTS
     66    applet_long_options = touch_longopts;
     67#endif
     68    /* -d and -t both set time. In coreutils,
     69     * accepted data format differs a bit between -d and -t.
     70     * We accept the same formats for both */
     71    opts = getopt32(argv, "c" IF_DESKTOP("r:d:t:")
     72                /*ignored:*/ "fma"
     73                IF_DESKTOP(, &reference_file)
     74                IF_DESKTOP(, &date_str)
     75                IF_DESKTOP(, &date_str)
     76    );
     77
     78    opts &= 1; /* only -c bit is left */
    3179    argv += optind;
    32 
    3380    if (!*argv) {
    3481        bb_show_usage();
    3582    }
    3683
     84    if (reference_file) {
     85        struct stat stbuf;
     86        xstat(reference_file, &stbuf);
     87        timebuf[1].tv_sec = timebuf[0].tv_sec = stbuf.st_mtime;
     88    }
     89
     90    if (date_str) {
     91        struct tm tm_time;
     92        time_t t;
     93
     94        //time(&t);
     95        //localtime_r(&t, &tm_time);
     96        memset(&tm_time, 0, sizeof(tm_time));
     97        parse_datestr(date_str, &tm_time);
     98
     99        /* Correct any day of week and day of year etc. fields */
     100        tm_time.tm_isdst = -1;  /* Be sure to recheck dst */
     101        t = validate_tm_time(date_str, &tm_time);
     102
     103        timebuf[1].tv_sec = timebuf[0].tv_sec = t;
     104    }
     105
    37106    do {
    38         if (utime(*argv, NULL)) {
    39             if (errno == ENOENT) {  /* no such file */
    40                 if (flags) {    /* Creation is disabled, so ignore. */
     107        if (utimes(*argv, (reference_file || date_str) ? timebuf : NULL) != 0) {
     108            if (errno == ENOENT) { /* no such file */
     109                if (opts) { /* creation is disabled, so ignore */
    41110                    continue;
    42111                }
    43                 /* Try to create the file. */
    44                 fd = open(*argv, O_RDWR | O_CREAT,
    45                           S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
    46                           );
    47                 if ((fd >= 0) && !close(fd)) {
     112                /* Try to create the file */
     113                fd = open(*argv, O_RDWR | O_CREAT, 0666);
     114                if (fd >= 0) {
     115                    xclose(fd);
     116                    if (reference_file || date_str)
     117                        utimes(*argv, timebuf);
    48118                    continue;
    49119                }
    50120            }
    51121            status = EXIT_FAILURE;
    52             bb_perror_msg("%s", *argv);
     122            bb_simple_perror_msg(*argv);
    53123        }
    54124    } while (*++argv);
  • branches/2.2.9/mindi-busybox/coreutils/tr.c

    r1765 r2725  
    1414 * by Erik Andersen <andersen@codepoet.org> to be used in busybox.
    1515 *
    16  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     16 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1717 */
    1818/* http://www.opengroup.org/onlinepubs/009695399/utilities/tr.html
    19  * TODO: xdigit, graph, print
     19 * TODO: graph, print
    2020 */
     21
     22//kbuild:lib-$(CONFIG_TR) += tr.o
     23
     24//config:config TR
     25//config:   bool "tr"
     26//config:   default y
     27//config:   help
     28//config:     tr is used to squeeze, and/or delete characters from standard
     29//config:     input, writing to standard output.
     30//config:
     31//config:config FEATURE_TR_CLASSES
     32//config:   bool "Enable character classes (such as [:upper:])"
     33//config:   default y
     34//config:   depends on TR
     35//config:   help
     36//config:     Enable character classes, enabling commands such as:
     37//config:     tr [:upper:] [:lower:] to convert input into lowercase.
     38//config:
     39//config:config FEATURE_TR_EQUIV
     40//config:   bool "Enable equivalence classes"
     41//config:   default y
     42//config:   depends on TR
     43//config:   help
     44//config:     Enable equivalence classes, which essentially add the enclosed
     45//config:     character to the current set. For instance, tr [=a=] xyz would
     46//config:     replace all instances of 'a' with 'xyz'. This option is mainly
     47//config:     useful for cases when no other way of expressing a character
     48//config:     is possible.
     49
    2150#include "libbb.h"
    2251
    23 #define ASCII 0377
    24 
    25 #define TR_OPT_complement   (1<<0)
    26 #define TR_OPT_delete       (1<<1)
    27 #define TR_OPT_squeeze_reps (1<<2)
     52enum {
     53    ASCII = 256,
     54    /* string buffer needs to be at least as big as the whole "alphabet".
     55     * BUFSIZ == ASCII is ok, but we will realloc in expand
     56     * even for smallest patterns, let's avoid that by using *2:
     57     */
     58    TR_BUFSIZ = (BUFSIZ > ASCII*2) ? BUFSIZ : ASCII*2,
     59};
    2860
    2961static void map(char *pvector,
    30         unsigned char *string1, unsigned int string1_len,
    31         unsigned char *string2, unsigned int string2_len)
     62        char *string1, unsigned string1_len,
     63        char *string2, unsigned string2_len)
    3264{
    3365    char last = '0';
    34     unsigned int i, j;
     66    unsigned i, j;
    3567
    3668    for (j = 0, i = 0; i < string1_len; i++) {
    3769        if (string2_len <= j)
    38             pvector[string1[i]] = last;
     70            pvector[(unsigned char)(string1[i])] = last;
    3971        else
    40             pvector[string1[i]] = last = string2[j++];
     72            pvector[(unsigned char)(string1[i])] = last = string2[j++];
    4173    }
    4274}
    4375
    4476/* supported constructs:
    45  *   Ranges,  e.g.,  [0-9]  ==>  0123456789
    46  *   Escapes, e.g.,  \a     ==>  Control-G
    47  *   Character classes, e.g. [:upper:] ==> A ... Z
     77 *   Ranges,  e.g.,  0-9   ==>  0123456789
     78 *   Escapes, e.g.,  \a    ==>  Control-G
     79 *   Character classes, e.g. [:upper:] ==> A...Z
     80 *   Equiv classess, e.g. [=A=] ==> A   (hmmmmmmm?)
     81 * not supported:
     82 *   \ooo-\ooo - octal ranges
     83 *   [x*N] - repeat char x N times
     84 *   [x*] - repeat char x until it fills STRING2:
     85 * # echo qwe123 | /usr/bin/tr 123456789 '[d]'
     86 * qwe[d]
     87 * # echo qwe123 | /usr/bin/tr 123456789 '[d*]'
     88 * qweddd
    4889 */
    49 static unsigned int expand(const char *arg, char *buffer)
     90static unsigned expand(const char *arg, char **buffer_p)
    5091{
    51     char *buffer_start = buffer;
    52     unsigned i; /* XXX: FIXME: use unsigned char? */
     92    char *buffer = *buffer_p;
     93    unsigned pos = 0;
     94    unsigned size = TR_BUFSIZ;
     95    unsigned i; /* can't be unsigned char: must be able to hold 256 */
    5396    unsigned char ac;
    54 #define CLO ":]\0"
    55     static const char classes[] ALIGN1 =
    56         "alpha"CLO "alnum"CLO "digit"CLO "lower"CLO "upper"CLO "space"CLO
    57         "blank"CLO "punct"CLO "cntrl"CLO;
    58 #define CLASS_invalid 0 /* we increment the retval */
    59 #define CLASS_alpha 1
    60 #define CLASS_alnum 2
    61 #define CLASS_digit 3
    62 #define CLASS_lower 4
    63 #define CLASS_upper 5
    64 #define CLASS_space 6
    65 #define CLASS_blank 7
    66 #define CLASS_punct 8
    67 #define CLASS_cntrl 9
    68 //#define CLASS_xdigit 10
    69 //#define CLASS_graph 11
    70 //#define CLASS_print 12
     97
    7198    while (*arg) {
     99        if (pos + ASCII > size) {
     100            size += ASCII;
     101            *buffer_p = buffer = xrealloc(buffer, size);
     102        }
    72103        if (*arg == '\\') {
    73104            arg++;
    74             *buffer++ = bb_process_escape_sequence(&arg);
    75         } else if (*(arg+1) == '-') {
    76             ac = *(arg+2);
    77             if (ac == 0) {
    78                 *buffer++ = *arg++;
    79                 continue;
    80             }
    81             i = *arg;
    82             while (i <= ac)
    83                 *buffer++ = i++;
    84             arg += 3; /* Skip the assumed a-z */
    85         } else if (*arg == '[') {
     105            buffer[pos++] = bb_process_escape_sequence(&arg);
     106            continue;
     107        }
     108        if (arg[1] == '-') { /* "0-9..." */
     109            ac = arg[2];
     110            if (ac == '\0') { /* "0-": copy verbatim */
     111                buffer[pos++] = *arg++; /* copy '0' */
     112                continue; /* next iter will copy '-' and stop */
     113            }
     114            i = (unsigned char) *arg;
     115            while (i <= ac) /* ok: i is unsigned _int_ */
     116                buffer[pos++] = i++;
     117            arg += 3; /* skip 0-9 */
     118            continue;
     119        }
     120        if ((ENABLE_FEATURE_TR_CLASSES || ENABLE_FEATURE_TR_EQUIV)
     121         && *arg == '['
     122        ) {
    86123            arg++;
    87             i = *arg++;
    88             if (ENABLE_FEATURE_TR_CLASSES && i == ':') {
     124            i = (unsigned char) *arg++;
     125            /* "[xyz...". i=x, arg points to y */
     126            if (ENABLE_FEATURE_TR_CLASSES && i == ':') { /* [:class:] */
     127#define CLO ":]\0"
     128                static const char classes[] ALIGN1 =
     129                    "alpha"CLO "alnum"CLO "digit"CLO
     130                    "lower"CLO "upper"CLO "space"CLO
     131                    "blank"CLO "punct"CLO "cntrl"CLO
     132                    "xdigit"CLO;
     133                enum {
     134                    CLASS_invalid = 0, /* we increment the retval */
     135                    CLASS_alpha = 1,
     136                    CLASS_alnum = 2,
     137                    CLASS_digit = 3,
     138                    CLASS_lower = 4,
     139                    CLASS_upper = 5,
     140                    CLASS_space = 6,
     141                    CLASS_blank = 7,
     142                    CLASS_punct = 8,
     143                    CLASS_cntrl = 9,
     144                    CLASS_xdigit = 10,
     145                    //CLASS_graph = 11,
     146                    //CLASS_print = 12,
     147                };
    89148                smalluint j;
    90                 { /* not really pretty.. */
    91                     char *tmp = xstrndup(arg, 7); // warning: xdigit needs 8, not 7
    92                     j = index_in_strings(classes, tmp) + 1;
    93                     free(tmp);
    94                 }
    95                 if (j == CLASS_alnum || j == CLASS_digit) {
     149                char *tmp;
     150
     151                /* xdigit needs 8, not 7 */
     152                i = 7 + (arg[0] == 'x');
     153                tmp = xstrndup(arg, i);
     154                j = index_in_strings(classes, tmp) + 1;
     155                free(tmp);
     156
     157                if (j == CLASS_invalid)
     158                    goto skip_bracket;
     159
     160                arg += i;
     161                if (j == CLASS_alnum || j == CLASS_digit || j == CLASS_xdigit) {
    96162                    for (i = '0'; i <= '9'; i++)
    97                         *buffer++ = i;
     163                        buffer[pos++] = i;
    98164                }
    99165                if (j == CLASS_alpha || j == CLASS_alnum || j == CLASS_upper) {
    100166                    for (i = 'A'; i <= 'Z'; i++)
    101                         *buffer++ = i;
     167                        buffer[pos++] = i;
    102168                }
    103169                if (j == CLASS_alpha || j == CLASS_alnum || j == CLASS_lower) {
    104170                    for (i = 'a'; i <= 'z'; i++)
    105                         *buffer++ = i;
     171                        buffer[pos++] = i;
    106172                }
    107173                if (j == CLASS_space || j == CLASS_blank) {
    108                     *buffer++ = '\t';
     174                    buffer[pos++] = '\t';
    109175                    if (j == CLASS_space) {
    110                         *buffer++ = '\n';
    111                         *buffer++ = '\v';
    112                         *buffer++ = '\f';
    113                         *buffer++ = '\r';
     176                        buffer[pos++] = '\n';
     177                        buffer[pos++] = '\v';
     178                        buffer[pos++] = '\f';
     179                        buffer[pos++] = '\r';
    114180                    }
    115                     *buffer++ = ' ';
     181                    buffer[pos++] = ' ';
    116182                }
    117183                if (j == CLASS_punct || j == CLASS_cntrl) {
    118                     for (i = 0; i <= ASCII; i++)
    119                         if ((j == CLASS_punct &&
    120                              isprint(i) && (!isalnum(i)) && (!isspace(i))) ||
    121                             (j == CLASS_cntrl && iscntrl(i)))
    122                             *buffer++ = i;
    123                 }
    124                 if (j == CLASS_invalid) {
    125                     *buffer++ = '[';
    126                     *buffer++ = ':';
    127                     continue;
    128                 }
    129                 break;
    130             }
    131             if (ENABLE_FEATURE_TR_EQUIV && i == '=') {
    132                 *buffer++ = *arg;
    133                 arg += 3;   /* Skip the closing =] */
     184                    for (i = '\0'; i < ASCII; i++) {
     185                        if ((j == CLASS_punct && isprint_asciionly(i) && !isalnum(i) && !isspace(i))
     186                         || (j == CLASS_cntrl && iscntrl(i))
     187                        ) {
     188                            buffer[pos++] = i;
     189                        }
     190                    }
     191                }
     192                if (j == CLASS_xdigit) {
     193                    for (i = 'A'; i <= 'F'; i++) {
     194                        buffer[pos + 6] = i | 0x20;
     195                        buffer[pos++] = i;
     196                    }
     197                    pos += 6;
     198                }
    134199                continue;
    135200            }
    136             if (*arg++ != '-') {
    137                 *buffer++ = '[';
    138                 arg -= 2;
     201            /* "[xyz...", i=x, arg points to y */
     202            if (ENABLE_FEATURE_TR_EQUIV && i == '=') { /* [=CHAR=] */
     203                buffer[pos++] = *arg; /* copy CHAR */
     204                if (!arg[0] || arg[1] != '=' || arg[2] != ']')
     205                    bb_show_usage();
     206                arg += 3;  /* skip CHAR=] */
    139207                continue;
    140208            }
    141             ac = *arg++;
    142             while (i <= ac)
    143                 *buffer++ = i++;
    144             arg++;  /* Skip the assumed ']' */
    145         } else
    146             *buffer++ = *arg++;
    147     }
    148     return (buffer - buffer_start);
     209            /* The rest of "[xyz..." cases is treated as normal
     210             * string, "[" has no special meaning here:
     211             * tr "[a-z]" "[A-Z]" can be written as tr "a-z" "A-Z",
     212             * also try tr "[a-z]" "_A-Z+" and you'll see that
     213             * [] is not special here.
     214             */
     215 skip_bracket:
     216            arg -= 2; /* points to "[" in "[xyz..." */
     217        }
     218        buffer[pos++] = *arg++;
     219    }
     220    return pos;
    149221}
    150222
     223/* NB: buffer is guaranteed to be at least TR_BUFSIZE
     224 * (which is >= ASCII) big.
     225 */
    151226static int complement(char *buffer, int buffer_len)
    152227{
    153     int i, j, ix;
    154     char conv[ASCII + 2];
    155 
    156     ix = 0;
    157     for (i = 0; i <= ASCII; i++) {
    158         for (j = 0; j < buffer_len; j++)
    159             if (buffer[j] == i)
    160                 break;
    161         if (j == buffer_len)
    162             conv[ix++] = i & ASCII;
    163     }
    164     memcpy(buffer, conv, ix);
    165     return ix;
     228    int len;
     229    char conv[ASCII];
     230    unsigned char ch;
     231
     232    len = 0;
     233    ch = '\0';
     234    while (1) {
     235        if (memchr(buffer, ch, buffer_len) == NULL)
     236            conv[len++] = ch;
     237        if (++ch == '\0')
     238            break;
     239    }
     240    memcpy(buffer, conv, len);
     241    return len;
    166242}
    167243
    168 int tr_main(int argc, char **argv);
    169 int tr_main(int argc, char **argv)
     244int tr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     245int tr_main(int argc UNUSED_PARAM, char **argv)
    170246{
    171     unsigned char *ptr;
    172     int output_length = 0, input_length;
    173     int idx = 1;
    174247    int i;
    175     smalluint flags = 0;
    176     size_t read_chars = 0, in_index = 0, out_index = 0, c, coded, last = -1;
    177     RESERVE_CONFIG_UBUFFER(output, BUFSIZ);
    178     RESERVE_CONFIG_BUFFER(vector, ASCII+1);
    179     RESERVE_CONFIG_BUFFER(invec,  ASCII+1);
    180     RESERVE_CONFIG_BUFFER(outvec, ASCII+1);
    181 
    182     if (argc > 1 && argv[idx][0] == '-') {
    183         for (ptr = (unsigned char *) &argv[idx][1]; *ptr; ptr++) {
    184             if (*ptr == 'c')
    185                 flags |= TR_OPT_complement;
    186             else if (*ptr == 'd')
    187                 flags |= TR_OPT_delete;
    188             else if (*ptr == 's')
    189                 flags |= TR_OPT_squeeze_reps;
    190             else
    191                 bb_show_usage();
    192         }
    193         idx++;
    194     }
    195     for (i = 0; i <= ASCII; i++) {
     248    smalluint opts;
     249    ssize_t read_chars;
     250    size_t in_index, out_index;
     251    unsigned last = UCHAR_MAX + 1; /* not equal to any char */
     252    unsigned char coded, c;
     253    char *str1 = xmalloc(TR_BUFSIZ);
     254    char *str2 = xmalloc(TR_BUFSIZ);
     255    int str2_length;
     256    int str1_length;
     257    char *vector = xzalloc(ASCII * 3);
     258    char *invec  = vector + ASCII;
     259    char *outvec = vector + ASCII * 2;
     260
     261#define TR_OPT_complement   (3 << 0)
     262#define TR_OPT_delete       (1 << 2)
     263#define TR_OPT_squeeze_reps (1 << 3)
     264
     265    for (i = 0; i < ASCII; i++) {
    196266        vector[i] = i;
    197         invec[i] = outvec[i] = FALSE;
    198     }
    199 
    200 #define tr_buf bb_common_bufsiz1
    201     if (argv[idx] != NULL) {
    202         input_length = expand(argv[idx++], tr_buf);
    203         if (flags & TR_OPT_complement)
    204             input_length = complement(tr_buf, input_length);
    205         if (argv[idx] != NULL) {
    206             if (*argv[idx] == '\0')
    207                 bb_error_msg_and_die("STRING2 cannot be empty");
    208             output_length = expand(argv[idx], output);
    209             map(vector, tr_buf, input_length, output, output_length);
    210         }
    211         for (i = 0; i < input_length; i++)
    212             invec[(unsigned char)tr_buf[i]] = TRUE;
    213         for (i = 0; i < output_length; i++)
    214             outvec[output[i]] = TRUE;
    215     }
    216 
     267        /*invec[i] = outvec[i] = FALSE; - done by xzalloc */
     268    }
     269
     270    /* -C/-c difference is that -C complements "characters",
     271     * and -c complements "values" (binary bytes I guess).
     272     * In POSIX locale, these are the same.
     273     */
     274
     275    opt_complementary = "-1";
     276    opts = getopt32(argv, "+Ccds"); /* '+': stop at first non-option */
     277    argv += optind;
     278
     279    str1_length = expand(*argv++, &str1);
     280    str2_length = 0;
     281    if (opts & TR_OPT_complement)
     282        str1_length = complement(str1, str1_length);
     283    if (*argv) {
     284        if (argv[0][0] == '\0')
     285            bb_error_msg_and_die("STRING2 cannot be empty");
     286        str2_length = expand(*argv, &str2);
     287        map(vector, str1, str1_length,
     288                str2, str2_length);
     289    }
     290    for (i = 0; i < str1_length; i++)
     291        invec[(unsigned char)(str1[i])] = TRUE;
     292    for (i = 0; i < str2_length; i++)
     293        outvec[(unsigned char)(str2[i])] = TRUE;
     294
     295    goto start_from;
     296
     297    /* In this loop, str1 space is reused as input buffer,
     298     * str2 - as output one. */
    217299    for (;;) {
    218300        /* If we're out of input, flush output and read more input. */
    219         if (in_index == read_chars) {
     301        if ((ssize_t)in_index == read_chars) {
    220302            if (out_index) {
    221                 xwrite(STDOUT_FILENO, (char *)output, out_index);
     303                xwrite(STDOUT_FILENO, str2, out_index);
     304 start_from:
    222305                out_index = 0;
    223306            }
    224             read_chars = read(STDIN_FILENO, tr_buf, BUFSIZ);
     307            read_chars = safe_read(STDIN_FILENO, str1, TR_BUFSIZ);
    225308            if (read_chars <= 0) {
    226                 if (write(STDOUT_FILENO, (char *)output, out_index) != out_index)
    227                     bb_perror_msg(bb_msg_write_error);
    228                 exit(EXIT_SUCCESS);
     309                if (read_chars < 0)
     310                    bb_perror_msg_and_die(bb_msg_read_error);
     311                break;
    229312            }
    230313            in_index = 0;
    231314        }
    232         c = tr_buf[in_index++];
     315        c = str1[in_index++];
     316        if ((opts & TR_OPT_delete) && invec[c])
     317            continue;
    233318        coded = vector[c];
    234         if ((flags & TR_OPT_delete) && invec[c])
     319        if ((opts & TR_OPT_squeeze_reps) && last == coded
     320         && (invec[c] || outvec[coded])
     321        ) {
    235322            continue;
    236         if ((flags & TR_OPT_squeeze_reps) && last == coded &&
    237             (invec[c] || outvec[coded]))
    238             continue;
    239         output[out_index++] = last = coded;
    240     }
    241     /* NOTREACHED */
     323        }
     324        str2[out_index++] = last = coded;
     325    }
     326
    242327    return EXIT_SUCCESS;
    243328}
  • branches/2.2.9/mindi-busybox/coreutils/true.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1515/* This is a NOFORK applet. Be very careful! */
    1616
    17 int true_main(int argc, char **argv);
    18 int true_main(int argc, char **argv)
     17int true_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     18int true_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
    1919{
    2020    return EXIT_SUCCESS;
  • branches/2.2.9/mindi-busybox/coreutils/tty.c

    r1765 r2725  
    55 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
    10 /* BB_AUDIT SUSv3 compliant */
    11 /* http://www.opengroup.org/onlinepubs/007904975/utilities/tty.html */
     10/* BB_AUDIT SUSv4 compliant */
     11/* http://www.opengroup.org/onlinepubs/9699919799/utilities/tty.html */
    1212
    1313#include "libbb.h"
    1414
    15 int tty_main(int argc, char **argv);
    16 int tty_main(int argc, char **argv)
     15int tty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     16int tty_main(int argc UNUSED_PARAM, char **argv)
    1717{
    1818    const char *s;
    19     USE_INCLUDE_SUSv2(int silent;)  /* Note: No longer relevant in SUSv3. */
     19    IF_INCLUDE_SUSv2(int silent;)  /* Note: No longer relevant in SUSv3. */
    2020    int retval;
    2121
    22     xfunc_error_retval = 2; /* SUSv3 requires > 1 for error. */
     22    xfunc_error_retval = 2;  /* SUSv3 requires > 1 for error. */
    2323
    24     USE_INCLUDE_SUSv2(silent = getopt32(argv, "s");)
     24    IF_INCLUDE_SUSv2(silent = getopt32(argv, "s");)
     25    IF_INCLUDE_SUSv2(argv += optind;)
     26    IF_NOT_INCLUDE_SUSv2(argv += 1;)
    2527
    2628    /* gnu tty outputs a warning that it is ignoring all args. */
    27     bb_warn_ignoring_args(argc - optind);
     29    bb_warn_ignoring_args(argv[0]);
    2830
    29     retval = 0;
     31    retval = EXIT_SUCCESS;
    3032
    31     s = ttyname(0);
     33    s = xmalloc_ttyname(STDIN_FILENO);
    3234    if (s == NULL) {
    33     /* According to SUSv3, ttyname can on fail with EBADF or ENOTTY.
     35    /* According to SUSv3, ttyname can fail with EBADF or ENOTTY.
    3436     * We know the file descriptor is good, so failure means not a tty. */
    3537        s = "not a tty";
    36         retval = 1;
     38        retval = EXIT_FAILURE;
    3739    }
    38     USE_INCLUDE_SUSv2(if (!silent) puts(s);)
    39     SKIP_INCLUDE_SUSv2(puts(s);)
     40    IF_INCLUDE_SUSv2(if (!silent) puts(s);)
     41    IF_NOT_INCLUDE_SUSv2(puts(s);)
    4042
    4143    fflush_stdout_and_exit(retval);
  • branches/2.2.9/mindi-busybox/coreutils/uname.c

    r1765 r2725  
    33 * Copyright (C) 1989-1999 Free Software Foundation, Inc.
    44 *
    5  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    66 */
    77
     
    1010
    1111/* Option       Example
    12 
    13    -s, --sysname    SunOS
    14    -n, --nodename   rocky8
    15    -r, --release    4.0
    16    -v, --version
    17    -m, --machine    sun
    18    -a, --all        SunOS rocky8 4.0  sun
    19 
    20    The default behavior is equivalent to `-s'.
    21 
    22    David MacKenzie <djm@gnu.ai.mit.edu> */
    23 
    24 /* Busyboxed by Erik Andersen */
    25 
    26 /* Further size reductions by Glenn McGrath and Manuel Novoa III. */
    27 
    28 /* Mar 16, 2003      Manuel Novoa III   (mjn3@codepoet.org)
     12 * -s, --sysname    SunOS
     13 * -n, --nodename   rocky8
     14 * -r, --release    4.0
     15 * -v, --version
     16 * -m, --machine    sun
     17 * -a, --all        SunOS rocky8 4.0  sun
    2918 *
    30  * Now does proper error checking on i/o.  Plus some further space savings.
     19 * The default behavior is equivalent to '-s'.
     20 *
     21 * David MacKenzie <djm@gnu.ai.mit.edu>
     22 *
     23 * GNU coreutils 6.10:
     24 * Option:                      struct   Example(s):
     25 *                              utsname
     26 *                              field:
     27 * -s, --kernel-name            sysname  Linux
     28 * -n, --nodename               nodename localhost.localdomain
     29 * -r, --kernel-release         release  2.6.29
     30 * -v, --kernel-version         version  #1 SMP Sun Jan 11 20:52:37 EST 2009
     31 * -m, --machine                machine  x86_64   i686
     32 * -p, --processor              (none)   x86_64   i686
     33 * -i, --hardware-platform      (none)   x86_64   i386
     34 *      NB: vanilla coreutils reports "unknown" -p and -i,
     35 *      x86_64 and i686/i386 shown above are Fedora's inventions.
     36 * -o, --operating-system       (none)   GNU/Linux
     37 * -a, --all: all of the above, in the order shown.
     38 *      If -p or -i is not known, don't show them
    3139 */
    3240
     41/* Busyboxed by Erik Andersen
     42 *
     43 * Before 2003: Glenn McGrath and Manuel Novoa III
     44 *  Further size reductions.
     45 * Mar 16, 2003: Manuel Novoa III (mjn3@codepoet.org)
     46 *  Now does proper error checking on i/o.  Plus some further space savings.
     47 * Jan 2009:
     48 *  Fix handling of -a to not print "unknown", add -o and -i support.
     49 */
     50
     51#include "libbb.h"
     52/* After libbb.h, since it needs sys/types.h on some systems */
    3353#include <sys/utsname.h>
    34 #include "libbb.h"
    3554
    3655typedef struct {
    3756    struct utsname name;
    38     char processor[8];          /* for "unknown" */
     57    char processor[sizeof(((struct utsname*)NULL)->machine)];
     58    char platform[sizeof(((struct utsname*)NULL)->machine)];
     59    char os[sizeof("GNU/Linux")];
    3960} uname_info_t;
    4061
    41 static const char options[] ALIGN1 = "snrvmpa";
    42 static const unsigned short utsname_offset[] ALIGN2 = {
    43     offsetof(uname_info_t,name.sysname),
    44     offsetof(uname_info_t,name.nodename),
    45     offsetof(uname_info_t,name.release),
    46     offsetof(uname_info_t,name.version),
    47     offsetof(uname_info_t,name.machine),
    48     offsetof(uname_info_t,processor)
     62static const char options[] ALIGN1 = "snrvmpioa";
     63static const unsigned short utsname_offset[] = {
     64    offsetof(uname_info_t, name.sysname), /* -s */
     65    offsetof(uname_info_t, name.nodename), /* -n */
     66    offsetof(uname_info_t, name.release), /* -r */
     67    offsetof(uname_info_t, name.version), /* -v */
     68    offsetof(uname_info_t, name.machine), /* -m */
     69    offsetof(uname_info_t, processor), /* -p */
     70    offsetof(uname_info_t, platform), /* -i */
     71    offsetof(uname_info_t, os), /* -o */
    4972};
    5073
    51 int uname_main(int argc, char **argv);
    52 int uname_main(int argc, char **argv)
     74int uname_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     75int uname_main(int argc UNUSED_PARAM, char **argv)
    5376{
     77#if ENABLE_LONG_OPTS
     78    static const char uname_longopts[] ALIGN1 =
     79        /* name, has_arg, val */
     80        "all\0"               No_argument       "a"
     81        "kernel-name\0"       No_argument       "s"
     82        "nodename\0"          No_argument       "n"
     83        "kernel-release\0"    No_argument       "r"
     84        "release\0"           No_argument       "r"
     85        "kernel-version\0"    No_argument       "v"
     86        "machine\0"           No_argument       "m"
     87        "processor\0"         No_argument       "p"
     88        "hardware-platform\0" No_argument       "i"
     89        "operating-system\0"  No_argument       "o"
     90    ;
     91#endif
    5492    uname_info_t uname_info;
    5593#if defined(__sparc__) && defined(__linux__)
    5694    char *fake_sparc = getenv("FAKE_SPARC");
    5795#endif
    58     const unsigned short int *delta;
    59     char toprint;
     96    const char *unknown_str = "unknown";
     97    const char *fmt;
     98    const unsigned short *delta;
     99    unsigned toprint;
    60100
     101    IF_LONG_OPTS(applet_long_options = uname_longopts);
    61102    toprint = getopt32(argv, options);
    62103
    63     if (argc != optind) {
     104    if (argv[optind]) { /* coreutils-6.9 compat */
    64105        bb_show_usage();
    65106    }
    66107
    67     if (toprint & (1 << 6)) {
    68         toprint = 0x3f;
     108    if (toprint & (1 << 8)) { /* -a => all opts on */
     109        toprint = (1 << 8) - 1;
     110        unknown_str = ""; /* -a does not print unknown fields */
    69111    }
    70112
    71     if (toprint == 0) {
    72         toprint = 1;            /* sysname */
     113    if (toprint == 0) { /* no opts => -s (sysname) */
     114        toprint = 1;
    73115    }
    74116
    75     if (uname(&uname_info.name) == -1) {
    76         bb_error_msg_and_die("cannot get system name");
    77     }
     117    uname(&uname_info.name); /* never fails */
    78118
    79119#if defined(__sparc__) && defined(__linux__)
    80     if ((fake_sparc != NULL)
    81         && ((fake_sparc[0] == 'y')
    82             || (fake_sparc[0] == 'Y'))) {
     120    if (fake_sparc && (fake_sparc[0] | 0x20) == 'y') {
    83121        strcpy(uname_info.name.machine, "sparc");
    84122    }
    85123#endif
    86 
    87     strcpy(uname_info.processor, "unknown");
     124    strcpy(uname_info.processor, unknown_str);
     125    strcpy(uname_info.platform, unknown_str);
     126    strcpy(uname_info.os, "GNU/Linux");
     127#if 0
     128    /* Fedora does something like this */
     129    strcpy(uname_info.processor, uname_info.name.machine);
     130    strcpy(uname_info.platform, uname_info.name.machine);
     131    if (uname_info.platform[0] == 'i'
     132     && uname_info.platform[1]
     133     && uname_info.platform[2] == '8'
     134     && uname_info.platform[3] == '6'
     135    ) {
     136        uname_info.platform[1] = '3';
     137    }
     138#endif
    88139
    89140    delta = utsname_offset;
     141    fmt = " %s" + 1;
    90142    do {
    91143        if (toprint & 1) {
    92             printf(((char *)(&uname_info)) + *delta);
    93             if (toprint > 1) {
    94                 putchar(' ');
     144            const char *p = (char *)(&uname_info) + *delta;
     145            if (p[0]) {
     146                printf(fmt, p);
     147                fmt = " %s";
    95148            }
    96149        }
    97150        ++delta;
    98151    } while (toprint >>= 1);
    99     putchar('\n');
     152    bb_putchar('\n');
    100153
    101     fflush_stdout_and_exit(EXIT_SUCCESS);
     154    fflush_stdout_and_exit(EXIT_SUCCESS); /* coreutils-6.9 compat */
    102155}
  • branches/2.2.9/mindi-busybox/coreutils/uniq.c

    r1765 r2725  
    55 * Copyright (C) 2005  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1313#include "libbb.h"
    1414
    15 static const char uniq_opts[] ALIGN1 = "cdu" "f:s:" "cdu\0\1\2\4";
    16 
    17 static FILE *xgetoptfile_uniq_s(char **argv, int read0write2)
     15int uniq_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     16int uniq_main(int argc UNUSED_PARAM, char **argv)
    1817{
    19     const char *n;
    20 
    21     n = *argv;
    22     if (n != NULL) {
    23         if ((*n != '-') || n[1]) {
    24             return xfopen(n, "r\0w" + read0write2);
    25         }
    26     }
    27     return (read0write2) ? stdout : stdin;
    28 }
    29 
    30 int uniq_main(int argc, char **argv);
    31 int uniq_main(int argc, char **argv)
    32 {
    33     FILE *in, *out;
    34     unsigned long dups, skip_fields, skip_chars, i;
    35     const char *s0, *e0, *s1, *e1, *input_filename;
     18    const char *input_filename;
     19    unsigned skip_fields, skip_chars, max_chars;
    3620    unsigned opt;
     21    char *cur_line;
     22    const char *cur_compare;
    3723
    3824    enum {
    3925        OPT_c = 0x1,
    40         OPT_d = 0x2,
    41         OPT_u = 0x4,
     26        OPT_d = 0x2, /* print only dups */
     27        OPT_u = 0x4, /* print only uniq */
    4228        OPT_f = 0x8,
    4329        OPT_s = 0x10,
     30        OPT_w = 0x20,
    4431    };
    4532
    4633    skip_fields = skip_chars = 0;
     34    max_chars = INT_MAX;
    4735
    48     opt = getopt32(argv, "cduf:s:", &s0, &s1);
    49     if (opt & OPT_f)
    50         skip_fields = xatoul(s0);
    51     if (opt & OPT_s)
    52         skip_chars = xatoul(s1);
     36    opt_complementary = "f+:s+:w+";
     37    opt = getopt32(argv, "cduf:s:w:", &skip_fields, &skip_chars, &max_chars);
    5338    argv += optind;
    5439
    55     input_filename = *argv;
     40    input_filename = argv[0];
     41    if (input_filename) {
     42        const char *output;
    5643
    57     in = xgetoptfile_uniq_s(argv, 0);
    58     if (*argv) {
    59         ++argv;
    60     }
    61     out = xgetoptfile_uniq_s(argv, 2);
    62     if (*argv && argv[1]) {
    63         bb_show_usage();
     44        if (input_filename[0] != '-' || input_filename[1]) {
     45            close(STDIN_FILENO); /* == 0 */
     46            xopen(input_filename, O_RDONLY); /* fd will be 0 */
     47        }
     48        output = argv[1];
     49        if (output) {
     50            if (argv[2])
     51                bb_show_usage();
     52            if (output[0] != '-' || output[1]) {
     53                // Won't work with "uniq - FILE" and closed stdin:
     54                //close(STDOUT_FILENO);
     55                //xopen(output, O_WRONLY | O_CREAT | O_TRUNC);
     56                xmove_fd(xopen(output, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO);
     57            }
     58        }
    6459    }
    6560
    66     s1 = e1 = NULL;             /* prime the pump */
     61    cur_compare = cur_line = NULL; /* prime the pump */
    6762
    6863    do {
    69         s0 = s1;
    70         e0 = e1;
     64        unsigned i;
     65        unsigned long dups;
     66        char *old_line;
     67        const char *old_compare;
     68
     69        old_line = cur_line;
     70        old_compare = cur_compare;
    7171        dups = 0;
    7272
    7373        /* gnu uniq ignores newlines */
    74         while ((s1 = xmalloc_getline(in)) != NULL) {
    75             e1 = s1;
     74        while ((cur_line = xmalloc_fgetline(stdin)) != NULL) {
     75            cur_compare = cur_line;
    7676            for (i = skip_fields; i; i--) {
    77                 e1 = skip_whitespace(e1);
    78                 e1 = skip_non_whitespace(e1);
     77                cur_compare = skip_whitespace(cur_compare);
     78                cur_compare = skip_non_whitespace(cur_compare);
    7979            }
    80             for (i = skip_chars; *e1 && i; i--) {
    81                 ++e1;
     80            for (i = skip_chars; *cur_compare && i; i--) {
     81                ++cur_compare;
    8282            }
    8383
    84             if (!s0 || strcmp(e0, e1)) {
     84            if (!old_line || strncmp(old_compare, cur_compare, max_chars)) {
    8585                break;
    8686            }
    8787
    88             ++dups;      /* Note: Testing for overflow seems excessive. */
     88            free(cur_line);
     89            ++dups;  /* testing for overflow seems excessive */
    8990        }
    9091
    91         if (s0) {
    92             if (!(opt & (OPT_d << !!dups))) { /* (if dups, opt & OPT_e) */
    93                 fprintf(out, "\0%d " + (opt & 1), dups + 1);
    94                 fprintf(out, "%s\n", s0);
     92        if (old_line) {
     93            if (!(opt & (OPT_d << !!dups))) { /* (if dups, opt & OPT_u) */
     94                if (opt & OPT_c) {
     95                    /* %7lu matches GNU coreutils 6.9 */
     96                    printf("%7lu ", dups + 1);
     97                }
     98                printf("%s\n", old_line);
    9599            }
    96             free((void *)s0);
     100            free(old_line);
    97101        }
    98     } while (s1);
     102    } while (cur_line);
    99103
    100     die_if_ferror(in, input_filename);
     104    die_if_ferror(stdin, input_filename);
    101105
    102106    fflush_stdout_and_exit(EXIT_SUCCESS);
  • branches/2.2.9/mindi-busybox/coreutils/usleep.c

    r1765 r2725  
    55 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1414/* This is a NOFORK applet. Be very careful! */
    1515
    16 int usleep_main(int argc, char **argv);
    17 int usleep_main(int argc, char **argv)
     16int usleep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     17int usleep_main(int argc UNUSED_PARAM, char **argv)
    1818{
    19     if (argc != 2) {
     19    if (!argv[1]) {
    2020        bb_show_usage();
    2121    }
  • branches/2.2.9/mindi-busybox/coreutils/uudecode.c

    r1765 r2725  
    11/* vi: set sw=4 ts=4: */
    22/*
    3  *  Copyright 2003, Glenn McGrath <bug1@iinet.net.au>
     3 * Copyright 2003, Glenn McGrath
    44 *
    5  *  Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    66 *
    7  *  Based on specification from
    8  *  http://www.opengroup.org/onlinepubs/007904975/utilities/uuencode.html
     7 * Based on specification from
     8 * http://www.opengroup.org/onlinepubs/007904975/utilities/uuencode.html
    99 *
    10  *  Bugs: the spec doesn't mention anything about "`\n`\n" prior to the
    11  *        "end" line
     10 * Bugs: the spec doesn't mention anything about "`\n`\n" prior to the
     11 * "end" line
    1212 */
    13 
    14 
    1513#include "libbb.h"
    1614
    17 static void read_stduu(FILE *src_stream, FILE *dst_stream)
     15#if ENABLE_UUDECODE
     16static void FAST_FUNC read_stduu(FILE *src_stream, FILE *dst_stream, int flags UNUSED_PARAM)
    1817{
    1918    char *line;
    2019
    21     while ((line = xmalloc_getline(src_stream)) != NULL) {
    22         int length;
    23         char *line_ptr = line;
     20    while ((line = xmalloc_fgetline(src_stream)) != NULL) {
     21        int encoded_len, str_len;
     22        char *line_ptr, *dst;
    2423
    2524        if (strcmp(line, "end") == 0) {
    26             return;
    27         }
    28         length = ((*line_ptr - 0x20) & 0x3f)* 4 / 3;
    29 
    30         if (length <= 0) {
     25            return; /* the only non-error exit */
     26        }
     27
     28        line_ptr = line;
     29        while (*line_ptr) {
     30            *line_ptr = (*line_ptr - 0x20) & 0x3f;
     31            line_ptr++;
     32        }
     33        str_len = line_ptr - line;
     34
     35        encoded_len = line[0] * 4 / 3;
     36        /* Check that line is not too short. (we tolerate
     37         * overly _long_ line to accomodate possible extra '`').
     38         * Empty line case is also caught here. */
     39        if (str_len <= encoded_len) {
     40            break; /* go to bb_error_msg_and_die("short file"); */
     41        }
     42        if (encoded_len <= 0) {
    3143            /* Ignore the "`\n" line, why is it even in the encode file ? */
     44            free(line);
    3245            continue;
    3346        }
    34         if (length > 60) {
     47        if (encoded_len > 60) {
    3548            bb_error_msg_and_die("line too long");
    3649        }
    3750
    38         line_ptr++;
    39         /* Tolerate an overly long line to accomodate a possible exta '`' */
    40         if (strlen(line_ptr) < (size_t)length) {
    41             bb_error_msg_and_die("short file");
    42         }
    43 
    44         while (length > 0) {
     51        dst = line;
     52        line_ptr = line + 1;
     53        do {
    4554            /* Merge four 6 bit chars to three 8 bit chars */
    46             fputc(((line_ptr[0] - 0x20) & 077) << 2 | ((line_ptr[1] - 0x20) & 077) >> 4, dst_stream);
    47             line_ptr++;
    48             length--;
    49             if (length == 0) {
     55            *dst++ = line_ptr[0] << 2 | line_ptr[1] >> 4;
     56            encoded_len--;
     57            if (encoded_len == 0) {
    5058                break;
    5159            }
    5260
    53             fputc(((line_ptr[0] - 0x20) & 077) << 4 | ((line_ptr[1] - 0x20) & 077) >> 2, dst_stream);
    54             line_ptr++;
    55             length--;
    56             if (length == 0) {
     61            *dst++ = line_ptr[1] << 4 | line_ptr[2] >> 2;
     62            encoded_len--;
     63            if (encoded_len == 0) {
    5764                break;
    5865            }
    5966
    60             fputc(((line_ptr[0] - 0x20) & 077) << 6 | ((line_ptr[1] - 0x20) & 077), dst_stream);
    61             line_ptr += 2;
    62             length -= 2;
    63         }
     67            *dst++ = line_ptr[2] << 6 | line_ptr[3];
     68            line_ptr += 4;
     69            encoded_len -= 2;
     70        } while (encoded_len > 0);
     71        fwrite(line, 1, dst - line, dst_stream);
    6472        free(line);
    6573    }
    6674    bb_error_msg_and_die("short file");
    6775}
    68 
    69 static void read_base64(FILE *src_stream, FILE *dst_stream)
     76#endif
     77
     78#if ENABLE_UUDECODE
     79int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     80int uudecode_main(int argc UNUSED_PARAM, char **argv)
    7081{
    71     int term_count = 1;
    72 
    73     while (1) {
    74         char translated[4];
    75         int count = 0;
    76 
    77         while (count < 4) {
    78             char *table_ptr;
    79             int ch;
    80 
    81             /* Get next _valid_ character.
    82              * global vector bb_uuenc_tbl_base64[] contains this string:
    83              * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n"
    84              */
    85             do {
    86                 ch = fgetc(src_stream);
    87                 if (ch == EOF) {
    88                     bb_error_msg_and_die("short file");
    89                 }
    90                 table_ptr = strchr(bb_uuenc_tbl_base64, ch);
    91             } while (table_ptr == NULL);
    92 
    93             /* Convert encoded character to decimal */
    94             ch = table_ptr - bb_uuenc_tbl_base64;
    95 
    96             if (*table_ptr == '=') {
    97                 if (term_count == 0) {
    98                     translated[count] = '\0';
    99                     break;
    100                 }
    101                 term_count++;
    102             } else if (*table_ptr == '\n') {
    103                 /* Check for terminating line */
    104                 if (term_count == 5) {
    105                     return;
    106                 }
    107                 term_count = 1;
    108                 continue;
    109             } else {
    110                 translated[count] = ch;
    111                 count++;
    112                 term_count = 0;
    113             }
    114         }
    115 
    116         /* Merge 6 bit chars to 8 bit */
    117         if (count > 1) {
    118             fputc(translated[0] << 2 | translated[1] >> 4, dst_stream);
    119         }
    120         if (count > 2) {
    121             fputc(translated[1] << 4 | translated[2] >> 2, dst_stream);
    122         }
    123         if (count > 3) {
    124             fputc(translated[2] << 6 | translated[3], dst_stream);
    125         }
    126     }
    127 }
    128 
    129 int uudecode_main(int argc, char **argv);
    130 int uudecode_main(int argc, char **argv)
    131 {
    132     FILE *src_stream = stdin;
     82    FILE *src_stream;
    13383    char *outname = NULL;
    13484    char *line;
     
    13888    argv += optind;
    13989
    140     if (argv[0])
    141         src_stream = xfopen(argv[0], "r");
     90    if (!argv[0])
     91        *--argv = (char*)"-";
     92    src_stream = xfopen_stdin(argv[0]);
    14293
    14394    /* Search for the start of the encoding */
    144     while ((line = xmalloc_getline(src_stream)) != NULL) {
    145         void (*decode_fn_ptr)(FILE * src, FILE * dst);
     95    while ((line = xmalloc_fgetline(src_stream)) != NULL) {
     96        void FAST_FUNC (*decode_fn_ptr)(FILE *src, FILE *dst, int flags);
    14697        char *line_ptr;
    14798        FILE *dst_stream;
     
    160111
    161112        /* begin line found. decode and exit */
    162         mode = strtoul(line_ptr, NULL, 8);
     113        mode = bb_strtou(line_ptr, NULL, 8);
    163114        if (outname == NULL) {
    164115            outname = strchr(line_ptr, ' ');
     
    170121        dst_stream = stdout;
    171122        if (NOT_LONE_DASH(outname)) {
    172             dst_stream = xfopen(outname, "w");
    173             chmod(outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO));
     123            dst_stream = xfopen_for_write(outname);
     124            fchmod(fileno(dst_stream), mode & (S_IRWXU | S_IRWXG | S_IRWXO));
    174125        }
    175126        free(line);
    176         decode_fn_ptr(src_stream, dst_stream);
     127        decode_fn_ptr(src_stream, dst_stream, /*flags:*/ BASE64_FLAG_UU_STOP + BASE64_FLAG_NO_STOP_CHAR);
    177128        /* fclose_if_not_stdin(src_stream); - redundant */
    178129        return EXIT_SUCCESS;
     
    180131    bb_error_msg_and_die("no 'begin' line");
    181132}
     133#endif
     134
     135//applet:IF_BASE64(APPLET(base64, _BB_DIR_BIN, _BB_SUID_DROP))
     136
     137//kbuild:lib-$(CONFIG_BASE64) += uudecode.o
     138
     139//config:config BASE64
     140//config:   bool "base64"
     141//config:   default y
     142//config:   help
     143//config:     Base64 encode and decode
     144
     145//usage:#define base64_trivial_usage
     146//usage:    "[-d] [FILE]"
     147//usage:#define base64_full_usage "\n\n"
     148//usage:       "Base64 encode or decode FILE to standard output"
     149//usage:     "\nOptions:"
     150//usage:     "\n    -d  Decode data"
     151////usage:     "\n  -w COL  Wrap lines at COL (default 76, 0 disables)"
     152////usage:     "\n  -i  When decoding, ignore non-alphabet characters"
     153
     154#if ENABLE_BASE64
     155int base64_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     156int base64_main(int argc UNUSED_PARAM, char **argv)
     157{
     158    FILE *src_stream;
     159    unsigned opts;
     160
     161    opt_complementary = "?1"; /* 1 argument max */
     162    opts = getopt32(argv, "d");
     163    argv += optind;
     164
     165    if (!argv[0])
     166        *--argv = (char*)"-";
     167    src_stream = xfopen_stdin(argv[0]);
     168    if (opts) {
     169        read_base64(src_stream, stdout, /*flags:*/ (char)EOF);
     170    } else {
     171        enum {
     172            SRC_BUF_SIZE = 76/4*3,  /* This *MUST* be a multiple of 3 */
     173            DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
     174        };
     175        char src_buf[SRC_BUF_SIZE];
     176        char dst_buf[DST_BUF_SIZE + 1];
     177        int src_fd = fileno(src_stream);
     178        while (1) {
     179            size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE);
     180            if (!size)
     181                break;
     182            if ((ssize_t)size < 0)
     183                bb_perror_msg_and_die(bb_msg_read_error);
     184            /* Encode the buffer we just read in */
     185            bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
     186            xwrite(STDOUT_FILENO, dst_buf, 4 * ((size + 2) / 3));
     187            bb_putchar('\n');
     188            fflush(stdout);
     189        }
     190    }
     191
     192    fflush_stdout_and_exit(EXIT_SUCCESS);
     193}
     194#endif
    182195
    183196/* Test script.
  • branches/2.2.9/mindi-busybox/coreutils/uuencode.c

    r1765 r2725  
    66 *  Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
     
    1212
    1313enum {
    14     SRC_BUF_SIZE = 45,  /* This *MUST* be a multiple of 3 */
     14    SRC_BUF_SIZE = 15*3,  /* This *MUST* be a multiple of 3 */
    1515    DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
    1616};
    1717
    18 int uuencode_main(int argc, char **argv);
    19 int uuencode_main(int argc, char **argv)
     18int uuencode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     19int uuencode_main(int argc UNUSED_PARAM, char **argv)
    2020{
    2121    struct stat stat_buf;
     
    3333    }
    3434    argv += optind;
    35     if (argc == optind + 2) {
    36         src_fd = xopen(*argv, O_RDONLY);
     35    if (argv[1]) {
     36        src_fd = xopen(argv[0], O_RDONLY);
    3737        fstat(src_fd, &stat_buf);
    3838        mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
     
    4949        /* Encode the buffer we just read in */
    5050        bb_uuencode(dst_buf, src_buf, size, tbl);
    51         putchar('\n');
     51        bb_putchar('\n');
    5252        if (tbl == bb_uuenc_tbl_std) {
    53             putchar(tbl[size]);
     53            bb_putchar(tbl[size]);
    5454        }
    5555        fflush(stdout);
  • branches/2.2.9/mindi-busybox/coreutils/wc.c

    r1765 r2725  
    55 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
    8  */
    9 
    10 /* BB_AUDIT SUSv3 _NOT_ compliant -- option -m is not currently supported. */
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
     8 */
     9
     10/* BB_AUDIT SUSv3 compliant. */
    1111/* http://www.opengroup.org/onlinepubs/007904975/utilities/wc.html */
    1212
     
    2020 *  4) isprint() wasn't considered when word counting.
    2121 *
    22  * TODO:
    23  *
    24  * When locale support is enabled, count multibyte chars in the '-m' case.
    25  *
    2622 * NOTES:
    2723 *
     
    4137 * for which 'wc -c' should output '0'.
    4238 */
    43 
    4439#include "libbb.h"
    45 
    46 #if ENABLE_LOCALE_SUPPORT
    47 #define isspace_given_isprint(c) isspace(c)
     40#include "unicode.h"
     41
     42#if !ENABLE_LOCALE_SUPPORT
     43# undef isprint
     44# undef isspace
     45# define isprint(c) ((unsigned)((c) - 0x20) <= (0x7e - 0x20))
     46# define isspace(c) ((c) == ' ')
     47#endif
     48
     49#if ENABLE_FEATURE_WC_LARGE
     50# define COUNT_T unsigned long long
     51# define COUNT_FMT "llu"
    4852#else
    49 #undef isspace
    50 #undef isprint
    51 #define isspace(c) ((((c) == ' ') || (((unsigned int)((c) - 9)) <= (13 - 9))))
    52 #define isprint(c) (((unsigned int)((c) - 0x20)) <= (0x7e - 0x20))
    53 #define isspace_given_isprint(c) ((c) == ' ')
     53# define COUNT_T unsigned
     54# define COUNT_FMT "u"
    5455#endif
    5556
    56 #if ENABLE_FEATURE_WC_LARGE
    57 #define COUNT_T unsigned long long
    58 #define COUNT_FMT "llu"
    59 #else
    60 #define COUNT_T unsigned
    61 #define COUNT_FMT "u"
    62 #endif
    63 
     57/* We support -m even when UNICODE_SUPPORT is off,
     58 * we just don't advertise it in help text,
     59 * since it is the same as -c in this case.
     60 */
     61
     62//usage:#define wc_trivial_usage
     63//usage:       "[-c"IF_UNICODE_SUPPORT("m")"lwL] [FILE]..."
     64//usage:
     65//usage:#define wc_full_usage "\n\n"
     66//usage:       "Count lines, words, and bytes for each FILE (or stdin)\n"
     67//usage:     "\nOptions:"
     68//usage:     "\n    -c  Count bytes"
     69//usage:    IF_UNICODE_SUPPORT(
     70//usage:     "\n    -m  Count characters"
     71//usage:    )
     72//usage:     "\n    -l  Count newlines"
     73//usage:     "\n    -w  Count words"
     74//usage:     "\n    -L  Print longest line length"
     75//usage:
     76//usage:#define wc_example_usage
     77//usage:       "$ wc /etc/passwd\n"
     78//usage:       "     31      46    1365 /etc/passwd\n"
     79
     80/* Order is important if we want to be compatible with
     81 * column order in "wc -cmlwL" output:
     82 */
    6483enum {
    65     WC_LINES    = 0,
    66     WC_WORDS    = 1,
    67     WC_CHARS    = 2,
    68     WC_LENGTH   = 3
     84    WC_LINES    = 0, /* -l */
     85    WC_WORDS    = 1, /* -w */
     86    WC_UNICHARS = 2, /* -m */
     87    WC_BYTES    = 3, /* -c */
     88    WC_LENGTH   = 4, /* -L */
     89    NUM_WCS     = 5,
    6990};
    7091
    71 int wc_main(int argc, char **argv);
    72 int wc_main(int argc, char **argv)
     92int wc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     93int wc_main(int argc UNUSED_PARAM, char **argv)
    7394{
    74     FILE *fp;
    75     const char *s, *arg;
    76     const char *start_fmt = "%9"COUNT_FMT;
     95    const char *arg;
     96    const char *start_fmt = " %9"COUNT_FMT + 1;
    7797    const char *fname_fmt = " %s\n";
    7898    COUNT_T *pcounts;
    79     COUNT_T counts[4];
    80     COUNT_T totals[4];
    81     unsigned linepos;
    82     unsigned u;
    83     int num_files = 0;
    84     int c;
     99    COUNT_T counts[NUM_WCS];
     100    COUNT_T totals[NUM_WCS];
     101    int num_files;
    85102    smallint status = EXIT_SUCCESS;
    86     smallint in_word;
    87103    unsigned print_type;
    88104
    89     print_type = getopt32(argv, "lwcL");
     105    init_unicode();
     106
     107    print_type = getopt32(argv, "lwmcL");
    90108
    91109    if (print_type == 0) {
    92         print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS);
     110        print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_BYTES);
    93111    }
    94112
     
    97115        *--argv = (char *) bb_msg_standard_input;
    98116        fname_fmt = "\n";
     117    }
     118    if (!argv[1]) { /* zero or one filename? */
    99119        if (!((print_type-1) & print_type)) /* exactly one option? */
    100120            start_fmt = "%"COUNT_FMT;
     
    105125    pcounts = counts;
    106126
    107     while ((arg = *argv++) != 0) {
     127    num_files = 0;
     128    while ((arg = *argv++) != NULL) {
     129        FILE *fp;
     130        const char *s;
     131        unsigned u;
     132        unsigned linepos;
     133        smallint in_word;
     134
    108135        ++num_files;
    109136        fp = fopen_or_warn_stdin(arg);
     
    117144        in_word = 0;
    118145
    119         do {
     146        while (1) {
     147            int c;
    120148            /* Our -w doesn't match GNU wc exactly... oh well */
    121149
    122             ++counts[WC_CHARS];
    123150            c = getc(fp);
    124             if (isprint(c)) {
     151            if (c == EOF) {
     152                if (ferror(fp)) {
     153                    bb_simple_perror_msg(arg);
     154                    status = EXIT_FAILURE;
     155                }
     156                goto DO_EOF;  /* Treat an EOF as '\r'. */
     157            }
     158
     159            /* Cater for -c and -m */
     160            ++counts[WC_BYTES];
     161            if (unicode_status != UNICODE_ON /* every byte is a new char */
     162             || (c & 0xc0) != 0x80 /* it isn't a 2nd+ byte of a Unicode char */
     163            ) {
     164                ++counts[WC_UNICHARS];
     165            }
     166
     167            if (isprint_asciionly(c)) { /* FIXME: not unicode-aware */
    125168                ++linepos;
    126                 if (!isspace_given_isprint(c)) {
     169                if (!isspace(c)) {
    127170                    in_word = 1;
    128171                    continue;
    129172                }
    130             } else if (((unsigned int)(c - 9)) <= 4) {
     173            } else if ((unsigned)(c - 9) <= 4) {
    131174                /* \t  9
    132175                 * \n 10
     
    137180                if (c == '\t') {
    138181                    linepos = (linepos | 7) + 1;
    139                 } else {            /* '\n', '\r', '\f', or '\v' */
    140                 DO_EOF:
     182                } else {  /* '\n', '\r', '\f', or '\v' */
     183 DO_EOF:
    141184                    if (linepos > counts[WC_LENGTH]) {
    142185                        counts[WC_LENGTH] = linepos;
     
    149192                    }
    150193                }
    151             } else if (c == EOF) {
    152                 if (ferror(fp)) {
    153                     bb_perror_msg("%s", arg);
    154                     status = EXIT_FAILURE;
    155                 }
    156                 --counts[WC_CHARS];
    157                 goto DO_EOF;        /* Treat an EOF as '\r'. */
    158194            } else {
    159195                continue;
     
    165201                break;
    166202            }
    167         } while (1);
     203        }
     204
     205        fclose_if_not_stdin(fp);
    168206
    169207        if (totals[WC_LENGTH] < counts[WC_LENGTH]) {
     
    172210        totals[WC_LENGTH] -= counts[WC_LENGTH];
    173211
    174         fclose_if_not_stdin(fp);
    175 
    176     OUTPUT:
     212 OUTPUT:
    177213        /* coreutils wc tries hard to print pretty columns
    178          * (saves results for all files, find max col len etc...)
     214         * (saves results for all files, finds max col len etc...)
    179215         * we won't try that hard, it will bloat us too much */
    180216        s = start_fmt;
     
    186222            }
    187223            totals[u] += pcounts[u];
    188         } while (++u < 4);
     224        } while (++u < NUM_WCS);
    189225        printf(fname_fmt, arg);
    190226    }
     
    195231     * irrelavent since we no longer need it. */
    196232    if (num_files > 1) {
    197         num_files = 0;              /* Make sure we don't get here again. */
     233        num_files = 0;  /* Make sure we don't get here again. */
    198234        arg = "total";
    199235        pcounts = totals;
  • branches/2.2.9/mindi-busybox/coreutils/who.c

    r1765 r2725  
    1313 * Copyright (c) 2002 AYR Networks, Inc.
    1414 *
    15  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     15 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1616 *
    1717 *----------------------------------------------------------------------
    1818 */
     19/* BB_AUDIT SUSv3 _NOT_ compliant -- missing options -b, -d, -l, -m, -p, -q, -r, -s, -t, -T, -u; Missing argument 'file'.  */
    1920
    2021#include "libbb.h"
    2122#include <utmp.h>
    22 #include <time.h>
    2323
    2424static void idle_string(char *str6, time_t t)
     
    4040}
    4141
    42 int who_main(int argc, char **argv);
    43 int who_main(int argc, char **argv)
     42int who_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     43int who_main(int argc UNUSED_PARAM, char **argv)
    4444{
    45     char str6[6];
    4645    struct utmp *ut;
    47     struct stat st;
    48     char *name;
     46    unsigned opt;
    4947
    50     if (argc > 1) {
    51         bb_show_usage();
    52     }
     48    opt_complementary = "=0";
     49    opt = getopt32(argv, "aH");
     50    if (opt & 2) // -H
     51        printf("USER\t\tTTY\t\tIDLE\tTIME\t\t HOST\n");
    5352
    5453    setutent();
    55     printf("USER       TTY      IDLE      TIME           HOST\n");
    5654    while ((ut = getutent()) != NULL) {
    57         if (ut->ut_user[0] && ut->ut_type == USER_PROCESS) {
    58             time_t thyme = ut->ut_tv.tv_sec;
     55        if (ut->ut_user[0]
     56         && ((opt & 1) || ut->ut_type == USER_PROCESS)
     57        ) {
     58            char str6[6];
     59            char name[sizeof("/dev/") + sizeof(ut->ut_line) + 1];
     60            struct stat st;
     61            time_t seconds;
    5962
    60             /* ut->ut_line is device name of tty - "/dev/" */
    61             name = concat_path_file("/dev", ut->ut_line);
    6263            str6[0] = '?';
    6364            str6[1] = '\0';
     65            strcpy(name, "/dev/");
     66            safe_strncpy(ut->ut_line[0] == '/' ? name : name + sizeof("/dev/")-1,
     67                ut->ut_line,
     68                sizeof(ut->ut_line)+1
     69            );
    6470            if (stat(name, &st) == 0)
    6571                idle_string(str6, st.st_atime);
    66             printf("%-10s %-8s %-9s %-14.14s %s\n",
    67                     ut->ut_user, ut->ut_line, str6,
    68                     ctime(&thyme) + 4, ut->ut_host);
    69             if (ENABLE_FEATURE_CLEAN_UP)
    70                 free(name);
     72            /* manpages say ut_tv.tv_sec *is* time_t,
     73             * but some systems have it wrong */
     74            seconds = ut->ut_tv.tv_sec;
     75            /* How wide time field can be?
     76             * "Nov 10 19:33:20": 15 chars
     77             * "2010-11-10 19:33": 16 chars
     78             */
     79            printf("%-15.*s %-15.*s %-7s %-16.16s %.*s\n",
     80                    (int)sizeof(ut->ut_user), ut->ut_user,
     81                    (int)sizeof(ut->ut_line), ut->ut_line,
     82                    str6,
     83                    ctime(&seconds) + 4,
     84                    (int)sizeof(ut->ut_host), ut->ut_host
     85            );
    7186        }
    7287    }
    7388    if (ENABLE_FEATURE_CLEAN_UP)
    7489        endutent();
    75     return 0;
     90    return EXIT_SUCCESS;
    7691}
  • branches/2.2.9/mindi-busybox/coreutils/whoami.c

    r1765 r2725  
    55 * Copyright (C) 2000  Edward Betts <edward@debian.org>.
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1414/* This is a NOFORK applet. Be very careful! */
    1515
    16 int whoami_main(int argc, char **argv);
    17 int whoami_main(int argc, char **argv)
     16int whoami_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     17int whoami_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
    1818{
    19     if (argc > 1)
     19    if (argv[1])
    2020        bb_show_usage();
    2121
    2222    /* Will complain and die if username not found */
    23     puts(bb_getpwuid(NULL, -1, geteuid()));
     23    puts(xuid2uname(geteuid()));
    2424
    25     return fflush(stdout);
     25    return fflush_all();
    2626}
  • branches/2.2.9/mindi-busybox/coreutils/yes.c

    r1765 r2725  
    55 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    1919/* This is a NOFORK applet. Be very careful! */
    2020
    21 int yes_main(int argc, char **argv);
    22 int yes_main(int argc, char **argv)
     21//usage:#define yes_trivial_usage
     22//usage:       "[STRING]"
     23//usage:#define yes_full_usage "\n\n"
     24//usage:       "Repeatedly output a line with STRING, or 'y'"
     25
     26int yes_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     27int yes_main(int argc UNUSED_PARAM, char **argv)
    2328{
    24     char **first_arg;
     29    char **pp;
    2530
    2631    argv[0] = (char*)"y";
    27     if (argc != 1) {
     32    if (argv[1])
    2833        ++argv;
    29     }
    3034
    31     first_arg = argv;
    3235    do {
     36        pp = argv;
    3337        while (1) {
    34             fputs(*argv, stdout);
    35             if (!*++argv)
     38            fputs(*pp, stdout);
     39            if (!*++pp)
    3640                break;
    3741            putchar(' ');
    3842        }
    39         argv = first_arg;
    4043    } while (putchar('\n') != EOF);
    4144
Note: See TracChangeset for help on using the changeset viewer.