aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-01-10 15:58:02 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-10 15:58:02 +0100
commita1184af5f87b82df34af7782f76df9a1041200f1 (patch)
tree4fa027f9c981897ffb084e1df5a76ac30b9ff30a /shell
parentf35ad3bd1287627fc6ca7cc9c1f48b186257dd87 (diff)
downloadbusybox-w32-a1184af5f87b82df34af7782f76df9a1041200f1.tar.gz
busybox-w32-a1184af5f87b82df34af7782f76df9a1041200f1.tar.bz2
busybox-w32-a1184af5f87b82df34af7782f76df9a1041200f1.zip
hush: reorder builtins (cd and pwd ought to be close, etc), no code changes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c592
1 files changed, 295 insertions, 297 deletions
diff --git a/shell/hush.c b/shell/hush.c
index c0325cf5e..7cce89183 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -8832,6 +8832,30 @@ static int FAST_FUNC builtin_printf(char **argv)
8832} 8832}
8833#endif 8833#endif
8834 8834
8835#if ENABLE_HUSH_HELP
8836static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM)
8837{
8838 const struct built_in_command *x;
8839
8840 printf(
8841 "Built-in commands:\n"
8842 "------------------\n");
8843 for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) {
8844 if (x->b_descr)
8845 printf("%-10s%s\n", x->b_cmd, x->b_descr);
8846 }
8847 return EXIT_SUCCESS;
8848}
8849#endif
8850
8851#if MAX_HISTORY && ENABLE_FEATURE_EDITING
8852static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM)
8853{
8854 show_history(G.line_input_state);
8855 return EXIT_SUCCESS;
8856}
8857#endif
8858
8835static char **skip_dash_dash(char **argv) 8859static char **skip_dash_dash(char **argv)
8836{ 8860{
8837 argv++; 8861 argv++;
@@ -8840,24 +8864,6 @@ static char **skip_dash_dash(char **argv)
8840 return argv; 8864 return argv;
8841} 8865}
8842 8866
8843static int FAST_FUNC builtin_eval(char **argv)
8844{
8845 int rcode = EXIT_SUCCESS;
8846
8847 argv = skip_dash_dash(argv);
8848 if (*argv) {
8849 char *str = expand_strvec_to_string(argv);
8850 /* bash:
8851 * eval "echo Hi; done" ("done" is syntax error):
8852 * "echo Hi" will not execute too.
8853 */
8854 parse_and_run_string(str);
8855 free(str);
8856 rcode = G.last_exitcode;
8857 }
8858 return rcode;
8859}
8860
8861static int FAST_FUNC builtin_cd(char **argv) 8867static int FAST_FUNC builtin_cd(char **argv)
8862{ 8868{
8863 const char *newdir; 8869 const char *newdir;
@@ -8885,6 +8891,30 @@ static int FAST_FUNC builtin_cd(char **argv)
8885 return EXIT_SUCCESS; 8891 return EXIT_SUCCESS;
8886} 8892}
8887 8893
8894static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
8895{
8896 puts(get_cwd(0));
8897 return EXIT_SUCCESS;
8898}
8899
8900static int FAST_FUNC builtin_eval(char **argv)
8901{
8902 int rcode = EXIT_SUCCESS;
8903
8904 argv = skip_dash_dash(argv);
8905 if (*argv) {
8906 char *str = expand_strvec_to_string(argv);
8907 /* bash:
8908 * eval "echo Hi; done" ("done" is syntax error):
8909 * "echo Hi" will not execute too.
8910 */
8911 parse_and_run_string(str);
8912 free(str);
8913 rcode = G.last_exitcode;
8914 }
8915 return rcode;
8916}
8917
8888static int FAST_FUNC builtin_exec(char **argv) 8918static int FAST_FUNC builtin_exec(char **argv)
8889{ 8919{
8890 argv = skip_dash_dash(argv); 8920 argv = skip_dash_dash(argv);
@@ -8930,6 +8960,147 @@ static int FAST_FUNC builtin_exit(char **argv)
8930 hush_exit(xatoi(argv[0]) & 0xff); 8960 hush_exit(xatoi(argv[0]) & 0xff);
8931} 8961}
8932 8962
8963#if ENABLE_HUSH_TYPE
8964/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
8965static int FAST_FUNC builtin_type(char **argv)
8966{
8967 int ret = EXIT_SUCCESS;
8968
8969 while (*++argv) {
8970 const char *type;
8971 char *path = NULL;
8972
8973 if (0) {} /* make conditional compile easier below */
8974 /*else if (find_alias(*argv))
8975 type = "an alias";*/
8976#if ENABLE_HUSH_FUNCTIONS
8977 else if (find_function(*argv))
8978 type = "a function";
8979#endif
8980 else if (find_builtin(*argv))
8981 type = "a shell builtin";
8982 else if ((path = find_in_path(*argv)) != NULL)
8983 type = path;
8984 else {
8985 bb_error_msg("type: %s: not found", *argv);
8986 ret = EXIT_FAILURE;
8987 continue;
8988 }
8989
8990 printf("%s is %s\n", *argv, type);
8991 free(path);
8992 }
8993
8994 return ret;
8995}
8996#endif
8997
8998#if ENABLE_HUSH_READ
8999/* Interruptibility of read builtin in bash
9000 * (tested on bash-4.2.8 by sending signals (not by ^C)):
9001 *
9002 * Empty trap makes read ignore corresponding signal, for any signal.
9003 *
9004 * SIGINT:
9005 * - terminates non-interactive shell;
9006 * - interrupts read in interactive shell;
9007 * if it has non-empty trap:
9008 * - executes trap and returns to command prompt in interactive shell;
9009 * - executes trap and returns to read in non-interactive shell;
9010 * SIGTERM:
9011 * - is ignored (does not interrupt) read in interactive shell;
9012 * - terminates non-interactive shell;
9013 * if it has non-empty trap:
9014 * - executes trap and returns to read;
9015 * SIGHUP:
9016 * - terminates shell (regardless of interactivity);
9017 * if it has non-empty trap:
9018 * - executes trap and returns to read;
9019 */
9020static int FAST_FUNC builtin_read(char **argv)
9021{
9022 const char *r;
9023 char *opt_n = NULL;
9024 char *opt_p = NULL;
9025 char *opt_t = NULL;
9026 char *opt_u = NULL;
9027 const char *ifs;
9028 int read_flags;
9029
9030 /* "!": do not abort on errors.
9031 * Option string must start with "sr" to match BUILTIN_READ_xxx
9032 */
9033 read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u);
9034 if (read_flags == (uint32_t)-1)
9035 return EXIT_FAILURE;
9036 argv += optind;
9037 ifs = get_local_var_value("IFS"); /* can be NULL */
9038
9039 again:
9040 r = shell_builtin_read(set_local_var_from_halves,
9041 argv,
9042 ifs,
9043 read_flags,
9044 opt_n,
9045 opt_p,
9046 opt_t,
9047 opt_u
9048 );
9049
9050 if ((uintptr_t)r == 1 && errno == EINTR) {
9051 unsigned sig = check_and_run_traps();
9052 if (sig && sig != SIGINT)
9053 goto again;
9054 }
9055
9056 if ((uintptr_t)r > 1) {
9057 bb_error_msg("%s", r);
9058 r = (char*)(uintptr_t)1;
9059 }
9060
9061 return (uintptr_t)r;
9062}
9063#endif
9064
9065#if ENABLE_HUSH_UMASK
9066static int FAST_FUNC builtin_umask(char **argv)
9067{
9068 int rc;
9069 mode_t mask;
9070
9071 rc = 1;
9072 mask = umask(0);
9073 argv = skip_dash_dash(argv);
9074 if (argv[0]) {
9075 mode_t old_mask = mask;
9076
9077 /* numeric umasks are taken as-is */
9078 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
9079 if (!isdigit(argv[0][0]))
9080 mask ^= 0777;
9081 mask = bb_parse_mode(argv[0], mask);
9082 if (!isdigit(argv[0][0]))
9083 mask ^= 0777;
9084 if ((unsigned)mask > 0777) {
9085 mask = old_mask;
9086 /* bash messages:
9087 * bash: umask: 'q': invalid symbolic mode operator
9088 * bash: umask: 999: octal number out of range
9089 */
9090 bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
9091 rc = 0;
9092 }
9093 } else {
9094 /* Mimic bash */
9095 printf("%04o\n", (unsigned) mask);
9096 /* fall through and restore mask which we set to 0 */
9097 }
9098 umask(mask);
9099
9100 return !rc; /* rc != 0 - success */
9101}
9102#endif
9103
8933#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP 9104#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP
8934static void print_escaped(const char *s) 9105static void print_escaped(const char *s)
8935{ 9106{
@@ -9218,72 +9389,60 @@ static int FAST_FUNC builtin_shift(char **argv)
9218 return EXIT_FAILURE; 9389 return EXIT_FAILURE;
9219} 9390}
9220 9391
9221#if ENABLE_HUSH_READ 9392static int FAST_FUNC builtin_source(char **argv)
9222/* Interruptibility of read builtin in bash
9223 * (tested on bash-4.2.8 by sending signals (not by ^C)):
9224 *
9225 * Empty trap makes read ignore corresponding signal, for any signal.
9226 *
9227 * SIGINT:
9228 * - terminates non-interactive shell;
9229 * - interrupts read in interactive shell;
9230 * if it has non-empty trap:
9231 * - executes trap and returns to command prompt in interactive shell;
9232 * - executes trap and returns to read in non-interactive shell;
9233 * SIGTERM:
9234 * - is ignored (does not interrupt) read in interactive shell;
9235 * - terminates non-interactive shell;
9236 * if it has non-empty trap:
9237 * - executes trap and returns to read;
9238 * SIGHUP:
9239 * - terminates shell (regardless of interactivity);
9240 * if it has non-empty trap:
9241 * - executes trap and returns to read;
9242 */
9243static int FAST_FUNC builtin_read(char **argv)
9244{ 9393{
9245 const char *r; 9394 char *arg_path, *filename;
9246 char *opt_n = NULL; 9395 FILE *input;
9247 char *opt_p = NULL; 9396 save_arg_t sv;
9248 char *opt_t = NULL; 9397 char *args_need_save;
9249 char *opt_u = NULL; 9398#if ENABLE_HUSH_FUNCTIONS
9250 const char *ifs; 9399 smallint sv_flg;
9251 int read_flags; 9400#endif
9252 9401
9253 /* "!": do not abort on errors. 9402 argv = skip_dash_dash(argv);
9254 * Option string must start with "sr" to match BUILTIN_READ_xxx 9403 filename = argv[0];
9255 */ 9404 if (!filename) {
9256 read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u); 9405 /* bash says: "bash: .: filename argument required" */
9257 if (read_flags == (uint32_t)-1) 9406 return 2; /* bash compat */
9407 }
9408 arg_path = NULL;
9409 if (!strchr(filename, '/')) {
9410 arg_path = find_in_path(filename);
9411 if (arg_path)
9412 filename = arg_path;
9413 }
9414 input = remember_FILE(fopen_or_warn(filename, "r"));
9415 free(arg_path);
9416 if (!input) {
9417 /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */
9418 /* POSIX: non-interactive shell should abort here,
9419 * not merely fail. So far no one complained :)
9420 */
9258 return EXIT_FAILURE; 9421 return EXIT_FAILURE;
9259 argv += optind; 9422 }
9260 ifs = get_local_var_value("IFS"); /* can be NULL */
9261 9423
9262 again: 9424#if ENABLE_HUSH_FUNCTIONS
9263 r = shell_builtin_read(set_local_var_from_halves, 9425 sv_flg = G_flag_return_in_progress;
9264 argv, 9426 /* "we are inside sourced file, ok to use return" */
9265 ifs, 9427 G_flag_return_in_progress = -1;
9266 read_flags, 9428#endif
9267 opt_n, 9429 args_need_save = argv[1]; /* used as a boolean variable */
9268 opt_p, 9430 if (args_need_save)
9269 opt_t, 9431 save_and_replace_G_args(&sv, argv);
9270 opt_u
9271 );
9272 9432
9273 if ((uintptr_t)r == 1 && errno == EINTR) { 9433 /* "false; . ./empty_line; echo Zero:$?" should print 0 */
9274 unsigned sig = check_and_run_traps(); 9434 G.last_exitcode = 0;
9275 if (sig && sig != SIGINT) 9435 parse_and_run_file(input);
9276 goto again; 9436 fclose_and_forget(input);
9277 }
9278 9437
9279 if ((uintptr_t)r > 1) { 9438 if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */
9280 bb_error_msg("%s", r); 9439 restore_G_args(&sv, argv);
9281 r = (char*)(uintptr_t)1; 9440#if ENABLE_HUSH_FUNCTIONS
9282 } 9441 G_flag_return_in_progress = sv_flg;
9442#endif
9283 9443
9284 return (uintptr_t)r; 9444 return G.last_exitcode;
9285} 9445}
9286#endif
9287 9446
9288#if ENABLE_HUSH_TRAP 9447#if ENABLE_HUSH_TRAP
9289static int FAST_FUNC builtin_trap(char **argv) 9448static int FAST_FUNC builtin_trap(char **argv)
@@ -9377,41 +9536,6 @@ static int FAST_FUNC builtin_trap(char **argv)
9377} 9536}
9378#endif 9537#endif
9379 9538
9380#if ENABLE_HUSH_TYPE
9381/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
9382static int FAST_FUNC builtin_type(char **argv)
9383{
9384 int ret = EXIT_SUCCESS;
9385
9386 while (*++argv) {
9387 const char *type;
9388 char *path = NULL;
9389
9390 if (0) {} /* make conditional compile easier below */
9391 /*else if (find_alias(*argv))
9392 type = "an alias";*/
9393#if ENABLE_HUSH_FUNCTIONS
9394 else if (find_function(*argv))
9395 type = "a function";
9396#endif
9397 else if (find_builtin(*argv))
9398 type = "a shell builtin";
9399 else if ((path = find_in_path(*argv)) != NULL)
9400 type = path;
9401 else {
9402 bb_error_msg("type: %s: not found", *argv);
9403 ret = EXIT_FAILURE;
9404 continue;
9405 }
9406
9407 printf("%s is %s\n", *argv, type);
9408 free(path);
9409 }
9410
9411 return ret;
9412}
9413#endif
9414
9415#if ENABLE_HUSH_JOB 9539#if ENABLE_HUSH_JOB
9416static struct pipe *parse_jobspec(const char *str) 9540static struct pipe *parse_jobspec(const char *str)
9417{ 9541{
@@ -9441,6 +9565,23 @@ static struct pipe *parse_jobspec(const char *str)
9441 return NULL; 9565 return NULL;
9442} 9566}
9443 9567
9568static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM)
9569{
9570 struct pipe *job;
9571 const char *status_string;
9572
9573 checkjobs(NULL, 0 /*(no pid to wait for)*/);
9574 for (job = G.job_list; job; job = job->next) {
9575 if (job->alive_cmds == job->stopped_cmds)
9576 status_string = "Stopped";
9577 else
9578 status_string = "Running";
9579
9580 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext);
9581 }
9582 return EXIT_SUCCESS;
9583}
9584
9444/* built-in 'fg' and 'bg' handler */ 9585/* built-in 'fg' and 'bg' handler */
9445static int FAST_FUNC builtin_fg_bg(char **argv) 9586static int FAST_FUNC builtin_fg_bg(char **argv)
9446{ 9587{
@@ -9496,192 +9637,6 @@ static int FAST_FUNC builtin_fg_bg(char **argv)
9496} 9637}
9497#endif 9638#endif
9498 9639
9499#if ENABLE_HUSH_HELP
9500static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM)
9501{
9502 const struct built_in_command *x;
9503
9504 printf(
9505 "Built-in commands:\n"
9506 "------------------\n");
9507 for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) {
9508 if (x->b_descr)
9509 printf("%-10s%s\n", x->b_cmd, x->b_descr);
9510 }
9511 return EXIT_SUCCESS;
9512}
9513#endif
9514
9515#if MAX_HISTORY && ENABLE_FEATURE_EDITING
9516static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM)
9517{
9518 show_history(G.line_input_state);
9519 return EXIT_SUCCESS;
9520}
9521#endif
9522
9523#if ENABLE_HUSH_JOB
9524static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM)
9525{
9526 struct pipe *job;
9527 const char *status_string;
9528
9529 checkjobs(NULL, 0 /*(no pid to wait for)*/);
9530 for (job = G.job_list; job; job = job->next) {
9531 if (job->alive_cmds == job->stopped_cmds)
9532 status_string = "Stopped";
9533 else
9534 status_string = "Running";
9535
9536 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext);
9537 }
9538 return EXIT_SUCCESS;
9539}
9540#endif
9541
9542#if ENABLE_HUSH_MEMLEAK
9543static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM)
9544{
9545 void *p;
9546 unsigned long l;
9547
9548# ifdef M_TRIM_THRESHOLD
9549 /* Optional. Reduces probability of false positives */
9550 malloc_trim(0);
9551# endif
9552 /* Crude attempt to find where "free memory" starts,
9553 * sans fragmentation. */
9554 p = malloc(240);
9555 l = (unsigned long)p;
9556 free(p);
9557 p = malloc(3400);
9558 if (l < (unsigned long)p) l = (unsigned long)p;
9559 free(p);
9560
9561
9562# if 0 /* debug */
9563 {
9564 struct mallinfo mi = mallinfo();
9565 printf("top alloc:0x%lx malloced:%d+%d=%d\n", l,
9566 mi.arena, mi.hblkhd, mi.arena + mi.hblkhd);
9567 }
9568# endif
9569
9570 if (!G.memleak_value)
9571 G.memleak_value = l;
9572
9573 l -= G.memleak_value;
9574 if ((long)l < 0)
9575 l = 0;
9576 l /= 1024;
9577 if (l > 127)
9578 l = 127;
9579
9580 /* Exitcode is "how many kilobytes we leaked since 1st call" */
9581 return l;
9582}
9583#endif
9584
9585static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
9586{
9587 puts(get_cwd(0));
9588 return EXIT_SUCCESS;
9589}
9590
9591static int FAST_FUNC builtin_source(char **argv)
9592{
9593 char *arg_path, *filename;
9594 FILE *input;
9595 save_arg_t sv;
9596 char *args_need_save;
9597#if ENABLE_HUSH_FUNCTIONS
9598 smallint sv_flg;
9599#endif
9600
9601 argv = skip_dash_dash(argv);
9602 filename = argv[0];
9603 if (!filename) {
9604 /* bash says: "bash: .: filename argument required" */
9605 return 2; /* bash compat */
9606 }
9607 arg_path = NULL;
9608 if (!strchr(filename, '/')) {
9609 arg_path = find_in_path(filename);
9610 if (arg_path)
9611 filename = arg_path;
9612 }
9613 input = remember_FILE(fopen_or_warn(filename, "r"));
9614 free(arg_path);
9615 if (!input) {
9616 /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */
9617 /* POSIX: non-interactive shell should abort here,
9618 * not merely fail. So far no one complained :)
9619 */
9620 return EXIT_FAILURE;
9621 }
9622
9623#if ENABLE_HUSH_FUNCTIONS
9624 sv_flg = G_flag_return_in_progress;
9625 /* "we are inside sourced file, ok to use return" */
9626 G_flag_return_in_progress = -1;
9627#endif
9628 args_need_save = argv[1]; /* used as a boolean variable */
9629 if (args_need_save)
9630 save_and_replace_G_args(&sv, argv);
9631
9632 /* "false; . ./empty_line; echo Zero:$?" should print 0 */
9633 G.last_exitcode = 0;
9634 parse_and_run_file(input);
9635 fclose_and_forget(input);
9636
9637 if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */
9638 restore_G_args(&sv, argv);
9639#if ENABLE_HUSH_FUNCTIONS
9640 G_flag_return_in_progress = sv_flg;
9641#endif
9642
9643 return G.last_exitcode;
9644}
9645
9646#if ENABLE_HUSH_UMASK
9647static int FAST_FUNC builtin_umask(char **argv)
9648{
9649 int rc;
9650 mode_t mask;
9651
9652 rc = 1;
9653 mask = umask(0);
9654 argv = skip_dash_dash(argv);
9655 if (argv[0]) {
9656 mode_t old_mask = mask;
9657
9658 /* numeric umasks are taken as-is */
9659 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
9660 if (!isdigit(argv[0][0]))
9661 mask ^= 0777;
9662 mask = bb_parse_mode(argv[0], mask);
9663 if (!isdigit(argv[0][0]))
9664 mask ^= 0777;
9665 if ((unsigned)mask > 0777) {
9666 mask = old_mask;
9667 /* bash messages:
9668 * bash: umask: 'q': invalid symbolic mode operator
9669 * bash: umask: 999: octal number out of range
9670 */
9671 bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
9672 rc = 0;
9673 }
9674 } else {
9675 /* Mimic bash */
9676 printf("%04o\n", (unsigned) mask);
9677 /* fall through and restore mask which we set to 0 */
9678 }
9679 umask(mask);
9680
9681 return !rc; /* rc != 0 - success */
9682}
9683#endif
9684
9685#if ENABLE_HUSH_KILL 9640#if ENABLE_HUSH_KILL
9686static int FAST_FUNC builtin_kill(char **argv) 9641static int FAST_FUNC builtin_kill(char **argv)
9687{ 9642{
@@ -9984,3 +9939,46 @@ static int FAST_FUNC builtin_return(char **argv)
9984 return rc; 9939 return rc;
9985} 9940}
9986#endif 9941#endif
9942
9943#if ENABLE_HUSH_MEMLEAK
9944static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM)
9945{
9946 void *p;
9947 unsigned long l;
9948
9949# ifdef M_TRIM_THRESHOLD
9950 /* Optional. Reduces probability of false positives */
9951 malloc_trim(0);
9952# endif
9953 /* Crude attempt to find where "free memory" starts,
9954 * sans fragmentation. */
9955 p = malloc(240);
9956 l = (unsigned long)p;
9957 free(p);
9958 p = malloc(3400);
9959 if (l < (unsigned long)p) l = (unsigned long)p;
9960 free(p);
9961
9962
9963# if 0 /* debug */
9964 {
9965 struct mallinfo mi = mallinfo();
9966 printf("top alloc:0x%lx malloced:%d+%d=%d\n", l,
9967 mi.arena, mi.hblkhd, mi.arena + mi.hblkhd);
9968 }
9969# endif
9970
9971 if (!G.memleak_value)
9972 G.memleak_value = l;
9973
9974 l -= G.memleak_value;
9975 if ((long)l < 0)
9976 l = 0;
9977 l /= 1024;
9978 if (l > 127)
9979 l = 127;
9980
9981 /* Exitcode is "how many kilobytes we leaked since 1st call" */
9982 return l;
9983}
9984#endif