diff options
Diffstat (limited to 'libbb')
78 files changed, 1823 insertions, 1049 deletions
diff --git a/libbb/Makefile.in b/libbb/Makefile.in index 6d2475b..c7916f1 100644 --- a/libbb/Makefile.in +++ b/libbb/Makefile.in @@ -42,26 +42,59 @@ LIBBB_SRC:= \ 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 \ time_string.c trim.c u_signal_names.c vdprintf.c verror_msg.c \ - vherror_msg.c vperror_msg.c wfopen.c xconnect.c xgetcwd.c xfuncs.c \ - xgethostbyname.c xgethostbyname2.c xreadlink.c xregcomp.c xgetlarg.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 LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC)) -LIBBB_MSRC:=$(LIBBB_DIR)messages.c -LIBBB_MOBJ:=full_version.o name_too_long.o omitting_directory.o not_a_directory.o \ - memory_exhausted.o invalid_date.o invalid_option.o io_error.o dash_dash_help.o \ - write_error.o too_few_args.o name_longer_than_foo.o unknown.o can_not_create_raw_socket.o \ - shadow_file.o passwd_file.o group_file.o gshadow_file.o nologin_file.o securetty_file.o \ - motd_file.o -LIBBB_MOBJS=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ)) +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:=vfprintf.o vprintf.o fprintf.o 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_MOBJS) - $(AR) -ro $@ $(LIBBB_OBJS) $(LIBBB_MOBJS) +$(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_MOBJS): $(LIBBB_MSRC) +$(LIBBB_MOBJS3): $(LIBBB_MSRC3) $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DL_$(notdir $*) -c $< -o $@ $(LIBBB_DIR)loop.o: $(LIBBB_DIR)loop.h diff --git a/libbb/ask_confirmation.c b/libbb/ask_confirmation.c index d4d943a..a99a4e7 100644 --- a/libbb/ask_confirmation.c +++ b/libbb/ask_confirmation.c @@ -1,49 +1,49 @@ /* vi: set sw=4 ts=4: */ /* - * Utility routines. + * bb_ask_confirmation implementation for busybox * - * Copyright (C) many different people. If you wrote this, please - * acknowledge your work. + * 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 + * 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 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* Read a line from stdin. If the first non-whitespace char is 'y' or 'Y', + * return 1. Otherwise return 0. */ #include <stdio.h> +#include <ctype.h> #include "libbb.h" - -int ask_confirmation() +int bb_ask_confirmation(void) { - int c = '\0'; - int ret = 0; + int retval = 0; + int first = 1; + int c; - while (c != '\n') { - c = getchar(); - if ( c != '\n' ) { - ret = ((c=='y')||(c=='Y')) ? 1 : 0; + while (((c = getchar()) != EOF) && (c != '\n')) { + /* Make sure we get the actual function call for isspace, + * as speed is not critical here. */ + if (first && !(isspace)(c)) { + --first; + if ((c == 'y') || (c == 'Y')) { + ++retval; + } } } - return ret; -} -/* END CODE */ -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ + return retval; +} diff --git a/libbb/bb_asprintf.c b/libbb/bb_asprintf.c index 9a71be7..7075b46 100644 --- a/libbb/bb_asprintf.c +++ b/libbb/bb_asprintf.c @@ -5,17 +5,18 @@ #include <stdlib.h> #include <stdio.h> #include <stdarg.h> - - #include "libbb.h" - -void bb_asprintf(char **string_ptr, const char *format, ...) +void bb_xasprintf(char **string_ptr, const char *format, ...) { - va_list p; + va_list p; + int r; + + va_start(p, format); + r = vasprintf(string_ptr, format, p); + va_end(p); - va_start(p, format); - if(vasprintf(string_ptr, format, p)<0) - error_msg_and_die(memory_exhausted); - va_end(p); + if (r < 0) { + bb_perror_msg_and_die("bb_xasprintf"); + } } diff --git a/libbb/change_identity.c b/libbb/change_identity.c index 819b216..c2b73ee 100644 --- a/libbb/change_identity.c +++ b/libbb/change_identity.c @@ -43,12 +43,12 @@ void change_identity ( const struct passwd *pw ) { if ( initgroups ( pw-> pw_name, pw-> pw_gid ) == -1 ) - perror_msg_and_die ( "cannot set groups" ); + bb_perror_msg_and_die ( "cannot set groups" ); endgrent ( ); if ( setgid ( pw-> pw_gid )) - perror_msg_and_die ( "cannot set group id" ); + bb_perror_msg_and_die ( "cannot set group id" ); if ( setuid ( pw->pw_uid )) - perror_msg_and_die ( "cannot set user id" ); + bb_perror_msg_and_die ( "cannot set user id" ); } diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c index b158ae4..993b462 100644 --- a/libbb/compare_string_array.c +++ b/libbb/compare_string_array.c @@ -27,4 +27,5 @@ extern unsigned short compare_string_array(const char *string_array[], const cha } } return(i); -}
\ No newline at end of file +} + diff --git a/libbb/concat_path_file.c b/libbb/concat_path_file.c index 0146606..b972ba6 100644 --- a/libbb/concat_path_file.c +++ b/libbb/concat_path_file.c @@ -38,7 +38,7 @@ extern char *concat_path_file(const char *path, const char *filename) lc = last_char_is(path, '/'); while (*filename == '/') filename++; - bb_asprintf(&outbuf, "%s%s%s", path, (lc==NULL)? "/" : "", filename); + bb_xasprintf(&outbuf, "%s%s%s", path, (lc==NULL)? "/" : "", filename); return outbuf; } diff --git a/libbb/copy_file.c b/libbb/copy_file.c index 23a2d75..81c5474 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -43,19 +43,19 @@ int copy_file(const char *source, const char *dest, int flags) lstat(source, &source_stat) < 0) || ((flags & FILEUTILS_DEREFERENCE) && stat(source, &source_stat) < 0)) { - perror_msg("%s", source); + bb_perror_msg("%s", source); return -1; } if (lstat(dest, &dest_stat) < 0) { if (errno != ENOENT) { - perror_msg("unable to stat `%s'", dest); + bb_perror_msg("unable to stat `%s'", dest); return -1; } } else { if (source_stat.st_dev == dest_stat.st_dev && source_stat.st_ino == dest_stat.st_ino) { - error_msg("`%s' and `%s' are the same file", source, dest); + bb_error_msg("`%s' and `%s' are the same file", source, dest); return -1; } dest_exists = 1; @@ -67,14 +67,14 @@ int copy_file(const char *source, const char *dest, int flags) mode_t saved_umask = 0; if (!(flags & FILEUTILS_RECUR)) { - error_msg("%s: omitting directory", source); + bb_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); + bb_error_msg("`%s' is not a directory", dest); return -1; } } else { @@ -88,7 +88,7 @@ int copy_file(const char *source, const char *dest, int flags) if (mkdir(dest, mode) < 0) { umask(saved_umask); - perror_msg("cannot create directory `%s'", dest); + bb_perror_msg("cannot create directory `%s'", dest); return -1; } @@ -97,7 +97,7 @@ int copy_file(const char *source, const char *dest, int flags) /* Recursively copy files in SOURCE. */ if ((dp = opendir(source)) == NULL) { - perror_msg("unable to open directory `%s'", source); + bb_perror_msg("unable to open directory `%s'", source); status = -1; goto end; } @@ -121,7 +121,7 @@ int copy_file(const char *source, const char *dest, int flags) if (!dest_exists && chmod(dest, source_stat.st_mode & ~saved_umask) < 0) { - perror_msg("unable to change permissions of `%s'", dest); + bb_perror_msg("unable to change permissions of `%s'", dest); status = -1; } } else if (S_ISREG(source_stat.st_mode)) { @@ -132,7 +132,7 @@ int copy_file(const char *source, const char *dest, int flags) if (!(flags & FILEUTILS_DEREFERENCE) && is_in_ino_dev_hashtable(&source_stat, &link_name)) { if (link(link_name, dest) < 0) { - perror_msg("unable to link `%s'", dest); + bb_perror_msg("unable to link `%s'", dest); return -1; } @@ -140,14 +140,14 @@ int copy_file(const char *source, const char *dest, int flags) } #endif - if ((sfp = wfopen(source, "r")) == NULL) { + if ((sfp = bb_wfopen(source, "r")) == NULL) { return -1; } if (dest_exists) { if (flags & FILEUTILS_INTERACTIVE) { - fprintf(stderr, "%s: overwrite `%s'? ", applet_name, dest); - if (!ask_confirmation()) { + fprintf(stderr, "%s: overwrite `%s'? ", bb_applet_name, dest); + if (!bb_ask_confirmation()) { fclose (sfp); return 0; } @@ -155,13 +155,13 @@ int copy_file(const char *source, const char *dest, int flags) if ((dfp = fopen(dest, "w")) == NULL) { if (!(flags & FILEUTILS_FORCE)) { - perror_msg("unable to open `%s'", dest); + bb_perror_msg("unable to open `%s'", dest); fclose (sfp); return -1; } if (unlink(dest) < 0) { - perror_msg("unable to remove `%s'", dest); + bb_perror_msg("unable to remove `%s'", dest); fclose (sfp); return -1; } @@ -177,22 +177,22 @@ int copy_file(const char *source, const char *dest, int flags) (dfp = fdopen(fd, "w")) == NULL) { if (fd >= 0) close(fd); - perror_msg("unable to open `%s'", dest); + bb_perror_msg("unable to open `%s'", dest); fclose (sfp); return -1; } } - if (copyfd(fileno(sfp), fileno(dfp), 0) == -1) + if (bb_copyfd(fileno(sfp), fileno(dfp), 0) == -1) status = -1; if (fclose(dfp) < 0) { - perror_msg("unable to close `%s'", dest); + bb_perror_msg("unable to close `%s'", dest); status = -1; } if (fclose(sfp) < 0) { - perror_msg("unable to close `%s'", source); + bb_perror_msg("unable to close `%s'", source); status = -1; } } @@ -202,23 +202,23 @@ int copy_file(const char *source, const char *dest, int flags) if (dest_exists && ((flags & FILEUTILS_FORCE) == 0 || unlink(dest) < 0)) { - perror_msg("unable to remove `%s'", dest); + bb_perror_msg("unable to remove `%s'", dest); return -1; } } else { - error_msg("internal error: unrecognized file type"); + bb_error_msg("internal error: unrecognized file type"); return -1; } 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); + bb_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); + bb_perror_msg("cannot create fifo `%s'", dest); return -1; } } else if (S_ISLNK(source_stat.st_mode)) { @@ -226,7 +226,7 @@ int copy_file(const char *source, const char *dest, int flags) lpath = xreadlink(source); if (symlink(lpath, dest) < 0) { - perror_msg("cannot create symlink `%s'", dest); + bb_perror_msg("cannot create symlink `%s'", dest); return -1; } free(lpath); @@ -234,7 +234,7 @@ int copy_file(const char *source, const char *dest, int flags) #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); + bb_perror_msg("unable to preserve ownership of `%s'", dest); #endif #ifdef CONFIG_FEATURE_PRESERVE_HARDLINKS @@ -256,13 +256,13 @@ end: 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); + bb_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); + bb_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); + bb_perror_msg("unable to preserve permissions of `%s'", dest); } return status; diff --git a/libbb/copy_file_chunk.c b/libbb/copy_file_chunk.c deleted file mode 100644 index 63d2ab1..0000000 --- a/libbb/copy_file_chunk.c +++ /dev/null @@ -1,70 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Utility routines. - * - * Copyright (C) many different people. If you wrote this, please - * 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 <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/libbb/copyfd.c b/libbb/copyfd.c index 4df1fd0..41b78c7 100644 --- a/libbb/copyfd.c +++ b/libbb/copyfd.c @@ -22,65 +22,51 @@ #include <unistd.h> #include <string.h> #include <errno.h> -#include "libbb.h" +#include "busybox.h" -/* If chunksize is 0 copy untill EOF */ -extern int copyfd(int fd1, int fd2, const off_t chunksize) +#if BUFSIZ < 4096 +#undef BUFSIZ +#define BUFSIZ 4096 +#endif + +/* If chunksize is 0 copy until EOF */ +extern int bb_copyfd(int fd1, int fd2, const off_t chunksize) { - size_t nread; - size_t nwritten; + ssize_t nread; size_t size; - size_t remaining; - char buffer[BUFSIZ]; + off_t remaining; + RESERVE_CONFIG_BUFFER(buffer,BUFSIZ); + remaining = size = BUFSIZ; if (chunksize) { remaining = chunksize; - } else { - remaining = -1; } do { - if ((chunksize > BUFSIZ) || (chunksize == 0)) { - size = BUFSIZ; - } else { - size = chunksize; + if (size > remaining) { + size = remaining; } - nread = safe_read(fd1, buffer, size); - - if (nread == -1) { - perror_msg("read failure"); - return(-1); - } - else if (nread == 0) { + if ((nread = safe_read(fd1, buffer, size)) > 0) { + if (bb_full_write(fd2, buffer, nread) < 0) { + bb_perror_msg(bb_msg_write_error); /* match Read error below */ + break; + } + if (chunksize && ((remaining -= nread) == 0)) { + return 0; + } + } else if (!nread) { if (chunksize) { - error_msg("Unable to read all data"); - return(-1); - } else { - return(0); + bb_error_msg("Unable to read all data"); + break; } + return 0; + } else { /* nread < 0 */ + bb_perror_msg("Read error"); /* match bb_msg_write_error above */ + break; } - nwritten = full_write(fd2, buffer, nread); + } while (1); - if (nwritten != nread) { - error_msg("Unable to write all data"); - return(-1); - } - - if (chunksize) { - remaining -= nwritten; - } - } while (remaining != 0); - - return 0; + return -1; } - -/* END CODE */ -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/libbb/correct_password.c b/libbb/correct_password.c index 758b89e..3962536 100644 --- a/libbb/correct_password.c +++ b/libbb/correct_password.c @@ -55,7 +55,7 @@ int correct_password ( const struct passwd *pw ) struct spwd *sp = getspnam ( pw-> pw_name ); if ( !sp ) - error_msg_and_die ( "no valid shadow password" ); + bb_error_msg_and_die ( "no valid shadow password" ); correct = sp-> sp_pwdp; } @@ -73,6 +73,6 @@ int correct_password ( const struct passwd *pw ) return 0; } encrypted = crypt ( unencrypted, correct ); - memset ( unencrypted, 0, xstrlen ( unencrypted )); + memset ( unencrypted, 0, bb_strlen ( unencrypted )); return ( strcmp ( encrypted, correct ) == 0 ) ? 1 : 0; } diff --git a/libbb/create_icmp6_socket.c b/libbb/create_icmp6_socket.c index 1d0b6b6..5966104 100644 --- a/libbb/create_icmp6_socket.c +++ b/libbb/create_icmp6_socket.c @@ -26,9 +26,9 @@ int create_icmp6_socket(void) if ((sock = socket(AF_INET6, SOCK_RAW, (proto ? proto->p_proto : IPPROTO_ICMPV6))) < 0) { if (errno == EPERM) - error_msg_and_die("permission denied. (are you root?)"); + bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); else - perror_msg_and_die(can_not_create_raw_socket); + bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); } /* drop root privs if running setuid */ diff --git a/libbb/create_icmp_socket.c b/libbb/create_icmp_socket.c index d804b39..58d792b 100644 --- a/libbb/create_icmp_socket.c +++ b/libbb/create_icmp_socket.c @@ -25,9 +25,9 @@ int create_icmp_socket(void) 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?)"); + bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); else - perror_msg_and_die(can_not_create_raw_socket); + bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); } /* drop root privs if running setuid */ diff --git a/libbb/default_error_retval.c b/libbb/default_error_retval.c new file mode 100644 index 0000000..7d2d89b --- /dev/null +++ b/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/libbb/dirname.c b/libbb/dirname.c index df9a49d..8129873 100644 --- a/libbb/dirname.c +++ b/libbb/dirname.c @@ -1,8 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini dirname function. + * dirname implementation for busybox (for libc's missing one) * - * Copyright (C) 2001 Matt Kraai. + * 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 @@ -17,39 +17,53 @@ * 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 + * + */ + +/* Note: The previous busybox implementation did not handle NULL path + * and also moved a pointer before path, which is not portable in C. + * So I replaced it with my uClibc version. */ #include <string.h> #include "libbb.h" -#if defined __UCLIBC__ || __GNU_LIBRARY___ < 5 - -/* Return a string containing the path name of the parent - * directory of PATH. */ +#if __GNU_LIBRARY__ < 5 +extern char *dirname(char *path) { - 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--; + static const char null_or_empty_or_noslash[] = "."; + register char *s; + register char *last; + char *first; - /* Strip the last component. */ - while (path <= s && s[0] != '/') - s--; + last = s = path; - while (path < s && s[0] == '/') - s--; + if (s != NULL) { - if (s < path) - return "."; + LOOP: + while (*s && (*s != '/')) ++s; + first = s; + while (*s == '/') ++s; + if (*s) { + last = first; + goto LOOP; + } - s[1] = '\0'; - return path; + if (last == path) { + if (*last != '/') { + goto DOT; + } + if ((*++last == '/') && (last[1] == 0)) { + ++last; + } + } + *last = 0; + return path; + } + DOT: + return (char *) null_or_empty_or_noslash; } #endif diff --git a/libbb/dump.c b/libbb/dump.c index 1afad83..26dabe5 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -25,94 +25,80 @@ #include <stdlib.h> #include <string.h> #include <ctype.h> /* for isdigit() */ -#include "dump.h" #include "libbb.h" +#include "dump.h" -enum _vflag vflag = FIRST; -FS *fshead; /* head of format strings */ -extern FS *fshead; /* head of format strings */ -extern int blocksize; +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 skip; /* bytes to skip */ -off_t saveaddress; -int exitval; /* final exit value */ -int blocksize; /* data block size */ -int length = -1; /* max bytes to read */ +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"; -int size(FS * fs) +static const char lcc[] = "diouxX"; + +int bb_dump_size(FS * fs) { register FU *fu; - register int bcnt, cursize; + register int bcnt, cur_size; register char *fmt; + const char *p; int prec; - /* figure out the data block size needed for each format unit */ - for (cursize = 0, fu = fs->nextfu; fu; fu = fu->nextfu) { + /* 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) { - cursize += fu->bcnt * fu->reps; + cur_size += fu->bcnt * fu->reps; continue; } for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) { if (*fmt != '%') continue; /* - * skip any special chars -- save precision in + * bb_dump_skip any special chars -- save precision in * case it's a %s format. */ - while (index(".#-+ 0123456789" + 1, *++fmt)); + while (strchr(index_str + 1, *++fmt)); if (*fmt == '.' && isdigit(*++fmt)) { prec = atoi(fmt); while (isdigit(*++fmt)); } - switch (*fmt) { - case 'c': - bcnt += 1; - break; - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': - bcnt += 4; - break; - case 'e': - case 'E': - case 'f': - case 'g': - case 'G': - bcnt += 8; - break; - case 's': - bcnt += prec; - break; - case '_': - switch (*++fmt) { - case 'c': - case 'p': - case 'u': - bcnt += 1; - break; + 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)]; } } - cursize += bcnt * fu->reps; + cur_size += bcnt * fu->reps; } - return (cursize); + return (cur_size); } -void rewrite(FS * fs) +static void rewrite(FS * fs) { enum { NOTOKAY, USEBCNT, USEPREC } sokay; register PR *pr, **nextpr = NULL; register FU *fu; register char *p1, *p2; char savech, *fmtp; + const char *byte_count_str; int nconv, prec = 0; for (fu = fs->nextfu; fu; fu = fu->nextfu) { @@ -128,7 +114,7 @@ void rewrite(FS * fs) else *nextpr = pr; - /* skip preceding text and up to the next % sign */ + /* bb_dump_skip preceding text and up to the next % sign */ for (p1 = fmtp; *p1 && *p1 != '%'; ++p1); /* only text in the string */ @@ -144,11 +130,11 @@ void rewrite(FS * fs) */ if (fu->bcnt) { sokay = USEBCNT; - /* skip to conversion character */ - for (++p1; index(".#-+ 0123456789", *p1); ++p1); + /* bb_dump_skip to conversion character */ + for (++p1; strchr(index_str, *p1); ++p1); } else { - /* skip any special chars, field width */ - while (index(".#-+ 0123456789" + 1, *++p1)); + /* bb_dump_skip any special chars, field width */ + while (strchr(index_str + 1, *++p1)); if (*p1 == '.' && isdigit(*++p1)) { sokay = USEPREC; prec = atoi(p1); @@ -162,104 +148,59 @@ void rewrite(FS * fs) /* * figure out the byte count for each conversion; * rewrite the format as necessary, set up blank- - * padding for end of data. + * pbb_dump_adding for end of data. */ - switch (*p1) { - case 'c': + + if (*p1 == 'c') { pr->flags = F_CHAR; - switch (fu->bcnt) { - case 0: - case 1: - pr->bcnt = 1; - break; - default: - p1[1] = '\0'; - error_msg_and_die - ("bad byte count for conversion character %s.", p1); + 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); } - break; - case 'd': - case 'i': - pr->flags = F_INT; - goto sw1; - case 'l': + /* 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; - switch (p1[1]) { - case 'd': - case 'i': - ++p1; + ++p1; + DO_INT_CONV: + { + const char *e; + if (!(e = strchr(lcc, *p1))) { + goto DO_BAD_CONV_CHAR; + } pr->flags = F_INT; - goto sw1; - case 'o': - case 'u': - case 'x': - case 'X': - ++p1; - pr->flags = F_UINT; - goto sw1; - default: - p1[2] = '\0'; - error_msg_and_die - ("hexdump: bad conversion character %%%s.\n", p1); + if (e > lcc + 1) { + pr->flags = F_UINT; + } + byte_count_str = "\004\002\001"; + goto DO_BYTE_COUNT; } /* NOTREACHED */ - case 'o': - case 'u': - case 'x': - case 'X': - pr->flags = F_UINT; - sw1:switch (fu->bcnt) { - case 0: - case 4: - pr->bcnt = 4; - break; - case 1: - pr->bcnt = 1; - break; - case 2: - pr->bcnt = 2; - break; - default: - p1[1] = '\0'; - error_msg_and_die - ("bad byte count for conversion character %s.", p1); - } - break; - case 'e': - case 'E': - case 'f': - case 'g': - case 'G': + } else if (strchr(lcc, *p1)) { + goto DO_INT_CONV; + } else if (strchr("eEfgG", *p1)) { pr->flags = F_DBL; - switch (fu->bcnt) { - case 0: - case 8: - pr->bcnt = 8; - break; - case 4: - pr->bcnt = 4; - break; - default: - p1[1] = '\0'; - error_msg_and_die - ("bad byte count for conversion character %s.", p1); - } - break; - case 's': + byte_count_str = "\010\004"; + goto DO_BYTE_COUNT; + } else if (*p1 == 's') { pr->flags = F_STR; - switch (sokay) { - case NOTOKAY: - error_msg_and_die - ("%%s requires a precision or a byte count."); - case USEBCNT: + if (sokay == USEBCNT) { pr->bcnt = fu->bcnt; - break; - case USEPREC: + } else if (sokay == USEPREC) { pr->bcnt = prec; - break; + } else { /* NOTOKAY */ + bb_error_msg_and_die("%%s requires a precision or a byte count."); } - break; - case '_': + } else if (*p1 == '_') { ++p2; switch (p1[1]) { case 'A': @@ -269,51 +210,29 @@ void rewrite(FS * fs) case 'a': pr->flags = F_ADDRESS; ++p2; - switch (p1[2]) { - case 'd': - case 'o': - case 'x': - *p1 = p1[2]; - break; - default: - p1[3] = '\0'; - error_msg_and_die - ("hexdump: bad conversion character %%%s.\n", p1); + 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 sw2; + goto DO_BYTE_COUNT_1; case 'p': pr->flags = F_P; *p1 = 'c'; - goto sw2; + goto DO_BYTE_COUNT_1; case 'u': pr->flags = F_U; /* *p1 = 'c'; set in conv_u */ - sw2:switch (fu->bcnt) { - case 0: - case 1: - pr->bcnt = 1; - break; - default: - p1[2] = '\0'; - error_msg_and_die - ("bad byte count for conversion character %s.", - p1); - } - break; + goto DO_BYTE_COUNT_1; default: - p1[2] = '\0'; - error_msg_and_die - ("hexdump: bad conversion character %%%s.\n", p1); + goto DO_BAD_CONV_CHAR; } - break; - default: - p1[1] = '\0'; - error_msg_and_die("hexdump: bad conversion character %%%s.\n", - p1); + } else { + DO_BAD_CONV_CHAR: + bb_error_msg_and_die("bad conversion character %%%s.\n", p1); } /* @@ -322,16 +241,14 @@ void rewrite(FS * fs) */ savech = *p2; p1[1] = '\0'; - if (!(pr->fmt = strdup(fmtp))) - perror_msg_and_die("hexdump"); + pr->fmt = bb_xstrdup(fmtp); *p2 = savech; pr->cchar = pr->fmt + (p1 - fmtp); fmtp = p2; /* only one conversion character if byte count */ if (!(pr->flags & F_ADDRESS) && fu->bcnt && nconv++) { - error_msg_and_die - ("hexdump: byte count with multiple conversion characters.\n"); + bb_error_msg_and_die("byte count with multiple conversion characters.\n"); } } /* @@ -344,7 +261,7 @@ void rewrite(FS * fs) } /* * if the format string interprets any data at all, and it's - * not the same as the blocksize, and its last format unit + * 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. * @@ -352,9 +269,9 @@ void rewrite(FS * fs) * gets output from the last iteration of the format unit. */ for (fu = fs->nextfu;; fu = fu->nextfu) { - if (!fu->nextfu && fs->bcnt < blocksize && + if (!fu->nextfu && fs->bcnt < bb_dump_blocksize && !(fu->flags & F_SETREP) && fu->bcnt) - fu->reps += (blocksize - fs->bcnt) / 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) @@ -369,31 +286,31 @@ void rewrite(FS * fs) } } -static void doskip(char *fname, int statok) +static void do_skip(char *fname, int statok) { struct stat sbuf; if (statok) { if (fstat(fileno(stdin), &sbuf)) { - perror_msg_and_die("hexdump: %s", fname); + bb_perror_msg_and_die("%s", fname); } if ((!(S_ISCHR(sbuf.st_mode) || S_ISBLK(sbuf.st_mode) || - S_ISFIFO(sbuf.st_mode))) && skip >= sbuf.st_size) { - /* If size valid and skip >= size */ - skip -= sbuf.st_size; + 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, skip, SEEK_SET)) { - perror_msg_and_die("hexdump: %s", fname); + if (fseek(stdin, bb_dump_skip, SEEK_SET)) { + bb_perror_msg_and_die("%s", fname); } - savaddress = address += skip; - skip = 0; + savaddress = address += bb_dump_skip; + bb_dump_skip = 0; } -int next(char **argv) +static int next(char **argv) { static int done; int statok; @@ -405,7 +322,7 @@ int next(char **argv) for (;;) { if (*_argv) { if (!(freopen(*_argv, "r", stdin))) { - perror_msg("%s", *_argv); + bb_perror_msg("%s", *_argv); exitval = 1; ++_argv; continue; @@ -416,11 +333,11 @@ int next(char **argv) return (0); statok = 0; } - if (skip) - doskip(statok ? *_argv : "stdin", statok); + if (bb_dump_skip) + do_skip(statok ? *_argv : "stdin", statok); if (*_argv) ++_argv; - if (!skip) + if (!bb_dump_skip) return (1); } /* NOTREACHED */ @@ -435,26 +352,26 @@ static u_char *get(void) u_char *tmpp; if (!curp) { - curp = (u_char *) xmalloc(blocksize); - savp = (u_char *) xmalloc(blocksize); + curp = (u_char *) xmalloc(bb_dump_blocksize); + savp = (u_char *) xmalloc(bb_dump_blocksize); } else { tmpp = curp; curp = savp; savp = tmpp; - address = savaddress += blocksize; + address = savaddress += bb_dump_blocksize; } - for (need = blocksize, nread = 0;;) { + 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 (!length || (ateof && !next((char **) NULL))) { - if (need == blocksize) { + if (!bb_dump_length || (ateof && !next((char **) NULL))) { + if (need == bb_dump_blocksize) { return ((u_char *) NULL); } - if (vflag != ALL && !bcmp(curp, savp, nread)) { - if (vflag != DUP) { + if (bb_dump_vflag != ALL && !bcmp(curp, savp, nread)) { + if (bb_dump_vflag != DUP) { printf("*\n"); } return ((u_char *) NULL); @@ -464,31 +381,32 @@ static u_char *get(void) return (curp); } n = fread((char *) curp + nread, sizeof(u_char), - length == -1 ? need : MIN(length, need), stdin); + bb_dump_length == -1 ? need : MIN(bb_dump_length, need), stdin); if (!n) { if (ferror(stdin)) { - perror_msg("%s", _argv[-1]); + bb_perror_msg("%s", _argv[-1]); } ateof = 1; continue; } ateof = 0; - if (length != -1) { - length -= n; + if (bb_dump_length != -1) { + bb_dump_length -= n; } if (!(need -= n)) { - if (vflag == ALL || vflag == FIRST || bcmp(curp, savp, blocksize)) { - if (vflag == DUP || vflag == FIRST) { - vflag = WAIT; + 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 (vflag == WAIT) { + if (bb_dump_vflag == WAIT) { printf("*\n"); } - vflag = DUP; - address = savaddress += blocksize; - need = blocksize; + bb_dump_vflag = DUP; + address = savaddress += bb_dump_blocksize; + need = bb_dump_blocksize; nread = 0; } else { nread += n; @@ -507,67 +425,59 @@ static void bpad(PR * pr) pr->flags = F_BPAD; *pr->cchar = 's'; for (p1 = pr->fmt; *p1 != '%'; ++p1); - for (p2 = ++p1; *p1 && index(" -0+#", *p1); ++p1); + for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1); while ((*p2++ = *p1++) != 0); } -void conv_c(PR * pr, u_char * p) +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) { - char buf[10], *str; - - switch (*p) { - case '\0': - str = "\\0"; - goto strpr; - /* case '\a': */ - case '\007': - str = "\\a"; - goto strpr; - case '\b': - str = "\\b"; - goto strpr; - case '\f': - str = "\\f"; - goto strpr; - case '\n': - str = "\\n"; - goto strpr; - case '\r': - str = "\\r"; - goto strpr; - case '\t': - str = "\\t"; - goto strpr; - case '\v': - str = "\\v"; - goto strpr; - default: - break; - } + 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(str = buf, "%03o", (int) *p); + sprintf(buf, "%03o", (int) *p); + str = buf; strpr: *pr->cchar = 's'; printf(pr->fmt, str); } } -void conv_u(PR * pr, u_char * p) +static void conv_u(PR * pr, u_char * p) { - static char *list[] = { - "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", - "bs", "ht", "lf", "vt", "ff", "cr", "so", "si", - "dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb", - "can", "em", "sub", "esc", "fs", "gs", "rs", "us", - }; + 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[*p]); + printf(pr->fmt, list[4 * (int)(*p)]); } else if (*p == 0x7f) { *pr->cchar = 's'; printf(pr->fmt, "del"); @@ -580,7 +490,7 @@ void conv_u(PR * pr, u_char * p) } } -void display(void) +static void display(void) { /* extern FU *endfu; */ register FS *fs; @@ -589,11 +499,11 @@ void display(void) register int cnt; register u_char *bp; -/* off_t saveaddress; */ + off_t saveaddress; u_char savech = 0, *savebp; while ((bp = get()) != NULL) { - for (fs = fshead, savebp = bp, saveaddress = address; fs; + 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) { @@ -707,8 +617,8 @@ void display(void) } if (endfu) { /* - * if eaddress not set, error or file size was multiple of - * blocksize, and no partial block ever found. + * 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) { @@ -729,19 +639,19 @@ void display(void) } } -int dump(char **argv) +int bb_dump_dump(char **argv) { register FS *tfs; - /* figure out the data block size */ - for (blocksize = 0, tfs = fshead; tfs; tfs = tfs->nextfs) { - tfs->bcnt = size(tfs); - if (blocksize < tfs->bcnt) { - blocksize = tfs->bcnt; + /* 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 = fshead; tfs; tfs = tfs->nextfs) { + for (tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) { rewrite(tfs); } @@ -751,21 +661,21 @@ int dump(char **argv) return (exitval); } -void add(char *fmt) +void bb_dump_add(const char *fmt) { - register char *p; + register const char *p; register char *p1; register char *p2; static FS **nextfs; FS *tfs; FU *tfu, **nextfu; - char *savep; + const char *savep; /* start new linked list of format units */ /* NOSTRICT */ tfs = (FS *) xmalloc(sizeof(FS)); - if (!fshead) { - fshead = tfs; + if (!bb_dump_fshead) { + bb_dump_fshead = tfs; } else { *nextfs = tfs; } @@ -774,8 +684,8 @@ void add(char *fmt) /* take the format string and break it up into format units */ for (p = fmt;;) { - /* skip leading white space */ - for (; isspace(*p); ++p); + /* bb_dump_skip leading white space */ + p = bb_skip_whitespace(p); if (!*p) { break; } @@ -791,43 +701,41 @@ void add(char *fmt) if (isdigit(*p)) { for (savep = p; isdigit(*p); ++p); if (!isspace(*p) && *p != '/') { - error_msg_and_die("hexdump: bad format {%s}", fmt); + bb_error_msg_and_die("bad format {%s}", fmt); } /* may overwrite either white space or slash */ tfu->reps = atoi(savep); tfu->flags = F_SETREP; - /* skip trailing white space */ - for (++p; isspace(*p); ++p); + /* bb_dump_skip trailing white space */ + p = bb_skip_whitespace(++p); } - /* skip slash and trailing white space */ + /* bb_dump_skip slash and trailing white space */ if (*p == '/') { - while (isspace(*++p)); + p = bb_skip_whitespace(++p); } /* byte count */ if (isdigit(*p)) { for (savep = p; isdigit(*p); ++p); if (!isspace(*p)) { - error_msg_and_die("hexdump: bad format {%s}", fmt); + bb_error_msg_and_die("bad format {%s}", fmt); } tfu->bcnt = atoi(savep); - /* skip trailing white space */ - for (++p; isspace(*p); ++p); + /* bb_dump_skip trailing white space */ + p = bb_skip_whitespace(++p); } /* format */ if (*p != '"') { - error_msg_and_die("hexdump: bad format {%s}", fmt); + bb_error_msg_and_die("bad format {%s}", fmt); } for (savep = ++p; *p != '"';) { if (*p++ == 0) { - error_msg_and_die("hexdump: bad format {%s}", fmt); + bb_error_msg_and_die("bad format {%s}", fmt); } } - if (!(tfu->fmt = malloc(p - savep + 1))) { - perror_msg_and_die("hexdump"); - } + tfu->fmt = xmalloc(p - savep + 1); strncpy(tfu->fmt, savep, p - savep); tfu->fmt[p - savep] = '\0'; /* escape(tfu->fmt); */ @@ -841,33 +749,16 @@ void add(char *fmt) break; } if (*p1 == '\\') { - switch (*++p1) { - case 'a': - /* *p2 = '\a'; */ - *p2 = '\007'; - break; - case 'b': - *p2 = '\b'; - break; - case 'f': - *p2 = '\f'; - break; - case 'n': - *p2 = '\n'; - break; - case 'r': - *p2 = '\r'; - break; - case 't': - *p2 = '\t'; - break; - case 'v': - *p2 = '\v'; - break; - default: - *p2 = *p1; - break; - } + const char *cs = conv_str + 4; + ++p1; + *p2 = *p1; + do { + if (*p1 == cs[2]) { + *p2 = cs[0]; + break; + } + cs += 4; + } while (*cs); } } diff --git a/libbb/error_msg.c b/libbb/error_msg.c index 58308b6..5456dd3 100644 --- a/libbb/error_msg.c +++ b/libbb/error_msg.c @@ -25,12 +25,12 @@ #include <stdlib.h> #include "libbb.h" -extern void error_msg(const char *s, ...) +extern void bb_error_msg(const char *s, ...) { va_list p; va_start(p, s); - verror_msg(s, p); + bb_verror_msg(s, p); va_end(p); putc('\n', stderr); } diff --git a/libbb/error_msg_and_die.c b/libbb/error_msg_and_die.c index 67a79c3..7e73937 100644 --- a/libbb/error_msg_and_die.c +++ b/libbb/error_msg_and_die.c @@ -25,15 +25,15 @@ #include <stdlib.h> #include "libbb.h" -extern void error_msg_and_die(const char *s, ...) +extern void bb_error_msg_and_die(const char *s, ...) { va_list p; va_start(p, s); - verror_msg(s, p); + bb_verror_msg(s, p); va_end(p); putc('\n', stderr); - exit(EXIT_FAILURE); + exit(bb_default_error_retval); } diff --git a/libbb/fclose_nonstdin.c b/libbb/fclose_nonstdin.c new file mode 100644 index 0000000..97e303e --- /dev/null +++ b/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/libbb/fflush_stdout_and_exit.c b/libbb/fflush_stdout_and_exit.c new file mode 100644 index 0000000..cbba042 --- /dev/null +++ b/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/libbb/find_root_device.c b/libbb/find_root_device.c index 0a3f1bc..763ac75 100644 --- a/libbb/find_root_device.c +++ b/libbb/find_root_device.c @@ -38,14 +38,14 @@ extern char *find_real_root_device_name(const char* name) dev_t dev; if (stat("/", &rootStat) != 0) - perror_msg("could not stat '/'"); + bb_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'"); + bb_perror_msg("could not open '/dev'"); else { while((entry = readdir(dir)) != NULL) { @@ -69,7 +69,7 @@ extern char *find_real_root_device_name(const char* name) } } if(fileName==NULL) - fileName=xstrdup("/dev/root"); + fileName=bb_xstrdup("/dev/root"); return fileName; } diff --git a/libbb/full_read.c b/libbb/full_read.c index ccf26fc..e75f967 100644 --- a/libbb/full_read.c +++ b/libbb/full_read.c @@ -23,17 +23,16 @@ #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) +ssize_t bb_full_read(int fd, void *buf, size_t len) { - int cc; - int total; + ssize_t cc; + ssize_t total; total = 0; @@ -41,12 +40,12 @@ int full_read(int fd, char *buf, int len) cc = read(fd, buf, len); if (cc < 0) - return -1; + return cc; /* read() returns -1 on failure. */ if (cc == 0) break; - buf += cc; + buf = ((char *)buf) + cc; total += cc; len -= cc; } diff --git a/libbb/full_write.c b/libbb/full_write.c index a2c07fb..1106a53 100644 --- a/libbb/full_write.c +++ b/libbb/full_write.c @@ -28,10 +28,10 @@ * 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) +ssize_t bb_full_write(int fd, const void *buf, size_t len) { - int cc; - int total; + ssize_t cc; + ssize_t total; total = 0; @@ -39,10 +39,10 @@ int full_write(int fd, const char *buf, int len) cc = write(fd, buf, len); if (cc < 0) - return -1; + return cc; /* write() returns -1 on failure. */ - buf += cc; total += cc; + buf = ((const char *)buf) + cc; len -= cc; } diff --git a/libbb/get_console.c b/libbb/get_console.c index 794888f..562b577 100644 --- a/libbb/get_console.c +++ b/libbb/get_console.c @@ -106,7 +106,7 @@ int get_console_fd(void) if (is_a_console(fd)) return fd; - error_msg("Couldn't get a file descriptor referring to the console"); + bb_error_msg("Couldn't get a file descriptor referring to the console"); return -1; /* total failure */ } diff --git a/libbb/get_last_path_component.c b/libbb/get_last_path_component.c index 6af726c..497d6ae 100644 --- a/libbb/get_last_path_component.c +++ b/libbb/get_last_path_component.c @@ -1,8 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * get_last_path_component implementation for busybox + * bb_get_last_path_component implementation for busybox * - * Copyright (C) 2001 Manuel Novoa III <mjn3@opensource.lineo.com> + * 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 @@ -24,7 +24,7 @@ /* WARNING!!! Doing so will break basename applet at least! */ #define EMULATE_BASENAME 0 -char *get_last_path_component(char *path) +char *bb_get_last_path_component(char *path) { #if EMULATE_BASENAME static const char null_or_empty[] = "."; diff --git a/libbb/get_line_from_file.c b/libbb/get_line_from_file.c index 5e70621..5af8989 100644 --- a/libbb/get_line_from_file.c +++ b/libbb/get_line_from_file.c @@ -21,41 +21,57 @@ */ #include <stdio.h> +#include <stdlib.h> #include "libbb.h" - - -/* get_line_from_file() - This function reads an entire line from a text file +/* 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) + * free'ed by the caller. If 'c' is nonzero, the trailing '\n' (if any) + * is removed. In event of a read error or EOF, NULL is returned. */ + +static char *private_get_line_from_file(FILE *file, int c) { - static const int GROWBY = 80; /* how large we will grow strings by */ +#define 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; + while ((ch = getc(file)) != EOF) { /* grow the line buffer as necessary */ - while (idx > linebufsz-2) + if (idx > linebufsz-2) { linebuf = xrealloc(linebuf, linebufsz += GROWBY); + } linebuf[idx++] = (char)ch; - if (ch == '\n' || ch == '\0') + if (ch == '\n' || ch == '\0') { + if (c) { + --idx; + } break; + } } - if (idx == 0) - return NULL; - - linebuf[idx] = 0; + if (linebuf) { + if (ferror(file)) { + free(linebuf); + return NULL; + } + linebuf[idx] = 0; + } return linebuf; } +extern char *bb_get_line_from_file(FILE *file) +{ + return private_get_line_from_file(file, 0); +} + +extern char *bb_get_chomped_line_from_file(FILE *file) +{ + return private_get_line_from_file(file, 1); +} + /* END CODE */ /* diff --git a/libbb/time_string.c b/libbb/getopt_ulflags.c index d103a02..91de392 100644 --- a/libbb/time_string.c +++ b/libbb/getopt_ulflags.c @@ -1,8 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Utility routines. + * getopt_ulflags implementation for busybox * - * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org> + * 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 @@ -17,46 +17,25 @@ * 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 <getopt.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) +unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts) { - 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'; + unsigned long flags = 0; + const char *s; + int c; + + while ((c = getopt(argc, argv, applet_opts)) > 0) { + if (!(s = strchr(applet_opts, c))) { + bb_show_usage(); + } + flags |= (1 << (s-applet_opts)); } - return buf; + return flags; } - - -/* END CODE */ -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/libbb/herror_msg.c b/libbb/herror_msg.c index 1081a56..4fe921b 100644 --- a/libbb/herror_msg.c +++ b/libbb/herror_msg.c @@ -24,12 +24,12 @@ #include "libbb.h" -extern void herror_msg(const char *s, ...) +extern void bb_herror_msg(const char *s, ...) { va_list p; va_start(p, s); - vherror_msg(s, p); + bb_vherror_msg(s, p); va_end(p); } diff --git a/libbb/herror_msg_and_die.c b/libbb/herror_msg_and_die.c index a47c7ff..33a8c3e 100644 --- a/libbb/herror_msg_and_die.c +++ b/libbb/herror_msg_and_die.c @@ -24,14 +24,14 @@ #include "libbb.h" -extern void herror_msg_and_die(const char *s, ...) +extern void bb_herror_msg_and_die(const char *s, ...) { va_list p; va_start(p, s); - vherror_msg(s, p); + bb_vherror_msg(s, p); va_end(p); - exit(EXIT_FAILURE); + exit(bb_default_error_retval); } diff --git a/libbb/inet_common.c b/libbb/inet_common.c index 16dd1db..5e2343b 100644 --- a/libbb/inet_common.c +++ b/libbb/inet_common.c @@ -4,7 +4,7 @@ * * Heavily modified by Manuel Novoa III Mar 12, 2001 * - * Version: $Id: inet_common.c,v 1.5 2002/11/28 09:52:23 bug1 Exp $ + * Version: $Id: inet_common.c,v 1.6 2003/03/19 09:12:07 mjn3 Exp $ * */ @@ -44,7 +44,7 @@ int INET_resolve(const char *name, struct sockaddr_in *s_in, int hostfirst) /* If we expect this to be a hostname, try hostname database first */ #ifdef DEBUG if (hostfirst) { - error_msg("gethostbyname (%s)", name); + bb_error_msg("gethostbyname (%s)", name); } #endif if (hostfirst && (hp = gethostbyname(name)) != (struct hostent *) NULL) { @@ -54,7 +54,7 @@ int INET_resolve(const char *name, struct sockaddr_in *s_in, int hostfirst) } /* Try the NETWORKS database to see if this is a known network. */ #ifdef DEBUG - error_msg("getnetbyname (%s)", name); + bb_error_msg("getnetbyname (%s)", name); #endif if ((np = getnetbyname(name)) != (struct netent *) NULL) { s_in->sin_addr.s_addr = htonl(np->n_net); @@ -71,7 +71,7 @@ int INET_resolve(const char *name, struct sockaddr_in *s_in, int hostfirst) #endif #ifdef DEBUG - error_msg("gethostbyname (%s)", name); + bb_error_msg("gethostbyname (%s)", name); #endif if ((hp = gethostbyname(name)) == (struct hostent *) NULL) { errno = h_errno; @@ -109,7 +109,7 @@ int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, /* Grmpf. -FvK */ if (s_in->sin_family != AF_INET) { #ifdef DEBUG - error_msg("rresolve: unsupport address family %d !", + bb_error_msg("rresolve: unsupport address family %d !", s_in->sin_family); #endif errno = EAFNOSUPPORT; @@ -117,7 +117,7 @@ int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, } ad = (unsigned long) s_in->sin_addr.s_addr; #ifdef DEBUG - error_msg("rresolve: %08lx, mask %08x, num %08x", ad, netmask, numeric); + bb_error_msg("rresolve: %08lx, mask %08x, num %08x", ad, netmask, numeric); #endif if (ad == INADDR_ANY) { if ((numeric & 0x0FFF) == 0) { @@ -143,7 +143,7 @@ int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, if (pn->addr.sin_addr.s_addr == ad && pn->host == host) { safe_strncpy(name, pn->name, len); #ifdef DEBUG - error_msg("rresolve: found %s %08lx in cache", + bb_error_msg("rresolve: found %s %08lx in cache", (host ? "host" : "net"), ad); #endif return (0); @@ -156,7 +156,7 @@ int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, ent = NULL; if (host) { #ifdef DEBUG - error_msg("gethostbyaddr (%08lx)", ad); + bb_error_msg("gethostbyaddr (%08lx)", ad); #endif ent = gethostbyaddr((char *) &ad, 4, AF_INET); if (ent != NULL) { @@ -164,7 +164,7 @@ int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, } } else { #ifdef DEBUG - error_msg("getnetbyaddr (%08lx)", host_ad); + bb_error_msg("getnetbyaddr (%08lx)", host_ad); #endif np = getnetbyaddr(host_ad, AF_INET); if (np != NULL) { @@ -178,7 +178,7 @@ int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, pn->addr = *s_in; pn->next = INET_nn; pn->host = host; - pn->name = xstrdup(name); + pn->name = bb_xstrdup(name); INET_nn = pn; return (0); @@ -194,7 +194,7 @@ int INET6_resolve(char *name, struct sockaddr_in6 *sin6) memset(&req, '\0', sizeof req); req.ai_family = AF_INET6; if ((s = getaddrinfo(name, NULL, &req, &ai))) { - error_msg("getaddrinfo: %s: %d", name, s); + bb_error_msg("getaddrinfo: %s: %d", name, s); return -1; } memcpy(sin6, ai->ai_addr, sizeof(struct sockaddr_in6)); @@ -219,7 +219,7 @@ int INET6_rresolve(char *name, size_t len, struct sockaddr_in6 *sin6, /* Grmpf. -FvK */ if (sin6->sin6_family != AF_INET6) { #ifdef DEBUG - error_msg(_("rresolve: unsupport address family %d !\n"), + bb_error_msg(_("rresolve: unsupport address family %d !\n"), sin6->sin6_family); #endif errno = EAFNOSUPPORT; @@ -240,7 +240,7 @@ int INET6_rresolve(char *name, size_t len, struct sockaddr_in6 *sin6, s = getnameinfo((struct sockaddr *) sin6, sizeof(struct sockaddr_in6), name, len, NULL, 0, 0); if (s) { - error_msg("getnameinfo failed"); + bb_error_msg("getnameinfo failed"); return -1; } return (0); diff --git a/libbb/interface.c b/libbb/interface.c index fb79416..531700f 100644 --- a/libbb/interface.c +++ b/libbb/interface.c @@ -15,7 +15,7 @@ * that either displays or sets the characteristics of * one or more of the system's networking interfaces. * - * Version: $Id: interface.c,v 1.14 2003/02/09 22:40:33 bug1 Exp $ + * Version: $Id: interface.c,v 1.15 2003/03/19 09:12:07 mjn3 Exp $ * * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> * and others. Copyright 1993 MicroWalt Corporation @@ -619,7 +619,7 @@ static int aftrans_opt(const char *arg) if (strcmp(tmp1, paft->alias)) continue; if (strlen(paft->name) + strlen(afname) + 1 >= sizeof(afname)) { - error_msg(_("Too many address family arguments.")); + bb_error_msg(_("Too many address family arguments.")); return (0); } if (paft->flag) @@ -630,7 +630,7 @@ static int aftrans_opt(const char *arg) break; } if (!paft->alias) { - error_msg(_("Unknown address family `%s'."), tmp1); + bb_error_msg(_("Unknown address family `%s'."), tmp1); return (1); } tmp1 = tmp2; @@ -693,7 +693,7 @@ static struct aftype *get_aftype(const char *name) afp++; } if (strchr(name, ',')) - error_msg(_("Please don't supply more than one address family.")); + bb_error_msg(_("Please don't supply more than one address family.")); return (NULL); } #endif /* KEEP_UNUSED */ @@ -888,7 +888,7 @@ static int sockets_open(int family) sfd = af->fd; } if (sfd < 0) { - error_msg(_("No usable address families found.")); + bb_error_msg(_("No usable address families found.")); } return sfd; } @@ -960,7 +960,7 @@ static int if_readconf(void) (as of 2.1.128) */ skfd2 = get_socket_for_af(AF_INET); if (skfd2 < 0) { - perror_msg(("warning: no inet socket available")); + bb_perror_msg(("warning: no inet socket available")); /* Try to soldier on with whatever socket we can get hold of. */ skfd2 = sockets_open(0); if (skfd2 < 0) @@ -1106,7 +1106,7 @@ static int if_readlist_proc(char *target) fh = fopen(_PATH_PROCNET_DEV, "r"); if (!fh) { - perror_msg(_("Warning: cannot open %s. Limited output."), _PATH_PROCNET_DEV); + bb_perror_msg(_("Warning: cannot open %s. Limited output."), _PATH_PROCNET_DEV); return if_readconf(); } fgets(buf, sizeof buf, fh); /* eat line */ @@ -1366,7 +1366,7 @@ static int do_if_fetch(struct interface *ife) } else { errmsg = strerror(errno); } - error_msg(_("%s: error fetching interface information: %s\n"), + bb_error_msg(_("%s: error fetching interface information: %s\n"), ife->name, errmsg); return -1; } @@ -1441,7 +1441,7 @@ static int in_ether(char *bufp, struct sockaddr *sap) val = c - 'A' + 10; else { #ifdef DEBUG - error_msg(_("in_ether(%s): invalid ether address!\n"), orig); + bb_error_msg(_("in_ether(%s): invalid ether address!\n"), orig); #endif errno = EINVAL; return (-1); @@ -1458,7 +1458,7 @@ static int in_ether(char *bufp, struct sockaddr *sap) val >>= 4; else { #ifdef DEBUG - error_msg(_("in_ether(%s): invalid ether address!"), orig); + bb_error_msg(_("in_ether(%s): invalid ether address!"), orig); #endif errno = EINVAL; return (-1); @@ -1472,7 +1472,7 @@ static int in_ether(char *bufp, struct sockaddr *sap) if (*bufp == ':') { #ifdef DEBUG if (i == ETH_ALEN) { - error_msg(_("in_ether(%s): trailing : ignored!"), orig); + bb_error_msg(_("in_ether(%s): trailing : ignored!"), orig); } #endif bufp++; @@ -1482,11 +1482,11 @@ static int in_ether(char *bufp, struct sockaddr *sap) #ifdef DEBUG /* That's it. Any trailing junk? */ if ((i == ETH_ALEN) && (*bufp != '\0')) { - error_msg(_("in_ether(%s): trailing junk!"), orig); + bb_error_msg(_("in_ether(%s): trailing junk!"), orig); errno = EINVAL; return (-1); } - error_msg("in_ether(%s): %s", orig, pr_ether(sap->sa_data)); + bb_error_msg("in_ether(%s): %s", orig, pr_ether(sap->sa_data)); #endif return (0); @@ -1511,7 +1511,7 @@ static struct hwtype ether_hwtype = { /* Start the PPP encapsulation on the file descriptor. */ static int do_ppp(int fd) { - error_msg(_("You cannot start PPP with this program.")); + bb_error_msg(_("You cannot start PPP with this program.")); return -1; } #endif /* KEEP_UNUSED */ @@ -2052,7 +2052,7 @@ int display_interfaces(char *ifname) /* Create a channel to the NET kernel. */ if ((skfd = sockets_open(0)) < 0) { - perror_msg_and_die("socket"); + bb_perror_msg_and_die("socket"); } /* Do we have to show the current setup? */ diff --git a/libbb/kernel_version.c b/libbb/kernel_version.c index 694af8e..14b1636 100644 --- a/libbb/kernel_version.c +++ b/libbb/kernel_version.c @@ -37,7 +37,7 @@ extern int get_kernel_revision(void) int i, r; if (uname(&name) == -1) { - perror_msg("cannot get system information"); + bb_perror_msg("cannot get system information"); return (0); } diff --git a/libbb/loop.c b/libbb/loop.c index 7e58b2f..29128ab 100644 --- a/libbb/loop.c +++ b/libbb/loop.c @@ -33,11 +33,11 @@ extern int del_loop(const char *device) int fd; if ((fd = open(device, O_RDONLY)) < 0) { - perror_msg("%s", device); + bb_perror_msg("%s", device); return (FALSE); } if (ioctl(fd, LOOP_CLR_FD, 0) < 0) { - perror_msg("ioctl: LOOP_CLR_FD"); + bb_perror_msg("ioctl: LOOP_CLR_FD"); return (FALSE); } close(fd); @@ -53,12 +53,12 @@ extern int set_loop(const char *device, const char *file, int offset, 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); + bb_perror_msg("%s", file); return 1; } if ((fd = open(device, mode)) < 0) { close(ffd); - perror_msg("%s", device); + bb_perror_msg("%s", device); return 1; } *loopro = (mode == O_RDONLY); @@ -70,14 +70,14 @@ extern int set_loop(const char *device, const char *file, int offset, loopinfo.lo_encrypt_key_size = 0; if (ioctl(fd, LOOP_SET_FD, ffd) < 0) { - perror_msg("ioctl: LOOP_SET_FD"); + bb_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"); + bb_perror_msg("ioctl: LOOP_SET_STATUS"); close(fd); close(ffd); return 1; diff --git a/libbb/make_directory.c b/libbb/make_directory.c index 65be397..e3d2c52 100644 --- a/libbb/make_directory.c +++ b/libbb/make_directory.c @@ -1,12 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini make_directory implementation for busybox + * parse_mode implementation for busybox * - * Copyright (C) 2001 Matt Kraai. - * - * Rewriten in 2002 - * Copyright (C) 2002 Glenn McGrath - * Copyright (C) 2002 Vladimir N. Oleynik + * 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 @@ -24,57 +20,87 @@ * */ +/* Mar 5, 2003 Manuel Novoa III + * + * This is the main work function for the 'mkdir' applet. As such, it + * strives to be SUSv3 compliant in it's behaviour when recursively + * making missing parent dirs, and in it's mode setting of the final + * directory 'path'. + * + * To recursively build all missing intermediate directories, make + * sure that (flags & FILEUTILS_RECUR) is non-zero. Newly created + * intermediate directories will have at least u+wx perms. + * + * To set specific permisions on 'path', pass the appropriate 'mode' + * val. Otherwise, pass -1 to get default permisions. + */ + #include <errno.h> -#include <fcntl.h> -#include <string.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) +int bb_make_directory (char *path, long mode, int flags) { - int ret; - - if (flags == FILEUTILS_RECUR) { - char *pp = strrchr(path, '/'); - if ((pp) && (pp != path)) { - *pp = '\0'; - make_directory(path, -1, flags); - *pp = '/'; - } - } + mode_t mask; + const char *fail_msg; + char *s = path; + char c; - if (mode == -1) { - struct stat statbuf; - char *pp = strrchr(path, '/'); + mask = umask(0); + umask(mask & ~0300); - statbuf.st_mode = 0777; + do { + c = 0; - /* stat the directory */ - if ((pp) && (pp != path)) { - *pp = '\0'; - stat(path, &statbuf); - *pp = '/'; + if (flags & FILEUTILS_RECUR) { /* Get the parent. */ + /* Bypass leading non-'/'s and then subsequent '/'s. */ + while (*s) { + if (*s == '/') { + do { + ++s; + } while (*s == '/'); + c = *s; /* Save the current char */ + *s = 0; /* and replace it with nul. */ + break; + } + ++s; + } } - mode = statbuf.st_mode; - } + if (mkdir(path, 0777) < 0) { + /* If we failed for any other reason than the directory + * already exists, output a diagnostic and return -1.*/ + if (errno != EEXIST) { + fail_msg = "create"; + umask(mask); + break; + } + /* Since the directory exists, don't attempt to change + * permissions if it was the full target. Note that + * this is not an error conditon. */ + if (!c) { + umask(mask); + return 0; + } + } - ret = mkdir(path, mode); - if (ret == -1) { - if ((flags == FILEUTILS_RECUR) && (errno == EEXIST)) { - ret = 0; - } else { - perror_msg_and_die("Cannot create directory '%s'", path); + if (!c) { + /* Done. If necessary, updated perms on the newly + * created directory. Failure to update here _is_ + * an error.*/ + umask(mask); + if ((mode != -1) && (chmod(path, mode) < 0)){ + fail_msg = "set permissions of"; + break; + } + return 0; } - } - return(ret); + /* Remove any inserted nul from the path (recursive mode). */ + *s = c; + + } while (1); + + bb_perror_msg ("Cannot %s directory `%s'", fail_msg, path); + return -1; } diff --git a/libbb/messages.c b/libbb/messages.c index cc7e214..e5ffbf7 100644 --- a/libbb/messages.c +++ b/libbb/messages.c @@ -23,82 +23,71 @@ #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"; + const char * const bb_msg_full_version = BB_BANNER " multi-call binary"; #endif #ifdef L_memory_exhausted - const char * const memory_exhausted = "memory exhausted"; + const char * const bb_msg_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"; + const char * const bb_msg_invalid_date = "invalid date `%s'"; #endif #ifdef L_io_error - const char * const io_error = "%s: input/output error -- %m"; -#endif -#ifdef L_dash_dash_help - const char * const dash_dash_help = "--help"; + const char * const bb_msg_io_error = "%s: input/output error -- %m"; #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"; + const char * const bb_msg_write_error = "Write Error"; #endif #ifdef L_name_longer_than_foo - const char * const name_longer_than_foo = "Names longer than %d chars not supported."; + const char * const bb_msg_name_longer_than_foo = "Names longer than %d chars not supported."; #endif #ifdef L_unknown - const char * const unknown = "(unknown)"; + const char * const bb_msg_unknown = "(unknown)"; #endif - #ifdef L_can_not_create_raw_socket - const char * const can_not_create_raw_socket = "can`t create raw socket"; + const char * const bb_msg_can_not_create_raw_socket = "can`t create raw socket"; +#endif +#ifdef L_perm_denied_are_you_root + const char * const bb_msg_perm_denied_are_you_root = "permission denied. (are you root?)"; +#endif +#ifdef L_msg_standard_input + const char * const bb_msg_standard_input = "standard input"; +#endif +#ifdef L_msg_standard_output + const char * const bb_msg_standard_output = "standard output"; #endif #ifdef L_passwd_file #define PASSWD_FILE "/etc/passwd" -const char * const passwd_file = PASSWD_FILE; +const char * const bb_path_passwd_file = PASSWD_FILE; #endif #ifdef L_shadow_file #define SHADOW_FILE "/etc/shadow" -const char * const shadow_file = SHADOW_FILE; +const char * const bb_path_shadow_file = SHADOW_FILE; #endif #ifdef L_group_file #define GROUP_FILE "/etc/group" -const char * const group_file = GROUP_FILE; +const char * const bb_path_group_file = GROUP_FILE; #endif #ifdef L_gshadow_file #define GSHADOW_FILE "/etc/gshadow" -const char * const gshadow_file = GSHADOW_FILE; +const char * const bb_path_gshadow_file = GSHADOW_FILE; #endif #ifdef L_nologin_file #define NOLOGIN_FILE "/etc/nologin" -const char * const nologin_file = NOLOGIN_FILE; +const char * const bb_path_nologin_file = NOLOGIN_FILE; #endif #ifdef L_securetty_file #define SECURETTY_FILE "/etc/securetty" -const char * const securetty_file = SECURETTY_FILE; +const char * const bb_path_securetty_file = SECURETTY_FILE; #endif #ifdef L_motd_file #define MOTD_FILE "/etc/motd" -const char * const motd_file = MOTD_FILE; +const char * const bb_path_motd_file = MOTD_FILE; #endif diff --git a/libbb/mode_string.c b/libbb/mode_string.c index 12dc179..8d4d736 100644 --- a/libbb/mode_string.c +++ b/libbb/mode_string.c @@ -1,78 +1,134 @@ /* vi: set sw=4 ts=4: */ /* - * Utility routines. + * mode_string implementation for busybox * - * Copyright (C) many different people. If you wrote this, please - * acknowledge your work. + * 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 + * 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 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * */ -#include <stdio.h> -#include "libbb.h" +#include <assert.h> +#include <sys/stat.h> +#if ( S_ISUID != 04000 ) || ( S_ISGID != 02000 ) || ( S_ISVTX != 01000 ) \ + || ( S_IRUSR != 00400 ) || ( S_IWUSR != 00200 ) || ( S_IXUSR != 00100 ) \ + || ( S_IRGRP != 00040 ) || ( S_IWGRP != 00020 ) || ( S_IXGRP != 00010 ) \ + || ( S_IROTH != 00004 ) || ( S_IWOTH != 00002 ) || ( S_IXOTH != 00001 ) +#error permission bitflag value assumption(s) violated! +#endif +#if ( S_IFSOCK!= 0140000 ) || ( S_IFLNK != 0120000 ) \ + || ( S_IFREG != 0100000 ) || ( S_IFBLK != 0060000 ) \ + || ( S_IFDIR != 0040000 ) || ( S_IFCHR != 0020000 ) \ + || ( S_IFIFO != 0010000 ) +#warning mode type bitflag value assumption(s) violated! falling back to larger version -#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f) -#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)]) +#if (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX) == 07777 +#undef mode_t +#define mode_t unsigned short +#endif -/* 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 +static const mode_t mode_flags[] = { + S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID, + S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID, + S_IROTH, S_IWOTH, S_IXOTH, 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 -}; +/* The static const char arrays below are duplicated for the two cases + * because moving them ahead of the mode_flags declaration cause a text + * size increase with the gcc version I'm using. */ -static const char MODE1[] = "rwxrwxrwx"; -static const char MODE0[] = "---------"; -static const char SMODE1[] = "..s..s..t"; -static const char SMODE0[] = "..S..S..T"; +/* The previous version used "0pcCd?bB-?l?s???". However, the '0', 'C', + * and 'B' types don't appear to be available on linux. So I removed them. */ +static const char type_chars[16] = "?pc?d?b?-?l?s???"; +/* 0123456789abcdef */ +static const char mode_chars[7] = "rwxSTst"; -/* - * 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) +const char *bb_mode_string(int mode) { static char buf[12]; + char *p = buf; + + int i, j, k; - int i; + *p = type_chars[ (mode >> 12) & 0xf ]; + i = 0; + do { + j = k = 0; + do { + *++p = '-'; + if (mode & mode_flags[i+j]) { + *p = mode_chars[j]; + k = j; + } + } while (++j < 3); + if (mode & mode_flags[i+j]) { + *p = mode_chars[3 + (k & 2) + ((i&8) >> 3)]; + } + i += 4; + } while (i < 12); + + /* Note: We don't bother with nul termination because bss initialization + * should have taken care of that for us. If the user scribbled in buf + * memory, they deserve whatever happens. But we'll at least assert. */ + assert(buf[10] == 0); - 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: -*/ +#else + +/* The previous version used "0pcCd?bB-?l?s???". However, the '0', 'C', + * and 'B' types don't appear to be available on linux. So I removed them. */ +static const char type_chars[16] = "?pc?d?b?-?l?s???"; +/* 0123456789abcdef */ +static const char mode_chars[7] = "rwxSTst"; + +const char *bb_mode_string(int mode) +{ + static char buf[12]; + char *p = buf; + + int i, j, k, m; + + *p = type_chars[ (mode >> 12) & 0xf ]; + i = 0; + m = 0400; + do { + j = k = 0; + do { + *++p = '-'; + if (mode & m) { + *p = mode_chars[j]; + k = j; + } + m >>= 1; + } while (++j < 3); + ++i; + if (mode & (010000 >> i)) { + *p = mode_chars[3 + k + (i >> 1)]; + } + } while (i < 3); + + /* Note: We don't bother with nul termination because bss initialization + * should have taken care of that for us. If the user scribbled in buf + * memory, they deserve whatever happens. But we'll at least assert. */ + assert(buf[10] == 0); + + return buf; +} + +#endif diff --git a/libbb/module_syscalls.c b/libbb/module_syscalls.c index 6bfff20..8fe9e52 100644 --- a/libbb/module_syscalls.c +++ b/libbb/module_syscalls.c @@ -51,7 +51,7 @@ _syscall5(int, init_module, void *, first, void *, second, void *, third, #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) { - error_msg("\n\nTo make this application work, you will need to recompile\n" + bb_error_msg("\n\nTo make this application work, you will need to recompile\n" "with a kernel supporting the query_module system call. -Erik\n"); errno=ENOSYS; return -1; diff --git a/libbb/mtab.c b/libbb/mtab.c index c521b1e..54905c7 100644 --- a/libbb/mtab.c +++ b/libbb/mtab.c @@ -27,21 +27,20 @@ #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"); + FILE *mountTable = setmntent(bb_path_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); + bb_perror_msg(bb_path_mtab_file); return; } @@ -55,7 +54,7 @@ void erase_mtab(const char *name) count++; } endmntent(mountTable); - if ((mountTable = setmntent(mtab_file, "w"))) { + if ((mountTable = setmntent(bb_path_mtab_file, "w"))) { int i; for (i = 0; i < count; i++) { @@ -69,17 +68,17 @@ void erase_mtab(const char *name) } endmntent(mountTable); } else if (errno != EROFS) - perror_msg("%s", mtab_file); + bb_perror_msg(bb_path_mtab_file); } void write_mtab(char *blockDevice, char *directory, char *filesystemType, long flags, char *string_flags) { - FILE *mountTable = setmntent(mtab_file, "a+"); + FILE *mountTable = setmntent(bb_path_mtab_file, "a+"); struct mntent m; if (mountTable == 0) { - perror_msg("%s", mtab_file); + bb_perror_msg(bb_path_mtab_file); return; } if (mountTable) { diff --git a/libbb/mtab_file.c b/libbb/mtab_file.c index 2124e01..898e2fa 100644 --- a/libbb/mtab_file.c +++ b/libbb/mtab_file.c @@ -26,9 +26,9 @@ /* Busybox mount uses either /proc/mounts or /etc/mtab to * get the list of currently mounted filesystems */ #if defined CONFIG_FEATURE_MTAB_SUPPORT -const char mtab_file[] = CONFIG_FEATURE_MTAB_FILENAME; +const char bb_path_mtab_file[] = CONFIG_FEATURE_MTAB_FILENAME; #else -const char mtab_file[] = "/proc/mounts"; +const char bb_path_mtab_file[] = "/proc/mounts"; #endif diff --git a/libbb/my_getgrnam.c b/libbb/my_getgrnam.c index f80d3f8..eb5b581 100644 --- a/libbb/my_getgrnam.c +++ b/libbb/my_getgrnam.c @@ -33,7 +33,7 @@ long my_getgrnam(const char *name) mygroup = getgrnam(name); if (mygroup==NULL) - error_msg_and_die("unknown group name: %s", name); + bb_error_msg_and_die("unknown group name: %s", name); return (mygroup->gr_gid); } diff --git a/libbb/my_getpwnam.c b/libbb/my_getpwnam.c index 04951a4..ada2ffb 100644 --- a/libbb/my_getpwnam.c +++ b/libbb/my_getpwnam.c @@ -33,7 +33,7 @@ long my_getpwnam(const char *name) myuser = getpwnam(name); if (myuser==NULL) - error_msg_and_die("unknown user name: %s", name); + bb_error_msg_and_die("unknown user name: %s", name); return myuser->pw_uid; } diff --git a/libbb/my_getpwnamegid.c b/libbb/my_getpwnamegid.c index 07e02c1..06071c9 100644 --- a/libbb/my_getpwnamegid.c +++ b/libbb/my_getpwnamegid.c @@ -35,11 +35,11 @@ long my_getpwnamegid(const char *name) myuser=getpwnam(name); if (myuser==NULL) - error_msg_and_die("unknown user name: %s", name); + bb_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); + bb_error_msg_and_die("unknown gid %ld", (long)myuser->pw_gid); return mygroup->gr_gid; } diff --git a/libbb/obscure.c b/libbb/obscure.c index 588ef5a..1a99b7c 100644 --- a/libbb/obscure.c +++ b/libbb/obscure.c @@ -143,7 +143,7 @@ password_check(const char *old, const char *newval, const struct passwd *pwdp) return "too simple"; msg = NULL; - newmono = str_lower(xstrdup(newval)); + newmono = str_lower(bb_xstrdup(newval)); lenwrap = strlen(old) * 2 + 1; wrapped = (char *) xmalloc(lenwrap); str_lower(strcpy(wrapped, old)); @@ -208,8 +208,8 @@ obscure_msg(const char *old, const char *newval, const struct passwd *pwdp) if (oldlen <= maxlen && newlen <= maxlen) return NULL; - new1 = (char *) xstrdup(newval); - old1 = (char *) xstrdup(old); + new1 = (char *) bb_xstrdup(newval); + old1 = (char *) bb_xstrdup(old); if (newlen > maxlen) new1[maxlen] = '\0'; if (oldlen > maxlen) diff --git a/libbb/parse_mode.c b/libbb/parse_mode.c index ba34ea9..49573df 100644 --- a/libbb/parse_mode.c +++ b/libbb/parse_mode.c @@ -1,134 +1,177 @@ /* vi: set sw=4 ts=4: */ /* - * Utility routines. + * parse_mode implementation for busybox * - * Copyright (C) many different people. If you wrote this, please - * acknowledge your work. + * 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 + * 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 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * */ -#include <stdio.h> +/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */ + #include <stdlib.h> +#include <assert.h> +#include <sys/stat.h> #include "libbb.h" +#define FILEMODEBITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) -/* 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) +extern int bb_parse_mode(const char *s, mode_t *current_mode) { - static const mode_t group_set[] = { + static const mode_t who_mask[] = { + S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */ 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 */ + S_IRWXO /* o */ }; - static const mode_t mode_set[] = { + static const mode_t perm_mask[] = { S_IRUSR | S_IRGRP | S_IROTH, /* r */ S_IWUSR | S_IWGRP | S_IWOTH, /* w */ S_IXUSR | S_IXGRP | S_IXOTH, /* x */ + S_IXUSR | S_IXGRP | S_IXOTH, /* X -- special -- see below */ S_ISUID | S_ISGID, /* s */ S_ISVTX /* t */ }; - static const char group_chars[] = "ugoa"; - static const char mode_chars[] = "rwxst"; + static const char who_chars[] = "augo"; + static const char perm_chars[] = "rwxXst"; 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; + mode_t wholist; + mode_t permlist; + mode_t mask; + mode_t new_mode; + char op; + + assert(s); + + if (((unsigned int)(*s - '0')) < 8) { + unsigned long tmp; + char *e; - if (s==NULL) { - return (FALSE); + tmp = strtol(s, &e, 8); + if (*e || (tmp > 0xffffU)) { /* Check range and trailing chars. */ + return 0; + } + *current_mode = tmp; + return 1; } - do { - mode = 0; - groups = 0; - NEXT_GROUP: - if ((c = *s++) == '\0') { - return -1; + mask = umask(0); + umask(mask); + + new_mode = *current_mode; + + /* Note: We allow empty clauses, and hence empty modes. + * We treat an empty mode as no change to perms. */ + + while (*s) { /* Process clauses. */ + + if (*s == ',') { /* We allow empty clauses. */ + ++s; + continue; } - for (p=group_chars ; *p ; p++) { - if (*p == c) { - groups |= group_set[(int)(p-group_chars)]; - goto NEXT_GROUP; + + /* Get a wholist. */ + wholist = 0; + + WHO_LIST: + p = who_chars; + do { + if (*p == *s) { + wholist |= who_mask[(int)(p-who_chars)]; + if (!*++s) { + return 0; + } + goto WHO_LIST; } - } - 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; + } while (*++p); + + do { /* Process action list. */ + if ((*s != '+') && (*s != '-')) { + if (*s != '=') { + return 0; } - break; - default: - if ((c < '0') || (c > '7') || (mode | groups)) { - return (FALSE); - } else { - *theMode = strtol(--s, NULL, 8); - return (TRUE); + /* Since op is '=', clear all bits corresponding to the + * wholist, of all file bits if wholist is empty. */ + permlist = ~FILEMODEBITS; + if (wholist) { + permlist = ~wholist; } - } + new_mode &= permlist; + } + op = *s++; + + /* Check for permcopy. */ + p = who_chars + 1; /* Skip 'a' entry. */ + do { + if (*p == *s) { + int i = 0; + permlist = who_mask[(int)(p-who_chars)] + & (S_IRWXU | S_IRWXG | S_IRWXO) + & new_mode; + do { + if (permlist & perm_mask[i]) { + permlist |= perm_mask[i]; + } + } while (++i < 3); + ++s; + goto GOT_ACTION; + } + } while (*++p); - 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; + /* It was not a permcopy, so get a permlist. */ + permlist = 0; + + PERM_LIST: + p = perm_chars; + do { + if (*p == *s) { + if ((*p != 'X') + || (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH)) + ) { + permlist |= perm_mask[(int)(p-perm_chars)]; + } + if (!*++s) { + break; + } + goto PERM_LIST; + } + } while (*++p); + + GOT_ACTION: + if (permlist) { /* The permlist was nonempty. */ + mode_t tmp = ~mask; + if (wholist) { + tmp = wholist; + } + permlist &= tmp; + + if (op == '-') { + new_mode &= ~permlist; + } else { + new_mode |= permlist; } } - 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 == ','); + } while (*s && (*s != ',')); + } - *theMode &= andMode; - *theMode |= orMode; + *current_mode = new_mode; - return TRUE; + return 1; } - -/* END CODE */ -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/libbb/parse_number.c b/libbb/parse_number.c index 755a357..92ad6a2 100644 --- a/libbb/parse_number.c +++ b/libbb/parse_number.c @@ -1,70 +1,64 @@ /* vi: set sw=4 ts=4: */ /* - * Utility routines. + * bb_xparse_number implementation for busybox * - * Copyright (C) many different people. If you wrote this, please - * acknowledge your work. + * 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 + * 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 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * */ -#include <stdio.h> -#include <string.h> #include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <errno.h> +#include <assert.h> #include "libbb.h" - -unsigned long parse_number(const char *numstr, - const struct suffix_mult *suffixes) +extern +unsigned long bb_xparse_number(const char *numstr, + const struct suffix_mult *suffixes) { - const struct suffix_mult *sm; - unsigned long int ret; - int len; - char *end; + unsigned long int r; + char *e; + int old_errno; - 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; + /* 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(numstr, &e, 10); + + if ((numstr != e) && !errno) { + errno = old_errno; /* Ok. So restore errno. */ + if (!*e) { + return r; + } + if (suffixes) { + assert(suffixes->suffix); /* No nul suffixes. */ + do { + if (strcmp(suffixes->suffix, e) == 0) { + if (ULONG_MAX / suffixes->mult < r) { /* Overflow! */ + break; + } + return r * suffixes->mult; } - sm++; - - } else - sm = 0; + ++suffixes; + } while (suffixes->suffix); } - if (sm == 0) - error_msg_and_die("invalid number `%s'", numstr); } - return ret; + bb_error_msg_and_die("invalid number `%s'", numstr); } - - -/* END CODE */ -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/libbb/perror_msg.c b/libbb/perror_msg.c index 8c57b0d..f32c1c8 100644 --- a/libbb/perror_msg.c +++ b/libbb/perror_msg.c @@ -25,12 +25,12 @@ #include <stdlib.h> #include "libbb.h" -extern void perror_msg(const char *s, ...) +extern void bb_perror_msg(const char *s, ...) { va_list p; va_start(p, s); - vperror_msg(s, p); + bb_vperror_msg(s, p); va_end(p); } diff --git a/libbb/perror_msg_and_die.c b/libbb/perror_msg_and_die.c index 9004925..57a2113 100644 --- a/libbb/perror_msg_and_die.c +++ b/libbb/perror_msg_and_die.c @@ -25,14 +25,14 @@ #include <stdlib.h> #include "libbb.h" -extern void perror_msg_and_die(const char *s, ...) +extern void bb_perror_msg_and_die(const char *s, ...) { va_list p; va_start(p, s); - vperror_msg(s, p); + bb_vperror_msg(s, p); va_end(p); - exit(EXIT_FAILURE); + exit(bb_default_error_retval); } diff --git a/libbb/perror_nomsg.c b/libbb/perror_nomsg.c new file mode 100644 index 0000000..464cb86 --- /dev/null +++ b/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/libbb/perror_nomsg_and_die.c b/libbb/perror_nomsg_and_die.c new file mode 100644 index 0000000..bab2284 --- /dev/null +++ b/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/libbb/print_file.c b/libbb/print_file.c index cdd60e7..8417c10 100644 --- a/libbb/print_file.c +++ b/libbb/print_file.c @@ -21,39 +21,50 @@ #include <stdio.h> #include <stdlib.h> -#include <sys/stat.h> #include "libbb.h" - -extern void print_file(FILE *file) +extern void bb_xprint_and_close_file(FILE *file) { - fflush(stdout); - if (copyfd(fileno(file), fileno(stdout), 0) == -1) { - exit(EXIT_FAILURE); + bb_xfflush_stdout(); + /* Note: Do not use STDOUT_FILENO here, as this is a lib routine + * and the calling code may have reassigned stdout. */ + if (bb_copyfd(fileno(file), fileno(stdout), 0) == -1) { + /* bb_copyfd outputs any needed messages, so just die. */ + exit(bb_default_error_retval); } + /* Note: Since we're reading, don't bother checking the return value + * of fclose(). The only possible failure is EINTR which + * should already have been taken care of. */ fclose(file); } -extern int print_file_by_name(char *filename) +/* Returns: + * 0 if successful + * -1 if 'filename' does not exist or is a directory + * exits with default error code if an error occurs + */ + +extern int bb_xprint_file_by_name(const char *filename) { + FILE *f; + +#if 0 + /* This check shouldn't be necessary for linux, but is left + * here disabled just in case. */ 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; + if(is_directory(filename, TRUE, &statBuf)) { + bb_error_msg("%s: Is directory", filename); + } else +#endif + if ((f = bb_wfopen(filename, "r")) != NULL) { + bb_xprint_and_close_file(f); + return 0; } - return status; + return -1; } - /* END CODE */ /* Local Variables: diff --git a/libbb/printf.c b/libbb/printf.c new file mode 100644 index 0000000..6862576 --- /dev/null +++ b/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_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_vprintf +extern int bb_vprintf(const char * __restrict format, va_list arg) +{ + return bb_vfprintf(stdout, format, arg); +} +#endif + +#ifdef L_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_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/libbb/process_escape_sequence.c b/libbb/process_escape_sequence.c index 9a16f80..ef2717b 100644 --- a/libbb/process_escape_sequence.c +++ b/libbb/process_escape_sequence.c @@ -2,7 +2,7 @@ /* * Utility routines. * - * Copyright (C) Manuel Nova III <mnovoa3@bellsouth.net> + * Copyright (C) Manuel Novoa III <mjn3@codepoet.org> * and Vladimir Oleynik <dzo@simtreas.ru> * * This program is free software; you can redistribute it and/or modify @@ -26,9 +26,7 @@ #include <limits.h> #include "libbb.h" - - -char process_escape_sequence(const char **ptr) +char bb_process_escape_sequence(const char **ptr) { static const char charmap[] = { 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', 0, @@ -36,40 +34,43 @@ char process_escape_sequence(const char **ptr) const char *p; const char *q; - int num_digits; + unsigned int num_digits; + unsigned int r; 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; + num_digits = 0; + do { + if (((unsigned int)(*q - '0')) <= 7) { + r = n * 8 + (*q - '0'); + if (r <= UCHAR_MAX) { + n = r; + ++q; + if (++num_digits < 3) { + continue; + } + } } - n = n * 8 + (*q++ - '0'); - } + break; + } while (1); if (num_digits == 0) { /* mnemonic escape sequence? */ - for (p=charmap ; *p ; p++) { + p = charmap; + do { if (*p == *q) { q++; break; } - } + } while (*++p); 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: diff --git a/libbb/procps.c b/libbb/procps.c index fcc9c2d..a513f3f 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -34,7 +34,7 @@ extern procps_status_t * procps_scan(int save_user_arg0) if (!dir) { dir = opendir("/proc"); if(!dir) - error_msg_and_die("Can't open /proc"); + bb_error_msg_and_die("Can't open /proc"); } for(;;) { if((entry = readdir(dir)) == NULL) { diff --git a/libbb/read_package_field.c b/libbb/read_package_field.c index 867b198..42628f3 100644 --- a/libbb/read_package_field.c +++ b/libbb/read_package_field.c @@ -102,10 +102,10 @@ int read_package_field(const char *package_buffer, char **field_name, char **fie if (name_length == 0) { *field_name = NULL; } else { - *field_name = xstrndup(&package_buffer[offset_name_start], name_length); + *field_name = bb_xstrndup(&package_buffer[offset_name_start], name_length); } if (value_length > 0) { - *field_value = xstrndup(&package_buffer[offset_value_start], value_length); + *field_value = bb_xstrndup(&package_buffer[offset_value_start], value_length); } else { *field_value = NULL; } diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c index 8f9cc2f..a4a4a7b 100644 --- a/libbb/recursive_action.c +++ b/libbb/recursive_action.c @@ -60,10 +60,10 @@ int recursive_action(const char *fileName, if (status < 0) { #ifdef DEBUG_RECURS_ACTION - error_msg("status=%d followLinks=%d TRUE=%d", + bb_error_msg("status=%d followLinks=%d TRUE=%d", status, followLinks, TRUE); #endif - perror_msg("%s", fileName); + bb_perror_msg("%s", fileName); return FALSE; } @@ -89,14 +89,14 @@ int recursive_action(const char *fileName, if (dirAction != NULL && ! depthFirst) { status = dirAction(fileName, &statbuf, userData); if (! status) { - perror_msg("%s", fileName); + bb_perror_msg("%s", fileName); return FALSE; } else if (status == SKIP) return TRUE; } dir = opendir(fileName); if (!dir) { - perror_msg("%s", fileName); + bb_perror_msg("%s", fileName); return FALSE; } status = TRUE; @@ -117,7 +117,7 @@ int recursive_action(const char *fileName, closedir(dir); if (dirAction != NULL && depthFirst) { if (! dirAction(fileName, &statbuf, userData)) { - perror_msg("%s", fileName); + bb_perror_msg("%s", fileName); return FALSE; } } diff --git a/libbb/remove_file.c b/libbb/remove_file.c index 988b091..65708a2 100644 --- a/libbb/remove_file.c +++ b/libbb/remove_file.c @@ -37,7 +37,7 @@ extern int remove_file(const char *path, int flags) if (lstat(path, &path_stat) < 0) { if (errno != ENOENT) { - perror_msg("unable to stat `%s'", path); + bb_perror_msg("unable to stat `%s'", path); return -1; } @@ -46,7 +46,7 @@ extern int remove_file(const char *path, int flags) if (!path_exists) { if (!(flags & FILEUTILS_FORCE)) { - perror_msg("cannot remove `%s'", path); + bb_perror_msg("cannot remove `%s'", path); return -1; } return 0; @@ -58,21 +58,21 @@ extern int remove_file(const char *path, int flags) int status = 0; if (!(flags & FILEUTILS_RECUR)) { - error_msg("%s: is a directory", path); + bb_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, + fprintf(stderr, "%s: descend into directory `%s'? ", bb_applet_name, path); - if (!ask_confirmation()) + if (!bb_ask_confirmation()) return 0; } if ((dp = opendir(path)) == NULL) { - perror_msg("unable to open `%s'", path); + bb_perror_msg("unable to open `%s'", path); return -1; } @@ -90,18 +90,18 @@ extern int remove_file(const char *path, int flags) } if (closedir(dp) < 0) { - perror_msg("unable to close `%s'", path); + bb_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()) + fprintf(stderr, "%s: remove directory `%s'? ", bb_applet_name, path); + if (!bb_ask_confirmation()) return status; } if (rmdir(path) < 0) { - perror_msg("unable to remove `%s'", path); + bb_perror_msg("unable to remove `%s'", path); return -1; } @@ -111,13 +111,13 @@ extern int remove_file(const char *path, int flags) !S_ISLNK(path_stat.st_mode) && isatty(0)) || (flags & FILEUTILS_INTERACTIVE)) { - fprintf(stderr, "%s: remove `%s'? ", applet_name, path); - if (!ask_confirmation()) + fprintf(stderr, "%s: remove `%s'? ", bb_applet_name, path); + if (!bb_ask_confirmation()) return 0; } if (unlink(path) < 0) { - perror_msg("unable to remove `%s'", path); + bb_perror_msg("unable to remove `%s'", path); return -1; } diff --git a/libbb/run_parts.c b/libbb/run_parts.c index 7829a84..5864566 100644 --- a/libbb/run_parts.c +++ b/libbb/run_parts.c @@ -69,7 +69,7 @@ extern int run_parts(char **args, const unsigned char test_mode) if (test_mode & 2) { return(2); } - perror_msg_and_die("failed to open directory %s", arg0); + bb_perror_msg_and_die("failed to open directory %s", arg0); } for (i = 0; i < entries; i++) { @@ -77,7 +77,7 @@ extern int run_parts(char **args, const unsigned char test_mode) filename = concat_path_file(arg0, namelist[i]->d_name); if (stat(filename, &st) < 0) { - perror_msg_and_die("failed to stat component %s", filename); + 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) { @@ -89,7 +89,7 @@ extern int run_parts(char **args, const unsigned char test_mode) int pid; if ((pid = vfork()) < 0) { - perror_msg_and_die("failed to fork"); + bb_perror_msg_and_die("failed to fork"); } else if (!pid) { args[0] = filename; execv(filename, args); @@ -100,19 +100,19 @@ extern int run_parts(char **args, const unsigned char test_mode) waitpid(pid, &result, 0); if(exec_errno) { errno = exec_errno; - perror_msg_and_die("failed to exec %s", filename); + bb_perror_msg_and_die("failed to exec %s", filename); } if (WIFEXITED(result) && WEXITSTATUS(result)) { - perror_msg("%s exited with return code %d", filename, WEXITSTATUS(result)); + bb_perror_msg("%s exited with return code %d", filename, WEXITSTATUS(result)); exitstatus = 1; } else if (WIFSIGNALED(result)) { - perror_msg("%s exited because of uncaught signal %d", filename, WTERMSIG(result)); + bb_perror_msg("%s exited because of uncaught signal %d", filename, WTERMSIG(result)); exitstatus = 1; } } } else if (!S_ISDIR(st.st_mode)) { - error_msg("component %s is not an executable plain file", filename); + bb_error_msg("component %s is not an executable plain file", filename); exitstatus = 1; } diff --git a/libbb/run_shell.c b/libbb/run_shell.c index b26eba1..d154b98 100644 --- a/libbb/run_shell.c +++ b/libbb/run_shell.c @@ -57,11 +57,11 @@ void run_shell ( const char *shell, int loginshell, const char *command, const c else args = (const char **) xmalloc (sizeof (char *) * 4 ); - args [0] = get_last_path_component ( xstrdup ( shell )); + args [0] = bb_get_last_path_component ( bb_xstrdup ( shell )); if ( loginshell ) { char *args0; - bb_asprintf ( &args0, "-%s", args [0] ); + bb_xasprintf ( &args0, "-%s", args [0] ); args [0] = args0; } @@ -75,6 +75,6 @@ void run_shell ( const char *shell, int loginshell, const char *command, const c } args [argno] = 0; execv ( shell, (char **) args ); - perror_msg_and_die ( "cannot run %s", shell ); + bb_perror_msg_and_die ( "cannot run %s", shell ); } diff --git a/libbb/setup_environment.c b/libbb/setup_environment.c index dc171fa..30d317c 100644 --- a/libbb/setup_environment.c +++ b/libbb/setup_environment.c @@ -45,7 +45,7 @@ static void xsetenv ( const char *key, const char *value ) { if ( setenv ( key, value, 1 )) - error_msg_and_die ( "out of memory" ); + bb_error_msg_and_die ( "out of memory" ); } void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw ) @@ -62,7 +62,7 @@ void setup_environment ( const char *shell, int loginshell, int changeenv, const 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 ); - error_msg_and_die ( "cannot cd to home directory or /" ); + bb_error_msg_and_die ( "cannot cd to home directory or /" ); } fputs ( "warning: cannot change to home directory\n", stderr ); } diff --git a/libbb/simplify_path.c b/libbb/simplify_path.c index 7b2a1ca..743133c 100644 --- a/libbb/simplify_path.c +++ b/libbb/simplify_path.c @@ -1,8 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * simplify_path implementation for busybox + * bb_simplify_path implementation for busybox * - * Copyright (C) 2001 Manuel Novoa III <mjn3@opensource.lineo.com> + * 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 @@ -21,15 +21,14 @@ */ #include <stdlib.h> - #include "libbb.h" -char *simplify_path(const char *path) +char *bb_simplify_path(const char *path) { char *s, *start, *p; if (path[0] == '/') - start = xstrdup(path); + start = bb_xstrdup(path); else { s = xgetcwd(NULL); start = concat_path_file(s, path); diff --git a/libbb/skip_whitespace.c b/libbb/skip_whitespace.c new file mode 100644 index 0000000..bf049a2 --- /dev/null +++ b/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/libbb/speed_table.c b/libbb/speed_table.c new file mode 100644 index 0000000..b04429e --- /dev/null +++ b/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/libbb/syscalls.c b/libbb/syscalls.c index 91e97b1..8d8c689 100644 --- a/libbb/syscalls.c +++ b/libbb/syscalls.c @@ -53,7 +53,7 @@ int pivot_root(const char * new_root,const char * put_old) * you will need to recompile with a kernel supporting the * pivot_root system call. */ - error_msg("\n\nTo make this application work, you will need to recompile\n" + bb_error_msg("\n\nTo make this application work, you will need to recompile\n" "with a kernel supporting the pivot_root system call. -Erik\n"); errno=ENOSYS; return -1; @@ -91,7 +91,7 @@ int umount2(const char * special_file, int flags) * you will need to recompile with a kernel supporting the * umount2 system call. */ - error_msg("\n\nTo make this application work, you will need to recompile\n" + bb_error_msg("\n\nTo make this application work, you will need to recompile\n" "with a kernel supporting the umount2 system call. -Erik\n"); errno=ENOSYS; return -1; diff --git a/libbb/syslog_msg_with_name.c b/libbb/syslog_msg_with_name.c index 6474da4..bd3f448 100644 --- a/libbb/syslog_msg_with_name.c +++ b/libbb/syslog_msg_with_name.c @@ -32,7 +32,7 @@ void syslog_msg_with_name(const char *name, int facility, int pri, const char *m void syslog_msg(int facility, int pri, const char *msg) { - syslog_msg_with_name(applet_name, facility, pri, msg); + syslog_msg_with_name(bb_applet_name, facility, pri, msg); } /* END CODE */ diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index 21cde20..4612bf3 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c @@ -25,10 +25,10 @@ #include <stdlib.h> #include "libbb.h" -extern void verror_msg(const char *s, va_list p) +extern void bb_verror_msg(const char *s, va_list p) { fflush(stdout); - fprintf(stderr, "%s: ", applet_name); + fprintf(stderr, "%s: ", bb_applet_name); vfprintf(stderr, s, p); } diff --git a/libbb/vherror_msg.c b/libbb/vherror_msg.c index 67db17f..eb341bf 100644 --- a/libbb/vherror_msg.c +++ b/libbb/vherror_msg.c @@ -26,11 +26,11 @@ #include "libbb.h" -extern void vherror_msg(const char *s, va_list p) +extern void bb_vherror_msg(const char *s, va_list p) { if(s == 0) s = ""; - verror_msg(s, p); + bb_verror_msg(s, p); if (*s) fputs(": ", stderr); herror(""); diff --git a/libbb/vperror_msg.c b/libbb/vperror_msg.c index 7da5bae..febe4e2 100644 --- a/libbb/vperror_msg.c +++ b/libbb/vperror_msg.c @@ -25,11 +25,11 @@ #include <stdlib.h> #include "libbb.h" -extern void vperror_msg(const char *s, va_list p) +extern void bb_vperror_msg(const char *s, va_list p) { int err=errno; if(s == 0) s = ""; - verror_msg(s, p); + bb_verror_msg(s, p); if (*s) s = ": "; fprintf(stderr, "%s%s\n", s, strerror(err)); } diff --git a/libbb/warn_ignoring_args.c b/libbb/warn_ignoring_args.c new file mode 100644 index 0000000..223831f --- /dev/null +++ b/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/libbb/wfopen.c b/libbb/wfopen.c index f58ec90..22f22b3 100644 --- a/libbb/wfopen.c +++ b/libbb/wfopen.c @@ -23,11 +23,11 @@ #include <errno.h> #include "libbb.h" -FILE *wfopen(const char *path, const char *mode) +FILE *bb_wfopen(const char *path, const char *mode) { FILE *fp; if ((fp = fopen(path, mode)) == NULL) { - perror_msg("%s", path); + bb_perror_msg("%s", path); errno = 0; } return fp; diff --git a/libbb/wfopen_input.c b/libbb/wfopen_input.c new file mode 100644 index 0000000..bff6606 --- /dev/null +++ b/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/libbb/xconnect.c b/libbb/xconnect.c index bc6505a..2945d76 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c @@ -30,7 +30,7 @@ int xconnect(const char *host, const char *port) hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(host, port, &hints, &res); if (error||!res) - perror_msg_and_die(gai_strerror(error)); + bb_perror_msg_and_die(gai_strerror(error)); addr_info=res; while (res) { s=socket(res->ai_family, res->ai_socktype, res->ai_protocol); @@ -50,7 +50,7 @@ int xconnect(const char *host, const char *port) freeaddrinfo(addr_info); if (error < 0) { - perror_msg_and_die("Unable to connect to remote host (%s)", host); + bb_perror_msg_and_die("Unable to connect to remote host (%s)", host); } return s; #else @@ -72,7 +72,7 @@ int xconnect(const char *host, const char *port) if (connect(s, (struct sockaddr *)&s_addr, sizeof s_addr) < 0) { - perror_msg_and_die("Unable to connect to remote host (%s)", host); + bb_perror_msg_and_die("Unable to connect to remote host (%s)", host); } return s; #endif diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 820a0d7..43e8aef 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -30,31 +30,38 @@ #ifndef DMALLOC +#ifdef L_xmalloc extern void *xmalloc(size_t size) { void *ptr = malloc(size); if (ptr == NULL && size != 0) - error_msg_and_die(memory_exhausted); + bb_error_msg_and_die(bb_msg_memory_exhausted); return ptr; } +#endif +#ifdef L_xrealloc extern void *xrealloc(void *ptr, size_t size) { ptr = realloc(ptr, size); if (ptr == NULL && size != 0) - error_msg_and_die(memory_exhausted); + bb_error_msg_and_die(bb_msg_memory_exhausted); return ptr; } +#endif +#ifdef L_xcalloc extern void *xcalloc(size_t nmemb, size_t size) { void *ptr = calloc(nmemb, size); if (ptr == NULL && nmemb != 0 && size != 0) - error_msg_and_die(memory_exhausted); + bb_error_msg_and_die(bb_msg_memory_exhausted); return ptr; } +#endif -extern char * xstrdup (const char *s) { +#ifdef L_xstrdup +extern char * bb_xstrdup (const char *s) { char *t; if (s == NULL) @@ -63,79 +70,121 @@ extern char * xstrdup (const char *s) { t = strdup (s); if (t == NULL) - error_msg_and_die(memory_exhausted); + bb_error_msg_and_die(bb_msg_memory_exhausted); return t; } #endif +#endif /* DMALLOC */ -extern char * xstrndup (const char *s, int n) { +#ifdef L_xstrndup +extern char * bb_xstrndup (const char *s, int n) { char *t; if (s == NULL) - error_msg_and_die("xstrndup bug"); + bb_error_msg_and_die("bb_xstrndup bug"); t = xmalloc(++n); return safe_strncpy(t,s,n); } +#endif -FILE *xfopen(const char *path, const char *mode) +#ifdef L_xfopen +FILE *bb_xfopen(const char *path, const char *mode) { FILE *fp; if ((fp = fopen(path, mode)) == NULL) - perror_msg_and_die("%s", path); + bb_perror_msg_and_die("%s", path); return fp; } +#endif -extern int xopen(const char *pathname, int flags) +#ifdef L_xopen +extern int bb_xopen(const char *pathname, int flags) { int ret; ret = open(pathname, flags, 0777); if (ret == -1) { - perror_msg_and_die("%s", pathname); + bb_perror_msg_and_die("%s", pathname); } return ret; } +#endif -extern ssize_t xread(int fd, void *buf, size_t count) +#ifdef L_xread +extern ssize_t bb_xread(int fd, void *buf, size_t count) { ssize_t size; size = read(fd, buf, count); if (size == -1) { - perror_msg_and_die("Read error"); + bb_perror_msg_and_die("Read error"); } return(size); } +#endif -extern void xread_all(int fd, void *buf, size_t count) +#ifdef L_xread_all +extern void bb_xread_all(int fd, void *buf, size_t count) { ssize_t size; - size = xread(fd, buf, count); - if (size != count) { - error_msg_and_die("Short read"); + while (count) { + if ((size = bb_xread(fd, buf, count)) == 0) { /* EOF */ + bb_error_msg_and_die("Short read"); + } + count -= size; } return; } +#endif -extern unsigned char xread_char(int fd) +#ifdef L_xread_char +extern unsigned char bb_xread_char(int fd) { char tmp; - xread_all(fd, &tmp, 1); + bb_xread_all(fd, &tmp, 1); return(tmp); } +#endif + +#ifdef L_xferror +extern void bb_xferror(FILE *fp, const char *fn) +{ + if (ferror(fp)) { + bb_error_msg_and_die("%s", fn); + } +} +#endif + +#ifdef L_xferror_stdout +extern void bb_xferror_stdout(void) +{ + bb_xferror(stdout, bb_msg_standard_output); +} +#endif + +#ifdef L_xfflush_stdout +extern void bb_xfflush_stdout(void) +{ + if (fflush(stdout)) { + bb_perror_msg_and_die(bb_msg_standard_output); + } +} +#endif +#ifdef L_strlen /* Stupid gcc always includes its own builtin strlen()... */ #undef strlen -size_t xstrlen(const char *string) +size_t bb_strlen(const char *string) { return(strlen(string)); } +#endif /* END CODE */ /* diff --git a/libbb/xgetcwd.c b/libbb/xgetcwd.c index 54e9785..85a5c41 100644 --- a/libbb/xgetcwd.c +++ b/libbb/xgetcwd.c @@ -40,7 +40,7 @@ xgetcwd (char *cwd) if (ret == NULL) { free (cwd); - perror_msg("getcwd()"); + bb_perror_msg("getcwd()"); return NULL; } diff --git a/libbb/xgethostbyname.c b/libbb/xgethostbyname.c index b719797..6b2dff7 100644 --- a/libbb/xgethostbyname.c +++ b/libbb/xgethostbyname.c @@ -29,7 +29,7 @@ struct hostent *xgethostbyname(const char *name) struct hostent *retval; if ((retval = gethostbyname(name)) == NULL) - herror_msg_and_die("%s", name); + bb_herror_msg_and_die("%s", name); return retval; } diff --git a/libbb/xgethostbyname2.c b/libbb/xgethostbyname2.c index f4cbb6a..3a16ae4 100644 --- a/libbb/xgethostbyname2.c +++ b/libbb/xgethostbyname2.c @@ -30,7 +30,7 @@ struct hostent *xgethostbyname2(const char *name, int af) struct hostent *retval; if ((retval = gethostbyname2(name, af)) == NULL) - herror_msg_and_die("%s", name); + bb_herror_msg_and_die("%s", name); return retval; } diff --git a/libbb/xgetlarg.c b/libbb/xgetlarg.c index 598b0b3..06e776d 100644 --- a/libbb/xgetlarg.c +++ b/libbb/xgetlarg.c @@ -9,6 +9,7 @@ #include <getopt.h> #include <errno.h> #include <assert.h> +#include <ctype.h> #include "busybox.h" @@ -19,10 +20,16 @@ extern long bb_xgetlarg(char *arg, int base, long lower, long upper) 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' || result < lower || result > upper) - show_usage(); + if (errno != 0 || *endptr!='\0' || endptr==arg || result < lower || result > upper) + bb_show_usage(); errno = errno_save; return result; } diff --git a/libbb/xgetularg.c b/libbb/xgetularg.c new file mode 100644 index 0000000..d743520 --- /dev/null +++ b/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/libbb/xreadlink.c b/libbb/xreadlink.c index 9944b51..b8cfe61 100644 --- a/libbb/xreadlink.c +++ b/libbb/xreadlink.c @@ -24,7 +24,7 @@ extern char *xreadlink(const char *path) buf = xrealloc(buf, bufsize += GROWBY); readsize = readlink(path, buf, bufsize); /* 1st try */ if (readsize == -1) { - perror_msg("%s", path); + bb_perror_msg("%s", path); return NULL; } } diff --git a/libbb/xregcomp.c b/libbb/xregcomp.c index 07cf779..56746ac 100644 --- a/libbb/xregcomp.c +++ b/libbb/xregcomp.c @@ -34,7 +34,7 @@ void xregcomp(regex_t *preg, const char *regex, int cflags) int errmsgsz = regerror(ret, preg, NULL, 0); char *errmsg = xmalloc(errmsgsz); regerror(ret, preg, errmsg, errmsgsz); - error_msg_and_die("xregcomp: %s", errmsg); + bb_error_msg_and_die("xregcomp: %s", errmsg); } } |