Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/miscutils


Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (10 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
4 added
1 deleted
29 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/3.3/mindi-busybox/miscutils/Config.src

    r3232 r3621  
    133133      manipulate real-time attributes of a process.
    134134      This requires sched_{g,s}etparam support in your libc.
    135 
    136 config CROND
    137     bool "crond"
    138     default y
    139     select FEATURE_SYSLOG
    140     help
    141       Crond is a background daemon that parses individual crontab
    142       files and executes commands on behalf of the users in question.
    143       This is a port of dcron from slackware. It uses files of the
    144       format /var/spool/cron/crontabs/<username> files, for example:
    145           $ cat /var/spool/cron/crontabs/root
    146           # Run daily cron jobs at 4:40 every day:
    147           40 4 * * * /etc/cron/daily > /dev/null 2>&1
    148 
    149 config FEATURE_CROND_D
    150     bool "Support option -d to redirect output to stderr"
    151     depends on CROND
    152     default y
    153     help
    154       -d sets loglevel to 0 (most verbose) and directs all output to stderr.
    155 
    156 config FEATURE_CROND_CALL_SENDMAIL
    157     bool "Report command output via email (using sendmail)"
    158     default y
    159     depends on CROND
    160     help
    161       Command output will be sent to corresponding user via email.
    162 
    163 config FEATURE_CROND_DIR
    164     string "crond spool directory"
    165     default "/var/spool/cron"
    166     depends on CROND || CRONTAB
    167     help
    168       Location of crond spool.
    169135
    170136config CRONTAB
    … …  
    343309      'last' displays a list of the last users that logged into the system.
    344310
    345 choice
    346     prompt "Choose last implementation"
     311config FEATURE_LAST_FANCY
     312    bool "Turn on output of extra information"
     313    default y
    347314    depends on LAST
    348     default FEATURE_LAST_FANCY
    349 
    350 config FEATURE_LAST_SMALL
    351     bool "small"
    352     help
    353       This is a small version of last with just the basic set of
    354       features.
    355 
    356 config FEATURE_LAST_FANCY
    357     bool "huge"
    358315    help
    359316      'last' displays detailed information about the last users that
    360317      logged into the system (mimics sysvinit last). +900 bytes.
    361 endchoice
    362318
    363319config HDPARM
    … …  
    504460      run this applet as a background job.
    505461
    506 config RFKILL
    507     bool "rfkill"
    508     default n  # doesn't build on Ubuntu 9.04
    509     select PLATFORM_LINUX
    510     help
    511       Enable/disable wireless devices.
    512 
    513       rfkill list : list all wireless devices
    514       rfkill list bluetooth : list all bluetooth devices
    515       rfkill list 1 : list device corresponding to the given index
    516       rfkill block|unblock wlan : block/unblock all wlan(wifi) devices
    517 
    518462config RUNLEVEL
    519463    bool "runlevel"
    … …  
    545489      strings prints the printable character sequences for each file
    546490      specified.
    547 
    548 config TASKSET
    549     bool "taskset"
    550     default n  # doesn't build on some non-x86 targets (m68k)
    551     help
    552       Retrieve or set a processes's CPU affinity.
    553       This requires sched_{g,s}etaffinity support in your libc.
    554 
    555 config FEATURE_TASKSET_FANCY
    556     bool "Fancy output"
    557     default y
    558     depends on TASKSET
    559     help
    560       Add code for fancy output. This merely silences a compiler-warning
    561       and adds about 135 Bytes. May be needed for machines with alot
    562       of CPUs.
    563491
    564492config TIME
    … …  
    591519    help
    592520      Prints a CD-ROM volume name.
    593 
    594 config WALL
    595     bool "wall"
    596     default y
    597     depends on FEATURE_UTMP
    598     help
    599       Write a message to all users that are logged in.
    600521
    601522config WATCHDOG
  • branches/3.3/mindi-busybox/miscutils/Kbuild.src

    r2725 r3621  
    1313lib-$(CONFIG_CHAT)        += chat.o
    1414lib-$(CONFIG_CHRT)        += chrt.o
    15 lib-$(CONFIG_CROND)       += crond.o
    1615lib-$(CONFIG_CRONTAB)     += crontab.o
    1716lib-$(CONFIG_DC)          += dc.o
    … …  
    2726lib-$(CONFIG_HDPARM)      += hdparm.o
    2827lib-$(CONFIG_INOTIFYD)    += inotifyd.o
    29 lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o
    30 lib-$(CONFIG_FEATURE_LAST_FANCY)+= last_fancy.o
     28
     29ifeq ($(CONFIG_FEATURE_LAST_FANCY),y)
     30lib-$(CONFIG_FEATURE_LAST_FANCY) += last_fancy.o
     31else
     32lib-$(CONFIG_LAST)        += last.o
     33endif
     34
    3135lib-$(CONFIG_LESS)        += less.o
    3236lib-$(CONFIG_MAKEDEVS)    += makedevs.o
    … …  
    3741lib-$(CONFIG_RAIDAUTORUN) += raidautorun.o
    3842lib-$(CONFIG_READAHEAD)   += readahead.o
    39 lib-$(CONFIG_RFKILL)      += rfkill.o
    4043lib-$(CONFIG_RUNLEVEL)    += runlevel.o
    4144lib-$(CONFIG_RX)          += rx.o
    4245lib-$(CONFIG_SETSID)      += setsid.o
    4346lib-$(CONFIG_STRINGS)     += strings.o
    44 lib-$(CONFIG_TASKSET)     += taskset.o
    4547lib-$(CONFIG_TIME)        += time.o
    4648lib-$(CONFIG_TIMEOUT)     += timeout.o
    4749lib-$(CONFIG_TTYSIZE)     += ttysize.o
    4850lib-$(CONFIG_VOLNAME)     += volname.o
    49 lib-$(CONFIG_WALL)        += wall.o
    5051lib-$(CONFIG_WATCHDOG)    += watchdog.o
  • branches/3.3/mindi-busybox/miscutils/adjtimex.c

    r3232 r3621  
    1515//usage:       "[-q] [-o OFF] [-f FREQ] [-p TCONST] [-t TICK]"
    1616//usage:#define adjtimex_full_usage "\n\n"
    17 //usage:       "Read and optionally set system timebase parameters. See adjtimex(2)\n"
     17//usage:       "Read or set kernel time variables. See adjtimex(2)\n"
    1818//usage:     "\n    -q  Quiet"
    1919//usage:     "\n    -o OFF  Time offset, microseconds"
    2020//usage:     "\n    -f FREQ Frequency adjust, integer kernel units (65536 is 1ppm)"
    21 //usage:     "\n        (positive values make clock run faster)"
    2221//usage:     "\n    -t TICK Microseconds per tick, usually 10000"
     22//usage:     "\n        (positive -t or -f values make clock run faster)"
    2323//usage:     "\n    -p TCONST"
    2424
    … …  
    3030#endif
    3131
    32 static const uint16_t statlist_bit[] = {
     32static const uint16_t statlist_bit[] ALIGN2 = {
    3333    STA_PLL,
    3434    STA_PPSFREQ,
    … …  
    4646    0
    4747};
    48 static const char statlist_name[] =
     48static const char statlist_name[] ALIGN1 =
    4949    "PLL"       "\0"
    5050    "PPSFREQ"   "\0"
    … …  
    6262;
    6363
    64 static const char ret_code_descript[] =
     64static const char ret_code_descript[] ALIGN1 =
    6565    "clock synchronized" "\0"
    6666    "insert leap second" "\0"
    … …  
    112112
    113113    if (!(opt & OPT_quiet)) {
    114         int sep;
     114        const char *sep;
    115115        const char *name;
    116116
    117117        printf(
    118118            "    mode:         %d\n"
    119             "-o  offset:       %ld\n"
    120             "-f  frequency:    %ld\n"
     119            "-o  offset:       %ld us\n"
     120            "-f  freq.adjust:  %ld (65536 = 1ppm)\n"
    121121            "    maxerror:     %ld\n"
    122122            "    esterror:     %ld\n"
    … …  
    126126
    127127        /* representative output of next code fragment:
    128            "PLL | PPSTIME" */
     128         * "PLL | PPSTIME"
     129         */
    129130        name = statlist_name;
    130         sep = 0;
     131        sep = "";
    131132        for (i = 0; statlist_bit[i]; i++) {
    132133            if (txc.status & statlist_bit[i]) {
    133                 if (sep)
    134                     fputs(" | ", stdout);
    135                 fputs(name, stdout);
    136                 sep = 1;
     134                printf("%s%s", sep, name);
     135                sep = " | ";
    137136            }
    138137            name += strlen(name) + 1;
    … …  
    144143        printf(")\n"
    145144            "-p  timeconstant: %ld\n"
    146             "    precision:    %ld\n"
     145            "    precision:    %ld us\n"
    147146            "    tolerance:    %ld\n"
    148             "-t  tick:         %ld\n"
     147            "-t  tick:         %ld us\n"
    149148            "    time.tv_sec:  %ld\n"
    150149            "    time.tv_usec: %ld\n"
  • branches/3.3/mindi-busybox/miscutils/beep.c

    r3232 r3621  
    8989        }
    9090        while (rep) {
    91 //bb_info_msg("rep[%d] freq=%d, length=%d, delay=%d", rep, freq, length, delay);
     91//bb_error_msg("rep[%d] freq=%d, length=%d, delay=%d", rep, freq, length, delay);
    9292            xioctl(speaker, KIOCSOUND, (void*)(uintptr_t)tickrate_div_freq);
    9393            usleep(1000 * length);
  • branches/3.3/mindi-busybox/miscutils/chat.c

    r3232 r3621  
    1818
    1919#include "libbb.h"
     20#include "common_bufsiz.h"
    2021
    2122// default timeout: 45 sec
    … …  
    286287                && (pfd.revents & POLLIN)
    287288            ) {
    288 #define buf bb_common_bufsiz1
    289289                llist_t *l;
    290290                ssize_t delta;
     291#define buf bb_common_bufsiz1
     292                setup_common_bufsiz();
    291293
    292294                // read next char from device
    … …  
    297299                    }
    298300                    // dump device input if ECHO ON
    299                     if (echo > 0) {
     301                    if (echo) {
    300302//                      if (buf[buf_len] < ' ') {
    301303//                          full_write(STDERR_FILENO, "^", 1);
  • branches/3.3/mindi-busybox/miscutils/chrt.c

    r3232 r3621  
    2424#include <sched.h>
    2525#include "libbb.h"
    26 #ifndef _POSIX_PRIORITY_SCHEDULING
    27 #warning your system may be foobared
    28 #endif
    2926
    3027static const struct {
  • branches/3.3/mindi-busybox/miscutils/conspy.c

    r3232 r3621  
    4343
    4444#include "libbb.h"
     45#include "common_bufsiz.h"
    4546#include <sys/kd.h>
    4647
    … …  
    364365{
    365366    char tty_name[sizeof(DEV_TTY "NN")];
    366 #define keybuf bb_common_bufsiz1
    367367    struct termios termbuf;
    368368    unsigned opts;
    … …  
    383383    applet_long_options = getopt_longopts;
    384384#endif
     385#define keybuf bb_common_bufsiz1
     386    setup_common_bufsiz();
     387
    385388    INIT_G();
    386389    strcpy(G.vcsa_name, DEV_VCSA);
    … …  
    514517            // Read the keys pressed
    515518            k = keybuf + G.key_count;
    516             bytes_read = read(G.kbd_fd, k, sizeof(keybuf) - G.key_count);
     519            bytes_read = read(G.kbd_fd, k, COMMON_BUFSIZE - G.key_count);
    517520            if (bytes_read < 0)
    518521                goto abort;
  • branches/3.3/mindi-busybox/miscutils/crond.c

    r3232 r3621  
    11/* vi: set sw=4 ts=4: */
    22/*
    3  * crond -d[#] -c <crondir> -f -b
    4  *
    53 * run as root, but NOT setuid root
    64 *
    … …  
    119 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1210 */
     11//config:config CROND
     12//config:   bool "crond"
     13//config:   default y
     14//config:   select FEATURE_SYSLOG
     15//config:   help
     16//config:     Crond is a background daemon that parses individual crontab
     17//config:     files and executes commands on behalf of the users in question.
     18//config:     This is a port of dcron from slackware. It uses files of the
     19//config:     format /var/spool/cron/crontabs/<username> files, for example:
     20//config:         $ cat /var/spool/cron/crontabs/root
     21//config:         # Run daily cron jobs at 4:40 every day:
     22//config:         40 4 * * * /etc/cron/daily > /dev/null 2>&1
     23//config:
     24//config:config FEATURE_CROND_D
     25//config:   bool "Support option -d to redirect output to stderr"
     26//config:   depends on CROND
     27//config:   default y
     28//config:   help
     29//config:     -d N sets loglevel (0:most verbose) and directs all output to stderr.
     30//config:
     31//config:config FEATURE_CROND_CALL_SENDMAIL
     32//config:   bool "Report command output via email (using sendmail)"
     33//config:   default y
     34//config:   depends on CROND
     35//config:   help
     36//config:     Command output will be sent to corresponding user via email.
     37//config:
     38//config:config FEATURE_CROND_DIR
     39//config:   string "crond spool directory"
     40//config:   default "/var/spool/cron"
     41//config:   depends on CROND || CRONTAB
     42//config:   help
     43//config:     Location of crond spool.
     44
     45//applet:IF_CROND(APPLET(crond, BB_DIR_USR_SBIN, BB_SUID_DROP))
     46
     47//kbuild:lib-$(CONFIG_CROND) += crond.o
    1348
    1449//usage:#define crond_trivial_usage
    … …  
    1853//usage:     "\n    -b  Background (default)"
    1954//usage:     "\n    -S  Log to syslog (default)"
    20 //usage:     "\n    -l  Set log level. 0 is the most verbose, default 8"
     55//usage:     "\n    -l N    Set log level. Most verbose:0, default:8"
    2156//usage:    IF_FEATURE_CROND_D(
    22 //usage:     "\n    -d  Set log level, log to stderr"
     57//usage:     "\n    -d N    Set log level, log to stderr"
    2358//usage:    )
    24 //usage:     "\n    -L  Log to file"
    25 //usage:     "\n    -c  Working dir"
     59//usage:     "\n    -L FILE Log to FILE"
     60//usage:     "\n    -c DIR  Cron dir. Default:"CONFIG_FEATURE_CROND_DIR"/crontabs"
    2661
    2762#include "libbb.h"
     63#include "common_bufsiz.h"
    2864#include <syslog.h>
    2965
    … …  
    3773
    3874
    39 #define TMPDIR          CONFIG_FEATURE_CROND_DIR
     75#define CRON_DIR        CONFIG_FEATURE_CROND_DIR
    4076#define CRONTABS        CONFIG_FEATURE_CROND_DIR "/crontabs"
    4177#ifndef SENDMAIL
    … …  
    70106    char *cl_mailto;                /* whom to mail results, may be NULL */
    71107#endif
     108    char *cl_shell;
    72109    /* ordered by size, not in natural order. makes code smaller: */
    73110    char cl_Dow[7];                 /* 0-6, beginning sunday */
    … …  
    91128    OPT_d = (1 << 6) * ENABLE_FEATURE_CROND_D,
    92129};
    93 #if ENABLE_FEATURE_CROND_D
    94 # define DebugOpt (option_mask32 & OPT_d)
    95 #else
    96 # define DebugOpt 0
    97 #endif
    98 
    99130
    100131struct globals {
    … …  
    107138    char *env_var_user;
    108139    char *env_var_home;
     140    char *env_var_shell;
     141    char *env_var_logname;
    109142#endif
    110143} FIX_ALIASING;
    111 #define G (*(struct globals*)&bb_common_bufsiz1)
     144#define G (*(struct globals*)bb_common_bufsiz1)
    112145#define INIT_G() do { \
     146    setup_common_bufsiz(); \
    113147    G.log_level = 8; \
    114148    G.crontab_dir_name = CRONTABS; \
    115149} while (0)
    116150
    117 
    118 /* 0 is the most verbose, default 8 */
    119 #define LVL5  "\x05"
    120 #define LVL7  "\x07"
    121 #define LVL8  "\x08"
    122 #define WARN9 "\x49"
    123 #define DIE9  "\xc9"
    124 /* level >= 20 is "error" */
    125 #define ERR20 "\x14"
    126 
    127 static void crondlog(const char *ctl, ...) __attribute__ ((format (printf, 1, 2)));
    128 static void crondlog(const char *ctl, ...)
     151/* Log levels:
     152 * 0 is the most verbose, default 8.
     153 * For some reason, in fact only 5, 7 and 8 are used.
     154 */
     155static void crondlog(unsigned level, const char *msg, va_list va)
     156{
     157    if (level >= G.log_level) {
     158        /*
     159         * We are called only for info meesages.
     160         * Warnings/errors use plain bb_[p]error_msg's, which
     161         * need not touch syslog_level
     162         * (they are ok with LOG_ERR default).
     163         */
     164        syslog_level = LOG_INFO;
     165        bb_verror_msg(msg, va, /* strerr: */ NULL);
     166        syslog_level = LOG_ERR;
     167    }
     168}
     169
     170static void log5(const char *msg, ...)
    129171{
    130172    va_list va;
    131     int level = (ctl[0] & 0x1f);
    132 
    133     va_start(va, ctl);
    134     if (level >= (int)G.log_level) {
    135         /* Debug mode: all to (non-redirected) stderr, */
    136         /* Syslog mode: all to syslog (logmode = LOGMODE_SYSLOG), */
    137         if (!DebugOpt && G.log_filename) {
    138             /* Otherwise (log to file): we reopen log file at every write: */
    139             int logfd = open_or_warn(G.log_filename, O_WRONLY | O_CREAT | O_APPEND);
    140             if (logfd >= 0)
    141                 xmove_fd(logfd, STDERR_FILENO);
    142         }
    143         /* When we log to syslog, level > 8 is logged at LOG_ERR
    144          * syslog level, level <= 8 is logged at LOG_INFO. */
    145         if (level > 8) {
    146             bb_verror_msg(ctl + 1, va, /* strerr: */ NULL);
    147         } else {
    148             char *msg = NULL;
    149             vasprintf(&msg, ctl + 1, va);
    150             bb_info_msg("%s: %s", applet_name, msg);
    151             free(msg);
    152         }
    153     }
     173    va_start(va, msg);
     174    crondlog(4, msg, va);
    154175    va_end(va);
    155     if (ctl[0] & 0x80)
    156         exit(20);
    157 }
     176}
     177
     178static void log7(const char *msg, ...)
     179{
     180    va_list va;
     181    va_start(va, msg);
     182    crondlog(7, msg, va);
     183    va_end(va);
     184}
     185
     186static void log8(const char *msg, ...)
     187{
     188    va_list va;
     189    va_start(va, msg);
     190    crondlog(8, msg, va);
     191    va_end(va);
     192}
     193
    158194
    159195static const char DowAry[] ALIGN1 =
    160196    "sun""mon""tue""wed""thu""fri""sat"
    161     /* "Sun""Mon""Tue""Wed""Thu""Fri""Sat" */
    162197;
    163198
    164199static const char MonAry[] ALIGN1 =
    165200    "jan""feb""mar""apr""may""jun""jul""aug""sep""oct""nov""dec"
    166     /* "Jan""Feb""Mar""Apr""May""Jun""Jul""Aug""Sep""Oct""Nov""Dec" */
    167201;
    168202
    … …  
    268302    if (*ptr) {
    269303 err:
    270         crondlog(WARN9 "user %s: parse error at %s", user, base);
     304        bb_error_msg("user %s: parse error at %s", user, base);
    271305        return;
    272306    }
    273307
    274     if (DebugOpt && (G.log_level <= 5)) { /* like LVL5 */
    275         /* can't use crondlog, it inserts '\n' */
     308    /* can't use log5 (it inserts newlines), open-coding it */
     309    if (G.log_level <= 5 && logmode != LOGMODE_SYSLOG) {
    276310        int i;
    277311        for (i = 0; i < modvalue; ++i)
    … …  
    369403    char *mailTo = NULL;
    370404#endif
     405    char *shell = NULL;
    371406
    372407    delete_cronfile(fileName);
    373408
    374409    if (!getpwnam(fileName)) {
    375         crondlog(LVL7 "ignoring file '%s' (no such user)", fileName);
     410        log7("ignoring file '%s' (no such user)", fileName);
    376411        return;
    377412    }
    … …  
    394429            CronLine *line;
    395430
    396             if (!--maxLines)
     431            if (!--maxLines) {
     432                bb_error_msg("user %s: too many lines", fileName);
    397433                break;
     434            }
     435
    398436            n = config_read(parser, tokens, 6, 1, "# \t", PARSE_NORMAL | PARSE_KEEP_COPY);
    399437            if (!n)
    400438                break;
    401439
    402             if (DebugOpt)
    403                 crondlog(LVL5 "user:%s entry:%s", fileName, parser->data);
     440            log5("user:%s entry:%s", fileName, parser->data);
    404441
    405442            /* check if line is setting MAILTO= */
    406             if (0 == strncmp(tokens[0], "MAILTO=", 7)) {
     443            if (is_prefixed_with(tokens[0], "MAILTO=")) {
    407444#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
    408445                free(mailTo);
    … …  
    411448                continue;
    412449            }
     450            if (is_prefixed_with(tokens[0], "SHELL=")) {
     451                free(shell);
     452                shell = xstrdup(&tokens[0][6]);
     453                continue;
     454            }
     455//TODO: handle HOME= too? "man crontab" says:
     456//name = value
     457//
     458//where the spaces around the equal-sign (=) are optional, and any subsequent
     459//non-leading spaces in value will be part of the value assigned to name.
     460//The value string may be placed in quotes (single or double, but matching)
     461//to preserve leading or trailing blanks.
     462//
     463//Several environment variables are set up automatically by the cron(8) daemon.
     464//SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd
     465//line of the crontab's owner. HOME and SHELL may be overridden by settings
     466//in the crontab; LOGNAME may not.
     467
    413468            /* check if a minimum of tokens is specified */
    414469            if (n < 6)
    … …  
    430485            line->cl_mailto = xstrdup(mailTo);
    431486#endif
     487            line->cl_shell = xstrdup(shell);
    432488            /* copy command */
    433489            line->cl_cmd = xstrdup(tokens[5]);
    434             if (DebugOpt) {
    435                 crondlog(LVL5 " command:%s", tokens[5]);
    436             }
    437490            pline = &line->cl_next;
    438491//bb_error_msg("M[%s]F[%s][%s][%s][%s][%s][%s]", mailTo, tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]);
    … …  
    442495        file->cf_next = G.cron_files;
    443496        G.cron_files = file;
    444 
    445         if (maxLines == 0) {
    446             crondlog(WARN9 "user %s: too many lines", fileName);
    447         }
    448497    }
    449498    config_close(parser);
     499#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
     500    free(mailTo);
     501#endif
     502    free(shell);
    450503}
    451504
    … …  
    483536    unlink(CRONUPDATE);
    484537    /* Re-chdir, in case directory was renamed & deleted */
    485     if (chdir(G.crontab_dir_name) < 0) {
    486         crondlog(DIE9 "chdir(%s)", G.crontab_dir_name);
    487     }
     538    xchdir(G.crontab_dir_name);
    488539
    489540    /* Scan directory and add associated users */
    … …  
    492543        struct dirent *den;
    493544
     545        /* xopendir exists, but "can't open '.'" is not informative */
    494546        if (!dir)
    495             crondlog(DIE9 "chdir(%s)", "."); /* exits */
     547            bb_error_msg_and_die("can't open '%s'", G.crontab_dir_name);
    496548        while ((den = readdir(dir)) != NULL) {
    497549            if (strchr(den->d_name, '.') != NULL) {
    … …  
    520572#endif
    521573
    522 static void set_env_vars(struct passwd *pas)
    523 {
     574static void set_env_vars(struct passwd *pas, const char *shell)
     575{
     576    /* POSIX requires crond to set up at least HOME, LOGNAME, PATH, SHELL.
     577     * We assume crond inherited suitable PATH.
     578     */
    524579#if SETENV_LEAKS
     580    safe_setenv(&G.env_var_logname, "LOGNAME", pas->pw_name);
    525581    safe_setenv(&G.env_var_user, "USER", pas->pw_name);
    526582    safe_setenv(&G.env_var_home, "HOME", pas->pw_dir);
    527     /* if we want to set user's shell instead: */
    528     /*safe_setenv(G.env_var_shell, "SHELL", pas->pw_shell);*/
     583    safe_setenv(&G.env_var_shell, "SHELL", shell);
    529584#else
     585    xsetenv("LOGNAME", pas->pw_name);
    530586    xsetenv("USER", pas->pw_name);
    531587    xsetenv("HOME", pas->pw_dir);
    532 #endif
    533     /* currently, we use constant one: */
    534     /*setenv("SHELL", DEFAULT_SHELL, 1); - done earlier */
     588    xsetenv("SHELL", shell);
     589#endif
    535590}
    536591
    … …  
    540595    change_identity(pas); /* - initgroups, setgid, setuid */
    541596    if (chdir(pas->pw_dir) < 0) {
    542         crondlog(WARN9 "chdir(%s)", pas->pw_dir);
    543         if (chdir(TMPDIR) < 0) {
    544             crondlog(DIE9 "chdir(%s)", TMPDIR); /* exits */
    545         }
     597        bb_error_msg("can't change directory to '%s'", pas->pw_dir);
     598        xchdir(CRON_DIR);
    546599    }
    547600}
    … …  
    551604
    552605static pid_t
    553 fork_job(const char *user, int mailFd,
    554         const char *prog,
    555         const char *shell_cmd /* if NULL, we run sendmail */
    556 ) {
     606fork_job(const char *user, int mailFd, CronLine *line, bool run_sendmail)
     607{
    557608    struct passwd *pas;
     609    const char *shell, *prog;
     610    smallint sv_logmode;
    558611    pid_t pid;
    559612
    … …  
    561614    pas = getpwnam(user);
    562615    if (!pas) {
    563         crondlog(WARN9 "can't get uid for %s", user);
     616        bb_error_msg("can't get uid for %s", user);
    564617        goto err;
    565618    }
    566     set_env_vars(pas);
    567 
     619
     620    shell = line->cl_shell ? line->cl_shell : DEFAULT_SHELL;
     621    prog = run_sendmail ? SENDMAIL : shell;
     622
     623    set_env_vars(pas, shell);
     624
     625    sv_logmode = logmode;
    568626    pid = vfork();
    569627    if (pid == 0) {
    570628        /* CHILD */
    571         /* initgroups, setgid, setuid, and chdir to home or TMPDIR */
     629        /* initgroups, setgid, setuid, and chdir to home or CRON_DIR */
    572630        change_user(pas);
    573         if (DebugOpt) {
    574             crondlog(LVL5 "child running %s", prog);
    575         }
     631        log5("child running %s", prog);
    576632        if (mailFd >= 0) {
    577             xmove_fd(mailFd, shell_cmd ? 1 : 0);
     633            xmove_fd(mailFd, run_sendmail ? 0 : 1);
    578634            dup2(1, 2);
    579635        }
    580636        /* crond 3.0pl1-100 puts tasks in separate process groups */
    581637        bb_setpgrp();
    582         execlp(prog, prog, (shell_cmd ? "-c" : SENDMAIL_ARGS), shell_cmd, (char *) NULL);
    583         crondlog(ERR20 "can't execute '%s' for user %s", prog, user);
    584         if (shell_cmd) {
    585             fdprintf(1, "Exec failed: %s -c %s\n", prog, shell_cmd);
    586         }
    587         _exit(EXIT_SUCCESS);
    588     }
     638        if (!run_sendmail)
     639            execlp(prog, prog, "-c", line->cl_cmd, (char *) NULL);
     640        else
     641            execlp(prog, prog, SENDMAIL_ARGS, (char *) NULL);
     642        /*
     643         * I want this error message on stderr too,
     644         * even if other messages go only to syslog:
     645         */
     646        logmode |= LOGMODE_STDIO;
     647        bb_error_msg_and_die("can't execute '%s' for user %s", prog, user);
     648    }
     649    logmode = sv_logmode;
    589650
    590651    if (pid < 0) {
    591         /* FORK FAILED */
    592         crondlog(ERR20 "can't vfork");
     652        bb_perror_msg("vfork");
    593653 err:
    594654        pid = 0;
    … …  
    615675    if (line->cl_mailto) {
    616676        /* Open mail file (owner is root so nobody can screw with it) */
    617         snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, getpid());
     677        snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", CRON_DIR, user, getpid());
    618678        mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600);
    619679
    … …  
    623683            line->cl_empty_mail_size = lseek(mailFd, 0, SEEK_CUR);
    624684        } else {
    625             crondlog(ERR20 "can't create mail file %s for user %s, "
     685            bb_error_msg("can't create mail file %s for user %s, "
    626686                    "discarding output", mailFile, user);
    627687        }
    628688    }
    629689
    630     line->cl_pid = fork_job(user, mailFd, DEFAULT_SHELL, line->cl_cmd);
     690    line->cl_pid = fork_job(user, mailFd, line, /*sendmail?*/ 0);
    631691    if (mailFd >= 0) {
    632692        if (line->cl_pid <= 0) {
    … …  
    634694        } else {
    635695            /* rename mail-file based on pid of process */
    636             char *mailFile2 = xasprintf("%s/cron.%s.%d", TMPDIR, user, (int)line->cl_pid);
     696            char *mailFile2 = xasprintf("%s/cron.%s.%d", CRON_DIR, user, (int)line->cl_pid);
    637697            rename(mailFile, mailFile2); // TODO: xrename?
    638698            free(mailFile2);
    … …  
    666726     * If size has changed and the file is still valid, we send it.
    667727     */
    668     snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, (int)pid);
     728    snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", CRON_DIR, user, (int)pid);
    669729    mailFd = open(mailFile, O_RDONLY);
    670730    unlink(mailFile);
    … …  
    684744    line->cl_empty_mail_size = 0;
    685745    /* if (line->cl_mailto) - always true if cl_empty_mail_size was nonzero */
    686         line->cl_pid = fork_job(user, mailFd, SENDMAIL, NULL);
     746        line->cl_pid = fork_job(user, mailFd, line, /*sendmail?*/ 1);
    687747}
    688748
    … …  
    691751static void start_one_job(const char *user, CronLine *line)
    692752{
     753    const char *shell;
    693754    struct passwd *pas;
    694755    pid_t pid;
    … …  
    696757    pas = getpwnam(user);
    697758    if (!pas) {
    698         crondlog(WARN9 "can't get uid for %s", user);
     759        bb_error_msg("can't get uid for %s", user);
    699760        goto err;
    700761    }
    701762
    702763    /* Prepare things before vfork */
    703     set_env_vars(pas);
     764    shell = line->cl_shell ? line->cl_shell : DEFAULT_SHELL;
     765    set_env_vars(pas, shell);
    704766
    705767    /* Fork as the user in question and run program */
    … …  
    707769    if (pid == 0) {
    708770        /* CHILD */
    709         /* initgroups, setgid, setuid, and chdir to home or TMPDIR */
     771        /* initgroups, setgid, setuid, and chdir to home or CRON_DIR */
    710772        change_user(pas);
    711         if (DebugOpt) {
    712             crondlog(LVL5 "child running %s", DEFAULT_SHELL);
    713         }
     773        log5("child running %s", shell);
    714774        /* crond 3.0pl1-100 puts tasks in separate process groups */
    715775        bb_setpgrp();
    716         execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_cmd, (char *) NULL);
    717         crondlog(ERR20 "can't execute '%s' for user %s", DEFAULT_SHELL, user);
    718         _exit(EXIT_SUCCESS);
     776        execl(shell, shell, "-c", line->cl_cmd, (char *) NULL);
     777        bb_error_msg_and_die("can't execute '%s' for user %s", shell, user);
    719778    }
    720779    if (pid < 0) {
    721         /* FORK FAILED */
    722         crondlog(ERR20 "can't vfork");
     780        bb_perror_msg("vfork");
    723781 err:
    724782        pid = 0;
    … …  
    752810        ptm = localtime(&t);
    753811        for (file = G.cron_files; file; file = file->cf_next) {
    754             if (DebugOpt)
    755                 crondlog(LVL5 "file %s:", file->cf_username);
     812            log5("file %s:", file->cf_username);
    756813            if (file->cf_deleted)
    757814                continue;
    758815            for (line = file->cf_lines; line; line = line->cl_next) {
    759                 if (DebugOpt)
    760                     crondlog(LVL5 " line %s", line->cl_cmd);
     816                log5(" line %s", line->cl_cmd);
    761817                if (line->cl_Mins[ptm->tm_min]
    762818                 && line->cl_Hrs[ptm->tm_hour]
    … …  
    764820                 && line->cl_Mons[ptm->tm_mon]
    765821                ) {
    766                     if (DebugOpt) {
    767                         crondlog(LVL5 " job: %d %s",
     822                    log5(" job: %d %s",
    768823                            (int)line->cl_pid, line->cl_cmd);
    769                     }
    770824                    if (line->cl_pid > 0) {
    771                         crondlog(LVL8 "user %s: process already running: %s",
     825                        log8("user %s: process already running: %s",
    772826                            file->cf_username, line->cl_cmd);
    773827                    } else if (line->cl_pid == 0) {
    … …  
    798852            start_one_job(file->cf_username, line);
    799853            pid = line->cl_pid;
    800             crondlog(LVL8 "USER %s pid %3d cmd %s",
     854            log8("USER %s pid %3d cmd %s",
    801855                file->cf_username, (int)pid, line->cl_cmd);
    802856            if (pid < 0) {
    … …  
    850904}
    851905
     906static void reopen_logfile_to_stderr(void)
     907{
     908    if (G.log_filename) {
     909        int logfd = open_or_warn(G.log_filename, O_WRONLY | O_CREAT | O_APPEND);
     910        if (logfd >= 0)
     911            xmove_fd(logfd, STDERR_FILENO);
     912    }
     913}
     914
    852915int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    853916int crond_main(int argc UNUSED_PARAM, char **argv)
    854917{
    855918    time_t t2;
    856     int rescan;
    857     int sleep_time;
     919    unsigned rescan;
     920    unsigned sleep_time;
    858921    unsigned opts;
    859922
    … …  
    881944    }
    882945
     946    //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
     947
     948    reopen_logfile_to_stderr();
    883949    xchdir(G.crontab_dir_name);
    884     //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
    885     xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */
    886     crondlog(LVL8 "crond (busybox "BB_VER") started, log level %d", G.log_level);
     950    log8("crond (busybox "BB_VER") started, log level %d", G.log_level);
    887951    rescan_crontab_dir();
    888952    write_pidfile(CONFIG_PID_FILE_PATH "/crond.pid");
    … …  
    897961        long dt;
    898962
     963        /* Synchronize to 1 minute, minimum 1 second */
    899964        t1 = t2;
    900 
    901         /* Synchronize to 1 minute, minimum 1 second */
    902         sleep(sleep_time - (time(NULL) % sleep_time) + 1);
    903 
     965        sleep(sleep_time - (time(NULL) % sleep_time));
    904966        t2 = time(NULL);
    905967        dt = (long)t2 - (long)t1;
     968
     969        reopen_logfile_to_stderr();
    906970
    907971        /*
    … …  
    932996        }
    933997        process_cron_update_file();
    934         if (DebugOpt)
    935             crondlog(LVL5 "wakeup dt=%ld", dt);
     998        log5("wakeup dt=%ld", dt);
    936999        if (dt < -60 * 60 || dt > 60 * 60) {
    937             crondlog(WARN9 "time disparity of %ld minutes detected", dt / 60);
     1000            bb_error_msg("time disparity of %ld minutes detected", dt / 60);
    9381001            /* and we do not run any jobs in this case */
    9391002        } else if (dt > 0) {
    … …  
    9411004            flag_starting_jobs(t1, t2);
    9421005            start_jobs();
     1006            sleep_time = 60;
    9431007            if (check_completions() > 0) {
    9441008                /* some jobs are still running */
    9451009                sleep_time = 10;
    946             } else {
    947                 sleep_time = 60;
    9481010            }
    9491011        }
  • branches/3.3/mindi-busybox/miscutils/crontab.c

    r3232 r3621  
    5454    BB_EXECLP(ptr, ptr, file, NULL);
    5555    bb_perror_msg_and_die("can't execute '%s'", ptr);
    56 }
    57 
    58 static int open_as_user(const struct passwd *pas, const char *file)
    59 {
    60     pid_t pid;
    61     char c;
    62 
    63     pid = xvfork();
    64     if (pid) { /* PARENT */
    65         if (wait4pid(pid) == 0) {
    66             /* exitcode 0: child says it can read */
    67             return open(file, O_RDONLY);
    68         }
    69         return -1;
    70     }
    71 
    72     /* CHILD */
    73     /* initgroups, setgid, setuid */
    74     change_identity(pas);
    75     /* We just try to read one byte. If it works, file is readable
    76      * under this user. We signal that by exiting with 0. */
    77     _exit(safe_read(xopen(file, O_RDONLY), &c, 1) < 0);
    7856}
    7957
    … …  
    138116            bb_show_usage();
    139117        if (NOT_LONE_DASH(argv[0])) {
    140             src_fd = open_as_user(pas, argv[0]);
    141             if (src_fd < 0)
    142                 bb_error_msg_and_die("user %s cannot read %s",
    143                         pas->pw_name, argv[0]);
     118            src_fd = xopen_as_uid_gid(argv[0], O_RDONLY, pas->pw_uid, pas->pw_gid);
    144119        }
    145120    }
    … …  
    196171        /*free(tmp_fname);*/
    197172        /*free(new_fname);*/
    198 
    199173    } /* switch */
    200174
  • branches/3.3/mindi-busybox/miscutils/dc.c

    r3232 r3621  
    55
    66#include "libbb.h"
     7#include "common_bufsiz.h"
    78#include <math.h>
    89
    … …  
    4849} FIX_ALIASING;
    4950enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof(double) };
    50 #define G (*(struct globals*)&bb_common_bufsiz1)
     51#define G (*(struct globals*)bb_common_bufsiz1)
    5152#define pointer   (G.pointer   )
    5253#define base      (G.base      )
    5354#define stack     (G.stack     )
    5455#define INIT_G() do { \
     56    setup_common_bufsiz(); \
    5557    base = 10; \
    5658} while (0)
    5759
     60
     61static void check_under(void)
     62{
     63    if (pointer == 0)
     64        bb_error_msg_and_die("stack underflow");
     65}
    5866
    5967static void push(double a)
    … …  
    6674static double pop(void)
    6775{
    68     if (pointer == 0)
    69         bb_error_msg_and_die("stack underflow");
     76    check_under();
    7077    return stack[--pointer];
    7178}
    … …  
    188195static void print_no_pop(void)
    189196{
     197    check_under();
    190198    print_base(stack[pointer-1]);
    191199}
    … …  
    197205
    198206static const struct op operators[] = {
    199     {"+",   add},
    200     {"add", add},
    201     {"-",   sub},
    202     {"sub", sub},
    203     {"*",   mul},
    204     {"mul", mul},
    205     {"/",   divide},
    206     {"div", divide},
    207207#if ENABLE_FEATURE_DC_LIBM
    208208    {"**",  power},
    … …  
    217217    {"eor", eor},
    218218    {"xor", eor},
     219    {"+",   add},
     220    {"add", add},
     221    {"-",   sub},
     222    {"sub", sub},
     223    {"*",   mul},
     224    {"mul", mul},
     225    {"/",   divide},
     226    {"div", divide},
    219227    {"p", print_no_pop},
    220228    {"f", print_stack_no_pop},
    … …  
    222230};
    223231
     232/* Feed the stack machine */
    224233static void stack_machine(const char *argument)
    225234{
    226235    char *end;
    227     double d;
     236    double number;
    228237    const struct op *o;
    229238
    230     d = strtod(argument, &end);
    231     if (end != argument && *end == '\0') {
    232         push(d);
     239 next:
     240    number = strtod(argument, &end);
     241    if (end != argument) {
     242        argument = end;
     243        push(number);
     244        goto next;
     245    }
     246
     247    /* We might have matched a digit, eventually advance the argument */
     248    argument = skip_whitespace(argument);
     249
     250    if (*argument == '\0')
    233251        return;
    234     }
    235252
    236253    o = operators;
    237254    do {
    238         if (strcmp(o->name, argument) == 0) {
     255        char *after_name = is_prefixed_with(argument, o->name);
     256        if (after_name) {
     257            argument = after_name;
    239258            o->function();
    240             return;
     259            goto next;
    241260        }
    242261        o++;
    … …  
    255274        /* take stuff from stdin if no args are given */
    256275        char *line;
    257         char *cursor;
    258         char *token;
    259276        while ((line = xmalloc_fgetline(stdin)) != NULL) {
    260             cursor = line;
    261             while (1) {
    262                 token = skip_whitespace(cursor);
    263                 if (*token == '\0')
    264                     break;
    265                 cursor = skip_non_whitespace(token);
    266                 if (*cursor != '\0')
    267                     *cursor++ = '\0';
    268                 stack_machine(token);
    269             }
     277            stack_machine(line);
    270278            free(line);
    271279        }
    272280    } else {
    273         // why? it breaks "dc -2 2 + p"
    274         //if (argv[0][0] == '-')
    275         //  bb_show_usage();
    276281        do {
    277282            stack_machine(*argv);
  • branches/3.3/mindi-busybox/miscutils/devfsd.c

    r3232 r3621  
    285285/* Busybox stuff */
    286286#if ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG
    287 #define info_logger(p, fmt, args...)                 bb_info_msg(fmt, ## args)
     287#define info_logger(p, fmt, args...)                 bb_error_msg(fmt, ## args)
    288288#define msg_logger(p, fmt, args...)                  bb_error_msg(fmt, ## args)
    289289#define msg_logger_and_die(p, fmt, args...)          bb_error_msg_and_die(fmt, ## args)
    … …  
    10841084    struct passwd *pw_ent;
    10851085    struct group *grp_ent;
    1086     static const char *msg;
     1086    const char *msg;
     1087
     1088    if (isdigit(string[0]) || ((string[0] == '-') && isdigit(string[1])))
     1089        return atoi(string);
     1090
     1091    if (flag == UID && (pw_ent = getpwnam(string)) != NULL)
     1092        return pw_ent->pw_uid;
    10871093
    10881094    if (ENABLE_DEVFSD_VERBOSE)
    10891095        msg = "user";
    10901096
    1091     if (isdigit(string[0]) ||((string[0] == '-') && isdigit(string[1])))
    1092         return atoi(string);
    1093 
    1094     if (flag == UID && (pw_ent = getpwnam(string)) != NULL)
    1095         return pw_ent->pw_uid;
    1096 
    1097     if (flag == GID && (grp_ent = getgrnam(string)) != NULL)
    1098         return grp_ent->gr_gid;
    1099     else if (ENABLE_DEVFSD_VERBOSE)
    1100         msg = "group";
     1097    if (flag == GID) {
     1098        if ((grp_ent = getgrnam(string)) != NULL)
     1099            return grp_ent->gr_gid;
     1100        if (ENABLE_DEVFSD_VERBOSE)
     1101            msg = "group";
     1102    }
    11011103
    11021104    if (ENABLE_DEVFSD_VERBOSE)
    … …  
    11411143static const char *get_variable(const char *variable, void *info)
    11421144{
    1143     static char sbuf[sizeof(int)*3 + 2]; /* sign and NUL */
    11441145    static char *hostname;
    11451146
    11461147    struct get_variable_info *gv_info = info;
    11471148    const char *field_names[] = {
    1148             "hostname", "mntpt", "devpath", "devname",
    1149             "uid", "gid", "mode", hostname, mount_point,
    1150             gv_info->devpath, gv_info->devname, NULL
     1149            "hostname", "mntpt", "devpath", "devname", "uid", "gid", "mode",
     1150            NULL, mount_point, gv_info->devpath, gv_info->devname, NULL
    11511151    };
    11521152    int i;
    … …  
    11541154    if (!hostname)
    11551155        hostname = safe_gethostname();
     1156    field_names[7] = hostname;
     1157
    11561158    /* index_in_str_array returns i>=0  */
    11571159    i = index_in_str_array(field_names, variable);
    … …  
    11631165
    11641166    if (i == 4)
    1165         sprintf(sbuf, "%u", gv_info->info->uid);
    1166     else if (i == 5)
    1167         sprintf(sbuf, "%u", gv_info->info->gid);
    1168     else if (i == 6)
    1169         sprintf(sbuf, "%o", gv_info->info->mode);
    1170     return sbuf;
     1167        return auto_string(xasprintf("%u", gv_info->info->uid));
     1168    if (i == 5)
     1169        return auto_string(xasprintf("%u", gv_info->info->gid));
     1170    /* i == 6 */
     1171    return auto_string(xasprintf("%o", gv_info->info->mode));
    11711172}   /*  End Function get_variable  */
    11721173
    … …  
    14041405    const char *pty1;
    14051406    const char *pty2;
    1406     size_t len;
    14071407    /* 1 to 5  "scsi/" , 6 to 9 "ide/host", 10 sbp/, 11 vcc/, 12 pty/ */
    14081408    static const char *const fmt[] = {
    … …  
    14241424
    14251425    for (trans = translate_table; trans->match != NULL; ++trans) {
    1426         len = strlen(trans->match);
    1427 
    1428         if (strncmp(devname, trans->match, len) == 0) {
     1426        char *after_match = is_prefixed_with(devname, trans->match);
     1427        if (after_match) {
    14291428            if (trans->format == NULL)
    1430                 return devname + len;
    1431             sprintf(buffer, trans->format, devname + len);
     1429                return after_match;
     1430            sprintf(buffer, trans->format, after_match);
    14321431            return buffer;
    14331432        }
  • branches/3.3/mindi-busybox/miscutils/eject.c

    r3232 r3621  
    2626#include <sys/mount.h>
    2727#include "libbb.h"
     28#if ENABLE_FEATURE_EJECT_SCSI
    2829/* Must be after libbb.h: they need size_t */
    29 #include "fix_u32.h"
    30 #include <scsi/sg.h>
    31 #include <scsi/scsi.h>
    32 
    33 /* various defines swiped from linux/cdrom.h */
    34 #define CDROMCLOSETRAY            0x5319  /* pendant of CDROMEJECT  */
    35 #define CDROMEJECT                0x5309  /* Ejects the cdrom media */
    36 #define CDROM_DRIVE_STATUS        0x5326  /* Get tray position, etc. */
    37 /* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
    38 #define CDS_TRAY_OPEN        2
     30# include "fix_u32.h"
     31# include <scsi/sg.h>
     32# include <scsi/scsi.h>
     33#endif
    3934
    4035#define dev_fd 3
    … …  
    4338 * refactored it a bit for busybox (ne-bb@nicoerfurth.de) */
    4439
     40#if ENABLE_FEATURE_EJECT_SCSI
    4541static void eject_scsi(const char *dev)
    4642{
    47     static const char sg_commands[3][6] = {
     43    static const char sg_commands[3][6] ALIGN1 = {
    4844        { ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0 },
    4945        { START_STOP, 0, 0, 0, 1, 0 },
    … …  
    7773    ioctl(dev_fd, BLKRRPART);
    7874}
     75#else
     76# define eject_scsi(dev) ((void)0)
     77#endif
     78
     79/* various defines swiped from linux/cdrom.h */
     80#define CDROMCLOSETRAY            0x5319  /* pendant of CDROMEJECT  */
     81#define CDROMEJECT                0x5309  /* Ejects the cdrom media */
     82#define CDROM_DRIVE_STATUS        0x5326  /* Get tray position, etc. */
     83/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
     84#define CDS_TRAY_OPEN        2
    7985
    8086#define FLAG_CLOSE  1
  • branches/3.3/mindi-busybox/miscutils/fbsplash.c

    r3232 r3621  
    3535
    3636#include "libbb.h"
     37#include "common_bufsiz.h"
    3738#include <linux/fb.h>
    3839
    … …  
    151152    // map the device in memory
    152153    G.addr = mmap(NULL,
    153             G.scr_var.yres * G.scr_fix.line_length,
     154            (G.scr_var.yres_virtual ?: G.scr_var.yres) * G.scr_fix.line_length,
    154155            PROT_WRITE, MAP_SHARED, fbfd, 0);
    155156    if (G.addr == MAP_FAILED)
    … …  
    354355        theme_file = stdin;
    355356    } else {
    356         int fd = open_zipped(G.image_filename);
     357        int fd = open_zipped(G.image_filename, /*fail_if_not_compressed:*/ 0);
    357358        if (fd < 0)
    358359            bb_simple_perror_msg_and_die(G.image_filename);
    … …  
    374375     */
    375376#define concat_buf bb_common_bufsiz1
     377    setup_common_bufsiz();
     378
    376379    read_ptr = concat_buf;
    377380    while (1) {
    378381        int w, h, max_color_val;
    379         int rem = concat_buf + sizeof(concat_buf) - read_ptr;
     382        int rem = concat_buf + COMMON_BUFSIZE - read_ptr;
    380383        if (rem < 2
    381384         || fgets(read_ptr, rem, theme_file) == NULL
    … …  
    517520    // already in the pipe
    518521    while ((num_buf = xmalloc_fgetline(fp)) != NULL) {
    519         if (strncmp(num_buf, "exit", 4) == 0) {
     522        if (is_prefixed_with(num_buf, "exit")) {
    520523            DEBUG_MESSAGE("exit");
    521524            break;
  • branches/3.3/mindi-busybox/miscutils/flash_eraseall.c

    r3232 r3621  
    1212
    1313//usage:#define flash_eraseall_trivial_usage
    14 //usage:       "[-jq] MTD_DEVICE"
     14//usage:       "[-jNq] MTD_DEVICE"
    1515//usage:#define flash_eraseall_full_usage "\n\n"
    1616//usage:       "Erase an MTD device\n"
    1717//usage:     "\n    -j  Format the device for jffs2"
     18//usage:     "\n    -N  Don't skip bad blocks"
    1819//usage:     "\n    -q  Don't display progress messages"
    1920
    … …  
    2324
    2425#define OPTION_J  (1 << 0)
    25 #define OPTION_Q  (1 << 1)
    26 #define IS_NAND   (1 << 2)
    27 #define BBTEST    (1 << 3)
     26#define OPTION_N  (1 << 1)
     27#define OPTION_Q  (1 << 2)
     28#define IS_NAND   (1 << 3)
    2829
    2930/* mtd/jffs2-user.h used to have this atrocity:
    … …  
    7273
    7374    opt_complementary = "=1";
    74     flags = BBTEST | getopt32(argv, "jq");
     75    flags = getopt32(argv, "jNq");
    7576
    7677    mtd_name = argv[optind];
    … …  
    140141    for (erase.start = 0; erase.start < meminfo.size;
    141142         erase.start += meminfo.erasesize) {
    142         if (flags & BBTEST) {
     143        if (!(flags & OPTION_N)) {
    143144            int ret;
    144145            loff_t offset = erase.start;
    … …  
    147148            if (ret > 0) {
    148149                if (!(flags & OPTION_Q))
    149                     bb_info_msg("\nSkipping bad block at 0x%08x", erase.start);
     150                    printf("\nSkipping bad block at 0x%08x\n", erase.start);
    150151                continue;
    151152            }
    … …  
    155156                 */
    156157                if (errno == EOPNOTSUPP) {
    157                     flags &= ~BBTEST;
     158                    flags |= OPTION_N;
    158159                    if (flags & IS_NAND)
    159160                        bb_error_msg_and_die("bad block check not available");
  • branches/3.3/mindi-busybox/miscutils/flashcp.c

    r3232 r3621  
    1717#include <mtd/mtd-user.h>
    1818
     19/* If 1, simulates "flashing" by writing to existing regular file */
    1920#define MTD_DEBUG 0
    2021
    2122#define OPT_v (1 << 0)
    2223
    23 #define BUFSIZE (8 * 1024)
     24#define BUFSIZE (4 * 1024)
    2425
    2526static void progress(int mode, uoff_t count, uoff_t total)
    … …  
    3334        percent = (unsigned) (percent / total);
    3435    printf("\r%s: %"OFF_FMT"u/%"OFF_FMT"u (%u%%) ",
    35         (mode == 0) ? "Erasing block" : ((mode == 1) ? "Writing kb" : "Verifying kb"),
     36        (mode < 0) ? "Erasing block" : ((mode == 0) ? "Writing kb" : "Verifying kb"),
    3637        count, total, (unsigned)percent);
    3738    fflush_all();
    … …  
    9899    e.start = 0;
    99100    for (i = 1; i <= erase_count; i++) {
    100         progress(0, i, erase_count);
    101         errno = 0;
     101        progress(-1, i, erase_count);
    102102#if !MTD_DEBUG
    103103        if (ioctl(fd_d, MEMERASE, &e) < 0) {
    … …  
    114114    /* doing this outer loop gives significantly smaller code
    115115     * than doing two separate loops for writing and verifying */
    116     for (i = 1; i <= 2; i++) {
     116    for (i = 0; i <= 1; i++) {
    117117        uoff_t done;
    118118        unsigned count;
    … …  
    123123        count = BUFSIZE;
    124124        while (1) {
    125             uoff_t rem = statb.st_size - done;
     125            uoff_t rem;
     126
     127            progress(i, done / 1024, (uoff_t)statb.st_size / 1024);
     128            rem = statb.st_size - done;
    126129            if (rem == 0)
    127130                break;
    128131            if (rem < BUFSIZE)
    129132                count = rem;
    130             progress(i, done / 1024, (uoff_t)statb.st_size / 1024);
    131133            xread(fd_f, buf, count);
    132             if (i == 1) {
     134            if (i == 0) {
    133135                int ret;
     136                if (count < BUFSIZE)
     137                    memset((char*)buf + count, 0, BUFSIZE - count);
    134138                errno = 0;
    135                 ret = full_write(fd_d, buf, count);
    136                 if (ret != count) {
     139                ret = full_write(fd_d, buf, BUFSIZE);
     140                if (ret != BUFSIZE) {
    137141                    bb_perror_msg_and_die("write error at 0x%"OFF_FMT"x on %s, "
    138142                        "write returned %d",
    139143                        done, devicename, ret);
    140144                }
    141             } else { /* i == 2 */
     145            } else { /* i == 1 */
    142146                xread(fd_d, buf2, count);
    143                 if (memcmp(buf, buf2, count)) {
     147                if (memcmp(buf, buf2, count) != 0) {
    144148                    bb_error_msg_and_die("verification mismatch at 0x%"OFF_FMT"x", done);
    145149                }
  • branches/3.3/mindi-busybox/miscutils/hdparm.c

    r3232 r3621  
    6464
    6565#include "libbb.h"
     66#include "common_bufsiz.h"
    6667/* must be _after_ libbb.h: */
    6768#include <linux/hdreg.h>
    … …  
    368369#endif
    369370} FIX_ALIASING;
    370 #define G (*(struct globals*)&bb_common_bufsiz1)
    371 struct BUG_G_too_big {
    372     char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
    373 };
     371#define G (*(struct globals*)bb_common_bufsiz1)
    374372#define get_identity       (G.get_identity           )
    375373#define get_geom           (G.get_geom               )
    … …  
    434432#define hwif_ctrl          (G.hwif_ctrl              )
    435433#define hwif_irq           (G.hwif_irq               )
    436 #define INIT_G() do { } while (0)
     434#define INIT_G() do { \
     435    setup_common_bufsiz(); \
     436    BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
     437} while (0)
    437438
    438439
    … …  
    466467{
    467468    if (get_arg) {
    468         printf(" setting %s to %ld", s, arg);
     469        printf(" setting %s to %lu", s, arg);
    469470        on_off(arg);
    470471    }
    … …  
    473474static void print_value_on_off(const char *str, unsigned long argp)
    474475{
    475     printf(" %s\t= %2ld", str, argp);
     476    printf(" %s\t= %2lu", str, argp);
    476477    on_off(argp != 0);
    477478}
    … …  
    764765        like_std = 5;
    765766        if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL))
    766             printf("powers-up in standby; SET FEATURES subcmd spins-up.\n");
     767            puts("powers-up in standby; SET FEATURES subcmd spins-up.");
    767768        if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE))
    768             printf("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n\n");
     769            puts("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n");
    769770    }
    770771
    … …  
    876877        min_std = like_std > 4 ? like_std - 3 : 1;
    877878
    878     printf("Configuration:\n");
     879    puts("Configuration:");
    879880    /* more info from the general configuration word */
    880881    if ((eqpt != CDROM) && (like_std == 1)) {
    … …  
    910911        bbbig = 0;
    911912        if ((ll > 0x00FBFC10) && (!val[LCYLS]))
    912             printf("\tCHS addressing not supported\n");
     913            puts("\tCHS addressing not supported");
    913914        else {
    914915            jj = val[WHATS_VALID] & OK_W54_58;
    … …  
    981982            (val[CAPAB_0] & IORDY_OFF) ? "" :"not");
    982983    } else
    983         printf("no IORDY\n");
     984        puts("no IORDY");
    984985
    985986    if ((like_std == 1) && val[BUF_TYPE]) {
    … …  
    10131014        printf("\tR/W multiple sector transfer: ");
    10141015        if ((like_std < 3) && !(val[SECTOR_XFER_MAX] & SECTOR_XFER))
    1015             printf("not supported\n");
     1016            puts("not supported");
    10161017        else {
    10171018            printf("Max = %u\tCurrent = ", val[SECTOR_XFER_MAX] & SECTOR_XFER);
    … …  
    10191020                printf("%u\n", val[SECTOR_XFER_CUR] & SECTOR_XFER);
    10201021            else
    1021                 printf("?\n");
     1022                puts("?");
    10221023        }
    10231024        if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008)) {
    … …  
    10411042        /* ATAPI */
    10421043        if (eqpt != CDROM && (val[CAPAB_0] & SWRST_REQ))
    1043             printf("\tATA sw reset required\n");
     1044            puts("\tATA sw reset required");
    10441045
    10451046        if (val[PKT_REL] || val[SVC_NBSY]) {
    … …  
    10571058    printf("\tDMA: ");
    10581059    if (!(val[CAPAB_0] & DMA_SUP))
    1059         printf("not supported\n");
     1060        puts("not supported");
    10601061    else {
    10611062        if (val[DMA_MODE] && !val[SINGLE_DMA] && !val[MULTI_DMA])
    … …  
    10801081
    10811082        if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP))
    1082             printf("\t\tInterleaved DMA support\n");
     1083            puts("\t\tInterleaved DMA support");
    10831084
    10841085        if ((val[WHATS_VALID] & OK_W64_70)
    … …  
    11221123
    11231124    if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) {
    1124         printf("Commands/features:\n"
    1125             "\tEnabled\tSupported:\n");
     1125        puts("Commands/features:\n"
     1126            "\tEnabled\tSupported:");
    11261127        jj = val[CMDS_SUPP_0];
    11271128        kk = val[CMDS_EN_0];
    … …  
    11511152     && (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME])
    11521153    ) {
    1153         printf("Security:\n");
     1154        puts("Security:");
    11541155        if (val[PSWD_CODE] && (val[PSWD_CODE] != NOVAL_1))
    11551156            printf("\tMaster password revision code = %u\n", val[PSWD_CODE]);
    … …  
    13671368    }
    13681369#endif /* __NEW_HD_DRIVE_ID */
    1369     printf("\n\n * current active mode\n\n");
     1370    puts("\n\n * current active mode\n");
    13701371}
    13711372#endif
    … …  
    15081509        on_off(0);
    15091510    else if (value == BUSSTATE_TRISTATE)
    1510         printf(" (tristate)\n");
     1511        puts(" (tristate)");
    15111512    else
    1512         printf(" (unknown: %d)\n", value);
     1513        printf(" (unknown: %u)\n", value);
    15131514}
    15141515#endif
    … …  
    15321533    if (standby == 254)
    15331534        printf("reserved");
    1534     printf(")\n");
     1535    puts(")");
    15351536}
    15361537
    … …  
    15831584    else
    15841585        printf("unknown");
    1585     printf(")\n");
     1586    puts(")");
    15861587}
    15871588#endif /* HDIO_DRIVE_CMD */
    … …  
    15901591{
    15911592    if (flag)
    1592         printf(" setting %s to %ld\n", s, value);
     1593        printf(" setting %s to %lu\n", s, value);
    15931594}
    15941595
    … …  
    16341635            printf(" attempting to ");
    16351636            if (piomode == 255)
    1636                 printf("auto-tune PIO mode\n");
     1637                puts("auto-tune PIO mode");
    16371638            else if (piomode < 100)
    16381639                printf("set PIO mode to %d\n", piomode);
    … …  
    17631764#define WIN_STANDBYNOW2 0x94
    17641765#endif
    1765         printf(" issuing standby command\n");
     1766        puts(" issuing standby command");
    17661767        args[0] = WIN_STANDBYNOW1;
    17671768        ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2);
    … …  
    17741775#define WIN_SLEEPNOW2 0x99
    17751776#endif
    1776         printf(" issuing sleep command\n");
     1777        puts(" issuing sleep command");
    17771778        args[0] = WIN_SLEEPNOW1;
    17781779        ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2);
    … …  
    17801781    if (set_seagate) {
    17811782        args[0] = 0xfb;
    1782         printf(" disabling Seagate auto powersaving mode\n");
     1783        puts(" disabling Seagate auto powersaving mode");
    17831784        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    17841785    }
    … …  
    18161817            printf(" IO_support\t=%3ld (", parm);
    18171818            if (parm == 0)
    1818                 printf("default 16-bit)\n");
     1819                puts("default 16-bit)");
    18191820            else if (parm == 2)
    1820                 printf("16-bit)\n");
     1821                puts("16-bit)");
    18211822            else if (parm == 1)
    1822                 printf("32-bit)\n");
     1823                puts("32-bit)");
    18231824            else if (parm == 3)
    1824                 printf("32-bit w/sync)\n");
     1825                puts("32-bit w/sync)");
    18251826            else if (parm == 8)
    1826                 printf("Request-Queue-Bypass)\n");
     1827                puts("Request-Queue-Bypass)");
    18271828            else
    1828                 printf("\?\?\?)\n");
     1829                puts("\?\?\?)");
    18291830        }
    18301831    }
    … …  
    18381839            printf(fmt, "using_dma", parm);
    18391840            if (parm == 8)
    1840                 printf(" (DMA-Assisted-PIO)\n");
     1841                puts(" (DMA-Assisted-PIO)");
    18411842            else
    18421843                on_off(parm != 0);
    … …  
    19221923            dump_identity(&id);
    19231924        } else if (errno == -ENOMSG)
    1924             printf(" no identification info available\n");
     1925            puts(" no identification info available");
    19251926        else if (ENABLE_IOCTL_HEX2STR_ERROR)  /* To be coherent with ioctl_or_warn */
    19261927            bb_perror_msg("HDIO_GET_IDENTITY");
  • branches/3.3/mindi-busybox/miscutils/inotifyd.c

    r3232 r3621  
    4848//usage:     "\n    x   File can't be watched anymore"
    4949//usage:     "\nIf watching a directory:"
    50 //usage:     "\n    m   Subfile is moved into dir"
    51 //usage:     "\n    y   Subfile is moved out of dir"
     50//usage:     "\n    y   Subfile is moved into dir"
     51//usage:     "\n    m   Subfile is moved out of dir"
    5252//usage:     "\n    n   Subfile is created"
    5353//usage:     "\n    d   Subfile is deleted"
    … …  
    5757
    5858#include "libbb.h"
     59#include "common_bufsiz.h"
    5960#include <sys/inotify.h>
    6061
    … …  
    162163        // read out all pending events
    163164        // (NB: len must be int, not ssize_t or long!)
     165#define eventbuf bb_common_bufsiz1
     166        setup_common_bufsiz();
    164167        xioctl(pfd.fd, FIONREAD, &len);
    165 #define eventbuf bb_common_bufsiz1
    166         ie = buf = (len <= sizeof(eventbuf)) ? eventbuf : xmalloc(len);
     168        ie = buf = (len <= COMMON_BUFSIZE) ? eventbuf : xmalloc(len);
    167169        len = full_read(pfd.fd, buf, len);
    168170        // process events. N.B. events may vary in length
  • branches/3.3/mindi-busybox/miscutils/ionice.c

    r3232 r3621  
    4242};
    4343
    44 static const char to_prio[] = "none\0realtime\0best-effort\0idle";
     44static const char to_prio[] ALIGN1 = "none\0realtime\0best-effort\0idle";
    4545
    4646#define IOPRIO_CLASS_SHIFT      13
  • branches/3.3/mindi-busybox/miscutils/last.c

    r3232 r3621  
    3333#if defined UT_LINESIZE \
    3434    && ((UT_LINESIZE != 32) || (UT_NAMESIZE != 32) || (UT_HOSTSIZE != 256))
    35 #error struct utmp member char[] size(s) have changed!
     35#error struct utmpx member char[] size(s) have changed!
    3636#elif defined __UT_LINESIZE \
    37     && ((__UT_LINESIZE != 32) || (__UT_NAMESIZE != 64) || (__UT_HOSTSIZE != 256))
    38 #error struct utmp member char[] size(s) have changed!
     37    && ((__UT_LINESIZE != 32) || (__UT_NAMESIZE != 32) || (__UT_HOSTSIZE != 256))
     38/* __UT_NAMESIZE was checked with 64 above, but glibc-2.11 definitely uses 32! */
     39#error struct utmpx member char[] size(s) have changed!
    3940#endif
    4041
    4142#if EMPTY != 0 || RUN_LVL != 1 || BOOT_TIME != 2 || NEW_TIME != 3 || \
    4243    OLD_TIME != 4
    43 #error Values for the ut_type field of struct utmp changed
     44#error Values for the ut_type field of struct utmpx changed
    4445#endif
    4546
    … …  
    4748int last_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
    4849{
    49     struct utmp ut;
     50    struct utmpx ut;
    5051    int n, file = STDIN_FILENO;
    5152    time_t t_tmp;
    … …  
    8889                ut.ut_type = n != 3 ? n : SHUTDOWN_TIME;
    8990#else
    90             if (strncmp(ut.ut_user, "shutdown", 8) == 0)
     91            if (is_prefixed_with(ut.ut_user, "shutdown"))
    9192                ut.ut_type = SHUTDOWN_TIME;
    92             else if (strncmp(ut.ut_user, "reboot", 6) == 0)
     93            else if (is_prefixed_with(ut.ut_user, "reboot"))
    9394                ut.ut_type = BOOT_TIME;
    94             else if (strncmp(ut.ut_user, "runlevel", 8) == 0)
     95            else if (is_prefixed_with(ut.ut_user, "runlevel"))
    9596                ut.ut_type = RUN_LVL;
    9697#endif
  • branches/3.3/mindi-busybox/miscutils/last_fancy.c

    r3232 r3621  
    2323    INET6_ADDRSTRLEN, INET6_ADDRSTRLEN, "HOST", "LOGIN", "  TIME", ""
    2424
     25#if !defined __UT_LINESIZE && defined UT_LINESIZE
     26# define __UT_LINESIZE UT_LINESIZE
     27#endif
     28
    2529enum {
    2630    NORMAL,
    … …  
    4044#define show_wide (option_mask32 & LAST_OPT_W)
    4145
    42 static void show_entry(struct utmp *ut, int state, time_t dur_secs)
     46static void show_entry(struct utmpx *ut, int state, time_t dur_secs)
    4347{
    4448    unsigned days, hours, mins;
    45     char duration[32];
     49    char duration[sizeof("(%u+02:02)") + sizeof(int)*3];
    4650    char login_time[17];
    4751    char logout_time[8];
    … …  
    5458    tmp = ut->ut_tv.tv_sec;
    5559    safe_strncpy(login_time, ctime(&tmp), 17);
    56     snprintf(logout_time, 8, "- %s", ctime(&dur_secs) + 11);
     60    tmp = dur_secs;
     61    snprintf(logout_time, 8, "- %s", ctime(&tmp) + 11);
    5762
    5863    dur_secs = MAX(dur_secs - (time_t)ut->ut_tv.tv_sec, (time_t)0);
    … …  
    104109}
    105110
    106 static int get_ut_type(struct utmp *ut)
     111static int get_ut_type(struct utmpx *ut)
    107112{
    108113    if (ut->ut_line[0] == '~') {
    … …  
    142147}
    143148
    144 static int is_runlevel_shutdown(struct utmp *ut)
     149static int is_runlevel_shutdown(struct utmpx *ut)
    145150{
    146151    if (((ut->ut_pid & 255) == '0') || ((ut->ut_pid & 255) == '6')) {
    … …  
    154159int last_main(int argc UNUSED_PARAM, char **argv)
    155160{
    156     struct utmp ut;
     161    struct utmpx ut;
    157162    const char *filename = _PATH_WTMP;
    158163    llist_t *zlist;
    … …  
    229234            }
    230235            /* add_entry */
    231             llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut)));
     236            llist_add_to(&zlist, xmemdup(&ut, sizeof(ut)));
    232237            break;
    233238        case USER_PROCESS: {
    … …  
    242247                llist_t *el, *next;
    243248                for (el = zlist; el; el = next) {
    244                     struct utmp *up = (struct utmp *)el->data;
     249                    struct utmpx *up = (struct utmpx *)el->data;
    245250                    next = el->link;
    246                     if (strncmp(up->ut_line, ut.ut_line, UT_LINESIZE) == 0) {
     251                    if (strncmp(up->ut_line, ut.ut_line, __UT_LINESIZE) == 0) {
    247252                        if (show) {
    248253                            show_entry(&ut, NORMAL, up->ut_tv.tv_sec);
    … …  
    271276            }
    272277            /* add_entry */
    273             llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut)));
     278            llist_add_to(&zlist, xmemdup(&ut, sizeof(ut)));
    274279            break;
    275280        }
  • branches/3.3/mindi-busybox/miscutils/less.c

    r3232 r3621  
    4848//config:   help
    4949//config:     The -M/-m flag enables a more sophisticated status line.
     50//config:
     51//config:config FEATURE_LESS_TRUNCATE
     52//config:   bool "Enable -S"
     53//config:   default y
     54//config:   depends on LESS
     55//config:   help
     56//config:     The -S flag causes long lines to be truncated rather than
     57//config:     wrapped.
    5058//config:
    5159//config:config FEATURE_LESS_MARKS
    … …  
    99107
    100108//usage:#define less_trivial_usage
    101 //usage:       "[-E" IF_FEATURE_LESS_FLAGS("Mm") "Nh~I?] [FILE]..."
     109//usage:       "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm")
     110//usage:       "N" IF_FEATURE_LESS_TRUNCATE("S") "h~] [FILE]..."
    102111//usage:#define less_full_usage "\n\n"
    103112//usage:       "View FILE (or stdin) one screenful at a time\n"
    104113//usage:     "\n    -E  Quit once the end of a file is reached"
     114//usage:    IF_FEATURE_LESS_REGEXP(
     115//usage:     "\n    -I  Ignore case in all searches"
     116//usage:    )
    105117//usage:    IF_FEATURE_LESS_FLAGS(
    106118//usage:     "\n    -M,-m   Display status line with line numbers"
    … …  
    108120//usage:    )
    109121//usage:     "\n    -N  Prefix line number to each line"
    110 //usage:     "\n    -I  Ignore case in all searches"
     122//usage:    IF_FEATURE_LESS_TRUNCATE(
     123//usage:     "\n    -S  Truncate long lines"
     124//usage:    )
    111125//usage:     "\n    -~  Suppress ~s displayed past EOF"
    112126
    … …  
    114128
    115129#include "libbb.h"
     130#include "common_bufsiz.h"
    116131#if ENABLE_FEATURE_LESS_REGEXP
    117132#include "xregex.h"
    … …  
    143158    FLAG_TILDE = 1 << 4,
    144159    FLAG_I = 1 << 5,
    145     FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_DASHCMD,
     160    FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_TRUNCATE,
    146161/* hijack command line options variable for internal state vars */
    147162    LESS_STATE_MATCH_BACKWARDS = 1 << 15,
    … …  
    175190    char *filename;
    176191    char **files;
     192#if ENABLE_FEATURE_LESS_FLAGS
     193    int num_lines; /* a flag if < 0, line count if >= 0 */
     194# define REOPEN_AND_COUNT (-1)
     195# define REOPEN_STDIN     (-2)
     196# define NOT_REGULAR_FILE (-3)
     197#endif
    177198#if ENABLE_FEATURE_LESS_MARKS
    178199    unsigned num_marks;
    … …  
    216237#define filename            (G.filename          )
    217238#define files               (G.files             )
     239#define num_lines           (G.num_lines         )
    218240#define num_marks           (G.num_marks         )
    219241#define mark_lines          (G.mark_lines        )
    … …  
    318340        if (*d != '\0') {
    319341            new_line_pos++;
    320             if (*d == '\t') /* tab */
     342            if (*d == '\t') { /* tab */
    321343                new_line_pos += 7;
     344                new_line_pos &= (~7);
     345            }
    322346            s++;
    323347            d++;
    … …  
    381405#endif
    382406
     407static int at_end(void)
     408{
     409    return (option_mask32 & FLAG_S)
     410        ? !(cur_fline <= max_fline &&
     411            max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
     412        : !(max_fline > cur_fline + max_displayed_line);
     413}
     414
    383415/* Devilishly complex routine.
    384416 *
    … …  
    403435 *      (takes into account tabs and backspaces)
    404436 * eof_error - < 0 error, == 0 EOF, > 0 not EOF/error
     437 *
     438 * "git log -p | less -m" on the kernel git tree is a good test for EAGAINs,
     439 * "/search on very long input" and "reaching max line count" corner cases.
    405440 */
    406441static void read_lines(void)
    407442{
    408 #define readbuf bb_common_bufsiz1
    409443    char *current_line, *p;
    410444    int w = width;
    411445    char last_terminated = terminated;
     446    time_t last_time = 0;
     447    int retry_EAGAIN = 2;
    412448#if ENABLE_FEATURE_LESS_REGEXP
    413449    unsigned old_max_fline = max_fline;
    414     time_t last_time = 0;
    415     unsigned seconds_p1 = 3; /* seconds_to_loop + 1 */
    416 #endif
     450#endif
     451
     452#define readbuf bb_common_bufsiz1
     453    setup_common_bufsiz();
     454
     455    /* (careful: max_fline can be -1) */
     456    if (max_fline + 1 > MAXLINES)
     457        return;
    417458
    418459    if (option_mask32 & FLAG_N)
    419460        w -= 8;
    420461
    421  IF_FEATURE_LESS_REGEXP(again0:)
    422 
    423     p = current_line = ((char*)xmalloc(w + 4)) + 4;
    424     max_fline += last_terminated;
     462    p = current_line = ((char*)xmalloc(w + 5)) + 4;
    425463    if (!last_terminated) {
    426464        const char *cp = flines[max_fline];
    427         strcpy(p, cp);
    428         p += strlen(current_line);
    429         free(MEMPTR(flines[max_fline]));
     465        p = stpcpy(p, cp);
     466        free(MEMPTR(cp));
    430467        /* last_line_pos is still valid from previous read_lines() */
    431468    } else {
     469        max_fline++;
    432470        last_line_pos = 0;
    433471    }
    … …  
    440478            /* if no unprocessed chars left, eat more */
    441479            if (readpos >= readeof) {
    442                 ndelay_on(0);
    443                 eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf));
    444                 ndelay_off(0);
     480                int flags = ndelay_on(0);
     481
     482                while (1) {
     483                    time_t t;
     484
     485                    errno = 0;
     486                    eof_error = safe_read(STDIN_FILENO, readbuf, COMMON_BUFSIZE);
     487                    if (errno != EAGAIN)
     488                        break;
     489                    t = time(NULL);
     490                    if (t != last_time) {
     491                        last_time = t;
     492                        if (--retry_EAGAIN < 0)
     493                            break;
     494                    }
     495                    sched_yield();
     496                }
     497                fcntl(0, F_SETFL, flags); /* ndelay_off(0) */
    445498                readpos = 0;
    446499                readeof = eof_error;
    447500                if (eof_error <= 0)
    448501                    goto reached_eof;
     502                retry_EAGAIN = 1;
    449503            }
    450504            c = readbuf[readpos];
    … …  
    465519                    new_last_line_pos &= (~7);
    466520                }
    467                 if ((int)new_last_line_pos >= w)
     521                if ((int)new_last_line_pos > w)
    468522                    break;
    469523                last_line_pos = new_last_line_pos;
    … …  
    481535            *p = '\0';
    482536        } /* end of "read chars until we have a line" loop */
     537#if 0
     538//BUG: also triggers on this:
     539// { printf "\nfoo\n"; sleep 1; printf "\nbar\n"; } | less
     540// (resulting in lost empty line between "foo" and "bar" lines)
     541// the "terminated" logic needs fixing (or explaining)
    483542        /* Corner case: linewrap with only "" wrapping to next line */
    484543        /* Looks ugly on screen, so we do not store this empty line */
    … …  
    488547            continue;
    489548        }
     549#endif
    490550 reached_eof:
    491551        last_terminated = terminated;
    … …  
    501561            break;
    502562        }
    503         if (!(option_mask32 & FLAG_S)
    504           ? (max_fline > cur_fline + max_displayed_line)
    505           : (max_fline >= cur_fline
    506              && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
    507         ) {
     563        if (!at_end()) {
    508564#if !ENABLE_FEATURE_LESS_REGEXP
    509565            break;
    … …  
    518574        }
    519575        if (eof_error <= 0) {
    520             if (eof_error < 0) {
    521                 if (errno == EAGAIN) {
    522                     /* not yet eof or error, reset flag (or else
    523                      * we will hog CPU - select() will return
    524                      * immediately */
    525                     eof_error = 1;
    526                 } else {
    527                     print_statusline(bb_msg_read_error);
    528                 }
    529             }
    530 #if !ENABLE_FEATURE_LESS_REGEXP
    531576            break;
    532 #else
    533             if (wanted_match < num_matches) {
    534                 break;
    535             } else { /* goto_match called us */
    536                 time_t t = time(NULL);
    537                 if (t != last_time) {
    538                     last_time = t;
    539                     if (--seconds_p1 == 0)
    540                         break;
    541                 }
    542                 sched_yield();
    543                 goto again0; /* go loop again (max 2 seconds) */
    544             }
    545 #endif
    546577        }
    547578        max_fline++;
    548         current_line = ((char*)xmalloc(w + 4)) + 4;
     579        current_line = ((char*)xmalloc(w + 5)) + 4;
    549580        p = current_line;
    550581        last_line_pos = 0;
    551582    } /* end of "read lines until we reach cur_fline" loop */
     583
     584    if (eof_error < 0) {
     585        if (errno == EAGAIN) {
     586            eof_error = 1;
     587        } else {
     588            print_statusline(bb_msg_read_error);
     589        }
     590    }
     591#if ENABLE_FEATURE_LESS_FLAGS
     592    else if (eof_error == 0)
     593        num_lines = max_lineno;
     594#endif
     595
    552596    fill_match_lines(old_max_fline);
    553597#if ENABLE_FEATURE_LESS_REGEXP
    … …  
    559603
    560604#if ENABLE_FEATURE_LESS_FLAGS
    561 /* Interestingly, writing calc_percent as a function saves around 32 bytes
    562  * on my build. */
    563 static int calc_percent(void)
    564 {
    565     unsigned p = (100 * (cur_fline+max_displayed_line+1) + max_fline/2) / (max_fline+1);
    566     return p <= 100 ? p : 100;
     605static int safe_lineno(int fline)
     606{
     607    if (fline >= max_fline)
     608        fline = max_fline - 1;
     609
     610    /* also catches empty file (max_fline == 0) */
     611    if (fline < 0)
     612        return 0;
     613
     614    return LINENO(flines[fline]) + 1;
     615}
     616
     617/* count number of lines in file */
     618static void update_num_lines(void)
     619{
     620    int count, fd;
     621    struct stat stbuf;
     622    ssize_t len, i;
     623    char buf[4096];
     624
     625    /* only do this for regular files */
     626    if (num_lines == REOPEN_AND_COUNT || num_lines == REOPEN_STDIN) {
     627        count = 0;
     628        fd = open("/proc/self/fd/0", O_RDONLY);
     629        if (fd < 0 && num_lines == REOPEN_AND_COUNT) {
     630            /* "filename" is valid only if REOPEN_AND_COUNT */
     631            fd = open(filename, O_RDONLY);
     632        }
     633        if (fd < 0) {
     634            /* somebody stole my file! */
     635            num_lines = NOT_REGULAR_FILE;
     636            return;
     637        }
     638        if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) {
     639            num_lines = NOT_REGULAR_FILE;
     640            goto do_close;
     641        }
     642        while ((len = safe_read(fd, buf, sizeof(buf))) > 0) {
     643            for (i = 0; i < len; ++i) {
     644                if (buf[i] == '\n' && ++count == MAXLINES)
     645                    goto done;
     646            }
     647        }
     648 done:
     649        num_lines = count;
     650 do_close:
     651        close(fd);
     652    }
    567653}
    568654
    … …  
    570656static void m_status_print(void)
    571657{
    572     int percentage;
     658    int first, last;
     659    unsigned percent;
    573660
    574661    if (less_gets_pos >= 0) /* don't touch statusline while input is done! */
    … …  
    579666    if (num_files > 1)
    580667        printf(" (file %i of %i)", current_file, num_files);
    581     printf(" lines %i-%i/%i ",
    582             cur_fline + 1, cur_fline + max_displayed_line + 1,
    583             max_fline + 1);
    584     if (cur_fline >= (int)(max_fline - max_displayed_line)) {
    585         printf("(END)"NORMAL);
     668
     669    first = safe_lineno(cur_fline);
     670    last = (option_mask32 & FLAG_S)
     671            ? MIN(first + max_displayed_line, max_lineno)
     672            : safe_lineno(cur_fline + max_displayed_line);
     673    printf(" lines %i-%i", first, last);
     674
     675    update_num_lines();
     676    if (num_lines >= 0)
     677        printf("/%i", num_lines);
     678
     679    if (at_end()) {
     680        printf(" (END)");
    586681        if (num_files > 1 && current_file != num_files)
    587             printf(HIGHLIGHT" - next: %s"NORMAL, files[current_file]);
    588         return;
    589     }
    590     percentage = calc_percent();
    591     printf("%i%%"NORMAL, percentage);
     682            printf(" - next: %s", files[current_file]);
     683    } else if (num_lines > 0) {
     684        percent = (100 * last + num_lines/2) / num_lines;
     685        printf(" %i%%", percent <= 100 ? percent : 100);
     686    }
     687    printf(NORMAL);
    592688}
    593689#endif
    … …  
    611707
    612708    clear_line();
    613     if (cur_fline && cur_fline < (int)(max_fline - max_displayed_line)) {
     709    if (cur_fline && !at_end()) {
    614710        bb_putchar(':');
    615711        return;
    … …  
    624720    }
    625721    print_hilite(p);
    626 }
    627 
    628 static void cap_cur_fline(int nlines)
    629 {
    630     int diff;
    631     if (cur_fline < 0)
    632         cur_fline = 0;
    633     if (cur_fline + max_displayed_line > max_fline + TILDES) {
    634         cur_fline -= nlines;
    635         if (cur_fline < 0)
    636             cur_fline = 0;
    637         diff = max_fline - (cur_fline + max_displayed_line) + TILDES;
    638         /* As the number of lines requested was too large, we just move
    639          * to the end of the file */
    640         if (diff > 0)
    641             cur_fline += diff;
    642     }
    643722}
    644723
    … …  
    654733    "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f";
    655734
    656 static void lineno_str(char *nbuf9, const char *line)
    657 {
    658     nbuf9[0] = '\0';
    659     if (option_mask32 & FLAG_N) {
    660         const char *fmt;
    661         unsigned n;
    662 
    663         if (line == empty_line_marker) {
    664             memset(nbuf9, ' ', 8);
    665             nbuf9[8] = '\0';
    666             return;
    667         }
     735static void print_lineno(const char *line)
     736{
     737    const char *fmt = "        ";
     738    unsigned n = n; /* for compiler */
     739
     740    if (line != empty_line_marker) {
    668741        /* Width of 7 preserves tab spacing in the text */
    669742        fmt = "%7u ";
    670743        n = LINENO(line) + 1;
    671         if (n > 9999999) {
     744        if (n > 9999999 && MAXLINES > 9999999) {
    672745            n %= 10000000;
    673746            fmt = "%07u ";
    674747        }
    675         sprintf(nbuf9, fmt, n);
    676     }
     748    }
     749    printf(fmt, n);
    677750}
    678751
    … …  
    686759    regmatch_t match_structs;
    687760
    688     char buf[width];
    689     char nbuf9[9];
     761    char buf[width+1];
    690762    const char *str = line;
    691763    char *p = buf;
    … …  
    737809    }
    738810
    739     lineno_str(nbuf9, line);
    740     if (!growline) {
    741         printf(CLEAR_2_EOL"%s%s\n", nbuf9, str);
    742         return;
    743     }
    744     printf(CLEAR_2_EOL"%s%s%s\n", nbuf9, growline, str);
     811    printf("%s%s\n", growline ? growline : "", str);
    745812    free(growline);
    746813}
    … …  
    751818static void print_ascii(const char *str)
    752819{
    753     char buf[width];
    754     char nbuf9[9];
     820    char buf[width+1];
    755821    char *p;
    756822    size_t n;
    757 
    758     lineno_str(nbuf9, str);
    759     printf(CLEAR_2_EOL"%s", nbuf9);
    760823
    761824    while (*str) {
    … …  
    791854
    792855    move_cursor(0, 0);
    793     for (i = 0; i <= max_displayed_line; i++)
     856    for (i = 0; i <= max_displayed_line; i++) {
     857        printf(CLEAR_2_EOL);
     858        if (option_mask32 & FLAG_N)
     859            print_lineno(buffer[i]);
    794860        if (pattern_valid)
    795861            print_found(buffer[i]);
    796862        else
    797863            print_ascii(buffer[i]);
     864    }
     865    if ((option_mask32 & FLAG_E)
     866     && eof_error <= 0
     867     && (max_fline - cur_fline) <= max_displayed_line
     868    ) {
     869        less_exit(EXIT_SUCCESS);
     870    }
    798871    status_print();
    799872}
    … …  
    802875{
    803876    unsigned i;
    804 #if ENABLE_FEATURE_LESS_DASHCMD
     877#if ENABLE_FEATURE_LESS_TRUNCATE
    805878    int fpos = cur_fline;
    806879
    … …  
    834907}
    835908
     909/* move cur_fline to a given line number, reading lines if necessary */
     910static void goto_lineno(int target)
     911{
     912    if (target <= 0 ) {
     913        cur_fline = 0;
     914    }
     915    else if (target > LINENO(flines[cur_fline])) {
     916 retry:
     917        while (LINENO(flines[cur_fline]) != target && cur_fline < max_fline)
     918            ++cur_fline;
     919        /* target not reached but more input is available */
     920        if (LINENO(flines[cur_fline]) != target && eof_error > 0) {
     921            read_lines();
     922            goto retry;
     923        }
     924    }
     925    else {
     926        /* search backwards through already-read lines */
     927        while (LINENO(flines[cur_fline]) != target && cur_fline > 0)
     928            --cur_fline;
     929    }
     930}
     931
     932static void cap_cur_fline(void)
     933{
     934    if ((option_mask32 & FLAG_S)) {
     935        if (cur_fline > max_fline)
     936            cur_fline = max_fline;
     937        if (LINENO(flines[cur_fline]) + max_displayed_line > max_lineno + TILDES) {
     938            goto_lineno(max_lineno - max_displayed_line + TILDES);
     939            read_lines();
     940        }
     941    }
     942    else {
     943        if (cur_fline + max_displayed_line > max_fline + TILDES)
     944            cur_fline = max_fline - max_displayed_line + TILDES;
     945        if (cur_fline < 0)
     946            cur_fline = 0;
     947    }
     948}
     949
    836950/* Move the buffer up and down in the file in order to scroll */
    837951static void buffer_down(int nlines)
    838952{
    839     cur_fline += nlines;
     953    if ((option_mask32 & FLAG_S))
     954        goto_lineno(LINENO(flines[cur_fline]) + nlines);
     955    else
     956        cur_fline += nlines;
    840957    read_lines();
    841     cap_cur_fline(nlines);
     958    cap_cur_fline();
    842959    buffer_fill_and_print();
    843960}
    … …  
    845962static void buffer_up(int nlines)
    846963{
    847     cur_fline -= nlines;
    848     if (cur_fline < 0) cur_fline = 0;
     964    if ((option_mask32 & FLAG_S)) {
     965        goto_lineno(LINENO(flines[cur_fline]) - nlines);
     966    }
     967    else {
     968        cur_fline -= nlines;
     969        if (cur_fline < 0)
     970            cur_fline = 0;
     971    }
    849972    read_lines();
    850973    buffer_fill_and_print();
    851974}
    852975
     976/* display a given line where the argument can be either an index into
     977 * the flines array or a line number */
     978static void buffer_to_line(int linenum, int is_lineno)
     979{
     980    if (linenum <= 0)
     981        cur_fline = 0;
     982    else if (is_lineno)
     983        goto_lineno(linenum);
     984    else
     985        cur_fline = linenum;
     986    read_lines();
     987    cap_cur_fline();
     988    buffer_fill_and_print();
     989}
     990
    853991static void buffer_line(int linenum)
    854992{
    855     if (linenum < 0)
    856         linenum = 0;
    857     cur_fline = linenum;
    858     read_lines();
    859     if (linenum + max_displayed_line > max_fline)
    860         linenum = max_fline - max_displayed_line + TILDES;
    861     if (linenum < 0)
    862         linenum = 0;
    863     cur_fline = linenum;
    864     buffer_fill_and_print();
     993    buffer_to_line(linenum, FALSE);
     994}
     995
     996static void buffer_lineno(int lineno)
     997{
     998    buffer_to_line(lineno, TRUE);
    865999}
    8661000
    … …  
    8691003    if (filename) {
    8701004        xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO);
     1005#if ENABLE_FEATURE_LESS_FLAGS
     1006        num_lines = REOPEN_AND_COUNT;
     1007#endif
    8711008    } else {
    8721009        /* "less" with no arguments in argv[] */
    8731010        /* For status line only */
    8741011        filename = xstrdup(bb_msg_standard_input);
     1012#if ENABLE_FEATURE_LESS_FLAGS
     1013        num_lines = REOPEN_STDIN;
     1014#endif
    8751015    }
    8761016    readpos = 0;
    … …  
    9241064    rd = 1;
    9251065    /* Are we interested in stdin? */
    926 //TODO: reuse code for determining this
    927     if (!(option_mask32 & FLAG_S)
    928        ? !(max_fline > cur_fline + max_displayed_line)
    929        : !(max_fline >= cur_fline
    930            && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
    931     ) {
     1066    if (at_end()) {
    9321067        if (eof_error > 0) /* did NOT reach eof yet */
    9331068            rd = 0; /* yes, we are interested in stdin */
    … …  
    12401375    while (i < sizeof(num_input)-1) {
    12411376        keypress = less_getch(i + 1);
    1242         if ((unsigned)keypress > 255 || !isdigit(num_input[i]))
     1377        if ((unsigned)keypress > 255 || !isdigit(keypress))
    12431378            break;
    12441379        num_input[i] = keypress;
    … …  
    12641399        break;
    12651400    case 'g': case '<': case 'G': case '>':
    1266         cur_fline = num + max_displayed_line;
    1267         read_lines();
    1268         buffer_line(num - 1);
     1401        buffer_lineno(num - 1);
    12691402        break;
    12701403    case 'p': case '%':
    1271         num = num * (max_fline / 100); /* + max_fline / 2; */
    1272         cur_fline = num + max_displayed_line;
    1273         read_lines();
    1274         buffer_line(num);
     1404#if ENABLE_FEATURE_LESS_FLAGS
     1405        update_num_lines();
     1406        num = num * (num_lines > 0 ? num_lines : max_lineno) / 100;
     1407#else
     1408        num = num * max_lineno / 100;
     1409#endif
     1410        buffer_lineno(num);
    12751411        break;
    12761412#if ENABLE_FEATURE_LESS_REGEXP
    … …  
    13121448        option_mask32 ^= FLAG_TILDE;
    13131449        break;
     1450#if ENABLE_FEATURE_LESS_TRUNCATE
    13141451    case 'S':
    13151452        option_mask32 ^= FLAG_S;
    13161453        buffer_fill_and_print();
    13171454        break;
     1455#endif
    13181456#if ENABLE_FEATURE_LESS_LINENUMS
    13191457    case 'N':
    … …  
    16091747int less_main(int argc, char **argv)
    16101748{
     1749    char *tty_name;
     1750    int tty_fd;
     1751
    16111752    INIT_G();
    16121753
    1613     /* TODO: -x: do not interpret backspace, -xx: tab also */
    1614     /* -xxx: newline also */
    1615     /* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */
    1616     getopt32(argv, "EMmN~I" IF_FEATURE_LESS_DASHCMD("S"));
     1754    /* TODO: -x: do not interpret backspace, -xx: tab also
     1755     * -xxx: newline also
     1756     * -w N: assume width N (-xxx -w 32: hex viewer of sorts)
     1757     * -s: condense many empty lines to one
     1758     *     (used by some setups for manpage display)
     1759     */
     1760    getopt32(argv, "EMmN~I" IF_FEATURE_LESS_TRUNCATE("S") /*ignored:*/"s");
    16171761    argc -= optind;
    16181762    argv += optind;
    … …  
    16381782        empty_line_marker = "";
    16391783
    1640     kbd_fd = open(CURRENT_TTY, O_RDONLY);
    1641     if (kbd_fd < 0)
    1642         return bb_cat(argv);
    1643     ndelay_on(kbd_fd);
     1784    /* Some versions of less can survive w/o controlling tty,
     1785     * try to do the same. This also allows to specify an alternative
     1786     * tty via "less 1<>TTY".
     1787     * We don't try to use STDOUT_FILENO directly,
     1788     * since we want to set this fd to non-blocking mode,
     1789     * and not bother with restoring it on exit.
     1790     */
     1791    tty_name = xmalloc_ttyname(STDOUT_FILENO);
     1792    if (tty_name) {
     1793        tty_fd = open(tty_name, O_RDONLY);
     1794        free(tty_name);
     1795        if (tty_fd < 0)
     1796            goto try_ctty;
     1797    } else {
     1798        /* Try controlling tty */
     1799 try_ctty:
     1800        tty_fd = open(CURRENT_TTY, O_RDONLY);
     1801        if (tty_fd < 0)
     1802            return bb_cat(argv);
     1803    }
     1804    ndelay_on(tty_fd);
     1805    kbd_fd = tty_fd; /* save in a global */
    16441806
    16451807    tcgetattr(kbd_fd, &term_orig);
    … …  
    18061968        or from within less by using the - or -- command.
    18071969        Options may be given in one of two forms: either a single
    1808         character preceded by a -, or a name preceeded by --.
     1970        character preceded by a -, or a name preceded by --.
    18091971  -?  ........  --help
    18101972                  Display help (from command line).
  • branches/3.3/mindi-busybox/miscutils/man.c

    r3232 r3621  
    6767
    6868        line = xmalloc_open_zipped_read_close(man_filename, NULL);
    69         if (!line || strncmp(line, ".so ", 4) != 0) {
     69        if (!line || !is_prefixed_with(line, ".so ")) {
    7070            free(line);
    7171            goto ordinary_manpage;
    … …  
    103103 ordinary_manpage:
    104104    close(STDIN_FILENO);
    105     open_zipped(man_filename); /* guaranteed to use fd 0 (STDIN_FILENO) */
     105    open_zipped(man_filename, /*fail_if_not_compressed:*/ 0); /* guaranteed to use fd 0 (STDIN_FILENO) */
    106106    /* "2>&1" is added so that nroff errors are shown in pager too.
    107107     * Otherwise it may show just empty screen */
    108108    cmd = xasprintf(
    109         man ? "gtbl | nroff -Tlatin1 -mandoc 2>&1 | %s"
     109        /* replaced -Tlatin1 with -Tascii for non-UTF8 displays */
     110        man ? "gtbl | nroff -Tascii -mandoc 2>&1 | %s"
    110111            : "%s",
    111112        pager);
    … …  
    147148}
    148149
     150static char **add_MANPATH(char **man_path_list, int *count_mp, char *path)
     151{
     152    if (path) while (*path) {
     153        char *next_path;
     154        char **path_element;
     155
     156        next_path = strchr(path, ':');
     157        if (next_path) {
     158            if (next_path == path) /* "::"? */
     159                goto next;
     160            *next_path = '\0';
     161        }
     162        /* Do we already have path? */
     163        path_element = man_path_list;
     164        if (path_element) while (*path_element) {
     165            if (strcmp(*path_element, path) == 0)
     166                goto skip;
     167            path_element++;
     168        }
     169        man_path_list = xrealloc_vector(man_path_list, 4, *count_mp);
     170        man_path_list[*count_mp] = xstrdup(path);
     171        (*count_mp)++;
     172        /* man_path_list is NULL terminated */
     173        /* man_path_list[*count_mp] = NULL; - xrealloc_vector did it */
     174 skip:
     175        if (!next_path)
     176            break;
     177        /* "path" may be a result of getenv(), be nice and don't mangle it */
     178        *next_path = ':';
     179 next:
     180        path = next_path + 1;
     181    }
     182    return man_path_list;
     183}
     184
    149185int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    150186int man_main(int argc UNUSED_PARAM, char **argv)
    151187{
    152188    parser_t *parser;
    153     const char *pager;
    154     char **man_path_list;
     189    const char *pager = ENABLE_LESS ? "less" : "more";
    155190    char *sec_list;
    156191    char *cur_path, *cur_sect;
    157     int count_mp, cur_mp;
     192    char **man_path_list;
     193    int count_mp;
     194    int cur_mp;
    158195    int opt, not_found;
    159196    char *token[2];
    … …  
    163200    argv += optind;
    164201
    165     sec_list = xstrdup("1:2:3:4:5:6:7:8:9");
    166     /* Last valid man_path_list[] is [0x10] */
     202    sec_list = xstrdup("0p:1:1p:2:3:3p:4:5:6:7:8:9");
     203
    167204    count_mp = 0;
    168     man_path_list = xzalloc(0x11 * sizeof(man_path_list[0]));
    169     man_path_list[0] = getenv("MANPATH");
    170     if (!man_path_list[0]) /* default, may be overridden by /etc/man.conf */
     205    man_path_list = add_MANPATH(NULL, &count_mp,
     206            getenv("MANDATORY_MANPATH"+10) /* "MANPATH" */
     207    );
     208    if (!man_path_list) {
     209        /* default, may be overridden by /etc/man.conf */
     210        man_path_list = xzalloc(2 * sizeof(man_path_list[0]));
    171211        man_path_list[0] = (char*)"/usr/man";
    172     else
    173         count_mp++;
    174     pager = getenv("MANPAGER");
    175     if (!pager) {
    176         pager = getenv("PAGER");
    177         if (!pager)
    178             pager = "more";
     212        /* count_mp stays 0.
     213         * Thus, man.conf will overwrite man_path_list[0]
     214         * if a path is defined there.
     215         */
    179216    }
    180217
    … …  
    191228        if (!token[1])
    192229            continue;
     230        if (strcmp("DEFINE", token[0]) == 0) {
     231            if (is_prefixed_with("pager", token[1])) {
     232                pager = xstrdup(skip_whitespace(token[1]) + 5);
     233            }
     234        } else
    193235        if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */
    194236         || strcmp("MANDATORY_MANPATH", token[0]) == 0
    195237        ) {
    196             char *path = token[1];
    197             while (*path) {
    198                 char *next_path;
    199                 char **path_element;
    200 
    201                 next_path = strchr(path, ':');
    202                 if (next_path) {
    203                     *next_path = '\0';
    204                     if (next_path++ == path) /* "::"? */
    205                         goto next;
    206                 }
    207                 /* Do we already have path? */
    208                 path_element = man_path_list;
    209                 while (*path_element) {
    210                     if (strcmp(*path_element, path) == 0)
    211                         goto skip;
    212                     path_element++;
    213                 }
    214                 man_path_list = xrealloc_vector(man_path_list, 4, count_mp);
    215                 man_path_list[count_mp] = xstrdup(path);
    216                 count_mp++;
    217                 /* man_path_list is NULL terminated */
    218                 /*man_path_list[count_mp] = NULL; - xrealloc_vector did it */
    219  skip:
    220                 if (!next_path)
    221                     break;
    222  next:
    223                 path = next_path;
    224             }
     238            man_path_list = add_MANPATH(man_path_list, &count_mp, token[1]);
    225239        }
    226240        if (strcmp("MANSECT", token[0]) == 0) {
    … …  
    230244    }
    231245    config_close(parser);
     246
     247    {
     248        /* environment overrides setting from man.config */
     249        char *env_pager = getenv("MANPAGER");
     250        if (!env_pager)
     251            env_pager = getenv("PAGER");
     252        if (env_pager)
     253            pager = env_pager;
     254    }
    232255
    233256    not_found = 0;
  • branches/3.3/mindi-busybox/miscutils/microcom.c

    r3232 r3621  
    2020
    2121#include "libbb.h"
     22#include "common_bufsiz.h"
    2223
    2324// set raw tty mode
    … …  
    156157        }
    157158        if (pfd[0].revents) {
     159            ssize_t len;
    158160#define iobuf bb_common_bufsiz1
    159             ssize_t len;
     161            setup_common_bufsiz();
    160162            // read from device -> write to stdout
    161             len = safe_read(sfd, iobuf, sizeof(iobuf));
     163            len = safe_read(sfd, iobuf, COMMON_BUFSIZE);
    162164            if (len > 0)
    163165                full_write(STDOUT_FILENO, iobuf, len);
  • branches/3.3/mindi-busybox/miscutils/nandwrite.c

    r3232 r3621  
    2424
    2525//applet:IF_NANDWRITE(APPLET(nandwrite, BB_DIR_USR_SBIN, BB_SUID_DROP))
    26 //applet:IF_NANDWRITE(APPLET_ODDNAME(nanddump, nandwrite, BB_DIR_USR_SBIN, BB_SUID_DROP, nanddump))
     26//applet:IF_NANDDUMP(APPLET_ODDNAME(nanddump, nandwrite, BB_DIR_USR_SBIN, BB_SUID_DROP, nanddump))
    2727
    2828//kbuild:lib-$(CONFIG_NANDWRITE) += nandwrite.o
    … …  
    3030
    3131//usage:#define nandwrite_trivial_usage
    32 //usage:    "[-p] [-s ADDR] MTD_DEVICE [FILE]"
     32//usage:    "[-np] [-s ADDR] MTD_DEVICE [FILE]"
    3333//usage:#define nandwrite_full_usage "\n\n"
    34 //usage:    "Write to the specified MTD device\n"
     34//usage:    "Write to MTD_DEVICE\n"
     35//usage:     "\n    -n  Write without ecc"
    3536//usage:     "\n    -p  Pad to page size"
    3637//usage:     "\n    -s ADDR Start address"
    3738
    3839//usage:#define nanddump_trivial_usage
    39 //usage:    "[-o] [-b] [-s ADDR] [-f FILE] MTD_DEVICE"
     40//usage:    "[-no]" IF_LONG_OPTS(" [--bb=padbad|skipbad]") " [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE"
    4041//usage:#define nanddump_full_usage "\n\n"
    41 //usage:    "Dump the specified MTD device\n"
     42//usage:    "Dump MTD_DEVICE\n"
     43//usage:     "\n    -n  Read without ecc"
    4244//usage:     "\n    -o  Dump oob data"
    43 //usage:     "\n    -b  Omit bad block from the dump"
    4445//usage:     "\n    -s ADDR Start address"
    4546//usage:     "\n    -l LEN  Length"
    4647//usage:     "\n    -f FILE Dump to file ('-' for stdout)"
     48//usage:     IF_LONG_OPTS(
     49//usage:     "\n    --bb=METHOD:"
     50//usage:     "\n        skipbad: skip bad blocks"
     51//usage:     "\n        padbad: substitute bad blocks by 0xff (default)"
     52//usage:     )
    4753
    4854#include "libbb.h"
    … …  
    5460#define OPT_p  (1 << 0) /* nandwrite only */
    5561#define OPT_o  (1 << 0) /* nanddump only */
    56 #define OPT_s  (1 << 1)
    57 #define OPT_b  (1 << 2)
     62#define OPT_n  (1 << 1)
     63#define OPT_s  (1 << 2)
    5864#define OPT_f  (1 << 3)
    5965#define OPT_l  (1 << 4)
     66#define OPT_bb (1 << 5) /* must be the last one in the list */
     67
     68#define BB_PADBAD (1 << 0)
     69#define BB_SKIPBAD (1 << 1)
    6070
    6171/* helper for writing out 0xff for bad blocks pad */
    … …  
    6575    unsigned count;
    6676
    67     /* round len to the next page */
    68     len = (len | ~(meminfo->writesize - 1)) + 1;
     77    /* round len to the next page only if len is not already on a page */
     78    len = ((len - 1) | (meminfo->writesize - 1)) + 1;
    6979
    7080    memset(buf, 0xff, sizeof(buf));
    … …  
    103113    unsigned char *oobbuf;
    104114    unsigned opts;
     115    unsigned bb_method = BB_SKIPBAD;
    105116    int fd;
    106117    ssize_t cnt;
    … …  
    110121    struct mtd_oob_buf oob;
    111122    unsigned char *filebuf;
    112     const char *opt_s = "0", *opt_f = "-", *opt_l;
     123    const char *opt_s = "0", *opt_f = "-", *opt_l, *opt_bb;
    113124
    114125    if (IS_NANDDUMP) {
    115126        opt_complementary = "=1";
    116         opts = getopt32(argv, "os:bf:l:", &opt_s, &opt_f, &opt_l);
     127#if ENABLE_LONG_OPTS
     128        applet_long_options =
     129            "bb\0" Required_argument "\xff"; /* no short equivalent */
     130#endif
     131        opts = getopt32(argv, "ons:f:l:", &opt_s, &opt_f, &opt_l, &opt_bb);
    117132    } else { /* nandwrite */
    118133        opt_complementary = "-1:?2";
    119         opts = getopt32(argv, "ps:", &opt_s);
     134        opts = getopt32(argv, "pns:", &opt_s);
    120135    }
    121136    argv += optind;
    … …  
    133148    xioctl(fd, MEMGETINFO, &meminfo);
    134149
     150    if (opts & OPT_n)
     151        xioctl(fd, MTDFILEMODE, (void *)MTD_FILE_MODE_RAW);
     152
    135153    mtdoffset = xstrtou(opt_s, 0);
    136154    if (IS_NANDDUMP && (opts & OPT_l)) {
    … …  
    138156        if (length < meminfo.size - mtdoffset)
    139157            end_addr = mtdoffset + length;
     158    }
     159    if (IS_NANDDUMP && (opts & OPT_bb)) {
     160        if (strcmp("skipbad", opt_bb) == 0)
     161            bb_method = BB_SKIPBAD;
     162        else if (strcmp("padbad", opt_bb) == 0)
     163            bb_method = BB_PADBAD;
     164        else
     165            bb_show_usage();
    140166    }
    141167
    … …  
    163189        if (tmp != blockstart) {
    164190            /* bad block(s), advance mtdoffset */
    165             if (IS_NANDDUMP && !(opts & OPT_b)) {
    166                 int bad_len = MIN(tmp, end_addr) - mtdoffset;
    167                 dump_bad(&meminfo, bad_len, opts & OPT_o);
     191            if (IS_NANDDUMP) {
     192                if (bb_method == BB_PADBAD) {
     193                    int bad_len = MIN(tmp, end_addr) - mtdoffset;
     194                    dump_bad(&meminfo, bad_len, opts & OPT_o);
     195                }
     196                /* with option skipbad, increase the total length */
     197                if (bb_method == BB_SKIPBAD) {
     198                    end_addr += (tmp - blockstart);
     199                }
    168200            }
    169201            mtdoffset = tmp;
    … …  
    183215            if (IS_NANDWRITE)
    184216                printf("Writing at 0x%08x\n", mtdoffset);
    185             else if (mtdoffset > blockstart && !(opts & OPT_b)) {
    186                 int bad_len = MIN(mtdoffset, limit) - blockstart;
    187                 dump_bad(&meminfo, bad_len, opts & OPT_o);
     217            else if (mtdoffset > blockstart) {
     218                if (bb_method == BB_PADBAD) {
     219                    /* dump FF padded bad block */
     220                    int bad_len = MIN(mtdoffset, limit) - blockstart;
     221                    dump_bad(&meminfo, bad_len, opts & OPT_o);
     222                } else if (bb_method == BB_SKIPBAD) {
     223                    /* for skipbad, increase the length */
     224                    if ((end_addr + mtdoffset - blockstart) > end_addr)
     225                        end_addr += (mtdoffset - blockstart);
     226                    else
     227                        end_addr = ~0;
     228                    limit = MIN(meminfo.size, end_addr);
     229                }
    188230            }
    189231            if (mtdoffset >= limit)
  • branches/3.3/mindi-busybox/miscutils/rfkill.c

    r3232 r3621  
    77* Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88*/
     9
     10//config:config RFKILL
     11//config:   bool "rfkill"
     12//config:   default n # doesn't build on Ubuntu 9.04
     13//config:   select PLATFORM_LINUX
     14//config:   help
     15//config:     Enable/disable wireless devices.
     16//config:
     17//config:     rfkill list : list all wireless devices
     18//config:     rfkill list bluetooth : list all bluetooth devices
     19//config:     rfkill list 1 : list device corresponding to the given index
     20//config:     rfkill block|unblock wlan : block/unblock all wlan(wifi) devices
     21//config:
     22
     23//applet:IF_RFKILL(APPLET(rfkill, BB_DIR_USR_SBIN, BB_SUID_DROP))
     24
     25//kbuild:lib-$(CONFIG_RFKILL) += rfkill.o
    926
    1027//usage:#define rfkill_trivial_usage
  • branches/3.3/mindi-busybox/miscutils/runlevel.c

    r3232 r3621  
    3030int runlevel_main(int argc UNUSED_PARAM, char **argv)
    3131{
    32     struct utmp *ut;
     32    struct utmpx *ut;
    3333    char prev;
    3434
    35     if (argv[1]) utmpname(argv[1]);
     35    if (argv[1]) utmpxname(argv[1]);
    3636
    37     setutent();
    38     while ((ut = getutent()) != NULL) {
     37    setutxent();
     38    while ((ut = getutxent()) != NULL) {
    3939        if (ut->ut_type == RUN_LVL) {
    4040            prev = ut->ut_pid / 256;
    … …  
    4242            printf("%c %c\n", prev, ut->ut_pid % 256);
    4343            if (ENABLE_FEATURE_CLEAN_UP)
    44                 endutent();
     44                endutxent();
    4545            return 0;
    4646        }
    … …  
    5050
    5151    if (ENABLE_FEATURE_CLEAN_UP)
    52         endutent();
     52        endutxent();
    5353    return 1;
    5454}
  • branches/3.3/mindi-busybox/miscutils/setsid.c

    r3232 r3621  
    1616
    1717//usage:#define setsid_trivial_usage
    18 //usage:       "PROG ARGS"
     18//usage:       "[-c] PROG ARGS"
    1919//usage:#define setsid_full_usage "\n\n"
    2020//usage:       "Run PROG in a new session. PROG will have no controlling terminal\n"
    21 //usage:       "and will not be affected by keyboard signals (Ctrl-C etc).\n"
    22 //usage:       "See setsid(2) for details."
     21//usage:       "and will not be affected by keyboard signals (^C etc).\n"
     22//usage:     "\n    -c  Set controlling terminal to stdin"
    2323
    2424#include "libbb.h"
    … …  
    2727int setsid_main(int argc UNUSED_PARAM, char **argv)
    2828{
    29     if (!argv[1])
    30         bb_show_usage();
     29    unsigned opt;
     30
     31    opt_complementary = "-1"; /* at least one arg */
     32    opt = getopt32(argv, "+c"); /* +: stop on first non-opt */
     33    argv += optind;
    3134
    3235    /* setsid() is allowed only when we are not a process group leader.
    3336     * Otherwise our PID serves as PGID of some existing process group
    34      * and cannot be used as PGID of a new process group. */
     37     * and cannot be used as PGID of a new process group.
     38     *
     39     * Example: setsid() below fails when run alone in interactive shell:
     40     *  $ setsid PROG
     41     * because shell's child (setsid) is put in a new process group.
     42     * But doesn't fail if shell is not interactive
     43     * (and therefore doesn't create process groups for pipes),
     44     * or if setsid is not the first process in the process group:
     45     *  $ true | setsid PROG
     46     * or if setsid is executed in backquotes (`setsid PROG`)...
     47     */
    3548    if (setsid() < 0) {
    3649        pid_t pid = fork_or_rexec(argv);
    … …  
    4457             * does not do such trick.
    4558             */
    46             exit(EXIT_SUCCESS);
     59            return EXIT_SUCCESS;
    4760        }
    4861
    … …  
    5265    }
    5366
    54     argv++;
     67    if (opt) {
     68        /* -c: set (with stealing) controlling tty */
     69        ioctl(0, TIOCSCTTY, 1);
     70    }
     71
    5572    BB_EXECVP_or_die(argv);
    5673}
  • branches/3.3/mindi-busybox/miscutils/taskset.c

    r3232 r3621  
    66 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    77 */
     8
     9//config:config TASKSET
     10//config:   bool "taskset"
     11//config:   default n  # doesn't build on some non-x86 targets (m68k)
     12//config:   help
     13//config:     Retrieve or set a processes's CPU affinity.
     14//config:     This requires sched_{g,s}etaffinity support in your libc.
     15//config:
     16//config:config FEATURE_TASKSET_FANCY
     17//config:   bool "Fancy output"
     18//config:   default y
     19//config:   depends on TASKSET
     20//config:   help
     21//config:     Add code for fancy output. This merely silences a compiler-warning
     22//config:     and adds about 135 Bytes. May be needed for machines with alot
     23//config:     of CPUs.
     24
     25//applet:IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP))
     26//kbuild:lib-$(CONFIG_TASKSET) += taskset.o
    827
    928//usage:#define taskset_trivial_usage
    … …  
    2342//usage:       "$ taskset -p 1\n"
    2443//usage:       "pid 1's current affinity mask: 3\n"
     44/*
     45 Not yet implemented:
     46 * -a/--all-tasks (affect all threads)
     47 * -c/--cpu-list  (specify CPUs via "1,3,5-7")
     48 */
    2549
    2650#include <sched.h>
    … …  
    5276static unsigned long long from_cpuset(cpu_set_t *mask)
    5377{
    54     struct BUG_CPU_SETSIZE_is_too_small {
    55         char BUG_CPU_SETSIZE_is_too_small[
    56             CPU_SETSIZE < sizeof(int) ? -1 : 1];
    57     };
    58     char *p = (void*)mask;
    59 
    60     /* Take the least significant bits. Careful!
    61      * Consider both CPU_SETSIZE=4 and CPU_SETSIZE=1024 cases
     78    BUILD_BUG_ON(CPU_SETSIZE < 8*sizeof(int));
     79
     80    /* Take the least significant bits. Assume cpu_set_t is
     81     * implemented as an array of unsigned long or unsigned
     82     * int.
    6283     */
    63 #if BB_BIG_ENDIAN
    64     /* For big endian, it means LAST bits */
    65     if (CPU_SETSIZE < sizeof(long))
    66         p += CPU_SETSIZE - sizeof(int);
    67     else if (CPU_SETSIZE < sizeof(long long))
    68         p += CPU_SETSIZE - sizeof(long);
    69     else
    70         p += CPU_SETSIZE - sizeof(long long);
    71 #endif
    72     if (CPU_SETSIZE < sizeof(long))
    73         return *(unsigned*)p;
    74     if (CPU_SETSIZE < sizeof(long long))
    75         return *(unsigned long*)p;
    76     return *(unsigned long long*)p;
     84    if (CPU_SETSIZE < 8*sizeof(long))
     85        return *(unsigned*)mask;
     86    if (CPU_SETSIZE < 8*sizeof(long long))
     87        return *(unsigned long*)mask;
     88# if BB_BIG_ENDIAN
     89    if (sizeof(long long) > sizeof(long)) {
     90        /* We can put two long in the long long, but they have to
     91         * be swapped: the least significant word comes first in the
     92         * array */
     93        unsigned long *p = (void*)mask;
     94        return p[0] + ((unsigned long long)p[1] << (8*sizeof(long)));
     95    }
     96# endif
     97    return *(unsigned long long*)mask;
    7798}
    7899#endif
    … …  
    129150    }
    130151
    131     { /* Affinity was specified, translate it into cpu_set_t */
     152    /* Affinity was specified, translate it into cpu_set_t */
     153    CPU_ZERO(&mask);
     154    if (!ENABLE_FEATURE_TASKSET_FANCY) {
    132155        unsigned i;
     156        unsigned long long m;
     157
    133158        /* Do not allow zero mask: */
    134         unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX);
    135         enum { CNT_BIT = CPU_SETSIZE < sizeof(m)*8 ? CPU_SETSIZE : sizeof(m)*8 };
    136 
    137         CPU_ZERO(&mask);
    138         for (i = 0; i < CNT_BIT; i++) {
    139             unsigned long long bit = (1ULL << i);
    140             if (bit & m)
     159        m = xstrtoull_range(aff, 0, 1, ULLONG_MAX);
     160        i = 0;
     161        do {
     162            if (m & 1)
    141163                CPU_SET(i, &mask);
     164            i++;
     165            m >>= 1;
     166        } while (m != 0);
     167    } else {
     168        unsigned i;
     169        char *last_byte;
     170        char *bin;
     171        uint8_t bit_in_byte;
     172
     173        /* Cheap way to get "long enough" buffer */
     174        bin = xstrdup(aff);
     175
     176        if (aff[0] != '0' || (aff[1]|0x20) != 'x') {
     177/* TODO: decimal/octal masks are still limited to 2^64 */
     178            unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX);
     179            bin += strlen(bin);
     180            last_byte = bin - 1;
     181            while (m) {
     182                *--bin = m & 0xff;
     183                m >>= 8;
     184            }
     185        } else {
     186            /* aff is "0x.....", we accept very long masks in this form */
     187            last_byte = hex2bin(bin, aff + 2, INT_MAX);
     188            if (!last_byte) {
     189 bad_aff:
     190                bb_error_msg_and_die("bad affinity '%s'", aff);
     191            }
     192            last_byte--; /* now points to the last byte */
     193        }
     194
     195        i = 0;
     196        bit_in_byte = 1;
     197        while (last_byte >= bin) {
     198            if (bit_in_byte & *last_byte) {
     199                if (i >= CPU_SETSIZE)
     200                    goto bad_aff;
     201                CPU_SET(i, &mask);
     202                //bb_error_msg("bit %d set", i);
     203            }
     204            i++;
     205            /* bit_in_byte is uint8_t! & 0xff is implied */
     206            bit_in_byte = (bit_in_byte << 1);
     207            if (!bit_in_byte) {
     208                bit_in_byte = 1;
     209                last_byte--;
     210            }
    142211        }
    143212    }
  • branches/3.3/mindi-busybox/miscutils/wall.c

    r3232 r3621  
    66 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    77 */
     8
     9//config:config WALL
     10//config:   bool "wall"
     11//config:   default y
     12//config:   depends on FEATURE_UTMP
     13//config:   help
     14//config:     Write a message to all users that are logged in.
     15
     16/* Needs to be run by root or be suid root - needs to write to /dev/TTY: */
     17//applet:IF_WALL(APPLET(wall, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
     18
     19//kbuild:lib-$(CONFIG_WALL) += wall.o
    820
    921//usage:#define wall_trivial_usage
    … …  
    2133int wall_main(int argc UNUSED_PARAM, char **argv)
    2234{
    23     struct utmp *ut;
     35    struct utmpx *ut;
    2436    char *msg;
    25     int fd = argv[1] ? xopen(argv[1], O_RDONLY) : STDIN_FILENO;
     37    int fd;
    2638
     39    fd = STDIN_FILENO;
     40    if (argv[1]) {
     41        /* The applet is setuid.
     42         * Access to the file must be under user's uid/gid.
     43         */
     44        fd = xopen_as_uid_gid(argv[1], O_RDONLY, getuid(), getgid());
     45    }
    2746    msg = xmalloc_read(fd, NULL);
    2847    if (ENABLE_FEATURE_CLEAN_UP && argv[1])
    2948        close(fd);
    30     setutent();
    31     while ((ut = getutent()) != NULL) {
     49    setutxent();
     50    while ((ut = getutxent()) != NULL) {
    3251        char *line;
    3352        if (ut->ut_type != USER_PROCESS)
    … …  
    3857    }
    3958    if (ENABLE_FEATURE_CLEAN_UP) {
    40         endutent();
     59        endutxent();
    4160        free(msg);
    4261    }
Note: See TracChangeset for help on using the changeset viewer.