diff options
Diffstat (limited to 'coreutils')
67 files changed, 3275 insertions, 2783 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in index 5b9996d..9f5c379 100644 --- a/coreutils/Config.in +++ b/coreutils/Config.in @@ -111,17 +111,31 @@ config CONFIG_DOS2UNIX Please submit a patch to add help text for this item. config CONFIG_DU - bool "du" + bool "du (default blocksize of 512 bytes)" default n help Please submit a patch to add help text for this item. +config CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K + bool " Use a default blocksize of 1024 bytes (1K)" + default y + depends on CONFIG_DU + help + Please submit a patch to add help text for this item. + config CONFIG_ECHO - bool "echo" + bool "echo (basic SUSv3 version taking no options" default n help Please submit a patch to add help text for this item. +config CONFIG_FEATURE_FANCY_ECHO + bool " Enable echo options (-n and -e)" + default y + depends on CONFIG_ECHO + help + Please submit a patch to add help text for this item. + config CONFIG_ENV bool "env" default n @@ -154,6 +168,13 @@ config CONFIG_HEAD help Please submit a patch to add help text for this item. +config CONFIG_FEATURE_FANCY_HEAD + bool " Enable head options (-c, -q, and -v)" + default n + depends on CONFIG_HEAD + help + Please submit a patch to add help text for this item. + config CONFIG_HOSTID bool "hostid" default n @@ -313,8 +334,15 @@ config CONFIG_SHA1SUM Compute and check SHA1 message digest config CONFIG_SLEEP - bool "sleep" + bool "sleep (single integer arg with no suffix)" + default n + help + Please submit a patch to add help text for this item. + +config CONFIG_FEATURE_FANCY_SLEEP + bool " Enable multiple integer args and optional time suffixes" default n + depends on CONFIG_SLEEP help Please submit a patch to add help text for this item. @@ -369,6 +397,13 @@ config CONFIG_TEE help Please submit a patch to add help text for this item. +config CONFIG_FEATURE_TEE_USE_BLOCK_IO + bool " Enable block i/o (larger/faster) instead of byte i/o." + default n + depends on CONFIG_TEE + help + Please submit a patch to add help text for this item. + if CONFIG_ASH || CONFIG_HUSH || CONFIG_LASH || CONFIG_MSH config CONFIG_TEST default y diff --git a/coreutils/basename.c b/coreutils/basename.c index bdbcec1..71bb9b3 100644 --- a/coreutils/basename.c +++ b/coreutils/basename.c @@ -21,32 +21,43 @@ * */ -/* getopt not needed */ +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */ + + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Changes: + * 1) Now checks for too many args. Need at least one and at most two. + * 2) Don't check for options, as per SUSv3. + * 3) Save some space by using strcmp(). Calling strncmp() here was silly. + */ #include <stdlib.h> -#include "busybox.h" +#include <stdio.h> #include <string.h> +#include "busybox.h" extern int basename_main(int argc, char **argv) { - int m, n; + size_t m, n; char *s; - if ((argc < 2) || (**(argv + 1) == '-')) { - show_usage(); + if (((unsigned int)(argc-2)) >= 2) { + bb_show_usage(); } - argv++; - - s = get_last_path_component(*argv); + s = bb_get_last_path_component(*++argv); - if (argc>2) { - argv++; + if (*++argv) { n = strlen(*argv); m = strlen(s); - if (m>n && strncmp(s+m-n, *argv, n)==0) + if ((m > n) && ((strcmp)(s+m-n, *argv) == 0)) { s[m-n] = '\0'; + } } + puts(s); - return EXIT_SUCCESS; + + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } diff --git a/coreutils/cal.c b/coreutils/cal.c index ab63157..ed480dd 100644 --- a/coreutils/cal.c +++ b/coreutils/cal.c @@ -1,3 +1,14 @@ +/* NOTE: + * + * Apparently, all "Steven J. Merrifield" did was grab the util-linux cal applet, + * spend maybe 5 minutes integrating it into busybox, slapped a copyright on it, + * and submitted it. I certainly saw no evidence of any attempt at size reduction. + * Not only do I consider his copyright below meaningless, I also consider his + * actions shameful. + * + * Manuel Novoa III (mjn3@codepoet.org) + */ + /* * Calendar implementation for busybox * @@ -20,7 +31,16 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ - + +/* BB_AUDIT SUSv3 compliant with -j and -y extensions (from util-linux). */ +/* BB_AUDIT BUG: The output of 'cal -j 1752' is incorrect. The upstream + * BB_AUDIT BUG: version in util-linux seems to be broken as well. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/cal.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Major size reduction... over 50% (>1.5k) on i386. + */ #include <sys/types.h> #include <ctype.h> @@ -46,44 +66,30 @@ #define MAXDAYS 42 /* max slots in a month array */ #define SPACE -1 /* used in day array */ -static int days_in_month[2][13] = { - {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, +static const char days_in_month[] = { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -int sep1752[MAXDAYS] = { - SPACE, SPACE, 1, 2, 14, 15, 16, +static const char sep1752[] = { + 1, 2, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, -}, j_sep1752[MAXDAYS] = { - SPACE, SPACE, 245, 246, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, -}, empty[MAXDAYS] = { - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, + 24, 25, 26, 27, 28, 29, 30 }; -char *month_names[12]; - -char day_headings[] = " "; -char j_day_headings[] = " "; +static int julian; /* leap year -- account for gregorian reformation in 1752 */ #define leap_year(yr) \ ((yr) <= 1752 ? !((yr) % 4) : \ (!((yr) % 4) && ((yr) % 100)) || !((yr) % 400)) +static int is_leap_year(int year) +{ + return leap_year(year); +} +#undef leap_year +#define leap_year(yr) is_leap_year(yr) + /* number of centuries since 1700, not inclusive */ #define centuries_since_1700(yr) \ ((yr) > 1700 ? (yr) / 100 - 17 : 0) @@ -96,178 +102,129 @@ char j_day_headings[] = " "; #define leap_years_since_year_1(yr) \ ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr)) -int julian; -void ascii_day __P((char *, int)); -void center __P((char *, int, int)); -void day_array __P((int, int, int *)); -int day_in_week __P((int, int, int)); -int day_in_year __P((int, int, int)); -void j_yearly __P((int)); -void monthly __P((int, int)); -void trim_trailing_spaces __P((char *)); -void yearly __P((int)); +static void center __P((char *, int, int)); +static void day_array __P((int, int, int *)); +static void trim_trailing_spaces_and_print __P((char *)); + +static void blank_string(char *buf, size_t buflen); +static char *build_row(char *p, int *dp); + +#define DAY_LEN 3 /* 3 spaces per day */ +#define J_DAY_LEN (DAY_LEN + 1) +#define WEEK_LEN 20 /* 7 * 3 - one space at the end */ +#define J_WEEK_LEN (WEEK_LEN + 7) +#define HEAD_SEP 2 /* spaces between day headings */ int cal_main(int argc, char **argv) { struct tm *local_time; - static struct tm zero_tm; + struct tm zero_tm; time_t now; - int ch, month, year, yflag, i; + int month, year, flags, i; + char *month_names[12]; + char day_headings[28]; /* 28 for julian, 21 for nonjulian */ char buf[40]; #ifdef CONFIG_LOCALE_SUPPORT setlocale(LC_TIME, ""); #endif - yflag = 0; - while ((ch = getopt(argc, argv, "jy")) != -1) - switch(ch) { - case 'j': - julian = 1; - break; - case 'y': - yflag = 1; - break; - default: - show_usage(); - } - argc -= optind; + flags = bb_getopt_ulflags(argc, argv, "jy"); + + julian = flags & 1; + argv += optind; month = 0; - switch(argc) { - case 2: - if ((month = atoi(*argv++)) < 1 || month > 12) - error_msg_and_die("Illegal month value: use 1-12"); - /* FALLTHROUGH */ - case 1: - if ((year = atoi(*argv)) < 1 || year > 9999) - error_msg_and_die("Illegal year value: use 1-9999"); - break; - case 0: + + if ((argc -= optind) > 2) { + bb_show_usage(); + } + + if (!argc) { time(&now); local_time = localtime(&now); year = local_time->tm_year + 1900; - if (!yflag) + if (!(flags & 2)) { month = local_time->tm_mon + 1; - break; - default: - show_usage(); + } + } else { + if (argc == 2) { + month = bb_xgetularg10_bnd(*argv++, 1, 12); + } + year = bb_xgetularg10_bnd(*argv, 1, 9999); } - for (i = 0; i < 12; i++) { + blank_string(day_headings, sizeof(day_headings) - 7 + 7*julian); + + i = 0; + do { zero_tm.tm_mon = i; strftime(buf, sizeof(buf), "%B", &zero_tm); - month_names[i] = xstrdup(buf); - } - for (i = 0; i < 7; i++) { - zero_tm.tm_wday = i; - strftime(buf, sizeof(buf), "%a", &zero_tm); - strncpy(day_headings + i * 3, buf, 2); - strncpy(j_day_headings + i * 4 + 1, buf, 2); - } - - if (month) - monthly(month, year); - else if (julian) - j_yearly(year); - else - yearly(year); - exit(0); -} + month_names[i] = bb_xstrdup(buf); -#define DAY_LEN 3 /* 3 spaces per day */ -#define J_DAY_LEN 4 /* 4 spaces per day */ -#define WEEK_LEN 20 /* 7 * 3 - one space at the end */ -#define J_WEEK_LEN 27 /* 7 * 4 - one space at the end */ -#define HEAD_SEP 2 /* spaces between day headings */ -#define J_HEAD_SEP 2 - -void monthly(int month, int year) -{ - int col, row, len, days[MAXDAYS]; - char *p, lineout[30]; - - day_array(month, year, days); - len = sprintf(lineout, "%s %d", month_names[month - 1], year); - printf("%*s%s\n%s\n", - ((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "", - lineout, julian ? j_day_headings : day_headings); - for (row = 0; row < 6; row++) { - for (col = 0, p = lineout; col < 7; col++, - p += julian ? J_DAY_LEN : DAY_LEN) - ascii_day(p, days[row * 7 + col]); - *p = '\0'; - trim_trailing_spaces(lineout); - printf("%s\n", lineout); - } -} - -void j_yearly(int year) -{ - int col, *dp, i, month, row, which_cal; - int days[12][MAXDAYS]; - char *p, lineout[80]; - - sprintf(lineout, "%d", year); - center(lineout, J_WEEK_LEN * 2 + J_HEAD_SEP, 0); - printf("\n\n"); - for (i = 0; i < 12; i++) - day_array(i + 1, year, days[i]); - memset(lineout, ' ', sizeof(lineout) - 1); - lineout[sizeof(lineout) - 1] = '\0'; - for (month = 0; month < 12; month += 2) { - center(month_names[month], J_WEEK_LEN, J_HEAD_SEP); - center(month_names[month + 1], J_WEEK_LEN, 0); - printf("\n%s%*s%s\n", j_day_headings, J_HEAD_SEP, "", - j_day_headings); - for (row = 0; row < 6; row++) { - for (which_cal = 0; which_cal < 2; which_cal++) { - p = lineout + which_cal * (J_WEEK_LEN + 2); - dp = &days[month + which_cal][row * 7]; - for (col = 0; col < 7; col++, p += J_DAY_LEN) - ascii_day(p, *dp++); - } - *p = '\0'; - trim_trailing_spaces(lineout); - printf("%s\n", lineout); + if (i < 7) { + zero_tm.tm_wday = i; + strftime(buf, sizeof(buf), "%a", &zero_tm); + strncpy(day_headings + i * (3+julian) + julian, buf, 2); } - } - printf("\n"); -} - -void yearly(int year) -{ - int col, *dp, i, month, row, which_cal; - int days[12][MAXDAYS]; - char *p, lineout[80]; - - sprintf(lineout, "%d", year); - center(lineout, WEEK_LEN * 3 + HEAD_SEP * 2, 0); - printf("\n\n"); - for (i = 0; i < 12; i++) - day_array(i + 1, year, days[i]); - memset(lineout, ' ', sizeof(lineout) - 1); - lineout[sizeof(lineout) - 1] = '\0'; - for (month = 0; month < 12; month += 3) { - center(month_names[month], WEEK_LEN, HEAD_SEP); - center(month_names[month + 1], WEEK_LEN, HEAD_SEP); - center(month_names[month + 2], WEEK_LEN, 0); - printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP, - "", day_headings, HEAD_SEP, "", day_headings); + } while (++i < 12); + + if (month) { + int row, len, days[MAXDAYS]; + int *dp = days; + char lineout[30]; + + day_array(month, year, dp); + len = sprintf(lineout, "%s %d", month_names[month - 1], year); + bb_printf("%*s%s\n%s\n", + ((7*julian + WEEK_LEN) - len) / 2, "", + lineout, day_headings); for (row = 0; row < 6; row++) { - for (which_cal = 0; which_cal < 3; which_cal++) { - p = lineout + which_cal * (WEEK_LEN + 2); - dp = &days[month + which_cal][row * 7]; - for (col = 0; col < 7; col++, p += DAY_LEN) - ascii_day(p, *dp++); + build_row(lineout, dp)[0] = '\0'; + dp += 7; + trim_trailing_spaces_and_print(lineout); + } + } else { + int row, which_cal, week_len, days[12][MAXDAYS]; + int *dp; + char lineout[80]; + + sprintf(lineout, "%d", year); + center(lineout, + (WEEK_LEN * 3 + HEAD_SEP * 2) + + julian * (J_WEEK_LEN * 2 + HEAD_SEP + - (WEEK_LEN * 3 + HEAD_SEP * 2)), + 0); + puts("\n"); /* two \n's */ + for (i = 0; i < 12; i++) { + day_array(i + 1, year, days[i]); + } + blank_string(lineout, sizeof(lineout)); + week_len = WEEK_LEN + julian * (J_WEEK_LEN - WEEK_LEN); + for (month = 0; month < 12; month += 3-julian) { + center(month_names[month], week_len, HEAD_SEP); + if (!julian) { + center(month_names[month + 1], week_len, HEAD_SEP); + } + center(month_names[month + 2 - julian], week_len, 0); + bb_printf("\n%s%*s%s", day_headings, HEAD_SEP, "", day_headings); + if (!julian) { + bb_printf("%*s%s", HEAD_SEP, "", day_headings); + } + putchar('\n'); + for (row = 0; row < (6*7); row += 7) { + for (which_cal = 0; which_cal < 3-julian; which_cal++) { + dp = days[month + which_cal] + row; + build_row(lineout + which_cal * (week_len + 2), dp); + } + /* blank_string took care of nul termination. */ + trim_trailing_spaces_and_print(lineout); } - *p = '\0'; - trim_trailing_spaces(lineout); - printf("%s\n", lineout); } } - printf("\n"); + + bb_fflush_stdout_and_exit(0); } /* @@ -277,118 +234,129 @@ void yearly(int year) * out end to end. You would have 42 numbers or spaces. This routine * builds that array for any month from Jan. 1 through Dec. 9999. */ -void day_array(int month, int year, int *days) +static void day_array(int month, int year, int *days) { + long temp; + int i; + int j_offset; int day, dw, dm; + memset(days, SPACE, MAXDAYS * sizeof(int)); + if ((month == 9) && (year == 1752)) { - memmove(days, - julian ? j_sep1752 : sep1752, MAXDAYS * sizeof(int)); + j_offset = julian * 244; + i = 0; + do { + days[i+2] = sep1752[i] + j_offset; + } while (++i < sizeof(sep1752)); + return; } - memmove(days, empty, MAXDAYS * sizeof(int)); - dm = days_in_month[leap_year(year)][month]; - dw = day_in_week(1, month, year); - day = julian ? day_in_year(1, month, year) : 1; - while (dm--) - days[dw++] = day++; -} -/* - * day_in_year -- - * return the 1 based day number within the year - */ -int day_in_year(int day, int month, int year) -{ - int i, leap; - - leap = leap_year(year); - for (i = 1; i < month; i++) - day += days_in_month[leap][i]; - return (day); -} + /* day_in_year + * return the 1 based day number within the year + */ + day = 1; + if ((month > 2) && leap_year(year)) { + ++day; + } -/* - * day_in_week - * return the 0 based day number for any date from 1 Jan. 1 to - * 31 Dec. 9999. Assumes the Gregorian reformation eliminates - * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all - * missing days. - */ -int day_in_week(int day, int month, int year) -{ - long temp; + i = month; + while (i) { + day += days_in_month[--i]; + } + /* day_in_week + * return the 0 based day number for any date from 1 Jan. 1 to + * 31 Dec. 9999. Assumes the Gregorian reformation eliminates + * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all + * missing days. + */ + dw = THURSDAY; temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1) - + day_in_year(day, month, year); - if (temp < FIRST_MISSING_DAY) - return ((temp - 1 + SATURDAY) % 7); - if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) - return (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7); - return (THURSDAY); + + day; + if (temp < FIRST_MISSING_DAY) { + dw = ((temp - 1 + SATURDAY) % 7); + } else if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) { + dw = (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7); + } + + if (!julian) { + day = 1; + } + + dm = days_in_month[month]; + if ((month == 2) && leap_year(year)) { + ++dm; + } + + while (dm) { + days[dw++] = day++; + --dm; + } } -void ascii_day(char *p, int day) +static void trim_trailing_spaces_and_print(char *s) { - int display, val; - static char *aday[] = { - "", - " 1", " 2", " 3", " 4", " 5", " 6", " 7", - " 8", " 9", "10", "11", "12", "13", "14", - "15", "16", "17", "18", "19", "20", "21", - "22", "23", "24", "25", "26", "27", "28", - "29", "30", "31", - }; - - if (day == SPACE) { - memset(p, ' ', julian ? J_DAY_LEN : DAY_LEN); - return; + char *p = s; + + while (*p) { + ++p; } - if (julian) { - if ((val = day / 100) != 0) { - day %= 100; - *p++ = val + '0'; - display = 1; - } else { - *p++ = ' '; - display = 0; + while (p > s) { + --p; + if (!(isspace)(*p)) { /* We want the function... not the inline. */ + p[1] = '\0'; + break; } - val = day / 10; - if (val || display) - *p++ = val + '0'; - else - *p++ = ' '; - *p++ = day % 10 + '0'; - } else { - *p++ = aday[day][0]; - *p++ = aday[day][1]; } - *p = ' '; + + puts(s); } -void trim_trailing_spaces(char *s) +static void center(char *str, int len, int separate) { - char *p; + int n = strlen(str); + len -= n; + bb_printf("%*s%*s", (len/2) + n, str, (len/2) + (len % 2) + separate, ""); +} - for (p = s; *p; ++p) - continue; - while (p > s && (--p, isspace(*p))) - continue; - if (p > s) - ++p; - *p = '\0'; +static void blank_string(char *buf, size_t buflen) +{ + memset(buf, ' ', buflen); + buf[buflen-1] = '\0'; } -void center(char *str, int len, int separate) +static char *build_row(char *p, int *dp) { + int col, val, day; + + memset(p, ' ', (julian + DAY_LEN) * 7); + + col = 0; + do { + if ((day = *dp++) != SPACE) { + if (julian) { + *++p; + if (day >= 100) { + *p = '0'; + p[-1] = (day / 100) + '0'; + day %= 100; + } + } + if ((val = day / 10) > 0) { + *p = val + '0'; + } + *++p = day % 10 + '0'; + p += 2; + } else { + p += DAY_LEN + julian; + } + } while (++col < 7); - len -= strlen(str); - printf("%*s%s%*s", len / 2, "", str, len / 2 + len % 2, ""); - if (separate) - printf("%*s", separate, ""); + return p; } - /* * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. diff --git a/coreutils/cat.c b/coreutils/cat.c index 33f15da..8652757 100644 --- a/coreutils/cat.c +++ b/coreutils/cat.c @@ -1,9 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini Cat implementation for busybox + * cat implementation for busybox * - * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen - * 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 @@ -21,33 +20,48 @@ * */ +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * This is a new implementation of 'cat' which aims to be SUSv3 compliant. + * + * Changes from the previous implementation include: + * 1) Multiple '-' args are accepted as required by SUSv3. The previous + * implementation would close stdin and segfault on a subsequent '-'. + * 2) The '-u' options is required by SUSv3. Note that the specified + * behavior for '-u' is done by default, so all we need do is accept + * the option. + */ + #include <stdlib.h> -#include <string.h> +#include <stdio.h> +#include <unistd.h> #include "busybox.h" extern int cat_main(int argc, char **argv) { - int status = EXIT_SUCCESS; + FILE *f; + int retval = EXIT_SUCCESS; - if (argc == 1) { - print_file(stdin); - return status; + bb_getopt_ulflags(argc, argv, "u"); + + argv += optind; + if (!*argv) { + *--argv = "-"; } - while (--argc > 0) { - if(!(strcmp(*++argv, "-"))) { - print_file(stdin); - } else if (! print_file_by_name(*argv)) { - status = EXIT_FAILURE; + do { + if ((f = bb_wfopen_input(*argv)) != NULL) { + int r = bb_copyfd(fileno(f), STDOUT_FILENO, 0); + bb_fclose_nonstdin(f); + if (r >= 0) { + continue; + } } - } - return status; -} + retval = EXIT_FAILURE; + } while (*++argv); -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ + return retval; +} diff --git a/coreutils/chgrp.c b/coreutils/chgrp.c index 968b448..f5e5d29 100644 --- a/coreutils/chgrp.c +++ b/coreutils/chgrp.c @@ -21,9 +21,12 @@ * */ -#include <stdio.h> +/* BB_AUDIT SUSv3 defects - unsupported options -h, -H, -L, and -P. */ +/* BB_AUDIT GNU defects - unsupported options -h, -c, -f, -v, and long options. */ +/* BB_AUDIT Note: gnu chgrp does not support -H, -L, or -P. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/chgrp.html */ + #include <stdlib.h> -#include <string.h> #include <unistd.h> #include "busybox.h" @@ -32,53 +35,46 @@ #define lchown chown #endif - -static long gid; - static int fileAction(const char *fileName, struct stat *statbuf, void* junk) { - if (lchown(fileName, statbuf->st_uid, (gid == -1) ? statbuf->st_gid : gid) == 0) { + if (lchown(fileName, statbuf->st_uid, *((long *) junk)) == 0) { return (TRUE); } - perror(fileName); + bb_perror_msg("%s", fileName); /* Avoid multibyte problems. */ return (FALSE); } int chgrp_main(int argc, char **argv) { - int opt; - int recursiveFlag = FALSE; - char *p=NULL; + long gid; + int recursiveFlag;; + int retval = EXIT_SUCCESS; + char *p; - /* do normal option parsing */ - while ((opt = getopt(argc, argv, "R")) > 0) { - switch (opt) { - case 'R': - recursiveFlag = TRUE; - break; - default: - show_usage(); - } + recursiveFlag = bb_getopt_ulflags(argc, argv, "R"); + + if (argc - optind < 2) { + bb_show_usage(); } - if (argc > optind && argc > 2 && argv[optind]) { - /* Find the selected group */ - gid = strtoul(argv[optind], &p, 10); /* maybe it's already numeric */ - if (argv[optind] == p) - gid = my_getgrnam(argv[optind]); - } else { - error_msg_and_die(too_few_args); + argv += optind; + + /* Find the selected group */ + gid = strtoul(*argv, &p, 10); /* maybe it's already numeric */ + if (*p || (p == *argv)) { /* trailing chars or nonnumeric */ + gid = my_getgrnam(*argv); } + ++argv; /* Ok, ready to do the deed now */ - while (++optind < argc) { - if (! recursive_action (argv[optind], recursiveFlag, FALSE, FALSE, - fileAction, fileAction, NULL)) { - return EXIT_FAILURE; + do { + if (! recursive_action (*argv, recursiveFlag, FALSE, FALSE, + fileAction, fileAction, &gid)) { + retval = EXIT_FAILURE; } - } - return EXIT_SUCCESS; + } while (*++argv); + return retval; } /* diff --git a/coreutils/chmod.c b/coreutils/chmod.c index ba80e02..28c9855 100644 --- a/coreutils/chmod.c +++ b/coreutils/chmod.c @@ -24,67 +24,84 @@ * */ +/* BB_AUDIT SUSv3 compliant */ +/* BB_AUDIT GNU defects - unsupported options -c, -f, -v, and long options. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */ + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <getopt.h> +#include <sys/stat.h> #include "busybox.h" static int fileAction(const char *fileName, struct stat *statbuf, void* junk) { - if (!parse_mode((char *)junk, &(statbuf->st_mode))) - error_msg_and_die( "unknown mode: %s", (char *)junk); + if (!bb_parse_mode((char *)junk, &(statbuf->st_mode))) + bb_error_msg_and_die( "unknown mode: %s", (char *)junk); if (chmod(fileName, statbuf->st_mode) == 0) return (TRUE); - perror(fileName); + bb_perror_msg("%s", fileName); /* Avoid multibyte problems. */ return (FALSE); } int chmod_main(int argc, char **argv) { - int opt; + int retval = EXIT_SUCCESS; int recursiveFlag = FALSE; - int modeind = 0; /* Index of the mode argument in `argv'. */ + int count; char *smode; - static const char chmod_modes[] = "Rrwxstugoa,+-="; + char **p; + char *p0; + char opt = '-'; - /* do normal option parsing */ - while (1) { - int thisind = optind ? optind : 1; + ++argv; + count = 0; - opt = getopt(argc, argv, chmod_modes); - if (opt == EOF) - break; - smode = strchr(chmod_modes, opt); - if(smode == NULL) - show_usage(); - if(smode == chmod_modes) { /* 'R' */ - recursiveFlag = TRUE; - } else { - if (modeind != 0 && modeind != thisind) - show_usage(); - modeind = thisind; + for (p = argv ; *p ; p++) { + p0 = p[0]; + if (p0[0] == opt) { + if ((p0[1] == '-') && !p0[2]) { + opt = 0; /* Disable further option processing. */ + continue; + } + if (p0[1] == 'R') { + char *s = p0 + 2; + while (*s == 'R') { + ++s; + } + if (*s) { + bb_show_usage(); + } + recursiveFlag = TRUE; + continue; + } + if (count) { + bb_show_usage(); + } } + argv[count] = p0; + ++count; } - if (modeind == 0) - modeind = optind++; + argv[count] = NULL; - opt = optind; - if (opt >= argc) { - error_msg_and_die(too_few_args); + if (count < 2) { + bb_show_usage(); } - smode = argv[modeind]; + smode = *argv; + ++argv; + /* Ok, ready to do the deed now */ - for (; opt < argc; opt++) { - if (! recursive_action (argv[opt], recursiveFlag, FALSE, FALSE, fileAction, - fileAction, smode)) { - return EXIT_FAILURE; + do { + if (! recursive_action (*argv, recursiveFlag, FALSE, FALSE, + fileAction, fileAction, smode)) { + retval = EXIT_FAILURE; } - } - return EXIT_SUCCESS; + } while (*++argv); + + return retval; } /* diff --git a/coreutils/chown.c b/coreutils/chown.c index 4e766a9..3e983cf 100644 --- a/coreutils/chown.c +++ b/coreutils/chown.c @@ -21,10 +21,14 @@ * */ -#include <stdio.h> +/* BB_AUDIT SUSv3 defects - unsupported options -h, -H, -L, and -P. */ +/* BB_AUDIT GNU defects - unsupported options -h, -c, -f, -v, and long options. */ +/* BB_AUDIT Note: gnu chown does not support -H, -L, or -P. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */ + #include <stdlib.h> -#include <string.h> #include <unistd.h> +#include <string.h> #include "busybox.h" /* Don't use lchown for libc5 or glibc older then 2.1.x */ @@ -42,65 +46,67 @@ static int fileAction(const char *fileName, struct stat *statbuf, void* junk) if (chown_func(fileName, uid, (gid == -1) ? statbuf->st_gid : gid) == 0) { return (TRUE); } - perror(fileName); + bb_perror_msg("%s", fileName); /* Avoid multibyte problems. */ return (FALSE); } +#define FLAG_R 1 +#define FLAG_h 2 + +static unsigned long get_ug_id(const char *s, long (*my_getxxnam)(const char *)) +{ + unsigned long r; + char *p; + + r = strtoul(s, &p, 10); + if (*p || (s == p)) { + r = my_getxxnam(s); + } + + return r; +} + int chown_main(int argc, char **argv) { - int opt; - int recursiveFlag = FALSE, - noderefFlag = FALSE; - char *groupName=NULL; - char *p=NULL; - - /* do normal option parsing */ - while ((opt = getopt(argc, argv, "Rh")) > 0) { - switch (opt) { - case 'R': - recursiveFlag = TRUE; - break; - case 'h': - noderefFlag = TRUE; - break; - default: - show_usage(); - } + int flags; + int retval = EXIT_SUCCESS; + char *groupName; + + flags = bb_getopt_ulflags(argc, argv, "Rh"); + + if (flags & FLAG_h) chown_func = lchown; + + if (argc - optind < 2) { + bb_show_usage(); } - if (noderefFlag) chown_func = lchown; - - if (argc > optind && argc > 2 && argv[optind]) { - /* First, check if there is a group name here */ - groupName = strchr(argv[optind], '.'); - if (groupName == NULL) - groupName = strchr(argv[optind], ':'); - if (groupName) { - *groupName++ = '\0'; - gid = strtoul(groupName, &p, 10); - if (groupName == p) - gid = my_getgrnam(groupName); - } else { - gid = -1; - } - /* Now check for the username */ - uid = strtoul(argv[optind], &p, 10); /* Is is numeric? */ - if (argv[optind] == p) { - uid = my_getpwnam(argv[optind]); - } - } else { - error_msg_and_die(too_few_args); + argv += optind; + + /* First, check if there is a group name here */ + if ((groupName = strchr(*argv, '.')) == NULL) { + groupName = strchr(*argv, ':'); + } + + gid = -1; + if (groupName) { + *groupName++ = '\0'; + gid = get_ug_id(groupName, my_getgrnam); } + /* Now check for the username */ + uid = get_ug_id(*argv, my_getpwnam); + + ++argv; + /* Ok, ready to do the deed now */ - while (++optind < argc) { - if (! recursive_action (argv[optind], recursiveFlag, FALSE, FALSE, - fileAction, fileAction, NULL)) { - return EXIT_FAILURE; + do { + if (! recursive_action (*argv, (flags & FLAG_R), FALSE, FALSE, + fileAction, fileAction, NULL)) { + retval = EXIT_FAILURE; } - } - return EXIT_SUCCESS; + } while (*++argv); + return retval; } /* diff --git a/coreutils/chroot.c b/coreutils/chroot.c index ba3e5f8..01e4d56 100644 --- a/coreutils/chroot.c +++ b/coreutils/chroot.c @@ -21,6 +21,8 @@ * */ +/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */ + #include <stdlib.h> #include <stdio.h> #include <unistd.h> @@ -29,46 +31,24 @@ int chroot_main(int argc, char **argv) { - char *prog; - - if ((argc < 2) || (**(argv + 1) == '-')) { - show_usage(); + if (argc < 2) { + bb_show_usage(); } - argc--; - argv++; + ++argv; if (chroot(*argv) || (chdir("/"))) { - perror_msg_and_die("cannot change root directory to %s", *argv); + bb_perror_msg_and_die("cannot change root directory to %s", *argv); } - argc--; - argv++; - if (argc >= 1) { - prog = *argv; - execvp(*argv, argv); - } else { -#if defined shell_main && defined CONFIG_FEATURE_SH_STANDALONE_SHELL - char shell[] = "/bin/sh"; - char *shell_argv[2] = { shell, NULL }; - applet_name = shell; - shell_main(1, shell_argv); - return EXIT_SUCCESS; -#else - prog = getenv("SHELL"); - if (!prog) - prog = "/bin/sh"; - execlp(prog, prog, NULL); -#endif + ++argv; + if (argc == 2) { + argv -= 2; + if (!(*argv = getenv("SHELL"))) { + *argv = (char *) "/bin/sh"; + } + argv[1] = (char *) "-i"; } - perror_msg_and_die("cannot execute %s", prog); + execvp(*argv, argv); + bb_perror_msg_and_die("cannot execute %s", *argv); } - - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/coreutils/cmp.c b/coreutils/cmp.c index 07bf3be..43dbc84 100644 --- a/coreutils/cmp.c +++ b/coreutils/cmp.c @@ -20,59 +20,133 @@ * */ +/* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Original version majorly reworked for SUSv3 compliance, bug fixes, and + * size optimizations. Changes include: + * 1) Now correctly distingusishes between errors and actual file differences. + * 2) Proper handling of '-' args. + * 3) Actual error checking of i/o. + * 4) Accept SUSv3 -l option. Note that we use the slightly nicer gnu format + * in the '-l' case. + */ + #include <stdio.h> -#include <string.h> -#include <errno.h> #include <stdlib.h> -#include <getopt.h> +#include <unistd.h> #include "busybox.h" +static FILE *cmp_xfopen_input(const char *filename) +{ + FILE *fp; + + if ((fp = bb_wfopen_input(filename)) != NULL) { + return fp; + } + + exit(bb_default_error_retval); /* We already output an error message. */ +} + +static const char fmt_eof[] = "cmp: EOF on %s\n"; +static const char fmt_differ[] = "%s %s differ: char %d, line %d\n"; +#if 0 +static const char fmt_l_opt[] = "%.0s%.0s%d %o %o\n"; /* SUSv3 format */ +#else +static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n"; /* nicer gnu format */ +#endif + +static const char opt_chars[] = "sl"; + +enum { + OPT_s = 1, + OPT_l = 2 +}; + int cmp_main(int argc, char **argv) { - FILE *fp1 = NULL, *fp2 = stdin; - char *filename1, *filename2 = "-"; - int c, c1, c2, char_pos = 1, line_pos = 1, silent = FALSE; - - while ((c = getopt(argc, argv, "s")) != EOF) { - switch (c) { - case 's': - silent = TRUE; - break; - default: - show_usage(); - } + FILE *fp1, *fp2, *outfile = stdout; + const char *filename1, *filename2; + const char *fmt; + int c1, c2, char_pos, line_pos; + int opt_flags; + int exit_val = 0; + + bb_default_error_retval = 2; /* 1 is returned if files are different. */ + + opt_flags = bb_getopt_ulflags(argc, argv, opt_chars); + + if ((opt_flags == 3) || (((unsigned int)(--argc - optind)) > 1)) { + bb_show_usage(); } - filename1 = argv[optind]; - switch (argc - optind) { - case 2: - fp2 = xfopen(filename2 = argv[optind + 1], "r"); - case 1: - fp1 = xfopen(filename1, "r"); - break; - default: - show_usage(); + fp1 = cmp_xfopen_input(filename1 = *(argv += optind)); + + filename2 = "-"; + if (*++argv) { + filename2 = *argv; } + fp2 = cmp_xfopen_input(filename2); + if (fp1 == fp2) { /* Paranioa check... stdin == stdin? */ + /* Note that we don't bother reading stdin. Neither does gnu wc. + * But perhaps we should, so that other apps down the chain don't + * get the input. Consider 'echo hello | (cmp - - && cat -)'. + */ + return 0; + } + + fmt = fmt_differ; + if (opt_flags == OPT_l) { + fmt = fmt_l_opt; + } + + char_pos = 0; + line_pos = 1; do { - c1 = fgetc(fp1); - c2 = fgetc(fp2); - if (c1 != c2) { - if (silent) - return EXIT_FAILURE; - if (c1 == EOF) - printf("EOF on %s\n", filename1); - else if (c2 == EOF) - printf("EOF on %s\n", filename2); - else - printf("%s %s differ: char %d, line %d\n", filename1, filename2, - char_pos, line_pos); - return EXIT_FAILURE; + c1 = getc(fp1); + c2 = getc(fp2); + ++char_pos; + if (c1 != c2) { /* Remember -- a read error may have occurred. */ + exit_val = 1; /* But assume the files are different for now. */ + if (c2 == EOF) { + /* We know that fp1 isn't at EOF or in an error state. But to + * save space below, things are setup to expect an EOF in fp1 + * if an EOF occurred. So, swap things around. + */ + fp1 = fp2; + filename1 = filename2; + c1 = c2; + } + if (c1 == EOF) { + bb_xferror(fp1, filename1); + fmt = fmt_eof; /* Well, no error, so it must really be EOF. */ + outfile = stderr; + /* There may have been output to stdout (option -l), so + * make sure we fflush before writing to stderr. */ + bb_xfflush_stdout(); + } + if (opt_flags != OPT_s) { + if (opt_flags == OPT_l) { + line_pos = c1; /* line_pos is unused in the -l case. */ + } + bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2); + if (opt_flags) { /* This must be -l since not -s. */ + /* If we encountered and EOF, the while check will catch it. */ + continue; + } + } + break; + } + if (c1 == '\n') { + ++line_pos; } - char_pos++; - if (c1 == '\n') - line_pos++; } while (c1 != EOF); - return EXIT_SUCCESS; + bb_xferror(fp1, filename1); + bb_xferror(fp2, filename2); + + bb_fflush_stdout_and_exit(exit_val); } diff --git a/coreutils/cp.c b/coreutils/cp.c index 8f8fe5e..c5dd31e 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -2,7 +2,6 @@ /* * Mini cp implementation for busybox * - * * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> * * This program is free software; you can redistribute it and/or modify @@ -21,6 +20,15 @@ * */ +/* BB_AUDIT SUSv3 defects - unsupported options -H, -L, and -P. */ +/* BB_AUDIT GNU defects - only extension options supported are -a and -d. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Size reduction. + */ + #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -29,86 +37,76 @@ #include <errno.h> #include <dirent.h> #include <stdlib.h> - +#include <assert.h> #include "busybox.h" +#include "libcoreutils/coreutils.h" + +static const char cp_opts[] = "pdRfia"; /* WARNING!! ORDER IS IMPORTANT!! */ extern int cp_main(int argc, char **argv) { + struct stat source_stat; + struct stat dest_stat; + const char *last; + const char *dest; + int s_flags; + int d_flags; + int flags; int status = 0; - int opt; - int flags = FILEUTILS_DEREFERENCE; - int i; - while ((opt = getopt(argc, argv, "adfipR")) != -1) - switch (opt) { - case 'a': - flags |= FILEUTILS_PRESERVE_STATUS | FILEUTILS_RECUR; - /* fallthrough */ - case 'd': - flags &= ~FILEUTILS_DEREFERENCE; - break; - case 'f': - flags |= FILEUTILS_FORCE; - break; - case 'i': - flags |= FILEUTILS_INTERACTIVE; - break; - case 'p': - flags |= FILEUTILS_PRESERVE_STATUS; - break; - case 'R': - flags |= FILEUTILS_RECUR; - break; - default: - show_usage(); - } - - if (optind + 2 > argc) - show_usage(); + /* Since these are enums, #if tests will not work. So use assert()s. */ + assert(FILEUTILS_PRESERVE_STATUS == 1); + assert(FILEUTILS_DEREFERENCE == 2); + assert(FILEUTILS_RECUR == 4); + assert(FILEUTILS_FORCE == 8); + assert(FILEUTILS_INTERACTIVE == 16); - /* If there are only two arguments and... */ - if (optind + 2 == argc) { - struct stat source_stat; - struct stat dest_stat; - int source_exists = 1; - int dest_exists = 1; + flags = bb_getopt_ulflags(argc, argv, cp_opts); - if ((!(flags & FILEUTILS_DEREFERENCE) && - lstat(argv[optind], &source_stat) < 0) || - ((flags & FILEUTILS_DEREFERENCE) && - stat(argv[optind], &source_stat))) { - if (errno != ENOENT) - perror_msg_and_die("unable to stat `%s'", argv[optind]); - source_exists = 0; - } + if (flags & 32) { + flags |= (FILEUTILS_PRESERVE_STATUS | FILEUTILS_RECUR | FILEUTILS_DEREFERENCE); + } + + flags ^= FILEUTILS_DEREFERENCE; /* The sense of this flag was reversed. */ + + if (optind + 2 > argc) { + bb_show_usage(); + } + + last = argv[argc - 1]; + argv += optind; - if (stat(argv[optind + 1], &dest_stat) < 0) { - if (errno != ENOENT) - perror_msg_and_die("unable to stat `%s'", argv[optind + 1]); - dest_exists = 0; + /* If there are only two arguments and... */ + if (optind + 2 == argc) { + s_flags = cp_mv_stat2(*argv, &source_stat, + (flags & FILEUTILS_DEREFERENCE) ? stat : lstat); + if ((s_flags < 0) || ((d_flags = cp_mv_stat(last, &dest_stat)) < 0)) { + exit(EXIT_FAILURE); } - /* ...if neither is a directory or... */ - if (((!source_exists || !S_ISDIR(source_stat.st_mode)) && - (!dest_exists || !S_ISDIR(dest_stat.st_mode))) || - /* ...recursing, the first is a directory, and the - * second doesn't exist, then... */ - ((flags & FILEUTILS_RECUR) && S_ISDIR(source_stat.st_mode) && - !dest_exists)) { + if ( !((s_flags | d_flags) & 2) || + /* ...recursing, the 1st is a directory, and the 2nd doesn't exist... */ + /* ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags) */ + /* Simplify the above since FILEUTILS_RECUR >> 1 == 2. */ + ((((flags & FILEUTILS_RECUR) >> 1) & s_flags) && !d_flags) + ) { /* ...do a simple copy. */ - if (copy_file(argv[optind], argv[optind + 1], flags) < 0) - status = 1; - return status; + dest = last; + goto DO_COPY; /* Note: optind+2==argc implies argv[1]==last below. */ } } - for (i = optind; i < argc - 1; i++) { - char *dest = concat_path_file(argv[argc - 1], - get_last_path_component(argv[i])); - if (copy_file(argv[i], dest, flags) < 0) + do { + dest = concat_path_file(last, bb_get_last_path_component(*argv)); + DO_COPY: + if (copy_file(*argv, dest, flags) < 0) { status = 1; - free(dest); - } + } + if (*++argv == last) { + break; + } + free((void *) dest); + } while (1); - return status; + exit(status); } diff --git a/coreutils/cut.c b/coreutils/cut.c index 3ed2648..c24cf66 100644 --- a/coreutils/cut.c +++ b/coreutils/cut.c @@ -92,7 +92,7 @@ static void parse_lists(char *lists) } else { s = strtoul(ntok, &junk, 10); if(*junk != '\0' || s < 0) - error_msg_and_die("invalid byte or field list"); + bb_error_msg_and_die("invalid byte or field list"); /* account for the fact that arrays are zero based, while the user * expects the first char on the line to be char # 1 */ @@ -109,7 +109,7 @@ static void parse_lists(char *lists) } else { e = strtoul(ntok, &junk, 10); if(*junk != '\0' || e < 0) - error_msg_and_die("invalid byte or field list"); + bb_error_msg_and_die("invalid byte or field list"); /* if the user specified and end position of 0, that means "til the * end of the line */ if (e == 0) @@ -121,7 +121,7 @@ static void parse_lists(char *lists) /* if there's something left to tokenize, the user past an invalid list */ if (ltok) - error_msg_and_die("invalid byte or field list"); + bb_error_msg_and_die("invalid byte or field list"); /* add the new list */ cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists)); @@ -131,7 +131,7 @@ static void parse_lists(char *lists) /* make sure we got some cut positions out of all that */ if (nlists == 0) - error_msg_and_die("missing list of positions"); + bb_error_msg_and_die("missing list of positions"); /* now that the lists are parsed, we need to sort them to make life easier * on us when it comes time to print the chars / fields / lines */ @@ -267,8 +267,7 @@ static void cut_file(FILE *file) unsigned int linenum = 0; /* keep these zero-based to be consistent */ /* go through every line in the file */ - while ((line = get_line_from_file(file)) != NULL) { - chomp(line); + while ((line = bb_get_chomped_line_from_file(file)) != NULL) { /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ if (part == 'c' || part == 'b') @@ -299,14 +298,14 @@ extern int cut_main(int argc, char **argv) case 'f': /* make sure they didn't ask for two types of lists */ if (part != 0) { - error_msg_and_die("only one type of list may be specified"); + bb_error_msg_and_die("only one type of list may be specified"); } part = (char)opt; parse_lists(optarg); break; case 'd': if (strlen(optarg) > 1) { - error_msg_and_die("the delimiter must be a single character"); + bb_error_msg_and_die("the delimiter must be a single character"); } delim = optarg[0]; break; @@ -320,17 +319,17 @@ extern int cut_main(int argc, char **argv) } if (part == 0) { - error_msg_and_die("you must specify a list of bytes, characters, or fields"); + bb_error_msg_and_die("you must specify a list of bytes, characters, or fields"); } /* non-field (char or byte) cutting has some special handling */ if (part != 'f') { if (supress_non_delimited_lines) { - error_msg_and_die("suppressing non-delimited lines makes sense" + bb_error_msg_and_die("suppressing non-delimited lines makes sense" " only when operating on fields"); } if (delim != '\t' && part != 'f') { - error_msg_and_die("a delimiter may be specified only when operating on fields"); + bb_error_msg_and_die("a delimiter may be specified only when operating on fields"); } } @@ -344,7 +343,7 @@ extern int cut_main(int argc, char **argv) int i; FILE *file; for (i = optind; i < argc; i++) { - file = wfopen(argv[i], "r"); + file = bb_wfopen(argv[i], "r"); if(file) { cut_file(file); fclose(file); diff --git a/coreutils/date.c b/coreutils/date.c index d68c04a..afbedb9 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -53,7 +53,7 @@ static struct tm *date_conv_time(struct tm *tm_time, const char *t_string) &(tm_time->tm_year)); if (nr < 4 || nr > 5) { - error_msg_and_die(invalid_date, t_string); + bb_error_msg_and_die(bb_msg_invalid_date, t_string); } /* correct for century - minor Y2K problem here? */ @@ -108,7 +108,7 @@ static struct tm *date_conv_ftime(struct tm *tm_time, const char *t_string) t.tm_year -= 1900; /* Adjust years */ t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ } else { - error_msg_and_die(invalid_date, t_string); + bb_error_msg_and_die(bb_msg_invalid_date, t_string); } *tm_time = t; return (tm_time); @@ -145,25 +145,25 @@ int date_main(int argc, char **argv) case 's': set_time = 1; if ((date_str != NULL) || ((date_str = optarg) == NULL)) { - show_usage(); + bb_show_usage(); } break; case 'u': utc = 1; if (putenv("TZ=UTC0") != 0) - error_msg_and_die(memory_exhausted); + bb_error_msg_and_die(bb_msg_memory_exhausted); break; case 'd': use_arg = 1; if ((date_str != NULL) || ((date_str = optarg) == NULL)) - show_usage(); + bb_show_usage(); break; #ifdef CONFIG_FEATURE_DATE_ISOFMT case 'I': if (!optarg) ifmt = 1; else { - int ifmt_len = xstrlen(optarg); + int ifmt_len = bb_strlen(optarg); if ((ifmt_len <= 4) && (strncmp(optarg, "date", ifmt_len) == 0)) { @@ -180,11 +180,11 @@ int date_main(int argc, char **argv) } } if (ifmt) { - break; /* else show_usage(); */ + break; /* else bb_show_usage(); */ } #endif default: - show_usage(); + bb_show_usage(); } } @@ -220,15 +220,15 @@ int date_main(int argc, char **argv) /* Correct any day of week and day of year etc. fields */ tm = mktime(&tm_time); if (tm < 0) { - error_msg_and_die(invalid_date, date_str); + bb_error_msg_and_die(bb_msg_invalid_date, date_str); } if (utc && (putenv("TZ=UTC0") != 0)) { - error_msg_and_die(memory_exhausted); + bb_error_msg_and_die(bb_msg_memory_exhausted); } /* if setting time, set it */ if (set_time && (stime(&tm) < 0)) { - perror_msg("cannot set date"); + bb_perror_msg("cannot set date"); } } diff --git a/coreutils/dd.c b/coreutils/dd.c index 8c7272b..1150861 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -62,19 +62,19 @@ int dd_main(int argc, char **argv) int ifd; int ofd; int i; - char *infile = NULL; - char *outfile = NULL; + const char *infile = NULL; + const char *outfile = NULL; char *buf; for (i = 1; i < argc; i++) { if (strncmp("bs=", argv[i], 3) == 0) - bs = parse_number(argv[i]+3, dd_suffixes); + bs = bb_xparse_number(argv[i]+3, dd_suffixes); else if (strncmp("count=", argv[i], 6) == 0) - count = parse_number(argv[i]+6, dd_suffixes); + count = bb_xparse_number(argv[i]+6, dd_suffixes); else if (strncmp("seek=", argv[i], 5) == 0) - seek = parse_number(argv[i]+5, dd_suffixes); + seek = bb_xparse_number(argv[i]+5, dd_suffixes); else if (strncmp("skip=", argv[i], 5) == 0) - skip = parse_number(argv[i]+5, dd_suffixes); + skip = bb_xparse_number(argv[i]+5, dd_suffixes); else if (strncmp("if=", argv[i], 3) == 0) infile = argv[i]+3; else if (strncmp("of=", argv[i], 3) == 0) @@ -92,7 +92,7 @@ int dd_main(int argc, char **argv) noerror = TRUE; buf += 7; } else { - error_msg_and_die("invalid conversion `%s'", argv[i]+5); + bb_error_msg_and_die("invalid conversion `%s'", argv[i]+5); } if (buf[0] == '\0') break; @@ -100,18 +100,18 @@ int dd_main(int argc, char **argv) buf++; } } else - show_usage(); + bb_show_usage(); } buf = xmalloc(bs); if (infile != NULL) { if ((ifd = open(infile, O_RDONLY)) < 0) { - perror_msg_and_die("%s", infile); + bb_perror_msg_and_die("%s", infile); } } else { ifd = STDIN_FILENO; - infile = "standard input"; + infile = bb_msg_standard_input; } if (outfile != NULL) { @@ -122,7 +122,7 @@ int dd_main(int argc, char **argv) } if ((ofd = open(outfile, oflag, 0666)) < 0) { - perror_msg_and_die("%s", outfile); + bb_perror_msg_and_die("%s", outfile); } if (seek && trunc) { @@ -131,24 +131,24 @@ int dd_main(int argc, char **argv) if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) || S_ISDIR (st.st_mode)) { - perror_msg_and_die("%s", outfile); + bb_perror_msg_and_die("%s", outfile); } } } } else { ofd = STDOUT_FILENO; - outfile = "standard output"; + outfile = bb_msg_standard_output; } if (skip) { if (lseek(ifd, skip * bs, SEEK_CUR) < 0) { - perror_msg_and_die("%s", infile); + bb_perror_msg_and_die("%s", infile); } } if (seek) { if (lseek(ofd, seek * bs, SEEK_CUR) < 0) { - perror_msg_and_die("%s", outfile); + bb_perror_msg_and_die("%s", outfile); } } @@ -161,9 +161,9 @@ int dd_main(int argc, char **argv) if (n < 0) { if (noerror) { n = bs; - perror_msg("%s", infile); + bb_perror_msg("%s", infile); } else { - perror_msg_and_die("%s", infile); + bb_perror_msg_and_die("%s", infile); } } if (n == 0) { @@ -178,9 +178,9 @@ int dd_main(int argc, char **argv) memset(buf + n, '\0', bs - n); n = bs; } - n = full_write(ofd, buf, n); + n = bb_full_write(ofd, buf, n); if (n < 0) { - perror_msg_and_die("%s", outfile); + bb_perror_msg_and_die("%s", outfile); } if (n == bs) { out_full++; @@ -190,15 +190,16 @@ int dd_main(int argc, char **argv) } if (close (ifd) < 0) { - perror_msg_and_die("%s", infile); + bb_perror_msg_and_die("%s", infile); } if (close (ofd) < 0) { - perror_msg_and_die("%s", outfile); + bb_perror_msg_and_die("%s", outfile); } - fprintf(stderr, "%ld+%ld records in\n", (long)in_full, (long)in_part); - fprintf(stderr, "%ld+%ld records out\n", (long)out_full, (long)out_part); + fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n", + (long)in_full, (long)in_part, + (long)out_full, (long)out_part); return EXIT_SUCCESS; } diff --git a/coreutils/df.c b/coreutils/df.c index 0e9e5d6..7d007a0 100644 --- a/coreutils/df.c +++ b/coreutils/df.c @@ -22,74 +22,45 @@ * */ +/* BB_AUDIT SUSv3 _NOT_ compliant -- options -P and -t missing. Also blocksize. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/df.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Size reduction. Removed floating point dependency. Added error checking + * on output. Output stats on 0-sized filesystems if specificly listed on + * the command line. Properly round *-blocks, Used, and Available quantities. + */ + #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include <mntent.h> #include <sys/vfs.h> -#include <getopt.h> #include "busybox.h" -extern const char mtab_file[]; /* Defined in utility.c */ -#ifdef CONFIG_FEATURE_HUMAN_READABLE -static unsigned long df_disp_hr = KILOBYTE; +#ifndef CONFIG_FEATURE_HUMAN_READABLE +static long kscale(long b, long bs) +{ + return ( b * (long long) bs + KILOBYTE/2 ) / KILOBYTE; +} #endif -static int do_df(char *device, const char *mount_point) +extern int df_main(int argc, char **argv) { - struct statfs s; long blocks_used; long blocks_percent_used; - - if (statfs(mount_point, &s) != 0) { - perror_msg("%s", mount_point); - return FALSE; - } - - if (s.f_blocks > 0) { - blocks_used = s.f_blocks - s.f_bfree; - if(blocks_used == 0) - blocks_percent_used = 0; - else { - blocks_percent_used = (long) - (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5); - } - if (strcmp(device, "/dev/root") == 0) { - /* Adjusts device to be the real root device, - * or leaves device alone if it can't find it */ - device = find_real_root_device_name(device); - if(device==NULL) - return FALSE; - } #ifdef CONFIG_FEATURE_HUMAN_READABLE - printf("%-20s %9s ", device, - make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr)); - - printf("%9s ", - make_human_readable_str( (s.f_blocks - s.f_bfree), s.f_bsize, df_disp_hr)); - - printf("%9s %3ld%% %s\n", - make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr), - blocks_percent_used, mount_point); -#else - printf("%-20s %9ld %9ld %9ld %3ld%% %s\n", - device, - (long) (s.f_blocks * (s.f_bsize / (double)KILOBYTE)), - (long) ((s.f_blocks - s.f_bfree)*(s.f_bsize/(double)KILOBYTE)), - (long) (s.f_bavail * (s.f_bsize / (double)KILOBYTE)), - blocks_percent_used, mount_point); + unsigned long df_disp_hr = KILOBYTE; #endif - } - - return TRUE; -} - -extern int df_main(int argc, char **argv) -{ int status = EXIT_SUCCESS; - int opt = 0; - int i = 0; - char disp_units_hdr[80] = "1k-blocks"; /* default display is kilobytes */ + int opt; + FILE *mount_table; + struct mntent *mount_entry; + struct statfs s; + static const char hdr_1k[] = "1k-blocks"; /* default display is kilobytes */; + const char *disp_units_hdr = hdr_1k; while ((opt = getopt(argc, argv, "k" #ifdef CONFIG_FEATURE_HUMAN_READABLE @@ -101,52 +72,106 @@ extern int df_main(int argc, char **argv) #ifdef CONFIG_FEATURE_HUMAN_READABLE case 'h': df_disp_hr = 0; - strcpy(disp_units_hdr, " Size"); + disp_units_hdr = " Size"; break; case 'm': df_disp_hr = MEGABYTE; - strcpy(disp_units_hdr, "1M-blocks"); + disp_units_hdr = "1M-blocks"; break; #endif case 'k': /* default display is kilobytes */ +#ifdef CONFIG_FEATURE_HUMAN_READABLE + df_disp_hr = KILOBYTE; + disp_units_hdr = hdr_1k; +#endif break; default: - show_usage(); + bb_show_usage(); } } - printf("%-20s %-14s %s %s %s %s\n", "Filesystem", disp_units_hdr, - "Used", "Available", "Use%", "Mounted on"); + bb_printf("Filesystem%11s%-15sUsed Available Use%% Mounted on\n", + "", disp_units_hdr); - if(optind < argc) { - struct mntent *mount_entry; - for(i = optind; i < argc; i++) - { - if ((mount_entry = find_mount_point(argv[i], mtab_file)) == 0) { - error_msg("%s: can't find mount point.", argv[i]); - status = EXIT_FAILURE; - } else if (!do_df(mount_entry->mnt_fsname, mount_entry->mnt_dir)) - status = EXIT_FAILURE; + mount_table = NULL; + argv += optind; + if (optind >= argc) { + if (!(mount_table = setmntent(bb_path_mtab_file, "r"))) { + bb_perror_msg_and_die(bb_path_mtab_file); } - } else { - FILE *mount_table; - struct mntent *mount_entry; + } - mount_table = setmntent(mtab_file, "r"); - if (mount_table == 0) { - perror_msg("%s", mtab_file); - return EXIT_FAILURE; - } + do { + const char *device; + const char *mount_point; - while ((mount_entry = getmntent(mount_table))) { - if (!do_df(mount_entry->mnt_fsname, mount_entry->mnt_dir)) + if (mount_table) { + if (!(mount_entry = getmntent(mount_table))) { + endmntent(mount_table); + break; + } + } else { + if (!(mount_point = *argv++)) { + break; + } + if (!(mount_entry = find_mount_point(mount_point, bb_path_mtab_file))) { + bb_error_msg("%s: can't find mount point.", mount_point); + SET_ERROR: status = EXIT_FAILURE; + continue; + } } - endmntent(mount_table); - } - return status; + device = mount_entry->mnt_fsname; + mount_point = mount_entry->mnt_dir; + + if (statfs(mount_point, &s) != 0) { + bb_perror_msg("%s", mount_point); + goto SET_ERROR; + } + + if ((s.f_blocks > 0) || !mount_table){ + blocks_used = s.f_blocks - s.f_bfree; + blocks_percent_used = 0; + if (blocks_used + s.f_bavail) { + blocks_percent_used = (((long long) blocks_used) * 100 + + (blocks_used + s.f_bavail)/2 + ) / (blocks_used + s.f_bavail); + } + + if (strcmp(device, "/dev/root") == 0) { + /* Adjusts device to be the real root device, + * or leaves device alone if it can't find it */ + if ((device = find_real_root_device_name(device)) != NULL) { + goto SET_ERROR; + } + } + +#ifdef CONFIG_FEATURE_HUMAN_READABLE + bb_printf("%-21s%9s ", device, + make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr)); + + bb_printf("%9s ", + make_human_readable_str( (s.f_blocks - s.f_bfree), + s.f_bsize, df_disp_hr)); + + bb_printf("%9s %3ld%% %s\n", + make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr), + blocks_percent_used, mount_point); +#else + bb_printf("%-21s%9ld %9ld %9ld %3ld%% %s\n", + device, + kscale(s.f_blocks, s.f_bsize), + kscale(s.f_blocks-s.f_bfree, s.f_bsize), + kscale(s.f_bavail, s.f_bsize), + blocks_percent_used, mount_point); +#endif + } + + } while (1); + + bb_fflush_stdout_and_exit(status); } /* diff --git a/coreutils/dirname.c b/coreutils/dirname.c index 3872337..4c6115e 100644 --- a/coreutils/dirname.c +++ b/coreutils/dirname.c @@ -21,20 +21,20 @@ * */ -/* getopt not needed */ +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/dirname.html */ #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "busybox.h" extern int dirname_main(int argc, char **argv) { - if ((argc < 2) || (**(argv + 1) == '-')) - show_usage(); - argv++; + if (argc != 2) { + bb_show_usage(); + } - puts (dirname (argv[0])); + puts(dirname(argv[1])); - return EXIT_SUCCESS; + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c index b1d0a9d..c28e6a8 100644 --- a/coreutils/dos2unix.c +++ b/coreutils/dos2unix.c @@ -35,6 +35,10 @@ #include <sys/time.h> #include "busybox.h" +#define CT_AUTO 0 +#define CT_UNIX2DOS 1 +#define CT_DOS2UNIX 2 + /* We are making a lame pseudo-random string generator here. in * convert(), each pass through the while loop will add more and more * stuff into value, which is _supposed_ to wrap. We don't care about @@ -55,15 +59,13 @@ static int convert(char *fn, int ConvType) FILE *in = stdin, *out = stdout; if (fn != NULL) { - if ((in = wfopen(fn, "rw")) == NULL) { - return -1; - } + in = bb_xfopen(fn, "rw"); safe_strncpy(tempFn, fn, sizeof(tempFn)); c = strlen(tempFn); tempFn[c] = '.'; while(1) { if (c >=BUFSIZ) - error_msg_and_die("unique name not found"); + bb_error_msg_and_die("unique name not found"); /* Get some semi random stuff to try and make a * random filename based (and in the same dir as) * the input file... */ @@ -92,7 +94,7 @@ static int convert(char *fn, int ConvType) // file is alredy in DOS format so it is not necessery to touch it remove(tempFn); if (fclose(in) < 0 || fclose(out) < 0) { - perror_msg(NULL); + bb_perror_nomsg(); return -2; } return 0; @@ -106,7 +108,7 @@ static int convert(char *fn, int ConvType) // file is alredy in UNIX format so it is not necessery to touch it remove(tempFn); if ((fclose(in) < 0) || (fclose(out) < 0)) { - perror_msg(NULL); + bb_perror_nomsg(); return -2; } return 0; @@ -137,7 +139,7 @@ static int convert(char *fn, int ConvType) if (fn != NULL) { if (fclose(in) < 0 || fclose(out) < 0) { - perror_msg(NULL); + bb_perror_nomsg(); remove(tempFn); return -2; } @@ -146,7 +148,7 @@ static int convert(char *fn, int ConvType) * should be true since we put them into the same directory * so we _should_ be ok, but you never know... */ if (rename(tempFn, fn) < 0) { - perror_msg("unable to rename '%s' as '%s'", tempFn, fn); + bb_perror_msg("unable to rename '%s' as '%s'", tempFn, fn); return -1; } } @@ -177,7 +179,7 @@ int dos2unix_main(int argc, char *argv[]) ConvType = CT_DOS2UNIX; break; default: - show_usage(); + bb_show_usage(); } } diff --git a/coreutils/du.c b/coreutils/du.c index 2e49b21..702a9aa 100644 --- a/coreutils/du.c +++ b/coreutils/du.c @@ -22,45 +22,65 @@ * */ -#include <sys/types.h> -#include <fcntl.h> -#include <dirent.h> -#include <stdio.h> +/* BB_AUDIT SUSv3 compliant (unless default blocksize set to 1k) */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/du.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Mostly rewritten for SUSv3 compliance and to fix bugs/defects. + * 1) Added support for SUSv3 -a, -H, -L, gnu -c, and (busybox) -d options. + * The -d option allows setting of max depth (similar to gnu --max-depth). + * 2) Fixed incorrect size calculations for links and directories, especially + * when errors occurred. Calculates sizes should now match gnu du output. + * 3) Added error checking of output. + * 4) Fixed busybox bug #1284 involving long overflow with human_readable. + */ + #include <stdlib.h> -#include <getopt.h> -#include <string.h> -#include <errno.h> +#include <limits.h> +#include <unistd.h> +#include <dirent.h> +#include <sys/stat.h> #include "busybox.h" - #ifdef CONFIG_FEATURE_HUMAN_READABLE +# ifdef CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K static unsigned long disp_hr = KILOBYTE; +# else +static unsigned long disp_hr = 512; +# endif +#elif defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K +static unsigned int disp_k = 1; +#else +static unsigned int disp_k; /* bss inits to 0 */ #endif -static int du_depth /*= 0*/; -static int count_hardlinks /*= 0*/; -static int one_file_system /*= 0*/; +static int max_print_depth = INT_MAX; +static int count_hardlinks = INT_MAX; + +static int status +#if EXIT_SUCCESS == 0 + = EXIT_SUCCESS +#endif + ; +static int print_files; +static int slink_depth; +static int du_depth; +static int one_file_system; static dev_t dir_dev; -static void (*print) (long, char *); -static void print_normal(long size, char *filename) +static void print(long size, char *filename) { + /* TODO - May not want to defer error checking here. */ #ifdef CONFIG_FEATURE_HUMAN_READABLE - printf("%s\t%s\n", make_human_readable_str(size << 10, 1, disp_hr), + bb_printf("%s\t%s\n", make_human_readable_str(size, 512, disp_hr), filename); #else - printf("%ld\t%s\n", size, filename); + bb_printf("%ld\t%s\n", size >> disp_k, filename); #endif } -static void print_summary(long size, char *filename) -{ - if (du_depth == 1) { - print_normal(size, filename); - } -} - /* tiny recursive du */ static long du(char *filename) { @@ -68,23 +88,43 @@ static long du(char *filename) long sum; if ((lstat(filename, &statbuf)) != 0) { - perror_msg("%s", filename); + bb_perror_msg("%s", filename); + status = EXIT_FAILURE; return 0; } - if (du_depth == 0) - dir_dev = statbuf.st_dev; - else if (one_file_system && dir_dev != statbuf.st_dev) - return 0; - du_depth++; - sum = (statbuf.st_blocks >> 1); + if (one_file_system) { + if (du_depth == 0) { + dir_dev = statbuf.st_dev; + } else if (dir_dev != statbuf.st_dev) { + return 0; + } + } + + sum = statbuf.st_blocks; - /* Don't add in stuff pointed to by symbolic links */ if (S_ISLNK(statbuf.st_mode)) { - sum = 0L; - if (du_depth == 1) { + if (slink_depth > du_depth) { /* -H or -L */ + if ((stat(filename, &statbuf)) != 0) { + bb_perror_msg("%s", filename); + status = EXIT_FAILURE; + return 0; + } + sum = statbuf.st_blocks; + if (slink_depth == 1) { + slink_depth = INT_MAX; /* Convert -H to -L. */ + } } } + + if (statbuf.st_nlink > count_hardlinks) { + /* Add files/directories with links only once */ + if (is_in_ino_dev_hashtable(&statbuf, NULL)) { + return 0; + } + add_to_ino_dev_hashtable(&statbuf, NULL); + } + if (S_ISDIR(statbuf.st_mode)) { DIR *dir; struct dirent *entry; @@ -92,8 +132,9 @@ static long du(char *filename) dir = opendir(filename); if (!dir) { - du_depth--; - return 0; + bb_perror_msg("%s", filename); + status = EXIT_FAILURE; + return sum; } newfile = last_char_is(filename, '/'); @@ -103,54 +144,86 @@ static long du(char *filename) while ((entry = readdir(dir))) { char *name = entry->d_name; - if ((strcmp(name, "..") == 0) - || (strcmp(name, ".") == 0)) { + if ((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2]))) { continue; } newfile = concat_path_file(filename, name); + ++du_depth; sum += du(newfile); + --du_depth; free(newfile); } closedir(dir); + } else if (du_depth > print_files) { + return sum; + } + if (du_depth <= max_print_depth) { print(sum, filename); - } else if (statbuf.st_nlink > 1 && !count_hardlinks) { - /* Add files with hard links only once */ - if (is_in_ino_dev_hashtable(&statbuf, NULL)) { - sum = 0L; - if (du_depth == 1) - print(sum, filename); - } else { - add_to_ino_dev_hashtable(&statbuf, NULL); - } } - du_depth--; return sum; } int du_main(int argc, char **argv) { - int status = EXIT_SUCCESS; - int i; + long total; + int slink_depth_save; + int print_final_total = 0; int c; - /* default behaviour */ - print = print_normal; +#ifdef CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K + if (getenv("POSIXLY_CORRECT")) { /* TODO - a new libbb function? */ +#ifdef CONFIG_FEATURE_HUMAN_READABLE + disp_hr = 512; +#else + disp_k = 0; +#endif + } +#endif + + /* Note: SUSv3 specifies that -a and -s options can not be used together + * in strictly conforming applications. However, it also says that some + * du implementations may produce output when -a and -s are used together. + * gnu du exits with an error code in this case. We choose to simply + * ignore -a. This is consistent with -s being equivalent to -d 0. + */ - /* parse argv[] */ - while ((c = getopt(argc, argv, "slx" + while ((c = getopt(argc, argv, "aHkLsx" "d:" "lc" #ifdef CONFIG_FEATURE_HUMAN_READABLE "hm" #endif - "k")) != EOF) { + )) > 0) { switch (c) { + case 'a': + print_files = INT_MAX; + break; + case 'H': + slink_depth = 1; + break; + case 'k': +#ifdef CONFIG_FEATURE_HUMAN_READABLE + disp_hr = KILOBYTE; +#elif !defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K + disp_k = 1; +#endif + break; + case 'L': + slink_depth = INT_MAX; + break; case 's': - print = print_summary; + max_print_depth = 0; + break; + case 'x': + one_file_system = 1; + break; + + case 'd': + max_print_depth = bb_xgetularg10_bnd(optarg, 0, INT_MAX); break; case 'l': count_hardlinks = 1; break; - case 'x': - one_file_system = 1; + case 'c': + print_final_total = 1; break; #ifdef CONFIG_FEATURE_HUMAN_READABLE case 'h': @@ -160,37 +233,31 @@ int du_main(int argc, char **argv) disp_hr = MEGABYTE; break; #endif - case 'k': - break; default: - show_usage(); + bb_show_usage(); } } /* go through remaining args (if any) */ + argv += optind; if (optind >= argc) { - if (du(".") == 0) - status = EXIT_FAILURE; - } else { - long sum; - - for (i = optind; i < argc; i++) { - sum = du(argv[i]); - if (is_directory(argv[i], FALSE, NULL) == FALSE) { - print_normal(sum, argv[i]); - } - reset_ino_dev_hashtable(); + *--argv = "."; + if (slink_depth == 1) { + slink_depth = 0; } } - return status; -} + slink_depth_save = slink_depth; + total = 0; + do { + total += du(*argv); + slink_depth = slink_depth_save; + } while (*++argv); + reset_ino_dev_hashtable(); -/* $Id: du.c,v 1.55 2002/08/23 07:28:45 aaronl Exp $ */ -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ + if (print_final_total) { + print(total, "total"); + } + + bb_fflush_stdout_and_exit(status); +} diff --git a/coreutils/echo.c b/coreutils/echo.c index 31c0315..b600a1f 100644 --- a/coreutils/echo.c +++ b/coreutils/echo.c @@ -22,94 +22,107 @@ * Original copyright notice is retained at the end of this file. */ +/* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Because of behavioral differences, implemented configureable SUSv3 + * or 'fancy' gnu-ish behaviors. Also, reduced size and fixed bugs. + * 1) In handling '\c' escape, the previous version only suppressed the + * trailing newline. SUSv3 specifies _no_ output after '\c'. + * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}. + * The previous version version did not allow 4-digit octals. + */ + #include <stdio.h> #include <string.h> #include <stdlib.h> #include "busybox.h" -extern int -echo_main(int argc, char** argv) +extern int echo_main(int argc, char** argv) { - int nflag = 0; +#ifndef CONFIG_FEATURE_FANCY_ECHO +#define eflag '\\' + ++argv; +#else + const char *p; + int nflag = 1; int eflag = 0; - /* Skip argv[0]. */ - argc--; - argv++; - - while (argc > 0 && *argv[0] == '-') - { - register char *temp; - register int ix; - - /* - * If it appears that we are handling options, then make sure + while (*++argv && (**argv == '-')) { + /* If it appears that we are handling options, then make sure * that all of the options specified are actually valid. * Otherwise, the string should just be echoed. */ - temp = argv[0] + 1; - - for (ix = 0; temp[ix]; ix++) - { - if (strrchr("neE", temp[ix]) == 0) - goto just_echo; - } - - if (!*temp) + + if (!*(p = *argv + 1)) { /* A single '-', so echo it. */ goto just_echo; + } - /* - * All of the options in temp are valid options to echo. - * Handle them. - */ - while (*temp) - { - if (*temp == 'n') - nflag = 1; - else if (*temp == 'e') - eflag = 1; - else if (*temp == 'E') - eflag = 0; - else + do { + if (strrchr("neE", *p) == 0) { goto just_echo; + } + } while (*++p); - temp++; - } - argc--; - argv++; + /* All of the options in this arg are valid, so handle them. */ + p = *argv + 1; + do { + if (*p == 'n') { + nflag = 0; + } else if (*p == 'e') { + eflag = '\\'; + } else { + eflag = 0; + } + } while (*++p); } just_echo: - while (argc > 0) { - const char *arg = argv[0]; +#endif + while (*argv) { register int c; - while ((c = *arg++)) { - - /* Check for escape sequence. */ - if (c == '\\' && eflag && *arg) { - if (*arg == 'c') { - /* '\c' means cancel newline. */ - nflag = 1; - arg++; - continue; - } else { - c = process_escape_sequence(&arg); + while ((c = *(*argv)++)) { + if (c == eflag) { /* Check for escape seq. */ + if (**argv == 'c') { + /* '\c' means cancel newline and + * ignore all subsequent chars. */ + goto DONE; + } +#ifndef CONFIG_FEATURE_FANCY_ECHO + /* SUSv3 specifies that octal escapes must begin with '0'. */ + if (((unsigned int)(**argv - '1')) >= 7) +#endif + { + /* Since SUSv3 mandates a first digit of 0, 4-digit octals + * of the form \0### are accepted. */ + if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) { + (*argv)++; + } + /* bb_process_escape_sequence can handle nul correctly */ + c = bb_process_escape_sequence((const char **) argv); } } - putchar(c); } - argc--; - argv++; - if (argc > 0) + + if (*++argv) { putchar(' '); + } } - if (!nflag) + +#ifdef CONFIG_FEATURE_FANCY_ECHO + if (nflag) { putchar('\n'); - fflush(stdout); + } +#else + putchar('\n'); +#endif - return EXIT_SUCCESS; +DONE: + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } /*- diff --git a/coreutils/env.c b/coreutils/env.c index 8bb690b..db13b3a 100644 --- a/coreutils/env.c +++ b/coreutils/env.c @@ -24,50 +24,66 @@ * Modified for BusyBox by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> */ +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/env.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Fixed bug involving exit return codes if execvp fails. Also added + * output error checking. + */ + #include <stdio.h> #include <string.h> -#include <getopt.h> #include <stdlib.h> +#include <errno.h> #include <unistd.h> #include "busybox.h" extern int env_main(int argc, char** argv) { char **ep, *p; - char *cleanenv[1]; - int ignore_environment = 0; + char *cleanenv[1] = { NULL }; int ch; - while ((ch = getopt(argc, argv, "+iu:")) != -1) { + while ((ch = getopt(argc, argv, "iu:")) > 0) { switch(ch) { case 'i': - ignore_environment = 1; + environ = cleanenv; break; case 'u': unsetenv(optarg); break; default: - show_usage(); + bb_show_usage(); } } - if (optind != argc && !strcmp(argv[optind], "-")) { - ignore_environment = 1; - argv++; - } - if (ignore_environment) { + + argv += optind; + + if (*argv && (argv[0][0] == '-') && !argv[0][1]) { environ = cleanenv; - cleanenv[0] = NULL; + ++argv; } - for (argv += optind; *argv && (p = strchr(*argv, '=')); ++argv) - if (putenv(*argv) < 0) - perror_msg_and_die("%s", *argv); + + while (*argv && ((p = strchr(*argv, '=')) != NULL)) { + if (putenv(*argv) < 0) { + bb_perror_msg_and_die("putenv"); + } + ++argv; + } + if (*argv) { execvp(*argv, argv); - perror_msg_and_die("%s", *argv); + bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */ + return (errno == ENOENT) ? 127 : 126; /* SUSv3-mandated exit codes. */ } - for (ep = environ; *ep; ep++) + + for (ep = environ; *ep; ep++) { puts(*ep); - return 0; + } + + bb_fflush_stdout_and_exit(0); } /* diff --git a/coreutils/expr.c b/coreutils/expr.c index 55ae3a9..ecba825 100644 --- a/coreutils/expr.c +++ b/coreutils/expr.c @@ -78,14 +78,14 @@ int expr_main (int argc, char **argv) VALUE *v; if (argc == 1) { - error_msg_and_die("too few arguments"); + bb_error_msg_and_die("too few arguments"); } args = argv + 1; v = eval (); if (*args) - error_msg_and_die ("syntax error"); + bb_error_msg_and_die ("syntax error"); if (v->type == integer) printf ("%d\n", v->u.i); @@ -147,7 +147,7 @@ static int null (VALUE *v) static void tostring (VALUE *v) { if (v->type == integer) { - bb_asprintf (&(v->u.s), "%d", v->u.i); + bb_xasprintf (&(v->u.s), "%d", v->u.i); v->type = string; } } @@ -216,7 +216,7 @@ static \ int name (VALUE *l, VALUE *r) \ { \ if (!toarith (l) || !toarith (r)) \ - error_msg_and_die ("non-numeric argument"); \ + bb_error_msg_and_die ("non-numeric argument"); \ return l->u.i op r->u.i; \ } @@ -224,9 +224,9 @@ int name (VALUE *l, VALUE *r) \ static int name (VALUE *l, VALUE *r) \ { \ if (!toarith (l) || !toarith (r)) \ - error_msg_and_die ( "non-numeric argument"); \ + bb_error_msg_and_die ( "non-numeric argument"); \ if (r->u.i == 0) \ - error_msg_and_die ( "division by zero"); \ + bb_error_msg_and_die ( "division by zero"); \ return l->u.i op r->u.i; \ } @@ -270,7 +270,7 @@ of a basic regular expression is not portable; it is being ignored", re_syntax_options = RE_SYNTAX_POSIX_BASIC; errmsg = re_compile_pattern (pv->u.s, len, &re_buffer); if (errmsg) { - error_msg_and_die("%s", errmsg); + bb_error_msg_and_die("%s", errmsg); } len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs); @@ -301,19 +301,19 @@ static VALUE *eval7 (void) VALUE *v; if (!*args) - error_msg_and_die ( "syntax error"); + bb_error_msg_and_die ( "syntax error"); if (nextarg ("(")) { args++; v = eval (); if (!nextarg (")")) - error_msg_and_die ( "syntax error"); + bb_error_msg_and_die ( "syntax error"); args++; return v; } if (nextarg (")")) - error_msg_and_die ( "syntax error"); + bb_error_msg_and_die ( "syntax error"); return str_value (*args++); } @@ -327,7 +327,7 @@ static VALUE *eval6 (void) if (nextarg ("quote")) { args++; if (!*args) - error_msg_and_die ( "syntax error"); + bb_error_msg_and_die ( "syntax error"); return str_value (*args++); } else if (nextarg ("length")) { @@ -373,7 +373,7 @@ static VALUE *eval6 (void) else { v = xmalloc (sizeof(VALUE)); v->type = string; - v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i); + v->u.s = bb_xstrndup(l->u.s + i1->u.i - 1, i2->u.i); } freev (l); freev (i1); diff --git a/coreutils/false.c b/coreutils/false.c index 96b1849..c17de76 100644 --- a/coreutils/false.c +++ b/coreutils/false.c @@ -21,7 +21,8 @@ * */ -/* getopt not needed */ +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/false.html */ #include <stdlib.h> #include "busybox.h" diff --git a/coreutils/head.c b/coreutils/head.c index ad21e1b..dab4de1 100644 --- a/coreutils/head.c +++ b/coreutils/head.c @@ -1,9 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini head implementation for busybox + * head implementation for busybox * - * Copyright (C) 1999 by Lineo, inc. and John Beppu - * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.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 @@ -21,82 +20,119 @@ * */ +/* BB_AUDIT SUSv3 compliant */ +/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */ + #include <stdio.h> -#include <getopt.h> #include <stdlib.h> -#include <string.h> +#include <limits.h> #include <ctype.h> +#include <unistd.h> #include "busybox.h" -static int head(int len, FILE *fp) -{ - int i; - char *input; +static const char head_opts[] = + "n:" +#ifdef CONFIG_FEATURE_FANCY_HEAD + "c:qv" +#endif + ; - for (i = 0; i < len; i++) { - if ((input = get_line_from_file(fp)) == NULL) - break; - fputs(input, stdout); - free(input); - } - return 0; -} +static const char header_fmt_str[] = "\n==> %s <==\n"; -/* BusyBoxed head(1) */ int head_main(int argc, char **argv) { + unsigned long count = 10; + unsigned long i; +#ifdef CONFIG_FEATURE_FANCY_HEAD + int count_bytes = 0; + int header_threshhold = 1; +#endif + FILE *fp; - int need_headers, opt, len = 10, status = EXIT_SUCCESS; + const char *fmt; + char *p; + int opt; + int c; + int retval = EXIT_SUCCESS; - if (( argc >= 2 ) && ( argv [1][0] == '-' ) && isdigit ( argv [1][1] )) { - len = atoi ( &argv [1][1] ); - optind = 2; + /* Allow legacy syntax of an initial numeric option without -n. */ + if ((argc > 1) && (argv[1][0] == '-') + /* && (isdigit)(argv[1][1]) */ + && (((unsigned int)(argv[1][1] - '0')) <= 9) + ) { + --argc; + ++argv; + p = (*argv) + 1; + goto GET_COUNT; } - /* parse argv[] */ - while ((opt = getopt(argc, argv, "n:")) > 0) { - switch (opt) { - case 'n': - len = atoi(optarg); - if (len >= 0) + while ((opt = getopt(argc, argv, head_opts)) > 0) { + switch(opt) { +#ifdef CONFIG_FEATURE_FANCY_HEAD + case 'q': + header_threshhold = INT_MAX; + break; + case 'v': + header_threshhold = -1; break; - /* fallthrough */ - default: - show_usage(); + case 'c': + count_bytes = 1; + /* fall through */ +#endif + case 'n': + p = optarg; + GET_COUNT: + count = bb_xgetularg10(p); + break; + default: + bb_show_usage(); } } - /* get rest of argv[] or stdin if nothing's left */ - if (argv[optind] == NULL) { - head(len, stdin); - return status; - } + argv += optind; + if (!*argv) { + *--argv = "-"; + } - need_headers = optind != (argc - 1); - while (argv[optind]) { - if (strcmp(argv[optind], "-") == 0) { - fp = stdin; - argv[optind] = "standard input"; - } else { - if ((fp = wfopen(argv[optind], "r")) == NULL) - status = EXIT_FAILURE; - } - if (fp) { - if (need_headers) { - printf("==> %s <==\n", argv[optind]); + fmt = header_fmt_str + 1; +#ifdef CONFIG_FEATURE_FANCY_HEAD + if (argc - optind <= header_threshhold) { + header_threshhold = 0; + } +#else + if (argc <= optind + 1) { + fmt += 11; + } + /* Now define some things here to avoid #ifdefs in the code below. + * These should optimize out of the if conditions below. */ +#define header_threshhold 1 +#define count_bytes 0 +#endif + + do { + if ((fp = bb_wfopen_input(*argv)) != NULL) { + if (fp == stdin) { + *argv = (char *) bb_msg_standard_input; } - head(len, fp); - if (ferror(fp)) { - perror_msg("%s", argv[optind]); - status = EXIT_FAILURE; + if (header_threshhold) { + bb_printf(fmt, *argv); } - if (optind < argc - 1) - putchar('\n'); - if (fp != stdin) - fclose(fp); + i = count; + while (i && ((c = getc(fp)) != EOF)) { + if (count_bytes || (c == '\n')) { + --i; + } + putchar(c); + } + if (bb_fclose_nonstdin(fp)) { + bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */ + retval = EXIT_FAILURE; + } + bb_xferror_stdout(); } - optind++; - } + fmt = header_fmt_str; + } while (*++argv); - return status; + bb_fflush_stdout_and_exit(retval); } diff --git a/coreutils/hostid.c b/coreutils/hostid.c index 68a2cc6..917dc22 100644 --- a/coreutils/hostid.c +++ b/coreutils/hostid.c @@ -20,13 +20,19 @@ * */ -#include <stdio.h> +/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */ + #include <stdlib.h> #include <unistd.h> #include "busybox.h" extern int hostid_main(int argc, char **argv) { - printf("%lx\n", gethostid()); - return EXIT_SUCCESS; + if (argc > 1) { + bb_show_usage(); + } + + bb_printf("%lx\n", gethostid()); + + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } diff --git a/coreutils/id.c b/coreutils/id.c index c7f6153..9b2d60d 100644 --- a/coreutils/id.c +++ b/coreutils/id.c @@ -20,6 +20,8 @@ * */ +/* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */ + #include "busybox.h" #include <stdio.h> #include <unistd.h> @@ -27,70 +29,58 @@ #include <string.h> #include <sys/types.h> +#define NO_GROUP 1 +#define NO_USER 2 +#define PRINT_REAL 4 +#define NAME_NOT_NUMBER 8 + extern int id_main(int argc, char **argv) { - int no_user = 0, no_group = 0, print_real = 0; - int name_not_number = 0; char user[9], group[9]; - long gid; long pwnam, grnam; - int opt; + int uid, gid; + int flags; - gid = 0; + flags = bb_getopt_ulflags(argc, argv, "ugrn"); - while ((opt = getopt(argc, argv, "ugrn")) > 0) { - switch (opt) { - case 'u': - no_group++; - break; - case 'g': - no_user++; - break; - case 'r': - print_real++; - break; - case 'n': - name_not_number++; - break; - default: - show_usage(); - } + if (((flags & (NO_USER | NO_GROUP)) == (NO_USER | NO_GROUP)) + || (argc > optind + 1) + ) { + bb_show_usage(); } - if (no_user && no_group) show_usage(); - if (argv[optind] == NULL) { - if (print_real) { - my_getpwuid(user, getuid()); - my_getgrgid(group, getgid()); + if (flags & PRINT_REAL) { + uid = getuid(); + gid = getgid(); } else { - my_getpwuid(user, geteuid()); - my_getgrgid(group, getegid()); + uid = geteuid(); + gid = getegid(); } + my_getpwuid(user, uid); } else { safe_strncpy(user, argv[optind], sizeof(user)); gid = my_getpwnamegid(user); - my_getgrgid(group, gid); } + my_getgrgid(group, gid); pwnam=my_getpwnam(user); grnam=my_getgrnam(group); - if (no_group) { - if(name_not_number) - puts(user); - else - printf("%ld\n", pwnam); - } else if (no_user) { - if(name_not_number) - puts(group); - else + if (flags & (NO_GROUP | NO_USER)) { + char *s = group; + if (flags & NO_GROUP) { + s = user; + grnam = pwnam; + } + if (flags & NAME_NOT_NUMBER) { + puts(s); + } else { printf("%ld\n", grnam); + } } else { printf("uid=%ld(%s) gid=%ld(%s)\n", pwnam, user, grnam, group); } - return(0); -} - -/* END CODE */ + bb_fflush_stdout_and_exit(0); +} diff --git a/coreutils/length.c b/coreutils/length.c index 73becd2..bce43ab 100644 --- a/coreutils/length.c +++ b/coreutils/length.c @@ -1,4 +1,7 @@ /* vi: set sw=4 ts=4: */ + +/* BB_AUDIT SUSv3 N/A -- Apparently a busybox (obsolete?) extension. */ + #include <stdlib.h> #include <string.h> #include <stdio.h> @@ -6,8 +9,11 @@ extern int length_main(int argc, char **argv) { - if (argc != 2 || **(argv + 1) == '-') - show_usage(); - printf("%lu\n", (long)strlen(argv[1])); - return EXIT_SUCCESS; + if ((argc != 2) || (**(++argv) == '-')) { + bb_show_usage(); + } + + bb_printf("%lu\n", (unsigned long)strlen(*argv)); + + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } diff --git a/coreutils/libcoreutils/Makefile b/coreutils/libcoreutils/Makefile new file mode 100644 index 0000000..59ec24e --- /dev/null +++ b/coreutils/libcoreutils/Makefile @@ -0,0 +1,30 @@ +# Makefile for busybox +# +# Copyright (C) 1999-2002 Erik Andersen <andersee@debian.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR:= ../../ +LIBCOREUTILS_DIR:=./ +include $(TOPDIR).config +include $(TOPDIR)Rules.mak +include Makefile.in +all: $(libraries-y) +-include $(TOPDIR).depend + +clean: + rm -f *.o *.a $(AR_TARGET) + diff --git a/coreutils/libcoreutils/Makefile.in b/coreutils/libcoreutils/Makefile.in new file mode 100644 index 0000000..47391dd --- /dev/null +++ b/coreutils/libcoreutils/Makefile.in @@ -0,0 +1,32 @@ +# Makefile for busybox +# +# Copyright (C) 1999-2002 Erik Andersen <andersee@debian.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +LIBCOREUTILS_AR:=libcoreutils.a +ifndef $(LIBCOREUTILS_DIR) +LIBCOREUTILS_DIR:=$(TOPDIR)coreutils/libcoreutils/ +endif + +LIBCOREUTILS_SRC:= cp_mv_stat.c getopt_mk_fifo_nod.c xgetoptfile_sort_uniq.c + +LIBCOREUTILS_OBJS=$(patsubst %.c,$(LIBCOREUTILS_DIR)%.o, $(LIBCOREUTILS_SRC)) + +libraries-y+=$(LIBCOREUTILS_DIR)$(LIBCOREUTILS_AR) + +$(LIBCOREUTILS_DIR)$(LIBCOREUTILS_AR): $(LIBCOREUTILS_OBJS) + $(AR) -ro $@ $(LIBCOREUTILS_OBJS) diff --git a/coreutils/libcoreutils/coreutils.h b/coreutils/libcoreutils/coreutils.h new file mode 100644 index 0000000..eabca82 --- /dev/null +++ b/coreutils/libcoreutils/coreutils.h @@ -0,0 +1,12 @@ +#ifndef COREUTILS_H +#define COREUTILS_H 1 + +typedef int (*stat_func)(const char *fn, struct stat *ps); + +extern int cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf); +extern int cp_mv_stat(const char *fn, struct stat *fn_stat); + +extern mode_t getopt_mk_fifo_nod(int argc, char **argv); +extern FILE *xgetoptfile_sort_uniq(char **argv, const char *mode); + +#endif diff --git a/coreutils/libcoreutils/cp_mv_stat.c b/coreutils/libcoreutils/cp_mv_stat.c new file mode 100644 index 0000000..5a70b02 --- /dev/null +++ b/coreutils/libcoreutils/cp_mv_stat.c @@ -0,0 +1,45 @@ +/* vi: set sw=4 ts=4: */ +/* + * coreutils utility routine + * + * 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 <errno.h> +#include <sys/stat.h> +#include "libbb.h" +#include "coreutils.h" + +extern int cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf) +{ + if (sf(fn, fn_stat) < 0) { + if (errno != ENOENT) { + bb_perror_msg("unable to stat `%s'", fn); + return -1; + } + return 0; + } else if (S_ISDIR(fn_stat->st_mode)) { + return 3; + } + return 1; +} + +extern int cp_mv_stat(const char *fn, struct stat *fn_stat) +{ + return cp_mv_stat2(fn, fn_stat, stat); +} diff --git a/coreutils/libcoreutils/getopt_mk_fifo_nod.c b/coreutils/libcoreutils/getopt_mk_fifo_nod.c new file mode 100644 index 0000000..0872bdc --- /dev/null +++ b/coreutils/libcoreutils/getopt_mk_fifo_nod.c @@ -0,0 +1,45 @@ +/* vi: set sw=4 ts=4: */ +/* + * coreutils utility routine + * + * 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 <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "libbb.h" +#include "coreutils.h" + +extern mode_t getopt_mk_fifo_nod(int argc, char **argv) +{ + mode_t mode = 0666; + int opt; + + while ((opt = getopt(argc, argv, "m:")) > 0) { + if (opt == 'm') { + mode = 0666; + if (bb_parse_mode(optarg, &mode)) { + umask(0); + continue; + } + } + bb_show_usage(); + } + return mode; +} diff --git a/coreutils/libcoreutils/xgetoptfile_sort_uniq.c b/coreutils/libcoreutils/xgetoptfile_sort_uniq.c new file mode 100644 index 0000000..a63daf9 --- /dev/null +++ b/coreutils/libcoreutils/xgetoptfile_sort_uniq.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * coreutils utility routine + * + * 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 <stdio.h> +#include <unistd.h> +#include "libbb.h" +#include "coreutils.h" + +extern FILE *xgetoptfile_sort_uniq(char **argv, const char *mode) +{ + const char *n; + + if ((n = *argv) != NULL) { + if ((*n != '-') || n[1]) { + return bb_xfopen(n, mode); + } + } + return (*mode == 'r') ? stdin : stdout; +} diff --git a/coreutils/ln.c b/coreutils/ln.c index 427ffcc..2edece1 100644 --- a/coreutils/ln.c +++ b/coreutils/ln.c @@ -21,113 +21,86 @@ * */ -#include <stdio.h> -#include <dirent.h> -#include <string.h> +/* BB_AUDIT SUSv3 compliant */ +/* BB_AUDIT GNU options missing: -b, -d, -F, -i, -S, and -v. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Fixed bug involving -n option. Essentially, -n was always in effect. + */ + #include <stdlib.h> -#include <errno.h> #include <unistd.h> #include "busybox.h" +#define LN_SYMLINK 1 +#define LN_FORCE 2 +#define LN_NODEREFERENCE 4 -static const int LN_SYMLINK = 1; -static const int LN_FORCE = 2; -static const int LN_NODEREFERENCE = 4; - -/* - * linkDestName is where the link points to, - * linkSrcName is the name of the link to be created. - */ -static int fs_link(const char *link_destname, const char *link_srcname, - const int flag) +extern int ln_main(int argc, char **argv) { - int status; - int src_is_dir; - char *src_name = 0; + int status = EXIT_SUCCESS; + int flag; + char *last; + char *src_name; const char *src; + int (*link_func)(const char *, const char *); - if (link_destname==NULL) - return(FALSE); - - if (link_srcname==NULL) - src = link_destname; - else - src = link_srcname; - - if (flag&LN_NODEREFERENCE) - src_is_dir = is_directory(src, TRUE, NULL); - else - src_is_dir = is_directory(src, FALSE, NULL); - - if ((src_is_dir==TRUE)&&((flag&LN_NODEREFERENCE)==0)) { - char* srcdir_name; - - srcdir_name = xstrdup(link_destname); - src_name = concat_path_file(src, get_last_path_component(srcdir_name)); - src = src_name; - free(srcdir_name); + flag = bb_getopt_ulflags(argc, argv, "sfn"); + + if (argc == optind) { + bb_show_usage(); } - - if (flag&LN_FORCE) - unlink(src); - - if (flag&LN_SYMLINK) - status = symlink(link_destname, src); - else - status = link(link_destname, src); - - if (status != 0) { - perror_msg(src); - status = FALSE; - } else { - status = TRUE; + + last = argv[argc - 1]; + argv += optind; + + if (argc == optind + 1) { + *--argv = last; + last = bb_get_last_path_component(bb_xstrdup(last)); } - free(src_name); - return status; -} -extern int ln_main(int argc, char **argv) -{ - int status = EXIT_SUCCESS; - int flag = 0; - int opt; - - /* Parse any options */ - while ((opt=getopt(argc, argv, "sfn")) != -1) { - switch(opt) { - case 's': - flag |= LN_SYMLINK; - break; - case 'f': - flag |= LN_FORCE; - break; - case 'n': - flag |= LN_NODEREFERENCE; - break; - default: - show_usage(); + do { + src_name = 0; + src = last; + + if (is_directory(src, + (flag & LN_NODEREFERENCE) ^ LN_NODEREFERENCE, + NULL)) { + src_name = bb_xstrdup(*argv); + src = concat_path_file(src, bb_get_last_path_component(src_name)); + free(src_name); + src_name = (char *)src; } - } - if (optind > (argc-1)) { - show_usage(); - } - if (optind == (argc-1)) { - if (fs_link(argv[optind], - get_last_path_component(argv[optind]), flag)==FALSE) - status = EXIT_FAILURE; - } - while(optind<(argc-1)) { - if (fs_link(argv[optind], argv[argc-1], flag)==FALSE) - status = EXIT_FAILURE; - optind++; - } + + if (flag & LN_FORCE) { + unlink(src); + } + + link_func = link; + if (flag & LN_SYMLINK) { + link_func = symlink; + } + + if (link_func(*argv, src) != 0) { + bb_perror_msg(src); + status = EXIT_FAILURE;; + } + + free(src_name); + + } while ((++argv)[1]); + return status; } -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ + + + + + + + + + diff --git a/coreutils/logname.c b/coreutils/logname.c index 3e10fba..9cedff0 100644 --- a/coreutils/logname.c +++ b/coreutils/logname.c @@ -20,6 +20,19 @@ * */ +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/logname.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * SUSv3 specifies the string used is that returned from getlogin(). + * The previous implementation used getpwuid() for geteuid(), which + * is _not_ the same. Erik apparently made this change almost 3 years + * ago to avoid failing when no utmp was available. However, the + * correct course of action wrt SUSv3 for a failing getlogin() is + * a dianostic message and an error return. + */ + #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -27,14 +40,16 @@ extern int logname_main(int argc, char **argv) { - char user[9]; + const char *p; - if (argc > 1) - show_usage(); + if (argc > 1) { + bb_show_usage(); + } - if (my_getpwuid(user, geteuid())) { - puts(user); - return EXIT_SUCCESS; + if ((p = getlogin()) != NULL) { + puts(p); + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } - error_msg_and_die("no login name"); + + bb_perror_msg_and_die("getlogin"); } diff --git a/coreutils/ls.c b/coreutils/ls.c index 64ec0fe..4a49566 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -73,58 +73,76 @@ enum { #endif /* what is the overall style of the listing */ -enum { - STYLE_AUTO = 0, - STYLE_LONG = 1, /* one record per line, extended info */ - STYLE_SINGLE = 2, /* one record per line */ - STYLE_COLUMNS = 3 /* fill columns */ -}; +#define STYLE_AUTO (0) +#define STYLE_COLUMNS (1U<<21) /* fill columns */ +#define STYLE_LONG (2U<<21) /* one record per line, extended info */ +#define STYLE_SINGLE (3U<<21) /* one record per line */ + +#define STYLE_MASK STYLE_SINGLE +#define STYLE_ONE_RECORD_FLAG STYLE_LONG /* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ /* what file information will be listed */ -#define LIST_INO (1<<0) -#define LIST_BLOCKS (1<<1) -#define LIST_MODEBITS (1<<2) -#define LIST_NLINKS (1<<3) -#define LIST_ID_NAME (1<<4) -#define LIST_ID_NUMERIC (1<<5) -#define LIST_SIZE (1<<6) -#define LIST_DEV (1<<7) -#define LIST_DATE_TIME (1<<8) -#define LIST_FULLTIME (1<<9) -#define LIST_FILENAME (1<<10) -#define LIST_SYMLINK (1<<11) -#define LIST_FILETYPE (1<<12) -#define LIST_EXEC (1<<13) +#define LIST_INO (1U<<0) +#define LIST_BLOCKS (1U<<1) +#define LIST_MODEBITS (1U<<2) +#define LIST_NLINKS (1U<<3) +#define LIST_ID_NAME (1U<<4) +#define LIST_ID_NUMERIC (1U<<5) +#define LIST_SIZE (1U<<6) +#define LIST_DEV (1U<<7) +#define LIST_DATE_TIME (1U<<8) +#define LIST_FULLTIME (1U<<9) +#define LIST_FILENAME (1U<<10) +#define LIST_SYMLINK (1U<<11) +#define LIST_FILETYPE (1U<<12) +#define LIST_EXEC (1U<<13) + +#define LIST_MASK ((LIST_EXEC << 1) - 1) /* what files will be displayed */ -#define DISP_NORMAL (0) /* show normal filenames */ -#define DISP_DIRNAME (1<<0) /* 2 or more items? label directories */ -#define DISP_HIDDEN (1<<1) /* show filenames starting with . */ -#define DISP_DOT (1<<2) /* show . and .. */ -#define DISP_NOLIST (1<<3) /* show directory as itself, not contents */ -#define DISP_RECURSIVE (1<<4) /* show directory and everything below it */ -#define DISP_ROWS (1<<5) /* print across rows */ +/* TODO -- We may be able to make DISP_NORMAL 0 to save a bit slot. */ +#define DISP_NORMAL (1U<<14) /* show normal filenames */ +#define DISP_DIRNAME (1U<<15) /* 2 or more items? label directories */ +#define DISP_HIDDEN (1U<<16) /* show filenames starting with . */ +#define DISP_DOT (1U<<17) /* show . and .. */ +#define DISP_NOLIST (1U<<18) /* show directory as itself, not contents */ +#define DISP_RECURSIVE (1U<<19) /* show directory and everything below it */ +#define DISP_ROWS (1U<<20) /* print across rows */ + +#define DISP_MASK (((DISP_ROWS << 1) - 1) & ~(DISP_NORMAL - 1)) #ifdef CONFIG_FEATURE_LS_SORTFILES /* how will the files be sorted */ -static const int SORT_FORWARD = 0; /* sort in reverse order */ -static const int SORT_REVERSE = 1; /* sort in reverse order */ -static const int SORT_NAME = 2; /* sort by file name */ -static const int SORT_SIZE = 3; /* sort by file size */ -static const int SORT_ATIME = 4; /* sort by last access time */ -static const int SORT_CTIME = 5; /* sort by last change time */ -static const int SORT_MTIME = 6; /* sort by last modification time */ -static const int SORT_VERSION = 7; /* sort by version */ -static const int SORT_EXT = 8; /* sort by file name extension */ -static const int SORT_DIR = 9; /* sort by file or directory */ +#define SORT_ORDER_FORWARD 0 /* sort in reverse order */ +#define SORT_ORDER_REVERSE (1U<<27) /* sort in reverse order */ + +#define SORT_NAME 0 /* sort by file name */ +#define SORT_SIZE (1U<<28) /* sort by file size */ +#define SORT_ATIME (2U<<28) /* sort by last access time */ +#define SORT_CTIME (3U<<28) /* sort by last change time */ +#define SORT_MTIME (4U<<28) /* sort by last modification time */ +#define SORT_VERSION (5U<<28) /* sort by version */ +#define SORT_EXT (6U<<28) /* sort by file name extension */ +#define SORT_DIR (7U<<28) /* sort by file or directory */ + +#define SORT_MASK (7U<<28) #endif #ifdef CONFIG_FEATURE_LS_TIMESTAMPS /* which of the three times will be used */ -static const int TIME_MOD = 0; -static const int TIME_CHANGE = 1; -static const int TIME_ACCESS = 2; +#define TIME_MOD 0 +#define TIME_CHANGE (1U<<23) +#define TIME_ACCESS (1U<<24) + +#define TIME_MASK (3U<<23) +#endif + +#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS +#define FOLLOW_LINKS (1U<<25) +#endif +#ifdef CONFIG_FEATURE_HUMAN_READABLE +#define LS_DISP_HR (1U<<26) #endif #define LIST_SHORT (LIST_FILENAME) @@ -133,9 +151,9 @@ static const int TIME_ACCESS = 2; LIST_DATE_TIME | LIST_FILENAME | LIST_SYMLINK) #define LIST_ILONG (LIST_INO | LIST_LONG) -static const int SPLIT_DIR = 0; -static const int SPLIT_FILE = 1; -static const int SPLIT_SUBDIR = 2; +#define SPLIT_DIR 1 +#define SPLIT_FILE 0 +#define SPLIT_SUBDIR 2 #define TYPEINDEX(mode) (((mode) >> 12) & 0x0f) #define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)]) @@ -169,20 +187,7 @@ static struct dnode **list_dir(const char *); static struct dnode **dnalloc(int); static int list_single(struct dnode *); -static unsigned int disp_opts; -static unsigned int style_fmt; -static unsigned int list_fmt; - -#ifdef CONFIG_FEATURE_LS_SORTFILES -static unsigned int sort_opts; -static unsigned int sort_order; -#endif -#ifdef CONFIG_FEATURE_LS_TIMESTAMPS -static unsigned int time_fmt; -#endif -#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS -static unsigned int follow_links = FALSE; -#endif +static unsigned int all_fmt; #ifdef CONFIG_FEATURE_AUTOWIDTH static unsigned short terminal_width = TERMINAL_WIDTH; @@ -194,26 +199,22 @@ static unsigned short tabstops = COLUMN_GAP; static int status = EXIT_SUCCESS; -#ifdef CONFIG_FEATURE_HUMAN_READABLE -static unsigned long ls_disp_hr = 0; -#endif - static struct dnode *my_stat(char *fullname, char *name) { struct stat dstat; struct dnode *cur; #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS - if (follow_links) { + if (all_fmt & FOLLOW_LINKS) { if (stat(fullname, &dstat)) { - perror_msg("%s", fullname); + bb_perror_msg("%s", fullname); status = EXIT_FAILURE; return 0; } } else #endif if (lstat(fullname, &dstat)) { - perror_msg("%s", fullname); + bb_perror_msg("%s", fullname); status = EXIT_FAILURE; return 0; } @@ -253,9 +254,9 @@ static char bgcolor(mode_t mode) #if defined(CONFIG_FEATURE_LS_FILETYPES) || defined(CONFIG_FEATURE_LS_COLOR) static char append_char(mode_t mode) { - if (!(list_fmt & LIST_FILETYPE)) + if (!(all_fmt & LIST_FILETYPE)) return '\0'; - if ((list_fmt & LIST_EXEC) && S_ISREG(mode) + if ((all_fmt & LIST_EXEC) && S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return '*'; return APPCHAR(mode); @@ -263,13 +264,11 @@ static char append_char(mode_t mode) #endif /*----------------------------------------------------------------------*/ -static int is_subdir(struct dnode *dn) -{ - return (S_ISDIR(dn->dstat.st_mode) && strcmp(dn->name, ".") != 0 && - strcmp(dn->name, "..") != 0); -} -static int countdirs(struct dnode **dn, int nfiles) +#define countdirs(A,B) count_dirs((A), (B), 1) +#define countsubdirs(A,B) count_dirs((A), (B), 0) + +static int count_dirs(struct dnode **dn, int nfiles, int notsubdirs) { int i, dirs; @@ -277,25 +276,17 @@ static int countdirs(struct dnode **dn, int nfiles) return (0); dirs = 0; for (i = 0; i < nfiles; i++) { - if (S_ISDIR(dn[i]->dstat.st_mode)) + if (S_ISDIR(dn[i]->dstat.st_mode) + && (notsubdirs + || ((dn[i]->name[0] != '.') + || (dn[i]->name[1] + && ((dn[i]->name[1] != '.') + || dn[i]->name[2]))))) dirs++; } return (dirs); } -static int countsubdirs(struct dnode **dn, int nfiles) -{ - int i, subdirs; - - if (dn == NULL || nfiles < 1) - return 0; - subdirs = 0; - for (i = 0; i < nfiles; i++) - if (is_subdir(dn[i])) - subdirs++; - return subdirs; -} - static int countfiles(struct dnode **dnp) { int nfiles; @@ -364,18 +355,18 @@ static struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which) /* copy the entrys into the file or dir array */ for (d = i = 0; i < nfiles; i++) { - if (which == SPLIT_DIR) { - if (S_ISDIR(dn[i]->dstat.st_mode)) { - dnp[d++] = dn[i]; - } /* else skip the file */ - } else if (which == SPLIT_SUBDIR) { - if (is_subdir(dn[i])) { - dnp[d++] = dn[i]; - } /* else skip the file or dir */ - } else { - if (!(S_ISDIR(dn[i]->dstat.st_mode))) { - dnp[d++] = dn[i]; - } /* else skip the dir */ + if (S_ISDIR(dn[i]->dstat.st_mode)) { + if (which & (SPLIT_DIR|SPLIT_SUBDIR)) { + if ((which & SPLIT_DIR) + || ((dn[i]->name[0] != '.') + || (dn[i]->name[1] + && ((dn[i]->name[1] != '.') + || dn[i]->name[2])))) { + dnp[d++] = dn[i]; + } + } + } else if (!(which & (SPLIT_DIR|SPLIT_SUBDIR))) { + dnp[d++] = dn[i]; } } return (dnp); @@ -385,29 +376,24 @@ static struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which) #ifdef CONFIG_FEATURE_LS_SORTFILES static int sortcmp(struct dnode *d1, struct dnode *d2) { - int cmp, dif; + unsigned int sort_opts = all_fmt & SORT_MASK; + int dif; - cmp = 0; + dif = 0; /* assume SORT_NAME */ if (sort_opts == SORT_SIZE) { - dif = (int) (d1->dstat.st_size - d2->dstat.st_size); + dif = (int) (d2->dstat.st_size - d1->dstat.st_size); } else if (sort_opts == SORT_ATIME) { - dif = (int) (d1->dstat.st_atime - d2->dstat.st_atime); + dif = (int) (d2->dstat.st_atime - d1->dstat.st_atime); } else if (sort_opts == SORT_CTIME) { - dif = (int) (d1->dstat.st_ctime - d2->dstat.st_ctime); + dif = (int) (d2->dstat.st_ctime - d1->dstat.st_ctime); } else if (sort_opts == SORT_MTIME) { - dif = (int) (d1->dstat.st_mtime - d2->dstat.st_mtime); + dif = (int) (d2->dstat.st_mtime - d1->dstat.st_mtime); } else if (sort_opts == SORT_DIR) { - dif = S_ISDIR(d1->dstat.st_mode) - S_ISDIR(d2->dstat.st_mode); + dif = S_ISDIR(d2->dstat.st_mode) - S_ISDIR(d1->dstat.st_mode); /* } else if (sort_opts == SORT_VERSION) { */ /* } else if (sort_opts == SORT_EXT) { */ - } else { /* assume SORT_NAME */ - dif = 0; } - if (dif > 0) - cmp = -1; - if (dif < 0) - cmp = 1; if (dif == 0) { /* sort by name- may be a tie_breaker for time or size cmp */ #ifdef CONFIG_LOCALE_SUPPORT @@ -415,16 +401,12 @@ static int sortcmp(struct dnode *d1, struct dnode *d2) #else dif = strcmp(d1->name, d2->name); #endif - if (dif > 0) - cmp = 1; - if (dif < 0) - cmp = -1; } - if (sort_order == SORT_REVERSE) { - cmp = -1 * cmp; + if (all_fmt & SORT_ORDER_REVERSE) { + dif = -dif; } - return (cmp); + return (dif); } /*----------------------------------------------------------------------*/ @@ -463,20 +445,17 @@ static void showfiles(struct dnode **dn, int nfiles) if (dn == NULL || nfiles < 1) return; - switch (style_fmt) { - case STYLE_LONG: /* one record per line, extended info */ - case STYLE_SINGLE: /* one record per line */ + if (all_fmt & STYLE_ONE_RECORD_FLAG) { ncols = 1; - break; - default: - /* find the longest file name- use that as the column width */ - for (i = 0; i < nfiles; i++) { + } else { + /* find the longest file name- use that as the column width */ + for (i = 0; i < nfiles; i++) { int len = strlen(dn[i]->name) + - ((list_fmt & LIST_INO) ? 8 : 0) + - ((list_fmt & LIST_BLOCKS) ? 5 : 0); - if (column_width < len) - column_width = len; - } + ((all_fmt & LIST_INO) ? 8 : 0) + + ((all_fmt & LIST_BLOCKS) ? 5 : 0); + if (column_width < len) + column_width = len; + } column_width += tabstops; ncols = (int) (terminal_width / column_width); } @@ -494,7 +473,7 @@ static void showfiles(struct dnode **dn, int nfiles) for (nc = 0; nc < ncols; nc++) { /* reach into the array based on the column and row */ i = (nc * nrows) + row; /* assume display by column */ - if (disp_opts & DISP_ROWS) + if (all_fmt & DISP_ROWS) i = (row * ncols) + nc; /* display across row */ if (i < nfiles) { if (column > 0) { @@ -528,7 +507,7 @@ static void showdirs(struct dnode **dn, int ndirs) return; for (i = 0; i < ndirs; i++) { - if (disp_opts & (DISP_DIRNAME | DISP_RECURSIVE)) { + if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) { printf("\n%s:\n", dn[i]->fullname); } subdnp = list_dir(dn[i]->fullname); @@ -540,7 +519,7 @@ static void showdirs(struct dnode **dn, int ndirs) #endif showfiles(subdnp, nfiles); #ifdef CONFIG_FEATURE_LS_RECURSIVE - if (disp_opts & DISP_RECURSIVE) { + if (all_fmt & DISP_RECURSIVE) { /* recursive- list the sub-dirs */ dnd = splitdnarray(subdnp, nfiles, SPLIT_SUBDIR); dndirs = countsubdirs(subdnp, nfiles); @@ -573,7 +552,7 @@ static struct dnode **list_dir(const char *path) nfiles = 0; dir = opendir(path); if (dir == NULL) { - perror_msg("%s", path); + bb_perror_msg("%s", path); status = EXIT_FAILURE; return (NULL); /* could not open the dir */ } @@ -585,9 +564,9 @@ static struct dnode **list_dir(const char *path) if ((entry->d_name[1] == 0 || ( entry->d_name[1] == '.' && entry->d_name[2] == 0)) - && !(disp_opts & DISP_DOT)) + && !(all_fmt & DISP_DOT)) continue; - if (!(disp_opts & DISP_HIDDEN)) + if (!(all_fmt & DISP_HIDDEN)) continue; } fullname = concat_path_file(path, entry->d_name); @@ -636,9 +615,9 @@ static int list_single(struct dnode *dn) #ifdef CONFIG_FEATURE_LS_TIMESTAMPS ttime = dn->dstat.st_mtime; /* the default time */ - if (time_fmt & TIME_ACCESS) + if (all_fmt & TIME_ACCESS) ttime = dn->dstat.st_atime; - if (time_fmt & TIME_CHANGE) + if (all_fmt & TIME_CHANGE) ttime = dn->dstat.st_ctime; filetime = ctime(&ttime); #endif @@ -647,7 +626,7 @@ static int list_single(struct dnode *dn) #endif for (i = 0; i <= 31; i++) { - switch (list_fmt & (1 << i)) { + switch (all_fmt & (1 << i)) { case LIST_INO: column += printf("%7ld ", (long int) dn->dstat.st_ino); break; @@ -659,7 +638,7 @@ static int list_single(struct dnode *dn) #endif break; case LIST_MODEBITS: - column += printf("%-10s ", (char *) mode_string(dn->dstat.st_mode)); + column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode)); break; case LIST_NLINKS: column += printf("%4ld ", (long) dn->dstat.st_nlink); @@ -683,7 +662,7 @@ static int list_single(struct dnode *dn) (int) MINOR(dn->dstat.st_rdev)); } else { #ifdef CONFIG_FEATURE_HUMAN_READABLE - if (ls_disp_hr == TRUE) { + if (all_fmt & LS_DISP_HR) { column += printf("%9s ", make_human_readable_str(dn->dstat.st_size, 1, 0)); } else @@ -700,7 +679,7 @@ static int list_single(struct dnode *dn) #ifdef CONFIG_FEATURE_LS_TIMESTAMPS case LIST_FULLTIME: case LIST_DATE_TIME: - if (list_fmt & LIST_FULLTIME) { + if (all_fmt & LIST_FULLTIME) { printf("%24.24s ", filetime); column += 25; break; @@ -774,47 +753,8 @@ static int list_single(struct dnode *dn) } /*----------------------------------------------------------------------*/ -extern int ls_main(int argc, char **argv) -{ - struct dnode **dnf, **dnd; - int dnfiles, dndirs; - struct dnode *dn, *cur, **dnp; - int i, nfiles; - int opt; - int oi, ac; - char **av; - -#ifdef CONFIG_FEATURE_AUTOWIDTH - struct winsize win = { 0, 0, 0, 0 }; -#endif - - disp_opts = DISP_NORMAL; - style_fmt = STYLE_AUTO; - list_fmt = LIST_SHORT; -#ifdef CONFIG_FEATURE_LS_SORTFILES - sort_opts = SORT_NAME; - sort_order = SORT_FORWARD; -#endif -#ifdef CONFIG_FEATURE_LS_TIMESTAMPS - time_fmt = TIME_MOD; -#endif -#ifdef CONFIG_FEATURE_AUTOWIDTH - ioctl(fileno(stdout), TIOCGWINSZ, &win); - if (win.ws_col > 0) - terminal_width = win.ws_col - 1; -#endif - nfiles = 0; -#ifdef CONFIG_FEATURE_LS_COLOR - if (isatty(fileno(stdout))) - show_color = 1; -#endif - - /* process options */ - while ((opt = getopt(argc, argv, "1AaCdgilnsx" -#ifdef CONFIG_FEATURE_AUTOWIDTH - "T:w:" -#endif +static const char ls_opts[] = "1AaCdgilnsx" #ifdef CONFIG_FEATURE_LS_FILETYPES "Fp" #endif @@ -825,7 +765,7 @@ extern int ls_main(int argc, char **argv) "rSvX" #endif #ifdef CONFIG_FEATURE_LS_TIMESTAMPS - "cetu" + "ecut" #endif #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS "L" @@ -833,141 +773,180 @@ extern int ls_main(int argc, char **argv) #ifdef CONFIG_FEATURE_HUMAN_READABLE "h" #endif - "k")) > 0) { - switch (opt) { - case '1': - style_fmt = STYLE_SINGLE; - list_fmt = LIST_SHORT; - break; - case 'A': - disp_opts |= DISP_HIDDEN; - break; - case 'a': - disp_opts |= DISP_HIDDEN | DISP_DOT; - break; - case 'C': - style_fmt = STYLE_COLUMNS; - list_fmt = LIST_SHORT; - break; - case 'd': - disp_opts |= DISP_NOLIST; - break; - case 'g': /* ignore -- for ftp servers */ - break; - case 'i': - list_fmt |= LIST_INO; - break; - case 'l': - style_fmt = STYLE_LONG; - list_fmt |= LIST_LONG; -#ifdef CONFIG_FEATURE_HUMAN_READABLE - ls_disp_hr = FALSE; + "k" +#ifdef CONFIG_FEATURE_AUTOWIDTH + "T:w:" #endif - break; - case 'n': - list_fmt |= LIST_ID_NUMERIC; - break; - case 's': - list_fmt |= LIST_BLOCKS; - break; - case 'x': - disp_opts = DISP_ROWS; - break; + ; + +#define LIST_MASK_TRIGGER LIST_SHORT +#define STYLE_MASK_TRIGGER STYLE_MASK +#define SORT_MASK_TRIGGER SORT_MASK +#define DISP_MASK_TRIGGER DISP_ROWS +#define TIME_MASK_TRIGGER TIME_MASK + +static const unsigned opt_flags[] = { + LIST_SHORT | STYLE_SINGLE, /* 1 */ + DISP_HIDDEN, /* A */ + DISP_HIDDEN | DISP_DOT, /* a */ + LIST_SHORT | STYLE_COLUMNS, /* C */ + DISP_NOLIST, /* d */ + 0, /* g - ingored */ + LIST_INO, /* i */ + LIST_LONG | STYLE_LONG, /* l - remember LS_DISP_HR in mask! */ + LIST_ID_NUMERIC, /* n */ + LIST_BLOCKS, /* s */ + DISP_ROWS, /* x */ #ifdef CONFIG_FEATURE_LS_FILETYPES - case 'F': - list_fmt |= LIST_FILETYPE | LIST_EXEC; - break; - case 'p': - list_fmt |= LIST_FILETYPE; - break; + LIST_FILETYPE | LIST_EXEC, /* F */ + LIST_FILETYPE, /* p */ #endif #ifdef CONFIG_FEATURE_LS_RECURSIVE - case 'R': - disp_opts |= DISP_RECURSIVE; - break; + DISP_RECURSIVE, /* R */ #endif #ifdef CONFIG_FEATURE_LS_SORTFILES - case 'r': - sort_order |= SORT_REVERSE; - break; - case 'S': - sort_opts = SORT_SIZE; - break; - case 'v': - sort_opts = SORT_VERSION; - break; - case 'X': - sort_opts = SORT_EXT; - break; + SORT_ORDER_REVERSE, /* r */ + SORT_SIZE, /* S */ + SORT_VERSION, /* v */ + SORT_EXT, /* v */ #endif #ifdef CONFIG_FEATURE_LS_TIMESTAMPS - case 'e': - list_fmt |= LIST_FULLTIME; - break; - case 'c': - time_fmt = TIME_CHANGE; + LIST_FULLTIME, /* e */ #ifdef CONFIG_FEATURE_LS_SORTFILES - sort_opts = SORT_CTIME; + TIME_CHANGE | SORT_CTIME, /* c */ +#else + TIME_CHANGE, /* c */ #endif - break; - case 'u': - time_fmt = TIME_ACCESS; #ifdef CONFIG_FEATURE_LS_SORTFILES - sort_opts = SORT_ATIME; + TIME_ACCESS | SORT_ATIME, /* u */ +#else + TIME_ACCESS, /* u */ #endif - break; - case 't': #ifdef CONFIG_FEATURE_LS_SORTFILES - sort_opts = SORT_MTIME; + SORT_MTIME, /* t */ +#else + 0, /* t - ignored -- is this correct? */ #endif - break; #endif #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS - case 'L': - follow_links = TRUE; - break; + FOLLOW_LINKS, /* L */ +#endif +#ifdef CONFIG_FEATURE_HUMAN_READABLE +LS_DISP_HR, /* h */ +#endif + 0, /* k - ingored */ +}; + + +/*----------------------------------------------------------------------*/ + +extern int ls_main(int argc, char **argv) +{ + struct dnode **dnf, **dnd; + int dnfiles, dndirs; + struct dnode *dn, *cur, **dnp; + int i, nfiles; + int opt; + int oi, ac; + char **av; + +#ifdef CONFIG_FEATURE_AUTOWIDTH + struct winsize win = { 0, 0, 0, 0 }; +#endif + + all_fmt = LIST_SHORT | DISP_NORMAL | STYLE_AUTO +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS + | TIME_MOD +#endif +#ifdef CONFIG_FEATURE_LS_SORTFILES + | SORT_NAME | SORT_ORDER_FORWARD +#endif + ; +#ifdef CONFIG_FEATURE_AUTOWIDTH + ioctl(fileno(stdout), TIOCGWINSZ, &win); + if (win.ws_col > 0) + terminal_width = win.ws_col - 1; +#endif + nfiles = 0; + +#ifdef CONFIG_FEATURE_LS_COLOR + if (isatty(fileno(stdout))) + show_color = 1; #endif + + /* process options */ + while ((opt = getopt(argc, argv, ls_opts)) > 0) { #ifdef CONFIG_FEATURE_AUTOWIDTH - case 'T': + if (opt == 'T') { tabstops = atoi(optarg); - break; - case 'w': + continue; + } + if (opt == 'w') { terminal_width = atoi(optarg); - break; + continue; + } + if (opt == ':') { + goto print_usage_message; + } #endif + { + unsigned int flags; + const char *p = strchr(ls_opts, opt); + if (!p) { /* shouldn't be necessary */ + goto print_usage_message; + } + flags = opt_flags[(int)(p - ls_opts)]; + if (flags & LIST_MASK_TRIGGER) { + all_fmt &= ~LIST_MASK; + } + if (flags & STYLE_MASK_TRIGGER) { + all_fmt &= ~STYLE_MASK; + } + if (flags & SORT_MASK_TRIGGER) { + all_fmt &= ~SORT_MASK; + } + if (flags & DISP_MASK_TRIGGER) { + all_fmt &= ~DISP_MASK; + } + if (flags & TIME_MASK_TRIGGER) { + all_fmt &= ~TIME_MASK; + } #ifdef CONFIG_FEATURE_HUMAN_READABLE - case 'h': - ls_disp_hr = TRUE; - break; + if (opt == 'l') { + all_fmt &= ~LS_DISP_HR; + } #endif - case 'k': - break; - default: - goto print_usage_message; + all_fmt |= flags; } } + /* sort out which command line options take precedence */ #ifdef CONFIG_FEATURE_LS_RECURSIVE - if (disp_opts & DISP_NOLIST) - disp_opts &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ + if (all_fmt & DISP_NOLIST) + all_fmt &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ #endif #if defined (CONFIG_FEATURE_LS_TIMESTAMPS) && defined (CONFIG_FEATURE_LS_SORTFILES) - if (time_fmt & TIME_CHANGE) - sort_opts = SORT_CTIME; - if (time_fmt & TIME_ACCESS) - sort_opts = SORT_ATIME; + if (all_fmt & TIME_CHANGE) + all_fmt = (all_fmt & ~SORT_MASK) | SORT_CTIME; + if (all_fmt & TIME_ACCESS) + all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME; #endif - if (style_fmt != STYLE_LONG) /* only for long list */ - list_fmt &= ~(LIST_ID_NUMERIC|LIST_FULLTIME|LIST_ID_NAME|LIST_ID_NUMERIC); + if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* only for long list */ + all_fmt &= ~(LIST_ID_NUMERIC|LIST_FULLTIME|LIST_ID_NAME|LIST_ID_NUMERIC); #ifdef CONFIG_FEATURE_LS_USERNAME - if (style_fmt == STYLE_LONG && (list_fmt & LIST_ID_NUMERIC)) - list_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */ + if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC)) + all_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */ #endif - + /* choose a display format */ - if (style_fmt == STYLE_AUTO) - style_fmt = isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE; + if ((all_fmt & STYLE_MASK) == STYLE_AUTO) +#if STYLE_AUTO != 0 + all_fmt = (all_fmt & ~STYLE_MASK) + | (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE); +#else + all_fmt |= (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE); +#endif /* * when there are no cmd line args we have to supply a default "." arg. @@ -979,7 +958,7 @@ extern int ls_main(int argc, char **argv) ac = argc - optind; /* how many cmd line args are left */ if (ac < 1) { av = (char **) xcalloc((size_t) 1, (size_t) (sizeof(char *))); - av[0] = xstrdup("."); + av[0] = bb_xstrdup("."); ac = 1; } else { av = (char **) xcalloc((size_t) ac, (size_t) (sizeof(char *))); @@ -990,12 +969,12 @@ extern int ls_main(int argc, char **argv) /* now, everything is in the av array */ if (ac > 1) - disp_opts |= DISP_DIRNAME; /* 2 or more items? label directories */ + all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */ /* stuff the command line file names into an dnode array */ dn = NULL; for (oi = 0; oi < ac; oi++) { - char *fullname = xstrdup(av[oi]); + char *fullname = bb_xstrdup(av[oi]); cur = my_stat(fullname, fullname); if (!cur) @@ -1015,7 +994,7 @@ extern int ls_main(int argc, char **argv) } - if (disp_opts & DISP_NOLIST) { + if (all_fmt & DISP_NOLIST) { #ifdef CONFIG_FEATURE_LS_SORTFILES shellsort(dnp, nfiles); #endif @@ -1042,5 +1021,5 @@ extern int ls_main(int argc, char **argv) return (status); print_usage_message: - show_usage(); + bb_show_usage(); } diff --git a/coreutils/md5sum.c b/coreutils/md5sum.c index f5be448..c1480cd 100644 --- a/coreutils/md5sum.c +++ b/coreutils/md5sum.c @@ -770,13 +770,13 @@ static int md5_file(const char *filename, have_read_stdin = 1; fp = stdin; } else { - fp = wfopen(filename, "r"); + fp = bb_wfopen(filename, "r"); if (fp == NULL) return FALSE; } if (md5_stream(fp, md5_result)) { - perror_msg("%s", filename); + bb_perror_msg("%s", filename); if (fp != stdin) fclose(fp); @@ -784,7 +784,7 @@ static int md5_file(const char *filename, } if (fp != stdin && fclose(fp) == EOF) { - perror_msg("%s", filename); + bb_perror_msg("%s", filename); return FALSE; } @@ -805,7 +805,7 @@ static int md5_check(const char *checkfile_name) have_read_stdin = 1; checkfile_stream = stdin; } else { - checkfile_stream = wfopen(checkfile_name, "r"); + checkfile_stream = bb_wfopen(checkfile_name, "r"); if (checkfile_stream == NULL) return FALSE; } @@ -836,7 +836,7 @@ static int md5_check(const char *checkfile_name) if (split_3(line, line_length, &md5num, &filename) || !hex_digits(md5num)) { if (warn) { - error_msg("%s: %lu: improperly formatted MD5 checksum line", + bb_error_msg("%s: %lu: improperly formatted MD5 checksum line", checkfile_name, (unsigned long) line_number); } } else { @@ -881,18 +881,18 @@ static int md5_check(const char *checkfile_name) while (!feof(checkfile_stream) && !ferror(checkfile_stream)); if (ferror(checkfile_stream)) { - error_msg("%s: read error", checkfile_name); + bb_error_msg("%s: read error", checkfile_name); return FALSE; } if (checkfile_stream != stdin && fclose(checkfile_stream) == EOF) { - perror_msg("md5sum: %s", checkfile_name); + bb_perror_msg("md5sum: %s", checkfile_name); return FALSE; } if (n_properly_formated_lines == 0) { /* Warn if no tests are found. */ - error_msg("%s: no properly formatted MD5 checksum lines found", + bb_error_msg("%s: no properly formatted MD5 checksum lines found", checkfile_name); return FALSE; } else { @@ -901,13 +901,13 @@ static int md5_check(const char *checkfile_name) - n_open_or_read_failures); if (n_open_or_read_failures > 0) { - error_msg("WARNING: %d of %d listed files could not be read", + bb_error_msg("WARNING: %d of %d listed files could not be read", n_open_or_read_failures, n_properly_formated_lines); return FALSE; } if (n_mismatched_checksums > 0) { - error_msg("WARNING: %d of %d computed checksums did NOT match", + bb_error_msg("WARNING: %d of %d computed checksums did NOT match", n_mismatched_checksums, n_computed_checkums); return FALSE; } @@ -965,31 +965,31 @@ int md5sum_main(int argc, break; default: - show_usage(); + bb_show_usage(); } } if (file_type_specified && do_check) { - error_msg_and_die("the -b and -t options are meaningless when verifying checksums"); + bb_error_msg_and_die("the -b and -t options are meaningless when verifying checksums"); } if (n_strings > 0 && do_check) { - error_msg_and_die("the -g and -c options are mutually exclusive"); + bb_error_msg_and_die("the -g and -c options are mutually exclusive"); } if (status_only && !do_check) { - error_msg_and_die("the -s option is meaningful only when verifying checksums"); + bb_error_msg_and_die("the -s option is meaningful only when verifying checksums"); } if (warn && !do_check) { - error_msg_and_die("the -w option is meaningful only when verifying checksums"); + bb_error_msg_and_die("the -w option is meaningful only when verifying checksums"); } if (n_strings > 0) { size_t i; if (optind < argc) { - error_msg_and_die("no files may be specified when using -g"); + bb_error_msg_and_die("no files may be specified when using -g"); } for (i = 0; i < n_strings; ++i) { size_t cnt; @@ -1002,7 +1002,7 @@ int md5sum_main(int argc, } } else if (do_check) { if (optind + 1 < argc) { - error_msg("only one argument may be specified when using -c"); + bb_error_msg("only one argument may be specified when using -c"); } err = md5_check ((optind == argc) ? "-" : argv[optind]); @@ -1060,11 +1060,11 @@ int md5sum_main(int argc, } if (fclose (stdout) == EOF) { - error_msg_and_die("write error"); + bb_error_msg_and_die("write error"); } if (have_read_stdin && fclose (stdin) == EOF) { - error_msg_and_die("standard input"); + bb_error_msg_and_die(bb_msg_standard_input); } if (err == 0) diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c index f003db9..b018ac1 100644 --- a/coreutils/mkdir.c +++ b/coreutils/mkdir.c @@ -20,46 +20,50 @@ * */ -#include <errno.h> -#include <getopt.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/mkdir.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Fixed broken permission setting when -p was used; especially in + * conjunction with -m. + */ +#include <stdlib.h> +#include <unistd.h> #include "busybox.h" extern int mkdir_main (int argc, char **argv) { - mode_t mode = -1; + mode_t mode = (mode_t)(-1); + int status = EXIT_SUCCESS; int flags = 0; - int i, opt; + int opt; - while ((opt = getopt (argc, argv, "m:p")) != -1) { - switch (opt) { - case 'm': + while ((opt = getopt (argc, argv, "m:p")) > 0) { + if (opt == 'm') { mode = 0777; - if (!parse_mode (optarg, &mode)) { - error_msg_and_die ("invalid mode `%s'", optarg); + if (!bb_parse_mode (optarg, &mode)) { + bb_error_msg_and_die ("invalid mode `%s'", optarg); } - umask(0); - break; - case 'p': + } else if (opt == 'p') { flags |= FILEUTILS_RECUR; - break; - default: - show_usage (); + } else { + bb_show_usage(); } } - if (optind == argc) - show_usage (); - - for (i = optind; i < argc; i++) { - make_directory (argv[i], mode, flags); + if (optind == argc) { + bb_show_usage(); } - return(EXIT_SUCCESS); + argv += optind; + + do { + if (bb_make_directory(*argv, mode, flags)) { + status = EXIT_FAILURE; + } + } while (*++argv); + + return status; } diff --git a/coreutils/mkfifo.c b/coreutils/mkfifo.c index ca217fa..77e0e6d 100644 --- a/coreutils/mkfifo.c +++ b/coreutils/mkfifo.c @@ -1,8 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini mkfifo implementation for busybox + * mkfifo implementation for busybox * - * Copyright (C) 1999 by Randolph Chung <tausq@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 @@ -20,41 +20,32 @@ * */ -#include <stdio.h> -#include <sys/types.h> -#include <errno.h> +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/mkfifo.html */ + #include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> #include "busybox.h" +#include "libcoreutils/coreutils.h" extern int mkfifo_main(int argc, char **argv) { - char *thisarg; - mode_t mode = 0666; + mode_t mode; + int retval = EXIT_SUCCESS; - argc--; - argv++; + mode = getopt_mk_fifo_nod(argc, argv); - /* Parse any options */ - while (argc > 1) { - if (**argv != '-') - show_usage(); - thisarg = *argv; - thisarg++; - switch (*thisarg) { - case 'm': - argc--; - argv++; - parse_mode(*argv, &mode); - break; - default: - show_usage(); - } - argc--; - argv++; + if (!*(argv += optind)) { + bb_show_usage(); } - if (argc < 1 || *argv[0] == '-') - show_usage(); - if (mkfifo(*argv, mode) < 0) - perror_msg_and_die("mkfifo"); - return EXIT_SUCCESS; + + do { + if (mkfifo(*argv, mode) < 0) { + bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */ + retval = EXIT_FAILURE; + } + } while (*++argv); + + return retval; } diff --git a/coreutils/mknod.c b/coreutils/mknod.c index 432ec2b..59294e9 100644 --- a/coreutils/mknod.c +++ b/coreutils/mknod.c @@ -1,9 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini mknod implementation for busybox + * mknod implementation for busybox * - * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. - * Copyright (C) 1999-2002 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 @@ -21,73 +20,44 @@ * */ -#include <stdio.h> -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> +/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */ + #include <stdlib.h> -#include <sys/types.h> +#include <string.h> #include <sys/stat.h> +#include <unistd.h> #include "busybox.h" +#include "libcoreutils/coreutils.h" + +static const char modes_chars[] = { 'p', 'c', 'u', 'b', 0, 1, 1, 2 }; +static const mode_t modes_cubp[] = { S_IFIFO, S_IFCHR, S_IFBLK }; -int mknod_main(int argc, char **argv) +extern int mknod_main(int argc, char **argv) { - char *thisarg; - mode_t mode = 0; - mode_t perm = 0666; - dev_t dev = (dev_t) 0; + mode_t mode; + dev_t dev; + const char *name; + + mode = getopt_mk_fifo_nod(argc, argv); + argv += optind; + argc -= optind; - argc--; - argv++; + if ((argc >= 2) && ((name = strchr(modes_chars, argv[1][0])) != NULL)) { + mode |= modes_cubp[(int)(name[4])]; - /* Parse any options */ - while (argc > 1) { - if (**argv != '-') - break; - thisarg = *argv; - thisarg++; - switch (*thisarg) { - case 'm': - argc--; - argv++; - parse_mode(*argv, &perm); - umask(0); - break; - default: - show_usage(); + dev = 0; + if ((*name != 'p') && ((argc -= 2) == 0)) { + dev = (bb_xgetularg10_bnd(argv[2], 0, 255) << 8) + + bb_xgetularg10_bnd(argv[3], 0, 255); } - argc--; - argv++; - } - if (argc != 4 && argc != 2) { - show_usage(); - } - switch (argv[1][0]) { - case 'c': - case 'u': - mode = S_IFCHR; - break; - case 'b': - mode = S_IFBLK; - break; - case 'p': - mode = S_IFIFO; - if (argc != 2) { - show_usage(); + + if (argc == 2) { + name = *argv; + if (mknod(name, mode, dev) == 0) { + return EXIT_SUCCESS; + } + bb_perror_msg_and_die("%s", name); } - break; - default: - show_usage(); - } - - if (mode == S_IFCHR || mode == S_IFBLK) { - dev = (dev_t) ((atoi(argv[2]) << 8) | atoi(argv[3])); } - - mode |= perm; - - if (mknod(argv[0], mode, dev) != 0) - perror_msg_and_die("%s", argv[0]); - return EXIT_SUCCESS; + bb_show_usage(); } diff --git a/coreutils/mv.c b/coreutils/mv.c index 1c4a347..ae0ee92 100644 --- a/coreutils/mv.c +++ b/coreutils/mv.c @@ -2,7 +2,6 @@ /* * Mini mv implementation for busybox * - * * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> * * This program is free software; you can redistribute it and/or modify @@ -21,148 +20,122 @@ * */ +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Size reduction and improved error checking. + */ + #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <dirent.h> #include <errno.h> #include <stdlib.h> - #include "busybox.h" +#include "libcoreutils/coreutils.h" -static int flags; +static const char *fmt = "cannot overwrite %sdirectory with %sdirectory"; -static int manual_rename(const char *source, const char *dest) +extern int mv_main(int argc, char **argv) { struct stat source_stat; struct stat dest_stat; - int source_exists = 1; - int dest_exists = 1; + const char *last; + const char *dest; + int dest_exists; + int source_exists; + int opt; + int flags = 0; + int status = 0; - if (stat(source, &source_stat) < 0) { - if (errno != ENOENT) { - perror_msg("unable to stat `%s'", source); - return -1; + while ((opt = getopt(argc, argv, "fi")) > 0) { + flags &= ~(FILEUTILS_INTERACTIVE | FILEUTILS_FORCE); + if (opt == 'i') { + flags |= FILEUTILS_INTERACTIVE; + } else if (opt == 'f') { + flags |= FILEUTILS_FORCE; + } else { + bb_show_usage(); } - source_exists = 0; } - if (stat(dest, &dest_stat) < 0) { - if (errno != ENOENT) { - perror_msg("unable to stat `%s'", dest); - return -1; - } - dest_exists = 0; - } + if (optind + 2 > argc) + bb_show_usage(); - if (dest_exists) { - if (S_ISDIR(dest_stat.st_mode) && - (!source_exists || !S_ISDIR(source_stat.st_mode))) { - error_msg("cannot overwrite directory with non-directory"); - return -1; - } + last = argv[argc - 1]; + argv += optind; - if (!S_ISDIR(dest_stat.st_mode) && source_exists && - S_ISDIR(source_stat.st_mode)) { - error_msg("cannot overwrite non-directory with directory"); - return -1; + if (optind + 2 == argc) { + if ((dest_exists = cp_mv_stat(last, &dest_stat)) < 0) { + return 1; } - if (unlink(dest) < 0) { - perror_msg("cannot remove `%s'", dest); - return -1; + if (!(dest_exists & 2)) { + dest = last; + goto DO_MOVE; } } + + do { + dest = concat_path_file(last, + bb_get_last_path_component(*argv)); - if (copy_file(source, dest, - FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) < 0) - return -1; - - if (remove_file(source, FILEUTILS_RECUR | FILEUTILS_FORCE) < 0) - return -1; - - return 0; -} - -static int move_file(const char *source, const char *dest) -{ - struct stat dest_stat; - int dest_exists = 1; - - if (stat(dest, &dest_stat) < 0) { - if (errno != ENOENT) { - perror_msg("unable to stat `%s'", dest); - return -1; + if ((dest_exists = cp_mv_stat(dest, &dest_stat)) < 0) { + goto RET_1; } - dest_exists = 0; - } - if (dest_exists && !(flags & FILEUTILS_FORCE) && + DO_MOVE: + + if (dest_exists && !(flags & FILEUTILS_FORCE) && ((access(dest, W_OK) < 0 && isatty(0)) || (flags & FILEUTILS_INTERACTIVE))) { - fprintf(stderr, "mv: overwrite `%s'? ", dest); - if (!ask_confirmation()) - return 0; - } - - if (rename(source, dest) < 0) { - if (errno == EXDEV) - return manual_rename(source, dest); - - perror_msg("unable to rename `%s'", source); - return -1; - } - - return 0; -} - -extern int mv_main(int argc, char **argv) -{ - int status = 0; - int opt; - int i; - - while ((opt = getopt(argc, argv, "fi")) != -1) - switch (opt) { - case 'f': - flags &= ~FILEUTILS_INTERACTIVE; - flags |= FILEUTILS_FORCE; - break; - case 'i': - flags &= ~FILEUTILS_FORCE; - flags |= FILEUTILS_INTERACTIVE; - break; - default: - show_usage(); - } - - if (optind + 2 > argc) - show_usage(); - - if (optind + 2 == argc) { - struct stat dest_stat; - int dest_exists = 1; - - if (stat(argv[optind + 1], &dest_stat) < 0) { - if (errno != ENOENT) - perror_msg_and_die("unable to stat `%s'", argv[optind + 1]); - dest_exists = 0; + if (fprintf(stderr, "mv: overwrite `%s'? ", dest) < 0) { + goto RET_1; /* Ouch! fprintf failed! */ + } + if (!bb_ask_confirmation()) + goto RET_0; + } + + if (rename(*argv, dest) < 0) { + if (errno != EXDEV) { + bb_perror_msg("unable to rename `%s'", *argv); + } else if ((source_exists = cp_mv_stat(*argv, &source_stat)) >= 0) { + if (dest_exists) { + if (dest_exists & 2) { + if (!(source_exists & 2)) { + bb_error_msg(fmt, "", "non-"); + goto RET_1; + } + } else { + if (source_exists & 2) { + bb_error_msg(fmt, "non-", ""); + goto RET_1; + } + } + if (unlink(dest) < 0) { + bb_perror_msg("cannot remove `%s'", dest); + goto RET_1; + } + } + + if ((copy_file(*argv, dest, + FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) >= 0) + && (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0) + ) { + goto RET_0; + } + + } + RET_1: + status = 1; } - if (!dest_exists || !S_ISDIR(dest_stat.st_mode)) { - if (move_file(argv[optind], argv[optind + 1]) < 0) - status = 1; - return status; + RET_0: + if (dest != last) { + free((void *) dest); } - } - - for (i = optind; i < argc - 1; i++) { - char *dest = concat_path_file(argv[argc - 1], - get_last_path_component(argv[i])); - if (move_file(argv[i], dest) < 0) - status = 1; - free(dest); - } - - return status; + + } while (*++argv != last); + + exit(status); } diff --git a/coreutils/od.c b/coreutils/od.c index 6187cad..5eaaf50 100644 --- a/coreutils/od.c +++ b/coreutils/od.c @@ -23,22 +23,18 @@ */ #include <ctype.h> +#include <string.h> #include <getopt.h> #include <stdlib.h> -#include "dump.h" #include "busybox.h" +#include "dump.h" -extern FS *fshead; /* head of format strings */ -extern int blocksize; /* data block size */ -extern int length; /* max bytes to read */ - -#define ishexdigit(c) \ - ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) +#define isdecdigit(c) (isdigit)(c) +#define ishexdigit(c) (isxdigit)(c) static void odoffset(int argc, char ***argvp) { - extern off_t skip; register char *num, *p; int base; char *end; @@ -62,13 +58,15 @@ odoffset(int argc, char ***argvp) return; } - if (*p != '+' && (argc < 2 || - (!isdigit(p[0]) && (p[0] != 'x' || !ishexdigit(p[1]))))) + if ((*p != '+') + && (argc < 2 + || (!isdecdigit(p[0]) + && ((p[0] != 'x') || !ishexdigit(p[1]))))) return; base = 0; /* - * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and + * bb_dump_skip over leading '+', 'x[0-9a-fA-f]' or '0x', and * set base. */ if (p[0] == '+') @@ -81,11 +79,11 @@ odoffset(int argc, char ***argvp) base = 16; } - /* skip over the number */ + /* bb_dump_skip over the number */ if (base == 16) for (num = p; ishexdigit(*p); ++p); else - for (num = p; isdigit(*p); ++p); + for (num = p; isdecdigit(*p); ++p); /* check for no number */ if (num == p) @@ -98,21 +96,23 @@ odoffset(int argc, char ***argvp) base = 10; } - skip = strtol(num, &end, base ? base : 8); + bb_dump_skip = strtol(num, &end, base ? base : 8); /* if end isn't the same as p, we got a non-octal digit */ if (end != p) - skip = 0; + bb_dump_skip = 0; else { if (*p) { - if (*p == 'b') - skip *= 512; - else if (*p == 'B') - skip *= 1024; - ++p; + if (*p == 'b') { + bb_dump_skip *= 512; + ++p; + } else if (*p == 'B') { + bb_dump_skip *= 1024; + ++p; + } } if (*p) - skip = 0; + bb_dump_skip = 0; else { ++*argvp; /* @@ -121,117 +121,76 @@ odoffset(int argc, char ***argvp) * but it's easy. */ #define TYPE_OFFSET 7 - if (base == 16) { - fshead->nextfu->fmt[TYPE_OFFSET] = 'x'; - fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x'; - } else if (base == 10) { - fshead->nextfu->fmt[TYPE_OFFSET] = 'd'; - fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd'; + { + char x_or_d; + if (base == 16) { + x_or_d = 'x'; + goto DO_X_OR_D; + } + if (base == 10) { + x_or_d = 'd'; + DO_X_OR_D: + bb_dump_fshead->nextfu->fmt[TYPE_OFFSET] + = bb_dump_fshead->nextfs->nextfu->fmt[TYPE_OFFSET] + = x_or_d; + } } } } } -static void odprecede(void) -{ - static int first = 1; - - if (first) { - first = 0; - add("\"%07.7_Ao\n\""); - add("\"%07.7_ao \""); - } else - add("\" \""); -} +static const char * const add_strings[] = { + "16/1 \"%3_u \" \"\\n\"", /* a */ + "8/2 \" %06o \" \"\\n\"", /* B, o */ + "16/1 \"%03o \" \"\\n\"", /* b */ + "16/1 \"%3_c \" \"\\n\"", /* c */ + "8/2 \" %05u \" \"\\n\"", /* d */ + "4/4 \" %010u \" \"\\n\"", /* D */ + "2/8 \" %21.14e \" \"\\n\"", /* e (undocumented in od), F */ + "4/4 \" %14.7e \" \"\\n\"", /* f */ + "4/4 \" %08x \" \"\\n\"", /* H, X */ + "8/2 \" %04x \" \"\\n\"", /* h, x */ + "4/4 \" %11d \" \"\\n\"", /* I, L, l */ + "8/2 \" %6d \" \"\\n\"", /* i */ + "4/4 \" %011o \" \"\\n\"", /* O */ +}; + +static const signed char od_opts[] = "aBbcDdeFfHhIiLlOovXx"; + +static const signed char od_o2si[] = { + 0, 1, 2, 3, 5, + 4, 6, 6, 7, 8, + 9, 0xa, 0xb, 0xa, 0xa, + 0xb, 1, -1, 8, 9, +}; int od_main(int argc, char **argv) { int ch; - extern enum _vflag vflag; - vflag = FIRST; - length = -1; - - while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != EOF) - switch (ch) { - case 'a': - odprecede(); - add("16/1 \"%3_u \" \"\\n\""); - break; - case 'B': - case 'o': - odprecede(); - add("8/2 \" %06o \" \"\\n\""); - break; - case 'b': - odprecede(); - add("16/1 \"%03o \" \"\\n\""); - break; - case 'c': - odprecede(); - add("16/1 \"%3_c \" \"\\n\""); - break; - case 'd': - odprecede(); - add("8/2 \" %05u \" \"\\n\""); - break; - case 'D': - odprecede(); - add("4/4 \" %010u \" \"\\n\""); - break; - case 'e': /* undocumented in od */ - case 'F': - odprecede(); - add("2/8 \" %21.14e \" \"\\n\""); - break; - - case 'f': - odprecede(); - add("4/4 \" %14.7e \" \"\\n\""); - break; - case 'H': - case 'X': - odprecede(); - add("4/4 \" %08x \" \"\\n\""); - break; - case 'h': - case 'x': - odprecede(); - add("8/2 \" %04x \" \"\\n\""); - break; - case 'I': - case 'L': - case 'l': - odprecede(); - add("4/4 \" %11d \" \"\\n\""); - break; - case 'i': - odprecede(); - add("8/2 \" %6d \" \"\\n\""); - break; - case 'O': - odprecede(); - add("4/4 \" %011o \" \"\\n\""); - break; - case 'v': - vflag = ALL; - break; - case 'P': - case 'p': - case 's': - case 'w': - case '?': - default: - error_msg("od: od(1) has been deprecated for hexdump(1).\n"); - if (ch != '?') { - error_msg("od: hexdump(1) compatibility doesn't support the -%c option%s\n", - ch, ch == 's' ? "; see strings(1)." : "."); + bb_dump_vflag = FIRST; + bb_dump_length = -1; + int first = 1; + signed char *p; + + while ((ch = getopt(argc, argv, od_opts)) > 0) { + if (((p = strchr(od_opts, ch)) != NULL) && (*p >= 0)) { + if (first) { + first = 0; + bb_dump_add("\"%07.7_Ao\n\""); + bb_dump_add("\"%07.7_ao \""); + } else { + bb_dump_add("\" \""); } - show_usage(); + bb_dump_add(add_strings[od_o2si[(int)(p-od_opts)]]); + } else if (ch == 'v') { + bb_dump_vflag = ALL; + } else { /* P, p, s, w, or other unhandled */ + bb_show_usage(); } - - if (!fshead) { - add("\"%07.7_Ao\n\""); - add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\""); + } + if (!bb_dump_fshead) { + bb_dump_add("\"%07.7_Ao\n\""); + bb_dump_add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\""); } argc -= optind; @@ -239,7 +198,7 @@ int od_main(int argc, char **argv) odoffset(argc, &argv); - return(dump(argv)); + return(bb_dump_dump(argv)); } /*- diff --git a/coreutils/printf.c b/coreutils/printf.c index d579a9b..9602788 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -124,7 +124,7 @@ int printf_main(int argc, char **argv) exit_status = 0; if (argc <= 1 || **(argv + 1) == '-') { - show_usage(); + bb_show_usage(); } format = argv[1]; diff --git a/coreutils/pwd.c b/coreutils/pwd.c index 9c5d70c..7e0dc05 100644 --- a/coreutils/pwd.c +++ b/coreutils/pwd.c @@ -20,24 +20,18 @@ * */ -/* getopt not needed */ - #include <stdio.h> -#include <dirent.h> -#include <errno.h> -#include <unistd.h> #include <stdlib.h> #include "busybox.h" extern int pwd_main(int argc, char **argv) { - static char *buf; - - buf = xgetcwd(buf); - - if (buf != NULL) { + char *buf; + + if ((buf = xgetcwd(NULL)) != NULL) { puts(buf); - return EXIT_SUCCESS; + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } + return EXIT_FAILURE; } diff --git a/coreutils/realpath.c b/coreutils/realpath.c index f89e0a2..ec98221 100644 --- a/coreutils/realpath.c +++ b/coreutils/realpath.c @@ -14,17 +14,26 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* BB_AUDIT SUSv3 N/A -- Apparently a busybox extension. */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Now does proper error checking on output and returns a failure exit code + * if one or more paths can not be resolved. + */ + #include <limits.h> #include <stdlib.h> - #include "busybox.h" int realpath_main(int argc, char **argv) { + int retval = EXIT_SUCCESS; + RESERVE_CONFIG_BUFFER(resolved_path, PATH_MAX); if (--argc == 0) { - show_usage(); + bb_show_usage(); } do { @@ -32,11 +41,14 @@ int realpath_main(int argc, char **argv) if (realpath(*argv, resolved_path) != NULL) { puts(resolved_path); } else { - perror_msg("%s", *argv); + retval = EXIT_FAILURE; + bb_perror_msg("%s", *argv); } } while (--argc); +#ifdef CONFIG_FEATURE_CLEAN_UP RELEASE_CONFIG_BUFFER(resolved_path); +#endif - return(EXIT_SUCCESS); + bb_fflush_stdout_and_exit(retval); } diff --git a/coreutils/rm.c b/coreutils/rm.c index 51c9f4c..5489350 100644 --- a/coreutils/rm.c +++ b/coreutils/rm.c @@ -2,7 +2,6 @@ /* * Mini rm implementation for busybox * - * * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu> * * @@ -22,55 +21,51 @@ * */ -#include <stdio.h> -#include <time.h> -#include <utime.h> -#include <dirent.h> -#include <errno.h> +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/rm.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Size reduction. + */ + #include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <getopt.h> #include "busybox.h" extern int rm_main(int argc, char **argv) { int status = 0; - int opt; int flags = 0; - int i; + int opt; - while ((opt = getopt(argc, argv, "fiRr")) != -1) { - switch (opt) { - case 'f': - flags &= ~FILEUTILS_INTERACTIVE; - flags |= FILEUTILS_FORCE; - break; - case 'i': - flags &= ~FILEUTILS_FORCE; - flags |= FILEUTILS_INTERACTIVE; - break; - case 'R': - case 'r': + while ((opt = getopt(argc, argv, "fiRr")) > 0) { + if ((opt == 'r') || (opt == 'R')) { flags |= FILEUTILS_RECUR; - break; + } else { + flags &= ~(FILEUTILS_INTERACTIVE | FILEUTILS_FORCE); + if (opt == 'i') { + flags |= FILEUTILS_INTERACTIVE; + } else if (opt == 'f') { + flags |= FILEUTILS_FORCE; + } else { + bb_show_usage(); + } } } - if (!(flags & FILEUTILS_FORCE) && optind == argc) - show_usage(); - - for (i = optind; i < argc; i++) { - char *base = get_last_path_component(argv[i]); - - if (strcmp(base, ".") == 0 || strcmp(base, "..") == 0) { - error_msg("cannot remove `.' or `..'"); - status = 1; - continue; - } + if (*(argv += optind) != NULL) { + do { + const char *base = bb_get_last_path_component(*argv); - if (remove_file(argv[i], flags) < 0) + if ((base[0] == '.') && (!base[1] || ((base[1] == '.') && !base[2]))) { + bb_error_msg("cannot remove `.' or `..'"); + } else if (remove_file(*argv, flags) >= 0) { + continue; + } status = 1; + } while (*++argv); + } else if (!(flags & FILEUTILS_FORCE)) { + bb_show_usage(); } return status; diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c index 83b27c9..3f60371 100644 --- a/coreutils/rmdir.c +++ b/coreutils/rmdir.c @@ -1,9 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini rmdir implementation for busybox + * rmdir implementation for busybox * - * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen - * 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 @@ -21,76 +20,54 @@ * */ -#include <getopt.h> -#include <unistd.h> -#include <stdlib.h> +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */ +#include <stdlib.h> +#include <unistd.h> +#include <libgen.h> #include "busybox.h" - -/* Return true if a path is composed of multiple components. */ - -static int -multiple_components_p (const char *path) -{ - const char *s = path; - - while (s[0] != '\0' && s[0] != '/') - s++; - - while (s[0] == '/') - s++; - - return (s[0] != '\0'); -} - - -/* Remove a directory. Returns 0 if successful, -1 on error. */ - -static int -remove_directory (char *path, int flags) -{ - if (!(flags & FILEUTILS_RECUR)) { - if (rmdir (path) < 0) { - perror_msg ("unable to remove `%s'", path); - return -1; - } - } else { - if (remove_directory (path, 0) < 0) - return -1; - - if (multiple_components_p (path)) - if (remove_directory (dirname (path), flags) < 0) - return -1; - } - - return 0; -} - - -extern int -rmdir_main (int argc, char **argv) +extern int rmdir_main(int argc, char **argv) { int status = EXIT_SUCCESS; - int flags = 0; - int i, opt; + int flags; + int do_dot; + char *path; - while ((opt = getopt (argc, argv, "p")) != -1) - switch (opt) { - case 'p': - flags |= FILEUTILS_RECUR; - break; + flags = bb_getopt_ulflags(argc, argv, "p"); - default: - show_usage (); - } + argv += optind; - if (optind == argc) - show_usage(); + if (!*argv) { + bb_show_usage(); + } - for (i = optind; i < argc; i++) - if (remove_directory (argv[i], flags) < 0) - status = EXIT_FAILURE; + do { + path = *argv; + + /* Record if the first char was a '.' so we can use dirname later. */ + do_dot = (*path == '.'); + + do { + if (rmdir(path) < 0) { + bb_perror_msg("`%s'", path); /* Match gnu rmdir msg. */ + status = EXIT_FAILURE; + } else if (flags) { + /* Note: path was not empty or null since rmdir succeeded. */ + path = dirname(path); + /* Path is now just the parent component. Note that dirname + * returns "." if there are no parents. We must distinguish + * this from the case of the original path starting with '.'. + */ + if (do_dot || (*path != '.') || path[1]) { + continue; + } + } + break; + } while (1); + + } while (*++argv); return status; } diff --git a/coreutils/sha1sum.c b/coreutils/sha1sum.c index 03009f7..d94cb4b 100644 --- a/coreutils/sha1sum.c +++ b/coreutils/sha1sum.c @@ -187,7 +187,7 @@ extern int authenticate(const int argc, char **argv, void (*hash_ptr)(FILE *stre break; #endif default: - show_usage(); + bb_show_usage(); } } @@ -204,7 +204,7 @@ extern int authenticate(const int argc, char **argv, void (*hash_ptr)(FILE *stre hash_ptr(stdin, hashval); print_hash(hash_length, hashval, NULL); } else { - FILE *stream = xfopen(argv[i], "r"); + FILE *stream = bb_xfopen(argv[i], "r"); hash_ptr(stream, hashval); fclose(stream); print_hash(hash_length, hashval, argv[i]); diff --git a/coreutils/sleep.c b/coreutils/sleep.c index 7bc98d8..506192d 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c @@ -1,8 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini sleep implementation for busybox + * sleep implementation for busybox * - * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. + * 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 @@ -20,18 +20,67 @@ * */ -#include <stdio.h> -#include <unistd.h> +/* BB_AUDIT SUSv3 compliant */ +/* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/sleep.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Rewritten to do proper arg and error checking. + * Also, added a 'fancy' configuration to accept multiple args with + * time suffixes for seconds, minutes, hours, and days. + */ + #include <stdlib.h> +#include <limits.h> +#include <unistd.h> #include "busybox.h" +#ifdef CONFIG_FEATURE_FANCY_SLEEP +static const struct suffix_mult sleep_suffixes[] = { + { "s", 1 }, + { "m", 60 }, + { "h", 60*60 }, + { "d", 24*60*60 }, + { NULL, 0 } +}; +#endif + extern int sleep_main(int argc, char **argv) { - if ((argc < 2) || (**(argv + 1) == '-')) { - show_usage(); + unsigned int duration; + +#ifdef CONFIG_FEATURE_FANCY_SLEEP + + if (argc < 2) { + bb_show_usage(); + } + + ++argv; + duration = 0; + do { + duration += bb_xgetularg_bnd_sfx(*argv, 10, + 0, UINT_MAX-duration, + sleep_suffixes); + } while (*++argv); + +#else /* CONFIG_FEATURE_FANCY_SLEEP */ + + if (argc != 2) { + bb_show_usage(); + } + +#if UINT_MAX == ULONG_MAX + duration = bb_xgetularg10(argv[1]); +#else + duration = bb_xgetularg10_bnd(argv[1], 0, UINT_MAX); +#endif + +#endif /* CONFIG_FEATURE_FANCY_SLEEP */ + + if (sleep(duration)) { + bb_perror_nomsg_and_die(); } - if (sleep(atoi(*(++argv))) != 0) - perror_msg_and_die("sleep"); return EXIT_SUCCESS; } diff --git a/coreutils/sort.c b/coreutils/sort.c index fc12dfb..8cc4d88 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c @@ -2,7 +2,6 @@ /* * Mini sort implementation for busybox * - * * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> * * This program is free software; you can redistribute it and/or modify @@ -21,10 +20,20 @@ * */ -#include <getopt.h> -#include <string.h> +/* BB_AUDIT SUSv3 _NOT_ compliant -- a number of options are not supported. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Now does proper error checking on i/o. Plus some space savings. + */ + +#include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <unistd.h> #include "busybox.h" +#include "libcoreutils/coreutils.h" static int compare_ascii(const void *x, const void *y) { @@ -41,66 +50,51 @@ int sort_main(int argc, char **argv) { FILE *fp; char *line, **lines = NULL; - int i, opt, nlines = 0; + int i, nlines = 0, inc; int (*compare)(const void *, const void *) = compare_ascii; -#ifdef CONFIG_FEATURE_SORT_REVERSE - int reverse = FALSE; -#endif -#ifdef CONFIG_FEATURE_SORT_UNIQUE - int unique = FALSE; -#endif - while ((opt = getopt(argc, argv, "nru")) != -1) { - switch (opt) { - case 'n': - compare = compare_numeric; - break; -#ifdef CONFIG_FEATURE_SORT_REVERSE - case 'r': - reverse = TRUE; - break; -#endif -#ifdef CONFIG_FEATURE_SORT_UNIQUE - case 'u': - unique = TRUE; - break; -#endif - default: - show_usage(); - } + int flags; + + bb_default_error_retval = 2; + + flags = bb_getopt_ulflags(argc, argv, "nru"); + if (flags & 1) { + compare = compare_numeric; } - /* read the input */ - for (i = optind; i == optind || i < argc; i++) { - if (argv[i] == NULL) - fp = stdin; - else - fp = xfopen(argv[i], "r"); + argv += optind; + if (!*argv) { + *--argv = "-"; + } - while ((line = get_line_from_file(fp)) != NULL) { + do { + fp = xgetoptfile_sort_uniq(argv, "r"); + while ((line = bb_get_chomped_line_from_file(fp)) != NULL) { lines = xrealloc(lines, sizeof(char *) * (nlines + 1)); - chomp(line); lines[nlines++] = line; } - } + bb_xferror(fp, *argv); + bb_fclose_nonstdin(fp); + } while (*++argv); /* sort it */ qsort(lines, nlines, sizeof(char *), compare); /* print it */ -#ifdef CONFIG_FEATURE_SORT_REVERSE - if (reverse) { - for (i = --nlines; 0 <= i; i--) -#ifdef CONFIG_FEATURE_SORT_UNIQUE - if((!unique) || (i == nlines) || (strcmp(lines[i + 1], lines[i]))) -#endif - puts(lines[i]); - } else -#endif - for (i = 0; i < nlines; i++) -#ifdef CONFIG_FEATURE_SORT_UNIQUE - if((!unique) || (!i) || (strcmp(lines[i - 1], lines[i]))) -#endif - puts(lines[i]); - return EXIT_SUCCESS; + i = 0; + --nlines; + if ((inc = 1 - (flags & 2)) < 0) { /* reverse */ + i = nlines; + } + flags &= 4; + + while (nlines >= 0) { + if (!flags || !nlines || strcmp(lines[i+inc], lines[i])) { + puts(lines[i]); + } + i += inc; + --nlines; + } + + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } diff --git a/coreutils/stty.c b/coreutils/stty.c index a67a17c..a3a98d9 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c @@ -30,9 +30,9 @@ //#define TEST +#include <stddef.h> #include <termios.h> #include <sys/ioctl.h> -#include <getopt.h> #include <sys/param.h> #include <unistd.h> @@ -155,13 +155,10 @@ enum speed_setting { input_speed, output_speed, both_speeds }; -/* What to output and how. */ -enum output_type { - changed, all, recoverable /* Default, -a, -g. */ -}; - /* Which member(s) of `struct termios' a mode uses. */ enum mode_type { + /* Do NOT change the order or values, as mode_type_flag() + * depends on them. */ control, input, output, local, combination }; @@ -199,156 +196,159 @@ static const char stty_dec [] = "dec"; /* Each mode. */ struct mode_info { const char *name; /* Name given on command line. */ - enum mode_type type; /* Which structure element to change. */ + /* enum mode_type type; */ + char type; /* Which structure element to change. */ char flags; /* Setting and display options. */ + unsigned short mask; /* Other bits to turn off for this mode. */ unsigned long bits; /* Bits to set for this mode. */ - unsigned long mask; /* Other bits to turn off for this mode. */ }; +#define MI_ENTRY(N,T,F,B,M) { N, T, F, M, B } + static const struct mode_info mode_info[] = { - {"parenb", control, REV, PARENB, 0 }, - {"parodd", control, REV, PARODD, 0 }, - {"cs5", control, 0, CS5, CSIZE}, - {"cs6", control, 0, CS6, CSIZE}, - {"cs7", control, 0, CS7, CSIZE}, - {"cs8", control, 0, CS8, CSIZE}, - {"hupcl", control, REV, HUPCL, 0 }, - {"hup", control, REV | OMIT, HUPCL, 0 }, - {"cstopb", control, REV, CSTOPB, 0 }, - {"cread", control, SANE_SET | REV, CREAD, 0 }, - {"clocal", control, REV, CLOCAL, 0 }, + MI_ENTRY("parenb", control, REV, PARENB, 0 ), + MI_ENTRY("parodd", control, REV, PARODD, 0 ), + MI_ENTRY("cs5", control, 0, CS5, CSIZE), + MI_ENTRY("cs6", control, 0, CS6, CSIZE), + MI_ENTRY("cs7", control, 0, CS7, CSIZE), + MI_ENTRY("cs8", control, 0, CS8, CSIZE), + MI_ENTRY("hupcl", control, REV, HUPCL, 0 ), + MI_ENTRY("hup", control, REV | OMIT, HUPCL, 0 ), + MI_ENTRY("cstopb", control, REV, CSTOPB, 0 ), + MI_ENTRY("cread", control, SANE_SET | REV, CREAD, 0 ), + MI_ENTRY("clocal", control, REV, CLOCAL, 0 ), #ifdef CRTSCTS - {"crtscts", control, REV, CRTSCTS, 0 }, -#endif - {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0 }, - {"brkint", input, SANE_SET | REV, BRKINT, 0 }, - {"ignpar", input, REV, IGNPAR, 0 }, - {"parmrk", input, REV, PARMRK, 0 }, - {"inpck", input, REV, INPCK, 0 }, - {"istrip", input, REV, ISTRIP, 0 }, - {"inlcr", input, SANE_UNSET | REV, INLCR, 0 }, - {"igncr", input, SANE_UNSET | REV, IGNCR, 0 }, - {"icrnl", input, SANE_SET | REV, ICRNL, 0 }, - {"ixon", input, REV, IXON, 0 }, - {"ixoff", input, SANE_UNSET | REV, IXOFF, 0 }, - {"tandem", input, REV | OMIT, IXOFF, 0 }, + MI_ENTRY("crtscts", control, REV, CRTSCTS, 0 ), +#endif + MI_ENTRY("ignbrk", input, SANE_UNSET | REV, IGNBRK, 0 ), + MI_ENTRY("brkint", input, SANE_SET | REV, BRKINT, 0 ), + MI_ENTRY("ignpar", input, REV, IGNPAR, 0 ), + MI_ENTRY("parmrk", input, REV, PARMRK, 0 ), + MI_ENTRY("inpck", input, REV, INPCK, 0 ), + MI_ENTRY("istrip", input, REV, ISTRIP, 0 ), + MI_ENTRY("inlcr", input, SANE_UNSET | REV, INLCR, 0 ), + MI_ENTRY("igncr", input, SANE_UNSET | REV, IGNCR, 0 ), + MI_ENTRY("icrnl", input, SANE_SET | REV, ICRNL, 0 ), + MI_ENTRY("ixon", input, REV, IXON, 0 ), + MI_ENTRY("ixoff", input, SANE_UNSET | REV, IXOFF, 0 ), + MI_ENTRY("tandem", input, REV | OMIT, IXOFF, 0 ), #ifdef IUCLC - {"iuclc", input, SANE_UNSET | REV, IUCLC, 0 }, + MI_ENTRY("iuclc", input, SANE_UNSET | REV, IUCLC, 0 ), #endif #ifdef IXANY - {"ixany", input, SANE_UNSET | REV, IXANY, 0 }, + MI_ENTRY("ixany", input, SANE_UNSET | REV, IXANY, 0 ), #endif #ifdef IMAXBEL - {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0 }, + MI_ENTRY("imaxbel", input, SANE_SET | REV, IMAXBEL, 0 ), #endif - {"opost", output, SANE_SET | REV, OPOST, 0 }, + MI_ENTRY("opost", output, SANE_SET | REV, OPOST, 0 ), #ifdef OLCUC - {"olcuc", output, SANE_UNSET | REV, OLCUC, 0 }, + MI_ENTRY("olcuc", output, SANE_UNSET | REV, OLCUC, 0 ), #endif #ifdef OCRNL - {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0 }, + MI_ENTRY("ocrnl", output, SANE_UNSET | REV, OCRNL, 0 ), #endif #ifdef ONLCR - {"onlcr", output, SANE_SET | REV, ONLCR, 0 }, + MI_ENTRY("onlcr", output, SANE_SET | REV, ONLCR, 0 ), #endif #ifdef ONOCR - {"onocr", output, SANE_UNSET | REV, ONOCR, 0 }, + MI_ENTRY("onocr", output, SANE_UNSET | REV, ONOCR, 0 ), #endif #ifdef ONLRET - {"onlret", output, SANE_UNSET | REV, ONLRET, 0 }, + MI_ENTRY("onlret", output, SANE_UNSET | REV, ONLRET, 0 ), #endif #ifdef OFILL - {"ofill", output, SANE_UNSET | REV, OFILL, 0 }, + MI_ENTRY("ofill", output, SANE_UNSET | REV, OFILL, 0 ), #endif #ifdef OFDEL - {"ofdel", output, SANE_UNSET | REV, OFDEL, 0 }, + MI_ENTRY("ofdel", output, SANE_UNSET | REV, OFDEL, 0 ), #endif #ifdef NLDLY - {"nl1", output, SANE_UNSET, NL1, NLDLY}, - {"nl0", output, SANE_SET, NL0, NLDLY}, + MI_ENTRY("nl1", output, SANE_UNSET, NL1, NLDLY), + MI_ENTRY("nl0", output, SANE_SET, NL0, NLDLY), #endif #ifdef CRDLY - {"cr3", output, SANE_UNSET, CR3, CRDLY}, - {"cr2", output, SANE_UNSET, CR2, CRDLY}, - {"cr1", output, SANE_UNSET, CR1, CRDLY}, - {"cr0", output, SANE_SET, CR0, CRDLY}, + MI_ENTRY("cr3", output, SANE_UNSET, CR3, CRDLY), + MI_ENTRY("cr2", output, SANE_UNSET, CR2, CRDLY), + MI_ENTRY("cr1", output, SANE_UNSET, CR1, CRDLY), + MI_ENTRY("cr0", output, SANE_SET, CR0, CRDLY), #endif #ifdef TABDLY - {"tab3", output, SANE_UNSET, TAB3, TABDLY}, - {"tab2", output, SANE_UNSET, TAB2, TABDLY}, - {"tab1", output, SANE_UNSET, TAB1, TABDLY}, - {"tab0", output, SANE_SET, TAB0, TABDLY}, + MI_ENTRY("tab3", output, SANE_UNSET, TAB3, TABDLY), + MI_ENTRY("tab2", output, SANE_UNSET, TAB2, TABDLY), + MI_ENTRY("tab1", output, SANE_UNSET, TAB1, TABDLY), + MI_ENTRY("tab0", output, SANE_SET, TAB0, TABDLY), #else # ifdef OXTABS - {"tab3", output, SANE_UNSET, OXTABS, 0 }, + MI_ENTRY("tab3", output, SANE_UNSET, OXTABS, 0 ), # endif #endif #ifdef BSDLY - {"bs1", output, SANE_UNSET, BS1, BSDLY}, - {"bs0", output, SANE_SET, BS0, BSDLY}, + MI_ENTRY("bs1", output, SANE_UNSET, BS1, BSDLY), + MI_ENTRY("bs0", output, SANE_SET, BS0, BSDLY), #endif #ifdef VTDLY - {"vt1", output, SANE_UNSET, VT1, VTDLY}, - {"vt0", output, SANE_SET, VT0, VTDLY}, + MI_ENTRY("vt1", output, SANE_UNSET, VT1, VTDLY), + MI_ENTRY("vt0", output, SANE_SET, VT0, VTDLY), #endif #ifdef FFDLY - {"ff1", output, SANE_UNSET, FF1, FFDLY}, - {"ff0", output, SANE_SET, FF0, FFDLY}, + MI_ENTRY("ff1", output, SANE_UNSET, FF1, FFDLY), + MI_ENTRY("ff0", output, SANE_SET, FF0, FFDLY), #endif - {"isig", local, SANE_SET | REV, ISIG, 0 }, - {"icanon", local, SANE_SET | REV, ICANON, 0 }, + MI_ENTRY("isig", local, SANE_SET | REV, ISIG, 0 ), + MI_ENTRY("icanon", local, SANE_SET | REV, ICANON, 0 ), #ifdef IEXTEN - {"iexten", local, SANE_SET | REV, IEXTEN, 0 }, -#endif - {"echo", local, SANE_SET | REV, ECHO, 0 }, - {"echoe", local, SANE_SET | REV, ECHOE, 0 }, - {"crterase", local, REV | OMIT, ECHOE, 0 }, - {"echok", local, SANE_SET | REV, ECHOK, 0 }, - {"echonl", local, SANE_UNSET | REV, ECHONL, 0 }, - {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0 }, + MI_ENTRY("iexten", local, SANE_SET | REV, IEXTEN, 0 ), +#endif + MI_ENTRY("echo", local, SANE_SET | REV, ECHO, 0 ), + MI_ENTRY("echoe", local, SANE_SET | REV, ECHOE, 0 ), + MI_ENTRY("crterase", local, REV | OMIT, ECHOE, 0 ), + MI_ENTRY("echok", local, SANE_SET | REV, ECHOK, 0 ), + MI_ENTRY("echonl", local, SANE_UNSET | REV, ECHONL, 0 ), + MI_ENTRY("noflsh", local, SANE_UNSET | REV, NOFLSH, 0 ), #ifdef XCASE - {"xcase", local, SANE_UNSET | REV, XCASE, 0 }, + MI_ENTRY("xcase", local, SANE_UNSET | REV, XCASE, 0 ), #endif #ifdef TOSTOP - {"tostop", local, SANE_UNSET | REV, TOSTOP, 0 }, + MI_ENTRY("tostop", local, SANE_UNSET | REV, TOSTOP, 0 ), #endif #ifdef ECHOPRT - {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0 }, - {"prterase", local, REV | OMIT, ECHOPRT, 0 }, + MI_ENTRY("echoprt", local, SANE_UNSET | REV, ECHOPRT, 0 ), + MI_ENTRY("prterase", local, REV | OMIT, ECHOPRT, 0 ), #endif #ifdef ECHOCTL - {"echoctl", local, SANE_SET | REV, ECHOCTL, 0 }, - {"ctlecho", local, REV | OMIT, ECHOCTL, 0 }, + MI_ENTRY("echoctl", local, SANE_SET | REV, ECHOCTL, 0 ), + MI_ENTRY("ctlecho", local, REV | OMIT, ECHOCTL, 0 ), #endif #ifdef ECHOKE - {"echoke", local, SANE_SET | REV, ECHOKE, 0 }, - {"crtkill", local, REV | OMIT, ECHOKE, 0 }, -#endif - {evenp, combination, REV | OMIT, 0, 0 }, - {parity, combination, REV | OMIT, 0, 0 }, - {stty_oddp, combination, REV | OMIT, 0, 0 }, - {stty_nl, combination, REV | OMIT, 0, 0 }, - {stty_ek, combination, OMIT, 0, 0 }, - {stty_sane, combination, OMIT, 0, 0 }, - {cooked, combination, REV | OMIT, 0, 0 }, - {raw, combination, REV | OMIT, 0, 0 }, - {stty_pass8, combination, REV | OMIT, 0, 0 }, - {litout, combination, REV | OMIT, 0, 0 }, - {cbreak, combination, REV | OMIT, 0, 0 }, + MI_ENTRY("echoke", local, SANE_SET | REV, ECHOKE, 0 ), + MI_ENTRY("crtkill", local, REV | OMIT, ECHOKE, 0 ), +#endif + MI_ENTRY(evenp, combination, REV | OMIT, 0, 0 ), + MI_ENTRY(parity, combination, REV | OMIT, 0, 0 ), + MI_ENTRY(stty_oddp, combination, REV | OMIT, 0, 0 ), + MI_ENTRY(stty_nl, combination, REV | OMIT, 0, 0 ), + MI_ENTRY(stty_ek, combination, OMIT, 0, 0 ), + MI_ENTRY(stty_sane, combination, OMIT, 0, 0 ), + MI_ENTRY(cooked, combination, REV | OMIT, 0, 0 ), + MI_ENTRY(raw, combination, REV | OMIT, 0, 0 ), + MI_ENTRY(stty_pass8, combination, REV | OMIT, 0, 0 ), + MI_ENTRY(litout, combination, REV | OMIT, 0, 0 ), + MI_ENTRY(cbreak, combination, REV | OMIT, 0, 0 ), #ifdef IXANY - {decctlq, combination, REV | OMIT, 0, 0 }, + MI_ENTRY(decctlq, combination, REV | OMIT, 0, 0 ), #endif #if defined (TABDLY) || defined (OXTABS) - {stty_tabs, combination, REV | OMIT, 0, 0 }, + MI_ENTRY(stty_tabs, combination, REV | OMIT, 0, 0 ), #endif #if defined(XCASE) && defined(IUCLC) && defined(OLCUC) - {stty_lcase, combination, REV | OMIT, 0, 0 }, - {stty_LCASE, combination, REV | OMIT, 0, 0 }, + MI_ENTRY(stty_lcase, combination, REV | OMIT, 0, 0 ), + MI_ENTRY(stty_LCASE, combination, REV | OMIT, 0, 0 ), #endif - {stty_crt, combination, OMIT, 0, 0 }, - {stty_dec, combination, OMIT, 0, 0 }, + MI_ENTRY(stty_crt, combination, OMIT, 0, 0 ), + MI_ENTRY(stty_dec, combination, OMIT, 0, 0 ), }; static const int NUM_mode_info = @@ -359,7 +359,7 @@ static const int NUM_mode_info = struct control_info { const char *name; /* Name given on command line. */ unsigned char saneval; /* Value to set for `stty sane'. */ - int offset; /* Offset in c_cc. */ + unsigned char offset; /* Offset in c_cc. */ }; /* Control characters. */ @@ -408,7 +408,6 @@ static const int NUM_control_info = static const char * visible(unsigned int ch); -static unsigned long baud_to_value(speed_t speed); static int recover_mode(char *arg, struct termios *mode); static int screen_columns(void); static int set_mode(const struct mode_info *info, @@ -416,12 +415,11 @@ static int set_mode(const struct mode_info *info, static speed_t string_to_baud(const char *arg); static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode); static void display_all(struct termios *mode, int fd, - const char *device_name); -static void display_changed(struct termios *mode); -static void display_recoverable(struct termios *mode); -static void display_settings(enum output_type output_type, - struct termios *mode, int fd, - const char *device_name); + const char *device_name); +static void display_changed(struct termios *mode, int fd, + const char *device_name); +static void display_recoverable(struct termios *mode, int fd, + const char *device_name); static void display_speed(struct termios *mode, int fancy); static void display_window_size(int fancy, int fd, const char *device_name); @@ -479,7 +477,7 @@ extern int main(int argc, char **argv) #endif { struct termios mode; - enum output_type output_type; + void (*output_func)(struct termios *, int, const char *); int optc; int require_set_attr; int speed_was_set; @@ -491,7 +489,7 @@ extern int main(int argc, char **argv) int fd; const char *device_name; - output_type = changed; + output_func = display_changed; verbose_output = 0; recoverable_output = 0; @@ -502,17 +500,17 @@ extern int main(int argc, char **argv) switch (optc) { case 'a': verbose_output = 1; - output_type = all; + output_func = display_all; break; case 'g': recoverable_output = 1; - output_type = recoverable; + output_func = display_recoverable; break; case 'F': if (file_name) - error_msg_and_die("only one device may be specified"); + bb_error_msg_and_die("only one device may be specified"); file_name = optarg; break; @@ -529,12 +527,12 @@ extern int main(int argc, char **argv) noargs = 0; /* Specifying both -a and -g gets an error. */ - if (verbose_output && recoverable_output) - error_msg_and_die ("verbose and stty-readable output styles are mutually exclusive"); + if (verbose_output & recoverable_output) + bb_error_msg_and_die ("verbose and stty-readable output styles are mutually exclusive"); /* Specifying any other arguments with -a or -g gets an error. */ - if (!noargs && (verbose_output || recoverable_output)) - error_msg_and_die ("modes may not be set when specifying an output style"); + if (~noargs & (verbose_output | recoverable_output)) + bb_error_msg_and_die ("modes may not be set when specifying an output style"); /* FIXME: it'd be better not to open the file until we've verified that all arguments are valid. Otherwise, we could end up doing @@ -547,26 +545,26 @@ extern int main(int argc, char **argv) device_name = file_name; fd = open(device_name, O_RDONLY | O_NONBLOCK); if (fd < 0) - perror_msg_and_die("%s", device_name); + bb_perror_msg_and_die("%s", device_name); if ((fdflags = fcntl(fd, F_GETFL)) == -1 || fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) - perror_msg_and_die("%s: couldn't reset non-blocking mode", + bb_perror_msg_and_die("%s: couldn't reset non-blocking mode", device_name); } else { fd = 0; - device_name = "standard input"; + device_name = bb_msg_standard_input; } /* Initialize to all zeroes so there is no risk memcmp will report a spurious difference in an uninitialized portion of the structure. */ memset(&mode, 0, sizeof(mode)); if (tcgetattr(fd, &mode)) - perror_msg_and_die("%s", device_name); + bb_perror_msg_and_die("%s", device_name); - if (verbose_output || recoverable_output || noargs) { + if (verbose_output | recoverable_output | noargs) { max_col = screen_columns(); current_col = 0; - display_settings(output_type, &mode, fd, device_name); + output_func(&mode, fd, device_name); return EXIT_SUCCESS; } @@ -610,13 +608,13 @@ extern int main(int argc, char **argv) } if (match_found == 0 && reversed) - error_msg_and_die("invalid argument `%s'", --argv[k]); + bb_error_msg_and_die("invalid argument `%s'", --argv[k]); if (match_found == 0) for (i = 0; i < NUM_control_info; ++i) if (STREQ(argv[k], control_info[i].name)) { if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); + bb_error_msg_and_die("missing argument to `%s'", argv[k]); match_found = 1; ++k; set_control_char(&control_info[i], argv[k], &mode); @@ -627,14 +625,14 @@ extern int main(int argc, char **argv) if (match_found == 0) { if (STREQ(argv[k], "ispeed")) { if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); + bb_error_msg_and_die("missing argument to `%s'", argv[k]); ++k; set_speed(input_speed, argv[k], &mode); speed_was_set = 1; require_set_attr = 1; } else if (STREQ(argv[k], "ospeed")) { if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); + bb_error_msg_and_die("missing argument to `%s'", argv[k]); ++k; set_speed(output_speed, argv[k], &mode); speed_was_set = 1; @@ -643,16 +641,16 @@ extern int main(int argc, char **argv) #ifdef TIOCGWINSZ else if (STREQ(argv[k], "rows")) { if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); + bb_error_msg_and_die("missing argument to `%s'", argv[k]); ++k; - set_window_size((int) parse_number(argv[k], stty_suffixes), + set_window_size((int) bb_xparse_number(argv[k], stty_suffixes), -1, fd, device_name); } else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) { if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); + bb_error_msg_and_die("missing argument to `%s'", argv[k]); ++k; set_window_size(-1, - (int) parse_number(argv[k], stty_suffixes), + (int) bb_xparse_number(argv[k], stty_suffixes), fd, device_name); } else if (STREQ(argv[k], "size")) { max_col = screen_columns(); @@ -663,9 +661,9 @@ extern int main(int argc, char **argv) #ifdef HAVE_C_LINE else if (STREQ(argv[k], "line")) { if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); + bb_error_msg_and_die("missing argument to `%s'", argv[k]); ++k; - mode.c_line = parse_number(argv[k], stty_suffixes); + mode.c_line = bb_xparse_number(argv[k], stty_suffixes); require_set_attr = 1; } #endif @@ -679,7 +677,7 @@ extern int main(int argc, char **argv) speed_was_set = 1; require_set_attr = 1; } else - error_msg_and_die("invalid argument `%s'", argv[k]); + bb_error_msg_and_die("invalid argument `%s'", argv[k]); } } @@ -687,7 +685,7 @@ extern int main(int argc, char **argv) struct termios new_mode; if (tcsetattr(fd, TCSADRAIN, &mode)) - perror_msg_and_die("%s", device_name); + bb_perror_msg_and_die("%s", device_name); /* POSIX (according to Zlotnick's book) tcsetattr returns zero if it performs *any* of the requested operations. This means it @@ -700,7 +698,7 @@ extern int main(int argc, char **argv) spurious difference in an uninitialized portion of the structure. */ memset(&new_mode, 0, sizeof(new_mode)); if (tcgetattr(fd, &new_mode)) - perror_msg_and_die("%s", device_name); + bb_perror_msg_and_die("%s", device_name); /* Normally, one shouldn't use memcmp to compare structures that may have `holes' containing uninitialized data, but we have been @@ -723,7 +721,7 @@ extern int main(int argc, char **argv) new_mode.c_cflag &= (~CIBAUD); if (speed_was_set || memcmp(&mode, &new_mode, sizeof(mode)) != 0) #endif - error_msg_and_die ("%s: unable to perform all requested operations", + bb_error_msg_and_die ("%s: unable to perform all requested operations", device_name); } } @@ -896,9 +894,9 @@ set_mode(const struct mode_info *info, int reversed, struct termios *mode) #endif } } else if (reversed) - *bitsp = *bitsp & ~info->mask & ~info->bits; + *bitsp = *bitsp & ~((unsigned long)info->mask) & ~info->bits; else - *bitsp = (*bitsp & ~info->mask) | info->bits; + *bitsp = (*bitsp & ~((unsigned long)info->mask)) | info->bits; return 1; } @@ -910,7 +908,7 @@ set_control_char(const struct control_info *info, const char *arg, unsigned char value; if (info->name == stty_min || info->name == stty_time) - value = parse_number(arg, stty_suffixes); + value = bb_xparse_number(arg, stty_suffixes); else if (arg[0] == '\0' || arg[1] == '\0') value = arg[0]; else if (STREQ(arg, "^-") || STREQ(arg, "undef")) @@ -921,7 +919,7 @@ set_control_char(const struct control_info *info, const char *arg, else value = arg[1] & ~0140; /* Non-letters get weird results. */ } else - value = parse_number(arg, stty_suffixes); + value = bb_xparse_number(arg, stty_suffixes); mode->c_cc[info->offset] = value; } @@ -931,10 +929,13 @@ set_speed(enum speed_setting type, const char *arg, struct termios *mode) speed_t baud; baud = string_to_baud(arg); - if (type == input_speed || type == both_speeds) + + if (type != output_speed) { /* either input or both */ cfsetispeed(mode, baud); - if (type == output_speed || type == both_speeds) + } + if (type != input_speed) { /* either output or both */ cfsetospeed(mode, baud); + } } #ifdef TIOCGWINSZ @@ -953,7 +954,7 @@ set_window_size(int rows, int cols, int fd, const char *device_name) if (get_win_size(fd, &win)) { if (errno != EINVAL) - perror_msg_and_die("%s", device_name); + bb_perror_msg_and_die("%s", device_name); memset(&win, 0, sizeof(win)); } @@ -975,32 +976,28 @@ set_window_size(int rows, int cols, int fd, const char *device_name) ttysz.ts_lines = win.ws_row; ttysz.ts_cols = win.ws_col; - win.ws_row = 1; - win.ws_col = 1; - - if (ioctl(fd, TIOCSWINSZ, (char *) &win)) - perror_msg_and_die("%s", device_name); + win.ws_row = win.ws_col = 1; - if (ioctl(fd, TIOCSSIZE, (char *) &ttysz)) - perror_msg_and_die("%s", device_name); + if ((ioctl(fd, TIOCSWINSZ, (char *) &win) != 0) + || (ioctl(fd, TIOCSSIZE, (char *) &ttysz) != 0)) { + bb_perror_msg_and_die("%s", device_name); return; } # endif if (ioctl(fd, TIOCSWINSZ, (char *) &win)) - perror_msg_and_die("%s", device_name); + bb_perror_msg_and_die("%s", device_name); } static void display_window_size(int fancy, int fd, const char *device_name) { + const char *fmt_str = "%s" "\0" "%s: no size information for this device"; struct winsize win; if (get_win_size(fd, &win)) { - if (errno != EINVAL) - perror_msg_and_die("%s", device_name); - if (!fancy) - perror_msg_and_die("%s: no size information for this device", - device_name); + if ((errno != EINVAL) || ((fmt_str += 2), !fancy)) { + bb_perror_msg_and_die(fmt_str, device_name); + } } else { wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n", win.ws_row, win.ws_col); @@ -1012,6 +1009,9 @@ static void display_window_size(int fancy, int fd, const char *device_name) static int screen_columns(void) { + int columns; + const char *s; + #ifdef TIOCGWINSZ struct winsize win; @@ -1025,51 +1025,29 @@ static int screen_columns(void) return win.ws_col; #endif - if (getenv("COLUMNS")) - return atoi(getenv("COLUMNS")); - return 80; -} - -static tcflag_t *mode_type_flag(enum mode_type type, struct termios *mode) -{ - switch (type) { - case control: - return &mode->c_cflag; - - case input: - return &mode->c_iflag; - - case output: - return &mode->c_oflag; - - case local: - return &mode->c_lflag; - - default: /* combination: */ - return NULL; + columns = 80; + if ((s = getenv("COLUMNS"))) { + columns = atoi(s); } + return columns; } -static void -display_settings(enum output_type output_type, struct termios *mode, - int fd, const char *device_name) +static tcflag_t *mode_type_flag(enum mode_type type, struct termios *mode) { - switch (output_type) { - case changed: - display_changed(mode); - break; - - case all: - display_all(mode, fd, device_name); - break; - - case recoverable: - display_recoverable(mode); - break; + static const unsigned char tcflag_offsets[] = { + offsetof(struct termios, c_cflag), /* control */ + offsetof(struct termios, c_iflag), /* input */ + offsetof(struct termios, c_oflag), /* output */ + offsetof(struct termios, c_lflag) /* local */ + }; + + if (((unsigned int) type) <= local) { + return (tcflag_t *)(((char *) mode) + tcflag_offsets[(int)type]); } + return NULL; } -static void display_changed(struct termios *mode) +static void display_changed(struct termios *mode, int fd, const char *device_name) { int i; int empty_line; @@ -1206,18 +1184,25 @@ display_all(struct termios *mode, int fd, const char *device_name) static void display_speed(struct termios *mode, int fancy) { - if (cfgetispeed(mode) == 0 || cfgetispeed(mode) == cfgetospeed(mode)) - wrapf(fancy ? "speed %lu baud;" : "%lu\n", - baud_to_value(cfgetospeed(mode))); - else - wrapf(fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n", - baud_to_value(cfgetispeed(mode)), - baud_to_value(cfgetospeed(mode))); + unsigned long ispeed, ospeed; + const char *fmt_str = + "%lu %lu\n\0" "ispeed %lu baud; ospeed %lu baud;\0" + "%lu\n\0" "\0\0\0\0" "speed %lu baud;"; + + ospeed = ispeed = cfgetispeed(mode); + if (ispeed == 0 || ispeed == (ospeed = cfgetospeed(mode))) { + ispeed = ospeed; /* in case ispeed was 0 */ + fmt_str += 43; + } + if (fancy) { + fmt_str += 9; + } + wrapf(fmt_str, bb_baud_to_value(ispeed), bb_baud_to_value(ospeed)); if (!fancy) current_col = 0; } -static void display_recoverable(struct termios *mode) +static void display_recoverable(struct termios *mode, int fd, const char *device_name) { int i; @@ -1259,62 +1244,9 @@ static int recover_mode(char *arg, struct termios *mode) return 1; } -struct speed_map { - speed_t speed; /* Internal form. */ - unsigned long value; /* Numeric 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}, - {B19200, 19200}, - {B38400, 38400}, -#ifdef B57600 - {B57600, 57600}, -#endif -#ifdef B115200 - {B115200, 115200}, -#endif -#ifdef B230400 - {B230400, 230400}, -#endif -#ifdef B460800 - {B460800, 460800}, -#endif -}; - -static const int NUM_SPEEDS = (sizeof(speeds) / sizeof(struct speed_map)); - static speed_t string_to_baud(const char *arg) { - int i; - - for (i = 0; i < NUM_SPEEDS; ++i) - if (parse_number(arg, 0) == speeds[i].value) - return speeds[i].speed; - return (speed_t) - 1; -} - -static unsigned long baud_to_value(speed_t speed) -{ - int i; - - for (i = 0; i < NUM_SPEEDS; ++i) - if (speed == speeds[i].speed) - return speeds[i].value; - return 0; + return bb_value_to_baud(bb_xparse_number(arg, 0)); } static void sane_mode(struct termios *mode) @@ -1333,10 +1265,12 @@ static void sane_mode(struct termios *mode) for (i = 0; i < NUM_mode_info; ++i) { if (mode_info[i].flags & SANE_SET) { bitsp = mode_type_flag(mode_info[i].type, mode); - *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits; + *bitsp = (*bitsp & ~((unsigned long)mode_info[i].mask)) + | mode_info[i].bits; } else if (mode_info[i].flags & SANE_UNSET) { bitsp = mode_type_flag(mode_info[i].type, mode); - *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits; + *bitsp = *bitsp & ~((unsigned long)mode_info[i].mask) + & ~mode_info[i].bits; } } } @@ -1349,47 +1283,32 @@ static const char *visible(unsigned int ch) static char buf[10]; char *bpout = buf; - if (ch == _POSIX_VDISABLE) + if (ch == _POSIX_VDISABLE) { return "<undef>"; + } - if (ch >= 32) { - if (ch < 127) - *bpout++ = ch; - else if (ch == 127) { - *bpout++ = '^'; - *bpout++ = '?'; - } else { - *bpout++ = 'M', *bpout++ = '-'; - if (ch >= 128 + 32) { - if (ch < 128 + 127) - *bpout++ = ch - 128; - else { - *bpout++ = '^'; - *bpout++ = '?'; - } - } else { - *bpout++ = '^'; - *bpout++ = ch - 128 + 64; - } - } - } else { + if (ch >= 128) { + ch -= 128; + *bpout++ = 'M'; + *bpout++ = '-'; + } + + if (ch < 32) { *bpout++ = '^'; *bpout++ = ch + 64; + } else if (ch < 127) { + *bpout++ = ch; + } else { + *bpout++ = '^'; + *bpout++ = '?'; } + *bpout = '\0'; return (const char *) buf; } #ifdef TEST -const char *applet_name = "stty"; +const char *bb_applet_name = "stty"; #endif - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/coreutils/sync.c b/coreutils/sync.c index d581680..8474631 100644 --- a/coreutils/sync.c +++ b/coreutils/sync.c @@ -20,15 +20,17 @@ * */ -#include <stdio.h> +/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */ + #include <stdlib.h> #include <unistd.h> #include "busybox.h" extern int sync_main(int argc, char **argv) { - if (argc > 1 && **(argv + 1) == '-') - show_usage(); + bb_warn_ignoring_args(argc - 1); + sync(); + return(EXIT_SUCCESS); } diff --git a/coreutils/tail.c b/coreutils/tail.c index 1703eef..8e0adf5 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c @@ -2,7 +2,6 @@ /* * Mini tail implementation for busybox * - * * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu> * * This program is free software; you can redistribute it and/or modify @@ -21,14 +20,30 @@ * */ +/* BB_AUDIT SUSv3 compliant (need fancy for -c) */ +/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/tail.html */ -#include <fcntl.h> -#include <getopt.h> +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Pretty much rewritten to fix numerous bugs and reduce realloc() calls. + * Bugs fixed (although I may have forgotten one or two... it was pretty bad) + * 1) mixing printf/write without fflush()ing stdout + * 2) no check that any open files are present + * 3) optstring had -q taking an arg + * 4) no error checking on write in some cases, and a warning even then + * 5) q and s interaction bug + * 6) no check for lseek error + * 7) lseek attempted when count==0 even if arg was +0 (from top) + */ + +#include <stdio.h> +#include <stdlib.h> #include <string.h> #include <ctype.h> -#include <stdlib.h> #include <unistd.h> -#include <sys/types.h> +#include <fcntl.h> +#include <sys/stat.h> #include "busybox.h" static const struct suffix_mult tail_suffixes[] = { @@ -38,234 +53,287 @@ static const struct suffix_mult tail_suffixes[] = { { NULL, 0 } }; -static const int BYTES = 0; -static const int LINES = 1; - -static char *tailbuf; -static int taillen; -static int newline; +static int status +#if EXIT_SUCCESS != 0 + = EXIT_SUCCESS /* If it is 0 (paranoid check), let bss initialize it. */ +#endif + ; -static void tailbuf_append(char *buf, int len) +static void tail_xprint_header(const char *fmt, const char *filename) { - tailbuf = xrealloc(tailbuf, taillen + len); - memcpy(tailbuf + taillen, buf, len); - taillen += len; + /* If we get an output error, there is really no sense in continuing. */ + if (dprintf(STDOUT_FILENO, fmt, filename) < 0) { + bb_perror_nomsg_and_die(); + } } -static void tailbuf_trunc(void) +/* len should probably be size_t */ +static void tail_xbb_full_write(const char *buf, size_t len) { - char *s; - s = memchr(tailbuf, '\n', taillen); - memmove(tailbuf, s + 1, taillen - ((s + 1) - tailbuf)); - taillen -= (s + 1) - tailbuf; - newline = 0; + /* If we get a write error, there is really no sense in continuing. */ + if (bb_full_write(STDOUT_FILENO, buf, len) < 0) { + bb_perror_nomsg_and_die(); + } } -int tail_main(int argc, char **argv) +static ssize_t tail_read(int fd, char *buf, size_t count) { - int from_top = 0, units = LINES, count = 10, sleep_period = 1; - int show_headers = 0, hide_headers = 0, follow = 0; - int *fds, nfiles = 0, status = EXIT_SUCCESS, nread, nwrite, seen = 0; - char *s, *start, *end, buf[BUFSIZ]; - int i, opt; - - if (argc >= 2) { - int line_num; - switch (argv[1][0]) { - case '+': - from_top = 1; - /* FALLS THROUGH */ - case '-': - line_num = atoi(&argv[1][1]); - if (line_num != 0) { - optind = 2; - count = line_num; - } - break; - } + ssize_t r; + + if ((r = safe_read(fd, buf, count)) < 0) { + bb_perror_msg("read"); + status = EXIT_FAILURE; } + return r; +} + +static const char tail_opts[] = + "fn:" +#ifdef CONFIG_FEATURE_FANCY_TAIL + "c:qs:v" +#endif + ; + +static const char header_fmt[] = "\n==> %s <==\n"; + +int tail_main(int argc, char **argv) +{ + long count = 10; + unsigned int sleep_period = 1; + int from_top = 0; + int follow = 0; + int header_threshhold = 1; #ifdef CONFIG_FEATURE_FANCY_TAIL - while ((opt = getopt(argc, argv, "c:fn:q:s:v")) > 0) { -#else - while ((opt = getopt(argc, argv, "fn:")) > 0) { + int count_bytes = 0; #endif + + char *tailbuf; + size_t tailbufsize; + int taillen = 0; + int newline = 0; + + int *fds, nfiles, nread, nwrite, seen, i, opt; + char *s, *buf; + const char *fmt; + + /* Allow legacy syntax of an initial numeric option without -n. */ + if ((argv[1][0] == '+') + || ((argv[1][0] == '-') + /* && (isdigit)(argv[1][1]) */ + && (((unsigned int)(argv[1][1] - '0')) <= 9)) + ) { + optind = 2; + optarg = argv[1]; + goto GET_COUNT; + } + + while ((opt = getopt(argc, argv, tail_opts)) > 0) { switch (opt) { case 'f': follow = 1; break; #ifdef CONFIG_FEATURE_FANCY_TAIL case 'c': - units = BYTES; + count_bytes = 1; /* FALLS THROUGH */ #endif case 'n': - count = parse_number(optarg, tail_suffixes); - if (count < 0) - count = -count; - if (optarg[0] == '+') + GET_COUNT: + count = bb_xgetlarg10_sfx(optarg, tail_suffixes); + /* Note: Leading whitespace is an error trapped above. */ + if (*optarg == '+') { from_top = 1; + } else { + from_top = 0; + } + if (count < 0) { + count = -count; + } break; #ifdef CONFIG_FEATURE_FANCY_TAIL case 'q': - hide_headers = 1; + header_threshhold = INT_MAX; break; case 's': - sleep_period = parse_number(optarg, 0); + sleep_period =bb_xgetularg10_bnd(optarg, 0, UINT_MAX); break; case 'v': - show_headers = 1; + header_threshhold = 0; break; #endif default: - show_usage(); + bb_show_usage(); } } /* open all the files */ fds = (int *)xmalloc(sizeof(int) * (argc - optind + 1)); - if (argc == optind) { - fds[nfiles++] = STDIN_FILENO; - argv[optind] = "standard input"; - } else { - for (i = optind; i < argc; i++) { - if (strcmp(argv[i], "-") == 0) { - fds[nfiles++] = STDIN_FILENO; - argv[i] = "standard input"; - } else if ((fds[nfiles++] = open(argv[i], O_RDONLY)) < 0) { - perror_msg("%s", argv[i]); - status = EXIT_FAILURE; - } + + argv += optind; + nfiles = i = 0; + + if ((argc -= optind) == 0) { + struct stat statbuf; + + if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) { + follow = 0; } + /* --argv; */ + *argv = (char *) bb_msg_standard_input; + goto DO_STDIN; + } + + do { + if ((argv[i][0] == '-') && !argv[i][1]) { + DO_STDIN: + fds[nfiles] = STDIN_FILENO; + } else if ((fds[nfiles] = open(argv[i], O_RDONLY)) < 0) { + bb_perror_msg("%s", argv[i]); + status = EXIT_FAILURE; + continue; + } + argv[nfiles] = argv[i]; + ++nfiles; + } while (++i < argc); + + if (!nfiles) { + bb_error_msg_and_die("no files"); } - + + tailbufsize = BUFSIZ; #ifdef CONFIG_FEATURE_FANCY_TAIL /* tail the files */ - if (!from_top && units == BYTES) - tailbuf = xmalloc(count); + if (from_top < count_bytes) { /* Each is 0 or 1, so true iff 0 < 1. */ + /* Hence, !from_top && count_bytes */ + if (tailbufsize < count) { + tailbufsize = count + BUFSIZ; + } + } #endif + buf = tailbuf = xmalloc(tailbufsize); - for (i = 0; i < nfiles; i++) { - if (fds[i] == -1) - continue; - if (!count) { - lseek(fds[i], 0, SEEK_END); + fmt = header_fmt + 1; /* Skip header leading newline on first output. */ + i = 0; + do { + /* Be careful. It would be possible to optimize the count-bytes + * case if the file is seekable. If you do though, remember that + * starting file position may not be the beginning of the file. + * Beware of backing up too far. See example in wc.c. + */ + if ((!(count|from_top)) && (lseek(fds[i], 0, SEEK_END) >= 0)) { continue; } - seen = 0; - if (show_headers || (!hide_headers && nfiles > 1)) - printf("%s==> %s <==\n", i == 0 ? "" : "\n", argv[optind + i]); - while ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0) { + + if (nfiles > header_threshhold) { + tail_xprint_header(fmt, argv[i]); + fmt = header_fmt; + } + + buf = tailbuf; + taillen = 0; + seen = 1; + + while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) { if (from_top) { + nwrite = nread; + if (seen < count) { #ifdef CONFIG_FEATURE_FANCY_TAIL - if (units == BYTES) { - if (count - 1 <= seen) - nwrite = nread; - else if (count - 1 <= seen + nread) - nwrite = nread + seen - (count - 1); - else - nwrite = 0; - seen += nread; - } else { -#else - { + if (count_bytes) { + nwrite -= (count - seen); + seen = count; + } else #endif - if (count - 1 <= seen) - nwrite = nread; - else { - nwrite = 0; - for (s = memchr(buf, '\n', nread); s != NULL; - s = memchr(s+1, '\n', nread - (s + 1 - buf))) { - if (count - 1 <= ++seen) { - nwrite = nread - (s + 1 - buf); + { + s = buf; + do { + --nwrite; + if ((*s++ == '\n') && (++seen == count)) { break; } - } + } while (nwrite); } } - if (full_write(STDOUT_FILENO, buf + nread - nwrite, - nwrite) < 0) { - perror_msg("write"); - status = EXIT_FAILURE; - break; - } - } else { + tail_xbb_full_write(buf + nread - nwrite, nwrite); + } else if (count) { #ifdef CONFIG_FEATURE_FANCY_TAIL - if (units == BYTES) { - if (nread < count) { - memmove(tailbuf, tailbuf + nread, count - nread); - memcpy(tailbuf + count - nread, buf, nread); - } else { - memcpy(tailbuf, buf + nread - count, count); + if (count_bytes) { + taillen += nread; + if (taillen > count) { + memmove(tailbuf, tailbuf + taillen - count, count); + taillen = count; } - seen += nread; - } else { -#else - { + } else #endif - for (start = buf, end = memchr(buf, '\n', nread); - end != NULL; start = end+1, - end = memchr(start, '\n', nread - (start - buf))) { - if (newline && count <= seen) - tailbuf_trunc(); - tailbuf_append(start, end - start + 1); - seen++; - newline = 1; + { + int k = nread; + int nbuf = 0; + + while (k) { + --k; + if (buf[k] == '\n') { + ++nbuf; + } } - if (newline && count <= seen && nread - (start - buf) > 0) - tailbuf_trunc(); - tailbuf_append(start, nread - (start - buf)); - } - } - } - if (nread < 0) { - perror_msg("read"); - status = EXIT_FAILURE; - } + if (newline + nbuf < count) { + newline += nbuf; + taillen += nread; -#ifdef CONFIG_FEATURE_FANCY_TAIL - if (!from_top && units == BYTES) { - if (count < seen) - seen = count; - if (full_write(STDOUT_FILENO, tailbuf + count - seen, seen) < 0) { - perror_msg("write"); - status = EXIT_FAILURE; + } else { + int extra = 0; + if (buf[nread-1] != '\n') { + extra = 1; + } + + k = newline + nbuf + extra - count; + s = tailbuf; + while (k) { + if (*s == '\n') { + --k; + } + ++s; + } + + taillen += nread - (s - tailbuf); + memmove(tailbuf, s, taillen); + newline = count - extra; + } + if (tailbufsize < taillen + BUFSIZ) { + tailbufsize = taillen + BUFSIZ; + tailbuf = xrealloc(tailbuf, tailbufsize); + } + } + buf = tailbuf + taillen; } } -#endif - if (!from_top && units == LINES) { - if (full_write(STDOUT_FILENO, tailbuf, taillen) < 0) { - perror_msg("write"); - status = EXIT_FAILURE; - } + if (!from_top) { + tail_xbb_full_write(tailbuf, taillen); } taillen = 0; - } - - while (follow) { - sleep(sleep_period); + } while (++i < nfiles); - for (i = 0; i < nfiles; i++) { - if (fds[i] == -1) - continue; + buf = xrealloc(tailbuf, BUFSIZ); - if ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0) { - if (show_headers || (!hide_headers && nfiles > 1)) - printf("\n==> %s <==\n", argv[optind + i]); + fmt = NULL; - do { - full_write(STDOUT_FILENO, buf, nread); - } while ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0); + while (follow) { + sleep(sleep_period); + i = 0; + do { + if (nfiles > header_threshhold) { + fmt = header_fmt; } - - if (nread < 0) { - perror_msg("read"); - status = EXIT_FAILURE; + while ((nread = tail_read(fds[i], buf, sizeof(buf))) > 0) { + if (fmt) { + tail_xprint_header(fmt, argv[i]); + fmt = NULL; + } + tail_xbb_full_write(buf, nread); } - } + } while (++i < nfiles); } return status; diff --git a/coreutils/tee.c b/coreutils/tee.c index 1c14542..7e86f2e 100644 --- a/coreutils/tee.c +++ b/coreutils/tee.c @@ -1,8 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini tee implementation for busybox + * tee implementation for busybox * - * Copyright (C) 2000,2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu> + * 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 @@ -20,47 +20,96 @@ * */ -#include "busybox.h" -#include <getopt.h> +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */ + #include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <unistd.h> +#include "busybox.h" -int -tee_main(int argc, char **argv) +int tee_main(int argc, char **argv) { - char *mode = "w"; - int c, i, status = 0, nfiles = 0; + const char *mode = "w\0a"; FILE **files; + FILE **p; + char **filenames; + int flags; + int retval = EXIT_SUCCESS; +#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO + size_t c; + RESERVE_CONFIG_BUFFER(buf, BUFSIZ); +#else + int c; +#endif + + flags = bb_getopt_ulflags(argc, argv, "ia"); /* 'a' must be 2nd */ + + mode += (flags & 2); /* Since 'a' is the 2nd option... */ + + if (flags & 1) { + signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction.*/ + } + + /* gnu tee ignores SIGPIPE in case one of the output files is a pipe + * that doesn't consume all its input. Good idea... */ + signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction.*/ - while ((c = getopt(argc, argv, "a")) != EOF) { - switch (c) { - case 'a': - mode = "a"; - break; - default: - show_usage(); + /* Allocate an array of FILE *'s, with one extra for a sentinal. */ + p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2)); + *p = stdout; + argv += optind - 1; + filenames = argv - 1; + *filenames = (char *) bb_msg_standard_input; /* for later */ + goto GOT_NEW_FILE; + + do { + if ((*p = bb_wfopen(*argv, mode)) == NULL) { + retval = EXIT_FAILURE; + continue; + } + filenames[(int)(p - files)] = *argv; + GOT_NEW_FILE: + setbuf(*p, NULL); /* tee must not buffer output. */ + ++p; + } while (*++argv); + + *p = NULL; /* Store the sentinal value. */ + +#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO + while ((c = fread(buf, 1, BUFSIZ, stdin)) != 0) { + for (p=files ; *p ; p++) { + fwrite(buf, 1, c, *p); } } - files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 1)); - files[nfiles++] = stdout; - while (optind < argc) { - if ((files[nfiles++] = wfopen(argv[optind++], mode)) == NULL) { - nfiles--; - status = 1; +#ifdef CONFIG_FEATURE_CLEAN_UP + RELEASE_CONFIG_BUFFER(buf); +#endif + +#else + while ((c = getchar()) != EOF) { + for (p=files ; *p ; p++) { + putc(c, *p); } } +#endif - while ((c = getchar()) != EOF) - for (i = 0; i < nfiles; i++) - putc(c, files[i]); + /* Now we need to check for i/o errors on stdin and the various + * output files. Since we know that the first entry in the output + * file table is stdout, we can save one "if ferror" test by + * setting the first entry to stdin and checking stdout error + * status with bb_fflush_stdout_and_exit()... although fflush()ing + * is unnecessary here. */ - return status; -} + p = files; + *p = stdin; + do { /* Now check for (input and) output errors. */ + /* Checking ferror should be sufficient, but we may want to fclose. + * If we do, remember not to close stdin! */ + bb_xferror(*p, filenames[(int)(p - files)]); + } while (*++p); -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ + bb_fflush_stdout_and_exit(retval); +} diff --git a/coreutils/test.c b/coreutils/test.c index 83e31ea..0bce66e 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -180,9 +180,9 @@ extern int test_main(int argc, char **argv) { int res; - if (strcmp(applet_name, "[") == 0) { + if (strcmp(bb_applet_name, "[") == 0) { if (strcmp(argv[--argc], "]")) - error_msg_and_die("missing ]"); + bb_error_msg_and_die("missing ]"); argv[argc] = NULL; } /* Implement special cases from POSIX.2, section 4.62.4 */ @@ -226,9 +226,9 @@ extern int test_main(int argc, char **argv) static void syntax(const char *op, const char *msg) { if (op && *op) { - error_msg_and_die("%s: %s", op, msg); + bb_error_msg_and_die("%s: %s", op, msg); } else { - error_msg_and_die("%s", msg); + bb_error_msg_and_die("%s", msg); } } @@ -450,13 +450,13 @@ static int getn(const char *s) r = strtol(s, &p, 10); if (errno != 0) - error_msg_and_die("%s: out of range", s); + bb_error_msg_and_die("%s: out of range", s); while (isspace(*p)) p++; if (*p) - error_msg_and_die("%s: bad number", s); + bb_error_msg_and_die("%s: bad number", s); return (int) r; } diff --git a/coreutils/touch.c b/coreutils/touch.c index f1c6dc4..c66f26e 100644 --- a/coreutils/touch.c +++ b/coreutils/touch.c @@ -21,6 +21,16 @@ * */ +/* BB_AUDIT SUSv3 _NOT_ compliant -- options -a, -m, -r, -t not supported. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/touch.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Previous version called open() and then utime(). While this will be + * be necessary to implement -r and -t, it currently only makes things bigger. + * Also, exiting on a failure was a bug. All args should be processed. + */ + #include <stdio.h> #include <sys/types.h> #include <fcntl.h> @@ -33,44 +43,35 @@ extern int touch_main(int argc, char **argv) { int fd; - int create = TRUE; + int flags; + int status = EXIT_SUCCESS; - /* Parse options */ - while (--argc > 0 && **(++argv) == '-') { - while (*(++(*argv))) { - switch (**argv) { - case 'c': - create = FALSE; - break; - default: - show_usage(); - } - } - } + flags = bb_getopt_ulflags(argc, argv, "c"); + + argv += optind; - if (argc < 1) { - show_usage(); + if (!*argv) { + bb_show_usage(); } - while (argc > 0) { - fd = open(*argv, create ? O_RDWR | O_CREAT : O_RDWR, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - if (fd < 0) { - if (! create && errno == ENOENT) { - argc--; - argv++; - continue; - } else { - perror_msg_and_die("%s", *argv); - } - } - close(fd); + do { if (utime(*argv, NULL)) { - perror_msg_and_die("%s", *argv); + if (errno == ENOENT) { /* no such file*/ + if (flags & 1) { /* Creation is disabled, so ignore. */ + continue; + } + /* Try to create the file. */ + fd = open(*argv, O_RDWR | O_CREAT, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH + ); + if ((fd >= 0) && !close(fd)) { + continue; + } + } + status = EXIT_FAILURE; + bb_perror_msg("%s", *argv); } - argc--; - argv++; - } + } while (*++argv); - return EXIT_SUCCESS; + return status; } diff --git a/coreutils/tr.c b/coreutils/tr.c index e2a4ef6..a00e361 100644 --- a/coreutils/tr.c +++ b/coreutils/tr.c @@ -54,7 +54,7 @@ static void convert(void) if (in_index == read_chars) { if ((read_chars = read(0, (char *) pinput, BUFSIZ)) <= 0) { if (write(1, (char *) poutput, out_index) != out_index) - error_msg("%s", write_error); + bb_error_msg(bb_msg_write_error); exit(0); } in_index = 0; @@ -68,7 +68,7 @@ static void convert(void) poutput[out_index++] = last = coded; if (out_index == BUFSIZ) { if (write(1, (char *) poutput, out_index) != out_index) - error_msg_and_die("%s", write_error); + bb_error_msg_and_die(bb_msg_write_error); out_index = 0; } } @@ -102,7 +102,7 @@ static unsigned int expand(const char *arg, register unsigned char *buffer) while (*arg) { if (*arg == '\\') { arg++; - *buffer++ = process_escape_sequence(&arg); + *buffer++ = bb_process_escape_sequence(&arg); } else if (*(arg+1) == '-') { ac = *(arg+2); if(ac == 0) { @@ -181,7 +181,7 @@ extern int tr_main(int argc, char **argv) sq_fl = TRUE; break; default: - show_usage(); + bb_show_usage(); } } idx++; @@ -197,7 +197,7 @@ extern int tr_main(int argc, char **argv) input_length = complement(input, input_length); if (argv[idx] != NULL) { if (*argv[idx] == '\0') - error_msg_and_die("STRING2 cannot be empty"); + bb_error_msg_and_die("STRING2 cannot be empty"); output_length = expand(argv[idx], output); map(input, input_length, output, output_length); } diff --git a/coreutils/true.c b/coreutils/true.c index 9644aad..0fbe102 100644 --- a/coreutils/true.c +++ b/coreutils/true.c @@ -21,7 +21,8 @@ * */ -/* getopt not needed */ +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/true.html */ #include <stdlib.h> #include "busybox.h" diff --git a/coreutils/tty.c b/coreutils/tty.c index 4510c29..cd2c784 100644 --- a/coreutils/tty.c +++ b/coreutils/tty.c @@ -1,8 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini tty implementation for busybox + * tty implementation for busybox * - * Copyright (C) 2000 Edward Betts <edward@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 @@ -20,25 +20,39 @@ * */ +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/tty.html */ + #include <stdio.h> #include <stdlib.h> #include <unistd.h> -#include <sys/types.h> #include "busybox.h" extern int tty_main(int argc, char **argv) { - char *tty; - - if (argc > 1) { - if (argv[1][0] != '-' || argv[1][1] != 's') - show_usage(); - } else { - tty = ttyname(0); - if (tty) - puts(tty); - else - puts("not a tty"); + const char *s; + int silent; /* Note: No longer relevant in SUSv3. */ + int retval; + + bb_default_error_retval = 2; /* SUSv3 requires > 1 for error. */ + + silent = bb_getopt_ulflags(argc, argv, "s"); + + /* gnu tty outputs a warning that it is ignoring all args. */ + bb_warn_ignoring_args(argc - optind); + + retval = 0; + + if ((s = ttyname(0)) == NULL) { + /* According to SUSv3, ttyname can on fail with EBADF or ENOTTY. + * We know the file descriptor is good, so failure means not a tty. */ + s = "not a tty"; + retval = 1; + } + + if (!silent) { + puts(s); } - return(isatty(0) ? EXIT_SUCCESS : EXIT_FAILURE); + + bb_fflush_stdout_and_exit(retval); } diff --git a/coreutils/uname.c b/coreutils/uname.c index df4f14e..a3e52e3 100644 --- a/coreutils/uname.c +++ b/coreutils/uname.c @@ -16,6 +16,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/uname.html */ + /* Option Example -s, --sysname SunOS @@ -33,13 +36,18 @@ /* Further size reductions by Glenn McGrath and Manuel Novoa III. */ +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Now does proper error checking on i/o. Plus some further space savings. + */ + #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <string.h> +#include <unistd.h> #include <sys/types.h> #include <sys/utsname.h> -#include <getopt.h> #include "busybox.h" typedef struct { @@ -48,7 +56,6 @@ typedef struct { } uname_info_t; static const char options[] = "snrvmpa"; -static const char flags[] = "\x01\x02\x04\x08\x10\x20\x3f"; static const unsigned short int utsname_offset[] = { offsetof(uname_info_t,name.sysname), offsetof(uname_info_t,name.nodename), @@ -61,29 +68,28 @@ static const unsigned short int utsname_offset[] = { int uname_main(int argc, char **argv) { uname_info_t uname_info; - #if defined(__sparc__) && defined(__linux__) char *fake_sparc = getenv("FAKE_SPARC"); #endif - const unsigned short int *delta; - int opt; - char toprint = 0; + char toprint; - while ((opt = getopt(argc, argv, options)) != -1) { - const char *p = strchr(options,opt); - if (p == NULL) { - show_usage(); - } - toprint |= flags[(int)(p-options)]; + toprint = bb_getopt_ulflags(argc, argv, options); + + if (argc != optind) { + bb_show_usage(); + } + + if (toprint & (1 << 6)) { + toprint = 0x3f; } if (toprint == 0) { - toprint = flags[0]; /* sysname */ + toprint = 1; /* sysname */ } if (uname(&uname_info.name) == -1) { - error_msg_and_die("cannot get system name"); + bb_error_msg_and_die("cannot get system name"); } #if defined(__sparc__) && defined(__linux__) @@ -99,7 +105,7 @@ int uname_main(int argc, char **argv) delta=utsname_offset; do { if (toprint & 1) { - printf(((char *)(&uname_info)) + *delta); + bb_printf(((char *)(&uname_info)) + *delta); if (toprint > 1) { putchar(' '); } @@ -108,5 +114,5 @@ int uname_main(int argc, char **argv) } while (toprint >>= 1); putchar('\n'); - return EXIT_SUCCESS; + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } diff --git a/coreutils/uniq.c b/coreutils/uniq.c index cb63c42..90686c9 100644 --- a/coreutils/uniq.c +++ b/coreutils/uniq.c @@ -1,10 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini uniq implementation for busybox + * uniq implementation for busybox * - * Copyright (C) 1999 by Lineo, inc. and John Beppu - * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org> - * Rewritten by Matt Kraai <kraai@alumni.carnegiemellon.edu> + * 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 @@ -22,67 +20,93 @@ * */ +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/uniq.html */ + #include <stdio.h> -#include <string.h> -#include <getopt.h> -#include <errno.h> #include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> #include "busybox.h" +#include "libcoreutils/coreutils.h" -static int print_count; -static int print_uniq = 1; -static int print_duplicates = 1; - -static void print_line(char *line, int count, FILE *fp) -{ - if ((print_duplicates && count > 1) || (print_uniq && count == 1)) { - if (print_count) - fprintf(fp, "%7d\t%s", count, line); - else - fputs(line, fp); - } -} +static const char uniq_opts[] = "f:s:cdu\0\7\3\5\1\2\4"; int uniq_main(int argc, char **argv) { - FILE *in = stdin, *out = stdout; - char *lastline = NULL, *input; - int opt, count = 0; + FILE *in, *out; + /* Note: Ignore the warning about dups and e0 possibly being uninitialized. + * They will be initialized on the fist pass of the loop (since s0 is NULL). */ + unsigned long dups, skip_fields, skip_chars, i; + const char *s0, *e0, *s1, *e1, *input_filename; + int opt; + int uniq_flags = 6; /* -u */ - /* parse argv[] */ - while ((opt = getopt(argc, argv, "cdu")) > 0) { - switch (opt) { - case 'c': - print_count = 1; - break; - case 'd': - print_duplicates = 1; - print_uniq = 0; - break; - case 'u': - print_duplicates = 0; - print_uniq = 1; - break; + skip_fields = skip_chars = 0; + + while ((opt = getopt(argc, argv, uniq_opts)) > 0) { + if (opt == 'f') { + skip_fields = bb_xgetularg10(optarg); + } else if (opt == 's') { + skip_chars = bb_xgetularg10(optarg); + } else if ((s0 = strchr(uniq_opts, opt)) != NULL) { + uniq_flags &= s0[4]; + uniq_flags |= s0[7]; + } else { + bb_show_usage(); } } - if (argv[optind] != NULL) { - in = xfopen(argv[optind], "r"); - if (argv[optind+1] != NULL) - out = xfopen(argv[optind+1], "w"); + input_filename = *(argv += optind); + + in = xgetoptfile_sort_uniq(argv, "r"); + if (*argv) { + ++argv; } + out = xgetoptfile_sort_uniq(argv, "w"); + if (*argv && argv[1]) { + bb_show_usage(); + } + + s0 = NULL; - while ((input = get_line_from_file(in)) != NULL) { - if (lastline == NULL || strcmp(input, lastline) != 0) { - print_line(lastline, count, out); - free(lastline); - lastline = input; - count = 0; + /* gnu uniq ignores newlines */ + while ((s1 = bb_get_chomped_line_from_file(in)) != NULL) { + e1 = s1; + for (i=skip_fields ; i ; i--) { + e1 = bb_skip_whitespace(e1); + while (*e1 && !isspace(*e1)) { + ++e1; + } + } + for (i = skip_chars ; *e1 && i ; i--) { + ++e1; + } + if (s0) { + if (strcmp(e0, e1) == 0) { + ++dups; /* Note: Testing for overflow seems excessive. */ + continue; + } + DO_LAST: + if ((dups && (uniq_flags & 2)) || (!dups && (uniq_flags & 4))) { + bb_fprintf(out, "\0%7d\t" + (uniq_flags & 1), dups + 1); + bb_fprintf(out, "%s\n", s0); + } + free((void *)s0); } - count++; + + s0 = s1; + e0 = e1; + dups = 0; + } + + if (s0) { + e1 = NULL; + goto DO_LAST; } - print_line(lastline, count, out); - free(lastline); - return EXIT_SUCCESS; + bb_xferror(in, input_filename); + + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } diff --git a/coreutils/usleep.c b/coreutils/usleep.c index ac268b4..f570f27 100644 --- a/coreutils/usleep.c +++ b/coreutils/usleep.c @@ -1,8 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini usleep implementation for busybox + * usleep implementation for busybox * - * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. + * 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 @@ -20,18 +20,22 @@ * */ -/* getopt not needed */ +/* BB_AUDIT SUSv3 N/A -- Apparently a busybox extension. */ #include <stdlib.h> +#include <limits.h> #include <unistd.h> #include "busybox.h" extern int usleep_main(int argc, char **argv) { - if ((argc < 2) || (**(argv + 1) == '-')) { - show_usage(); + if (argc != 2) { + bb_show_usage(); + } + + if (usleep(bb_xgetularg10_bnd(argv[1], 0, UINT_MAX))) { + bb_perror_nomsg_and_die(); } - usleep(atoi(*(++argv))); /* return void */ return EXIT_SUCCESS; } diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index a5ac002..4f9270c 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -46,7 +46,7 @@ static int read_stduu (const char *inname) char *p; if (fgets (buf, sizeof(buf), stdin) == NULL) { - error_msg("%s: Short file", inname); + bb_error_msg("%s: Short file", inname); return FALSE; } p = buf; @@ -81,7 +81,7 @@ static int read_stduu (const char *inname) if (fgets (buf, sizeof(buf), stdin) == NULL || strcmp (buf, "end\n")) { - error_msg("%s: No `end' line", inname); + bb_error_msg("%s: No `end' line", inname); return FALSE; } @@ -131,7 +131,7 @@ static int read_base64 (const char *inname) unsigned char *p; if (fgets (buf, sizeof(buf), stdin) == NULL) { - error_msg("%s: Short file", inname); + bb_error_msg("%s: Short file", inname); return FALSE; } p = buf; @@ -139,7 +139,7 @@ static int read_base64 (const char *inname) if (memcmp (buf, "====", 4) == 0) break; if (last_data != 0) { - error_msg("%s: data following `=' padding character", inname); + bb_error_msg("%s: data following `=' padding character", inname); return FALSE; } @@ -161,14 +161,14 @@ static int read_base64 (const char *inname) while ((b64_tab[*p] & '\100') != 0) if (*p == '\n' || *p++ == '=') { - error_msg("%s: illegal line", inname); + bb_error_msg("%s: illegal line", inname); return FALSE; } c2 = b64_tab[*p++]; while (b64_tab[*p] == '\177') if (*p++ == '\n') { - error_msg("%s: illegal line", inname); + bb_error_msg("%s: illegal line", inname); return FALSE; } if (*p == '=') { @@ -180,7 +180,7 @@ static int read_base64 (const char *inname) while (b64_tab[*p] == '\177') if (*p++ == '\n') { - error_msg("%s: illegal line", inname); + bb_error_msg("%s: illegal line", inname); return FALSE; } putchar (c1 << 2 | c2 >> 4); @@ -213,7 +213,7 @@ static int decode (const char *inname, while (1) { if (fgets (buf, sizeof (buf), stdin) == NULL) { - error_msg("%s: No `begin' line", inname); + bb_error_msg("%s: No `begin' line", inname); return FALSE; } @@ -239,13 +239,13 @@ static int decode (const char *inname, while (*p != '/') ++p; if (*p == '\0') { - error_msg("%s: Illegal ~user", inname); + bb_error_msg("%s: Illegal ~user", inname); return FALSE; } *p++ = '\0'; pw = getpwnam (buf + 1); if (pw == NULL) { - error_msg("%s: No user `%s'", inname, buf + 1); + bb_error_msg("%s: No user `%s'", inname, buf + 1); return FALSE; } outname = concat_path_file(pw->pw_dir, p); @@ -258,7 +258,7 @@ static int decode (const char *inname, && (freopen (outname, "w", stdout) == NULL || chmod (outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)) )) { - perror_msg("%s", outname); /* */ + bb_perror_msg("%s", outname); /* */ if (dofre) free(outname); return FALSE; @@ -295,7 +295,7 @@ int uudecode_main (int argc, break; default: - show_usage(); + bb_show_usage(); } } @@ -308,7 +308,7 @@ int uudecode_main (int argc, if (decode (argv[optind], outname) != 0) exit_status = FALSE; } else { - perror_msg("%s", argv[optind]); + bb_perror_msg("%s", argv[optind]); exit_status = EXIT_FAILURE; } optind++; diff --git a/coreutils/uuencode.c b/coreutils/uuencode.c index 49b2d91..fd3326d 100644 --- a/coreutils/uuencode.c +++ b/coreutils/uuencode.c @@ -29,7 +29,7 @@ #include "busybox.h" /* Conversion table. for base 64 */ -static char tbl_base64[65] = { +static const char tbl_base64[65] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', @@ -41,7 +41,7 @@ static char tbl_base64[65] = { '=' /* termination character */ }; -static char tbl_std[65] = { +static const char tbl_std[65] = { '`', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', @@ -92,40 +92,36 @@ int uuencode_main(int argc, char **argv) int write_size = dst_buf_size; struct stat stat_buf; FILE *src_stream = stdin; - char *tbl = tbl_std; + const char *tbl; size_t size; mode_t mode; - int opt; RESERVE_CONFIG_BUFFER(src_buf, SRC_BUF_SIZE + 1); RESERVE_CONFIG_BUFFER(dst_buf, DST_BUF_SIZE + 1); - while ((opt = getopt(argc, argv, "m")) != -1) { - switch (opt) { - case 'm': - tbl = tbl_base64; - break; - default: - show_usage(); - } + tbl = tbl_std; + if (bb_getopt_ulflags(argc, argv, "m") & 1) { + tbl = tbl_base64; } switch (argc - optind) { case 2: - src_stream = xfopen(argv[optind], "r"); - stat(argv[optind], &stat_buf); + src_stream = bb_xfopen(argv[optind], "r"); + if (stat(argv[optind], &stat_buf) < 0) { + bb_perror_msg_and_die("stat"); + } mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); if (src_stream == stdout) { - printf("NULL\n"); + puts("NULL"); } break; case 1: mode = 0666 & ~umask(0666); break; default: - show_usage(); + bb_show_usage(); } - printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]); + bb_printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]); while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) { if (size != src_buf_size) { @@ -142,10 +138,12 @@ int uuencode_main(int argc, char **argv) putchar(tbl[size]); } if (fwrite(dst_buf, 1, write_size, stdout) != write_size) { - perror("Couldnt finish writing"); + bb_perror_msg_and_die(bb_msg_write_error); } } - printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n"); + bb_printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n"); + + bb_xferror(src_stream, "source"); /* TODO - Fix this! */ - return(EXIT_SUCCESS); + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } diff --git a/coreutils/watch.c b/coreutils/watch.c index c275f3b..f9f4018 100644 --- a/coreutils/watch.c +++ b/coreutils/watch.c @@ -20,67 +20,76 @@ * */ -/* getopt not needed */ +/* BB_AUDIT SUSv3 N/A */ +/* BB_AUDIT GNU defects -- only option -n is supported. */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Removed dependency on date_main(), added proper error checking, and + * reduced size. + */ #include <stdio.h> -#include <errno.h> -#include <unistd.h> #include <stdlib.h> #include <string.h> +#include <limits.h> +#include <time.h> +#include <assert.h> +#include <unistd.h> #include <sys/wait.h> #include "busybox.h" extern int watch_main(int argc, char **argv) { - const char date_argv[2][10] = { "date", "" }; const int header_len = 40; - char header[header_len + 1]; - int period = 2; - char **cargv; - int cargc; + time_t t; pid_t pid; + unsigned period = 2; int old_stdout; - int i; + int len, len2; + char **watched_argv; + char header[header_len + 1]; if (argc < 2) { - show_usage(); - } else { - cargv = argv + 1; - cargc = argc - 1; - - /* don't use getopt, because it permutes the arguments */ - if (argc >= 3 && !strcmp(argv[1], "-n")) { - period = strtol(argv[2], NULL, 10); - if (period < 1) - show_usage(); - cargv += 2; - cargc -= 2; - } + bb_show_usage(); } - - /* create header */ - snprintf(header, header_len, "Every %ds: ", period); - for (i = 0; i < cargc && (strlen(header) + strlen(cargv[i]) < header_len); - i++) { - strcat(header, cargv[i]); - strcat(header, " "); + /* don't use getopt, because it permutes the arguments */ + ++argv; + if ((argc > 3) && !strcmp(*argv, "-n") + ) { + period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX); + argv += 2; } + watched_argv = argv; - /* fill with blanks */ - for (i = strlen(header); i < header_len; i++) - header[i] = ' '; + /* create header */ - header[header_len - 1] = '\0'; + len = snprintf(header, header_len, "Every %ds:", period); + /* Don't bother checking for len < 0, as it should never happen. + * But, just to be prepared... */ + assert(len >= 0); + do { + len2 = strlen(*argv); + if (len + len2 >= header_len-1) { + break; + } + header[len] = ' '; + memcpy(header+len+1, *argv, len2); + len += len2+1; + } while (*++argv); + header[len] = 0; /* thanks to lye, who showed me how to redirect stdin/stdout */ old_stdout = dup(1); while (1) { - printf("\033[H\033[J%s", header); - date_main(1, (char **) date_argv); - printf("\n"); + time(&t); + /* Use dprintf to avoid fflush()ing stdout. */ + if (dprintf(1, "\033[H\033[J%-*s%s\n", header_len, header, ctime(&t)) < 0) { + bb_perror_msg_and_die("printf"); + } pid = vfork(); /* vfork, because of ucLinux */ if (pid > 0) { @@ -91,13 +100,11 @@ extern int watch_main(int argc, char **argv) //child close(1); dup(old_stdout); - if (execvp(*cargv, cargv)) - error_msg_and_die("Couldn't run command\n"); + if (execvp(*watched_argv, watched_argv)) { + bb_error_msg_and_die("Couldn't run command\n"); + } } else { - error_msg_and_die("Couldn't vfork\n"); + bb_error_msg_and_die("Couldn't vfork\n"); } } - - - return EXIT_SUCCESS; } diff --git a/coreutils/wc.c b/coreutils/wc.c index 8e3b5bb..7799015 100644 --- a/coreutils/wc.c +++ b/coreutils/wc.c @@ -1,8 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini wc implementation for busybox + * wc implementation for busybox * - * Copyright (C) 2000 Edward Betts <edward@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 @@ -20,159 +20,208 @@ * */ +/* BB_AUDIT SUSv3 _NOT_ compliant -- option -m is not currently supported. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/wc.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Rewritten to fix a number of problems and do some size optimizations. + * Problems in the previous busybox implementation (besides bloat) included: + * 1) broken 'wc -c' optimization (read note below) + * 2) broken handling of '-' args + * 3) no checking of ferror on EOF returns + * 4) isprint() wasn't considered when word counting. + * + * TODO: + * + * When locale support is enabled, count multibyte chars in the '-m' case. + * + * NOTES: + * + * The previous busybox wc attempted an optimization using stat for the + * case of counting chars only. I omitted that because it was broken. + * It didn't take into account the possibility of input coming from a + * pipe, or input from a file with file pointer not at the beginning. + * + * To implement such a speed optimization correctly, not only do you + * need the size, but also the file position. Note also that the + * file position may be past the end of file. Consider the example + * (adapted from example in gnu wc.c) + * + * echo hello > /tmp/testfile && + * (dd ibs=1k skip=1 count=0 &> /dev/null ; wc -c) < /tmp/testfile + * + * for which 'wc -c' should output '0'. + */ + #include <stdio.h> -#include <getopt.h> -#include <string.h> #include <stdlib.h> +#include <string.h> +#include <unistd.h> #include "busybox.h" -enum print_e { - print_lines = 1, - print_words = 2, - print_chars = 4, - print_length = 8 +#ifdef CONFIG_LOCALE_SUPPORT +#include <locale.h> +#include <ctype.h> +#define isspace_given_isprint(c) isspace(c) +#else +#undef isspace +#undef isprint +#define isspace(c) ((((c) == ' ') || (((unsigned int)((c) - 9)) <= (13 - 9)))) +#define isprint(c) (((unsigned int)((c) - 0x20)) <= (0x7e - 0x20)) +#define isspace_given_isprint(c) ((c) == ' ') +#endif + +enum { + WC_LINES = 0, + WC_WORDS = 1, + WC_CHARS = 2, + WC_LENGTH = 3 }; -static unsigned int total_lines = 0; -static unsigned int total_words = 0; -static unsigned int total_chars = 0; -static unsigned int max_length = 0; -static char print_type = 0; +/* Note: If this changes, remember to change the initialization of + * 'name' in wc_main. It needs to point to the terminating nul. */ +static const char wc_opts[] = "lwcL"; /* READ THE WARNING ABOVE! */ -static void print_counts(const unsigned int lines, const unsigned int words, - const unsigned int chars, const unsigned int length, const char *name) -{ - int output = 0; +enum { + OP_INC_LINE = 1, /* OP_INC_LINE must be 1. */ + OP_SPACE = 2, + OP_NEWLINE = 4, + OP_TAB = 8, + OP_NUL = 16, +}; - if (print_type & print_lines) { - printf("%7d", lines); - output++; - } - if (print_type & print_words) { - if (output++) - putchar(' '); - printf("%7d", words); - } - if (print_type & print_chars) { - if (output++) - putchar(' '); - printf("%7d", chars); - } - if (print_type & print_length) { - if (output++) - putchar(' '); - printf("%7d", length); - } - if (*name) { - printf(" %s", name); - } - putchar('\n'); -} +/* Note: If fmt_str changes, the offsets to 's' in the OUTPUT section + * will need to be updated. */ +static const char fmt_str[] = " %7u\0 %s\n"; +static const char total_str[] = "total"; -static void wc_file(FILE * file, const char *name) +int wc_main(int argc, char **argv) { - unsigned int lines = 0; - unsigned int words = 0; - unsigned int chars = 0; - unsigned int length = 0; - unsigned int linepos = 0; - char in_word = 0; + FILE *fp; + const char *s; + unsigned int *pcounts; + unsigned int counts[4]; + unsigned int totals[4]; + unsigned int linepos; + unsigned int u; + int num_files = 0; int c; - - while ((c = getc(file)) != EOF) { - chars++; - switch (c) { - case '\n': - lines++; - case '\r': - case '\f': - if (linepos > length) - length = linepos; - linepos = 0; - goto word_separator; - case '\t': - linepos += 8 - (linepos % 8); - goto word_separator; - case ' ': - linepos++; - case '\v': -word_separator: - if (in_word) { - in_word = 0; - words++; - } - break; - default: - linepos++; - in_word = 1; - break; - } - } - if (linepos > length) { - length = linepos; - } - if (in_word) { - words++; + char status = EXIT_SUCCESS; + char in_word; + char print_type; + + print_type = bb_getopt_ulflags(argc, argv, wc_opts); + + if (print_type == 0) { + print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS); } - print_counts(lines, words, chars, length, name); - total_lines += lines; - total_words += words; - total_chars += chars; - if (length > max_length) { - max_length = length; + + argv += optind; + if (!*argv) { + *--argv = (char *) bb_msg_standard_input; } -} - -int wc_main(int argc, char **argv) -{ - int opt; - - while ((opt = getopt(argc, argv, "clLw")) > 0) { - switch (opt) { - case 'c': - print_type |= print_chars; - break; - case 'l': - print_type |= print_lines; - break; - case 'L': - print_type |= print_length; - break; - case 'w': - print_type |= print_words; - break; - default: - show_usage(); + + memset(totals, 0, sizeof(totals)); + + pcounts = counts; + + do { + ++num_files; + if (!(fp = bb_wfopen_input(*argv))) { + status = EXIT_FAILURE; + continue; } - } - - if (print_type == 0) { - print_type = print_lines | print_words | print_chars; - } - - if (argv[optind] == NULL || strcmp(argv[optind], "-") == 0) { - wc_file(stdin, ""); - } else { - unsigned short num_files_counted = 0; - while (optind < argc) { - if (print_type == print_chars) { - struct stat statbuf; - stat(argv[optind], &statbuf); - print_counts(0, 0, statbuf.st_size, 0, argv[optind]); - total_chars += statbuf.st_size; + + memset(counts, 0, sizeof(counts)); + linepos = 0; + in_word = 0; + + do { + ++counts[WC_CHARS]; + c = getc(fp); + if (isprint(c)) { + ++linepos; + if (!isspace_given_isprint(c)) { + in_word = 1; + continue; + } + } else if (((unsigned int)(c - 9)) <= 4) { + /* \t 9 + * \n 10 + * \v 11 + * \f 12 + * \r 13 + */ + if (c == '\t') { + linepos = (linepos | 7) + 1; + } else { /* '\n', '\r', '\f', or '\v' */ + DO_EOF: + if (linepos > counts[WC_LENGTH]) { + counts[WC_LENGTH] = linepos; + } + if (c == '\n') { + ++counts[WC_LINES]; + } + if (c != '\v') { + linepos = 0; + } + } + } else if (c == EOF) { + if (ferror(fp)) { + bb_perror_msg("%s", *argv); + status = EXIT_FAILURE; + } + --counts[WC_CHARS]; + goto DO_EOF; /* Treat an EOF as '\r'. */ } else { - FILE *file; - file = xfopen(argv[optind], "r"); - wc_file(file, argv[optind]); - fclose(file); + continue; + } + + counts[WC_WORDS] += in_word; + in_word = 0; + if (c == EOF) { + break; } - optind++; - num_files_counted++; + } while (1); + + if (totals[WC_LENGTH] < counts[WC_LENGTH]) { + totals[WC_LENGTH] = counts[WC_LENGTH]; } - if (num_files_counted > 1) { - print_counts(total_lines, total_words, total_chars, max_length, "total"); + totals[WC_LENGTH] -= counts[WC_LENGTH]; + + bb_fclose_nonstdin(fp); + + OUTPUT: + s = fmt_str + 1; /* Skip the leading space on 1st pass. */ + u = 0; + do { + if (print_type & (1 << u)) { + bb_printf(s, pcounts[u]); + s = fmt_str; /* Ok... restore the leading space. */ + } + totals[u] += pcounts[u]; + } while (++u < 4); + + s += 8; /* Set the format to the empty string. */ + + if (*argv != bb_msg_standard_input) { + s -= 3; /* We have a name, so do %s conversion. */ } + bb_printf(s, *argv); + + } while (*++argv); + + /* If more than one file was processed, we want the totals. To save some + * space, we set the pcounts ptr to the totals array. This has the side + * effect of trashing the totals array after outputting it, but that's + * irrelavent since we no longer need it. */ + if (num_files > 1) { + num_files = 0; /* Make sure we don't get here again. */ + *--argv = (char *) total_str; + pcounts = totals; + goto OUTPUT; } - - return(EXIT_SUCCESS); + + bb_fflush_stdout_and_exit(status); } diff --git a/coreutils/who.c b/coreutils/who.c index 3da7ed1..1bf5520 100644 --- a/coreutils/who.c +++ b/coreutils/who.c @@ -23,7 +23,7 @@ #include <errno.h> #include <string.h> #include <time.h> -#include <busybox.h> +#include "busybox.h" extern int who_main(int argc, char **argv) { @@ -33,7 +33,7 @@ extern int who_main(int argc, char **argv) time_t now, idle; if (argc > 1) - show_usage(); + bb_show_usage(); setutent(); devlen = sizeof("/dev/") - 1; @@ -81,5 +81,3 @@ extern int who_main(int argc, char **argv) return 0; } - - diff --git a/coreutils/whoami.c b/coreutils/whoami.c index a9d6ecf..f93034d 100644 --- a/coreutils/whoami.c +++ b/coreutils/whoami.c @@ -20,7 +20,7 @@ * */ -/* getopt not needed */ +/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */ #include <stdio.h> #include <stdlib.h> @@ -30,14 +30,15 @@ extern int whoami_main(int argc, char **argv) { char user[9]; - uid_t uid = geteuid(); + uid_t uid; if (argc > 1) - show_usage(); + bb_show_usage(); + uid = geteuid(); if (my_getpwuid(user, uid)) { puts(user); - return EXIT_SUCCESS; + bb_fflush_stdout_and_exit(EXIT_SUCCESS); } - error_msg_and_die("cannot find username for UID %u", (unsigned) uid); + bb_error_msg_and_die("cannot find username for UID %u", (unsigned) uid); } diff --git a/coreutils/yes.c b/coreutils/yes.c index 7d9596d..74f7571 100644 --- a/coreutils/yes.c +++ b/coreutils/yes.c @@ -1,8 +1,8 @@ /* vi: set sw=4 ts=4: */ /* - * Mini yes implementation for busybox + * yes implementation for busybox * - * Copyright (C) 2000 Edward Betts <edward@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 @@ -20,7 +20,12 @@ * */ -/* getopt not needed */ +/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) + * + * Size reductions and removed redundant applet name prefix from error messages. + */ #include <stdio.h> #include <stdlib.h> @@ -28,26 +33,24 @@ extern int yes_main(int argc, char **argv) { - int i; - - if (argc >= 2 && *argv[1] == '-') - show_usage(); + static const char fmt_str[] = " %s"; + const char *fmt; + char **first_arg; - if (argc == 1) { - while (1) - if (puts("y") == EOF) { - perror("yes"); - return EXIT_FAILURE; - } + *argv = "y"; + if (argc != 1) { + ++argv; } - while (1) - for (i = 1; i < argc; i++) - if (fputs(argv[i], stdout) == EOF - || putchar(i == argc - 1 ? '\n' : ' ') == EOF) { - perror("yes"); - return EXIT_FAILURE; - } + first_arg = argv; + do { + fmt = fmt_str + 1; + do { + bb_printf(fmt, *argv); + fmt = fmt_str; + } while (*++argv); + argv = first_arg; + } while (putchar('\n') != EOF); - return EXIT_SUCCESS; + bb_perror_nomsg_and_die(); } |