hush: print cd error to stderr; use fopen_or_warn in builtin_source;

prepare builtin_unset for function support
libbb: do not clear errno in fopen_or_warn

function                                             old     new   delta
builtin_unset                                        242     271     +29
fopen_or_warn                                         42      31     -11
builtin_cd                                            90      74     -16
builtin_source                                        89      72     -17
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/3 up/down: 29/-44)            Total: -15 bytes
This commit is contained in:
Denis Vlasenko 2009-04-06 12:04:42 +00:00
parent b0a6478eef
commit bfbc971f9f
2 changed files with 39 additions and 25 deletions

View File

@ -14,7 +14,7 @@ FILE* FAST_FUNC fopen_or_warn(const char *path, const char *mode)
FILE *fp = fopen(path, mode); FILE *fp = fopen(path, mode);
if (!fp) { if (!fp) {
bb_simple_perror_msg(path); bb_simple_perror_msg(path);
errno = 0; //errno = 0; /* why? */
} }
return fp; return fp;
} }

View File

@ -5457,17 +5457,16 @@ static int builtin_eval(char **argv)
static int builtin_cd(char **argv) static int builtin_cd(char **argv)
{ {
const char *newdir; const char *newdir = argv[1];
if (*++argv == NULL) { if (newdir == NULL) {
/* bash does nothing (exitcode 0) if HOME is ""; if it's unset, /* bash does nothing (exitcode 0) if HOME is ""; if it's unset,
* bash says "bash: cd: HOME not set" and does nothing (exitcode 1) * bash says "bash: cd: HOME not set" and does nothing (exitcode 1)
*/ */
newdir = getenv("HOME") ? : "/"; newdir = getenv("HOME") ? : "/";
} else {
newdir = *argv;
} }
if (chdir(newdir)) { if (chdir(newdir)) {
printf("cd: %s: %s\n", newdir, strerror(errno)); /* Mimic bash message exactly */
bb_perror_msg("cd: %s", newdir);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
set_cwd(); set_cwd();
@ -5763,18 +5762,19 @@ static int builtin_source(char **argv)
{ {
FILE *input; FILE *input;
if (argv[1] == NULL) if (*++argv == NULL)
return EXIT_FAILURE; return EXIT_FAILURE;
/* XXX search through $PATH is missing */ /* XXX search through $PATH is missing */
input = fopen_for_read(argv[1]); input = fopen_or_warn(*argv, "r");
if (!input) { if (!input) {
bb_error_msg("can't open '%s'", argv[1]); /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */
return EXIT_FAILURE; return EXIT_FAILURE;
} }
close_on_exec_on(fileno(input)); close_on_exec_on(fileno(input));
/* Now run the file */ /* Now run the file */
//TODO:
/* XXX argv and argc are broken; need to save old G.global_argv /* XXX argv and argc are broken; need to save old G.global_argv
* (pointer only is OK!) on this stack frame, * (pointer only is OK!) on this stack frame,
* set G.global_argv=argv+1, recurse, and restore. */ * set G.global_argv=argv+1, recurse, and restore. */
@ -5788,12 +5788,18 @@ static int builtin_umask(char **argv)
mode_t new_umask; mode_t new_umask;
const char *arg = argv[1]; const char *arg = argv[1];
if (arg) { if (arg) {
//TODO: umask may take chmod-like symbolic masks
new_umask = bb_strtou(arg, NULL, 8); new_umask = bb_strtou(arg, NULL, 8);
if (errno) if (errno) {
//Message? bash examples:
//bash: umask: 'q': invalid symbolic mode operator
//bash: umask: 999: octal number out of range
return EXIT_FAILURE; return EXIT_FAILURE;
}
} else { } else {
new_umask = umask(0); new_umask = umask(0);
printf("%.3o\n", (unsigned) new_umask); printf("%.3o\n", (unsigned) new_umask);
/* fall through and restore new_umask which we set to 0 */
} }
umask(new_umask); umask(new_umask);
return EXIT_SUCCESS; return EXIT_SUCCESS;
@ -5802,35 +5808,43 @@ static int builtin_umask(char **argv)
/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */ /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */
static int builtin_unset(char **argv) static int builtin_unset(char **argv)
{ {
size_t i;
int ret; int ret;
bool var = true; char var;
if (!argv[1]) if (!*++argv)
return EXIT_SUCCESS; return EXIT_SUCCESS;
i = 0; var = 'v';
if (argv[1][0] == '-') { if (argv[0][0] == '-') {
switch (argv[1][1]) { switch (argv[0][1]) {
case 'v': break; case 'v':
case 'f': if (ENABLE_HUSH_FUNCTIONS) { var = false; break; } case 'f':
var = argv[0][1];
break;
default: default:
bb_error_msg("unset: %s: invalid option", argv[1]); bb_error_msg("unset: %s: invalid option", *argv);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
++i; //TODO: disallow "unset -vf ..." too
argv++;
} }
ret = EXIT_SUCCESS; ret = EXIT_SUCCESS;
while (argv[++i]) { while (*argv) {
if (var) { if (var == 'v') {
if (unset_local_var(argv[i])) if (unset_local_var(*argv)) {
/* unset <nonexistent_var> doesn't fail.
* Error is when one tries to unset RO var.
* Message was printed by unset_local_var. */
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
}
} }
#if ENABLE_HUSH_FUNCTIONS #if ENABLE_HUSH_FUNCTIONS
else else {
unset_local_func(argv[i]); unset_local_func(*argv);
}
#endif #endif
argv++;
} }
return ret; return ret;
} }