aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-03-06 20:12:00 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-03-06 20:12:00 +0100
commitf3c742f925c31bdf1b0d52c82e0ef608a344e10f (patch)
treec74cf752e03ef906fc74014882843640262a2322
parentcbcc1236f806f18e6386e6e1f495a9832b7d307d (diff)
downloadbusybox-w32-f3c742f925c31bdf1b0d52c82e0ef608a344e10f.tar.gz
busybox-w32-f3c742f925c31bdf1b0d52c82e0ef608a344e10f.tar.bz2
busybox-w32-f3c742f925c31bdf1b0d52c82e0ef608a344e10f.zip
hush: use ash's ulimit builtin; make it more more bash0like while at it
Based on a patch by Tobias Klauser <tklauser@distanz.ch> function old new delta shell_builtin_ulimit - 498 +498 limits_tbl 33 88 +55 ulimit_opt_string - 38 +38 bltins1 288 300 +12 limits_name 127 - -127 ulimitcmd 415 7 -408 ------------------------------------------------------------------------------ (add/remove: 3/1 grow/shrink: 2/1 up/down: 603/-535) Total: 68 bytes text data bss dec hex filename 839229 453 6828 846510 ceaae busybox_old 839423 453 6828 846704 ceb70 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/Kbuild4
-rw-r--r--shell/ash.c214
-rw-r--r--shell/builtin_ulimit.c227
-rw-r--r--shell/builtin_ulimit.h19
-rw-r--r--shell/hush.c4
5 files changed, 253 insertions, 215 deletions
diff --git a/shell/Kbuild b/shell/Kbuild
index d8306dc96..8b528654a 100644
--- a/shell/Kbuild
+++ b/shell/Kbuild
@@ -5,8 +5,8 @@
5# Licensed under the GPL v2, see the file LICENSE in this tarball. 5# Licensed under the GPL v2, see the file LICENSE in this tarball.
6 6
7lib-y:= 7lib-y:=
8lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o builtin_read.o 8lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o builtin_read.o builtin_ulimit.o
9lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o builtin_read.o 9lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o builtin_read.o builtin_ulimit.o
10lib-$(CONFIG_CTTYHACK) += cttyhack.o 10lib-$(CONFIG_CTTYHACK) += cttyhack.o
11 11
12lib-$(CONFIG_SH_MATH_SUPPORT) += math.o 12lib-$(CONFIG_SH_MATH_SUPPORT) += math.o
diff --git a/shell/ash.c b/shell/ash.c
index 8ffe67cca..0a8b6c0f2 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -51,6 +51,7 @@
51 51
52#include "shell_common.h" 52#include "shell_common.h"
53#include "builtin_read.h" 53#include "builtin_read.h"
54#include "builtin_ulimit.h"
54#include "math.h" 55#include "math.h"
55#if ENABLE_ASH_RANDOM_SUPPORT 56#if ENABLE_ASH_RANDOM_SUPPORT
56# include "random.h" 57# include "random.h"
@@ -12614,219 +12615,10 @@ umaskcmd(int argc UNUSED_PARAM, char **argv)
12614 return 0; 12615 return 0;
12615} 12616}
12616 12617
12617/*
12618 * ulimit builtin
12619 *
12620 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12621 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12622 * ash by J.T. Conklin.
12623 *
12624 * Public domain.
12625 */
12626struct limits {
12627 uint8_t cmd; /* RLIMIT_xxx fit into it */
12628 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12629 char option;
12630};
12631
12632static const struct limits limits_tbl[] = {
12633#ifdef RLIMIT_CPU
12634 { RLIMIT_CPU, 0, 't' },
12635#endif
12636#ifdef RLIMIT_FSIZE
12637 { RLIMIT_FSIZE, 9, 'f' },
12638#endif
12639#ifdef RLIMIT_DATA
12640 { RLIMIT_DATA, 10, 'd' },
12641#endif
12642#ifdef RLIMIT_STACK
12643 { RLIMIT_STACK, 10, 's' },
12644#endif
12645#ifdef RLIMIT_CORE
12646 { RLIMIT_CORE, 9, 'c' },
12647#endif
12648#ifdef RLIMIT_RSS
12649 { RLIMIT_RSS, 10, 'm' },
12650#endif
12651#ifdef RLIMIT_MEMLOCK
12652 { RLIMIT_MEMLOCK, 10, 'l' },
12653#endif
12654#ifdef RLIMIT_NPROC
12655 { RLIMIT_NPROC, 0, 'p' },
12656#endif
12657#ifdef RLIMIT_NOFILE
12658 { RLIMIT_NOFILE, 0, 'n' },
12659#endif
12660#ifdef RLIMIT_AS
12661 { RLIMIT_AS, 10, 'v' },
12662#endif
12663#ifdef RLIMIT_LOCKS
12664 { RLIMIT_LOCKS, 0, 'w' },
12665#endif
12666};
12667static const char limits_name[] =
12668#ifdef RLIMIT_CPU
12669 "time(seconds)" "\0"
12670#endif
12671#ifdef RLIMIT_FSIZE
12672 "file(blocks)" "\0"
12673#endif
12674#ifdef RLIMIT_DATA
12675 "data(kb)" "\0"
12676#endif
12677#ifdef RLIMIT_STACK
12678 "stack(kb)" "\0"
12679#endif
12680#ifdef RLIMIT_CORE
12681 "coredump(blocks)" "\0"
12682#endif
12683#ifdef RLIMIT_RSS
12684 "memory(kb)" "\0"
12685#endif
12686#ifdef RLIMIT_MEMLOCK
12687 "locked memory(kb)" "\0"
12688#endif
12689#ifdef RLIMIT_NPROC
12690 "process" "\0"
12691#endif
12692#ifdef RLIMIT_NOFILE
12693 "nofiles" "\0"
12694#endif
12695#ifdef RLIMIT_AS
12696 "vmemory(kb)" "\0"
12697#endif
12698#ifdef RLIMIT_LOCKS
12699 "locks" "\0"
12700#endif
12701;
12702
12703enum limtype { SOFT = 0x1, HARD = 0x2 };
12704
12705static void
12706printlim(enum limtype how, const struct rlimit *limit,
12707 const struct limits *l)
12708{
12709 rlim_t val;
12710
12711 val = limit->rlim_max;
12712 if (how & SOFT)
12713 val = limit->rlim_cur;
12714
12715 if (val == RLIM_INFINITY)
12716 out1fmt("unlimited\n");
12717 else {
12718 val >>= l->factor_shift;
12719 out1fmt("%lld\n", (long long) val);
12720 }
12721}
12722
12723static int FAST_FUNC 12618static int FAST_FUNC
12724ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 12619ulimitcmd(int argc UNUSED_PARAM, char **argv)
12725{ 12620{
12726 rlim_t val; 12621 return shell_builtin_ulimit(argv);
12727 enum limtype how = SOFT | HARD;
12728 const struct limits *l;
12729 int set, all = 0;
12730 int optc, what;
12731 struct rlimit limit;
12732
12733 what = 'f';
12734 while ((optc = nextopt("HSa"
12735#ifdef RLIMIT_CPU
12736 "t"
12737#endif
12738#ifdef RLIMIT_FSIZE
12739 "f"
12740#endif
12741#ifdef RLIMIT_DATA
12742 "d"
12743#endif
12744#ifdef RLIMIT_STACK
12745 "s"
12746#endif
12747#ifdef RLIMIT_CORE
12748 "c"
12749#endif
12750#ifdef RLIMIT_RSS
12751 "m"
12752#endif
12753#ifdef RLIMIT_MEMLOCK
12754 "l"
12755#endif
12756#ifdef RLIMIT_NPROC
12757 "p"
12758#endif
12759#ifdef RLIMIT_NOFILE
12760 "n"
12761#endif
12762#ifdef RLIMIT_AS
12763 "v"
12764#endif
12765#ifdef RLIMIT_LOCKS
12766 "w"
12767#endif
12768 )) != '\0')
12769 switch (optc) {
12770 case 'H':
12771 how = HARD;
12772 break;
12773 case 'S':
12774 how = SOFT;
12775 break;
12776 case 'a':
12777 all = 1;
12778 break;
12779 default:
12780 what = optc;
12781 }
12782
12783 for (l = limits_tbl; l->option != what; l++)
12784 continue;
12785
12786 set = *argptr ? 1 : 0;
12787 val = 0;
12788 if (set) {
12789 char *p = *argptr;
12790
12791 if (all || argptr[1])
12792 ash_msg_and_raise_error("too many arguments");
12793 if (strncmp(p, "unlimited\n", 9) == 0)
12794 val = RLIM_INFINITY;
12795 else {
12796 if (sizeof(val) == sizeof(int))
12797 val = bb_strtou(p, NULL, 10);
12798 else if (sizeof(val) == sizeof(long))
12799 val = bb_strtoul(p, NULL, 10);
12800 else
12801 val = bb_strtoull(p, NULL, 10);
12802 if (errno)
12803 ash_msg_and_raise_error("bad number");
12804 val <<= l->factor_shift;
12805 }
12806 }
12807 if (all) {
12808 const char *lname = limits_name;
12809 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12810 getrlimit(l->cmd, &limit);
12811 out1fmt("%-20s ", lname);
12812 lname += strlen(lname) + 1;
12813 printlim(how, &limit, l);
12814 }
12815 return 0;
12816 }
12817
12818 getrlimit(l->cmd, &limit);
12819 if (set) {
12820 if (how & HARD)
12821 limit.rlim_max = val;
12822 if (how & SOFT)
12823 limit.rlim_cur = val;
12824 if (setrlimit(l->cmd, &limit) < 0)
12825 ash_msg_and_raise_error("error setting limit (%m)");
12826 } else {
12827 printlim(how, &limit, l);
12828 }
12829 return 0;
12830} 12622}
12831 12623
12832/* ============ main() and helpers */ 12624/* ============ main() and helpers */
diff --git a/shell/builtin_ulimit.c b/shell/builtin_ulimit.c
new file mode 100644
index 000000000..7e8678341
--- /dev/null
+++ b/shell/builtin_ulimit.c
@@ -0,0 +1,227 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ulimit builtin
4 *
5 * Adapted from ash applet code
6 *
7 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
8 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
9 * ash by J.T. Conklin.
10 *
11 * Public domain.
12 *
13 * Copyright (c) 2010 Tobias Klauser
14 * Split from ash.c and slightly adapted.
15 *
16 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
17 */
18#include "libbb.h"
19#include "builtin_ulimit.h"
20
21
22struct limits {
23 uint8_t cmd; /* RLIMIT_xxx fit into it */
24 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
25 char option;
26 const char *name;
27};
28
29static const struct limits limits_tbl[] = {
30#ifdef RLIMIT_FSIZE
31 { RLIMIT_FSIZE, 9, 'f', "file size (blocks)" },
32#endif
33#ifdef RLIMIT_CPU
34 { RLIMIT_CPU, 0, 't', "cpu time (seconds)" },
35#endif
36#ifdef RLIMIT_DATA
37 { RLIMIT_DATA, 10, 'd', "data seg size (kb)" },
38#endif
39#ifdef RLIMIT_STACK
40 { RLIMIT_STACK, 10, 's', "stack size (kb)" },
41#endif
42#ifdef RLIMIT_CORE
43 { RLIMIT_CORE, 9, 'c', "core file size (blocks)" },
44#endif
45#ifdef RLIMIT_RSS
46 { RLIMIT_RSS, 10, 'm', "resident set size (kb)" },
47#endif
48#ifdef RLIMIT_MEMLOCK
49 { RLIMIT_MEMLOCK, 10, 'l', "locked memory (kb)" },
50#endif
51#ifdef RLIMIT_NPROC
52 { RLIMIT_NPROC, 0, 'p', "processes" },
53#endif
54#ifdef RLIMIT_NOFILE
55 { RLIMIT_NOFILE, 0, 'n', "file descriptors" },
56#endif
57#ifdef RLIMIT_AS
58 { RLIMIT_AS, 10, 'v', "address space (kb)" },
59#endif
60#ifdef RLIMIT_LOCKS
61 { RLIMIT_LOCKS, 0, 'w', "locks" },
62#endif
63};
64
65enum {
66 OPT_hard = (1 << 0),
67 OPT_soft = (1 << 1),
68};
69
70/* "-": treat args as parameters of option with ASCII code 1 */
71static const char ulimit_opt_string[] = "-HSa"
72#ifdef RLIMIT_FSIZE
73 "f::"
74#endif
75#ifdef RLIMIT_CPU
76 "t::"
77#endif
78#ifdef RLIMIT_DATA
79 "d::"
80#endif
81#ifdef RLIMIT_STACK
82 "s::"
83#endif
84#ifdef RLIMIT_CORE
85 "c::"
86#endif
87#ifdef RLIMIT_RSS
88 "m::"
89#endif
90#ifdef RLIMIT_MEMLOCK
91 "l::"
92#endif
93#ifdef RLIMIT_NPROC
94 "p::"
95#endif
96#ifdef RLIMIT_NOFILE
97 "n::"
98#endif
99#ifdef RLIMIT_AS
100 "v::"
101#endif
102#ifdef RLIMIT_LOCKS
103 "w::"
104#endif
105 ;
106
107static void printlim(unsigned opts, const struct rlimit *limit,
108 const struct limits *l)
109{
110 rlim_t val;
111
112 val = limit->rlim_max;
113 if (!(opts & OPT_hard))
114 val = limit->rlim_cur;
115
116 if (val == RLIM_INFINITY)
117 printf("unlimited\n");
118 else {
119 val >>= l->factor_shift;
120 printf("%llu\n", (long long) val);
121 }
122}
123
124int FAST_FUNC shell_builtin_ulimit(char **argv)
125{
126 unsigned opts;
127 unsigned argc;
128
129 /* We can't use getopt32: need to handle commands like
130 * ulimit 123 -c2 -l 456
131 */
132
133 /* In case getopt was already called:
134 * reset the libc getopt() function, which keeps internal state.
135 */
136#ifdef __GLIBC__
137 optind = 0;
138#else /* BSD style */
139 optind = 1;
140 /* optreset = 1; */
141#endif
142 /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */
143
144 argc = 1;
145 while (argv[argc])
146 argc++;
147
148 opts = 0;
149 while (1) {
150 struct rlimit limit;
151 const struct limits *l;
152 int opt_char = getopt(argc, argv, ulimit_opt_string);
153
154 if (opt_char == -1)
155 break;
156 if (opt_char == 'H') {
157 opts |= OPT_hard;
158 continue;
159 }
160 if (opt_char == 'S') {
161 opts |= OPT_soft;
162 continue;
163 }
164
165 if (opt_char == 'a') {
166 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
167 getrlimit(l->cmd, &limit);
168 printf("-%c: %-30s ", l->option, l->name);
169 printlim(opts, &limit, l);
170 }
171 continue;
172 }
173
174 if (opt_char == 1)
175 opt_char = 'f';
176 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
177 if (opt_char == l->option) {
178 char *val_str = optarg ? optarg : (argv[optind] && argv[optind][0] != '-' ? argv[optind] : NULL);
179
180 getrlimit(l->cmd, &limit);
181 if (val_str) {
182 rlim_t val;
183
184 if (!optarg) /* -c NNN: make getopt skip NNN */
185 optind++;
186
187 if (strcmp(val_str, "unlimited") == 0)
188 val = RLIM_INFINITY;
189 else {
190 if (sizeof(val) == sizeof(int))
191 val = bb_strtou(val_str, NULL, 10);
192 else if (sizeof(val) == sizeof(long))
193 val = bb_strtoul(val_str, NULL, 10);
194 else
195 val = bb_strtoull(val_str, NULL, 10);
196 if (errno) {
197 bb_error_msg("bad number");
198 return EXIT_FAILURE;
199 }
200 val <<= l->factor_shift;
201 }
202//bb_error_msg("opt %c val_str:'%s' val:%lld", opt_char, val_str, (long long)val);
203 if (opts & OPT_hard)
204 limit.rlim_max = val;
205 if ((opts & OPT_soft) || opts == 0)
206 limit.rlim_cur = val;
207//bb_error_msg("setrlimit(%d, %lld, %lld)", l->cmd, (long long)limit.rlim_cur, (long long)limit.rlim_max);
208 if (setrlimit(l->cmd, &limit) < 0) {
209 bb_perror_msg("error setting limit");
210 return EXIT_FAILURE;
211 }
212 } else {
213 printlim(opts, &limit, l);
214 }
215 break;
216 }
217 } /* for (every possible opt) */
218
219 if (l == &limits_tbl[ARRAY_SIZE(limits_tbl)]) {
220 /* bad option. getopt already complained. */
221 break;
222 }
223
224 } /* while (there are options) */
225
226 return 0;
227}
diff --git a/shell/builtin_ulimit.h b/shell/builtin_ulimit.h
new file mode 100644
index 000000000..ec1af78a6
--- /dev/null
+++ b/shell/builtin_ulimit.h
@@ -0,0 +1,19 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Adapted from ash applet code
4 *
5 * Copyright (c) 2010 Tobias Klauser
6 * Split from ash.c and slightly adapted.
7 *
8 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
9 */
10#ifndef SHELL_BUILTIN_ULIMIT_H
11#define SHELL_BUILTIN_ULIMIT_H 1
12
13PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
14
15int FAST_FUNC shell_builtin_ulimit(char **argv);
16
17POP_SAVED_FUNCTION_VISIBILITY
18
19#endif
diff --git a/shell/hush.c b/shell/hush.c
index 0310b02ed..6f391b881 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -57,7 +57,6 @@
57 * 57 *
58 * TODOs: 58 * TODOs:
59 * grep for "TODO" and fix (some of them are easy) 59 * grep for "TODO" and fix (some of them are easy)
60 * builtins: ulimit
61 * special variables (done: PWD) 60 * special variables (done: PWD)
62 * follow IFS rules more precisely, including update semantics 61 * follow IFS rules more precisely, including update semantics
63 * export builtin should be special, its arguments are assignments 62 * export builtin should be special, its arguments are assignments
@@ -87,6 +86,7 @@
87 86
88#include "shell_common.h" 87#include "shell_common.h"
89#include "builtin_read.h" 88#include "builtin_read.h"
89#include "builtin_ulimit.h"
90#include "math.h" 90#include "math.h"
91#include "match.h" 91#include "match.h"
92#if ENABLE_HUSH_RANDOM_SUPPORT 92#if ENABLE_HUSH_RANDOM_SUPPORT
@@ -671,7 +671,7 @@ static const struct built_in_command bltins1[] = {
671 BLTIN("shift" , builtin_shift , "Shift positional parameters"), 671 BLTIN("shift" , builtin_shift , "Shift positional parameters"),
672 BLTIN("trap" , builtin_trap , "Trap signals"), 672 BLTIN("trap" , builtin_trap , "Trap signals"),
673 BLTIN("type" , builtin_type , "Write a description of command type"), 673 BLTIN("type" , builtin_type , "Write a description of command type"),
674// BLTIN("ulimit" , builtin_ulimit , "Control resource limits"), 674 BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"),
675 BLTIN("umask" , builtin_umask , "Set file creation mask"), 675 BLTIN("umask" , builtin_umask , "Set file creation mask"),
676 BLTIN("unset" , builtin_unset , "Unset variables"), 676 BLTIN("unset" , builtin_unset , "Unset variables"),
677 BLTIN("wait" , builtin_wait , "Wait for process"), 677 BLTIN("wait" , builtin_wait , "Wait for process"),