diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-06 20:12:00 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-06 20:12:00 +0100 |
commit | f3c742f925c31bdf1b0d52c82e0ef608a344e10f (patch) | |
tree | c74cf752e03ef906fc74014882843640262a2322 | |
parent | cbcc1236f806f18e6386e6e1f495a9832b7d307d (diff) | |
download | busybox-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/Kbuild | 4 | ||||
-rw-r--r-- | shell/ash.c | 214 | ||||
-rw-r--r-- | shell/builtin_ulimit.c | 227 | ||||
-rw-r--r-- | shell/builtin_ulimit.h | 19 | ||||
-rw-r--r-- | shell/hush.c | 4 |
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 | ||
7 | lib-y:= | 7 | lib-y:= |
8 | lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o builtin_read.o | 8 | lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o builtin_read.o builtin_ulimit.o |
9 | lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o builtin_read.o | 9 | lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o builtin_read.o builtin_ulimit.o |
10 | lib-$(CONFIG_CTTYHACK) += cttyhack.o | 10 | lib-$(CONFIG_CTTYHACK) += cttyhack.o |
11 | 11 | ||
12 | lib-$(CONFIG_SH_MATH_SUPPORT) += math.o | 12 | lib-$(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 | */ | ||
12626 | struct 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 | |||
12632 | static 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 | }; | ||
12667 | static 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 | |||
12703 | enum limtype { SOFT = 0x1, HARD = 0x2 }; | ||
12704 | |||
12705 | static void | ||
12706 | printlim(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 | |||
12723 | static int FAST_FUNC | 12618 | static int FAST_FUNC |
12724 | ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | 12619 | ulimitcmd(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 | |||
22 | struct 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 | |||
29 | static 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 | |||
65 | enum { | ||
66 | OPT_hard = (1 << 0), | ||
67 | OPT_soft = (1 << 1), | ||
68 | }; | ||
69 | |||
70 | /* "-": treat args as parameters of option with ASCII code 1 */ | ||
71 | static 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 | |||
107 | static 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 | |||
124 | int 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 | |||
13 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | ||
14 | |||
15 | int FAST_FUNC shell_builtin_ulimit(char **argv); | ||
16 | |||
17 | POP_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"), |