diff options
Diffstat (limited to 'release/src/router/busybox/libbb')
114 files changed, 13189 insertions, 0 deletions
diff --git a/release/src/router/busybox/libbb/Makefile b/release/src/router/busybox/libbb/Makefile new file mode 100644 index 00000000..a9ea7694 --- /dev/null +++ b/release/src/router/busybox/libbb/Makefile @@ -0,0 +1,11 @@ +# Silly wrapper makefile. This Makefile is _not_ used by the build system for +# busybox, it is just to make working on libbb more conveinient. +# -Erik Andersen + +all: + make -C .. libbb.a + +clean: + - rm -rf libbb.a + - find -name \*.o -exec rm -f {} \; + diff --git a/release/src/router/busybox/libbb/Makefile.in b/release/src/router/busybox/libbb/Makefile.in new file mode 100755 index 00000000..b60adc95 --- /dev/null +++ b/release/src/router/busybox/libbb/Makefile.in @@ -0,0 +1,105 @@ +# Makefile for busybox +# +# Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + +LIBBB_AR:=libbb.a +ifndef $(LIBBB_DIR) +LIBBB_DIR:=$(TOPDIR)libbb/ +endif + +LIBBB_SRC:= \ + arith.c bb_asprintf.c ask_confirmation.c change_identity.c chomp.c \ + compare_string_array.c concat_path_file.c copy_file.c \ + copyfd.c correct_password.c create_icmp_socket.c \ + create_icmp6_socket.c device_open.c dump.c error_msg.c \ + error_msg_and_die.c find_mount_point.c find_pid_by_name.c \ + find_root_device.c fgets_str.c full_read.c full_write.c get_console.c \ + get_last_path_component.c get_line_from_file.c herror_msg.c \ + herror_msg_and_die.c human_readable.c inet_common.c inode_hash.c \ + interface.c isdirectory.c kernel_version.c last_char_is.c \ + llist_add_to.c login.c loop.c make_directory.c mode_string.c \ + module_syscalls.c mtab.c mtab_file.c my_getgrgid.c my_getgrnam.c \ + my_getpwnam.c my_getpwnamegid.c my_getpwuid.c obscure.c parse_mode.c \ + parse_number.c perror_msg.c perror_msg_and_die.c print_file.c \ + process_escape_sequence.c procps.c pwd2spwd.c pw_encrypt.c \ + qmodule.c read_package_field.c recursive_action.c remove_file.c \ + restricted_shell.c run_parts.c run_shell.c safe_read.c safe_strncpy.c \ + setup_environment.c simplify_path.c syscalls.c syslog_msg_with_name.c \ + trim.c u_signal_names.c vdprintf.c verror_msg.c \ + vherror_msg.c vperror_msg.c wfopen.c xconnect.c xgetcwd.c \ + xgethostbyname.c xgethostbyname2.c xreadlink.c xregcomp.c xgetlarg.c \ + \ + fclose_nonstdin.c fflush_stdout_and_exit.c getopt_ulflags.c \ + default_error_retval.c wfopen_input.c speed_table.c \ + perror_nomsg_and_die.c perror_nomsg.c skip_whitespace.c \ + warn_ignoring_args.c concat_subpath_file.c vfork_daemon_rexec.c + +LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC)) + +LIBBB_MSRC0:=$(LIBBB_DIR)messages.c +LIBBB_MOBJ0:=full_version.o \ + memory_exhausted.o invalid_date.o io_error.o \ + write_error.o name_longer_than_foo.o unknown.o \ + can_not_create_raw_socket.o perm_denied_are_you_root.o \ + shadow_file.o passwd_file.o group_file.o gshadow_file.o nologin_file.o \ + securetty_file.o motd_file.o \ + msg_standard_input.o msg_standard_output.o + +LIBBB_MSRC1:=$(LIBBB_DIR)xfuncs.c +LIBBB_MOBJ1:=xmalloc.o xrealloc.o xcalloc.o xstrdup.o xstrndup.o \ + xfopen.o xopen.o xread.o xread_all.o xread_char.o \ + xferror.o xferror_stdout.o xfflush_stdout.o strlen.o + +LIBBB_MSRC2:=$(LIBBB_DIR)printf.c +LIBBB_MOBJ2:=bb_vfprintf.o bb_vprintf.o bb_fprintf.o bb_printf.o + +LIBBB_MSRC3:=$(LIBBB_DIR)xgetularg.c +LIBBB_MOBJ3:=xgetularg_bnd_sfx.o xgetlarg_bnd_sfx.o getlarg10_sfx.o \ + xgetularg_bnd.o xgetularg10_bnd.o xgetularg10.o + +LIBBB_MOBJS0=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ0)) +LIBBB_MOBJS1=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ1)) +LIBBB_MOBJS2=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ2)) +LIBBB_MOBJS3=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ3)) + +libraries-y+=$(LIBBB_DIR)$(LIBBB_AR) + +$(LIBBB_DIR)$(LIBBB_AR): $(LIBBB_OBJS) $(LIBBB_MOBJS0) $(LIBBB_MOBJS1) \ + $(LIBBB_MOBJS2) $(LIBBB_MOBJS3) + $(AR) -ro $@ $(LIBBB_OBJS) $(LIBBB_MOBJS0) $(LIBBB_MOBJS1) \ + $(LIBBB_MOBJS2) $(LIBBB_MOBJS3) + +$(LIBBB_MOBJS0): $(LIBBB_MSRC0) + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DL_$(notdir $*) -c $< -o $@ + +$(LIBBB_MOBJS1): $(LIBBB_MSRC1) + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DL_$(notdir $*) -c $< -o $@ + +$(LIBBB_MOBJS2): $(LIBBB_MSRC2) + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DL_$(notdir $*) -c $< -o $@ + +$(LIBBB_MOBJS3): $(LIBBB_MSRC3) + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DL_$(notdir $*) -c $< -o $@ + +$(LIBBB_DIR)loop.o: $(LIBBB_DIR)loop.h + +$(LIBBB_DIR)loop.h: $(LIBBB_DIR)mk_loop_h.sh + @ $(SHELL) $< > $@ + + diff --git a/release/src/router/busybox/libbb/README b/release/src/router/busybox/libbb/README new file mode 100644 index 00000000..0e36f84b --- /dev/null +++ b/release/src/router/busybox/libbb/README @@ -0,0 +1,15 @@ +Please see the LICENSE file for copyright information. + +libbb is BusyBox's utility library. This all used to be in a single file +(utility.c to be specific). When I split utility.c up to create libbb, I did +not carefully fix up the copyright and licensing information. I'll do that for +the next release. + +For now, justtrust me that a bunch of people have worked on this stuff, +and it is all GPL'ed. + + Erik Andersen + <andersen@lineo.com> + <andersee@debian.org> + <andersee@codepoet.org> + diff --git a/release/src/router/busybox/libbb/arith.c b/release/src/router/busybox/libbb/arith.c new file mode 100644 index 00000000..04c45ec3 --- /dev/null +++ b/release/src/router/busybox/libbb/arith.c @@ -0,0 +1,263 @@ +/* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com> + + 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 + * than a comparable parser writen in yacc. The supported operators are + * listed in #defines below. Parens, order of operations, and error handling + * are supported. This code is threadsafe. */ + +/* To use the routine, call it with an expression string. It returns an + * integer result. You will also need to define an "error" function + * that takes printf arguments and _does not return_, or modify the code + * to use another error mechanism. */ + +#include <stdlib.h> +#include <string.h> +#include "libbb.h" + +typedef char operator; + +#define tok_decl(prec,id) (((id)<<5)|(prec)) +#define PREC(op) ((op)&0x1F) + +#define TOK_LPAREN tok_decl(0,0) + +#define TOK_OR tok_decl(1,0) + +#define TOK_AND tok_decl(2,0) + +#define TOK_BOR tok_decl(3,0) + +#define TOK_BXOR tok_decl(4,0) + +#define TOK_BAND tok_decl(5,0) + +#define TOK_EQ tok_decl(6,0) +#define TOK_NE tok_decl(6,1) + +#define TOK_LT tok_decl(7,0) +#define TOK_GT tok_decl(7,1) +#define TOK_GE tok_decl(7,2) +#define TOK_LE tok_decl(7,3) + +#define TOK_LSHIFT tok_decl(8,0) +#define TOK_RSHIFT tok_decl(8,1) + +#define TOK_ADD tok_decl(9,0) +#define TOK_SUB tok_decl(9,1) + +#define TOK_MUL tok_decl(10,0) +#define TOK_DIV tok_decl(10,1) +#define TOK_REM tok_decl(10,2) + +#define UNARYPREC 14 +#define TOK_BNOT tok_decl(UNARYPREC,0) +#define TOK_NOT tok_decl(UNARYPREC,1) +#define TOK_UMINUS tok_decl(UNARYPREC,2) + +#define TOK_NUM tok_decl(15,0) + +#define ARITH_APPLY(op) arith_apply(op, numstack, &numstackptr) +#define NUMPTR (*numstackptr) +static short arith_apply(operator op, long *numstack, long **numstackptr) +{ + if (NUMPTR == numstack) goto err; + if (op == TOK_UMINUS) + NUMPTR[-1] *= -1; + else if (op == TOK_NOT) + NUMPTR[-1] = !(NUMPTR[-1]); + else if (op == TOK_BNOT) + NUMPTR[-1] = ~(NUMPTR[-1]); + + /* Binary operators */ + else { + if (NUMPTR-1 == numstack) goto err; + --NUMPTR; + if (op == TOK_BOR) + NUMPTR[-1] |= *NUMPTR; + else if (op == TOK_OR) + NUMPTR[-1] = *NUMPTR || NUMPTR[-1]; + else if (op == TOK_BAND) + NUMPTR[-1] &= *NUMPTR; + else if (op == TOK_AND) + NUMPTR[-1] = NUMPTR[-1] && *NUMPTR; + else if (op == TOK_EQ) + NUMPTR[-1] = (NUMPTR[-1] == *NUMPTR); + else if (op == TOK_NE) + NUMPTR[-1] = (NUMPTR[-1] != *NUMPTR); + else if (op == TOK_GE) + NUMPTR[-1] = (NUMPTR[-1] >= *NUMPTR); + else if (op == TOK_RSHIFT) + NUMPTR[-1] >>= *NUMPTR; + else if (op == TOK_LSHIFT) + NUMPTR[-1] <<= *NUMPTR; + else if (op == TOK_GT) + NUMPTR[-1] = (NUMPTR[-1] > *NUMPTR); + else if (op == TOK_LT) + NUMPTR[-1] = (NUMPTR[-1] < *NUMPTR); + else if (op == TOK_LE) + NUMPTR[-1] = (NUMPTR[-1] <= *NUMPTR); + else if (op == TOK_MUL) + NUMPTR[-1] *= *NUMPTR; + else if (op == TOK_DIV) { + if(*NUMPTR==0) + return -2; + NUMPTR[-1] /= *NUMPTR; + } + else if (op == TOK_REM) { + if(*NUMPTR==0) + return -2; + NUMPTR[-1] %= *NUMPTR; + } + else if (op == TOK_ADD) + NUMPTR[-1] += *NUMPTR; + else if (op == TOK_SUB) + NUMPTR[-1] -= *NUMPTR; + } + return 0; +err: return(-1); +} + +extern long arith (const char *startbuf, int *errcode) +{ + register char arithval; + const char *expr = startbuf; + + operator lasttok = TOK_MUL, op; + size_t datasizes = strlen(startbuf); + unsigned char prec; + + long *numstack, *numstackptr; + operator *stack = alloca(datasizes * sizeof(operator)), *stackptr = stack; + + *errcode = 0; + numstack = alloca((datasizes/2+1)*sizeof(long)), numstackptr = numstack; + + while ((arithval = *expr)) { + if (arithval == ' ' || arithval == '\n' || arithval == '\t') + goto prologue; + if ((unsigned)arithval-'0' <= 9) /* isdigit */ { + *numstackptr++ = strtol(expr, (char **) &expr, 10); + lasttok = TOK_NUM; + continue; + } if (arithval == '(') { + *stackptr++ = TOK_LPAREN; + lasttok = TOK_LPAREN; + goto prologue; + } if (arithval == ')') { + lasttok = TOK_NUM; + while (stackptr != stack) { + op = *--stackptr; + if (op == TOK_LPAREN) + goto prologue; + *errcode = ARITH_APPLY(op); + if(*errcode) return *errcode; + } + goto err; /* Mismatched parens */ + } if (arithval == '|') { + if (*++expr == '|') + op = TOK_OR; + else { + --expr; + op = TOK_BOR; + } + } else if (arithval == '&') { + if (*++expr == '&') + op = TOK_AND; + else { + --expr; + op = TOK_BAND; + } + } else if (arithval == '=') { + if (*++expr != '=') goto err; /* Unknown token */ + op = TOK_EQ; + } else if (arithval == '!') { + if (*++expr == '=') + op = TOK_NE; + else { + --expr; + op = TOK_NOT; + } + } else if (arithval == '>') { + switch (*++expr) { + case '=': + op = TOK_GE; + break; + case '>': + op = TOK_RSHIFT; + break; + default: + --expr; + op = TOK_GT; + } + } else if (arithval == '<') { + switch (*++expr) { + case '=': + op = TOK_LE; + break; + case '<': + op = TOK_LSHIFT; + break; + default: + --expr; + op = TOK_LT; + } + } else if (arithval == '*') + op = TOK_MUL; + else if (arithval == '/') + op = TOK_DIV; + else if (arithval == '%') + op = TOK_REM; + else if (arithval == '+') { + if (lasttok != TOK_NUM) goto prologue; /* Unary plus */ + op = TOK_ADD; + } else if (arithval == '-') + op = (lasttok == TOK_NUM) ? TOK_SUB : TOK_UMINUS; + else if (arithval == '~') + op = TOK_BNOT; + else goto err; /* Unknown token */ + + prec = PREC(op); + if (prec != UNARYPREC) + while (stackptr != stack && PREC(stackptr[-1]) >= prec) { + *errcode = ARITH_APPLY(*--stackptr); + if(*errcode) return *errcode; + } + *stackptr++ = op; + lasttok = op; +prologue: ++expr; + } /* yay */ + + while (stackptr != stack) { + *errcode = ARITH_APPLY(*--stackptr); + if(*errcode) return *errcode; + } + if (numstackptr != numstack+1) { +err: + *errcode = -1; + return -1; + /* NOTREACHED */ + } + + return *numstack; +} diff --git a/release/src/router/busybox/libbb/ask_confirmation.c b/release/src/router/busybox/libbb/ask_confirmation.c new file mode 100644 index 00000000..f2922379 --- /dev/null +++ b/release/src/router/busybox/libbb/ask_confirmation.c @@ -0,0 +1,53 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include "libbb.h" + + +int ask_confirmation() +{ + int c = '\0'; + int ret = 0; + + while (c != '\n') { + c = getchar(); + if ( c != '\n' ) { + ret = ((c=='y')||(c=='Y')) ? 1 : 0; + } + } + return ret; +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/bb_asprintf.c b/release/src/router/busybox/libbb/bb_asprintf.c new file mode 100644 index 00000000..7075b46d --- /dev/null +++ b/release/src/router/busybox/libbb/bb_asprintf.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2002 Vladimir Oleynik <dzo@simtreas.ru> +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include "libbb.h" + +void bb_xasprintf(char **string_ptr, const char *format, ...) +{ + va_list p; + int r; + + va_start(p, format); + r = vasprintf(string_ptr, format, p); + va_end(p); + + if (r < 0) { + bb_perror_msg_and_die("bb_xasprintf"); + } +} diff --git a/release/src/router/busybox/libbb/change_identity.c b/release/src/router/busybox/libbb/change_identity.c new file mode 100644 index 00000000..c2b73eeb --- /dev/null +++ b/release/src/router/busybox/libbb/change_identity.c @@ -0,0 +1,54 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl@austin.rr.com> + * 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. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``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 JULIE HAUGH OR CONTRIBUTORS 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. + */ + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <syslog.h> +#include <ctype.h> + +#include "libbb.h" + + +/* Become the user and group(s) specified by PW. */ +void change_identity ( const struct passwd *pw ) +{ + if ( initgroups ( pw-> pw_name, pw-> pw_gid ) == -1 ) + bb_perror_msg_and_die ( "cannot set groups" ); + endgrent ( ); + + if ( setgid ( pw-> pw_gid )) + bb_perror_msg_and_die ( "cannot set group id" ); + if ( setuid ( pw->pw_uid )) + bb_perror_msg_and_die ( "cannot set user id" ); +} + diff --git a/release/src/router/busybox/libbb/chomp.c b/release/src/router/busybox/libbb/chomp.c new file mode 100644 index 00000000..111d4cf7 --- /dev/null +++ b/release/src/router/busybox/libbb/chomp.c @@ -0,0 +1,49 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include "libbb.h" + + +void chomp(char *s) +{ + char *lc = last_char_is(s, '\n'); + + if(lc) + *lc = 0; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/compare_string_array.c b/release/src/router/busybox/libbb/compare_string_array.c new file mode 100644 index 00000000..993b4626 --- /dev/null +++ b/release/src/router/busybox/libbb/compare_string_array.c @@ -0,0 +1,31 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <string.h> + +/* returns the array number of the string */ +extern unsigned short compare_string_array(const char *string_array[], const char *key) +{ + unsigned short i; + + for (i = 0; string_array[i] != 0; i++) { + if (strcmp(string_array[i], key) == 0) { + break; + } + } + return(i); +} + diff --git a/release/src/router/busybox/libbb/concat_path_file.c b/release/src/router/busybox/libbb/concat_path_file.c new file mode 100644 index 00000000..86dd2fbb --- /dev/null +++ b/release/src/router/busybox/libbb/concat_path_file.c @@ -0,0 +1,26 @@ +/* + * busybox library eXtendet funcion + * + * concatenate path and file name to new allocation buffer, + * not addition '/' if path name already have '/' + * +*/ + +#include <string.h> +#include "libbb.h" + +extern char *concat_path_file(const char *path, const char *filename) +{ + char *outbuf; + char *lc; + + if (!path) + path=""; + lc = last_char_is(path, '/'); + while (*filename == '/') + filename++; + outbuf = xmalloc(strlen(path)+strlen(filename)+1+(lc==NULL)); + sprintf(outbuf, "%s%s%s", path, (lc==NULL)? "/" : "", filename); + + return outbuf; +} diff --git a/release/src/router/busybox/libbb/concat_subpath_file.c b/release/src/router/busybox/libbb/concat_subpath_file.c new file mode 100644 index 00000000..6d86f5e8 --- /dev/null +++ b/release/src/router/busybox/libbb/concat_subpath_file.c @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) (C) 2003 Vladimir Oleynik <dzo@simtreas.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +/* + This function make special for recursive actions with usage + concat_path_file(path, filename) + and skiping "." and ".." directory entries +*/ + +#include "libbb.h" + +extern char *concat_subpath_file(const char *path, const char *f) +{ + if(f && *f == '.' && (!f[1] || (f[1] == '.' && !f[2]))) + return NULL; + return concat_path_file(path, f); +} diff --git a/release/src/router/busybox/libbb/copy_file.c b/release/src/router/busybox/libbb/copy_file.c new file mode 100644 index 00000000..c79fbeb1 --- /dev/null +++ b/release/src/router/busybox/libbb/copy_file.c @@ -0,0 +1,237 @@ +/* vi: set sw=4 ts=4: */ +/* + * Mini copy_file implementation for busybox + * + * + * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <utime.h> +#include <errno.h> +#include <dirent.h> +#include <stdlib.h> +#include <string.h> + +#include "libbb.h" + +int copy_file(const char *source, const char *dest, int flags) +{ + struct stat source_stat; + struct stat dest_stat; + int dest_exists = 1; + int status = 0; + + if (((flags & FILEUTILS_PRESERVE_SYMLINKS) && + lstat(source, &source_stat) < 0) || + (!(flags & FILEUTILS_PRESERVE_SYMLINKS) && + stat(source, &source_stat) < 0)) { + perror_msg("%s", source); + return -1; + } + + if (stat(dest, &dest_stat) < 0) { + if (errno != ENOENT) { + perror_msg("unable to stat `%s'", dest); + return -1; + } + dest_exists = 0; + } + + if (dest_exists && source_stat.st_rdev == dest_stat.st_rdev && + source_stat.st_ino == dest_stat.st_ino) { + error_msg("`%s' and `%s' are the same file", source, dest); + return -1; + } + + if (S_ISDIR(source_stat.st_mode)) { + DIR *dp; + struct dirent *d; + mode_t saved_umask = 0; + + if (!(flags & FILEUTILS_RECUR)) { + error_msg("%s: omitting directory", source); + return -1; + } + + /* Create DEST. */ + if (dest_exists) { + if (!S_ISDIR(dest_stat.st_mode)) { + error_msg("`%s' is not a directory", dest); + return -1; + } + } else { + mode_t mode; + saved_umask = umask(0); + + mode = source_stat.st_mode; + if (!(flags & FILEUTILS_PRESERVE_STATUS)) + mode = source_stat.st_mode & ~saved_umask; + mode |= S_IRWXU; + + if (mkdir(dest, mode) < 0) { + umask(saved_umask); + perror_msg("cannot create directory `%s'", dest); + return -1; + } + + umask(saved_umask); + } + + /* Recursively copy files in SOURCE. */ + if ((dp = opendir(source)) == NULL) { + perror_msg("unable to open directory `%s'", source); + status = -1; + goto end; + } + + while ((d = readdir(dp)) != NULL) { + char *new_source, *new_dest; + + if (strcmp(d->d_name, ".") == 0 || + strcmp(d->d_name, "..") == 0) + continue; + + new_source = concat_path_file(source, d->d_name); + new_dest = concat_path_file(dest, d->d_name); + if (copy_file(new_source, new_dest, flags) < 0) + status = -1; + free(new_source); + free(new_dest); + } + + /* ??? What if an error occurs in readdir? */ + + if (closedir(dp) < 0) { + perror_msg("unable to close directory `%s'", source); + status = -1; + } + + if (!dest_exists && + chmod(dest, source_stat.st_mode & ~saved_umask) < 0) { + perror_msg("unable to change permissions of `%s'", dest); + status = -1; + } + } else if (S_ISREG(source_stat.st_mode)) { + FILE *sfp, *dfp; + + if (dest_exists) { + if (flags & FILEUTILS_INTERACTIVE) { + fprintf(stderr, "%s: overwrite `%s'? ", applet_name, dest); + if (!ask_confirmation()) + return 0; + } + + if ((dfp = fopen(dest, "w")) == NULL) { + if (!(flags & FILEUTILS_FORCE)) { + perror_msg("unable to open `%s'", dest); + return -1; + } + + if (unlink(dest) < 0) { + perror_msg("unable to remove `%s'", dest); + return -1; + } + + dest_exists = 0; + } + } + + if (!dest_exists) { + int fd; + + if ((fd = open(dest, O_WRONLY|O_CREAT, source_stat.st_mode)) < 0 || + (dfp = fdopen(fd, "w")) == NULL) { + if (fd >= 0) + close(fd); + perror_msg("unable to open `%s'", dest); + return -1; + } + } + + if ((sfp = fopen(source, "r")) == NULL) { + fclose(dfp); + perror_msg("unable to open `%s'", source); + status = -1; + goto end; + } + + if (copy_file_chunk(sfp, dfp, -1) < 0) + status = -1; + + if (fclose(dfp) < 0) { + perror_msg("unable to close `%s'", dest); + status = -1; + } + + if (fclose(sfp) < 0) { + perror_msg("unable to close `%s'", source); + status = -1; + } + } else if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) || + S_ISSOCK(source_stat.st_mode)) { + if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) { + perror_msg("unable to create `%s'", dest); + return -1; + } + } else if (S_ISFIFO(source_stat.st_mode)) { + if (mkfifo(dest, source_stat.st_mode) < 0) { + perror_msg("cannot create fifo `%s'", dest); + return -1; + } + } else if (S_ISLNK(source_stat.st_mode)) { + char *lpath = xreadlink(source); + if (symlink(lpath, dest) < 0) { + perror_msg("cannot create symlink `%s'", dest); + return -1; + } + free(lpath); + +#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) + if (flags & FILEUTILS_PRESERVE_STATUS) + if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0) + perror_msg("unable to preserve ownership of `%s'", dest); +#endif + return 0; + } else { + error_msg("internal error: unrecognized file type"); + return -1; + } + +end: + + if (flags & FILEUTILS_PRESERVE_STATUS) { + struct utimbuf times; + + times.actime = source_stat.st_atime; + times.modtime = source_stat.st_mtime; + if (utime(dest, ×) < 0) + perror_msg("unable to preserve times of `%s'", dest); + if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) { + source_stat.st_mode &= ~(S_ISUID | S_ISGID); + perror_msg("unable to preserve ownership of `%s'", dest); + } + if (chmod(dest, source_stat.st_mode) < 0) + perror_msg("unable to preserve permissions of `%s'", dest); + } + + return status; +} diff --git a/release/src/router/busybox/libbb/copy_file_chunk.c b/release/src/router/busybox/libbb/copy_file_chunk.c new file mode 100644 index 00000000..c440a610 --- /dev/null +++ b/release/src/router/busybox/libbb/copy_file_chunk.c @@ -0,0 +1,74 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <sys/stat.h> +#include "libbb.h" + +/* Copy CHUNKSIZE bytes (or until EOF if CHUNKSIZE equals -1) from SRC_FILE + * to DST_FILE. */ +extern int copy_file_chunk(FILE *src_file, FILE *dst_file, unsigned long long chunksize) +{ + size_t nread, nwritten, size; + char buffer[BUFSIZ]; + + while (chunksize != 0) { + if (chunksize > BUFSIZ) + size = BUFSIZ; + else + size = chunksize; + + nread = fread (buffer, 1, size, src_file); + + if (nread != size && ferror (src_file)) { + perror_msg ("read"); + return -1; + } else if (nread == 0) { + if (chunksize != -1) { + error_msg ("Unable to read all data"); + return -1; + } + + return 0; + } + + nwritten = fwrite (buffer, 1, nread, dst_file); + + if (nwritten != nread) { + if (ferror (dst_file)) + perror_msg ("write"); + else + error_msg ("Unable to write all data"); + return -1; + } + + if (chunksize != -1) + chunksize -= nwritten; + } + + return 0; +} diff --git a/release/src/router/busybox/libbb/copyfd.c b/release/src/router/busybox/libbb/copyfd.c new file mode 100644 index 00000000..aa938d10 --- /dev/null +++ b/release/src/router/busybox/libbb/copyfd.c @@ -0,0 +1,59 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) 1999-2001 Erik Andersen <andersee@debian.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include "libbb.h" + + +extern int copyfd(int fd1, int fd2) +{ + char buf[8192]; + ssize_t nread, nwrote; + + while (1) { + nread = safe_read(fd1, buf, sizeof(buf)); + if (nread == 0) + break; + if (nread == -1) { + perror_msg("read"); + return -1; + } + + nwrote = full_write(fd2, buf, nread); + if (nwrote == -1) { + perror_msg("write"); + return -1; + } + } + + return 0; +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/correct_password.c b/release/src/router/busybox/libbb/correct_password.c new file mode 100644 index 00000000..39625361 --- /dev/null +++ b/release/src/router/busybox/libbb/correct_password.c @@ -0,0 +1,78 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl@austin.rr.com> + * 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. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``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 JULIE HAUGH OR CONTRIBUTORS 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. + */ + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <syslog.h> +#include <ctype.h> +#include <crypt.h> + +#include "libbb.h" + + + +/* Ask the user for a password. + Return 1 if the user gives the correct password for entry PW, + 0 if not. Return 1 without asking for a password if run by UID 0 + or if PW has an empty password. */ + +int correct_password ( const struct passwd *pw ) +{ + char *unencrypted, *encrypted, *correct; + +#ifdef CONFIG_FEATURE_SHADOWPASSWDS + if (( strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( strcmp ( pw-> pw_passwd, "*" ) == 0 )) { + struct spwd *sp = getspnam ( pw-> pw_name ); + + if ( !sp ) + bb_error_msg_and_die ( "no valid shadow password" ); + + correct = sp-> sp_pwdp; + } + else +#endif + correct = pw-> pw_passwd; + + if ( correct == 0 || correct[0] == '\0' ) + return 1; + + unencrypted = getpass ( "Password: " ); + if ( !unencrypted ) + { + fputs ( "getpass: cannot open /dev/tty\n", stderr ); + return 0; + } + encrypted = crypt ( unencrypted, correct ); + memset ( unencrypted, 0, bb_strlen ( unencrypted )); + return ( strcmp ( encrypted, correct ) == 0 ) ? 1 : 0; +} diff --git a/release/src/router/busybox/libbb/create_icmp6_socket.c b/release/src/router/busybox/libbb/create_icmp6_socket.c new file mode 100644 index 00000000..59661044 --- /dev/null +++ b/release/src/router/busybox/libbb/create_icmp6_socket.c @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * create raw socket for icmp (IPv6 version) protocol test permision + * and drop root privilegies if running setuid + * + */ + +#include <sys/types.h> +#include <netdb.h> +#include <sys/socket.h> +#include <errno.h> +#include <unistd.h> +#include "libbb.h" + +#ifdef CONFIG_FEATURE_IPV6 +int create_icmp6_socket(void) +{ + struct protoent *proto; + int sock; + + proto = getprotobyname("ipv6-icmp"); + /* if getprotobyname failed, just silently force + * proto->p_proto to have the correct value for "ipv6-icmp" */ + if ((sock = socket(AF_INET6, SOCK_RAW, + (proto ? proto->p_proto : IPPROTO_ICMPV6))) < 0) { + if (errno == EPERM) + bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); + else + bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); + } + + /* drop root privs if running setuid */ + setuid(getuid()); + + return sock; +} +#endif diff --git a/release/src/router/busybox/libbb/create_icmp_socket.c b/release/src/router/busybox/libbb/create_icmp_socket.c new file mode 100644 index 00000000..d804b398 --- /dev/null +++ b/release/src/router/busybox/libbb/create_icmp_socket.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * create raw socket for icmp protocol test permision + * and drop root privilegies if running setuid + * + */ + +#include <sys/types.h> +#include <netdb.h> +#include <sys/socket.h> +#include <errno.h> +#include <unistd.h> +#include "libbb.h" + +int create_icmp_socket(void) +{ + struct protoent *proto; + int sock; + + proto = getprotobyname("icmp"); + /* if getprotobyname failed, just silently force + * proto->p_proto to have the correct value for "icmp" */ + if ((sock = socket(AF_INET, SOCK_RAW, + (proto ? proto->p_proto : 1))) < 0) { /* 1 == ICMP */ + if (errno == EPERM) + error_msg_and_die("permission denied. (are you root?)"); + else + perror_msg_and_die(can_not_create_raw_socket); + } + + /* drop root privs if running setuid */ + setuid(getuid()); + + return sock; +} diff --git a/release/src/router/busybox/libbb/daemon.c b/release/src/router/busybox/libbb/daemon.c new file mode 100644 index 00000000..6d4169ed --- /dev/null +++ b/release/src/router/busybox/libbb/daemon.c @@ -0,0 +1,101 @@ +/* vi: set sw=4 ts=4: */ +/* + * daemon implementation for uClibc + * + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Modified for uClibc by Erik Andersen + * <andersee@debian.org>, <andersen@lineo.com> + * + * The uClibc Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the GNU C Library; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Original copyright notice is retained at the end of this file. + */ + +#include <features.h> +#include <fcntl.h> +#include <paths.h> +#include <unistd.h> + + +#if __GNU_LIBRARY__ < 5 + +int daemon( int nochdir, int noclose ) +{ + int fd; + + switch (fork()) { + case -1: + return(-1); + case 0: + break; + default: + _exit(0); + } + + if (setsid() == -1) + return(-1); + + if (!nochdir) + chdir("/"); + + if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + if (fd > 2) + close(fd); + } + return(0); +} +#endif + + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. 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. <BSD Advertising Clause omitted per the July 22, 1999 licensing change + * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change> + * + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + */ + + diff --git a/release/src/router/busybox/libbb/default_error_retval.c b/release/src/router/busybox/libbb/default_error_retval.c new file mode 100644 index 00000000..7d2d89bb --- /dev/null +++ b/release/src/router/busybox/libbb/default_error_retval.c @@ -0,0 +1,32 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* Seems silly to copyright a global variable. ;-) Oh well. + * + * At least one applet (cmp) returns a value different from the typical + * EXIT_FAILURE values (1) when an error occurs. So, make it configureable + * by the applet. I suppose we could use a wrapper function to set it, but + * that too seems silly. + */ + +#include <stdlib.h> +#include "libbb.h" + +int bb_default_error_retval = EXIT_FAILURE; diff --git a/release/src/router/busybox/libbb/device_open.c b/release/src/router/busybox/libbb/device_open.c new file mode 100644 index 00000000..8e97ce6c --- /dev/null +++ b/release/src/router/busybox/libbb/device_open.c @@ -0,0 +1,59 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <fcntl.h> +#include "libbb.h" + + +/* try to open up the specified device */ +extern int device_open(char *device, int mode) +{ + int m, f, fd = -1; + + m = mode | O_NONBLOCK; + + /* Retry up to 5 times */ + for (f = 0; f < 5; f++) + if ((fd = open(device, m, 0600)) >= 0) + break; + if (fd < 0) + return fd; + /* Reset original flags. */ + if (m != mode) + fcntl(fd, F_SETFL, mode); + return fd; +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/dirname.c b/release/src/router/busybox/libbb/dirname.c new file mode 100644 index 00000000..5f839945 --- /dev/null +++ b/release/src/router/busybox/libbb/dirname.c @@ -0,0 +1,49 @@ +/* vi: set sw=4 ts=4: */ +/* + * Mini dirname function. + * + * Copyright (C) 2001 Matt Kraai. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <string.h> +#include "libbb.h" + +/* Return a string on the heap containing the directory component of PATH. */ + +char *dirname(const char *path) +{ + const char *s; + + /* Go to the end of the string. */ + s = path + strlen(path) - 1; + + /* Strip off trailing /s (unless it is also the leading /). */ + while (path < s && s[0] == '/') + s--; + + /* Strip the last component. */ + while (path <= s && s[0] != '/') + s--; + + while (path < s && s[0] == '/') + s--; + + if (s < path) + return xstrdup ("."); + else + return xstrndup (path, s - path + 1); +} diff --git a/release/src/router/busybox/libbb/dump.c b/release/src/router/busybox/libbb/dump.c new file mode 100644 index 00000000..5a43b7c7 --- /dev/null +++ b/release/src/router/busybox/libbb/dump.c @@ -0,0 +1,818 @@ +/* + * Support code for the hexdump and od applets, + * based on code from util-linux v 2.11l + * + * Copyright (c) 1989 + * The Regents of the University of California. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Original copyright notice is retained at the end of this file. + */ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> /* for isdigit() */ +#include "libbb.h" +#include "dump.h" + +enum _vflag bb_dump_vflag = FIRST; +FS *bb_dump_fshead; /* head of format strings */ +static FU *endfu; +static char **_argv; +static off_t savaddress; /* saved address/offset in stream */ +static off_t eaddress; /* end address */ +static off_t address; /* address/offset in stream */ +off_t bb_dump_skip; /* bytes to skip */ +static int exitval; /* final exit value */ +int bb_dump_blocksize; /* data block size */ +int bb_dump_length = -1; /* max bytes to read */ + +static const char index_str[] = ".#-+ 0123456789"; + +static const char size_conv_str[] = +"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG"; + +static const char lcc[] = "diouxX"; + +int bb_dump_size(FS * fs) +{ + register FU *fu; + register int bcnt, cur_size; + register char *fmt; + const char *p; + int prec; + + /* figure out the data block bb_dump_size needed for each format unit */ + for (cur_size = 0, fu = fs->nextfu; fu; fu = fu->nextfu) { + if (fu->bcnt) { + cur_size += fu->bcnt * fu->reps; + continue; + } + for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) { + if (*fmt != '%') + continue; + /* + * bb_dump_skip any special chars -- save precision in + * case it's a %s format. + */ + while (strchr(index_str + 1, *++fmt)); + if (*fmt == '.' && isdigit(*++fmt)) { + prec = atoi(fmt); + while (isdigit(*++fmt)); + } + if (!(p = strchr(size_conv_str + 12, *fmt))) { + if (*fmt == 's') { + bcnt += prec; + } else if (*fmt == '_') { + ++fmt; + if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) { + bcnt += 1; + } + } + } else { + bcnt += size_conv_str[p - (size_conv_str + 12)]; + } + } + cur_size += bcnt * fu->reps; + } + return (cur_size); +} + +static void rewrite(FS * fs) +{ + enum { NOTOKAY, USEBCNT, USEPREC } sokay; + register PR *pr, **nextpr = NULL; + register FU *fu; + register char *p1, *p2, *p3; + char savech, *fmtp; + const char *byte_count_str; + int nconv, prec = 0; + + for (fu = fs->nextfu; fu; fu = fu->nextfu) { + /* + * break each format unit into print units; each + * conversion character gets its own. + */ + for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) { + /* NOSTRICT */ + /* DBU:[dvae@cray.com] calloc so that forward ptrs start out NULL*/ + pr = (PR *) xcalloc(1,sizeof(PR)); + if (!fu->nextpr) + fu->nextpr = pr; + /* ignore nextpr -- its unused inside the loop and is + * uninitialized 1st time thru. + */ + + /* bb_dump_skip preceding text and up to the next % sign */ + for (p1 = fmtp; *p1 && *p1 != '%'; ++p1); + + /* only text in the string */ + if (!*p1) { + pr->fmt = fmtp; + pr->flags = F_TEXT; + break; + } + + /* + * get precision for %s -- if have a byte count, don't + * need it. + */ + if (fu->bcnt) { + sokay = USEBCNT; + /* bb_dump_skip to conversion character */ + for (++p1; strchr(index_str, *p1); ++p1); + } else { + /* bb_dump_skip any special chars, field width */ + while (strchr(index_str + 1, *++p1)); + if (*p1 == '.' && isdigit(*++p1)) { + sokay = USEPREC; + prec = atoi(p1); + while (isdigit(*++p1)); + } else + sokay = NOTOKAY; + } + + p2 = p1 + 1; /* set end pointer */ + + /* + * figure out the byte count for each conversion; + * rewrite the format as necessary, set up blank- + * pbb_dump_adding for end of data. + */ + + if (*p1 == 'c') { + pr->flags = F_CHAR; + DO_BYTE_COUNT_1: + byte_count_str = "\001"; + DO_BYTE_COUNT: + if (fu->bcnt) { + do { + if (fu->bcnt == *byte_count_str) { + break; + } + } while (*++byte_count_str); + } + /* Unlike the original, output the remainder of the format string. */ + if (!*byte_count_str) { + bb_error_msg_and_die("bad byte count for conversion character %s.", p1); + } + pr->bcnt = *byte_count_str; + } else if (*p1 == 'l') { + ++p2; + ++p1; + DO_INT_CONV: + { + const char *e; + if (!(e = strchr(lcc, *p1))) { + goto DO_BAD_CONV_CHAR; + } + pr->flags = F_INT; + if (e > lcc + 1) { + pr->flags = F_UINT; + } + byte_count_str = "\004\002\001"; + goto DO_BYTE_COUNT; + } + /* NOTREACHED */ + } else if (strchr(lcc, *p1)) { + goto DO_INT_CONV; + } else if (strchr("eEfgG", *p1)) { + pr->flags = F_DBL; + byte_count_str = "\010\004"; + goto DO_BYTE_COUNT; + } else if (*p1 == 's') { + pr->flags = F_STR; + if (sokay == USEBCNT) { + pr->bcnt = fu->bcnt; + } else if (sokay == USEPREC) { + pr->bcnt = prec; + } else { /* NOTOKAY */ + bb_error_msg_and_die("%%s requires a precision or a byte count."); + } + } else if (*p1 == '_') { + ++p2; + switch (p1[1]) { + case 'A': + endfu = fu; + fu->flags |= F_IGNORE; + /* FALLTHROUGH */ + case 'a': + pr->flags = F_ADDRESS; + ++p2; + if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) { + goto DO_BAD_CONV_CHAR; + } + *p1 = p1[2]; + break; + case 'c': + pr->flags = F_C; + /* *p1 = 'c'; set in conv_c */ + goto DO_BYTE_COUNT_1; + case 'p': + pr->flags = F_P; + *p1 = 'c'; + goto DO_BYTE_COUNT_1; + case 'u': + pr->flags = F_U; + /* *p1 = 'c'; set in conv_u */ + goto DO_BYTE_COUNT_1; + default: + goto DO_BAD_CONV_CHAR; + } + } else { + DO_BAD_CONV_CHAR: + bb_error_msg_and_die("bad conversion character %%%s.\n", p1); + } + + /* + * copy to PR format string, set conversion character + * pointer, update original. + */ + savech = *p2; + p1[1] = '\0'; + pr->fmt = bb_xstrdup(fmtp); + *p2 = savech; + pr->cchar = pr->fmt + (p1 - fmtp); + + /* DBU:[dave@cray.com] w/o this, trailing fmt text, space is lost. + * Skip subsequent text and up to the next % sign and tack the + * additional text onto fmt: eg. if fmt is "%x is a HEX number", + * we lose the " is a HEX number" part of fmt. + */ + for (p3 = p2; *p3 && *p3 != '%'; p3++); + if (p3 > p2) + { + savech = *p3; + *p3 = '\0'; + if (!(pr->fmt = realloc(pr->fmt, strlen(pr->fmt)+(p3-p2)+1))) + bb_perror_msg_and_die("hexdump"); + strcat(pr->fmt, p2); + *p3 = savech; + p2 = p3; + } + + fmtp = p2; + + /* only one conversion character if byte count */ + if (!(pr->flags & F_ADDRESS) && fu->bcnt && nconv++) { + bb_error_msg_and_die("byte count with multiple conversion characters.\n"); + } + } + /* + * if format unit byte count not specified, figure it out + * so can adjust rep count later. + */ + if (!fu->bcnt) + for (pr = fu->nextpr; pr; pr = pr->nextpr) + fu->bcnt += pr->bcnt; + } + /* + * if the format string interprets any data at all, and it's + * not the same as the bb_dump_blocksize, and its last format unit + * interprets any data at all, and has no iteration count, + * repeat it as necessary. + * + * if, rep count is greater than 1, no trailing whitespace + * gets output from the last iteration of the format unit. + */ + for (fu = fs->nextfu;; fu = fu->nextfu) { + if (!fu->nextfu && fs->bcnt < bb_dump_blocksize && + !(fu->flags & F_SETREP) && fu->bcnt) + fu->reps += (bb_dump_blocksize - fs->bcnt) / fu->bcnt; + if (fu->reps > 1) { + for (pr = fu->nextpr;; pr = pr->nextpr) + if (!pr->nextpr) + break; + for (p1 = pr->fmt, p2 = NULL; *p1; ++p1) + p2 = isspace(*p1) ? p1 : NULL; + if (p2) + pr->nospace = p2; + } + if (!fu->nextfu) + break; + } +} + +static void do_skip(char *fname, int statok) +{ + struct stat sbuf; + + if (statok) { + if (fstat(fileno(stdin), &sbuf)) { + bb_perror_msg_and_die("%s", fname); + } + if ((!(S_ISCHR(sbuf.st_mode) || + S_ISBLK(sbuf.st_mode) || + S_ISFIFO(sbuf.st_mode))) && bb_dump_skip >= sbuf.st_size) { + /* If bb_dump_size valid and bb_dump_skip >= size */ + bb_dump_skip -= sbuf.st_size; + address += sbuf.st_size; + return; + } + } + if (fseek(stdin, bb_dump_skip, SEEK_SET)) { + bb_perror_msg_and_die("%s", fname); + } + savaddress = address += bb_dump_skip; + bb_dump_skip = 0; +} + +static int next(char **argv) +{ + static int done; + int statok; + + if (argv) { + _argv = argv; + return (1); + } + for (;;) { + if (*_argv) { + if (!(freopen(*_argv, "r", stdin))) { + bb_perror_msg("%s", *_argv); + exitval = 1; + ++_argv; + continue; + } + statok = done = 1; + } else { + if (done++) + return (0); + statok = 0; + } + if (bb_dump_skip) + do_skip(statok ? *_argv : "stdin", statok); + if (*_argv) + ++_argv; + if (!bb_dump_skip) + return (1); + } + /* NOTREACHED */ +} + +static u_char *get(void) +{ + static int ateof = 1; + static u_char *curp=NULL, *savp; /*DBU:[dave@cray.com]initialize curp */ + register int n; + int need, nread; + u_char *tmpp; + + if (!curp) { + address = (off_t)0; /*DBU:[dave@cray.com] initialize,initialize..*/ + curp = (u_char *) xmalloc(bb_dump_blocksize); + savp = (u_char *) xmalloc(bb_dump_blocksize); + } else { + tmpp = curp; + curp = savp; + savp = tmpp; + address = savaddress += bb_dump_blocksize; + } + for (need = bb_dump_blocksize, nread = 0;;) { + /* + * if read the right number of bytes, or at EOF for one file, + * and no other files are available, zero-pad the rest of the + * block and set the end flag. + */ + if (!bb_dump_length || (ateof && !next((char **) NULL))) { + if (need == bb_dump_blocksize) { + return ((u_char *) NULL); + } + if (bb_dump_vflag != ALL && !bcmp(curp, savp, nread)) { + if (bb_dump_vflag != DUP) { + printf("*\n"); + } + return ((u_char *) NULL); + } + bzero((char *) curp + nread, need); + eaddress = address + nread; + return (curp); + } + n = fread((char *) curp + nread, sizeof(u_char), + bb_dump_length == -1 ? need : MIN(bb_dump_length, need), stdin); + if (!n) { + if (ferror(stdin)) { + bb_perror_msg("%s", _argv[-1]); + } + ateof = 1; + continue; + } + ateof = 0; + if (bb_dump_length != -1) { + bb_dump_length -= n; + } + if (!(need -= n)) { + if (bb_dump_vflag == ALL || bb_dump_vflag == FIRST + || bcmp(curp, savp, bb_dump_blocksize)) { + if (bb_dump_vflag == DUP || bb_dump_vflag == FIRST) { + bb_dump_vflag = WAIT; + } + return (curp); + } + if (bb_dump_vflag == WAIT) { + printf("*\n"); + } + bb_dump_vflag = DUP; + address = savaddress += bb_dump_blocksize; + need = bb_dump_blocksize; + nread = 0; + } else { + nread += n; + } + } +} + +static void bpad(PR * pr) +{ + register char *p1, *p2; + + /* + * remove all conversion flags; '-' is the only one valid + * with %s, and it's not useful here. + */ + pr->flags = F_BPAD; + *pr->cchar = 's'; + for (p1 = pr->fmt; *p1 != '%'; ++p1); + for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1); + while ((*p2++ = *p1++) != 0); +} + +static const char conv_str[] = + "\0\\0\0" + "\007\\a\0" /* \a */ + "\b\\b\0" + "\f\\b\0" + "\n\\n\0" + "\r\\r\0" + "\t\\t\0" + "\v\\v\0" + "\0"; + + +static void conv_c(PR * pr, u_char * p) +{ + const char *str = conv_str; + char buf[10]; + + do { + if (*p == *str) { + ++str; + goto strpr; + } + str += 4; + } while (*str); + + if (isprint(*p)) { + *pr->cchar = 'c'; + (void) printf(pr->fmt, *p); + } else { + sprintf(buf, "%03o", (int) *p); + str = buf; + strpr: + *pr->cchar = 's'; + printf(pr->fmt, str); + } +} + +static void conv_u(PR * pr, u_char * p) +{ + static const char list[] = + "nul\0soh\0stx\0etx\0eot\0enq\0ack\0bel\0" + "bs\0_ht\0_lf\0_vt\0_ff\0_cr\0_so\0_si\0_" + "dle\0dcl\0dc2\0dc3\0dc4\0nak\0syn\0etb\0" + "can\0em\0_sub\0esc\0fs\0_gs\0_rs\0_us"; + + /* od used nl, not lf */ + if (*p <= 0x1f) { + *pr->cchar = 's'; + printf(pr->fmt, list[4 * (int)(*p)]); + } else if (*p == 0x7f) { + *pr->cchar = 's'; + printf(pr->fmt, "del"); + } else if (isprint(*p)) { + *pr->cchar = 'c'; + printf(pr->fmt, *p); + } else { + *pr->cchar = 'x'; + printf(pr->fmt, (int) *p); + } +} + +static void display(void) +{ +/* extern FU *endfu; */ + register FS *fs; + register FU *fu; + register PR *pr; + register int cnt; + register u_char *bp; + + off_t saveaddress; + u_char savech = 0, *savebp; + + while ((bp = get()) != NULL) { + for (fs = bb_dump_fshead, savebp = bp, saveaddress = address; fs; + fs = fs->nextfs, bp = savebp, address = saveaddress) { + for (fu = fs->nextfu; fu; fu = fu->nextfu) { + if (fu->flags & F_IGNORE) { + break; + } + for (cnt = fu->reps; cnt; --cnt) { + for (pr = fu->nextpr; pr; address += pr->bcnt, + bp += pr->bcnt, pr = pr->nextpr) { + if (eaddress && address >= eaddress && + !(pr->flags & (F_TEXT | F_BPAD))) { + bpad(pr); + } + if (cnt == 1 && pr->nospace) { + savech = *pr->nospace; + *pr->nospace = '\0'; + } +/* PRINT; */ + switch (pr->flags) { + case F_ADDRESS: + printf(pr->fmt, address); + break; + case F_BPAD: + printf(pr->fmt, ""); + break; + case F_C: + conv_c(pr, bp); + break; + case F_CHAR: + printf(pr->fmt, *bp); + break; + case F_DBL:{ + double dval; + float fval; + + switch (pr->bcnt) { + case 4: + bcopy((char *) bp, (char *) &fval, + sizeof(fval)); + printf(pr->fmt, fval); + break; + case 8: + bcopy((char *) bp, (char *) &dval, + sizeof(dval)); + printf(pr->fmt, dval); + break; + } + break; + } + case F_INT:{ + int ival; + short sval; + + switch (pr->bcnt) { + case 1: + printf(pr->fmt, (int) *bp); + break; + case 2: + bcopy((char *) bp, (char *) &sval, + sizeof(sval)); + printf(pr->fmt, (int) sval); + break; + case 4: + bcopy((char *) bp, (char *) &ival, + sizeof(ival)); + printf(pr->fmt, ival); + break; + } + break; + } + case F_P: + printf(pr->fmt, isprint(*bp) ? *bp : '.'); + break; + case F_STR: + printf(pr->fmt, (char *) bp); + break; + case F_TEXT: + printf(pr->fmt); + break; + case F_U: + conv_u(pr, bp); + break; + case F_UINT:{ + u_int ival; + u_short sval; + + switch (pr->bcnt) { + case 1: + printf(pr->fmt, (u_int) * bp); + break; + case 2: + bcopy((char *) bp, (char *) &sval, + sizeof(sval)); + printf(pr->fmt, (u_int) sval); + break; + case 4: + bcopy((char *) bp, (char *) &ival, + sizeof(ival)); + printf(pr->fmt, ival); + break; + } + break; + } + } + if (cnt == 1 && pr->nospace) { + *pr->nospace = savech; + } + } + } + } + } + } + if (endfu) { + /* + * if eaddress not set, error or file bb_dump_size was multiple of + * bb_dump_blocksize, and no partial block ever found. + */ + if (!eaddress) { + if (!address) { + return; + } + eaddress = address; + } + for (pr = endfu->nextpr; pr; pr = pr->nextpr) { + switch (pr->flags) { + case F_ADDRESS: + (void) printf(pr->fmt, eaddress); + break; + case F_TEXT: + (void) printf(pr->fmt); + break; + } + } + } +} + +int bb_dump_dump(char **argv) +{ + register FS *tfs; + + /* figure out the data block bb_dump_size */ + for (bb_dump_blocksize = 0, tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) { + tfs->bcnt = bb_dump_size(tfs); + if (bb_dump_blocksize < tfs->bcnt) { + bb_dump_blocksize = tfs->bcnt; + } + } + /* rewrite the rules, do syntax checking */ + for (tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) { + rewrite(tfs); + } + + next(argv); + display(); + + return (exitval); +} + +void bb_dump_add(const char *fmt) +{ + register const char *p; + register char *p1; + register char *p2; + static FS **nextfs; + FS *tfs; + FU *tfu, **nextfu; + const char *savep; + + /* start new linked list of format units */ + /* NOSTRICT */ + tfs = (FS *) xcalloc(1,sizeof(FS)); /*DBU:[dave@cray.com] start out NULL */ + if (!bb_dump_fshead) { + bb_dump_fshead = tfs; + } else { + *nextfs = tfs; + } + nextfs = &tfs->nextfs; + nextfu = &tfs->nextfu; + + /* take the format string and break it up into format units */ + for (p = fmt;;) { + /* bb_dump_skip leading white space */ + p = bb_skip_whitespace(p); + if (!*p) { + break; + } + + /* allocate a new format unit and link it in */ + /* NOSTRICT */ + /* DBU:[dave@cray.com] calloc so that forward pointers start out NULL */ + tfu = (FU *) xcalloc(1,sizeof(FU)); + *nextfu = tfu; + nextfu = &tfu->nextfu; + tfu->reps = 1; + + /* if leading digit, repetition count */ + if (isdigit(*p)) { + for (savep = p; isdigit(*p); ++p); + if (!isspace(*p) && *p != '/') { + bb_error_msg_and_die("bad format {%s}", fmt); + } + /* may overwrite either white space or slash */ + tfu->reps = atoi(savep); + tfu->flags = F_SETREP; + /* bb_dump_skip trailing white space */ + p = bb_skip_whitespace(++p); + } + + /* bb_dump_skip slash and trailing white space */ + if (*p == '/') { + p = bb_skip_whitespace(++p); + } + + /* byte count */ + if (isdigit(*p)) { + for (savep = p; isdigit(*p); ++p); + if (!isspace(*p)) { + bb_error_msg_and_die("bad format {%s}", fmt); + } + tfu->bcnt = atoi(savep); + /* bb_dump_skip trailing white space */ + p = bb_skip_whitespace(++p); + } + + /* format */ + if (*p != '"') { + bb_error_msg_and_die("bad format {%s}", fmt); + } + for (savep = ++p; *p != '"';) { + if (*p++ == 0) { + bb_error_msg_and_die("bad format {%s}", fmt); + } + } + tfu->fmt = xmalloc(p - savep + 1); + strncpy(tfu->fmt, savep, p - savep); + tfu->fmt[p - savep] = '\0'; +/* escape(tfu->fmt); */ + + p1 = tfu->fmt; + + /* alphabetic escape sequences have to be done in place */ + for (p2 = p1;; ++p1, ++p2) { + if (!*p1) { + *p2 = *p1; + break; + } + if (*p1 == '\\') { + const char *cs = conv_str + 4; + ++p1; + *p2 = *p1; + do { + if (*p1 == cs[2]) { + *p2 = cs[0]; + break; + } + cs += 4; + } while (*cs); + } + } + + p++; + } +} + +/* + * Copyright (c) 1989 The Regents of the University of California. + * 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. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + */ diff --git a/release/src/router/busybox/libbb/error_msg.c b/release/src/router/busybox/libbb/error_msg.c new file mode 100644 index 00000000..c7d5fdb9 --- /dev/null +++ b/release/src/router/busybox/libbb/error_msg.c @@ -0,0 +1,52 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include "libbb.h" + +extern void error_msg(const char *s, ...) +{ + va_list p; + + va_start(p, s); + verror_msg(s, p); + va_end(p); + putc('\n', stderr); +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/error_msg_and_die.c b/release/src/router/busybox/libbb/error_msg_and_die.c new file mode 100644 index 00000000..b950ee00 --- /dev/null +++ b/release/src/router/busybox/libbb/error_msg_and_die.c @@ -0,0 +1,53 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include "libbb.h" + +extern void error_msg_and_die(const char *s, ...) +{ + va_list p; + + va_start(p, s); + verror_msg(s, p); + va_end(p); + putc('\n', stderr); + exit(EXIT_FAILURE); +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/fclose_nonstdin.c b/release/src/router/busybox/libbb/fclose_nonstdin.c new file mode 100644 index 00000000..97e303e9 --- /dev/null +++ b/release/src/router/busybox/libbb/fclose_nonstdin.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* + * fclose_nonstdin implementation for busybox + * + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* A number of standard utilites can accept multiple command line args + * of '-' for stdin, according to SUSv3. So we encapsulate the check + * here to save a little space. + */ + +#include <stdio.h> +#include <libbb.h> + +int bb_fclose_nonstdin(FILE *f) +{ + if (f != stdin) { + return fclose(f); + } + return 0; +} diff --git a/release/src/router/busybox/libbb/fflush_stdout_and_exit.c b/release/src/router/busybox/libbb/fflush_stdout_and_exit.c new file mode 100644 index 00000000..cbba0420 --- /dev/null +++ b/release/src/router/busybox/libbb/fflush_stdout_and_exit.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* + * fflush_stdout_and_exit implementation for busybox + * + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* Attempt to fflush(stdout), and exit with an error code if stdout is + * in an error state. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <libbb.h> + +void bb_fflush_stdout_and_exit(int retval) +{ + if (fflush(stdout)) { + retval = bb_default_error_retval; + } + exit(retval); +} diff --git a/release/src/router/busybox/libbb/fgets_str.c b/release/src/router/busybox/libbb/fgets_str.c new file mode 100644 index 00000000..33d8d00c --- /dev/null +++ b/release/src/router/busybox/libbb/fgets_str.c @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * Continue reading from file until the terminating string is encountered. + * Return data as string. + * e.g. fgets_str(file, "\n"); will read till end of file + */ + +char *fgets_str(FILE *file, const char *terminating_string) +{ + char *linebuf = NULL; + const int term_length = strlen(terminating_string); + int end_string_offset; + int linebufsz = 0; + int idx = 0; + int ch; + + while (1) { + ch = fgetc(file); + if (ch == EOF) { + break; + } + + /* grow the line buffer as necessary */ + while (idx > linebufsz - 2) { + linebuf = realloc(linebuf, linebufsz += 1000); /* GROWBY */ + } + + linebuf[idx] = ch; + idx++; + + /* Check for terminating string */ + end_string_offset = idx - term_length; + if ((end_string_offset > 0) && (memcmp(&linebuf[end_string_offset], terminating_string, term_length) == 0)) { + idx -= term_length; + break; + } + } + if (idx == 0) { + return NULL; + } + linebuf[idx] = '\0'; + return(linebuf); +} + diff --git a/release/src/router/busybox/libbb/find_mount_point.c b/release/src/router/busybox/libbb/find_mount_point.c new file mode 100644 index 00000000..2d9481a6 --- /dev/null +++ b/release/src/router/busybox/libbb/find_mount_point.c @@ -0,0 +1,81 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include "libbb.h" + + +#include <mntent.h> +/* + * Given a block device, find the mount table entry if that block device + * is mounted. + * + * Given any other file (or directory), find the mount table entry for its + * filesystem. + */ +extern struct mntent *find_mount_point(const char *name, const char *table) +{ + struct stat s; + dev_t mountDevice; + FILE *mountTable; + struct mntent *mountEntry; + + if (stat(name, &s) != 0) + return 0; + + if ((s.st_mode & S_IFMT) == S_IFBLK) + mountDevice = s.st_rdev; + else + mountDevice = s.st_dev; + + + if ((mountTable = setmntent(table, "r")) == 0) + return 0; + + while ((mountEntry = getmntent(mountTable)) != 0) { + if (strcmp(name, mountEntry->mnt_dir) == 0 + || strcmp(name, mountEntry->mnt_fsname) == 0) /* String match. */ + break; + if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == mountDevice) /* Match the device. */ + break; + if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == mountDevice) /* Match the directory's mount point. */ + break; + } + endmntent(mountTable); + return mountEntry; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/find_pid_by_name.c b/release/src/router/busybox/libbb/find_pid_by_name.c new file mode 100644 index 00000000..7f39dd41 --- /dev/null +++ b/release/src/router/busybox/libbb/find_pid_by_name.c @@ -0,0 +1,199 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <dirent.h> +#include <stdlib.h> +#include "libbb.h" + +#define READ_BUF_SIZE 50 + + +/* For Erik's nifty devps device driver */ +#ifdef BB_FEATURE_USE_DEVPS_PATCH +#include <linux/devps.h> + +/* find_pid_by_name() + * + * This finds the pid of the specified process, + * by using the /dev/ps device driver. + * + * Returns a list of all matching PIDs + */ +extern pid_t* find_pid_by_name( char* pidName) +{ + int fd, i, j; + char device[] = "/dev/ps"; + pid_t num_pids; + pid_t* pid_array = NULL; + pid_t* pidList=NULL; + + /* open device */ + fd = open(device, O_RDONLY); + if (fd < 0) + perror_msg_and_die("open failed for `%s'", device); + + /* Find out how many processes there are */ + if (ioctl (fd, DEVPS_GET_NUM_PIDS, &num_pids)<0) + perror_msg_and_die("\nDEVPS_GET_PID_LIST"); + + /* Allocate some memory -- grab a few extras just in case + * some new processes start up while we wait. The kernel will + * just ignore any extras if we give it too many, and will trunc. + * the list if we give it too few. */ + pid_array = (pid_t*) xcalloc( num_pids+10, sizeof(pid_t)); + pid_array[0] = num_pids+10; + + /* Now grab the pid list */ + if (ioctl (fd, DEVPS_GET_PID_LIST, pid_array)<0) + perror_msg_and_die("\nDEVPS_GET_PID_LIST"); + + /* Now search for a match */ + for (i=1, j=0; i<pid_array[0] ; i++) { + char* p; + struct pid_info info; + + info.pid = pid_array[i]; + if (ioctl (fd, DEVPS_GET_PID_INFO, &info)<0) + perror_msg_and_die("\nDEVPS_GET_PID_INFO"); + + /* Make sure we only match on the process name */ + p=info.command_line+1; + while ((*p != 0) && !isspace(*(p)) && (*(p-1) != '\\')) { + (p)++; + } + if (isspace(*(p))) + *p='\0'; + + if ((strstr(info.command_line, pidName) != NULL) + && (strlen(pidName) == strlen(info.command_line))) { + pidList=xrealloc( pidList, sizeof(pid_t) * (j+2)); + pidList[j++]=info.pid; + } + } + if (pidList) { + pidList[j]=0; + } else if ( strcmp(pidName, "init")==0) { + /* If we found nothing and they were trying to kill "init", + * guess PID 1 and call it good... Perhaps we should simply + * exit if /proc isn't mounted, but this will do for now. */ + pidList=xrealloc( pidList, sizeof(pid_t)); + pidList[0]=1; + } else { + pidList=xrealloc( pidList, sizeof(pid_t)); + pidList[0]=-1; + } + + /* Free memory */ + free( pid_array); + + /* close device */ + if (close (fd) != 0) + perror_msg_and_die("close failed for `%s'", device); + + return pidList; +} + +#else /* BB_FEATURE_USE_DEVPS_PATCH */ + +/* find_pid_by_name() + * + * This finds the pid of the specified process. + * Currently, it's implemented by rummaging through + * the proc filesystem. + * + * Returns a list of all matching PIDs + */ +extern pid_t* find_pid_by_name( char* pidName) +{ + DIR *dir; + struct dirent *next; + pid_t* pidList=NULL; + int i=0; + + dir = opendir("/proc"); + if (!dir) + perror_msg_and_die("Cannot open /proc"); + + while ((next = readdir(dir)) != NULL) { + FILE *status; + char filename[READ_BUF_SIZE]; + char buffer[READ_BUF_SIZE]; + char name[READ_BUF_SIZE]; + + /* Must skip ".." since that is outside /proc */ + if (strcmp(next->d_name, "..") == 0) + continue; + + /* If it isn't a number, we don't want it */ + if (!isdigit(*next->d_name)) + continue; + + sprintf(filename, "/proc/%s/status", next->d_name); + if (! (status = fopen(filename, "r")) ) { + continue; + } + if (fgets(buffer, READ_BUF_SIZE-1, status) == NULL) { + fclose(status); + continue; + } + fclose(status); + + /* Buffer should contain a string like "Name: binary_name" */ + sscanf(buffer, "%*s %s", name); + if (strcmp(name, pidName) == 0) { + pidList=xrealloc( pidList, sizeof(pid_t) * (i+2)); + pidList[i++]=strtol(next->d_name, NULL, 0); + } + } + + if (pidList) + pidList[i]=0; + else if ( strcmp(pidName, "init")==0) { + /* If we found nothing and they were trying to kill "init", + * guess PID 1 and call it good... Perhaps we should simply + * exit if /proc isn't mounted, but this will do for now. */ + pidList=xrealloc( pidList, sizeof(pid_t)); + pidList[0]=1; + } else { + pidList=xrealloc( pidList, sizeof(pid_t)); + pidList[0]=-1; + } + return pidList; +} +#endif /* BB_FEATURE_USE_DEVPS_PATCH */ + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/find_root_device.c b/release/src/router/busybox/libbb/find_root_device.c new file mode 100644 index 00000000..f8f68464 --- /dev/null +++ b/release/src/router/busybox/libbb/find_root_device.c @@ -0,0 +1,84 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000,2001 by Lineo, inc. + * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> + * + * Patched by a bunch of people. Feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdio.h> +#include <string.h> +#include <dirent.h> +#include <stdlib.h> +#include "libbb.h" + + + +extern char *find_real_root_device_name(const char* name) +{ + DIR *dir; + struct dirent *entry; + struct stat statBuf, rootStat; + char *fileName = NULL; + dev_t dev; + + if (stat("/", &rootStat) != 0) + perror_msg("could not stat '/'"); + else { + if ((dev = rootStat.st_rdev)==0) + dev=rootStat.st_dev; + + dir = opendir("/dev"); + if (!dir) + perror_msg("could not open '/dev'"); + else { + while((entry = readdir(dir)) != NULL) { + + /* Must skip ".." since that is "/", and so we + * would get a false positive on ".." */ + if (strcmp(entry->d_name, "..") == 0) + continue; + + fileName = concat_path_file("/dev", entry->d_name); + + /* Some char devices have the same dev_t as block + * devices, so make sure this is a block device */ + if (stat(fileName, &statBuf) == 0 && + S_ISBLK(statBuf.st_mode)!=0 && + statBuf.st_rdev == dev) + break; + free(fileName); + fileName=NULL; + } + closedir(dir); + } + } + if(fileName==NULL) + fileName=xstrdup("/dev/root"); + return fileName; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/full_read.c b/release/src/router/busybox/libbb/full_read.c new file mode 100644 index 00000000..e9c4bbfc --- /dev/null +++ b/release/src/router/busybox/libbb/full_read.c @@ -0,0 +1,70 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <unistd.h> +#include "libbb.h" + + +/* + * Read all of the supplied buffer from a file. + * This does multiple reads as necessary. + * Returns the amount read, or -1 on an error. + * A short read is returned on an end of file. + */ +int full_read(int fd, char *buf, int len) +{ + int cc; + int total; + + total = 0; + + while (len > 0) { + cc = read(fd, buf, len); + + if (cc < 0) + return -1; + + if (cc == 0) + break; + + buf += cc; + total += cc; + len -= cc; + } + + return total; +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/full_write.c b/release/src/router/busybox/libbb/full_write.c new file mode 100644 index 00000000..dc9937fa --- /dev/null +++ b/release/src/router/busybox/libbb/full_write.c @@ -0,0 +1,66 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <unistd.h> +#include "libbb.h" + +/* + * Write all of the supplied buffer out to a file. + * This does multiple writes as necessary. + * Returns the amount written, or -1 on an error. + */ +int full_write(int fd, const char *buf, int len) +{ + int cc; + int total; + + total = 0; + + while (len > 0) { + cc = write(fd, buf, len); + + if (cc < 0) + return -1; + + buf += cc; + total += cc; + len -= cc; + } + + return total; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/get_console.c b/release/src/router/busybox/libbb/get_console.c new file mode 100644 index 00000000..3b36a59e --- /dev/null +++ b/release/src/router/busybox/libbb/get_console.c @@ -0,0 +1,129 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include "libbb.h" + + + + + +/* From <linux/kd.h> */ +static const int KDGKBTYPE = 0x4B33; /* get keyboard type */ +static const int KB_84 = 0x01; +static const int KB_101 = 0x02; /* this is what we always answer */ + +int is_a_console(int fd) +{ + char arg; + + arg = 0; + return (ioctl(fd, KDGKBTYPE, &arg) == 0 + && ((arg == KB_101) || (arg == KB_84))); +} + +static int open_a_console(char *fnam) +{ + int fd; + + /* try read-only */ + fd = open(fnam, O_RDWR); + + /* if failed, try read-only */ + if (fd < 0 && errno == EACCES) + fd = open(fnam, O_RDONLY); + + /* if failed, try write-only */ + if (fd < 0 && errno == EACCES) + fd = open(fnam, O_WRONLY); + + /* if failed, fail */ + if (fd < 0) + return -1; + + /* if not a console, fail */ + if (!is_a_console(fd)) { + close(fd); + return -1; + } + + /* success */ + return fd; +} + +/* + * Get an fd for use with kbd/console ioctls. + * We try several things because opening /dev/console will fail + * if someone else used X (which does a chown on /dev/console). + * + * if tty_name is non-NULL, try this one instead. + */ + +int get_console_fd(char *tty_name) +{ + int fd; + + if (tty_name) { + if (-1 == (fd = open_a_console(tty_name))) + return -1; + else + return fd; + } + + fd = open_a_console(CURRENT_TTY); + if (fd >= 0) + return fd; + + fd = open_a_console(CURRENT_VC); + if (fd >= 0) + return fd; + + fd = open_a_console(CONSOLE_DEV); + if (fd >= 0) + return fd; + + for (fd = 0; fd < 3; fd++) + if (is_a_console(fd)) + return fd; + + error_msg("Couldn't get a file descriptor referring to the console"); + return -1; /* total failure */ +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/get_last_path_component.c b/release/src/router/busybox/libbb/get_last_path_component.c new file mode 100644 index 00000000..f1ddfbde --- /dev/null +++ b/release/src/router/busybox/libbb/get_last_path_component.c @@ -0,0 +1,71 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include "libbb.h" + + +char *get_last_path_component(char *path) +{ + char *s; + register char *ptr = path; + register char *prev = 0; + + while (*ptr) + ptr++; + s = ptr - 1; + + /* strip trailing slashes */ + while (s != path && *s == '/') { + *s-- = '\0'; + } + + /* find last component */ + ptr = path; + while (*ptr != '\0') { + if (*ptr == '/') + prev = ptr; + ptr++; + } + s = prev; + + if (s == NULL || s[1] == '\0') + return path; + else + return s+1; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/get_line_from_file.c b/release/src/router/busybox/libbb/get_line_from_file.c new file mode 100644 index 00000000..75948173 --- /dev/null +++ b/release/src/router/busybox/libbb/get_line_from_file.c @@ -0,0 +1,72 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include "libbb.h" + + + +/* get_line_from_file() - This function reads an entire line from a text file + * up to a newline. It returns a malloc'ed char * which must be stored and + * free'ed by the caller. */ +extern char *get_line_from_file(FILE *file) +{ + static const int GROWBY = 80; /* how large we will grow strings by */ + + int ch; + int idx = 0; + char *linebuf = NULL; + int linebufsz = 0; + + while (1) { + ch = fgetc(file); + if (ch == EOF) + break; + /* grow the line buffer as necessary */ + while (idx > linebufsz-2) + linebuf = xrealloc(linebuf, linebufsz += GROWBY); + linebuf[idx++] = (char)ch; + if ((char)ch == '\n') + break; + } + + if (idx == 0) + return NULL; + + linebuf[idx] = 0; + return linebuf; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/getopt_ulflags.c b/release/src/router/busybox/libbb/getopt_ulflags.c new file mode 100644 index 00000000..9bf8c055 --- /dev/null +++ b/release/src/router/busybox/libbb/getopt_ulflags.c @@ -0,0 +1,170 @@ +/* vi: set sw=4 ts=4: */ +/* + * universal getopt_ulflags implementation for busybox + * + * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <getopt.h> +#include <string.h> +#include <assert.h> +#include <stdlib.h> +#include "libbb.h" + +/* +You can set bb_opt_complementaly as string with one or more +complementaly or incongruously options. +If sequential founded option haved from this string +then your incongruously pairs unsets and complementaly make add sets. +Format: +one char - option for check, +chars - complementaly option for add sets. +- chars - option triggered for unsets. +~ chars - option incongruously. +* - option list, called add_to_list(*ptr_from_usaged, optarg) +: - separator. +Example: du applet can have options "-s" and "-d size" +If getopt found -s then -d option flag unset or if found -d then -s unset. +For this result you must set bb_opt_complementaly = "s-d:d-s". +Result have last option flag only from called arguments. +Warning! You can check returned flag, pointer to "d:" argument seted +to own optarg always. +Example two: cut applet must only one type of list may be specified, +and -b, -c and -f incongruously option, overwited option is error also. +You must set bb_opt_complementaly = "b~bcf:c~bcf:f~bcf". +If called have more one specified, return value have error flag - +high bite set (0x80000000UL). +Example three: grep applet can have one or more "-e pattern" arguments. +You should use bb_getopt_ulflags() as +llist_t *paterns; +bb_opt_complementaly = "e*"; +bb_getopt_ulflags (argc, argv, "e:", &paterns); +*/ + +const char *bb_opt_complementaly; + +typedef struct +{ + char opt; + char list_flg; + unsigned long switch_on; + unsigned long switch_off; + unsigned long incongruously; + void **optarg; /* char **optarg or llist_t **optarg */ +} t_complementaly; + +/* You can set bb_applet_long_options for parse called long options */ + +static const struct option bb_default_long_options[] = { + /* { "help", 0, NULL, '?' }, */ + { 0, 0, 0, 0 } +}; + +const struct option *bb_applet_long_options = bb_default_long_options; + + +unsigned long +bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) +{ + unsigned long flags = 0; + int c = 0; + const char *s; + t_complementaly *complementaly; + t_complementaly *on_off; + va_list p; + + va_start (p, applet_opts); + + for (s = applet_opts; *s; s++) { + c++; + while (s[1] == ':') { + /* check GNU extension "o::" - optional arg */ + s++; + } + } + complementaly = xcalloc (c + 1, sizeof (t_complementaly)); + c = 0; + for (s = applet_opts; *s; s++) { + complementaly->opt = *s; + complementaly->switch_on |= (1 << c); + c++; + if (s[1] == ':') { + complementaly->optarg = va_arg (p, void **); + do + s++; + while (s[1] == ':'); + } + complementaly++; + } + complementaly->opt = 0; + complementaly -= c; + c = 0; + for (s = bb_opt_complementaly; s && *s; s++) { + t_complementaly *pair; + + if (*s == ':') { + c = 0; + continue; + } + if (c) + continue; + for (on_off = complementaly; on_off->opt; on_off++) + if (on_off->opt == *s) + break; + pair = on_off; + for(s++; *s && *s != ':'; s++) { + if (*s == '-' || *s == '~') { + c = *s; + } else if(*s == '*') { + pair->list_flg++; + } else { + unsigned long *pair_switch = &(pair->switch_on); + + if(c) + pair_switch = c == '-' ? &(pair->switch_off) : &(pair->incongruously); + for (on_off = complementaly; on_off->opt; on_off++) + if (on_off->opt == *s) { + *pair_switch |= on_off->switch_on; + break; + } + } + } + s--; + } + + while ((c = getopt_long (argc, argv, applet_opts, + bb_applet_long_options, NULL)) > 0) { + + for (on_off = complementaly; on_off->opt != c; on_off++) { + if(!on_off->opt) + bb_show_usage (); + } + if(flags & on_off->incongruously) + flags |= 0x80000000UL; + flags &= ~on_off->switch_off; + flags |= on_off->switch_on; + if(on_off->list_flg) { + *(llist_t **)(on_off->optarg) = + llist_add_to(*(llist_t **)(on_off->optarg), optarg); + } else if (on_off->optarg) { + *(char **)(on_off->optarg) = optarg; + } + } + free(complementaly); + return flags; +} diff --git a/release/src/router/busybox/libbb/gz_open.c b/release/src/router/busybox/libbb/gz_open.c new file mode 100644 index 00000000..ef30ff89 --- /dev/null +++ b/release/src/router/busybox/libbb/gz_open.c @@ -0,0 +1,35 @@ +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "libbb.h" + +extern FILE *gz_open(FILE *compressed_file, int *pid) +{ + int unzip_pipe[2]; + + if (pipe(unzip_pipe)!=0) { + error_msg("pipe error"); + return(NULL); + } + if ((*pid = fork()) == -1) { + error_msg("fork failed"); + return(NULL); + } + if (*pid==0) { + /* child process */ + close(unzip_pipe[0]); + unzip(compressed_file, fdopen(unzip_pipe[1], "w")); + fflush(NULL); + fclose(compressed_file); + close(unzip_pipe[1]); + exit(EXIT_SUCCESS); + } + close(unzip_pipe[1]); + if (unzip_pipe[0] == -1) { + error_msg("gzip stream init failed"); + } + return(fdopen(unzip_pipe[0], "r")); +} diff --git a/release/src/router/busybox/libbb/herror_msg.c b/release/src/router/busybox/libbb/herror_msg.c new file mode 100644 index 00000000..f4210eda --- /dev/null +++ b/release/src/router/busybox/libbb/herror_msg.c @@ -0,0 +1,50 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdarg.h> +#include <stdlib.h> + +#include "libbb.h" + +extern void herror_msg(const char *s, ...) +{ + va_list p; + + va_start(p, s); + vherror_msg(s, p); + va_end(p); +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/herror_msg_and_die.c b/release/src/router/busybox/libbb/herror_msg_and_die.c new file mode 100644 index 00000000..0df5ed01 --- /dev/null +++ b/release/src/router/busybox/libbb/herror_msg_and_die.c @@ -0,0 +1,51 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdarg.h> +#include <stdlib.h> + +#include "libbb.h" + +extern void herror_msg_and_die(const char *s, ...) +{ + va_list p; + + va_start(p, s); + vherror_msg(s, p); + va_end(p); + exit(EXIT_FAILURE); +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/human_readable.c b/release/src/router/busybox/libbb/human_readable.c new file mode 100644 index 00000000..21e13dc4 --- /dev/null +++ b/release/src/router/busybox/libbb/human_readable.c @@ -0,0 +1,78 @@ +/* + * June 30, 2001 Manuel Novoa III + * + * All-integer version (hey, not everyone has floating point) of + * make_human_readable_str, modified from similar code I had written + * for busybox several months ago. + * + * Notes: + * 1) I'm using an unsigned long long to hold the product size * block_size, + * as df (which calls this routine) could request a representation of a + * partition size in bytes > max of unsigned long. If long longs aren't + * available, it would be possible to do what's needed using polynomial + * representations (say, powers of 1024) and manipulating coefficients. + * The base ten "bytes" output could be handled similarly. + * + * 2) This routine always outputs a decimal point and a tenths digit when + * display_unit != 0. Hence, it isn't uncommon for the returned string + * to have a length of 5 or 6. + * + * It might be nice to add a flag to indicate no decimal digits in + * that case. This could be either an additional parameter, or a + * special value of display_unit. Such a flag would also be nice for du. + * + * Some code to omit the decimal point and tenths digit is sketched out + * and "#if 0"'d below. + */ + +#include <stdio.h> +#include "libbb.h" + +const char *make_human_readable_str(unsigned long size, + unsigned long block_size, + unsigned long display_unit) +{ + /* The code will adjust for additional (appended) units. */ + static const char zero_and_units[] = { '0', 0, 'k', 'M', 'G', 'T' }; + static const char fmt[] = "%Lu"; + static const char fmt_tenths[] = "%Lu.%d%c"; + + static char str[21]; /* Sufficient for 64 bit unsigned integers. */ + + unsigned long long val; + int frac; + const char *u; + const char *f; + + u = zero_and_units; + f = fmt; + frac = 0; + + val = ((unsigned long long) size) * block_size; + if (val == 0) { + return u; + } + + if (display_unit) { + val += display_unit/2; /* Deal with rounding. */ + val /= display_unit; /* Don't combine with the line above!!! */ + } else { + ++u; + while ((val >= KILOBYTE) + && (u < zero_and_units + sizeof(zero_and_units) - 1)) { + f = fmt_tenths; + ++u; + frac = ((((int)(val % KILOBYTE)) * 10) + (KILOBYTE/2)) / KILOBYTE; + val /= KILOBYTE; + } + if (frac >= 10) { /* We need to round up here. */ + ++val; + frac = 0; + } + } + + /* If f==fmt then 'frac' and 'u' are ignored. */ + snprintf(str, sizeof(str), f, val, frac, *u); + + return str; +} diff --git a/release/src/router/busybox/libbb/inet_common.c b/release/src/router/busybox/libbb/inet_common.c new file mode 100644 index 00000000..4e574ea5 --- /dev/null +++ b/release/src/router/busybox/libbb/inet_common.c @@ -0,0 +1,249 @@ +/* + * stolen from net-tools-1.59 and stripped down for busybox by + * Erik Andersen <andersen@codepoet.org> + * + * Heavily modified by Manuel Novoa III Mar 12, 2001 + * + * Version: $Id: inet_common.c,v 1.1.3.1 2004/12/29 07:07:45 honor Exp $ + * + */ + +#include "inet_common.h" +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "libbb.h" + +#ifdef DEBUG +# include <resolv.h> +#endif + + +const char bb_INET_default[] = "default"; + +int INET_resolve(const char *name, struct sockaddr_in *s_in, int hostfirst) +{ + struct hostent *hp; + struct netent *np; + + /* Grmpf. -FvK */ + s_in->sin_family = AF_INET; + s_in->sin_port = 0; + + /* Default is special, meaning 0.0.0.0. */ + if (!strcmp(name, bb_INET_default)) { + s_in->sin_addr.s_addr = INADDR_ANY; + return (1); + } + /* Look to see if it's a dotted quad. */ + if (inet_aton(name, &s_in->sin_addr)) { + return 0; + } + /* If we expect this to be a hostname, try hostname database first */ +#ifdef DEBUG + if (hostfirst) { + bb_error_msg("gethostbyname (%s)", name); + } +#endif + if (hostfirst && (hp = gethostbyname(name)) != (struct hostent *) NULL) { + memcpy((char *) &s_in->sin_addr, (char *) hp->h_addr_list[0], + sizeof(struct in_addr)); + return 0; + } + /* Try the NETWORKS database to see if this is a known network. */ +#ifdef DEBUG + bb_error_msg("getnetbyname (%s)", name); +#endif + if ((np = getnetbyname(name)) != (struct netent *) NULL) { + s_in->sin_addr.s_addr = htonl(np->n_net); + return 1; + } + if (hostfirst) { + /* Don't try again */ + errno = h_errno; + return -1; + } +#ifdef DEBUG + res_init(); + _res.options |= RES_DEBUG; +#endif + +#ifdef DEBUG + bb_error_msg("gethostbyname (%s)", name); +#endif + if ((hp = gethostbyname(name)) == (struct hostent *) NULL) { + errno = h_errno; + return -1; + } + memcpy((char *) &s_in->sin_addr, (char *) hp->h_addr_list[0], + sizeof(struct in_addr)); + + return 0; +} + +/* cache */ +struct addr { + struct sockaddr_in addr; + char *name; + int host; + struct addr *next; +}; + +static struct addr *INET_nn = NULL; /* addr-to-name cache */ + +/* numeric: & 0x8000: default instead of *, + * & 0x4000: host instead of net, + * & 0x0fff: don't resolve + */ +int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, + int numeric, unsigned int netmask) +{ + struct hostent *ent; + struct netent *np; + struct addr *pn; + unsigned long ad, host_ad; + int host = 0; + + /* Grmpf. -FvK */ + if (s_in->sin_family != AF_INET) { +#ifdef DEBUG + bb_error_msg("rresolve: unsupport address family %d !", + s_in->sin_family); +#endif + errno = EAFNOSUPPORT; + return (-1); + } + ad = (unsigned long) s_in->sin_addr.s_addr; +#ifdef DEBUG + bb_error_msg("rresolve: %08lx, mask %08x, num %08x", ad, netmask, numeric); +#endif + if (ad == INADDR_ANY) { + if ((numeric & 0x0FFF) == 0) { + if (numeric & 0x8000) + safe_strncpy(name, bb_INET_default, len); + else + safe_strncpy(name, "*", len); + return (0); + } + } + if (numeric & 0x0FFF) { + safe_strncpy(name, inet_ntoa(s_in->sin_addr), len); + return (0); + } + + if ((ad & (~netmask)) != 0 || (numeric & 0x4000)) + host = 1; +#if 0 + INET_nn = NULL; +#endif + pn = INET_nn; + while (pn != NULL) { + if (pn->addr.sin_addr.s_addr == ad && pn->host == host) { + safe_strncpy(name, pn->name, len); +#ifdef DEBUG + bb_error_msg("rresolve: found %s %08lx in cache", + (host ? "host" : "net"), ad); +#endif + return (0); + } + pn = pn->next; + } + + host_ad = ntohl(ad); + np = NULL; + ent = NULL; + if (host) { +#ifdef DEBUG + bb_error_msg("gethostbyaddr (%08lx)", ad); +#endif + ent = gethostbyaddr((char *) &ad, 4, AF_INET); + if (ent != NULL) { + safe_strncpy(name, ent->h_name, len); + } + } else { +#ifdef DEBUG + bb_error_msg("getnetbyaddr (%08lx)", host_ad); +#endif + np = getnetbyaddr(host_ad, AF_INET); + if (np != NULL) { + safe_strncpy(name, np->n_name, len); + } + } + if ((ent == NULL) && (np == NULL)) { + safe_strncpy(name, inet_ntoa(s_in->sin_addr), len); + } + pn = (struct addr *) xmalloc(sizeof(struct addr)); + pn->addr = *s_in; + pn->next = INET_nn; + pn->host = host; + pn->name = bb_xstrdup(name); + INET_nn = pn; + + return (0); +} + +#ifdef CONFIG_FEATURE_IPV6 + +int INET6_resolve(char *name, struct sockaddr_in6 *sin6) +{ + struct addrinfo req, *ai; + int s; + + memset(&req, '\0', sizeof req); + req.ai_family = AF_INET6; + if ((s = getaddrinfo(name, NULL, &req, &ai))) { + bb_error_msg("getaddrinfo: %s: %d", name, s); + return -1; + } + memcpy(sin6, ai->ai_addr, sizeof(struct sockaddr_in6)); + + freeaddrinfo(ai); + + return (0); +} + +#ifndef IN6_IS_ADDR_UNSPECIFIED +# define IN6_IS_ADDR_UNSPECIFIED(a) \ + (((__u32 *) (a))[0] == 0 && ((__u32 *) (a))[1] == 0 && \ + ((__u32 *) (a))[2] == 0 && ((__u32 *) (a))[3] == 0) +#endif + + +int INET6_rresolve(char *name, size_t len, struct sockaddr_in6 *sin6, + int numeric) +{ + int s; + + /* Grmpf. -FvK */ + if (sin6->sin6_family != AF_INET6) { +#ifdef DEBUG + bb_error_msg(_("rresolve: unsupport address family %d !\n"), + sin6->sin6_family); +#endif + errno = EAFNOSUPPORT; + return (-1); + } + if (numeric & 0x7FFF) { + inet_ntop(AF_INET6, &sin6->sin6_addr, name, len); + return (0); + } + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + if (numeric & 0x8000) { + strcpy(name, "default"); + } else { + strcpy(name, "*"); + } + return (0); + } + + s = getnameinfo((struct sockaddr *) sin6, sizeof(struct sockaddr_in6), name, len, NULL, 0, 0); + if (s) { + bb_error_msg("getnameinfo failed"); + return -1; + } + return (0); +} + +#endif /* CONFIG_FEATURE_IPV6 */ diff --git a/release/src/router/busybox/libbb/inode_hash.c b/release/src/router/busybox/libbb/inode_hash.c new file mode 100644 index 00000000..790af8f3 --- /dev/null +++ b/release/src/router/busybox/libbb/inode_hash.c @@ -0,0 +1,106 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "libbb.h" + +#define HASH_SIZE 311 /* Should be prime */ +#define hash_inode(i) ((i) % HASH_SIZE) + +static ino_dev_hashtable_bucket_t *ino_dev_hashtable[HASH_SIZE]; + +/* + * Return 1 if statbuf->st_ino && statbuf->st_dev are recorded in + * `ino_dev_hashtable', else return 0 + * + * If NAME is a non-NULL pointer to a character pointer, and there is + * a match, then set *NAME to the value of the name slot in that + * bucket. + */ +int is_in_ino_dev_hashtable(const struct stat *statbuf, char **name) +{ + ino_dev_hashtable_bucket_t *bucket; + + bucket = ino_dev_hashtable[hash_inode(statbuf->st_ino)]; + while (bucket != NULL) { + if ((bucket->ino == statbuf->st_ino) && + (bucket->dev == statbuf->st_dev)) + { + if (name) *name = bucket->name; + return 1; + } + bucket = bucket->next; + } + return 0; +} + +/* Add statbuf to statbuf hash table */ +void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name) +{ + int i; + size_t s; + ino_dev_hashtable_bucket_t *bucket; + + i = hash_inode(statbuf->st_ino); + s = name ? strlen(name) : 0; + bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + s); + bucket->ino = statbuf->st_ino; + bucket->dev = statbuf->st_dev; + if (name) + strcpy(bucket->name, name); + else + bucket->name[0] = '\0'; + bucket->next = ino_dev_hashtable[i]; + ino_dev_hashtable[i] = bucket; +} + +/* Clear statbuf hash table */ +void reset_ino_dev_hashtable(void) +{ + int i; + ino_dev_hashtable_bucket_t *bucket; + + for (i = 0; i < HASH_SIZE; i++) { + while (ino_dev_hashtable[i] != NULL) { + bucket = ino_dev_hashtable[i]->next; + free(ino_dev_hashtable[i]); + ino_dev_hashtable[i] = bucket; + } + } +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/interface.c b/release/src/router/busybox/libbb/interface.c new file mode 100644 index 00000000..4af35fcb --- /dev/null +++ b/release/src/router/busybox/libbb/interface.c @@ -0,0 +1,2113 @@ +/* + * ifconfig This file contains an implementation of the command + * that either displays or sets the characteristics of + * one or more of the system's networking interfaces. + * + * Version: $Id: interface.c,v 1.1.1.4 2003/10/14 08:09:39 sparq Exp $ + * + * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> + * and others. Copyright 1993 MicroWalt Corporation + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * Patched to support 'add' and 'del' keywords for INET(4) addresses + * by Mrs. Brisby <mrs.brisby@nimh.org> + * + * {1.34} - 19980630 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> + * - gettext instead of catgets for i18n + * 10/1998 - Andi Kleen. Use interface list primitives. + * 20001008 - Bernd Eckenfels, Patch from RH for setting mtu + * (default AF was wrong) + * stolen from net-tools-1.59 and stripped down for busybox by + * Erik Andersen <andersee@debian.org> + */ + +/* + * Heavily modified by Manuel Novoa III Mar 12, 2001 + * + * Pruned unused code using KEEP_UNUSED define. + * Added print_bytes_scaled function to reduce code size. + * Added some (potentially) missing defines. + * Improved display support for -a and for a named interface. + */ + +/* #define KEEP_UNUSED */ + +/* + * + * Protocol Families. + * + */ +#define HAVE_AFINET 1 +#undef HAVE_AFINET6 +#undef HAVE_AFIPX +#undef HAVE_AFATALK +#undef HAVE_AFNETROM +#undef HAVE_AFX25 +#undef HAVE_AFECONET +#undef HAVE_AFASH + +/* + * + * Device Hardware types. + * + */ +#define HAVE_HWETHER 1 +#define HAVE_HWPPP 1 +#undef HAVE_HWSLIP + + +#include <features.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <net/if.h> +#include <net/if_arp.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <netdb.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "libbb.h" + +#define _(x) x +#define _PATH_PROCNET_DEV "/proc/net/dev" +#define new(p) ((p) = xcalloc(1,sizeof(*(p)))) +#define KRELEASE(maj,min,patch) ((maj) * 65536 + (min)*256 + (patch)) + +static int procnetdev_vsn = 1; + + +/* Ugh. But libc5 doesn't provide POSIX types. */ +#include <asm/types.h> + + +#ifdef HAVE_HWSLIP +#include <linux/if_slip.h> +#endif + +#if HAVE_AFINET6 + +#ifndef _LINUX_IN6_H +/* + * This is in linux/include/net/ipv6.h. + */ + +struct in6_ifreq { + struct in6_addr ifr6_addr; + __u32 ifr6_prefixlen; + unsigned int ifr6_ifindex; +}; + +#endif + +#endif /* HAVE_AFINET6 */ + +#if HAVE_AFIPX +#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) +#include <netipx/ipx.h> +#else +#include "ipx.h" +#endif +#endif + +/* Defines for glibc2.0 users. */ +#ifndef SIOCSIFTXQLEN +#define SIOCSIFTXQLEN 0x8943 +#define SIOCGIFTXQLEN 0x8942 +#endif + +/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */ +#ifndef ifr_qlen +#define ifr_qlen ifr_ifru.ifru_mtu +#endif + +#ifndef HAVE_TXQUEUELEN +#define HAVE_TXQUEUELEN 1 +#endif + +#ifndef IFF_DYNAMIC +#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */ +#endif + +/* This structure defines protocol families and their handlers. */ +struct aftype { + const char *name; + const char *title; + int af; + int alen; + char *(*print) (unsigned char *); + char *(*sprint) (struct sockaddr *, int numeric); + int (*input) (int type, char *bufp, struct sockaddr *); + void (*herror) (char *text); + int (*rprint) (int options); + int (*rinput) (int typ, int ext, char **argv); + + /* may modify src */ + int (*getmask) (char *src, struct sockaddr * mask, char *name); + + int fd; + char *flag_file; +}; + +static struct aftype *aftypes[]; + +#ifdef KEEP_UNUSED + +static int flag_unx; +#ifdef HAVE_AFIPX +static int flag_ipx; +#endif +#ifdef HAVE_AFX25 +static int flag_ax25; +#endif +#ifdef HAVE_AFATALK +static int flag_ddp; +#endif +#ifdef HAVE_AFNETROM +static int flag_netrom; +#endif +static int flag_inet; +#ifdef HAVE_AFINET6 +static int flag_inet6; +#endif +#ifdef HAVE_AFECONET +static int flag_econet; +#endif +#ifdef HAVE_AFX25 +static int flag_x25 = 0; +#endif +#ifdef HAVE_AFASH +static int flag_ash; +#endif + + +static struct aftrans_t { + char *alias; + char *name; + int *flag; +} aftrans[] = { + +#ifdef HAVE_AFX25 + { + "ax25", "ax25", &flag_ax25 + }, +#endif + { + "ip", "inet", &flag_inet + }, +#ifdef HAVE_AFINET6 + { + "ip6", "inet6", &flag_inet6 + }, +#endif +#ifdef HAVE_AFIPX + { + "ipx", "ipx", &flag_ipx + }, +#endif +#ifdef HAVE_AFATALK + { + "appletalk", "ddp", &flag_ddp + }, +#endif +#ifdef HAVE_AFNETROM + { + "netrom", "netrom", &flag_netrom + }, +#endif + { + "inet", "inet", &flag_inet + }, +#ifdef HAVE_AFINET6 + { + "inet6", "inet6", &flag_inet6 + }, +#endif +#ifdef HAVE_AFATALK + { + "ddp", "ddp", &flag_ddp + }, +#endif + { + "unix", "unix", &flag_unx + }, + { + "tcpip", "inet", &flag_inet + }, +#ifdef HAVE_AFECONET + { + "econet", "ec", &flag_econet + }, +#endif +#ifdef HAVE_AFX25 + { + "x25", "x25", &flag_x25 + }, +#endif +#ifdef HAVE_AFASH + { + "ash", "ash", &flag_ash + }, +#endif + { + 0, 0, 0 + } +}; + +static char afname[256] = ""; +#endif /* KEEP_UNUSED */ + +#if HAVE_AFUNIX + +/* Display a UNIX domain address. */ +static char *UNIX_print(unsigned char *ptr) +{ + return (ptr); +} + + +/* Display a UNIX domain address. */ +static char *UNIX_sprint(struct sockaddr *sap, int numeric) +{ + static char buf[64]; + + if (sap->sa_family == 0xFFFF || sap->sa_family == 0) + return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf)); + return (UNIX_print(sap->sa_data)); +} + + +static struct aftype unix_aftype = +{ + "unix", "UNIX Domain", AF_UNIX, 0, + UNIX_print, UNIX_sprint, NULL, NULL, + NULL, NULL, NULL, + -1, + "/proc/net/unix" +}; +#endif /* HAVE_AFUNIX */ + +#if HAVE_AFINET + + +/* cache */ +struct addr { + struct sockaddr_in addr; + char *name; + int host; + struct addr *next; +}; + +static struct addr *INET_nn = NULL; /* addr-to-name cache */ + +#ifdef KEEP_UNUSED +static int INET_resolve(char *name, struct sockaddr_in *sin, int hostfirst) +{ + struct hostent *hp; + struct netent *np; + + /* Grmpf. -FvK */ + sin->sin_family = AF_INET; + sin->sin_port = 0; + + /* Default is special, meaning 0.0.0.0. */ + if (!strcmp(name, "default")) { + sin->sin_addr.s_addr = INADDR_ANY; + return (1); + } + /* Look to see if it's a dotted quad. */ + if (inet_aton(name, &sin->sin_addr)) { + return 0; + } + /* If we expect this to be a hostname, try hostname database first */ +#ifdef DEBUG + if (hostfirst) fprintf (stderr, "gethostbyname (%s)\n", name); +#endif + if (hostfirst && + (hp = gethostbyname(name)) != (struct hostent *) NULL) { + memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], + sizeof(struct in_addr)); + return 0; + } + /* Try the NETWORKS database to see if this is a known network. */ +#ifdef DEBUG + fprintf (stderr, "getnetbyname (%s)\n", name); +#endif + if ((np = getnetbyname(name)) != (struct netent *) NULL) { + sin->sin_addr.s_addr = htonl(np->n_net); + return 1; + } + if (hostfirst) { + /* Don't try again */ + errno = h_errno; + return -1; + } +#ifdef DEBUG + res_init(); + _res.options |= RES_DEBUG; +#endif + +#ifdef DEBUG + fprintf (stderr, "gethostbyname (%s)\n", name); +#endif + if ((hp = gethostbyname(name)) == (struct hostent *) NULL) { + errno = h_errno; + return -1; + } + memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], + sizeof(struct in_addr)); + + return 0; +} +#endif /* KEEP_UNUSED */ + +/* numeric: & 0x8000: default instead of *, + * & 0x4000: host instead of net, + * & 0x0fff: don't resolve + */ +static int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, + int numeric, unsigned int netmask) +{ + struct hostent *ent; + struct netent *np; + struct addr *pn; + unsigned long ad, host_ad; + int host = 0; + + /* Grmpf. -FvK */ + if (s_in->sin_family != AF_INET) { +#ifdef DEBUG + fprintf(stderr, _("rresolve: unsupport address family %d !\n"), s_in->sin_family); +#endif + errno = EAFNOSUPPORT; + return (-1); + } + ad = (unsigned long) s_in->sin_addr.s_addr; +#ifdef DEBUG + fprintf (stderr, "rresolve: %08lx, mask %08x, num %08x \n", ad, netmask, numeric); +#endif + if (ad == INADDR_ANY) { + if ((numeric & 0x0FFF) == 0) { + if (numeric & 0x8000) + safe_strncpy(name, "default", len); + else + safe_strncpy(name, "*", len); + return (0); + } + } + if (numeric & 0x0FFF) { + safe_strncpy(name, inet_ntoa(s_in->sin_addr), len); + return (0); + } + + if ((ad & (~netmask)) != 0 || (numeric & 0x4000)) + host = 1; + pn = INET_nn; + while (pn != NULL) { + if (pn->addr.sin_addr.s_addr == ad && pn->host == host) { + safe_strncpy(name, pn->name, len); +#ifdef DEBUG + fprintf (stderr, "rresolve: found %s %08lx in cache\n", (host? "host": "net"), ad); +#endif + return (0); + } + pn = pn->next; + } + + host_ad = ntohl(ad); + np = NULL; + ent = NULL; + if (host) { +#ifdef DEBUG + fprintf (stderr, "gethostbyaddr (%08lx)\n", ad); +#endif + ent = gethostbyaddr((char *) &ad, 4, AF_INET); + if (ent != NULL) + safe_strncpy(name, ent->h_name, len); + } else { +#ifdef DEBUG + fprintf (stderr, "getnetbyaddr (%08lx)\n", host_ad); +#endif + } + if ((ent == NULL) && (np == NULL)) + safe_strncpy(name, inet_ntoa(s_in->sin_addr), len); + pn = (struct addr *) xmalloc(sizeof(struct addr)); + pn->addr = *s_in; + pn->next = INET_nn; + pn->host = host; + pn->name = (char *) xmalloc(strlen(name) + 1); + strcpy(pn->name, name); + INET_nn = pn; + + return (0); +} + +#ifdef KEEP_UNUSED +static void INET_reserror(char *text) +{ + herror(text); +} + +/* Display an Internet socket address. */ +static char *INET_print(unsigned char *ptr) +{ + return (inet_ntoa((*(struct in_addr *) ptr))); +} +#endif /* KEEP_UNUSED */ + +/* Display an Internet socket address. */ +static char *INET_sprint(struct sockaddr *sap, int numeric) +{ + static char buff[128]; + + if (sap->sa_family == 0xFFFF || sap->sa_family == 0) + return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); + + if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap, + numeric, 0xffffff00) != 0) + return (NULL); + + return (buff); +} + +#ifdef KEEP_UNUSED +static char *INET_sprintmask(struct sockaddr *sap, int numeric, + unsigned int netmask) +{ + static char buff[128]; + + if (sap->sa_family == 0xFFFF || sap->sa_family == 0) + return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); + if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap, + numeric, netmask) != 0) + return (NULL); + return (buff); +} + +static int INET_getsock(char *bufp, struct sockaddr *sap) +{ + char *sp = bufp, *bp; + unsigned int i; + unsigned val; + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *) sap; + sin->sin_family = AF_INET; + sin->sin_port = 0; + + val = 0; + bp = (char *) &val; + for (i = 0; i < sizeof(sin->sin_addr.s_addr); i++) { + *sp = toupper(*sp); + + if ((*sp >= 'A') && (*sp <= 'F')) + bp[i] |= (int) (*sp - 'A') + 10; + else if ((*sp >= '0') && (*sp <= '9')) + bp[i] |= (int) (*sp - '0'); + else + return (-1); + + bp[i] <<= 4; + sp++; + *sp = toupper(*sp); + + if ((*sp >= 'A') && (*sp <= 'F')) + bp[i] |= (int) (*sp - 'A') + 10; + else if ((*sp >= '0') && (*sp <= '9')) + bp[i] |= (int) (*sp - '0'); + else + return (-1); + + sp++; + } + sin->sin_addr.s_addr = htonl(val); + + return (sp - bufp); +} + +static int INET_input(int type, char *bufp, struct sockaddr *sap) +{ + switch (type) { + case 1: + return (INET_getsock(bufp, sap)); + case 256: + return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1)); + default: + return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0)); + } +} + +static int INET_getnetmask(char *adr, struct sockaddr *m, char *name) +{ + struct sockaddr_in *mask = (struct sockaddr_in *) m; + char *slash, *end; + int prefix; + + if ((slash = strchr(adr, '/')) == NULL) + return 0; + + *slash++ = '\0'; + prefix = strtoul(slash, &end, 0); + if (*end != '\0') + return -1; + + if (name) { + sprintf(name, "/%d", prefix); + } + mask->sin_family = AF_INET; + mask->sin_addr.s_addr = htonl(~(0xffffffffU >> prefix)); + return 1; +} +#endif /* KEEP_UNUSED */ + +static struct aftype inet_aftype = +{ + "inet", "DARPA Internet", AF_INET, sizeof(unsigned long), + NULL /* UNUSED INET_print */, INET_sprint, + NULL /* UNUSED INET_input */, NULL /* UNUSED INET_reserror */, + NULL /*INET_rprint */ , NULL /*INET_rinput */ , + NULL /* UNUSED INET_getnetmask */, + -1, + NULL +}; + +#endif /* HAVE_AFINET */ + +/* Display an UNSPEC address. */ +static char *UNSPEC_print(unsigned char *ptr) +{ + static char buff[sizeof(struct sockaddr)*3+1]; + char *pos; + unsigned int i; + + pos = buff; + for (i = 0; i < sizeof(struct sockaddr); i++) { + /* careful -- not every libc's sprintf returns # bytes written */ + sprintf(pos, "%02X-", (*ptr++ & 0377)); + pos += 3; + } + /* Erase trailing "-". Works as long as sizeof(struct sockaddr) != 0 */ + *--pos = '\0'; + return (buff); +} + +/* Display an UNSPEC socket address. */ +static char *UNSPEC_sprint(struct sockaddr *sap, int numeric) +{ + static char buf[64]; + + if (sap->sa_family == 0xFFFF || sap->sa_family == 0) + return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf)); + return (UNSPEC_print(sap->sa_data)); +} + +static struct aftype unspec_aftype = +{ + "unspec", "UNSPEC", AF_UNSPEC, 0, + UNSPEC_print, UNSPEC_sprint, NULL, NULL, + NULL, +}; + +static struct aftype *aftypes[] = +{ +#if HAVE_AFUNIX + &unix_aftype, +#endif +#if HAVE_AFINET + &inet_aftype, +#endif +#if HAVE_AFINET6 + &inet6_aftype, +#endif +#if HAVE_AFAX25 + &ax25_aftype, +#endif +#if HAVE_AFNETROM + &netrom_aftype, +#endif +#if HAVE_AFROSE + &rose_aftype, +#endif +#if HAVE_AFIPX + &ipx_aftype, +#endif +#if HAVE_AFATALK + &ddp_aftype, +#endif +#if HAVE_AFECONET + &ec_aftype, +#endif +#if HAVE_AFASH + &ash_aftype, +#endif +#if HAVE_AFX25 + &x25_aftype, +#endif + &unspec_aftype, + NULL +}; + +#ifdef KEEP_UNUSED +static short sVafinit = 0; + +static void afinit() +{ + unspec_aftype.title = _("UNSPEC"); +#if HAVE_AFUNIX + unix_aftype.title = _("UNIX Domain"); +#endif +#if HAVE_AFINET + inet_aftype.title = _("DARPA Internet"); +#endif +#if HAVE_AFINET6 + inet6_aftype.title = _("IPv6"); +#endif +#if HAVE_AFAX25 + ax25_aftype.title = _("AMPR AX.25"); +#endif +#if HAVE_AFNETROM + netrom_aftype.title = _("AMPR NET/ROM"); +#endif +#if HAVE_AFIPX + ipx_aftype.title = _("Novell IPX"); +#endif +#if HAVE_AFATALK + ddp_aftype.title = _("Appletalk DDP"); +#endif +#if HAVE_AFECONET + ec_aftype.title = _("Econet"); +#endif +#if HAVE_AFX25 + x25_aftype.title = _("CCITT X.25"); +#endif +#if HAVE_AFROSE + rose_aftype.title = _("AMPR ROSE"); +#endif +#if HAVE_AFASH + ash_aftype.title = _("Ash"); +#endif + sVafinit = 1; +} + +static int aftrans_opt(const char *arg) +{ + struct aftrans_t *paft; + char *tmp1, *tmp2; + char buf[256]; + + safe_strncpy(buf, arg, sizeof(buf)); + + tmp1 = buf; + + while (tmp1) { + + tmp2 = strchr(tmp1, ','); + + if (tmp2) + *(tmp2++) = '\0'; + + paft = aftrans; + for (paft = aftrans; paft->alias; paft++) { + if (strcmp(tmp1, paft->alias)) + continue; + if (strlen(paft->name) + strlen(afname) + 1 >= sizeof(afname)) { + fprintf(stderr, _("Too much address family arguments.\n")); + return (0); + } + if (paft->flag) + (*paft->flag)++; + if (afname[0]) + strcat(afname, ","); + strcat(afname, paft->name); + break; + } + if (!paft->alias) { + fprintf(stderr, _("Unknown address family `%s'.\n"), tmp1); + return (1); + } + tmp1 = tmp2; + } + + return (0); +} + +/* set the default AF list from the program name or a constant value */ +static void aftrans_def(char *tool, char *argv0, char *dflt) +{ + char *tmp; + char *buf; + + strcpy(afname, dflt); + + if (!(tmp = strrchr(argv0, '/'))) + tmp = argv0; /* no slash?! */ + else + tmp++; + + if (!(buf = strdup(tmp))) + return; + + if (strlen(tool) >= strlen(tmp)) { + free(buf); + return; + } + tmp = buf + (strlen(tmp) - strlen(tool)); + + if (strcmp(tmp, tool) != 0) { + free(buf); + return; + } + *tmp = '\0'; + if ((tmp = strchr(buf, '_'))) + *tmp = '\0'; + + afname[0] = '\0'; + if (aftrans_opt(buf)) + strcpy(afname, buf); + + free(buf); +} + +/* Check our protocol family table for this family. */ +static struct aftype *get_aftype(const char *name) +{ + struct aftype **afp; + +#ifdef KEEP_UNUSED + if (!sVafinit) + afinit(); +#endif /* KEEP_UNUSED */ + + afp = aftypes; + while (*afp != NULL) { + if (!strcmp((*afp)->name, name)) + return (*afp); + afp++; + } + if (strchr(name, ',')) + fprintf(stderr, _("Please don't supply more than one address family.\n")); + return (NULL); +} +#endif /* KEEP_UNUSED */ + +/* Check our protocol family table for this family. */ +static struct aftype *get_afntype(int af) +{ + struct aftype **afp; + +#ifdef KEEP_UNUSED + if (!sVafinit) + afinit(); +#endif /* KEEP_UNUSED */ + + afp = aftypes; + while (*afp != NULL) { + if ((*afp)->af == af) + return (*afp); + afp++; + } + return (NULL); +} + +/* Check our protocol family table for this family and return its socket */ +static int get_socket_for_af(int af) +{ + struct aftype **afp; + +#ifdef KEEP_UNUSED + if (!sVafinit) + afinit(); +#endif /* KEEP_UNUSED */ + + afp = aftypes; + while (*afp != NULL) { + if ((*afp)->af == af) + return (*afp)->fd; + afp++; + } + return -1; +} + +#ifdef KEEP_UNUSED +/* type: 0=all, 1=getroute */ +static void print_aflist(int type) { + int count = 0; + char * txt; + struct aftype **afp; + +#ifdef KEEP_UNUSED + if (!sVafinit) + afinit(); +#endif /* KEEP_UNUSED */ + + afp = aftypes; + while (*afp != NULL) { + if ((type == 1 && ((*afp)->rprint == NULL)) || ((*afp)->af == 0)) { + afp++; continue; + } + if ((count % 3) == 0) fprintf(stderr,count?"\n ":" "); + txt = (*afp)->name; if (!txt) txt = ".."; + fprintf(stderr,"%s (%s) ",txt,_((*afp)->title)); + count++; + afp++; + } + fprintf(stderr,"\n"); +} +#endif /* KEEP_UNUSED */ + +struct user_net_device_stats { + unsigned long long rx_packets; /* total packets received */ + unsigned long long tx_packets; /* total packets transmitted */ + unsigned long long rx_bytes; /* total bytes received */ + unsigned long long tx_bytes; /* total bytes transmitted */ + unsigned long rx_errors; /* bad packets received */ + unsigned long tx_errors; /* packet transmit problems */ + unsigned long rx_dropped; /* no space in linux buffers */ + unsigned long tx_dropped; /* no space available in linux */ + unsigned long rx_multicast; /* multicast packets received */ + unsigned long rx_compressed; + unsigned long tx_compressed; + unsigned long collisions; + + /* detailed rx_errors: */ + unsigned long rx_length_errors; + unsigned long rx_over_errors; /* receiver ring buff overflow */ + unsigned long rx_crc_errors; /* recved pkt with crc error */ + unsigned long rx_frame_errors; /* recv'd frame alignment error */ + unsigned long rx_fifo_errors; /* recv'r fifo overrun */ + unsigned long rx_missed_errors; /* receiver missed packet */ + /* detailed tx_errors */ + unsigned long tx_aborted_errors; + unsigned long tx_carrier_errors; + unsigned long tx_fifo_errors; + unsigned long tx_heartbeat_errors; + unsigned long tx_window_errors; +}; + +struct interface { + struct interface *next, *prev; + char name[IFNAMSIZ]; /* interface name */ + short type; /* if type */ + short flags; /* various flags */ + int metric; /* routing metric */ + int mtu; /* MTU value */ + int tx_queue_len; /* transmit queue length */ + struct ifmap map; /* hardware setup */ + struct sockaddr addr; /* IP address */ + struct sockaddr dstaddr; /* P-P IP address */ + struct sockaddr broadaddr; /* IP broadcast address */ + struct sockaddr netmask; /* IP network mask */ + struct sockaddr ipxaddr_bb; /* IPX network address */ + struct sockaddr ipxaddr_sn; /* IPX network address */ + struct sockaddr ipxaddr_e3; /* IPX network address */ + struct sockaddr ipxaddr_e2; /* IPX network address */ + struct sockaddr ddpaddr; /* Appletalk DDP address */ + struct sockaddr ecaddr; /* Econet address */ + int has_ip; + int has_ipx_bb; + int has_ipx_sn; + int has_ipx_e3; + int has_ipx_e2; + int has_ax25; + int has_ddp; + int has_econet; + char hwaddr[32]; /* HW address */ + int statistics_valid; + struct user_net_device_stats stats; /* statistics */ + int keepalive; /* keepalive value for SLIP */ + int outfill; /* outfill value for SLIP */ +}; + + +int interface_opt_a = 0; /* show all interfaces */ + +#ifdef KEEP_UNUSED +static int opt_i = 0; /* show the statistics */ +static int opt_v = 0; /* debugging output flag */ + +static int addr_family = 0; /* currently selected AF */ +#endif /* KEEP_UNUSED */ + +static struct interface *int_list, *int_last; +static int skfd = -1; /* generic raw socket desc. */ + + +static int sockets_open(int family) +{ + struct aftype **aft; + int sfd = -1; + static int force = -1; + + if (force < 0) { + force = 0; + if (get_kernel_revision() < KRELEASE(2, 1, 0)) + force = 1; + if (access("/proc/net", R_OK)) + force = 1; + } + for (aft = aftypes; *aft; aft++) { + struct aftype *af = *aft; + int type = SOCK_DGRAM; + if (af->af == AF_UNSPEC) + continue; + if (family && family != af->af) + continue; + if (af->fd != -1) { + sfd = af->fd; + continue; + } + /* Check some /proc file first to not stress kmod */ + if (!family && !force && af->flag_file) { + if (access(af->flag_file, R_OK)) + continue; + } +#if HAVE_AFNETROM + if (af->af == AF_NETROM) + type = SOCK_SEQPACKET; +#endif +#if HAVE_AFX25 + if (af->af == AF_X25) + type = SOCK_SEQPACKET; +#endif + af->fd = socket(af->af, type, 0); + if (af->fd >= 0) + sfd = af->fd; + } + if (sfd < 0) + fprintf(stderr, _("No usable address families found.\n")); + return sfd; +} + +/* like strcmp(), but knows about numbers */ +static int nstrcmp(const char *astr, const char *b) +{ + const char *a = astr; + + while (*a == *b) { + if (*a == '\0') + return 0; + a++; + b++; + } + if (isdigit(*a)) { + if (!isdigit(*b)) + return -1; + while (a > astr) { + a--; + if (!isdigit(*a)) { + a++; + break; + } + if (!isdigit(*b)) + return -1; + b--; + } + return atoi(a) > atoi(b) ? 1 : -1; + } + return *a - *b; +} + +static struct interface *add_interface(char *name) +{ + struct interface *ife, **nextp, *new; + + for (ife = int_last; ife; ife = ife->prev) { + int n = nstrcmp(ife->name, name); + if (n == 0) + return ife; + if (n < 0) + break; + } + new(new); + safe_strncpy(new->name, name, IFNAMSIZ); + nextp = ife ? &ife->next : &int_list; + new->prev = ife; + new->next = *nextp; + if (new->next) + new->next->prev = new; + else + int_last = new; + *nextp = new; + return new; +} + + +static int if_readconf(void) +{ + int numreqs = 30; + struct ifconf ifc; + struct ifreq *ifr; + int n, err = -1; + int skfd2; + + /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets + (as of 2.1.128) */ + skfd2 = get_socket_for_af(AF_INET); + if (skfd2 < 0) { + fprintf(stderr, _("warning: no inet socket available: %s\n"), + strerror(errno)); + /* Try to soldier on with whatever socket we can get hold of. */ + skfd2 = sockets_open(0); + if (skfd2 < 0) + return -1; + } + + ifc.ifc_buf = NULL; + for (;;) { + ifc.ifc_len = sizeof(struct ifreq) * numreqs; + ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); + + if (ioctl(skfd2, SIOCGIFCONF, &ifc) < 0) { + perror("SIOCGIFCONF"); + goto out; + } + if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) { + /* assume it overflowed and try again */ + numreqs += 10; + continue; + } + break; + } + + ifr = ifc.ifc_req; + for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) { + add_interface(ifr->ifr_name); + ifr++; + } + err = 0; + +out: + free(ifc.ifc_buf); + return err; +} + +static char *get_name(char *name, char *p) +{ + while (isspace(*p)) + p++; + while (*p) { + if (isspace(*p)) + break; + if (*p == ':') { /* could be an alias */ + char *dot = p, *dotname = name; + *name++ = *p++; + while (isdigit(*p)) + *name++ = *p++; + if (*p != ':') { /* it wasn't, backup */ + p = dot; + name = dotname; + } + if (*p == '\0') + return NULL; + p++; + break; + } + *name++ = *p++; + } + *name++ = '\0'; + return p; +} + +static int get_dev_fields(char *bp, struct interface *ife) +{ + switch (procnetdev_vsn) { + case 3: + sscanf(bp, + "%Lu %Lu %lu %lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu %lu", + &ife->stats.rx_bytes, + &ife->stats.rx_packets, + &ife->stats.rx_errors, + &ife->stats.rx_dropped, + &ife->stats.rx_fifo_errors, + &ife->stats.rx_frame_errors, + &ife->stats.rx_compressed, + &ife->stats.rx_multicast, + + &ife->stats.tx_bytes, + &ife->stats.tx_packets, + &ife->stats.tx_errors, + &ife->stats.tx_dropped, + &ife->stats.tx_fifo_errors, + &ife->stats.collisions, + &ife->stats.tx_carrier_errors, + &ife->stats.tx_compressed); + break; + case 2: + sscanf(bp, "%Lu %Lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu", + &ife->stats.rx_bytes, + &ife->stats.rx_packets, + &ife->stats.rx_errors, + &ife->stats.rx_dropped, + &ife->stats.rx_fifo_errors, + &ife->stats.rx_frame_errors, + + &ife->stats.tx_bytes, + &ife->stats.tx_packets, + &ife->stats.tx_errors, + &ife->stats.tx_dropped, + &ife->stats.tx_fifo_errors, + &ife->stats.collisions, + &ife->stats.tx_carrier_errors); + ife->stats.rx_multicast = 0; + break; + case 1: + sscanf(bp, "%Lu %lu %lu %lu %lu %Lu %lu %lu %lu %lu %lu", + &ife->stats.rx_packets, + &ife->stats.rx_errors, + &ife->stats.rx_dropped, + &ife->stats.rx_fifo_errors, + &ife->stats.rx_frame_errors, + + &ife->stats.tx_packets, + &ife->stats.tx_errors, + &ife->stats.tx_dropped, + &ife->stats.tx_fifo_errors, + &ife->stats.collisions, + &ife->stats.tx_carrier_errors); + ife->stats.rx_bytes = 0; + ife->stats.tx_bytes = 0; + ife->stats.rx_multicast = 0; + break; + } + return 0; +} + +static inline int procnetdev_version(char *buf) +{ + if (strstr(buf, "compressed")) + return 3; + if (strstr(buf, "bytes")) + return 2; + return 1; +} + +static int if_readlist_proc(char *target) +{ + static int proc_read; + FILE *fh; + char buf[512]; + struct interface *ife; + int err; + + if (proc_read) + return 0; + if (!target) + proc_read = 1; + + fh = fopen(_PATH_PROCNET_DEV, "r"); + if (!fh) { + fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"), + _PATH_PROCNET_DEV, strerror(errno)); + return if_readconf(); + } + fgets(buf, sizeof buf, fh); /* eat line */ + fgets(buf, sizeof buf, fh); + + procnetdev_vsn = procnetdev_version(buf); + + err = 0; + while (fgets(buf, sizeof buf, fh)) { + char *s, name[IFNAMSIZ]; + s = get_name(name, buf); + ife = add_interface(name); + get_dev_fields(s, ife); + ife->statistics_valid = 1; + if (target && !strcmp(target,name)) + break; + } + if (ferror(fh)) { + perror(_PATH_PROCNET_DEV); + err = -1; + proc_read = 0; + } + + fclose(fh); + return err; +} + +static int if_readlist(void) +{ + int err = if_readlist_proc(NULL); + if (!err) + err = if_readconf(); + return err; +} + +static int for_all_interfaces(int (*doit) (struct interface *, void *), void *cookie) +{ + struct interface *ife; + + if (!int_list && (if_readlist() < 0)) + return -1; + for (ife = int_list; ife; ife = ife->next) { + int err = doit(ife, cookie); + if (err) + return err; + } + return 0; +} + +/* Support for fetching an IPX address */ + +#if HAVE_AFIPX +static int ipx_getaddr(int sock, int ft, struct ifreq *ifr) +{ + ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft; + return ioctl(sock, SIOCGIFADDR, ifr); +} +#endif + + +/* Fetch the interface configuration from the kernel. */ +static int if_fetch(struct interface *ife) +{ + struct ifreq ifr; + int fd; + char *ifname = ife->name; + + strcpy(ifr.ifr_name, ifname); + if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) + return (-1); + ife->flags = ifr.ifr_flags; + + strcpy(ifr.ifr_name, ifname); + if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) + memset(ife->hwaddr, 0, 32); + else + memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); + + ife->type = ifr.ifr_hwaddr.sa_family; + + strcpy(ifr.ifr_name, ifname); + if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) + ife->metric = 0; + else + ife->metric = ifr.ifr_metric; + + strcpy(ifr.ifr_name, ifname); + if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0) + ife->mtu = 0; + else + ife->mtu = ifr.ifr_mtu; + +#ifdef HAVE_HWSLIP + if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP || + ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 || + ife->type == ARPHRD_ADAPT) { +#ifdef SIOCGOUTFILL + strcpy(ifr.ifr_name, ifname); + if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0) + ife->outfill = 0; + else + ife->outfill = (unsigned int) ifr.ifr_data; +#endif +#ifdef SIOCGKEEPALIVE + strcpy(ifr.ifr_name, ifname); + if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0) + ife->keepalive = 0; + else + ife->keepalive = (unsigned int) ifr.ifr_data; +#endif + } +#endif + + strcpy(ifr.ifr_name, ifname); + if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) + memset(&ife->map, 0, sizeof(struct ifmap)); + else + memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap)); + + strcpy(ifr.ifr_name, ifname); + if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) + memset(&ife->map, 0, sizeof(struct ifmap)); + else + ife->map = ifr.ifr_map; + +#ifdef HAVE_TXQUEUELEN + strcpy(ifr.ifr_name, ifname); + if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0) + ife->tx_queue_len = -1; /* unknown value */ + else + ife->tx_queue_len = ifr.ifr_qlen; +#else + ife->tx_queue_len = -1; /* unknown value */ +#endif + +#if HAVE_AFINET + /* IPv4 address? */ + fd = get_socket_for_af(AF_INET); + if (fd >= 0) { + strcpy(ifr.ifr_name, ifname); + ifr.ifr_addr.sa_family = AF_INET; + if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { + ife->has_ip = 1; + ife->addr = ifr.ifr_addr; + strcpy(ifr.ifr_name, ifname); + if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0) + memset(&ife->dstaddr, 0, sizeof(struct sockaddr)); + else + ife->dstaddr = ifr.ifr_dstaddr; + + strcpy(ifr.ifr_name, ifname); + if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0) + memset(&ife->broadaddr, 0, sizeof(struct sockaddr)); + else + ife->broadaddr = ifr.ifr_broadaddr; + + strcpy(ifr.ifr_name, ifname); + if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0) + memset(&ife->netmask, 0, sizeof(struct sockaddr)); + else + ife->netmask = ifr.ifr_netmask; + } else + memset(&ife->addr, 0, sizeof(struct sockaddr)); + } +#endif + +#if HAVE_AFATALK + /* DDP address maybe ? */ + fd = get_socket_for_af(AF_APPLETALK); + if (fd >= 0) { + strcpy(ifr.ifr_name, ifname); + if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { + ife->ddpaddr = ifr.ifr_addr; + ife->has_ddp = 1; + } + } +#endif + +#if HAVE_AFIPX + /* Look for IPX addresses with all framing types */ + fd = get_socket_for_af(AF_IPX); + if (fd >= 0) { + strcpy(ifr.ifr_name, ifname); + if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) { + ife->has_ipx_bb = 1; + ife->ipxaddr_bb = ifr.ifr_addr; + } + strcpy(ifr.ifr_name, ifname); + if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) { + ife->has_ipx_sn = 1; + ife->ipxaddr_sn = ifr.ifr_addr; + } + strcpy(ifr.ifr_name, ifname); + if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) { + ife->has_ipx_e3 = 1; + ife->ipxaddr_e3 = ifr.ifr_addr; + } + strcpy(ifr.ifr_name, ifname); + if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) { + ife->has_ipx_e2 = 1; + ife->ipxaddr_e2 = ifr.ifr_addr; + } + } +#endif + +#if HAVE_AFECONET + /* Econet address maybe? */ + fd = get_socket_for_af(AF_ECONET); + if (fd >= 0) { + strcpy(ifr.ifr_name, ifname); + if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { + ife->ecaddr = ifr.ifr_addr; + ife->has_econet = 1; + } + } +#endif + + return 0; +} + + +static int do_if_fetch(struct interface *ife) +{ + if (if_fetch(ife) < 0) { + char *errmsg; + if (errno == ENODEV) { + /* Give better error message for this case. */ + errmsg = _("Device not found"); + } else { + errmsg = strerror(errno); + } + fprintf(stderr, _("%s: error fetching interface information: %s\n"), + ife->name, errmsg); + return -1; + } + return 0; +} + +/* This structure defines hardware protocols and their handlers. */ +struct hwtype { + const char *name; + const char *title; + int type; + int alen; + char *(*print) (unsigned char *); + int (*input) (char *, struct sockaddr *); + int (*activate) (int fd); + int suppress_null_addr; +}; + +static struct hwtype unspec_hwtype = +{ + "unspec", "UNSPEC", -1, 0, + UNSPEC_print, NULL, NULL +}; + +static struct hwtype loop_hwtype = +{ + "loop", "Local Loopback", ARPHRD_LOOPBACK, 0, + NULL, NULL, NULL +}; + +#if HAVE_HWETHER +#include <net/if_arp.h> +#include <linux/if_ether.h> + +static struct hwtype ether_hwtype; + +/* Display an Ethernet address in readable format. */ +static char *pr_ether(unsigned char *ptr) +{ + static char buff[64]; + + snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X", + (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377), + (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377) + ); + return (buff); +} + +#ifdef KEEP_UNUSED +/* Input an Ethernet address and convert to binary. */ +static int in_ether(char *bufp, struct sockaddr *sap) +{ + unsigned char *ptr; + char c, *orig; + int i; + unsigned val; + + sap->sa_family = ether_hwtype.type; + ptr = sap->sa_data; + + i = 0; + orig = bufp; + while ((*bufp != '\0') && (i < ETH_ALEN)) { + val = 0; + c = *bufp++; + if (isdigit(c)) + val = c - '0'; + else if (c >= 'a' && c <= 'f') + val = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val = c - 'A' + 10; + else { +#ifdef DEBUG + fprintf(stderr, _("in_ether(%s): invalid ether address!\n"), orig); +#endif + errno = EINVAL; + return (-1); + } + val <<= 4; + c = *bufp; + if (isdigit(c)) + val |= c - '0'; + else if (c >= 'a' && c <= 'f') + val |= c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val |= c - 'A' + 10; + else if (c == ':' || c == 0) + val >>= 4; + else { +#ifdef DEBUG + fprintf(stderr, _("in_ether(%s): invalid ether address!\n"), orig); +#endif + errno = EINVAL; + return (-1); + } + if (c != 0) + bufp++; + *ptr++ = (unsigned char) (val & 0377); + i++; + + /* We might get a semicolon here - not required. */ + if (*bufp == ':') { + if (i == ETH_ALEN) { +#ifdef DEBUG + fprintf(stderr, _("in_ether(%s): trailing : ignored!\n"), + orig) +#endif + ; /* nothing */ + } + bufp++; + } + } + + /* That's it. Any trailing junk? */ + if ((i == ETH_ALEN) && (*bufp != '\0')) { +#ifdef DEBUG + fprintf(stderr, _("in_ether(%s): trailing junk!\n"), orig); + errno = EINVAL; + return (-1); +#endif + } +#ifdef DEBUG + fprintf(stderr, "in_ether(%s): %s\n", orig, pr_ether(sap->sa_data)); +#endif + + return (0); +} +#endif /* KEEP_UNUSED */ + + +static struct hwtype ether_hwtype = +{ + "ether", "Ethernet", ARPHRD_ETHER, ETH_ALEN, + pr_ether, NULL /* UNUSED in_ether */, NULL +}; + + +#endif /* HAVE_HWETHER */ + + +#if HAVE_HWPPP + +#include <net/if_arp.h> + +#ifdef KEEP_UNUSED +/* Start the PPP encapsulation on the file descriptor. */ +static int do_ppp(int fd) +{ + fprintf(stderr, _("You cannot start PPP with this program.\n")); + return -1; +} +#endif /* KEEP_UNUSED */ + +static struct hwtype ppp_hwtype = +{ + "ppp", "Point-Point Protocol", ARPHRD_PPP, 0, + NULL, NULL, NULL /* UNUSED do_ppp */, 0 +}; + + +#endif /* HAVE_PPP */ + +static struct hwtype *hwtypes[] = +{ + + &loop_hwtype, + +#if HAVE_HWSLIP + &slip_hwtype, + &cslip_hwtype, + &slip6_hwtype, + &cslip6_hwtype, + &adaptive_hwtype, +#endif +#if HAVE_HWSTRIP + &strip_hwtype, +#endif +#if HAVE_HWASH + &ash_hwtype, +#endif +#if HAVE_HWETHER + ðer_hwtype, +#endif +#if HAVE_HWTR + &tr_hwtype, +#ifdef ARPHRD_IEEE802_TR + &tr_hwtype1, +#endif +#endif +#if HAVE_HWAX25 + &ax25_hwtype, +#endif +#if HAVE_HWNETROM + &netrom_hwtype, +#endif +#if HAVE_HWROSE + &rose_hwtype, +#endif +#if HAVE_HWTUNNEL + &tunnel_hwtype, +#endif +#if HAVE_HWPPP + &ppp_hwtype, +#endif +#if HAVE_HWHDLCLAPB + &hdlc_hwtype, + &lapb_hwtype, +#endif +#if HAVE_HWARC + &arcnet_hwtype, +#endif +#if HAVE_HWFR + &dlci_hwtype, + &frad_hwtype, +#endif +#if HAVE_HWSIT + &sit_hwtype, +#endif +#if HAVE_HWFDDI + &fddi_hwtype, +#endif +#if HAVE_HWHIPPI + &hippi_hwtype, +#endif +#if HAVE_HWIRDA + &irda_hwtype, +#endif +#if HAVE_HWEC + &ec_hwtype, +#endif +#if HAVE_HWX25 + &x25_hwtype, +#endif + &unspec_hwtype, + NULL +}; + +#ifdef KEEP_UNUSED +static short sVhwinit = 0; + +static void hwinit() +{ + loop_hwtype.title = _("Local Loopback"); + unspec_hwtype.title = _("UNSPEC"); +#if HAVE_HWSLIP + slip_hwtype.title = _("Serial Line IP"); + cslip_hwtype.title = _("VJ Serial Line IP"); + slip6_hwtype.title = _("6-bit Serial Line IP"); + cslip6_hwtype.title = _("VJ 6-bit Serial Line IP"); + adaptive_hwtype.title = _("Adaptive Serial Line IP"); +#endif +#if HAVE_HWETHER + ether_hwtype.title = _("Ethernet"); +#endif +#if HAVE_HWASH + ash_hwtype.title = _("Ash"); +#endif +#if HAVE_HWFDDI + fddi_hwtype.title = _("Fiber Distributed Data Interface"); +#endif +#if HAVE_HWHIPPI + hippi_hwtype.title = _("HIPPI"); +#endif +#if HAVE_HWAX25 + ax25_hwtype.title = _("AMPR AX.25"); +#endif +#if HAVE_HWROSE + rose_hwtype.title = _("AMPR ROSE"); +#endif +#if HAVE_HWNETROM + netrom_hwtype.title = _("AMPR NET/ROM"); +#endif +#if HAVE_HWX25 + x25_hwtype.title = _("generic X.25"); +#endif +#if HAVE_HWTUNNEL + tunnel_hwtype.title = _("IPIP Tunnel"); +#endif +#if HAVE_HWPPP + ppp_hwtype.title = _("Point-to-Point Protocol"); +#endif +#if HAVE_HWHDLCLAPB + hdlc_hwtype.title = _("(Cisco)-HDLC"); + lapb_hwtype.title = _("LAPB"); +#endif +#if HAVE_HWARC + arcnet_hwtype.title = _("ARCnet"); +#endif +#if HAVE_HWFR + dlci_hwtype.title = _("Frame Relay DLCI"); + frad_hwtype.title = _("Frame Relay Access Device"); +#endif +#if HAVE_HWSIT + sit_hwtype.title = _("IPv6-in-IPv4"); +#endif +#if HAVE_HWIRDA + irda_hwtype.title = _("IrLAP"); +#endif +#if HAVE_HWTR + tr_hwtype.title = _("16/4 Mbps Token Ring"); +#ifdef ARPHRD_IEEE802_TR + tr_hwtype1.title = _("16/4 Mbps Token Ring (New)") ; +#endif +#endif +#if HAVE_HWEC + ec_hwtype.title = _("Econet"); +#endif + sVhwinit = 1; +} +#endif /* KEEP_UNUSED */ + +#ifdef IFF_PORTSEL +static const char *if_port_text[][4] = +{ + /* Keep in step with <linux/netdevice.h> */ + {"unknown", NULL, NULL, NULL}, + {"10base2", "bnc", "coax", NULL}, + {"10baseT", "utp", "tpe", NULL}, + {"AUI", "thick", "db15", NULL}, + {"100baseT", NULL, NULL, NULL}, + {"100baseTX", NULL, NULL, NULL}, + {"100baseFX", NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL}, +}; +#endif + +/* Check our hardware type table for this type. */ +static struct hwtype *get_hwntype(int type) +{ + struct hwtype **hwp; + +#ifdef KEEP_UNUSED + if (!sVhwinit) + hwinit(); +#endif /* KEEP_UNUSED */ + + hwp = hwtypes; + while (*hwp != NULL) { + if ((*hwp)->type == type) + return (*hwp); + hwp++; + } + return (NULL); +} + +/* return 1 if address is all zeros */ +static int hw_null_address(struct hwtype *hw, void *ap) +{ + unsigned int i; + unsigned char *address = (unsigned char *)ap; + for (i = 0; i < hw->alen; i++) + if (address[i]) + return 0; + return 1; +} + +static const char TRext[] = "\0\0k\0M"; + +static void print_bytes_scaled(unsigned long long ull, const char *end) +{ + unsigned long long int_part; + unsigned long frac_part; + const char *ext; + int i; + + frac_part = 0; + ext = TRext; + int_part = ull; + for (i=0 ; i<2 ; i++) { + if (int_part >= 1024) { + frac_part = ((int_part % 1024) * 10) / 1024; + int_part /= 1024; + ext += 2; /* Kb, Mb */ + } + } + + printf("X bytes:%Lu (%Lu.%lu %sb)%s", ull, int_part, frac_part, ext, end); +} + +static void ife_print(struct interface *ptr) +{ + struct aftype *ap; + struct hwtype *hw; + int hf; + int can_compress = 0; + +#if HAVE_AFIPX + static struct aftype *ipxtype = NULL; +#endif +#if HAVE_AFECONET + static struct aftype *ectype = NULL; +#endif +#if HAVE_AFATALK + static struct aftype *ddptype = NULL; +#endif +#if HAVE_AFINET6 + FILE *f; + char addr6[40], devname[20]; + struct sockaddr_in6 sap; + int plen, scope, dad_status, if_idx; + extern struct aftype inet6_aftype; + char addr6p[8][5]; +#endif + + ap = get_afntype(ptr->addr.sa_family); + if (ap == NULL) + ap = get_afntype(0); + + hf = ptr->type; + + if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6) + can_compress = 1; + + hw = get_hwntype(hf); + if (hw == NULL) + hw = get_hwntype(-1); + + printf(_("%-9.9s Link encap:%s "), ptr->name, _(hw->title)); + /* For some hardware types (eg Ash, ATM) we don't print the + hardware address if it's null. */ + if (hw->print != NULL && (! (hw_null_address(hw, ptr->hwaddr) && + hw->suppress_null_addr))) + printf(_("HWaddr %s "), hw->print(ptr->hwaddr)); +#ifdef IFF_PORTSEL + if (ptr->flags & IFF_PORTSEL) { + printf(_("Media:%s"), if_port_text[ptr->map.port][0]); + if (ptr->flags & IFF_AUTOMEDIA) + printf(_("(auto)")); + } +#endif + printf("\n"); + +#if HAVE_AFINET + if (ptr->has_ip) { + printf(_(" %s addr:%s "), ap->name, + ap->sprint(&ptr->addr, 1)); + if (ptr->flags & IFF_POINTOPOINT) { + printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1)); + } + if (ptr->flags & IFF_BROADCAST) { + printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1)); + } + printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1)); + } +#endif + +#if HAVE_AFINET6 + + if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) { + while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", + addr6p[0], addr6p[1], addr6p[2], addr6p[3], + addr6p[4], addr6p[5], addr6p[6], addr6p[7], + &if_idx, &plen, &scope, &dad_status, devname) != EOF) { + if (!strcmp(devname, ptr->name)) { + sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", + addr6p[0], addr6p[1], addr6p[2], addr6p[3], + addr6p[4], addr6p[5], addr6p[6], addr6p[7]); + inet6_aftype.input(1, addr6, (struct sockaddr *) &sap); + printf(_(" inet6 addr: %s/%d"), + inet6_aftype.sprint((struct sockaddr *) &sap, 1), plen); + printf(_(" Scope:")); + switch (scope) { + case 0: + printf(_("Global")); + break; + case IPV6_ADDR_LINKLOCAL: + printf(_("Link")); + break; + case IPV6_ADDR_SITELOCAL: + printf(_("Site")); + break; + case IPV6_ADDR_COMPATv4: + printf(_("Compat")); + break; + case IPV6_ADDR_LOOPBACK: + printf(_("Host")); + break; + default: + printf(_("Unknown")); + } + printf("\n"); + } + } + fclose(f); + } +#endif + +#if HAVE_AFIPX + if (ipxtype == NULL) + ipxtype = get_afntype(AF_IPX); + + if (ipxtype != NULL) { + if (ptr->has_ipx_bb) + printf(_(" IPX/Ethernet II addr:%s\n"), + ipxtype->sprint(&ptr->ipxaddr_bb, 1)); + if (ptr->has_ipx_sn) + printf(_(" IPX/Ethernet SNAP addr:%s\n"), + ipxtype->sprint(&ptr->ipxaddr_sn, 1)); + if (ptr->has_ipx_e2) + printf(_(" IPX/Ethernet 802.2 addr:%s\n"), + ipxtype->sprint(&ptr->ipxaddr_e2, 1)); + if (ptr->has_ipx_e3) + printf(_(" IPX/Ethernet 802.3 addr:%s\n"), + ipxtype->sprint(&ptr->ipxaddr_e3, 1)); + } +#endif + +#if HAVE_AFATALK + if (ddptype == NULL) + ddptype = get_afntype(AF_APPLETALK); + if (ddptype != NULL) { + if (ptr->has_ddp) + printf(_(" EtherTalk Phase 2 addr:%s\n"), ddptype->sprint(&ptr->ddpaddr, 1)); + } +#endif + +#if HAVE_AFECONET + if (ectype == NULL) + ectype = get_afntype(AF_ECONET); + if (ectype != NULL) { + if (ptr->has_econet) + printf(_(" econet addr:%s\n"), ectype->sprint(&ptr->ecaddr, 1)); + } +#endif + + printf(" "); + /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */ + if (ptr->flags == 0) + printf(_("[NO FLAGS] ")); + if (ptr->flags & IFF_UP) + printf(_("UP ")); + if (ptr->flags & IFF_BROADCAST) + printf(_("BROADCAST ")); + if (ptr->flags & IFF_DEBUG) + printf(_("DEBUG ")); + if (ptr->flags & IFF_LOOPBACK) + printf(_("LOOPBACK ")); + if (ptr->flags & IFF_POINTOPOINT) + printf(_("POINTOPOINT ")); + if (ptr->flags & IFF_NOTRAILERS) + printf(_("NOTRAILERS ")); + if (ptr->flags & IFF_RUNNING) + printf(_("RUNNING ")); + if (ptr->flags & IFF_NOARP) + printf(_("NOARP ")); + if (ptr->flags & IFF_PROMISC) + printf(_("PROMISC ")); + if (ptr->flags & IFF_ALLMULTI) + printf(_("ALLMULTI ")); + if (ptr->flags & IFF_SLAVE) + printf(_("SLAVE ")); + if (ptr->flags & IFF_MASTER) + printf(_("MASTER ")); + if (ptr->flags & IFF_MULTICAST) + printf(_("MULTICAST ")); +#ifdef HAVE_DYNAMIC + if (ptr->flags & IFF_DYNAMIC) + printf(_("DYNAMIC ")); +#endif + /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */ + printf(_(" MTU:%d Metric:%d"), + ptr->mtu, ptr->metric ? ptr->metric : 1); +#ifdef SIOCSKEEPALIVE + if (ptr->outfill || ptr->keepalive) + printf(_(" Outfill:%d Keepalive:%d"), + ptr->outfill, ptr->keepalive); +#endif + printf("\n"); + + /* If needed, display the interface statistics. */ + + if (ptr->statistics_valid) { + printf(" "); + + printf(_("RX packets:%Lu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"), + ptr->stats.rx_packets, ptr->stats.rx_errors, + ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors, + ptr->stats.rx_frame_errors); + if (can_compress) + printf(_(" compressed:%lu\n"), ptr->stats.rx_compressed); + printf(" "); + printf(_("TX packets:%Lu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"), + ptr->stats.tx_packets, ptr->stats.tx_errors, + ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors, + ptr->stats.tx_carrier_errors); + printf(_(" collisions:%lu "), ptr->stats.collisions); + if (can_compress) + printf(_("compressed:%lu "), ptr->stats.tx_compressed); + if (ptr->tx_queue_len != -1) + printf(_("txqueuelen:%d "), ptr->tx_queue_len); + printf("\n R"); + print_bytes_scaled(ptr->stats.rx_bytes, " T"); + print_bytes_scaled(ptr->stats.tx_bytes, "\n"); + + } + + if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma || + ptr->map.base_addr)) { + printf(" "); + if (ptr->map.irq) + printf(_("Interrupt:%d "), ptr->map.irq); + if (ptr->map.base_addr >= 0x100) /* Only print devices using it for + I/O maps */ + printf(_("Base address:0x%x "), ptr->map.base_addr); + if (ptr->map.mem_start) { + printf(_("Memory:%lx-%lx "), ptr->map.mem_start, ptr->map.mem_end); + } + if (ptr->map.dma) + printf(_("DMA chan:%x "), ptr->map.dma); + printf("\n"); + } + printf("\n"); +} + + +static int do_if_print(struct interface *ife, void *cookie) +{ + int *opt_a = (int *) cookie; + int res; + + res = do_if_fetch(ife); + if (res >= 0) { + if ((ife->flags & IFF_UP) || *opt_a) + ife_print(ife); + } + return res; +} + +static struct interface *lookup_interface(char *name) +{ + struct interface *ife = NULL; + + if (if_readlist_proc(name) < 0) + return NULL; + ife = add_interface(name); + return ife; +} + +/* for ipv4 add/del modes */ +static int if_print(char *ifname) +{ + int res; + + if (!ifname) { + res = for_all_interfaces(do_if_print, &interface_opt_a); + } else { + struct interface *ife; + + ife = lookup_interface(ifname); + res = do_if_fetch(ife); + if (res >= 0) + ife_print(ife); + } + return res; +} + +int display_interfaces(char *ifname) +{ + int status; + + /* Create a channel to the NET kernel. */ + if ((skfd = sockets_open(0)) < 0) { + perror_msg_and_die("socket"); + } + + /* Do we have to show the current setup? */ + status = if_print(ifname); + close(skfd); + exit(status < 0); +} diff --git a/release/src/router/busybox/libbb/isdirectory.c b/release/src/router/busybox/libbb/isdirectory.c new file mode 100644 index 00000000..65f4fee0 --- /dev/null +++ b/release/src/router/busybox/libbb/isdirectory.c @@ -0,0 +1,71 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include "libbb.h" + +/* + * Return TRUE if a fileName is a directory. + * Nonexistant files return FALSE. + */ +int is_directory(const char *fileName, const int followLinks, struct stat *statBuf) +{ + int status; + int didMalloc = 0; + + if (statBuf == NULL) { + statBuf = (struct stat *)xmalloc(sizeof(struct stat)); + ++didMalloc; + } + + if (followLinks == TRUE) + status = stat(fileName, statBuf); + else + status = lstat(fileName, statBuf); + + if (status < 0 || !(S_ISDIR(statBuf->st_mode))) { + status = FALSE; + } + else status = TRUE; + + if (didMalloc) { + free(statBuf); + statBuf = NULL; + } + return status; +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/kernel_version.c b/release/src/router/busybox/libbb/kernel_version.c new file mode 100644 index 00000000..09cd582c --- /dev/null +++ b/release/src/router/busybox/libbb/kernel_version.c @@ -0,0 +1,66 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/utsname.h> /* for uname(2) */ + +#include "libbb.h" + +/* Returns kernel version encoded as major*65536 + minor*256 + patch, + * so, for example, to check if the kernel is greater than 2.2.11: + * if (get_kernel_revision() <= 2*65536+2*256+11) { <stuff> } + */ +extern int get_kernel_revision(void) +{ + struct utsname name; + char *s; + int i, r; + + if (uname(&name) == -1) { + perror_msg("cannot get system information"); + return (0); + } + + s = name.release; + r = 0; + for (i=0 ; i<3 ; i++) { + r = r * 256 + atoi(strtok(s, ".")); + s = NULL; + } + return r; +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/last_char_is.c b/release/src/router/busybox/libbb/last_char_is.c new file mode 100644 index 00000000..4e2ee92e --- /dev/null +++ b/release/src/router/busybox/libbb/last_char_is.c @@ -0,0 +1,40 @@ +/* + * busybox library eXtended function + * + * Copyright (C) 2001 Larry Doolittle, <ldoolitt@recycle.lbl.gov> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <string.h> +#include "libbb.h" + +/* Find out if the last character of a string matches the one given Don't + * underrun the buffer if the string length is 0. Also avoids a possible + * space-hogging inline of strlen() per usage. + */ +char * last_char_is(const char *s, int c) +{ + char *sret; + if (!s) + return NULL; + sret = (char *)s+strlen(s)-1; + if (sret>=s && *sret == c) { + return sret; + } else { + return NULL; + } +} diff --git a/release/src/router/busybox/libbb/libbb.h b/release/src/router/busybox/libbb/libbb.h new file mode 100644 index 00000000..04ed2ae8 --- /dev/null +++ b/release/src/router/busybox/libbb/libbb.h @@ -0,0 +1,325 @@ +/* vi: set sw=4 ts=4: */ +/* + * Busybox main internal header file + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ +#ifndef __LIBBB_H__ +#define __LIBBB_H__ 1 + +#include <stdio.h> +#include <stdarg.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <netdb.h> + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#include <features.h> + +#ifndef _BB_INTERNAL_H_ +#include "../busybox.h" +#endif + +#if (__GNU_LIBRARY__ < 5) && (!defined __dietlibc__) +/* libc5 doesn't define socklen_t */ +typedef unsigned int socklen_t; +/* libc5 doesn't implement BSD 4.4 daemon() */ +extern int daemon (int nochdir, int noclose); +/* libc5 doesn't implement strtok_r */ +char *strtok_r(char *s, const char *delim, char **ptrptr); +#endif + +/* Some useful definitions */ +#define FALSE ((int) 0) +#define TRUE ((int) 1) +#define SKIP ((int) 2) + +/* for mtab.c */ +#define MTAB_GETMOUNTPT '1' +#define MTAB_GETDEVICE '2' + +#define BUF_SIZE 8192 +#define EXPAND_ALLOC 1024 + +static inline int is_decimal(int ch) { return ((ch >= '0') && (ch <= '9')); } +static inline int is_octal(int ch) { return ((ch >= '0') && (ch <= '7')); } + +/* Macros for min/max. */ +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + + + +extern void show_usage(void) __attribute__ ((noreturn)); +extern void error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))); +extern void error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))); +extern void perror_msg(const char *s, ...); +extern void perror_msg_and_die(const char *s, ...) __attribute__ ((noreturn)); +extern void vherror_msg(const char *s, va_list p); +extern void herror_msg(const char *s, ...); +extern void herror_msg_and_die(const char *s, ...) __attribute__ ((noreturn)); + +/* These two are used internally -- you shouldn't need to use them */ +extern void verror_msg(const char *s, va_list p); +extern void vperror_msg(const char *s, va_list p); + +const char *mode_string(int mode); +const char *time_string(time_t timeVal); +int is_directory(const char *name, int followLinks, struct stat *statBuf); +int isDevice(const char *name); + +int remove_file(const char *path, int flags); +int copy_file(const char *source, const char *dest, int flags); +int copy_file_chunk(FILE *src_file, FILE *dst_file, unsigned long long chunksize); +char *buildName(const char *dirName, const char *fileName); +int makeString(int argc, const char **argv, char *buf, int bufLen); +char *getChunk(int size); +char *chunkstrdup(const char *str); +void freeChunks(void); +ssize_t safe_read(int fd, void *buf, size_t count); +int full_write(int fd, const char *buf, int len); +int full_read(int fd, char *buf, int len); +int recursive_action(const char *fileName, int recurse, int followLinks, int depthFirst, + int (*fileAction) (const char *fileName, struct stat* statbuf, void* userData), + int (*dirAction) (const char *fileName, struct stat* statbuf, void* userData), + void* userData); + +extern int parse_mode( const char* s, mode_t* theMode); + +extern int get_kernel_revision(void); + +extern int get_console_fd(char* tty_name); +extern struct mntent *find_mount_point(const char *name, const char *table); +extern void write_mtab(char* blockDevice, char* directory, + char* filesystemType, long flags, char* string_flags); +extern void erase_mtab(const char * name); +extern long atoi_w_units (const char *cp); +extern pid_t* find_pid_by_name( char* pidName); +extern char *find_real_root_device_name(const char* name); +extern char *get_line_from_file(FILE *file); +extern void print_file(FILE *file); +extern int copyfd(int fd1, int fd2); +extern int print_file_by_name(char *filename); +extern char process_escape_sequence(const char **ptr); +extern char *get_last_path_component(char *path); +extern FILE *wfopen(const char *path, const char *mode); +extern FILE *xfopen(const char *path, const char *mode); +extern void chomp(char *s); +extern void trim(char *s); +extern struct BB_applet *find_applet_by_name(const char *name); +void run_applet_by_name(const char *name, int argc, char **argv); + +#ifndef DMALLOC +extern void *xmalloc (size_t size); +extern void *xrealloc(void *old, size_t size); +extern void *xcalloc(size_t nmemb, size_t size); +extern char *xstrdup (const char *s); +#endif +extern char *xstrndup (const char *s, int n); +extern char * safe_strncpy(char *dst, const char *src, size_t size); + +struct suffix_mult { + const char *suffix; + int mult; +}; + +extern unsigned long parse_number(const char *numstr, + const struct suffix_mult *suffixes); + + +/* These parse entries in /etc/passwd and /etc/group. This is desirable + * for BusyBox since we want to avoid using the glibc NSS stuff, which + * increases target size and is often not needed embedded systems. */ +extern long my_getpwnam(const char *name); +extern long my_getgrnam(const char *name); +extern void my_getpwuid(char *name, long uid); +extern void my_getgrgid(char *group, long gid); +extern long my_getpwnamegid(const char *name); + +extern int device_open(char *device, int mode); + +extern int del_loop(const char *device); +extern int set_loop(const char *device, const char *file, int offset, int *loopro); +extern char *find_unused_loop_device (void); + + +#if (__GLIBC__ < 2) +extern int vdprintf(int d, const char *format, va_list ap); +#endif + +int nfsmount(const char *spec, const char *node, int *flags, + char **extra_opts, char **mount_opts, int running_bg); + +void syslog_msg_with_name(const char *name, int facility, int pri, const char *msg); +void syslog_msg(int facility, int pri, const char *msg); + +/* Include our own copy of struct sysinfo to avoid binary compatability + * problems with Linux 2.4, which changed things. Grumble, grumble. */ +struct sysinfo { + long uptime; /* Seconds since boot */ + unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ + unsigned long totalram; /* Total usable main memory size */ + unsigned long freeram; /* Available memory size */ + unsigned long sharedram; /* Amount of shared memory */ + unsigned long bufferram; /* Memory used by buffers */ + unsigned long totalswap; /* Total swap space size */ + unsigned long freeswap; /* swap space still available */ + unsigned short procs; /* Number of current processes */ + unsigned short pad; /* Padding needed for m68k */ + unsigned long totalhigh; /* Total high memory size */ + unsigned long freehigh; /* Available high memory size */ + unsigned int mem_unit; /* Memory unit size in bytes */ + char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ +}; +extern int sysinfo (struct sysinfo* info); + +enum { + KILOBYTE = 1024, + MEGABYTE = (KILOBYTE*1024), + GIGABYTE = (MEGABYTE*1024) +}; +const char *make_human_readable_str(unsigned long size, unsigned long block_size, unsigned long display_unit); + +int ask_confirmation(void); +int klogctl(int type, char * b, int len); + +char *xgetcwd(char *cwd); +char *xreadlink(const char *path); +char *concat_path_file(const char *path, const char *filename); +char *last_char_is(const char *s, int c); + +extern long arith (const char *startbuf, int *errcode); + +typedef struct file_headers_s { + char *name; + char *link_name; + off_t size; + uid_t uid; + gid_t gid; + mode_t mode; + time_t mtime; + dev_t device; +} file_header_t; +file_header_t *get_header_ar(FILE *in_file); +file_header_t *get_header_cpio(FILE *src_stream); +file_header_t *get_header_tar(FILE *tar_stream); + +enum extract_functions_e { + extract_verbose_list = 1, + extract_list = 2, + extract_one_to_buffer = 4, + extract_to_stdout = 8, + extract_all_to_fs = 16, + extract_preserve_date = 32, + extract_data_tar_gz = 64, + extract_control_tar_gz = 128, + extract_unzip_only = 256, + extract_unconditional = 512, + extract_create_leading_dirs = 1024, + extract_quiet = 2048, + extract_exclude_list = 4096 +}; +char *unarchive(FILE *src_stream, FILE *out_stream, file_header_t *(*get_header)(FILE *), + const int extract_function, const char *prefix, char **extract_names); +char *deb_extract(const char *package_filename, FILE *out_stream, const int extract_function, + const char *prefix, const char *filename); +int read_package_field(const char *package_buffer, char **field_name, char **field_value); +char *fgets_str(FILE *file, const char *terminating_string); + +extern int unzip(FILE *l_in_file, FILE *l_out_file); +extern void gz_close(int gunzip_pid); +extern FILE *gz_open(FILE *compressed_file, int *pid); + +extern struct hostent *xgethostbyname(const char *name); +extern int create_icmp_socket(void); + +char *dirname (const char *path); + +int make_directory (char *path, long mode, int flags); + +const char *u_signal_names(const char *str_sig, int *signo, int startnum); + +#define CT_AUTO 0 +#define CT_UNIX2DOS 1 +#define CT_DOS2UNIX 2 +/* extern int convert(char *fn, int ConvType); */ + +enum { + FILEUTILS_PRESERVE_STATUS = 1, + FILEUTILS_PRESERVE_SYMLINKS = 2, + FILEUTILS_RECUR = 4, + FILEUTILS_FORCE = 8, + FILEUTILS_INTERACTIVE = 16 +}; + +extern const char *applet_name; +extern const char * const full_version; +extern const char * const name_too_long; +extern const char * const omitting_directory; +extern const char * const not_a_directory; +extern const char * const memory_exhausted; +extern const char * const invalid_date; +extern const char * const invalid_option; +extern const char * const io_error; +extern const char * const dash_dash_help; +extern const char * const write_error; +extern const char * const too_few_args; +extern const char * const name_longer_than_foo; +extern const char * const unknown; +extern const char * const can_not_create_raw_socket; + +#ifdef BB_FEATURE_DEVFS +# define CURRENT_VC "/dev/vc/0" +# define VC_1 "/dev/vc/1" +# define VC_2 "/dev/vc/2" +# define VC_3 "/dev/vc/3" +# define VC_4 "/dev/vc/4" +# define VC_5 "/dev/vc/5" +# define SC_0 "/dev/tts/0" +# define SC_1 "/dev/tts/1" +# define VC_FORMAT "/dev/vc/%d" +# define SC_FORMAT "/dev/tts/%d" +#else +# define CURRENT_VC "/dev/tty0" +# define VC_1 "/dev/tty1" +# define VC_2 "/dev/tty2" +# define VC_3 "/dev/tty3" +# define VC_4 "/dev/tty4" +# define VC_5 "/dev/tty5" +# define SC_0 "/dev/ttyS0" +# define SC_1 "/dev/ttyS1" +# define VC_FORMAT "/dev/tty%d" +# define SC_FORMAT "/dev/ttyS%d" +#endif + +/* The following devices are the same on devfs and non-devfs systems. */ +#define CURRENT_TTY "/dev/tty" +#define CONSOLE_DEV "/dev/console" + +#endif /* __LIBBB_H__ */ diff --git a/release/src/router/busybox/libbb/libc5.c b/release/src/router/busybox/libbb/libc5.c new file mode 100644 index 00000000..20295fd4 --- /dev/null +++ b/release/src/router/busybox/libbb/libc5.c @@ -0,0 +1,167 @@ +/* vi: set sw=4 ts=4: */ + + +#include <features.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <paths.h> +#include <unistd.h> + + +#if __GNU_LIBRARY__ < 5 + + +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* + * Modified by Manuel Novoa III Mar 1, 2001 + * + * Converted original strtok.c code of strtok to __strtok_r. + * Cleaned up logic and reduced code size. + */ + + +char *strtok_r(char *s, const char *delim, char **save_ptr) +{ + char *token; + + token = 0; /* Initialize to no token. */ + + if (s == 0) { /* If not first time called... */ + s = *save_ptr; /* restart from where we left off. */ + } + + if (s != 0) { /* If not finished... */ + *save_ptr = 0; + + s += strspn(s, delim); /* Skip past any leading delimiters. */ + if (*s != '\0') { /* We have a token. */ + token = s; + *save_ptr = strpbrk(token, delim); /* Find token's end. */ + if (*save_ptr != 0) { + /* Terminate the token and make SAVE_PTR point past it. */ + *(*save_ptr)++ = '\0'; + } + } + } + + return token; +} + +/* Basically getdelim() with the delimiter hard wired to '\n' */ +ssize_t getline(char **linebuf, size_t *n, FILE *file) +{ + return (getdelim (linebuf, n, '\n', file)); +} + + +/* + * daemon implementation for uClibc + * + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Modified for uClibc by Erik Andersen + * <andersee@debian.org>, <andersen@lineo.com> + * + * The uClibc Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the GNU C Library; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Original copyright notice is retained at the end of this file. + */ + +int daemon( int nochdir, int noclose ) +{ + int fd; + + switch (fork()) { + case -1: + return(-1); + case 0: + break; + default: + _exit(0); + } + + if (setsid() == -1) + return(-1); + + if (!nochdir) + chdir("/"); + + if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + if (fd > 2) + close(fd); + } + return(0); +} + + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. 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. <BSD Advertising Clause omitted per the July 22, 1999 licensing change + * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change> + * + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + */ + + +#endif + diff --git a/release/src/router/busybox/libbb/llist_add_to.c b/release/src/router/busybox/libbb/llist_add_to.c new file mode 100644 index 00000000..61e53f0c --- /dev/null +++ b/release/src/router/busybox/libbb/llist_add_to.c @@ -0,0 +1,15 @@ +#include <stdlib.h> +#include <string.h> +#include "unarchive.h" +#include "libbb.h" + +extern llist_t *llist_add_to(llist_t *old_head, char *new_item) +{ + llist_t *new_head; + + new_head = xmalloc(sizeof(llist_t)); + new_head->data = new_item; + new_head->link = old_head; + + return(new_head); +} diff --git a/release/src/router/busybox/libbb/login.c b/release/src/router/busybox/libbb/login.c new file mode 100644 index 00000000..3f67a819 --- /dev/null +++ b/release/src/router/busybox/libbb/login.c @@ -0,0 +1,128 @@ +/* + * issue.c: issue printing code + * + * Copyright (C) 2003 Bastian Blank <waldi@tuxbox.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Optimize and correcting OCRNL by Vladimir Oleynik <dzo@simtreas.ru> + */ + +#include <sys/param.h> /* MAXHOSTNAMELEN */ +#include <stdio.h> +#include <unistd.h> +#include "libbb.h" + +#include <sys/utsname.h> +#include <time.h> + +#define LOGIN " login: " + +static const char fmtstr_d[] = "%A, %d %B %Y"; +static const char fmtstr_t[] = "%H:%M:%S"; + +void print_login_issue(const char *issue_file, const char *tty) +{ + FILE *fd; + int c; + char buf[256]; + const char *outbuf; + time_t t; + struct utsname uts; + + time(&t); + uname(&uts); + + puts("\r"); /* start a new line */ + + if ((fd = fopen(issue_file, "r"))) { + while ((c = fgetc(fd)) != EOF) { + outbuf = buf; + buf[0] = c; + if(c == '\n') { + buf[1] = '\r'; + buf[2] = 0; + } else { + buf[1] = 0; + } + if (c == '\\' || c == '%') { + c = fgetc(fd); + switch (c) { + case 's': + outbuf = uts.sysname; + break; + + case 'n': + outbuf = uts.nodename; + break; + + case 'r': + outbuf = uts.release; + break; + + case 'v': + outbuf = uts.version; + break; + + case 'm': + outbuf = uts.machine; + break; + + case 'D': + case 'o': + getdomainname(buf, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + break; + + case 'd': + strftime(buf, sizeof(buf), fmtstr_d, localtime(&t)); + break; + + case 't': + strftime(buf, sizeof(buf), fmtstr_t, localtime(&t)); + break; + + case 'h': + gethostname(buf, sizeof(buf) - 1); + break; + + case 'l': + outbuf = tty; + break; + + default: + buf[0] = c; + } + } + fputs(outbuf, stdout); + } + + fclose(fd); + + fflush(stdout); + } +} + +void print_login_prompt(void) +{ + char buf[MAXHOSTNAMELEN+1]; + + gethostname(buf, MAXHOSTNAMELEN); + fputs(buf, stdout); + + fputs(LOGIN, stdout); + fflush(stdout); +} + diff --git a/release/src/router/busybox/libbb/loop.c b/release/src/router/busybox/libbb/loop.c new file mode 100644 index 00000000..4754b8da --- /dev/null +++ b/release/src/router/busybox/libbb/loop.c @@ -0,0 +1,128 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include "libbb.h" +#include "loop.h" /* Pull in loop device support */ + +extern int del_loop(const char *device) +{ + int fd; + + if ((fd = open(device, O_RDONLY)) < 0) { + perror_msg("%s", device); + return (FALSE); + } + if (ioctl(fd, LOOP_CLR_FD, 0) < 0) { + perror_msg("ioctl: LOOP_CLR_FD"); + return (FALSE); + } + close(fd); + return (TRUE); +} + +extern int set_loop(const char *device, const char *file, int offset, + int *loopro) +{ + struct loop_info loopinfo; + int fd, ffd, mode; + + mode = *loopro ? O_RDONLY : O_RDWR; + if ((ffd = open(file, mode)) < 0 && !*loopro + && (errno != EROFS || (ffd = open(file, mode = O_RDONLY)) < 0)) { + perror_msg("%s", file); + return 1; + } + if ((fd = open(device, mode)) < 0) { + close(ffd); + perror_msg("%s", device); + return 1; + } + *loopro = (mode == O_RDONLY); + + memset(&loopinfo, 0, sizeof(loopinfo)); + safe_strncpy(loopinfo.lo_name, file, LO_NAME_SIZE); + + loopinfo.lo_offset = offset; + + loopinfo.lo_encrypt_key_size = 0; + if (ioctl(fd, LOOP_SET_FD, ffd) < 0) { + perror_msg("ioctl: LOOP_SET_FD"); + close(fd); + close(ffd); + return 1; + } + if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) { + (void) ioctl(fd, LOOP_CLR_FD, 0); + perror_msg("ioctl: LOOP_SET_STATUS"); + close(fd); + close(ffd); + return 1; + } + close(fd); + close(ffd); + return 0; +} + +extern char *find_unused_loop_device(void) +{ + char dev[20]; + int i, fd; + struct stat statbuf; + struct loop_info loopinfo; + + for (i = 0; i <= 7; i++) { + sprintf(dev, "/dev/loop%d", i); + if (stat(dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) { + if ((fd = open(dev, O_RDONLY)) >= 0) { + if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) != 0) { + if (errno == ENXIO) { /* probably free */ + close(fd); + return strdup(dev); + } + } + close(fd); + } + } + } + return NULL; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/make_directory.c b/release/src/router/busybox/libbb/make_directory.c new file mode 100644 index 00000000..0a9d7b16 --- /dev/null +++ b/release/src/router/busybox/libbb/make_directory.c @@ -0,0 +1,67 @@ +/* vi: set sw=4 ts=4: */ +/* + * Mini make_directory implementation for busybox + * + * Copyright (C) 2001 Matt Kraai. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> + +#include "libbb.h" + +/* Create the directory PATH with mode MODE, or the default if MODE is -1. + * Also create parent directories as necessary if flags contains + * FILEUTILS_RECUR. */ + +int make_directory (char *path, long mode, int flags) +{ + if (!(flags & FILEUTILS_RECUR)) { + if (mkdir (path, 0777) < 0) { + perror_msg ("Cannot create directory `%s'", path); + return -1; + } + + if (mode != -1 && chmod (path, mode) < 0) { + perror_msg ("Cannot set permissions of directory `%s'", path); + return -1; + } + } else { + struct stat st; + + if (stat (path, &st) < 0 && errno == ENOENT) { + char *parent = dirname (path); + mode_t mask = umask (0); + umask (mask); + + if (make_directory (parent, (0777 & ~mask) | 0300, + FILEUTILS_RECUR) < 0) + return -1; + free (parent); + + if (make_directory (path, mode, 0) < 0) + return -1; + } + } + + return 0; +} diff --git a/release/src/router/busybox/libbb/messages.c b/release/src/router/busybox/libbb/messages.c new file mode 100644 index 00000000..552c3ab5 --- /dev/null +++ b/release/src/router/busybox/libbb/messages.c @@ -0,0 +1,67 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2001 by Lineo, inc. + * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "libbb.h" + +#ifdef L_full_version + const char * const full_version = BB_BANNER " multi-call binary"; +#endif +#ifdef L_name_too_long + const char * const name_too_long = "file name too long"; +#endif + +#ifdef L_omitting_directory + const char * const omitting_directory = "%s: omitting directory"; +#endif +#ifdef L_not_a_directory + const char * const not_a_directory = "%s: not a directory"; +#endif +#ifdef L_memory_exhausted + const char * const memory_exhausted = "memory exhausted"; +#endif +#ifdef L_invalid_date + const char * const invalid_date = "invalid date `%s'"; +#endif +#ifdef L_invalid_option + const char * const invalid_option = "invalid option -- %c"; +#endif +#ifdef L_io_error + const char * const io_error = "%s: input/output error -- %s"; +#endif +#ifdef L_dash_dash_help + const char * const dash_dash_help = "--help"; +#endif +#ifdef L_write_error + const char * const write_error = "Write Error"; +#endif +#ifdef L_too_few_args + const char * const too_few_args = "too few arguments"; +#endif +#ifdef L_name_longer_than_foo + const char * const name_longer_than_foo = "Names longer than %d chars not supported."; +#endif +#ifdef L_unknown + const char * const unknown = "(unknown)"; +#endif + +#ifdef L_can_not_create_raw_socket + const char * const can_not_create_raw_socket = "can`t create raw socket"; +#endif diff --git a/release/src/router/busybox/libbb/mk_loop_h.sh b/release/src/router/busybox/libbb/mk_loop_h.sh new file mode 100755 index 00000000..71c98737 --- /dev/null +++ b/release/src/router/busybox/libbb/mk_loop_h.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# Figure out (i) the type of dev_t (ii) the defines for loop stuff +# +# Output of this script is normally redirected to "loop.h". + +# Since 1.3.79 there is an include file <asm/posix_types.h> +# that defines __kernel_dev_t. +# (The file itself appeared in 1.3.78, but there it defined __dev_t.) +# If it exists, we use it, or, rather, <linux/posix_types.h> which +# avoids namespace pollution. Otherwise we guess that __kernel_dev_t +# is an unsigned short (which is true on i386, but false on alpha). + +# BUG: This test is actually broken if your gcc is not configured to +# search /usr/include, as may well happen with cross-compilers. +# It would be better to ask $(CC) if these files can be found. + +if [ -f /usr/include/linux/posix_types.h ]; then + echo '#include <linux/posix_types.h>' + echo '#undef dev_t' + echo '#define dev_t __kernel_dev_t' +else + echo '#undef dev_t' + echo '#define dev_t unsigned short' +fi + +# Next we have to find the loop stuff itself. +# First try kernel source, then a private version. + +if [ -f /usr/include/linux/loop.h ]; then + echo '#include <linux/loop.h>' +else + echo '#include "real_loop.h"' +fi + +echo '#undef dev_t' + diff --git a/release/src/router/busybox/libbb/mode_string.c b/release/src/router/busybox/libbb/mode_string.c new file mode 100644 index 00000000..0a3d6e6f --- /dev/null +++ b/release/src/router/busybox/libbb/mode_string.c @@ -0,0 +1,82 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include "libbb.h" + + + +#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f) +#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)]) + +/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */ +static const mode_t SBIT[] = { + 0, 0, S_ISUID, + 0, 0, S_ISGID, + 0, 0, S_ISVTX +}; + +/* The 9 mode bits to test */ +static const mode_t MBIT[] = { + S_IRUSR, S_IWUSR, S_IXUSR, + S_IRGRP, S_IWGRP, S_IXGRP, + S_IROTH, S_IWOTH, S_IXOTH +}; + +static const char MODE1[] = "rwxrwxrwx"; +static const char MODE0[] = "---------"; +static const char SMODE1[] = "..s..s..t"; +static const char SMODE0[] = "..S..S..T"; + +/* + * Return the standard ls-like mode string from a file mode. + * This is static and so is overwritten on each call. + */ +const char *mode_string(int mode) +{ + static char buf[12]; + + int i; + + buf[0] = TYPECHAR(mode); + for (i = 0; i < 9; i++) { + if (mode & SBIT[i]) + buf[i + 1] = (mode & MBIT[i]) ? SMODE1[i] : SMODE0[i]; + else + buf[i + 1] = (mode & MBIT[i]) ? MODE1[i] : MODE0[i]; + } + return buf; +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/module_syscalls.c b/release/src/router/busybox/libbb/module_syscalls.c new file mode 100644 index 00000000..36b75fb9 --- /dev/null +++ b/release/src/router/busybox/libbb/module_syscalls.c @@ -0,0 +1,88 @@ +/* vi: set sw=4 ts=4: */ +/* + * some system calls possibly missing from libc + * + * Copyright (C) 1999,2000,2001 by Lineo, inc. + * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +/* Kernel headers before 2.1.mumble need this on the Alpha to get + _syscall* defined. */ +#define __LIBRARY__ +#include <sys/syscall.h> +#ifndef __UCLIBC__ +#include <asm/unistd.h> +#endif +#include "libbb.h" + + +#if __GNU_LIBRARY__ < 5 +/* These syscalls are not included as part of libc5 */ +_syscall1(int, delete_module, const char *, name); +_syscall1(int, get_kernel_syms, __ptr_t, ks); + +/* This may have 5 arguments (for old 2.0 kernels) or 2 arguments + * (for 2.2 and 2.4 kernels). Use the greatest common denominator, + * and let the kernel cope with whatever it gets. Its good at that. */ +_syscall5(int, init_module, void *, first, void *, second, void *, third, + void *, fourth, void *, fifth); + +#ifndef __NR_query_module +#warning This kernel does not support the query_module syscall +#warning -> The query_module system call is being stubbed out... +int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret) +{ + fprintf(stderr, "\n\nTo make this application work, you will need to recompile\n"); + fprintf(stderr, "with a kernel supporting the query_module system call. -Erik\n\n"); + errno=ENOSYS; + return -1; +} +#else +_syscall5(int, query_module, const char *, name, int, which, + void *, buf, size_t, bufsize, size_t*, ret); +#endif + +/* Jump through hoops to fixup error return codes */ +#define __NR___create_module __NR_create_module +static inline _syscall2(long, __create_module, const char *, name, size_t, size) +unsigned long create_module(const char *name, size_t size) +{ + long ret = __create_module(name, size); + + if (ret == -1 && errno > 125) { + ret = -errno; + errno = 0; + } + return ret; +} + +#endif /* __GNU_LIBRARY__ < 5 */ + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ + diff --git a/release/src/router/busybox/libbb/mtab.c b/release/src/router/busybox/libbb/mtab.c new file mode 100644 index 00000000..28c9978e --- /dev/null +++ b/release/src/router/busybox/libbb/mtab.c @@ -0,0 +1,95 @@ +/* vi: set sw=4 ts=4: */ +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <mntent.h> +#include "libbb.h" + +extern const char mtab_file[]; /* Defined in utility.c */ +static const int MS_RDONLY = 1; /* Mount read-only. */ + +void erase_mtab(const char *name) +{ + struct mntent entries[20]; + int count = 0; + FILE *mountTable = setmntent(mtab_file, "r"); + struct mntent *m; + + /* Check if reading the mtab file failed */ + if (mountTable == 0 + /* Bummer. fall back on trying the /proc filesystem */ + && (mountTable = setmntent("/proc/mounts", "r")) == 0) { + perror_msg("%s", mtab_file); + return; + } + + while ((m = getmntent(mountTable)) != 0) { + entries[count].mnt_fsname = strdup(m->mnt_fsname); + entries[count].mnt_dir = strdup(m->mnt_dir); + entries[count].mnt_type = strdup(m->mnt_type); + entries[count].mnt_opts = strdup(m->mnt_opts); + entries[count].mnt_freq = m->mnt_freq; + entries[count].mnt_passno = m->mnt_passno; + count++; + } + endmntent(mountTable); + if ((mountTable = setmntent(mtab_file, "w"))) { + int i; + + for (i = 0; i < count; i++) { + int result = (strcmp(entries[i].mnt_fsname, name) == 0 + || strcmp(entries[i].mnt_dir, name) == 0); + + if (result) + continue; + else + addmntent(mountTable, &entries[i]); + } + endmntent(mountTable); + } else if (errno != EROFS) + perror_msg("%s", mtab_file); +} + +void write_mtab(char *blockDevice, char *directory, + char *filesystemType, long flags, char *string_flags) +{ + FILE *mountTable = setmntent(mtab_file, "a+"); + struct mntent m; + + if (mountTable == 0) { + perror_msg("%s", mtab_file); + return; + } + if (mountTable) { + int length = strlen(directory); + + if (length > 1 && directory[length - 1] == '/') + directory[length - 1] = '\0'; + + if (filesystemType == 0) { + struct mntent *p = find_mount_point(blockDevice, "/proc/mounts"); + + if (p && p->mnt_type) + filesystemType = p->mnt_type; + } + m.mnt_fsname = blockDevice; + m.mnt_dir = directory; + m.mnt_type = filesystemType ? filesystemType : "default"; + + if (*string_flags) { + m.mnt_opts = string_flags; + } else { + if ((flags | MS_RDONLY) == flags) + m.mnt_opts = "ro"; + else + m.mnt_opts = "rw"; + } + + m.mnt_freq = 0; + m.mnt_passno = 0; + addmntent(mountTable, &m); + endmntent(mountTable); + } +} diff --git a/release/src/router/busybox/libbb/mtab_file.c b/release/src/router/busybox/libbb/mtab_file.c new file mode 100644 index 00000000..c872b9a7 --- /dev/null +++ b/release/src/router/busybox/libbb/mtab_file.c @@ -0,0 +1,52 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include "libbb.h" + + +/* Busybox mount uses either /proc/mounts or /dev/mtab to + * get the list of currently mounted filesystems */ +#if defined BB_FEATURE_MOUNT_MTAB_SUPPORT +const char mtab_file[] = "/etc/mtab"; +#else +# if defined BB_FEATURE_USE_DEVPS_PATCH + const char mtab_file[] = "/dev/mtab"; +# else + const char mtab_file[] = "/proc/mounts"; +# endif +#endif + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/my_getgrgid.c b/release/src/router/busybox/libbb/my_getgrgid.c new file mode 100644 index 00000000..fabd4776 --- /dev/null +++ b/release/src/router/busybox/libbb/my_getgrgid.c @@ -0,0 +1,55 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include "../pwd_grp/pwd.h" +#include "../pwd_grp/grp.h" +#include "libbb.h" + + +/* gets a groupname given a gid */ +void my_getgrgid(char *group, long gid) +{ + struct group *mygroup; + + mygroup = getgrgid(gid); + if (mygroup==NULL) + sprintf(group, "%-8ld ", (long)gid); + else + strcpy(group, mygroup->gr_name); +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/my_getgrnam.c b/release/src/router/busybox/libbb/my_getgrnam.c new file mode 100644 index 00000000..e3226a27 --- /dev/null +++ b/release/src/router/busybox/libbb/my_getgrnam.c @@ -0,0 +1,56 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include "../pwd_grp/pwd.h" +#include "../pwd_grp/grp.h" +#include "libbb.h" + + + +/* returns a gid given a group name */ +long my_getgrnam(const char *name) +{ + struct group *mygroup; + + mygroup = getgrnam(name); + if (mygroup==NULL) + error_msg_and_die("unknown group name: %s", name); + + return (mygroup->gr_gid); +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/my_getpwnam.c b/release/src/router/busybox/libbb/my_getpwnam.c new file mode 100644 index 00000000..ae73ae7f --- /dev/null +++ b/release/src/router/busybox/libbb/my_getpwnam.c @@ -0,0 +1,56 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include "../pwd_grp/pwd.h" +#include "../pwd_grp/grp.h" +#include "libbb.h" + + + +/* returns a uid given a username */ +long my_getpwnam(const char *name) +{ + struct passwd *myuser; + + myuser = getpwnam(name); + if (myuser==NULL) + error_msg_and_die("unknown user name: %s", name); + + return myuser->pw_uid; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/my_getpwnamegid.c b/release/src/router/busybox/libbb/my_getpwnamegid.c new file mode 100644 index 00000000..fb3d148c --- /dev/null +++ b/release/src/router/busybox/libbb/my_getpwnamegid.c @@ -0,0 +1,61 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include "../pwd_grp/pwd.h" +#include "../pwd_grp/grp.h" +#include "libbb.h" + + + +/* gets a gid given a user name */ +long my_getpwnamegid(const char *name) +{ + struct group *mygroup; + struct passwd *myuser; + + myuser=getpwnam(name); + if (myuser==NULL) + error_msg_and_die("unknown user name: %s", name); + + mygroup = getgrgid(myuser->pw_gid); + if (mygroup==NULL) + error_msg_and_die("unknown gid %ld", (long)myuser->pw_gid); + + return mygroup->gr_gid; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/my_getpwuid.c b/release/src/router/busybox/libbb/my_getpwuid.c new file mode 100644 index 00000000..46c7a884 --- /dev/null +++ b/release/src/router/busybox/libbb/my_getpwuid.c @@ -0,0 +1,55 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include "../pwd_grp/pwd.h" +#include "../pwd_grp/grp.h" +#include "libbb.h" + + + +/* gets a username given a uid */ +void my_getpwuid(char *name, long uid) +{ + struct passwd *myuser; + + myuser = getpwuid(uid); + if (myuser==NULL) + sprintf(name, "%-8ld ", (long)uid); + else + strcpy(name, myuser->pw_name); +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/obscure.c b/release/src/router/busybox/libbb/obscure.c new file mode 100644 index 00000000..537d4484 --- /dev/null +++ b/release/src/router/busybox/libbb/obscure.c @@ -0,0 +1,251 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh <jockgrrl@austin.rr.com> + * 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. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``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 JULIE HAUGH OR CONTRIBUTORS 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. + */ + +/* + * This version of obscure.c contains modifications to support "cracklib" + * by Alec Muffet (alec.muffett@uk.sun.com). You must obtain the Cracklib + * library source code for this function to operate. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "libbb.h" + +/* + * can't be a palindrome - like `R A D A R' or `M A D A M' + */ + +static int palindrome(const char *newval) +{ + int i, j; + + i = strlen(newval); + + for (j = 0; j < i; j++) + if (newval[i - j - 1] != newval[j]) + return 0; + + return 1; +} + +/* + * more than half of the characters are different ones. + */ + +static int similiar(const char *old, const char *newval) +{ + int i, j; + + for (i = j = 0; newval[i] && old[i]; i++) + if (strchr(newval, old[i])) + j++; + + if (i >= j * 2) + return 0; + + return 1; +} + +/* + * a nice mix of characters. + */ + +static int simple(const char *newval) +{ + int digits = 0; + int uppers = 0; + int lowers = 0; + int others = 0; + int c; + int size; + int i; + + for (i = 0; (c = *newval++) != 0; i++) { + if (isdigit(c)) + digits = c; + else if (isupper(c)) + uppers = c; + else if (islower(c)) + lowers = c; + else + others = c; + } + + /* + * The scam is this - a password of only one character type + * must be 8 letters long. Two types, 7, and so on. + */ + + size = 9; + if (digits) + size--; + if (uppers) + size--; + if (lowers) + size--; + if (others) + size--; + + if (size <= i) + return 0; + + return 1; +} + +static char *str_lower(char *string) +{ + char *cp; + + for (cp = string; *cp; cp++) + *cp = tolower(*cp); + return string; +} + +static const char * +password_check(const char *old, const char *newval, const struct passwd *pwdp) +{ + const char *msg; + char *newmono, *wrapped; + int lenwrap; + + if (strcmp(newval, old) == 0) + return "no change"; + if (simple(newval)) + return "too simple"; + + msg = NULL; + newmono = str_lower(bb_xstrdup(newval)); + lenwrap = strlen(old) * 2 + 1; + wrapped = (char *) xmalloc(lenwrap); + str_lower(strcpy(wrapped, old)); + + if (palindrome(newmono)) + msg = "a palindrome"; + + else if (strcmp(wrapped, newmono) == 0) + msg = "case changes only"; + + else if (similiar(wrapped, newmono)) + msg = "too similiar"; + + else { + safe_strncpy(wrapped + lenwrap, wrapped, lenwrap + 1); + if (strstr(wrapped, newmono)) + msg = "rotated"; + } + + bzero(newmono, strlen(newmono)); + bzero(wrapped, lenwrap); + free(newmono); + free(wrapped); + + return msg; +} + +static const char * +obscure_msg(const char *old, const char *newval, const struct passwd *pwdp) +{ + int maxlen, oldlen, newlen; + char *new1, *old1; + const char *msg; + + oldlen = strlen(old); + newlen = strlen(newval); + +#if 0 /* why not check the password when set for the first time? --marekm */ + if (old[0] == '\0') + /* return (1); */ + return NULL; +#endif + + if (newlen < 5) + return "too short"; + + /* + * Remaining checks are optional. + */ + /* Not for us -- Sean + *if (!getdef_bool("OBSCURE_CHECKS_ENAB")) + * return NULL; + */ + msg = password_check(old, newval, pwdp); + if (msg) + return msg; + + /* The traditional crypt() truncates passwords to 8 chars. It is + possible to circumvent the above checks by choosing an easy + 8-char password and adding some random characters to it... + Example: "password$%^&*123". So check it again, this time + truncated to the maximum length. Idea from npasswd. --marekm */ + + maxlen = 8; + if (oldlen <= maxlen && newlen <= maxlen) + return NULL; + + new1 = (char *) bb_xstrdup(newval); + old1 = (char *) bb_xstrdup(old); + if (newlen > maxlen) + new1[maxlen] = '\0'; + if (oldlen > maxlen) + old1[maxlen] = '\0'; + + msg = password_check(old1, new1, pwdp); + + bzero(new1, newlen); + bzero(old1, oldlen); + free(new1); + free(old1); + + return msg; +} + +/* + * Obscure - see if password is obscure enough. + * + * The programmer is encouraged to add as much complexity to this + * routine as desired. Included are some of my favorite ways to + * check passwords. + */ + +extern int obscure(const char *old, const char *newval, const struct passwd *pwdp) +{ + const char *msg = obscure_msg(old, newval, pwdp); + + /* if (msg) { */ + if (msg != NULL) { + printf("Bad password: %s.\n", msg); + /* return 0; */ + return 1; + } + /* return 1; */ + return 0; +} diff --git a/release/src/router/busybox/libbb/parse_mode.c b/release/src/router/busybox/libbb/parse_mode.c new file mode 100644 index 00000000..30d2f21c --- /dev/null +++ b/release/src/router/busybox/libbb/parse_mode.c @@ -0,0 +1,138 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include "libbb.h" + + +/* This function parses the sort of string you might pass + * to chmod (i.e., [ugoa]{+|-|=}[rwxst] ) and returns the + * correct mode described by the string. */ +extern int parse_mode(const char *s, mode_t * theMode) +{ + static const mode_t group_set[] = { + S_ISUID | S_IRWXU, /* u */ + S_ISGID | S_IRWXG, /* g */ + S_IRWXO, /* o */ + S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO /* a */ + }; + + static const mode_t mode_set[] = { + S_IRUSR | S_IRGRP | S_IROTH, /* r */ + S_IWUSR | S_IWGRP | S_IWOTH, /* w */ + S_IXUSR | S_IXGRP | S_IXOTH, /* x */ + S_ISUID | S_ISGID, /* s */ + S_ISVTX /* t */ + }; + + static const char group_chars[] = "ugoa"; + static const char mode_chars[] = "rwxst"; + + const char *p; + + mode_t andMode = + S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; + mode_t orMode = 0; + mode_t mode; + mode_t groups; + char type; + char c; + + if (s==NULL) { + return (FALSE); + } + + do { + mode = 0; + groups = 0; + NEXT_GROUP: + if ((c = *s++) == '\0') { + return -1; + } + for (p=group_chars ; *p ; p++) { + if (*p == c) { + groups |= group_set[(int)(p-group_chars)]; + goto NEXT_GROUP; + } + } + switch (c) { + case '=': + case '+': + case '-': + type = c; + if (groups == 0) { /* The default is "all" */ + groups |= S_ISUID | S_ISGID | S_ISVTX + | S_IRWXU | S_IRWXG | S_IRWXO; + } + break; + default: + if ((c < '0') || (c > '7') || (mode | groups)) { + return (FALSE); + } else { + *theMode = strtol(--s, NULL, 8); + return (TRUE); + } + } + + NEXT_MODE: + if (((c = *s++) != '\0') && (c != ',')) { + for (p=mode_chars ; *p ; p++) { + if (*p == c) { + mode |= mode_set[(int)(p-mode_chars)]; + goto NEXT_MODE; + } + } + break; /* We're done so break out of loop.*/ + } + switch (type) { + case '=': + andMode &= ~(groups); /* Now fall through. */ + case '+': + orMode |= mode & groups; + break; + case '-': + andMode &= ~(mode & groups); + orMode &= ~(mode & groups); + break; + } + } while (c == ','); + + *theMode &= andMode; + *theMode |= orMode; + + return TRUE; +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/parse_number.c b/release/src/router/busybox/libbb/parse_number.c new file mode 100644 index 00000000..c90511dc --- /dev/null +++ b/release/src/router/busybox/libbb/parse_number.c @@ -0,0 +1,74 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "libbb.h" + + +unsigned long parse_number(const char *numstr, + const struct suffix_mult *suffixes) +{ + const struct suffix_mult *sm; + unsigned long int ret; + int len; + char *end; + + ret = strtoul(numstr, &end, 10); + if (numstr == end) + error_msg_and_die("invalid number `%s'", numstr); + while (end[0] != '\0') { + sm = suffixes; + while ( sm != 0 ) { + if(sm->suffix) { + len = strlen(sm->suffix); + if (strncmp(sm->suffix, end, len) == 0) { + ret *= sm->mult; + end += len; + break; + } + sm++; + + } else + sm = 0; + } + if (sm == 0) + error_msg_and_die("invalid number `%s'", numstr); + } + return ret; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/perror_msg.c b/release/src/router/busybox/libbb/perror_msg.c new file mode 100644 index 00000000..18c71ab1 --- /dev/null +++ b/release/src/router/busybox/libbb/perror_msg.c @@ -0,0 +1,51 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include "libbb.h" + +extern void perror_msg(const char *s, ...) +{ + va_list p; + + va_start(p, s); + vperror_msg(s, p); + va_end(p); +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/perror_msg_and_die.c b/release/src/router/busybox/libbb/perror_msg_and_die.c new file mode 100644 index 00000000..9d304a26 --- /dev/null +++ b/release/src/router/busybox/libbb/perror_msg_and_die.c @@ -0,0 +1,52 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include "libbb.h" + +extern void perror_msg_and_die(const char *s, ...) +{ + va_list p; + + va_start(p, s); + vperror_msg(s, p); + va_end(p); + exit(EXIT_FAILURE); +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/perror_nomsg.c b/release/src/router/busybox/libbb/perror_nomsg.c new file mode 100644 index 00000000..464cb86c --- /dev/null +++ b/release/src/router/busybox/libbb/perror_nomsg.c @@ -0,0 +1,30 @@ +/* vi: set sw=4 ts=4: */ +/* + * bb_perror_nomsg implementation for busybox + * + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stddef.h> +#include <libbb.h> + +extern void bb_perror_nomsg(void) +{ + /* Ignore the gcc warning about a null format string. */ + bb_perror_msg(NULL); +} diff --git a/release/src/router/busybox/libbb/perror_nomsg_and_die.c b/release/src/router/busybox/libbb/perror_nomsg_and_die.c new file mode 100644 index 00000000..bab22845 --- /dev/null +++ b/release/src/router/busybox/libbb/perror_nomsg_and_die.c @@ -0,0 +1,30 @@ +/* vi: set sw=4 ts=4: */ +/* + * bb_perror_nomsg_and_die implementation for busybox + * + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stddef.h> +#include "libbb.h" + +extern void bb_perror_nomsg_and_die(void) +{ + /* Ignore the gcc warning about a null format string. */ + bb_perror_msg_and_die(NULL); +} diff --git a/release/src/router/busybox/libbb/print_file.c b/release/src/router/busybox/libbb/print_file.c new file mode 100644 index 00000000..bfedc5ef --- /dev/null +++ b/release/src/router/busybox/libbb/print_file.c @@ -0,0 +1,61 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) 1999-2001 Erik Andersen <andersee@debian.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <sys/stat.h> +#include "libbb.h" + + +extern void print_file(FILE *file) +{ + fflush(stdout); + copyfd(fileno(file), fileno(stdout)); + fclose(file); +} + +extern int print_file_by_name(char *filename) +{ + struct stat statBuf; + int status = TRUE; + + if(is_directory(filename, TRUE, &statBuf)==TRUE) { + error_msg("%s: Is directory", filename); + status = FALSE; + } else { + FILE *f = wfopen(filename, "r"); + if(f!=NULL) + print_file(f); + else + status = FALSE; + } + + return status; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/printf.c b/release/src/router/busybox/libbb/printf.c new file mode 100644 index 00000000..923c5a1a --- /dev/null +++ b/release/src/router/busybox/libbb/printf.c @@ -0,0 +1,177 @@ +/* vi: set sw=4 ts=4: */ +/* + * *printf implementations for busybox + * + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* Mar 12, 2003 Manuel Novoa III + * + * While fwrite(), fputc(), fputs(), etc. all set the stream error flag + * on failure, the *printf functions are unique in that they can fail + * for reasons not related to the actual output itself. Among the possible + * reasons for failure which don't set the streams error indicator, + * SUSv3 lists EILSEQ, EINVAL, and ENOMEM. + * + * In some cases, it would be desireable to have a group of *printf() + * functions available that _always_ set the stream error indicator on + * failure. That would allow us to defer error checking until applet + * exit. Unfortunately, there is no standard way of setting a streams + * error indicator... even though we can clear it with clearerr(). + * + * Therefore, we have to resort to implementation dependent code. Feel + * free to send patches for stdio implementations where the following + * fails. + * + * NOTE: None of this is threadsafe. As busybox is a nonthreaded app, + * that isn't currently an issue. + */ + +#include <stdio.h> +#include <stdarg.h> +#include "libbb.h" + +#if defined(__UCLIBC__) + +# if defined(__FLAG_ERROR) +/* Using my newer stdio implementation. Unlocked macros are: + * #define __CLEARERR(stream) \ + ((stream)->modeflags &= ~(__FLAG_EOF|__FLAG_ERROR), (void)0) + * #define __FEOF(stream) ((stream)->modeflags & __FLAG_EOF) + * #define __FERROR(stream) ((stream)->modeflags & __FLAG_ERROR) + */ +#define SET_FERROR_UNLOCKED(S) ((S)->modeflags |= __FLAG_ERROR) + +#elif defined(__MODE_ERR) +/* Using either the original stdio implementation (from dev86) or + * my original stdio rewrite. Macros were: + * #define ferror(fp) (((fp)->mode&__MODE_ERR) != 0) + * #define feof(fp) (((fp)->mode&__MODE_EOF) != 0) + * #define clearerr(fp) ((fp)->mode &= ~(__MODE_EOF|__MODE_ERR),0) + */ +#define SET_FERROR_UNLOCKED(S) ((S)->mode |= __MODE_ERR) + +#else +#error unknown uClibc stdio implemenation! +#endif + +#elif defined(__GLIBC__) + +# if defined(_STDIO_USES_IOSTREAM) +/* Apparently using the newer libio implementation, with associated defines: + * #define _IO_feof_unlocked(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0) + * #define _IO_ferror_unlocked(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0) + */ +#define SET_FERROR_UNLOCKED(S) ((S)->_flags |= _IO_ERR_SEEN) + +# else +/* Assume the older version of glibc which used a bitfield entry + * as a stream error flag. The associated defines were: + * #define __clearerr(stream) ((stream)->__error = (stream)->__eof = 0) + * #define feof_unlocked(stream) ((stream)->__eof != 0) + * #define ferror_unlocked(stream) ((stream)->__error != 0) + */ +#define SET_FERROR_UNLOCKED(S) ((S)->__error = 1) + +# endif + +#elif defined(__NEWLIB_H__) +/* I honestly don't know if there are different versions of stdio in + * newlibs history. Anyway, here's what's current. + * #define __sfeof(p) (((p)->_flags & __SEOF) != 0) + * #define __sferror(p) (((p)->_flags & __SERR) != 0) + * #define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF))) + */ +#define SET_FERROR_UNLOCKED(S) ((S)->_flags |= __SERR) + +#elif defined(__dietlibc__) +/* + * WARNING!!! dietlibc is quite buggy. WARNING!!! + * + * Some example bugs as of March 12, 2003... + * 1) fputc() doesn't set the error indicator on failure. + * 2) freopen() doesn't maintain the same stream object, contary to + * standards. This makes it useless in its primary role of + * reassociating stdin/stdout/stderr. + * 3) printf() often fails to correctly format output when conversions + * involve padding. It is also practically useless for floating + * point output. + * + * But, if you're determined to use it anyway, (as of the current version) + * you can extract the information you need from dietstdio.h. See the + * other library implementations for examples. + */ +#error dietlibc is currently not supported. Please see the commented source. + +#else /* some other lib */ +/* Please see the comments for the above supported libaries for examples + * of what is required to support your stdio implementation. + */ +#error Your stdio library is currently not supported. Please see the commented source. +#endif + +#ifdef L_bb_vfprintf +extern int bb_vfprintf(FILE * __restrict stream, + const char * __restrict format, + va_list arg) +{ + int rv; + + if ((rv = vfprintf(stream, format, arg)) < 0) { + SET_FERROR_UNLOCKED(stream); + } + + return rv; +} +#endif + +#ifdef L_bb_vprintf +extern int bb_vprintf(const char * __restrict format, va_list arg) +{ + return bb_vfprintf(stdout, format, arg); +} +#endif + +#ifdef L_bb_fprintf +extern int bb_fprintf(FILE * __restrict stream, + const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = bb_vfprintf(stream, format, arg); + va_end(arg); + + return rv; +} +#endif + +#ifdef L_bb_printf +extern int bb_printf(const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = bb_vfprintf(stdout, format, arg); + va_end(arg); + + return rv; +} +#endif diff --git a/release/src/router/busybox/libbb/process_escape_sequence.c b/release/src/router/busybox/libbb/process_escape_sequence.c new file mode 100644 index 00000000..67b0490c --- /dev/null +++ b/release/src/router/busybox/libbb/process_escape_sequence.c @@ -0,0 +1,80 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) Manuel Nova III <mnovoa3@bellsouth.net> + * and Vladimir Oleynik <vodz@usa.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + */ + +#include <stdio.h> +#include <limits.h> +#include "libbb.h" + + + +char process_escape_sequence(const char **ptr) +{ + static const char charmap[] = { + 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', 0, + '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' }; + + const char *p; + const char *q; + int num_digits; + unsigned int n; + + n = 0; + q = *ptr; + + for ( num_digits = 0 ; num_digits < 3 ; ++num_digits) { + if ((*q < '0') || (*q > '7')) { /* not a digit? */ + break; + } + n = n * 8 + (*q++ - '0'); + } + + if (num_digits == 0) { /* mnemonic escape sequence? */ + for (p=charmap ; *p ; p++) { + if (*p == *q) { + q++; + break; + } + } + n = *(p+(sizeof(charmap)/2)); + } + + /* doesn't hurt to fall through to here from mnemonic case */ + if (n > UCHAR_MAX) { /* is octal code too big for a char? */ + n /= 8; /* adjust value and */ + --q; /* back up one char */ + } + + *ptr = q; + return (char) n; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/procps.c b/release/src/router/busybox/libbb/procps.c new file mode 100644 index 00000000..44103fae --- /dev/null +++ b/release/src/router/busybox/libbb/procps.c @@ -0,0 +1,152 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright 1998 by Albert Cahalan; all rights reserved. + * Copyright (C) 2002 by Vladimir Oleynik <dzo@simtreas.ru> + * GNU Library General Public License Version 2, or any later version + * + */ + +#include <dirent.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <asm/page.h> + +#include "libbb.h" + +extern procps_status_t * procps_scan(int save_user_arg0 +#ifdef CONFIG_SELINUX + , int use_selinux , security_id_t *sid +#endif + ) +{ + static DIR *dir; + struct dirent *entry; + static procps_status_t ret_status; + char *name; + int n; + char status[32]; + char buf[1024]; + FILE *fp; + procps_status_t curstatus; + int pid; + long tasknice; + struct stat sb; + + if (!dir) { + dir = opendir("/proc"); + if(!dir) + bb_error_msg_and_die("Can't open /proc"); + } + for(;;) { + if((entry = readdir(dir)) == NULL) { + closedir(dir); + dir = 0; + return 0; + } + name = entry->d_name; + if (!(*name >= '0' && *name <= '9')) + continue; + + memset(&curstatus, 0, sizeof(procps_status_t)); + pid = atoi(name); + curstatus.pid = pid; + + sprintf(status, "/proc/%d/stat", pid); + if((fp = fopen(status, "r")) == NULL) + continue; +#ifdef CONFIG_SELINUX + if(use_selinux) + { + if(fstat_secure(fileno(fp), &sb, sid)) + continue; + } + else +#endif + if(fstat(fileno(fp), &sb)) + continue; + my_getpwuid(curstatus.user, sb.st_uid); + name = fgets(buf, sizeof(buf), fp); + fclose(fp); + if(name == NULL) + continue; + name = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */ + if(name == 0 || name[1] != ' ') + continue; + *name = 0; + sscanf(buf, "%*s (%15c", curstatus.short_cmd); + n = sscanf(name+2, + "%c %d " + "%*s %*s %*s %*s " /* pgrp, session, tty, tpgid */ + "%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */ +#ifdef FEATURE_CPU_USAGE_PERCENTAGE + "%lu %lu " +#else + "%*s %*s " +#endif + "%*s %*s %*s " /* cutime, cstime, priority */ + "%ld " + "%*s %*s %*s " /* timeout, it_real_value, start_time */ + "%*s " /* vsize */ + "%ld", + curstatus.state, &curstatus.ppid, +#ifdef FEATURE_CPU_USAGE_PERCENTAGE + &curstatus.utime, &curstatus.stime, +#endif + &tasknice, + &curstatus.rss); +#ifdef FEATURE_CPU_USAGE_PERCENTAGE + if(n != 6) +#else + if(n != 4) +#endif + continue; + + if (curstatus.rss == 0 && curstatus.state[0] != 'Z') + curstatus.state[1] = 'W'; + else + curstatus.state[1] = ' '; + if (tasknice < 0) + curstatus.state[2] = '<'; + else if (tasknice > 0) + curstatus.state[2] = 'N'; + else + curstatus.state[2] = ' '; + + curstatus.rss <<= (PAGE_SHIFT - 10); /* 2**10 = 1kb */ + + if(save_user_arg0) { + sprintf(status, "/proc/%d/cmdline", pid); + if((fp = fopen(status, "r")) == NULL) + continue; + if((n=fread(buf, 1, sizeof(buf)-1, fp)) > 0) { + if(buf[n-1]=='\n') + buf[--n] = 0; + name = buf; + while(n) { + if(((unsigned char)*name) < ' ') + *name = ' '; + name++; + n--; + } + *name = 0; + if(buf[0]) + curstatus.cmd = strdup(buf); + /* if NULL it work true also */ + } + fclose(fp); + } + return memcpy(&ret_status, &curstatus, sizeof(procps_status_t)); + } +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/pw_encrypt.c b/release/src/router/busybox/libbb/pw_encrypt.c new file mode 100644 index 00000000..ce607853 --- /dev/null +++ b/release/src/router/busybox/libbb/pw_encrypt.c @@ -0,0 +1,45 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routine. + * + * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <string.h> +#include <crypt.h> +#include "libbb.h" + + +extern char *pw_encrypt(const char *clear, const char *salt) +{ + static char cipher[128]; + char *cp; + +#ifdef CONFIG_FEATURE_SHA1_PASSWORDS + if (strncmp(salt, "$2$", 3) == 0) { + return sha1_crypt(clear); + } +#endif + cp = (char *) crypt(clear, salt); + /* if crypt (a nonstandard crypt) returns a string too large, + truncate it so we don't overrun buffers and hope there is + enough security in what's left */ + safe_strncpy(cipher, cp, sizeof(cipher)); + return cipher; +} + diff --git a/release/src/router/busybox/libbb/pwd2spwd.c b/release/src/router/busybox/libbb/pwd2spwd.c new file mode 100644 index 00000000..3dd625b2 --- /dev/null +++ b/release/src/router/busybox/libbb/pwd2spwd.c @@ -0,0 +1,74 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh <jockgrrl@austin.rr.com> + * 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. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``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 JULIE HAUGH OR CONTRIBUTORS 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. + */ + +#include <time.h> +#include <sys/types.h> +#include "libbb.h" +#include "shadow_.h" + +/* + * pwd_to_spwd - create entries for new spwd structure + * + * pwd_to_spwd() creates a new (struct spwd) containing the + * information in the pointed-to (struct passwd). + */ +#define DAY (24L*3600L) +#define WEEK (7*DAY) +#define SCALE DAY +struct spwd *pwd_to_spwd(const struct passwd *pw) +{ + static struct spwd sp; + + /* + * Nice, easy parts first. The name and passwd map directly + * from the old password structure to the new one. + */ + sp.sp_namp = pw->pw_name; + sp.sp_pwdp = pw->pw_passwd; + + /* + * Defaults used if there is no pw_age information. + */ + sp.sp_min = 0; + sp.sp_max = (10000L * DAY) / SCALE; + sp.sp_lstchg = time((time_t *) 0) / SCALE; + + /* + * These fields have no corresponding information in the password + * file. They are set to uninitialized values. + */ + sp.sp_warn = -1; + sp.sp_expire = -1; + sp.sp_inact = -1; + sp.sp_flag = -1; + + return &sp; +} + diff --git a/release/src/router/busybox/libbb/qmodule.c b/release/src/router/busybox/libbb/qmodule.c new file mode 100644 index 00000000..fd14d10f --- /dev/null +++ b/release/src/router/busybox/libbb/qmodule.c @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002 Tim Riker <Tim@Rikers.org> + everyone seems to claim it someplace. ;-) +*/ + +#include <errno.h> + +#include "libbb.h" + +int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret); + +int my_query_module(const char *name, int which, void **buf, + size_t *bufsize, size_t *ret) +{ + int my_ret; + + my_ret = query_module(name, which, *buf, *bufsize, ret); + + if (my_ret == -1 && errno == ENOSPC) { + *buf = xrealloc(*buf, *ret); + *bufsize = *ret; + + my_ret = query_module(name, which, *buf, *bufsize, ret); + } + + return my_ret; +} + + diff --git a/release/src/router/busybox/libbb/read_package_field.c b/release/src/router/busybox/libbb/read_package_field.c new file mode 100644 index 00000000..f561df83 --- /dev/null +++ b/release/src/router/busybox/libbb/read_package_field.c @@ -0,0 +1,91 @@ +#include <stdlib.h> +#include <string.h> +#include "libbb.h" + +/* + * Gets the next package field from package_buffer, seperated into the field name + * and field value, it returns the int offset to the first character of the next field + */ +int read_package_field(const char *package_buffer, char **field_name, char **field_value) +{ + int offset_name_start = 0; + int offset_name_end = 0; + int offset_value_start = 0; + int offset_value_end = 0; + int offset = 0; + int next_offset; + int name_length; + int value_length; + int exit_flag = FALSE; + + if (package_buffer == NULL) { + *field_name = NULL; + *field_value = NULL; + return(-1); + } + while (1) { + next_offset = offset + 1; + switch (package_buffer[offset]) { + case('\0'): + exit_flag = TRUE; + break; + case(':'): + if (offset_name_end == 0) { + offset_name_end = offset; + offset_value_start = next_offset; + } + /* TODO: Name might still have trailing spaces if ':' isnt + * immediately after name */ + break; + case('\n'): + /* TODO: The char next_offset may be out of bounds */ + if (package_buffer[next_offset] != ' ') { + exit_flag = TRUE; + break; + } + case('\t'): + case(' '): + /* increment the value start point if its a just filler */ + if (offset_name_start == offset) { + offset_name_start++; + } + if (offset_value_start == offset) { + offset_value_start++; + } + break; + } + if (exit_flag == TRUE) { + /* Check that the names are valid */ + offset_value_end = offset; + name_length = offset_name_end - offset_name_start; + value_length = offset_value_end - offset_value_start; + if (name_length == 0) { + break; + } + if ((name_length > 0) && (value_length > 0)) { + break; + } + + /* If not valid, start fresh with next field */ + exit_flag = FALSE; + offset_name_start = offset + 1; + offset_name_end = 0; + offset_value_start = offset + 1; + offset_value_end = offset + 1; + offset++; + } + offset++; + } + if (name_length == 0) { + *field_name = NULL; + } else { + *field_name = xstrndup(&package_buffer[offset_name_start], name_length); + } + if (value_length > 0) { + *field_value = xstrndup(&package_buffer[offset_value_start], value_length); + } else { + *field_value = NULL; + } + return(next_offset); +} + diff --git a/release/src/router/busybox/libbb/real_loop.h b/release/src/router/busybox/libbb/real_loop.h new file mode 100644 index 00000000..1bd7fa87 --- /dev/null +++ b/release/src/router/busybox/libbb/real_loop.h @@ -0,0 +1,37 @@ +/* + * include/linux/loop.h + * + * Written by Theodore Ts'o, 3/29/93. + * + * Copyright 1993 by Theodore Ts'o. Redistribution of this file is + * permitted under the GNU Public License. + */ + +#define LO_NAME_SIZE 64 +#define LO_KEY_SIZE 32 + +struct loop_info { + int lo_number; /* ioctl r/o */ + dev_t lo_device; /* ioctl r/o */ + unsigned long lo_inode; /* ioctl r/o */ + dev_t lo_rdevice; /* ioctl r/o */ + int lo_offset; + int lo_encrypt_type; + int lo_encrypt_key_size; /* ioctl w/o */ + int lo_flags; /* ioctl r/o */ + char lo_name[LO_NAME_SIZE]; + unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + unsigned long lo_init[2]; + char reserved[4]; +}; + +#define LO_CRYPT_NONE 0 +#define LO_CRYPT_XOR 1 +#define LO_CRYPT_DES 2 +#define LO_CRYPT_IDEA 3 +#define MAX_LO_CRYPT 4 + +#define LOOP_SET_FD 0x4C00 +#define LOOP_CLR_FD 0x4C01 +#define LOOP_SET_STATUS 0x4C02 +#define LOOP_GET_STATUS 0x4C03 diff --git a/release/src/router/busybox/libbb/recursive_action.c b/release/src/router/busybox/libbb/recursive_action.c new file mode 100644 index 00000000..6672db17 --- /dev/null +++ b/release/src/router/busybox/libbb/recursive_action.c @@ -0,0 +1,150 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include <dirent.h> +#include <sys/stat.h> +#include <stdlib.h> /* free() */ +#include "libbb.h" + +#undef DEBUG_RECURS_ACTION + + +/* + * Walk down all the directories under the specified + * location, and do something (something specified + * by the fileAction and dirAction function pointers). + * + * Unfortunately, while nftw(3) could replace this and reduce + * code size a bit, nftw() wasn't supported before GNU libc 2.1, + * and so isn't sufficiently portable to take over since glibc2.1 + * is so stinking huge. + */ +int recursive_action(const char *fileName, + int recurse, int followLinks, int depthFirst, + int (*fileAction) (const char *fileName, + struct stat * statbuf, + void* userData), + int (*dirAction) (const char *fileName, + struct stat * statbuf, + void* userData), + void* userData) +{ + int status; + struct stat statbuf; + struct dirent *next; + + if (followLinks == TRUE) + status = stat(fileName, &statbuf); + else + status = lstat(fileName, &statbuf); + + if (status < 0) { +#ifdef DEBUG_RECURS_ACTION + fprintf(stderr, + "status=%d followLinks=%d TRUE=%d\n", + status, followLinks, TRUE); +#endif + perror_msg("%s", fileName); + return FALSE; + } + + if ((followLinks == FALSE) && (S_ISLNK(statbuf.st_mode))) { + if (fileAction == NULL) + return TRUE; + else + return fileAction(fileName, &statbuf, userData); + } + + if (recurse == FALSE) { + if (S_ISDIR(statbuf.st_mode)) { + if (dirAction != NULL) + return (dirAction(fileName, &statbuf, userData)); + else + return TRUE; + } + } + + if (S_ISDIR(statbuf.st_mode)) { + DIR *dir; + + if (dirAction != NULL && depthFirst == FALSE) { + status = dirAction(fileName, &statbuf, userData); + if (status == FALSE) { + perror_msg("%s", fileName); + return FALSE; + } else if (status == SKIP) + return TRUE; + } + dir = opendir(fileName); + if (!dir) { + perror_msg("%s", fileName); + return FALSE; + } + status = TRUE; + while ((next = readdir(dir)) != NULL) { + char *nextFile; + + if ((strcmp(next->d_name, "..") == 0) + || (strcmp(next->d_name, ".") == 0)) { + continue; + } + nextFile = concat_path_file(fileName, next->d_name); + if (recursive_action(nextFile, TRUE, followLinks, depthFirst, + fileAction, dirAction, userData) == FALSE) { + status = FALSE; + } + free(nextFile); + } + closedir(dir); + if (dirAction != NULL && depthFirst == TRUE) { + if (dirAction(fileName, &statbuf, userData) == FALSE) { + perror_msg("%s", fileName); + return FALSE; + } + } + if (status == FALSE) + return FALSE; + } else { + if (fileAction == NULL) + return TRUE; + else + return fileAction(fileName, &statbuf, userData); + } + return TRUE; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/remove_file.c b/release/src/router/busybox/libbb/remove_file.c new file mode 100644 index 00000000..3b84680c --- /dev/null +++ b/release/src/router/busybox/libbb/remove_file.c @@ -0,0 +1,129 @@ +/* vi: set sw=4 ts=4: */ +/* + * Mini remove_file implementation for busybox + * + * + * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdio.h> +#include <time.h> +#include <utime.h> +#include <dirent.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include "libbb.h" + +extern int remove_file(const char *path, int flags) +{ + struct stat path_stat; + int path_exists = 1; + + if (lstat(path, &path_stat) < 0) { + if (errno != ENOENT) { + perror_msg("unable to stat `%s'", path); + return -1; + } + + path_exists = 0; + } + + if (!path_exists) { + if (!(flags & FILEUTILS_FORCE)) { + perror_msg("cannot remove `%s'", path); + return -1; + } + return 0; + } + + if (S_ISDIR(path_stat.st_mode)) { + DIR *dp; + struct dirent *d; + int status = 0; + + if (!(flags & FILEUTILS_RECUR)) { + error_msg("%s: is a directory", path); + return -1; + } + + if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 && + isatty(0)) || + (flags & FILEUTILS_INTERACTIVE)) { + fprintf(stderr, "%s: descend into directory `%s'? ", applet_name, + path); + if (!ask_confirmation()) + return 0; + } + + if ((dp = opendir(path)) == NULL) { + perror_msg("unable to open `%s'", path); + return -1; + } + + while ((d = readdir(dp)) != NULL) { + char *new_path; + + if (strcmp(d->d_name, ".") == 0 || + strcmp(d->d_name, "..") == 0) + continue; + + new_path = concat_path_file(path, d->d_name); + if (remove_file(new_path, flags) < 0) + status = -1; + free(new_path); + } + + if (closedir(dp) < 0) { + perror_msg("unable to close `%s'", path); + return -1; + } + + if (flags & FILEUTILS_INTERACTIVE) { + fprintf(stderr, "%s: remove directory `%s'? ", applet_name, path); + if (!ask_confirmation()) + return status; + } + + if (rmdir(path) < 0) { + perror_msg("unable to remove `%s'", path); + return -1; + } + + return status; + } else { + if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 && + !S_ISLNK(path_stat.st_mode) && + isatty(0)) || + (flags & FILEUTILS_INTERACTIVE)) { + fprintf(stderr, "%s: remove `%s'? ", applet_name, path); + if (!ask_confirmation()) + return 0; + } + + if (unlink(path) < 0) { + perror_msg("unable to remove `%s'", path); + return -1; + } + + return 0; + } +} diff --git a/release/src/router/busybox/libbb/restricted_shell.c b/release/src/router/busybox/libbb/restricted_shell.c new file mode 100644 index 00000000..74a64140 --- /dev/null +++ b/release/src/router/busybox/libbb/restricted_shell.c @@ -0,0 +1,57 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl@austin.rr.com> + * 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. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``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 JULIE HAUGH OR CONTRIBUTORS 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. + */ + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <syslog.h> +#include <ctype.h> +#include "libbb.h" + + + +/* Return 1 if SHELL is a restricted shell (one not returned by + getusershell), else 0, meaning it is a standard shell. */ + +int restricted_shell ( const char *shell ) +{ + char *line; + + setusershell ( ); + while (( line = getusershell ( ))) { + if (( *line != '#' ) && ( strcmp ( line, shell ) == 0 )) + break; + } + endusershell ( ); + return line ? 0 : 1; +} + diff --git a/release/src/router/busybox/libbb/run_parts.c b/release/src/router/busybox/libbb/run_parts.c new file mode 100644 index 00000000..171d9379 --- /dev/null +++ b/release/src/router/busybox/libbb/run_parts.c @@ -0,0 +1,125 @@ +/* vi: set sw=4 ts=4: */ +/* + * run command from specified directory + * + * + * Copyright (C) 2001 by Emanuele Aina <emanuele.aina@tiscali.it> + * rewrite to vfork usage by + * Copyright (C) 2002 by Vladimir Oleynik <dzo@simtreas.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * + */ + + +#include <sys/types.h> +#include <sys/wait.h> +#include <stdlib.h> +#include <dirent.h> +#include <unistd.h> +#include <ctype.h> +#include <errno.h> + +#include "libbb.h" + +/* valid_name */ +/* True or false? Is this a valid filename (upper/lower alpha, digits, + * underscores, and hyphens only?) + */ +static int valid_name(const struct dirent *d) +{ + char *c = d->d_name; + + while (*c) { + if (!isalnum(*c) && (*c != '_') && (*c != '-')) { + return 0; + } + ++c; + } + return 1; +} + +/* test mode = 1 is the same as offical run_parts + * test_mode = 2 means to fail siliently on missing directories + */ + +extern int run_parts(char **args, const unsigned char test_mode, char **env) +{ + struct dirent **namelist = 0; + struct stat st; + char *filename; + char *arg0 = args[0]; + int entries; + int i; + int exitstatus = 0; + +#if __GNUC__ + /* Avoid longjmp clobbering */ + (void) &i; + (void) &exitstatus; +#endif + /* scandir() isn't POSIX, but it makes things easy. */ + entries = scandir(arg0, &namelist, valid_name, alphasort); + + if (entries == -1) { + if (test_mode & 2) { + return(2); + } + bb_perror_msg_and_die("failed to open directory %s", arg0); + } + + for (i = 0; i < entries; i++) { + + filename = concat_path_file(arg0, namelist[i]->d_name); + + if (stat(filename, &st) < 0) { + bb_perror_msg_and_die("failed to stat component %s", filename); + } + if (S_ISREG(st.st_mode) && !access(filename, X_OK)) { + if (test_mode & 1) { + puts(filename); + } else { + /* exec_errno is common vfork variable */ + volatile int exec_errno = 0; + int result; + int pid; + + if ((pid = vfork()) < 0) { + bb_perror_msg_and_die("failed to fork"); + } else if (!pid) { + args[0] = filename; + execve(filename, args, env); + exec_errno = errno; + _exit(1); + } + + waitpid(pid, &result, 0); + if(exec_errno) { + errno = exec_errno; + bb_perror_msg_and_die("failed to exec %s", filename); + } + if (WIFEXITED(result) && WEXITSTATUS(result)) { + bb_perror_msg("%s exited with return code %d", filename, WEXITSTATUS(result)); + exitstatus = 1; + } else if (WIFSIGNALED(result)) { + bb_perror_msg("%s exited because of uncaught signal %d", filename, WTERMSIG(result)); + exitstatus = 1; + } + } + } + else if (!S_ISDIR(st.st_mode)) { + bb_error_msg("component %s is not an executable plain file", filename); + exitstatus = 1; + } + + free(namelist[i]); + free(filename); + } + free(namelist); + + return(exitstatus); +} diff --git a/release/src/router/busybox/libbb/run_shell.c b/release/src/router/busybox/libbb/run_shell.c new file mode 100644 index 00000000..4855d763 --- /dev/null +++ b/release/src/router/busybox/libbb/run_shell.c @@ -0,0 +1,87 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl@austin.rr.com> + * 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. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``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 JULIE HAUGH OR CONTRIBUTORS 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. + */ + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <syslog.h> +#include <ctype.h> +#include "libbb.h" +#ifdef CONFIG_SELINUX +#include <proc_secure.h> +#endif + +/* Run SHELL, or DEFAULT_SHELL if SHELL is empty. + If COMMAND is nonzero, pass it to the shell with the -c option. + If ADDITIONAL_ARGS is nonzero, pass it to the shell as more + arguments. */ + +void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args +#ifdef CONFIG_SELINUX + , security_id_t sid +#endif +) +{ + const char **args; + int argno = 1; + int additional_args_cnt = 0; + + for ( args = additional_args; args && *args; args++ ) + additional_args_cnt++; + + args = (const char **) xmalloc (sizeof (char *) * ( 4 + additional_args_cnt )); + + args [0] = bb_get_last_path_component ( bb_xstrdup ( shell )); + + if ( loginshell ) { + char *args0; + bb_xasprintf ( &args0, "-%s", args [0] ); + args [0] = args0; + } + + if ( command ) { + args [argno++] = "-c"; + args [argno++] = command; + } + if ( additional_args ) { + for ( ; *additional_args; ++additional_args ) + args [argno++] = *additional_args; + } + args [argno] = 0; +#ifdef CONFIG_SELINUX + if(sid) + execve_secure(shell, (char **) args, environ, sid); + else +#endif + execv ( shell, (char **) args ); + bb_perror_msg_and_die ( "cannot run %s", shell ); +} diff --git a/release/src/router/busybox/libbb/safe_read.c b/release/src/router/busybox/libbb/safe_read.c new file mode 100644 index 00000000..dbf4aa7e --- /dev/null +++ b/release/src/router/busybox/libbb/safe_read.c @@ -0,0 +1,54 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include "libbb.h" + + + +ssize_t safe_read(int fd, void *buf, size_t count) +{ + ssize_t n; + + do { + n = read(fd, buf, count); + } while (n < 0 && errno == EINTR); + + return n; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/safe_strncpy.c b/release/src/router/busybox/libbb/safe_strncpy.c new file mode 100644 index 00000000..55ec7980 --- /dev/null +++ b/release/src/router/busybox/libbb/safe_strncpy.c @@ -0,0 +1,48 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <string.h> +#include "libbb.h" + + + +/* Like strncpy but make sure the resulting string is always 0 terminated. */ +extern char * safe_strncpy(char *dst, const char *src, size_t size) +{ + dst[size-1] = '\0'; + return strncpy(dst, src, size-1); +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/setup_environment.c b/release/src/router/busybox/libbb/setup_environment.c new file mode 100644 index 00000000..b18f8967 --- /dev/null +++ b/release/src/router/busybox/libbb/setup_environment.c @@ -0,0 +1,93 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl@austin.rr.com> + * 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. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``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 JULIE HAUGH OR CONTRIBUTORS 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. + */ + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <syslog.h> +#include <ctype.h> +#include "libbb.h" + + + +#define DEFAULT_LOGIN_PATH "/bin:/usr/bin" +#define DEFAULT_ROOT_LOGIN_PATH "/usr/sbin:/bin:/usr/bin:/sbin" + +static void xsetenv ( const char *key, const char *value ) +{ + if ( setenv ( key, value, 1 )) + bb_error_msg_and_die (bb_msg_memory_exhausted); +} + +void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw ) +{ + if ( loginshell ) { + const char *term; + + /* Change the current working directory to be the home directory + * of the user. It is a fatal error for this process to be unable + * to change to that directory. There is no "default" home + * directory. + * Some systems default to HOME=/ + */ + if ( chdir ( pw-> pw_dir )) { + if ( chdir ( "/" )) { + syslog ( LOG_WARNING, "unable to cd to %s' for user %s'\n", pw-> pw_dir, pw-> pw_name ); + bb_error_msg_and_die ( "cannot cd to home directory or /" ); + } + fputs ( "warning: cannot change to home directory\n", stderr ); + } + + /* Leave TERM unchanged. Set HOME, SHELL, USER, LOGNAME, PATH. + Unset all other environment variables. */ + term = getenv ("TERM"); + clearenv ( ); + if ( term ) + xsetenv ( "TERM", term ); + xsetenv ( "HOME", pw-> pw_dir ); + xsetenv ( "SHELL", shell ); + xsetenv ( "USER", pw-> pw_name ); + xsetenv ( "LOGNAME", pw-> pw_name ); + xsetenv ( "PATH", ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH )); + } + else if ( changeenv ) { + /* Set HOME, SHELL, and if not becoming a super-user, + USER and LOGNAME. */ + xsetenv ( "HOME", pw-> pw_dir ); + xsetenv ( "SHELL", shell ); + if ( pw-> pw_uid ) { + xsetenv ( "USER", pw-> pw_name ); + xsetenv ( "LOGNAME", pw-> pw_name ); + } + } +} + diff --git a/release/src/router/busybox/libbb/simplify_path.c b/release/src/router/busybox/libbb/simplify_path.c new file mode 100644 index 00000000..743133cd --- /dev/null +++ b/release/src/router/busybox/libbb/simplify_path.c @@ -0,0 +1,64 @@ +/* vi: set sw=4 ts=4: */ +/* + * bb_simplify_path implementation for busybox + * + * Copyright (C) 2001 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdlib.h> +#include "libbb.h" + +char *bb_simplify_path(const char *path) +{ + char *s, *start, *p; + + if (path[0] == '/') + start = bb_xstrdup(path); + else { + s = xgetcwd(NULL); + start = concat_path_file(s, path); + free(s); + } + p = s = start; + + do { + if (*p == '/') { + if (*s == '/') { /* skip duplicate (or initial) slash */ + continue; + } else if (*s == '.') { + if (s[1] == '/' || s[1] == 0) { /* remove extra '.' */ + continue; + } else if ((s[1] == '.') && (s[2] == '/' || s[2] == 0)) { + ++s; + if (p > start) { + while (*--p != '/'); /* omit previous dir */ + } + continue; + } + } + } + *++p = *s; + } while (*++s); + + if ((p == start) || (*p != '/')) { /* not a trailing slash */ + ++p; /* so keep last character */ + } + *p = 0; + + return start; +} diff --git a/release/src/router/busybox/libbb/skip_whitespace.c b/release/src/router/busybox/libbb/skip_whitespace.c new file mode 100644 index 00000000..bf049a2d --- /dev/null +++ b/release/src/router/busybox/libbb/skip_whitespace.c @@ -0,0 +1,33 @@ +/* vi: set sw=4 ts=4: */ +/* + * skip_whitespace implementation for busybox + * + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <ctype.h> +#include "libbb.h" + +extern const char *bb_skip_whitespace(const char *s) +{ + while (isspace(*s)) { + ++s; + } + + return s; +} diff --git a/release/src/router/busybox/libbb/speed_table.c b/release/src/router/busybox/libbb/speed_table.c new file mode 100644 index 00000000..b04429e9 --- /dev/null +++ b/release/src/router/busybox/libbb/speed_table.c @@ -0,0 +1,130 @@ +/* vi: set sw=4 ts=4: */ +/* + * compact speed_t <-> speed functions for busybox + * + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <termios.h> +#include "libbb.h" + +struct speed_map { + unsigned short speed; + unsigned short value; +}; + +static const struct speed_map speeds[] = { + {B0, 0}, + {B50, 50}, + {B75, 75}, + {B110, 110}, + {B134, 134}, + {B150, 150}, + {B200, 200}, + {B300, 300}, + {B600, 600}, + {B1200, 1200}, + {B1800, 1800}, + {B2400, 2400}, + {B4800, 4800}, + {B9600, 9600}, +#ifdef B19200 + {B19200, 19200}, +#elif defined(EXTA) + {EXTA, 19200}, +#endif +#ifdef B38400 + {B38400, 38400/256 + 0x8000U}, +#elif defined(EXTB) + {EXTB, 38400/256 + 0x8000U}, +#endif +#ifdef B57600 + {B57600, 57600/256 + 0x8000U}, +#endif +#ifdef B115200 + {B115200, 115200/256 + 0x8000U}, +#endif +#ifdef B230400 + {B230400, 230400/256 + 0x8000U}, +#endif +#ifdef B460800 + {B460800, 460800/256 + 0x8000U}, +#endif +}; + +static const int NUM_SPEEDS = (sizeof(speeds) / sizeof(struct speed_map)); + +unsigned long bb_baud_to_value(speed_t speed) +{ + int i = 0; + + do { + if (speed == speeds[i].speed) { + if (speeds[i].value & 0x8000U) { + return ((unsigned long) (speeds[i].value) & 0x7fffU) * 256; + } + return speeds[i].value; + } + } while (++i < NUM_SPEEDS); + + return 0; +} + +speed_t bb_value_to_baud(unsigned long value) +{ + int i = 0; + + do { + if (value == bb_baud_to_value(speeds[i].speed)) { + return speeds[i].speed; + } + } while (++i < NUM_SPEEDS); + + return (speed_t) - 1; +} + +#if 0 +/* testing code */ +#include <stdio.h> + +int main(void) +{ + unsigned long v; + speed_t s; + + for (v = 0 ; v < 500000 ; v++) { + s = bb_value_to_baud(v); + if (s == (speed_t) -1) { + continue; + } + printf("v = %lu -- s = %0lo\n", v, (unsigned long) s); + } + + printf("-------------------------------\n"); + + for (s = 0 ; s < 010017+1 ; s++) { + v = bb_baud_to_value(s); + if (!v) { + continue; + } + printf("v = %lu -- s = %0lo\n", v, (unsigned long) s); + } + + return 0; +} +#endif diff --git a/release/src/router/busybox/libbb/syscalls.c b/release/src/router/busybox/libbb/syscalls.c new file mode 100644 index 00000000..426a14aa --- /dev/null +++ b/release/src/router/busybox/libbb/syscalls.c @@ -0,0 +1,115 @@ +/* vi: set sw=4 ts=4: */ +/* + * some system calls possibly missing from libc + * + * Copyright (C) 1999,2000,2001 by Lineo, inc. + * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +/* Kernel headers before 2.1.mumble need this on the Alpha to get + _syscall* defined. */ +#define __LIBRARY__ + + +#include <sys/syscall.h> +#ifndef __UCLIBC__ +#include <asm/unistd.h> +#endif +#include "libbb.h" + +#if defined(__ia64__) +int sysfs( int option, unsigned int fs_index, char * buf) +{ + return(syscall(__NR_sysfs, option, fs_index, buf)); +} +#else +_syscall3(int, sysfs, int, option, unsigned int, fs_index, char *, buf); +#endif + +#ifndef __NR_pivot_root +#warning This kernel does not support the pivot_root syscall +#warning -> The pivot_root system call is being stubbed out... +int pivot_root(const char * new_root,const char * put_old) +{ + /* BusyBox was compiled against a kernel that did not support + * the pivot_root system call. To make this application work, + * you will need to recompile with a kernel supporting the + * pivot_root system call. + */ + fprintf(stderr, "\n\nTo make this application work, you will need to recompile\n"); + fprintf(stderr, "with a kernel supporting the pivot_root system call. -Erik\n\n"); + errno=ENOSYS; + return -1; +} +#else +# if defined(__ia64__) + int pivot_root(const char * new_root,const char * put_old) + { + return(syscall(__NR_pivot_root, new_root, put_old)); + } +# else + _syscall2(int,pivot_root,const char *,new_root,const char *,put_old); +# endif +#endif + + + + +#if __GNU_LIBRARY__ < 5 || ((__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1)) +/* These syscalls are not included as part of libc5 */ +_syscall2(int, bdflush, int, func, int, data); + +#ifndef __alpha__ +# define __NR_klogctl __NR_syslog + _syscall3(int, klogctl, int, type, char *, b, int, len); +#endif + +#ifndef __NR_umount2 +# warning This kernel does not support the umount2 syscall +# warning -> The umount2 system call is being stubbed out... +int umount2(const char * special_file, int flags) +{ + /* BusyBox was compiled against a kernel that did not support + * the umount2 system call. To make this application work, + * you will need to recompile with a kernel supporting the + * umount2 system call. + */ + fprintf(stderr, "\n\nTo make this application work, you will need to recompile\n"); + fprintf(stderr, "with a kernel supporting the umount2 system call. -Erik\n\n"); + errno=ENOSYS; + return -1; +} +# else +_syscall2(int, umount2, const char *, special_file, int, flags); +#endif + + +#endif /* __GNU_LIBRARY__ < 5 */ + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/syslog_msg_with_name.c b/release/src/router/busybox/libbb/syslog_msg_with_name.c new file mode 100644 index 00000000..5dadcc43 --- /dev/null +++ b/release/src/router/busybox/libbb/syslog_msg_with_name.c @@ -0,0 +1,51 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <sys/syslog.h> +#include "libbb.h" + +void syslog_msg_with_name(const char *name, int facility, int pri, const char *msg) +{ + openlog(name, 0, facility); + syslog(pri, "%s", msg); + closelog(); +} + +void syslog_msg(int facility, int pri, const char *msg) +{ + syslog_msg_with_name(applet_name, facility, pri, msg); +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/time_string.c b/release/src/router/busybox/libbb/time_string.c new file mode 100644 index 00000000..07652900 --- /dev/null +++ b/release/src/router/busybox/libbb/time_string.c @@ -0,0 +1,68 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <utime.h> +#include "libbb.h" + + +/* + * Return the standard ls-like time string from a time_t + * This is static and so is overwritten on each call. + */ +const char *time_string(time_t timeVal) +{ + time_t now; + char *str; + static char buf[26]; + + time(&now); + + str = ctime(&timeVal); + + strcpy(buf, &str[4]); + buf[12] = '\0'; + + if ((timeVal > now) || (timeVal < now - 365 * 24 * 60 * 60L)) { + strcpy(&buf[7], &str[20]); + buf[11] = '\0'; + } + + return buf; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/trim.c b/release/src/router/busybox/libbb/trim.c new file mode 100644 index 00000000..76b87ca1 --- /dev/null +++ b/release/src/router/busybox/libbb/trim.c @@ -0,0 +1,53 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "libbb.h" + + +void trim(char *s) +{ + int len = strlen(s); + + /* trim trailing whitespace */ + while ( len > 0 && isspace(s[len-1])) + s[--len]='\0'; + + /* trim leading whitespace */ + memmove(s, &s[strspn(s, " \n\r\t\v")], len); +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/u_signal_names.c b/release/src/router/busybox/libbb/u_signal_names.c new file mode 100644 index 00000000..623b1031 --- /dev/null +++ b/release/src/router/busybox/libbb/u_signal_names.c @@ -0,0 +1,166 @@ +#include <signal.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +struct signal_name { + const char *name; + int number; +}; + +static const struct signal_name signames[] = { + /* POSIX signals */ + { "EXIT", 0 }, /* 0 */ + { "HUP", SIGHUP }, /* 1 */ + { "INT", SIGINT }, /* 2 */ + { "QUIT", SIGQUIT }, /* 3 */ + { "ILL", SIGILL }, /* 4 */ + { "ABRT", SIGABRT }, /* 6 */ + { "FPE", SIGFPE }, /* 8 */ + { "KILL", SIGKILL }, /* 9 */ + { "SEGV", SIGSEGV }, /* 11 */ + { "PIPE", SIGPIPE }, /* 13 */ + { "ALRM", SIGALRM }, /* 14 */ + { "TERM", SIGTERM }, /* 15 */ + { "USR1", SIGUSR1 }, /* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */ + { "USR2", SIGUSR2 }, /* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */ + { "CHLD", SIGCHLD }, /* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */ + { "CONT", SIGCONT }, /* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */ + { "STOP", SIGSTOP }, /* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */ + { "TSTP", SIGTSTP }, /* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */ + { "TTIN", SIGTTIN }, /* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */ + { "TTOU", SIGTTOU }, /* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */ + /* Miscellaneous other signals */ +#ifdef SIGTRAP + { "TRAP", SIGTRAP }, /* 5 */ +#endif +#ifdef SIGIOT + { "IOT", SIGIOT }, /* 6, same as SIGABRT */ +#endif +#ifdef SIGEMT + { "EMT", SIGEMT }, /* 7 (mips,alpha,sparc*) */ +#endif +#ifdef SIGBUS + { "BUS", SIGBUS }, /* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */ +#endif +#ifdef SIGSYS + { "SYS", SIGSYS }, /* 12 (mips,alpha,sparc*) */ +#endif +#ifdef SIGSTKFLT + { "STKFLT", SIGSTKFLT }, /* 16 (arm,i386,m68k,ppc) */ +#endif +#ifdef SIGURG + { "URG", SIGURG }, /* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */ +#endif +#ifdef SIGIO + { "IO", SIGIO }, /* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */ +#endif +#ifdef SIGPOLL + { "POLL", SIGPOLL }, /* same as SIGIO */ +#endif +#ifdef SIGCLD + { "CLD", SIGCLD }, /* same as SIGCHLD (mips) */ +#endif +#ifdef SIGXCPU + { "XCPU", SIGXCPU }, /* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */ +#endif +#ifdef SIGXFSZ + { "XFSZ", SIGXFSZ }, /* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */ +#endif +#ifdef SIGVTALRM + { "VTALRM", SIGVTALRM }, /* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */ +#endif +#ifdef SIGPROF + { "PROF", SIGPROF }, /* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */ +#endif +#ifdef SIGPWR + { "PWR", SIGPWR }, /* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */ +#endif +#ifdef SIGINFO + { "INFO", SIGINFO }, /* 29 (alpha) */ +#endif +#ifdef SIGLOST + { "LOST", SIGLOST }, /* 29 (arm,i386,m68k,ppc,sparc*) */ +#endif +#ifdef SIGWINCH + { "WINCH", SIGWINCH }, /* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */ +#endif +#ifdef SIGUNUSED + { "UNUSED", SIGUNUSED }, /* 31 (arm,i386,m68k,ppc) */ +#endif + {0, 0} +}; + +/* + if str_sig == NULL returned signal name [*signo], + if str_sig != NULL - set *signo from signal_name, + findings with digit number or with or without SIG-prefix name + + if startnum=0 flag for support finding zero signal, + but str_sig="0" always found, (hmm - standart or realize?) + if startnum<0 returned reverse signal_number <-> signal_name + if found error - returned NULL + +*/ + +const char * +u_signal_names(const char *str_sig, int *signo, int startnum) +{ + static char retstr[16]; + const struct signal_name *s = signames; + static const char prefix[] = "SIG"; + const char *sptr; + + if(startnum) + s++; + if(str_sig==NULL) { + while (s->name != 0) { + if(s->number == *signo) + break; + s++; + } + } else { + if (isdigit(((unsigned char)*str_sig))) { + char *endp; + long int sn = strtol(str_sig, &endp, 10); + /* test correct and overflow */ + if(*endp == 0 && sn >= 0 && sn < NSIG) { + *signo = (int)sn; + /* test for unnamed */ + sptr = u_signal_names(0, signo, 0); + if(sptr==NULL) + return NULL; + if(sn!=0) + sptr += 3; + return sptr; + } + } else { + sptr = str_sig; + while (s->name != 0) { + if (strcasecmp(s->name, sptr) == 0) { + *signo = s->number; + if(startnum<0) { + sprintf(retstr, "%d", *signo); + return retstr; + } + break; + } + if(s!=signames && sptr == str_sig && + strncasecmp(sptr, prefix, 3) == 0) { + sptr += 3; /* strlen(prefix) */ + continue; + } + sptr = str_sig; + s++; + } + } + } + if(s->name==0) + return NULL; + if(s!=signames) + strcpy(retstr, prefix); + else + retstr[0] = 0; + return strcat(retstr, s->name); +} diff --git a/release/src/router/busybox/libbb/unarchive.c b/release/src/router/busybox/libbb/unarchive.c new file mode 100644 index 00000000..91db2e3b --- /dev/null +++ b/release/src/router/busybox/libbb/unarchive.c @@ -0,0 +1,601 @@ +/* + * Copyright (C) 2000 by Glenn McGrath + * Copyright (C) 2001 by Laurence Anderson + * + * Based on previous work by busybox developers and others. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <utime.h> +#include "libbb.h" + +extern void seek_sub_file(FILE *src_stream, const int count); +extern char *extract_archive(FILE *src_stream, FILE *out_stream, const file_header_t *file_entry, + const int function, const char *prefix); + + +#ifdef L_archive_offset +off_t archive_offset; +#else +extern off_t archive_offset; +#endif + +#ifdef L_seek_sub_file +void seek_sub_file(FILE *src_stream, const int count) +{ + int i; + /* Try to fseek as faster */ + archive_offset += count; + if (fseek(src_stream, count, SEEK_CUR) != 0 && errno == ESPIPE) { + for (i = 0; i < count; i++) { + fgetc(src_stream); + } + } + return; +} +#endif + + + +#ifdef L_extract_archive +/* Extract the data postioned at src_stream to either filesystem, stdout or + * buffer depending on the value of 'function' which is defined in libbb.h + * + * prefix doesnt have to be just a directory, it may prefix the filename as well. + * + * e.g. '/var/lib/dpkg/info/dpkg.' will extract all files to the base bath + * '/var/lib/dpkg/info/' and all files/dirs created in that dir will have + * 'dpkg.' as their prefix + * + * For this reason if prefix does point to a dir then it must end with a + * trailing '/' or else the last dir will be assumed to be the file prefix + */ +char *extract_archive(FILE *src_stream, FILE *out_stream, const file_header_t *file_entry, + const int function, const char *prefix) +{ + FILE *dst_stream = NULL; + char *full_name = NULL; + char *buffer = NULL; + struct utimbuf t; + + /* prefix doesnt have to be a proper path it may prepend + * the filename as well */ + if (prefix != NULL) { + /* strip leading '/' in filename to extract as prefix may not be dir */ + /* Cant use concat_path_file here as prefix might not be a directory */ + char *path = file_entry->name; + if (strncmp("./", path, 2) == 0) { + path += 2; + if (strlen(path) == 0) { + return(NULL); + } + } + full_name = xmalloc(strlen(prefix) + strlen(path) + 1); + strcpy(full_name, prefix); + strcat(full_name, path); + } else { + full_name = file_entry->name; + } + if (function & extract_to_stdout) { + if (S_ISREG(file_entry->mode)) { + copy_file_chunk(src_stream, out_stream, file_entry->size); + archive_offset += file_entry->size; + } + } + else if (function & extract_one_to_buffer) { + if (S_ISREG(file_entry->mode)) { + buffer = (char *) xmalloc(file_entry->size + 1); + fread(buffer, 1, file_entry->size, src_stream); + buffer[file_entry->size] = '\0'; + archive_offset += file_entry->size; + return(buffer); + } + } + else if (function & extract_all_to_fs) { + struct stat oldfile; + int stat_res; + stat_res = lstat (full_name, &oldfile); + if (stat_res == 0) { /* The file already exists */ + if ((function & extract_unconditional) || (oldfile.st_mtime < file_entry->mtime)) { + if (!S_ISDIR(oldfile.st_mode)) { + unlink(full_name); /* Directories might not be empty etc */ + } + } else { + if ((function & extract_quiet) != extract_quiet) { + error_msg("%s not created: newer or same age file exists", file_entry->name); + } + seek_sub_file(src_stream, file_entry->size); + return (NULL); + } + } + if (function & extract_create_leading_dirs) { /* Create leading directories with default umask */ + char *parent = dirname(full_name); + if (make_directory (parent, -1, FILEUTILS_RECUR) != 0) { + if ((function & extract_quiet) != extract_quiet) { + error_msg("couldn't create leading directories"); + } + } + free (parent); + } + switch(file_entry->mode & S_IFMT) { + case S_IFREG: + if (file_entry->link_name) { /* Found a cpio hard link */ + if (link(file_entry->link_name, full_name) != 0) { + if ((function & extract_quiet) != extract_quiet) { + perror_msg("Cannot link from %s to '%s'", + file_entry->name, file_entry->link_name); + } + } + } else { + if ((dst_stream = wfopen(full_name, "w")) == NULL) { + seek_sub_file(src_stream, file_entry->size); + return NULL; + } + archive_offset += file_entry->size; + copy_file_chunk(src_stream, dst_stream, file_entry->size); + fclose(dst_stream); + } + break; + case S_IFDIR: + if (stat_res != 0) { + if (mkdir(full_name, file_entry->mode) < 0) { + if ((function & extract_quiet) != extract_quiet) { + perror_msg("extract_archive: "); + } + } + } + break; + case S_IFLNK: + if (symlink(file_entry->link_name, full_name) < 0) { + if ((function & extract_quiet) != extract_quiet) { + perror_msg("Cannot create symlink from %s to '%s'", file_entry->name, file_entry->link_name); + } + return NULL; + } + break; + case S_IFSOCK: + case S_IFBLK: + case S_IFCHR: + case S_IFIFO: + if (mknod(full_name, file_entry->mode, file_entry->device) == -1) { + if ((function & extract_quiet) != extract_quiet) { + perror_msg("Cannot create node %s", file_entry->name); + } + return NULL; + } + break; + } + + /* Changing a symlink's properties normally changes the properties of the + * file pointed to, so dont try and change the date or mode, lchown does + * does the right thing, but isnt available in older versions of libc */ + if (S_ISLNK(file_entry->mode)) { +#if (__GLIBC__ > 2) && (__GLIBC_MINOR__ > 1) + lchown(full_name, file_entry->uid, file_entry->gid); +#endif + } else { + if (function & extract_preserve_date) { + t.actime = file_entry->mtime; + t.modtime = file_entry->mtime; + utime(full_name, &t); + } + chmod(full_name, file_entry->mode); + chown(full_name, file_entry->uid, file_entry->gid); + } + } else { + /* If we arent extracting data we have to skip it, + * if data size is 0 then then just do it anyway + * (saves testing for it) */ + seek_sub_file(src_stream, file_entry->size); + } + + /* extract_list and extract_verbose_list can be used in conjunction + * with one of the above four extraction functions, so do this seperately */ + if (function & extract_verbose_list) { + fprintf(out_stream, "%s %d/%d %8d %s ", mode_string(file_entry->mode), + file_entry->uid, file_entry->gid, + (int) file_entry->size, time_string(file_entry->mtime)); + } + if ((function & extract_list) || (function & extract_verbose_list)){ + /* fputs doesnt add a trailing \n, so use fprintf */ + fprintf(out_stream, "%s\n", file_entry->name); + } + + free(full_name); + + return(NULL); /* Maybe we should say if failed */ +} +#endif + +#ifdef L_unarchive +char *unarchive(FILE *src_stream, FILE *out_stream, file_header_t *(*get_headers)(FILE *), + const int extract_function, const char *prefix, char **extract_names) +{ + file_header_t *file_entry; + int found; + int i; + char *buffer = NULL; + + archive_offset = 0; + while ((file_entry = get_headers(src_stream)) != NULL) { + found = FALSE; + if (extract_names == NULL) { + found = TRUE; + } else { + for(i = 0; extract_names[i] != 0; i++) { + if (strcmp(extract_names[i], file_entry->name) == 0) { + found = TRUE; + } + } + } + + if (found) { + buffer = extract_archive(src_stream, out_stream, file_entry, extract_function, prefix); + } else { + /* seek past the data entry */ + seek_sub_file(src_stream, file_entry->size); + } + } + return(buffer); +} +#endif + +#ifdef L_get_header_ar +file_header_t *get_header_ar(FILE *src_stream) +{ + file_header_t *typed; + union { + char raw[60]; + struct { + char name[16]; + char date[12]; + char uid[6]; + char gid[6]; + char mode[8]; + char size[10]; + char magic[2]; + } formated; + } ar; + static char *ar_long_names; + + if (fread(ar.raw, 1, 60, src_stream) != 60) { + return(NULL); + } + archive_offset += 60; + /* align the headers based on the header magic */ + if ((ar.formated.magic[0] != '`') || (ar.formated.magic[1] != '\n')) { + /* some version of ar, have an extra '\n' after each data entry, + * this puts the next header out by 1 */ + if (ar.formated.magic[1] != '`') { + error_msg("Invalid magic"); + return(NULL); + } + /* read the next char out of what would be the data section, + * if its a '\n' then it is a valid header offset by 1*/ + archive_offset++; + if (fgetc(src_stream) != '\n') { + error_msg("Invalid magic"); + return(NULL); + } + /* fix up the header, we started reading 1 byte too early */ + /* raw_header[60] wont be '\n' as it should, but it doesnt matter */ + memmove(ar.raw, &ar.raw[1], 59); + } + + typed = (file_header_t *) xcalloc(1, sizeof(file_header_t)); + + typed->size = (size_t) atoi(ar.formated.size); + /* long filenames have '/' as the first character */ + if (ar.formated.name[0] == '/') { + if (ar.formated.name[1] == '/') { + /* If the second char is a '/' then this entries data section + * stores long filename for multiple entries, they are stored + * in static variable long_names for use in future entries */ + ar_long_names = (char *) xrealloc(ar_long_names, typed->size); + fread(ar_long_names, 1, typed->size, src_stream); + archive_offset += typed->size; + /* This ar entries data section only contained filenames for other records + * they are stored in the static ar_long_names for future reference */ + return (get_header_ar(src_stream)); /* Return next header */ + } else if (ar.formated.name[1] == ' ') { + /* This is the index of symbols in the file for compilers */ + seek_sub_file(src_stream, typed->size); + return (get_header_ar(src_stream)); /* Return next header */ + } else { + /* The number after the '/' indicates the offset in the ar data section + (saved in variable long_name) that conatains the real filename */ + if (!ar_long_names) { + error_msg("Cannot resolve long file name"); + return (NULL); + } + typed->name = xstrdup(ar_long_names + atoi(&ar.formated.name[1])); + } + } else { + /* short filenames */ + typed->name = xcalloc(1, 16); + strncpy(typed->name, ar.formated.name, 16); + } + typed->name[strcspn(typed->name, " /")]='\0'; + + /* convert the rest of the now valid char header to its typed struct */ + parse_mode(ar.formated.mode, &typed->mode); + typed->mtime = atoi(ar.formated.date); + typed->uid = atoi(ar.formated.uid); + typed->gid = atoi(ar.formated.gid); + + return(typed); +} +#endif + +#ifdef L_get_header_cpio +struct hardlinks { + file_header_t *entry; + int inode; + struct hardlinks *next; +}; + +file_header_t *get_header_cpio(FILE *src_stream) +{ + file_header_t *cpio_entry = NULL; + char cpio_header[110]; + int namesize; + char dummy[16]; + int major, minor, nlink, inode; + static struct hardlinks *saved_hardlinks = NULL; + static int pending_hardlinks = 0; + + if (pending_hardlinks) { /* Deal with any pending hardlinks */ + struct hardlinks *tmp = saved_hardlinks, *oldtmp = NULL; + while (tmp) { + if (tmp->entry->link_name) { /* Found a hardlink ready to be extracted */ + cpio_entry = tmp->entry; + if (oldtmp) oldtmp->next = tmp->next; /* Remove item from linked list */ + else saved_hardlinks = tmp->next; + free(tmp); + return (cpio_entry); + } + oldtmp = tmp; + tmp = tmp->next; + } + pending_hardlinks = 0; /* No more pending hardlinks, read next file entry */ + } + + /* There can be padding before archive header */ + seek_sub_file(src_stream, (4 - (archive_offset % 4)) % 4); + if (fread(cpio_header, 1, 110, src_stream) == 110) { + archive_offset += 110; + if (strncmp(cpio_header, "07070", 5) != 0) { + error_msg("Unsupported format or invalid magic"); + return(NULL); + } + switch (cpio_header[5]) { + case '2': /* "crc" header format */ + /* Doesnt do the crc check yet */ + case '1': /* "newc" header format */ + cpio_entry = (file_header_t *) xcalloc(1, sizeof(file_header_t)); + sscanf(cpio_header, "%6c%8x%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c", + dummy, &inode, (unsigned int*)&cpio_entry->mode, + (unsigned int*)&cpio_entry->uid, (unsigned int*)&cpio_entry->gid, + &nlink, &cpio_entry->mtime, &cpio_entry->size, + dummy, &major, &minor, &namesize, dummy); + + cpio_entry->name = (char *) xcalloc(1, namesize); + fread(cpio_entry->name, 1, namesize, src_stream); /* Read in filename */ + archive_offset += namesize; + /* Skip padding before file contents */ + seek_sub_file(src_stream, (4 - (archive_offset % 4)) % 4); + if (strcmp(cpio_entry->name, "TRAILER!!!") == 0) { + printf("%d blocks\n", (int) (archive_offset % 512 ? (archive_offset / 512) + 1 : archive_offset / 512)); /* Always round up */ + if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */ + struct hardlinks *tmp = saved_hardlinks, *oldtmp = NULL; + while (tmp) { + error_msg("%s not created: cannot resolve hardlink", tmp->entry->name); + oldtmp = tmp; + tmp = tmp->next; + free (oldtmp->entry->name); + free (oldtmp->entry); + free (oldtmp); + } + saved_hardlinks = NULL; + pending_hardlinks = 0; + } + return(NULL); + } + + if (S_ISLNK(cpio_entry->mode)) { + cpio_entry->link_name = (char *) xcalloc(1, cpio_entry->size + 1); + fread(cpio_entry->link_name, 1, cpio_entry->size, src_stream); + archive_offset += cpio_entry->size; + cpio_entry->size = 0; /* Stop possiable seeks in future */ + } + if (nlink > 1 && !S_ISDIR(cpio_entry->mode)) { + if (cpio_entry->size == 0) { /* Put file on a linked list for later */ + struct hardlinks *new = xmalloc(sizeof(struct hardlinks)); + new->next = saved_hardlinks; + new->inode = inode; + new->entry = cpio_entry; + saved_hardlinks = new; + return(get_header_cpio(src_stream)); /* Recurse to next file */ + } else { /* Found the file with data in */ + struct hardlinks *tmp = saved_hardlinks; + pending_hardlinks = 1; + while (tmp) { + if (tmp->inode == inode) { + tmp->entry->link_name = xstrdup(cpio_entry->name); + nlink--; + } + tmp = tmp->next; + } + if (nlink > 1) error_msg("error resolving hardlink: did you create the archive with GNU cpio 2.0-2.2?"); + } + } + cpio_entry->device = (major << 8) | minor; + break; + default: + error_msg("Unsupported format"); + return(NULL); + } + if (ferror(src_stream) || feof(src_stream)) { + perror_msg("Stream error"); + return(NULL); + } + } + return(cpio_entry); +} +#endif + +#ifdef L_get_header_tar +file_header_t *get_header_tar(FILE *tar_stream) +{ + union { + unsigned char raw[512]; + struct { + char name[100]; /* 0-99 */ + char mode[8]; /* 100-107 */ + char uid[8]; /* 108-115 */ + char gid[8]; /* 116-123 */ + char size[12]; /* 124-135 */ + char mtime[12]; /* 136-147 */ + char chksum[8]; /* 148-155 */ + char typeflag; /* 156-156 */ + char linkname[100]; /* 157-256 */ + char magic[6]; /* 257-262 */ + char version[2]; /* 263-264 */ + char uname[32]; /* 265-296 */ + char gname[32]; /* 297-328 */ + char devmajor[8]; /* 329-336 */ + char devminor[8]; /* 337-344 */ + char prefix[155]; /* 345-499 */ + char padding[12]; /* 500-512 */ + } formated; + } tar; + file_header_t *tar_entry = NULL; + long i; + long sum = 0; + + if (archive_offset % 512 != 0) { + seek_sub_file(tar_stream, 512 - (archive_offset % 512)); + } + + if (fread(tar.raw, 1, 512, tar_stream) != 512) { + /* Unfortunatly its common for tar files to have all sorts of + * trailing garbage, fail silently */ +// error_msg("Couldnt read header"); + return(NULL); + } + archive_offset += 512; + + /* Check header has valid magic, unfortunately some tar files + * have empty (0'ed) tar entries at the end, which will + * cause this to fail, so fail silently for now + */ + if (strncmp(tar.formated.magic, "ustar", 5) != 0) { + return(NULL); + } + + /* Do checksum on headers */ + for (i = 0; i < 148 ; i++) { + sum += tar.raw[i]; + } + sum += ' ' * 8; + for (i = 156; i < 512 ; i++) { + sum += tar.raw[i]; + } + if (sum != strtol(tar.formated.chksum, NULL, 8)) { + error_msg("Invalid tar header checksum"); + return(NULL); + } + + /* convert to type'ed variables */ + tar_entry = xcalloc(1, sizeof(file_header_t)); + tar_entry->name = xstrdup(tar.formated.name); + + parse_mode(tar.formated.mode, &tar_entry->mode); + tar_entry->uid = strtol(tar.formated.uid, NULL, 8); + tar_entry->gid = strtol(tar.formated.gid, NULL, 8); + tar_entry->size = strtol(tar.formated.size, NULL, 8); + tar_entry->mtime = strtol(tar.formated.mtime, NULL, 8); + tar_entry->link_name = strlen(tar.formated.linkname) ? + xstrdup(tar.formated.linkname) : NULL; + tar_entry->device = (strtol(tar.formated.devmajor, NULL, 8) << 8) + + strtol(tar.formated.devminor, NULL, 8); + + return(tar_entry); +} +#endif + +#ifdef L_deb_extract +char *deb_extract(const char *package_filename, FILE *out_stream, + const int extract_function, const char *prefix, const char *filename) +{ + FILE *deb_stream; + FILE *uncompressed_stream = NULL; + file_header_t *ar_header = NULL; + char **file_list = NULL; + char *output_buffer = NULL; + char *ared_file = NULL; + char ar_magic[8]; + int gunzip_pid; + + if (filename != NULL) { + file_list = xmalloc(sizeof(char *) * 2); + file_list[0] = xstrdup(filename); + file_list[1] = NULL; + } + + if (extract_function & extract_control_tar_gz) { + ared_file = xstrdup("control.tar.gz"); + } + else if (extract_function & extract_data_tar_gz) { + ared_file = xstrdup("data.tar.gz"); + } + + /* open the debian package to be worked on */ + deb_stream = wfopen(package_filename, "r"); + if (deb_stream == NULL) { + return(NULL); + } + /* set the buffer size */ + setvbuf(deb_stream, NULL, _IOFBF, 0x8000); + + /* check ar magic */ + fread(ar_magic, 1, 8, deb_stream); + if (strncmp(ar_magic,"!<arch>",7) != 0) { + error_msg_and_die("invalid magic"); + } + archive_offset = 8; + + while ((ar_header = get_header_ar(deb_stream)) != NULL) { + if (strcmp(ared_file, ar_header->name) == 0) { + /* open a stream of decompressed data */ + uncompressed_stream = gz_open(deb_stream, &gunzip_pid); + archive_offset = 0; + output_buffer = unarchive(uncompressed_stream, out_stream, get_header_tar, extract_function, prefix, file_list); + } + seek_sub_file(deb_stream, ar_header->size); + } + gz_close(gunzip_pid); + fclose(deb_stream); + fclose(uncompressed_stream); + free(ared_file); + return(output_buffer); +} +#endif diff --git a/release/src/router/busybox/libbb/unzip.c b/release/src/router/busybox/libbb/unzip.c new file mode 100644 index 00000000..67cb540d --- /dev/null +++ b/release/src/router/busybox/libbb/unzip.c @@ -0,0 +1,1007 @@ +/* vi: set sw=4 ts=4: */ +/* + * gunzip implementation for busybox + * + * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly. + * + * Originally adjusted for busybox by Sven Rudolph <sr1@inf.tu-dresden.de> + * based on gzip sources + * + * Adjusted further by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> + * to support files as well as stdin/stdout, and to generally behave itself wrt + * command line handling. + * + * General cleanup to better adhere to the style guide and make use of standard + * busybox functions by Glenn McGrath <bug1@optushome.com.au> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface + * Copyright (C) 1992-1993 Jean-loup Gailly + * The unzip code was written and put in the public domain by Mark Adler. + * Portions of the lzw code are derived from the public domain 'compress' + * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies, + * Ken Turkowski, Dave Mack and Peter Jannesen. + * + * See the license_msg below and the file COPYING for the software license. + * See the file algorithm.doc for the compression algorithms and file formats. + */ + + +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include "libbb.h" + +static FILE *in_file, *out_file; + +/* these are freed by gz_close */ +static unsigned char *window; +static unsigned long *crc_table; + +static unsigned long crc = 0xffffffffL; /* shift register contents */ + +/* Return codes from gzip */ +static const int ERROR = 1; + +/* + * window size--must be a power of two, and + * at least 32K for zip's deflate method + */ +static const int WSIZE = 0x8000; + +/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ +static const int BMAX = 16; /* maximum bit length of any code (16 for explode) */ +static const int N_MAX = 288; /* maximum number of codes in any set */ + +static long bytes_out; /* number of output bytes */ +static unsigned long outcnt; /* bytes in output buffer */ + +static unsigned hufts; /* track memory usage */ +static unsigned long bb; /* bit buffer */ +static unsigned bk; /* bits in bit buffer */ + +typedef struct huft_s { + unsigned char e; /* number of extra bits or operation */ + unsigned char b; /* number of bits in this code or subcode */ + union { + unsigned short n; /* literal, length base, or distance base */ + struct huft_s *t; /* pointer to next level of table */ + } v; +} huft_t; + +static const unsigned short mask_bits[] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +//static int error_number = 0; +/* ======================================================================== + * Signal and error handler. + */ + +static void abort_gzip() +{ + error_msg("gzip aborted\n"); + exit(ERROR); +} + +static void make_crc_table() +{ + unsigned long table_entry; /* crc shift register */ + unsigned long poly = 0; /* polynomial exclusive-or pattern */ + int i; /* counter for all possible eight bit values */ + int k; /* byte being shifted into crc apparatus */ + + /* terms of polynomial defining this crc (except x^32): */ + static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + crc_table = (unsigned long *) malloc(256 * sizeof(unsigned long)); + + /* Make exclusive-or pattern from polynomial (0xedb88320) */ + for (i = 0; i < sizeof(p)/sizeof(int); i++) + poly |= 1L << (31 - p[i]); + + /* Compute and print table of CRC's, five per line */ + for (i = 0; i < 256; i++) { + table_entry = i; + /* The idea to initialize the register with the byte instead of + * zero was stolen from Haruhiko Okumura's ar002 + */ + for (k = 8; k; k--) { + table_entry = table_entry & 1 ? (table_entry >> 1) ^ poly : table_entry >> 1; + } + crc_table[i]=table_entry; + } +} + +/* =========================================================================== + * Write the output window window[0..outcnt-1] and update crc and bytes_out. + * (Used for the decompressed data only.) + */ +static void flush_window(void) +{ + int n; + + if (outcnt == 0) + return; + + for (n = 0; n < outcnt; n++) { + crc = crc_table[((int) crc ^ (window[n])) & 0xff] ^ (crc >> 8); + } + + if (fwrite(window, 1, outcnt, out_file) != outcnt) { + error_msg_and_die("Couldnt write"); + } + bytes_out += (unsigned long) outcnt; + outcnt = 0; +} + +/* + * Free the malloc'ed tables built by huft_build(), which makes a linked + * list of the tables it made, with the links in a dummy first entry of + * each table. + * t: table to free + */ +static int huft_free(huft_t *t) +{ + huft_t *p, *q; + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != (huft_t *) NULL) { + q = (--p)->v.t; + free((char *) p); + p = q; + } + return 0; +} + +/* Given a list of code lengths and a maximum table size, make a set of + * tables to decode that set of codes. Return zero on success, one if + * the given code set is incomplete (the tables are still built in this + * case), two if the input is invalid (all zero length codes or an + * oversubscribed set of lengths), and three if not enough memory. + * + * b: code lengths in bits (all assumed <= BMAX) + * n: number of codes (assumed <= N_MAX) + * s: number of simple-valued codes (0..s-1) + * d: list of base values for non-simple codes + * e: list of extra bits for non-simple codes + * t: result: starting table + * m: maximum lookup bits, returns actual + */ +static int huft_build(unsigned int *b, const unsigned int n, const unsigned int s, + const unsigned short *d, const unsigned short *e, huft_t **t, int *m) +{ + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX + 1]; /* bit length count table */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register unsigned i; /* counter, current code */ + register unsigned j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + register unsigned *p; /* pointer into c[], b[], or v[] */ + register huft_t *q; /* points to current table */ + huft_t r; /* table entry for structure assignment */ + huft_t *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + unsigned x[BMAX + 1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + + /* Generate counts for each bit length */ + memset ((void *)(c), 0, sizeof(c)); + p = b; + i = n; + do { + c[*p]++; /* assume all entries <= BMAX */ + p++; /* Can't combine with above line (Solaris bug) */ + } while (--i); + if (c[0] == n) { /* null input--all zero length codes */ + *t = (huft_t *) NULL; + *m = 0; + return 0; + } + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((unsigned) l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned) l > i) + l = i; + *m = l; + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= c[i]) < 0) + return 2; + c[i] += y; + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; + xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + /* Make a table of values in order of bit lengths */ + p = b; + i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (huft_t *) NULL; /* just to keep compilers happy */ + q = (huft_t *) NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) { + a = c[k]; + while (a--) { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = (z = g - w) > (unsigned) l ? l : z; /* upper limit on table size */ + if ((f = 1 << (j = k - w)) > a + 1) { /* try a k-w bit table *//* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) { /* try smaller tables up to z bits */ + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table */ + if ((q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t))) == NULL) { + if (h) { + huft_free(u[0]); + } + return 3; /* not enough memory */ + } + hufts += z + 1; /* track memory usage */ + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->v.t)) = NULL; + u[h] = ++q; /* table starts after link */ + + /* connect to last table, if there is one */ + if (h) { + x[h] = i; /* save pattern for backing up */ + r.b = (unsigned char) l; /* bits to dump before this table */ + r.e = (unsigned char) (16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = i >> (w - l); /* (get around Turbo C bug) */ + u[h - 1][j] = r; /* connect to last table */ + } + } + + /* set up table entry in r */ + r.b = (unsigned char) (k - w); + if (p >= v + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) { + r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = (unsigned short) (*p); /* simple code is just the value */ + p++; /* one compiler does not like *p++ */ + } else { + r.e = (unsigned char) e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) { + h--; /* don't need to update q */ + w -= l; + } + } + } + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + +/* + * inflate (decompress) the codes in a deflated (compressed) block. + * Return an error code or zero if it all goes ok. + * + * tl, td: literal/length and distance decoder tables + * bl, bd: number of bits decoded by tl[] and td[] + */ +static int inflate_codes(huft_t *tl, huft_t *td, int bl, int bd) +{ + register unsigned long e; /* table entry flag/number of extra bits */ + unsigned long n, d; /* length and index for copy */ + unsigned long w; /* current window position */ + huft_t *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + /* make local copies of globals */ + b = bb; /* initialize bit buffer */ + k = bk; + w = outcnt; /* initialize window position */ + + /* inflate the coded data */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + for (;;) { /* do until end of block */ + while (k < (unsigned) bl) { + b |= ((unsigned long)fgetc(in_file)) << k; + k += 8; + } + if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) + do { + if (e == 99) { + return 1; + } + b >>= t->b; + k -= t->b; + e -= 16; + while (k < e) { + b |= ((unsigned long)fgetc(in_file)) << k; + k += 8; + } + } while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); + b >>= t->b; + k -= t->b; + if (e == 16) { /* then it's a literal */ + window[w++] = (unsigned char) t->v.n; + if (w == WSIZE) { + outcnt=(w), + flush_window(); + w = 0; + } + } else { /* it's an EOB or a length */ + + /* exit if end of block */ + if (e == 15) { + break; + } + + /* get length of block to copy */ + while (k < e) { + b |= ((unsigned long)fgetc(in_file)) << k; + k += 8; + } + n = t->v.n + ((unsigned) b & mask_bits[e]); + b >>= e; + k -= e; + + /* decode distance of block to copy */ + while (k < (unsigned) bd) { + b |= ((unsigned long)fgetc(in_file)) << k; + k += 8; + } + + if ((e = (t = td + ((unsigned) b & md))->e) > 16) + do { + if (e == 99) + return 1; + b >>= t->b; + k -= t->b; + e -= 16; + while (k < e) { + b |= ((unsigned long)fgetc(in_file)) << k; + k += 8; + } + } while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); + b >>= t->b; + k -= t->b; + while (k < e) { + b |= ((unsigned long)fgetc(in_file)) << k; + k += 8; + } + d = w - t->v.n - ((unsigned) b & mask_bits[e]); + b >>= e; + k -= e; + + /* do the copy */ + do { + n -= (e = (e = WSIZE - ((d &= WSIZE - 1) > w ? d : w)) > n ? n : e); +#if !defined(NOMEMCPY) && !defined(DEBUG) + if (w - d >= e) { /* (this test assumes unsigned comparison) */ + memcpy(window + w, window + d, e); + w += e; + d += e; + } else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + window[w++] = window[d++]; + } while (--e); + if (w == WSIZE) { + outcnt=(w), + flush_window(); + w = 0; + } + } while (n); + } + } + + /* restore the globals from the locals */ + outcnt = w; /* restore global window pointer */ + bb = b; /* restore global bit buffer */ + bk = k; + + /* done */ + return 0; +} + +/* + * decompress an inflated block + * e: last block flag + * + * GLOBAL VARIABLES: bb, kk, + */ +static int inflate_block(int *e) +{ + unsigned t; /* block type */ + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + static unsigned short cplens[] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + }; + /* note: see note #13 above about the 258 in this list. */ + static unsigned short cplext[] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 + }; /* 99==invalid */ + static unsigned short cpdist[] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + static unsigned short cpdext[] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13 + }; + + /* make local bit buffer */ + b = bb; + k = bk; + + /* read in last block bit */ + while (k < 1) { + b |= ((unsigned long)fgetc(in_file)) << k; + k += 8; + } + *e = (int) b & 1; + b >>= 1; + k -= 1; + + /* read in block type */ + while (k < 2) { + b |= ((unsigned long)fgetc(in_file)) << k; + k += 8; + } + t = (unsigned) b & 3; + b >>= 2; + k -= 2; + + /* restore the global bit buffer */ + bb = b; + bk = k; + + /* inflate that block type */ + switch (t) { + case 0: /* Inflate stored */ + { + unsigned long n; /* number of bytes in block */ + unsigned long w; /* current window position */ + register unsigned long b_stored; /* bit buffer */ + register unsigned long k_stored; /* number of bits in bit buffer */ + + /* make local copies of globals */ + b_stored = bb; /* initialize bit buffer */ + k_stored = bk; + w = outcnt; /* initialize window position */ + + /* go to byte boundary */ + n = k_stored & 7; + b_stored >>= n; + k_stored -= n; + + /* get the length and its complement */ + while (k_stored < 16) { + b_stored |= ((unsigned long)fgetc(in_file)) << k_stored; + k_stored += 8; + } + n = ((unsigned) b_stored & 0xffff); + b_stored >>= 16; + k_stored -= 16; + while (k_stored < 16) { + b_stored |= ((unsigned long)fgetc(in_file)) << k_stored; + k_stored += 8; + } + if (n != (unsigned) ((~b_stored) & 0xffff)) { + return 1; /* error in compressed data */ + } + b_stored >>= 16; + k_stored -= 16; + + /* read and output the compressed data */ + while (n--) { + while (k_stored < 8) { + b_stored |= ((unsigned long)fgetc(in_file)) << k_stored; + k_stored += 8; + } + window[w++] = (unsigned char) b_stored; + if (w == (unsigned long)WSIZE) { + outcnt=(w), + flush_window(); + w = 0; + } + b_stored >>= 8; + k_stored -= 8; + } + + /* restore the globals from the locals */ + outcnt = w; /* restore global window pointer */ + bb = b_stored; /* restore global bit buffer */ + bk = k_stored; + return 0; + } + case 1: /* Inflate fixed + * decompress an inflated type 1 (fixed Huffman codes) block. We should + * either replace this with a custom decoder, or at least precompute the + * Huffman tables. + */ + { + int i; /* temporary variable */ + huft_t *tl; /* literal/length code table */ + huft_t *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned int l[288]; /* length list for huft_build */ + + /* set up literal table */ + for (i = 0; i < 144; i++) { + l[i] = 8; + } + for (; i < 256; i++) { + l[i] = 9; + } + for (; i < 280; i++) { + l[i] = 7; + } + for (; i < 288; i++) { /* make a complete, but wrong code set */ + l[i] = 8; + } + bl = 7; + if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0) { + return i; + } + + /* set up distance table */ + for (i = 0; i < 30; i++) { /* make an incomplete code set */ + l[i] = 5; + } + bd = 5; + if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) { + huft_free(tl); + return i; + } + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; + } + case 2: /* Inflate dynamic */ + { + /* Tables for deflate from PKZIP's appnote.txt. */ + static unsigned border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + }; + int dbits = 6; /* bits in base distance lookup table */ + int lbits = 9; /* bits in base literal/length lookup table */ + + int i; /* temporary variables */ + unsigned j; + unsigned l; /* last length */ + unsigned m; /* mask for bit lengths table */ + unsigned n; /* number of lengths to get */ + huft_t *tl; /* literal/length code table */ + huft_t *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned nb; /* number of bit length codes */ + unsigned nl; /* number of literal/length codes */ + unsigned nd; /* number of distance codes */ + + unsigned ll[286 + 30]; /* literal/length and distance code lengths */ + register unsigned long b_dynamic; /* bit buffer */ + register unsigned k_dynamic; /* number of bits in bit buffer */ + + /* make local bit buffer */ + b_dynamic = bb; + k_dynamic = bk; + + /* read in table lengths */ + while (k_dynamic < 5) { + b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic; + k_dynamic += 8; + } + nl = 257 + ((unsigned) b_dynamic & 0x1f); /* number of literal/length codes */ + b_dynamic >>= 5; + k_dynamic -= 5; + while (k_dynamic < 5) { + b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic; + k_dynamic += 8; + } + nd = 1 + ((unsigned) b_dynamic & 0x1f); /* number of distance codes */ + b_dynamic >>= 5; + k_dynamic -= 5; + while (k_dynamic < 4) { + b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic; + k_dynamic += 8; + } + nb = 4 + ((unsigned) b_dynamic & 0xf); /* number of bit length codes */ + b_dynamic >>= 4; + k_dynamic -= 4; + if (nl > 286 || nd > 30) { + return 1; /* bad lengths */ + } + + /* read in bit-length-code lengths */ + for (j = 0; j < nb; j++) { + while (k_dynamic < 3) { + b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic; + k_dynamic += 8; + } + ll[border[j]] = (unsigned) b_dynamic & 7; + b_dynamic >>= 3; + k_dynamic -= 3; + } + for (; j < 19; j++) { + ll[border[j]] = 0; + } + + /* build decoding table for trees--single level, 7 bit lookup */ + bl = 7; + if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) { + if (i == 1) { + huft_free(tl); + } + return i; /* incomplete code set */ + } + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while ((unsigned) i < n) { + while (k_dynamic < (unsigned) bl) { + b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic; + k_dynamic += 8; + } + j = (td = tl + ((unsigned) b_dynamic & m))->b; + b_dynamic >>= j; + k_dynamic -= j; + j = td->v.n; + if (j < 16) { /* length of code in bits (0..15) */ + ll[i++] = l = j; /* save last length in l */ + } + else if (j == 16) { /* repeat last length 3 to 6 times */ + while (k_dynamic < 2) { + b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic; + k_dynamic += 8; + } + j = 3 + ((unsigned) b_dynamic & 3); + b_dynamic >>= 2; + k_dynamic -= 2; + if ((unsigned) i + j > n) { + return 1; + } + while (j--) { + ll[i++] = l; + } + } else if (j == 17) { /* 3 to 10 zero length codes */ + while (k_dynamic < 3) { + b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic; + k_dynamic += 8; + } + j = 3 + ((unsigned) b_dynamic & 7); + b_dynamic >>= 3; + k_dynamic -= 3; + if ((unsigned) i + j > n) { + return 1; + } + while (j--) { + ll[i++] = 0; + } + l = 0; + } else { /* j == 18: 11 to 138 zero length codes */ + while (k_dynamic < 7) { + b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic; + k_dynamic += 8; + } + j = 11 + ((unsigned) b_dynamic & 0x7f); + b_dynamic >>= 7; + k_dynamic -= 7; + if ((unsigned) i + j > n) { + return 1; + } + while (j--) { + ll[i++] = 0; + } + l = 0; + } + } + + /* free decoding table for trees */ + huft_free(tl); + + /* restore the global bit buffer */ + bb = b_dynamic; + bk = k_dynamic; + + /* build the decoding tables for literal/length and distance codes */ + bl = lbits; + if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) { + if (i == 1) { + error_msg("Incomplete literal tree"); + huft_free(tl); + } + return i; /* incomplete code set */ + } + bd = dbits; + if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) { + if (i == 1) { + error_msg("incomplete distance tree"); + huft_free(td); + } + huft_free(tl); + return i; /* incomplete code set */ + } + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; + } + default: + /* bad block type */ + return 2; + } +} + +/* + * decompress an inflated entry + * + * GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr + */ +static int inflate() +{ + int e; /* last block flag */ + int r; /* result code */ + unsigned h = 0; /* maximum struct huft's malloc'ed */ + + /* initialize window, bit buffer */ + outcnt = 0; + bk = 0; + bb = 0; + + /* decompress until the last block */ + do { + hufts = 0; + if ((r = inflate_block(&e)) != 0) { + return r; + } + if (hufts > h) { + h = hufts; + } + } while (!e); + + /* flush out window */ + flush_window(); + + /* return success */ + return 0; +} + +/* =========================================================================== + * Unzip in to out. This routine works on both gzip and pkzip files. + * + * IN assertions: the buffer inbuf contains already the beginning of + * the compressed data, from offsets inptr to insize-1 included. + * The magic header has already been checked. The output buffer is cleared. + * in, out: input and output file descriptors + */ +extern int unzip(FILE *l_in_file, FILE *l_out_file) +{ + const int extra_field = 0x04; /* bit 2 set: extra field present */ + const int orig_name = 0x08; /* bit 3 set: original file name present */ + const int comment = 0x10; /* bit 4 set: file comment present */ + unsigned char buf[8]; /* extended local header */ + unsigned char flags; /* compression flags */ + char magic[2]; /* magic header */ + int method; + typedef void (*sig_type) (int); + int exit_code=0; /* program exit code */ + int i; + + in_file = l_in_file; + out_file = l_out_file; + + if (signal(SIGINT, SIG_IGN) != SIG_IGN) { + (void) signal(SIGINT, (sig_type) abort_gzip); + } +#ifdef SIGTERM +// if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { +// (void) signal(SIGTERM, (sig_type) abort_gzip); +// } +#endif +#ifdef SIGHUP + if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { + (void) signal(SIGHUP, (sig_type) abort_gzip); + } +#endif + + /* Allocate all global buffers (for DYN_ALLOC option) */ + window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char))); + outcnt = 0; + bytes_out = 0L; + + magic[0] = fgetc(in_file); + magic[1] = fgetc(in_file); + + /* Magic header for gzip files, 1F 8B = \037\213 */ + if (memcmp(magic, "\037\213", 2) != 0) { + error_msg("Invalid gzip magic"); + return EXIT_FAILURE; + } + + method = (int) fgetc(in_file); + if (method != 8) { + error_msg("unknown method %d -- get newer version of gzip", method); + exit_code = 1; + return -1; + } + + flags = (unsigned char) fgetc(in_file); + + /* Ignore time stamp(4), extra flags(1), OS type(1) */ + for (i = 0; i < 6; i++) + fgetc(in_file); + + if ((flags & extra_field) != 0) { + size_t extra; + extra = fgetc(in_file); + extra += fgetc(in_file) << 8; + + for (i = 0; i < extra; i++) + fgetc(in_file); + } + + /* Discard original name if any */ + if ((flags & orig_name) != 0) { + while (fgetc(in_file) != 0); /* null */ + } + + /* Discard file comment if any */ + if ((flags & comment) != 0) { + while (fgetc(in_file) != 0); /* null */ + } + + if (method < 0) { + printf("it failed\n"); + return(exit_code); /* error message already emitted */ + } + + make_crc_table(); + + /* Decompress */ + if (method == 8) { + + int res = inflate(); + + if (res == 3) { + error_msg(memory_exhausted); + } else if (res != 0) { + error_msg("invalid compressed data--format violated"); + } + + } else { + error_msg("internal error, invalid method"); + } + + /* Get the crc and original length + * crc32 (see algorithm.doc) + * uncompressed input size modulo 2^32 + */ + fread(buf, 1, 8, in_file); + + /* Validate decompression - crc */ + if ((unsigned int)((buf[0] | (buf[1] << 8)) |((buf[2] | (buf[3] << 8)) << 16)) != (crc ^ 0xffffffffL)) { + error_msg("invalid compressed data--crc error"); + } + /* Validate decompression - size */ + if (((buf[4] | (buf[5] << 8)) |((buf[6] | (buf[7] << 8)) << 16)) != (unsigned long) bytes_out) { + error_msg("invalid compressed data--length error"); + } + + free(window); + free(crc_table); + + return 0; +} + +/* + * This needs access to global variables wondow and crc_table, so its not in its own file. + */ +extern void gz_close(int gunzip_pid) +{ + if (kill(gunzip_pid, SIGTERM) == -1) { + error_msg_and_die("*** Couldnt kill old gunzip process *** aborting"); + } + + if (waitpid(gunzip_pid, NULL, 0) == -1) { + printf("Couldnt wait ?"); + } + free(window); + free(crc_table); +} diff --git a/release/src/router/busybox/libbb/vdprintf.c b/release/src/router/busybox/libbb/vdprintf.c new file mode 100644 index 00000000..8c3e32a7 --- /dev/null +++ b/release/src/router/busybox/libbb/vdprintf.c @@ -0,0 +1,53 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <unistd.h> +#include "libbb.h" + + + +#if (__GLIBC__ < 2) +extern int vdprintf(int d, const char *format, va_list ap) +{ + char buf[BUF_SIZE]; + int len; + + len = vsprintf(buf, format, ap); + return write(d, buf, len); +} +#endif + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/verror_msg.c b/release/src/router/busybox/libbb/verror_msg.c new file mode 100644 index 00000000..b3482156 --- /dev/null +++ b/release/src/router/busybox/libbb/verror_msg.c @@ -0,0 +1,49 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include "libbb.h" + +extern void verror_msg(const char *s, va_list p) +{ + fflush(stdout); + fprintf(stderr, "%s: ", applet_name); + vfprintf(stderr, s, p); +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/vfork_daemon_rexec.c b/release/src/router/busybox/libbb/vfork_daemon_rexec.c new file mode 100644 index 00000000..c8f9d277 --- /dev/null +++ b/release/src/router/busybox/libbb/vfork_daemon_rexec.c @@ -0,0 +1,27 @@ +/* + * Rexec program for system have fork() as vfork() with foregound option + * Copyright (C) Vladminr Oleynik and many different people. + */ + +#include <unistd.h> +#include "libbb.h" + + +#if defined(__uClinux__) +void vfork_daemon_rexec(int argc, char **argv, char *foreground_opt) +{ + char **vfork_args; + int a = 0; + + vfork_args = xcalloc(sizeof(char *), argc + 3); + while(*argv) { + vfork_args[a++] = *argv; + argv++; + } + vfork_args[a] = foreground_opt; + execvp("/proc/self/exe", vfork_args); + vfork_args[0] = "/bin/busybox"; + execv(vfork_args[0], vfork_args); + bb_perror_msg_and_die("execv %s", vfork_args[0]); +} +#endif /* uClinux */ diff --git a/release/src/router/busybox/libbb/vherror_msg.c b/release/src/router/busybox/libbb/vherror_msg.c new file mode 100644 index 00000000..ee0bb500 --- /dev/null +++ b/release/src/router/busybox/libbb/vherror_msg.c @@ -0,0 +1,44 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdarg.h> +#include <netdb.h> +extern int h_errno; + +#include <stdio.h> + +#include "libbb.h" + +extern void vherror_msg(const char *s, va_list p) +{ + if(s == 0) + s = ""; + verror_msg(s, p); + if (*s) + fputs(": ", stderr); + herror(""); +} diff --git a/release/src/router/busybox/libbb/vperror_msg.c b/release/src/router/busybox/libbb/vperror_msg.c new file mode 100644 index 00000000..ca9361e4 --- /dev/null +++ b/release/src/router/busybox/libbb/vperror_msg.c @@ -0,0 +1,51 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include "libbb.h" + +extern void vperror_msg(const char *s, va_list p) +{ + int err=errno; + if(s == 0) s = ""; + verror_msg(s, p); + if (*s) s = ": "; + fprintf(stderr, "%s%s\n", s, strerror(err)); +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/warn_ignoring_args.c b/release/src/router/busybox/libbb/warn_ignoring_args.c new file mode 100644 index 00000000..223831fd --- /dev/null +++ b/release/src/router/busybox/libbb/warn_ignoring_args.c @@ -0,0 +1,30 @@ +/* vi: set sw=4 ts=4: */ +/* + * warn_ingoring_args implementations for busybox + * + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <libbb.h> + +extern void bb_warn_ignoring_args(int n) +{ + if (n) { + bb_perror_msg("ignoring all arguments"); + } +} diff --git a/release/src/router/busybox/libbb/wfopen.c b/release/src/router/busybox/libbb/wfopen.c new file mode 100644 index 00000000..8b074d2f --- /dev/null +++ b/release/src/router/busybox/libbb/wfopen.c @@ -0,0 +1,50 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <errno.h> +#include "libbb.h" + +FILE *wfopen(const char *path, const char *mode) +{ + FILE *fp; + if ((fp = fopen(path, mode)) == NULL) { + perror_msg("%s", path); + errno = 0; + } + return fp; +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/wfopen_input.c b/release/src/router/busybox/libbb/wfopen_input.c new file mode 100644 index 00000000..bff6606b --- /dev/null +++ b/release/src/router/busybox/libbb/wfopen_input.c @@ -0,0 +1,54 @@ +/* vi: set sw=4 ts=4: */ +/* + * wfopen_input implementation for busybox + * + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* A number of applets need to open a file for reading, where the filename + * is a command line arg. Since often that arg is '-' (meaning stdin), + * we avoid testing everywhere by consolidating things in this routine. + * + * Note: We also consider "" to main stdin (for 'cmp' at least). + */ + +#include <stdio.h> +#include <sys/stat.h> +#include <libbb.h> + +FILE *bb_wfopen_input(const char *filename) +{ + FILE *fp = stdin; + + if ((filename != bb_msg_standard_input) + && filename[0] && ((filename[0] != '-') || filename[1]) + ) { +#if 0 + /* This check shouldn't be necessary for linux, but is left + * here disabled just in case. */ + struct stat stat_buf; + if (is_directory(filename, 1, &stat_buf)) { + bb_error_msg("%s: Is a directory", filename); + return NULL; + } +#endif + fp = bb_wfopen(filename, "r"); + } + + return fp; +} diff --git a/release/src/router/busybox/libbb/xconnect.c b/release/src/router/busybox/libbb/xconnect.c new file mode 100644 index 00000000..2945d760 --- /dev/null +++ b/release/src/router/busybox/libbb/xconnect.c @@ -0,0 +1,79 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Connect to host at port using address resolusion from getaddrinfo + * + */ + +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> +#include <netinet/in.h> +#include "libbb.h" + +int xconnect(const char *host, const char *port) +{ +#ifdef CONFIG_FEATURE_IPV6 + struct addrinfo hints; + struct addrinfo *res; + struct addrinfo *addr_info; + int error; + int s; + + memset(&hints, 0, sizeof(hints)); + /* set-up hints structure */ + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(host, port, &hints, &res); + if (error||!res) + bb_perror_msg_and_die(gai_strerror(error)); + addr_info=res; + while (res) { + s=socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s<0) + { + error=s; + res=res->ai_next; + continue; + } + /* try to connect() to res->ai_addr */ + error = connect(s, res->ai_addr, res->ai_addrlen); + if (error >= 0) + break; + close(s); + res=res->ai_next; + } + freeaddrinfo(addr_info); + if (error < 0) + { + bb_perror_msg_and_die("Unable to connect to remote host (%s)", host); + } + return s; +#else + struct sockaddr_in s_addr; + int s = socket(AF_INET, SOCK_STREAM, 0); + struct servent *tserv; + int port_nr=htons(atoi(port)); + struct hostent * he; + + if (port_nr==0 && (tserv = getservbyname(port, "tcp")) != NULL) + port_nr = tserv->s_port; + + memset(&s_addr, 0, sizeof(struct sockaddr_in)); + s_addr.sin_family = AF_INET; + s_addr.sin_port = port_nr; + + he = xgethostbyname(host); + memcpy(&s_addr.sin_addr, he->h_addr, sizeof s_addr.sin_addr); + + if (connect(s, (struct sockaddr *)&s_addr, sizeof s_addr) < 0) + { + bb_perror_msg_and_die("Unable to connect to remote host (%s)", host); + } + return s; +#endif +} diff --git a/release/src/router/busybox/libbb/xfuncs.c b/release/src/router/busybox/libbb/xfuncs.c new file mode 100644 index 00000000..eb93bf13 --- /dev/null +++ b/release/src/router/busybox/libbb/xfuncs.c @@ -0,0 +1,112 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include "libbb.h" + + +#ifndef DMALLOC +extern void *xmalloc(size_t size) +{ + void *ptr = malloc(size); + + if (!ptr) + error_msg_and_die(memory_exhausted); + return ptr; +} + +extern void *xrealloc(void *old, size_t size) +{ + void *ptr; + + /* SuS2 says "If size is 0 and ptr is not a null pointer, the + * object pointed to is freed." Do that here, in case realloc + * returns a NULL, since we don't want to choke in that case. */ + if (size==0 && old) { + free(old); + return NULL; + } + + ptr = realloc(old, size); + if (!ptr) + error_msg_and_die(memory_exhausted); + return ptr; +} + +extern void *xcalloc(size_t nmemb, size_t size) +{ + void *ptr = calloc(nmemb, size); + if (!ptr) + error_msg_and_die(memory_exhausted); + return ptr; +} + +extern char * xstrdup (const char *s) { + char *t; + + if (s == NULL) + return NULL; + + t = strdup (s); + + if (t == NULL) + error_msg_and_die(memory_exhausted); + + return t; +} +#endif + +extern char * xstrndup (const char *s, int n) { + char *t; + + if (s == NULL) + error_msg_and_die("xstrndup bug"); + + t = xmalloc(++n); + + return safe_strncpy(t,s,n); +} + +FILE *xfopen(const char *path, const char *mode) +{ + FILE *fp; + if ((fp = fopen(path, mode)) == NULL) + perror_msg_and_die("%s", path); + return fp; +} + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/release/src/router/busybox/libbb/xgetcwd.c b/release/src/router/busybox/libbb/xgetcwd.c new file mode 100644 index 00000000..27466816 --- /dev/null +++ b/release/src/router/busybox/libbb/xgetcwd.c @@ -0,0 +1,52 @@ +/* + * xgetcwd.c -- return current directory with unlimited length + * Copyright (C) 1992, 1996 Free Software Foundation, Inc. + * Written by David MacKenzie <djm@gnu.ai.mit.edu>. + * + * Special function for busybox written by Vladimir Oleynik <vodz@usa.net> +*/ + +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <limits.h> +#include "libbb.h" + +/* Amount to increase buffer size by in each try. */ +#define PATH_INCR 32 + +/* Return the current directory, newly allocated, arbitrarily long. + Return NULL and set errno on error. + If argument is not NULL (previous usage allocate memory), call free() +*/ + +char * +xgetcwd (char *cwd) +{ + char *ret; + unsigned path_max; + + errno = 0; + path_max = (unsigned) PATH_MAX; + path_max += 2; /* The getcwd docs say to do this. */ + + if(cwd==0) + cwd = xmalloc (path_max); + + errno = 0; + while ((ret = getcwd (cwd, path_max)) == NULL && errno == ERANGE) { + path_max += PATH_INCR; + cwd = xrealloc (cwd, path_max); + errno = 0; + } + + if (ret == NULL) { + int save_errno = errno; + free (cwd); + errno = save_errno; + perror_msg("getcwd()"); + return NULL; + } + + return cwd; +} diff --git a/release/src/router/busybox/libbb/xgethostbyname.c b/release/src/router/busybox/libbb/xgethostbyname.c new file mode 100644 index 00000000..25851033 --- /dev/null +++ b/release/src/router/busybox/libbb/xgethostbyname.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* + * Mini xgethostbyname implementation. + * + * + * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <netdb.h> +extern int h_errno; + +#include "libbb.h" + +struct hostent *xgethostbyname(const char *name) +{ + struct hostent *retval; + + if ((retval = gethostbyname(name)) == NULL) + herror_msg_and_die("%s", name); + + return retval; +} diff --git a/release/src/router/busybox/libbb/xgethostbyname2.c b/release/src/router/busybox/libbb/xgethostbyname2.c new file mode 100644 index 00000000..3a16ae4d --- /dev/null +++ b/release/src/router/busybox/libbb/xgethostbyname2.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* + * Mini xgethostbyname2 implementation. + * + * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <netdb.h> +#include "libbb.h" + + +#ifdef CONFIG_FEATURE_IPV6 +struct hostent *xgethostbyname2(const char *name, int af) +{ + struct hostent *retval; + + if ((retval = gethostbyname2(name, af)) == NULL) + bb_herror_msg_and_die("%s", name); + + return retval; +} +#endif diff --git a/release/src/router/busybox/libbb/xgetlarg.c b/release/src/router/busybox/libbb/xgetlarg.c new file mode 100644 index 00000000..ed5d3eb4 --- /dev/null +++ b/release/src/router/busybox/libbb/xgetlarg.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2003 Erik Andersen <andersen@codepoet.org> + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#include <errno.h> +#include <assert.h> +#include <ctype.h> + +#include "busybox.h" + +extern long bb_xgetlarg(const char *arg, int base, long lower, long upper) +{ + long result; + char *endptr; + int errno_save = errno; + + assert(arg!=NULL); + + /* Don't allow leading whitespace. */ + if ((isspace)(*arg)) { /* Use an actual funciton call for minimal size. */ + bb_show_usage(); + } + + errno = 0; + result = strtol(arg, &endptr, base); + if (errno != 0 || *endptr!='\0' || endptr==arg || result < lower || result > upper) + bb_show_usage(); + errno = errno_save; + return result; +} diff --git a/release/src/router/busybox/libbb/xgetularg.c b/release/src/router/busybox/libbb/xgetularg.c new file mode 100644 index 00000000..d743520c --- /dev/null +++ b/release/src/router/busybox/libbb/xgetularg.c @@ -0,0 +1,160 @@ +/* vi: set sw=4 ts=4: */ +/* + * xgetularg* implementations for busybox + * + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <ctype.h> +#include <errno.h> +#include <assert.h> +#include "libbb.h" + +#ifdef L_xgetularg_bnd_sfx +extern +unsigned long bb_xgetularg_bnd_sfx(const char *arg, int base, + unsigned long lower, + unsigned long upper, + const struct suffix_mult *suffixes) +{ + unsigned long r; + int old_errno; + char *e; + + assert(arg); + + /* Disallow '-' and any leading whitespace. Speed isn't critical here + * since we're parsing commandline args. So make sure we get the + * actual isspace function rather than a larger macro implementaion. */ + if ((*arg == '-') || (isspace)(*arg)) { + bb_show_usage(); + } + + /* Since this is a lib function, we're not allowed to reset errno to 0. + * Doing so could break an app that is deferring checking of errno. + * So, save the old value so that we can restore it if successful. */ + old_errno = errno; + errno = 0; + r = strtoul(arg, &e, base); + /* Do the initial validity check. Note: The standards do not + * guarantee that errno is set if no digits were found. So we + * must test for this explicitly. */ + if (errno || (arg == e)) { /* error or no digits */ + bb_show_usage(); + } + errno = old_errno; /* Ok. So restore errno. */ + + /* Do optional suffix parsing. Allow 'empty' suffix tables. + * Note that we also all nul suffixes with associated multipliers, + * to allow for scaling of the arg by some default multiplier. */ + + if (suffixes) { + while (suffixes->suffix) { + if (strcmp(suffixes->suffix, e) == 0) { + if (ULONG_MAX / suffixes->mult < r) { /* Overflow! */ + bb_show_usage(); + } + ++e; + r *= suffixes->mult; + break; + } + ++suffixes; + } + } + + /* Finally, check for illegal trailing chars and range limits. */ + /* Note: although we allow leading space (via stroul), trailing space + * is an error. It would be easy enough to allow though if desired. */ + if (*e || (r < lower) || (r > upper)) { + bb_show_usage(); + } + + return r; +} +#endif + +#ifdef L_xgetlarg_bnd_sfx +extern +long bb_xgetlarg_bnd_sfx(const char *arg, int base, + long lower, + long upper, + const struct suffix_mult *suffixes) +{ + unsigned long u = LONG_MAX; + long r; + const char *p = arg; + + if ((*p == '-') && (p[1] != '+')) { + ++p; +#if LONG_MAX == (-(LONG_MIN + 1)) + ++u; /* two's complement */ +#endif + } + + r = bb_xgetularg_bnd_sfx(p, base, 0, u, suffixes); + + if (*arg == '-') { + r = -r; + } + + if ((r < lower) || (r > upper)) { + bb_show_usage(); + } + + return r; +} +#endif + +#ifdef L_getlarg10_sfx +extern +long bb_xgetlarg10_sfx(const char *arg, const struct suffix_mult *suffixes) +{ + return bb_xgetlarg_bnd_sfx(arg, 10, LONG_MIN, LONG_MAX, suffixes); +} +#endif + +#ifdef L_xgetularg_bnd +extern +unsigned long bb_xgetularg_bnd(const char *arg, int base, + unsigned long lower, + unsigned long upper) +{ + return bb_xgetularg_bnd_sfx(arg, base, lower, upper, NULL); +} +#endif + +#ifdef L_xgetularg10_bnd +extern +unsigned long bb_xgetularg10_bnd(const char *arg, + unsigned long lower, + unsigned long upper) +{ + return bb_xgetularg_bnd(arg, 10, lower, upper); +} +#endif + +#ifdef L_xgetularg10 +extern +unsigned long bb_xgetularg10(const char *arg) +{ + return bb_xgetularg10_bnd(arg, 0, ULONG_MAX); +} +#endif diff --git a/release/src/router/busybox/libbb/xreadlink.c b/release/src/router/busybox/libbb/xreadlink.c new file mode 100644 index 00000000..932e487a --- /dev/null +++ b/release/src/router/busybox/libbb/xreadlink.c @@ -0,0 +1,37 @@ +/* + * xreadlink.c - safe implementation of readlink. + * Returns a NULL on failure... + */ + +#include <stdio.h> + +/* + * NOTE: This function returns a malloced char* that you will have to free + * yourself. You have been warned. + */ + +#include <unistd.h> +#include "libbb.h" + +extern char *xreadlink(const char *path) +{ + static const int GROWBY = 80; /* how large we will grow strings by */ + + char *buf = NULL; + int bufsize = 0, readsize = 0; + + do { + buf = xrealloc(buf, bufsize += GROWBY); + readsize = readlink(path, buf, bufsize); /* 1st try */ + if (readsize == -1) { + perror_msg("%s:%s", applet_name, path); + return NULL; + } + } + while (bufsize < readsize + 1); + + buf[readsize] = '\0'; + + return buf; +} + diff --git a/release/src/router/busybox/libbb/xregcomp.c b/release/src/router/busybox/libbb/xregcomp.c new file mode 100644 index 00000000..6f5e2f0c --- /dev/null +++ b/release/src/router/busybox/libbb/xregcomp.c @@ -0,0 +1,53 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) tons of folks. Tracking down who wrote what + * isn't something I'm going to worry about... If you wrote something + * here, please feel free to acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. + * + */ + +#include <stdio.h> +#include "libbb.h" +#include <regex.h> + + + +void xregcomp(regex_t *preg, const char *regex, int cflags) +{ + int ret; + if ((ret = regcomp(preg, regex, cflags)) != 0) { + int errmsgsz = regerror(ret, preg, NULL, 0); + char *errmsg = xmalloc(errmsgsz); + regerror(ret, preg, errmsg, errmsgsz); + error_msg_and_die("xregcomp: %s", errmsg); + } +} + + +/* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ |