bc: if ^C handling is not selected, there is no interactive mode
[oweals/busybox.git] / miscutils / bc.c
index e9cfeccccd26e9b7ddaa9674cc89fb30b1bdb061..ee4f2136430badf09bf4b6391cef5468139d8499 100644 (file)
 
 //See www.gnu.org/software/bc/manual/bc.html
 //usage:#define bc_trivial_usage
-//usage:       "[-sqli] FILE..."
+//usage:       "[-sqliw] FILE..."
 //usage:
 //usage:#define bc_full_usage "\n"
 //usage:     "\nArbitrary precision calculator"
 //usage:     "\n       -q      Quiet"
 //usage:     "\n       -w      Warn if extensions are used"
 ///////:     "\n       -v      Version"
+//usage:     "\n$BC_LINE_LENGTH changes output width"
 //usage:
 //usage:#define bc_example_usage
 //usage:       "3 + 4.129\n"
@@ -734,7 +735,7 @@ static void bc_program_reset(void);
 #define BC_MAX_VARS   ((unsigned long) SIZE_MAX - 1)
 
 struct globals {
-       smallint ttyin;
+       IF_FEATURE_BC_SIGNALS(smallint ttyin;)
        smallint eof;
        char sbgn;
        char send;
@@ -761,7 +762,11 @@ struct globals {
 #define G_warn  (ENABLE_BC && (option_mask32 & BC_FLAG_W))
 #define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X))
 #define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0)
-
+#if ENABLE_FEATURE_BC_SIGNALS
+# define G_ttyin G.ttyin
+#else
+# define G_ttyin 0
+#endif
 #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b'))
 
 #if ENABLE_BC
@@ -904,7 +909,7 @@ static void fflush_and_check(void)
 #if ENABLE_FEATURE_CLEAN_UP
 #define quit_or_return_for_exit() \
 do { \
-       G.ttyin = 0; /* do not loop in main loop anymore */ \
+       IF_FEATURE_BC_SIGNALS(G_ttyin = 0;) /* do not loop in main loop anymore */ \
        return BC_STATUS_FAILURE; \
 } while (0)
 #else
@@ -942,7 +947,7 @@ static NOINLINE int bc_error_fmt(const char *fmt, ...)
        bc_verror_msg(fmt, p);
        va_end(p);
 
-       if (!ENABLE_FEATURE_CLEAN_UP && !G.ttyin)
+       if (!ENABLE_FEATURE_CLEAN_UP && !G_ttyin)
                exit(1);
        return BC_STATUS_FAILURE;
 }
@@ -962,7 +967,7 @@ static NOINLINE int bc_posix_error_fmt(const char *fmt, ...)
        // Do we treat non-POSIX constructs as errors?
        if (!(option_mask32 & BC_FLAG_S))
                return BC_STATUS_SUCCESS; // no, it's a warning
-       if (!ENABLE_FEATURE_CLEAN_UP && !G.ttyin)
+       if (!ENABLE_FEATURE_CLEAN_UP && !G_ttyin)
                exit(1);
        return BC_STATUS_FAILURE;
 }
@@ -1017,15 +1022,6 @@ static int bc_error_nested_read_call(void)
        return bc_error("read() call inside of a read() call");
 }
 
-static void bc_vm_info(void)
-{
-       printf("%s "BB_VER"\n"
-               "Copyright (c) 2018 Gavin D. Howard and contributors\n"
-               "Report bugs at: https://github.com/gavinhoward/bc\n"
-               "This is free software with ABSOLUTELY NO WARRANTY\n"
-       , applet_name);
-}
-
 static void bc_vec_grow(BcVec *v, size_t n)
 {
        size_t cap = v->cap * 2;
@@ -1220,7 +1216,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt)
                                , stderr);
                }
 #endif
-               if (G.ttyin && !G_posix)
+               if (G_ttyin && !G_posix)
                        fputs(prompt, stderr);
 
 #if ENABLE_FEATURE_BC_SIGNALS
@@ -1284,35 +1280,6 @@ static char* bc_read_file(const char *path)
        return buf;
 }
 
-static void bc_args(char **argv)
-{
-       unsigned opts;
-       int i;
-
-       GETOPT_RESET();
-#if ENABLE_FEATURE_BC_LONG_OPTIONS
-       opts = option_mask32 |= getopt32long(argv, "xwvsqli",
-               "extended-register\0" No_argument "x"
-               "warn\0"              No_argument "w"
-               "version\0"           No_argument "v"
-               "standard\0"          No_argument "s"
-               "quiet\0"             No_argument "q"
-               "mathlib\0"           No_argument "l"
-               "interactive\0"       No_argument "i"
-       );
-#else
-       opts = option_mask32 |= getopt32(argv, "xwvsqli");
-#endif
-       if (getenv("POSIXLY_CORRECT"))
-               option_mask32 |= BC_FLAG_S;
-
-///should be in bc_vm_run() instead??
-       if (opts & BC_FLAG_V) bc_vm_info();
-
-       for (i = optind; argv[i]; ++i)
-               bc_vec_push(&G.files, argv + i);
-}
-
 static void bc_num_setToZero(BcNum *n, size_t scale)
 {
        n->len = 0;
@@ -6866,14 +6833,53 @@ static BcStatus bc_program_exec(void)
        return s;
 }
 
