Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/shell/msh.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/shell/msh.c
r902 r1770 11 11 * Erik Andersen <andersen@codepoet.org> 12 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 * 27 * Original copyright notice is retained at the end of this file. 28 */ 29 30 #include "busybox.h" 31 #include <ctype.h> 32 #include <dirent.h> 33 #include <errno.h> 34 #include <fcntl.h> 35 #include <limits.h> 13 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 14 */ 15 16 #include <sys/times.h> 36 17 #include <setjmp.h> 37 #include <signal.h> 38 #include <stddef.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <time.h> 43 #include <unistd.h> 44 #include <sys/stat.h> 45 #include <sys/times.h> 46 #include <sys/types.h> 47 #include <sys/wait.h> 48 49 #include "cmdedit.h" 50 51 52 /* Conditional use of "register" keyword */ 53 #define REGISTER register 54 18 19 #ifdef STANDALONE 20 # ifndef _GNU_SOURCE 21 # define _GNU_SOURCE 22 # endif 23 # include <sys/types.h> 24 # include <sys/stat.h> 25 # include <sys/wait.h> 26 # include <signal.h> 27 # include <stdio.h> 28 # include <stdlib.h> 29 # include <unistd.h> 30 # include <string.h> 31 # include <errno.h> 32 # include <dirent.h> 33 # include <fcntl.h> 34 # include <ctype.h> 35 # include <assert.h> 36 # define bb_dev_null "/dev/null" 37 # define DEFAULT_SHELL "/proc/self/exe" 38 # define CONFIG_BUSYBOX_EXEC_PATH "/proc/self/exe" 39 # define bb_banner "busybox standalone" 40 # define ENABLE_FEATURE_SH_STANDALONE 0 41 # define bb_msg_memory_exhausted "memory exhausted" 42 # define xmalloc(size) malloc(size) 43 # define msh_main(argc,argv) main(argc,argv) 44 # define safe_read(fd,buf,count) read(fd,buf,count) 45 # define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1]) 46 # define LONE_CHAR(s,c) ((s)[0] == (c) && !(s)[1]) 47 # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) 48 static char *find_applet_by_name(const char *applet) 49 { 50 return NULL; 51 } 52 static char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) 53 { 54 unsigned i, out, res; 55 assert(sizeof(unsigned) == 4); 56 if (buflen) { 57 out = 0; 58 for (i = 1000000000; i; i /= 10) { 59 res = n / i; 60 if (res || out || i == 1) { 61 if (!--buflen) break; 62 out++; 63 n -= res*i; 64 *buf++ = '0' + res; 65 } 66 } 67 } 68 return buf; 69 } 70 static char *itoa_to_buf(int n, char *buf, unsigned buflen) 71 { 72 if (buflen && n < 0) { 73 n = -n; 74 *buf++ = '-'; 75 buflen--; 76 } 77 return utoa_to_buf((unsigned)n, buf, buflen); 78 } 79 static char local_buf[12]; 80 static char *itoa(int n) 81 { 82 *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0'; 83 return local_buf; 84 } 85 #else 86 # include "busybox.h" 87 extern char **environ; 88 #endif 55 89 56 90 /*#define MSHDEBUG 1*/ … … 59 93 int mshdbg = MSHDEBUG; 60 94 61 #define DBGPRINTF(x) if (mshdbg>0)printf x62 #define DBGPRINTF0(x) if (mshdbg>0)printf x63 #define DBGPRINTF1(x) if (mshdbg>1)printf x64 #define DBGPRINTF2(x) if (mshdbg>2)printf x65 #define DBGPRINTF3(x) if (mshdbg>3)printf x66 #define DBGPRINTF4(x) if (mshdbg>4)printf x67 #define DBGPRINTF5(x) if (mshdbg>5)printf x68 #define DBGPRINTF6(x) if (mshdbg>6)printf x69 #define DBGPRINTF7(x) if (mshdbg>7)printf x70 #define DBGPRINTF8(x) if (mshdbg>8)printf x71 #define DBGPRINTF9(x) if (mshdbg>9)printf x95 #define DBGPRINTF(x) if (mshdbg>0) printf x 96 #define DBGPRINTF0(x) if (mshdbg>0) printf x 97 #define DBGPRINTF1(x) if (mshdbg>1) printf x 98 #define DBGPRINTF2(x) if (mshdbg>2) printf x 99 #define DBGPRINTF3(x) if (mshdbg>3) printf x 100 #define DBGPRINTF4(x) if (mshdbg>4) printf x 101 #define DBGPRINTF5(x) if (mshdbg>5) printf x 102 #define DBGPRINTF6(x) if (mshdbg>6) printf x 103 #define DBGPRINTF7(x) if (mshdbg>7) printf x 104 #define DBGPRINTF8(x) if (mshdbg>8) printf x 105 #define DBGPRINTF9(x) if (mshdbg>9) printf x 72 106 73 107 int mshdbg_rc = 0; 74 108 75 #define RCPRINTF(x) if(mshdbg_rc)printf x109 #define RCPRINTF(x) if (mshdbg_rc) printf x 76 110 77 111 #else 78 112 79 113 #define DBGPRINTF(x) 80 #define DBGPRINTF0(x) 81 #define DBGPRINTF1(x) 82 #define DBGPRINTF2(x) 83 #define DBGPRINTF3(x) 84 #define DBGPRINTF4(x) 85 #define DBGPRINTF5(x) 86 #define DBGPRINTF6(x) 87 #define DBGPRINTF7(x) 88 #define DBGPRINTF8(x) 89 #define DBGPRINTF9(x) 90 91 #define RCPRINTF(x) 114 #define DBGPRINTF0(x) ((void)0) 115 #define DBGPRINTF1(x) ((void)0) 116 #define DBGPRINTF2(x) ((void)0) 117 #define DBGPRINTF3(x) ((void)0) 118 #define DBGPRINTF4(x) ((void)0) 119 #define DBGPRINTF5(x) ((void)0) 120 #define DBGPRINTF6(x) ((void)0) 121 #define DBGPRINTF7(x) ((void)0) 122 #define DBGPRINTF8(x) ((void)0) 123 #define DBGPRINTF9(x) ((void)0) 124 125 #define RCPRINTF(x) ((void)0) 92 126 93 127 #endif /* MSHDEBUG */ 94 128 95 129 96 #if def CONFIG_FEATURE_SH_FANCY_PROMPT130 #if ENABLE_FEATURE_EDITING_FANCY_PROMPT 97 131 # define DEFAULT_ROOT_PROMPT "\\u:\\w> " 98 132 # define DEFAULT_USER_PROMPT "\\u:\\w$ " … … 119 153 * values returned by wait 120 154 */ 121 #define WAITSIG(s) ((s) &0177)122 #define WAITVAL(s) (((s) >>8)&0377)123 #define WAITCORE(s) (((s) &0200)!=0)155 #define WAITSIG(s) ((s) & 0177) 156 #define WAITVAL(s) (((s) >> 8) & 0377) 157 #define WAITCORE(s) (((s) & 0200) != 0) 124 158 125 159 /* … … 131 165 * shell components 132 166 */ 133 134 #define QUOTE 0200135 136 167 #define NOBLOCK ((struct op *)NULL) 137 168 #define NOWORD ((char *)NULL) 138 169 #define NOWORDS ((char **)NULL) 139 170 #define NOPIPE ((int *)NULL) 171 172 /* 173 * redirection 174 */ 175 struct ioword { 176 short io_unit; /* unit affected */ 177 short io_flag; /* action (below) */ 178 char *io_name; /* file name */ 179 }; 180 181 #define IOREAD 1 /* < */ 182 #define IOHERE 2 /* << (here file) */ 183 #define IOWRITE 4 /* > */ 184 #define IOCAT 8 /* >> */ 185 #define IOXHERE 16 /* ${}, ` in << */ 186 #define IODUP 32 /* >&digit */ 187 #define IOCLOSE 64 /* >&- */ 188 189 #define IODEFAULT (-1) /* token for default IO unit */ 190 140 191 141 192 /* … … 173 224 /* Strings for names to make debug easier */ 174 225 #ifdef MSHDEBUG 175 static c har *T_CMD_NAMES[] = {226 static const char *const T_CMD_NAMES[] = { 176 227 "PLACEHOLDER", 177 228 "TCOM", … … 198 249 * actions determining the environment of a process 199 250 */ 200 #define BIT(i) (1<<(i)) 201 #define FEXEC BIT(0) /* execute without forking */ 202 203 #if 0 /* Original value */ 204 #define AREASIZE (65000) 205 #else 206 #define AREASIZE (90000) 207 #endif 251 #define FEXEC 1 /* execute without forking */ 252 253 #define AREASIZE (90000) 208 254 209 255 /* 210 256 * flags to control evaluation of words 211 257 */ 212 #define DOSUB 1 /* interpret $, `, and quotes */ 213 #define DOBLANK 2 /* perform blank interpretation */ 214 #define DOGLOB 4 /* interpret [?* */ 215 #define DOKEY 8 /* move words with `=' to 2nd arg. list */ 216 #define DOTRIM 16 /* trim resulting string */ 217 218 #define DOALL (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM) 219 220 221 /* PROTOTYPES */ 222 static int newfile(char *s); 223 static char *findeq(char *cp); 224 static char *cclass(char *p, int sub); 225 static void initarea(void); 226 extern int msh_main(int argc, char **argv); 258 #define DOSUB 1 /* interpret $, `, and quotes */ 259 #define DOBLANK 2 /* perform blank interpretation */ 260 #define DOGLOB 4 /* interpret [?* */ 261 #define DOKEY 8 /* move words with `=' to 2nd arg. list */ 262 #define DOTRIM 16 /* trim resulting string */ 263 264 #define DOALL (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM) 227 265 228 266 … … 232 270 }; 233 271 234 235 /*236 * redirection237 */238 struct ioword {239 short io_unit; /* unit affected */240 short io_flag; /* action (below) */241 char *io_name; /* file name */242 };243 244 #define IOREAD 1 /* < */245 #define IOHERE 2 /* << (here file) */246 #define IOWRITE 4 /* > */247 #define IOCAT 8 /* >> */248 #define IOXHERE 16 /* ${}, ` in << */249 #define IODUP 32 /* >&digit */250 #define IOCLOSE 64 /* >&- */251 252 #define IODEFAULT (-1) /* token for default IO unit */253 254 255 256 /*257 * parsing & execution environment258 */259 static struct env {260 char *linep;261 struct io *iobase;262 struct io *iop;263 xint *errpt; /* void * */264 int iofd;265 struct env *oenv;266 } e;267 272 268 273 /* … … 276 281 * -u: unset variables net diagnostic 277 282 */ 278 static char *flag; 279 280 static char *null; /* null value for variable */ 281 static int intr; /* interrupt pending */ 282 283 static char *trap[_NSIG + 1]; 284 static char ourtrap[_NSIG + 1]; 283 static char flags['z' - 'a' + 1] ALIGN1; 284 /* this looks weird, but is OK ... we index FLAG with 'a'...'z' */ 285 #define FLAG (flags - 'a') 286 287 /* moved to G: static char *trap[_NSIG + 1]; */ 288 /* moved to G: static char ourtrap[_NSIG + 1]; */ 285 289 static int trapset; /* trap pending */ 286 290 287 static int heedint; /* heed interrupt signals */288 289 291 static int yynerrs; /* yacc */ 290 292 291 static char line[LINELIM]; 292 static char *elinep; 293 /* moved to G: static char line[LINELIM]; */ 294 295 #if ENABLE_FEATURE_EDITING 296 static char *current_prompt; 297 static line_input_t *line_input_state; 298 #endif 293 299 294 300 … … 296 302 * other functions 297 303 */ 298 static int (*inbuilt(char *s)) (struct op *); 299 300 static char *rexecve(char *c, char **v, char **envp); 301 static char *space(int n); 302 static char *strsave(char *s, int a); 304 static const char *rexecve(char *c, char **v, char **envp); 303 305 static char *evalstr(char *cp, int f); 304 306 static char *putn(int n); 305 static char *itoa(int n);306 307 static char *unquote(char *as); 307 static struct var *lookup(char *n);308 308 static int rlookup(char *n); 309 309 static struct wdblock *glob(char *cp, struct wdblock *wb); … … 319 319 static int newenv(int f); 320 320 static void quitenv(void); 321 static void err(char *s);322 static int anys(char *s1, char *s2);323 static int any(int c, char *s);324 321 static void next(int f); 325 322 static void setdash(void); 326 323 static void onecommand(void); 327 324 static void runtrap(int i); 328 static int gmatch(char *s, char *p);329 330 331 /*332 * error handling333 */334 static void leave(void); /* abort shell (or fail in subshell) */335 static void fail(void); /* fail but return to process next command */336 static void warn(char *s);337 static void sig(int i); /* default signal handler */338 339 325 340 326 341 327 /* -------- area stuff -------- */ 342 328 343 #define REGSIZEsizeof(struct region)344 #define GROWBY 345 /* #define SHRINKBY(64) */346 #undef 347 #define FREE 348 #define BUSY 349 #define ALIGN(sizeof(int)-1)329 #define REGSIZE sizeof(struct region) 330 #define GROWBY (256) 331 /* #define SHRINKBY (64) */ 332 #undef SHRINKBY 333 #define FREE (32767) 334 #define BUSY (0) 335 #define ALIGN (sizeof(int)-1) 350 336 351 337 … … 354 340 int area; 355 341 }; 356 357 342 358 343 … … 365 350 } YYSTYPE; 366 351 367 #define WORD256368 #define LOGAND257369 #define LOGOR258370 #define BREAK259371 #define IF260372 #define THEN261373 #define ELSE262374 #define ELIF263375 #define FI264376 #define CASE265377 #define ESAC266378 #define FOR267379 #define WHILE268380 #define UNTIL269381 #define DO270382 #define DONE271383 #define IN272352 #define WORD 256 353 #define LOGAND 257 354 #define LOGOR 258 355 #define BREAK 259 356 #define IF 260 357 #define THEN 261 358 #define ELSE 262 359 #define ELIF 263 360 #define FI 264 361 #define CASE 265 362 #define ESAC 266 363 #define FOR 267 364 #define WHILE 268 365 #define UNTIL 269 366 #define DO 270 367 #define DONE 271 368 #define IN 272 384 369 /* Added for "." file expansion */ 385 #define DOT273370 #define DOT 273 386 371 387 372 #define YYERRCODE 300 388 373 389 374 /* flags to yylex */ 390 #define CONTIN 01 /* skip new lines to complete command */ 391 392 #define SYNTAXERR zzerr() 375 #define CONTIN 01 /* skip new lines to complete command */ 393 376 394 377 static struct op *pipeline(int cf); … … 415 398 static struct ioword **copyio(void); 416 399 static struct ioword *io(int u, int f, char *cp); 417 static void zzerr(void);418 static void yyerror(char *s);419 400 static int yylex(int cf); 420 401 static int collect(int c, int c1); … … 438 419 439 420 static int yyparse(void); 440 static struct var *lookup(char *n);441 static void setval(struct var *vp, char *val);442 static void nameval(struct var *vp, char *val, char *name);443 static void export(struct var *vp);444 static void ronly(struct var *vp);445 static int isassign(char *s);446 static int checkname(char *cp);447 static int assign(char *s, int cf);448 static void putvlist(int f, int out);449 static int eqname(char *n1, char *n2);450 421 451 422 static int execute(struct op *t, int *pin, int *pout, int act); 423 424 425 #define AFID_NOBUF (~0) 426 #define AFID_ID 0 452 427 453 428 … … 455 430 /* io buffer */ 456 431 struct iobuf { 457 unsigned id; 458 char buf[512]; 459 char *bufp; 460 char *ebufp; 432 unsigned id; /* buffer id */ 433 char buf[512]; /* buffer */ 434 char *bufp; /* pointer into buffer */ 435 char *ebufp; /* pointer to end of buffer */ 461 436 }; 462 437 463 438 /* possible arguments to an IO function */ 464 439 struct ioarg { 465 c har *aword;440 const char *aword; 466 441 char **awordlist; 467 int afile; 468 unsigned afid; 469 long afpos; 470 struct iobuf *afbuf; 442 int afile; /* file descriptor */ 443 unsigned afid; /* buffer id */ 444 long afpos; /* file position */ 445 struct iobuf *afbuf; /* buffer for this file */ 471 446 }; 472 473 //static struct ioarg ioargstack[NPUSH];474 #define AFID_NOBUF (~0)475 #define AFID_ID 0476 447 477 448 /* an input generator's state */ … … 480 451 struct ioarg *argp; 481 452 int peekc; 482 char prev; 483 char nlcount; 484 char xchar; 485 char task; 453 char prev; /* previous character read by readc() */ 454 char nlcount; /* for `'s */ 455 char xchar; /* for `'s */ 456 char task; /* reason for pushed IO */ 486 457 }; 487 458 488 //static struct io iostack[NPUSH];489 459 #define XOTHER 0 /* none of the below */ 490 460 #define XDOLL 1 /* expanding ${} */ 491 461 #define XGRAVE 2 /* expanding `'s */ 492 #define XIO 3 462 #define XIO 3 /* file IO */ 493 463 494 464 /* in substitution */ 495 465 #define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL) 466 467 static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 }; /* temporary for PUSHIO */ 468 /* moved to G: static struct ioarg ioargstack[NPUSH]; */ 469 static struct io iostack[NPUSH]; 470 /* moved to G: static struct iobuf sharedbuf = { AFID_NOBUF }; */ 471 /* moved to G: static struct iobuf mainbuf = { AFID_NOBUF }; */ 472 static unsigned bufid = AFID_ID; /* buffer id counter */ 473 474 #define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen))) 496 475 497 476 … … 517 496 518 497 519 /*520 * IO functions521 */522 498 static int eofc(void); 523 499 static int readc(void); 524 500 static void unget(int c); 525 501 static void ioecho(char c); 526 static void prs(const char *s);527 static void prn(unsigned u);528 static void closef(int i);529 static void closeall(void);530 502 531 503 … … 534 506 */ 535 507 static void pushio(struct ioarg *argp, int (*f) (struct ioarg *)); 508 #define PUSHIO(what,arg,gen) ((temparg.what = (arg)), pushio(&temparg,(gen))) 536 509 static int remap(int fd); 537 510 static int openpipe(int *pv); 538 511 static void closepipe(int *pv); 539 512 static struct io *setbase(struct io *ip); 540 541 #define PUSHIO(what,arg,gen) ((temparg.what = (arg)),pushio(&temparg,(gen)))542 #define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))543 513 544 514 /* -------- word.h -------- */ … … 557 527 static char **getwords(struct wdblock *wb); 558 528 559 /* -------- area.h -------- */560 561 /*562 * storage allocation563 */564 static char *getcell(unsigned nbytes);565 static void garbage(void);566 static void setarea(char *cp, int a);567 static int getarea(char *cp);568 static void freearea(int a);569 static void freecell(char *cp);570 static int areanum; /* current allocation area */571 572 #define NEW(type) (type *)getcell(sizeof(type))573 #define DELETE(obj) freecell((char *)obj)574 575 576 529 /* -------- misc stuff -------- */ 577 530 578 531 static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp); 579 532 static int iosetup(struct ioword *iop, int pipein, int pipeout); 580 static void echo(char **wp);581 static struct op **find1case(struct op *t, char *w);582 static struct op *findcase(struct op *t, char *w);583 533 static void brkset(struct brkcon *bc); 584 534 static int dolabel(struct op *t); … … 608 558 static void varput(char *s, int out); 609 559 static int dotimes(struct op *t); 610 static int expand(c har *cp, struct wdblock **wbp, int f);560 static int expand(const char *cp, struct wdblock **wbp, int f); 611 561 static char *blank(int f); 612 562 static int dollar(int quoted); … … 616 566 static int anyspcl(struct wdblock *wb); 617 567 static int xstrcmp(char *p1, char *p2); 618 static void glob0(char *a0, unsigned inta1, int a2,568 static void glob0(char *a0, unsigned a1, int a2, 619 569 int (*a3) (char *, char *)); 620 static void glob1(char *base, char *lim);621 static void glob2(char *i, char *j);622 static void glob3(char *i, char *j, char *k);623 570 static void readhere(char **name, char *s, int ec); 624 static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));625 571 static int xxchar(struct ioarg *ap); 626 572 … … 632 578 }; 633 579 634 static const char * 580 static const char *const signame[] = { 635 581 "Signal 0", 636 582 "Hangup", 637 (char *) NULL,/* interrupt */583 NULL, /* interrupt */ 638 584 "Quit", 639 585 "Illegal instruction", … … 646 592 "SIGSEGV", 647 593 "SIGUSR2", 648 (char *) NULL,/* broken pipe */594 NULL, /* broken pipe */ 649 595 "Alarm clock", 650 "Terminated" ,596 "Terminated" 651 597 }; 652 598 653 #define NSIGNAL (sizeof(signame)/sizeof(signame[0]))654 599 655 600 struct res { … … 658 603 }; 659 604 static const struct res restab[] = { 660 { "for", FOR},661 { "case", CASE},662 { "esac", ESAC},663 { "while", WHILE},664 { "do", DO},665 { "done", DONE},666 { "if", IF},667 { "in", IN},668 { "then", THEN},669 { "else", ELSE},670 { "elif", ELIF},671 { "until", UNTIL},672 { "fi", FI},673 { ";;", BREAK},674 { "||", LOGOR},675 { "&&", LOGAND},676 { "{", '{'},677 { "}", '}'},678 { ".", DOT},679 { 0, 0},605 { "for" , FOR }, 606 { "case" , CASE }, 607 { "esac" , ESAC }, 608 { "while", WHILE }, 609 { "do" , DO }, 610 { "done" , DONE }, 611 { "if" , IF }, 612 { "in" , IN }, 613 { "then" , THEN }, 614 { "else" , ELSE }, 615 { "elif" , ELIF }, 616 { "until", UNTIL }, 617 { "fi" , FI }, 618 { ";;" , BREAK }, 619 { "||" , LOGOR }, 620 { "&&" , LOGAND }, 621 { "{" , '{' }, 622 { "}" , '}' }, 623 { "." , DOT }, 624 { NULL , 0 }, 680 625 }; 681 682 626 683 627 struct builtincmd { 684 628 const char *name; 685 int (*builtinfunc) (struct op *t);629 int (*builtinfunc)(struct op *t); 686 630 }; 687 631 static const struct builtincmd builtincmds[] = { 688 { ".", dodot},689 { ":", dolabel},690 { "break", dobreak},691 { "cd", dochdir},692 { "continue", docontinue},693 { "eval", doeval},694 { "exec", doexec},695 { "exit", doexit},696 { "export", doexport},697 { "help", dohelp},698 { "login", dologin},699 { "newgrp", dologin},700 { "read", doread},701 { "readonly", doreadonly},702 { "set", doset},703 { "shift", doshift},704 { "times", dotimes},705 { "trap", dotrap},706 { "umask", doumask},707 { "wait", dowait},708 { 0, 0}632 { "." , dodot }, 633 { ":" , dolabel }, 634 { "break" , dobreak }, 635 { "cd" , dochdir }, 636 { "continue", docontinue }, 637 { "eval" , doeval }, 638 { "exec" , doexec }, 639 { "exit" , doexit }, 640 { "export" , doexport }, 641 { "help" , dohelp }, 642 { "login" , dologin }, 643 { "newgrp" , dologin }, 644 { "read" , doread }, 645 { "readonly", doreadonly }, 646 { "set" , doset }, 647 { "shift" , doshift }, 648 { "times" , dotimes }, 649 { "trap" , dotrap }, 650 { "umask" , doumask }, 651 { "wait" , dowait }, 652 { NULL , NULL }, 709 653 }; 710 654 … … 712 656 static struct op *dowholefile(int, int); 713 657 658 714 659 /* Globals */ 715 extern char **environ; /* environment pointer */716 717 660 static char **dolv; 718 661 static int dolc; … … 729 672 static struct wdblock *wdlist; 730 673 static struct wdblock *iolist; 731 static char *trap[_NSIG + 1];732 static char ourtrap[_NSIG + 1];733 static int trapset; /* trap pending */734 static int yynerrs; /* yacc */735 static char line[LINELIM];736 674 737 675 #ifdef MSHDEBUG … … 746 684 static struct var *ifs; /* field separators */ 747 685 748 static int areanum; 749 static int intr; 686 static int areanum; /* current allocation area */ 687 static int intr; /* interrupt pending */ 750 688 static int inparse; 751 static char flags['z' - 'a' + 1]; 752 static char *flag = flags - 'a'; 753 static char *null = ""; 754 static int heedint = 1; 755 static void (*qflag) (int) = SIG_IGN; 689 static char *null = (char*)""; /* null value for variable */ 690 static int heedint = 1; /* heed interrupt signals */ 691 static void (*qflag)(int) = SIG_IGN; 756 692 static int startl; 757 693 static int peeksym; … … 759 695 static int iounit = IODEFAULT; 760 696 static YYSTYPE yylval; 761 static char *elinep = line + sizeof(line) - 5; 762 763 static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 }; /* temporary for PUSHIO */ 764 static struct ioarg ioargstack[NPUSH]; 765 static struct io iostack[NPUSH]; 766 static struct iobuf sharedbuf = { AFID_NOBUF }; 767 static struct iobuf mainbuf = { AFID_NOBUF }; 768 static unsigned bufid = AFID_ID; /* buffer id counter */ 769 770 static struct here *inhere; /* list of hear docs while parsing */ 771 static struct here *acthere; /* list of active here documents */ 772 static struct region *areabot; /* bottom of area */ 773 static struct region *areatop; /* top of area */ 774 static struct region *areanxt; /* starting point of scan */ 697 static char *elinep; /* done in main(): = line + sizeof(line) - 5 */ 698 699 static struct here *inhere; /* list of hear docs while parsing */ 700 static struct here *acthere; /* list of active here documents */ 701 static struct region *areabot; /* bottom of area */ 702 static struct region *areatop; /* top of area */ 703 static struct region *areanxt; /* starting point of scan */ 775 704 static void *brktop; 776 705 static void *brkaddr; 777 706 707 /* 708 * parsing & execution environment 709 */ 710 struct env { 711 char *linep; 712 struct io *iobase; 713 struct io *iop; 714 xint *errpt; /* void * */ 715 int iofd; 716 struct env *oenv; 717 }; 718 778 719 static struct env e = { 779 line,/* linep: char ptr */780 iostack, 781 iostack - 1, 782 (xint *) NULL, 783 FDBASE, 784 (struct env *) NULL 720 NULL /* set to line in main() */, /* linep: char ptr */ 721 iostack, /* iobase: struct io ptr */ 722 iostack - 1, /* iop: struct io ptr */ 723 (xint *) NULL, /* errpt: void ptr for errors? */ 724 FDBASE, /* iofd: file desc */ 725 (struct env *) NULL /* oenv: struct env ptr */ 785 726 }; 786 727 728 729 struct globals { 730 char ourtrap[_NSIG + 1]; 731 char *trap[_NSIG + 1]; 732 struct iobuf sharedbuf; /* in main(): set to { AFID_NOBUF } */ 733 struct iobuf mainbuf; /* in main(): set to { AFID_NOBUF } */ 734 struct ioarg ioargstack[NPUSH]; 735 char filechar_cmdbuf[BUFSIZ]; 736 char line[LINELIM]; 737 char child_cmd[LINELIM]; 738 }; 739 740 #define G (*ptr_to_globals) 741 #define ourtrap (G.ourtrap ) 742 #define trap (G.trap ) 743 #define sharedbuf (G.sharedbuf ) 744 #define mainbuf (G.mainbuf ) 745 #define ioargstack (G.ioargstack ) 746 #define filechar_cmdbuf (G.filechar_cmdbuf) 747 #define line (G.line ) 748 #define child_cmd (G.child_cmd ) 749 750 787 751 #ifdef MSHDEBUG 788 void print_t(struct op *t);789 752 void print_t(struct op *t) 790 753 { … … 795 758 DBGPRINTF(("T: W1: %s", t->words[0])); 796 759 } 797 798 return; 799 } 800 801 void print_tree(struct op *head); 760 } 761 802 762 void print_tree(struct op *head) 803 763 { … … 815 775 if (head->right) 816 776 print_tree(head->right); 817 818 return; 819 } 820 #endif /* MSHDEBUG */ 821 822 823 #ifdef CONFIG_FEATURE_COMMAND_EDITING 824 static char *current_prompt; 777 } 778 #endif /* MSHDEBUG */ 779 780 781 /* 782 * IO functions 783 */ 784 static void prs(const char *s) 785 { 786 if (*s) 787 write(2, s, strlen(s)); 788 } 789 790 static void prn(unsigned u) 791 { 792 prs(itoa(u)); 793 } 794 795 static void echo(char **wp) 796 { 797 int i; 798 799 prs("+"); 800 for (i = 0; wp[i]; i++) { 801 if (i) 802 prs(" "); 803 prs(wp[i]); 804 } 805 prs("\n"); 806 } 807 808 static void closef(int i) 809 { 810 if (i > 2) 811 close(i); 812 } 813 814 static void closeall(void) 815 { 816 int u; 817 818 for (u = NUFILE; u < NOFILE;) 819 close(u++); 820 } 821 822 823 /* fail but return to process next command */ 824 static void fail(void) ATTRIBUTE_NORETURN; 825 static void fail(void) 826 { 827 longjmp(failpt, 1); 828 /* NOTREACHED */ 829 } 830 831 /* abort shell (or fail in subshell) */ 832 static void leave(void) ATTRIBUTE_NORETURN; 833 static void leave(void) 834 { 835 DBGPRINTF(("LEAVE: leave called!\n")); 836 837 if (execflg) 838 fail(); 839 scraphere(); 840 freehere(1); 841 runtrap(0); 842 _exit(exstat); 843 /* NOTREACHED */ 844 } 845 846 static void warn(const char *s) 847 { 848 if (*s) { 849 prs(s); 850 exstat = -1; 851 } 852 prs("\n"); 853 if (FLAG['e']) 854 leave(); 855 } 856 857 static void err(const char *s) 858 { 859 warn(s); 860 if (FLAG['n']) 861 return; 862 if (!interactive) 863 leave(); 864 if (e.errpt) 865 longjmp(e.errpt, 1); 866 closeall(); 867 e.iop = e.iobase = iostack; 868 } 869 870 871 /* -------- area.c -------- */ 872 873 /* 874 * All memory between (char *)areabot and (char *)(areatop+1) is 875 * exclusively administered by the area management routines. 876 * It is assumed that sbrk() and brk() manipulate the high end. 877 */ 878 879 #define sbrk(X) ({ \ 880 void * __q = (void *)-1; \ 881 if (brkaddr + (int)(X) < brktop) { \ 882 __q = brkaddr; \ 883 brkaddr += (int)(X); \ 884 } \ 885 __q; \ 886 }) 887 888 static void initarea(void) 889 { 890 brkaddr = xmalloc(AREASIZE); 891 brktop = brkaddr + AREASIZE; 892 893 while ((long) sbrk(0) & ALIGN) 894 sbrk(1); 895 areabot = (struct region *) sbrk(REGSIZE); 896 897 areabot->next = areabot; 898 areabot->area = BUSY; 899 areatop = areabot; 900 areanxt = areabot; 901 } 902 903 static char *getcell(unsigned nbytes) 904 { 905 int nregio; 906 struct region *p, *q; 907 int i; 908 909 if (nbytes == 0) { 910 puts("getcell(0)"); 911 abort(); 912 } 913 /* silly and defeats the algorithm */ 914 /* 915 * round upwards and add administration area 916 */ 917 nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1; 918 p = areanxt; 919 for (;;) { 920 if (p->area > areanum) { 921 /* 922 * merge free cells 923 */ 924 while ((q = p->next)->area > areanum && q != areanxt) 925 p->next = q->next; 926 /* 927 * exit loop if cell big enough 928 */ 929 if (q >= p + nregio) 930 goto found; 931 } 932 p = p->next; 933 if (p == areanxt) 934 break; 935 } 936 i = nregio >= GROWBY ? nregio : GROWBY; 937 p = (struct region *) sbrk(i * REGSIZE); 938 if (p == (struct region *) -1) 939 return NULL; 940 p--; 941 if (p != areatop) { 942 puts("not contig"); 943 abort(); /* allocated areas are contiguous */ 944 } 945 q = p + i; 946 p->next = q; 947 p->area = FREE; 948 q->next = areabot; 949 q->area = BUSY; 950 areatop = q; 951 found: 952 /* 953 * we found a FREE area big enough, pointed to by 'p', and up to 'q' 954 */ 955 areanxt = p + nregio; 956 if (areanxt < q) { 957 /* 958 * split into requested area and rest 959 */ 960 if (areanxt + 1 > q) { 961 puts("OOM"); 962 abort(); /* insufficient space left for admin */ 963 } 964 areanxt->next = q; 965 areanxt->area = FREE; 966 p->next = areanxt; 967 } 968 p->area = areanum; 969 return (char *) (p + 1); 970 } 971 972 static void freecell(char *cp) 973 { 974 struct region *p; 975 976 p = (struct region *) cp; 977 if (p != NULL) { 978 p--; 979 if (p < areanxt) 980 areanxt = p; 981 p->area = FREE; 982 } 983 } 984 #define DELETE(obj) freecell((char *)obj) 985 986 static void freearea(int a) 987 { 988 struct region *p, *top; 989 990 top = areatop; 991 for (p = areabot; p != top; p = p->next) 992 if (p->area >= a) 993 p->area = FREE; 994 } 995 996 static void setarea(char *cp, int a) 997 { 998 struct region *p; 999 1000 p = (struct region *) cp; 1001 if (p != NULL) 1002 (p - 1)->area = a; 1003 } 1004 1005 static int getarea(char *cp) 1006 { 1007 return ((struct region *) cp - 1)->area; 1008 } 1009 1010 static void garbage(void) 1011 { 1012 struct region *p, *q, *top; 1013 1014 top = areatop; 1015 for (p = areabot; p != top; p = p->next) { 1016 if (p->area > areanum) { 1017 while ((q = p->next)->area > areanum) 1018 p->next = q->next; 1019 areanxt = p; 1020 } 1021 } 1022 #ifdef SHRINKBY 1023 if (areatop >= q + SHRINKBY && q->area > areanum) { 1024 brk((char *) (q + 1)); 1025 q->next = areabot; 1026 q->area = BUSY; 1027 areatop = q; 1028 } 825 1029 #endif 826 827 /* -------- sh.c -------- */ 828 /* 829 * shell 830 */ 831 832 833 int msh_main(int argc, char **argv) 834 { 835 REGISTER int f; 836 REGISTER char *s; 837 int cflag; 838 char *name, **ap; 839 int (*iof) (struct ioarg *); 840 841 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ)); 842 843 initarea(); 844 if ((ap = environ) != NULL) { 845 while (*ap) 846 assign(*ap++, !COPYV); 847 for (ap = environ; *ap;) 848 export(lookup(*ap++)); 849 } 850 closeall(); 851 areanum = 1; 852 853 shell = lookup("SHELL"); 854 if (shell->value == null) 855 setval(shell, (char *)DEFAULT_SHELL); 856 export(shell); 857 858 homedir = lookup("HOME"); 859 if (homedir->value == null) 860 setval(homedir, "/"); 861 export(homedir); 862 863 setval(lookup("$"), putn(getpid())); 864 865 path = lookup("PATH"); 866 if (path->value == null) { 867 if (geteuid() == 0) 868 setval(path, "/sbin:/bin:/usr/sbin:/usr/bin"); 869 else 870 setval(path, "/bin:/usr/bin"); 871 } 872 export(path); 873 874 ifs = lookup("IFS"); 875 if (ifs->value == null) 876 setval(ifs, " \t\n"); 877 878 #ifdef MSHDEBUG 879 mshdbg_var = lookup("MSHDEBUG"); 880 if (mshdbg_var->value == null) 881 setval(mshdbg_var, "0"); 882 #endif 883 884 prompt = lookup("PS1"); 885 #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT 886 if (prompt->value == null) 887 #endif 888 setval(prompt, DEFAULT_USER_PROMPT); 889 if (geteuid() == 0) { 890 setval(prompt, DEFAULT_ROOT_PROMPT); 891 prompt->status &= ~EXPORT; 892 } 893 cprompt = lookup("PS2"); 894 #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT 895 if (cprompt->value == null) 896 #endif 897 setval(cprompt, "> "); 898 899 iof = filechar; 900 cflag = 0; 901 name = *argv++; 902 if (--argc >= 1) { 903 if (argv[0][0] == '-' && argv[0][1] != '\0') { 904 for (s = argv[0] + 1; *s; s++) 905 switch (*s) { 906 case 'c': 907 prompt->status &= ~EXPORT; 908 cprompt->status &= ~EXPORT; 909 setval(prompt, ""); 910 setval(cprompt, ""); 911 cflag = 1; 912 if (--argc > 0) 913 PUSHIO(aword, *++argv, iof = nlchar); 914 break; 915 916 case 'q': 917 qflag = SIG_DFL; 918 break; 919 920 case 's': 921 /* standard input */ 922 break; 923 924 case 't': 925 prompt->status &= ~EXPORT; 926 setval(prompt, ""); 927 iof = linechar; 928 break; 929 930 case 'i': 931 interactive++; 932 default: 933 if (*s >= 'a' && *s <= 'z') 934 flag[(int) *s]++; 935 } 936 } else { 937 argv--; 938 argc++; 939 } 940 941 if (iof == filechar && --argc > 0) { 942 setval(prompt, ""); 943 setval(cprompt, ""); 944 prompt->status &= ~EXPORT; 945 cprompt->status &= ~EXPORT; 946 947 /* Shell is non-interactive, activate printf-based debug */ 948 #ifdef MSHDEBUG 949 mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0'); 950 if (mshdbg < 0) 951 mshdbg = 0; 952 #endif 953 DBGPRINTF(("MSH_MAIN: calling newfile()\n")); 954 955 if (newfile(name = *++argv)) 956 exit(1); /* Exit on error */ 957 } 958 } 959 960 setdash(); 961 962 /* This won't be true if PUSHIO has been called, say from newfile() above */ 963 if (e.iop < iostack) { 964 PUSHIO(afile, 0, iof); 965 if (isatty(0) && isatty(1) && !cflag) { 966 interactive++; 967 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET 968 #ifdef MSHDEBUG 969 printf("\n\n%s Built-in shell (msh with debug)\n", BB_BANNER); 970 #else 971 printf("\n\n%s Built-in shell (msh)\n", BB_BANNER); 972 #endif 973 printf("Enter 'help' for a list of built-in commands.\n\n"); 974 #endif 975 } 976 } 977 978 signal(SIGQUIT, qflag); 979 if (name && name[0] == '-') { 980 interactive++; 981 if ((f = open(".profile", 0)) >= 0) 982 next(remap(f)); 983 if ((f = open("/etc/profile", 0)) >= 0) 984 next(remap(f)); 985 } 986 if (interactive) 987 signal(SIGTERM, sig); 988 989 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 990 signal(SIGINT, onintr); 991 dolv = argv; 992 dolc = argc; 993 dolv[0] = name; 994 if (dolc > 1) { 995 for (ap = ++argv; --argc > 0;) { 996 if (assign(*ap = *argv++, !COPYV)) { 997 dolc--; /* keyword */ 998 } else { 999 ap++; 1000 } 1001 } 1002 } 1003 setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc)); 1004 1005 DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack)); 1006 1007 for (;;) { 1008 if (interactive && e.iop <= iostack) { 1009 #ifdef CONFIG_FEATURE_COMMAND_EDITING 1010 current_prompt = prompt->value; 1011 #else 1012 prs(prompt->value); 1013 #endif 1014 } 1015 onecommand(); 1016 /* Ensure that getenv("PATH") stays current */ 1017 setenv("PATH", path->value, 1); 1018 } 1019 1020 DBGPRINTF(("MSH_MAIN: returning.\n")); 1021 } 1030 } 1031 1032 static char *space(int n) 1033 { 1034 char *cp; 1035 1036 cp = getcell(n); 1037 if (cp == NULL) 1038 err("out of string space"); 1039 return cp; 1040 } 1041 1042 static char *strsave(const char *s, int a) 1043 { 1044 char *cp; 1045 1046 cp = space(strlen(s) + 1); 1047 if (cp == NULL) { 1048 // FIXME: I highly doubt this is good. 1049 return (char*)""; 1050 } 1051 setarea(cp, a); 1052 strcpy(cp, s); 1053 return cp; 1054 } 1055 1056 1057 /* -------- var.c -------- */ 1058 1059 static int eqname(const char *n1, const char *n2) 1060 { 1061 for (; *n1 != '=' && *n1 != '\0'; n1++) 1062 if (*n2++ != *n1) 1063 return 0; 1064 return *n2 == '\0' || *n2 == '='; 1065 } 1066 1067 static const char *findeq(const char *cp) 1068 { 1069 while (*cp != '\0' && *cp != '=') 1070 cp++; 1071 return cp; 1072 } 1073 1074 /* 1075 * Find the given name in the dictionary 1076 * and return its value. If the name was 1077 * not previously there, enter it now and 1078 * return a null value. 1079 */ 1080 static struct var *lookup(const char *n) 1081 { 1082 // FIXME: dirty hack 1083 static struct var dummy; 1084 1085 struct var *vp; 1086 const char *cp; 1087 char *xp; 1088 int c; 1089 1090 if (isdigit(*n)) { 1091 dummy.name = (char*)n; 1092 for (c = 0; isdigit(*n) && c < 1000; n++) 1093 c = c * 10 + *n - '0'; 1094 dummy.status = RONLY; 1095 dummy.value = (c <= dolc ? dolv[c] : null); 1096 return &dummy; 1097 } 1098 1099 for (vp = vlist; vp; vp = vp->next) 1100 if (eqname(vp->name, n)) 1101 return vp; 1102 1103 cp = findeq(n); 1104 vp = (struct var *) space(sizeof(*vp)); 1105 if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) { 1106 dummy.name = dummy.value = (char*)""; 1107 return &dummy; 1108 } 1109 1110 xp = vp->name; 1111 while ((*xp = *n++) != '\0' && *xp != '=') 1112 xp++; 1113 *xp++ = '='; 1114 *xp = '\0'; 1115 setarea((char *) vp, 0); 1116 setarea((char *) vp->name, 0); 1117 vp->value = null; 1118 vp->next = vlist; 1119 vp->status = GETCELL; 1120 vlist = vp; 1121 return vp; 1122 } 1123 1124 /* 1125 * if name is not NULL, it must be 1126 * a prefix of the space `val', 1127 * and end with `='. 1128 * this is all so that exporting 1129 * values is reasonably painless. 1130 */ 1131 static void nameval(struct var *vp, const char *val, const char *name) 1132 { 1133 const char *cp; 1134 char *xp; 1135 int fl; 1136 1137 if (vp->status & RONLY) { 1138 xp = vp->name; 1139 while (*xp && *xp != '=') 1140 putc(*xp++, stderr); 1141 err(" is read-only"); 1142 return; 1143 } 1144 fl = 0; 1145 if (name == NULL) { 1146 xp = space(strlen(vp->name) + strlen(val) + 2); 1147 if (xp == NULL) 1148 return; 1149 /* make string: name=value */ 1150 setarea(xp, 0); 1151 name = xp; 1152 cp = vp->name; 1153 while ((*xp = *cp++) != '\0' && *xp != '=') 1154 xp++; 1155 *xp++ = '='; 1156 strcpy(xp, val); 1157 val = xp; 1158 fl = GETCELL; 1159 } 1160 if (vp->status & GETCELL) 1161 freecell(vp->name); /* form new string `name=value' */ 1162 vp->name = (char*)name; 1163 vp->value = (char*)val; 1164 vp->status |= fl; 1165 } 1166 1167 /* 1168 * give variable at `vp' the value `val'. 1169 */ 1170 static void setval(struct var *vp, const char *val) 1171 { 1172 nameval(vp, val, NULL); 1173 } 1174 1175 static void export(struct var *vp) 1176 { 1177 vp->status |= EXPORT; 1178 } 1179 1180 static void ronly(struct var *vp) 1181 { 1182 if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */ 1183 vp->status |= RONLY; 1184 } 1185 1186 static int isassign(const char *s) 1187 { 1188 unsigned char c; 1189 DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s)); 1190 1191 c = *s; 1192 /* no isalpha() - we shouldn't use locale */ 1193 /* c | 0x20 - lowercase (Latin) letters */ 1194 if (c != '_' && (unsigned)((c|0x20) - 'a') > 25) 1195 /* not letter */ 1196 return 0; 1197 1198 while (1) { 1199 c = *++s; 1200 if (c == '=') 1201 return 1; 1202 if (c == '\0') 1203 return 0; 1204 if (c != '_' 1205 && (unsigned)(c - '0') > 9 /* not number */ 1206 && (unsigned)((c|0x20) - 'a') > 25 /* not letter */ 1207 ) { 1208 return 0; 1209 } 1210 } 1211 } 1212 1213 static int assign(const char *s, int cf) 1214 { 1215 const char *cp; 1216 struct var *vp; 1217 1218 DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf)); 1219 1220 if (!isalpha(*s) && *s != '_') 1221 return 0; 1222 for (cp = s; *cp != '='; cp++) 1223 if (*cp == '\0' || (!isalnum(*cp) && *cp != '_')) 1224 return 0; 1225 vp = lookup(s); 1226 nameval(vp, ++cp, cf == COPYV ? NULL : s); 1227 if (cf != COPYV) 1228 vp->status &= ~GETCELL; 1229 return 1; 1230 } 1231 1232 static int checkname(char *cp) 1233 { 1234 DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp)); 1235 1236 if (!isalpha(*cp++) && *(cp - 1) != '_') 1237 return 0; 1238 while (*cp) 1239 if (!isalnum(*cp++) && *(cp - 1) != '_') 1240 return 0; 1241 return 1; 1242 } 1243 1244 static void putvlist(int f, int out) 1245 { 1246 struct var *vp; 1247 1248 for (vp = vlist; vp; vp = vp->next) { 1249 if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) { 1250 if (vp->status & EXPORT) 1251 write(out, "export ", 7); 1252 if (vp->status & RONLY) 1253 write(out, "readonly ", 9); 1254 write(out, vp->name, (int) (findeq(vp->name) - vp->name)); 1255 write(out, "\n", 1); 1256 } 1257 } 1258 } 1259 1260 1261 /* 1262 * trap handling 1263 */ 1264 static void sig(int i) 1265 { 1266 trapset = i; 1267 signal(i, sig); 1268 } 1269 1270 static void runtrap(int i) 1271 { 1272 char *trapstr; 1273 1274 trapstr = trap[i]; 1275 if (trapstr == NULL) 1276 return; 1277 1278 if (i == 0) 1279 trap[i] = NULL; 1280 1281 RUN(aword, trapstr, nlchar); 1282 } 1283 1022 1284 1023 1285 static void setdash(void) 1024 1286 { 1025 REGISTERchar *cp;1026 REGISTERint c;1287 char *cp; 1288 int c; 1027 1289 char m['z' - 'a' + 1]; 1028 1290 1029 1291 cp = m; 1030 1292 for (c = 'a'; c <= 'z'; c++) 1031 if ( flag[(int)c])1293 if (FLAG[c]) 1032 1294 *cp++ = c; 1033 *cp = 0;1295 *cp = '\0'; 1034 1296 setval(lookup("-"), m); 1035 1297 } 1036 1298 1037 static int newfile( REGISTERchar *s)1038 { 1039 REGISTERint f;1299 static int newfile(char *s) 1300 { 1301 int f; 1040 1302 1041 1303 DBGPRINTF7(("NEWFILE: opening %s\n", s)); 1042 1304 1043 if (strcmp(s, "-") != 0) { 1305 f = 0; 1306 if (NOT_LONE_DASH(s)) { 1044 1307 DBGPRINTF(("NEWFILE: s is %s\n", s)); 1045 f = open(s, 0);1308 f = open(s, O_RDONLY); 1046 1309 if (f < 0) { 1047 1310 prs(s); 1048 1311 err(": cannot open"); 1049 return (1); 1050 } 1051 } else 1052 f = 0; 1312 return 1; 1313 } 1314 } 1053 1315 1054 1316 next(remap(f)); 1055 return (0);1317 return 0; 1056 1318 } 1057 1319 … … 1062 1324 1063 1325 if (head == NULL) 1064 return (NULL);1326 return NULL; 1065 1327 1066 1328 if (head->left != NULL) { 1067 1329 dotnode = scantree(head->left); 1068 1330 if (dotnode) 1069 return (dotnode);1331 return dotnode; 1070 1332 } 1071 1333 … … 1073 1335 dotnode = scantree(head->right); 1074 1336 if (dotnode) 1075 return (dotnode);1337 return dotnode; 1076 1338 } 1077 1339 1078 1340 if (head->words == NULL) 1079 return (NULL);1341 return NULL; 1080 1342 1081 1343 DBGPRINTF5(("SCANTREE: checking node %p\n", head)); 1082 1344 1083 if ((head->type != TDOT) && (strcmp(".", head->words[0]) == 0)) {1345 if ((head->type != TDOT) && LONE_CHAR(head->words[0], '.')) { 1084 1346 DBGPRINTF5(("SCANTREE: dot found in node %p\n", head)); 1085 return (head);1086 } 1087 1088 return (NULL);1347 return head; 1348 } 1349 1350 return NULL; 1089 1351 } 1090 1352 … … 1092 1354 static void onecommand(void) 1093 1355 { 1094 REGISTERint i;1356 int i; 1095 1357 jmp_buf m1; 1096 1358 … … 1114 1376 execflg = 0; 1115 1377 1116 setjmp(failpt = m1); /* Bruce Evans' fix */ 1117 if (setjmp(failpt = m1) || yyparse() || intr) { 1118 1378 failpt = m1; 1379 setjmp(failpt); /* Bruce Evans' fix */ 1380 failpt = m1; 1381 if (setjmp(failpt) || yyparse() || intr) { 1119 1382 DBGPRINTF(("ONECOMMAND: this is not good.\n")); 1120 1383 … … 1134 1397 execflg = 0; 1135 1398 1136 if (! flag['n']) {1399 if (!FLAG['n']) { 1137 1400 DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n", 1138 1401 outtree)); … … 1145 1408 } 1146 1409 1147 if ((i = trapset) != 0) { 1410 i = trapset; 1411 if (i != 0) { 1148 1412 trapset = 0; 1149 1413 runtrap(i); … … 1151 1415 } 1152 1416 1153 static void fail(void)1154 {1155 longjmp(failpt, 1);1156 /* NOTREACHED */1157 }1158 1159 static void leave(void)1160 {1161 DBGPRINTF(("LEAVE: leave called!\n"));1162 1163 if (execflg)1164 fail();1165 scraphere();1166 freehere(1);1167 runtrap(0);1168 _exit(exstat);1169 /* NOTREACHED */1170 }1171 1172 static void warn(REGISTER char *s)1173 {1174 if (*s) {1175 prs(s);1176 exstat = -1;1177 }1178 prs("\n");1179 if (flag['e'])1180 leave();1181 }1182 1183 static void err(char *s)1184 {1185 warn(s);1186 if (flag['n'])1187 return;1188 if (!interactive)1189 leave();1190 if (e.errpt)1191 longjmp(e.errpt, 1);1192 closeall();1193 e.iop = e.iobase = iostack;1194 }1195 1196 1417 static int newenv(int f) 1197 1418 { 1198 REGISTERstruct env *ep;1419 struct env *ep; 1199 1420 1200 1421 DBGPRINTF(("NEWENV: f=%d (indicates quitenv and return)\n", f)); … … 1202 1423 if (f) { 1203 1424 quitenv(); 1204 return (1);1425 return 1; 1205 1426 } 1206 1427 … … 1215 1436 e.errpt = errpt; 1216 1437 1217 return (0);1438 return 0; 1218 1439 } 1219 1440 1220 1441 static void quitenv(void) 1221 1442 { 1222 REGISTERstruct env *ep;1223 REGISTERint fd;1443 struct env *ep; 1444 int fd; 1224 1445 1225 1446 DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv)); 1226 1447 1227 if ((ep = e.oenv) != NULL) { 1448 ep = e.oenv; 1449 if (ep != NULL) { 1228 1450 fd = e.iofd; 1229 1451 e = *ep; … … 1236 1458 1237 1459 /* 1460 * Is character c in s? 1461 */ 1462 static int any(int c, const char *s) 1463 { 1464 while (*s) 1465 if (*s++ == c) 1466 return 1; 1467 return 0; 1468 } 1469 1470 /* 1238 1471 * Is any character from s1 in s2? 1239 1472 */ 1240 static int anys( REGISTER char *s1, REGISTERchar *s2)1473 static int anys(const char *s1, const char *s2) 1241 1474 { 1242 1475 while (*s1) 1243 1476 if (any(*s1++, s2)) 1244 return (1); 1245 return (0); 1246 } 1247 1248 /* 1249 * Is character c in s? 1250 */ 1251 static int any(REGISTER int c, REGISTER char *s) 1252 { 1253 while (*s) 1254 if (*s++ == c) 1255 return (1); 1256 return (0); 1257 } 1258 1259 static char *putn(REGISTER int n) 1260 { 1261 return (itoa(n)); 1262 } 1263 1264 static char *itoa(REGISTER int n) 1265 { 1266 static char s[20]; 1267 1268 snprintf(s, sizeof(s), "%u", n); 1269 return (s); 1270 } 1271 1477 return 1; 1478 return 0; 1479 } 1480 1481 static char *putn(int n) 1482 { 1483 return itoa(n); 1484 } 1272 1485 1273 1486 static void next(int f) … … 1291 1504 } 1292 1505 1293 static char *space(int n)1294 {1295 REGISTER char *cp;1296 1297 if ((cp = getcell(n)) == 0)1298 err("out of string space");1299 return (cp);1300 }1301 1302 static char *strsave(REGISTER char *s, int a)1303 {1304 REGISTER char *cp, *xp;1305 1306 if ((cp = space(strlen(s) + 1)) != NULL) {1307 setarea((char *) cp, a);1308 for (xp = cp; (*xp++ = *s++) != '\0';);1309 return (cp);1310 }1311 return ("");1312 }1313 1314 /*1315 * trap handling1316 */1317 static void sig(REGISTER int i)1318 {1319 trapset = i;1320 signal(i, sig);1321 }1322 1323 static void runtrap(int i)1324 {1325 char *trapstr;1326 1327 if ((trapstr = trap[i]) == NULL)1328 return;1329 1330 if (i == 0)1331 trap[i] = 0;1332 1333 RUN(aword, trapstr, nlchar);1334 }1335 1336 /* -------- var.c -------- */1337 1338 /*1339 * Find the given name in the dictionary1340 * and return its value. If the name was1341 * not previously there, enter it now and1342 * return a null value.1343 */1344 static struct var *lookup(REGISTER char *n)1345 {1346 REGISTER struct var *vp;1347 REGISTER char *cp;1348 REGISTER int c;1349 static struct var dummy;1350 1351 if (isdigit(*n)) {1352 dummy.name = n;1353 for (c = 0; isdigit(*n) && c < 1000; n++)1354 c = c * 10 + *n - '0';1355 dummy.status = RONLY;1356 dummy.value = c <= dolc ? dolv[c] : null;1357 return (&dummy);1358 }1359 for (vp = vlist; vp; vp = vp->next)1360 if (eqname(vp->name, n))1361 return (vp);1362 cp = findeq(n);1363 vp = (struct var *) space(sizeof(*vp));1364 if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) {1365 dummy.name = dummy.value = "";1366 return (&dummy);1367 }1368 for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++);1369 if (*cp == 0)1370 *cp = '=';1371 *++cp = 0;1372 setarea((char *) vp, 0);1373 setarea((char *) vp->name, 0);1374 vp->value = null;1375 vp->next = vlist;1376 vp->status = GETCELL;1377 vlist = vp;1378 return (vp);1379 }1380 1381 /*1382 * give variable at `vp' the value `val'.1383 */1384 static void setval(struct var *vp, char *val)1385 {1386 nameval(vp, val, (char *) NULL);1387 }1388 1389 /*1390 * if name is not NULL, it must be1391 * a prefix of the space `val',1392 * and end with `='.1393 * this is all so that exporting1394 * values is reasonably painless.1395 */1396 static void nameval(REGISTER struct var *vp, char *val, char *name)1397 {1398 REGISTER char *cp, *xp;1399 char *nv;1400 int fl;1401 1402 if (vp->status & RONLY) {1403 for (xp = vp->name; *xp && *xp != '=';)1404 putc(*xp++, stderr);1405 err(" is read-only");1406 return;1407 }1408 fl = 0;1409 if (name == NULL) {1410 xp = space(strlen(vp->name) + strlen(val) + 2);1411 if (xp == 0)1412 return;1413 /* make string: name=value */1414 setarea((char *) xp, 0);1415 name = xp;1416 for (cp = vp->name; (*xp = *cp++) && *xp != '='; xp++);1417 if (*xp++ == 0)1418 xp[-1] = '=';1419 nv = xp;1420 for (cp = val; (*xp++ = *cp++) != '\0';);1421 val = nv;1422 fl = GETCELL;1423 }1424 if (vp->status & GETCELL)1425 freecell(vp->name); /* form new string `name=value' */1426 vp->name = name;1427 vp->value = val;1428 vp->status |= fl;1429 }1430 1431 static void export(struct var *vp)1432 {1433 vp->status |= EXPORT;1434 }1435 1436 static void ronly(struct var *vp)1437 {1438 if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */1439 vp->status |= RONLY;1440 }1441 1442 static int isassign(REGISTER char *s)1443 {1444 DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));1445 1446 if (!isalpha((int) *s) && *s != '_')1447 return (0);1448 for (; *s != '='; s++)1449 if (*s == 0 || (!isalnum(*s) && *s != '_'))1450 return (0);1451 1452 return (1);1453 }1454 1455 static int assign(REGISTER char *s, int cf)1456 {1457 REGISTER char *cp;1458 struct var *vp;1459 1460 DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));1461 1462 if (!isalpha(*s) && *s != '_')1463 return (0);1464 for (cp = s; *cp != '='; cp++)1465 if (*cp == 0 || (!isalnum(*cp) && *cp != '_'))1466 return (0);1467 vp = lookup(s);1468 nameval(vp, ++cp, cf == COPYV ? (char *) NULL : s);1469 if (cf != COPYV)1470 vp->status &= ~GETCELL;1471 return (1);1472 }1473 1474 static int checkname(REGISTER char *cp)1475 {1476 DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));1477 1478 if (!isalpha(*cp++) && *(cp - 1) != '_')1479 return (0);1480 while (*cp)1481 if (!isalnum(*cp++) && *(cp - 1) != '_')1482 return (0);1483 return (1);1484 }1485 1486 static void putvlist(REGISTER int f, REGISTER int out)1487 {1488 REGISTER struct var *vp;1489 1490 for (vp = vlist; vp; vp = vp->next)1491 if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {1492 if (vp->status & EXPORT)1493 write(out, "export ", 7);1494 if (vp->status & RONLY)1495 write(out, "readonly ", 9);1496 write(out, vp->name, (int) (findeq(vp->name) - vp->name));1497 write(out, "\n", 1);1498 }1499 }1500 1501 static int eqname(REGISTER char *n1, REGISTER char *n2)1502 {1503 for (; *n1 != '=' && *n1 != 0; n1++)1504 if (*n2++ != *n1)1505 return (0);1506 return (*n2 == 0 || *n2 == '=');1507 }1508 1509 static char *findeq(REGISTER char *cp)1510 {1511 while (*cp != '\0' && *cp != '=')1512 cp++;1513 return (cp);1514 }1515 1506 1516 1507 /* -------- gmatch.c -------- */ … … 1524 1515 #define CMASK 0377 1525 1516 #define QUOTE 0200 1526 #define QMASK (CMASK &~QUOTE)1517 #define QMASK (CMASK & ~QUOTE) 1527 1518 #define NOT '!' /* might use ^ */ 1528 1519 1529 static int gmatch(REGISTER char *s, REGISTER char *p) 1530 { 1531 REGISTER int sc, pc; 1532 1533 if (s == NULL || p == NULL) 1534 return (0); 1535 while ((pc = *p++ & CMASK) != '\0') { 1536 sc = *s++ & QMASK; 1537 switch (pc) { 1538 case '[': 1539 if ((p = cclass(p, sc)) == NULL) 1540 return (0); 1541 break; 1542 1543 case '?': 1544 if (sc == 0) 1545 return (0); 1546 break; 1547 1548 case '*': 1549 s--; 1550 do { 1551 if (*p == '\0' || gmatch(s, p)) 1552 return (1); 1553 } while (*s++ != '\0'); 1554 return (0); 1555 1556 default: 1557 if (sc != (pc & ~QUOTE)) 1558 return (0); 1559 } 1560 } 1561 return (*s == 0); 1562 } 1563 1564 static char *cclass(REGISTER char *p, REGISTER int sub) 1565 { 1566 REGISTER int c, d, not, found; 1567 1568 if ((not = *p == NOT) != 0) 1520 static const char *cclass(const char *p, int sub) 1521 { 1522 int c, d, not, found; 1523 1524 not = (*p == NOT); 1525 if (not != 0) 1569 1526 p++; 1570 1527 found = not; 1571 1528 do { 1572 1529 if (*p == '\0') 1573 return ((char *) NULL);1530 return NULL; 1574 1531 c = *p & CMASK; 1575 1532 if (p[1] == '-' && p[2] != ']') { … … 1581 1538 found = !not; 1582 1539 } while (*++p != ']'); 1583 return (found ? p + 1 : (char *) NULL); 1584 } 1585 1586 1587 /* -------- area.c -------- */ 1588 1589 /* 1590 * All memory between (char *)areabot and (char *)(areatop+1) is 1591 * exclusively administered by the area management routines. 1592 * It is assumed that sbrk() and brk() manipulate the high end. 1593 */ 1594 1595 #define sbrk(X) ({ void * __q = (void *)-1; if (brkaddr + (int)(X) < brktop) { __q = brkaddr; brkaddr+=(int)(X); } __q;}) 1596 1597 static void initarea(void) 1598 { 1599 brkaddr = xmalloc(AREASIZE); 1600 brktop = brkaddr + AREASIZE; 1601 1602 while ((long) sbrk(0) & ALIGN) 1603 sbrk(1); 1604 areabot = (struct region *) sbrk(REGSIZE); 1605 1606 areabot->next = areabot; 1607 areabot->area = BUSY; 1608 areatop = areabot; 1609 areanxt = areabot; 1610 } 1611 1612 char *getcell(unsigned nbytes) 1613 { 1614 REGISTER int nregio; 1615 REGISTER struct region *p, *q; 1616 REGISTER int i; 1617 1618 if (nbytes == 0) { 1619 puts("getcell(0)"); 1620 abort(); 1621 } 1622 /* silly and defeats the algorithm */ 1623 /* 1624 * round upwards and add administration area 1625 */ 1626 nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1; 1627 for (p = areanxt;;) { 1628 if (p->area > areanum) { 1629 /* 1630 * merge free cells 1631 */ 1632 while ((q = p->next)->area > areanum && q != areanxt) 1633 p->next = q->next; 1634 /* 1635 * exit loop if cell big enough 1636 */ 1637 if (q >= p + nregio) 1638 goto found; 1639 } 1640 p = p->next; 1641 if (p == areanxt) 1540 return found ? p + 1 : NULL; 1541 } 1542 1543 static int gmatch(const char *s, const char *p) 1544 { 1545 int sc, pc; 1546 1547 if (s == NULL || p == NULL) 1548 return 0; 1549 1550 while ((pc = *p++ & CMASK) != '\0') { 1551 sc = *s++ & QMASK; 1552 switch (pc) { 1553 case '[': 1554 p = cclass(p, sc); 1555 if (p == NULL) 1556 return 0; 1642 1557 break; 1643 } 1644 i = nregio >= GROWBY ? nregio : GROWBY; 1645 p = (struct region *) sbrk(i * REGSIZE); 1646 if (p == (struct region *) -1) 1647 return ((char *) NULL); 1648 p--; 1649 if (p != areatop) { 1650 puts("not contig"); 1651 abort(); /* allocated areas are contiguous */ 1652 } 1653 q = p + i; 1654 p->next = q; 1655 p->area = FREE; 1656 q->next = areabot; 1657 q->area = BUSY; 1658 areatop = q; 1659 found: 1660 /* 1661 * we found a FREE area big enough, pointed to by 'p', and up to 'q' 1662 */ 1663 areanxt = p + nregio; 1664 if (areanxt < q) { 1665 /* 1666 * split into requested area and rest 1667 */ 1668 if (areanxt + 1 > q) { 1669 puts("OOM"); 1670 abort(); /* insufficient space left for admin */ 1671 } 1672 areanxt->next = q; 1673 areanxt->area = FREE; 1674 p->next = areanxt; 1675 } 1676 p->area = areanum; 1677 return ((char *) (p + 1)); 1678 } 1679 1680 static void freecell(char *cp) 1681 { 1682 REGISTER struct region *p; 1683 1684 if ((p = (struct region *) cp) != NULL) { 1685 p--; 1686 if (p < areanxt) 1687 areanxt = p; 1688 p->area = FREE; 1689 } 1690 } 1691 1692 static void freearea(REGISTER int a) 1693 { 1694 REGISTER struct region *p, *top; 1695 1696 top = areatop; 1697 for (p = areabot; p != top; p = p->next) 1698 if (p->area >= a) 1699 p->area = FREE; 1700 } 1701 1702 static void setarea(char *cp, int a) 1703 { 1704 REGISTER struct region *p; 1705 1706 if ((p = (struct region *) cp) != NULL) 1707 (p - 1)->area = a; 1708 } 1709 1710 int getarea(char *cp) 1711 { 1712 return ((struct region *) cp - 1)->area; 1713 } 1714 1715 static void garbage(void) 1716 { 1717 REGISTER struct region *p, *q, *top; 1718 1719 top = areatop; 1720 for (p = areabot; p != top; p = p->next) { 1721 if (p->area > areanum) { 1722 while ((q = p->next)->area > areanum) 1723 p->next = q->next; 1724 areanxt = p; 1725 } 1726 } 1727 #ifdef SHRINKBY 1728 if (areatop >= q + SHRINKBY && q->area > areanum) { 1729 brk((char *) (q + 1)); 1730 q->next = areabot; 1731 q->area = BUSY; 1732 areatop = q; 1733 } 1734 #endif 1735 } 1558 1559 case '?': 1560 if (sc == 0) 1561 return 0; 1562 break; 1563 1564 case '*': 1565 s--; 1566 do { 1567 if (*p == '\0' || gmatch(s, p)) 1568 return 1; 1569 } while (*s++ != '\0'); 1570 return 0; 1571 1572 default: 1573 if (sc != (pc & ~QUOTE)) 1574 return 0; 1575 } 1576 } 1577 return *s == '\0'; 1578 } 1579 1736 1580 1737 1581 /* -------- csyn.c -------- */ … … 1739 1583 * shell: syntax (C version) 1740 1584 */ 1585 1586 static void yyerror(const char *s) ATTRIBUTE_NORETURN; 1587 static void yyerror(const char *s) 1588 { 1589 yynerrs++; 1590 if (interactive && e.iop <= iostack) { 1591 multiline = 0; 1592 while (eofc() == 0 && yylex(0) != '\n'); 1593 } 1594 err(s); 1595 fail(); 1596 } 1597 1598 static void zzerr(void) ATTRIBUTE_NORETURN; 1599 static void zzerr(void) 1600 { 1601 yyerror("syntax error"); 1602 } 1741 1603 1742 1604 int yyparse(void) … … 1754 1616 static struct op *pipeline(int cf) 1755 1617 { 1756 REGISTERstruct op *t, *p;1757 REGISTERint c;1618 struct op *t, *p; 1619 int c; 1758 1620 1759 1621 DBGPRINTF7(("PIPELINE: enter, cf=%d\n", cf)); … … 1765 1627 if (t != NULL) { 1766 1628 while ((c = yylex(0)) == '|') { 1767 if ((p = command(CONTIN)) == NULL) { 1629 p = command(CONTIN); 1630 if (p == NULL) { 1768 1631 DBGPRINTF8(("PIPELINE: error!\n")); 1769 SYNTAXERR;1632 zzerr(); 1770 1633 } 1771 1634 … … 1781 1644 1782 1645 DBGPRINTF7(("PIPELINE: returning t=%p\n", t)); 1783 return (t);1646 return t; 1784 1647 } 1785 1648 1786 1649 static struct op *andor(void) 1787 1650 { 1788 REGISTERstruct op *t, *p;1789 REGISTERint c;1651 struct op *t, *p; 1652 int c; 1790 1653 1791 1654 DBGPRINTF7(("ANDOR: enter...\n")); … … 1797 1660 if (t != NULL) { 1798 1661 while ((c = yylex(0)) == LOGAND || c == LOGOR) { 1799 if ((p = pipeline(CONTIN)) == NULL) { 1662 p = pipeline(CONTIN); 1663 if (p == NULL) { 1800 1664 DBGPRINTF8(("ANDOR: error!\n")); 1801 SYNTAXERR;1665 zzerr(); 1802 1666 } 1803 1667 … … 1809 1673 1810 1674 DBGPRINTF7(("ANDOR: returning t=%p\n", t)); 1811 return (t);1675 return t; 1812 1676 } 1813 1677 1814 1678 static struct op *c_list(void) 1815 1679 { 1816 REGISTERstruct op *t, *p;1817 REGISTERint c;1680 struct op *t, *p; 1681 int c; 1818 1682 1819 1683 DBGPRINTF7(("C_LIST: enter...\n")); … … 1822 1686 1823 1687 if (t != NULL) { 1824 if ((peeksym = yylex(0)) == '&') 1688 peeksym = yylex(0); 1689 if (peeksym == '&') 1825 1690 t = block(TASYNC, t, NOBLOCK, NOWORDS); 1826 1691 … … 1828 1693 || (multiline && c == '\n')) { 1829 1694 1830 if ((p = andor()) == NULL) 1831 return (t); 1832 1833 if ((peeksym = yylex(0)) == '&') 1695 p = andor(); 1696 if (p== NULL) 1697 return t; 1698 1699 peeksym = yylex(0); 1700 if (peeksym == '&') 1834 1701 p = block(TASYNC, p, NOBLOCK, NOWORDS); 1835 1702 … … 1841 1708 /* IF */ 1842 1709 DBGPRINTF7(("C_LIST: returning t=%p\n", t)); 1843 return (t);1710 return t; 1844 1711 } 1845 1712 1846 1713 static int synio(int cf) 1847 1714 { 1848 REGISTERstruct ioword *iop;1849 REGISTERint i;1850 REGISTERint c;1715 struct ioword *iop; 1716 int i; 1717 int c; 1851 1718 1852 1719 DBGPRINTF7(("SYNIO: enter, cf=%d\n", cf)); 1853 1720 1854 if ((c = yylex(cf)) != '<' && c != '>') { 1721 c = yylex(cf); 1722 if (c != '<' && c != '>') { 1855 1723 peeksym = c; 1856 return (0);1724 return 0; 1857 1725 } 1858 1726 … … 1866 1734 1867 1735 DBGPRINTF7(("SYNIO: returning 1\n")); 1868 return (1);1736 return 1; 1869 1737 } 1870 1738 1871 1739 static void musthave(int c, int cf) 1872 1740 { 1873 if ((peeksym = yylex(cf)) != c) { 1741 peeksym = yylex(cf); 1742 if (peeksym != c) { 1874 1743 DBGPRINTF7(("MUSTHAVE: error!\n")); 1875 SYNTAXERR;1744 zzerr(); 1876 1745 } 1877 1746 … … 1881 1750 static struct op *simple(void) 1882 1751 { 1883 REGISTERstruct op *t;1752 struct op *t; 1884 1753 1885 1754 t = NULL; … … 1901 1770 1902 1771 default: 1903 return (t);1772 return t; 1904 1773 } 1905 1774 } … … 1908 1777 static struct op *nested(int type, int mark) 1909 1778 { 1910 REGISTERstruct op *t;1779 struct op *t; 1911 1780 1912 1781 DBGPRINTF3(("NESTED: enter, type=%d, mark=%d\n", type, mark)); … … 1916 1785 musthave(mark, 0); 1917 1786 multiline--; 1918 return (block(type, t, NOBLOCK, NOWORDS));1787 return block(type, t, NOBLOCK, NOWORDS); 1919 1788 } 1920 1789 1921 1790 static struct op *command(int cf) 1922 1791 { 1923 REGISTERstruct op *t;1792 struct op *t; 1924 1793 struct wdblock *iosave; 1925 REGISTERint c;1794 int c; 1926 1795 1927 1796 DBGPRINTF(("COMMAND: enter, cf=%d\n", cf)); … … 1941 1810 default: 1942 1811 peeksym = c; 1943 if ((t = simple()) == NULL) { 1812 t = simple(); 1813 if (t == NULL) { 1944 1814 if (iolist == NULL) 1945 return ((struct op *) NULL);1815 return NULL; 1946 1816 t = newtp(); 1947 1817 t->type = TCOM; … … 1965 1835 multiline++; 1966 1836 t->words = wordlist(); 1967 if ((c = yylex(0)) != '\n' && c != ';') 1837 c = yylex(0); 1838 if (c != '\n' && c != ';') 1968 1839 peeksym = c; 1969 1840 t->left = dogroup(0); … … 2029 1900 DBGPRINTF(("COMMAND: returning %p\n", t)); 2030 1901 2031 return (t);1902 return t; 2032 1903 } 2033 1904 2034 1905 static struct op *dowholefile(int type, int mark) 2035 1906 { 2036 REGISTERstruct op *t;1907 struct op *t; 2037 1908 2038 1909 DBGPRINTF(("DOWHOLEFILE: enter, type=%d, mark=%d\n", type, mark)); … … 2043 1914 t = block(type, t, NOBLOCK, NOWORDS); 2044 1915 DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t)); 2045 return (t);1916 return t; 2046 1917 } 2047 1918 2048 1919 static struct op *dogroup(int onlydone) 2049 1920 { 2050 REGISTERint c;2051 REGISTERstruct op *mylist;1921 int c; 1922 struct op *mylist; 2052 1923 2053 1924 c = yylex(CONTIN); 2054 1925 if (c == DONE && onlydone) 2055 return ((struct op *) NULL);1926 return NULL; 2056 1927 if (c != DO) 2057 SYNTAXERR;1928 zzerr(); 2058 1929 mylist = c_list(); 2059 1930 musthave(DONE, 0); 2060 return (mylist);1931 return mylist; 2061 1932 } 2062 1933 2063 1934 static struct op *thenpart(void) 2064 1935 { 2065 REGISTER int c; 2066 REGISTER struct op *t; 2067 2068 if ((c = yylex(0)) != THEN) { 1936 int c; 1937 struct op *t; 1938 1939 c = yylex(0); 1940 if (c != THEN) { 2069 1941 peeksym = c; 2070 return ((struct op *) NULL);1942 return NULL; 2071 1943 } 2072 1944 t = newtp(); … … 2074 1946 t->left = c_list(); 2075 1947 if (t->left == NULL) 2076 SYNTAXERR;1948 zzerr(); 2077 1949 t->right = elsepart(); 2078 return (t);1950 return t; 2079 1951 } 2080 1952 2081 1953 static struct op *elsepart(void) 2082 1954 { 2083 REGISTERint c;2084 REGISTERstruct op *t;1955 int c; 1956 struct op *t; 2085 1957 2086 1958 switch (c = yylex(0)) { 2087 1959 case ELSE: 2088 if ((t = c_list()) == NULL) 2089 SYNTAXERR; 2090 return (t); 1960 t = c_list(); 1961 if (t == NULL) 1962 zzerr(); 1963 return t; 2091 1964 2092 1965 case ELIF: … … 2095 1968 t->left = c_list(); 2096 1969 t->right = thenpart(); 2097 return (t);1970 return t; 2098 1971 2099 1972 default: 2100 1973 peeksym = c; 2101 return ((struct op *) NULL);1974 return NULL; 2102 1975 } 2103 1976 } … … 2105 1978 static struct op *caselist(void) 2106 1979 { 2107 REGISTERstruct op *t;1980 struct op *t; 2108 1981 2109 1982 t = NULL; … … 2114 1987 2115 1988 DBGPRINTF(("CASELIST, returning t=%p\n", t)); 2116 return (t);1989 return t; 2117 1990 } 2118 1991 2119 1992 static struct op *casepart(void) 2120 1993 { 2121 REGISTERstruct op *t;1994 struct op *t; 2122 1995 2123 1996 DBGPRINTF7(("CASEPART: enter...\n")); … … 2128 2001 musthave(')', 0); 2129 2002 t->left = c_list(); 2130 if ((peeksym = yylex(CONTIN)) != ESAC) 2003 peeksym = yylex(CONTIN); 2004 if (peeksym != ESAC) 2131 2005 musthave(BREAK, CONTIN); 2132 2006 2133 2007 DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t)); 2134 2008 2135 return (t);2009 return t; 2136 2010 } 2137 2011 2138 2012 static char **pattern(void) 2139 2013 { 2140 REGISTERint c, cf;2014 int c, cf; 2141 2015 2142 2016 cf = CONTIN; … … 2145 2019 word(yylval.cp); 2146 2020 cf = 0; 2147 } while ((c = yylex(0)) == '|'); 2021 c = yylex(0); 2022 } while (c == '|'); 2148 2023 peeksym = c; 2149 2024 word(NOWORD); 2150 2025 2151 return (copyw());2026 return copyw(); 2152 2027 } 2153 2028 2154 2029 static char **wordlist(void) 2155 2030 { 2156 REGISTER int c; 2157 2158 if ((c = yylex(0)) != IN) { 2031 int c; 2032 2033 c = yylex(0); 2034 if (c != IN) { 2159 2035 peeksym = c; 2160 return ((char **) NULL);2036 return NULL; 2161 2037 } 2162 2038 startl = 0; … … 2165 2041 word(NOWORD); 2166 2042 peeksym = c; 2167 return (copyw());2043 return copyw(); 2168 2044 } 2169 2045 … … 2171 2047 * supporting functions 2172 2048 */ 2173 static struct op *list( REGISTER struct op *t1, REGISTERstruct op *t2)2049 static struct op *list(struct op *t1, struct op *t2) 2174 2050 { 2175 2051 DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2)); 2176 2052 2177 2053 if (t1 == NULL) 2178 return (t2);2054 return t2; 2179 2055 if (t2 == NULL) 2180 return (t1);2181 2182 return (block(TLIST, t1, t2, NOWORDS));2056 return t1; 2057 2058 return block(TLIST, t1, t2, NOWORDS); 2183 2059 } 2184 2060 2185 2061 static struct op *block(int type, struct op *t1, struct op *t2, char **wp) 2186 2062 { 2187 REGISTERstruct op *t;2063 struct op *t; 2188 2064 2189 2065 DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type])); … … 2198 2074 t2)); 2199 2075 2200 return (t);2076 return t; 2201 2077 } 2202 2078 2203 2079 /* See if given string is a shell multiline (FOR, IF, etc) */ 2204 static int rlookup( REGISTERchar *n)2205 { 2206 REGISTERconst struct res *rp;2080 static int rlookup(char *n) 2081 { 2082 const struct res *rp; 2207 2083 2208 2084 DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n)); … … 2211 2087 if (strcmp(rp->r_name, n) == 0) { 2212 2088 DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val)); 2213 return (rp->r_val); /* Return numeric code for shell multiline */2089 return rp->r_val; /* Return numeric code for shell multiline */ 2214 2090 } 2215 2091 2216 2092 DBGPRINTF7(("RLOOKUP: NO match, returning 0\n")); 2217 return (0); /* Not a shell multiline */2093 return 0; /* Not a shell multiline */ 2218 2094 } 2219 2095 2220 2096 static struct op *newtp(void) 2221 2097 { 2222 REGISTERstruct op *t;2098 struct op *t; 2223 2099 2224 2100 t = (struct op *) tree(sizeof(*t)); … … 2232 2108 DBGPRINTF3(("NEWTP: allocated %p\n", t)); 2233 2109 2234 return (t); 2235 } 2236 2237 static struct op *namelist(REGISTER struct op *t) 2238 { 2239 2110 return t; 2111 } 2112 2113 static struct op *namelist(struct op *t) 2114 { 2240 2115 DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t, 2241 2116 T_CMD_NAMES[t->type], iolist)); … … 2253 2128 t->left->ioact = NULL; 2254 2129 } 2255 return (t);2130 return t; 2256 2131 } 2257 2132 … … 2259 2134 t->words = copyw(); 2260 2135 2261 2262 return (t); 2136 return t; 2263 2137 } 2264 2138 2265 2139 static char **copyw(void) 2266 2140 { 2267 REGISTERchar **wd;2141 char **wd; 2268 2142 2269 2143 wd = getwords(wdlist); 2270 2144 wdlist = 0; 2271 return (wd);2145 return wd; 2272 2146 } 2273 2147 … … 2279 2153 static struct ioword **copyio(void) 2280 2154 { 2281 REGISTERstruct ioword **iop;2155 struct ioword **iop; 2282 2156 2283 2157 iop = (struct ioword **) getwords(iolist); 2284 2158 iolist = 0; 2285 return (iop);2159 return iop; 2286 2160 } 2287 2161 2288 2162 static struct ioword *io(int u, int f, char *cp) 2289 2163 { 2290 REGISTERstruct ioword *iop;2164 struct ioword *iop; 2291 2165 2292 2166 iop = (struct ioword *) tree(sizeof(*iop)); … … 2295 2169 iop->io_name = cp; 2296 2170 iolist = addword((char *) iop, iolist); 2297 return (iop); 2298 } 2299 2300 static void zzerr(void) 2301 { 2302 yyerror("syntax error"); 2303 } 2304 2305 static void yyerror(char *s) 2306 { 2307 yynerrs++; 2308 if (interactive && e.iop <= iostack) { 2309 multiline = 0; 2310 while (eofc() == 0 && yylex(0) != '\n'); 2311 } 2312 err(s); 2313 fail(); 2171 return iop; 2314 2172 } 2315 2173 2316 2174 static int yylex(int cf) 2317 2175 { 2318 REGISTERint c, c1;2176 int c, c1; 2319 2177 int atstart; 2320 2178 2321 if ((c = peeksym) > 0) { 2179 c = peeksym; 2180 if (c > 0) { 2322 2181 peeksym = 0; 2323 2182 if (c == '\n') 2324 2183 startl = 1; 2325 return (c); 2326 } 2327 2184 return c; 2185 } 2328 2186 2329 2187 nlseen = 0; … … 2336 2194 line[LINELIM - 1] = '\0'; 2337 2195 2338 2196 loop: 2339 2197 while ((c = my_getc(0)) == ' ' || c == '\t') /* Skip whitespace */ 2340 2198 ; … … 2343 2201 default: 2344 2202 if (any(c, "0123456789")) { 2345 unget(c1 = my_getc(0)); 2203 c1 = my_getc(0); 2204 unget(c1); 2346 2205 if (c1 == '<' || c1 == '>') { 2347 2206 iounit = c - '0'; … … 2354 2213 2355 2214 case '#': /* Comment, skip to next newline or End-of-string */ 2356 while ((c = my_getc(0)) != 0&& c != '\n');2215 while ((c = my_getc(0)) != '\0' && c != '\n'); 2357 2216 unget(c); 2358 2217 goto loop; … … 2360 2219 case 0: 2361 2220 DBGPRINTF5(("YYLEX: return 0, c=%d\n", c)); 2362 return (c);2221 return c; 2363 2222 2364 2223 case '$': 2365 2224 DBGPRINTF9(("YYLEX: found $\n")); 2366 2225 *e.linep++ = c; 2367 if ((c = my_getc(0)) == '{') { 2368 if ((c = collect(c, '}')) != '\0') 2369 return (c); 2226 c = my_getc(0); 2227 if (c == '{') { 2228 c = collect(c, '}'); 2229 if (c != '\0') 2230 return c; 2370 2231 goto pack; 2371 2232 } … … 2375 2236 case '\'': 2376 2237 case '"': 2377 if ((c = collect(c, c)) != '\0') 2378 return (c); 2238 c = collect(c, c); 2239 if (c != '\0') 2240 return c; 2379 2241 goto pack; 2380 2242 … … 2384 2246 startl = 1; 2385 2247 /* If more chars process them, else return NULL char */ 2386 if ((c1 = dual(c)) != '\0')2387 return (c1);2388 else2389 return (c);2248 c1 = dual(c); 2249 if (c1 != '\0') 2250 return c1; 2251 return c; 2390 2252 2391 2253 case '^': 2392 2254 startl = 1; 2393 return ('|');2255 return '|'; 2394 2256 case '>': 2395 2257 case '<': 2396 2258 diag(c); 2397 return (c);2259 return c; 2398 2260 2399 2261 case '\n': … … 2403 2265 if (multiline || cf & CONTIN) { 2404 2266 if (interactive && e.iop <= iostack) { 2405 #if def CONFIG_FEATURE_COMMAND_EDITING2267 #if ENABLE_FEATURE_EDITING 2406 2268 current_prompt = cprompt->value; 2407 2269 #else … … 2412 2274 goto loop; 2413 2275 } 2414 return (c);2276 return c; 2415 2277 2416 2278 case '(': 2417 2279 case ')': 2418 2280 startl = 1; 2419 return (c);2281 return c; 2420 2282 } 2421 2283 2422 2284 unget(c); 2423 2285 2424 2425 while ((c = my_getc(0)) != 0&& !any(c, "`$ '\"\t;&<>()|^\n")) {2286 pack: 2287 while ((c = my_getc(0)) != '\0' && !any(c, "`$ '\"\t;&<>()|^\n")) { 2426 2288 if (e.linep >= elinep) 2427 2289 err("word too long"); … … 2437 2299 *e.linep++ = '\0'; 2438 2300 2439 if (atstart && (c = rlookup(line)) != 0) { 2440 startl = 1; 2441 return (c); 2301 if (atstart) { 2302 c = rlookup(line); 2303 if (c != 0) { 2304 startl = 1; 2305 return c; 2306 } 2442 2307 } 2443 2308 2444 2309 yylval.cp = strsave(line, areanum); 2445 return (WORD);2446 } 2447 2448 2449 static int collect( REGISTER int c, REGISTERint c1)2310 return WORD; 2311 } 2312 2313 2314 static int collect(int c, int c1) 2450 2315 { 2451 2316 char s[2]; … … 2461 2326 prs("no closing "); 2462 2327 yyerror(s); 2463 return (YYERRCODE);2328 return YYERRCODE; 2464 2329 } 2465 2330 if (interactive && c == '\n' && e.iop <= iostack) { 2466 #if def CONFIG_FEATURE_COMMAND_EDITING2331 #if ENABLE_FEATURE_EDITING 2467 2332 current_prompt = cprompt->value; 2468 2333 #else … … 2477 2342 DBGPRINTF8(("COLLECT: return 0, line is %s\n", line)); 2478 2343 2479 return (0);2344 return 0; 2480 2345 } 2481 2346 2482 2347 /* "multiline commands" helper func */ 2483 2348 /* see if next 2 chars form a shell multiline */ 2484 static int dual( REGISTERint c)2349 static int dual(int c) 2485 2350 { 2486 2351 char s[3]; 2487 REGISTERchar *cp = s;2352 char *cp = s; 2488 2353 2489 2354 DBGPRINTF8(("DUAL: enter, c=%d\n", c)); 2490 2355 2491 *cp++ = c; 2492 *cp++ = my_getc(0); 2493 *cp = 0;/* add EOS marker */2494 2495 c = rlookup(s); 2356 *cp++ = c; /* c is the given "peek" char */ 2357 *cp++ = my_getc(0); /* get next char of input */ 2358 *cp = '\0'; /* add EOS marker */ 2359 2360 c = rlookup(s); /* see if 2 chars form a shell multiline */ 2496 2361 if (c == 0) 2497 unget(*--cp); 2498 2499 return (c);/* String is multiline, return numeric multiline (restab) code */2500 } 2501 2502 static void diag( REGISTERint ec)2503 { 2504 REGISTERint c;2362 unget(*--cp); /* String is not a shell multiline, put peek char back */ 2363 2364 return c; /* String is multiline, return numeric multiline (restab) code */ 2365 } 2366 2367 static void diag(int ec) 2368 { 2369 int c; 2505 2370 2506 2371 DBGPRINTF8(("DIAG: enter, ec=%d\n", ec)); … … 2510 2375 if (c != ec) 2511 2376 zzerr(); 2512 yylval.i = ec == '>' ? IOWRITE | IOCAT : IOHERE;2377 yylval.i = (ec == '>' ? IOWRITE | IOCAT : IOHERE); 2513 2378 c = my_getc(0); 2514 2379 } else 2515 yylval.i = ec == '>' ? IOWRITE : IOREAD;2380 yylval.i = (ec == '>' ? IOWRITE : IOREAD); 2516 2381 if (c != '&' || yylval.i == IOHERE) 2517 2382 unget(c); … … 2522 2387 static char *tree(unsigned size) 2523 2388 { 2524 REGISTER char *t; 2525 2526 if ((t = getcell(size)) == NULL) { 2389 char *t; 2390 2391 t = getcell(size); 2392 if (t == NULL) { 2527 2393 DBGPRINTF2(("TREE: getcell(%d) failed!\n", size)); 2528 2394 prs("command line too complicated\n"); … … 2530 2396 /* NOTREACHED */ 2531 2397 } 2532 return (t); 2533 } 2398 return t; 2399 } 2400 2534 2401 2535 2402 /* VARARGS1 */ … … 2538 2405 /* -------- exec.c -------- */ 2539 2406 2407 static struct op **find1case(struct op *t, const char *w) 2408 { 2409 struct op *t1; 2410 struct op **tp; 2411 char **wp; 2412 char *cp; 2413 2414 if (t == NULL) { 2415 DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n")); 2416 return NULL; 2417 } 2418 2419 DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type, 2420 T_CMD_NAMES[t->type])); 2421 2422 if (t->type == TLIST) { 2423 tp = find1case(t->left, w); 2424 if (tp != NULL) { 2425 DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp)); 2426 return tp; 2427 } 2428 t1 = t->right; /* TPAT */ 2429 } else 2430 t1 = t; 2431 2432 for (wp = t1->words; *wp;) { 2433 cp = evalstr(*wp++, DOSUB); 2434 if (cp && gmatch(w, cp)) { 2435 DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n", 2436 &t1->left)); 2437 return &t1->left; 2438 } 2439 } 2440 2441 DBGPRINTF(("FIND1CASE: returning NULL\n")); 2442 return NULL; 2443 } 2444 2445 static struct op *findcase(struct op *t, const char *w) 2446 { 2447 struct op **tp; 2448 2449 tp = find1case(t, w); 2450 return tp != NULL ? *tp : NULL; 2451 } 2452 2540 2453 /* 2541 2454 * execute tree 2542 2455 */ 2543 2456 2544 2545 static int execute(REGISTER struct op *t, int *pin, int *pout, int act) 2546 { 2547 REGISTER struct op *t1; 2457 static int execute(struct op *t, int *pin, int *pout, int act) 2458 { 2459 struct op *t1; 2548 2460 volatile int i, rv, a; 2549 char *cp, **wp, **wp2; 2461 const char *cp; 2462 char **wp, **wp2; 2550 2463 struct var *vp; 2551 2464 struct op *outtree_save; … … 2559 2472 if (t == NULL) { 2560 2473 DBGPRINTF4(("EXECUTE: enter, t==null, returning.\n")); 2561 return (0);2474 return 0; 2562 2475 } 2563 2476 … … 2572 2485 : NULL; 2573 2486 2574 /* Hard to know how many words there are, be careful of garbage pointer values */2575 /* They are likely to cause "PCI bus fault" errors */2576 #if 02577 DBGPRINTF(("EXECUTE: t->left=%p, t->right=%p, t->words[1] is %s\n",2578 t->left, t->right,2579 ((t->words[1] == NULL) ? "NULL" : t->words[1])));2580 DBGPRINTF7(("EXECUTE: t->words[2] is %s, t->words[3] is %s\n",2581 ((t->words[2] == NULL) ? "NULL" : t->words[2]),2582 ((t->words[3] == NULL) ? "NULL" : t->words[3])));2583 #endif2584 2585 2586 2487 switch (t->type) { 2587 2488 case TDOT: … … 2608 2509 2609 2510 case TCOM: 2610 { 2611 rv = forkexec(t, pin, pout, act, wp); 2612 } 2511 rv = forkexec(t, pin, pout, act, wp); 2613 2512 break; 2614 2513 … … 2617 2516 int pv[2]; 2618 2517 2619 if ((rv = openpipe(pv)) < 0) 2518 rv = openpipe(pv); 2519 if (rv < 0) 2620 2520 break; 2621 2521 pv[0] = remap(pv[0]); … … 2638 2538 2639 2539 i = vfork(); 2640 if (i != 0) { 2641 interactive = hinteractive; 2642 if (i != -1) { 2643 setval(lookup("!"), putn(i)); 2644 if (pin != NULL) 2645 closepipe(pin); 2646 if (interactive) { 2647 prs(putn(i)); 2648 prs("\n"); 2649 } 2650 } else 2651 rv = -1; 2652 setstatus(rv); 2653 } else { 2540 if (i == 0) { /* child */ 2654 2541 signal(SIGINT, SIG_IGN); 2655 2542 signal(SIGQUIT, SIG_IGN); … … 2659 2546 if (pin == NULL) { 2660 2547 close(0); 2661 open(bb_dev_null, 0);2548 xopen(bb_dev_null, O_RDONLY); 2662 2549 } 2663 2550 _exit(execute(t->left, pin, pout, FEXEC)); 2664 2551 } 2552 interactive = hinteractive; 2553 if (i != -1) { 2554 setval(lookup("!"), putn(i)); 2555 if (pin != NULL) 2556 closepipe(pin); 2557 if (interactive) { 2558 prs(putn(i)); 2559 prs("\n"); 2560 } 2561 } else 2562 rv = -1; 2563 setstatus(rv); 2665 2564 } 2666 2565 break; … … 2669 2568 case TAND: 2670 2569 rv = execute(t->left, pin, pout, 0); 2671 if ((t1 = t->right) != NULL && (rv == 0) == (t->type == TAND)) 2570 t1 = t->right; 2571 if (t1 != NULL && (rv == 0) == (t->type == TAND)) 2672 2572 rv = execute(t1, pin, pout, 0); 2673 2573 break; … … 2676 2576 if (wp == NULL) { 2677 2577 wp = dolv + 1; 2678 if ((i = dolc) < 0) 2578 i = dolc; 2579 if (i < 0) 2679 2580 i = 0; 2680 2581 } else { … … 2716 2617 2717 2618 case TCASE: 2718 if ((cp = evalstr(t->str, DOSUB | DOTRIM)) == 0) 2619 cp = evalstr(t->str, DOSUB | DOTRIM); 2620 if (cp == NULL) 2719 2621 cp = ""; 2720 2622 … … 2723 2625 ((cp == NULL) ? "NULL" : cp))); 2724 2626 2725 if ((t1 = findcase(t->left, cp)) != NULL) { 2627 t1 = findcase(t->left, cp); 2628 if (t1 != NULL) { 2726 2629 DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1)); 2727 2630 rv = execute(t1, pin, pout, 0); … … 2732 2635 case TBRACE: 2733 2636 /* 2734 if (iopp = t->ioact) 2637 iopp = t->ioact; 2638 if (i) 2735 2639 while (*iopp) 2736 2640 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) { … … 2739 2643 } 2740 2644 */ 2741 if (rv >= 0 && (t1 = t->left)) 2742 rv = execute(t1, pin, pout, 0); 2645 if (rv >= 0) { 2646 t1 = t->left; 2647 if (t1) { 2648 rv = execute(t1, pin, pout, 0); 2649 } 2650 } 2743 2651 break; 2744 2652 2745 2653 }; 2746 2654 2747 2655 broken: 2748 2656 t->words = wp2; 2749 2657 isbreak = 0; … … 2756 2664 } 2757 2665 2758 if ((i = trapset) != 0) { 2666 i = trapset; 2667 if (i != 0) { 2759 2668 trapset = 0; 2760 2669 runtrap(i); … … 2762 2671 2763 2672 DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv)); 2764 return (rv); 2765 } 2766 2767 static int 2768 forkexec(REGISTER struct op *t, int *pin, int *pout, int act, char **wp) 2673 return rv; 2674 } 2675 2676 typedef int (*builtin_func_ptr)(struct op *); 2677 2678 static builtin_func_ptr inbuilt(const char *s) 2679 { 2680 const struct builtincmd *bp; 2681 2682 for (bp = builtincmds; bp->name; bp++) 2683 if (strcmp(bp->name, s) == 0) 2684 return bp->builtinfunc; 2685 return NULL; 2686 } 2687 2688 static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) 2769 2689 { 2770 2690 pid_t newpid; 2771 2691 int i, rv; 2772 int (*shcom) (struct op *)= NULL;2773 REGISTERint f;2774 c har *cp = NULL;2692 builtin_func_ptr shcom = NULL; 2693 int f; 2694 const char *cp = NULL; 2775 2695 struct ioword **iopp; 2776 2696 int resetsig; … … 2802 2722 ((t->words == NULL) ? "NULL" : t->words[0]))); 2803 2723 2804 /* Hard to know how many words there are, be careful of garbage pointer values */2805 /* They are likely to cause "PCI bus fault" errors */2806 #if 02807 DBGPRINTF7(("FORKEXEC: t->words is %s, t->words[1] is %s\n",2808 ((t->words == NULL) ? "NULL" : t->words[0]),2809 ((t->words == NULL) ? "NULL" : t->words[1])));2810 DBGPRINTF7(("FORKEXEC: wp is %s, wp[1] is %s\n",2811 ((wp == NULL) ? "NULL" : wp[0]),2812 ((wp[1] == NULL) ? "NULL" : wp[1])));2813 DBGPRINTF7(("FORKEXEC: wp2 is %s, wp[3] is %s\n",2814 ((wp[2] == NULL) ? "NULL" : wp[2]),2815 ((wp[3] == NULL) ? "NULL" : wp[3])));2816 #endif2817 2818 2819 2724 owp = wp; 2820 2725 resetsig = 0; 2821 2726 rv = -1; /* system-detected error */ 2822 2727 if (t->type == TCOM) { 2823 while ((cp = *wp++) != NULL); 2728 while (*wp++ != NULL) 2729 continue; 2824 2730 cp = *wp; 2825 2731 2826 2732 /* strip all initial assignments */ 2827 2733 /* not correct wrt PATH=yyy command etc */ 2828 if ( flag['x']) {2734 if (FLAG['x']) { 2829 2735 DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n", 2830 2736 cp, wp, owp)); 2831 2737 echo(cp ? wp : owp); 2832 2738 } 2833 #if 02834 DBGPRINTF9(("FORKEXEC: t->words is %s, t->words[1] is %s\n",2835 ((t->words == NULL) ? "NULL" : t->words[0]),2836 ((t->words == NULL) ? "NULL" : t->words[1])));2837 DBGPRINTF9(("FORKEXEC: wp is %s, wp[1] is %s\n",2838 ((wp == NULL) ? "NULL" : wp[0]),2839 ((wp == NULL) ? "NULL" : wp[1])));2840 #endif2841 2739 2842 2740 if (cp == NULL && t->ioact == NULL) { 2843 while ((cp = *owp++) != NULL && assign(cp, COPYV)); 2741 while ((cp = *owp++) != NULL && assign(cp, COPYV)) 2742 continue; 2844 2743 DBGPRINTF(("FORKEXEC: returning setstatus()\n")); 2845 return (setstatus(0)); 2846 } else if (cp != NULL) { 2744 return setstatus(0); 2745 } 2746 if (cp != NULL) { 2847 2747 shcom = inbuilt(cp); 2848 2748 } … … 2852 2752 f = act; 2853 2753 2854 #if 02855 DBGPRINTF3(("FORKEXEC: t->words is %s, t->words[1] is %s\n",2856 ((t->words == NULL) ? "NULL" : t->words[0]),2857 ((t->words == NULL) ? "NULL" : t->words[1])));2858 #endif2859 2754 DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom, 2860 2755 f & FEXEC, owp)); … … 2875 2770 2876 2771 if (newpid == -1) { 2877 DBGPRINTF(("FORKEXEC: ERROR, unable to vfork()!\n")); 2878 return (-1); 2879 } 2880 2881 2882 if (newpid > 0) { /* Parent */ 2883 2772 DBGPRINTF(("FORKEXEC: ERROR, cannot vfork()!\n")); 2773 return -1; 2774 } 2775 2776 if (newpid > 0) { /* Parent */ 2884 2777 /* Restore values */ 2885 2778 pin = hpin; … … 2890 2783 brklist = hbrklist; 2891 2784 execflg = hexecflg; 2892 2893 2785 /* moved up 2894 2786 if (i == -1) 2895 return (rv);2787 return rv; 2896 2788 */ 2897 2898 2789 if (pin != NULL) 2899 2790 closepipe(pin); … … 2917 2808 } 2918 2809 2919 2920 2810 if (owp != NULL) 2921 2811 while ((cp = *owp++) != NULL && assign(cp, COPYV)) … … 2928 2818 if (forked) 2929 2819 _exit(-1); 2930 return (-1);2820 return -1; 2931 2821 } 2932 2822 #endif 2933 2823 2934 2824 if (pin != NULL) { 2935 dup2(pin[0], 0);2936 closepipe(pin);2825 xmove_fd(pin[0], 0); 2826 if (pin[1] != 0) close(pin[1]); 2937 2827 } 2938 2828 if (pout != NULL) { 2939 dup2(pout[1], 1); 2940 closepipe(pout); 2941 } 2942 2943 if ((iopp = t->ioact) != NULL) { 2829 xmove_fd(pout[1], 1); 2830 if (pout[1] != 1) close(pout[0]); 2831 } 2832 2833 iopp = t->ioact; 2834 if (iopp != NULL) { 2944 2835 if (shcom != NULL && shcom != doexec) { 2945 2836 prs(cp); … … 2947 2838 if (forked) 2948 2839 _exit(-1); 2949 return (-1);2840 return -1; 2950 2841 } 2951 2842 while (*iopp) … … 2953 2844 if (forked) 2954 2845 _exit(rv); 2955 return (rv);2846 return rv; 2956 2847 } 2957 2848 } … … 2962 2853 _exit(i); 2963 2854 DBGPRINTF(("FORKEXEC: returning i=%d\n", i)); 2964 return (i);2855 return i; 2965 2856 } 2966 2857 … … 2996 2887 * within pipelines. 2997 2888 */ 2998 static int iosetup(REGISTER struct ioword *iop, int pipein, int pipeout) 2999 { 3000 REGISTER int u = -1; 3001 char *cp = NULL, *msg; 2889 static int iosetup(struct ioword *iop, int pipein, int pipeout) 2890 { 2891 int u = -1; 2892 char *cp = NULL; 2893 const char *msg; 3002 2894 3003 2895 DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop, … … 3008 2900 3009 2901 if (pipein && iop->io_unit == 0) 3010 return (0);2902 return 0; 3011 2903 3012 2904 if (pipeout && iop->io_unit == 1) 3013 return (0);2905 return 0; 3014 2906 3015 2907 msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create"; 3016 2908 if ((iop->io_flag & IOHERE) == 0) { 3017 cp = iop->io_name; 3018 if ((cp = evalstr(cp, DOSUB | DOTRIM)) == NULL) 3019 return (1); 2909 cp = iop->io_name; /* huh?? */ 2910 cp = evalstr(cp, DOSUB | DOTRIM); 2911 if (cp == NULL) 2912 return 1; 3020 2913 } 3021 2914 … … 3024 2917 prs(cp); 3025 2918 err(": illegal >& argument"); 3026 return (1);2919 return 1; 3027 2920 } 3028 2921 if (*cp == '-') … … 3032 2925 switch (iop->io_flag) { 3033 2926 case IOREAD: 3034 u = open(cp, 0);2927 u = open(cp, O_RDONLY); 3035 2928 break; 3036 2929 … … 3038 2931 case IOHERE | IOXHERE: 3039 2932 u = herein(iop->io_name, iop->io_flag & IOXHERE); 3040 cp = "here file";2933 cp = (char*)"here file"; 3041 2934 break; 3042 2935 3043 2936 case IOWRITE | IOCAT: 3044 if ((u = open(cp, 1)) >= 0) { 3045 lseek(u, (long) 0, 2); 2937 u = open(cp, O_WRONLY); 2938 if (u >= 0) { 2939 lseek(u, (long) 0, SEEK_END); 3046 2940 break; 3047 2941 } … … 3056 2950 case IOCLOSE: 3057 2951 close(iop->io_unit); 3058 return (0);2952 return 0; 3059 2953 } 3060 2954 if (u < 0) { … … 3062 2956 prs(": cannot "); 3063 2957 warn(msg); 3064 return (1); 3065 } else { 3066 if (u != iop->io_unit) { 3067 dup2(u, iop->io_unit); 3068 close(u); 3069 } 3070 } 3071 return (0); 3072 } 3073 3074 static void echo(REGISTER char **wp) 3075 { 3076 REGISTER int i; 3077 3078 prs("+"); 3079 for (i = 0; wp[i]; i++) { 3080 if (i) 3081 prs(" "); 3082 prs(wp[i]); 3083 } 3084 prs("\n"); 3085 } 3086 3087 static struct op **find1case(struct op *t, char *w) 3088 { 3089 REGISTER struct op *t1; 3090 struct op **tp; 3091 REGISTER char **wp, *cp; 3092 3093 3094 if (t == NULL) { 3095 DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n")); 3096 return ((struct op **) NULL); 3097 } 3098 3099 DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type, 3100 T_CMD_NAMES[t->type])); 3101 3102 if (t->type == TLIST) { 3103 if ((tp = find1case(t->left, w)) != NULL) { 3104 DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp)); 3105 return (tp); 3106 } 3107 t1 = t->right; /* TPAT */ 3108 } else 3109 t1 = t; 3110 3111 for (wp = t1->words; *wp;) 3112 if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp)) { 3113 DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n", 3114 &t1->left)); 3115 return (&t1->left); 3116 } 3117 3118 DBGPRINTF(("FIND1CASE: returning NULL\n")); 3119 return ((struct op **) NULL); 3120 } 3121 3122 static struct op *findcase(struct op *t, char *w) 3123 { 3124 REGISTER struct op **tp; 3125 3126 return ((tp = find1case(t, w)) != NULL ? *tp : (struct op *) NULL); 2958 return 1; 2959 } 2960 if (u != iop->io_unit) { 2961 dup2(u, iop->io_unit); 2962 close(u); 2963 } 2964 return 0; 3127 2965 } 3128 2966 … … 3143 2981 * unless `canintr' is true. 3144 2982 */ 3145 static int waitfor( REGISTERint lastpid, int canintr)3146 { 3147 REGISTERint pid, rv;2983 static int waitfor(int lastpid, int canintr) 2984 { 2985 int pid, rv; 3148 2986 int s; 3149 2987 int oheedint = heedint; … … 3157 2995 break; 3158 2996 } else { 3159 if ((rv = WAITSIG(s)) != 0) { 3160 if (rv < NSIGNAL) { 2997 rv = WAITSIG(s); 2998 if (rv != 0) { 2999 if (rv < ARRAY_SIZE(signame)) { 3161 3000 if (signame[rv] != NULL) { 3162 3001 if (pid != lastpid) { … … 3177 3016 if (WAITCORE(s)) 3178 3017 prs(" - core dumped"); 3179 if (rv >= NSIGNAL|| signame[rv])3018 if (rv >= ARRAY_SIZE(signame) || signame[rv]) 3180 3019 prs("\n"); 3181 3020 rv = -1; … … 3195 3034 } 3196 3035 } 3197 return (rv);3198 } 3199 3200 static int setstatus( REGISTERint s)3036 return rv; 3037 } 3038 3039 static int setstatus(int s) 3201 3040 { 3202 3041 exstat = s; 3203 3042 setval(lookup("?"), putn(s)); 3204 return (s);3043 return s; 3205 3044 } 3206 3045 … … 3210 3049 * execvp might be used. 3211 3050 */ 3212 static char *rexecve(char *c, char **v, char **envp) 3213 { 3214 REGISTER int i; 3215 REGISTER char *sp, *tp; 3051 static const char *rexecve(char *c, char **v, char **envp) 3052 { 3053 int i; 3054 const char *sp; 3055 char *tp; 3216 3056 int eacces = 0, asis = 0; 3217 3057 char *name = c; 3218 3058 3219 if (ENABLE_FEATURE_SH_STANDALONE_SHELL) { 3220 optind = 1; 3059 if (ENABLE_FEATURE_SH_STANDALONE) { 3221 3060 if (find_applet_by_name(name)) { 3222 3061 /* We have to exec here since we vforked. Running 3223 * run_applet_ by_name() won't work and bad things3062 * run_applet_and_exit() won't work and bad things 3224 3063 * will happen. */ 3225 execve( CONFIG_BUSYBOX_EXEC_PATH, v, envp);3064 execve(bb_busybox_exec_path, v, envp); 3226 3065 } 3227 3066 } … … 3230 3069 3231 3070 sp = any('/', c) ? "" : path->value; 3232 asis = *sp == '\0';3071 asis = (*sp == '\0'); 3233 3072 while (asis || *sp != '\0') { 3234 3073 asis = 0; 3235 3074 tp = e.linep; 3236 for (; *sp != '\0'; tp++) 3237 if ((*tp = *sp++) == ':') { 3238 asis = *sp == '\0'; 3075 for (; *sp != '\0'; tp++) { 3076 *tp = *sp++; 3077 if (*tp == ':') { 3078 asis = (*sp == '\0'); 3239 3079 break; 3240 3080 } 3081 } 3241 3082 if (tp != e.linep) 3242 3083 *tp++ = '/'; … … 3254 3095 execve(DEFAULT_SHELL, v, envp); 3255 3096 *v = tp; 3256 return ("no Shell");3097 return "no Shell"; 3257 3098 3258 3099 case ENOMEM: 3259 return ( (char *) bb_msg_memory_exhausted);3100 return (char *) bb_msg_memory_exhausted; 3260 3101 3261 3102 case E2BIG: 3262 return ("argument list too long");3103 return "argument list too long"; 3263 3104 3264 3105 case EACCES: … … 3267 3108 } 3268 3109 } 3269 return (errno == ENOENT ? "not found" : "cannot execute");3110 return errno == ENOENT ? "not found" : "cannot execute"; 3270 3111 } 3271 3112 … … 3298 3139 rv = -1; 3299 3140 3300 if (newenv(setjmp(errpt = ev)) == 0) { 3141 errpt = ev; 3142 if (newenv(setjmp(errpt)) == 0) { 3301 3143 wdlist = 0; 3302 3144 iolist = 0; … … 3304 3146 e.iobase = e.iop; 3305 3147 yynerrs = 0; 3306 if (setjmp(failpt = rt) == 0 && yyparse() == 0) 3148 failpt = rt; 3149 if (setjmp(failpt) == 0 && yyparse() == 0) 3307 3150 rv = execute(outtree, NOPIPE, NOPIPE, 0); 3308 3151 quitenv(); … … 3317 3160 freearea(areanum--); 3318 3161 3319 return (rv);3162 return rv; 3320 3163 } 3321 3164 … … 3331 3174 const struct builtincmd *x; 3332 3175 3333 p rintf("\nBuilt-in commands:\n");3334 printf("-------------------\n");3335 3336 for (col = 0, x = builtincmds; x->builtinfunc != NULL; x++) {3337 if (!x->name)3338 continue;3339 col += printf("% s%s", ((col == 0) ? "\t" : " "), x->name);3176 puts("\nBuilt-in commands:\n" 3177 "-------------------"); 3178 3179 col = 0; 3180 x = builtincmds; 3181 while (x->name) { 3182 col += printf("%c%s", ((col == 0) ? '\t' : ' '), x->name); 3340 3183 if (col > 60) { 3341 p rintf("\n");3184 puts(""); 3342 3185 col = 0; 3343 3186 } 3344 } 3345 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL 3187 x++; 3188 } 3189 #if ENABLE_FEATURE_SH_STANDALONE 3346 3190 { 3347 int i; 3348 const struct BB_applet *applet; 3349 extern const struct BB_applet applets[]; 3350 extern const size_t NUM_APPLETS; 3351 3352 for (i = 0, applet = applets; i < NUM_APPLETS; applet++, i++) { 3353 if (!applet->name) 3354 continue; 3355 3356 col += printf("%s%s", ((col == 0) ? "\t" : " "), applet->name); 3191 const struct bb_applet *applet = applets; 3192 3193 while (applet->name) { 3194 col += printf("%c%s", ((col == 0) ? '\t' : ' '), applet->name); 3357 3195 if (col > 60) { 3358 p rintf("\n");3196 puts(""); 3359 3197 col = 0; 3360 3198 } 3199 applet++; 3361 3200 } 3362 3201 } 3363 3202 #endif 3364 p rintf("\n\n");3203 puts("\n"); 3365 3204 return EXIT_SUCCESS; 3366 3205 } 3367 3206 3368 3369 3370 3207 static int dolabel(struct op *t) 3371 3208 { 3372 return (0); 3373 } 3374 3375 static int dochdir(REGISTER struct op *t) 3376 { 3377 REGISTER char *cp, *er; 3378 3379 if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL) 3209 return 0; 3210 } 3211 3212 static int dochdir(struct op *t) 3213 { 3214 const char *cp, *er; 3215 3216 cp = t->words[1]; 3217 if (cp == NULL) { 3218 cp = homedir->value; 3219 if (cp != NULL) 3220 goto do_cd; 3380 3221 er = ": no home directory"; 3381 else if (chdir(cp) < 0) 3222 } else { 3223 do_cd: 3224 if (chdir(cp) >= 0) 3225 return 0; 3382 3226 er = ": bad directory"; 3383 else 3384 return (0); 3227 } 3385 3228 prs(cp != NULL ? cp : "cd"); 3386 3229 err(er); 3387 return (1);3388 } 3389 3390 static int doshift( REGISTERstruct op *t)3391 { 3392 REGISTERint n;3230 return 1; 3231 } 3232 3233 static int doshift(struct op *t) 3234 { 3235 int n; 3393 3236 3394 3237 n = t->words[1] ? getn(t->words[1]) : 1; 3395 3238 if (dolc < n) { 3396 3239 err("nothing to shift"); 3397 return (1);3240 return 1; 3398 3241 } 3399 3242 dolv[n] = dolv[0]; … … 3401 3244 dolc -= n; 3402 3245 setval(lookup("#"), putn(dolc)); 3403 return (0);3246 return 0; 3404 3247 } 3405 3248 … … 3409 3252 static int dologin(struct op *t) 3410 3253 { 3411 REGISTERchar *cp;3254 const char *cp; 3412 3255 3413 3256 if (interactive) { … … 3419 3262 prs(": "); 3420 3263 err(cp); 3421 return (1); 3422 } 3423 3424 static int doumask(REGISTER struct op *t) 3425 { 3426 REGISTER int i, n; 3427 REGISTER char *cp; 3428 3429 if ((cp = t->words[1]) == NULL) { 3264 return 1; 3265 } 3266 3267 static int doumask(struct op *t) 3268 { 3269 int i, n; 3270 char *cp; 3271 3272 cp = t->words[1]; 3273 if (cp == NULL) { 3430 3274 i = umask(0); 3431 3275 umask(i); … … 3434 3278 putc('\n', stderr); 3435 3279 } else { 3280 /* huh??? '8','9' are not allowed! */ 3436 3281 for (n = 0; *cp >= '0' && *cp <= '9'; cp++) 3437 3282 n = n * 8 + (*cp - '0'); 3438 3283 umask(n); 3439 3284 } 3440 return (0);3441 } 3442 3443 static int doexec( REGISTERstruct op *t)3444 { 3445 REGISTERint i;3285 return 0; 3286 } 3287 3288 static int doexec(struct op *t) 3289 { 3290 int i; 3446 3291 jmp_buf ex; 3447 3292 xint *ofail; … … 3450 3295 for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++); 3451 3296 if (i == 0) 3452 return (1);3297 return 1; 3453 3298 execflg = 1; 3454 3299 ofail = failpt; 3455 if (setjmp(failpt = ex) == 0) 3300 failpt = ex; 3301 if (setjmp(failpt) == 0) 3456 3302 execute(t, NOPIPE, NOPIPE, FEXEC); 3457 3303 failpt = ofail; 3458 3304 execflg = 0; 3459 return (1);3305 return 1; 3460 3306 } 3461 3307 3462 3308 static int dodot(struct op *t) 3463 3309 { 3464 REGISTER int i; 3465 REGISTER char *sp, *tp; 3310 int i; 3311 const char *sp; 3312 char *tp; 3466 3313 char *cp; 3467 3314 int maltmp; … … 3469 3316 DBGPRINTF(("DODOT: enter, t=%p, tleft %p, tright %p, e.linep is %s\n", t, t->left, t->right, ((e.linep == NULL) ? "NULL" : e.linep))); 3470 3317 3471 if ((cp = t->words[1]) == NULL) { 3318 cp = t->words[1]; 3319 if (cp == NULL) { 3472 3320 DBGPRINTF(("DODOT: bad args, ret 0\n")); 3473 return (0); 3474 } else { 3475 DBGPRINTF(("DODOT: cp is %s\n", cp)); 3476 } 3321 return 0; 3322 } 3323 DBGPRINTF(("DODOT: cp is %s\n", cp)); 3477 3324 3478 3325 sp = any('/', cp) ? ":" : path->value; … … 3492 3339 3493 3340 /* Original code */ 3494 if ((i = open(e.linep, 0)) >= 0) { 3341 i = open(e.linep, O_RDONLY); 3342 if (i >= 0) { 3495 3343 exstat = 0; 3496 3344 maltmp = remap(i); … … 3501 3349 DBGPRINTF(("DODOT: returning exstat=%d\n", exstat)); 3502 3350 3503 return (exstat); 3504 } 3505 3506 } /* While */ 3351 return exstat; 3352 } 3353 } /* while */ 3507 3354 3508 3355 prs(cp); 3509 3356 err(": not found"); 3510 3357 3511 return (-1);3358 return -1; 3512 3359 } 3513 3360 3514 3361 static int dowait(struct op *t) 3515 3362 { 3516 REGISTER int i; 3517 REGISTER char *cp; 3518 3519 if ((cp = t->words[1]) != NULL) { 3363 int i; 3364 char *cp; 3365 3366 cp = t->words[1]; 3367 if (cp != NULL) { 3520 3368 i = getn(cp); 3521 3369 if (i == 0) 3522 return (0);3370 return 0; 3523 3371 } else 3524 3372 i = -1; 3525 3373 setstatus(waitfor(i, 1)); 3526 return (0);3374 return 0; 3527 3375 } 3528 3376 3529 3377 static int doread(struct op *t) 3530 3378 { 3531 REGISTERchar *cp, **wp;3532 REGISTERint nb = 0;3533 REGISTERint nl = 0;3379 char *cp, **wp; 3380 int nb = 0; 3381 int nl = 0; 3534 3382 3535 3383 if (t->words[1] == NULL) { 3536 3384 err("Usage: read name ..."); 3537 return (1);3385 return 1; 3538 3386 } 3539 3387 for (wp = t->words + 1; *wp; wp++) { 3540 for (cp = e.linep; !nl && cp < elinep - 1; cp++) 3541 if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||3542 (nl = (*cp == '\n')) || (wp[1] && any(*cp, ifs->value)))3388 for (cp = e.linep; !nl && cp < elinep - 1; cp++) { 3389 nb = read(0, cp, sizeof(*cp)); 3390 if (nb != sizeof(*cp)) 3543 3391 break; 3544 *cp = 0; 3392 nl = (*cp == '\n'); 3393 if (nl || (wp[1] && any(*cp, ifs->value))) 3394 break; 3395 } 3396 *cp = '\0'; 3545 3397 if (nb <= 0) 3546 3398 break; 3547 3399 setval(lookup(*wp), e.linep); 3548 3400 } 3549 return (nb <= 0);3550 } 3551 3552 static int doeval( REGISTERstruct op *t)3553 { 3554 return (RUN(awordlist, t->words + 1, wdchar));3555 } 3556 3557 static int dotrap( REGISTERstruct op *t)3558 { 3559 REGISTERint n, i;3560 REGISTERint resetsig;3401 return nb <= 0; 3402 } 3403 3404 static int doeval(struct op *t) 3405 { 3406 return RUN(awordlist, t->words + 1, wdchar); 3407 } 3408 3409 static int dotrap(struct op *t) 3410 { 3411 int n, i; 3412 int resetsig; 3561 3413 3562 3414 if (t->words[1] == NULL) { … … 3568 3420 prs("\n"); 3569 3421 } 3570 return (0);3422 return 0; 3571 3423 } 3572 3424 resetsig = isdigit(*t->words[1]); … … 3582 3434 setsig(n, SIG_IGN); 3583 3435 } else { 3584 if (interactive) 3436 if (interactive) { 3585 3437 if (n == SIGINT) 3586 3438 setsig(n, onintr); 3587 3439 else 3588 3440 setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL); 3589 else3441 } else 3590 3442 setsig(n, SIG_DFL); 3591 3443 } 3592 3444 } 3593 return (0);3445 return 0; 3594 3446 } 3595 3447 3596 3448 static int getsig(char *s) 3597 3449 { 3598 REGISTER int n; 3599 3600 if ((n = getn(s)) < 0 || n > _NSIG) { 3450 int n; 3451 3452 n = getn(s); 3453 if (n < 0 || n > _NSIG) { 3601 3454 err("trap: bad signal number"); 3602 3455 n = 0; 3603 3456 } 3604 return (n);3605 } 3606 3607 static void setsig( REGISTERint n, sighandler_t f)3457 return n; 3458 } 3459 3460 static void setsig(int n, sighandler_t f) 3608 3461 { 3609 3462 if (n == 0) … … 3617 3470 static int getn(char *as) 3618 3471 { 3619 REGISTERchar *s;3620 REGISTERint n, m;3472 char *s; 3473 int n, m; 3621 3474 3622 3475 s = as; … … 3632 3485 err(": bad number"); 3633 3486 } 3634 return (n * m);3487 return n * m; 3635 3488 } 3636 3489 3637 3490 static int dobreak(struct op *t) 3638 3491 { 3639 return (brkcontin(t->words[1], 1));3492 return brkcontin(t->words[1], 1); 3640 3493 } 3641 3494 3642 3495 static int docontinue(struct op *t) 3643 3496 { 3644 return (brkcontin(t->words[1], 0));3645 } 3646 3647 static int brkcontin( REGISTERchar *cp, int val)3648 { 3649 REGISTERstruct brkcon *bc;3650 REGISTERint nl;3497 return brkcontin(t->words[1], 0); 3498 } 3499 3500 static int brkcontin(char *cp, int val) 3501 { 3502 struct brkcon *bc; 3503 int nl; 3651 3504 3652 3505 nl = cp == NULL ? 1 : getn(cp); … … 3654 3507 nl = 999; 3655 3508 do { 3656 if ((bc = brklist) == NULL) 3509 bc = brklist; 3510 if (bc == NULL) 3657 3511 break; 3658 3512 brklist = bc->nextlev; … … 3660 3514 if (nl) { 3661 3515 err("bad break/continue level"); 3662 return (1);3516 return 1; 3663 3517 } 3664 3518 isbreak = val; … … 3669 3523 static int doexit(struct op *t) 3670 3524 { 3671 REGISTERchar *cp;3525 char *cp; 3672 3526 3673 3527 execflg = 0; 3674 if ((cp = t->words[1]) != NULL) 3528 cp = t->words[1]; 3529 if (cp != NULL) 3675 3530 setstatus(getn(cp)); 3676 3531 … … 3679 3534 leave(); 3680 3535 /* NOTREACHED */ 3681 return (0);3536 return 0; 3682 3537 } 3683 3538 … … 3685 3540 { 3686 3541 rdexp(t->words + 1, export, EXPORT); 3687 return (0);3542 return 0; 3688 3543 } 3689 3544 … … 3691 3546 { 3692 3547 rdexp(t->words + 1, ronly, RONLY); 3693 return (0);3548 return 0; 3694 3549 } 3695 3550 … … 3717 3572 } 3718 3573 3719 static void badid( REGISTERchar *s)3574 static void badid(char *s) 3720 3575 { 3721 3576 prs(s); … … 3723 3578 } 3724 3579 3725 static int doset(REGISTER struct op *t) 3726 { 3727 REGISTER struct var *vp; 3728 REGISTER char *cp; 3729 REGISTER int n; 3730 3731 if ((cp = t->words[1]) == NULL) { 3580 static int doset(struct op *t) 3581 { 3582 struct var *vp; 3583 char *cp; 3584 int n; 3585 3586 cp = t->words[1]; 3587 if (cp == NULL) { 3732 3588 for (vp = vlist; vp; vp = vp->next) 3733 3589 varput(vp->name, 1); 3734 return (0);3590 return 0; 3735 3591 } 3736 3592 if (*cp == '-') { … … 3738 3594 for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++); 3739 3595 if (*++cp == 0) 3740 flag['x'] = flag['v'] = 0;3741 else 3742 for (; *cp; cp++) 3596 FLAG['x'] = FLAG['v'] = 0; 3597 else { 3598 for (; *cp; cp++) { 3743 3599 switch (*cp) { 3744 3600 case 'e': 3745 3601 if (!interactive) 3746 flag['e']++;3602 FLAG['e']++; 3747 3603 break; 3748 3604 3749 3605 default: 3750 3606 if (*cp >= 'a' && *cp <= 'z') 3751 flag[(int) *cp]++;3607 FLAG[(int) *cp]++; 3752 3608 break; 3753 3609 } 3610 } 3611 } 3754 3612 setdash(); 3755 3613 } … … 3763 3621 setarea((char *) (dolv - 1), 0); 3764 3622 } 3765 return (0);3766 } 3767 3768 static void varput( REGISTERchar *s, int out)3623 return 0; 3624 } 3625 3626 static void varput(char *s, int out) 3769 3627 { 3770 3628 if (isalnum(*s) || *s == '_') { … … 3782 3640 { 3783 3641 struct tms buf; 3784 long intclk_tck = sysconf(_SC_CLK_TCK);3642 long clk_tck = sysconf(_SC_CLK_TCK); 3785 3643 3786 3644 times(&buf); … … 3798 3656 3799 3657 3800 static int (*inbuilt(char *s)) (struct op *) {3801 const struct builtincmd *bp;3802 3803 for (bp = builtincmds; bp->name != NULL; bp++)3804 if (strcmp(bp->name, s) == 0)3805 return (bp->builtinfunc);3806 3807 return (NULL);3808 }3809 3810 3658 /* -------- eval.c -------- */ 3811 3659 … … 3836 3684 wb = NULL; 3837 3685 wf = NULL; 3838 if (newenv(setjmp(errpt = ev)) == 0) { 3686 errpt = ev; 3687 if (newenv(setjmp(errpt)) == 0) { 3839 3688 while (*ap && isassign(*ap)) 3840 3689 expand(*ap++, &wb, f & ~DOGLOB); 3841 if ( flag['k']) {3690 if (FLAG['k']) { 3842 3691 for (wf = ap; *wf; wf++) { 3843 3692 if (isassign(*wf)) … … 3846 3695 } 3847 3696 for (wb = addword((char *) 0, wb); *ap; ap++) { 3848 if (! flag['k'] || !isassign(*ap))3697 if (!FLAG['k'] || !isassign(*ap)) 3849 3698 expand(*ap, &wb, f & ~DOKEY); 3850 3699 } … … 3855 3704 gflg = 1; 3856 3705 3857 return (gflg ? (char **) NULL : wp); 3858 } 3706 return gflg ? (char **) NULL : wp; 3707 } 3708 3859 3709 3860 3710 /* … … 3865 3715 static char **makenv(int all, struct wdblock *wb) 3866 3716 { 3867 REGISTERstruct var *vp;3717 struct var *vp; 3868 3718 3869 3719 DBGPRINTF5(("MAKENV: enter, all=%d\n", all)); … … 3873 3723 wb = addword(vp->name, wb); 3874 3724 wb = addword((char *) 0, wb); 3875 return (getwords(wb)); 3876 } 3877 3878 static char *evalstr(REGISTER char *cp, int f) 3879 { 3880 struct wdblock *wb; 3881 3882 DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f)); 3883 3884 wb = NULL; 3885 if (expand(cp, &wb, f)) { 3886 if (wb == NULL || wb->w_nword == 0 3887 || (cp = wb->w_words[0]) == NULL) 3888 cp = ""; 3889 DELETE(wb); 3890 } else 3891 cp = NULL; 3892 return (cp); 3893 } 3894 3895 static int expand(char *cp, REGISTER struct wdblock **wbp, int f) 3725 return getwords(wb); 3726 } 3727 3728 static int expand(const char *cp, struct wdblock **wbp, int f) 3896 3729 { 3897 3730 jmp_buf ev; 3731 char *xp; 3898 3732 3899 3733 #if __GNUC__ … … 3907 3741 3908 3742 if (cp == NULL) 3909 return (0); 3910 3911 if (!anys("$`'\"", cp) && 3912 !anys(ifs->value, cp) && ((f & DOGLOB) == 0 || !anys("[*?", cp))) { 3913 cp = strsave(cp, areanum); 3743 return 0; 3744 3745 if (!anys("$`'\"", cp) && !anys(ifs->value, cp) 3746 && ((f & DOGLOB) == 0 || !anys("[*?", cp)) 3747 ) { 3748 xp = strsave(cp, areanum); 3914 3749 if (f & DOTRIM) 3915 unquote(cp); 3916 *wbp = addword(cp, *wbp); 3917 return (1); 3918 } 3919 if (newenv(setjmp(errpt = ev)) == 0) { 3750 unquote(xp); 3751 *wbp = addword(xp, *wbp); 3752 return 1; 3753 } 3754 errpt = ev; 3755 if (newenv(setjmp(errpt)) == 0) { 3920 3756 PUSHIO(aword, cp, strchar); 3921 3757 e.iobase = e.iop; 3922 while (( cp = blank(f)) && gflg == 0) {3923 e.linep = cp;3924 cp = strsave(cp, areanum);3758 while ((xp = blank(f)) && gflg == 0) { 3759 e.linep = xp; 3760 xp = strsave(xp, areanum); 3925 3761 if ((f & DOGLOB) == 0) { 3926 3762 if (f & DOTRIM) 3927 unquote( cp);3928 *wbp = addword( cp, *wbp);3763 unquote(xp); 3764 *wbp = addword(xp, *wbp); 3929 3765 } else 3930 *wbp = glob( cp, *wbp);3766 *wbp = glob(xp, *wbp); 3931 3767 } 3932 3768 quitenv(); 3933 3769 } else 3934 3770 gflg = 1; 3935 return (gflg == 0); 3936 } 3771 return gflg == 0; 3772 } 3773 3774 static char *evalstr(char *cp, int f) 3775 { 3776 struct wdblock *wb; 3777 3778 DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f)); 3779 3780 wb = NULL; 3781 if (expand(cp, &wb, f)) { 3782 if (wb == NULL || wb->w_nword == 0 3783 || (cp = wb->w_words[0]) == NULL 3784 ) { 3785 // TODO: I suspect that 3786 // char *evalstr(char *cp, int f) is actually 3787 // const char *evalstr(const char *cp, int f)! 3788 cp = (char*)""; 3789 } 3790 DELETE(wb); 3791 } else 3792 cp = NULL; 3793 return cp; 3794 } 3795 3937 3796 3938 3797 /* … … 3941 3800 static char *blank(int f) 3942 3801 { 3943 REGISTERint c, c1;3944 REGISTERchar *sp;3802 int c, c1; 3803 char *sp; 3945 3804 int scanequals, foundequals; 3946 3805 … … 3951 3810 foundequals = 0; 3952 3811 3953 loop: 3954 switch (c = subgetc('"', foundequals)) { 3812 loop: 3813 c = subgetc('"', foundequals); 3814 switch (c) { 3955 3815 case 0: 3956 3816 if (sp == e.linep) 3957 return (0);3817 return 0; 3958 3818 *e.linep++ = 0; 3959 return (sp);3819 return sp; 3960 3820 3961 3821 default: … … 4002 3862 } 4003 3863 *e.linep++ = 0; 4004 return (sp);3864 return sp; 4005 3865 } 4006 3866 … … 4008 3868 * Get characters, substituting for ` and $ 4009 3869 */ 4010 static int subgetc( REGISTERchar ec, int quoted)4011 { 4012 REGISTERchar c;3870 static int subgetc(char ec, int quoted) 3871 { 3872 char c; 4013 3873 4014 3874 DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted)); 4015 3875 4016 3876 again: 4017 3877 c = my_getc(ec); 4018 3878 if (!INSUB() && ec != '\'') { 4019 3879 if (c == '`') { 4020 3880 if (grave(quoted) == 0) 4021 return (0);3881 return 0; 4022 3882 e.iop->task = XGRAVE; 4023 3883 goto again; 4024 3884 } 4025 if (c == '$' && (c = dollar(quoted)) == 0) { 4026 e.iop->task = XDOLL; 4027 goto again; 4028 } 4029 } 4030 return (c); 3885 if (c == '$') { 3886 c = dollar(quoted); 3887 if (c == 0) { 3888 e.iop->task = XDOLL; 3889 goto again; 3890 } 3891 } 3892 } 3893 return c; 4031 3894 } 4032 3895 … … 4039 3902 struct io *oiop; 4040 3903 char *dolp; 4041 REGISTERchar *s, c, *cp = NULL;3904 char *s, c, *cp = NULL; 4042 3905 struct var *vp; 4043 3906 … … 4068 3931 err("unclosed ${"); 4069 3932 gflg++; 4070 return (c);3933 return c; 4071 3934 } 4072 3935 } … … 4090 3953 e.linep = s; 4091 3954 PUSHIO(awordlist, dolv + 1, dolchar); 4092 return (0);3955 return 0; 4093 3956 } else { /* trap the nasty ${=} */ 4094 3957 s[0] = '1'; 4095 s[1] = 0;3958 s[1] = '\0'; 4096 3959 } 4097 3960 } 4098 3961 vp = lookup(s); 4099 if ((dolp = vp->value) == null) { 3962 dolp = vp->value; 3963 if (dolp == null) { 4100 3964 switch (c) { 4101 3965 case '=': … … 4124 3988 } else if (c == '+') 4125 3989 dolp = strsave(cp, areanum); 4126 if ( flag['u'] && dolp == null) {3990 if (FLAG['u'] && dolp == null) { 4127 3991 prs("unset variable: "); 4128 3992 err(s); … … 4131 3995 e.linep = s; 4132 3996 PUSHIO(aword, dolp, quoted ? qstrchar : strchar); 4133 return (0);3997 return 0; 4134 3998 } 4135 3999 … … 4140 4004 static int grave(int quoted) 4141 4005 { 4142 char *cp; 4143 REGISTER int i; 4006 /* moved to G: static char child_cmd[LINELIM]; */ 4007 4008 const char *cp; 4009 int i; 4144 4010 int j; 4145 4011 int pf[2]; 4146 static char child_cmd[LINELIM]; 4147 char *src; 4012 const char *src; 4148 4013 char *dest; 4149 4014 int count; … … 4158 4023 #endif 4159 4024 4160 for (cp = e.iop->argp->aword; *cp != '`'; cp++) 4025 for (cp = e.iop->argp->aword; *cp != '`'; cp++) { 4161 4026 if (*cp == 0) { 4162 4027 err("no closing `"); 4163 return (0); 4164 } 4028 return 0; 4029 } 4030 } 4165 4031 4166 4032 /* string copy with dollar expansion */ … … 4208 4074 default: 4209 4075 err("unclosed ${\n"); 4210 return (0);4076 return 0; 4211 4077 } 4212 4078 if (operator) { … … 4218 4084 if (*src != '}') { 4219 4085 err("unclosed ${\n"); 4220 return (0);4086 return 0; 4221 4087 } 4222 4088 } … … 4253 4119 else if (operator == '?') { 4254 4120 err(alt_value); 4255 return (0);4121 return 0; 4256 4122 } else if (alt_index && (operator != '+')) { 4257 4123 value = alt_value; … … 4275 4141 4276 4142 if (openpipe(pf) < 0) 4277 return (0);4143 return 0; 4278 4144 4279 4145 while ((i = vfork()) == -1 && errno == EAGAIN); … … 4284 4150 closepipe(pf); 4285 4151 err((char *) bb_msg_memory_exhausted); 4286 return (0);4152 return 0; 4287 4153 } 4288 4154 if (i != 0) { … … 4291 4157 close(pf[1]); 4292 4158 PUSHIO(afile, remap(pf[0]), 4293 (int (*)(struct ioarg *)) ((quoted) ? qgravechar : 4294 gravechar)); 4295 return (1); 4159 (int (*)(struct ioarg *)) ((quoted) ? qgravechar : gravechar)); 4160 return 1; 4296 4161 } 4297 4162 /* allow trapped signals */ … … 4301 4166 signal(j, SIG_DFL); 4302 4167 4303 dup2(pf[1], 1); 4304 closepipe(pf); 4168 /* Testcase where below checks are needed: 4169 * close stdout & run this script: 4170 * files=`ls` 4171 * echo "$files" >zz 4172 */ 4173 xmove_fd(pf[1], 1); 4174 if (pf[0] != 1) close(pf[0]); 4305 4175 4306 4176 argument_list[0] = (char *) DEFAULT_SHELL; 4307 argument_list[1] = "-c";4177 argument_list[1] = (char *) "-c"; 4308 4178 argument_list[2] = child_cmd; 4309 argument_list[3] = 0;4179 argument_list[3] = NULL; 4310 4180 4311 4181 cp = rexecve(argument_list[0], argument_list, makenv(1, wb)); … … 4317 4187 4318 4188 4319 static char *unquote(REGISTER char *as) 4320 { 4321 REGISTER char *s; 4322 4323 if ((s = as) != NULL) 4189 static char *unquote(char *as) 4190 { 4191 char *s; 4192 4193 s = as; 4194 if (s != NULL) 4324 4195 while (*s) 4325 4196 *s++ &= ~QUOTE; 4326 return (as);4197 return as; 4327 4198 } 4328 4199 … … 4338 4209 4339 4210 static struct wdblock *cl, *nl; 4340 static c har spcl[]= "[?*";4211 static const char spcl[] ALIGN1= "[?*"; 4341 4212 4342 4213 static struct wdblock *glob(char *cp, struct wdblock *wb) 4343 4214 { 4344 REGISTERint i;4345 REGISTERchar *pp;4215 int i; 4216 char *pp; 4346 4217 4347 4218 if (cp == 0) 4348 return (wb);4219 return wb; 4349 4220 i = 0; 4350 4221 for (pp = cp; *pp; pp++) … … 4354 4225 *pp &= ~QUOTE; 4355 4226 if (i != 0) { 4356 for (cl = addword(scopy(cp), (struct wdblock *) 0); anyspcl(cl); 4357 cl = nl) { 4227 for (cl = addword(scopy(cp), NULL); anyspcl(cl); cl = nl) { 4358 4228 nl = newword(cl->w_nword * 2); 4359 4229 for (i = 0; i < cl->w_nword; i++) { /* for each argument */ … … 4377 4247 wb = addword(cl->w_words[i], wb); 4378 4248 DELETE(cl); 4379 return (wb);4249 return wb; 4380 4250 } 4381 4251 } 4382 4252 wb = addword(unquote(cp), wb); 4383 return (wb);4384 } 4385 4386 static void globname(char *we, REGISTERchar *pp)4387 { 4388 REGISTERchar *np, *cp;4253 return wb; 4254 } 4255 4256 static void globname(char *we, char *pp) 4257 { 4258 char *np, *cp; 4389 4259 char *name, *gp, *dp; 4390 4260 int k; … … 4415 4285 /* 4416 4286 if (ent[j].d_ino == 0) 4417 continue;4287 continue; 4418 4288 */ 4419 4289 strncpy(dname, de->d_name, NAME_MAX); … … 4445 4315 * the slashes come for free 4446 4316 */ 4447 static char *generate(char *start1, REGISTERchar *end1, char *middle, char *end)4317 static char *generate(char *start1, char *end1, char *middle, char *end) 4448 4318 { 4449 4319 char *p; 4450 REGISTER char *op, *xp; 4451 4452 p = op = 4453 space((int) (end1 - start1) + strlen(middle) + strlen(end) + 2); 4320 char *op, *xp; 4321 4322 p = op = space((int)(end1 - start1) + strlen(middle) + strlen(end) + 2); 4454 4323 for (xp = start1; xp != end1;) 4455 4324 *op++ = *xp++; … … 4457 4326 op--; 4458 4327 for (xp = end; (*op++ = *xp++) != '\0';); 4459 return (p);4460 } 4461 4462 static int anyspcl( REGISTERstruct wdblock *wb)4463 { 4464 REGISTERint i;4465 REGISTERchar **wd;4328 return p; 4329 } 4330 4331 static int anyspcl(struct wdblock *wb) 4332 { 4333 int i; 4334 char **wd; 4466 4335 4467 4336 wd = wb->w_words; 4468 4337 for (i = 0; i < wb->w_nword; i++) 4469 4338 if (anys(spcl, *wd++)) 4470 return (1);4471 return (0);4339 return 1; 4340 return 0; 4472 4341 } 4473 4342 4474 4343 static int xstrcmp(char *p1, char *p2) 4475 4344 { 4476 return (strcmp(*(char **) p1, *(char **) p2)); 4477 } 4345 return strcmp(*(char **) p1, *(char **) p2); 4346 } 4347 4478 4348 4479 4349 /* -------- word.c -------- */ 4480 4350 4481 static struct wdblock *newword( REGISTERint nw)4482 { 4483 REGISTERstruct wdblock *wb;4351 static struct wdblock *newword(int nw) 4352 { 4353 struct wdblock *wb; 4484 4354 4485 4355 wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *)); 4486 4356 wb->w_bsize = nw; 4487 4357 wb->w_nword = 0; 4488 return (wb);4489 } 4490 4491 static struct wdblock *addword(char *wd, REGISTERstruct wdblock *wb)4492 { 4493 REGISTERstruct wdblock *wb2;4494 REGISTERint nw;4358 return wb; 4359 } 4360 4361 static struct wdblock *addword(char *wd, struct wdblock *wb) 4362 { 4363 struct wdblock *wb2; 4364 int nw; 4495 4365 4496 4366 if (wb == NULL) 4497 4367 wb = newword(NSTART); 4498 if ((nw = wb->w_nword) >= wb->w_bsize) { 4368 nw = wb->w_nword; 4369 if (nw >= wb->w_bsize) { 4499 4370 wb2 = newword(nw * 2); 4500 4371 memcpy((char *) wb2->w_words, (char *) wb->w_words, … … 4505 4376 } 4506 4377 wb->w_words[wb->w_nword++] = wd; 4507 return (wb); 4508 } 4509 4510 static 4511 char **getwords(REGISTER struct wdblock *wb) 4512 { 4513 REGISTER char **wd; 4514 REGISTER int nb; 4378 return wb; 4379 } 4380 4381 static char **getwords(struct wdblock *wb) 4382 { 4383 char **wd; 4384 int nb; 4515 4385 4516 4386 if (wb == NULL) 4517 return ((char **) NULL);4387 return NULL; 4518 4388 if (wb->w_nword == 0) { 4519 4389 DELETE(wb); 4520 return ((char **) NULL);4390 return NULL; 4521 4391 } 4522 4392 wd = (char **) space(nb = sizeof(*wd) * wb->w_nword); 4523 4393 memcpy((char *) wd, (char *) wb->w_words, nb); 4524 4394 DELETE(wb); /* perhaps should done by caller */ 4525 return (wd);4395 return wd; 4526 4396 } 4527 4397 … … 4529 4399 static int globv; 4530 4400 4531 static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *))4532 {4533 func = a3;4534 globv = a2;4535 glob1(a0, a0 + a1 * a2);4536 }4537 4538 static void glob1(char *base, char *lim)4539 {4540 REGISTER char *i, *j;4541 int v2;4542 char *lptr, *hptr;4543 int c;4544 unsigned n;4545 4546 4547 v2 = globv;4548 4549 top:4550 if ((n = (int) (lim - base)) <= v2)4551 return;4552 n = v2 * (n / (2 * v2));4553 hptr = lptr = base + n;4554 i = base;4555 j = lim - v2;4556 for (;;) {4557 if (i < lptr) {4558 if ((c = (*func) (i, lptr)) == 0) {4559 glob2(i, lptr -= v2);4560 continue;4561 }4562 if (c < 0) {4563 i += v2;4564 continue;4565 }4566 }4567 4568 begin:4569 if (j > hptr) {4570 if ((c = (*func) (hptr, j)) == 0) {4571 glob2(hptr += v2, j);4572 goto begin;4573 }4574 if (c > 0) {4575 if (i == lptr) {4576 glob3(i, hptr += v2, j);4577 i = lptr += v2;4578 goto begin;4579 }4580 glob2(i, j);4581 j -= v2;4582 i += v2;4583 continue;4584 }4585 j -= v2;4586 goto begin;4587 }4588 4589 4590 if (i == lptr) {4591 if (lptr - base >= lim - hptr) {4592 glob1(hptr + v2, lim);4593 lim = lptr;4594 } else {4595 glob1(base, lptr);4596 base = hptr + v2;4597 }4598 goto top;4599 }4600 4601 4602 glob3(j, lptr -= v2, i);4603 j = hptr -= v2;4604 }4605 }4606 4607 static void glob2(char *i, char *j)4608 {4609 REGISTER char *index1, *index2, c;4610 int m;4611 4612 m = globv;4613 index1 = i;4614 index2 = j;4615 do {4616 c = *index1;4617 *index1++ = *index2;4618 *index2++ = c;4619 } while (--m);4620 }4621 4622 4401 static void glob3(char *i, char *j, char *k) 4623 4402 { 4624 REGISTERchar *index1, *index2, *index3;4403 char *index1, *index2, *index3; 4625 4404 int c; 4626 4405 int m; … … 4638 4417 } 4639 4418 4419 static void glob2(char *i, char *j) 4420 { 4421 char *index1, *index2, c; 4422 int m; 4423 4424 m = globv; 4425 index1 = i; 4426 index2 = j; 4427 do { 4428 c = *index1; 4429 *index1++ = *index2; 4430 *index2++ = c; 4431 } while (--m); 4432 } 4433 4434 static void glob1(char *base, char *lim) 4435 { 4436 char *i, *j; 4437 int v2; 4438 char *lptr, *hptr; 4439 int c; 4440 unsigned n; 4441 4442 v2 = globv; 4443 4444 top: 4445 n = (int) (lim - base); 4446 if (n <= v2) 4447 return; 4448 n = v2 * (n / (2 * v2)); 4449 hptr = lptr = base + n; 4450 i = base; 4451 j = lim - v2; 4452 for (;;) { 4453 if (i < lptr) { 4454 c = (*func) (i, lptr); 4455 if (c == 0) { 4456 lptr -= v2; 4457 glob2(i, lptr); 4458 continue; 4459 } 4460 if (c < 0) { 4461 i += v2; 4462 continue; 4463 } 4464 } 4465 4466 begin: 4467 if (j > hptr) { 4468 c = (*func) (hptr, j); 4469 if (c == 0) { 4470 hptr += v2; 4471 glob2(hptr, j); 4472 goto begin; 4473 } 4474 if (c > 0) { 4475 if (i == lptr) { 4476 hptr += v2; 4477 glob3(i, hptr, j); 4478 i = (lptr += v2); 4479 goto begin; 4480 } 4481 glob2(i, j); 4482 j -= v2; 4483 i += v2; 4484 continue; 4485 } 4486 j -= v2; 4487 goto begin; 4488 } 4489 4490 4491 if (i == lptr) { 4492 if (lptr - base >= lim - hptr) { 4493 glob1(hptr + v2, lim); 4494 lim = lptr; 4495 } else { 4496 glob1(base, lptr); 4497 base = hptr + v2; 4498 } 4499 goto top; 4500 } 4501 4502 lptr -= v2; 4503 glob3(j, lptr, i); 4504 j = (hptr -= v2); 4505 } 4506 } 4507 4508 static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *)) 4509 { 4510 func = a3; 4511 globv = a2; 4512 glob1(a0, a0 + a1 * a2); 4513 } 4514 4515 4640 4516 /* -------- io.c -------- */ 4641 4517 … … 4646 4522 static int my_getc(int ec) 4647 4523 { 4648 REGISTERint c;4524 int c; 4649 4525 4650 4526 if (e.linep > elinep) { … … 4652 4528 err("input line too long"); 4653 4529 gflg++; 4654 return (c);4530 return c; 4655 4531 } 4656 4532 c = readc(); … … 4659 4535 c = readc(); 4660 4536 if (c == '\n' && ec != '\"') 4661 return (my_getc(ec));4537 return my_getc(ec); 4662 4538 c |= QUOTE; 4663 4539 } 4664 4540 } 4665 return (c);4541 return c; 4666 4542 } 4667 4543 … … 4679 4555 static int readc(void) 4680 4556 { 4681 REGISTERint c;4557 int c; 4682 4558 4683 4559 RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase)); … … 4685 4561 for (; e.iop >= e.iobase; e.iop--) { 4686 4562 RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc)); 4687 if ((c = e.iop->peekc) != '\0') { 4563 c = e.iop->peekc; 4564 if (c != '\0') { 4688 4565 e.iop->peekc = 0; 4689 return (c); 4690 } else { 4691 if (e.iop->prev != 0) { 4692 if ((c = (*e.iop->iofn) (e.iop->argp, e.iop)) != '\0') { 4693 if (c == -1) { 4694 e.iop++; 4695 continue; 4696 } 4697 if (e.iop == iostack) 4698 ioecho(c); 4699 return (e.iop->prev = c); 4700 } else if (e.iop->task == XIO && e.iop->prev != '\n') { 4701 e.iop->prev = 0; 4702 if (e.iop == iostack) 4703 ioecho('\n'); 4704 return '\n'; 4566 return c; 4567 } 4568 if (e.iop->prev != 0) { 4569 c = (*e.iop->iofn)(e.iop->argp, e.iop); 4570 if (c != '\0') { 4571 if (c == -1) { 4572 e.iop++; 4573 continue; 4705 4574 } 4575 if (e.iop == iostack) 4576 ioecho(c); 4577 e.iop->prev = c; 4578 return e.iop->prev; 4706 4579 } 4707 if (e.iop->task == XIO) { 4708 if (multiline) { 4709 return e.iop->prev = 0; 4710 } 4711 if (interactive && e.iop == iostack + 1) { 4712 #ifdef CONFIG_FEATURE_COMMAND_EDITING 4713 current_prompt = prompt->value; 4580 if (e.iop->task == XIO && e.iop->prev != '\n') { 4581 e.iop->prev = 0; 4582 if (e.iop == iostack) 4583 ioecho('\n'); 4584 return '\n'; 4585 } 4586 } 4587 if (e.iop->task == XIO) { 4588 if (multiline) { 4589 e.iop->prev = 0; 4590 return e.iop->prev; 4591 } 4592 if (interactive && e.iop == iostack + 1) { 4593 #if ENABLE_FEATURE_EDITING 4594 current_prompt = prompt->value; 4714 4595 #else 4715 4596 prs(prompt->value); 4716 4597 #endif 4717 }4718 4598 } 4719 4599 } 4720 4721 4600 } /* FOR */ 4722 4601 4723 4602 if (e.iop >= iostack) { 4724 4603 RCPRINTF(("READC: return 0, e.iop %p\n", e.iop)); 4725 return (0);4604 return 0; 4726 4605 } 4727 4606 … … 4730 4609 4731 4610 /* NOTREACHED */ 4732 return (0);4611 return 0; 4733 4612 } 4734 4613 4735 4614 static void ioecho(char c) 4736 4615 { 4737 if ( flag['v'])4616 if (FLAG['v']) 4738 4617 write(2, &c, sizeof c); 4739 4618 } … … 4775 4654 if ((isatty(e.iop->argp->afile) == 0) 4776 4655 && (e.iop == &iostack[0] 4777 || lseek(e.iop->argp->afile, 0L, 1) != -1)) {4656 || lseek(e.iop->argp->afile, 0L, SEEK_CUR) != -1)) { 4778 4657 if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */ 4779 4658 bufid = AFID_ID; /* AFID_ID = 0 */ … … 4797 4676 e.iop->task = XIO; 4798 4677 else if (fn == (int (*)(struct ioarg *)) gravechar 4799 4678 || fn == (int (*)(struct ioarg *)) qgravechar) 4800 4679 e.iop->task = XGRAVE; 4801 4680 else 4802 4681 e.iop->task = XOTHER; 4803 4804 return;4805 4682 } 4806 4683 4807 4684 static struct io *setbase(struct io *ip) 4808 4685 { 4809 REGISTERstruct io *xp;4686 struct io *xp; 4810 4687 4811 4688 xp = e.iobase; 4812 4689 e.iobase = ip; 4813 return (xp);4690 return xp; 4814 4691 } 4815 4692 … … 4821 4698 * Produce the characters of a string, then a newline, then EOF. 4822 4699 */ 4823 static int nlchar( REGISTERstruct ioarg *ap)4824 { 4825 REGISTERint c;4700 static int nlchar(struct ioarg *ap) 4701 { 4702 int c; 4826 4703 4827 4704 if (ap->aword == NULL) 4828 return (0); 4829 if ((c = *ap->aword++) == 0) { 4705 return 0; 4706 c = *ap->aword++; 4707 if (c == 0) { 4830 4708 ap->aword = NULL; 4831 return ('\n');4832 } 4833 return (c);4709 return '\n'; 4710 } 4711 return c; 4834 4712 } 4835 4713 … … 4838 4716 * in them, with a space after each word. 4839 4717 */ 4840 static int wdchar(REGISTER struct ioarg *ap) 4841 { 4842 REGISTER char c; 4843 REGISTER char **wl; 4844 4845 if ((wl = ap->awordlist) == NULL) 4846 return (0); 4718 static int wdchar(struct ioarg *ap) 4719 { 4720 char c; 4721 char **wl; 4722 4723 wl = ap->awordlist; 4724 if (wl == NULL) 4725 return 0; 4847 4726 if (*wl != NULL) { 4848 if ((c = *(*wl)++) != 0) 4849 return (c & 0177); 4727 c = *(*wl)++; 4728 if (c != 0) 4729 return c & 0177; 4850 4730 ap->awordlist++; 4851 return (' ');4731 return ' '; 4852 4732 } 4853 4733 ap->awordlist = NULL; 4854 return ('\n');4734 return '\n'; 4855 4735 } 4856 4736 … … 4859 4739 * producing a space between them. 4860 4740 */ 4861 static int dolchar(REGISTER struct ioarg *ap) 4862 { 4863 REGISTER char *wp; 4864 4865 if ((wp = *ap->awordlist++) != NULL) { 4741 static int dolchar(struct ioarg *ap) 4742 { 4743 char *wp; 4744 4745 wp = *ap->awordlist++; 4746 if (wp != NULL) { 4866 4747 PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar); 4867 return (-1);4868 } 4869 return (0);4870 } 4871 4872 static int xxchar( REGISTERstruct ioarg *ap)4873 { 4874 REGISTERint c;4748 return -1; 4749 } 4750 return 0; 4751 } 4752 4753 static int xxchar(struct ioarg *ap) 4754 { 4755 int c; 4875 4756 4876 4757 if (ap->aword == NULL) 4877 return (0); 4878 if ((c = *ap->aword++) == '\0') { 4758 return 0; 4759 c = *ap->aword++; 4760 if (c == '\0') { 4879 4761 ap->aword = NULL; 4880 return (' ');4881 } 4882 return (c);4762 return ' '; 4763 } 4764 return c; 4883 4765 } 4884 4766 … … 4886 4768 * Produce the characters from a single word (string). 4887 4769 */ 4888 static int strchar(REGISTER struct ioarg *ap) 4889 { 4890 REGISTER int c; 4891 4892 if (ap->aword == NULL || (c = *ap->aword++) == 0) 4893 return (0); 4894 return (c); 4770 static int strchar(struct ioarg *ap) 4771 { 4772 if (ap->aword == NULL) 4773 return 0; 4774 return *ap->aword++; 4895 4775 } 4896 4776 … … 4898 4778 * Produce quoted characters from a single word (string). 4899 4779 */ 4900 static int qstrchar(REGISTER struct ioarg *ap) 4901 { 4902 REGISTER int c; 4903 4904 if (ap->aword == NULL || (c = *ap->aword++) == 0) 4905 return (0); 4906 return (c | QUOTE); 4780 static int qstrchar(struct ioarg *ap) 4781 { 4782 int c; 4783 4784 if (ap->aword == NULL) 4785 return 0; 4786 c = *ap->aword++; 4787 if (c) 4788 c |= QUOTE; 4789 return c; 4907 4790 } 4908 4791 … … 4910 4793 * Return the characters from a file. 4911 4794 */ 4912 static int filechar( REGISTERstruct ioarg *ap)4913 { 4914 REGISTERint i;4795 static int filechar(struct ioarg *ap) 4796 { 4797 int i; 4915 4798 char c; 4916 4799 struct iobuf *bp = ap->afbuf; 4917 4800 4918 4801 if (ap->afid != AFID_NOBUF) { 4919 i f ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {4920 4802 i = (ap->afid != bp->id); 4803 if (i || bp->bufp == bp->ebufp) { 4921 4804 if (i) 4922 lseek(ap->afile, ap->afpos, 0);4805 lseek(ap->afile, ap->afpos, SEEK_SET); 4923 4806 4924 4807 i = safe_read(ap->afile, bp->buf, sizeof(bp->buf)); 4925 4926 4808 if (i <= 0) { 4927 4809 closef(ap->afile); … … 4930 4812 4931 4813 bp->id = ap->afid; 4932 bp->ebufp = (bp->bufp = bp->buf) + i; 4814 bp->bufp = bp->buf; 4815 bp->ebufp = bp->bufp + i; 4933 4816 } 4934 4817 … … 4936 4819 return *bp->bufp++ & 0177; 4937 4820 } 4938 #if def CONFIG_FEATURE_COMMAND_EDITING4821 #if ENABLE_FEATURE_EDITING 4939 4822 if (interactive && isatty(ap->afile)) { 4940 static char mycommand[BUFSIZ];4823 /* moved to G: static char filechar_cmdbuf[BUFSIZ]; */ 4941 4824 static int position = 0, size = 0; 4942 4825 4943 4826 while (size == 0 || position >= size) { 4944 cmdedit_read_input(current_prompt, mycommand);4945 size = strlen( mycommand);4827 read_line_input(current_prompt, filechar_cmdbuf, BUFSIZ, line_input_state); 4828 size = strlen(filechar_cmdbuf); 4946 4829 position = 0; 4947 4830 } 4948 c = mycommand[position];4831 c = filechar_cmdbuf[position]; 4949 4832 position++; 4950 return (c);4951 } else4833 return c; 4834 } 4952 4835 #endif 4953 4954 { 4955 i = safe_read(ap->afile, &c, sizeof(c)); 4956 return (i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0)); 4957 } 4836 i = safe_read(ap->afile, &c, sizeof(c)); 4837 return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0); 4958 4838 } 4959 4839 … … 4961 4841 * Return the characters from a here temp file. 4962 4842 */ 4963 static int herechar( REGISTERstruct ioarg *ap)4843 static int herechar(struct ioarg *ap) 4964 4844 { 4965 4845 char c; 4966 4967 4846 4968 4847 if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) { 4969 4848 close(ap->afile); 4970 c = 0; 4971 } 4972 return (c); 4973 4849 c = '\0'; 4850 } 4851 return c; 4974 4852 } 4975 4853 … … 4980 4858 static int gravechar(struct ioarg *ap, struct io *iop) 4981 4859 { 4982 REGISTER int c; 4983 4984 if ((c = qgravechar(ap, iop) & ~QUOTE) == '\n') 4860 int c; 4861 4862 c = qgravechar(ap, iop) & ~QUOTE; 4863 if (c == '\n') 4985 4864 c = ' '; 4986 return (c);4987 } 4988 4989 static int qgravechar( REGISTERstruct ioarg *ap, struct io *iop)4990 { 4991 REGISTERint c;4865 return c; 4866 } 4867 4868 static int qgravechar(struct ioarg *ap, struct io *iop) 4869 { 4870 int c; 4992 4871 4993 4872 DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop)); … … 4996 4875 if (iop->nlcount) { 4997 4876 iop->nlcount--; 4998 return ('\n' | QUOTE);4877 return '\n' | QUOTE; 4999 4878 } 5000 4879 c = iop->xchar; … … 5006 4885 iop->xchar = c; 5007 4886 if (c == 0) 5008 return (c);4887 return c; 5009 4888 iop->nlcount--; 5010 4889 c = '\n'; 5011 4890 } 5012 return (c != 0 ? c | QUOTE : 0);4891 return c != 0 ? c | QUOTE : 0; 5013 4892 } 5014 4893 … … 5016 4895 * Return a single command (usually the first line) from a file. 5017 4896 */ 5018 static int linechar(REGISTER struct ioarg *ap) 5019 { 5020 REGISTER int c; 5021 5022 if ((c = filechar(ap)) == '\n') { 4897 static int linechar(struct ioarg *ap) 4898 { 4899 int c; 4900 4901 c = filechar(ap); 4902 if (c == '\n') { 5023 4903 if (!multiline) { 5024 4904 closef(ap->afile); … … 5026 4906 } 5027 4907 } 5028 return (c); 5029 } 5030 5031 static void prs(REGISTER const char *s) 5032 { 5033 if (*s) 5034 write(2, s, strlen(s)); 5035 } 5036 5037 static void prn(unsigned u) 5038 { 5039 prs(itoa(u)); 5040 } 5041 5042 static void closef(REGISTER int i) 5043 { 5044 if (i > 2) 5045 close(i); 5046 } 5047 5048 static void closeall(void) 5049 { 5050 REGISTER int u; 5051 5052 for (u = NUFILE; u < NOFILE;) 5053 close(u++); 5054 } 5055 4908 return c; 4909 } 5056 4910 5057 4911 /* 5058 4912 * remap fd into Shell's fd space 5059 4913 */ 5060 static int remap( REGISTERint fd)5061 { 5062 REGISTERint i;4914 static int remap(int fd) 4915 { 4916 int i; 5063 4917 int map[NOFILE]; 5064 4918 int newfd; 5065 5066 4919 5067 4920 DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd)); … … 5085 4938 } 5086 4939 5087 return (fd); 5088 } 5089 5090 static int openpipe(REGISTER int *pv) 5091 { 5092 REGISTER int i; 5093 5094 if ((i = pipe(pv)) < 0) 4940 return fd; 4941 } 4942 4943 static int openpipe(int *pv) 4944 { 4945 int i; 4946 4947 i = pipe(pv); 4948 if (i < 0) 5095 4949 err("can't create pipe - try again"); 5096 return (i);5097 } 5098 5099 static void closepipe( REGISTERint *pv)4950 return i; 4951 } 4952 4953 static void closepipe(int *pv) 5100 4954 { 5101 4955 if (pv != NULL) { … … 5105 4959 } 5106 4960 4961 5107 4962 /* -------- here.c -------- */ 5108 4963 … … 5111 4966 */ 5112 4967 5113 static void markhere( REGISTERchar *s, struct ioword *iop)5114 { 5115 REGISTERstruct here *h, *lh;4968 static void markhere(char *s, struct ioword *iop) 4969 { 4970 struct here *h, *lh; 5116 4971 5117 4972 DBGPRINTF7(("MARKHERE: enter, s=%p\n", s)); 5118 4973 5119 4974 h = (struct here *) space(sizeof(struct here)); 5120 if (h == 0)4975 if (h == NULL) 5121 4976 return; 5122 4977 … … 5130 4985 if (inhere == 0) 5131 4986 inhere = h; 5132 else 5133 for (lh = inhere; lh != NULL; lh = lh->h_next) 4987 else { 4988 for (lh = inhere; lh != NULL; lh = lh->h_next) { 5134 4989 if (lh->h_next == 0) { 5135 4990 lh->h_next = h; 5136 4991 break; 5137 4992 } 4993 } 4994 } 5138 4995 iop->io_flag |= IOHERE | IOXHERE; 5139 for (s = h->h_tag; *s; s++) 4996 for (s = h->h_tag; *s; s++) { 5140 4997 if (*s & QUOTE) { 5141 4998 iop->io_flag &= ~IOXHERE; 5142 4999 *s &= ~QUOTE; 5143 5000 } 5001 } 5144 5002 h->h_dosub = iop->io_flag & IOXHERE; 5145 5003 } … … 5147 5005 static void gethere(void) 5148 5006 { 5149 REGISTERstruct here *h, *hp;5007 struct here *h, *hp; 5150 5008 5151 5009 DBGPRINTF7(("GETHERE: enter...\n")); … … 5163 5021 } 5164 5022 5165 static void readhere(char **name, REGISTERchar *s, int ec)5023 static void readhere(char **name, char *s, int ec) 5166 5024 { 5167 5025 int tf; 5168 5026 char tname[30] = ".msh_XXXXXX"; 5169 REGISTERint c;5027 int c; 5170 5028 jmp_buf ev; 5171 5029 char myline[LINELIM + 1]; … … 5179 5037 5180 5038 *name = strsave(tname, areanum); 5181 if (newenv(setjmp(errpt = ev)) != 0) 5039 errpt = ev; 5040 if (newenv(setjmp(errpt)) != 0) 5182 5041 unlink(tname); 5183 5042 else { … … 5186 5045 for (;;) { 5187 5046 if (interactive && e.iop <= iostack) { 5188 #if def CONFIG_FEATURE_COMMAND_EDITING5047 #if ENABLE_FEATURE_EDITING 5189 5048 current_prompt = cprompt->value; 5190 5049 #else … … 5224 5083 static int herein(char *hname, int xdoll) 5225 5084 { 5226 REGISTERint hf;5085 int hf; 5227 5086 int tf; 5228 5087 … … 5232 5091 #endif 5233 5092 if (hname == NULL) 5234 return (-1);5093 return -1; 5235 5094 5236 5095 DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll)); 5237 5096 5238 hf = open(hname, 0);5097 hf = open(hname, O_RDONLY); 5239 5098 if (hf < 0) 5240 return (-1);5099 return -1; 5241 5100 5242 5101 if (xdoll) { … … 5247 5106 tf = mkstemp(tname); 5248 5107 if (tf < 0) 5249 return (-1); 5250 if (newenv(setjmp(errpt = ev)) == 0) { 5108 return -1; 5109 errpt = ev; 5110 if (newenv(setjmp(errpt)) == 0) { 5251 5111 PUSHIO(afile, hf, herechar); 5252 5112 setbase(e.iop); … … 5259 5119 unlink(tname); 5260 5120 close(tf); 5261 tf = open(tname, 0);5121 tf = open(tname, O_RDONLY); 5262 5122 unlink(tname); 5263 return (tf);5264 } else5265 return (hf);5123 return tf; 5124 } 5125 return hf; 5266 5126 } 5267 5127 5268 5128 static void scraphere(void) 5269 5129 { 5270 REGISTERstruct here *h;5130 struct here *h; 5271 5131 5272 5132 DBGPRINTF7(("SCRAPHERE: enter...\n")); … … 5282 5142 static void freehere(int area) 5283 5143 { 5284 REGISTERstruct here *h, *hl;5144 struct here *h, *hl; 5285 5145 5286 5146 DBGPRINTF6(("FREEHERE: enter, area=%d\n", area)); … … 5299 5159 } 5300 5160 5161 5162 /* -------- sh.c -------- */ 5163 /* 5164 * shell 5165 */ 5166 5167 int msh_main(int argc, char **argv); 5168 int msh_main(int argc, char **argv) 5169 { 5170 int f; 5171 char *s; 5172 int cflag; 5173 char *name, **ap; 5174 int (*iof) (struct ioarg *); 5175 5176 PTR_TO_GLOBALS = xzalloc(sizeof(G)); 5177 sharedbuf.id = AFID_NOBUF; 5178 mainbuf.id = AFID_NOBUF; 5179 e.linep = line; 5180 elinep = line + sizeof(line) - 5; 5181 5182 #if ENABLE_FEATURE_EDITING 5183 line_input_state = new_line_input_t(FOR_SHELL); 5184 #endif 5185 5186 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ)); 5187 5188 initarea(); 5189 ap = environ; 5190 if (ap != NULL) { 5191 while (*ap) 5192 assign(*ap++, !COPYV); 5193 for (ap = environ; *ap;) 5194 export(lookup(*ap++)); 5195 } 5196 closeall(); 5197 areanum = 1; 5198 5199 shell = lookup("SHELL"); 5200 if (shell->value == null) 5201 setval(shell, (char *)DEFAULT_SHELL); 5202 export(shell); 5203 5204 homedir = lookup("HOME"); 5205 if (homedir->value == null) 5206 setval(homedir, "/"); 5207 export(homedir); 5208 5209 setval(lookup("$"), putn(getpid())); 5210 5211 path = lookup("PATH"); 5212 if (path->value == null) { 5213 /* Can be merged with same string elsewhere in bbox */ 5214 if (geteuid() == 0) 5215 setval(path, bb_default_root_path); 5216 else 5217 setval(path, bb_default_path); 5218 } 5219 export(path); 5220 5221 ifs = lookup("IFS"); 5222 if (ifs->value == null) 5223 setval(ifs, " \t\n"); 5224 5225 #ifdef MSHDEBUG 5226 mshdbg_var = lookup("MSHDEBUG"); 5227 if (mshdbg_var->value == null) 5228 setval(mshdbg_var, "0"); 5229 #endif 5230 5231 prompt = lookup("PS1"); 5232 #if ENABLE_FEATURE_EDITING_FANCY_PROMPT 5233 if (prompt->value == null) 5234 #endif 5235 setval(prompt, DEFAULT_USER_PROMPT); 5236 if (geteuid() == 0) { 5237 setval(prompt, DEFAULT_ROOT_PROMPT); 5238 prompt->status &= ~EXPORT; 5239 } 5240 cprompt = lookup("PS2"); 5241 #if ENABLE_FEATURE_EDITING_FANCY_PROMPT 5242 if (cprompt->value == null) 5243 #endif 5244 setval(cprompt, "> "); 5245 5246 iof = filechar; 5247 cflag = 0; 5248 name = *argv++; 5249 if (--argc >= 1) { 5250 if (argv[0][0] == '-' && argv[0][1] != '\0') { 5251 for (s = argv[0] + 1; *s; s++) 5252 switch (*s) { 5253 case 'c': 5254 prompt->status &= ~EXPORT; 5255 cprompt->status &= ~EXPORT; 5256 setval(prompt, ""); 5257 setval(cprompt, ""); 5258 cflag = 1; 5259 if (--argc > 0) 5260 PUSHIO(aword, *++argv, iof = nlchar); 5261 break; 5262 5263 case 'q': 5264 qflag = SIG_DFL; 5265 break; 5266 5267 case 's': 5268 /* standard input */ 5269 break; 5270 5271 case 't': 5272 prompt->status &= ~EXPORT; 5273 setval(prompt, ""); 5274 iof = linechar; 5275 break; 5276 5277 case 'i': 5278 interactive++; 5279 default: 5280 if (*s >= 'a' && *s <= 'z') 5281 FLAG[(int) *s]++; 5282 } 5283 } else { 5284 argv--; 5285 argc++; 5286 } 5287 5288 if (iof == filechar && --argc > 0) { 5289 setval(prompt, ""); 5290 setval(cprompt, ""); 5291 prompt->status &= ~EXPORT; 5292 cprompt->status &= ~EXPORT; 5293 5294 /* Shell is non-interactive, activate printf-based debug */ 5295 #ifdef MSHDEBUG 5296 mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0'); 5297 if (mshdbg < 0) 5298 mshdbg = 0; 5299 #endif 5300 DBGPRINTF(("MSH_MAIN: calling newfile()\n")); 5301 5302 name = *++argv; 5303 if (newfile(name)) 5304 exit(1); /* Exit on error */ 5305 } 5306 } 5307 5308 setdash(); 5309 5310 /* This won't be true if PUSHIO has been called, say from newfile() above */ 5311 if (e.iop < iostack) { 5312 PUSHIO(afile, 0, iof); 5313 if (isatty(0) && isatty(1) && !cflag) { 5314 interactive++; 5315 #if !ENABLE_FEATURE_SH_EXTRA_QUIET 5316 #ifdef MSHDEBUG 5317 printf("\n\n%s built-in shell (msh with debug)\n", bb_banner); 5318 #else 5319 printf("\n\n%s built-in shell (msh)\n", bb_banner); 5320 #endif 5321 printf("Enter 'help' for a list of built-in commands.\n\n"); 5322 #endif 5323 } 5324 } 5325 5326 signal(SIGQUIT, qflag); 5327 if (name && name[0] == '-') { 5328 interactive++; 5329 f = open(".profile", O_RDONLY); 5330 if (f >= 0) 5331 next(remap(f)); 5332 f = open("/etc/profile", O_RDONLY); 5333 if (f >= 0) 5334 next(remap(f)); 5335 } 5336 if (interactive) 5337 signal(SIGTERM, sig); 5338 5339 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 5340 signal(SIGINT, onintr); 5341 dolv = argv; 5342 dolc = argc; 5343 dolv[0] = name; 5344 if (dolc > 1) { 5345 for (ap = ++argv; --argc > 0;) { 5346 *ap = *argv++; 5347 if (assign(*ap, !COPYV)) { 5348 dolc--; /* keyword */ 5349 } else { 5350 ap++; 5351 } 5352 } 5353 } 5354 setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc)); 5355 5356 DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack)); 5357 5358 for (;;) { 5359 if (interactive && e.iop <= iostack) { 5360 #if ENABLE_FEATURE_EDITING 5361 current_prompt = prompt->value; 5362 #else 5363 prs(prompt->value); 5364 #endif 5365 } 5366 onecommand(); 5367 /* Ensure that getenv("PATH") stays current */ 5368 setenv("PATH", path->value, 1); 5369 } 5370 5371 DBGPRINTF(("MSH_MAIN: returning.\n")); 5372 } 5301 5373 5302 5374
Note:
See TracChangeset
for help on using the changeset viewer.