diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-12-16 17:20:38 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-12-16 17:20:38 +0000 |
| commit | 0163111325009ea10979105508bb294d4d67680c (patch) | |
| tree | af0c356024acfde96833b0b9d0c938560139f242 /shell | |
| parent | 9ad2cb3f1a3a8999df1d08422ed7cf01242158a5 (diff) | |
| download | busybox-w32-0163111325009ea10979105508bb294d4d67680c.tar.gz busybox-w32-0163111325009ea10979105508bb294d4d67680c.tar.bz2 busybox-w32-0163111325009ea10979105508bb294d4d67680c.zip | |
ash: reduce global data/bss usage
(add/remove: 4/29 grow/shrink: 76/21 up/down: 1007/-1713) Total: -706 bytes
text data bss dec hex filename
777206 1084 8976 787266 c0342 busybox_old
778077 908 7568 786553 c0079 busybox_unstripped
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 456 |
1 files changed, 277 insertions, 179 deletions
diff --git a/shell/ash.c b/shell/ash.c index 4c8a28911..f7604cf93 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -67,6 +67,13 @@ extern char **environ; | |||
| 67 | #endif | 67 | #endif |
| 68 | 68 | ||
| 69 | 69 | ||
| 70 | /* ============ Hash table sizes. Configurable. */ | ||
| 71 | |||
| 72 | #define VTABSIZE 39 | ||
| 73 | #define ATABSIZE 39 | ||
| 74 | #define CMDTABLESIZE 31 /* should be prime */ | ||
| 75 | |||
| 76 | |||
| 70 | /* ============ Misc helpers */ | 77 | /* ============ Misc helpers */ |
| 71 | 78 | ||
| 72 | #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0) | 79 | #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0) |
| @@ -127,30 +134,10 @@ static char optlist[NOPTS] ALIGN1; | |||
| 127 | 134 | ||
| 128 | /* ============ Misc data */ | 135 | /* ============ Misc data */ |
| 129 | 136 | ||
| 130 | static char nullstr[1] ALIGN1; /* zero length string */ | ||
| 131 | static const char homestr[] ALIGN1 = "HOME"; | 137 | static const char homestr[] ALIGN1 = "HOME"; |
| 132 | static const char snlfmt[] ALIGN1 = "%s\n"; | 138 | static const char snlfmt[] ALIGN1 = "%s\n"; |
| 133 | static const char illnum[] ALIGN1 = "Illegal number: %s"; | 139 | static const char illnum[] ALIGN1 = "Illegal number: %s"; |
| 134 | 140 | ||
| 135 | static char *minusc; /* argument to -c option */ | ||
| 136 | |||
| 137 | /* pid of main shell */ | ||
| 138 | static int rootpid; | ||
| 139 | /* shell level: 0 for the main shell, 1 for its children, and so on */ | ||
| 140 | static int shlvl; | ||
| 141 | #define rootshell (!shlvl) | ||
| 142 | /* trap handler commands */ | ||
| 143 | static char *trap[NSIG]; | ||
| 144 | static smallint isloginsh; | ||
| 145 | /* current value of signal */ | ||
| 146 | static char sigmode[NSIG - 1]; | ||
| 147 | /* indicates specified signal received */ | ||
| 148 | static char gotsig[NSIG - 1]; | ||
| 149 | static char *arg0; /* value of $0 */ | ||
| 150 | |||
| 151 | |||
| 152 | /* ============ Interrupts / exceptions */ | ||
| 153 | |||
| 154 | /* | 141 | /* |
| 155 | * We enclose jmp_buf in a structure so that we can declare pointers to | 142 | * We enclose jmp_buf in a structure so that we can declare pointers to |
| 156 | * jump locations. The global variable handler contains the location to | 143 | * jump locations. The global variable handler contains the location to |
| @@ -163,34 +150,84 @@ static char *arg0; /* value of $0 */ | |||
| 163 | struct jmploc { | 150 | struct jmploc { |
| 164 | jmp_buf loc; | 151 | jmp_buf loc; |
| 165 | }; | 152 | }; |
| 166 | static struct jmploc *exception_handler; | 153 | |
| 167 | static int exception; | 154 | struct globals_misc { |
| 168 | /* exceptions */ | 155 | /* pid of main shell */ |
| 156 | int rootpid; | ||
| 157 | /* shell level: 0 for the main shell, 1 for its children, and so on */ | ||
| 158 | int shlvl; | ||
| 159 | #define rootshell (!shlvl) | ||
| 160 | char *minusc; /* argument to -c option */ | ||
| 161 | |||
| 162 | char *curdir; // = nullstr; /* current working directory */ | ||
| 163 | char *physdir; // = nullstr; /* physical working directory */ | ||
| 164 | |||
| 165 | char *arg0; /* value of $0 */ | ||
| 166 | |||
| 167 | struct jmploc *exception_handler; | ||
| 168 | int exception; | ||
| 169 | /* exceptions */ | ||
| 169 | #define EXINT 0 /* SIGINT received */ | 170 | #define EXINT 0 /* SIGINT received */ |
| 170 | #define EXERROR 1 /* a generic error */ | 171 | #define EXERROR 1 /* a generic error */ |
| 171 | #define EXSHELLPROC 2 /* execute a shell procedure */ | 172 | #define EXSHELLPROC 2 /* execute a shell procedure */ |
| 172 | #define EXEXEC 3 /* command execution failed */ | 173 | #define EXEXEC 3 /* command execution failed */ |
| 173 | #define EXEXIT 4 /* exit the shell */ | 174 | #define EXEXIT 4 /* exit the shell */ |
| 174 | #define EXSIG 5 /* trapped signal in wait(1) */ | 175 | #define EXSIG 5 /* trapped signal in wait(1) */ |
| 175 | static volatile int suppressint; | 176 | volatile int suppressint; |
| 176 | static volatile sig_atomic_t intpending; | 177 | volatile sig_atomic_t intpending; |
| 177 | /* do we generate EXSIG events */ | 178 | /* do we generate EXSIG events */ |
| 178 | static int exsig; | 179 | int exsig; |
| 179 | /* last pending signal */ | 180 | /* last pending signal */ |
| 180 | static volatile sig_atomic_t pendingsig; | 181 | volatile sig_atomic_t pendingsig; |
| 181 | 182 | ||
| 182 | /* | 183 | /* trap handler commands */ |
| 183 | * Sigmode records the current value of the signal handlers for the various | 184 | char *trap[NSIG]; |
| 184 | * modes. A value of zero means that the current handler is not known. | 185 | smallint isloginsh; |
| 185 | * S_HARD_IGN indicates that the signal was ignored on entry to the shell, | 186 | char nullstr[1]; /* zero length string */ |
| 186 | */ | 187 | /* |
| 187 | 188 | * Sigmode records the current value of the signal handlers for the various | |
| 189 | * modes. A value of zero means that the current handler is not known. | ||
| 190 | * S_HARD_IGN indicates that the signal was ignored on entry to the shell, | ||
| 191 | */ | ||
| 192 | char sigmode[NSIG - 1]; | ||
| 188 | #define S_DFL 1 /* default signal handling (SIG_DFL) */ | 193 | #define S_DFL 1 /* default signal handling (SIG_DFL) */ |
| 189 | #define S_CATCH 2 /* signal is caught */ | 194 | #define S_CATCH 2 /* signal is caught */ |
| 190 | #define S_IGN 3 /* signal is ignored (SIG_IGN) */ | 195 | #define S_IGN 3 /* signal is ignored (SIG_IGN) */ |
| 191 | #define S_HARD_IGN 4 /* signal is ignored permenantly */ | 196 | #define S_HARD_IGN 4 /* signal is ignored permenantly */ |
| 192 | #define S_RESET 5 /* temporary - to reset a hard ignored sig */ | 197 | #define S_RESET 5 /* temporary - to reset a hard ignored sig */ |
| 193 | 198 | ||
| 199 | /* indicates specified signal received */ | ||
| 200 | char gotsig[NSIG - 1]; | ||
| 201 | }; | ||
| 202 | /* Make it reside in writable memory, yet make compiler understand that it is not going to change. */ | ||
| 203 | static struct globals_misc *const ptr_to_globals_misc __attribute__ ((section (".data"))); | ||
| 204 | #define G_misc (*ptr_to_globals_misc) | ||
| 205 | #define rootpid (G_misc.rootpid ) | ||
| 206 | #define shlvl (G_misc.shlvl ) | ||
| 207 | #define minusc (G_misc.minusc ) | ||
| 208 | #define curdir (G_misc.curdir ) | ||
| 209 | #define physdir (G_misc.physdir ) | ||
| 210 | #define arg0 (G_misc.arg0 ) | ||
| 211 | #define exception_handler (G_misc.exception_handler) | ||
| 212 | #define exception (G_misc.exception ) | ||
| 213 | #define suppressint (G_misc.suppressint ) | ||
| 214 | #define intpending (G_misc.intpending ) | ||
| 215 | #define exsig (G_misc.exsig ) | ||
| 216 | #define pendingsig (G_misc.pendingsig ) | ||
| 217 | #define trap (G_misc.trap ) | ||
| 218 | #define isloginsh (G_misc.isloginsh) | ||
| 219 | #define nullstr (G_misc.nullstr ) | ||
| 220 | #define sigmode (G_misc.sigmode ) | ||
| 221 | #define gotsig (G_misc.gotsig ) | ||
| 222 | #define INIT_G_misc() do { \ | ||
| 223 | (*(struct globals_misc**)&ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \ | ||
| 224 | curdir = nullstr; \ | ||
| 225 | physdir = nullstr; \ | ||
| 226 | } while (0) | ||
| 227 | |||
| 228 | |||
| 229 | /* ============ Interrupts / exceptions */ | ||
| 230 | |||
| 194 | /* | 231 | /* |
| 195 | * These macros allow the user to suspend the handling of interrupt signals | 232 | * These macros allow the user to suspend the handling of interrupt signals |
| 196 | * over a period of time. This is similar to SIGHOLD to or sigblock, but | 233 | * over a period of time. This is similar to SIGHOLD to or sigblock, but |
| @@ -1090,7 +1127,7 @@ enum { | |||
| 1090 | * on many machines. */ | 1127 | * on many machines. */ |
| 1091 | SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1, | 1128 | SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1, |
| 1092 | /* Minimum size of a block */ | 1129 | /* Minimum size of a block */ |
| 1093 | MINSIZE = SHELL_ALIGN(504), | 1130 | MINSIZE = SHELL_ALIGN(504), |
| 1094 | }; | 1131 | }; |
| 1095 | 1132 | ||
| 1096 | struct stack_block { | 1133 | struct stack_block { |
| @@ -1105,16 +1142,38 @@ struct stackmark { | |||
| 1105 | struct stackmark *marknext; | 1142 | struct stackmark *marknext; |
| 1106 | }; | 1143 | }; |
| 1107 | 1144 | ||
| 1108 | static struct stack_block stackbase; | ||
| 1109 | static struct stack_block *stackp = &stackbase; | ||
| 1110 | static struct stackmark *markp; | ||
| 1111 | static char *stacknxt = stackbase.space; | ||
| 1112 | static size_t stacknleft = MINSIZE; | ||
| 1113 | static char *sstrend = stackbase.space + MINSIZE; | ||
| 1114 | static int herefd = -1; | ||
| 1115 | 1145 | ||
| 1116 | #define stackblock() ((void *)stacknxt) | 1146 | struct globals_memstack { |
| 1117 | #define stackblocksize() stacknleft | 1147 | struct stack_block *g_stackp; // = &stackbase; |
| 1148 | struct stackmark *markp; | ||
| 1149 | char *g_stacknxt; // = stackbase.space; | ||
| 1150 | char *sstrend; // = stackbase.space + MINSIZE; | ||
| 1151 | size_t g_stacknleft; // = MINSIZE; | ||
| 1152 | int herefd; // = -1; | ||
| 1153 | struct stack_block stackbase; | ||
| 1154 | }; | ||
| 1155 | /* Make it reside in writable memory, yet make compiler understand that it is not going to change. */ | ||
| 1156 | static struct globals_memstack *const ptr_to_globals_memstack __attribute__ ((section (".data"))); | ||
| 1157 | #define G_memstack (*ptr_to_globals_memstack) | ||
| 1158 | #define g_stackp (G_memstack.g_stackp ) | ||
| 1159 | #define markp (G_memstack.markp ) | ||
| 1160 | #define g_stacknxt (G_memstack.g_stacknxt ) | ||
| 1161 | #define sstrend (G_memstack.sstrend ) | ||
| 1162 | #define g_stacknleft (G_memstack.g_stacknleft) | ||
| 1163 | #define herefd (G_memstack.herefd ) | ||
| 1164 | #define stackbase (G_memstack.stackbase ) | ||
| 1165 | #define INIT_G_memstack() do { \ | ||
| 1166 | (*(struct globals_memstack**)&ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \ | ||
| 1167 | g_stackp = &stackbase; \ | ||
| 1168 | g_stacknxt = stackbase.space; \ | ||
| 1169 | g_stacknleft = MINSIZE; \ | ||
| 1170 | sstrend = stackbase.space + MINSIZE; \ | ||
| 1171 | herefd = -1; \ | ||
| 1172 | } while (0) | ||
| 1173 | |||
| 1174 | #define stackblock() ((void *)g_stacknxt) | ||
| 1175 | #define stackblocksize() g_stacknleft | ||
| 1176 | |||
| 1118 | 1177 | ||
| 1119 | static void * | 1178 | static void * |
| 1120 | ckrealloc(void * p, size_t nbytes) | 1179 | ckrealloc(void * p, size_t nbytes) |
| @@ -1158,7 +1217,7 @@ stalloc(size_t nbytes) | |||
| 1158 | size_t aligned; | 1217 | size_t aligned; |
| 1159 | 1218 | ||
| 1160 | aligned = SHELL_ALIGN(nbytes); | 1219 | aligned = SHELL_ALIGN(nbytes); |
| 1161 | if (aligned > stacknleft) { | 1220 | if (aligned > g_stacknleft) { |
| 1162 | size_t len; | 1221 | size_t len; |
| 1163 | size_t blocksize; | 1222 | size_t blocksize; |
| 1164 | struct stack_block *sp; | 1223 | struct stack_block *sp; |
| @@ -1171,16 +1230,16 @@ stalloc(size_t nbytes) | |||
| 1171 | ash_msg_and_raise_error(bb_msg_memory_exhausted); | 1230 | ash_msg_and_raise_error(bb_msg_memory_exhausted); |
| 1172 | INT_OFF; | 1231 | INT_OFF; |
| 1173 | sp = ckmalloc(len); | 1232 | sp = ckmalloc(len); |
| 1174 | sp->prev = stackp; | 1233 | sp->prev = g_stackp; |
| 1175 | stacknxt = sp->space; | 1234 | g_stacknxt = sp->space; |
| 1176 | stacknleft = blocksize; | 1235 | g_stacknleft = blocksize; |
| 1177 | sstrend = stacknxt + blocksize; | 1236 | sstrend = g_stacknxt + blocksize; |
| 1178 | stackp = sp; | 1237 | g_stackp = sp; |
| 1179 | INT_ON; | 1238 | INT_ON; |
| 1180 | } | 1239 | } |
| 1181 | p = stacknxt; | 1240 | p = g_stacknxt; |
| 1182 | stacknxt += aligned; | 1241 | g_stacknxt += aligned; |
| 1183 | stacknleft -= aligned; | 1242 | g_stacknleft -= aligned; |
| 1184 | return p; | 1243 | return p; |
| 1185 | } | 1244 | } |
| 1186 | 1245 | ||
| @@ -1188,13 +1247,13 @@ static void | |||
| 1188 | stunalloc(void *p) | 1247 | stunalloc(void *p) |
| 1189 | { | 1248 | { |
| 1190 | #if DEBUG | 1249 | #if DEBUG |
| 1191 | if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) { | 1250 | if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) { |
| 1192 | write(2, "stunalloc\n", 10); | 1251 | write(2, "stunalloc\n", 10); |
| 1193 | abort(); | 1252 | abort(); |
| 1194 | } | 1253 | } |
| 1195 | #endif | 1254 | #endif |
| 1196 | stacknleft += stacknxt - (char *)p; | 1255 | g_stacknleft += g_stacknxt - (char *)p; |
| 1197 | stacknxt = p; | 1256 | g_stacknxt = p; |
| 1198 | } | 1257 | } |
| 1199 | 1258 | ||
| 1200 | /* | 1259 | /* |
| @@ -1210,9 +1269,9 @@ ststrdup(const char *p) | |||
| 1210 | static void | 1269 | static void |
| 1211 | setstackmark(struct stackmark *mark) | 1270 | setstackmark(struct stackmark *mark) |
| 1212 | { | 1271 | { |
| 1213 | mark->stackp = stackp; | 1272 | mark->stackp = g_stackp; |
| 1214 | mark->stacknxt = stacknxt; | 1273 | mark->stacknxt = g_stacknxt; |
| 1215 | mark->stacknleft = stacknleft; | 1274 | mark->stacknleft = g_stacknleft; |
| 1216 | mark->marknext = markp; | 1275 | mark->marknext = markp; |
| 1217 | markp = mark; | 1276 | markp = mark; |
| 1218 | } | 1277 | } |
| @@ -1227,13 +1286,13 @@ popstackmark(struct stackmark *mark) | |||
| 1227 | 1286 | ||
| 1228 | INT_OFF; | 1287 | INT_OFF; |
| 1229 | markp = mark->marknext; | 1288 | markp = mark->marknext; |
| 1230 | while (stackp != mark->stackp) { | 1289 | while (g_stackp != mark->stackp) { |
| 1231 | sp = stackp; | 1290 | sp = g_stackp; |
| 1232 | stackp = sp->prev; | 1291 | g_stackp = sp->prev; |
| 1233 | free(sp); | 1292 | free(sp); |
| 1234 | } | 1293 | } |
| 1235 | stacknxt = mark->stacknxt; | 1294 | g_stacknxt = mark->stacknxt; |
| 1236 | stacknleft = mark->stacknleft; | 1295 | g_stacknleft = mark->stacknleft; |
| 1237 | sstrend = mark->stacknxt + mark->stacknleft; | 1296 | sstrend = mark->stacknxt + mark->stacknleft; |
| 1238 | INT_ON; | 1297 | INT_ON; |
| 1239 | } | 1298 | } |
| @@ -1252,13 +1311,13 @@ growstackblock(void) | |||
| 1252 | { | 1311 | { |
| 1253 | size_t newlen; | 1312 | size_t newlen; |
| 1254 | 1313 | ||
| 1255 | newlen = stacknleft * 2; | 1314 | newlen = g_stacknleft * 2; |
| 1256 | if (newlen < stacknleft) | 1315 | if (newlen < g_stacknleft) |
| 1257 | ash_msg_and_raise_error(bb_msg_memory_exhausted); | 1316 | ash_msg_and_raise_error(bb_msg_memory_exhausted); |
| 1258 | if (newlen < 128) | 1317 | if (newlen < 128) |
| 1259 | newlen += 128; | 1318 | newlen += 128; |
| 1260 | 1319 | ||
| 1261 | if (stacknxt == stackp->space && stackp != &stackbase) { | 1320 | if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) { |
| 1262 | struct stack_block *oldstackp; | 1321 | struct stack_block *oldstackp; |
| 1263 | struct stackmark *xmark; | 1322 | struct stackmark *xmark; |
| 1264 | struct stack_block *sp; | 1323 | struct stack_block *sp; |
| @@ -1266,15 +1325,15 @@ growstackblock(void) | |||
| 1266 | size_t grosslen; | 1325 | size_t grosslen; |
| 1267 | 1326 | ||
| 1268 | INT_OFF; | 1327 | INT_OFF; |
| 1269 | oldstackp = stackp; | 1328 | oldstackp = g_stackp; |
| 1270 | sp = stackp; | 1329 | sp = g_stackp; |
| 1271 | prevstackp = sp->prev; | 1330 | prevstackp = sp->prev; |
| 1272 | grosslen = newlen + sizeof(struct stack_block) - MINSIZE; | 1331 | grosslen = newlen + sizeof(struct stack_block) - MINSIZE; |
| 1273 | sp = ckrealloc(sp, grosslen); | 1332 | sp = ckrealloc(sp, grosslen); |
| 1274 | sp->prev = prevstackp; | 1333 | sp->prev = prevstackp; |
| 1275 | stackp = sp; | 1334 | g_stackp = sp; |
| 1276 | stacknxt = sp->space; | 1335 | g_stacknxt = sp->space; |
| 1277 | stacknleft = newlen; | 1336 | g_stacknleft = newlen; |
| 1278 | sstrend = sp->space + newlen; | 1337 | sstrend = sp->space + newlen; |
| 1279 | 1338 | ||
| 1280 | /* | 1339 | /* |
| @@ -1283,20 +1342,20 @@ growstackblock(void) | |||
| 1283 | */ | 1342 | */ |
| 1284 | xmark = markp; | 1343 | xmark = markp; |
| 1285 | while (xmark != NULL && xmark->stackp == oldstackp) { | 1344 | while (xmark != NULL && xmark->stackp == oldstackp) { |
| 1286 | xmark->stackp = stackp; | 1345 | xmark->stackp = g_stackp; |
| 1287 | xmark->stacknxt = stacknxt; | 1346 | xmark->stacknxt = g_stacknxt; |
| 1288 | xmark->stacknleft = stacknleft; | 1347 | xmark->stacknleft = g_stacknleft; |
| 1289 | xmark = xmark->marknext; | 1348 | xmark = xmark->marknext; |
| 1290 | } | 1349 | } |
| 1291 | INT_ON; | 1350 | INT_ON; |
| 1292 | } else { | 1351 | } else { |
| 1293 | char *oldspace = stacknxt; | 1352 | char *oldspace = g_stacknxt; |
| 1294 | int oldlen = stacknleft; | 1353 | int oldlen = g_stacknleft; |
| 1295 | char *p = stalloc(newlen); | 1354 | char *p = stalloc(newlen); |
| 1296 | 1355 | ||
| 1297 | /* free the space we just allocated */ | 1356 | /* free the space we just allocated */ |
| 1298 | stacknxt = memcpy(p, oldspace, oldlen); | 1357 | g_stacknxt = memcpy(p, oldspace, oldlen); |
| 1299 | stacknleft += newlen; | 1358 | g_stacknleft += newlen; |
| 1300 | } | 1359 | } |
| 1301 | } | 1360 | } |
| 1302 | 1361 | ||
| @@ -1304,8 +1363,8 @@ static void | |||
| 1304 | grabstackblock(size_t len) | 1363 | grabstackblock(size_t len) |
| 1305 | { | 1364 | { |
| 1306 | len = SHELL_ALIGN(len); | 1365 | len = SHELL_ALIGN(len); |
| 1307 | stacknxt += len; | 1366 | g_stacknxt += len; |
| 1308 | stacknleft -= len; | 1367 | g_stacknleft -= len; |
| 1309 | } | 1368 | } |
| 1310 | 1369 | ||
| 1311 | /* | 1370 | /* |
| @@ -1343,7 +1402,7 @@ growstackstr(void) | |||
| 1343 | static char * | 1402 | static char * |
| 1344 | makestrspace(size_t newlen, char *p) | 1403 | makestrspace(size_t newlen, char *p) |
| 1345 | { | 1404 | { |
| 1346 | size_t len = p - stacknxt; | 1405 | size_t len = p - g_stacknxt; |
| 1347 | size_t size = stackblocksize(); | 1406 | size_t size = stackblocksize(); |
| 1348 | 1407 | ||
| 1349 | for (;;) { | 1408 | for (;;) { |
| @@ -1568,41 +1627,26 @@ static unsigned long rseed; | |||
| 1568 | 1627 | ||
| 1569 | /* ============ Shell variables */ | 1628 | /* ============ Shell variables */ |
| 1570 | 1629 | ||
| 1571 | /* flags */ | 1630 | /* |
| 1572 | #define VEXPORT 0x01 /* variable is exported */ | 1631 | * The parsefile structure pointed to by the global variable parsefile |
| 1573 | #define VREADONLY 0x02 /* variable cannot be modified */ | 1632 | * contains information about the current file being read. |
| 1574 | #define VSTRFIXED 0x04 /* variable struct is statically allocated */ | 1633 | */ |
| 1575 | #define VTEXTFIXED 0x08 /* text is statically allocated */ | 1634 | struct redirtab { |
| 1576 | #define VSTACK 0x10 /* text is allocated on the stack */ | 1635 | struct redirtab *next; |
| 1577 | #define VUNSET 0x20 /* the variable is not set */ | 1636 | int renamed[10]; |
| 1578 | #define VNOFUNC 0x40 /* don't call the callback function */ | 1637 | int nullredirs; |
| 1579 | #define VNOSET 0x80 /* do not set variable - just readonly test */ | 1638 | }; |
| 1580 | #define VNOSAVE 0x100 /* when text is on the heap before setvareq */ | ||
| 1581 | #ifdef DYNAMIC_VAR | ||
| 1582 | # define VDYNAMIC 0x200 /* dynamic variable */ | ||
| 1583 | #else | ||
| 1584 | # define VDYNAMIC 0 | ||
| 1585 | #endif | ||
| 1586 | |||
| 1587 | #ifdef IFS_BROKEN | ||
| 1588 | static const char defifsvar[] ALIGN1 = "IFS= \t\n"; | ||
| 1589 | #define defifs (defifsvar + 4) | ||
| 1590 | #else | ||
| 1591 | static const char defifs[] ALIGN1 = " \t\n"; | ||
| 1592 | #endif | ||
| 1593 | 1639 | ||
| 1594 | struct shparam { | 1640 | struct shparam { |
| 1595 | int nparam; /* # of positional parameters (without $0) */ | 1641 | int nparam; /* # of positional parameters (without $0) */ |
| 1596 | unsigned char malloc; /* if parameter list dynamically allocated */ | ||
| 1597 | char **p; /* parameter list */ | ||
| 1598 | #if ENABLE_ASH_GETOPTS | 1642 | #if ENABLE_ASH_GETOPTS |
| 1599 | int optind; /* next parameter to be processed by getopts */ | 1643 | int optind; /* next parameter to be processed by getopts */ |
| 1600 | int optoff; /* used by getopts */ | 1644 | int optoff; /* used by getopts */ |
| 1601 | #endif | 1645 | #endif |
| 1646 | unsigned char malloced; /* if parameter list dynamically allocated */ | ||
| 1647 | char **p; /* parameter list */ | ||
| 1602 | }; | 1648 | }; |
| 1603 | 1649 | ||
| 1604 | static struct shparam shellparam; /* $@ current positional parameters */ | ||
| 1605 | |||
| 1606 | /* | 1650 | /* |
| 1607 | * Free the list of positional parameters. | 1651 | * Free the list of positional parameters. |
| 1608 | */ | 1652 | */ |
| @@ -1611,7 +1655,7 @@ freeparam(volatile struct shparam *param) | |||
| 1611 | { | 1655 | { |
| 1612 | char **ap; | 1656 | char **ap; |
| 1613 | 1657 | ||
| 1614 | if (param->malloc) { | 1658 | if (param->malloced) { |
| 1615 | for (ap = param->p; *ap; ap++) | 1659 | for (ap = param->p; *ap; ap++) |
| 1616 | free(*ap); | 1660 | free(*ap); |
| 1617 | free(param->p); | 1661 | free(param->p); |
| @@ -1619,12 +1663,7 @@ freeparam(volatile struct shparam *param) | |||
| 1619 | } | 1663 | } |
| 1620 | 1664 | ||
| 1621 | #if ENABLE_ASH_GETOPTS | 1665 | #if ENABLE_ASH_GETOPTS |
| 1622 | static void | 1666 | static void getoptsreset(const char *value); |
| 1623 | getoptsreset(const char *value) | ||
| 1624 | { | ||
| 1625 | shellparam.optind = number(value); | ||
| 1626 | shellparam.optoff = -1; | ||
| 1627 | } | ||
| 1628 | #endif | 1667 | #endif |
| 1629 | 1668 | ||
| 1630 | struct var { | 1669 | struct var { |
| @@ -1642,7 +1681,31 @@ struct localvar { | |||
| 1642 | const char *text; /* saved text */ | 1681 | const char *text; /* saved text */ |
| 1643 | }; | 1682 | }; |
| 1644 | 1683 | ||
| 1645 | /* Forward decls for varinit[] */ | 1684 | /* flags */ |
| 1685 | #define VEXPORT 0x01 /* variable is exported */ | ||
| 1686 | #define VREADONLY 0x02 /* variable cannot be modified */ | ||
| 1687 | #define VSTRFIXED 0x04 /* variable struct is statically allocated */ | ||
| 1688 | #define VTEXTFIXED 0x08 /* text is statically allocated */ | ||
| 1689 | #define VSTACK 0x10 /* text is allocated on the stack */ | ||
| 1690 | #define VUNSET 0x20 /* the variable is not set */ | ||
| 1691 | #define VNOFUNC 0x40 /* don't call the callback function */ | ||
| 1692 | #define VNOSET 0x80 /* do not set variable - just readonly test */ | ||
| 1693 | #define VNOSAVE 0x100 /* when text is on the heap before setvareq */ | ||
| 1694 | #ifdef DYNAMIC_VAR | ||
| 1695 | # define VDYNAMIC 0x200 /* dynamic variable */ | ||
| 1696 | #else | ||
| 1697 | # define VDYNAMIC 0 | ||
| 1698 | #endif | ||
| 1699 | |||
| 1700 | #ifdef IFS_BROKEN | ||
| 1701 | static const char defifsvar[] ALIGN1 = "IFS= \t\n"; | ||
| 1702 | #define defifs (defifsvar + 4) | ||
| 1703 | #else | ||
| 1704 | static const char defifs[] ALIGN1 = " \t\n"; | ||
| 1705 | #endif | ||
| 1706 | |||
| 1707 | |||
| 1708 | /* Need to be before varinit_data[] */ | ||
| 1646 | #if ENABLE_LOCALE_SUPPORT | 1709 | #if ENABLE_LOCALE_SUPPORT |
| 1647 | static void | 1710 | static void |
| 1648 | change_lc_all(const char *value) | 1711 | change_lc_all(const char *value) |
| @@ -1666,46 +1729,78 @@ static void changepath(const char *); | |||
| 1666 | static void change_random(const char *); | 1729 | static void change_random(const char *); |
| 1667 | #endif | 1730 | #endif |
| 1668 | 1731 | ||
| 1669 | static struct var varinit[] = { | 1732 | static const struct { |
| 1733 | int flags; | ||
| 1734 | const char *text; | ||
| 1735 | void (*func)(const char *); | ||
| 1736 | } varinit_data[] = { | ||
| 1670 | #ifdef IFS_BROKEN | 1737 | #ifdef IFS_BROKEN |
| 1671 | { NULL, VSTRFIXED|VTEXTFIXED, defifsvar, NULL }, | 1738 | { VSTRFIXED|VTEXTFIXED , defifsvar , NULL }, |
| 1672 | #else | 1739 | #else |
| 1673 | { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", NULL }, | 1740 | { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0" , NULL }, |
| 1674 | #endif | 1741 | #endif |
| 1675 | #if ENABLE_ASH_MAIL | 1742 | #if ENABLE_ASH_MAIL |
| 1676 | { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail }, | 1743 | { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0" , changemail }, |
| 1677 | { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail }, | 1744 | { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail }, |
| 1678 | #endif | 1745 | #endif |
| 1679 | { NULL, VSTRFIXED|VTEXTFIXED, bb_PATH_root_path, changepath }, | 1746 | { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath }, |
| 1680 | { NULL, VSTRFIXED|VTEXTFIXED, "PS1=$ ", NULL }, | 1747 | { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL }, |
| 1681 | { NULL, VSTRFIXED|VTEXTFIXED, "PS2=> ", NULL }, | 1748 | { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL }, |
| 1682 | { NULL, VSTRFIXED|VTEXTFIXED, "PS4=+ ", NULL }, | 1749 | { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL }, |
| 1683 | #if ENABLE_ASH_GETOPTS | 1750 | #if ENABLE_ASH_GETOPTS |
| 1684 | { NULL, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset }, | 1751 | { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset }, |
| 1685 | #endif | 1752 | #endif |
| 1686 | #if ENABLE_ASH_RANDOM_SUPPORT | 1753 | #if ENABLE_ASH_RANDOM_SUPPORT |
| 1687 | { NULL, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random }, | 1754 | { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random }, |
| 1688 | #endif | 1755 | #endif |
| 1689 | #if ENABLE_LOCALE_SUPPORT | 1756 | #if ENABLE_LOCALE_SUPPORT |
| 1690 | { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all }, | 1757 | { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0" , change_lc_all }, |
| 1691 | { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype }, | 1758 | { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype }, |
| 1692 | #endif | 1759 | #endif |
| 1693 | #if ENABLE_FEATURE_EDITING_SAVEHISTORY | 1760 | #if ENABLE_FEATURE_EDITING_SAVEHISTORY |
| 1694 | { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL }, | 1761 | { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL }, |
| 1695 | #endif | 1762 | #endif |
| 1696 | }; | 1763 | }; |
| 1697 | 1764 | ||
| 1698 | #define vifs varinit[0] | 1765 | |
| 1766 | struct globals_var { | ||
| 1767 | struct shparam shellparam; /* $@ current positional parameters */ | ||
| 1768 | struct redirtab *redirlist; | ||
| 1769 | int g_nullredirs; | ||
| 1770 | int preverrout_fd; /* save fd2 before print debug if xflag is set. */ | ||
| 1771 | struct var *vartab[VTABSIZE]; | ||
| 1772 | struct var varinit[ARRAY_SIZE(varinit_data)]; | ||
| 1773 | }; | ||
| 1774 | /* Make it reside in writable memory, yet make compiler understand that it is not going to change. */ | ||
| 1775 | static struct globals_var *const ptr_to_globals_var __attribute__ ((section (".data"))); | ||
| 1776 | #define G_var (*ptr_to_globals_var) | ||
| 1777 | #define shellparam (G_var.shellparam ) | ||
| 1778 | #define redirlist (G_var.redirlist ) | ||
| 1779 | #define g_nullredirs (G_var.g_nullredirs ) | ||
| 1780 | #define preverrout_fd (G_var.preverrout_fd) | ||
| 1781 | #define vartab (G_var.vartab ) | ||
| 1782 | #define varinit (G_var.varinit ) | ||
| 1783 | #define INIT_G_var() do { \ | ||
| 1784 | int i; \ | ||
| 1785 | (*(struct globals_var**)&ptr_to_globals_var) = xzalloc(sizeof(G_var)); \ | ||
| 1786 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ | ||
| 1787 | varinit[i].flags = varinit_data[i].flags; \ | ||
| 1788 | varinit[i].text = varinit_data[i].text; \ | ||
| 1789 | varinit[i].func = varinit_data[i].func; \ | ||
| 1790 | } \ | ||
| 1791 | } while (0) | ||
| 1792 | |||
| 1793 | #define vifs varinit[0] | ||
| 1699 | #if ENABLE_ASH_MAIL | 1794 | #if ENABLE_ASH_MAIL |
| 1700 | #define vmail (&vifs)[1] | 1795 | #define vmail (&vifs)[1] |
| 1701 | #define vmpath (&vmail)[1] | 1796 | #define vmpath (&vmail)[1] |
| 1702 | #else | 1797 | #else |
| 1703 | #define vmpath vifs | 1798 | #define vmpath vifs |
| 1704 | #endif | 1799 | #endif |
| 1705 | #define vpath (&vmpath)[1] | 1800 | #define vpath (&vmpath)[1] |
| 1706 | #define vps1 (&vpath)[1] | 1801 | #define vps1 (&vpath)[1] |
| 1707 | #define vps2 (&vps1)[1] | 1802 | #define vps2 (&vps1)[1] |
| 1708 | #define vps4 (&vps2)[1] | 1803 | #define vps4 (&vps2)[1] |
| 1709 | #define voptind (&vps4)[1] | 1804 | #define voptind (&vps4)[1] |
| 1710 | #if ENABLE_ASH_GETOPTS | 1805 | #if ENABLE_ASH_GETOPTS |
| 1711 | #define vrandom (&voptind)[1] | 1806 | #define vrandom (&voptind)[1] |
| @@ -1730,27 +1825,19 @@ static struct var varinit[] = { | |||
| 1730 | 1825 | ||
| 1731 | #define mpathset() ((vmpath.flags & VUNSET) == 0) | 1826 | #define mpathset() ((vmpath.flags & VUNSET) == 0) |
| 1732 | 1827 | ||
| 1733 | /* | ||
| 1734 | * The parsefile structure pointed to by the global variable parsefile | ||
| 1735 | * contains information about the current file being read. | ||
| 1736 | */ | ||
| 1737 | struct redirtab { | ||
| 1738 | struct redirtab *next; | ||
| 1739 | int renamed[10]; | ||
| 1740 | int nullredirs; | ||
| 1741 | }; | ||
| 1742 | |||
| 1743 | static struct redirtab *redirlist; | ||
| 1744 | static int nullredirs; | ||
| 1745 | static int preverrout_fd; /* save fd2 before print debug if xflag is set. */ | ||
| 1746 | |||
| 1747 | #define VTABSIZE 39 | ||
| 1748 | |||
| 1749 | static struct var *vartab[VTABSIZE]; | ||
| 1750 | 1828 | ||
| 1751 | #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c))) | 1829 | #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c))) |
| 1752 | #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c))) | 1830 | #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c))) |
| 1753 | 1831 | ||
| 1832 | #if ENABLE_ASH_GETOPTS | ||
| 1833 | static void | ||
| 1834 | getoptsreset(const char *value) | ||
| 1835 | { | ||
| 1836 | shellparam.optind = number(value); | ||
| 1837 | shellparam.optoff = -1; | ||
| 1838 | } | ||
| 1839 | #endif | ||
| 1840 | |||
| 1754 | /* | 1841 | /* |
| 1755 | * Return of a legal variable name (a letter or underscore followed by zero or | 1842 | * Return of a legal variable name (a letter or underscore followed by zero or |
| 1756 | * more letters, underscores, and digits). | 1843 | * more letters, underscores, and digits). |
| @@ -2221,9 +2308,6 @@ setprompt(int whichprompt) | |||
| 2221 | 2308 | ||
| 2222 | static int docd(const char *, int); | 2309 | static int docd(const char *, int); |
| 2223 | 2310 | ||
| 2224 | static char *curdir = nullstr; /* current working directory */ | ||
| 2225 | static char *physdir = nullstr; /* physical working directory */ | ||
| 2226 | |||
| 2227 | static int | 2311 | static int |
| 2228 | cdopt(void) | 2312 | cdopt(void) |
| 2229 | { | 2313 | { |
| @@ -2310,7 +2394,7 @@ updatepwd(const char *dir) | |||
| 2310 | static char * | 2394 | static char * |
| 2311 | getpwd(void) | 2395 | getpwd(void) |
| 2312 | { | 2396 | { |
| 2313 | char *dir = getcwd(0, 0); | 2397 | char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */ |
| 2314 | return dir ? dir : nullstr; | 2398 | return dir ? dir : nullstr; |
| 2315 | } | 2399 | } |
| 2316 | 2400 | ||
| @@ -2903,8 +2987,6 @@ static const char syntax_index_table[258] = { | |||
| 2903 | #define ALIASINUSE 1 | 2987 | #define ALIASINUSE 1 |
| 2904 | #define ALIASDEAD 2 | 2988 | #define ALIASDEAD 2 |
| 2905 | 2989 | ||
| 2906 | #define ATABSIZE 39 | ||
| 2907 | |||
| 2908 | struct alias { | 2990 | struct alias { |
| 2909 | struct alias *next; | 2991 | struct alias *next; |
| 2910 | char *name; | 2992 | char *name; |
| @@ -2912,7 +2994,12 @@ struct alias { | |||
| 2912 | int flag; | 2994 | int flag; |
| 2913 | }; | 2995 | }; |
| 2914 | 2996 | ||
| 2915 | static struct alias *atab[ATABSIZE]; | 2997 | |
| 2998 | static struct alias **atab; // [ATABSIZE]; | ||
| 2999 | #define INIT_G_alias() do { \ | ||
| 3000 | atab = xzalloc(ATABSIZE * sizeof(atab[0])); \ | ||
| 3001 | } while (0) | ||
| 3002 | |||
| 2916 | 3003 | ||
| 2917 | static struct alias ** | 3004 | static struct alias ** |
| 2918 | __lookupalias(const char *name) { | 3005 | __lookupalias(const char *name) { |
| @@ -4797,7 +4884,7 @@ redirect(union node *redir, int flags) | |||
| 4797 | int fd; | 4884 | int fd; |
| 4798 | int newfd; | 4885 | int newfd; |
| 4799 | 4886 | ||
| 4800 | nullredirs++; | 4887 | g_nullredirs++; |
| 4801 | if (!redir) { | 4888 | if (!redir) { |
| 4802 | return; | 4889 | return; |
| 4803 | } | 4890 | } |
| @@ -4807,10 +4894,10 @@ redirect(union node *redir, int flags) | |||
| 4807 | sv = ckmalloc(sizeof(*sv)); | 4894 | sv = ckmalloc(sizeof(*sv)); |
| 4808 | sv->next = redirlist; | 4895 | sv->next = redirlist; |
| 4809 | redirlist = sv; | 4896 | redirlist = sv; |
| 4810 | sv->nullredirs = nullredirs - 1; | 4897 | sv->nullredirs = g_nullredirs - 1; |
| 4811 | for (i = 0; i < 10; i++) | 4898 | for (i = 0; i < 10; i++) |
| 4812 | sv->renamed[i] = EMPTY; | 4899 | sv->renamed[i] = EMPTY; |
| 4813 | nullredirs = 0; | 4900 | g_nullredirs = 0; |
| 4814 | } | 4901 | } |
| 4815 | n = redir; | 4902 | n = redir; |
| 4816 | do { | 4903 | do { |
| @@ -4861,7 +4948,7 @@ popredir(int drop) | |||
| 4861 | struct redirtab *rp; | 4948 | struct redirtab *rp; |
| 4862 | int i; | 4949 | int i; |
| 4863 | 4950 | ||
| 4864 | if (--nullredirs >= 0) | 4951 | if (--g_nullredirs >= 0) |
| 4865 | return; | 4952 | return; |
| 4866 | INT_OFF; | 4953 | INT_OFF; |
| 4867 | rp = redirlist; | 4954 | rp = redirlist; |
| @@ -4880,7 +4967,7 @@ popredir(int drop) | |||
| 4880 | } | 4967 | } |
| 4881 | } | 4968 | } |
| 4882 | redirlist = rp->next; | 4969 | redirlist = rp->next; |
| 4883 | nullredirs = rp->nullredirs; | 4970 | g_nullredirs = rp->nullredirs; |
| 4884 | free(rp); | 4971 | free(rp); |
| 4885 | INT_ON; | 4972 | INT_ON; |
| 4886 | } | 4973 | } |
| @@ -4896,7 +4983,7 @@ static void | |||
| 4896 | clearredir(int drop) | 4983 | clearredir(int drop) |
| 4897 | { | 4984 | { |
| 4898 | for (;;) { | 4985 | for (;;) { |
| 4899 | nullredirs = 0; | 4986 | g_nullredirs = 0; |
| 4900 | if (!redirlist) | 4987 | if (!redirlist) |
| 4901 | break; | 4988 | break; |
| 4902 | popredir(drop); | 4989 | popredir(drop); |
| @@ -6458,7 +6545,6 @@ static void find_command(char *, struct cmdentry *, int, const char *); | |||
| 6458 | * would make the command name "hash" a misnomer. | 6545 | * would make the command name "hash" a misnomer. |
| 6459 | */ | 6546 | */ |
| 6460 | 6547 | ||
| 6461 | #define CMDTABLESIZE 31 /* should be prime */ | ||
| 6462 | #define ARB 1 /* actual size determined at run time */ | 6548 | #define ARB 1 /* actual size determined at run time */ |
| 6463 | 6549 | ||
| 6464 | struct tblentry { | 6550 | struct tblentry { |
| @@ -6469,8 +6555,13 @@ struct tblentry { | |||
| 6469 | char cmdname[ARB]; /* name of command */ | 6555 | char cmdname[ARB]; /* name of command */ |
| 6470 | }; | 6556 | }; |
| 6471 | 6557 | ||
| 6472 | static struct tblentry *cmdtable[CMDTABLESIZE]; | 6558 | static struct tblentry **cmdtable; |
| 6473 | static int builtinloc = -1; /* index in path of %builtin, or -1 */ | 6559 | #define INIT_G_cmdtable() do { \ |
| 6560 | cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \ | ||
| 6561 | } while (0) | ||
| 6562 | |||
| 6563 | static int builtinloc = -1; /* index in path of %builtin, or -1 */ | ||
| 6564 | |||
| 6474 | 6565 | ||
| 6475 | static void | 6566 | static void |
| 6476 | tryexec(char *cmd, char **argv, char **envp) | 6567 | tryexec(char *cmd, char **argv, char **envp) |
| @@ -7840,7 +7931,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) | |||
| 7840 | savehandler = exception_handler; | 7931 | savehandler = exception_handler; |
| 7841 | exception_handler = &jmploc; | 7932 | exception_handler = &jmploc; |
| 7842 | localvars = NULL; | 7933 | localvars = NULL; |
| 7843 | shellparam.malloc = 0; | 7934 | shellparam.malloced = 0; |
| 7844 | func->count++; | 7935 | func->count++; |
| 7845 | funcnest++; | 7936 | funcnest++; |
| 7846 | INT_ON; | 7937 | INT_ON; |
| @@ -7851,7 +7942,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) | |||
| 7851 | shellparam.optoff = -1; | 7942 | shellparam.optoff = -1; |
| 7852 | #endif | 7943 | #endif |
| 7853 | evaltree(&func->n, flags & EV_TESTED); | 7944 | evaltree(&func->n, flags & EV_TESTED); |
| 7854 | funcdone: | 7945 | funcdone: |
| 7855 | INT_OFF; | 7946 | INT_OFF; |
| 7856 | funcnest--; | 7947 | funcnest--; |
| 7857 | freefunc(func); | 7948 | freefunc(func); |
| @@ -8979,7 +9070,7 @@ setparam(char **argv) | |||
| 8979 | } | 9070 | } |
| 8980 | *ap = NULL; | 9071 | *ap = NULL; |
| 8981 | freeparam(&shellparam); | 9072 | freeparam(&shellparam); |
| 8982 | shellparam.malloc = 1; | 9073 | shellparam.malloced = 1; |
| 8983 | shellparam.nparam = nparam; | 9074 | shellparam.nparam = nparam; |
| 8984 | shellparam.p = newparam; | 9075 | shellparam.p = newparam; |
| 8985 | #if ENABLE_ASH_GETOPTS | 9076 | #if ENABLE_ASH_GETOPTS |
| @@ -9094,7 +9185,7 @@ shiftcmd(int argc, char **argv) | |||
| 9094 | INT_OFF; | 9185 | INT_OFF; |
| 9095 | shellparam.nparam -= n; | 9186 | shellparam.nparam -= n; |
| 9096 | for (ap1 = shellparam.p; --n >= 0; ap1++) { | 9187 | for (ap1 = shellparam.p; --n >= 0; ap1++) { |
| 9097 | if (shellparam.malloc) | 9188 | if (shellparam.malloced) |
| 9098 | free(*ap1); | 9189 | free(*ap1); |
| 9099 | } | 9190 | } |
| 9100 | ap2 = shellparam.p; | 9191 | ap2 = shellparam.p; |
| @@ -10971,7 +11062,7 @@ dotcmd(int argc, char **argv) | |||
| 10971 | 11062 | ||
| 10972 | if (argc > 2) { | 11063 | if (argc > 2) { |
| 10973 | saveparam = shellparam; | 11064 | saveparam = shellparam; |
| 10974 | shellparam.malloc = 0; | 11065 | shellparam.malloced = 0; |
| 10975 | shellparam.nparam = argc - 2; | 11066 | shellparam.nparam = argc - 2; |
| 10976 | shellparam.p = argv + 2; | 11067 | shellparam.p = argv + 2; |
| 10977 | }; | 11068 | }; |
| @@ -12741,7 +12832,7 @@ procargs(int argc, char **argv) | |||
| 12741 | shellparam.optind = 1; | 12832 | shellparam.optind = 1; |
| 12742 | shellparam.optoff = -1; | 12833 | shellparam.optoff = -1; |
| 12743 | #endif | 12834 | #endif |
| 12744 | /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */ | 12835 | /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */ |
| 12745 | while (*xargv) { | 12836 | while (*xargv) { |
| 12746 | shellparam.nparam++; | 12837 | shellparam.nparam++; |
| 12747 | xargv++; | 12838 | xargv++; |
| @@ -12805,6 +12896,13 @@ int ash_main(int argc, char **argv) | |||
| 12805 | struct jmploc jmploc; | 12896 | struct jmploc jmploc; |
| 12806 | struct stackmark smark; | 12897 | struct stackmark smark; |
| 12807 | 12898 | ||
| 12899 | /* Initialize global data */ | ||
| 12900 | INIT_G_misc(); | ||
| 12901 | INIT_G_memstack(); | ||
| 12902 | INIT_G_var(); | ||
| 12903 | INIT_G_alias(); | ||
| 12904 | INIT_G_cmdtable(); | ||
| 12905 | |||
| 12808 | #if PROFILE | 12906 | #if PROFILE |
| 12809 | monitor(4, etext, profile_buf, sizeof(profile_buf), 50); | 12907 | monitor(4, etext, profile_buf, sizeof(profile_buf), 50); |
| 12810 | #endif | 12908 | #endif |
