From b771c654cab511b172484479cafd006d52588103 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 13 Sep 2010 00:34:26 +0200 Subject: shell: shrink arith code; and prepare for returning text error codes function old new delta arith 701 680 -21 Signed-off-by: Denys Vlasenko --- shell/hush.c | 8 ++-- shell/math.c | 120 +++++++++++++++++++++++++++++------------------------------ 2 files changed, 63 insertions(+), 65 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 752efd0c8..ef0c454ec 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4728,9 +4728,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha if (beg < 0) /* bash compat */ beg = 0; debug_printf_varexp("from val:'%s'\n", val); - if (len == 0 || !val || beg >= strlen(val)) - val = ""; - else { + if (len == 0 || !val || beg >= strlen(val)) { + val = NULL; + } else { /* Paranoia. What if user entered 9999999999999 * which fits in arith_t but not int? */ if (len >= INT_MAX) @@ -4742,7 +4742,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha #endif { die_if_script("malformed ${%s:...}", var); - val = ""; + val = NULL; } } else { /* one of "-=+?" */ /* Standard-mandated substitution ops: diff --git a/shell/math.c b/shell/math.c index a4c55a4d0..2f093391f 100644 --- a/shell/math.c +++ b/shell/math.c @@ -124,9 +124,6 @@ #define setvar (math_hooks->setvar ) //#define endofname (math_hooks->endofname) -#define arith_isspace(arithval) \ - (arithval == ' ' || arithval == '\n' || arithval == '\t') - typedef unsigned char operator; /* An operator's token id is a bit of a bitfield. The lower 5 bits are the @@ -156,7 +153,7 @@ typedef unsigned char operator; #define TOK_REM_ASSIGN tok_decl(3,2) /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */ -#define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0) +#define convert_prec_is_assign(prec) do { if (prec == 3) prec = 2; } while (0) /* conditional is right associativity too */ #define TOK_CONDITIONAL tok_decl(4,0) @@ -223,7 +220,7 @@ tok_have_assign(operator op) { operator prec = PREC(op); - convert_prec_is_assing(prec); + convert_prec_is_assign(prec); return (prec == PREC(TOK_ASSIGN) || prec == PREC_PRE || prec == PREC_POST); } @@ -477,7 +474,7 @@ static const char op_tokens[] ALIGN1 = { 0 }; /* ptr to ")" */ -#define endexpression (&op_tokens[sizeof(op_tokens)-7]) +#define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7]) const char* FAST_FUNC endofname(const char *name) @@ -494,32 +491,36 @@ endofname(const char *name) arith_t arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) { - char arithval; /* Current character under analysis */ - operator lasttok, op; - operator prec; - operator *stack, *stackptr; - const char *p = endexpression; + operator lasttok; int errcode; - v_n_t *numstack, *numstackptr; - unsigned datasizes = strlen(expr) + 2; - + const char *start_expr = expr = skip_whitespace(expr); + unsigned expr_len = strlen(expr) + 2; /* Stack of integers */ /* The proof that there can be no more than strlen(startbuf)/2+1 integers * in any given correct or incorrect expression is left as an exercise to * the reader. */ - numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0])); + v_n_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0])); + v_n_t *numstackptr = numstack; /* Stack of operator tokens */ - stackptr = stack = alloca(datasizes * sizeof(stack[0])); + operator *const stack = alloca(expr_len * sizeof(stack[0])); + operator *stackptr = stack; *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */ - *perrcode = errcode = 0; + errcode = 0; while (1) { + const char *p; + operator op; + operator prec; + char arithval; + + expr = skip_whitespace(expr); arithval = *expr; - if (arithval == 0) { - if (p == endexpression) { + if (arithval == '\0') { + if (expr == start_expr) { /* Null expression. */ - return 0; + numstack->val = 0; + goto ret; } /* This is only reached after all tokens have been extracted from the @@ -527,38 +528,29 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) * are to be applied in order. At the end, there should be a final * result on the integer stack */ - if (expr != endexpression + 1) { + if (expr != ptr_to_rparen + 1) { /* If we haven't done so already, */ /* append a closing right paren */ - expr = endexpression; + expr = ptr_to_rparen; /* and let the loop process it. */ continue; } /* At this point, we're done with the expression. */ - if (numstackptr != numstack+1) { + if (numstackptr != numstack + 1) { /* ... but if there isn't, it's bad */ - err: - *perrcode = -1; - return *perrcode; + goto err; } if (numstack->var) { /* expression is $((var)) only, lookup now */ errcode = arith_lookup_val(numstack, math_hooks); } - ret: - *perrcode = errcode; - return numstack->val; + goto ret; } - /* Continue processing the expression. */ - if (arith_isspace(arithval)) { - /* Skip whitespace */ - goto prologue; - } p = endofname(expr); if (p != expr) { - size_t var_name_size = (p-expr) + 1; /* trailing zero */ - + /* Name */ + size_t var_name_size = (p-expr) + 1; /* +1 for NUL */ numstackptr->var = alloca(var_name_size); safe_strncpy(numstackptr->var, expr, var_name_size); expr = p; @@ -568,36 +560,37 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) lasttok = TOK_NUM; continue; } + if (isdigit(arithval)) { + /* Number */ numstackptr->var = NULL; errno = 0; - /* call strtoul[l]: */ - numstackptr->val = strto_arith_t(expr, (char **) &expr, 0); + numstackptr->val = strto_arith_t(expr, (char**) &expr, 0); if (errno) numstackptr->val = 0; /* bash compat */ goto num; } - for (p = op_tokens; ; p++) { - const char *o; - if (*p == 0) { - /* strange operator not found */ - goto err; - } - for (o = expr; *p && *o == *p; p++) - o++; - if (!*p) { - /* found */ - expr = o - 1; + /* Should be an operator */ + p = op_tokens; + while (1) { + const char *e = expr; + /* Compare expr to current op_tokens[] element */ + while (*p && *e == *p) + p++, e++; + if (*p == '\0') { /* match: operator is found */ + expr = e; break; } - /* skip tail uncompared token */ + /* Go to next element of op_tokens[] */ while (*p) p++; - /* skip zero delim */ - p++; + p += 2; /* skip NUL and TOK_foo bytes */ + if (*p == '\0') /* no next element, operator not found */ + goto err; } - op = p[1]; + op = p[1]; /* fetch TOK_foo value */ + /* NB: expr now points past the operator */ /* post grammar: a++ reduce to num */ if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC) @@ -651,13 +644,12 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) /* Any operator directly after a */ lasttok = TOK_NUM; /* close paren should consider itself binary */ - goto prologue; + goto next; } } else { operator prev_prec = PREC(stackptr[-1]); - - convert_prec_is_assing(prec); - convert_prec_is_assing(prev_prec); + convert_prec_is_assign(prec); + convert_prec_is_assign(prev_prec); if (prev_prec < prec) break; /* check right assoc */ @@ -665,7 +657,8 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) break; } errcode = arith_apply(*--stackptr, numstack, &numstackptr, math_hooks); - if (errcode) goto ret; + if (errcode) + goto ret; } if (op == TOK_RPAREN) { goto err; @@ -674,9 +667,14 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) /* Push this operator to the stack and remember it. */ *stackptr++ = lasttok = op; - prologue: - ++expr; - } /* while */ + next: ; + } /* while (1) */ + + err: + numstack->val = errcode = -1; + ret: + *perrcode = errcode; + return numstack->val; } /* -- cgit v1.2.3-55-g6feb From 51850c818cf909cde0e07091a8015532cc645b7a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 13 Sep 2010 01:09:11 +0200 Subject: shell: small code shrink function old new delta arith 680 675 -5 Signed-off-by: Denys Vlasenko --- shell/math.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/shell/math.c b/shell/math.c index 2f093391f..c698a442b 100644 --- a/shell/math.c +++ b/shell/math.c @@ -635,28 +635,29 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) goto err; } while (stackptr != stack) { + operator prev_op = *--stackptr; if (op == TOK_RPAREN) { /* The algorithm employed here is simple: while we don't * hit an open paren nor the bottom of the stack, pop * tokens and apply them */ - if (stackptr[-1] == TOK_LPAREN) { - --stackptr; + if (prev_op == TOK_LPAREN) { /* Any operator directly after a */ lasttok = TOK_NUM; /* close paren should consider itself binary */ goto next; } } else { - operator prev_prec = PREC(stackptr[-1]); + operator prev_prec = PREC(prev_op); convert_prec_is_assign(prec); convert_prec_is_assign(prev_prec); - if (prev_prec < prec) - break; - /* check right assoc */ - if (prev_prec == prec && is_right_associativity(prec)) + if (prev_prec < prec + || (prev_prec == prec && is_right_associativity(prec)) + ) { + stackptr++; break; + } } - errcode = arith_apply(*--stackptr, numstack, &numstackptr, math_hooks); + errcode = arith_apply(prev_op, numstack, &numstackptr, math_hooks); if (errcode) goto ret; } -- cgit v1.2.3-55-g6feb From bd14770b0c8594ce5b0ab9b0b1249b72fc781dd3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 13 Sep 2010 11:11:40 +0200 Subject: shell/math.c: small code shrink; fixed incomprehensible comments function old new delta arith_apply 1334 1304 -30 Signed-off-by: Denys Vlasenko --- shell/math.c | 225 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 113 insertions(+), 112 deletions(-) diff --git a/shell/math.c b/shell/math.c index c698a442b..a9fbc8910 100644 --- a/shell/math.c +++ b/shell/math.c @@ -52,17 +52,18 @@ * than a comparable parser written in yacc. The supported operators are * listed in #defines below. Parens, order of operations, and error handling * are supported. This code is thread safe. The exact expression format should - * be that which POSIX specifies for shells. */ - -/* The code uses a simple two-stack algorithm. See + * be that which POSIX specifies for shells. + * + * The code uses a simple two-stack algorithm. See * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html * for a detailed explanation of the infix-to-postfix algorithm on which * this is based (this code differs in that it applies operators immediately * to the stack instead of adding them to a queue to end up with an - * expression). */ - -/* To use the routine, call it with an expression string and error return - * pointer */ + * expression). + * + * To use the routine, call it with an expression string and error return + * pointer + */ /* * Aug 24, 2001 Manuel Novoa III @@ -104,22 +105,21 @@ * (C) 2003 Vladimir Oleynik * * - allow access to variable, - * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6) - * - realize assign syntax (VAR=expr, +=, *= etc) - * - realize exponentiation (** operator) - * - realize comma separated - expr, expr - * - realise ++expr --expr expr++ expr-- - * - realise expr ? expr : expr (but, second expr calculate always) + * use recursive value indirection: c="2*2"; a="c"; echo $((a+=2)) produce 6 + * - implement assign syntax (VAR=expr, +=, *= etc) + * - implement exponentiation (** operator) + * - implement comma separated - expr, expr + * - implement ++expr --expr expr++ expr-- + * - implement expr ? expr : expr (but second expr is always calculated) * - allow hexadecimal and octal numbers - * - was restored loses XOR operator - * - remove one goto label, added three ;-) - * - protect $((num num)) as true zero expr (Manuel`s error) + * - restore lost XOR operator + * - protect $((num num)) as true zero expr (Manuel's error) * - always use special isspace(), see comment from bash ;-) */ #include "libbb.h" #include "math.h" -#define a_e_h_t arith_eval_hooks_t +#define a_e_h_t arith_eval_hooks_t #define lookupvar (math_hooks->lookupvar) #define setvar (math_hooks->setvar ) //#define endofname (math_hooks->endofname) @@ -130,103 +130,104 @@ typedef unsigned char operator; * precedence, and 3 high bits are an ID unique across operators of that * precedence. The ID portion is so that multiple operators can have the * same precedence, ensuring that the leftmost one is evaluated first. - * Consider * and /. */ - -#define tok_decl(prec,id) (((id)<<5)|(prec)) -#define PREC(op) ((op) & 0x1F) - -#define TOK_LPAREN tok_decl(0,0) + * Consider * and / + */ +#define tok_decl(prec,id) (((id)<<5) | (prec)) +#define PREC(op) ((op) & 0x1F) -#define TOK_COMMA tok_decl(1,0) +#define TOK_LPAREN tok_decl(0,0) -#define TOK_ASSIGN tok_decl(2,0) -#define TOK_AND_ASSIGN tok_decl(2,1) -#define TOK_OR_ASSIGN tok_decl(2,2) -#define TOK_XOR_ASSIGN tok_decl(2,3) -#define TOK_PLUS_ASSIGN tok_decl(2,4) -#define TOK_MINUS_ASSIGN tok_decl(2,5) -#define TOK_LSHIFT_ASSIGN tok_decl(2,6) -#define TOK_RSHIFT_ASSIGN tok_decl(2,7) +#define TOK_COMMA tok_decl(1,0) -#define TOK_MUL_ASSIGN tok_decl(3,0) -#define TOK_DIV_ASSIGN tok_decl(3,1) -#define TOK_REM_ASSIGN tok_decl(3,2) +/* All assignments are right associative and have the same precedence, + * but there are 11 of them, which doesn't fit into 3 bits for unique id. + * Abusing another precedence level: + */ +#define TOK_ASSIGN tok_decl(2,0) +#define TOK_AND_ASSIGN tok_decl(2,1) +#define TOK_OR_ASSIGN tok_decl(2,2) +#define TOK_XOR_ASSIGN tok_decl(2,3) +#define TOK_PLUS_ASSIGN tok_decl(2,4) +#define TOK_MINUS_ASSIGN tok_decl(2,5) +#define TOK_LSHIFT_ASSIGN tok_decl(2,6) +#define TOK_RSHIFT_ASSIGN tok_decl(2,7) -/* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */ -#define convert_prec_is_assign(prec) do { if (prec == 3) prec = 2; } while (0) +#define TOK_MUL_ASSIGN tok_decl(3,0) +#define TOK_DIV_ASSIGN tok_decl(3,1) +#define TOK_REM_ASSIGN tok_decl(3,2) -/* conditional is right associativity too */ -#define TOK_CONDITIONAL tok_decl(4,0) -#define TOK_CONDITIONAL_SEP tok_decl(4,1) +#define fix_assignment_prec(prec) do { if (prec == 3) prec = 2; } while (0) -#define TOK_OR tok_decl(5,0) +/* ternary conditional operator is right associative too */ +#define TOK_CONDITIONAL tok_decl(4,0) +#define TOK_CONDITIONAL_SEP tok_decl(4,1) -#define TOK_AND tok_decl(6,0) +#define TOK_OR tok_decl(5,0) -#define TOK_BOR tok_decl(7,0) +#define TOK_AND tok_decl(6,0) -#define TOK_BXOR tok_decl(8,0) +#define TOK_BOR tok_decl(7,0) -#define TOK_BAND tok_decl(9,0) +#define TOK_BXOR tok_decl(8,0) -#define TOK_EQ tok_decl(10,0) -#define TOK_NE tok_decl(10,1) +#define TOK_BAND tok_decl(9,0) -#define TOK_LT tok_decl(11,0) -#define TOK_GT tok_decl(11,1) -#define TOK_GE tok_decl(11,2) -#define TOK_LE tok_decl(11,3) +#define TOK_EQ tok_decl(10,0) +#define TOK_NE tok_decl(10,1) -#define TOK_LSHIFT tok_decl(12,0) -#define TOK_RSHIFT tok_decl(12,1) +#define TOK_LT tok_decl(11,0) +#define TOK_GT tok_decl(11,1) +#define TOK_GE tok_decl(11,2) +#define TOK_LE tok_decl(11,3) -#define TOK_ADD tok_decl(13,0) -#define TOK_SUB tok_decl(13,1) +#define TOK_LSHIFT tok_decl(12,0) +#define TOK_RSHIFT tok_decl(12,1) -#define TOK_MUL tok_decl(14,0) -#define TOK_DIV tok_decl(14,1) -#define TOK_REM tok_decl(14,2) +#define TOK_ADD tok_decl(13,0) +#define TOK_SUB tok_decl(13,1) -/* exponent is right associativity */ -#define TOK_EXPONENT tok_decl(15,1) +#define TOK_MUL tok_decl(14,0) +#define TOK_DIV tok_decl(14,1) +#define TOK_REM tok_decl(14,2) -/* For now unary operators. */ -#define UNARYPREC 16 -#define TOK_BNOT tok_decl(UNARYPREC,0) -#define TOK_NOT tok_decl(UNARYPREC,1) +/* exponent is right associative */ +#define TOK_EXPONENT tok_decl(15,1) -#define TOK_UMINUS tok_decl(UNARYPREC+1,0) -#define TOK_UPLUS tok_decl(UNARYPREC+1,1) +/* unary operators */ +#define UNARYPREC 16 +#define TOK_BNOT tok_decl(UNARYPREC,0) +#define TOK_NOT tok_decl(UNARYPREC,1) -#define PREC_PRE (UNARYPREC+2) +#define TOK_UMINUS tok_decl(UNARYPREC+1,0) +#define TOK_UPLUS tok_decl(UNARYPREC+1,1) -#define TOK_PRE_INC tok_decl(PREC_PRE, 0) -#define TOK_PRE_DEC tok_decl(PREC_PRE, 1) +#define PREC_PRE (UNARYPREC+2) -#define PREC_POST (UNARYPREC+3) +#define TOK_PRE_INC tok_decl(PREC_PRE, 0) +#define TOK_PRE_DEC tok_decl(PREC_PRE, 1) -#define TOK_POST_INC tok_decl(PREC_POST, 0) -#define TOK_POST_DEC tok_decl(PREC_POST, 1) +#define PREC_POST (UNARYPREC+3) -#define SPEC_PREC (UNARYPREC+4) +#define TOK_POST_INC tok_decl(PREC_POST, 0) +#define TOK_POST_DEC tok_decl(PREC_POST, 1) -#define TOK_NUM tok_decl(SPEC_PREC, 0) -#define TOK_RPAREN tok_decl(SPEC_PREC, 1) +#define SPEC_PREC (UNARYPREC+4) -#define NUMPTR (*numstackptr) +#define TOK_NUM tok_decl(SPEC_PREC, 0) +#define TOK_RPAREN tok_decl(SPEC_PREC, 1) static int tok_have_assign(operator op) { operator prec = PREC(op); - convert_prec_is_assign(prec); + fix_assignment_prec(prec); return (prec == PREC(TOK_ASSIGN) || prec == PREC_PRE || prec == PREC_POST); } static int -is_right_associativity(operator prec) +is_right_associative(operator prec) { return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) || prec == PREC(TOK_CONDITIONAL)); @@ -255,25 +256,25 @@ arith_lookup_val(v_n_t *t, a_e_h_t *math_hooks) if (p) { int errcode; - - /* recursive try as expression */ chk_var_recursive_looped_t *cur; chk_var_recursive_looped_t cur_save; + /* recursively try p as expression */ + for (cur = prev_chk_var_recursive; cur; cur = cur->next) { if (strcmp(cur->var, t->var) == 0) { /* expression recursion loop detected */ return -5; } } - /* save current lookuped var name */ + /* save current var name */ cur = prev_chk_var_recursive; cur_save.var = t->var; cur_save.next = cur; prev_chk_var_recursive = &cur_save; - t->val = arith (p, &errcode, math_hooks); - /* restore previous ptr after recursiving */ + t->val = arith(p, &errcode, math_hooks); + /* restore previous ptr after recursion */ prev_chk_var_recursive = cur; return errcode; } @@ -283,21 +284,24 @@ arith_lookup_val(v_n_t *t, a_e_h_t *math_hooks) return 0; } -/* "applying" a token means performing it on the top elements on the integer - * stack. For a unary operator it will only change the top element, but a - * binary operator will pop two arguments and push a result */ +/* "Applying" a token means performing it on the top elements on the integer + * stack. For an unary operator it will only change the top element, but a + * binary operator will pop two arguments and push the result */ static NOINLINE int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hooks) { +#define NUMPTR (*numstackptr) + v_n_t *numptr_m1; arith_t numptr_val, rez; int ret_arith_lookup_val; /* There is no operator that can work without arguments */ - if (NUMPTR == numstack) goto err; + if (NUMPTR == numstack) + goto err; numptr_m1 = NUMPTR - 1; - /* check operand is var with noninteger value */ + /* Check operand is var with noninteger value */ ret_arith_lookup_val = arith_lookup_val(numptr_m1, math_hooks); if (ret_arith_lookup_val) return ret_arith_lookup_val; @@ -388,16 +392,13 @@ arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hoo rez = rez ? numptr_val : numptr_m1->contidional_second_val; } else if (op == TOK_EXPONENT) { + arith_t c; if (numptr_val < 0) return -3; /* exponent less than 0 */ - else { - arith_t c = 1; - - if (numptr_val) - while (numptr_val--) - c *= rez; - rez = c; - } + c = 1; + while (--numptr_val >= 0) + c *= rez; + rez = c; } else if (numptr_val==0) /* zero divisor check */ return -2; else if (op == TOK_DIV || op == TOK_DIV_ASSIGN) @@ -422,11 +423,12 @@ arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hoo rez++; } numptr_m1->val = rez; - /* protect geting var value, is number now */ + /* erase var name, it is just a number now */ numptr_m1->var = NULL; return 0; err: return -1; +#undef NUMPTR } /* longest must be first */ @@ -473,7 +475,6 @@ static const char op_tokens[] ALIGN1 = { '(', 0, TOK_LPAREN, 0 }; -/* ptr to ")" */ #define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7]) const char* FAST_FUNC @@ -529,15 +530,15 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) * result on the integer stack */ if (expr != ptr_to_rparen + 1) { - /* If we haven't done so already, */ - /* append a closing right paren */ + /* If we haven't done so already, + * append a closing right paren + * and let the loop process it */ expr = ptr_to_rparen; - /* and let the loop process it. */ continue; } - /* At this point, we're done with the expression. */ + /* At this point, we're done with the expression */ if (numstackptr != numstack + 1) { - /* ... but if there isn't, it's bad */ + /* ...but if there isn't, it's bad */ goto err; } if (numstack->var) { @@ -619,11 +620,11 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) /* We don't want an unary operator to cause recursive descent on the * stack, because there can be many in a row and it could cause an * operator to be evaluated before its argument is pushed onto the - * integer stack. */ - /* But for binary operators, "apply" everything on the operator + * integer stack. + * But for binary operators, "apply" everything on the operator * stack until we find an operator with a lesser priority than the - * one we have just extracted. */ - /* Left paren is given the lowest priority so it will never be + * one we have just extracted. + * Left paren is given the lowest priority so it will never be * "applied" in this way. * if associativity is right and priority eq, applied also skip */ @@ -641,17 +642,17 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) * hit an open paren nor the bottom of the stack, pop * tokens and apply them */ if (prev_op == TOK_LPAREN) { - /* Any operator directly after a */ + /* Any operator directly after a + * close paren should consider itself binary */ lasttok = TOK_NUM; - /* close paren should consider itself binary */ goto next; } } else { operator prev_prec = PREC(prev_op); - convert_prec_is_assign(prec); - convert_prec_is_assign(prev_prec); + fix_assignment_prec(prec); + fix_assignment_prec(prev_prec); if (prev_prec < prec - || (prev_prec == prec && is_right_associativity(prec)) + || (prev_prec == prec && is_right_associative(prec)) ) { stackptr++; break; -- cgit v1.2.3-55-g6feb From 06d44d7dfb709bfe02e74d187cceb8591bbda3b4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 13 Sep 2010 12:49:03 +0200 Subject: shell/math.c: rename arith_eval_hooks to arith_state, put error code into it function old new delta expand_and_evaluate_arith 79 89 +10 arith 675 674 -1 arith_lookup_val 151 142 -9 ash_arith 135 122 -13 arith_apply 1304 1269 -35 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/4 up/down: 10/-58) Total: -48 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 19 ++++++------- shell/hush.c | 11 ++++---- shell/math.c | 38 ++++++++++++------------- shell/math.h | 91 ++++++++++++++++++++++++++++++------------------------------ 4 files changed, 78 insertions(+), 81 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index f631e3d25..c27ab7de2 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5442,22 +5442,21 @@ redirectsafe(union node *redir, int flags) static arith_t ash_arith(const char *s) { - arith_eval_hooks_t math_hooks; + arith_state_t math_state; arith_t result; - int errcode = 0; - math_hooks.lookupvar = lookupvar; - math_hooks.setvar = setvar2; - //math_hooks.endofname = endofname; + math_state.lookupvar = lookupvar; + math_state.setvar = setvar2; + //math_state.endofname = endofname; INT_OFF; - result = arith(s, &errcode, &math_hooks); - if (errcode < 0) { - if (errcode == -3) + result = arith(&math_state, s); + if (math_state.errcode < 0) { + if (math_state.errcode == -3) ash_msg_and_raise_error("exponent less than 0"); - if (errcode == -2) + if (math_state.errcode == -2) ash_msg_and_raise_error("divide by zero"); - if (errcode == -5) + if (math_state.errcode == -5) ash_msg_and_raise_error("expression recursion loop detected"); raise_error_syntax(s); } diff --git a/shell/hush.c b/shell/hush.c index ef0c454ec..4ca5403de 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4463,15 +4463,16 @@ static char *encode_then_expand_string(const char *str, int process_bkslash, int #if ENABLE_SH_MATH_SUPPORT static arith_t expand_and_evaluate_arith(const char *arg, int *errcode_p) { - arith_eval_hooks_t hooks; + arith_state_t math_state; arith_t res; char *exp_str; - hooks.lookupvar = get_local_var_value; - hooks.setvar = set_local_var_from_halves; - //hooks.endofname = endofname; + math_state.lookupvar = get_local_var_value; + math_state.setvar = set_local_var_from_halves; + //math_state.endofname = endofname; exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); - res = arith(exp_str ? exp_str : arg, errcode_p, &hooks); + res = arith(&math_state, exp_str ? exp_str : arg); + *errcode_p = math_state.errcode; free(exp_str); return res; } diff --git a/shell/math.c b/shell/math.c index a9fbc8910..555559a26 100644 --- a/shell/math.c +++ b/shell/math.c @@ -119,10 +119,9 @@ #include "libbb.h" #include "math.h" -#define a_e_h_t arith_eval_hooks_t -#define lookupvar (math_hooks->lookupvar) -#define setvar (math_hooks->setvar ) -//#define endofname (math_hooks->endofname) +#define lookupvar (math_state->lookupvar) +#define setvar (math_state->setvar ) +//#define endofname (math_state->endofname) typedef unsigned char operator; @@ -249,13 +248,12 @@ typedef struct chk_var_recursive_looped_t { static chk_var_recursive_looped_t *prev_chk_var_recursive; static int -arith_lookup_val(v_n_t *t, a_e_h_t *math_hooks) +arith_lookup_val(arith_state_t *math_state, v_n_t *t) { if (t->var) { const char *p = lookupvar(t->var); if (p) { - int errcode; chk_var_recursive_looped_t *cur; chk_var_recursive_looped_t cur_save; @@ -273,10 +271,10 @@ arith_lookup_val(v_n_t *t, a_e_h_t *math_hooks) cur_save.next = cur; prev_chk_var_recursive = &cur_save; - t->val = arith(p, &errcode, math_hooks); + t->val = arith(math_state, p); /* restore previous ptr after recursion */ prev_chk_var_recursive = cur; - return errcode; + return math_state->errcode; } /* allow undefined var as 0 */ t->val = 0; @@ -288,13 +286,13 @@ arith_lookup_val(v_n_t *t, a_e_h_t *math_hooks) * stack. For an unary operator it will only change the top element, but a * binary operator will pop two arguments and push the result */ static NOINLINE int -arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hooks) +arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **numstackptr) { #define NUMPTR (*numstackptr) v_n_t *numptr_m1; arith_t numptr_val, rez; - int ret_arith_lookup_val; + int err; /* There is no operator that can work without arguments */ if (NUMPTR == numstack) @@ -302,9 +300,9 @@ arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hoo numptr_m1 = NUMPTR - 1; /* Check operand is var with noninteger value */ - ret_arith_lookup_val = arith_lookup_val(numptr_m1, math_hooks); - if (ret_arith_lookup_val) - return ret_arith_lookup_val; + err = arith_lookup_val(math_state, numptr_m1); + if (err) + return err; rez = numptr_m1->val; if (op == TOK_UMINUS) @@ -339,9 +337,9 @@ arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hoo numptr_m1 = NUMPTR - 1; if (op != TOK_ASSIGN) { /* check operand is var with noninteger value for not '=' */ - ret_arith_lookup_val = arith_lookup_val(numptr_m1, math_hooks); - if (ret_arith_lookup_val) - return ret_arith_lookup_val; + err = arith_lookup_val(math_state, numptr_m1); + if (err) + return err; } if (op == TOK_CONDITIONAL) { numptr_m1->contidional_second_val = rez; @@ -490,7 +488,7 @@ endofname(const char *name) } arith_t -arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) +arith(arith_state_t *math_state, const char *expr) { operator lasttok; int errcode; @@ -543,7 +541,7 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) } if (numstack->var) { /* expression is $((var)) only, lookup now */ - errcode = arith_lookup_val(numstack, math_hooks); + errcode = arith_lookup_val(math_state, numstack); } goto ret; } @@ -658,7 +656,7 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) break; } } - errcode = arith_apply(prev_op, numstack, &numstackptr, math_hooks); + errcode = arith_apply(math_state, prev_op, numstack, &numstackptr); if (errcode) goto ret; } @@ -675,7 +673,7 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) err: numstack->val = errcode = -1; ret: - *perrcode = errcode; + math_state->errcode = errcode; return numstack->val; } diff --git a/shell/math.h b/shell/math.h index 96088b4d2..9f3da7f59 100644 --- a/shell/math.h +++ b/shell/math.h @@ -9,61 +9,59 @@ /* The math library has just one function: * - * arith_t arith(const char *expr, int *perrcode, arith_eval_hooks_t *hooks); + * arith_t arith(arith_state_t *states, const char *expr); * - * The first argument is the math string to parse. All normal expansions must - * be done already. i.e. no dollar symbols should be present. + * The expr argument is the math string to parse. All normal expansions must + * be done already. i.e. no dollar symbols should be present. * - * The second argument is a semi-detailed error description in case something - * goes wrong in the parsing steps. Currently, those values are (for - * compatibility, you should assume all negative values are errors): - * 0 - no errors (yay!) - * -1 - unspecified problem - * -2 - divide by zero - * -3 - exponent less than 0 - * -5 - expression recursion loop detected + * The state argument is a pointer to a struct of hooks for your shell (see below), + * and a semi-detailed error code. Currently, those values are (for + * compatibility, you should assume all negative values are errors): + * 0 - no errors (yay!) + * -1 - unspecified problem + * -2 - divide by zero + * -3 - exponent less than 0 + * -5 - expression recursion loop detected * - * The third argument is a struct pointer of hooks for your shell (see below). - * - * The function returns the answer to the expression. So if you called it - * with the expression: - * "1 + 2 + 3" - * You would obviously get back 6. + * The function returns the answer to the expression. So if you called it + * with the expression: + * "1 + 2 + 3" + * you would obviously get back 6. */ /* To add support to a shell, you need to implement three functions: * - * lookupvar() - look up and return the value of a variable + * lookupvar() - look up and return the value of a variable * - * If the shell does: - * foo=123 - * Then the code: - * const char *val = lookupvar("foo"); - * Will result in val pointing to "123" + * If the shell does: + * foo=123 + * Then the code: + * const char *val = lookupvar("foo"); + * will result in val pointing to "123" * - * setvar() - set a variable to some value + * setvar() - set a variable to some value * - * If the arithmetic expansion does something like: - * $(( i = 1)) - * Then the math code will make a call like so: - * setvar("i", "1", 0); - * The storage for the first two parameters are not allocated, so your - * shell implementation will most likely need to strdup() them to save. + * If the arithmetic expansion does something like: + * $(( i = 1)) + * then the math code will make a call like so: + * setvar("i", "1", 0); + * The storage for the first two parameters are not allocated, so your + * shell implementation will most likely need to strdup() them to save. * - * endofname() - return the end of a variable name from input + * endofname() - return the end of a variable name from input * - * The arithmetic code does not know about variable naming conventions. - * So when it is given an experession, it knows something is not numeric, - * but it is up to the shell to dictate what is a valid identifiers. - * So when it encounters something like: - * $(( some_var + 123 )) - * It will make a call like so: - * end = endofname("some_var + 123"); - * So the shell needs to scan the input string and return a pointer to the - * first non-identifier string. In this case, it should return the input - * pointer with an offset pointing to the first space. The typical - * implementation will return the offset of first char that does not match - * the regex (in C locale): ^[a-zA-Z_][a-zA-Z_0-9]* + * The arithmetic code does not know about variable naming conventions. + * So when it is given an experession, it knows something is not numeric, + * but it is up to the shell to dictate what is a valid identifiers. + * So when it encounters something like: + * $(( some_var + 123 )) + * It will make a call like so: + * end = endofname("some_var + 123"); + * So the shell needs to scan the input string and return a pointer to the + * first non-identifier string. In this case, it should return the input + * pointer with an offset pointing to the first space. The typical + * implementation will return the offset of first char that does not match + * the regex (in C locale): ^[a-zA-Z_][a-zA-Z_0-9]* */ /* To make your life easier when dealing with optional 64bit math support, @@ -96,13 +94,14 @@ typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); //typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name); -typedef struct arith_eval_hooks { +typedef struct arith_state_t { arith_var_lookup_t lookupvar; arith_var_set_t setvar; // arith_var_endofname_t endofname; -} arith_eval_hooks_t; + int errcode; +} arith_state_t; -arith_t arith(const char *expr, int *perrcode, arith_eval_hooks_t*); +arith_t arith(arith_state_t *state, const char *expr); POP_SAVED_FUNCTION_VISIBILITY -- cgit v1.2.3-55-g6feb From 0eac8ff1648f94a79a0e21731ec993dd73d946db Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 13 Sep 2010 12:49:52 +0200 Subject: shell/math.c: stop using bss variable function old new delta evaluate_string - 678 +678 expand_one_var 1543 1563 +20 builtin_type 114 116 +2 expand_and_evaluate_arith 89 87 -2 prev_chk_var_recursive 4 - -4 ash_arith 122 118 -4 arith_lookup_val 142 132 -10 arith 674 12 -662 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 2/4 up/down: 700/-682) Total: 18 bytes Signed-off-by: Denys Vlasenko --- shell/math.c | 54 ++++++++++++++++++++++++++++++++++-------------------- shell/math.h | 5 +++-- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/shell/math.c b/shell/math.c index 555559a26..839715776 100644 --- a/shell/math.c +++ b/shell/math.c @@ -232,6 +232,7 @@ is_right_associative(operator prec) || prec == PREC(TOK_CONDITIONAL)); } + typedef struct { arith_t val; arith_t contidional_second_val; @@ -240,43 +241,49 @@ typedef struct { else is variable name */ } v_n_t; -typedef struct chk_var_recursive_looped_t { +typedef struct remembered_name { + struct remembered_name *next; const char *var; - struct chk_var_recursive_looped_t *next; -} chk_var_recursive_looped_t; +} remembered_name; + -static chk_var_recursive_looped_t *prev_chk_var_recursive; +static arith_t FAST_FUNC +evaluate_string(arith_state_t *math_state, const char *expr); static int arith_lookup_val(arith_state_t *math_state, v_n_t *t) { if (t->var) { const char *p = lookupvar(t->var); - if (p) { - chk_var_recursive_looped_t *cur; - chk_var_recursive_looped_t cur_save; + remembered_name *cur; + remembered_name cur_save; - /* recursively try p as expression */ - - for (cur = prev_chk_var_recursive; cur; cur = cur->next) { + /* did we already see this name? + * testcase: a=b; b=a; echo $((a)) + */ + for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) { if (strcmp(cur->var, t->var) == 0) { - /* expression recursion loop detected */ + /* Yes. Expression recursion loop detected */ return -5; } } - /* save current var name */ - cur = prev_chk_var_recursive; + + /* push current var name */ + cur = math_state->list_of_recursed_names; cur_save.var = t->var; cur_save.next = cur; - prev_chk_var_recursive = &cur_save; + math_state->list_of_recursed_names = &cur_save; + + /* recursively evaluate p as expression */ + t->val = evaluate_string(math_state, p); + + /* pop current var name */ + math_state->list_of_recursed_names = cur; - t->val = arith(math_state, p); - /* restore previous ptr after recursion */ - prev_chk_var_recursive = cur; return math_state->errcode; } - /* allow undefined var as 0 */ + /* treat undefined var as 0 */ t->val = 0; } return 0; @@ -487,8 +494,8 @@ endofname(const char *name) return name; } -arith_t -arith(arith_state_t *math_state, const char *expr) +static arith_t FAST_FUNC +evaluate_string(arith_state_t *math_state, const char *expr) { operator lasttok; int errcode; @@ -677,6 +684,13 @@ arith(arith_state_t *math_state, const char *expr) return numstack->val; } +arith_t FAST_FUNC +arith(arith_state_t *math_state, const char *expr) +{ + math_state->list_of_recursed_names = NULL; + return evaluate_string(math_state, expr); +} + /* * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. diff --git a/shell/math.h b/shell/math.h index 9f3da7f59..e34b65d5d 100644 --- a/shell/math.h +++ b/shell/math.h @@ -95,13 +95,14 @@ typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *v //typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name); typedef struct arith_state_t { + int errcode; arith_var_lookup_t lookupvar; arith_var_set_t setvar; // arith_var_endofname_t endofname; - int errcode; + void *list_of_recursed_names; } arith_state_t; -arith_t arith(arith_state_t *state, const char *expr); +arith_t FAST_FUNC arith(arith_state_t *state, const char *expr); POP_SAVED_FUNCTION_VISIBILITY -- cgit v1.2.3-55-g6feb From 197a6b3c14a8be7101903118516e0e16ec843eb5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 14 Sep 2010 12:57:05 +0200 Subject: sleep: make it non-NOFORK. Fixes ^C in standalone shell Signed-off-by: Denys Vlasenko --- coreutils/sleep.c | 2 +- include/applets.src.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/coreutils/sleep.c b/coreutils/sleep.c index b983df47e..12798d9a7 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c @@ -20,7 +20,7 @@ #include "libbb.h" -/* This is a NOFORK applet. Be very careful! */ +/* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells */ #if ENABLE_FEATURE_FANCY_SLEEP || ENABLE_FEATURE_FLOAT_SLEEP diff --git a/include/applets.src.h b/include/applets.src.h index 0e4f966de..106b72077 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -345,7 +345,8 @@ IF_SHA256SUM(APPLET_ODDNAME(sha256sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_D IF_SHA512SUM(APPLET_ODDNAME(sha512sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha512sum)) IF_SHOWKEY(APPLET(showkey, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_SLATTACH(APPLET(slattach, _BB_DIR_SBIN, _BB_SUID_DROP)) -IF_SLEEP(APPLET_NOFORK(sleep, sleep, _BB_DIR_BIN, _BB_SUID_DROP, sleep)) +/* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells */ +IF_SLEEP(APPLET(sleep, _BB_DIR_BIN, _BB_SUID_DROP)) IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, _BB_DIR_USR_BIN, _BB_SUID_DROP, softlimit)) IF_SORT(APPLET_NOEXEC(sort, sort, _BB_DIR_USR_BIN, _BB_SUID_DROP, sort)) IF_SPLIT(APPLET(split, _BB_DIR_USR_BIN, _BB_SUID_DROP)) @@ -358,7 +359,7 @@ IF_SULOGIN(APPLET(sulogin, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_SUM(APPLET(sum, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_SV(APPLET(sv, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_SVLOGD(APPLET(svlogd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) -IF_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, _BB_DIR_SBIN, _BB_SUID_DROP,swapoff)) +IF_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, _BB_DIR_SBIN, _BB_SUID_DROP, swapoff)) IF_SWAPONOFF(APPLET_ODDNAME(swapon, swap_on_off, _BB_DIR_SBIN, _BB_SUID_DROP, swapon)) IF_SWITCH_ROOT(APPLET(switch_root, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_SYNC(APPLET_NOFORK(sync, sync, _BB_DIR_BIN, _BB_SUID_DROP, sync)) -- cgit v1.2.3-55-g6feb From 063847d6bd23e184c409f37645ba90fa4d039ada Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 15 Sep 2010 13:33:02 +0200 Subject: shell/math: return string error indicator, not integer function old new delta expand_and_evaluate_arith 87 106 +19 expand_one_var 1563 1570 +7 arith 12 18 +6 evaluate_string 678 680 +2 arith_apply 1269 1271 +2 builtin_umask 133 132 -1 ash_arith 118 75 -43 expand_vars_to_list 1094 1038 -56 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 5/3 up/down: 36/-100) Total: -64 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 11 +---- shell/ash_test/ash-arith/arith.right | 56 +++++++++++------------ shell/hush.c | 40 +++++++---------- shell/hush_test/hush-arith/arith.right | 54 +++++++++++------------ shell/math.c | 81 +++++++++++++++++----------------- shell/math.h | 2 +- 6 files changed, 113 insertions(+), 131 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index c27ab7de2..ec887e088 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5451,15 +5451,8 @@ ash_arith(const char *s) INT_OFF; result = arith(&math_state, s); - if (math_state.errcode < 0) { - if (math_state.errcode == -3) - ash_msg_and_raise_error("exponent less than 0"); - if (math_state.errcode == -2) - ash_msg_and_raise_error("divide by zero"); - if (math_state.errcode == -5) - ash_msg_and_raise_error("expression recursion loop detected"); - raise_error_syntax(s); - } + if (math_state.errmsg) + ash_msg_and_raise_error(math_state.errmsg); INT_ON; return result; diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right index 3ea7ce680..7257cc566 100644 --- a/shell/ash_test/ash-arith/arith.right +++ b/shell/ash_test/ash-arith/arith.right @@ -55,28 +55,28 @@ Format: 'expected actual' 30 30 20 20 30 30 -./arith.tests: line 117: syntax error: 1 ? 20 : x+=2 +./arith.tests: line 117: arithmetic syntax error 6 6 6,5,3 6,5,3 263 263 255 255 40 40 -./arith.tests: line 163: syntax error: 7 = 43 +./arith.tests: line 163: arithmetic syntax error ./arith.tests: line 165: divide by zero -./arith.tests: let: line 166: syntax error: jv += $iv -./arith.tests: line 167: syntax error: jv += $iv -./arith.tests: let: line 168: syntax error: rv = 7 + (43 * 6 +./arith.tests: let: line 166: arithmetic syntax error +./arith.tests: line 167: arithmetic syntax error +./arith.tests: let: line 168: arithmetic syntax error abc def ghi -./arith.tests: line 191: syntax error: ( 4 + A ) + 4 +./arith.tests: line 191: arithmetic syntax error 16 16 -./arith.tests: line 196: syntax error: 4 ? : 3 + 5 -./arith.tests: line 197: syntax error: 1 ? 20 -./arith.tests: line 198: syntax error: 4 ? 20 : +./arith.tests: line 196: arithmetic syntax error +./arith.tests: line 197: arithmetic syntax error +./arith.tests: line 198: arithmetic syntax error 9 9 -./arith.tests: line 205: syntax error: 0 && B=42 -./arith.tests: line 208: syntax error: 1 || B=88 +./arith.tests: line 205: arithmetic syntax error +./arith.tests: line 208: arithmetic syntax error 9 9 9 9 9 9 @@ -97,18 +97,18 @@ ghi 3 3 4 4 4 4 -./arith.tests: line 257: syntax error: 7-- -./arith.tests: line 259: syntax error: --x=7 -./arith.tests: line 260: syntax error: ++x=7 -./arith.tests: line 262: syntax error: x++=7 -./arith.tests: line 263: syntax error: x--=7 +./arith.tests: line 257: arithmetic syntax error +./arith.tests: line 259: arithmetic syntax error +./arith.tests: line 260: arithmetic syntax error +./arith.tests: line 262: arithmetic syntax error +./arith.tests: line 263: arithmetic syntax error 4 4 7 7 -7 -7 -./arith1.sub: line 2: syntax error: 4-- -./arith1.sub: line 3: syntax error: 4++ -./arith1.sub: line 4: syntax error: 4 -- -./arith1.sub: line 5: syntax error: 4 ++ +./arith1.sub: line 2: arithmetic syntax error +./arith1.sub: line 3: arithmetic syntax error +./arith1.sub: line 4: arithmetic syntax error +./arith1.sub: line 5: arithmetic syntax error 6 6 3 3 7 7 @@ -119,19 +119,19 @@ ghi 2 2 -2 -2 1 1 -./arith1.sub: line 37: syntax error: +++7 -./arith2.sub: line 2: syntax error: --7 -./arith2.sub: line 3: syntax error: ++7 -./arith2.sub: line 4: syntax error: -- 7 -./arith2.sub: line 5: syntax error: ++ 7 +./arith1.sub: line 37: arithmetic syntax error +./arith2.sub: line 2: arithmetic syntax error +./arith2.sub: line 3: arithmetic syntax error +./arith2.sub: line 4: arithmetic syntax error +./arith2.sub: line 5: arithmetic syntax error 5 5 1 1 4 4 0 0 -./arith2.sub: line 42: syntax error: -- - 7 -./arith2.sub: line 47: syntax error: ++ + 7 +./arith2.sub: line 42: arithmetic syntax error +./arith2.sub: line 47: arithmetic syntax error 8 12 -./arith.tests: line 290: syntax error: a b +./arith.tests: line 290: arithmetic syntax error 42 42 42 diff --git a/shell/hush.c b/shell/hush.c index 4ca5403de..ad30ac1ea 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4461,7 +4461,7 @@ static char *encode_then_expand_string(const char *str, int process_bkslash, int } #if ENABLE_SH_MATH_SUPPORT -static arith_t expand_and_evaluate_arith(const char *arg, int *errcode_p) +static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) { arith_state_t math_state; arith_t res; @@ -4472,8 +4472,11 @@ static arith_t expand_and_evaluate_arith(const char *arg, int *errcode_p) //math_state.endofname = endofname; exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); res = arith(&math_state, exp_str ? exp_str : arg); - *errcode_p = math_state.errcode; free(exp_str); + if (errmsg_p) + *errmsg_p = math_state.errmsg; + if (math_state.errmsg) + die_if_script(math_state.errmsg); return res; } #endif @@ -4714,22 +4717,26 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha * var:NM */ arith_t beg, len; - int errcode = 0; + const char *errmsg; - beg = expand_and_evaluate_arith(exp_word, &errcode); + beg = expand_and_evaluate_arith(exp_word, &errmsg); + if (errmsg) + goto arith_err; debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg); *p++ = SPECIAL_VAR_SYMBOL; exp_word = p; p = strchr(p, SPECIAL_VAR_SYMBOL); *p = '\0'; - len = expand_and_evaluate_arith(exp_word, &errcode); + len = expand_and_evaluate_arith(exp_word, &errmsg); + if (errmsg) + goto arith_err; debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len); - - if (errcode >= 0 && len >= 0) { /* bash compat: len < 0 is illegal */ + if (len >= 0) { /* bash compat: len < 0 is illegal */ if (beg < 0) /* bash compat */ beg = 0; debug_printf_varexp("from val:'%s'\n", val); if (len == 0 || !val || beg >= strlen(val)) { + arith_err: val = NULL; } else { /* Paranoia. What if user entered 9999999999999 @@ -4926,28 +4933,11 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) #if ENABLE_SH_MATH_SUPPORT case '+': { /* +cmd */ arith_t res; - int errcode; arg++; /* skip '+' */ *p = '\0'; /* replace trailing */ debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch); - res = expand_and_evaluate_arith(arg, &errcode); - - if (errcode < 0) { - const char *msg = "error in arithmetic"; - switch (errcode) { - case -3: - msg = "exponent less than 0"; - break; - case -2: - msg = "divide by 0"; - break; - case -5: - msg = "expression recursion loop detected"; - break; - } - die_if_script(msg); - } + res = expand_and_evaluate_arith(arg, NULL); debug_printf_subst("ARITH RES '"arith_t_fmt"'\n", res); sprintf(arith_buf, arith_t_fmt, res); val = arith_buf; diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right index 718c26ad0..fd4ea8e01 100644 --- a/shell/hush_test/hush-arith/arith.right +++ b/shell/hush_test/hush-arith/arith.right @@ -61,7 +61,7 @@ check that the unevaluated part of the ternary operator does not do evaluation o 20 20 30 30 check precedence of assignment vs. conditional operator -hush: error in arithmetic +hush: arithmetic syntax error check precedence of assignment vs. conditional operator associativity of assignment-operator operator 6 6 @@ -70,22 +70,22 @@ octal, hex 263 263 255 255 40 40 -hush: error in arithmetic -hush: divide by 0 +hush: arithmetic syntax error +hush: divide by zero hush: can't execute 'let': No such file or directory -hush: error in arithmetic +hush: arithmetic syntax error hush: can't execute 'let': No such file or directory abc def ghi -hush: error in arithmetic +hush: arithmetic syntax error 16 16 -hush: error in arithmetic -hush: error in arithmetic -hush: error in arithmetic +hush: arithmetic syntax error +hush: arithmetic syntax error +hush: arithmetic syntax error 9 9 -hush: error in arithmetic -hush: error in arithmetic +hush: arithmetic syntax error +hush: arithmetic syntax error 9 9 9 9 9 9 @@ -106,18 +106,18 @@ hush: error in arithmetic 3 3 4 4 4 4 -hush: error in arithmetic -hush: error in arithmetic -hush: error in arithmetic -hush: error in arithmetic -hush: error in arithmetic +hush: arithmetic syntax error +hush: arithmetic syntax error +hush: arithmetic syntax error +hush: arithmetic syntax error +hush: arithmetic syntax error 4 4 7 7 -7 -7 -hush: error in arithmetic -hush: error in arithmetic -hush: error in arithmetic -hush: error in arithmetic +hush: arithmetic syntax error +hush: arithmetic syntax error +hush: arithmetic syntax error +hush: arithmetic syntax error 6 6 3 3 7 7 @@ -128,19 +128,19 @@ hush: error in arithmetic 2 2 -2 -2 1 1 -hush: error in arithmetic -hush: error in arithmetic -hush: error in arithmetic -hush: error in arithmetic -hush: error in arithmetic +hush: arithmetic syntax error +hush: arithmetic syntax error +hush: arithmetic syntax error +hush: arithmetic syntax error +hush: arithmetic syntax error 5 5 1 1 4 4 0 0 -hush: error in arithmetic -hush: error in arithmetic +hush: arithmetic syntax error +hush: arithmetic syntax error 8 12 -hush: error in arithmetic +hush: arithmetic syntax error 42 42 42 diff --git a/shell/math.c b/shell/math.c index 839715776..871c06c3e 100644 --- a/shell/math.c +++ b/shell/math.c @@ -26,26 +26,26 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ /* Copyright (c) 2001 Aaron Lehmann - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ /* This is my infix parser/evaluator. It is optimized for size, intended * as a replacement for yacc-based parsers. However, it may well be faster @@ -60,9 +60,6 @@ * this is based (this code differs in that it applies operators immediately * to the stack instead of adding them to a queue to end up with an * expression). - * - * To use the routine, call it with an expression string and error return - * pointer */ /* @@ -250,7 +247,7 @@ typedef struct remembered_name { static arith_t FAST_FUNC evaluate_string(arith_state_t *math_state, const char *expr); -static int +static const char* arith_lookup_val(arith_state_t *math_state, v_n_t *t) { if (t->var) { @@ -264,8 +261,8 @@ arith_lookup_val(arith_state_t *math_state, v_n_t *t) */ for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) { if (strcmp(cur->var, t->var) == 0) { - /* Yes. Expression recursion loop detected */ - return -5; + /* Yes */ + return "expression recursion loop detected"; } } @@ -281,7 +278,7 @@ arith_lookup_val(arith_state_t *math_state, v_n_t *t) /* pop current var name */ math_state->list_of_recursed_names = cur; - return math_state->errcode; + return math_state->errmsg; } /* treat undefined var as 0 */ t->val = 0; @@ -292,14 +289,14 @@ arith_lookup_val(arith_state_t *math_state, v_n_t *t) /* "Applying" a token means performing it on the top elements on the integer * stack. For an unary operator it will only change the top element, but a * binary operator will pop two arguments and push the result */ -static NOINLINE int +static NOINLINE const char* arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **numstackptr) { #define NUMPTR (*numstackptr) v_n_t *numptr_m1; arith_t numptr_val, rez; - int err; + const char *err; /* There is no operator that can work without arguments */ if (NUMPTR == numstack) @@ -399,13 +396,13 @@ arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **num } else if (op == TOK_EXPONENT) { arith_t c; if (numptr_val < 0) - return -3; /* exponent less than 0 */ + return "exponent less than 0"; c = 1; while (--numptr_val >= 0) c *= rez; rez = c; - } else if (numptr_val==0) /* zero divisor check */ - return -2; + } else if (numptr_val == 0) + return "divide by zero"; else if (op == TOK_DIV || op == TOK_DIV_ASSIGN) rez /= numptr_val; else if (op == TOK_REM || op == TOK_REM_ASSIGN) @@ -430,9 +427,9 @@ arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **num numptr_m1->val = rez; /* erase var name, it is just a number now */ numptr_m1->var = NULL; - return 0; + return NULL; err: - return -1; + return "arithmetic syntax error"; #undef NUMPTR } @@ -498,7 +495,7 @@ static arith_t FAST_FUNC evaluate_string(arith_state_t *math_state, const char *expr) { operator lasttok; - int errcode; + const char *errmsg; const char *start_expr = expr = skip_whitespace(expr); unsigned expr_len = strlen(expr) + 2; /* Stack of integers */ @@ -512,7 +509,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) operator *stackptr = stack; *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */ - errcode = 0; + errmsg = NULL; while (1) { const char *p; @@ -548,7 +545,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) } if (numstack->var) { /* expression is $((var)) only, lookup now */ - errcode = arith_lookup_val(math_state, numstack); + errmsg = arith_lookup_val(math_state, numstack); } goto ret; } @@ -663,8 +660,8 @@ evaluate_string(arith_state_t *math_state, const char *expr) break; } } - errcode = arith_apply(math_state, prev_op, numstack, &numstackptr); - if (errcode) + errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); + if (errmsg) goto ret; } if (op == TOK_RPAREN) { @@ -678,15 +675,17 @@ evaluate_string(arith_state_t *math_state, const char *expr) } /* while (1) */ err: - numstack->val = errcode = -1; + numstack->val = -1; + errmsg = "arithmetic syntax error"; ret: - math_state->errcode = errcode; + math_state->errmsg = errmsg; return numstack->val; } arith_t FAST_FUNC arith(arith_state_t *math_state, const char *expr) { + math_state->errmsg = NULL; math_state->list_of_recursed_names = NULL; return evaluate_string(math_state, expr); } diff --git a/shell/math.h b/shell/math.h index e34b65d5d..2dcab130d 100644 --- a/shell/math.h +++ b/shell/math.h @@ -95,7 +95,7 @@ typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *v //typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name); typedef struct arith_state_t { - int errcode; + const char *errmsg; arith_var_lookup_t lookupvar; arith_var_set_t setvar; // arith_var_endofname_t endofname; -- cgit v1.2.3-55-g6feb From bed7c81ea24e9e9ba2a897e233de2abefe611e8b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 16 Sep 2010 11:50:46 +0200 Subject: shell/math: deconvolute and explain ?: handling. Give better error message function old new delta arith_apply 1271 1283 +12 Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- shell/ash_test/ash-arith/arith.right | 2 +- shell/hush.c | 4 +- shell/hush_test/hush-arith/arith.right | 2 +- shell/math.c | 243 ++++++++++++++++++--------------- shell/math.h | 20 +-- 6 files changed, 144 insertions(+), 129 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index ec887e088..9089adc63 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5516,7 +5516,7 @@ cvtnum(arith_t num) int len; expdest = makestrspace(32, expdest); - len = fmtstr(expdest, 32, arith_t_fmt, num); + len = fmtstr(expdest, 32, ARITH_FMT, num); STADJUST(len, expdest); return len; } diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right index 7257cc566..9b9ca8e2f 100644 --- a/shell/ash_test/ash-arith/arith.right +++ b/shell/ash_test/ash-arith/arith.right @@ -72,7 +72,7 @@ ghi ./arith.tests: line 191: arithmetic syntax error 16 16 ./arith.tests: line 196: arithmetic syntax error -./arith.tests: line 197: arithmetic syntax error +./arith.tests: line 197: malformed ?: operator ./arith.tests: line 198: arithmetic syntax error 9 9 ./arith.tests: line 205: arithmetic syntax error diff --git a/shell/hush.c b/shell/hush.c index ad30ac1ea..a888332bc 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4938,8 +4938,8 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) *p = '\0'; /* replace trailing */ debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch); res = expand_and_evaluate_arith(arg, NULL); - debug_printf_subst("ARITH RES '"arith_t_fmt"'\n", res); - sprintf(arith_buf, arith_t_fmt, res); + debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res); + sprintf(arith_buf, ARITH_FMT, res); val = arith_buf; break; } diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right index fd4ea8e01..8a201fb3b 100644 --- a/shell/hush_test/hush-arith/arith.right +++ b/shell/hush_test/hush-arith/arith.right @@ -81,7 +81,7 @@ ghi hush: arithmetic syntax error 16 16 hush: arithmetic syntax error -hush: arithmetic syntax error +hush: malformed ?: operator hush: arithmetic syntax error 9 9 hush: arithmetic syntax error diff --git a/shell/math.c b/shell/math.c index 871c06c3e..9d3b912a7 100644 --- a/shell/math.c +++ b/shell/math.c @@ -1,5 +1,5 @@ /* - * arithmetic code ripped out of ash shell for code sharing + * Arithmetic code ripped out of ash shell for code sharing. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. @@ -154,7 +154,7 @@ typedef unsigned char operator; #define fix_assignment_prec(prec) do { if (prec == 3) prec = 2; } while (0) -/* ternary conditional operator is right associative too */ +/* Ternary conditional operator is right associative too */ #define TOK_CONDITIONAL tok_decl(4,0) #define TOK_CONDITIONAL_SEP tok_decl(4,1) @@ -186,10 +186,10 @@ typedef unsigned char operator; #define TOK_DIV tok_decl(14,1) #define TOK_REM tok_decl(14,2) -/* exponent is right associative */ +/* Exponent is right associative */ #define TOK_EXPONENT tok_decl(15,1) -/* unary operators */ +/* Unary operators */ #define UNARYPREC 16 #define TOK_BNOT tok_decl(UNARYPREC,0) #define TOK_NOT tok_decl(UNARYPREC,1) @@ -213,30 +213,37 @@ typedef unsigned char operator; #define TOK_RPAREN tok_decl(SPEC_PREC, 1) static int -tok_have_assign(operator op) +is_assign_op(operator op) { operator prec = PREC(op); - fix_assignment_prec(prec); - return (prec == PREC(TOK_ASSIGN) || - prec == PREC_PRE || prec == PREC_POST); + return prec == PREC(TOK_ASSIGN) + || prec == PREC_PRE + || prec == PREC_POST; } static int is_right_associative(operator prec) { - return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) - || prec == PREC(TOK_CONDITIONAL)); + return prec == PREC(TOK_ASSIGN) + || prec == PREC(TOK_EXPONENT) + || prec == PREC(TOK_CONDITIONAL); } typedef struct { arith_t val; - arith_t contidional_second_val; - char contidional_second_val_initialized; - char *var; /* if NULL then is regular number, - else is variable name */ -} v_n_t; + /* We acquire second_val only when "expr1 : expr2" part + * of ternary ?: op is evaluated. + * We treat ?: as two binary ops: (expr ? (expr1 : expr2)). + * ':' produces a new value which has two parts, val and second_val; + * then '?' selects one of them based on its left side. + */ + arith_t second_val; + char second_val_present; + /* If NULL then it's just a number, else it's a named variable */ + char *var; +} var_or_num_t; typedef struct remembered_name { struct remembered_name *next; @@ -248,7 +255,7 @@ static arith_t FAST_FUNC evaluate_string(arith_state_t *math_state, const char *expr); static const char* -arith_lookup_val(arith_state_t *math_state, v_n_t *t) +arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) { if (t->var) { const char *p = lookupvar(t->var); @@ -290,27 +297,28 @@ arith_lookup_val(arith_state_t *math_state, v_n_t *t) * stack. For an unary operator it will only change the top element, but a * binary operator will pop two arguments and push the result */ static NOINLINE const char* -arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **numstackptr) +arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_or_num_t **numstackptr) { #define NUMPTR (*numstackptr) - v_n_t *numptr_m1; - arith_t numptr_val, rez; + var_or_num_t *top_of_stack; + arith_t rez; const char *err; /* There is no operator that can work without arguments */ if (NUMPTR == numstack) goto err; - numptr_m1 = NUMPTR - 1; - /* Check operand is var with noninteger value */ - err = arith_lookup_val(math_state, numptr_m1); + top_of_stack = NUMPTR - 1; + + /* Resolve name to value, if needed */ + err = arith_lookup_val(math_state, top_of_stack); if (err) return err; - rez = numptr_m1->val; + rez = top_of_stack->val; if (op == TOK_UMINUS) - rez *= -1; + rez = -rez; else if (op == TOK_NOT) rez = !rez; else if (op == TOK_BNOT) @@ -321,112 +329,119 @@ arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **num rez--; else if (op != TOK_UPLUS) { /* Binary operators */ + arith_t right_side_val; + char bad_second_val; - /* check and binary operators need two arguments */ - if (numptr_m1 == numstack) goto err; - - /* ... and they pop one */ - --NUMPTR; - numptr_val = rez; - if (op == TOK_CONDITIONAL) { - if (!numptr_m1->contidional_second_val_initialized) { - /* protect $((expr1 ? expr2)) without ": expr" */ - goto err; - } - rez = numptr_m1->contidional_second_val; - } else if (numptr_m1->contidional_second_val_initialized) { - /* protect $((expr1 : expr2)) without "expr ? " */ + /* Binary operators need two arguments */ + if (top_of_stack == numstack) goto err; + /* ...and they pop one */ + NUMPTR = top_of_stack; /* this decrements NUMPTR */ + + bad_second_val = top_of_stack->second_val_present; + if (op == TOK_CONDITIONAL) { /* ? operation */ + /* Make next if (...) protect against + * $((expr1 ? expr2)) - that is, missing ": expr" */ + bad_second_val = !bad_second_val; + } + if (bad_second_val) { + /* Protect against $((expr expr1 : expr2)) */ + return "malformed ?: operator"; } - numptr_m1 = NUMPTR - 1; + + top_of_stack--; /* now points to left side */ + if (op != TOK_ASSIGN) { - /* check operand is var with noninteger value for not '=' */ - err = arith_lookup_val(math_state, numptr_m1); + /* Resolve left side value (unless the op is '=') */ + err = arith_lookup_val(math_state, top_of_stack); if (err) return err; } - if (op == TOK_CONDITIONAL) { - numptr_m1->contidional_second_val = rez; + + right_side_val = rez; + rez = top_of_stack->val; + if (op == TOK_CONDITIONAL) /* ? operation */ + rez = (rez ? right_side_val : top_of_stack[1].second_val); + else if (op == TOK_CONDITIONAL_SEP) { /* : operation */ + if (top_of_stack == numstack) { + /* Protect against $((expr : expr)) */ + return "malformed ?: operator"; + } + top_of_stack->second_val_present = op; + top_of_stack->second_val = right_side_val; } - rez = numptr_m1->val; - if (op == TOK_BOR || op == TOK_OR_ASSIGN) - rez |= numptr_val; + else if (op == TOK_BOR || op == TOK_OR_ASSIGN) + rez |= right_side_val; else if (op == TOK_OR) - rez = numptr_val || rez; + rez = right_side_val || rez; else if (op == TOK_BAND || op == TOK_AND_ASSIGN) - rez &= numptr_val; + rez &= right_side_val; else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN) - rez ^= numptr_val; + rez ^= right_side_val; else if (op == TOK_AND) - rez = rez && numptr_val; + rez = rez && right_side_val; else if (op == TOK_EQ) - rez = (rez == numptr_val); + rez = (rez == right_side_val); else if (op == TOK_NE) - rez = (rez != numptr_val); + rez = (rez != right_side_val); else if (op == TOK_GE) - rez = (rez >= numptr_val); + rez = (rez >= right_side_val); else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN) - rez >>= numptr_val; + rez >>= right_side_val; else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN) - rez <<= numptr_val; + rez <<= right_side_val; else if (op == TOK_GT) - rez = (rez > numptr_val); + rez = (rez > right_side_val); else if (op == TOK_LT) - rez = (rez < numptr_val); + rez = (rez < right_side_val); else if (op == TOK_LE) - rez = (rez <= numptr_val); + rez = (rez <= right_side_val); else if (op == TOK_MUL || op == TOK_MUL_ASSIGN) - rez *= numptr_val; + rez *= right_side_val; else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN) - rez += numptr_val; + rez += right_side_val; else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN) - rez -= numptr_val; + rez -= right_side_val; else if (op == TOK_ASSIGN || op == TOK_COMMA) - rez = numptr_val; - else if (op == TOK_CONDITIONAL_SEP) { - if (numptr_m1 == numstack) { - /* protect $((expr : expr)) without "expr ? " */ - goto err; - } - numptr_m1->contidional_second_val_initialized = op; - numptr_m1->contidional_second_val = numptr_val; - } else if (op == TOK_CONDITIONAL) { - rez = rez ? - numptr_val : numptr_m1->contidional_second_val; - } else if (op == TOK_EXPONENT) { + rez = right_side_val; + else if (op == TOK_EXPONENT) { arith_t c; - if (numptr_val < 0) + if (right_side_val < 0) return "exponent less than 0"; c = 1; - while (--numptr_val >= 0) + while (--right_side_val >= 0) c *= rez; rez = c; - } else if (numptr_val == 0) + } + else if (right_side_val == 0) return "divide by zero"; else if (op == TOK_DIV || op == TOK_DIV_ASSIGN) - rez /= numptr_val; + rez /= right_side_val; else if (op == TOK_REM || op == TOK_REM_ASSIGN) - rez %= numptr_val; + rez %= right_side_val; } - if (tok_have_assign(op)) { + + if (is_assign_op(op)) { char buf[sizeof(arith_t)*3 + 2]; - if (numptr_m1->var == NULL) { + if (top_of_stack->var == NULL) { /* Hmm, 1=2 ? */ +//TODO: actually, bash allows ++7 but for some reason it evals to 7, not 8 goto err; } - /* save to shell variable */ - sprintf(buf, arith_t_fmt, rez); - setvar(numptr_m1->var, buf); - /* after saving, make previous value for v++ or v-- */ + /* Save to shell variable */ + sprintf(buf, ARITH_FMT, rez); + setvar(top_of_stack->var, buf); + /* After saving, make previous value for v++ or v-- */ if (op == TOK_POST_INC) rez--; else if (op == TOK_POST_DEC) rez++; } - numptr_m1->val = rez; - /* erase var name, it is just a number now */ - numptr_m1->var = NULL; + + top_of_stack->val = rez; + /* Erase var name, it is just a number now */ + top_of_stack->var = NULL; return NULL; err: return "arithmetic syntax error"; @@ -499,16 +514,17 @@ evaluate_string(arith_state_t *math_state, const char *expr) const char *start_expr = expr = skip_whitespace(expr); unsigned expr_len = strlen(expr) + 2; /* Stack of integers */ - /* The proof that there can be no more than strlen(startbuf)/2+1 integers - * in any given correct or incorrect expression is left as an exercise to - * the reader. */ - v_n_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0])); - v_n_t *numstackptr = numstack; + /* The proof that there can be no more than strlen(startbuf)/2+1 + * integers in any given correct or incorrect expression + * is left as an exercise to the reader. */ + var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0])); + var_or_num_t *numstackptr = numstack; /* Stack of operator tokens */ operator *const stack = alloca(expr_len * sizeof(stack[0])); operator *stackptr = stack; - *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */ + /* Start with a left paren */ + *stackptr++ = lasttok = TOK_LPAREN; errmsg = NULL; while (1) { @@ -521,7 +537,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) arithval = *expr; if (arithval == '\0') { if (expr == start_expr) { - /* Null expression. */ + /* Null expression */ numstack->val = 0; goto ret; } @@ -558,7 +574,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) safe_strncpy(numstackptr->var, expr, var_name_size); expr = p; num: - numstackptr->contidional_second_val_initialized = 0; + numstackptr->second_val_present = 0; numstackptr++; lasttok = TOK_NUM; continue; @@ -577,21 +593,32 @@ evaluate_string(arith_state_t *math_state, const char *expr) /* Should be an operator */ p = op_tokens; while (1) { - const char *e = expr; +// TODO: bash allows 7+++v, treats it as 7 + ++v +// we treat it as 7++ + v and reject /* Compare expr to current op_tokens[] element */ - while (*p && *e == *p) - p++, e++; - if (*p == '\0') { /* match: operator is found */ - expr = e; - break; + const char *e = expr; + while (1) { + if (*p == '\0') { + /* Match: operator is found */ + expr = e; + goto tok_found; + } + if (*p != *e) + break; + p++; + e++; } - /* Go to next element of op_tokens[] */ + /* No match, go to next element of op_tokens[] */ while (*p) p++; p += 2; /* skip NUL and TOK_foo bytes */ - if (*p == '\0') /* no next element, operator not found */ + if (*p == '\0') { + /* No next element, operator not found */ + //math_state->syntax_error_at = expr; goto err; + } } + tok_found: op = p[1]; /* fetch TOK_foo value */ /* NB: expr now points past the operator */ @@ -662,21 +689,21 @@ evaluate_string(arith_state_t *math_state, const char *expr) } errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); if (errmsg) - goto ret; + goto err_with_custom_msg; } - if (op == TOK_RPAREN) { + if (op == TOK_RPAREN) goto err; - } } - /* Push this operator to the stack and remember it. */ + /* Push this operator to the stack and remember it */ *stackptr++ = lasttok = op; next: ; } /* while (1) */ err: - numstack->val = -1; errmsg = "arithmetic syntax error"; + err_with_custom_msg: + numstack->val = -1; ret: math_state->errmsg = errmsg; return numstack->val; diff --git a/shell/math.h b/shell/math.h index 2dcab130d..2d305eb12 100644 --- a/shell/math.h +++ b/shell/math.h @@ -9,19 +9,13 @@ /* The math library has just one function: * - * arith_t arith(arith_state_t *states, const char *expr); + * arith_t arith(arith_state_t *state, const char *expr); * * The expr argument is the math string to parse. All normal expansions must * be done already. i.e. no dollar symbols should be present. * * The state argument is a pointer to a struct of hooks for your shell (see below), - * and a semi-detailed error code. Currently, those values are (for - * compatibility, you should assume all negative values are errors): - * 0 - no errors (yay!) - * -1 - unspecified problem - * -2 - divide by zero - * -3 - exponent less than 0 - * -5 - expression recursion loop detected + * and an error message string (NULL if no error). * * The function returns the answer to the expression. So if you called it * with the expression: @@ -64,12 +58,6 @@ * the regex (in C locale): ^[a-zA-Z_][a-zA-Z_0-9]* */ -/* To make your life easier when dealing with optional 64bit math support, - * rather than assume that the type is "signed long" and you can always - * use "%ld" to scan/print the value, use the arith_t helper defines. See - * below for the exact things that are available. - */ - #ifndef SHELL_MATH_H #define SHELL_MATH_H 1 @@ -77,11 +65,11 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN #if ENABLE_SH_MATH_SUPPORT_64 typedef long long arith_t; -#define arith_t_fmt "%lld" +#define ARITH_FMT "%lld" #define strto_arith_t strtoull #else typedef long arith_t; -#define arith_t_fmt "%ld" +#define ARITH_FMT "%ld" #define strto_arith_t strtoul #endif -- cgit v1.2.3-55-g6feb From 06a80bdbea6237257bd3de4919243cba57493b42 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 16 Sep 2010 13:23:15 +0200 Subject: build system: test that od is present in the host system Signed-off-by: Denys Vlasenko --- applets/usage_compressed | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/applets/usage_compressed b/applets/usage_compressed index e1fd0d94d..9436dcd5d 100755 --- a/applets/usage_compressed +++ b/applets/usage_compressed @@ -9,6 +9,12 @@ test -x "$loc/usage" || exit 1 test "$SED" || SED=sed test "$DD" || DD=dd +true | od -v -t x1 >/dev/null +if test $? != 0; then + echo 'od tool is not installed or cannot accept "-v -t x1" options' + exit 1 +fi + exec >"$target.$$" echo '#define UNPACKED_USAGE "" \' -- cgit v1.2.3-55-g6feb From 0fdf2e1026bed831e3254843e27b0577c9908030 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 16 Sep 2010 15:46:20 +0200 Subject: simpler check for od Signed-off-by: Denys Vlasenko --- applets/usage_compressed | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/applets/usage_compressed b/applets/usage_compressed index 9436dcd5d..af66bc5dc 100755 --- a/applets/usage_compressed +++ b/applets/usage_compressed @@ -9,7 +9,8 @@ test -x "$loc/usage" || exit 1 test "$SED" || SED=sed test "$DD" || DD=dd -true | od -v -t x1 >/dev/null +# Some people were bitten by their system lacking a (proper) od +od -v -t x1 /dev/null if test $? != 0; then echo 'od tool is not installed or cannot accept "-v -t x1" options' exit 1 -- cgit v1.2.3-55-g6feb From 52e460b7440ed5b85e4125a4eccf1e665d92c0ff Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 16 Sep 2010 16:12:00 +0200 Subject: hush: move shell_ver from globals to main's stack. function old new delta hush_main 995 1011 +16 pseudo_exec_argv 253 251 -2 execvp_or_die 50 48 -2 maybe_set_to_sigexit 50 47 -3 hush_exit 78 75 -3 builtin_wait 274 271 -3 check_and_run_traps 205 200 -5 init_sigmasks 214 190 -24 builtin_trap 465 441 -24 reset_traps_to_defaults 238 211 -27 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/9 up/down: 16/-93) Total: -77 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index a888332bc..6e36078c2 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -707,8 +707,7 @@ struct globals { #endif const char *ifs; const char *cwd; - struct variable *top_var; /* = &G.shell_ver (set in main()) */ - struct variable shell_ver; + struct variable *top_var; char **expanded_assignments; #if ENABLE_HUSH_FUNCTIONS struct function *top_func; @@ -7337,6 +7336,7 @@ int hush_main(int argc, char **argv) unsigned builtin_argc; char **e; struct variable *cur_var; + struct variable shell_ver; INIT_G(); if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, it is already done */ @@ -7345,12 +7345,13 @@ int hush_main(int argc, char **argv) G.argv0_for_re_execing = argv[0]; #endif /* Deal with HUSH_VERSION */ - G.shell_ver.flg_export = 1; - G.shell_ver.flg_read_only = 1; + memset(&shell_ver, 0, sizeof(shell_ver)); + shell_ver.flg_export = 1; + shell_ver.flg_read_only = 1; /* Code which handles ${var...} needs writable values for all variables, * therefore we xstrdup: */ - G.shell_ver.varstr = xstrdup(hush_version_str), - G.top_var = &G.shell_ver; + shell_ver.varstr = xstrdup(hush_version_str), + G.top_var = &shell_ver; /* Create shell local variables from the values * currently living in the environment */ debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); @@ -7369,8 +7370,8 @@ int hush_main(int argc, char **argv) e++; } /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */ - debug_printf_env("putenv '%s'\n", G.shell_ver.varstr); - putenv(G.shell_ver.varstr); + debug_printf_env("putenv '%s'\n", shell_ver.varstr); + putenv(shell_ver.varstr); /* Export PWD */ set_pwd_var(/*exp:*/ 1); -- cgit v1.2.3-55-g6feb From 9fe98f701d40835db32baa12c94b661d40231ea4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 16 Sep 2010 17:51:13 +0200 Subject: libbb: merge mail and uudecode's base64 decoders function old new delta read_base64 - 378 +378 uudecode_main 306 315 +9 parse 953 958 +5 read_stduu 250 254 +4 base64_main 217 219 +2 read_base64 358 - -358 decode_base64 371 - -371 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 4/0 up/down: 398/-729) Total: -331 bytes Signed-off-by: Denys Vlasenko --- coreutils/uudecode.c | 73 +++--------------------------------------------- include/libbb.h | 6 ++++ libbb/base64.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mailutils/mail.c | 67 -------------------------------------------- mailutils/mail.h | 1 - mailutils/mime.c | 4 +-- 6 files changed, 90 insertions(+), 139 deletions(-) create mode 100644 libbb/base64.c diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index 0da9b0988..0c4311f24 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -13,7 +13,7 @@ #include "libbb.h" #if ENABLE_UUDECODE -static void read_stduu(FILE *src_stream, FILE *dst_stream) +static void FAST_FUNC read_stduu(FILE *src_stream, FILE *dst_stream, int flags UNUSED_PARAM) { char *line; @@ -75,71 +75,6 @@ static void read_stduu(FILE *src_stream, FILE *dst_stream) } #endif -static void read_base64(FILE *src_stream, FILE *dst_stream) -{ - int term_count = 0; - - while (1) { - unsigned char translated[4]; - int count = 0; - - /* Process one group of 4 chars */ - while (count < 4) { - char *table_ptr; - int ch; - - /* Get next _valid_ character. - * bb_uuenc_tbl_base64[] contains this string: - * 0 1 2 3 4 5 6 - * 012345678901234567890123456789012345678901234567890123456789012345 - * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" - */ - do { - ch = fgetc(src_stream); - if (ch == EOF) { - if (ENABLE_BASE64 - && (!ENABLE_UUDECODE || applet_name[0] == 'b') - && count == 0 - ) { - return; - } - bb_error_msg_and_die("short file"); - } - table_ptr = strchr(bb_uuenc_tbl_base64, ch); - } while (!table_ptr); - - /* Convert encoded character to decimal */ - ch = table_ptr - bb_uuenc_tbl_base64; - - if (ch == 65 /* '\n' */) { - /* Terminating "====" line? */ - if (term_count == 4) - return; /* yes */ - term_count = 0; - continue; - } - /* ch is 64 is char was '=', otherwise 0..63 */ - translated[count] = ch & 63; /* 64 -> 0 */ - if (ch == 64) { - term_count++; - break; - } - count++; - } - - /* Merge 6 bit chars to 8 bit. - * count can be < 4 when we decode the tail: - * "eQ==" -> "y", not "y NUL NUL" - */ - if (count > 1) - fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); - if (count > 2) - fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); - if (count > 3) - fputc(translated[2] << 6 | translated[3], dst_stream); - } /* while (1) */ -} - #if ENABLE_UUDECODE int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int uudecode_main(int argc UNUSED_PARAM, char **argv) @@ -158,7 +93,7 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) /* Search for the start of the encoding */ while ((line = xmalloc_fgetline(src_stream)) != NULL) { - void (*decode_fn_ptr)(FILE *src, FILE *dst); + void FAST_FUNC (*decode_fn_ptr)(FILE *src, FILE *dst, int flags); char *line_ptr; FILE *dst_stream; int mode; @@ -189,7 +124,7 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) fchmod(fileno(dst_stream), mode & (S_IRWXU | S_IRWXG | S_IRWXO)); } free(line); - decode_fn_ptr(src_stream, dst_stream); + decode_fn_ptr(src_stream, dst_stream, /*flags:*/ BASE64_FLAG_UU_STOP + BASE64_FLAG_NO_STOP_CHAR); /* fclose_if_not_stdin(src_stream); - redundant */ return EXIT_SUCCESS; } @@ -231,7 +166,7 @@ int base64_main(int argc UNUSED_PARAM, char **argv) *--argv = (char*)"-"; src_stream = xfopen_stdin(argv[0]); if (opts) { - read_base64(src_stream, stdout); + read_base64(src_stream, stdout, /*flags:*/ (char)EOF); } else { enum { SRC_BUF_SIZE = 76/4*3, /* This *MUST* be a multiple of 3 */ diff --git a/include/libbb.h b/include/libbb.h index d5580b4b0..8d7beffe7 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1505,6 +1505,12 @@ unsigned get_cpu_count(void) FAST_FUNC; extern const char bb_uuenc_tbl_base64[]; extern const char bb_uuenc_tbl_std[]; void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; +enum { + BASE64_FLAG_UU_STOP = 0x100, + /* Sign-extends to a value which never matches fgetc result: */ + BASE64_FLAG_NO_STOP_CHAR = 0x80, +}; +void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags); typedef struct sha1_ctx_t { uint32_t hash[8]; /* 5, +3 elements for sha256 */ diff --git a/libbb/base64.c b/libbb/base64.c new file mode 100644 index 000000000..b9d47ae08 --- /dev/null +++ b/libbb/base64.c @@ -0,0 +1,78 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright 2003, Glenn McGrath + * Copyright 2010, Denys Vlasenko + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ +#include "libbb.h" + +//kbuild:lib-y += base64.o + +void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) +{ +/* Note that EOF _can_ be passed as exit_char too */ +#define exit_char ((int)(signed char)flags) +#define uu_style_end (flags & BASE64_FLAG_UUEND) + + int term_count = 0; + + while (1) { + unsigned char translated[4]; + int count = 0; + + /* Process one group of 4 chars */ + while (count < 4) { + char *table_ptr; + int ch; + + /* Get next _valid_ character. + * bb_uuenc_tbl_base64[] contains this string: + * 0 1 2 3 4 5 6 + * 012345678901234567890123456789012345678901234567890123456789012345 + * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" + */ + do { + ch = fgetc(src_stream); + if (ch == exit_char && count == 0) + return; + if (ch == EOF) + bb_error_msg_and_die("truncated base64 input"); + table_ptr = strchr(bb_uuenc_tbl_base64, ch); +//TODO: add BASE64_FLAG_foo to die on bad char? +//Note that then we may need to still allow '\r' (for mail processing) + } while (!table_ptr); + + /* Convert encoded character to decimal */ + ch = table_ptr - bb_uuenc_tbl_base64; + + if (ch == 65 /* '\n' */) { + /* Terminating "====" line? */ + if (uu_style_end && term_count == 4) + return; /* yes */ + continue; + } + /* ch is 64 if char was '=', otherwise 0..63 */ + translated[count] = ch & 63; /* 64 -> 0 */ + if (ch == 64) { + term_count++; + break; + } + term_count = 0; + count++; + } + + /* Merge 6 bit chars to 8 bit. + * count can be < 4 when we decode the tail: + * "eQ==" -> "y", not "y NUL NUL" + */ + if (count > 1) + fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); + if (count > 2) + fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); + if (count > 3) + fputc(translated[2] << 6 | translated[3], dst_stream); + } /* while (1) */ +} diff --git a/mailutils/mail.c b/mailutils/mail.c index 8e52a3efc..89db66166 100644 --- a/mailutils/mail.c +++ b/mailutils/mail.c @@ -161,73 +161,6 @@ void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol) #undef src_buf } -void FAST_FUNC decode_base64(FILE *src_stream, FILE *dst_stream) -{ - int term_count = 1; - - while (1) { - char translated[4]; - int count = 0; - - while (count < 4) { - char *table_ptr; - int ch; - - /* Get next _valid_ character. - * global vector bb_uuenc_tbl_base64[] contains this string: - * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" - */ - do { - ch = fgetc(src_stream); - if (ch == EOF) { - bb_error_msg_and_die(bb_msg_read_error); - } - // - means end of MIME section - if ('-' == ch) { - // push it back - ungetc(ch, src_stream); - return; - } - table_ptr = strchr(bb_uuenc_tbl_base64, ch); - } while (table_ptr == NULL); - - /* Convert encoded character to decimal */ - ch = table_ptr - bb_uuenc_tbl_base64; - - if (*table_ptr == '=') { - if (term_count == 0) { - translated[count] = '\0'; - break; - } - term_count++; - } else if (*table_ptr == '\n') { - /* Check for terminating line */ - if (term_count == 5) { - return; - } - term_count = 1; - continue; - } else { - translated[count] = ch; - count++; - term_count = 0; - } - } - - /* Merge 6 bit chars to 8 bit */ - if (count > 1) { - fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); - } - if (count > 2) { - fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); - } - if (count > 3) { - fputc(translated[2] << 6 | translated[3], dst_stream); - } - } -} - - /* * get username and password from a file descriptor */ diff --git a/mailutils/mail.h b/mailutils/mail.h index bb747c4c5..e0048fbfa 100644 --- a/mailutils/mail.h +++ b/mailutils/mail.h @@ -32,4 +32,3 @@ void FAST_FUNC get_cred_or_die(int fd); const FAST_FUNC char *command(const char *fmt, const char *param); void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol); -void FAST_FUNC decode_base64(FILE *src_stream, FILE *dst_stream); diff --git a/mailutils/mime.c b/mailutils/mime.c index 44c7d0216..682cf4536 100644 --- a/mailutils/mime.c +++ b/mailutils/mime.c @@ -225,7 +225,7 @@ static int parse(const char *boundary, char **argv) // prepare unique string pattern uniq = xasprintf("%%llu.%u.%s", (unsigned)getpid(), safe_gethostname()); -//bb_info_msg("PARSE[%s]", terminator); +//bb_info_msg("PARSE[%s]", uniq); while ((line = xmalloc_fgets_str(stdin, "\r\n\r\n")) != NULL) { @@ -306,7 +306,7 @@ static int parse(const char *boundary, char **argv) // dump to fp if (0 == strcasecmp(encoding, "base64")) { - decode_base64(stdin, fp); + read_base64(stdin, fp, '-'); } else if (0 != strcasecmp(encoding, "7bit") && 0 != strcasecmp(encoding, "8bit") ) { -- cgit v1.2.3-55-g6feb From c8f9a8d3c0f9e5d47cc650bf0425926b03e8bbc6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 16 Sep 2010 18:10:04 +0200 Subject: move read_base64 to libbb/uuencode.c Signed-off-by: Denys Vlasenko --- libbb/base64.c | 78 -------------------------------------------------------- libbb/uuencode.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++- mailutils/mail.c | 5 ++-- 3 files changed, 77 insertions(+), 82 deletions(-) delete mode 100644 libbb/base64.c diff --git a/libbb/base64.c b/libbb/base64.c deleted file mode 100644 index b9d47ae08..000000000 --- a/libbb/base64.c +++ /dev/null @@ -1,78 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Utility routines. - * - * Copyright 2003, Glenn McGrath - * Copyright 2010, Denys Vlasenko - * - * Licensed under GPLv2 or later, see file LICENSE in this source tree. - */ -#include "libbb.h" - -//kbuild:lib-y += base64.o - -void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) -{ -/* Note that EOF _can_ be passed as exit_char too */ -#define exit_char ((int)(signed char)flags) -#define uu_style_end (flags & BASE64_FLAG_UUEND) - - int term_count = 0; - - while (1) { - unsigned char translated[4]; - int count = 0; - - /* Process one group of 4 chars */ - while (count < 4) { - char *table_ptr; - int ch; - - /* Get next _valid_ character. - * bb_uuenc_tbl_base64[] contains this string: - * 0 1 2 3 4 5 6 - * 012345678901234567890123456789012345678901234567890123456789012345 - * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" - */ - do { - ch = fgetc(src_stream); - if (ch == exit_char && count == 0) - return; - if (ch == EOF) - bb_error_msg_and_die("truncated base64 input"); - table_ptr = strchr(bb_uuenc_tbl_base64, ch); -//TODO: add BASE64_FLAG_foo to die on bad char? -//Note that then we may need to still allow '\r' (for mail processing) - } while (!table_ptr); - - /* Convert encoded character to decimal */ - ch = table_ptr - bb_uuenc_tbl_base64; - - if (ch == 65 /* '\n' */) { - /* Terminating "====" line? */ - if (uu_style_end && term_count == 4) - return; /* yes */ - continue; - } - /* ch is 64 if char was '=', otherwise 0..63 */ - translated[count] = ch & 63; /* 64 -> 0 */ - if (ch == 64) { - term_count++; - break; - } - term_count = 0; - count++; - } - - /* Merge 6 bit chars to 8 bit. - * count can be < 4 when we decode the tail: - * "eQ==" -> "y", not "y NUL NUL" - */ - if (count > 1) - fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); - if (count > 2) - fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); - if (count > 3) - fputc(translated[2] << 6 | translated[3], dst_stream); - } /* while (1) */ -} diff --git a/libbb/uuencode.c b/libbb/uuencode.c index 181f49de0..03e708fd5 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c @@ -1,6 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Copyright 2006 Rob Landley + * Copyright 2003, Glenn McGrath + * Copyright 2006, Rob Landley + * Copyright 2010, Denys Vlasenko * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ @@ -69,3 +71,75 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl length++; } } + +/* + * Decode base64 encoded stream. + * Can stop on EOF, specified char, or on uuencode-style "====" line: + * flags argument controls it. + */ +void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) +{ +/* Note that EOF _can_ be passed as exit_char too */ +#define exit_char ((int)(signed char)flags) +#define uu_style_end (flags & BASE64_FLAG_UU_STOP) + + int term_count = 0; + + while (1) { + unsigned char translated[4]; + int count = 0; + + /* Process one group of 4 chars */ + while (count < 4) { + char *table_ptr; + int ch; + + /* Get next _valid_ character. + * bb_uuenc_tbl_base64[] contains this string: + * 0 1 2 3 4 5 6 + * 012345678901234567890123456789012345678901234567890123456789012345 + * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" + */ + do { + ch = fgetc(src_stream); + if (ch == exit_char && count == 0) + return; + if (ch == EOF) + bb_error_msg_and_die("truncated base64 input"); + table_ptr = strchr(bb_uuenc_tbl_base64, ch); +//TODO: add BASE64_FLAG_foo to die on bad char? +//Note that then we may need to still allow '\r' (for mail processing) + } while (!table_ptr); + + /* Convert encoded character to decimal */ + ch = table_ptr - bb_uuenc_tbl_base64; + + if (ch == 65 /* '\n' */) { + /* Terminating "====" line? */ + if (uu_style_end && term_count == 4) + return; /* yes */ + term_count = 0; + continue; + } + /* ch is 64 if char was '=', otherwise 0..63 */ + translated[count] = ch & 63; /* 64 -> 0 */ + if (ch == 64) { + term_count++; + break; + } + count++; + term_count = 0; + } + + /* Merge 6 bit chars to 8 bit. + * count can be < 4 when we decode the tail: + * "eQ==" -> "y", not "y NUL NUL" + */ + if (count > 1) + fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); + if (count > 2) + fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); + if (count > 3) + fputc(translated[2] << 6 | translated[3], dst_stream); + } /* while (1) */ +} diff --git a/mailutils/mail.c b/mailutils/mail.c index 89db66166..9b4bebce5 100644 --- a/mailutils/mail.c +++ b/mailutils/mail.c @@ -116,16 +116,15 @@ void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol) SRC_BUF_SIZE = 45, /* This *MUST* be a multiple of 3 */ DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3), }; - #define src_buf text + char src[SRC_BUF_SIZE]; FILE *fp = fp; ssize_t len = len; char dst_buf[DST_BUF_SIZE + 1]; if (fname) { fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : (FILE *)text; - src_buf = bb_common_bufsiz1; - // N.B. strlen(NULL) segfaults! + src_buf = src; } else if (text) { // though we do not call uuencode(NULL, NULL) explicitly // still we do not want to break things suddenly -- cgit v1.2.3-55-g6feb From 395b97aeac4ac25dca32bd8480441ce64c17f7d9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 17 Sep 2010 18:02:17 +0200 Subject: shell/math: better comment. no code changes Signed-off-by: Denys Vlasenko --- shell/math.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/math.c b/shell/math.c index 9d3b912a7..760645d0f 100644 --- a/shell/math.c +++ b/shell/math.c @@ -652,10 +652,10 @@ evaluate_string(arith_state_t *math_state, const char *expr) * integer stack. * But for binary operators, "apply" everything on the operator * stack until we find an operator with a lesser priority than the - * one we have just extracted. + * one we have just extracted. If op is right-associative, + * then stop "applying" on the equal priority too. * Left paren is given the lowest priority so it will never be * "applied" in this way. - * if associativity is right and priority eq, applied also skip */ prec = PREC(op); if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { -- cgit v1.2.3-55-g6feb From 63adf838143e78b0857af39a2d365fc86bcf0cd4 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Sun, 19 Sep 2010 17:13:21 +0200 Subject: fix build failure for pmap Signed-off-by: Dan Fandrich Signed-off-by: Denys Vlasenko --- libbb/procps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbb/procps.c b/libbb/procps.c index 14d4481bd..792466048 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -120,7 +120,7 @@ void FAST_FUNC free_procps_scan(procps_status_t* sp) free(sp); } -#if ENABLE_FEATURE_TOPMEM +#if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP static unsigned long fast_strtoul_16(char **endptr) { unsigned char c; -- cgit v1.2.3-55-g6feb From 0e13b4019c3d05933ba8d37357023bfcd82e8106 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 21 Sep 2010 12:35:39 +0200 Subject: hush: use smaller EXP_FLAG_foo constants function old new delta expand_string_to_string 126 124 -2 parse_stream 2376 2370 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-8) Total: -8 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 6e36078c2..4c597e1ed 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -391,18 +391,10 @@ enum { RES_SNTX }; -enum { - EXP_FLAG_GLOB = 0x200, - EXP_FLAG_ESC_GLOB_CHARS = 0x100, - EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ -}; - typedef struct o_string { char *data; int length; /* position where data is appended */ int maxlen; - /* Protect newly added chars against globbing - * (by prepending \ to *, ?, [, \) */ int o_expflags; /* At least some part of the string was inside '' or "", * possibly empty one: word"", wo''rd etc. */ @@ -411,10 +403,18 @@ typedef struct o_string { smallint o_assignment; /* 0:maybe, 1:yes, 2:no */ } o_string; enum { - MAYBE_ASSIGNMENT = 0, + EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ + EXP_FLAG_GLOB = 0x2, + /* Protect newly added chars against globbing + * by prepending \ to *, ?, [, \ */ + EXP_FLAG_ESC_GLOB_CHARS = 0x1, +}; +enum { + MAYBE_ASSIGNMENT = 0, DEFINITELY_ASSIGNMENT = 1, - NOT_ASSIGNMENT = 2, - WORD_IS_KEYWORD = 3, /* not assigment, but next word may be: "if v=xyz cmd;" */ + NOT_ASSIGNMENT = 2, + /* Not an assigment, but next word may be: "if v=xyz cmd;" */ + WORD_IS_KEYWORD = 3, }; /* Used for initialization: o_string foo = NULL_O_STRING; */ #define NULL_O_STRING { NULL } -- cgit v1.2.3-55-g6feb From 361b1a6884bc9d4f5cece22d0eb9fe5eae17bda7 Mon Sep 17 00:00:00 2001 From: Harald Becker Date: Wed, 22 Sep 2010 14:50:15 +0200 Subject: deluser: make it simpler, fix inability to delete user from group Also makes menuconfig order more sensible Signed-off-by: Harald Becker Signed-off-by: Denys Vlasenko --- loginutils/Config.src | 84 +++++++++++++++++++++++++-------------------------- loginutils/deluser.c | 54 ++++++++++++++++----------------- 2 files changed, 68 insertions(+), 70 deletions(-) diff --git a/loginutils/Config.src b/loginutils/Config.src index 5d497c4dc..8158bce74 100644 --- a/loginutils/Config.src +++ b/loginutils/Config.src @@ -93,41 +93,18 @@ config USE_BB_CRYPT_SHA With this option off, login will fail password check for any user which has password encrypted with these algorithms. -config ADDGROUP - bool "addgroup" +config ADDUSER + bool "adduser" default y help - Utility for creating a new group account. + Utility for creating a new user account. -config FEATURE_ADDGROUP_LONG_OPTIONS +config FEATURE_ADDUSER_LONG_OPTIONS bool "Enable long options" default y - depends on ADDGROUP && LONG_OPTS - help - Support long options for the addgroup applet. - -config FEATURE_ADDUSER_TO_GROUP - bool "Support for adding users to groups" - default y - depends on ADDGROUP - help - If called with two non-option arguments, - addgroup will add an existing user to an - existing group. - -config DELGROUP - bool "delgroup" - default y - help - Utility for deleting a group account. - -config FEATURE_DEL_USER_FROM_GROUP - bool "Support for removing users from groups" - default y - depends on DELGROUP + depends on ADDUSER && LONG_OPTS help - If called with two non-option arguments, deluser - or delgroup will remove an user from a specified group. + Support long options for the adduser applet. config FEATURE_CHECK_NAMES bool "Enable sanity check on user/group names in adduser and addgroup" @@ -141,19 +118,6 @@ config FEATURE_CHECK_NAMES For compatibility with Samba machine accounts "$" is also supported at the end of the user or group name. -config ADDUSER - bool "adduser" - default y - help - Utility for creating a new user account. - -config FEATURE_ADDUSER_LONG_OPTIONS - bool "Enable long options" - default y - depends on ADDUSER && LONG_OPTS - help - Support long options for the adduser applet. - config FIRST_SYSTEM_ID int "First valid system uid or gid for adduser and addgroup" depends on ADDUSER || ADDGROUP @@ -170,12 +134,48 @@ config LAST_SYSTEM_ID help Last valid system uid or gid for adduser and addgroup +config ADDGROUP + bool "addgroup" + default y + help + Utility for creating a new group account. + +config FEATURE_ADDGROUP_LONG_OPTIONS + bool "Enable long options" + default y + depends on ADDGROUP && LONG_OPTS + help + Support long options for the addgroup applet. + +config FEATURE_ADDUSER_TO_GROUP + bool "Support for adding users to groups" + default y + depends on ADDGROUP + help + If called with two non-option arguments, + addgroup will add an existing user to an + existing group. + config DELUSER bool "deluser" default y help Utility for deleting a user account. +config DELGROUP + bool "delgroup" + default y + help + Utility for deleting a group account. + +config FEATURE_DEL_USER_FROM_GROUP + bool "Support for removing users from groups" + default y + depends on DELGROUP + help + If called with two non-option arguments, deluser + or delgroup will remove an user from a specified group. + config GETTY bool "getty" default y diff --git a/loginutils/deluser.c b/loginutils/deluser.c index e234d6678..65817b943 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c @@ -6,25 +6,18 @@ * Copyright (C) 1999,2000,2001 by John Beppu * Copyright (C) 2007 by Tito Ragusa * - * Licensed under GPLv2, see file LICENSE in this source tree. + * Licensed under GPL version 2, see file LICENSE in this tarball for details. * */ #include "libbb.h" -static int del_line_matching(char **args, const char *filename) -{ - if (ENABLE_FEATURE_DEL_USER_FROM_GROUP && args[2]) { - return update_passwd(filename, args[2], NULL, args[1]); - } - return update_passwd(filename, args[1], NULL, NULL); -} - int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int deluser_main(int argc, char **argv) { if (argc != 2 && (!ENABLE_FEATURE_DEL_USER_FROM_GROUP - || (applet_name[3] != 'g' || argc != 3)) + || applet_name[3] != 'g' + || argc != 3) ) { bb_show_usage(); } @@ -32,25 +25,30 @@ int deluser_main(int argc, char **argv) if (geteuid()) bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); - if ((ENABLE_FEATURE_DEL_USER_FROM_GROUP && argc != 3) - || ENABLE_DELUSER - || (ENABLE_DELGROUP && ENABLE_DESKTOP) - ) { - if (ENABLE_DELUSER - && (!ENABLE_DELGROUP || applet_name[3] == 'u') - ) { - if (del_line_matching(argv, bb_path_passwd_file) < 0) + if (ENABLE_DELUSER && applet_name[3] == 'u') { + /* deluser USER */ + if (update_passwd(bb_path_passwd_file, argv[1], NULL, NULL) < 0) + return EXIT_FAILURE; + if (ENABLE_FEATURE_SHADOWPASSWDS) + if (update_passwd(bb_path_shadow_file, argv[1], NULL, NULL) < 0) return EXIT_FAILURE; - if (ENABLE_FEATURE_SHADOWPASSWDS) { - del_line_matching(argv, bb_path_shadow_file); - } - } else if (ENABLE_DESKTOP && ENABLE_DELGROUP && getpwnam(argv[1])) - bb_error_msg_and_die("can't remove primary group of user %s", argv[1]); - } - if (del_line_matching(argv, bb_path_group_file) < 0) - return EXIT_FAILURE; - if (ENABLE_FEATURE_SHADOWPASSWDS) { - del_line_matching(argv, bb_path_gshadow_file); + } else if (ENABLE_DELGROUP) { + /* delgroup ... */ + if (!ENABLE_FEATURE_DEL_USER_FROM_GROUP || argc != 3) { + /* delgroup GROUP */ + if (update_passwd(bb_path_group_file, argv[1], NULL, NULL) < 0) + return EXIT_FAILURE; + if (ENABLE_FEATURE_SHADOWPASSWDS) + if (update_passwd(bb_path_gshadow_file, argv[1], NULL, NULL) < 0) + return EXIT_FAILURE; + } else { + /* delgroup USER GROUP */ + if (update_passwd(bb_path_group_file, argv[2], NULL, argv[1]) < 0) + return EXIT_FAILURE; + if (ENABLE_FEATURE_SHADOWPASSWDS) + if (update_passwd(bb_path_gshadow_file, argv[2], NULL, argv[1]) < 0) + return EXIT_FAILURE; + } } return EXIT_SUCCESS; } -- cgit v1.2.3-55-g6feb From 1fc20c446fde454bbff690a17b0b89de5e127d96 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 23 Sep 2010 02:03:47 +0200 Subject: nbd-client: new applet function old new delta nbdclient_main - 537 +537 daemon - 162 +162 packed_usage 27682 27724 +42 applet_names 2355 2366 +11 bbconfig_config_bz2 4918 4922 +4 applet_main 1376 1380 +4 applet_nameofs 688 690 +2 applet_install_loc 172 173 +1 ------------------------------------------------------------------------------ (add/remove: 4/0 grow/shrink: 6/0 up/down: 763/0) Total: 763 bytes Signed-off-by: Rob Landley Signed-off-by: Denys Vlasenko --- networking/nbd-client.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 networking/nbd-client.c diff --git a/networking/nbd-client.c b/networking/nbd-client.c new file mode 100644 index 000000000..5ac190c32 --- /dev/null +++ b/networking/nbd-client.c @@ -0,0 +1,153 @@ +/* + * Copyright 2010 Rob Landley + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +#include "libbb.h" +#include +#include + +//applet:IF_NBDCLIENT(APPLET_ODDNAME(nbd-client, nbdclient, _BB_DIR_USR_SBIN, _BB_SUID_DROP, nbdclient)) + +//kbuild:lib-$(CONFIG_NBDCLIENT) += nbd-client.o + +//config:config NBDCLIENT +//config: bool "nbd-client" +//config: default y +//config: help +//config: Network block device client + +#define NBD_SET_SOCK _IO(0xab, 0) +#define NBD_SET_BLKSIZE _IO(0xab, 1) +#define NBD_SET_SIZE _IO(0xab, 2) +#define NBD_DO_IT _IO(0xab, 3) +#define NBD_CLEAR_SOCK _IO(0xab, 4) +#define NBD_CLEAR_QUEUE _IO(0xab, 5) +#define NBD_PRINT_DEBUG _IO(0xab, 6) +#define NBD_SET_SIZE_BLOCKS _IO(0xab, 7) +#define NBD_DISCONNECT _IO(0xab, 8) +#define NBD_SET_TIMEOUT _IO(0xab, 9) + +//usage:#define nbdclient_trivial_usage +//usage: "HOST PORT BLOCKDEV" +//usage:#define nbdclient_full_usage "\n\n" +//usage: "Connect to HOST and provide a network block device on BLOCKDEV" + +//TODO: more compat with nbd-client version 2.9.13 - +//Usage: nbd-client [bs=blocksize] [timeout=sec] host port nbd_device [-swap] [-persist] [-nofork] +//Or : nbd-client -d nbd_device +//Or : nbd-client -c nbd_device +//Default value for blocksize is 1024 (recommended for ethernet) +//Allowed values for blocksize are 512,1024,2048,4096 +//Note, that kernel 2.4.2 and older ones do not work correctly with +//blocksizes other than 1024 without patches + +int nbdclient_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int nbdclient_main(int argc, char **argv) +{ + unsigned long timeout = 0; + int nofork = 0; + char *host, *port, *device; + struct nbd_header_t { + uint64_t magic1; // "NBDMAGIC" + uint64_t magic2; // 0x420281861253 big endian + uint64_t devsize; + uint32_t flags; + char data[124]; + } nbd_header; + struct bug_check { + char c[offsetof(struct nbd_header_t, data) == 8+8+8+4 ? 1 : -1]; + }; + + // Parse command line stuff (just a stub now) + if (argc != 4) + bb_show_usage(); + +#if !BB_MMU + bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); +#endif + + host = argv[1]; + port = argv[2]; + device = argv[3]; + + // Repeat until spanked (-persist behavior) + for (;;) { + int sock, nbd; + int ro; + + // Make sure the /dev/nbd exists + nbd = xopen(device, O_RDWR); + + // Find and connect to server + sock = create_and_connect_stream_or_die(host, xatou16(port)); + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1)); + + // Log on to the server + xread(sock, &nbd_header, 8+8+8+4 + 124); + if (memcmp(&nbd_header.magic1, "NBDMAGIC""\x00\x00\x42\x02\x81\x86\x12\x53", 16) != 0) + bb_error_msg_and_die("login failed"); + + // Set 4k block size. Everything uses that these days + ioctl(nbd, NBD_SET_BLKSIZE, 4096); + ioctl(nbd, NBD_SET_SIZE_BLOCKS, SWAP_BE64(nbd_header.devsize) / 4096); + ioctl(nbd, NBD_CLEAR_SOCK); + + // If the sucker was exported read only, respect that locally + ro = (nbd_header.flags & SWAP_BE32(2)) / SWAP_BE32(2); + if (ioctl(nbd, BLKROSET, &ro) < 0) + bb_perror_msg_and_die("BLKROSET"); + + if (timeout) + if (ioctl(nbd, NBD_SET_TIMEOUT, timeout)) + bb_perror_msg_and_die("NBD_SET_TIMEOUT"); + if (ioctl(nbd, NBD_SET_SOCK, sock)) + bb_perror_msg_and_die("NBD_SET_SOCK"); + + // if (swap) mlockall(MCL_CURRENT|MCL_FUTURE); + +#if BB_MMU + // Open the device to force reread of the partition table. + // Need to do it in a separate process, since open(device) + // needs some other process to sit in ioctl(nbd, NBD_DO_IT). + if (fork() == 0) { + char *s = strrchr(device, '/'); + sprintf(nbd_header.data, "/sys/block/%.32s/pid", s ? s + 1 : device); + // Is it up yet? + for (;;) { + int fd = open(nbd_header.data, O_RDONLY); + if (fd >= 0) { + //close(fd); + break; + } + sleep(1); + } + open(device, O_RDONLY); + return 0; + } + + // Daemonize here + if (!nofork) { + daemon(0, 0); + nofork = 1; + } +#endif + + // This turns us (the process that calls this ioctl) + // into a dedicated NBD request handler. + // We block here for a long time. + // When exactly ioctl returns? On a signal, + // or if someone does ioctl(NBD_DISCONNECT) [nbd-client -d]. + if (ioctl(nbd, NBD_DO_IT) >= 0 || errno == EBADR) { + // Flush queue and exit + ioctl(nbd, NBD_CLEAR_QUEUE); + ioctl(nbd, NBD_CLEAR_SOCK); + break; + } + + close(sock); + close(nbd); + } + + return 0; +} -- cgit v1.2.3-55-g6feb From ebec11dff1783023482a044a881aae5ebb020882 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Thu, 23 Sep 2010 15:18:41 +0200 Subject: wget: flush output to network before receving reply MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Denys Vlasenko --- networking/wget.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/networking/wget.c b/networking/wget.c index 88bb09eb2..4521abfcf 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -737,6 +737,8 @@ int wget_main(int argc UNUSED_PARAM, char **argv) fprintf(sfp, /* "Connection: close\r\n" */ "\r\n"); } + fflush(sfp); + /* * Retrieve HTTP response line and check for "200" status code. */ -- cgit v1.2.3-55-g6feb From 0f2e278a8a44751594f461ee753b81da365b1147 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 24 Sep 2010 12:39:45 +0200 Subject: sleep: fix fractional arguments in non-POSIX locale function old new delta sleep_main 390 379 -11 Signed-off-by: Denys Vlasenko --- coreutils/sleep.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/coreutils/sleep.c b/coreutils/sleep.c index 12798d9a7..9acb2d15f 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c @@ -49,6 +49,9 @@ int sleep_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_FLOAT_SLEEP +# if ENABLE_LOCALE_SUPPORT + setlocale (LC_NUMERIC, "C"); +# endif duration = 0; do { char *arg = *argv; @@ -62,14 +65,15 @@ int sleep_main(int argc UNUSED_PARAM, char **argv) d = strtod(arg, &pp); if (errno || *pp) bb_show_usage(); - arg[len] = sv; - len--; - sv = arg[len]; - arg[len] = '1'; - duration += d * xatoul_sfx(&arg[len], sfx); - arg[len] = sv; - } else + arg += len; + *arg-- = sv; + sv = *arg; + *arg = '1'; + duration += d * xatoul_sfx(arg, sfx); + *arg = sv; + } else { duration += xatoul_sfx(arg, sfx); + } } while (*++argv); ts.tv_sec = MAXINT(typeof(ts.tv_sec)); -- cgit v1.2.3-55-g6feb From 5b3151c201f4a67e998ec054d653e8177679d505 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 25 Sep 2010 14:37:06 +0200 Subject: modprobe-simple; do not error out on "rmmod module" if module is unloaded ok ...even if it wasn't found in /lib/modules/VER/ Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 05f2c34eb..e0d251ee9 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -18,10 +18,13 @@ extern int delete_module(const char *module, unsigned flags); extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret); -#define dbg1_error_msg(...) ((void)0) -#define dbg2_error_msg(...) ((void)0) -//#define dbg1_error_msg(...) bb_error_msg(__VA_ARGS__) -//#define dbg2_error_msg(...) bb_error_msg(__VA_ARGS__) +#if 1 +# define dbg1_error_msg(...) ((void)0) +# define dbg2_error_msg(...) ((void)0) +#else +# define dbg1_error_msg(...) bb_error_msg(__VA_ARGS__) +# define dbg2_error_msg(...) bb_error_msg(__VA_ARGS__) +#endif #define DEPFILE_BB CONFIG_DEFAULT_DEPMOD_FILE".bb" @@ -579,10 +582,9 @@ static void process_module(char *name, const char *cmdline_options) /* rmmod? unload it by name */ if (is_rmmod) { - if (delete_module(name, O_NONBLOCK | O_EXCL) != 0 - && !(option_mask32 & OPT_q) - ) { - bb_perror_msg("remove '%s'", name); + if (delete_module(name, O_NONBLOCK | O_EXCL) != 0) { + if (!(option_mask32 & OPT_q)) + bb_perror_msg("remove '%s'", name); goto ret; } /* N.B. we do not stop here - @@ -594,9 +596,9 @@ static void process_module(char *name, const char *cmdline_options) if (!info) { /* both dirscan and find_alias found nothing */ - if (applet_name[0] != 'd') /* it wasn't depmod */ + if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ bb_error_msg("module '%s' not found", name); -//TODO: _and_die()? +//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? goto ret; } @@ -811,8 +813,8 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) /* Load/remove modules. * Only rmmod loops here, modprobe has only argv[0] */ do { - process_module(*argv++, options); - } while (*argv); + process_module(*argv, options); + } while (*++argv); if (ENABLE_FEATURE_CLEAN_UP) { IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);) -- cgit v1.2.3-55-g6feb From b563f62bbb1c9a6d931924f8fd7c3e52bb3d5875 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 25 Sep 2010 17:15:13 +0200 Subject: ash: fix signal and "set -e" interaction Signed-off-by: Denys Vlasenko --- shell/ash.c | 19 +++++++++++++------ shell/ash_test/ash-signals/signal8.right | 3 +++ shell/ash_test/ash-signals/signal8.tests | 18 ++++++++++++++++++ shell/ash_test/ash-signals/signal9.right | 3 +++ shell/ash_test/ash-signals/signal9.tests | 21 +++++++++++++++++++++ 5 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 shell/ash_test/ash-signals/signal8.right create mode 100755 shell/ash_test/ash-signals/signal8.tests create mode 100644 shell/ash_test/ash-signals/signal9.right create mode 100755 shell/ash_test/ash-signals/signal9.tests diff --git a/shell/ash.c b/shell/ash.c index 9089adc63..ea835527e 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8214,7 +8214,7 @@ static int evalstring(char *s, int mask); /* Called to execute a trap. * Single callsite - at the end of evaltree(). - * If we return non-zero, exaltree raises EXEXIT exception. + * If we return non-zero, evaltree raises EXEXIT exception. * * Perhaps we should avoid entering new trap handlers * while we are executing a trap handler. [is it a TODO?] @@ -8404,11 +8404,15 @@ evaltree(union node *n, int flags) out: exception_handler = savehandler; + out1: + /* Order of checks below is important: + * signal handlers trigger before exit caused by "set -e". + */ + if (pending_sig && dotrap()) + goto exexit; if (checkexit & exitstatus) evalskip |= SKIPEVAL; - else if (pending_sig && dotrap()) - goto exexit; if (flags & EV_EXIT) { exexit: @@ -8740,7 +8744,7 @@ poplocalvars(void) while ((lvp = localvars) != NULL) { localvars = lvp->next; vp = lvp->vp; - TRACE(("poplocalvar %s\n", vp ? vp->text : "-")); + TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-")); if (vp == NULL) { /* $- saved */ memcpy(optlist, lvp->text, sizeof(optlist)); free((char*)lvp->text); @@ -13009,10 +13013,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv) if (e == EXERROR) exitstatus = 2; s = state; - if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) + if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) { exitshell(); - if (e == EXINT) + } + if (e == EXINT) { outcslow('\n', stderr); + } popstackmark(&smark); FORCE_INT_ON; /* enable interrupts */ @@ -13105,6 +13111,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) _mcleanup(); } #endif + TRACE(("End of main reached\n")); exitshell(); /* NOTREACHED */ } diff --git a/shell/ash_test/ash-signals/signal8.right b/shell/ash_test/ash-signals/signal8.right new file mode 100644 index 000000000..39572f30e --- /dev/null +++ b/shell/ash_test/ash-signals/signal8.right @@ -0,0 +1,3 @@ +Removing traps +End of exit_func +Done: 0 diff --git a/shell/ash_test/ash-signals/signal8.tests b/shell/ash_test/ash-signals/signal8.tests new file mode 100755 index 000000000..731af7477 --- /dev/null +++ b/shell/ash_test/ash-signals/signal8.tests @@ -0,0 +1,18 @@ +"$THIS_SH" -c ' +exit_func() { + echo "Removing traps" + trap - EXIT TERM INT + echo "End of exit_func" +} +set -e +trap exit_func EXIT TERM INT +sleep 2 +exit 77 +' & + +sleep 1 +# BUG: ash kills -PGRP, but in non-interactive shell we do not create pgrps! +# In this case, bash kills by PID, not PGRP. +kill -TERM %1 +wait +echo Done: $? diff --git a/shell/ash_test/ash-signals/signal9.right b/shell/ash_test/ash-signals/signal9.right new file mode 100644 index 000000000..39572f30e --- /dev/null +++ b/shell/ash_test/ash-signals/signal9.right @@ -0,0 +1,3 @@ +Removing traps +End of exit_func +Done: 0 diff --git a/shell/ash_test/ash-signals/signal9.tests b/shell/ash_test/ash-signals/signal9.tests new file mode 100755 index 000000000..18e71012b --- /dev/null +++ b/shell/ash_test/ash-signals/signal9.tests @@ -0,0 +1,21 @@ +# Note: the inner script is a test which checks for a different bug +# (ordering between INT handler and exit on "set -e"), +# but so far I did not figure out how to simulate it non-interactively. + +"$THIS_SH" -c ' +exit_func() { + echo "Removing traps" + trap - EXIT TERM INT + echo "End of exit_func" +} +set -e +trap exit_func EXIT TERM INT +sleep 2 +exit 77 +' & + +child=$! +sleep 1 +kill -TERM $child +wait +echo Done: $? -- cgit v1.2.3-55-g6feb From 04bcd998ca48954db738232f46fe3dfc273db36a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 25 Sep 2010 17:19:04 +0200 Subject: style fix. no code chages Signed-off-by: Denys Vlasenko --- coreutils/sleep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/coreutils/sleep.c b/coreutils/sleep.c index 9acb2d15f..433f9d6ee 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c @@ -50,7 +50,8 @@ int sleep_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_FLOAT_SLEEP # if ENABLE_LOCALE_SUPPORT - setlocale (LC_NUMERIC, "C"); + /* undo busybox.c setlocale */ + setlocale(LC_NUMERIC, "C"); # endif duration = 0; do { -- cgit v1.2.3-55-g6feb From 7d3a48a003cd645edfae2b404493688022b13193 Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Sun, 26 Sep 2010 00:15:12 +0200 Subject: udhcp: add support for 0x21 ROUTES and 0xf9 MS_STATIC_ROUTES options Signed-off-by: Vladislav Grishenko Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 4 ++++ networking/udhcp/common.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 97ab4cdbb..b6b274d91 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -37,6 +37,7 @@ const struct dhcp_optflag dhcp_optflags[] = { { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ { OPTION_U16 , 0x1a }, /* DHCP_MTU */ { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ + { OPTION_IP_PAIR | OPTION_LIST , 0x21 }, /* DHCP_ROUTES */ { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */ { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */ { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */ @@ -54,6 +55,7 @@ const struct dhcp_optflag dhcp_optflags[] = { { OPTION_SIP_SERVERS , 0x78 }, /* DHCP_SIP_SERVERS */ #endif { OPTION_STATIC_ROUTES , 0x79 }, /* DHCP_STATIC_ROUTES */ + { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ /* Options below have no match in dhcp_option_strings[], @@ -95,6 +97,7 @@ const char dhcp_option_strings[] ALIGN1 = "ipttl" "\0" /* DHCP_IP_TTL */ "mtu" "\0" /* DHCP_MTU */ "broadcast" "\0" /* DHCP_BROADCAST */ + "routes" "\0" /* DHCP_ROUTES */ "nisdomain" "\0" /* DHCP_NIS_DOMAIN */ "nissrv" "\0" /* DHCP_NIS_SERVER */ "ntpsrv" "\0" /* DHCP_NTP_SERVER */ @@ -114,6 +117,7 @@ const char dhcp_option_strings[] ALIGN1 = // doesn't work in udhcpd.conf since OPTION_STATIC_ROUTES // is not handled yet by "string->option" conversion code: "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ + "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ "wpad" "\0" /* DHCP_WPAD */ ; diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index c5abf17d5..9020b9c96 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -123,6 +123,7 @@ enum { //#define DHCP_IP_TTL 0x17 //#define DHCP_MTU 0x1a //#define DHCP_BROADCAST 0x1c +//#define DHCP_ROUTES 0x21 //#define DHCP_NIS_DOMAIN 0x28 //#define DHCP_NIS_SERVER 0x29 //#define DHCP_NTP_SERVER 0x2a @@ -144,6 +145,7 @@ enum { //#define DHCP_DOMAIN_SEARCH 0x77 /* RFC 3397. set of ASCIZ string, DNS-style compressed */ //#define DHCP_SIP_SERVERS 0x78 /* RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */ //#define DHCP_STATIC_ROUTES 0x79 /* RFC 3442. (mask,ip,router) tuples */ +//#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */ //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ #define DHCP_END 0xff -- cgit v1.2.3-55-g6feb From ccb7a4390004e3c32fbf93e93474fc124bcd17be Mon Sep 17 00:00:00 2001 From: Souf Oued Date: Sun, 26 Sep 2010 12:40:05 +0200 Subject: acpid: add config file and map file function old new delta acpid_main 434 1137 +703 find_action - 204 +204 f_evt_tab - 48 +48 packed_usage 27724 27755 +31 f_act_tab - 16 +16 process_event 126 - -126 ------------------------------------------------------------------------------ (add/remove: 3/1 grow/shrink: 2/0 up/down: 1002/-126) Total: 876 bytes Signed-off-by: Souf Oued Signed-off-by: Denys Vlasenko --- include/usage.src.h | 14 ++- util-linux/acpid.c | 306 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 218 insertions(+), 102 deletions(-) diff --git a/include/usage.src.h b/include/usage.src.h index 2866bdbba..922774674 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -18,21 +18,27 @@ INSERT #define acpid_trivial_usage \ - "[-d] [-c CONFDIR] [-l LOGFILE] [-e PROC_EVENT_FILE] [EVDEV_EVENT_FILE]..." + "[-d] [-c CONFDIR] [-l LOGFILE] [-a ACTIONFILE] [-M MAPFILE] [-e PROC_EVENT_FILE] [-p PIDFILE]" #define acpid_full_usage "\n\n" \ "Listen to ACPI events and spawn specific helpers on event arrival\n" \ "\nOptions:" \ - "\n -d Don't daemonize, log to stderr" \ "\n -c DIR Config directory [/etc/acpi]" \ + "\n -d Don't daemonize, (implies -f)" \ "\n -e FILE /proc event file [/proc/acpi/event]" \ - "\n -l FILE Log file [/var/log/acpid]" \ + "\n -f Run in foreground" \ + "\n -l FILE Log file [/var/log/acpid.log]" \ + "\n -p FILE Pid file [/var/run/acpid.pid]" \ + "\n -a FILE Action file [/etc/acpid.conf]" \ + "\n -M FILE Map file [/etc/acpi.map]" \ IF_FEATURE_ACPID_COMPAT( \ "\n\nAccept and ignore compatibility options -g -m -s -S -v" \ ) #define acpid_example_usage \ + "Without -e option, acpid uses all /dev/input/event* files\n" \ + "# acpid\n" \ "# acpid -l /var/log/my-acpi-log\n" \ - "# acpid -d /dev/input/event*\n" + "# acpid -e /proc/acpi/event\n" #define addgroup_trivial_usage \ "[-g GID] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP" diff --git a/util-linux/acpid.c b/util-linux/acpid.c index c3b3c8b0b..5a3bd5a6a 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c @@ -7,27 +7,58 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ #include "libbb.h" - +#include #include -#ifndef EV_SW -# define EV_SW 0x05 -#endif -#ifndef EV_KEY -# define EV_KEY 0x01 -#endif -#ifndef SW_LID -# define SW_LID 0x00 -#endif -#ifndef SW_RFKILL_ALL -# define SW_RFKILL_ALL 0x03 -#endif -#ifndef KEY_POWER -# define KEY_POWER 116 /* SC System Power Down */ -#endif -#ifndef KEY_SLEEP -# define KEY_SLEEP 142 /* SC System Sleep */ -#endif +enum { + OPT_c = (1 << 0), + OPT_d = (1 << 1), + OPT_e = (1 << 2), + OPT_f = (1 << 3), + OPT_l = (1 << 4), + OPT_p = (1 << 5) * ENABLE_FEATURE_PIDFILE, + OPT_a = (1 << 6), + OPT_M = (1 << 7), +}; + +struct acpi_event { + const char *s_type; + uint16_t n_type; + const char *s_code; + uint16_t n_code; + uint32_t value; + const char *desc; +}; + +static const struct acpi_event f_evt_tab[] = { + { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRF 00000080" }, + { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRB 00000080" }, +}; + +struct acpi_action { + const char *key; + const char *action; +}; + +static const struct acpi_action f_act_tab[] = { + { "PWRF", "PWRF/00000080" }, + { "LID0", "LID/00000080" }, +}; + +struct globals { + struct acpi_action *act_tab; + int n_act; + struct acpi_event *evt_tab; + int n_evt; +} FIX_ALIASING; +#define G (*ptr_to_globals) +#define act_tab (G.act_tab) +#define n_act (G.n_act ) +#define evt_tab (G.evt_tab) +#define n_evt (G.n_evt ) +#define INIT_G() do { \ + SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ +} while (0) /* * acpid listens to ACPI events coming either in textual form @@ -48,7 +79,7 @@ static void process_event(const char *event) const char *args[] = { "run-parts", handler, NULL }; // debug info - if (option_mask32 & 8) { // -d + if (option_mask32 & OPT_d) { bb_error_msg("%s", event); } @@ -60,125 +91,204 @@ static void process_event(const char *event) spawn((char **)args + (0==(st.st_mode & S_IFDIR))); else bb_simple_perror_msg(event); + free(handler); } +static const char *find_action(struct input_event *ev, const char *buf) +{ + const char *action = NULL; + int i; + + // map event + for (i = 0; i < n_evt; i++) { + if (ev) { + if (ev->type == evt_tab[i].n_type && ev->code == evt_tab[i].n_code && ev->value == evt_tab[i].value) { + action = evt_tab[i].desc; + break; + } + } + + if (buf) { + if (strncmp(buf, evt_tab[i].desc, strlen(buf)) == 0) { + action = evt_tab[i].desc; + break; + } + } + } + + // get action + if (action) { + for (i = 0; i < n_act; i++) { + if (strstr(action, act_tab[i].key)) { + action = act_tab[i].action; + break; + } + } + } + + return action; +} + +static void parse_conf_file(const char *filename) +{ + parser_t *parser; + char *tokens[2]; + + parser = config_open2(filename, fopen_for_read); + + if (parser) { + while (config_read(parser, tokens, 2, 2, "# \t", PARSE_NORMAL)) { + act_tab = xrealloc_vector(act_tab, 1, n_act); + act_tab[n_act].key = xstrdup(tokens[0]); + act_tab[n_act].action = xstrdup(tokens[1]); + n_act++; + } + config_close(parser); + } else { + act_tab = (void*)f_act_tab; + n_act = ARRAY_SIZE(f_act_tab); + } +} + +static void parse_map_file(const char *filename) +{ + parser_t *parser; + char *tokens[6]; + + parser = config_open2(filename, fopen_for_read); + + if (parser) { + while (config_read(parser, tokens, 6, 6, "# \t", PARSE_NORMAL)) { + evt_tab = xrealloc_vector(evt_tab, 1, n_evt); + evt_tab[n_evt].s_type = xstrdup(tokens[0]); + evt_tab[n_evt].n_type = xstrtou(tokens[1], 16); + evt_tab[n_evt].s_code = xstrdup(tokens[2]); + evt_tab[n_evt].n_code = xatou16(tokens[3]); + evt_tab[n_evt].value = xatoi_positive(tokens[4]); + evt_tab[n_evt].desc = xstrdup(tokens[5]); + n_evt++; + } + config_close(parser); + } else { + evt_tab = (void*)f_evt_tab; + n_evt = ARRAY_SIZE(f_evt_tab); + } +} + /* - * acpid [-c conf_dir] [-l log_file] [-e proc_event_file] [evdev_event_file...] -*/ + * acpid [-c conf_dir] [-r conf_file ] [-a map_file ] [-l log_file] [-e proc_event_file] + */ int acpid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int acpid_main(int argc, char **argv) +int acpid_main(int argc UNUSED_PARAM, char **argv) { + struct input_event ev; + int nfd; + int opts; struct pollfd *pfd; - int i, nfd; - const char *opt_conf = "/etc/acpi"; - const char *opt_input = "/proc/acpi/event"; + const char *opt_dir = "/etc/acpi"; + const char *opt_input = "/dev/input/event"; const char *opt_logfile = "/var/log/acpid.log"; + const char *opt_action = "/etc/acpid.conf"; + const char *opt_map = "/etc/acpi.map"; +#if ENABLE_FEATURE_PIDFILE + const char *opt_pidfile = "/var/run/acpid.pid"; +#endif + + INIT_G(); - getopt32(argv, "c:e:l:d" - IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), - &opt_conf, &opt_input, &opt_logfile - IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL, NULL) + opt_complementary = "df:e--e"; + opts = getopt32(argv, "c:de:fl:p:a:M:" IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), + &opt_dir, &opt_input, &opt_logfile, &opt_pidfile, &opt_action, &opt_map + IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL) ); - // daemonize unless -d given - if (!(option_mask32 & 8)) { // ! -d - bb_daemonize_or_rexec(0, argv); - close(2); - xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC); + if (!(opts & OPT_f)) { + bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); } - argv += optind; - argc -= optind; + if (!(opts & OPT_d)) { + openlog(applet_name, LOG_PID, LOG_DAEMON); + logmode = LOGMODE_SYSLOG | LOGMODE_STDIO; + } else { + xmove_fd(xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); + } - // goto configuration directory - xchdir(opt_conf); + parse_conf_file(opt_action); + parse_map_file(opt_map); - // prevent zombies - signal(SIGCHLD, SIG_IGN); + xchdir(opt_dir); - // no explicit evdev files given? -> use proc event interface - if (!*argv) { - // proc_event file is just a "config" :) - char *token[4]; - parser_t *parser = config_open(opt_input); + bb_signals((1 << SIGCHLD), SIG_IGN); + bb_signals(BB_FATAL_SIGS, record_signo); - // dispatch events - while (config_read(parser, token, 4, 4, "\0 ", PARSE_NORMAL)) { - char *event = xasprintf("%s/%s", token[1], token[2]); - process_event(event); - free(event); - } + pfd = NULL; + nfd = 0; + while (1) { + int fd; + char *dev_event; - if (ENABLE_FEATURE_CLEAN_UP) - config_close(parser); - return EXIT_SUCCESS; + dev_event = xasprintf((option_mask32 & OPT_e) ? "%s" : "%s%u", opt_input, nfd); + fd = open(dev_event, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + if (nfd == 0) + bb_simple_perror_msg_and_die(dev_event); + break; + } + pfd = xrealloc_vector(pfd, 1, nfd); + pfd[nfd].fd = fd; + pfd[nfd].events = POLLIN; + nfd++; } - // evdev files given, use evdev interface - - // open event devices - pfd = xzalloc(sizeof(*pfd) * argc); - nfd = 0; - while (*argv) { - pfd[nfd].fd = open_or_warn(*argv++, O_RDONLY | O_NONBLOCK); - if (pfd[nfd].fd >= 0) - pfd[nfd++].events = POLLIN; - } + write_pidfile(opt_pidfile); - // dispatch events - while (/* !bb_got_signal && */ poll(pfd, nfd, -1) > 0) { + while (poll(pfd, nfd, -1) > 0) { + int i; for (i = 0; i < nfd; i++) { - const char *event; - struct input_event ev; + const char *event = NULL; - if (!(pfd[i].revents & POLLIN)) - continue; + memset(&ev, 0, sizeof(ev)); - if (sizeof(ev) != full_read(pfd[i].fd, &ev, sizeof(ev))) - continue; -//bb_info_msg("%d: %d %d %4d", i, ev.type, ev.code, ev.value); - - // filter out unneeded events - if (ev.value != 1) + if (!(pfd[i].revents & POLLIN)) continue; - event = NULL; + if (option_mask32 & OPT_e) { + char *buf; + int len; - // N.B. we will conform to /proc/acpi/event - // naming convention when assigning event names + buf = xmalloc_reads(pfd[i].fd, NULL, NULL); + /* buf = "button/power PWRB 00000080 00000000" */ + len = strlen(buf) - 9; + if (len >= 0) + buf[len] = '\0'; + event = find_action(NULL, buf); + } else { + if (sizeof(ev) != full_read(pfd[i].fd, &ev, sizeof(ev))) + continue; - // TODO: do we want other events? + if (ev.value != 1 && ev.value != 0) + continue; - // power and sleep buttons delivered as keys pressed - if (EV_KEY == ev.type) { - if (KEY_POWER == ev.code) - event = "PWRF/00000080"; - else if (KEY_SLEEP == ev.code) - event = "SLPB/00000080"; - } - // switches - else if (EV_SW == ev.type) { - if (SW_LID == ev.code) - event = "LID/00000080"; - else if (SW_RFKILL_ALL == ev.code) - event = "RFKILL"; + event = find_action(&ev, NULL); } - // filter out unneeded events if (!event) continue; - // spawn event handler process_event(event); } } if (ENABLE_FEATURE_CLEAN_UP) { - for (i = 0; i < nfd; i++) - close(pfd[i].fd); + while (nfd--) { + if (pfd[nfd].fd) { + close(pfd[nfd].fd); + } + } free(pfd); } + remove_pidfile(opt_pidfile); return EXIT_SUCCESS; } -- cgit v1.2.3-55-g6feb From 6e852408a9ded4b5c6e5db001419d94471d2aad5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 30 Sep 2010 18:51:25 +0200 Subject: deluser: use the same licensing template in the header as other files do Signed-off-by: Denys Vlasenko --- loginutils/deluser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loginutils/deluser.c b/loginutils/deluser.c index 65817b943..08ca266d0 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c @@ -6,7 +6,7 @@ * Copyright (C) 1999,2000,2001 by John Beppu * Copyright (C) 2007 by Tito Ragusa * - * Licensed under GPL version 2, see file LICENSE in this tarball for details. + * Licensed under GPLv2, see file LICENSE in this source tree. * */ #include "libbb.h" -- cgit v1.2.3-55-g6feb From ee5ab8f321f7060c5720b50b1834f273e00f5859 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 30 Sep 2010 23:44:08 +0200 Subject: halt/poweroff/reboot: unify help text function old new delta packed_usage 27755 27733 -22 Signed-off-by: Denys Vlasenko --- include/usage.src.h | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/include/usage.src.h b/include/usage.src.h index 922774674..c26ed8b12 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -1521,13 +1521,31 @@ INSERT #define halt_full_usage "\n\n" \ "Halt the system\n" \ "\nOptions:" \ - "\n -d Delay interval for halting" \ - "\n -n No call to sync()" \ - "\n -f Force halt (don't go through init)" \ + "\n -d SEC Delay interval" \ + "\n -n Do not sync" \ + "\n -f Force (don't go through init)" \ IF_FEATURE_WTMP( \ "\n -w Only write a wtmp record" \ ) +#define poweroff_trivial_usage \ + "[-d DELAY] [-n] [-f]" +#define poweroff_full_usage "\n\n" \ + "Halt and shut off power\n" \ + "\nOptions:" \ + "\n -d SEC Delay interval" \ + "\n -n Do not sync" \ + "\n -f Force (don't go through init)" \ + +#define reboot_trivial_usage \ + "[-d DELAY] [-n] [-f]" +#define reboot_full_usage "\n\n" \ + "Reboot the system\n" \ + "\nOptions:" \ + "\n -d SEC Delay interval" \ + "\n -n Do not sync" \ + "\n -f Force (don't go through init)" \ + #define hdparm_trivial_usage \ "[OPTIONS] [DEVICE]" #define hdparm_full_usage "\n\n" \ @@ -3222,15 +3240,6 @@ INSERT "$ popmaildir -k ~/Maildir -- nc pop.drvv.ru 110 [ Date: Fri, 1 Oct 2010 21:57:59 +0200 Subject: free: add -b/k/m/g options; remove 4 TB limitation. +100 bytes Based on patch by Stefan Tomanek (stefan@pico.ruhr.de) Signed-off-by: Denys Vlasenko --- procps/free.c | 98 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/procps/free.c b/procps/free.c index be65f46f1..efbac5ba6 100644 --- a/procps/free.c +++ b/procps/free.c @@ -11,47 +11,58 @@ #include "libbb.h" +struct globals { + unsigned mem_unit; +#if ENABLE_DESKTOP + unsigned unit_steps; +# define G_unit_steps G.unit_steps +#else +# define G_unit_steps 10 +#endif +}; +#define G (*(struct globals*)&bb_common_bufsiz1) +#define INIT_G() do { } while (0) + + +static unsigned long long scale(unsigned long d) +{ + return ((unsigned long long)d * G.mem_unit) >> G_unit_steps; +} + + int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) { struct sysinfo info; - unsigned mem_unit; + + INIT_G(); #if ENABLE_DESKTOP - if (argv[1] && argv[1][0] == '-') - bb_show_usage(); + G.unit_steps = 10; + if (argv[1] && argv[1][0] == '-') { + switch (argv[1][1]) { + case 'b': + G.unit_steps = 0; + break; + case 'k': /* 2^10 */ + /* G.unit_steps = 10; - already is */ + break; + case 'm': /* 2^(2*10) */ + G.unit_steps = 20; + break; + case 'g': /* 2^(3*10) */ + G.unit_steps = 30; + break; + default: + bb_show_usage(); + } + } #endif sysinfo(&info); /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ - mem_unit = 1; - if (info.mem_unit != 0) { - mem_unit = info.mem_unit; - } - - /* Convert values to kbytes */ - if (mem_unit == 1) { - info.totalram >>= 10; - info.freeram >>= 10; -#if BB_MMU - info.totalswap >>= 10; - info.freeswap >>= 10; -#endif - info.sharedram >>= 10; - info.bufferram >>= 10; - } else { - mem_unit >>= 10; - /* TODO: Make all this stuff not overflow when mem >= 4 Tb */ - info.totalram *= mem_unit; - info.freeram *= mem_unit; -#if BB_MMU - info.totalswap *= mem_unit; - info.freeswap *= mem_unit; -#endif - info.sharedram *= mem_unit; - info.bufferram *= mem_unit; - } + G.mem_unit = (info.mem_unit ? info.mem_unit : 1); printf(" %13s%13s%13s%13s%13s\n", "total", @@ -63,30 +74,33 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) * /proc/meminfo instead and get "Cached: NNN kB" from there. */ ); -#define FIELDS_5 "%13lu%13lu%13lu%13lu%13lu\n" -#define FIELDS_3 (FIELDS_5 + 2*5) -#define FIELDS_2 (FIELDS_5 + 3*5) + +#define FIELDS_5 "%13llu%13llu%13llu%13llu%13llu\n" +#define FIELDS_3 (FIELDS_5 + 2*6) +#define FIELDS_2 (FIELDS_5 + 3*6) + printf("Mem: "); printf(FIELDS_5, - info.totalram, - info.totalram - info.freeram, - info.freeram, - info.sharedram, info.bufferram + scale(info.totalram), + scale(info.totalram - info.freeram), + scale(info.freeram), + scale(info.sharedram), + scale(info.bufferram) ); /* Show alternate, more meaningful busy/free numbers by counting * buffer cache as free memory (make it "-/+ buffers/cache" * if/when we add support for "cached" column): */ printf("-/+ buffers: "); printf(FIELDS_2, - info.totalram - info.freeram - info.bufferram, - info.freeram + info.bufferram + scale(info.totalram - info.freeram - info.bufferram), + scale(info.freeram + info.bufferram) ); #if BB_MMU printf("Swap:"); printf(FIELDS_3, - info.totalswap, - info.totalswap - info.freeswap, - info.freeswap + scale(info.totalswap), + scale(info.totalswap - info.freeswap), + scale(info.freeswap) ); #endif return EXIT_SUCCESS; -- cgit v1.2.3-55-g6feb From 5657d374dbd0b355980fb2128aa07d8dbe0e2934 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 1 Oct 2010 22:42:44 +0200 Subject: free: document newly added options Signed-off-by: Denys Vlasenko --- include/usage.src.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/usage.src.h b/include/usage.src.h index c26ed8b12..577eb5746 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -1301,7 +1301,7 @@ INSERT "\n -w Use WIDTH columns instead of 80" \ #define free_trivial_usage \ - "" + "" IF_DESKTOP("[-b/k/m/g]") #define free_full_usage "\n\n" \ "Display the amount of free and used system memory" #define free_example_usage \ -- cgit v1.2.3-55-g6feb From 2d1a78b88f6c986cbe147fc6f99091fd61f3bdd9 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Thu, 30 Sep 2010 14:31:12 -0700 Subject: Marked some more applets NOEXEC/NOFORK Signed-off-by: Dan Fandrich Signed-off-by: Denys Vlasenko --- coreutils/cksum.c | 2 ++ coreutils/dos2unix.c | 2 ++ coreutils/fold.c | 2 ++ coreutils/head.c | 2 ++ coreutils/id.c | 2 ++ coreutils/md5_sha1_sum.c | 2 ++ coreutils/mkfifo.c | 2 ++ coreutils/mknod.c | 2 ++ coreutils/printenv.c | 2 ++ include/applets.src.h | 26 +++++++++++++------------- 10 files changed, 31 insertions(+), 13 deletions(-) diff --git a/coreutils/cksum.c b/coreutils/cksum.c index 8e7800ee9..7bf383e2d 100644 --- a/coreutils/cksum.c +++ b/coreutils/cksum.c @@ -8,6 +8,8 @@ */ #include "libbb.h" +/* This is a NOEXEC applet. Be very careful! */ + int cksum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int cksum_main(int argc UNUSED_PARAM, char **argv) { diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c index 626c414f2..ba1ca8c79 100644 --- a/coreutils/dos2unix.c +++ b/coreutils/dos2unix.c @@ -14,6 +14,8 @@ #include "libbb.h" +/* This is a NOEXEC applet. Be very careful! */ + enum { CT_UNIX2DOS = 1, CT_DOS2UNIX diff --git a/coreutils/fold.c b/coreutils/fold.c index 54f1aa2ac..4a6429ad7 100644 --- a/coreutils/fold.c +++ b/coreutils/fold.c @@ -12,6 +12,8 @@ #include "libbb.h" #include "unicode.h" +/* This is a NOEXEC applet. Be very careful! */ + /* Must match getopt32 call */ #define FLAG_COUNT_BYTES 1 #define FLAG_BREAK_SPACES 2 diff --git a/coreutils/head.c b/coreutils/head.c index 0845b4375..669aae819 100644 --- a/coreutils/head.c +++ b/coreutils/head.c @@ -13,6 +13,8 @@ #include "libbb.h" +/* This is a NOEXEC applet. Be very careful! */ + static const char head_opts[] ALIGN1 = "n:" #if ENABLE_FEATURE_FANCY_HEAD diff --git a/coreutils/id.c b/coreutils/id.c index 56286f4d4..ed1dc862e 100644 --- a/coreutils/id.c +++ b/coreutils/id.c @@ -17,6 +17,8 @@ #include "libbb.h" +/* This is a NOEXEC applet. Be very careful! */ + #if !ENABLE_USE_BB_PWD_GRP #if defined(__UCLIBC_MAJOR__) && (__UCLIBC_MAJOR__ == 0) #if (__UCLIBC_MINOR__ < 9) || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 30) diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index 646f8bd10..5e36d391a 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c @@ -8,6 +8,8 @@ #include "libbb.h" +/* This is a NOEXEC applet. Be very careful! */ + typedef enum { /* 4th letter of applet_name is... */ HASH_MD5 = 's', /* "md5>s Date: Sat, 2 Oct 2010 12:42:28 +0200 Subject: grep: cap insane -B NUM values to MAX_INT / 8. Fixes bug 2653. function old new delta grep_main 766 779 +13 Signed-off-by: Denys Vlasenko --- findutils/grep.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/findutils/grep.c b/findutils/grep.c index 024f27609..ff6742a69 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -621,30 +621,33 @@ int grep_main(int argc UNUSED_PARAM, char **argv) /* do normal option parsing */ #if ENABLE_FEATURE_GREP_CONTEXT - int Copt; + int Copt, opts; /* -H unsets -h; -C unsets -A,-B; -e,-f are lists; * -m,-A,-B,-C have numeric param */ opt_complementary = "H-h:C-AB:e::f::m+:A+:B+:C+"; - getopt32(argv, + opts = getopt32(argv, OPTSTR_GREP, &pattern_head, &fopt, &max_matches, &lines_after, &lines_before, &Copt); - if (option_mask32 & OPT_C) { + if (opts & OPT_C) { /* -C unsets prev -A and -B, but following -A or -B may override it */ - if (!(option_mask32 & OPT_A)) /* not overridden */ + if (!(opts & OPT_A)) /* not overridden */ lines_after = Copt; - if (!(option_mask32 & OPT_B)) /* not overridden */ + if (!(opts & OPT_B)) /* not overridden */ lines_before = Copt; } /* sanity checks */ - if (option_mask32 & (OPT_c|OPT_q|OPT_l|OPT_L)) { + if (opts & (OPT_c|OPT_q|OPT_l|OPT_L)) { option_mask32 &= ~OPT_n; lines_before = 0; lines_after = 0; } else if (lines_before > 0) { + if (lines_before > INT_MAX / sizeof(long long)) + lines_before = INT_MAX / sizeof(long long); + /* overflow in (lines_before * sizeof(x)) is prevented (above) */ before_buf = xzalloc(lines_before * sizeof(before_buf[0])); IF_EXTRA_COMPAT(before_buf_size = xzalloc(lines_before * sizeof(before_buf_size[0]));) } -- cgit v1.2.3-55-g6feb From 238081f750f442c1dd851ba70243bd0819f3ca04 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 3 Oct 2010 14:26:26 +0200 Subject: hush: preparatory patch, no code changes Signed-off-by: Denys Vlasenko --- shell/hush.c | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 4c597e1ed..3b9362e10 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2000,26 +2000,9 @@ static void o_addstr_with_NUL(o_string *o, const char *str) o_addblock(o, str, strlen(str) + 1); } -static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len) -{ - while (len) { - len--; - o_addchr(o, *str); - if (*str++ == '\\') { - /* \z -> \\\z; \ -> \\ */ - o_addchr(o, '\\'); - if (len) { - len--; - o_addchr(o, '\\'); - o_addchr(o, *str++); - } - } - } -} - -#undef HUSH_BRACE_EXP +#undef HUSH_BRACE_EXPANSION /* - * HUSH_BRACE_EXP code needs corresponding quoting on variable expansion side. + * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side. * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v. * Apparently, on unquoted $v bash still does globbing * ("v='*.txt'; echo $v" prints all .txt files), @@ -2029,7 +2012,7 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len * We have only second one. */ -#ifdef HUSH_BRACE_EXP +#ifdef HUSH_BRACE_EXPANSION # define MAYBE_BRACES "{}" #else # define MAYBE_BRACES "" @@ -2197,7 +2180,7 @@ static int o_get_last_ptr(o_string *o, int n) return ((int)(uintptr_t)list[n-1]) + string_start; } -#ifdef HUSH_BRACE_EXP +#ifdef HUSH_BRACE_EXPANSION /* There in a GNU extension, GLOB_BRACE, but it is not usable: * first, it processes even {a} (no commas), second, * I didn't manage to make it return strings when they don't match @@ -2393,7 +2376,7 @@ static int perform_glob(o_string *o, int n) return n; } -#else /* !HUSH_BRACE_EXP */ +#else /* !HUSH_BRACE_EXPANSION */ /* Helper */ static int glob_needed(const char *s) @@ -2470,7 +2453,7 @@ static int perform_glob(o_string *o, int n) return n; } -#endif /* !HUSH_BRACE_EXP */ +#endif /* !HUSH_BRACE_EXPANSION */ /* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered. * Otherwise, just finish current list[] and start new */ @@ -4387,6 +4370,24 @@ static int process_command_subs(o_string *dest, const char *s); * followed by strings themselves. * Caller can deallocate entire list by single free(list). */ +/* A horde of its helpers come first: */ + +static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len) +{ + while (--len >= 0) { + o_addchr(o, *str); + if (*str++ == '\\') { + /* \z -> \\\z; \ -> \\ */ + o_addchr(o, '\\'); + if (len) { + len--; + o_addchr(o, '\\'); + o_addchr(o, *str++); + } + } + } +} + /* Store given string, finalizing the word and starting new one whenever * we encounter IFS char(s). This is used for expanding variable values. * End-of-string does NOT finalize word: think about 'echo -$VAR-' */ @@ -4395,9 +4396,9 @@ static int expand_on_ifs(o_string *output, int n, const char *str) while (1) { int word_len = strcspn(str, G.ifs); if (word_len) { - if (!(output->o_expflags & EXP_FLAG_GLOB)) + if (!(output->o_expflags & EXP_FLAG_GLOB)) { o_addblock(output, str, word_len); - else { + } else { /* Protect backslashes against globbing up :) * Example: "v='\*'; echo b$v" prints "b\*" * (and does not try to glob on "*") -- cgit v1.2.3-55-g6feb From 9e800223f13edeb02412936c810e7ee79f35c27c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 3 Oct 2010 14:28:04 +0200 Subject: hush: implement brace expansion When enabled: function old new delta glob_brace - 402 +402 next_brace_sub - 70 +70 expand_on_ifs 185 231 +46 bbconfig_config_bz2 4923 4929 +6 o_save_ptr 282 140 -142 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 2/1 up/down: 524/-142) Total: 382 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 3b9362e10..5b73f0c53 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -129,6 +129,13 @@ //config: help //config: Enable bash-compatible extensions. //config: +//config:config HUSH_BRACE_EXPANSION +//config: bool "Brace expansion" +//config: default y +//config: depends on HUSH_BASH_COMPAT +//config: help +//config: Enable {abc,def} extension. +//config: //config:config HUSH_HELP //config: bool "help builtin" //config: default y @@ -2000,7 +2007,6 @@ static void o_addstr_with_NUL(o_string *o, const char *str) o_addblock(o, str, strlen(str) + 1); } -#undef HUSH_BRACE_EXPANSION /* * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side. * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v. @@ -2012,7 +2018,7 @@ static void o_addstr_with_NUL(o_string *o, const char *str) * We have only second one. */ -#ifdef HUSH_BRACE_EXPANSION +#if ENABLE_HUSH_BRACE_EXPANSION # define MAYBE_BRACES "{}" #else # define MAYBE_BRACES "" @@ -2180,7 +2186,7 @@ static int o_get_last_ptr(o_string *o, int n) return ((int)(uintptr_t)list[n-1]) + string_start; } -#ifdef HUSH_BRACE_EXPANSION +#if ENABLE_HUSH_BRACE_EXPANSION /* There in a GNU extension, GLOB_BRACE, but it is not usable: * first, it processes even {a} (no commas), second, * I didn't manage to make it return strings when they don't match @@ -4375,8 +4381,17 @@ static int process_command_subs(o_string *dest, const char *s); static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len) { while (--len >= 0) { - o_addchr(o, *str); - if (*str++ == '\\') { + char c = *str++; +#if ENABLE_HUSH_BRACE_EXPANSION + if (c == '{' || c == '}') { + /* { -> \{, } -> \} */ + o_addchr(o, '\\'); + o_addchr(o, c); + continue; + } +#endif + o_addchr(o, c); + if (c == '\\') { /* \z -> \\\z; \ -> \\ */ o_addchr(o, '\\'); if (len) { -- cgit v1.2.3-55-g6feb From 2bcba5cc53a171fba2d9d0b5185f45d8026a2657 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 3 Oct 2010 17:07:57 +0200 Subject: hush: add brace expansion testcase Signed-off-by: Denys Vlasenko --- shell/hush_test/hush-glob/bash_brace1.right | 4 ++++ shell/hush_test/hush-glob/bash_brace1.tests | 10 ++++++++++ 2 files changed, 14 insertions(+) create mode 100644 shell/hush_test/hush-glob/bash_brace1.right create mode 100755 shell/hush_test/hush-glob/bash_brace1.tests diff --git a/shell/hush_test/hush-glob/bash_brace1.right b/shell/hush_test/hush-glob/bash_brace1.right new file mode 100644 index 000000000..63365c9e4 --- /dev/null +++ b/shell/hush_test/hush-glob/bash_brace1.right @@ -0,0 +1,4 @@ +bash_brace1.tests +*{b,b}race1.t* +bash_brace1.tests bash_brace1.tests +Done: 0 diff --git a/shell/hush_test/hush-glob/bash_brace1.tests b/shell/hush_test/hush-glob/bash_brace1.tests new file mode 100755 index 000000000..eb2f0e974 --- /dev/null +++ b/shell/hush_test/hush-glob/bash_brace1.tests @@ -0,0 +1,10 @@ +# unquoted $v should be globbed: +v='*brace1.t*'; echo $v + +# ...but not brace expanded: +v='*{b,b}race1.t*'; echo $v + +# whereas direct brces are expanded: +echo *{b,b}race1.t* + +echo Done: $? -- cgit v1.2.3-55-g6feb From 957f79f4714fbb0ee7d653d98609054f2a8d7545 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 3 Oct 2010 17:15:50 +0200 Subject: hush: small code shrink function old new delta expand_on_ifs 231 222 -9 Signed-off-by: Denys Vlasenko --- shell/hush.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 5b73f0c53..67a6d87f5 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4382,12 +4382,16 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len { while (--len >= 0) { char c = *str++; + #if ENABLE_HUSH_BRACE_EXPANSION if (c == '{' || c == '}') { /* { -> \{, } -> \} */ o_addchr(o, '\\'); - o_addchr(o, c); - continue; + /* And now we want to add { or } and continue: + * o_addchr(o, c); + * continue; + * luckily, just falling throught achieves this. + */ } #endif o_addchr(o, c); -- cgit v1.2.3-55-g6feb From bbecd74d5a9413412b59dafc2f200a181f960b20 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 3 Oct 2010 17:22:52 +0200 Subject: hush: remove brace expansion from TODO list in comments. No code changes. Signed-off-by: Denys Vlasenko --- shell/hush.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 67a6d87f5..1f907e1ba 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -8,6 +8,8 @@ * Copyright (C) 2000,2001 Larry Doolittle * Copyright (C) 2008,2009 Denys Vlasenko * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + * * Credits: * The parser routines proper are all original material, first * written Dec 2000 and Jan 2001 by Larry Doolittle. The @@ -50,7 +52,6 @@ * * Bash compat TODO: * redirection of stdout+stderr: &> and >& - * brace expansion: one/{two,three,four} * reserved words: function select * advanced test: [[ ]] * process substitution: <(list) and >(list) @@ -63,7 +64,9 @@ * The EXPR is evaluated according to ARITHMETIC EVALUATION. * This is exactly equivalent to let "EXPR". * $[EXPR]: synonym for $((EXPR)) - * export builtin should be special, its arguments are assignments + * + * Won't do: + * In bash, export builtin is special, its arguments are assignments * and therefore expansion of them should be "one-word" expansion: * $ export i=`echo 'a b'` # export has one arg: "i=a b" * compare with: @@ -77,8 +80,6 @@ * aaa bbb * $ "export" i=`echo 'aaa bbb'`; echo "$i" * aaa - * - * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ #include /* for malloc_trim */ -- cgit v1.2.3-55-g6feb From e2069fb325f598c81a37222c8e44436439757029 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 4 Oct 2010 00:01:47 +0200 Subject: hush: remove "doesn't support brace expansion" from config help text Signed-off-by: Denys Vlasenko --- shell/hush.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 1f907e1ba..75083dc2e 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -120,8 +120,8 @@ //config: //config: It will compile and work on no-mmu systems. //config: -//config: It does not handle select, aliases, brace expansion, -//config: tilde expansion, &>file and >&file redirection of stdout+stderr. +//config: It does not handle select, aliases, tilde expansion, +//config: &>file and >&file redirection of stdout+stderr. //config: //config:config HUSH_BASH_COMPAT //config: bool "bash-compatible extensions" -- cgit v1.2.3-55-g6feb From 9d113cac425d7f496da4d7b6f309b707cedd6b61 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 4 Oct 2010 00:49:48 +0200 Subject: patch: tweaks 1) Eliminate spurious warnings about possibly reduced hunks. Instead only note a possible location if we don't find a non-reversed place to apply it. (Otherwise, hunks that move code forward around within a file look reversed at the removal site.) 2) Open the source file read-only, so we can apply patches to read-only files. Signed-off-by: Rob Landley Signed-off-by: Denys Vlasenko --- editors/patch.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/editors/patch.c b/editors/patch.c index c40f54155..0bde2cab3 100644 --- a/editors/patch.c +++ b/editors/patch.c @@ -344,14 +344,12 @@ static int apply_one_hunk(void) while (plist && *plist->data == "+-"[reverse]) { if (data && !strcmp(data, plist->data+1)) { if (!backwarn) { - backwarn++; + backwarn = TT.linenum; if (option_mask32 & FLAG_IGNORE) { dummy_revert = 1; reverse ^= 1; continue; } - fdprintf(2,"Possibly reversed hunk %d at %ld\n", - TT.hunknum, TT.linenum); } } plist = plist->next; @@ -364,6 +362,10 @@ static int apply_one_hunk(void) // Does this hunk need to match EOF? if (!plist && matcheof) break; + if (backwarn) + fdprintf(2,"Possibly reversed hunk %d at %ld\n", + TT.hunknum, TT.linenum); + // File ended before we found a place for this hunk. fail_hunk(); goto done; @@ -592,7 +594,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) TT.filein = xopen3(name, O_CREAT|O_EXCL|O_RDWR, 0666); } else { printf("patching file %s\n", name); - TT.filein = xopen(name, O_RDWR); + TT.filein = xopen(name, O_RDONLY); } TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname); TT.linenum = 0; -- cgit v1.2.3-55-g6feb From d678257c26e0993efc48ac4433d153e1e9dfc954 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 4 Oct 2010 01:20:44 +0200 Subject: ntpd: allow peer-less (standalone stratum 1 server) operation Based on patch by Jean-Christophe Dubois (jcd@tribudubois.net) function old new delta ntp_init 384 399 +15 recv_and_process_client_pkt 469 480 +11 Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 6707e9bdb..ca4afa045 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -1765,6 +1765,10 @@ recv_and_process_client_pkt(void /*int fd*/) /* this time was obtained between poll() and recv() */ msg.m_rectime = d_to_lfp(G.cur_time); msg.m_xmttime = d_to_lfp(gettime1900d()); /* this instant */ + if (G.peer_cnt == 0) { + /* we have no peers: "stratum 1 server" mode. reftime = our own time */ + G.reftime = G.cur_time; + } msg.m_reftime = d_to_lfp(G.reftime); msg.m_orgtime = query_xmttime; msg.m_rootdelay = d_to_sfp(G.rootdelay); @@ -1902,8 +1906,13 @@ static NOINLINE void ntp_init(char **argv) bb_show_usage(); // if (opts & OPT_x) /* disable stepping, only slew is allowed */ // G.time_was_stepped = 1; - while (peers) - add_peers(llist_pop(&peers)); + if (peers) { + while (peers) + add_peers(llist_pop(&peers)); + } else { + /* -l but no peers: "stratum 1 server" mode */ + G.stratum = 1; + } if (!(opts & OPT_n)) { bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); logmode = LOGMODE_NONE; -- cgit v1.2.3-55-g6feb From 9a1b2605476c8e6e69a3666e9f538004b6623962 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 4 Oct 2010 14:19:59 +0200 Subject: man: add compatibility with man-db Signed-off-by: Denys Vlasenko --- miscutils/man.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/miscutils/man.c b/miscutils/man.c index 2d3776cf3..b356e726f 100644 --- a/miscutils/man.c +++ b/miscutils/man.c @@ -182,16 +182,21 @@ int man_main(int argc UNUSED_PARAM, char **argv) pager = "more"; } - /* Parse man.conf[ig] */ + /* Parse man.conf[ig] or man_db.conf */ /* man version 1.6f uses man.config */ + /* man-db implementation of man uses man_db.conf */ parser = config_open2("/etc/man.config", fopen_for_read); if (!parser) parser = config_open2("/etc/man.conf", fopen_for_read); + if (!parser) + parser = config_open2("/etc/man_db.conf", fopen_for_read); while (config_read(parser, token, 2, 0, "# \t", PARSE_NORMAL)) { if (!token[1]) continue; - if (strcmp("MANPATH", token[0]) == 0) { + if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */ + || strcmp("MANDATORY_MANPATH", token[0]) == 0 + ) { char *path = token[1]; while (*path) { char *next_path; -- cgit v1.2.3-55-g6feb From 09e7dafbfe358bed5a3bbf45dc2369760c09a47e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 4 Oct 2010 17:04:20 +0200 Subject: wc: preparatory patch, no logic changes Signed-off-by: Denys Vlasenko --- coreutils/wc.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/coreutils/wc.c b/coreutils/wc.c index 4f14374c3..ae38fd5fe 100644 --- a/coreutils/wc.c +++ b/coreutils/wc.c @@ -59,10 +59,11 @@ #endif enum { - WC_LINES = 0, - WC_WORDS = 1, - WC_CHARS = 2, - WC_LENGTH = 3 + WC_LINES = 0, + WC_WORDS = 1, + WC_CHARS = 2, + WC_LENGTH = 3, + NUM_WCS = 4, }; int wc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -72,8 +73,8 @@ int wc_main(int argc UNUSED_PARAM, char **argv) const char *start_fmt = " %9"COUNT_FMT + 1; const char *fname_fmt = " %s\n"; COUNT_T *pcounts; - COUNT_T counts[4]; - COUNT_T totals[4]; + COUNT_T counts[NUM_WCS]; + COUNT_T totals[NUM_WCS]; int num_files; smallint status = EXIT_SUCCESS; unsigned print_type; @@ -99,7 +100,7 @@ int wc_main(int argc UNUSED_PARAM, char **argv) pcounts = counts; num_files = 0; - while ((arg = *argv++) != 0) { + while ((arg = *argv++) != NULL) { FILE *fp; const char *s; unsigned u; @@ -117,20 +118,20 @@ int wc_main(int argc UNUSED_PARAM, char **argv) linepos = 0; in_word = 0; - do { + while (1) { int c; /* Our -w doesn't match GNU wc exactly... oh well */ - ++counts[WC_CHARS]; c = getc(fp); if (c == EOF) { if (ferror(fp)) { bb_simple_perror_msg(arg); status = EXIT_FAILURE; } - --counts[WC_CHARS]; goto DO_EOF; /* Treat an EOF as '\r'. */ } + ++counts[WC_CHARS]; + if (isprint_asciionly(c)) { ++linepos; if (!isspace(c)) { @@ -167,18 +168,18 @@ int wc_main(int argc UNUSED_PARAM, char **argv) if (c == EOF) { break; } - } while (1); + } + + fclose_if_not_stdin(fp); if (totals[WC_LENGTH] < counts[WC_LENGTH]) { totals[WC_LENGTH] = counts[WC_LENGTH]; } totals[WC_LENGTH] -= counts[WC_LENGTH]; - fclose_if_not_stdin(fp); - OUTPUT: /* coreutils wc tries hard to print pretty columns - * (saves results for all files, find max col len etc...) + * (saves results for all files, finds max col len etc...) * we won't try that hard, it will bloat us too much */ s = start_fmt; u = 0; @@ -188,7 +189,7 @@ int wc_main(int argc UNUSED_PARAM, char **argv) s = " %9"COUNT_FMT; /* Ok... restore the leading space. */ } totals[u] += pcounts[u]; - } while (++u < 4); + } while (++u < NUM_WCS); printf(fname_fmt, arg); } -- cgit v1.2.3-55-g6feb From afc7b4c0d83ab82eb20cedae5d9676c3a21af4bf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 4 Oct 2010 17:08:14 +0200 Subject: wc: add support for -m function old new delta wc_main 601 637 +36 packed_usage 27357 27358 +1 Signed-off-by: Denys Vlasenko --- coreutils/wc.c | 58 +++++++++++++++++++++++++++++++++++++++++------------ include/usage.src.h | 15 -------------- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/coreutils/wc.c b/coreutils/wc.c index ae38fd5fe..ecadae59b 100644 --- a/coreutils/wc.c +++ b/coreutils/wc.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -/* BB_AUDIT SUSv3 _NOT_ compliant -- option -m is not currently supported. */ +/* BB_AUDIT SUSv3 compliant. */ /* http://www.opengroup.org/onlinepubs/007904975/utilities/wc.html */ /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) @@ -19,10 +19,6 @@ * 3) no checking of ferror on EOF returns * 4) isprint() wasn't considered when word counting. * - * TODO: - * - * When locale support is enabled, count multibyte chars in the '-m' case. - * * NOTES: * * The previous busybox wc attempted an optimization using stat for the @@ -40,8 +36,8 @@ * * for which 'wc -c' should output '0'. */ - #include "libbb.h" +#include "unicode.h" #if !ENABLE_LOCALE_SUPPORT # undef isprint @@ -58,12 +54,39 @@ # define COUNT_FMT "u" #endif +/* We support -m even when UNICODE_SUPPORT is off, + * we just don't advertise it in help text, + * since it is the same as -c in this case. + */ + +//usage:#define wc_trivial_usage +//usage: "[-c"IF_UNICODE_SUPPORT("m")"lwL] [FILE]..." +//usage: +//usage:#define wc_full_usage "\n\n" +//usage: "Count lines, words, and bytes for each FILE (or stdin)\n" +//usage: "\nOptions:" +//usage: "\n -c Count bytes" +//usage: IF_UNICODE_SUPPORT( +//usage: "\n -m Count characters" +//usage: ) +//usage: "\n -l Count newlines" +//usage: "\n -w Count words" +//usage: "\n -L Print longest line length" +//usage: +//usage:#define wc_example_usage +//usage: "$ wc /etc/passwd\n" +//usage: " 31 46 1365 /etc/passwd\n" + +/* Order is important if we want to be compatible with + * column order in "wc -cmlwL" output: + */ enum { - WC_LINES = 0, - WC_WORDS = 1, - WC_CHARS = 2, - WC_LENGTH = 3, - NUM_WCS = 4, + WC_LINES = 0, + WC_WORDS = 1, + WC_UNICHARS = 2, + WC_CHARS = 3, + WC_LENGTH = 4, + NUM_WCS = 5, }; int wc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -79,7 +102,9 @@ int wc_main(int argc UNUSED_PARAM, char **argv) smallint status = EXIT_SUCCESS; unsigned print_type; - print_type = getopt32(argv, "lwcL"); + init_unicode(); + + print_type = getopt32(argv, "lwcmL"); if (print_type == 0) { print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS); @@ -130,9 +155,16 @@ int wc_main(int argc UNUSED_PARAM, char **argv) } goto DO_EOF; /* Treat an EOF as '\r'. */ } + + /* Cater for -c and -m */ ++counts[WC_CHARS]; + if (unicode_status != UNICODE_ON /* every byte is a new char */ + || (c & 0xc0) != 0x80 /* it isn't a 2nd+ byte of a Unicode char */ + ) { + ++counts[WC_UNICHARS]; + } - if (isprint_asciionly(c)) { + if (isprint_asciionly(c)) { /* FIXME: not unicode-aware */ ++linepos; if (!isspace(c)) { in_word = 1; diff --git a/include/usage.src.h b/include/usage.src.h index 577eb5746..e7e9269e9 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -4764,21 +4764,6 @@ INSERT "\n" \ "\nUse 500ms to specify period in milliseconds" \ -#define wc_trivial_usage \ - "[OPTIONS] [FILE]..." -#define wc_full_usage "\n\n" \ - "Print line, word, and byte counts for each FILE (or stdin),\n" \ - "and a total line if more than one FILE is specified\n" \ - "\nOptions:" \ - "\n -c Print the byte counts" \ - "\n -l Print the newline counts" \ - "\n -L Print the length of the longest line" \ - "\n -w Print the word counts" \ - -#define wc_example_usage \ - "$ wc /etc/passwd\n" \ - " 31 46 1365 /etc/passwd\n" - #define wget_trivial_usage \ IF_FEATURE_WGET_LONG_OPTIONS( \ "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n" \ -- cgit v1.2.3-55-g6feb From cacb2cd281392135871364c3beb1f8143396ccc0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 5 Oct 2010 00:13:02 +0200 Subject: *: whitespace fixes Signed-off-by: Denys Vlasenko --- editors/patch.c | 2 +- editors/patch_toybox.c | 2 +- shell/ash.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/editors/patch.c b/editors/patch.c index 0bde2cab3..764f0f183 100644 --- a/editors/patch.c +++ b/editors/patch.c @@ -554,7 +554,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) int oldsum, newsum, del = 0; char *name; - oldsum = TT.oldline + TT.oldlen; + oldsum = TT.oldline + TT.oldlen; newsum = TT.newline + TT.newlen; name = reverse ? oldname : newname; diff --git a/editors/patch_toybox.c b/editors/patch_toybox.c index 7f3234e66..04bd98eea 100644 --- a/editors/patch_toybox.c +++ b/editors/patch_toybox.c @@ -522,7 +522,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) int oldsum, newsum, del = 0; char *s, *name; - oldsum = TT.oldline + TT.oldlen; + oldsum = TT.oldline + TT.oldlen; newsum = TT.newline + TT.newlen; name = reverse ? oldname : newname; diff --git a/shell/ash.c b/shell/ash.c index ea835527e..fbf3efce2 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12840,7 +12840,7 @@ init(void) /* bash re-enables SIGHUP which is SIG_IGNed on entry. * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$" */ - signal(SIGHUP, SIG_DFL); + signal(SIGHUP, SIG_DFL); /* from var.c: */ { -- cgit v1.2.3-55-g6feb From 5aa4d532735b715f10560513e79e96f237957570 Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Tue, 5 Oct 2010 00:39:46 +0200 Subject: tune2fs: implement -c and -i options function old new delta tune2fs_main 165 256 +91 Signed-off-by: Richard Braun Signed-off-by: Denys Vlasenko --- e2fsprogs/tune2fs.c | 40 +++++++++++++++++++++++++++++++++++----- include/usage.src.h | 12 ------------ 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/e2fsprogs/tune2fs.c b/e2fsprogs/tune2fs.c index 311349fec..75e4f6bcf 100644 --- a/e2fsprogs/tune2fs.c +++ b/e2fsprogs/tune2fs.c @@ -27,24 +27,40 @@ do { \ #define FETCH_LE32(field) \ (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size()) +//usage:#define tune2fs_trivial_usage +//usage: "[-c MOUNT_CNT] " +////usage: "[-e errors-behavior] [-g group] " +//usage: "[-i DAYS] " +////usage: "[-j] [-J journal-options] [-l] [-s sparse-flag] " +////usage: "[-m reserved-blocks-percent] [-o [^]mount-options[,...]] " +////usage: "[-r reserved-blocks-count] [-u user] [-C mount-count] " +//usage: "[-L LABEL] " +////usage: "[-M last-mounted-dir] [-O [^]feature[,...]] " +////usage: "[-T last-check-time] [-U UUID] " +//usage: "BLOCKDEV" +//usage: +//usage:#define tune2fs_full_usage "\n\n" +//usage: "Adjust filesystem options on ext[23] filesystems" + enum { OPT_L = 1 << 0, // label + OPT_c = 1 << 1, // max mount count + OPT_i = 1 << 2, // check interval }; int tune2fs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int tune2fs_main(int argc UNUSED_PARAM, char **argv) { unsigned opts; - const char *label; + const char *label, *str_c, *str_i; struct ext2_super_block *sb; int fd; opt_complementary = "=1"; - opts = getopt32(argv, "L:", &label); - argv += optind; // argv[0] -- device - + opts = getopt32(argv, "L:c:i:", &label, &str_c, &str_i); if (!opts) bb_show_usage(); + argv += optind; // argv[0] -- device // read superblock fd = xopen(argv[0], O_RDWR); @@ -54,9 +70,23 @@ int tune2fs_main(int argc UNUSED_PARAM, char **argv) // mangle superblock //STORE_LE(sb->s_wtime, time(NULL)); - why bother? + // set the label - if (1 /*opts & OPT_L*/) + if (opts & OPT_L) safe_strncpy((char *)sb->s_volume_name, label, sizeof(sb->s_volume_name)); + + if (opts & OPT_c) { + int n = xatoi_range(str_c, -1, 0xfffe); + if (n == 0) + n = -1; + STORE_LE(sb->s_max_mnt_count, (unsigned)n); + } + + if (opts & OPT_i) { + unsigned n = xatou_range(str_i, 0, (unsigned)0xffffffff / (24*60*60)) * 24*60*60; + STORE_LE(sb->s_checkinterval, n); + } + // write superblock xlseek(fd, 1024, SEEK_SET); xwrite(fd, sb, 1024); diff --git a/include/usage.src.h b/include/usage.src.h index e7e9269e9..92a106e3b 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -4459,18 +4459,6 @@ INSERT "# tunctl\n" \ "# tunctl -d tun0\n" -#define tune2fs_trivial_usage \ -/* "[-c max-mounts-count] [-e errors-behavior] [-g group] " */ \ -/* "[-i interval[d|m|w]] [-j] [-J journal-options] [-l] [-s sparse-flag] " */ \ -/* "[-m reserved-blocks-percent] [-o [^]mount-options[,...]] " */ \ -/* "[-r reserved-blocks-count] [-u user] [-C mount-count] " */ \ - "[-L LABEL] " \ -/* "[-M last-mounted-dir] [-O [^]feature[,...]] " */ \ -/* "[-T last-check-time] [-U UUID] " */ \ - "BLOCKDEV" -#define tune2fs_full_usage "\n\n" \ - "Adjust filesystem options on ext[23] filesystems" - #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 # define IF_UDHCP_VERBOSE(...) __VA_ARGS__ #else -- cgit v1.2.3-55-g6feb From 5b3430017895001e134b6c37a0ea4d2c082ba209 Mon Sep 17 00:00:00 2001 From: Vladimir Dronnikov Date: Tue, 5 Oct 2010 01:21:32 +0200 Subject: sendmail: fix assumption that headers should have a space after the colon Signed-off-by: Vladimir Dronnikov Signed-off-by: Denys Vlasenko --- mailutils/sendmail.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mailutils/sendmail.c b/mailutils/sendmail.c index 59591ee4b..ec97cf8af 100644 --- a/mailutils/sendmail.c +++ b/mailutils/sendmail.c @@ -221,12 +221,12 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) // analyze headers // To: or Cc: headers add recipients - if (0 == strncasecmp("To: ", s, 4) || 0 == strncasecmp("Bcc: " + 1, s, 4)) { - rcptto(sane_address(s+4)); + if (0 == strncasecmp("To:", s, 3) || 0 == strncasecmp("Bcc:" + 1, s, 3)) { + rcptto(sane_address(s+3)); goto addheader; // Bcc: header adds blind copy (hidden) recipient - } else if (0 == strncasecmp("Bcc: ", s, 5)) { - rcptto(sane_address(s+5)); + } else if (0 == strncasecmp("Bcc:", s, 4)) { + rcptto(sane_address(s+4)); free(s); // N.B. Bcc: vanishes from headers! -- cgit v1.2.3-55-g6feb From d527e0c81d2efe98f258f1e1516a0e9cbe879154 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 5 Oct 2010 13:22:11 +0200 Subject: awk: 00.123 is not a octal constant; neither is 009.123. fixing this function old new delta my_strtod 80 113 +33 Signed-off-by: Denys Vlasenko --- editors/awk.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- testsuite/awk.tests | 6 ++++++ 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/editors/awk.c b/editors/awk.c index f47d1ab02..d9f9e0f6e 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -17,10 +17,14 @@ /* If you comment out one of these below, it will be #defined later * to perform debug printfs to stderr: */ #define debug_printf_walker(...) do {} while (0) +#define debug_printf_eval(...) do {} while (0) #ifndef debug_printf_walker # define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__)) #endif +#ifndef debug_printf_eval +# define debug_printf_eval(...) (fprintf(stderr, __VA_ARGS__)) +#endif @@ -700,14 +704,27 @@ static ALWAYS_INLINE int isalnum_(int c) static double my_strtod(char **pp) { + char *cp = *pp; #if ENABLE_DESKTOP - if ((*pp)[0] == '0' - && ((((*pp)[1] | 0x20) == 'x') || isdigit((*pp)[1])) - ) { - return strtoull(*pp, pp, 0); + if (cp[0] == '0') { + /* Might be hex or octal integer: 0x123abc or 07777 */ + char c = (cp[1] | 0x20); + if (c == 'x' || isdigit(cp[1])) { + unsigned long long ull = strtoull(cp, pp, 0); + if (c == 'x') + return ull; + c = **pp; + if (!isdigit(c) && c != '.') + return ull; + /* else: it may be a floating number. Examples: + * 009.123 (*pp points to '9') + * 000.123 (*pp points to '.') + * fall through to strtod. + */ + } } #endif - return strtod(*pp, pp); + return strtod(cp, pp); } /* -------- working with variables (set/get/copy/etc) -------- */ @@ -817,17 +834,21 @@ static double getvar_i(var *v) v->number = 0; s = v->string; if (s && *s) { + debug_printf_eval("getvar_i: '%s'->", s); v->number = my_strtod(&s); + debug_printf_eval("%f (s:'%s')\n", v->number, s); if (v->type & VF_USER) { s = skip_spaces(s); if (*s != '\0') v->type &= ~VF_USER; } } else { + debug_printf_eval("getvar_i: '%s'->zero\n", s); v->type &= ~VF_USER; } v->type |= VF_CACHED; } + debug_printf_eval("getvar_i: %f\n", v->number); return v->number; } @@ -849,6 +870,7 @@ static var *copyvar(var *dest, const var *src) if (dest != src) { clrvar(dest); dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR)); + debug_printf_eval("copyvar: number:%f string:'%s'\n", src->number, src->string); dest->number = src->number; if (src->string) dest->string = xstrdup(src->string); @@ -2347,18 +2369,25 @@ static var *evaluate(node *op, var *res) opn = (opinfo & OPNMASK); g_lineno = op->lineno; op1 = op->l.n; + debug_printf_eval("opinfo:%08x opn:%08x XC:%x\n", opinfo, opn, XC(opinfo & OPCLSMASK)); /* execute inevitable things */ if (opinfo & OF_RES1) L.v = evaluate(op1, v1); if (opinfo & OF_RES2) R.v = evaluate(op->r.n, v1+1); - if (opinfo & OF_STR1) + if (opinfo & OF_STR1) { L.s = getvar_s(L.v); - if (opinfo & OF_STR2) + debug_printf_eval("L.s:'%s'\n", L.s); + } + if (opinfo & OF_STR2) { R.s = getvar_s(R.v); - if (opinfo & OF_NUM1) + debug_printf_eval("R.s:'%s'\n", R.s); + } + if (opinfo & OF_NUM1) { L_d = getvar_i(L.v); + debug_printf_eval("L_d:%f\n", L_d); + } switch (XC(opinfo & OPCLSMASK)) { @@ -2526,6 +2555,7 @@ static var *evaluate(node *op, var *res) break; case XC( OC_MOVE ): + debug_printf_eval("MOVE\n"); /* if source is a temporary string, jusk relink it to dest */ //Disabled: if R.v is numeric but happens to have cached R.v->string, //then L.v ends up being a string, which is wrong @@ -2777,6 +2807,7 @@ static var *evaluate(node *op, var *res) case XC( OC_BINARY ): case XC( OC_REPLACE ): { double R_d = getvar_i(R.v); + debug_printf_eval("BINARY/REPLACE: R_d:%f opn:%c\n", R_d, opn); switch (opn) { case '+': L_d += R_d; @@ -2805,6 +2836,7 @@ static var *evaluate(node *op, var *res) L_d -= (int)(L_d / R_d) * R_d; break; } + debug_printf_eval("BINARY/REPLACE result:%f\n", L_d); res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : L.v, L_d); break; } diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 9e5e5a0f1..56b11ca46 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests @@ -24,6 +24,12 @@ testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" SKIP= +# check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN +testing "awk floating const with leading zeroes" \ + "awk '{ printf \"%f %f\n\", \"000.123\", \"009.123\" }'" \ + "0.123000 9.123000\n" \ + "" "\n" + # long field seps requiring regex testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ "2 0 \n3 0 \n4 0 \n5 0 \n" \ -- cgit v1.2.3-55-g6feb From 28458c64db779c27ecd63f400ea9af0e3e6b555a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 5 Oct 2010 16:49:03 +0200 Subject: awk: code shrink function old new delta fsrealloc 112 107 -5 next_token 862 844 -18 Signed-off-by: Denys Vlasenko --- editors/awk.c | 84 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/editors/awk.c b/editors/awk.c index d9f9e0f6e..2245cad03 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -987,7 +987,6 @@ static uint32_t next_token(uint32_t expected) const char *tl; uint32_t tc; const uint32_t *ti; - int l; if (t_rollback) { t_rollback = FALSE; @@ -1053,7 +1052,7 @@ static uint32_t next_token(uint32_t expected) char *pp = p; t_double = my_strtod(&pp); p = pp; - if (*pp == '.') + if (*p == '.') syntax_error(EMSG_UNEXP_TOKEN); tc = TC_NUMBER; @@ -1063,52 +1062,51 @@ static uint32_t next_token(uint32_t expected) tc = 0x00000001; ti = tokeninfo; while (*tl) { - l = *tl++; - if (l == NTCC) { + int l = (unsigned char) *tl++; + if (l == (unsigned char) NTCC) { tc <<= 1; continue; } - /* if token class is expected, token - * matches and it's not a longer word, - * then this is what we are looking for + /* if token class is expected, + * token matches, + * and it's not a longer word, */ if ((tc & (expected | TC_WORD | TC_NEWLINE)) - && *tl == *p && strncmp(p, tl, l) == 0 + && strncmp(p, tl, l) == 0 && !((tc & TC_WORD) && isalnum_(p[l])) ) { + /* then this is what we are looking for */ t_info = *ti; p += l; - break; + goto token_found; } ti++; tl += l; } - - if (!*tl) { - /* it's a name (var/array/function), - * otherwise it's something wrong - */ - if (!isalnum_(*p)) - syntax_error(EMSG_UNEXP_TOKEN); - - t_string = --p; - while (isalnum_(*++p)) { - p[-1] = *p; - } - p[-1] = '\0'; - tc = TC_VARIABLE; - /* also consume whitespace between functionname and bracket */ - if (!(expected & TC_VARIABLE) || (expected & TC_ARRAY)) - p = skip_spaces(p); - if (*p == '(') { - tc = TC_FUNCTION; - } else { - if (*p == '[') { - p++; - tc = TC_ARRAY; - } + /* not a known token */ + + /* is it a name? (var/array/function) */ + if (!isalnum_(*p)) + syntax_error(EMSG_UNEXP_TOKEN); /* no */ + /* yes */ + t_string = --p; + while (isalnum_(*++p)) { + p[-1] = *p; + } + p[-1] = '\0'; + tc = TC_VARIABLE; + /* also consume whitespace between functionname and bracket */ + if (!(expected & TC_VARIABLE) || (expected & TC_ARRAY)) + p = skip_spaces(p); + if (*p == '(') { + tc = TC_FUNCTION; + } else { + if (*p == '[') { + p++; + tc = TC_ARRAY; } } + token_found: ; } g_pos = p; @@ -1186,6 +1184,7 @@ static node *parse_expr(uint32_t iexp) xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; while (!((tc = next_token(xtc)) & iexp)) { + if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) { /* input redirection (<) attached to glptr node */ cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37)); @@ -1522,10 +1521,10 @@ static node *mk_splitter(const char *s, tsplitter *spl) regfree(re); regfree(ire); // TODO: nuke ire, use re+1? } - if (strlen(s) > 1) { + if (s[0] && s[1]) { /* strlen(s) > 1 */ mk_re_node(s, n, re); } else { - n->info = (uint32_t) *s; + n->info = (uint32_t) s[0]; } return n; @@ -1582,24 +1581,22 @@ static void fsrealloc(int size) if (size >= maxfields) { i = maxfields; maxfields = size + 16; - Fields = xrealloc(Fields, maxfields * sizeof(var)); + Fields = xrealloc(Fields, maxfields * sizeof(Fields[0])); for (; i < maxfields; i++) { Fields[i].type = VF_SPECIAL; Fields[i].string = NULL; } } - - if (size < nfields) { - for (i = size; i < nfields; i++) { - clrvar(Fields + i); - } + /* if size < nfields, clear extra field variables */ + for (i = size; i < nfields; i++) { + clrvar(Fields + i); } nfields = size; } static int awk_split(const char *s, node *spl, char **slist) { - int l, n = 0; + int l, n; char c[4]; char *s1; regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... @@ -1613,6 +1610,7 @@ static int awk_split(const char *s, node *spl, char **slist) if (*getvar_s(intvar[RS]) == '\0') c[2] = '\n'; + n = 0; if ((spl->info & OPCLSMASK) == OC_REGEXP) { /* regex split */ if (!*s) return n; /* "": zero fields */ @@ -1658,7 +1656,7 @@ static int awk_split(const char *s, node *spl, char **slist) } if (*s1) n++; - while ((s1 = strpbrk(s1, c))) { + while ((s1 = strpbrk(s1, c)) != NULL) { *s1++ = '\0'; n++; } -- cgit v1.2.3-55-g6feb From c0f39b0fb288206036d2c442588cf597390c3622 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 6 Oct 2010 01:45:24 +0200 Subject: dhcprelay: code shrink, and explain its workings a bit more function old new delta sendto_ip4 - 55 +55 dhcprelay_main 1059 942 -117 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 55/-117) Total: -62 bytes Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcprelay.c | 189 +++++++++++++++++++++++++++---------------- 1 file changed, 118 insertions(+), 71 deletions(-) diff --git a/networking/udhcp/dhcprelay.c b/networking/udhcp/dhcprelay.c index a2c7f359d..759a4ba03 100644 --- a/networking/udhcp/dhcprelay.c +++ b/networking/udhcp/dhcprelay.c @@ -11,9 +11,12 @@ */ #include "common.h" -#define SERVER_PORT 67 -#define SELECT_TIMEOUT 5 /* select timeout in sec. */ -#define MAX_LIFETIME 2*60 /* lifetime of an xid entry in sec. */ +#define SERVER_PORT 67 + +/* lifetime of an xid entry in sec. */ +#define MAX_LIFETIME 2*60 +/* select timeout in sec. */ +#define SELECT_TIMEOUT (MAX_LIFETIME / 8) /* This list holds information about clients. The xid_* functions manipulate this list. */ struct xid_item { @@ -67,11 +70,11 @@ static struct xid_item *xid_find(uint32_t xid) struct xid_item *item = dhcprelay_xid_list.next; while (item != NULL) { if (item->xid == xid) { - return item; + break; } item = item->next; } - return NULL; + return item; } static void xid_del(uint32_t xid) @@ -110,62 +113,72 @@ static int get_dhcp_packet_type(struct dhcp_packet *p) } /** - * get_client_devices - parses the devices list - * dev_list - comma separated list of devices + * make_iface_list - parses client/server interface names * returns array */ -static char **get_client_devices(char *dev_list, int *client_number) +static char **make_iface_list(char **client_and_server_ifaces, int *client_number) { - char *s, **client_dev; + char *s, **iface_list; int i, cn; - /* copy list */ - dev_list = xstrdup(dev_list); - - /* get number of items, replace ',' with NULs */ - s = dev_list; - cn = 1; + /* get number of items */ + cn = 2; /* 1 server iface + at least 1 client one */ + s = client_and_server_ifaces[0]; /* list of client ifaces */ while (*s) { - if (*s == ',') { - *s = '\0'; + if (*s == ',') cn++; - } s++; } *client_number = cn; /* create vector of pointers */ - client_dev = xzalloc(cn * sizeof(*client_dev)); - client_dev[0] = dev_list; + iface_list = xzalloc(cn * sizeof(iface_list[0])); + + iface_list[0] = client_and_server_ifaces[1]; /* server iface */ + i = 1; - while (i != cn) { - client_dev[i] = client_dev[i - 1] + strlen(client_dev[i - 1]) + 1; - i++; + s = xstrdup(client_and_server_ifaces[0]); /* list of client ifaces */ + goto store_client_iface_name; + + while (i < cn) { + if (*s++ == ',') { + s[-1] = '\0'; + store_client_iface_name: + iface_list[i++] = s; + } } - return client_dev; + + return iface_list; } /* Creates listen sockets (in fds) bound to client and server ifaces, * and returns numerically max fd. */ -static int init_sockets(char **client_ifaces, int num_clients, - char *server_iface, int *fds) +static int init_sockets(char **iface_list, int num_clients, int *fds) { int i, n; - /* talk to real server on bootps */ - fds[0] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, server_iface); - n = fds[0]; - - for (i = 1; i < num_clients; i++) { - /* listen for clients on bootps */ - fds[i] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, client_ifaces[i-1]); - if (fds[i] > n) + n = 0; + for (i = 0; i < num_clients; i++) { + fds[i] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, iface_list[i]); + if (n < fds[i]) n = fds[i]; } return n; } +static int sendto_ip4(int sock, const void *msg, int msg_len, struct sockaddr_in *to) +{ + int err; + + errno = 0; + err = sendto(sock, msg, msg_len, 0, (struct sockaddr*) to, sizeof(*to)); + err -= msg_len; + if (err) + bb_perror_msg("sendto"); + return err; +} + /** * pass_to_server() - forwards dhcp packets from client to server * p - packet to send @@ -174,7 +187,7 @@ static int init_sockets(char **client_ifaces, int num_clients, static void pass_to_server(struct dhcp_packet *p, int packet_len, int client, int *fds, struct sockaddr_in *client_addr, struct sockaddr_in *server_addr) { - int res, type; + int type; /* check packet_type */ type = get_dhcp_packet_type(p); @@ -188,13 +201,12 @@ static void pass_to_server(struct dhcp_packet *p, int packet_len, int client, in /* create new xid entry */ xid_add(p->xid, client_addr, client); - /* forward request to LAN (server) */ - errno = 0; - res = sendto(fds[0], p, packet_len, 0, (struct sockaddr*)server_addr, - sizeof(struct sockaddr_in)); - if (res != packet_len) { - bb_perror_msg("sendto"); - } + /* forward request to server */ + /* note that we send from fds[0] which is bound to SERVER_PORT (67). + * IOW: we send _from_ SERVER_PORT! Although this may look strange, + * RFC 1542 not only allows, but prescribes this for BOOTP relays. + */ + sendto_ip4(fds[0], p, packet_len, server_addr); } /** @@ -203,7 +215,7 @@ static void pass_to_server(struct dhcp_packet *p, int packet_len, int client, in */ static void pass_to_client(struct dhcp_packet *p, int packet_len, int *fds) { - int res, type; + int type; struct xid_item *item; /* check xid */ @@ -218,14 +230,12 @@ static void pass_to_client(struct dhcp_packet *p, int packet_len, int *fds) return; } +//TODO: also do it if (p->flags & htons(BROADCAST_FLAG)) is set! if (item->ip.sin_addr.s_addr == htonl(INADDR_ANY)) item->ip.sin_addr.s_addr = htonl(INADDR_BROADCAST); - errno = 0; - res = sendto(fds[item->client], p, packet_len, 0, (struct sockaddr*) &(item->ip), - sizeof(item->ip)); - if (res != packet_len) { - bb_perror_msg("sendto"); - return; + + if (sendto_ip4(fds[item->client], p, packet_len, &item->ip) != 0) { + return; /* send error occurred */ } /* remove xid entry */ @@ -235,36 +245,30 @@ static void pass_to_client(struct dhcp_packet *p, int packet_len, int *fds) int dhcprelay_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int dhcprelay_main(int argc, char **argv) { - struct dhcp_packet dhcp_msg; struct sockaddr_in server_addr; - struct sockaddr_in client_addr; - fd_set rfds; - char **client_ifaces; + char **iface_list; int *fds; int num_sockets, max_socket; uint32_t our_nip; server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); server_addr.sin_port = htons(SERVER_PORT); - /* dhcprelay client_iface1,client_iface2,... server_iface [server_IP] */ + /* dhcprelay CLIENT_IFACE1[,CLIENT_IFACE2...] SERVER_IFACE [SERVER_IP] */ if (argc == 4) { if (!inet_aton(argv[3], &server_addr.sin_addr)) bb_perror_msg_and_die("bad server IP"); - } else if (argc == 3) { - server_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); - } else { + } else if (argc != 3) { bb_show_usage(); } - /* Produce list of client ifaces */ - client_ifaces = get_client_devices(argv[1], &num_sockets); + iface_list = make_iface_list(argv + 1, &num_sockets); - num_sockets++; /* for server socket at fds[0] */ fds = xmalloc(num_sockets * sizeof(fds[0])); /* Create sockets and bind one to every iface */ - max_socket = init_sockets(client_ifaces, num_sockets, argv[2], fds); + max_socket = init_sockets(iface_list, num_sockets, fds); /* Get our IP on server_iface */ if (udhcp_read_interface(argv[2], NULL, &our_nip, NULL)) @@ -272,11 +276,10 @@ int dhcprelay_main(int argc, char **argv) /* Main loop */ while (1) { -//reinit stuff from time to time? go back to get_client_devices -//every N minutes? +// reinit stuff from time to time? go back to make_iface_list +// every N minutes? + fd_set rfds; struct timeval tv; - size_t packlen; - socklen_t addr_size; int i; FD_ZERO(&rfds); @@ -285,6 +288,9 @@ int dhcprelay_main(int argc, char **argv) tv.tv_sec = SELECT_TIMEOUT; tv.tv_usec = 0; if (select(max_socket + 1, &rfds, NULL, NULL, &tv) > 0) { + int packlen; + struct dhcp_packet dhcp_msg; + /* server */ if (FD_ISSET(fds[0], &rfds)) { packlen = udhcp_recv_kernel_packet(&dhcp_msg, fds[0]); @@ -292,24 +298,65 @@ int dhcprelay_main(int argc, char **argv) pass_to_client(&dhcp_msg, packlen, fds); } } + /* clients */ for (i = 1; i < num_sockets; i++) { + struct sockaddr_in client_addr; + socklen_t addr_size; + if (!FD_ISSET(fds[i], &rfds)) continue; - addr_size = sizeof(struct sockaddr_in); + + addr_size = sizeof(client_addr); packlen = recvfrom(fds[i], &dhcp_msg, sizeof(dhcp_msg), 0, (struct sockaddr *)(&client_addr), &addr_size); if (packlen <= 0) continue; /* Get our IP on corresponding client_iface */ -//why? what if server can't route such IP? - if (udhcp_read_interface(client_ifaces[i-1], NULL, &dhcp_msg.gateway_nip, NULL)) { - /* Fall back to our server_iface's IP */ -//this makes more sense! +// RFC 1542 +// 4.1 General BOOTP Processing for Relay Agents +// 4.1.1 BOOTREQUEST Messages +// If the relay agent does decide to relay the request, it MUST examine +// the 'giaddr' ("gateway" IP address) field. If this field is zero, +// the relay agent MUST fill this field with the IP address of the +// interface on which the request was received. If the interface has +// more than one IP address logically associated with it, the relay +// agent SHOULD choose one IP address associated with that interface and +// use it consistently for all BOOTP messages it relays. If the +// 'giaddr' field contains some non-zero value, the 'giaddr' field MUST +// NOT be modified. The relay agent MUST NOT, under any circumstances, +// fill the 'giaddr' field with a broadcast address as is suggested in +// [1] (Section 8, sixth paragraph). + +// but why? what if server can't route such IP? Client ifaces may be, say, NATed! + +// 4.1.2 BOOTREPLY Messages +// BOOTP relay agents relay BOOTREPLY messages only to BOOTP clients. +// It is the responsibility of BOOTP servers to send BOOTREPLY messages +// directly to the relay agent identified in the 'giaddr' field. +// (yeah right, unless it is impossible... see comment above) +// Therefore, a relay agent may assume that all BOOTREPLY messages it +// receives are intended for BOOTP clients on its directly-connected +// networks. +// +// When a relay agent receives a BOOTREPLY message, it should examine +// the BOOTP 'giaddr', 'yiaddr', 'chaddr', 'htype', and 'hlen' fields. +// These fields should provide adequate information for the relay agent +// to deliver the BOOTREPLY message to the client. +// +// The 'giaddr' field can be used to identify the logical interface from +// which the reply must be sent (i.e., the host or router interface +// connected to the same network as the BOOTP client). If the content +// of the 'giaddr' field does not match one of the relay agent's +// directly-connected logical interfaces, the BOOTREPLY messsage MUST be +// silently discarded. + if (udhcp_read_interface(iface_list[i], NULL, &dhcp_msg.gateway_nip, NULL)) { + /* Fall back to our IP on server iface */ +// this makes more sense! dhcp_msg.gateway_nip = our_nip; } -//maybe set dhcp_msg.flags |= BROADCAST_FLAG too? +// maybe dhcp_msg.hops++? drop packets with too many hops (RFC 1542 says 4 or 16)? pass_to_server(&dhcp_msg, packlen, i, fds, &client_addr, &server_addr); } } -- cgit v1.2.3-55-g6feb From 6b0ac8487a7a0332244db86246d3205fa76d7aae Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 7 Oct 2010 13:25:09 +0200 Subject: tweak usage texts Signed-off-by: Denys Vlasenko --- include/usage.src.h | 135 +++++++++++++++++++++++++++------------------------- 1 file changed, 69 insertions(+), 66 deletions(-) diff --git a/include/usage.src.h b/include/usage.src.h index 92a106e3b..38d6089b1 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -101,7 +101,7 @@ INSERT "\n -n Don't resolve names" \ "\n -i IF Network interface" \ "\n -D Read from given device" \ - "\n -A, -p AF Protocol family" \ + "\n -A,-p AF Protocol family" \ "\n -H HWTYPE Hardware address type" \ #define arping_trivial_usage \ @@ -220,7 +220,7 @@ INSERT "\n -F Don't store or verify checksum" \ #define unlzma_trivial_usage \ - "[OPTIONS] [FILE]..." + "[-cf] [FILE]..." #define unlzma_full_usage "\n\n" \ "Decompress FILE (or stdin)\n" \ "\nOptions:" \ @@ -228,7 +228,7 @@ INSERT "\n -f Force" \ #define lzma_trivial_usage \ - "-d [OPTIONS] [FILE]..." + "-d [-cf] [FILE]..." #define lzma_full_usage "\n\n" \ "Decompress FILE (or stdin)\n" \ "\nOptions:" \ @@ -242,7 +242,7 @@ INSERT "Decompress to stdout" #define unxz_trivial_usage \ - "[OPTIONS] [FILE]..." + "[-cf] [FILE]..." #define unxz_full_usage "\n\n" \ "Decompress FILE (or stdin)\n" \ "\nOptions:" \ @@ -250,7 +250,7 @@ INSERT "\n -f Force" \ #define xz_trivial_usage \ - "-d [OPTIONS] [FILE]..." + "-d [-cf] [FILE]..." #define xz_full_usage "\n\n" \ "Decompress FILE (or stdin)\n" \ "\nOptions:" \ @@ -534,7 +534,7 @@ INSERT "Print the config file used by busybox build" #define chrt_trivial_usage \ - "[OPTIONS] [PRIO] [PID | PROG ARGS]" + "[-prfom] [PRIO] [PID | PROG ARGS]" #define chrt_full_usage "\n\n" \ "Change scheduling priority and class for a process\n" \ "\nOptions:" \ @@ -916,7 +916,7 @@ INSERT "\n nameserver NORNAL_DNS_SERVER" \ #define dos2unix_trivial_usage \ - "[OPTIONS] [FILE]" + "[-ud] [FILE]" #define dos2unix_full_usage "\n\n" \ "Convert FILE in-place from DOS to Unix format.\n" \ "When no file is given, use stdin/stdout.\n" \ @@ -925,7 +925,7 @@ INSERT "\n -d unix2dos" \ #define unix2dos_trivial_usage \ - "[OPTIONS] [FILE]" + "[-ud] [FILE]" #define unix2dos_full_usage "\n\n" \ "Convert FILE in-place from Unix to DOS format.\n" \ "When no file is given, use stdin/stdout.\n" \ @@ -1406,8 +1406,7 @@ INSERT "Find processes which use FILEs or PORTs\n" \ "\nOptions:" \ "\n -m Find processes which use same fs as FILEs" \ - "\n -4 Search only IPv4 space" \ - "\n -6 Search only IPv6 space" \ + "\n -4,-6 Search only IPv4/IPv6 space" \ "\n -s Don't display PIDs" \ "\n -k Kill found processes" \ "\n -SIGNAL Signal to send (default: KILL)" \ @@ -1485,7 +1484,7 @@ INSERT "\n -H HOST Log HOST into the utmp file as the hostname" \ #define gunzip_trivial_usage \ - "[OPTIONS] [FILE]..." + "[-cft] [FILE]..." #define gunzip_full_usage "\n\n" \ "Decompress FILEs (or stdin)\n" \ "\nOptions:" \ @@ -1501,7 +1500,7 @@ INSERT "-rw-rw-r-- 1 andersen andersen 1761280 Apr 14 17:47 /tmp/BusyBox-0.43.tar\n" #define gzip_trivial_usage \ - "[OPTIONS] [FILE]..." + "[-cfd] [FILE]..." #define gzip_full_usage "\n\n" \ "Compress FILEs (or stdin)\n" \ "\nOptions:" \ @@ -1703,7 +1702,7 @@ INSERT "\n -i Inetd mode" \ "\n -f Don't daemonize" \ "\n -v[v] Verbose" \ - "\n -p [IP:]PORT Bind to ip:port (default *:80)" \ + "\n -p [IP:]PORT Bind to IP:PORT (default *:80)" \ IF_FEATURE_HTTPD_SETUID( \ "\n -u USER[:GRP] Set uid/gid after binding to port") \ IF_FEATURE_HTTPD_BASIC_AUTH( \ @@ -1740,13 +1739,13 @@ INSERT "Print information about USER or the current user\n" \ "\nOptions:" \ IF_SELINUX( \ - "\n -Z Print the security context" \ + "\n -Z Security context" \ ) \ - "\n -u Print user ID" \ - "\n -g Print group ID" \ - "\n -G Print supplementary group IDs" \ - "\n -n Print name instead of a number" \ - "\n -r Print real user ID instead of effective ID" \ + "\n -u User ID" \ + "\n -g Group ID" \ + "\n -G Supplementary group IDs" \ + "\n -n Print names instead of numbers" \ + "\n -r Print real ID instead of effective ID" \ #define id_example_usage \ "$ id\n" \ @@ -1778,10 +1777,10 @@ INSERT #define ifenslave_full_usage "\n\n" \ "Configure network interfaces for parallel routing\n" \ "\nOptions:" \ - "\n -c, --change-active Change active slave" \ - "\n -d, --detach Remove slave interface from bonding device" \ - "\n -f, --force Force, even if interface is not Ethernet" \ -/* "\n -r, --receive-slave Create a receive-only slave" */ + "\n -c,--change-active Change active slave" \ + "\n -d,--detach Remove slave interface from bonding device" \ + "\n -f,--force Force, even if interface is not Ethernet" \ +/* "\n -r,--receive-slave Create a receive-only slave" */ #define ifenslave_example_usage \ "To create a bond device, simply follow these three steps:\n" \ @@ -1826,7 +1825,7 @@ INSERT "\n -k Kill running daemon" \ #define ifup_trivial_usage \ - "[-ain"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] IFACE..." + "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..." #define ifup_full_usage "\n\n" \ "Options:" \ "\n -a De/configure all interfaces automatically" \ @@ -1840,7 +1839,7 @@ INSERT "\n -f Force de/configuration" \ #define ifdown_trivial_usage \ - "[-ain"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] ifaces..." + "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..." #define ifdown_full_usage "\n\n" \ "Options:" \ "\n -a De/configure all interfaces automatically" \ @@ -2327,7 +2326,7 @@ INSERT "root\n" #define logread_trivial_usage \ - "[OPTIONS]" + "[-f]" #define logread_full_usage "\n\n" \ "Show messages in syslogd's circular buffer\n" \ "\nOptions:" \ @@ -2544,7 +2543,7 @@ INSERT "\nOther options are silently ignored" \ #define man_trivial_usage \ - "[OPTIONS] [MANPAGE]..." + "[-aw] [MANPAGE]..." #define man_full_usage "\n\n" \ "Format and display manual page\n" \ "\nOptions:" \ @@ -2561,8 +2560,8 @@ INSERT "\n -V Verify file context on disk matches defaults" \ #define md5sum_trivial_usage \ - "[OPTIONS] [FILE]..." \ - IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: md5sum [OPTIONS] -c [FILE]") + "[FILE]..." \ + IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: md5sum -c [-sw] [FILE]") #define md5sum_full_usage "\n\n" \ "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " MD5 checksums" \ IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ @@ -2583,8 +2582,8 @@ INSERT "^D\n" #define sha1sum_trivial_usage \ - "[OPTIONS] [FILE]..." \ - IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha1sum [OPTIONS] -c [FILE]") + "[FILE]..." \ + IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha1sum -c [-sw] [FILE]") #define sha1sum_full_usage "\n\n" \ "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA1 checksums" \ IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ @@ -2595,8 +2594,8 @@ INSERT ) #define sha256sum_trivial_usage \ - "[OPTIONS] [FILE]..." \ - IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha256sum [OPTIONS] -c [FILE]") + "[FILE]..." \ + IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha256sum -c [-sw] [FILE]") #define sha256sum_full_usage "\n\n" \ "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA256 checksums" \ IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ @@ -2607,8 +2606,8 @@ INSERT ) #define sha512sum_trivial_usage \ - "[OPTIONS] [FILE]..." \ - IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha512sum [OPTIONS] -c [FILE]") + "[FILE]..." \ + IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha512sum -c [-sw] [FILE]") #define sha512sum_full_usage "\n\n" \ "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA512 checksums" \ IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ @@ -2675,7 +2674,7 @@ INSERT #define mkdir_full_usage "\n\n" \ "Create DIRECTORY\n" \ "\nOptions:" \ - "\n -m Mode" \ + "\n -m MODE Mode" \ "\n -p No error if exists; make parent directories as needed" \ IF_SELINUX( \ "\n -Z Set security context" \ @@ -2690,9 +2689,9 @@ INSERT "$ mkdir -p /tmp/foo/bar/baz\n" #define mkfifo_trivial_usage \ - "[OPTIONS] name" + "[-m MODE] " IF_SELINUX("[-Z] ") "NAME" #define mkfifo_full_usage "\n\n" \ - "Create named pipe (identical to 'mknod name p')\n" \ + "Create named pipe\n" \ "\nOptions:" \ "\n -m MODE Mode (default a=rw)" \ IF_SELINUX( \ @@ -2774,25 +2773,25 @@ INSERT "\n -n LBL Volume label" \ #define mknod_trivial_usage \ - "[OPTIONS] NAME TYPE MAJOR MINOR" + "[-m MODE] " IF_SELINUX("[-Z] ") "NAME TYPE MAJOR MINOR" #define mknod_full_usage "\n\n" \ "Create a special file (block, character, or pipe)\n" \ "\nOptions:" \ - "\n -m Create the special file using the specified mode (default a=rw)" \ - "\nTYPEs include:" \ - "\n b: Make a block device" \ - "\n c or u: Make a character device" \ - "\n p: Make a named pipe (MAJOR and MINOR are ignored)" \ + "\n -m MODE Creation mode (default a=rw)" \ IF_SELINUX( \ "\n -Z Set security context" \ - ) + ) \ + "\nTYPEs:" \ + "\n b Block device" \ + "\n c or u Character device" \ + "\n p Named pipe (MAJOR and MINOR are ignored)" \ #define mknod_example_usage \ "$ mknod /dev/fd0 b 2 0\n" \ "$ mknod -m 644 /tmp/pipe p\n" #define mkswap_trivial_usage \ - "[OPTIONS] BLOCKDEV [KBYTES]" + "[-L LBL] BLOCKDEV [KBYTES]" #define mkswap_full_usage "\n\n" \ "Prepare BLOCKDEV to be used as swap partition\n" \ "\nOptions:" \ @@ -2914,8 +2913,8 @@ INSERT "setpart tell unload unlock weof wset" \ #define mv_trivial_usage \ - "[OPTIONS] SOURCE DEST\n" \ - "or: mv [OPTIONS] SOURCE... DIRECTORY" + "[-fi] SOURCE DEST\n" \ + "or: mv [-fi] SOURCE... DIRECTORY" #define mv_full_usage "\n\n" \ "Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY\n" \ "\nOptions:" \ @@ -3050,7 +3049,7 @@ INSERT "Change USER's password. If no USER is specified,\n" \ "changes the password for the current user.\n" \ "\nOptions:" \ - "\n -a Algorithm to use for password (des, md5)" /* ", sha1)" */ \ + "\n -a ALG Algorithm to use for password (des, md5)" /* ", sha1)" */ \ "\n -d Delete password for the account" \ "\n -l Lock (disable) account" \ "\n -u Unlock (re-enable) account" \ @@ -3117,10 +3116,12 @@ INSERT "List PIDs of all processes with names that match NAMEs" \ USAGE_PIDOF \ IF_FEATURE_PIDOF_SINGLE( \ - "\n -s Show only one PID") \ + "\n -s Show only one PID" \ + ) \ IF_FEATURE_PIDOF_OMIT( \ "\n -o PID Omit given pid" \ - "\n Use %PPID to omit pid of pidof's parent") \ + "\n Use %PPID to omit pid of pidof's parent" \ + ) \ #define pidof_example_usage \ "$ pidof init\n" \ @@ -3145,7 +3146,7 @@ INSERT #define ping_full_usage "\n\n" \ "Send ICMP ECHO_REQUEST packets to network hosts\n" \ "\nOptions:" \ - "\n -4, -6 Force IP or IPv6 name resolution" \ + "\n -4,-6 Force IP or IPv6 name resolution" \ "\n -c CNT Send only CNT pings" \ "\n -s SIZE Send SIZE data bytes in packets (default:56)" \ "\n -I IFACE/IP Use interface or IP address as source" \ @@ -3437,7 +3438,7 @@ INSERT "\n wimax, wwan, gps, fm" \ #define rm_trivial_usage \ - "[OPTIONS] FILE..." + "[-irf] FILE..." #define rm_full_usage "\n\n" \ "Remove (unlink) FILEs\n" \ "\nOptions:" \ @@ -3465,12 +3466,12 @@ INSERT "# rmdir /tmp/foo\n" #define rmmod_trivial_usage \ - "[OPTIONS] [MODULE]..." + "[-wfa] [MODULE]..." #define rmmod_full_usage "\n\n" \ - "Unload the specified kernel modules from the kernel\n" \ + "Unload kernel modules\n" \ "\nOptions:" \ "\n -w Wait until the module is no longer used" \ - "\n -f Force unloading" \ + "\n -f Force unload" \ "\n -a Remove all unused modules (recursively)" \ #define rmmod_example_usage \ @@ -3855,9 +3856,9 @@ INSERT "[OPTIONS] [INPUT [PREFIX]]" #define split_full_usage "\n\n" \ "Options:" \ - "\n -b n[k|m] Split by bytes" \ - "\n -l n Split by lines" \ - "\n -a n Use n letters as suffix" \ + "\n -b N[k|m] Split by N (kilo|mega)bytes" \ + "\n -l N Split by N lines" \ + "\n -a N Use N letters as suffix" \ #define split_example_usage \ "$ split TODO foo\n" \ @@ -4086,7 +4087,7 @@ INSERT "Write all buffered blocks to disk" #define fsync_trivial_usage \ - "[OPTIONS] FILE..." + "[-d] FILE..." #define fsync_full_usage "\n\n" \ "Write files' buffered blocks to disk\n" \ "\nOptions:" \ @@ -4162,7 +4163,7 @@ INSERT "pid 1's current affinity mask: 3\n" #define tee_trivial_usage \ - "[OPTIONS] [FILE]..." + "[-ai] [FILE]..." #define tee_full_usage "\n\n" \ "Copy stdin to each FILE, and also to stdout\n" \ "\nOptions:" \ @@ -4323,7 +4324,7 @@ INSERT "\n -u Access files as USER" \ #define time_trivial_usage \ - "[OPTIONS] PROG ARGS" + "[-v] PROG ARGS" #define time_full_usage "\n\n" \ "Run PROG, display resource usage when it exits\n" \ "\nOptions:" \ @@ -4379,7 +4380,7 @@ INSERT "Trace the route to HOST\n" \ "\nOptions:" \ IF_TRACEROUTE6( \ - "\n -4, -6 Force IP or IPv6 name resolution" \ + "\n -4,-6 Force IP or IPv6 name resolution" \ ) \ "\n -F Set the don't fragment bit" \ "\n -I Use ICMP ECHO instead of UDP datagrams" \ @@ -4702,13 +4703,15 @@ INSERT "Edit FILE\n" \ "\nOptions:" \ IF_FEATURE_VI_COLON( \ - "\n -c Initial command to run ($EXINIT also available)") \ + "\n -c Initial command to run ($EXINIT also available)" \ + ) \ IF_FEATURE_VI_READONLY( \ - "\n -R Read-only") \ + "\n -R Read-only" \ + ) \ "\n -H Short help regarding available features" \ #define vlock_trivial_usage \ - "[OPTIONS]" + "[-a]" #define vlock_full_usage "\n\n" \ "Lock a virtual terminal. A password is required to unlock.\n" \ "\nOptions:" \ -- cgit v1.2.3-55-g6feb From c1e3027f11bd3dc12df508cde10457b9215424e4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 8 Oct 2010 15:04:23 +0200 Subject: fix help text punctuation Signed-off-by: Denys Vlasenko --- include/usage.src.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/usage.src.h b/include/usage.src.h index 38d6089b1..f058a9d49 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -4268,7 +4268,7 @@ INSERT "\n -u USER[:GRP] Change to user/group after bind" \ "\n -c N Handle up to N connections simultaneously" \ "\n -b N Allow a backlog of approximately N TCP SYNs" \ - "\n -C N[:MSG] Allow only up to N connections from the same IP" \ + "\n -C N[:MSG] Allow only up to N connections from the same IP." \ "\n New connections from this IP address are closed" \ "\n immediately. MSG is written to the peer before close" \ "\n -h Look up peer's hostname" \ -- cgit v1.2.3-55-g6feb From 3b2acb759cac73fe2af096af8641c01197fa4214 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 9 Oct 2010 21:10:32 +0200 Subject: tweak help text Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 2 +- include/usage.src.h | 2 +- modutils/insmod.c | 2 +- networking/nc_bloaty.c | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 787f4124d..6b6457673 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -305,7 +305,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //usage:#define bunzip2_trivial_usage -//usage: "[OPTIONS] [FILE]..." +//usage: "[-cf] [FILE]..." //usage:#define bunzip2_full_usage "\n\n" //usage: "Decompress FILEs (or stdin)\n" //usage: "\nOptions:" diff --git a/include/usage.src.h b/include/usage.src.h index f058a9d49..555250366 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -2781,7 +2781,7 @@ INSERT IF_SELINUX( \ "\n -Z Set security context" \ ) \ - "\nTYPEs:" \ + "\nTYPE:" \ "\n b Block device" \ "\n c or u Character device" \ "\n p Named pipe (MAJOR and MINOR are ignored)" \ diff --git a/modutils/insmod.c b/modutils/insmod.c index 17fc18c09..4fe388bdc 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c @@ -16,7 +16,7 @@ //usage:#define insmod_trivial_usage //usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ") //usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") -//usage: "[symbol=value]..." +//usage: "[SYMBOL=VALUE]..." //usage:#define insmod_full_usage "\n\n" //usage: "Load the specified kernel modules into the kernel" //usage: IF_FEATURE_2_4_MODULES( "\n" diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 6b5b176c9..8594a67a6 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c @@ -57,7 +57,8 @@ //usage:#define nc_trivial_usage //usage: "[OPTIONS] HOST PORT - connect" //usage: IF_NC_SERVER("\n" -//usage: "nc [OPTIONS] -l -p PORT [HOST] [PORT] - listen") +//usage: "nc [OPTIONS] -l -p PORT [HOST] [PORT] - listen" +//usage: ) //usage:#define nc_full_usage "\n\n" //usage: "Options:" //usage: "\n -e PROG Run PROG after connect (must be last)" -- cgit v1.2.3-55-g6feb From b1993380ba4a89062a08b2b6c579158aa667759e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Oct 2010 12:53:19 +0200 Subject: remove findutils/.gitignore, top-level one covers it Signed-off-by: Denys Vlasenko --- findutils/.gitignore | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 findutils/.gitignore diff --git a/findutils/.gitignore b/findutils/.gitignore deleted file mode 100644 index 7a30caf5c..000000000 --- a/findutils/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Config.in and Kbuild are auto-generated -Config.in -Kbuild -- cgit v1.2.3-55-g6feb From d4d289acf5eb59ebae414f9aae8a74de30dce36a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 12 Oct 2010 04:18:05 +0200 Subject: tweaks to build system, mainly making menuconfig text and order clearer Signed-off-by: Denys Vlasenko --- Config.in | 61 ++++++++++++++++++++++++++++----------------------- include/applets.src.h | 5 ----- include/busybox.h | 7 +++++- libbb/appletlib.c | 8 ++++--- miscutils/Config.src | 1 - networking/Config.src | 2 +- 6 files changed, 46 insertions(+), 38 deletions(-) diff --git a/Config.in b/Config.in index 828b30471..d9c823199 100644 --- a/Config.in +++ b/Config.in @@ -123,6 +123,14 @@ config FEATURE_INSTALLER busybox at runtime to create hard links or symlinks for all the applets that are compiled into busybox. +config INSTALL_NO_USR + bool "Don't use /usr" + default n + depends on FEATURE_INSTALLER + help + Disable use of /usr. busybox --install will install applets + only to /bin and /sbin, never to /usr/bin or /usr/sbin. + config LOCALE_SUPPORT bool "Enable locale support (system needs locale for this to work)" default n @@ -275,15 +283,6 @@ config FEATURE_CLEAN_UP Don't enable this unless you have a really good reason to clean things up manually. -config FEATURE_UTMP - bool "Support utmp file" - default y - help - The file /var/run/utmp is used to track who is currently logged in. - With this option on, certain applets (getty, login, telnetd etc) - will create and delete entries there. - "who" applet requires this option. - config FEATURE_WTMP bool "Support wtmp file" default y @@ -295,6 +294,15 @@ config FEATURE_WTMP will append new entries there. "last" applet requires this option. +config FEATURE_UTMP + bool "Support utmp file" + default y + help + The file /var/run/utmp is used to track who is currently logged in. + With this option on, certain applets (getty, login, telnetd etc) + will create and delete entries there. + "who" applet requires this option. + config FEATURE_PIDFILE bool "Support writing pidfiles" default y @@ -307,14 +315,19 @@ config FEATURE_SUID default y help With this option you can install the busybox binary belonging - to root with the suid bit set, and it will automatically drop - priviledges for applets that don't need root access. + to root with the suid bit set, enabling some applets to perform + root-level operations even when run by ordinary users + (for example, mounting of user mounts in fstab needs this). + + Busybox will automatically drop priviledges for applets + that don't need root access. If you are really paranoid and don't want to do this, build two busybox binaries with different applets in them (and the appropriate symlinks pointing to each binary), and only set the suid bit on the - one that needs it. The applets currently marked to need the suid bit - are: + one that needs it. + + The applets currently marked to need the suid bit are: crontab, dnsd, findfs, ipcrm, ipcs, login, passwd, ping, su, traceroute, vlock. @@ -651,20 +664,13 @@ endchoice endmenu -menu 'Installation Options' - -config INSTALL_NO_USR - bool "Don't use /usr" - default n - help - Disable use of /usr. Don't activate this option if you don't know - that you really want this behaviour. +menu 'Installation Options ("make install" behavior)' choice - prompt "Applets links" + prompt "What kind of applet links to install" default INSTALL_APPLET_SYMLINKS help - Choose how you install applets links. + Choose what kind of links to applets are created by "make install". config INSTALL_APPLET_SYMLINKS bool "as soft-links" @@ -688,8 +694,9 @@ config INSTALL_APPLET_DONT bool "not installed" depends on FEATURE_INSTALLER || FEATURE_SH_STANDALONE || FEATURE_PREFER_APPLETS help - Do not install applet links. Useful when using the -install feature - or a standalone shell for rescue purposes. + Do not install applet links. Useful when you plan to use + busybox --install for installing links, or plan to use + a standalone shell and thus don't need applet links. endchoice @@ -713,8 +720,8 @@ config INSTALL_SH_APPLET_HARDLINK config INSTALL_SH_APPLET_SCRIPT_WRAPPER bool "as script wrapper" help - Install /bin/sh applet as script wrapper that call the busybox - binary. + Install /bin/sh applet as script wrapper that calls + the busybox binary. endchoice diff --git a/include/applets.src.h b/include/applets.src.h index d2b1d198f..6a14a6588 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -56,11 +56,6 @@ s - suid type: # define APPLET_NOFORK(name,main,l,s,name2) { #name, #main, l, s, 1, 1 }, #endif -#if ENABLE_INSTALL_NO_USR -# define _BB_DIR_USR_BIN _BB_DIR_BIN -# define _BB_DIR_USR_SBIN _BB_DIR_SBIN -#endif - INSERT IF_TEST(APPLET_NOFORK([, test, _BB_DIR_USR_BIN, _BB_SUID_DROP, test)) diff --git a/include/busybox.h b/include/busybox.h index 76415dd72..757317fc7 100644 --- a/include/busybox.h +++ b/include/busybox.h @@ -16,8 +16,13 @@ typedef enum bb_install_loc_t { _BB_DIR_ROOT = 0, _BB_DIR_BIN, _BB_DIR_SBIN, +#if ENABLE_INSTALL_NO_USR + _BB_DIR_USR_BIN = _BB_DIR_BIN, + _BB_DIR_USR_SBIN = _BB_DIR_SBIN, +#else _BB_DIR_USR_BIN, - _BB_DIR_USR_SBIN + _BB_DIR_USR_SBIN, +#endif } bb_install_loc_t; typedef enum bb_suid_t { diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 7326f4fa5..b32ff8808 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -592,9 +592,11 @@ static const char usr_sbin[] ALIGN1 = "/usr/sbin/"; static const char *const install_dir[] = { &usr_bin [8], /* "/" */ &usr_bin [4], /* "/bin/" */ - &usr_sbin[4], /* "/sbin/" */ - usr_bin, - usr_sbin + &usr_sbin[4] /* "/sbin/" */ +# if !ENABLE_INSTALL_NO_USR + ,usr_bin + ,usr_sbin +# endif }; diff --git a/miscutils/Config.src b/miscutils/Config.src index 151f61bcc..4912daf88 100644 --- a/miscutils/Config.src +++ b/miscutils/Config.src @@ -136,7 +136,6 @@ config CHRT config CROND bool "crond" default y - select FEATURE_SUID select FEATURE_SYSLOG help Crond is a background daemon that parses individual crontab diff --git a/networking/Config.src b/networking/Config.src index 9fc122bf3..6dd7df754 100644 --- a/networking/Config.src +++ b/networking/Config.src @@ -804,7 +804,7 @@ config TELNETD mount -t devpts devpts /dev/pts - You need to be sure that Busybox has LOGIN and + You need to be sure that busybox has LOGIN and FEATURE_SUID enabled. And finally, you should make certain that Busybox has been installed setuid root: -- cgit v1.2.3-55-g6feb From b1db09be5a19f814ed5dc7e0ab095c3355926da6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 12 Oct 2010 13:47:15 +0200 Subject: init/*: move applet/kbuild/config/help bits into applet source files Signed-off-by: Denys Vlasenko --- include/applets.src.h | 7 -- include/usage.src.h | 169 ------------------------------------ init/Config.src | 127 --------------------------- init/Kbuild.src | 4 - init/bootchartd.c | 4 + init/halt.c | 62 ++++++++++++++ init/init.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++ init/mesg.c | 18 ++++ 8 files changed, 315 insertions(+), 307 deletions(-) diff --git a/include/applets.src.h b/include/applets.src.h index 6a14a6588..545d3c5c2 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -72,7 +72,6 @@ IF_BASENAME(APPLET_NOFORK(basename, basename, _BB_DIR_USR_BIN, _BB_SUID_DROP, ba IF_BBCONFIG(APPLET(bbconfig, _BB_DIR_BIN, _BB_SUID_DROP)) IF_BEEP(APPLET(beep, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_BLKID(APPLET(blkid, _BB_DIR_SBIN, _BB_SUID_DROP)) -IF_BOOTCHARTD(APPLET(bootchartd, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_BRCTL(APPLET(brctl, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_BZIP2(APPLET(bzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_CAL(APPLET(cal, _BB_DIR_USR_BIN, _BB_SUID_DROP)) @@ -165,7 +164,6 @@ IF_GETSEBOOL(APPLET(getsebool, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_GETTY(APPLET(getty, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_GUNZIP(APPLET(gunzip, _BB_DIR_BIN, _BB_SUID_DROP)) IF_GZIP(APPLET(gzip, _BB_DIR_BIN, _BB_SUID_DROP)) -IF_HALT(APPLET(halt, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_HD(APPLET_NOEXEC(hd, hexdump, _BB_DIR_USR_BIN, _BB_SUID_DROP, hd)) IF_HDPARM(APPLET(hdparm, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_HEAD(APPLET_NOEXEC(head, head, _BB_DIR_USR_BIN, _BB_SUID_DROP, head)) @@ -181,7 +179,6 @@ IF_IFENSLAVE(APPLET(ifenslave, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_IFPLUGD(APPLET(ifplugd, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_IFUPDOWN(APPLET_ODDNAME(ifup, ifupdown, _BB_DIR_SBIN, _BB_SUID_DROP, ifup)) IF_INETD(APPLET(inetd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) -IF_INIT(APPLET(init, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_INOTIFYD(APPLET(inotifyd, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_INSMOD(APPLET(insmod, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) @@ -212,7 +209,6 @@ IF_LENGTH(APPLET_NOFORK(length, length, _BB_DIR_USR_BIN, _BB_SUID_DROP, length)) IF_LESS(APPLET(less, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_SETARCH(APPLET_ODDNAME(linux32, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux32)) IF_SETARCH(APPLET_ODDNAME(linux64, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux64)) -IF_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, _BB_DIR_ROOT, _BB_SUID_DROP, linuxrc)) IF_LN(APPLET_NOEXEC(ln, ln, _BB_DIR_BIN, _BB_SUID_DROP, ln)) IF_LOAD_POLICY(APPLET(load_policy, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_LOADFONT(APPLET(loadfont, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) @@ -241,7 +237,6 @@ IF_MAN(APPLET(man, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_MATCHPATHCON(APPLET(matchpathcon, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_MD5SUM(APPLET_NOEXEC(md5sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, md5sum)) IF_MDEV(APPLET(mdev, _BB_DIR_SBIN, _BB_SUID_DROP)) -IF_MESG(APPLET(mesg, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_MICROCOM(APPLET(microcom, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_MKDIR(APPLET_NOFORK(mkdir, mkdir, _BB_DIR_BIN, _BB_SUID_DROP, mkdir)) IF_MKFS_VFAT(APPLET_ODDNAME(mkdosfs, mkfs_vfat, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_vfat)) @@ -284,7 +279,6 @@ IF_PIPE_PROGRESS(APPLET(pipe_progress, _BB_DIR_BIN, _BB_SUID_DROP)) IF_PIVOT_ROOT(APPLET(pivot_root, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_PKILL(APPLET_ODDNAME(pkill, pgrep, _BB_DIR_USR_BIN, _BB_SUID_DROP, pkill)) IF_POPMAILDIR(APPLET(popmaildir, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) -IF_HALT(APPLET_ODDNAME(poweroff, halt, _BB_DIR_SBIN, _BB_SUID_DROP, poweroff)) IF_PRINTENV(APPLET_NOFORK(printenv, printenv, _BB_DIR_BIN, _BB_SUID_DROP, printenv)) IF_PRINTF(APPLET_NOFORK(printf, printf, _BB_DIR_USR_BIN, _BB_SUID_DROP, printf)) IF_PS(APPLET(ps, _BB_DIR_BIN, _BB_SUID_DROP)) @@ -297,7 +291,6 @@ IF_READAHEAD(APPLET(readahead, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_READLINK(APPLET(readlink, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_READPROFILE(APPLET(readprofile, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_REALPATH(APPLET(realpath, _BB_DIR_USR_BIN, _BB_SUID_DROP)) -IF_HALT(APPLET_ODDNAME(reboot, halt, _BB_DIR_SBIN, _BB_SUID_DROP, reboot)) IF_REFORMIME(APPLET(reformime, _BB_DIR_BIN, _BB_SUID_DROP)) IF_RENICE(APPLET(renice, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_RESET(APPLET(reset, _BB_DIR_USR_BIN, _BB_SUID_DROP)) diff --git a/include/usage.src.h b/include/usage.src.h index 555250366..084427cc0 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -1515,36 +1515,6 @@ INSERT "$ ls -la /tmp/busybox*\n" \ "-rw-rw-r-- 1 andersen andersen 554058 Apr 14 17:49 /tmp/busybox.tar.gz\n" -#define halt_trivial_usage \ - "[-d DELAY] [-n] [-f]" IF_FEATURE_WTMP(" [-w]") -#define halt_full_usage "\n\n" \ - "Halt the system\n" \ - "\nOptions:" \ - "\n -d SEC Delay interval" \ - "\n -n Do not sync" \ - "\n -f Force (don't go through init)" \ - IF_FEATURE_WTMP( \ - "\n -w Only write a wtmp record" \ - ) - -#define poweroff_trivial_usage \ - "[-d DELAY] [-n] [-f]" -#define poweroff_full_usage "\n\n" \ - "Halt and shut off power\n" \ - "\nOptions:" \ - "\n -d SEC Delay interval" \ - "\n -n Do not sync" \ - "\n -f Force (don't go through init)" \ - -#define reboot_trivial_usage \ - "[-d DELAY] [-n] [-f]" -#define reboot_full_usage "\n\n" \ - "Reboot the system\n" \ - "\nOptions:" \ - "\n -d SEC Delay interval" \ - "\n -n Do not sync" \ - "\n -f Force (don't go through init)" \ - #define hdparm_trivial_usage \ "[OPTIONS] [DEVICE]" #define hdparm_full_usage "\n\n" \ @@ -1863,138 +1833,6 @@ INSERT "\n -R N Pause services after N connects/min" \ "\n (default: 0 - disabled)" \ -#define init_trivial_usage \ - "" -#define init_full_usage "\n\n" \ - "Init is the parent of all processes" - -#define init_notes_usage \ -"This version of init is designed to be run only by the kernel.\n" \ -"\n" \ -"BusyBox init doesn't support multiple runlevels. The runlevels field of\n" \ -"the /etc/inittab file is completely ignored by BusyBox init. If you want\n" \ -"runlevels, use sysvinit.\n" \ -"\n" \ -"BusyBox init works just fine without an inittab. If no inittab is found,\n" \ -"it has the following default behavior:\n" \ -"\n" \ -" ::sysinit:/etc/init.d/rcS\n" \ -" ::askfirst:/bin/sh\n" \ -" ::ctrlaltdel:/sbin/reboot\n" \ -" ::shutdown:/sbin/swapoff -a\n" \ -" ::shutdown:/bin/umount -a -r\n" \ -" ::restart:/sbin/init\n" \ -"\n" \ -"if it detects that /dev/console is _not_ a serial console, it will also run:\n" \ -"\n" \ -" tty2::askfirst:/bin/sh\n" \ -" tty3::askfirst:/bin/sh\n" \ -" tty4::askfirst:/bin/sh\n" \ -"\n" \ -"If you choose to use an /etc/inittab file, the inittab entry format is as follows:\n" \ -"\n" \ -" :::\n" \ -"\n" \ -" :\n" \ -"\n" \ -" WARNING: This field has a non-traditional meaning for BusyBox init!\n" \ -" The id field is used by BusyBox init to specify the controlling tty for\n" \ -" the specified process to run on. The contents of this field are\n" \ -" appended to \"/dev/\" and used as-is. There is no need for this field to\n" \ -" be unique, although if it isn't you may have strange results. If this\n" \ -" field is left blank, the controlling tty is set to the console. Also\n" \ -" note that if BusyBox detects that a serial console is in use, then only\n" \ -" entries whose controlling tty is either the serial console or /dev/null\n" \ -" will be run. BusyBox init does nothing with utmp. We don't need no\n" \ -" stinkin' utmp.\n" \ -"\n" \ -" :\n" \ -"\n" \ -" The runlevels field is completely ignored.\n" \ -"\n" \ -" :\n" \ -"\n" \ -" Valid actions include: sysinit, respawn, askfirst, wait,\n" \ -" once, restart, ctrlaltdel, and shutdown.\n" \ -"\n" \ -" The available actions can be classified into two groups: actions\n" \ -" that are run only once, and actions that are re-run when the specified\n" \ -" process exits.\n" \ -"\n" \ -" Run only-once actions:\n" \ -"\n" \ -" 'sysinit' is the first item run on boot. init waits until all\n" \ -" sysinit actions are completed before continuing. Following the\n" \ -" completion of all sysinit actions, all 'wait' actions are run.\n" \ -" 'wait' actions, like 'sysinit' actions, cause init to wait until\n" \ -" the specified task completes. 'once' actions are asynchronous,\n" \ -" therefore, init does not wait for them to complete. 'restart' is\n" \ -" the action taken to restart the init process. By default this should\n" \ -" simply run /sbin/init, but can be a script which runs pivot_root or it\n" \ -" can do all sorts of other interesting things. The 'ctrlaltdel' init\n" \ -" actions are run when the system detects that someone on the system\n" \ -" console has pressed the CTRL-ALT-DEL key combination. Typically one\n" \ -" wants to run 'reboot' at this point to cause the system to reboot.\n" \ -" Finally the 'shutdown' action specifies the actions to taken when\n" \ -" init is told to reboot. Unmounting filesystems and disabling swap\n" \ -" is a very good here.\n" \ -"\n" \ -" Run repeatedly actions:\n" \ -"\n" \ -" 'respawn' actions are run after the 'once' actions. When a process\n" \ -" started with a 'respawn' action exits, init automatically restarts\n" \ -" it. Unlike sysvinit, BusyBox init does not stop processes from\n" \ -" respawning out of control. The 'askfirst' actions acts just like\n" \ -" respawn, except that before running the specified process it\n" \ -" displays the line \"Please press Enter to activate this console.\"\n" \ -" and then waits for the user to press enter before starting the\n" \ -" specified process.\n" \ -"\n" \ -" Unrecognized actions (like initdefault) will cause init to emit an\n" \ -" error message, and then go along with its business. All actions are\n" \ -" run in the order they appear in /etc/inittab.\n" \ -"\n" \ -" :\n" \ -"\n" \ -" Specifies the process to be executed and its command line.\n" \ -"\n" \ -"Example /etc/inittab file:\n" \ -"\n" \ -" # This is run first except when booting in single-user mode\n" \ -" #\n" \ -" ::sysinit:/etc/init.d/rcS\n" \ -" \n" \ -" # /bin/sh invocations on selected ttys\n" \ -" #\n" \ -" # Start an \"askfirst\" shell on the console (whatever that may be)\n" \ -" ::askfirst:-/bin/sh\n" \ -" # Start an \"askfirst\" shell on /dev/tty2-4\n" \ -" tty2::askfirst:-/bin/sh\n" \ -" tty3::askfirst:-/bin/sh\n" \ -" tty4::askfirst:-/bin/sh\n" \ -" \n" \ -" # /sbin/getty invocations for selected ttys\n" \ -" #\n" \ -" tty4::respawn:/sbin/getty 38400 tty4\n" \ -" tty5::respawn:/sbin/getty 38400 tty5\n" \ -" \n" \ -" \n" \ -" # Example of how to put a getty on a serial line (for a terminal)\n" \ -" #\n" \ -" #::respawn:/sbin/getty -L ttyS0 9600 vt100\n" \ -" #::respawn:/sbin/getty -L ttyS1 9600 vt100\n" \ -" #\n" \ -" # Example how to put a getty on a modem line\n" \ -" #::respawn:/sbin/getty 57600 ttyS2\n" \ -" \n" \ -" # Stuff to do when restarting the init process\n" \ -" ::restart:/sbin/init\n" \ -" \n" \ -" # Stuff to do before rebooting\n" \ -" ::ctrlaltdel:/sbin/reboot\n" \ -" ::shutdown:/bin/umount -a -r\n" \ -" ::shutdown:/sbin/swapoff -a\n" - #define inotifyd_trivial_usage \ "PROG FILE1[:MASK]..." #define inotifyd_full_usage "\n\n" \ @@ -2651,13 +2489,6 @@ INSERT "the last line match .* to override this.)\n\n" \ ) -#define mesg_trivial_usage \ - "[y|n]" -#define mesg_full_usage "\n\n" \ - "Control write access to your terminal\n" \ - " y Allow write access to your terminal\n" \ - " n Disallow write access to your terminal" - #define microcom_trivial_usage \ "[-d DELAY] [-t TIMEOUT] [-s SPEED] [-X] TTY" #define microcom_full_usage "\n\n" \ diff --git a/init/Config.src b/init/Config.src index 2cac3573e..5767c93f0 100644 --- a/init/Config.src +++ b/init/Config.src @@ -7,131 +7,4 @@ menu "Init Utilities" INSERT -config INIT - bool "init" - default y - select FEATURE_SYSLOG - help - init is the first program run when the system boots. - -config FEATURE_USE_INITTAB - bool "Support reading an inittab file" - default y - depends on INIT - help - Allow init to read an inittab file when the system boot. - -config FEATURE_KILL_REMOVED - bool "Support killing processes that have been removed from inittab" - default n - depends on FEATURE_USE_INITTAB - help - When respawn entries are removed from inittab and a SIGHUP is - sent to init, this option will make init kill the processes - that have been removed. - -config FEATURE_KILL_DELAY - int "How long to wait between TERM and KILL (0 - send TERM only)" if FEATURE_KILL_REMOVED - range 0 1024 - default 0 - depends on FEATURE_KILL_REMOVED - help - With nonzero setting, init sends TERM, forks, child waits N - seconds, sends KILL and exits. Setting it too high is unwise - (child will hang around for too long and could actually kill - the wrong process!) - -config FEATURE_INIT_SCTTY - bool "Run commands with leading dash with controlling tty" - default y - depends on INIT - help - If this option is enabled, init will try to give a controlling - tty to any command which has leading hyphen (often it's "-/bin/sh"). - More precisely, init will do "ioctl(STDIN_FILENO, TIOCSCTTY, 0)". - If device attached to STDIN_FILENO can be a ctty but is not yet - a ctty for other session, it will become this process' ctty. - This is not the traditional init behavour, but is often what you want - in an embedded system where the console is only accessed during - development or for maintenance. - NB: using cttyhack applet may work better. - -config FEATURE_INIT_SYSLOG - bool "Enable init to write to syslog" - default y - depends on INIT - -config FEATURE_EXTRA_QUIET - bool "Be _extra_ quiet on boot" - default y - depends on INIT - help - Prevent init from logging some messages to the console during boot. - -config FEATURE_INIT_COREDUMPS - bool "Support dumping core for child processes (debugging only)" - default y - depends on INIT - help - If this option is enabled and the file /.init_enable_core - exists, then init will call setrlimit() to allow unlimited - core file sizes. If this option is disabled, processes - will not generate any core files. - -config FEATURE_INITRD - bool "Support running init from within an initrd (not initramfs)" - default y - depends on INIT - help - Legacy support for running init under the old-style initrd. Allows - the name linuxrc to act as init, and it doesn't assume init is PID 1. - - This does not apply to initramfs, which runs /init as PID 1 and - requires no special support. - -config INIT_TERMINAL_TYPE - string "Initial terminal type" - default "linux" - depends on INIT - help - This is the initial value set by init for the TERM environment - variable. This variable is used by programs which make use of - extended terminal capabilities. - - Note that on Linux, init attempts to detect serial terminal and - sets TERM to "vt102" if one is found. - -config HALT - bool "poweroff, halt, and reboot" - default y - help - Stop all processes and either halt, reboot, or power off the system. - -config FEATURE_CALL_TELINIT - bool "Call telinit on shutdown and reboot" - default y - depends on HALT && !INIT - help - Call an external program (normally telinit) to facilitate - a switch to a proper runlevel. - - This option is only available if you selected halt and friends, - but did not select init. - -config TELINIT_PATH - string "Path to telinit executable" - default "/sbin/telinit" - depends on FEATURE_CALL_TELINIT - help - When busybox halt and friends have to call external telinit - to facilitate proper shutdown, this path is to be used when - locating telinit executable. - -config MESG - bool "mesg" - default y - help - Mesg controls access to your terminal by others. It is typically - used to allow or disallow other users to write to your terminal - endmenu diff --git a/init/Kbuild.src b/init/Kbuild.src index 32dd5a045..6b4fb7470 100644 --- a/init/Kbuild.src +++ b/init/Kbuild.src @@ -7,7 +7,3 @@ lib-y:= INSERT -lib-$(CONFIG_HALT) += halt.o -lib-$(CONFIG_INIT) += init.o -lib-$(CONFIG_MESG) += mesg.o -lib-$(CONFIG_BOOTCHARTD) += bootchartd.o diff --git a/init/bootchartd.c b/init/bootchartd.c index f14d5c0fd..5a1b3e8e8 100644 --- a/init/bootchartd.c +++ b/init/bootchartd.c @@ -3,6 +3,10 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//applet:IF_BOOTCHARTD(APPLET(bootchartd, _BB_DIR_SBIN, _BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_BOOTCHARTD) += bootchartd.o + //config:config BOOTCHARTD //config: bool "bootchartd" //config: default y diff --git a/init/halt.c b/init/halt.c index 903953e80..47f1ef7b2 100644 --- a/init/halt.c +++ b/init/halt.c @@ -7,6 +7,68 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ +//applet:IF_HALT(APPLET(halt, _BB_DIR_SBIN, _BB_SUID_DROP)) +//applet:IF_HALT(APPLET_ODDNAME(poweroff, halt, _BB_DIR_SBIN, _BB_SUID_DROP, poweroff)) +//applet:IF_HALT(APPLET_ODDNAME(reboot, halt, _BB_DIR_SBIN, _BB_SUID_DROP, reboot)) + +//kbuild:lib-$(CONFIG_HALT) += halt.o + +//config:config HALT +//config: bool "poweroff, halt, and reboot" +//config: default y +//config: help +//config: Stop all processes and either halt, reboot, or power off the system. +//config: +//config:config FEATURE_CALL_TELINIT +//config: bool "Call telinit on shutdown and reboot" +//config: default y +//config: depends on HALT && !INIT +//config: help +//config: Call an external program (normally telinit) to facilitate +//config: a switch to a proper runlevel. +//config: +//config: This option is only available if you selected halt and friends, +//config: but did not select init. +//config: +//config:config TELINIT_PATH +//config: string "Path to telinit executable" +//config: default "/sbin/telinit" +//config: depends on FEATURE_CALL_TELINIT +//config: help +//config: When busybox halt and friends have to call external telinit +//config: to facilitate proper shutdown, this path is to be used when +//config: locating telinit executable. + +//usage:#define halt_trivial_usage +//usage: "[-d DELAY] [-n] [-f]" IF_FEATURE_WTMP(" [-w]") +//usage:#define halt_full_usage "\n\n" +//usage: "Halt the system\n" +//usage: "\nOptions:" +//usage: "\n -d SEC Delay interval" +//usage: "\n -n Do not sync" +//usage: "\n -f Force (don't go through init)" +//usage: IF_FEATURE_WTMP( +//usage: "\n -w Only write a wtmp record" +//usage: ) +//usage: +//usage:#define poweroff_trivial_usage +//usage: "[-d DELAY] [-n] [-f]" +//usage:#define poweroff_full_usage "\n\n" +//usage: "Halt and shut off power\n" +//usage: "\nOptions:" +//usage: "\n -d SEC Delay interval" +//usage: "\n -n Do not sync" +//usage: "\n -f Force (don't go through init)" +//usage: +//usage:#define reboot_trivial_usage +//usage: "[-d DELAY] [-n] [-f]" +//usage:#define reboot_full_usage "\n\n" +//usage: "Reboot the system\n" +//usage: "\nOptions:" +//usage: "\n -d SEC Delay interval" +//usage: "\n -n Do not sync" +//usage: "\n -f Force (don't go through init)" + #include "libbb.h" #include "reboot.h" diff --git a/init/init.c b/init/init.c index 5c0d11402..340731b8b 100644 --- a/init/init.c +++ b/init/init.c @@ -9,6 +9,237 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//applet:IF_INIT(APPLET(init, _BB_DIR_SBIN, _BB_SUID_DROP)) +//applet:IF_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, _BB_DIR_ROOT, _BB_SUID_DROP, linuxrc)) + +//kbuild:lib-$(CONFIG_INIT) += init.o + +//config:config INIT +//config: bool "init" +//config: default y +//config: select FEATURE_SYSLOG +//config: help +//config: init is the first program run when the system boots. +//config: +//config:config FEATURE_USE_INITTAB +//config: bool "Support reading an inittab file" +//config: default y +//config: depends on INIT +//config: help +//config: Allow init to read an inittab file when the system boot. +//config: +//config:config FEATURE_KILL_REMOVED +//config: bool "Support killing processes that have been removed from inittab" +//config: default n +//config: depends on FEATURE_USE_INITTAB +//config: help +//config: When respawn entries are removed from inittab and a SIGHUP is +//config: sent to init, this option will make init kill the processes +//config: that have been removed. +//config: +//config:config FEATURE_KILL_DELAY +//config: int "How long to wait between TERM and KILL (0 - send TERM only)" if FEATURE_KILL_REMOVED +//config: range 0 1024 +//config: default 0 +//config: depends on FEATURE_KILL_REMOVED +//config: help +//config: With nonzero setting, init sends TERM, forks, child waits N +//config: seconds, sends KILL and exits. Setting it too high is unwise +//config: (child will hang around for too long and could actually kill +//config: the wrong process!) +//config: +//config:config FEATURE_INIT_SCTTY +//config: bool "Run commands with leading dash with controlling tty" +//config: default y +//config: depends on INIT +//config: help +//config: If this option is enabled, init will try to give a controlling +//config: tty to any command which has leading hyphen (often it's "-/bin/sh"). +//config: More precisely, init will do "ioctl(STDIN_FILENO, TIOCSCTTY, 0)". +//config: If device attached to STDIN_FILENO can be a ctty but is not yet +//config: a ctty for other session, it will become this process' ctty. +//config: This is not the traditional init behavour, but is often what you want +//config: in an embedded system where the console is only accessed during +//config: development or for maintenance. +//config: NB: using cttyhack applet may work better. +//config: +//config:config FEATURE_INIT_SYSLOG +//config: bool "Enable init to write to syslog" +//config: default y +//config: depends on INIT +//config: +//config:config FEATURE_EXTRA_QUIET +//config: bool "Be _extra_ quiet on boot" +//config: default y +//config: depends on INIT +//config: help +//config: Prevent init from logging some messages to the console during boot. +//config: +//config:config FEATURE_INIT_COREDUMPS +//config: bool "Support dumping core for child processes (debugging only)" +//config: default y +//config: depends on INIT +//config: help +//config: If this option is enabled and the file /.init_enable_core +//config: exists, then init will call setrlimit() to allow unlimited +//config: core file sizes. If this option is disabled, processes +//config: will not generate any core files. +//config: +//config:config FEATURE_INITRD +//config: bool "Support running init from within an initrd (not initramfs)" +//config: default y +//config: depends on INIT +//config: help +//config: Legacy support for running init under the old-style initrd. Allows +//config: the name linuxrc to act as init, and it doesn't assume init is PID 1. +//config: +//config: This does not apply to initramfs, which runs /init as PID 1 and +//config: requires no special support. +//config: +//config:config INIT_TERMINAL_TYPE +//config: string "Initial terminal type" +//config: default "linux" +//config: depends on INIT +//config: help +//config: This is the initial value set by init for the TERM environment +//config: variable. This variable is used by programs which make use of +//config: extended terminal capabilities. +//config: +//config: Note that on Linux, init attempts to detect serial terminal and +//config: sets TERM to "vt102" if one is found. + +//usage:#define init_trivial_usage +//usage: "" +//usage:#define init_full_usage "\n\n" +//usage: "Init is the parent of all processes" +//usage: +//usage:#define init_notes_usage +//usage: "This version of init is designed to be run only by the kernel.\n" +//usage: "\n" +//usage: "BusyBox init doesn't support multiple runlevels. The runlevels field of\n" +//usage: "the /etc/inittab file is completely ignored by BusyBox init. If you want\n" +//usage: "runlevels, use sysvinit.\n" +//usage: "\n" +//usage: "BusyBox init works just fine without an inittab. If no inittab is found,\n" +//usage: "it has the following default behavior:\n" +//usage: "\n" +//usage: " ::sysinit:/etc/init.d/rcS\n" +//usage: " ::askfirst:/bin/sh\n" +//usage: " ::ctrlaltdel:/sbin/reboot\n" +//usage: " ::shutdown:/sbin/swapoff -a\n" +//usage: " ::shutdown:/bin/umount -a -r\n" +//usage: " ::restart:/sbin/init\n" +//usage: "\n" +//usage: "if it detects that /dev/console is _not_ a serial console, it will also run:\n" +//usage: "\n" +//usage: " tty2::askfirst:/bin/sh\n" +//usage: " tty3::askfirst:/bin/sh\n" +//usage: " tty4::askfirst:/bin/sh\n" +//usage: "\n" +//usage: "If you choose to use an /etc/inittab file, the inittab entry format is as follows:\n" +//usage: "\n" +//usage: " :::\n" +//usage: "\n" +//usage: " :\n" +//usage: "\n" +//usage: " WARNING: This field has a non-traditional meaning for BusyBox init!\n" +//usage: " The id field is used by BusyBox init to specify the controlling tty for\n" +//usage: " the specified process to run on. The contents of this field are\n" +//usage: " appended to \"/dev/\" and used as-is. There is no need for this field to\n" +//usage: " be unique, although if it isn't you may have strange results. If this\n" +//usage: " field is left blank, the controlling tty is set to the console. Also\n" +//usage: " note that if BusyBox detects that a serial console is in use, then only\n" +//usage: " entries whose controlling tty is either the serial console or /dev/null\n" +//usage: " will be run. BusyBox init does nothing with utmp. We don't need no\n" +//usage: " stinkin' utmp.\n" +//usage: "\n" +//usage: " :\n" +//usage: "\n" +//usage: " The runlevels field is completely ignored.\n" +//usage: "\n" +//usage: " :\n" +//usage: "\n" +//usage: " Valid actions include: sysinit, respawn, askfirst, wait,\n" +//usage: " once, restart, ctrlaltdel, and shutdown.\n" +//usage: "\n" +//usage: " The available actions can be classified into two groups: actions\n" +//usage: " that are run only once, and actions that are re-run when the specified\n" +//usage: " process exits.\n" +//usage: "\n" +//usage: " Run only-once actions:\n" +//usage: "\n" +//usage: " 'sysinit' is the first item run on boot. init waits until all\n" +//usage: " sysinit actions are completed before continuing. Following the\n" +//usage: " completion of all sysinit actions, all 'wait' actions are run.\n" +//usage: " 'wait' actions, like 'sysinit' actions, cause init to wait until\n" +//usage: " the specified task completes. 'once' actions are asynchronous,\n" +//usage: " therefore, init does not wait for them to complete. 'restart' is\n" +//usage: " the action taken to restart the init process. By default this should\n" +//usage: " simply run /sbin/init, but can be a script which runs pivot_root or it\n" +//usage: " can do all sorts of other interesting things. The 'ctrlaltdel' init\n" +//usage: " actions are run when the system detects that someone on the system\n" +//usage: " console has pressed the CTRL-ALT-DEL key combination. Typically one\n" +//usage: " wants to run 'reboot' at this point to cause the system to reboot.\n" +//usage: " Finally the 'shutdown' action specifies the actions to taken when\n" +//usage: " init is told to reboot. Unmounting filesystems and disabling swap\n" +//usage: " is a very good here.\n" +//usage: "\n" +//usage: " Run repeatedly actions:\n" +//usage: "\n" +//usage: " 'respawn' actions are run after the 'once' actions. When a process\n" +//usage: " started with a 'respawn' action exits, init automatically restarts\n" +//usage: " it. Unlike sysvinit, BusyBox init does not stop processes from\n" +//usage: " respawning out of control. The 'askfirst' actions acts just like\n" +//usage: " respawn, except that before running the specified process it\n" +//usage: " displays the line \"Please press Enter to activate this console.\"\n" +//usage: " and then waits for the user to press enter before starting the\n" +//usage: " specified process.\n" +//usage: "\n" +//usage: " Unrecognized actions (like initdefault) will cause init to emit an\n" +//usage: " error message, and then go along with its business. All actions are\n" +//usage: " run in the order they appear in /etc/inittab.\n" +//usage: "\n" +//usage: " :\n" +//usage: "\n" +//usage: " Specifies the process to be executed and its command line.\n" +//usage: "\n" +//usage: "Example /etc/inittab file:\n" +//usage: "\n" +//usage: " # This is run first except when booting in single-user mode\n" +//usage: " #\n" +//usage: " ::sysinit:/etc/init.d/rcS\n" +//usage: " \n" +//usage: " # /bin/sh invocations on selected ttys\n" +//usage: " #\n" +//usage: " # Start an \"askfirst\" shell on the console (whatever that may be)\n" +//usage: " ::askfirst:-/bin/sh\n" +//usage: " # Start an \"askfirst\" shell on /dev/tty2-4\n" +//usage: " tty2::askfirst:-/bin/sh\n" +//usage: " tty3::askfirst:-/bin/sh\n" +//usage: " tty4::askfirst:-/bin/sh\n" +//usage: " \n" +//usage: " # /sbin/getty invocations for selected ttys\n" +//usage: " #\n" +//usage: " tty4::respawn:/sbin/getty 38400 tty4\n" +//usage: " tty5::respawn:/sbin/getty 38400 tty5\n" +//usage: " \n" +//usage: " \n" +//usage: " # Example of how to put a getty on a serial line (for a terminal)\n" +//usage: " #\n" +//usage: " #::respawn:/sbin/getty -L ttyS0 9600 vt100\n" +//usage: " #::respawn:/sbin/getty -L ttyS1 9600 vt100\n" +//usage: " #\n" +//usage: " # Example how to put a getty on a modem line\n" +//usage: " #::respawn:/sbin/getty 57600 ttyS2\n" +//usage: " \n" +//usage: " # Stuff to do when restarting the init process\n" +//usage: " ::restart:/sbin/init\n" +//usage: " \n" +//usage: " # Stuff to do before rebooting\n" +//usage: " ::ctrlaltdel:/sbin/reboot\n" +//usage: " ::shutdown:/bin/umount -a -r\n" +//usage: " ::shutdown:/sbin/swapoff -a\n" + #include "libbb.h" #include #include diff --git a/init/mesg.c b/init/mesg.c index ef5f0eb66..b560df205 100644 --- a/init/mesg.c +++ b/init/mesg.c @@ -7,6 +7,24 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//applet:IF_MESG(APPLET(mesg, _BB_DIR_USR_BIN, _BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_MESG) += mesg.o + +//config:config MESG +//config: bool "mesg" +//config: default y +//config: help +//config: Mesg controls access to your terminal by others. It is typically +//config: used to allow or disallow other users to write to your terminal + +//usage:#define mesg_trivial_usage +//usage: "[y|n]" +//usage:#define mesg_full_usage "\n\n" +//usage: "Control write access to your terminal\n" +//usage: " y Allow write access to your terminal\n" +//usage: " n Disallow write access to your terminal" + #include "libbb.h" #ifdef USE_TTY_GROUP -- cgit v1.2.3-55-g6feb From 05e8605ab8a01120af7c9f011c2334ab34381fdf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Oct 2010 12:53:27 +0200 Subject: remove runit/runit_lib.c function old new delta runsv_main 1770 1786 +16 svstatus_get 176 188 +12 sv_main 1180 1186 +6 runsvdir_main 683 689 +6 processorstart 385 391 +6 control 126 132 +6 logdir_open 1184 1187 +3 lock_exnb 14 - -14 lock_ex 14 - -14 open_write 17 - -17 open_read 17 - -17 ------------------------------------------------------------------------------ (add/remove: 0/5 grow/shrink: 7/0 up/down: 55/-62) Total: -7 bytes Signed-off-by: Denys Vlasenko --- runit/Kbuild.src | 8 +- runit/runit_lib.c | 275 ------------------------------------------------------ runit/runit_lib.h | 53 ----------- runit/runsv.c | 6 +- runit/runsvdir.c | 2 +- runit/sv.c | 11 ++- runit/svlogd.c | 50 +++++++++- 7 files changed, 63 insertions(+), 342 deletions(-) delete mode 100644 runit/runit_lib.c diff --git a/runit/Kbuild.src b/runit/Kbuild.src index d38bad20f..0fce95507 100644 --- a/runit/Kbuild.src +++ b/runit/Kbuild.src @@ -8,10 +8,10 @@ lib-y:= INSERT -lib-$(CONFIG_RUNSV) += runsv.o runit_lib.o -lib-$(CONFIG_RUNSVDIR) += runsvdir.o runit_lib.o -lib-$(CONFIG_SV) += sv.o runit_lib.o -lib-$(CONFIG_SVLOGD) += svlogd.o runit_lib.o +lib-$(CONFIG_RUNSV) += runsv.o +lib-$(CONFIG_RUNSVDIR) += runsvdir.o +lib-$(CONFIG_SV) += sv.o +lib-$(CONFIG_SVLOGD) += svlogd.o lib-$(CONFIG_CHPST) += chpst.o lib-$(CONFIG_ENVDIR) += chpst.o diff --git a/runit/runit_lib.c b/runit/runit_lib.c deleted file mode 100644 index 8182a909a..000000000 --- a/runit/runit_lib.c +++ /dev/null @@ -1,275 +0,0 @@ -/* -Copyright (c) 2001-2006, Gerrit Pape -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* Busyboxed by Denys Vlasenko */ -/* Collected into one file from runit's many tiny files */ -/* TODO: review, eliminate unneeded stuff, move good stuff to libbb */ - -#include -#include -#include "libbb.h" -#include "runit_lib.h" - -#ifdef UNUSED -unsigned byte_chr(char *s,unsigned n,int c) -{ - char ch; - char *t; - - ch = c; - t = s; - for (;;) { - if (!n) break; - if (*t == ch) break; - ++t; - --n; - } - return t - s; -} - -static /* as it isn't used anywhere else */ -void tai_pack(char *s, const struct tai *t) -{ - uint64_t x; - - x = t->x; - s[7] = x & 255; x >>= 8; - s[6] = x & 255; x >>= 8; - s[5] = x & 255; x >>= 8; - s[4] = x & 255; x >>= 8; - s[3] = x & 255; x >>= 8; - s[2] = x & 255; x >>= 8; - s[1] = x & 255; x >>= 8; - s[0] = x; -} - -void tai_unpack(const char *s,struct tai *t) -{ - uint64_t x; - - x = (unsigned char) s[0]; - x <<= 8; x += (unsigned char) s[1]; - x <<= 8; x += (unsigned char) s[2]; - x <<= 8; x += (unsigned char) s[3]; - x <<= 8; x += (unsigned char) s[4]; - x <<= 8; x += (unsigned char) s[5]; - x <<= 8; x += (unsigned char) s[6]; - x <<= 8; x += (unsigned char) s[7]; - t->x = x; -} - - -void taia_add(struct taia *t,const struct taia *u,const struct taia *v) -{ - t->sec.x = u->sec.x + v->sec.x; - t->nano = u->nano + v->nano; - t->atto = u->atto + v->atto; - if (t->atto > 999999999UL) { - t->atto -= 1000000000UL; - ++t->nano; - } - if (t->nano > 999999999UL) { - t->nano -= 1000000000UL; - ++t->sec.x; - } -} - -int taia_less(const struct taia *t, const struct taia *u) -{ - if (t->sec.x < u->sec.x) return 1; - if (t->sec.x > u->sec.x) return 0; - if (t->nano < u->nano) return 1; - if (t->nano > u->nano) return 0; - return t->atto < u->atto; -} - -void taia_now(struct taia *t) -{ - struct timeval now; - gettimeofday(&now, NULL); - tai_unix(&t->sec, now.tv_sec); - t->nano = 1000 * now.tv_usec + 500; - t->atto = 0; -} - -/* UNUSED -void taia_pack(char *s, const struct taia *t) -{ - unsigned long x; - - tai_pack(s, &t->sec); - s += 8; - - x = t->atto; - s[7] = x & 255; x >>= 8; - s[6] = x & 255; x >>= 8; - s[5] = x & 255; x >>= 8; - s[4] = x; - x = t->nano; - s[3] = x & 255; x >>= 8; - s[2] = x & 255; x >>= 8; - s[1] = x & 255; x >>= 8; - s[0] = x; -} -*/ - -void taia_sub(struct taia *t, const struct taia *u, const struct taia *v) -{ - unsigned long unano = u->nano; - unsigned long uatto = u->atto; - - t->sec.x = u->sec.x - v->sec.x; - t->nano = unano - v->nano; - t->atto = uatto - v->atto; - if (t->atto > uatto) { - t->atto += 1000000000UL; - --t->nano; - } - if (t->nano > unano) { - t->nano += 1000000000UL; - --t->sec.x; - } -} - -/* XXX: breaks tai encapsulation */ -void taia_uint(struct taia *t, unsigned s) -{ - t->sec.x = s; - t->nano = 0; - t->atto = 0; -} - -static -uint64_t taia2millisec(const struct taia *t) -{ - return (t->sec.x * 1000) + (t->nano / 1000000); -} - -void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp) -{ - int millisecs; - int i; - - if (taia_less(deadline, stamp)) - millisecs = 0; - else { - uint64_t m; - struct taia t; - t = *stamp; - taia_sub(&t, deadline, &t); - millisecs = m = taia2millisec(&t); - if (m > 1000) millisecs = 1000; - millisecs += 20; - } - - for (i = 0; i < len; ++i) - x[i].revents = 0; - - poll(x, len, millisecs); - /* XXX: some kernels apparently need x[0] even if len is 0 */ - /* XXX: how to handle EAGAIN? are kernels really this dumb? */ - /* XXX: how to handle EINVAL? when exactly can this happen? */ -} -#endif - -int lock_ex(int fd) -{ - return flock(fd, LOCK_EX); -} - -int lock_exnb(int fd) -{ - return flock(fd, LOCK_EX | LOCK_NB); -} - -#ifdef UNUSED -int open_append(const char *fn) -{ - return open(fn, O_WRONLY | O_NDELAY | O_APPEND | O_CREAT, 0600); -} - -int open_trunc(const char *fn) -{ - return open(fn, O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT, 0644); -} -#endif - -int open_read(const char *fn) -{ - return open(fn, O_RDONLY|O_NDELAY); -} - -int open_write(const char *fn) -{ - return open(fn, O_WRONLY|O_NDELAY); -} - -unsigned FAST_FUNC pmatch(const char *p, const char *s, unsigned len) -{ - for (;;) { - char c = *p++; - if (!c) return !len; - switch (c) { - case '*': - c = *p; - if (!c) return 1; - for (;;) { - if (!len) return 0; - if (*s == c) break; - ++s; - --len; - } - continue; - case '+': - c = *p++; - if (c != *s) return 0; - for (;;) { - if (!len) return 1; - if (*s != c) break; - ++s; - --len; - } - continue; - /* - case '?': - if (*p == '?') { - if (*s != '?') return 0; - ++p; - } - ++s; --len; - continue; - */ - default: - if (!len) return 0; - if (*s != c) return 0; - ++s; - --len; - continue; - } - } - return 0; -} diff --git a/runit/runit_lib.h b/runit/runit_lib.h index d8304aca6..c36ea4ca5 100644 --- a/runit/runit_lib.h +++ b/runit/runit_lib.h @@ -27,59 +27,6 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN -//extern unsigned byte_chr(char *s,unsigned n,int c); -// -//struct tai { -// uint64_t x; -//}; -// -//#define tai_unix(t,u) ((void) ((t)->x = 0x400000000000000aULL + (uint64_t) (u))) -// -//#define TAI_PACK 8 -//extern void tai_unpack(const char *,struct tai *); -// -//extern void tai_uint(struct tai *,unsigned); -// -//struct taia { -// struct tai sec; -// unsigned long nano; /* 0...999999999 */ -// unsigned long atto; /* 0...999999999 */ -//}; -// -//extern void taia_now(struct taia *); -// -//extern void taia_add(struct taia *,const struct taia *,const struct taia *); -//extern void taia_addsec(struct taia *,const struct taia *,int); -//extern void taia_sub(struct taia *,const struct taia *,const struct taia *); -//extern void taia_half(struct taia *,const struct taia *); -//extern int taia_less(const struct taia *,const struct taia *); -// -//#define TAIA_PACK 16 -//extern void taia_pack(char *,const struct taia *); -// -//extern void taia_uint(struct taia *,unsigned); -// -//typedef struct pollfd iopause_fd; -//#define IOPAUSE_READ POLLIN -//#define IOPAUSE_WRITE POLLOUT -// -//extern void iopause(iopause_fd *,unsigned,struct taia *,struct taia *); - -extern int lock_ex(int); -//extern int lock_un(int); -extern int lock_exnb(int); - -extern int open_read(const char *); -extern int open_write(const char *); -//extern int open_excl(const char *); -//extern int open_append(const char *); -//extern int open_trunc(const char *); - -extern unsigned FAST_FUNC pmatch(const char *, const char *, unsigned); - -//#define str_diff(s,t) strcmp((s), (t)) -#define str_equal(s,t) (!strcmp((s), (t))) - /* * runsv / supervise / sv stuff */ diff --git a/runit/runsv.c b/runit/runsv.c index 6bb6ec886..ebb031837 100644 --- a/runit/runsv.c +++ b/runit/runsv.c @@ -524,7 +524,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) } svd[0].fdlock = xopen3("log/supervise/lock"+4, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); - if (lock_exnb(svd[0].fdlock) == -1) + if (flock(svd[0].fdlock, LOCK_EX | LOCK_NB) == -1) fatal_cannot("lock supervise/lock"); close_on_exec_on(svd[0].fdlock); if (haslog) { @@ -548,7 +548,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) } svd[1].fdlock = xopen3("log/supervise/lock", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); - if (lock_ex(svd[1].fdlock) == -1) + if (flock(svd[1].fdlock, LOCK_EX) == -1) fatal_cannot("lock log/supervise/lock"); close_on_exec_on(svd[1].fdlock); } @@ -618,7 +618,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) pidchanged = 1; svd[0].ctrl &= ~C_TERM; if (svd[0].state != S_FINISH) { - fd = open_read("finish"); + fd = open("finish", O_RDONLY|O_NDELAY); if (fd != -1) { close(fd); svd[0].state = S_FINISH; diff --git a/runit/runsvdir.c b/runit/runsvdir.c index 71fde757e..e77eeff04 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c @@ -276,7 +276,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) } run: #endif - curdir = open_read("."); + curdir = open(".", O_RDONLY|O_NDELAY); if (curdir == -1) fatal2_cannot("open current directory", ""); close_on_exec_on(curdir); diff --git a/runit/sv.c b/runit/sv.c index 3f76a2d47..c420a91a6 100644 --- a/runit/sv.c +++ b/runit/sv.c @@ -176,6 +176,9 @@ struct globals { #define INIT_G() do { } while (0) +#define str_equal(s,t) (!strcmp((s), (t))) + + static void fatal_cannot(const char *m1) NORETURN; static void fatal_cannot(const char *m1) { @@ -221,7 +224,7 @@ static int svstatus_get(void) { int fd, r; - fd = open_write("supervise/ok"); + fd = open("supervise/ok", O_WRONLY|O_NDELAY); if (fd == -1) { if (errno == ENODEV) { *acts == 'x' ? ok("runsv not running") @@ -232,7 +235,7 @@ static int svstatus_get(void) return -1; } close(fd); - fd = open_read("supervise/status"); + fd = open("supervise/status", O_RDONLY|O_NDELAY); if (fd == -1) { warn("can't open supervise/status"); return -1; @@ -397,7 +400,7 @@ static int control(const char *a) if (svstatus.want == *a) return 0; */ - fd = open_write("supervise/control"); + fd = open("supervise/control", O_WRONLY|O_NDELAY); if (fd == -1) { if (errno != ENODEV) warn("can't open supervise/control"); @@ -446,7 +449,7 @@ int sv_main(int argc UNUSED_PARAM, char **argv) tnow = time(NULL) + 0x400000000000000aULL; tstart = tnow; - curdir = open_read("."); + curdir = open(".", O_RDONLY|O_NDELAY); if (curdir == -1) fatal_cannot("open current directory"); diff --git a/runit/svlogd.c b/runit/svlogd.c index 1f0a77cc2..052806c25 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c @@ -261,6 +261,52 @@ static char* wstrdup(const char *str) return s; } +static unsigned pmatch(const char *p, const char *s, unsigned len) +{ + for (;;) { + char c = *p++; + if (!c) return !len; + switch (c) { + case '*': + c = *p; + if (!c) return 1; + for (;;) { + if (!len) return 0; + if (*s == c) break; + ++s; + --len; + } + continue; + case '+': + c = *p++; + if (c != *s) return 0; + for (;;) { + if (!len) return 1; + if (*s != c) break; + ++s; + --len; + } + continue; + /* + case '?': + if (*p == '?') { + if (*s != '?') return 0; + ++p; + } + ++s; --len; + continue; + */ + default: + if (!len) return 0; + if (*s != c) return 0; + ++s; + --len; + continue; + } + } + return 0; +} + /*** ex fmt_ptime.[ch] ***/ /* NUL terminated */ @@ -342,7 +388,7 @@ static void processorstart(struct logdir *ld) ld->fnsave[26] = 't'; /* <- that's why we need sv_ch! */ fd = xopen(ld->fnsave, O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT); xmove_fd(fd, 1); - fd = open_read("state"); + fd = open("state", O_RDONLY|O_NDELAY); if (fd == -1) { if (errno != ENOENT) bb_perror_msg_and_die(FATAL"can't %s processor %s", "open state for", ld->name); @@ -626,7 +672,7 @@ static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn) } ld->fdlock = open("lock", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); if ((ld->fdlock == -1) - || (lock_exnb(ld->fdlock) == -1) + || (flock(ld->fdlock, LOCK_EX | LOCK_NB) == -1) ) { logdir_close(ld); warn2("can't lock directory", (char*)fn); -- cgit v1.2.3-55-g6feb From f2710d02210bbba4a9580c11ff053b01081eaf54 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 15 Oct 2010 10:42:17 +0200 Subject: date: move applet and usage bits to date.c Signed-off-by: Denys Vlasenko --- coreutils/date.c | 106 +++++++++++++++++++++++++++++++++++--------------- include/applets.src.h | 1 - include/usage.src.h | 40 ------------------- 3 files changed, 74 insertions(+), 73 deletions(-) diff --git a/coreutils/date.c b/coreutils/date.c index c9dfedf81..87cc8f2ef 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -19,38 +19,7 @@ /* Input parsing code is always bulky - used heavy duty libc stuff as much as possible, missed out a lot of bounds checking */ -/* Default input handling to save surprising some people */ - -/* GNU coreutils 6.9 man page: - * date [OPTION]... [+FORMAT] - * date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]] - * -d, --date=STRING - * display time described by STRING, not `now' - * -f, --file=DATEFILE - * like --date once for each line of DATEFILE - * -r, --reference=FILE - * display the last modification time of FILE - * -R, --rfc-2822 - * output date and time in RFC 2822 format. - * Example: Mon, 07 Aug 2006 12:34:56 -0600 - * --rfc-3339=TIMESPEC - * output date and time in RFC 3339 format. - * TIMESPEC='date', 'seconds', or 'ns' - * Date and time components are separated by a single space: - * 2006-08-07 12:34:56-06:00 - * -s, --set=STRING - * set time described by STRING - * -u, --utc, --universal - * print or set Coordinated Universal Time - * - * Busybox: - * long options are not supported - * -f is not supported - * -I seems to roughly match --rfc-3339, but -I has _optional_ param - * (thus "-I seconds" doesn't work, only "-Iseconds"), - * and does not support -Ins - * -D FMT is a bbox extension for _input_ conversion of -d DATE - */ +//applet:IF_DATE(APPLET(date, _BB_DIR_BIN, _BB_SUID_DROP)) //kbuild:lib-$(CONFIG_DATE) += date.o @@ -69,6 +38,7 @@ //config: Enable option (-I) to output an ISO-8601 compliant //config: date/time string. //config: +//config:# defaults to "no": stat's nanosecond field is a bit non-portable //config:config FEATURE_DATE_NANO //config: bool "Support %[num]N nanosecond format specifier" //config: default n @@ -92,6 +62,78 @@ //config: the same format. With it on, 'date DATE' additionally supports //config: MMDDhhmm[[YY]YY][.ss] format. +/* GNU coreutils 6.9 man page: + * date [OPTION]... [+FORMAT] + * date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]] + * -d, --date=STRING + * display time described by STRING, not `now' + * -f, --file=DATEFILE + * like --date once for each line of DATEFILE + * -r, --reference=FILE + * display the last modification time of FILE + * -R, --rfc-2822 + * output date and time in RFC 2822 format. + * Example: Mon, 07 Aug 2006 12:34:56 -0600 + * --rfc-3339=TIMESPEC + * output date and time in RFC 3339 format. + * TIMESPEC='date', 'seconds', or 'ns' + * Date and time components are separated by a single space: + * 2006-08-07 12:34:56-06:00 + * -s, --set=STRING + * set time described by STRING + * -u, --utc, --universal + * print or set Coordinated Universal Time + * + * Busybox: + * long options are not supported + * -f is not supported + * -I seems to roughly match --rfc-3339, but -I has _optional_ param + * (thus "-I seconds" doesn't work, only "-Iseconds"), + * and does not support -Ins + * -D FMT is a bbox extension for _input_ conversion of -d DATE + */ + +//usage:#define date_trivial_usage +//usage: "[OPTIONS] [+FMT] [TIME]" +//usage:#define date_full_usage "\n\n" +//usage: "Display time (using +FMT), or set time\n" +//usage: "\nOptions:" +//usage: IF_NOT_LONG_OPTS( +//usage: "\n [-s] TIME Set time to TIME" +//usage: "\n -u Work in UTC (don't convert to local time)" +//usage: "\n -R Output RFC-2822 compliant date string" +//usage: ) IF_LONG_OPTS( +//usage: "\n [-s,--set] TIME Set time to TIME" +//usage: "\n -u,--utc Work in UTC (don't convert to local time)" +//usage: "\n -R,--rfc-2822 Output RFC-2822 compliant date string" +//usage: ) +//usage: IF_FEATURE_DATE_ISOFMT( +//usage: "\n -I[SPEC] Output ISO-8601 compliant date string" +//usage: "\n SPEC='date' (default) for date only," +//usage: "\n 'hours', 'minutes', or 'seconds' for date and" +//usage: "\n time to the indicated precision" +//usage: ) +//usage: IF_NOT_LONG_OPTS( +//usage: "\n -r FILE Display last modification time of FILE" +//usage: "\n -d TIME Display TIME, not 'now'" +//usage: ) IF_LONG_OPTS( +//usage: "\n -r,--reference FILE Display last modification time of FILE" +//usage: "\n -d,--date TIME Display TIME, not 'now'" +//usage: ) +//usage: IF_FEATURE_DATE_ISOFMT( +//usage: "\n -D FMT Use FMT for -d TIME conversion" +//usage: ) +//usage: "\n" +//usage: "\nRecognized TIME formats:" +//usage: "\n hh:mm[:ss]" +//usage: "\n [YYYY.]MM.DD-hh:mm[:ss]" +//usage: "\n YYYY-MM-DD hh:mm[:ss]" +//usage: "\n [[[[[YY]YY]MM]DD]hh]mm[.ss]" +//usage: +//usage:#define date_example_usage +//usage: "$ date\n" +//usage: "Wed Apr 12 18:52:41 MDT 2000\n" + #include "libbb.h" #if ENABLE_FEATURE_DATE_NANO # include diff --git a/include/applets.src.h b/include/applets.src.h index 545d3c5c2..a42f6fffa 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -98,7 +98,6 @@ IF_CROND(APPLET(crond, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_CRONTAB(APPLET(crontab, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) IF_CRYPTPW(APPLET(cryptpw, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_CUT(APPLET_NOEXEC(cut, cut, _BB_DIR_USR_BIN, _BB_SUID_DROP, cut)) -IF_DATE(APPLET(date, _BB_DIR_BIN, _BB_SUID_DROP)) IF_DC(APPLET(dc, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_DD(APPLET_NOEXEC(dd, dd, _BB_DIR_BIN, _BB_SUID_DROP, dd)) IF_DEALLOCVT(APPLET(deallocvt, _BB_DIR_USR_BIN, _BB_SUID_DROP)) diff --git a/include/usage.src.h b/include/usage.src.h index 084427cc0..1bb4b563c 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -702,46 +702,6 @@ INSERT "$ echo \"Hello world\" | cut -f 2 -d ' '\n" \ "world\n" -#define date_trivial_usage \ - "[OPTIONS] [+FMT] [TIME]" -#define date_full_usage "\n\n" \ - "Display time (using +FMT), or set time\n" \ - "\nOptions:" \ - IF_NOT_LONG_OPTS( \ - "\n [-s] TIME Set time to TIME" \ - "\n -u Work in UTC (don't convert to local time)" \ - "\n -R Output RFC-2822 compliant date string" \ - ) IF_LONG_OPTS( \ - "\n [-s,--set] TIME Set time to TIME" \ - "\n -u,--utc Work in UTC (don't convert to local time)" \ - "\n -R,--rfc-2822 Output RFC-2822 compliant date string" \ - ) \ - IF_FEATURE_DATE_ISOFMT( \ - "\n -I[SPEC] Output ISO-8601 compliant date string" \ - "\n SPEC='date' (default) for date only," \ - "\n 'hours', 'minutes', or 'seconds' for date and" \ - "\n time to the indicated precision" \ - ) IF_NOT_LONG_OPTS( \ - "\n -r FILE Display last modification time of FILE" \ - "\n -d TIME Display TIME, not 'now'" \ - ) IF_LONG_OPTS( \ - "\n -r,--reference FILE Display last modification time of FILE" \ - "\n -d,--date TIME Display TIME, not 'now'" \ - ) \ - IF_FEATURE_DATE_ISOFMT( \ - "\n -D FMT Use FMT for -d TIME conversion" \ - ) \ - "\n" \ - "\nRecognized TIME formats:" \ - "\n hh:mm[:ss]" \ - "\n [YYYY.]MM.DD-hh:mm[:ss]" \ - "\n YYYY-MM-DD hh:mm[:ss]" \ - "\n [[[[[YY]YY]MM]DD]hh]mm[.ss]" \ - -#define date_example_usage \ - "$ date\n" \ - "Wed Apr 12 18:52:41 MDT 2000\n" - #define dd_trivial_usage \ "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" \ " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]") -- cgit v1.2.3-55-g6feb From c15613c9757f5a26da3623c1bcfa3580c81b74c3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 15 Oct 2010 11:29:02 +0200 Subject: modutils/*: move applet bits into corresponding *.c files Signed-off-by: Denys Vlasenko --- include/applets.src.h | 10 ---------- modutils/depmod.c | 2 ++ modutils/insmod.c | 2 ++ modutils/lsmod.c | 3 +++ modutils/modprobe-small.c | 6 ++++++ modutils/modprobe.c | 25 ++++++++++++++----------- modutils/rmmod.c | 2 ++ 7 files changed, 29 insertions(+), 21 deletions(-) diff --git a/include/applets.src.h b/include/applets.src.h index a42f6fffa..879dbf760 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -103,8 +103,6 @@ IF_DD(APPLET_NOEXEC(dd, dd, _BB_DIR_BIN, _BB_SUID_DROP, dd)) IF_DEALLOCVT(APPLET(deallocvt, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_DELGROUP(APPLET_ODDNAME(delgroup, deluser, _BB_DIR_BIN, _BB_SUID_DROP, delgroup)) IF_DELUSER(APPLET(deluser, _BB_DIR_BIN, _BB_SUID_DROP)) -IF_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_DROP)) -IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) IF_DEVFSD(APPLET(devfsd, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_DEVMEM(APPLET(devmem, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_DF(APPLET(df, _BB_DIR_BIN, _BB_SUID_DROP)) @@ -179,8 +177,6 @@ IF_IFPLUGD(APPLET(ifplugd, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_IFUPDOWN(APPLET_ODDNAME(ifup, ifupdown, _BB_DIR_SBIN, _BB_SUID_DROP, ifup)) IF_INETD(APPLET(inetd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_INOTIFYD(APPLET(inotifyd, _BB_DIR_SBIN, _BB_SUID_DROP)) -IF_INSMOD(APPLET(insmod, _BB_DIR_SBIN, _BB_SUID_DROP)) -IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) IF_INSTALL(APPLET(install, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_IONICE(APPLET(ionice, _BB_DIR_BIN, _BB_SUID_DROP)) #if ENABLE_FEATURE_IP_ADDRESS \ @@ -222,8 +218,6 @@ IF_LPQ(APPLET_ODDNAME(lpq, lpqr, _BB_DIR_USR_BIN, _BB_SUID_DROP, lpq)) IF_LPR(APPLET_ODDNAME(lpr, lpqr, _BB_DIR_USR_BIN, _BB_SUID_DROP, lpr)) IF_LS(APPLET_NOEXEC(ls, ls, _BB_DIR_BIN, _BB_SUID_DROP, ls)) IF_LSATTR(APPLET(lsattr, _BB_DIR_BIN, _BB_SUID_DROP)) -IF_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_DROP)) -IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) IF_LSPCI(APPLET(lspci, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_LSUSB(APPLET(lsusb, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_UNLZMA(APPLET_ODDNAME(lzcat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_DROP, lzcat)) @@ -250,8 +244,6 @@ IF_MKNOD(APPLET_NOEXEC(mknod, mknod, _BB_DIR_BIN, _BB_SUID_DROP, mknod)) IF_CRYPTPW(APPLET_ODDNAME(mkpasswd, cryptpw, _BB_DIR_USR_BIN, _BB_SUID_DROP, mkpasswd)) IF_MKSWAP(APPLET(mkswap, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_MKTEMP(APPLET(mktemp, _BB_DIR_BIN, _BB_SUID_DROP)) -IF_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) -IF_MODPROBE_SMALL(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_MORE(APPLET(more, _BB_DIR_BIN, _BB_SUID_DROP)) IF_MOUNT(APPLET(mount, _BB_DIR_BIN, IF_DESKTOP(_BB_SUID_MAYBE) IF_NOT_DESKTOP(_BB_SUID_DROP))) IF_MOUNTPOINT(APPLET(mountpoint, _BB_DIR_BIN, _BB_SUID_DROP)) @@ -298,8 +290,6 @@ IF_RESTORECON(APPLET_ODDNAME(restorecon, setfiles, _BB_DIR_SBIN, _BB_SUID_DROP, IF_RFKILL(APPLET(rfkill, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_RM(APPLET_NOFORK(rm, rm, _BB_DIR_BIN, _BB_SUID_DROP, rm)) IF_RMDIR(APPLET_NOFORK(rmdir, rmdir, _BB_DIR_BIN, _BB_SUID_DROP, rmdir)) -IF_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_DROP)) -IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) IF_ROUTE(APPLET(route, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_DROP)) IF_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_DROP)) diff --git a/modutils/depmod.c b/modutils/depmod.c index 006a7bcc1..6a43aa110 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c @@ -8,6 +8,8 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//applet:IF_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_DROP)) + #include "libbb.h" #include "modutils.h" #include /* uname() */ diff --git a/modutils/insmod.c b/modutils/insmod.c index 4fe388bdc..d1f1b076b 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c @@ -7,6 +7,8 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//applet:IF_INSMOD(APPLET(insmod, _BB_DIR_SBIN, _BB_SUID_DROP)) + #include "libbb.h" #include "modutils.h" diff --git a/modutils/lsmod.c b/modutils/lsmod.c index 9558a2510..a1477ed85 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c @@ -7,6 +7,9 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ + +//applet:IF_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_DROP)) + #include "libbb.h" #include "unicode.h" diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index e0d251ee9..86470892a 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -8,6 +8,12 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ +//applet:IF_MODPROBE_SMALL(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) +//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) +//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) +//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) +//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) + #include "libbb.h" /* After libbb.h, since it needs sys/types.h on some systems */ #include /* uname() */ diff --git a/modutils/modprobe.c b/modutils/modprobe.c index ab35628f4..a5cf4babf 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -8,17 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -/* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), - * we expect the full dependency list to be specified in modules.dep. - * Older versions would only export the direct dependency list. - */ -#include "libbb.h" -#include "modutils.h" -#include -#include - -//#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) -#define DBG(...) ((void)0) +//applet:IF_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) //usage:#if !ENABLE_MODPROBE_SMALL //usage:#define modprobe_notes_usage @@ -98,6 +88,19 @@ //usage: ) //usage:#endif /* !ENABLE_MODPROBE_SMALL */ +#include "libbb.h" +#include "modutils.h" +#include +#include + +//#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) +#define DBG(...) ((void)0) + +/* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), + * we expect the full dependency list to be specified in modules.dep. + * Older versions would only export the direct dependency list. + */ + /* Note that usage text doesn't document various 2.4 options * we pull in through INSMOD_OPTS define */ diff --git a/modutils/rmmod.c b/modutils/rmmod.c index aa1bb01d6..51390eb83 100644 --- a/modutils/rmmod.c +++ b/modutils/rmmod.c @@ -8,6 +8,8 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//applet:IF_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_DROP)) + #include "libbb.h" #include "modutils.h" -- cgit v1.2.3-55-g6feb From 3d160984944a915cfac13da2b835fa29fc556321 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 15 Oct 2010 18:05:51 +0200 Subject: libbb/md5: small code shrink function old new delta md5_end 151 123 -28 Signed-off-by: Denys Vlasenko --- libbb/md5.c | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/libbb/md5.c b/libbb/md5.c index d8655ba91..9e5b496ce 100644 --- a/libbb/md5.c +++ b/libbb/md5.c @@ -56,6 +56,10 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) const uint32_t *words = buffer; #if MD5_SIZE_VS_SPEED > 0 + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64 + */ static const uint32_t C_array[] = { /* round 1 */ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, @@ -93,15 +97,13 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) 4, 11, 16, 23, 6, 10, 15, 21 }; -# endif /* MD5_SIZE_VS_SPEED > 1 */ +# endif #endif uint32_t A = ctx->A; uint32_t B = ctx->B; uint32_t C = ctx->C; uint32_t D = ctx->D; - /* Process all bytes in the buffer with 64 bytes in each round of - the loop. */ uint32_t *cwp = correct_words; uint32_t A_save = A; uint32_t B_save = B; @@ -149,7 +151,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) C = B; B = temp; } -# else +# else /* MD5_SIZE_VS_SPEED == 2 */ pc = C_array; pp = P_array; ps = S_array; @@ -193,15 +195,17 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) C = B; B = temp; } +# endif + +#else /* MD5_SIZE_VS_SPEED == 0 or 1 */ -# endif /* MD5_SIZE_VS_SPEED > 2 */ -#else /* First round: using the given function, the context and a constant - the next context is computed. Because the algorithms processing + the next context is computed. Because the algorithm's processing unit is a 32-bit word and it is determined to work on words in little endian byte order we perhaps have to change the byte order before the computation. To reduce the work for the next steps we store the swapped words in the array CORRECT_WORDS. */ +# undef OP # define OP(a, b, c, d, s, T) \ do { \ a += FF(b, c, d) + (*cwp++ = SWAP_LE32(*words)) + T; \ @@ -210,16 +214,11 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) a += b; \ } while (0) - /* Before we start, one word to the strange constants. - They are defined in RFC 1321 as - T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64 - */ - # if MD5_SIZE_VS_SPEED == 1 const uint32_t *pc; const char *pp; int i; -# endif /* MD5_SIZE_VS_SPEED */ +# endif /* Round 1. */ # if MD5_SIZE_VS_SPEED == 1 @@ -247,7 +246,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) OP(D, A, B, C, 12, 0xfd987193); OP(C, D, A, B, 17, 0xa679438e); OP(B, C, D, A, 22, 0x49b40821); -# endif /* MD5_SIZE_VS_SPEED == 1 */ +# endif /* For the second to fourth round we have the possibly swapped words in CORRECT_WORDS. Redefine the macro to take an additional first @@ -286,7 +285,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8); OP(FG, C, D, A, B, 7, 14, 0x676f02d9); OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); -# endif /* MD5_SIZE_VS_SPEED == 1 */ +# endif /* Round 3. */ # if MD5_SIZE_VS_SPEED == 1 @@ -313,7 +312,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) OP(FH, D, A, B, C, 12, 11, 0xe6db99e5); OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8); OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); -# endif /* MD5_SIZE_VS_SPEED == 1 */ +# endif /* Round 4. */ # if MD5_SIZE_VS_SPEED == 1 @@ -340,8 +339,8 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) OP(FI, D, A, B, C, 11, 10, 0xbd3af235); OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP(FI, B, C, D, A, 9, 21, 0xeb86d391); -# endif /* MD5_SIZE_VS_SPEED == 1 */ -#endif /* MD5_SIZE_VS_SPEED > 1 */ +# endif +#endif /* Add the starting values of the context. */ A += A_save; @@ -395,6 +394,7 @@ void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx) */ void FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx) { + uint64_t total; char *buf = ctx->buffer; int i; @@ -402,12 +402,16 @@ void FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx) buf[ctx->buflen++] = 0x80; memset(buf + ctx->buflen, 0, 128 - ctx->buflen); - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - ctx->total <<= 3; + /* Put the 64-bit file length, expressed in *bits*, + * at the end of the buffer. + */ + total = ctx->total << 3; if (ctx->buflen > 56) buf += 64; - for (i = 0; i < 8; i++) - buf[56 + i] = ctx->total >> (i*8); + for (i = 0; i < 8; i++) { + buf[56 + i] = total; + total >>= 8; + } /* Process last bytes. */ if (buf != ctx->buffer) -- cgit v1.2.3-55-g6feb From 70186711f45816bdf4562831af3bd995172eb47b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 16 Oct 2010 01:08:32 +0200 Subject: libbb/md5: code shrink function old new delta md5_end 123 117 -6 md5_begin 49 42 -7 md5_hash 119 104 -15 Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 - libbb/md5.c | 48 ++++++++++++++++++++++++++---------------------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 8d7beffe7..034016f4a 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1540,7 +1540,6 @@ typedef struct md5_ctx_t { uint32_t C; uint32_t D; uint64_t total; - uint32_t buflen; char buffer[128]; } md5_ctx_t; #else diff --git a/libbb/md5.c b/libbb/md5.c index 9e5b496ce..1f9d59e6e 100644 --- a/libbb/md5.c +++ b/libbb/md5.c @@ -1,7 +1,7 @@ /* vi: set sw=4 ts=4: */ /* - * md5.c - Compute MD5 checksum of strings according to the - * definition of MD5 in RFC 1321 from April 1992. + * Compute MD5 checksum of strings according to the + * definition of MD5 in RFC 1321 from April 1992. * * Written by Ulrich Drepper , 1995. * @@ -34,7 +34,6 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx) ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->total = 0; - ctx->buflen = 0; } /* These are the four functions used in the four steps of the MD5 algorithm @@ -355,35 +354,39 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) ctx->D = D; } +/* The size of filled part of ctx->buffer: */ +#define BUFLEN(ctx) (((unsigned)ctx->total) & 63) + /* Feed data through a temporary buffer to call md5_hash_aligned_block() * with chunks of data that are 4-byte aligned and a multiple of 64 bytes. * This function's internal buffer remembers previous data until it has 64 * bytes worth to pass on. Call md5_end() to flush this buffer. */ void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx) { - char *buf = (char *)buffer; + const char *buf = buffer; + unsigned buflen = BUFLEN(ctx); - /* RFC 1321 specifies the possible length of the file up to 2^64 bits, + /* RFC 1321 specifies the possible length of the file up to 2^64 bits. * Here we only track the number of bytes. */ ctx->total += len; /* Process all input. */ - while (len) { - unsigned i = 64 - ctx->buflen; - - /* Copy data into aligned buffer. */ + while (1) { + unsigned i = 64 - buflen; if (i > len) i = len; - memcpy(ctx->buffer + ctx->buflen, buf, i); + /* Copy data into aligned buffer. */ + memcpy(ctx->buffer + buflen, buf, i); len -= i; - ctx->buflen += i; buf += i; - - /* When buffer fills up, process it. */ - if (ctx->buflen == 64) { - md5_hash_block(ctx->buffer, ctx); - ctx->buflen = 0; - } + buflen += i; + /* clever way to do "if (buflen != 64) break; ... ; buflen = 0;" */ + buflen -= 64; + if (buflen != 0) + break; + /* Buffer is filled up, process it. */ + md5_hash_block(ctx->buffer, ctx); + /*buflen = 0; - already is */ } } @@ -396,18 +399,19 @@ void FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx) { uint64_t total; char *buf = ctx->buffer; - int i; + unsigned i; + unsigned buflen = BUFLEN(ctx); /* Pad data to block size. */ - buf[ctx->buflen++] = 0x80; - memset(buf + ctx->buflen, 0, 128 - ctx->buflen); + buf[buflen++] = 0x80; + memset(buf + buflen, 0, 128 - buflen); /* Put the 64-bit file length, expressed in *bits*, * at the end of the buffer. */ + /* clever way to do "if (buflen > 56) buf += 64": */ + buf += ((buflen + 7) & 64); total = ctx->total << 3; - if (ctx->buflen > 56) - buf += 64; for (i = 0; i < 8; i++) { buf[56 + i] = total; total >>= 8; -- cgit v1.2.3-55-g6feb From 1a5e11c874a1f53c5205140a9d675b7e6404bbc9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 16 Oct 2010 01:56:41 +0200 Subject: modutils/*: move help bits into corresponding .c files Signed-off-by: Denys Vlasenko --- include/usage.src.h | 20 -------------------- modutils/depmod.c | 5 +++++ modutils/insmod.c | 2 ++ modutils/lsmod.c | 7 +++++++ modutils/modprobe-small.c | 43 ++++++++++++++++++++++++++++++++++++++++++- modutils/rmmod.c | 13 +++++++++++++ 6 files changed, 69 insertions(+), 21 deletions(-) diff --git a/include/usage.src.h b/include/usage.src.h index 1bb4b563c..048e3e08f 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -751,9 +751,6 @@ INSERT #define deluser_full_usage "\n\n" \ "Delete USER from the system" -#define depmod_trivial_usage NOUSAGE_STR -#define depmod_full_usage "" - #define devmem_trivial_usage \ "ADDRESS [WIDTH [VALUE]]" @@ -2251,11 +2248,6 @@ INSERT "\n -l List long flag names" \ "\n -v List the file's version/generation number" \ -#define lsmod_trivial_usage \ - "" -#define lsmod_full_usage "\n\n" \ - "List the currently loaded kernel modules" - #define lspci_trivial_usage \ "[-mk]" #define lspci_full_usage "\n\n" \ @@ -3256,18 +3248,6 @@ INSERT #define rmdir_example_usage \ "# rmdir /tmp/foo\n" -#define rmmod_trivial_usage \ - "[-wfa] [MODULE]..." -#define rmmod_full_usage "\n\n" \ - "Unload kernel modules\n" \ - "\nOptions:" \ - "\n -w Wait until the module is no longer used" \ - "\n -f Force unload" \ - "\n -a Remove all unused modules (recursively)" \ - -#define rmmod_example_usage \ - "$ rmmod tulip\n" - #define route_trivial_usage \ "[{add|del|delete}]" #define route_full_usage "\n\n" \ diff --git a/modutils/depmod.c b/modutils/depmod.c index 6a43aa110..fec649882 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c @@ -10,6 +10,11 @@ //applet:IF_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_DROP)) +//usage:#if !ENABLE_MODPROBE_SMALL +//usage:#define depmod_trivial_usage NOUSAGE_STR +//usage:#define depmod_full_usage "" +//usage:#endif + #include "libbb.h" #include "modutils.h" #include /* uname() */ diff --git a/modutils/insmod.c b/modutils/insmod.c index d1f1b076b..7ec3cae47 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c @@ -15,6 +15,7 @@ /* 2.6 style insmod has no options and required filename * (not module name - .ko can't be omitted) */ +//usage:#if !ENABLE_MODPROBE_SMALL //usage:#define insmod_trivial_usage //usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ") //usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") @@ -33,6 +34,7 @@ //usage: ) //usage: "\n -x Don't export externs" //usage: ) +//usage:#endif int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int insmod_main(int argc UNUSED_PARAM, char **argv) diff --git a/modutils/lsmod.c b/modutils/lsmod.c index a1477ed85..ab7c11f2a 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c @@ -10,6 +10,13 @@ //applet:IF_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_DROP)) +//usage:#if !ENABLE_MODPROBE_SMALL +//usage:#define lsmod_trivial_usage +//usage: "" +//usage:#define lsmod_full_usage "\n\n" +//usage: "List the currently loaded kernel modules" +//usage:#endif + #include "libbb.h" #include "unicode.h" diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 86470892a..ec3ddfb8f 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -694,6 +694,46 @@ The following options are useful for people managing distributions: */ //usage:#if ENABLE_MODPROBE_SMALL + +//usage:#define depmod_trivial_usage NOUSAGE_STR +//usage:#define depmod_full_usage "" + +//usage:#define lsmod_trivial_usage +//usage: "" +//usage:#define lsmod_full_usage "\n\n" +//usage: "List the currently loaded kernel modules" + +//usage:#define insmod_trivial_usage +//usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ") +//usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") +//usage: "[SYMBOL=VALUE]..." +//usage:#define insmod_full_usage "\n\n" +//usage: "Load the specified kernel modules into the kernel" +//usage: IF_FEATURE_2_4_MODULES( "\n" +//usage: "\nOptions:" +//usage: "\n -f Force module to load into the wrong kernel version" +//usage: "\n -k Make module autoclean-able" +//usage: "\n -v Verbose" +//usage: "\n -q Quiet" +//usage: "\n -L Lock: prevent simultaneous loads" +//usage: IF_FEATURE_INSMOD_LOAD_MAP( +//usage: "\n -m Output load map to stdout" +//usage: ) +//usage: "\n -x Don't export externs" +//usage: ) + +//usage:#define rmmod_trivial_usage +//usage: "[-wfa] [MODULE]..." +//usage:#define rmmod_full_usage "\n\n" +//usage: "Unload kernel modules\n" +//usage: "\nOptions:" +//usage: "\n -w Wait until the module is no longer used" +//usage: "\n -f Force unload" +//usage: "\n -a Remove all unused modules (recursively)" +//usage: +//usage:#define rmmod_example_usage +//usage: "$ rmmod tulip\n" + //usage:#define modprobe_trivial_usage //usage: "[-qfwrsv] MODULE [symbol=value]..." //usage:#define modprobe_full_usage "\n\n" @@ -704,7 +744,8 @@ The following options are useful for people managing distributions: //usage: "\n -f Force" //usage: "\n -w Wait for unload" //usage: "\n -s Report via syslog instead of stderr" -//usage:#endif /* ENABLE_MODPROBE_SMALL */ + +//usage:#endif int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int modprobe_main(int argc UNUSED_PARAM, char **argv) diff --git a/modutils/rmmod.c b/modutils/rmmod.c index 51390eb83..dde77731f 100644 --- a/modutils/rmmod.c +++ b/modutils/rmmod.c @@ -10,6 +10,19 @@ //applet:IF_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_DROP)) +//usage:#if !ENABLE_MODPROBE_SMALL +//usage:#define rmmod_trivial_usage +//usage: "[-wfa] [MODULE]..." +//usage:#define rmmod_full_usage "\n\n" +//usage: "Unload kernel modules\n" +//usage: "\nOptions:" +//usage: "\n -w Wait until the module is no longer used" +//usage: "\n -f Force unload" +//usage: "\n -a Remove all unused modules (recursively)" +//usage:#define rmmod_example_usage +//usage: "$ rmmod tulip\n" +//usage:#endif + #include "libbb.h" #include "modutils.h" -- cgit v1.2.3-55-g6feb From c0683acce88efc1fe15d9a4332428b5a9fdc6c2e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 16 Oct 2010 20:45:27 +0200 Subject: *: pass md5/shaN context pointer as 1st arg, not last function old new delta md5_hash_block 458 459 +1 filter_rename_config 252 250 -2 md5_crypt 591 587 -4 Signed-off-by: Denys Vlasenko --- archival/dpkg.c | 4 ++-- coreutils/md5_sha1_sum.c | 6 +++--- include/libbb.h | 12 ++++++------ libbb/md5.c | 12 ++++++------ libbb/pw_encrypt_md5.c | 32 ++++++++++++++++---------------- libbb/sha1.c | 8 ++++---- mailutils/popmaildir.c | 6 +++--- 7 files changed, 40 insertions(+), 40 deletions(-) diff --git a/archival/dpkg.c b/archival/dpkg.c index b36c26198..07f01501b 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c @@ -1524,8 +1524,8 @@ static char FAST_FUNC filter_rename_config(archive_handle_t *archive_handle) buf = xmalloc(4096); md5_begin(&md5); while ((count = safe_read(fd, buf, 4096)) > 0) - md5_hash(buf, count, &md5); - md5_end(buf, &md5); /* using buf as result storage */ + md5_hash(&md5, buf, count); + md5_end(&md5, buf); /* using buf as result storage */ close(fd); md5line = xmalloc(16 * 2 + 2 + strlen(name_ptr) + 1); diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index 5e36d391a..e79210c0d 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c @@ -43,7 +43,7 @@ static uint8_t *hash_file(const char *filename /*, hash_algo_t hash_algo*/) } context; uint8_t *hash_value = NULL; RESERVE_CONFIG_UBUFFER(in_buf, 4096); - void FAST_FUNC (*update)(const void*, size_t, void*); + void FAST_FUNC (*update)(void*, const void*, size_t); void FAST_FUNC (*final)(void*, void*); hash_algo_t hash_algo = applet_name[3]; @@ -78,11 +78,11 @@ static uint8_t *hash_file(const char *filename /*, hash_algo_t hash_algo*/) } while (0 < (count = safe_read(src_fd, in_buf, 4096))) { - update(in_buf, count, &context); + update(&context, in_buf, count); } if (count == 0) { - final(in_buf, &context); + final(&context, in_buf); hash_value = hash_bin_to_hex(in_buf, hash_len); } diff --git a/include/libbb.h b/include/libbb.h index 034016f4a..1031cad8b 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1519,8 +1519,8 @@ typedef struct sha1_ctx_t { void (*process_block)(struct sha1_ctx_t*) FAST_FUNC; } sha1_ctx_t; void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC; -void sha1_hash(const void *data, size_t length, sha1_ctx_t *ctx) FAST_FUNC; -void sha1_end(void *resbuf, sha1_ctx_t *ctx) FAST_FUNC; +void sha1_hash(sha1_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; +void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC; typedef struct sha1_ctx_t sha256_ctx_t; void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC; #define sha256_hash sha1_hash @@ -1531,8 +1531,8 @@ typedef struct sha512_ctx_t { uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */ } sha512_ctx_t; void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC; -void sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx) FAST_FUNC; -void sha512_end(void *resbuf, sha512_ctx_t *ctx) FAST_FUNC; +void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; +void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC; #if 1 typedef struct md5_ctx_t { uint32_t A; @@ -1551,8 +1551,8 @@ typedef struct md5_ctx_t { } md5_ctx_t; #endif void md5_begin(md5_ctx_t *ctx) FAST_FUNC; -void md5_hash(const void *data, size_t length, md5_ctx_t *ctx) FAST_FUNC; -void md5_end(void *resbuf, md5_ctx_t *ctx) FAST_FUNC; +void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; +void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC; uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; diff --git a/libbb/md5.c b/libbb/md5.c index 1f9d59e6e..47f5fc6f8 100644 --- a/libbb/md5.c +++ b/libbb/md5.c @@ -49,7 +49,7 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx) #define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s)))) /* Hash a single block, 64 bytes long and 4-byte aligned. */ -static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) +static void md5_hash_block(md5_ctx_t *ctx, const void *buffer) { uint32_t correct_words[16]; const uint32_t *words = buffer; @@ -361,7 +361,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) * with chunks of data that are 4-byte aligned and a multiple of 64 bytes. * This function's internal buffer remembers previous data until it has 64 * bytes worth to pass on. Call md5_end() to flush this buffer. */ -void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx) +void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) { const char *buf = buffer; unsigned buflen = BUFLEN(ctx); @@ -385,7 +385,7 @@ void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx) if (buflen != 0) break; /* Buffer is filled up, process it. */ - md5_hash_block(ctx->buffer, ctx); + md5_hash_block(ctx, ctx->buffer); /*buflen = 0; - already is */ } } @@ -395,7 +395,7 @@ void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx) * endian byte order, so that a byte-wise output yields to the wanted * ASCII representation of the message digest. */ -void FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx) +void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) { uint64_t total; char *buf = ctx->buffer; @@ -419,8 +419,8 @@ void FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx) /* Process last bytes. */ if (buf != ctx->buffer) - md5_hash_block(ctx->buffer, ctx); - md5_hash_block(buf, ctx); + md5_hash_block(ctx, ctx->buffer); + md5_hash_block(ctx, buf); /* The MD5 result is in little endian byte order. * We (ab)use the fact that A-D are consecutive in memory. diff --git a/libbb/pw_encrypt_md5.c b/libbb/pw_encrypt_md5.c index 58964b567..889e09cab 100644 --- a/libbb/pw_encrypt_md5.c +++ b/libbb/pw_encrypt_md5.c @@ -92,10 +92,10 @@ md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned /* Hash. the password first, since that is what is most unknown */ md5_begin(&ctx); pw_len = strlen((char*)pw); - md5_hash(pw, pw_len, &ctx); + md5_hash(&ctx, pw, pw_len); /* Then the salt including "$1$" */ - md5_hash(salt, sl, &ctx); + md5_hash(&ctx, salt, sl); /* Copy salt to result; skip "$1$" */ memcpy(result, salt, sl); @@ -105,19 +105,19 @@ md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned /* Then just as many characters of the MD5(pw, salt, pw) */ md5_begin(&ctx1); - md5_hash(pw, pw_len, &ctx1); - md5_hash(salt, sl, &ctx1); - md5_hash(pw, pw_len, &ctx1); - md5_end(final, &ctx1); + md5_hash(&ctx1, pw, pw_len); + md5_hash(&ctx1, salt, sl); + md5_hash(&ctx1, pw, pw_len); + md5_end(&ctx1, final); for (pl = pw_len; pl > 0; pl -= 16) - md5_hash(final, pl > 16 ? 16 : pl, &ctx); + md5_hash(&ctx, final, pl > 16 ? 16 : pl); /* Then something really weird... */ memset(final, 0, sizeof(final)); for (i = pw_len; i; i >>= 1) { - md5_hash(((i & 1) ? final : (const unsigned char *) pw), 1, &ctx); + md5_hash(&ctx, ((i & 1) ? final : (const unsigned char *) pw), 1); } - md5_end(final, &ctx); + md5_end(&ctx, final); /* And now, just to make sure things don't run too fast. * On a 60 Mhz Pentium this takes 34 msec, so you would @@ -126,21 +126,21 @@ md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned for (i = 0; i < 1000; i++) { md5_begin(&ctx1); if (i & 1) - md5_hash(pw, pw_len, &ctx1); + md5_hash(&ctx1, pw, pw_len); else - md5_hash(final, 16, &ctx1); + md5_hash(&ctx1, final, 16); if (i % 3) - md5_hash(salt, sl, &ctx1); + md5_hash(&ctx1, salt, sl); if (i % 7) - md5_hash(pw, pw_len, &ctx1); + md5_hash(&ctx1, pw, pw_len); if (i & 1) - md5_hash(final, 16, &ctx1); + md5_hash(&ctx1, final, 16); else - md5_hash(pw, pw_len, &ctx1); - md5_end(final, &ctx1); + md5_hash(&ctx1, pw, pw_len); + md5_end(&ctx1, final); } p = result + sl + 4; /* 12 bytes max (sl is up to 8 bytes) */ diff --git a/libbb/sha1.c b/libbb/sha1.c index beeb70cf6..fac23c0ec 100644 --- a/libbb/sha1.c +++ b/libbb/sha1.c @@ -361,7 +361,7 @@ void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) /* Used also for sha256 */ -void FAST_FUNC sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx) +void FAST_FUNC sha1_hash(sha1_ctx_t *ctx, const void *buffer, size_t len) { unsigned in_buf = ctx->total64 & 63; unsigned add = 64 - in_buf; @@ -380,7 +380,7 @@ void FAST_FUNC sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx) memcpy(ctx->wbuffer + in_buf, buffer, len); } -void FAST_FUNC sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx) +void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) { unsigned in_buf = ctx->total64[0] & 127; unsigned add = 128 - in_buf; @@ -406,7 +406,7 @@ void FAST_FUNC sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx) /* Used also for sha256 */ -void FAST_FUNC sha1_end(void *resbuf, sha1_ctx_t *ctx) +void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) { unsigned pad, in_buf; @@ -442,7 +442,7 @@ void FAST_FUNC sha1_end(void *resbuf, sha1_ctx_t *ctx) memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * in_buf); } -void FAST_FUNC sha512_end(void *resbuf, sha512_ctx_t *ctx) +void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) { unsigned pad, in_buf; diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c index f37db03d5..77ec71129 100644 --- a/mailutils/popmaildir.c +++ b/mailutils/popmaildir.c @@ -109,9 +109,9 @@ int popmaildir_main(int argc UNUSED_PARAM, char **argv) s[1] = '\0'; // get md5 sum of "password" string md5_begin(&md5.ctx); - md5_hash(buf, strlen(buf), &md5.ctx); - md5_hash(G.pass, strlen(G.pass), &md5.ctx); - md5_end(res, &md5.ctx); + md5_hash(&md5.ctx, buf, strlen(buf)); + md5_hash(&md5.ctx, G.pass, strlen(G.pass)); + md5_end(&md5.ctx, res); *bin2hex(md5.hex, (char*)res, 16) = '\0'; // APOP s = xasprintf("%s %s", G.user, md5.hex); -- cgit v1.2.3-55-g6feb From bcccad35318004922cc04487e1df4eade4545966 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 16 Oct 2010 20:46:35 +0200 Subject: md5: code shrink; and use 64-byte temp buf, not 128-byte. function old new delta md5_hash 111 108 -3 md5_end 129 125 -4 md5_hash_block 459 454 -5 filter_rename_config 250 244 -6 md5_crypt 587 578 -9 popmaildir_main 828 816 -12 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/6 up/down: 0/-39) Total: -39 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- include/platform.h | 4 ++++ libbb/md5.c | 51 +++++++++++++++++++++++++-------------------------- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 1031cad8b..f406fc6f1 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1540,7 +1540,7 @@ typedef struct md5_ctx_t { uint32_t C; uint32_t D; uint64_t total; - char buffer[128]; + char buffer[64]; } md5_ctx_t; #else /* libbb/md5prime.c uses a bit different one: */ diff --git a/include/platform.h b/include/platform.h index 85efa53cd..c255a17ce 100644 --- a/include/platform.h +++ b/include/platform.h @@ -197,6 +197,8 @@ # define SWAP_LE16(x) bswap_16(x) # define SWAP_LE32(x) bswap_32(x) # define SWAP_LE64(x) bswap_64(x) +# define IF_BIG_ENDIAN(...) __VA_ARGS__ +# define IF_LITTLE_ENDIAN(...) #else # define SWAP_BE16(x) bswap_16(x) # define SWAP_BE32(x) bswap_32(x) @@ -204,6 +206,8 @@ # define SWAP_LE16(x) (x) # define SWAP_LE32(x) (x) # define SWAP_LE64(x) (x) +# define IF_BIG_ENDIAN(...) +# define IF_LITTLE_ENDIAN(...) __VA_ARGS__ #endif /* ---- Unaligned access ------------------------------------ */ diff --git a/libbb/md5.c b/libbb/md5.c index 47f5fc6f8..3c24bc60b 100644 --- a/libbb/md5.c +++ b/libbb/md5.c @@ -49,11 +49,8 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx) #define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s)))) /* Hash a single block, 64 bytes long and 4-byte aligned. */ -static void md5_hash_block(md5_ctx_t *ctx, const void *buffer) +static void md5_hash_block(md5_ctx_t *ctx) { - uint32_t correct_words[16]; - const uint32_t *words = buffer; - #if MD5_SIZE_VS_SPEED > 0 /* Before we start, one word to the strange constants. They are defined in RFC 1321 as @@ -98,12 +95,13 @@ static void md5_hash_block(md5_ctx_t *ctx, const void *buffer) }; # endif #endif + const uint32_t *words = (const void*) ctx->buffer; + uint32_t A = ctx->A; uint32_t B = ctx->B; uint32_t C = ctx->C; uint32_t D = ctx->D; - uint32_t *cwp = correct_words; uint32_t A_save = A; uint32_t B_save = B; uint32_t C_save = C; @@ -116,9 +114,10 @@ static void md5_hash_block(md5_ctx_t *ctx, const void *buffer) int i; uint32_t temp; +# if BB_BIG_ENDIAN for (i = 0; i < 16; i++) - cwp[i] = SWAP_LE32(words[i]); - words += 16; + words[i] = SWAP_LE32(words[i]); +# endif # if MD5_SIZE_VS_SPEED > 2 pc = C_array; @@ -142,7 +141,7 @@ static void md5_hash_block(md5_ctx_t *ctx, const void *buffer) case 3: temp += FI(B, C, D); } - temp += cwp[(int) (*pp++)] + *pc++; + temp += words[(int) (*pp++)] + *pc++; temp = rotl32(temp, ps[i & 3]); temp += B; A = D; @@ -156,7 +155,7 @@ static void md5_hash_block(md5_ctx_t *ctx, const void *buffer) ps = S_array; for (i = 0; i < 16; i++) { - temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++; + temp = A + FF(B, C, D) + words[(int) (*pp++)] + *pc++; temp = rotl32(temp, ps[i & 3]); temp += B; A = D; @@ -166,7 +165,7 @@ static void md5_hash_block(md5_ctx_t *ctx, const void *buffer) } ps += 4; for (i = 0; i < 16; i++) { - temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++; + temp = A + FG(B, C, D) + words[(int) (*pp++)] + *pc++; temp = rotl32(temp, ps[i & 3]); temp += B; A = D; @@ -176,7 +175,7 @@ static void md5_hash_block(md5_ctx_t *ctx, const void *buffer) } ps += 4; for (i = 0; i < 16; i++) { - temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++; + temp = A + FH(B, C, D) + words[(int) (*pp++)] + *pc++; temp = rotl32(temp, ps[i & 3]); temp += B; A = D; @@ -186,7 +185,7 @@ static void md5_hash_block(md5_ctx_t *ctx, const void *buffer) } ps += 4; for (i = 0; i < 16; i++) { - temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++; + temp = A + FI(B, C, D) + words[(int) (*pp++)] + *pc++; temp = rotl32(temp, ps[i & 3]); temp += B; A = D; @@ -203,12 +202,12 @@ static void md5_hash_block(md5_ctx_t *ctx, const void *buffer) unit is a 32-bit word and it is determined to work on words in little endian byte order we perhaps have to change the byte order before the computation. To reduce the work for the next steps - we store the swapped words in the array CORRECT_WORDS. */ + we save swapped words in WORDS array. */ # undef OP # define OP(a, b, c, d, s, T) \ do { \ - a += FF(b, c, d) + (*cwp++ = SWAP_LE32(*words)) + T; \ - ++words; \ + a += FF(b, c, d) + (*words IF_BIG_ENDIAN(= SWAP_LE32(*words))) + T; \ + words++; \ a = rotl32(a, s); \ a += b; \ } while (0) @@ -248,7 +247,7 @@ static void md5_hash_block(md5_ctx_t *ctx, const void *buffer) # endif /* For the second to fourth round we have the possibly swapped words - in CORRECT_WORDS. Redefine the macro to take an additional first + in WORDS. Redefine the macro to take an additional first argument specifying the function to use. */ # undef OP # define OP(f, a, b, c, d, k, s, T) \ @@ -385,7 +384,7 @@ void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) if (buflen != 0) break; /* Buffer is filled up, process it. */ - md5_hash_block(ctx, ctx->buffer); + md5_hash_block(ctx); /*buflen = 0; - already is */ } } @@ -398,29 +397,29 @@ void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) { uint64_t total; - char *buf = ctx->buffer; unsigned i; unsigned buflen = BUFLEN(ctx); /* Pad data to block size. */ - buf[buflen++] = 0x80; - memset(buf + buflen, 0, 128 - buflen); + ctx->buffer[buflen++] = 0x80; + memset(ctx->buffer + buflen, 0, 64 - buflen); + + if (buflen > 56) { + md5_hash_block(ctx); + memset(ctx->buffer, 0, 64); + } /* Put the 64-bit file length, expressed in *bits*, * at the end of the buffer. */ - /* clever way to do "if (buflen > 56) buf += 64": */ - buf += ((buflen + 7) & 64); total = ctx->total << 3; for (i = 0; i < 8; i++) { - buf[56 + i] = total; + ctx->buffer[56 + i] = total; total >>= 8; } /* Process last bytes. */ - if (buf != ctx->buffer) - md5_hash_block(ctx, ctx->buffer); - md5_hash_block(ctx, buf); + md5_hash_block(ctx); /* The MD5 result is in little endian byte order. * We (ab)use the fact that A-D are consecutive in memory. -- cgit v1.2.3-55-g6feb From e8ee86250d78b7a9c59699aca597f392c1593225 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 16 Oct 2010 21:26:47 +0200 Subject: testsuite: add tests for {ms5,shaN}sum Signed-off-by: Denys Vlasenko --- testsuite/gunzip.tests | 2 +- testsuite/md5sum.tests | 46 ++++++++++++++++++++++++++++++++++++++++++++++ testsuite/sha1sum.tests | 3 +++ testsuite/sha256sum.tests | 3 +++ testsuite/sha512sum.tests | 3 +++ 5 files changed, 56 insertions(+), 1 deletion(-) create mode 100755 testsuite/md5sum.tests create mode 100755 testsuite/sha1sum.tests create mode 100755 testsuite/sha256sum.tests create mode 100755 testsuite/sha512sum.tests diff --git a/testsuite/gunzip.tests b/testsuite/gunzip.tests index d7810044f..68c07555d 100755 --- a/testsuite/gunzip.tests +++ b/testsuite/gunzip.tests @@ -1,3 +1,3 @@ #!/bin/sh -. bunzip2.tests +. ./bunzip2.tests diff --git a/testsuite/md5sum.tests b/testsuite/md5sum.tests new file mode 100755 index 000000000..5bbdb3b58 --- /dev/null +++ b/testsuite/md5sum.tests @@ -0,0 +1,46 @@ +#!/bin/sh +# Used by {ms5,shaN}sum + +# We pipe texts 0...999 bytes long, {md5,shaN}sum them, +# then {md5,shaN}sum the resulting list. +# Then we compare the result with expected result. +# +# Here are the expected results: +# efe30c482e0b687e0cca0612f42ca29b +# d41337e834377140ae7f98460d71d908598ef04f +# 8e1d3ed57ebc130f0f72508446559eeae06451ae6d61b1e8ce46370cfb8963c3 +# fe413e0f177324d1353893ca0772ceba83fd41512ba63895a0eebb703ef9feac2fb4e92b2cb430b3bda41b46b0cb4ea8307190a5cc795157cfb680a9cd635d0f + +if ! test "$1"; then + set -- md5sum efe30c482e0b687e0cca0612f42ca29b +fi + +sum="$1" +expected="$2" + +mkdir testdir 2>/dev/null + +result=`( +cd testdir || { echo "cannot cd testdir!" >&2; exit 1; } + +text="The quick brown fox jumps over the lazy dog" + +n=0 +while test $n -le 999; do + yes "$text" | head -c $n | "$sum" + : $((n++)) +done | "$sum" + +)` + +rm -rf testdir + +FAILCOUNT=0 + +if test x"$result" = x"$expected -"; then + echo "PASS: $sum" + exit 0 +fi + +echo "FAIL: $sum (r:$result exp:$expected)" +exit 1 diff --git a/testsuite/sha1sum.tests b/testsuite/sha1sum.tests new file mode 100755 index 000000000..a968fa87c --- /dev/null +++ b/testsuite/sha1sum.tests @@ -0,0 +1,3 @@ +#!/bin/sh + +. ./md5sum.tests sha1sum d41337e834377140ae7f98460d71d908598ef04f diff --git a/testsuite/sha256sum.tests b/testsuite/sha256sum.tests new file mode 100755 index 000000000..d2dd78f2a --- /dev/null +++ b/testsuite/sha256sum.tests @@ -0,0 +1,3 @@ +#!/bin/sh + +. ./md5sum.tests sha256sum 8e1d3ed57ebc130f0f72508446559eeae06451ae6d61b1e8ce46370cfb8963c3 diff --git a/testsuite/sha512sum.tests b/testsuite/sha512sum.tests new file mode 100755 index 000000000..3bc7cae4f --- /dev/null +++ b/testsuite/sha512sum.tests @@ -0,0 +1,3 @@ +#!/bin/sh + +. ./md5sum.tests sha512sum fe413e0f177324d1353893ca0772ceba83fd41512ba63895a0eebb703ef9feac2fb4e92b2cb430b3bda41b46b0cb4ea8307190a5cc795157cfb680a9cd635d0f -- cgit v1.2.3-55-g6feb From 1ac476bb8561f57703b84f090ed7a575fa512823 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 16 Oct 2010 21:34:36 +0200 Subject: md5: fix "fast" md5 broken by prev commit Signed-off-by: Denys Vlasenko --- libbb/md5.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libbb/md5.c b/libbb/md5.c index 3c24bc60b..f192d0e47 100644 --- a/libbb/md5.c +++ b/libbb/md5.c @@ -245,6 +245,7 @@ static void md5_hash_block(md5_ctx_t *ctx) OP(C, D, A, B, 17, 0xa679438e); OP(B, C, D, A, 22, 0x49b40821); # endif + words -= 16; /* For the second to fourth round we have the possibly swapped words in WORDS. Redefine the macro to take an additional first @@ -252,7 +253,7 @@ static void md5_hash_block(md5_ctx_t *ctx) # undef OP # define OP(f, a, b, c, d, k, s, T) \ do { \ - a += f(b, c, d) + correct_words[k] + T; \ + a += f(b, c, d) + words[k] + T; \ a = rotl32(a, s); \ a += b; \ } while (0) -- cgit v1.2.3-55-g6feb From 273abcbf664adc92ef3bc1d9752a2b571623ad52 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 16 Oct 2010 22:43:34 +0200 Subject: shaN: small code shrink function old new delta sha512_hash 134 128 -6 sha1_hash 114 106 -8 Signed-off-by: Denys Vlasenko --- libbb/md5.c | 61 +++++++++++++++++--------- libbb/sha1.c | 115 ++++++++++++++++++++++++++++++++++++------------- testsuite/md5sum.tests | 14 ++---- 3 files changed, 129 insertions(+), 61 deletions(-) diff --git a/libbb/md5.c b/libbb/md5.c index f192d0e47..cf3825a34 100644 --- a/libbb/md5.c +++ b/libbb/md5.c @@ -354,8 +354,8 @@ static void md5_hash_block(md5_ctx_t *ctx) ctx->D = D; } -/* The size of filled part of ctx->buffer: */ -#define BUFLEN(ctx) (((unsigned)ctx->total) & 63) +/* The first unused position in ctx->buffer: */ +#define BUFPOS(ctx) (((unsigned)ctx->total) & 63) /* Feed data through a temporary buffer to call md5_hash_aligned_block() * with chunks of data that are 4-byte aligned and a multiple of 64 bytes. @@ -363,31 +363,52 @@ static void md5_hash_block(md5_ctx_t *ctx) * bytes worth to pass on. Call md5_end() to flush this buffer. */ void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) { - const char *buf = buffer; - unsigned buflen = BUFLEN(ctx); +#if 1 + /* Tiny bit smaller code */ + unsigned bufpos = BUFPOS(ctx); /* RFC 1321 specifies the possible length of the file up to 2^64 bits. * Here we only track the number of bytes. */ ctx->total += len; - /* Process all input. */ while (1) { - unsigned i = 64 - buflen; - if (i > len) - i = len; + unsigned remaining = 64 - bufpos; + if (remaining > len) + remaining = len; /* Copy data into aligned buffer. */ - memcpy(ctx->buffer + buflen, buf, i); - len -= i; - buf += i; - buflen += i; - /* clever way to do "if (buflen != 64) break; ... ; buflen = 0;" */ - buflen -= 64; - if (buflen != 0) + memcpy(ctx->buffer + bufpos, buffer, remaining); + len -= remaining; + buffer = (const char *)buffer + remaining; + bufpos += remaining; + /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */ + bufpos -= 64; + if (bufpos != 0) break; /* Buffer is filled up, process it. */ md5_hash_block(ctx); - /*buflen = 0; - already is */ + /*bufpos = 0; - already is */ } +#else + unsigned bufpos = BUFPOS(ctx); + unsigned add = 64 - bufpos; + + /* RFC 1321 specifies the possible length of the file up to 2^64 bits. + * Here we only track the number of bytes. */ + ctx->total += len; + + /* Hash whole blocks */ + while (len >= add) { + memcpy(ctx->buffer + bufpos, buffer, add); + buffer = (const char *)buffer + add; + len -= add; + add = 64; + bufpos = 0; + md5_hash_block(ctx); + } + + /* Save last, partial blosk */ + memcpy(ctx->buffer + bufpos, buffer, len); +#endif } /* Process the remaining bytes in the buffer and put result from CTX @@ -399,13 +420,13 @@ void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) { uint64_t total; unsigned i; - unsigned buflen = BUFLEN(ctx); + unsigned bufpos = BUFPOS(ctx); /* Pad data to block size. */ - ctx->buffer[buflen++] = 0x80; - memset(ctx->buffer + buflen, 0, 64 - buflen); + ctx->buffer[bufpos++] = 0x80; + memset(ctx->buffer + bufpos, 0, 64 - bufpos); - if (buflen > 56) { + if (bufpos > 56) { md5_hash_block(ctx); memset(ctx->buffer, 0, 64); } diff --git a/libbb/sha1.c b/libbb/sha1.c index fac23c0ec..8c67d07bc 100644 --- a/libbb/sha1.c +++ b/libbb/sha1.c @@ -363,62 +363,117 @@ void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) /* Used also for sha256 */ void FAST_FUNC sha1_hash(sha1_ctx_t *ctx, const void *buffer, size_t len) { - unsigned in_buf = ctx->total64 & 63; - unsigned add = 64 - in_buf; +#if 0 + unsigned bufpos = ctx->total64 & 63; + unsigned add = 64 - bufpos; ctx->total64 += len; - while (len >= add) { /* transfer whole blocks while possible */ - memcpy(ctx->wbuffer + in_buf, buffer, add); + /* Hash whole blocks */ + while (len >= add) { + memcpy(ctx->wbuffer + bufpos, buffer, add); buffer = (const char *)buffer + add; len -= add; add = 64; - in_buf = 0; + bufpos = 0; ctx->process_block(ctx); } - memcpy(ctx->wbuffer + in_buf, buffer, len); + /* Save last, partial blosk */ + memcpy(ctx->wbuffer + bufpos, buffer, len); +#else + /* Tiny bit smaller code */ + unsigned bufpos = ctx->total64 & 63; + + ctx->total64 += len; + + while (1) { + unsigned remaining = 64 - bufpos; + if (remaining > len) + remaining = len; + /* Copy data into aligned buffer */ + memcpy(ctx->wbuffer + bufpos, buffer, remaining); + len -= remaining; + buffer = (const char *)buffer + remaining; + bufpos += remaining; + /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */ + bufpos -= 64; + if (bufpos != 0) + break; + /* Buffer is filled up, process it */ + ctx->process_block(ctx); + /*bufpos = 0; - already is */ + } +#endif } void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) { - unsigned in_buf = ctx->total64[0] & 127; - unsigned add = 128 - in_buf; +#if 0 + unsigned bufpos = ctx->total64[0] & 127; + unsigned add = 128 - bufpos; - /* First increment the byte count. FIPS 180-2 specifies the possible - length of the file up to 2^128 _bits_. - We compute the number of _bytes_ and convert to bits later. */ ctx->total64[0] += len; if (ctx->total64[0] < len) ctx->total64[1]++; - while (len >= add) { /* transfer whole blocks while possible */ - memcpy(ctx->wbuffer + in_buf, buffer, add); + /* Hash whole blocks */ + while (len >= add) { + memcpy(ctx->wbuffer + bufpos, buffer, add); buffer = (const char *)buffer + add; len -= add; add = 128; - in_buf = 0; + bufpos = 0; sha512_process_block128(ctx); } - memcpy(ctx->wbuffer + in_buf, buffer, len); + /* Save last, partial blosk */ + memcpy(ctx->wbuffer + bufpos, buffer, len); +#else + unsigned bufpos = ctx->total64[0] & 127; + + /* First increment the byte count. FIPS 180-2 specifies the possible + length of the file up to 2^128 _bits_. + We compute the number of _bytes_ and convert to bits later. */ + ctx->total64[0] += len; + if (ctx->total64[0] < len) + ctx->total64[1]++; + + while (1) { + unsigned remaining = 128 - bufpos; + if (remaining > len) + remaining = len; + /* Copy data into aligned buffer. */ + memcpy(ctx->wbuffer + bufpos, buffer, remaining); + len -= remaining; + buffer = (const char *)buffer + remaining; + bufpos += remaining; + /* clever way to do "if (bufpos != 128) break; ... ; bufpos = 0;" */ + bufpos -= 128; + if (bufpos != 0) + break; + /* Buffer is filled up, process it. */ + sha512_process_block128(ctx); + /*bufpos = 0; - already is */ + } +#endif } /* Used also for sha256 */ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) { - unsigned pad, in_buf; + unsigned pad, bufpos; - in_buf = ctx->total64 & 63; + bufpos = ctx->total64 & 63; /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ - ctx->wbuffer[in_buf++] = 0x80; + ctx->wbuffer[bufpos++] = 0x80; /* This loop iterates either once or twice, no more, no less */ while (1) { - pad = 64 - in_buf; - memset(ctx->wbuffer + in_buf, 0, pad); - in_buf = 0; + pad = 64 - bufpos; + memset(ctx->wbuffer + bufpos, 0, pad); + bufpos = 0; /* Do we have enough space for the length count? */ if (pad >= 8) { /* Store the 64-bit counter of bits in the buffer in BE format */ @@ -432,30 +487,30 @@ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) break; } - in_buf = (ctx->process_block == sha1_process_block64) ? 5 : 8; + bufpos = (ctx->process_block == sha1_process_block64) ? 5 : 8; /* This way we do not impose alignment constraints on resbuf: */ if (BB_LITTLE_ENDIAN) { unsigned i; - for (i = 0; i < in_buf; ++i) + for (i = 0; i < bufpos; ++i) ctx->hash[i] = htonl(ctx->hash[i]); } - memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * in_buf); + memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * bufpos); } void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) { - unsigned pad, in_buf; + unsigned pad, bufpos; - in_buf = ctx->total64[0] & 127; + bufpos = ctx->total64[0] & 127; /* Pad the buffer to the next 128-byte boundary with 0x80,0,0,0... * (FIPS 180-2:5.1.2) */ - ctx->wbuffer[in_buf++] = 0x80; + ctx->wbuffer[bufpos++] = 0x80; while (1) { - pad = 128 - in_buf; - memset(ctx->wbuffer + in_buf, 0, pad); - in_buf = 0; + pad = 128 - bufpos; + memset(ctx->wbuffer + bufpos, 0, pad); + bufpos = 0; if (pad >= 16) { /* Store the 128-bit counter of bits in the buffer in BE format */ uint64_t t; diff --git a/testsuite/md5sum.tests b/testsuite/md5sum.tests index 5bbdb3b58..35ec67cb4 100755 --- a/testsuite/md5sum.tests +++ b/testsuite/md5sum.tests @@ -18,25 +18,17 @@ fi sum="$1" expected="$2" -mkdir testdir 2>/dev/null - -result=`( -cd testdir || { echo "cannot cd testdir!" >&2; exit 1; } - text="The quick brown fox jumps over the lazy dog" +text=`yes "$text" | head -c 9999` +result=`( n=0 while test $n -le 999; do - yes "$text" | head -c $n | "$sum" + echo "$text" | head -c $n | "$sum" : $((n++)) done | "$sum" - )` -rm -rf testdir - -FAILCOUNT=0 - if test x"$result" = x"$expected -"; then echo "PASS: $sum" exit 0 -- cgit v1.2.3-55-g6feb From 4bc3b85894920df5a3102000e1d86e1c3321fc76 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 16 Oct 2010 23:31:15 +0200 Subject: sha512: inline rotr64 function old new delta sha1_process_block64 461 446 -15 Signed-off-by: Denys Vlasenko --- libbb/sha1.c | 108 ++++++++++++++++++++++++++++------------------------------- 1 file changed, 51 insertions(+), 57 deletions(-) diff --git a/libbb/sha1.c b/libbb/sha1.c index 8c67d07bc..7e9b37d57 100644 --- a/libbb/sha1.c +++ b/libbb/sha1.c @@ -30,11 +30,29 @@ #include "libbb.h" -#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) -#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) -/* for sha512: */ -#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n)))) +/* gcc 4.2.1 optimizes rotr64 better with inline than with macro + * (for rotX32, there is no difference). Why? My guess is that + * macro requires clever common subexpression elimination heuristics + * in gcc, while inline basically forces it to happen. + */ +//#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) +static ALWAYS_INLINE uint32_t rotl32(uint32_t x, unsigned n) +{ + return (x << n) | (x >> (32 - n)); +} +//#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) +static ALWAYS_INLINE uint32_t rotr32(uint32_t x, unsigned n) +{ + return (x >> n) | (x << (32 - n)); +} +/* rotr64 in needed for sha512 only: */ +//#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n)))) +static ALWAYS_INLINE uint64_t rotr64(uint64_t x, unsigned n) +{ + return (x >> n) | (x << (64 - n)); +} #if BB_LITTLE_ENDIAN +/* ALWAYS_INLINE below would hurt code size, using plain inline: */ static inline uint64_t hton64(uint64_t v) { return (((uint64_t)htonl(v)) << 32) | htonl(v >> 32); @@ -44,14 +62,6 @@ static inline uint64_t hton64(uint64_t v) #endif #define ntoh64(v) hton64(v) -/* To check alignment gcc has an appropriate operator. Other - compilers don't. */ -#if defined(__GNUC__) && __GNUC__ >= 2 -# define UNALIGNED_P(p,type) (((uintptr_t) p) % __alignof__(type) != 0) -#else -# define UNALIGNED_P(p,type) (((uintptr_t) p) % sizeof(type) != 0) -#endif - /* Some arch headers have conflicting defines */ #undef ch @@ -65,11 +75,8 @@ static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) uint32_t W[80], a, b, c, d, e; const uint32_t *words = (uint32_t*) ctx->wbuffer; - for (t = 0; t < 16; ++t) { - W[t] = ntohl(*words); - words++; - } - + for (t = 0; t < 16; ++t) + W[t] = ntohl(words[t]); for (/*t = 16*/; t < 80; ++t) { uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; W[t] = rotl32(T, 1); @@ -190,11 +197,8 @@ static void FAST_FUNC sha256_process_block64(sha256_ctx_t *ctx) #define R1(x) (rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10)) /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */ - for (t = 0; t < 16; ++t) { - W[t] = ntohl(*words); - words++; - } - + for (t = 0; t < 16; ++t) + W[t] = ntohl(words[t]); for (/*t = 16*/; t < 64; ++t) W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16]; @@ -269,10 +273,8 @@ static void FAST_FUNC sha512_process_block128(sha512_ctx_t *ctx) #define R1(x) (rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6)) /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */ - for (t = 0; t < 16; ++t) { - W[t] = ntoh64(*words); - words++; - } + for (t = 0; t < 16; ++t) + W[t] = ntoh64(words[t]); for (/*t = 16*/; t < 80; ++t) W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16]; @@ -363,18 +365,19 @@ void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) /* Used also for sha256 */ void FAST_FUNC sha1_hash(sha1_ctx_t *ctx, const void *buffer, size_t len) { -#if 0 unsigned bufpos = ctx->total64 & 63; - unsigned add = 64 - bufpos; + unsigned remaining; ctx->total64 += len; +#if 0 + remaining = 64 - bufpos; /* Hash whole blocks */ - while (len >= add) { - memcpy(ctx->wbuffer + bufpos, buffer, add); - buffer = (const char *)buffer + add; - len -= add; - add = 64; + while (len >= remaining) { + memcpy(ctx->wbuffer + bufpos, buffer, remaining); + buffer = (const char *)buffer + remaining; + len -= remaining; + remaining = 64; bufpos = 0; ctx->process_block(ctx); } @@ -383,12 +386,8 @@ void FAST_FUNC sha1_hash(sha1_ctx_t *ctx, const void *buffer, size_t len) memcpy(ctx->wbuffer + bufpos, buffer, len); #else /* Tiny bit smaller code */ - unsigned bufpos = ctx->total64 & 63; - - ctx->total64 += len; - while (1) { - unsigned remaining = 64 - bufpos; + remaining = 64 - bufpos; if (remaining > len) remaining = len; /* Copy data into aligned buffer */ @@ -409,20 +408,24 @@ void FAST_FUNC sha1_hash(sha1_ctx_t *ctx, const void *buffer, size_t len) void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) { -#if 0 unsigned bufpos = ctx->total64[0] & 127; - unsigned add = 128 - bufpos; + unsigned remaining; + /* First increment the byte count. FIPS 180-2 specifies the possible + length of the file up to 2^128 _bits_. + We compute the number of _bytes_ and convert to bits later. */ ctx->total64[0] += len; if (ctx->total64[0] < len) ctx->total64[1]++; +#if 0 + remaining = 128 - bufpos; /* Hash whole blocks */ - while (len >= add) { - memcpy(ctx->wbuffer + bufpos, buffer, add); - buffer = (const char *)buffer + add; - len -= add; - add = 128; + while (len >= remaining) { + memcpy(ctx->wbuffer + bufpos, buffer, remaining); + buffer = (const char *)buffer + remaining; + len -= remaining; + remaining = 128; bufpos = 0; sha512_process_block128(ctx); } @@ -430,20 +433,11 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) /* Save last, partial blosk */ memcpy(ctx->wbuffer + bufpos, buffer, len); #else - unsigned bufpos = ctx->total64[0] & 127; - - /* First increment the byte count. FIPS 180-2 specifies the possible - length of the file up to 2^128 _bits_. - We compute the number of _bytes_ and convert to bits later. */ - ctx->total64[0] += len; - if (ctx->total64[0] < len) - ctx->total64[1]++; - while (1) { - unsigned remaining = 128 - bufpos; + remaining = 128 - bufpos; if (remaining > len) remaining = len; - /* Copy data into aligned buffer. */ + /* Copy data into aligned buffer */ memcpy(ctx->wbuffer + bufpos, buffer, remaining); len -= remaining; buffer = (const char *)buffer + remaining; @@ -452,7 +446,7 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) bufpos -= 128; if (bufpos != 0) break; - /* Buffer is filled up, process it. */ + /* Buffer is filled up, process it */ sha512_process_block128(ctx); /*bufpos = 0; - already is */ } -- cgit v1.2.3-55-g6feb From 446c2349b608fc4e25ac5846f4491bfa389330a6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 16 Oct 2010 23:39:43 +0200 Subject: whitespace fix Signed-off-by: Denys Vlasenko --- libbb/sha1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libbb/sha1.c b/libbb/sha1.c index 7e9b37d57..6d2f88457 100644 --- a/libbb/sha1.c +++ b/libbb/sha1.c @@ -38,18 +38,18 @@ //#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) static ALWAYS_INLINE uint32_t rotl32(uint32_t x, unsigned n) { - return (x << n) | (x >> (32 - n)); + return (x << n) | (x >> (32 - n)); } //#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) static ALWAYS_INLINE uint32_t rotr32(uint32_t x, unsigned n) { - return (x >> n) | (x << (32 - n)); + return (x >> n) | (x << (32 - n)); } /* rotr64 in needed for sha512 only: */ //#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n)))) static ALWAYS_INLINE uint64_t rotr64(uint64_t x, unsigned n) { - return (x >> n) | (x << (64 - n)); + return (x >> n) | (x << (64 - n)); } #if BB_LITTLE_ENDIAN /* ALWAYS_INLINE below would hurt code size, using plain inline: */ -- cgit v1.2.3-55-g6feb From a971a192e8af4279fb384be9ff0f0e8387b229cb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 17 Oct 2010 01:35:16 +0200 Subject: shaN: code shrink function old new delta init512_lo 32 40 +8 init256 32 40 +8 sha256_begin 42 28 -14 sha512_begin 81 53 -28 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/2 up/down: 16/-42) Total: -26 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 4 ++-- libbb/sha1.c | 15 ++++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index f406fc6f1..d05b2d48a 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1514,7 +1514,7 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags); typedef struct sha1_ctx_t { uint32_t hash[8]; /* 5, +3 elements for sha256 */ - uint64_t total64; + uint64_t total64; /* must be directly after hash[] */ uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */ void (*process_block)(struct sha1_ctx_t*) FAST_FUNC; } sha1_ctx_t; @@ -1527,7 +1527,7 @@ void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC; #define sha256_end sha1_end typedef struct sha512_ctx_t { uint64_t hash[8]; - uint64_t total64[2]; + uint64_t total64[2]; /* must be directly after hash[] */ uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */ } sha512_ctx_t; void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC; diff --git a/libbb/sha1.c b/libbb/sha1.c index 6d2f88457..70efd581b 100644 --- a/libbb/sha1.c +++ b/libbb/sha1.c @@ -329,7 +329,9 @@ static const uint32_t init256[] = { 0x510e527f, 0x9b05688c, 0x1f83d9ab, - 0x5be0cd19 + 0x5be0cd19, + 0, + 0, }; static const uint32_t init512_lo[] = { 0xf3bcc908, @@ -339,7 +341,9 @@ static const uint32_t init512_lo[] = { 0xade682d1, 0x2b3e6c1f, 0xfb41bd6b, - 0x137e2179 + 0x137e2179, + 0, + 0, }; /* Initialize structure containing state of computation. @@ -347,7 +351,7 @@ static const uint32_t init512_lo[] = { void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) { memcpy(ctx->hash, init256, sizeof(init256)); - ctx->total64 = 0; + /*ctx->total64 = 0; - done by extending init256 with two 32-bit zeros */ ctx->process_block = sha256_process_block64; } @@ -356,9 +360,10 @@ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) { int i; - for (i = 0; i < 8; i++) + /* Two extra iterations zero out ctx->total64[] */ + for (i = 0; i < 8+2; i++) ctx->hash[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i]; - ctx->total64[0] = ctx->total64[1] = 0; + /*ctx->total64[0] = ctx->total64[1] = 0; - already done */ } -- cgit v1.2.3-55-g6feb From 36ab585f68295487a0973bde86bcb0ab7577a8ff Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 17 Oct 2010 03:00:36 +0200 Subject: md5: code shrink function old new delta md5_end 125 104 -21 Signed-off-by: Denys Vlasenko --- libbb/md5.c | 37 ++++++++++++++++++------------------- libbb/sha1.c | 18 +++++++----------- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/libbb/md5.c b/libbb/md5.c index cf3825a34..a1f0a923f 100644 --- a/libbb/md5.c +++ b/libbb/md5.c @@ -418,31 +418,30 @@ void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) */ void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) { - uint64_t total; - unsigned i; unsigned bufpos = BUFPOS(ctx); - - /* Pad data to block size. */ + /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ ctx->buffer[bufpos++] = 0x80; - memset(ctx->buffer + bufpos, 0, 64 - bufpos); - if (bufpos > 56) { + /* This loop iterates either once or twice, no more, no less */ + while (1) { + unsigned remaining = 64 - bufpos; + memset(ctx->buffer + bufpos, 0, remaining); + /* Do we have enough space for the length count? */ + if (remaining >= 8) { + /* Store the 64-bit counter of bits in the buffer in BE format */ + uint64_t t = ctx->total << 3; + unsigned i; + for (i = 0; i < 8; i++) { + ctx->buffer[56 + i] = t; + t >>= 8; + } + } md5_hash_block(ctx); - memset(ctx->buffer, 0, 64); - } - - /* Put the 64-bit file length, expressed in *bits*, - * at the end of the buffer. - */ - total = ctx->total << 3; - for (i = 0; i < 8; i++) { - ctx->buffer[56 + i] = total; - total >>= 8; + if (remaining >= 8) + break; + bufpos = 0; } - /* Process last bytes. */ - md5_hash_block(ctx); - /* The MD5 result is in little endian byte order. * We (ab)use the fact that A-D are consecutive in memory. */ diff --git a/libbb/sha1.c b/libbb/sha1.c index 70efd581b..3e61aff6d 100644 --- a/libbb/sha1.c +++ b/libbb/sha1.c @@ -462,17 +462,15 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) /* Used also for sha256 */ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) { - unsigned pad, bufpos; + unsigned bufpos = ctx->total64 & 63; - bufpos = ctx->total64 & 63; /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ ctx->wbuffer[bufpos++] = 0x80; /* This loop iterates either once or twice, no more, no less */ while (1) { - pad = 64 - bufpos; + unsigned pad = 64 - bufpos; memset(ctx->wbuffer + bufpos, 0, pad); - bufpos = 0; /* Do we have enough space for the length count? */ if (pad >= 8) { /* Store the 64-bit counter of bits in the buffer in BE format */ @@ -484,6 +482,7 @@ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) ctx->process_block(ctx); if (pad >= 8) break; + bufpos = 0; } bufpos = (ctx->process_block == sha1_process_block64) ? 5 : 8; @@ -498,18 +497,14 @@ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) { - unsigned pad, bufpos; + unsigned bufpos = ctx->total64[0] & 127; - bufpos = ctx->total64[0] & 127; - /* Pad the buffer to the next 128-byte boundary with 0x80,0,0,0... - * (FIPS 180-2:5.1.2) - */ + /* Pad the buffer to the next 128-byte boundary with 0x80,0,0,0... */ ctx->wbuffer[bufpos++] = 0x80; while (1) { - pad = 128 - bufpos; + unsigned pad = 128 - bufpos; memset(ctx->wbuffer + bufpos, 0, pad); - bufpos = 0; if (pad >= 16) { /* Store the 128-bit counter of bits in the buffer in BE format */ uint64_t t; @@ -523,6 +518,7 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) sha512_process_block128(ctx); if (pad >= 16) break; + bufpos = 0; } if (BB_LITTLE_ENDIAN) { -- cgit v1.2.3-55-g6feb From f6dacc23ff495cbdd3f1baf5985ded21a7e4a9c9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 17 Oct 2010 03:21:51 +0200 Subject: bring md5 and sha1 names closer. no code changes Signed-off-by: Denys Vlasenko --- include/libbb.h | 4 +-- libbb/md5.c | 76 ++++++++++++++++++++++++++------------------------------- libbb/sha1.c | 16 ++++++------ 3 files changed, 44 insertions(+), 52 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index d05b2d48a..dec4e3af5 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1539,8 +1539,8 @@ typedef struct md5_ctx_t { uint32_t B; uint32_t C; uint32_t D; - uint64_t total; - char buffer[64]; + uint64_t total64; + char wbuffer[64]; } md5_ctx_t; #else /* libbb/md5prime.c uses a bit different one: */ diff --git a/libbb/md5.c b/libbb/md5.c index a1f0a923f..f5d083e3f 100644 --- a/libbb/md5.c +++ b/libbb/md5.c @@ -33,7 +33,7 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx) ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; - ctx->total = 0; + ctx->total64 = 0; } /* These are the four functions used in the four steps of the MD5 algorithm @@ -48,8 +48,8 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx) #define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s)))) -/* Hash a single block, 64 bytes long and 4-byte aligned. */ -static void md5_hash_block(md5_ctx_t *ctx) +/* Hash a single block, 64 bytes long and 4-byte aligned */ +static void md5_process_block64(md5_ctx_t *ctx) { #if MD5_SIZE_VS_SPEED > 0 /* Before we start, one word to the strange constants. @@ -95,7 +95,7 @@ static void md5_hash_block(md5_ctx_t *ctx) }; # endif #endif - const uint32_t *words = (const void*) ctx->buffer; + const uint32_t *words = (const void*) ctx->wbuffer; uint32_t A = ctx->A; uint32_t B = ctx->B; @@ -354,29 +354,41 @@ static void md5_hash_block(md5_ctx_t *ctx) ctx->D = D; } -/* The first unused position in ctx->buffer: */ -#define BUFPOS(ctx) (((unsigned)ctx->total) & 63) - /* Feed data through a temporary buffer to call md5_hash_aligned_block() * with chunks of data that are 4-byte aligned and a multiple of 64 bytes. * This function's internal buffer remembers previous data until it has 64 * bytes worth to pass on. Call md5_end() to flush this buffer. */ void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) { -#if 1 - /* Tiny bit smaller code */ - unsigned bufpos = BUFPOS(ctx); + unsigned bufpos = ctx->total64 & 63; + unsigned remaining; /* RFC 1321 specifies the possible length of the file up to 2^64 bits. * Here we only track the number of bytes. */ - ctx->total += len; + ctx->total64 += len; +#if 0 + remaining = 64 - bufpos; + /* Hash whole blocks */ + while (len >= remaining) { + memcpy(ctx->wbuffer + bufpos, buffer, remaining); + buffer = (const char *)buffer + remaining; + len -= remaining; + remaining = 64; + bufpos = 0; + md5_process_block64(ctx); + } + + /* Save last, partial blosk */ + memcpy(ctx->wbuffer + bufpos, buffer, len); +#else + /* Tiny bit smaller code */ while (1) { - unsigned remaining = 64 - bufpos; + remaining = 64 - bufpos; if (remaining > len) remaining = len; - /* Copy data into aligned buffer. */ - memcpy(ctx->buffer + bufpos, buffer, remaining); + /* Copy data into aligned buffer */ + memcpy(ctx->wbuffer + bufpos, buffer, remaining); len -= remaining; buffer = (const char *)buffer + remaining; bufpos += remaining; @@ -384,30 +396,10 @@ void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) bufpos -= 64; if (bufpos != 0) break; - /* Buffer is filled up, process it. */ - md5_hash_block(ctx); + /* Buffer is filled up, process it */ + md5_process_block64(ctx); /*bufpos = 0; - already is */ } -#else - unsigned bufpos = BUFPOS(ctx); - unsigned add = 64 - bufpos; - - /* RFC 1321 specifies the possible length of the file up to 2^64 bits. - * Here we only track the number of bytes. */ - ctx->total += len; - - /* Hash whole blocks */ - while (len >= add) { - memcpy(ctx->buffer + bufpos, buffer, add); - buffer = (const char *)buffer + add; - len -= add; - add = 64; - bufpos = 0; - md5_hash_block(ctx); - } - - /* Save last, partial blosk */ - memcpy(ctx->buffer + bufpos, buffer, len); #endif } @@ -418,25 +410,25 @@ void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) */ void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) { - unsigned bufpos = BUFPOS(ctx); + unsigned bufpos = ctx->total64 & 63; /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ - ctx->buffer[bufpos++] = 0x80; + ctx->wbuffer[bufpos++] = 0x80; /* This loop iterates either once or twice, no more, no less */ while (1) { unsigned remaining = 64 - bufpos; - memset(ctx->buffer + bufpos, 0, remaining); + memset(ctx->wbuffer + bufpos, 0, remaining); /* Do we have enough space for the length count? */ if (remaining >= 8) { /* Store the 64-bit counter of bits in the buffer in BE format */ - uint64_t t = ctx->total << 3; + uint64_t t = ctx->total64 << 3; unsigned i; for (i = 0; i < 8; i++) { - ctx->buffer[56 + i] = t; + ctx->wbuffer[56 + i] = t; t >>= 8; } } - md5_hash_block(ctx); + md5_process_block64(ctx); if (remaining >= 8) break; bufpos = 0; diff --git a/libbb/sha1.c b/libbb/sha1.c index 3e61aff6d..d79291148 100644 --- a/libbb/sha1.c +++ b/libbb/sha1.c @@ -469,10 +469,10 @@ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) /* This loop iterates either once or twice, no more, no less */ while (1) { - unsigned pad = 64 - bufpos; - memset(ctx->wbuffer + bufpos, 0, pad); + unsigned remaining = 64 - bufpos; + memset(ctx->wbuffer + bufpos, 0, remaining); /* Do we have enough space for the length count? */ - if (pad >= 8) { + if (remaining >= 8) { /* Store the 64-bit counter of bits in the buffer in BE format */ uint64_t t = ctx->total64 << 3; t = hton64(t); @@ -480,7 +480,7 @@ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; } ctx->process_block(ctx); - if (pad >= 8) + if (remaining >= 8) break; bufpos = 0; } @@ -503,9 +503,9 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) ctx->wbuffer[bufpos++] = 0x80; while (1) { - unsigned pad = 128 - bufpos; - memset(ctx->wbuffer + bufpos, 0, pad); - if (pad >= 16) { + unsigned remaining = 128 - bufpos; + memset(ctx->wbuffer + bufpos, 0, remaining); + if (remaining >= 16) { /* Store the 128-bit counter of bits in the buffer in BE format */ uint64_t t; t = ctx->total64[0] << 3; @@ -516,7 +516,7 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t; } sha512_process_block128(ctx); - if (pad >= 16) + if (remaining >= 16) break; bufpos = 0; } -- cgit v1.2.3-55-g6feb From cfe114c4f3d4e1dfc00196d8df316874eaf2d2b8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 17 Oct 2010 11:38:44 +0200 Subject: md5: code shrink -5 bytes Signed-off-by: Denys Vlasenko --- libbb/md5.c | 75 +++++++++++++++++++++++++++++-------------------------------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/libbb/md5.c b/libbb/md5.c index f5d083e3f..6001a9c8e 100644 --- a/libbb/md5.c +++ b/libbb/md5.c @@ -64,7 +64,7 @@ static void md5_process_block64(md5_ctx_t *ctx) 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, /* round 2 */ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, - 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, /* round 3 */ @@ -86,28 +86,21 @@ static void md5_process_block64(md5_ctx_t *ctx) 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ }; -# if MD5_SIZE_VS_SPEED > 1 - static const char S_array[] ALIGN1 = { - 7, 12, 17, 22, - 5, 9, 14, 20, - 4, 11, 16, 23, - 6, 10, 15, 21 - }; -# endif #endif const uint32_t *words = (const void*) ctx->wbuffer; - uint32_t A = ctx->A; uint32_t B = ctx->B; uint32_t C = ctx->C; uint32_t D = ctx->D; - uint32_t A_save = A; - uint32_t B_save = B; - uint32_t C_save = C; - uint32_t D_save = D; +#if MD5_SIZE_VS_SPEED >= 2 /* 2 or 3 */ -#if MD5_SIZE_VS_SPEED > 1 + static const char S_array[] ALIGN1 = { + 7, 12, 17, 22, + 5, 9, 14, 20, + 4, 11, 16, 23, + 6, 10, 15, 21 + }; const uint32_t *pc; const char *pp; const char *ps; @@ -119,7 +112,7 @@ static void md5_process_block64(md5_ctx_t *ctx) words[i] = SWAP_LE32(words[i]); # endif -# if MD5_SIZE_VS_SPEED > 2 +# if MD5_SIZE_VS_SPEED == 3 pc = C_array; pp = P_array; ps = S_array - 4; @@ -149,7 +142,7 @@ static void md5_process_block64(md5_ctx_t *ctx) C = B; B = temp; } -# else /* MD5_SIZE_VS_SPEED == 2 */ +# else /* MD5_SIZE_VS_SPEED == 2 */ pc = C_array; pp = P_array; ps = S_array; @@ -194,8 +187,23 @@ static void md5_process_block64(md5_ctx_t *ctx) B = temp; } # endif + /* Add checksum to the starting values */ + ctx->A += A; + ctx->B += B; + ctx->C += C; + ctx->D += D; -#else /* MD5_SIZE_VS_SPEED == 0 or 1 */ +#else /* MD5_SIZE_VS_SPEED == 0 or 1 */ + + uint32_t A_save = A; + uint32_t B_save = B; + uint32_t C_save = C; + uint32_t D_save = D; +# if MD5_SIZE_VS_SPEED == 1 + const uint32_t *pc; + const char *pp; + int i; +# endif /* First round: using the given function, the context and a constant the next context is computed. Because the algorithm's processing @@ -212,13 +220,7 @@ static void md5_process_block64(md5_ctx_t *ctx) a += b; \ } while (0) -# if MD5_SIZE_VS_SPEED == 1 - const uint32_t *pc; - const char *pp; - int i; -# endif - - /* Round 1. */ + /* Round 1 */ # if MD5_SIZE_VS_SPEED == 1 pc = C_array; for (i = 0; i < 4; i++) { @@ -258,7 +260,7 @@ static void md5_process_block64(md5_ctx_t *ctx) a += b; \ } while (0) - /* Round 2. */ + /* Round 2 */ # if MD5_SIZE_VS_SPEED == 1 pp = P_array; for (i = 0; i < 4; i++) { @@ -286,7 +288,7 @@ static void md5_process_block64(md5_ctx_t *ctx) OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); # endif - /* Round 3. */ + /* Round 3 */ # if MD5_SIZE_VS_SPEED == 1 for (i = 0; i < 4; i++) { OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++); @@ -313,7 +315,7 @@ static void md5_process_block64(md5_ctx_t *ctx) OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); # endif - /* Round 4. */ + /* Round 4 */ # if MD5_SIZE_VS_SPEED == 1 for (i = 0; i < 4; i++) { OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++); @@ -339,19 +341,12 @@ static void md5_process_block64(md5_ctx_t *ctx) OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP(FI, B, C, D, A, 9, 21, 0xeb86d391); # endif + /* Add checksum to the starting values */ + ctx->A = A_save + A; + ctx->B = B_save + B; + ctx->C = C_save + C; + ctx->D = D_save + D; #endif - - /* Add the starting values of the context. */ - A += A_save; - B += B_save; - C += C_save; - D += D_save; - - /* Put checksum in context given as argument. */ - ctx->A = A; - ctx->B = B; - ctx->C = C; - ctx->D = D; } /* Feed data through a temporary buffer to call md5_hash_aligned_block() -- cgit v1.2.3-55-g6feb From ad8def2d8ad980a5b759c32a220828ea1248e5b6 Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Sun, 17 Oct 2010 12:27:50 +0200 Subject: udhcpc: fix OPTION_IP_PAIR parsing http://git.busybox.net/busybox/commit/?id=7d3a48a003cd645edfae2b404493688022 revealed incorrect OPTION_IP_PAIR implementation, which doesn't respect option length and causes erroneous classful routes, composed from garbage or first bytes from the next DHCP packet option. Signed-off-by: Vladislav Grishenko Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index de1b79844..27d6ad1a8 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -89,6 +89,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ /* option points to OPT_DATA, need to go back and get OPT_LEN */ len = option[OPT_LEN - OPT_DATA]; + type = optflag->flags & OPTION_TYPE_MASK; optlen = dhcp_option_lengths[type]; upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen); @@ -97,17 +98,16 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ dest += sprintf(ret, "%s=", opt_name); while (len >= optlen) { + unsigned ip_ofs = 0; + switch (type) { case OPTION_IP_PAIR: dest += sprint_nip(dest, "", option); *dest++ = '/'; - option += 4; - optlen = 4; + ip_ofs = 4; + /* fall through */ case OPTION_IP: - dest += sprint_nip(dest, "", option); -// TODO: it can be a list only if (optflag->flags & OPTION_LIST). -// Should we bail out/warn if we see multi-ip option which is -// not allowed to be such? For example, DHCP_BROADCAST... + dest += sprint_nip(dest, "", option + ip_ofs); break; // case OPTION_BOOLEAN: // dest += sprintf(dest, *option ? "yes" : "no"); @@ -218,7 +218,10 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ } /* switch */ option += optlen; len -= optlen; - if (len <= 0) +// TODO: it can be a list only if (optflag->flags & OPTION_LIST). +// Should we bail out/warn if we see multi-ip option which is +// not allowed to be such (for example, DHCP_BROADCAST)? - + if (len <= 0 /* || !(optflag->flags & OPTION_LIST) */) break; *dest++ = ' '; *dest = '\0'; -- cgit v1.2.3-55-g6feb From 786635e62e4c8a8646d01ede1c7bb98ce604c7fa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 17 Oct 2010 12:44:39 +0200 Subject: seq: exit on write errors Signed-off-by: Denys Vlasenko --- coreutils/seq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/coreutils/seq.c b/coreutils/seq.c index 8be25360f..22bf3ec9d 100644 --- a/coreutils/seq.c +++ b/coreutils/seq.c @@ -86,7 +86,8 @@ int seq_main(int argc, char **argv) v = first; n = 0; while (increment >= 0 ? v <= last : v >= last) { - printf("%s%0*.*f", sep, width, frac_part, v); + if (printf("%s%0*.*f", sep, width, frac_part, v) < 0) + break; /* I/O error, bail out (yes, this really happens) */ sep = opt_s; /* v += increment; - would accumulate floating point errors */ n++; -- cgit v1.2.3-55-g6feb From ea694163af05fd9cf71af52d5d8d64af81577b14 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 17 Oct 2010 12:45:24 +0200 Subject: typo fix Signed-off-by: Denys Vlasenko --- coreutils/tee.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/tee.c b/coreutils/tee.c index 2e1e367f2..e66e885ec 100644 --- a/coreutils/tee.c +++ b/coreutils/tee.c @@ -42,7 +42,7 @@ int tee_main(int argc, char **argv) * that doesn't consume all its input. Good idea... */ signal(SIGPIPE, SIG_IGN); - /* Allocate an array of FILE *'s, with one extra for a sentinal. */ + /* Allocate an array of FILE *'s, with one extra for a sentinel. */ fp = files = xzalloc(sizeof(FILE *) * (argc + 2)); np = names = argv - 1; -- cgit v1.2.3-55-g6feb From 20e2c35b7cc77c5dc5696c9592a7d6f982036ac5 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Sun, 10 Oct 2010 13:09:31 -0700 Subject: docs: Change CVS references to Git Signed-off-by: Kevin Cernekee Signed-off-by: Denys Vlasenko --- docs/contributing.txt | 53 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/docs/contributing.txt b/docs/contributing.txt index 39aaef1b5..e3289fd49 100644 --- a/docs/contributing.txt +++ b/docs/contributing.txt @@ -229,8 +229,11 @@ Here are some guidelines on how to submit a patch to Busybox. Making A Patch ~~~~~~~~~~~~~~ -If you've got anonymous CVS access set up, making a patch is simple. Just make -sure you're in the busybox/ directory and type 'cvs diff -bwu > mychanges.patch'. +If you've got anonymous Git access set up, making a patch is simple. Just make +sure you're in the busybox/ directory and type: + + git diff -b -w > mychanges.patch + You can send the resulting .patch file to the mailing list with a description of what it does. (But not before you test it! See the next section for some guidelines.) It is preferred that patches be sent as attachments, but it is @@ -238,8 +241,12 @@ not required. Also, feel free to help test other people's patches and reply to them with comments. You can apply a patch by saving it into your busybox/ directory and -typing 'patch < mychanges.patch'. Then you can recompile, see if it runs, test -if it works as advertised, and post your findings to the mailing list. +typing: + + patch -p1 < mychanges.patch + +Then you can recompile, see if it runs, test if it works as advertised, and +post your findings to the mailing list. NOTE: Please do not include extraneous or irrelevant changes in your patches. Please do not try to "bundle" two patches together into one. Make single, @@ -252,7 +259,7 @@ Testing Guidelines ~~~~~~~~~~~~~~~~~~ It's considered good form to test your new feature before you submit a patch -to the mailing list, and especially before you commit a change to CVS. Here +to the mailing list, and especially before you push a change to Git. Here are some guidelines on how to test your changes. - Always test Busybox applets against GNU counterparts and make sure the @@ -348,7 +355,7 @@ responses from queries to applet maintainer or positive responses from folks on the mailing list. We've made strident efforts to put a useful "collaboration" infrastructure in -place in the form of mailing lists, the bug tracking system, and CVS. Please +place in the form of mailing lists, the bug tracking system, and Git. Please use these resources. @@ -373,39 +380,43 @@ opposite effect. -Committing Changes to CVS -------------------------- +Pushing Changes to Git +---------------------- If you submit several patches that demonstrate that you are a skilled and wise -coder, you may be invited to become a committer, thus enabling you to commit -changes directly to CVS. This is nice because you don't have to wait for -someone else to commit your change for you, you can just do it yourself. +coder, you may be invited to become a committer, thus enabling you to push +changes directly to Git. This is nice because you don't have to wait for +someone else to push your change for you, you can just do it yourself. But note that this is a privilege that comes with some responsibilities. You -should test your changes before you commit them. You should also talk to an +should test your changes before you push them. You should also talk to an applet maintainer before you make any kind of sweeping changes to somebody else's code. Big changes should still go to the mailing list first. Remember, being wise, polite, and discreet is more important than being clever. +For more information on Git push access, see: -When To Commit -~~~~~~~~~~~~~~ + http://busybox.net/developer.html -Generally, you should feel free to commit a change if: + +When To Push +~~~~~~~~~~~~ + +Generally, you should feel free to push a change if: - Your changes are small and don't touch many files - You are fixing a bug - Somebody has told you that it's okay - It's obviously the Right Thing -The more of the above are true, the better it is to just commit a change -directly to CVS. +The more of the above are true, the better it is to just push a change +directly to Git. -When Not To Commit -~~~~~~~~~~~~~~~~~~ +When Not To Push +~~~~~~~~~~~~~~~~ -Even if you have commit rights, you should probably still post a patch to the +Even if you have push access, you should probably still post a patch to the mailing list if: - Your changes are broad and touch many different files @@ -414,7 +425,7 @@ mailing list if: - You are not the maintainer and your changes make the maintainer cringe The more of the above are true, the better it is to post a patch to the -mailing list instead of committing. +mailing list instead of pushing. -- cgit v1.2.3-55-g6feb From 2b0116803bd123d4e2486a221649fd6540a60c99 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Sun, 10 Oct 2010 13:15:57 -0700 Subject: docs: Sync up AUTHORS and busybox_footer.pod Signed-off-by: Kevin Cernekee Signed-off-by: Denys Vlasenko --- docs/busybox_footer.pod | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/busybox_footer.pod b/docs/busybox_footer.pod index 47eabaeeb..c346c736b 100644 --- a/docs/busybox_footer.pod +++ b/docs/busybox_footer.pod @@ -252,4 +252,34 @@ Tito Ragusa devfsd and size optimizations in strings, openvt and deallocvt. +=for html
+ +Paul Fox + + vi editing mode for ash, various other patches/fixes + +=for html
+ +Roberto A. Foglietta + + port: dnsd + +=for html
+ +Bernhard Reutner-Fischer + + misc + +=for html
+ +Mike Frysinger + + initial e2fsprogs, printenv, setarch, sum, misc + +=for html
+ +Jie Zhang + + fixed two bugs in msh and hush (exitcode of killed processes) + =cut -- cgit v1.2.3-55-g6feb From b8d02597e3dcea16b6aeda2d1aae11ca3812932a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 17 Oct 2010 23:01:32 +0200 Subject: md5: fix biuld failure on big-endian machines Signed-off-by: Denys Vlasenko --- libbb/md5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbb/md5.c b/libbb/md5.c index 6001a9c8e..051c8ede4 100644 --- a/libbb/md5.c +++ b/libbb/md5.c @@ -87,7 +87,7 @@ static void md5_process_block64(md5_ctx_t *ctx) 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ }; #endif - const uint32_t *words = (const void*) ctx->wbuffer; + uint32_t *words = (void*) ctx->wbuffer; uint32_t A = ctx->A; uint32_t B = ctx->B; uint32_t C = ctx->C; -- cgit v1.2.3-55-g6feb From 122a4b30f48d4e643148683ddd0ce74186259ca6 Mon Sep 17 00:00:00 2001 From: Pascal Bellard Date: Mon, 18 Oct 2010 00:43:07 +0200 Subject: touch: update help text Signed-off-by: Pascal Bellard Signed-off-by: Denys Vlasenko --- include/usage.src.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/usage.src.h b/include/usage.src.h index 048e3e08f..5d7767bb4 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -4116,12 +4116,13 @@ INSERT //TODO: add options and keyboard commands #define touch_trivial_usage \ - "[-c] [-d DATE] FILE [FILE]..." + "[-c] [-d DATE] [-r FILE] FILE [FILE]..." #define touch_full_usage "\n\n" \ "Update the last-modified date on the given FILE[s]\n" \ "\nOptions:" \ "\n -c Don't create files" \ "\n -d DT Date/time to use" \ + "\n -r FILE Use FILE's date/time" \ #define touch_example_usage \ "$ ls -l /tmp/foo\n" \ -- cgit v1.2.3-55-g6feb From cadf90184c2c74e2c37161efe55cd05fb04e0c59 Mon Sep 17 00:00:00 2001 From: Pascal Bellard Date: Mon, 18 Oct 2010 00:51:16 +0200 Subject: depmod: accept and ignore -u, -q, -C FILE Signed-off-by: Pascal Bellard Signed-off-by: Denys Vlasenko --- modutils/depmod.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modutils/depmod.c b/modutils/depmod.c index fec649882..85b64a229 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c @@ -151,6 +151,8 @@ static void xfreopen_write(const char *file, FILE *f) * Print to stdout all the symbols each module depends on * and the module's file name which provides that symbol. * -r No-op + * -u No-op + * -q No-op * * So far we only support: [-rn] [-b BASE] [VERSION] [MODFILES]... * -aAeF are accepted but ignored. -vC are not accepted. @@ -162,7 +164,10 @@ enum { //OPT_e = (1 << 3), /* with -F, print unresolved symbols */ //OPT_F = (1 << 4), /* System.map that contains the symbols */ OPT_n = (1 << 5), /* dry-run, print to stdout only */ - OPT_r = (1 << 6) /* Compat dummy. Linux Makefile uses it */ + OPT_r = (1 << 6), /* Compat dummy. Linux Makefile uses it */ + OPT_u = (1 << 7), /* -u,--unresolved-error: ignored */ + OPT_q = (1 << 8), /* -q,--quiet: ignored */ + OPT_C = (1 << 9), /* -C,--config etc_modules_conf: ignored */ }; int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -174,7 +179,7 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) struct utsname uts; int tmp; - getopt32(argv, "aAb:eF:nr", &moddir_base, NULL); + getopt32(argv, "aAb:eF:nruqC:", &moddir_base, NULL, NULL); argv += optind; /* goto modules location */ -- cgit v1.2.3-55-g6feb From 873bb31d1703aae080d1928b5928c0011a944485 Mon Sep 17 00:00:00 2001 From: Pascal Bellard Date: Mon, 18 Oct 2010 00:54:51 +0200 Subject: cpio: avoid 'not created: newer or same age file exists' message for dirs Signed-off-by: Pascal Bellard Signed-off-by: Denys Vlasenko --- archival/libunarchive/data_extract_all.c | 4 +++- testsuite/cpio.tests | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/archival/libunarchive/data_extract_all.c b/archival/libunarchive/data_extract_all.c index cc549cd78..5fb1ab2ae 100644 --- a/archival/libunarchive/data_extract_all.c +++ b/archival/libunarchive/data_extract_all.c @@ -69,7 +69,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) } } else if (existing_sb.st_mtime >= file_header->mtime) { - if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { + if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) + && !S_ISDIR(file_header->mode) + ) { bb_error_msg("%s not created: newer or " "same age file exists", file_header->name); } diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index 05b92dbe4..4cd441a60 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests @@ -116,6 +116,16 @@ link " "" "" SKIP= +# avoid 'not created: newer or same age file exists' message for directories +rm -rf cpio.testdir cpio.testdir2 2>/dev/null +mkdir cpio.testdir +testing "cpio extracts in existing directory" \ +"$ECHO -ne '$hexdump' | bzcat | cpio -id 2>&1; echo \$?" \ +"\ +1 blocks +0 +" "" "" +SKIP= # Clean up rm -rf cpio.testdir cpio.testdir2 2>/dev/null -- cgit v1.2.3-55-g6feb From 36af2f7977edc818af8c01392ef700439a9fe163 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 18 Oct 2010 02:36:34 +0200 Subject: nanddump: new applet function old new delta nandwrite_main 418 936 +518 dump_bad - 119 +119 packed_usage 27752 27810 +58 next_good_eraseblock 84 106 +22 applet_names 2366 2375 +9 applet_main 1380 1384 +4 applet_nameofs 690 692 +2 bbconfig_config_bz2 4932 4922 -10 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 6/1 up/down: 732/-10) Total: 722 bytes Signed-off-by: Baruch Siach Signed-off-by: Denys Vlasenko --- miscutils/nandwrite.c | 155 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 127 insertions(+), 28 deletions(-) diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c index f42242687..6c85ea346 100644 --- a/miscutils/nandwrite.c +++ b/miscutils/nandwrite.c @@ -1,5 +1,5 @@ /* - * nandwrite.c - ported to busybox from mtd-utils + * nandwrite and nanddump ported to busybox from mtd-utils * * Author: Baruch Siach , Orex Computed Radiography * @@ -9,8 +9,10 @@ */ //applet:IF_NANDWRITE(APPLET(nandwrite, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) +//applet:IF_NANDWRITE(APPLET_ODDNAME(nanddump, nandwrite, _BB_DIR_USR_SBIN, _BB_SUID_DROP, nanddump)) //kbuild:lib-$(CONFIG_NANDWRITE) += nandwrite.o +//kbuild:lib-$(CONFIG_NANDDUMP) += nandwrite.o //config:config NANDWRITE //config: bool "nandwrite" @@ -18,9 +20,13 @@ //config: depends on PLATFORM_LINUX //config: help //config: Write to the specified MTD device, with bad blocks awareness - -#include "libbb.h" -#include +//config: +//config:config NANDDUMP +//config: bool "nanddump" +//config: default n +//config: depends on PLATFORM_LINUX +//config: help +//config: Dump the content of raw NAND chip //usage:#define nandwrite_trivial_usage //usage: "[-p] [-s ADDR] MTD_DEVICE [FILE]" @@ -30,18 +36,65 @@ //usage: "\n -p Pad to page size" //usage: "\n -s ADDR Start address" +//usage:#define nanddump_trivial_usage +//usage: "[-o] [-b] [-s ADDR] [-f FILE] MTD_DEVICE" +//usage:#define nanddump_full_usage "\n\n" +//usage: "Dump the sepcified MTD device\n" +//usage: "\nOptions:" +//usage: "\n -o Omit oob data" +//usage: "\n -b Omit bad block from the dump" +//usage: "\n -s ADDR Start address" +//usage: "\n -l LEN Length" +//usage: "\n -f FILE Dump to file ('-' for stdout)" + +#include "libbb.h" +#include + +#define IS_NANDDUMP (ENABLE_NANDDUMP && (!ENABLE_NANDWRITE || (applet_name[4] == 'd'))) +#define IS_NANDWRITE (ENABLE_NANDWRITE && (!ENABLE_NANDDUMP || (applet_name[4] != 'd'))) + +#define OPT_p (1 << 0) /* nandwrite only */ +#define OPT_o (1 << 0) /* nanddump only */ +#define OPT_s (1 << 1) +#define OPT_b (1 << 2) +#define OPT_f (1 << 3) +#define OPT_l (1 << 4) + +#define NAND_MAX_OOBSIZE 256 +/* helper for writing out 0xff for bad blocks pad */ +static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob) +{ + unsigned char buf[meminfo->writesize]; + unsigned count; + + /* round len to the next page */ + len = (len | ~(meminfo->writesize - 1)) + 1; + + memset(buf, 0xff, sizeof(buf)); + for (count = 0; count < len; count += meminfo->writesize) { + xwrite(STDOUT_FILENO, buf, meminfo->writesize); + if (oob) + xwrite(STDOUT_FILENO, buf, meminfo->oobsize); + } +} + static unsigned next_good_eraseblock(int fd, struct mtd_info_user *meminfo, unsigned block_offset) { while (1) { loff_t offs; - if (block_offset >= meminfo->size) - bb_error_msg_and_die("not enough space in MTD device"); + + if (block_offset >= meminfo->size) { + if (IS_NANDWRITE) + bb_error_msg_and_die("not enough space in MTD device"); + return block_offset; /* let the caller exit */ + } offs = block_offset; if (xioctl(fd, MEMGETBADBLOCK, &offs) == 0) return block_offset; /* ioctl returned 1 => "bad block" */ - printf("Skipping bad block at 0x%08x\n", block_offset); + if (IS_NANDWRITE) + printf("Skipping bad block at 0x%08x\n", block_offset); block_offset += meminfo->erasesize; } } @@ -49,31 +102,49 @@ static unsigned next_good_eraseblock(int fd, struct mtd_info_user *meminfo, int nandwrite_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int nandwrite_main(int argc UNUSED_PARAM, char **argv) { + /* Buffer for OOB data */ + unsigned char oobbuf[NAND_MAX_OOBSIZE]; unsigned opts; int fd; ssize_t cnt; - unsigned mtdoffset, meminfo_writesize, blockstart; + unsigned mtdoffset, meminfo_writesize, blockstart, limit; + unsigned end_addr = ~0; struct mtd_info_user meminfo; + struct mtd_oob_buf oob; unsigned char *filebuf; - const char *opt_s = "0"; - enum { - OPT_p = (1 << 0), - OPT_s = (1 << 1), - }; - - opt_complementary = "-1:?2"; - opts = getopt32(argv, "ps:", &opt_s); + const char *opt_s = "0", *opt_f = "-", *opt_l; + + if (IS_NANDDUMP) { + opt_complementary = "=1"; + opts = getopt32(argv, "os:bf:l:", &opt_s, &opt_f, &opt_l); + } else { /* nandwrite */ + opt_complementary = "-1:?2"; + opts = getopt32(argv, "ps:", &opt_s); + } argv += optind; - if (argv[1]) - xmove_fd(xopen_stdin(argv[1]), STDIN_FILENO); + if (IS_NANDWRITE && argv[1]) + opt_f = argv[1]; + if (!LONE_DASH(opt_f)) { + int tmp_fd = xopen(opt_f, + IS_NANDDUMP ? O_WRONLY | O_TRUNC | O_CREAT : O_RDONLY + ); + xmove_fd(tmp_fd, IS_NANDDUMP ? STDOUT_FILENO : STDIN_FILENO); + } fd = xopen(argv[0], O_RDWR); xioctl(fd, MEMGETINFO, &meminfo); - mtdoffset = bb_strtou(opt_s, NULL, 0); - if (errno) - bb_error_msg_and_die("invalid number '%s'", opt_s); + oob.start = 0; + oob.length = meminfo.oobsize; + oob.ptr = oobbuf; + + mtdoffset = xstrtou(opt_s, 0); + if (IS_NANDDUMP && (opts & OPT_l)) { + unsigned length = xstrtou(opt_l, 0); + if (length < meminfo.size - mtdoffset) + end_addr = mtdoffset + length; + } /* Pull it into a CPU register (hopefully) - smaller code that way */ meminfo_writesize = meminfo.writesize; @@ -91,20 +162,39 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv) * bad. */ tmp = next_good_eraseblock(fd, &meminfo, blockstart); - if (tmp != blockstart) /* bad block(s), advance mtdoffset */ + if (tmp != blockstart) { + /* bad block(s), advance mtdoffset */ + if (IS_NANDDUMP & !(opts & OPT_b)) { + int bad_len = MIN(tmp, end_addr) - mtdoffset; + dump_bad(&meminfo, bad_len, !(opts & OPT_o)); + } mtdoffset = tmp; + } } cnt = -1; - while (mtdoffset < meminfo.size) { + limit = MIN(meminfo.size, end_addr); + while (mtdoffset < limit) { + int input_fd = IS_NANDWRITE ? STDIN_FILENO : fd; + int output_fd = IS_NANDWRITE ? fd : STDOUT_FILENO; + blockstart = mtdoffset & ~(meminfo.erasesize - 1); if (blockstart == mtdoffset) { /* starting a new eraseblock */ mtdoffset = next_good_eraseblock(fd, &meminfo, blockstart); - printf("Writing at 0x%08x\n", mtdoffset); + if (IS_NANDWRITE) + printf("Writing at 0x%08x\n", mtdoffset); + else if (mtdoffset > blockstart) { + int bad_len = MIN(mtdoffset, limit) - blockstart; + dump_bad(&meminfo, bad_len, !(opts & OPT_o)); + } + if (mtdoffset >= limit) + break; } + xlseek(fd, mtdoffset, SEEK_SET); + /* get some more data from input */ - cnt = full_read(STDIN_FILENO, filebuf, meminfo_writesize); + cnt = full_read(input_fd, filebuf, meminfo_writesize); if (cnt == 0) { /* even with -p, we do not pad past the end of input * (-p only zero-pads last incomplete page) @@ -112,20 +202,29 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv) break; } if (cnt < meminfo_writesize) { + if (IS_NANDDUMP) + bb_error_msg_and_die("short read"); if (!(opts & OPT_p)) bb_error_msg_and_die("input size is not rounded up to page size, " "use -p to zero pad"); /* zero pad to end of write block */ memset(filebuf + cnt, 0, meminfo_writesize - cnt); } - xlseek(fd, mtdoffset, SEEK_SET); - xwrite(fd, filebuf, meminfo_writesize); + xwrite(output_fd, filebuf, meminfo_writesize); + + if (IS_NANDDUMP && !(opts & OPT_o)) { + /* Dump OOB data */ + oob.start = mtdoffset; + xioctl(fd, MEMREADOOB, &oob); + xwrite(output_fd, oobbuf, meminfo.oobsize); + } + mtdoffset += meminfo_writesize; if (cnt < meminfo_writesize) break; } - if (cnt != 0) { + if (IS_NANDWRITE && cnt != 0) { /* We filled entire MTD, but did we reach EOF on input? */ if (full_read(STDIN_FILENO, filebuf, meminfo_writesize) != 0) { /* no */ -- cgit v1.2.3-55-g6feb From c05387d5deca9e57c38077debc0f705199f32006 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 18 Oct 2010 02:38:27 +0200 Subject: *: replace xopen3 with xopen where makes sense function old new delta uniq_main 421 416 -5 sort_main 803 798 -5 patch_main 2051 2046 -5 cpio_main 547 542 -5 Signed-off-by: Denys Vlasenko --- archival/cpio.c | 2 +- coreutils/sort.c | 2 +- coreutils/uniq.c | 4 ++-- editors/patch.c | 2 +- editors/patch_toybox.c | 2 +- libbb/xfuncs_printf.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/archival/cpio.c b/archival/cpio.c index 7cd8ee8a7..a2d74dc79 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -370,7 +370,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) if (cpio_fmt[0] != 'n') /* we _require_ "-H newc" */ bb_show_usage(); if (opt & CPIO_OPT_FILE) { - xmove_fd(xopen3(cpio_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666), STDOUT_FILENO); + xmove_fd(xopen(cpio_filename, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); } dump: return cpio_o(); diff --git a/coreutils/sort.c b/coreutils/sort.c index 4407b7105..716824321 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c @@ -412,7 +412,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_SORT_BIG /* Open output file _after_ we read all input ones */ if (option_mask32 & FLAG_o) - xmove_fd(xopen3(str_o, O_WRONLY, 0666), STDOUT_FILENO); + xmove_fd(xopen(str_o, O_WRONLY), STDOUT_FILENO); #endif flag = (option_mask32 & FLAG_z) ? '\0' : '\n'; for (i = 0; i < linecount; i++) diff --git a/coreutils/uniq.c b/coreutils/uniq.c index f0364b9a1..358de7894 100644 --- a/coreutils/uniq.c +++ b/coreutils/uniq.c @@ -52,8 +52,8 @@ int uniq_main(int argc UNUSED_PARAM, char **argv) if (output[0] != '-' || output[1]) { // Won't work with "uniq - FILE" and closed stdin: //close(STDOUT_FILENO); - //xopen3(output, O_WRONLY | O_CREAT | O_TRUNC, 0666); - xmove_fd(xopen3(output, O_WRONLY | O_CREAT | O_TRUNC, 0666), STDOUT_FILENO); + //xopen(output, O_WRONLY | O_CREAT | O_TRUNC); + xmove_fd(xopen(output, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); } } } diff --git a/editors/patch.c b/editors/patch.c index 764f0f183..66a9474fe 100644 --- a/editors/patch.c +++ b/editors/patch.c @@ -591,7 +591,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) xmkpath(name, -1); *s = '/'; } - TT.filein = xopen3(name, O_CREAT|O_EXCL|O_RDWR, 0666); + TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR); } else { printf("patching file %s\n", name); TT.filein = xopen(name, O_RDONLY); diff --git a/editors/patch_toybox.c b/editors/patch_toybox.c index 04bd98eea..a60bf070f 100644 --- a/editors/patch_toybox.c +++ b/editors/patch_toybox.c @@ -559,7 +559,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) xmkpath(name, -1); *s = '/'; } - TT.filein = xopen3(name, O_CREAT|O_EXCL|O_RDWR, 0666); + TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR); } else { printf("patching file %s\n", name); TT.filein = xopen(name, O_RDWR); diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index c6db38d33..ba660a2db 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c @@ -134,7 +134,7 @@ int FAST_FUNC xopen3(const char *pathname, int flags, int mode) return ret; } -// Die if we can't open an existing file and return a fd. +// Die if we can't open a file and return a fd. int FAST_FUNC xopen(const char *pathname, int flags) { return xopen3(pathname, flags, 0666); -- cgit v1.2.3-55-g6feb From 5fe2f863b9cee5ab0e7ac873538bce48846dbad8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 18 Oct 2010 02:43:57 +0200 Subject: sort: -o FILE should create/truncate FILE Signed-off-by: Denys Vlasenko --- coreutils/sort.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/sort.c b/coreutils/sort.c index 716824321..eccc2d437 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c @@ -412,7 +412,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_SORT_BIG /* Open output file _after_ we read all input ones */ if (option_mask32 & FLAG_o) - xmove_fd(xopen(str_o, O_WRONLY), STDOUT_FILENO); + xmove_fd(xopen(str_o, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO); #endif flag = (option_mask32 & FLAG_z) ? '\0' : '\n'; for (i = 0; i < linecount; i++) -- cgit v1.2.3-55-g6feb