hush: print cd error to stderr; use fopen_or_warn in builtin_source;
authorDenis Vlasenko <vda.linux@googlemail.com>
Mon, 6 Apr 2009 12:04:42 +0000 (12:04 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Mon, 6 Apr 2009 12:04:42 +0000 (12:04 -0000)
 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

libbb/wfopen.c
shell/hush.c

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