hush: reorder builtins (cd and pwd ought to be close, etc), no code changes
No binary (build failed)
—
(log yok)
| @@ -8832,6 +8832,30 @@ static int FAST_FUNC builtin_printf(char **argv) | |
| } | |
| #endif | |
| + | #if ENABLE_HUSH_HELP |
| + | static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM) |
| + | { |
| + | const struct built_in_command *x; |
| + | |
| + | printf( |
| + | "Built-in commands:\n" |
| + | "------------------\n"); |
| + | for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) { |
| + | if (x->b_descr) |
| + | printf("%-10s%s\n", x->b_cmd, x->b_descr); |
| + | } |
| + | return EXIT_SUCCESS; |
| + | } |
| + | #endif |
| + | |
| + | #if MAX_HISTORY && ENABLE_FEATURE_EDITING |
| + | static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM) |
| + | { |
| + | show_history(G.line_input_state); |
| + | return EXIT_SUCCESS; |
| + | } |
| + | #endif |
| + | |
| static char **skip_dash_dash(char **argv) | |
| { | |
| argv++; | |
| @@ -8840,24 +8864,6 @@ static char **skip_dash_dash(char **argv) | |
| return argv; | |
| } | |
| - | static int FAST_FUNC builtin_eval(char **argv) |
| - | { |
| - | int rcode = EXIT_SUCCESS; |
| - | |
| - | argv = skip_dash_dash(argv); |
| - | if (*argv) { |
| - | char *str = expand_strvec_to_string(argv); |
| - | /* bash: |
| - | * eval "echo Hi; done" ("done" is syntax error): |
| - | * "echo Hi" will not execute too. |
| - | */ |
| - | parse_and_run_string(str); |
| - | free(str); |
| - | rcode = G.last_exitcode; |
| - | } |
| - | return rcode; |
| - | } |
| - | |
| static int FAST_FUNC builtin_cd(char **argv) | |
| { | |
| const char *newdir; | |
| @@ -8885,6 +8891,30 @@ static int FAST_FUNC builtin_cd(char **argv) | |
| return EXIT_SUCCESS; | |
| } | |
| + | static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM) |
| + | { |
| + | puts(get_cwd(0)); |
| + | return EXIT_SUCCESS; |
| + | } |
| + | |
| + | static int FAST_FUNC builtin_eval(char **argv) |
| + | { |
| + | int rcode = EXIT_SUCCESS; |
| + | |
| + | argv = skip_dash_dash(argv); |
| + | if (*argv) { |
| + | char *str = expand_strvec_to_string(argv); |
| + | /* bash: |
| + | * eval "echo Hi; done" ("done" is syntax error): |
| + | * "echo Hi" will not execute too. |
| + | */ |
| + | parse_and_run_string(str); |
| + | free(str); |
| + | rcode = G.last_exitcode; |
| + | } |
| + | return rcode; |
| + | } |
| + | |
| static int FAST_FUNC builtin_exec(char **argv) | |
| { | |
| argv = skip_dash_dash(argv); | |
| @@ -8930,6 +8960,147 @@ static int FAST_FUNC builtin_exit(char **argv) | |
| hush_exit(xatoi(argv[0]) & 0xff); | |
| } | |
| + | #if ENABLE_HUSH_TYPE |
| + | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */ |
| + | static int FAST_FUNC builtin_type(char **argv) |
| + | { |
| + | int ret = EXIT_SUCCESS; |
| + | |
| + | while (*++argv) { |
| + | const char *type; |
| + | char *path = NULL; |
| + | |
| + | if (0) {} /* make conditional compile easier below */ |
| + | /*else if (find_alias(*argv)) |
| + | type = "an alias";*/ |
| + | #if ENABLE_HUSH_FUNCTIONS |
| + | else if (find_function(*argv)) |
| + | type = "a function"; |
| + | #endif |
| + | else if (find_builtin(*argv)) |
| + | type = "a shell builtin"; |
| + | else if ((path = find_in_path(*argv)) != NULL) |
| + | type = path; |
| + | else { |
| + | bb_error_msg("type: %s: not found", *argv); |
| + | ret = EXIT_FAILURE; |
| + | continue; |
| + | } |
| + | |
| + | printf("%s is %s\n", *argv, type); |
| + | free(path); |
| + | } |
| + | |
| + | return ret; |
| + | } |
| + | #endif |
| + | |
| + | #if ENABLE_HUSH_READ |
| + | /* Interruptibility of read builtin in bash |
| + | * (tested on bash-4.2.8 by sending signals (not by ^C)): |
| + | * |
| + | * Empty trap makes read ignore corresponding signal, for any signal. |
| + | * |
| + | * SIGINT: |
| + | * - terminates non-interactive shell; |
| + | * - interrupts read in interactive shell; |
| + | * if it has non-empty trap: |
| + | * - executes trap and returns to command prompt in interactive shell; |
| + | * - executes trap and returns to read in non-interactive shell; |
| + | * SIGTERM: |
| + | * - is ignored (does not interrupt) read in interactive shell; |
| + | * - terminates non-interactive shell; |
| + | * if it has non-empty trap: |
| + | * - executes trap and returns to read; |
| + | * SIGHUP: |
| + | * - terminates shell (regardless of interactivity); |
| + | * if it has non-empty trap: |
| + | * - executes trap and returns to read; |
| + | */ |
| + | static int FAST_FUNC builtin_read(char **argv) |
| + | { |
| + | const char *r; |
| + | char *opt_n = NULL; |
| + | char *opt_p = NULL; |
| + | char *opt_t = NULL; |
| + | char *opt_u = NULL; |
| + | const char *ifs; |
| + | int read_flags; |
| + | |
| + | /* "!": do not abort on errors. |
| + | * Option string must start with "sr" to match BUILTIN_READ_xxx |
| + | */ |
| + | read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u); |
| + | if (read_flags == (uint32_t)-1) |
| + | return EXIT_FAILURE; |
| + | argv += optind; |
| + | ifs = get_local_var_value("IFS"); /* can be NULL */ |
| + | |
| + | again: |
| + | r = shell_builtin_read(set_local_var_from_halves, |
| + | argv, |
| + | ifs, |
| + | read_flags, |
| + | opt_n, |
| + | opt_p, |
| + | opt_t, |
| + | opt_u |
| + | ); |
| + | |
| + | if ((uintptr_t)r == 1 && errno == EINTR) { |
| + | unsigned sig = check_and_run_traps(); |
| + | if (sig && sig != SIGINT) |
| + | goto again; |
| + | } |
| + | |
| + | if ((uintptr_t)r > 1) { |
| + | bb_error_msg("%s", r); |
| + | r = (char*)(uintptr_t)1; |
| + | } |
| + | |
| + | return (uintptr_t)r; |
| + | } |
| + | #endif |
| + | |
| + | #if ENABLE_HUSH_UMASK |
| + | static int FAST_FUNC builtin_umask(char **argv) |
| + | { |
| + | int rc; |
| + | mode_t mask; |
| + | |
| + | rc = 1; |
| + | mask = umask(0); |
| + | argv = skip_dash_dash(argv); |
| + | if (argv[0]) { |
| + | mode_t old_mask = mask; |
| + | |
| + | /* numeric umasks are taken as-is */ |
| + | /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */ |
| + | if (!isdigit(argv[0][0])) |
| + | mask ^= 0777; |
| + | mask = bb_parse_mode(argv[0], mask); |
| + | if (!isdigit(argv[0][0])) |
| + | mask ^= 0777; |
| + | if ((unsigned)mask > 0777) { |
| + | mask = old_mask; |
| + | /* bash messages: |
| + | * bash: umask: 'q': invalid symbolic mode operator |
| + | * bash: umask: 999: octal number out of range |
| + | */ |
| + | bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]); |
| + | rc = 0; |
| + | } |
| + | } else { |
| + | /* Mimic bash */ |
| + | printf("%04o\n", (unsigned) mask); |
| + | /* fall through and restore mask which we set to 0 */ |
| + | } |
| + | umask(mask); |
| + | |
| + | return !rc; /* rc != 0 - success */ |
| + | } |
| + | #endif |
| + | |
| #if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP | |
| static void print_escaped(const char *s) | |
| { | |
| @@ -9218,72 +9389,60 @@ static int FAST_FUNC builtin_shift(char **argv) | |
| return EXIT_FAILURE; | |
| } | |
| - | #if ENABLE_HUSH_READ |
| - | /* Interruptibility of read builtin in bash |
| - | * (tested on bash-4.2.8 by sending signals (not by ^C)): |
| - | * |
| - | * Empty trap makes read ignore corresponding signal, for any signal. |
| - | * |
| - | * SIGINT: |
| - | * - terminates non-interactive shell; |
| - | * - interrupts read in interactive shell; |
| - | * if it has non-empty trap: |
| - | * - executes trap and returns to command prompt in interactive shell; |
| - | * - executes trap and returns to read in non-interactive shell; |
| - | * SIGTERM: |
| - | * - is ignored (does not interrupt) read in interactive shell; |
| - | * - terminates non-interactive shell; |
| - | * if it has non-empty trap: |
| - | * - executes trap and returns to read; |
| - | * SIGHUP: |
| - | * - terminates shell (regardless of interactivity); |
| - | * if it has non-empty trap: |
| - | * - executes trap and returns to read; |
| - | */ |
| - | static int FAST_FUNC builtin_read(char **argv) |
| + | static int FAST_FUNC builtin_source(char **argv) |
| { | |
| - | const char *r; |
| - | char *opt_n = NULL; |
| - | char *opt_p = NULL; |
| - | char *opt_t = NULL; |
| - | char *opt_u = NULL; |
| - | const char *ifs; |
| - | int read_flags; |
| + | char *arg_path, *filename; |
| + | FILE *input; |
| + | save_arg_t sv; |
| + | char *args_need_save; |
| + | #if ENABLE_HUSH_FUNCTIONS |
| + | smallint sv_flg; |
| + | #endif |
| - | /* "!": do not abort on errors. |
| - | * Option string must start with "sr" to match BUILTIN_READ_xxx |
| - | */ |
| - | read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u); |
| - | if (read_flags == (uint32_t)-1) |
| + | argv = skip_dash_dash(argv); |
| + | filename = argv[0]; |
| + | if (!filename) { |
| + | /* bash says: "bash: .: filename argument required" */ |
| + | return 2; /* bash compat */ |
| + | } |
| + | arg_path = NULL; |
| + | if (!strchr(filename, '/')) { |
| + | arg_path = find_in_path(filename); |
| + | if (arg_path) |
| + | filename = arg_path; |
| + | } |
| + | input = remember_FILE(fopen_or_warn(filename, "r")); |
| + | free(arg_path); |
| + | if (!input) { |
| + | /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ |
| + | /* POSIX: non-interactive shell should abort here, |
| + | * not merely fail. So far no one complained :) |
| + | */ |
| return EXIT_FAILURE; | |
| - | argv += optind; |
| - | ifs = get_local_var_value("IFS"); /* can be NULL */ |
| + | } |
| - | again: |
| - | r = shell_builtin_read(set_local_var_from_halves, |
| - | argv, |
| - | ifs, |
| - | read_flags, |
| - | opt_n, |
| - | opt_p, |
| - | opt_t, |
| - | opt_u |
| - | ); |
| + | #if ENABLE_HUSH_FUNCTIONS |
| + | sv_flg = G_flag_return_in_progress; |
| + | /* "we are inside sourced file, ok to use return" */ |
| + | G_flag_return_in_progress = -1; |
| + | #endif |
| + | args_need_save = argv[1]; /* used as a boolean variable */ |
| + | if (args_need_save) |
| + | save_and_replace_G_args(&sv, argv); |
| - | if ((uintptr_t)r == 1 && errno == EINTR) { |
| - | unsigned sig = check_and_run_traps(); |
| - | if (sig && sig != SIGINT) |
| - | goto again; |
| - | } |
| + | /* "false; . ./empty_line; echo Zero:$?" should print 0 */ |
| + | G.last_exitcode = 0; |
| + | parse_and_run_file(input); |
| + | fclose_and_forget(input); |
| - | if ((uintptr_t)r > 1) { |
| - | bb_error_msg("%s", r); |
| - | r = (char*)(uintptr_t)1; |
| - | } |
| + | if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */ |
| + | restore_G_args(&sv, argv); |
| + | #if ENABLE_HUSH_FUNCTIONS |
| + | G_flag_return_in_progress = sv_flg; |
| + | #endif |
| - | return (uintptr_t)r; |
| + | return G.last_exitcode; |
| } | |
| - | #endif |
| #if ENABLE_HUSH_TRAP | |
| static int FAST_FUNC builtin_trap(char **argv) | |
| @@ -9368,47 +9527,12 @@ static int FAST_FUNC builtin_trap(char **argv) | |
| if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */ | |
| argv++; | |
| } | |
| - | /* else: "-something", no special meaning */ |
| - | } |
| - | new_cmd = *argv; |
| - | reset_traps: |
| - | argv++; |
| - | goto process_sig_list; |
| - | } |
| - | #endif |
| - | |
| - | #if ENABLE_HUSH_TYPE |
| - | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */ |
| - | static int FAST_FUNC builtin_type(char **argv) |
| - | { |
| - | int ret = EXIT_SUCCESS; |
| - | |
| - | while (*++argv) { |
| - | const char *type; |
| - | char *path = NULL; |
| - | |
| - | if (0) {} /* make conditional compile easier below */ |
| - | /*else if (find_alias(*argv)) |
| - | type = "an alias";*/ |
| - | #if ENABLE_HUSH_FUNCTIONS |
| - | else if (find_function(*argv)) |
| - | type = "a function"; |
| - | #endif |
| - | else if (find_builtin(*argv)) |
| - | type = "a shell builtin"; |
| - | else if ((path = find_in_path(*argv)) != NULL) |
| - | type = path; |
| - | else { |
| - | bb_error_msg("type: %s: not found", *argv); |
| - | ret = EXIT_FAILURE; |
| - | continue; |
| - | } |
| - | |
| - | printf("%s is %s\n", *argv, type); |
| - | free(path); |
| + | /* else: "-something", no special meaning */ |
| } | |
| - | |
| - | return ret; |
| + | new_cmd = *argv; |
| + | reset_traps: |
| + | argv++; |
| + | goto process_sig_list; |
| } | |
| #endif | |
| @@ -9441,6 +9565,23 @@ static struct pipe *parse_jobspec(const char *str) | |
| return NULL; | |
| } | |
| + | static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM) |
| + | { |
| + | struct pipe *job; |
| + | const char *status_string; |
| + | |
| + | checkjobs(NULL, 0 /*(no pid to wait for)*/); |
| + | for (job = G.job_list; job; job = job->next) { |
| + | if (job->alive_cmds == job->stopped_cmds) |
| + | status_string = "Stopped"; |
| + | else |
| + | status_string = "Running"; |
| + | |
| + | printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext); |
| + | } |
| + | return EXIT_SUCCESS; |
| + | } |
| + | |
| /* built-in 'fg' and 'bg' handler */ | |
| static int FAST_FUNC builtin_fg_bg(char **argv) | |
| { | |
| @@ -9496,192 +9637,6 @@ static int FAST_FUNC builtin_fg_bg(char **argv) | |
| } | |
| #endif | |
| - | #if ENABLE_HUSH_HELP |
| - | static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM) |
| - | { |
| - | const struct built_in_command *x; |
| - | |
| - | printf( |
| - | "Built-in commands:\n" |
| - | "------------------\n"); |
| - | for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) { |
| - | if (x->b_descr) |
| - | printf("%-10s%s\n", x->b_cmd, x->b_descr); |
| - | } |
| - | return EXIT_SUCCESS; |
| - | } |
| - | #endif |
| - | |
| - | #if MAX_HISTORY && ENABLE_FEATURE_EDITING |
| - | static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM) |
| - | { |
| - | show_history(G.line_input_state); |
| - | return EXIT_SUCCESS; |
| - | } |
| - | #endif |
| - | |
| - | #if ENABLE_HUSH_JOB |
| - | static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM) |
| - | { |
| - | struct pipe *job; |
| - | const char *status_string; |
| - | |
| - | checkjobs(NULL, 0 /*(no pid to wait for)*/); |
| - | for (job = G.job_list; job; job = job->next) { |
| - | if (job->alive_cmds == job->stopped_cmds) |
| - | status_string = "Stopped"; |
| - | else |
| - | status_string = "Running"; |
| - | |
| - | printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext); |
| - | } |
| - | return EXIT_SUCCESS; |
| - | } |
| - | #endif |
| - | |
| - | #if ENABLE_HUSH_MEMLEAK |
| - | static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM) |
| - | { |
| - | void *p; |
| - | unsigned long l; |
| - | |
| - | # ifdef M_TRIM_THRESHOLD |
| - | /* Optional. Reduces probability of false positives */ |
| - | malloc_trim(0); |
| - | # endif |
| - | /* Crude attempt to find where "free memory" starts, |
| - | * sans fragmentation. */ |
| - | p = malloc(240); |
| - | l = (unsigned long)p; |
| - | free(p); |
| - | p = malloc(3400); |
| - | if (l < (unsigned long)p) l = (unsigned long)p; |
| - | free(p); |
| - | |
| - | |
| - | # if 0 /* debug */ |
| - | { |
| - | struct mallinfo mi = mallinfo(); |
| - | printf("top alloc:0x%lx malloced:%d+%d=%d\n", l, |
| - | mi.arena, mi.hblkhd, mi.arena + mi.hblkhd); |
| - | } |
| - | # endif |
| - | |
| - | if (!G.memleak_value) |
| - | G.memleak_value = l; |
| - | |
| - | l -= G.memleak_value; |
| - | if ((long)l < 0) |
| - | l = 0; |
| - | l /= 1024; |
| - | if (l > 127) |
| - | l = 127; |
| - | |
| - | /* Exitcode is "how many kilobytes we leaked since 1st call" */ |
| - | return l; |
| - | } |
| - | #endif |
| - | |
| - | static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM) |
| - | { |
| - | puts(get_cwd(0)); |
| - | return EXIT_SUCCESS; |
| - | } |
| - | |
| - | static int FAST_FUNC builtin_source(char **argv) |
| - | { |
| - | char *arg_path, *filename; |
| - | FILE *input; |
| - | save_arg_t sv; |
| - | char *args_need_save; |
| - | #if ENABLE_HUSH_FUNCTIONS |
| - | smallint sv_flg; |
| - | #endif |
| - | |
| - | argv = skip_dash_dash(argv); |
| - | filename = argv[0]; |
| - | if (!filename) { |
| - | /* bash says: "bash: .: filename argument required" */ |
| - | return 2; /* bash compat */ |
| - | } |
| - | arg_path = NULL; |
| - | if (!strchr(filename, '/')) { |
| - | arg_path = find_in_path(filename); |
| - | if (arg_path) |
| - | filename = arg_path; |
| - | } |
| - | input = remember_FILE(fopen_or_warn(filename, "r")); |
| - | free(arg_path); |
| - | if (!input) { |
| - | /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ |
| - | /* POSIX: non-interactive shell should abort here, |
| - | * not merely fail. So far no one complained :) |
| - | */ |
| - | return EXIT_FAILURE; |
| - | } |
| - | |
| - | #if ENABLE_HUSH_FUNCTIONS |
| - | sv_flg = G_flag_return_in_progress; |
| - | /* "we are inside sourced file, ok to use return" */ |
| - | G_flag_return_in_progress = -1; |
| - | #endif |
| - | args_need_save = argv[1]; /* used as a boolean variable */ |
| - | if (args_need_save) |
| - | save_and_replace_G_args(&sv, argv); |
| - | |
| - | /* "false; . ./empty_line; echo Zero:$?" should print 0 */ |
| - | G.last_exitcode = 0; |
| - | parse_and_run_file(input); |
| - | fclose_and_forget(input); |
| - | |
| - | if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */ |
| - | restore_G_args(&sv, argv); |
| - | #if ENABLE_HUSH_FUNCTIONS |
| - | G_flag_return_in_progress = sv_flg; |
| - | #endif |
| - | |
| - | return G.last_exitcode; |
| - | } |
| - | |
| - | #if ENABLE_HUSH_UMASK |
| - | static int FAST_FUNC builtin_umask(char **argv) |
| - | { |
| - | int rc; |
| - | mode_t mask; |
| - | |
| - | rc = 1; |
| - | mask = umask(0); |
| - | argv = skip_dash_dash(argv); |
| - | if (argv[0]) { |
| - | mode_t old_mask = mask; |
| - | |
| - | /* numeric umasks are taken as-is */ |
| - | /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */ |
| - | if (!isdigit(argv[0][0])) |
| - | mask ^= 0777; |
| - | mask = bb_parse_mode(argv[0], mask); |
| - | if (!isdigit(argv[0][0])) |
| - | mask ^= 0777; |
| - | if ((unsigned)mask > 0777) { |
| - | mask = old_mask; |
| - | /* bash messages: |
| - | * bash: umask: 'q': invalid symbolic mode operator |
| - | * bash: umask: 999: octal number out of range |
| - | */ |
| - | bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]); |
| - | rc = 0; |
| - | } |
| - | } else { |
| - | /* Mimic bash */ |
| - | printf("%04o\n", (unsigned) mask); |
| - | /* fall through and restore mask which we set to 0 */ |
| - | } |
| - | umask(mask); |
| - | |
| - | return !rc; /* rc != 0 - success */ |
| - | } |
| - | #endif |
| - | |
| #if ENABLE_HUSH_KILL | |
| static int FAST_FUNC builtin_kill(char **argv) | |
| { | |
| @@ -9984,3 +9939,46 @@ static int FAST_FUNC builtin_return(char **argv) | |
| return rc; | |
| } | |
| #endif | |
| + | |
| + | #if ENABLE_HUSH_MEMLEAK |
| + | static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM) |
| + | { |
| + | void *p; |
| + | unsigned long l; |
| + | |
| + | # ifdef M_TRIM_THRESHOLD |
| + | /* Optional. Reduces probability of false positives */ |
| + | malloc_trim(0); |
| + | # endif |
| + | /* Crude attempt to find where "free memory" starts, |
| + | * sans fragmentation. */ |
| + | p = malloc(240); |
| + | l = (unsigned long)p; |
| + | free(p); |
| + | p = malloc(3400); |
| + | if (l < (unsigned long)p) l = (unsigned long)p; |
| + | free(p); |
| + | |
| + | |
| + | # if 0 /* debug */ |
| + | { |
| + | struct mallinfo mi = mallinfo(); |
| + | printf("top alloc:0x%lx malloced:%d+%d=%d\n", l, |
| + | mi.arena, mi.hblkhd, mi.arena + mi.hblkhd); |
| + | } |
| + | # endif |
| + | |
| + | if (!G.memleak_value) |
| + | G.memleak_value = l; |
| + | |
| + | l -= G.memleak_value; |
| + | if ((long)l < 0) |
| + | l = 0; |
| + | l /= 1024; |
| + | if (l > 127) |
| + | l = 127; |
| + | |
| + | /* Exitcode is "how many kilobytes we leaked since 1st call" */ |
| + | return l; |
| + | } |
| + | #endif |