+static void bc_vm_info(void)
+{
+       printf("%s "BB_VER"\n"
+               "Copyright (c) 2018 Gavin D. Howard and contributors\n"
+               "Report bugs at: https://github.com/gavinhoward/bc\n"
+               "This is free software with ABSOLUTELY NO WARRANTY\n"
+       , applet_name);
+}
+
+static void bc_args(char **argv)
+{
+       unsigned opts;
+       int i;
+
+       GETOPT_RESET();
+#if ENABLE_FEATURE_BC_LONG_OPTIONS
+       opts = option_mask32 |= getopt32long(argv, "xwvsqli",
+               "extended-register\0" No_argument "x"
+               "warn\0"              No_argument "w"
+               "version\0"           No_argument "v"
+               "standard\0"          No_argument "s"
+               "quiet\0"             No_argument "q"
+               "mathlib\0"           No_argument "l"
+               "interactive\0"       No_argument "i"
+       );
+#else
+       opts = option_mask32 |= getopt32(argv, "xwvsqli");
+#endif
+       if (getenv("POSIXLY_CORRECT"))
+               option_mask32 |= BC_FLAG_S;
+
+///should be in bc_vm_run() instead??
+       if (opts & BC_FLAG_V) {
+               bc_vm_info();
+               exit(0);
+       }
+
+       for (i = optind; argv[i]; ++i)
+               bc_vec_push(&G.files, argv + i);
+}
+
 #if ENABLE_BC
 static void bc_vm_envArgs(void)
 {
-       static char *const nullptr = NULL;
-
        BcVec v;
-       char *env_args = getenv("BC_ENV_ARGS");
        char *buf;
+       char *env_args = getenv("BC_ENV_ARGS");
 
        if (!env_args) return;
 
@@ -6881,7 +6887,6 @@ static void bc_vm_envArgs(void)
        buf = G.env_args;
 
        bc_vec_init(&v, sizeof(char *), NULL);
-       bc_vec_push(&v, &nullptr);
 
        while (*(buf = skip_whitespace(buf)) != '\0') {
                bc_vec_push(&v, &buf);
@@ -6891,8 +6896,14 @@ static void bc_vm_envArgs(void)
                *buf++ = '\0';
        }
 
-       bc_vec_push(&v, &nullptr);
-       bc_args((char **) v.v);
+       // NULL terminate, and pass argv[] so that first arg is argv[1]
+       if (sizeof(int) == sizeof(char*)) {
+               bc_vec_push(&v, &const_int_0);
+       } else {
+               static char *const nullptr = NULL;
+               bc_vec_push(&v, &nullptr);
+       }
+       bc_args(((char **)v.v) - 1);
 
        bc_vec_free(&v);
 }
@@ -7028,7 +7039,7 @@ static BcStatus bc_vm_stdin(void)
                bc_vec_concat(&buffer, buf.v);
                s = bc_vm_process(buffer.v);
                if (s) {
-                       if (ENABLE_FEATURE_CLEAN_UP && !G.ttyin) {
+                       if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin) {
                                // Debug config, non-interactive mode:
                                // return all the way back to main.
                                // Non-debug builds do not come here, they exit.
@@ -7257,7 +7268,7 @@ static BcStatus bc_vm_exec(void)
        for (i = 0; !s && i < G.files.len; ++i)
                s = bc_vm_file(*((char **) bc_vec_item(&G.files, i)));
        if (s) {
-               if (ENABLE_FEATURE_CLEAN_UP && !G.ttyin) {
+               if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin) {
                        // Debug config, non-interactive mode:
                        // return all the way back to main.
                        // Non-debug builds do not come here, they exit.
@@ -7385,9 +7396,9 @@ static BcStatus bc_vm_run(char **argv, const char *env_len)
        bc_vm_init();
        bc_args(argv);
 
-       G.ttyin = isatty(0);
-       if (G.ttyin) {
+       if (isatty(0)) {
 #if ENABLE_FEATURE_BC_SIGNALS
+               G_ttyin = 1;
                // With SA_RESTART, most system calls will restart
                // (IOW: they won't fail with EINTR).
                // In particular, this means ^C won't cause