aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-19 22:45:43 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-19 22:45:43 +0000
commit75810c0feeb259a08290f2207314a358066997e0 (patch)
treecae26fc88e8f21cc6cc34b3f53b9de6cff27b9ac /shell/ash.c
parent26cff6c3a9282d8a928dee12f1952b669168fa97 (diff)
downloadbusybox-w32-75810c0feeb259a08290f2207314a358066997e0.tar.gz
busybox-w32-75810c0feeb259a08290f2207314a358066997e0.tar.bz2
busybox-w32-75810c0feeb259a08290f2207314a358066997e0.zip
ash: move ash_main() and helpers to end of ash.c, more fuctions renamed,
superfluous casts from memory allocators removed git-svn-id: svn://busybox.net/trunk/busybox@17933 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c805
1 files changed, 382 insertions, 423 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 532dad15a..e262c0e13 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -141,6 +141,7 @@ static char optlist[NOPTS];
141 141
142/* ============ Misc data */ 142/* ============ Misc data */
143 143
144static int isloginsh;
144/* pid of main shell */ 145/* pid of main shell */
145static int rootpid; 146static int rootpid;
146/* shell level: 0 for the main shell, 1 for its children, and so on */ 147/* shell level: 0 for the main shell, 1 for its children, and so on */
@@ -779,8 +780,6 @@ static char *endofname(const char *);
779 780
780/* shell.h */ 781/* shell.h */
781 782
782typedef void *pointer;
783
784static char nullstr[1]; /* zero length string */ 783static char nullstr[1]; /* zero length string */
785static const char spcstr[] = " "; 784static const char spcstr[] = " ";
786static const char snlfmt[] = "%s\n"; 785static const char snlfmt[] = "%s\n";
@@ -1356,7 +1355,7 @@ static const char syntax_index_table[258] = {
1356 1355
1357static int funcblocksize; /* size of structures in function */ 1356static int funcblocksize; /* size of structures in function */
1358static int funcstringsize; /* size of strings in node */ 1357static int funcstringsize; /* size of strings in node */
1359static pointer funcblock; /* block to allocate function from */ 1358static void *funcblock; /* block to allocate function from */
1360static char *funcstring; /* block to allocate strings from */ 1359static char *funcstring; /* block to allocate strings from */
1361 1360
1362static const short nodesize[26] = { 1361static const short nodesize[26] = {
@@ -1853,45 +1852,6 @@ static void initvar(void)
1853 } while (++vp < end); 1852 } while (++vp < end);
1854} 1853}
1855 1854
1856static void init(void)
1857{
1858
1859 /* from input.c: */
1860 {
1861 basepf.nextc = basepf.buf = basebuf;
1862 }
1863
1864 /* from trap.c: */
1865 {
1866 signal(SIGCHLD, SIG_DFL);
1867 }
1868
1869 /* from var.c: */
1870 {
1871 char **envp;
1872 char ppid[32];
1873 const char *p;
1874 struct stat st1, st2;
1875
1876 initvar();
1877 for (envp = environ; envp && *envp; envp++) {
1878 if (strchr(*envp, '=')) {
1879 setvareq(*envp, VEXPORT|VTEXTFIXED);
1880 }
1881 }
1882
1883 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1884 setvar("PPID", ppid, 0);
1885
1886 p = lookupvar("PWD");
1887 if (p)
1888 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
1889 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1890 p = 0;
1891 setpwd(p, 0);
1892 }
1893}
1894
1895/* PEOF (the end of file marker) */ 1855/* PEOF (the end of file marker) */
1896 1856
1897enum { 1857enum {
@@ -1989,8 +1949,7 @@ static void showjobs(FILE *, int);
1989 1949
1990 1950
1991static void readcmdfile(char *); 1951static void readcmdfile(char *);
1992static int cmdloop(int); 1952
1993
1994/* memalloc.h */ 1953/* memalloc.h */
1995 1954
1996 1955
@@ -2018,11 +1977,11 @@ static char *sstrend = stackbase.space + MINSIZE;
2018static int herefd = -1; 1977static int herefd = -1;
2019 1978
2020 1979
2021static pointer ckmalloc(size_t); 1980static void *ckmalloc(size_t);
2022static pointer ckrealloc(pointer, size_t); 1981static void *ckrealloc(void *, size_t);
2023static char *savestr(const char *); 1982static char *savestr(const char *);
2024static pointer stalloc(size_t); 1983static void *stalloc(size_t);
2025static void stunalloc(pointer); 1984static void stunalloc(void *);
2026static void setstackmark(struct stackmark *); 1985static void setstackmark(struct stackmark *);
2027static void popstackmark(struct stackmark *); 1986static void popstackmark(struct stackmark *);
2028static void growstackblock(void); 1987static void growstackblock(void);
@@ -2098,7 +2057,6 @@ static char *optptr; /* used by nextopt */
2098static char *minusc; /* argument to -c option */ 2057static char *minusc; /* argument to -c option */
2099 2058
2100 2059
2101static void procargs(int, char **);
2102static void optschanged(void); 2060static void optschanged(void);
2103static void setparam(char **); 2061static void setparam(char **);
2104static void freeparam(volatile struct shparam *); 2062static void freeparam(volatile struct shparam *);
@@ -2187,27 +2145,19 @@ static void
2187reset(void) 2145reset(void)
2188{ 2146{
2189 /* from eval.c: */ 2147 /* from eval.c: */
2190 { 2148 evalskip = 0;
2191 evalskip = 0; 2149 loopnest = 0;
2192 loopnest = 0;
2193 }
2194 2150
2195 /* from input.c: */ 2151 /* from input.c: */
2196 { 2152 parselleft = parsenleft = 0; /* clear input buffer */
2197 parselleft = parsenleft = 0; /* clear input buffer */ 2153 popallfiles();
2198 popallfiles();
2199 }
2200 2154
2201 /* from parser.c: */ 2155 /* from parser.c: */
2202 { 2156 tokpushback = 0;
2203 tokpushback = 0; 2157 checkkwd = 0;
2204 checkkwd = 0;
2205 }
2206 2158
2207 /* from redir.c: */ 2159 /* from redir.c: */
2208 { 2160 clearredir(0);
2209 clearredir(0);
2210 }
2211} 2161}
2212 2162
2213#if ENABLE_ASH_ALIAS 2163#if ENABLE_ASH_ALIAS
@@ -4578,7 +4528,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
4578 } else { 4528 } else {
4579 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ 4529 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4580 rmescapes(p); 4530 rmescapes(p);
4581 sp = (struct strlist *)stalloc(sizeof(struct strlist)); 4531 sp = stalloc(sizeof(*sp));
4582 sp->text = p; 4532 sp->text = p;
4583 *exparg.lastp = sp; 4533 *exparg.lastp = sp;
4584 exparg.lastp = &sp->next; 4534 exparg.lastp = &sp->next;
@@ -5386,7 +5336,7 @@ recordregion(int start, int end, int nulonly)
5386 ifsp = &ifsfirst; 5336 ifsp = &ifsfirst;
5387 } else { 5337 } else {
5388 INT_OFF; 5338 INT_OFF;
5389 ifsp = (struct ifsregion *)ckmalloc(sizeof(struct ifsregion)); 5339 ifsp = ckmalloc(sizeof(*ifsp));
5390 ifsp->next = NULL; 5340 ifsp->next = NULL;
5391 ifslastp->next = ifsp; 5341 ifslastp->next = ifsp;
5392 INT_ON; 5342 INT_ON;
@@ -5440,7 +5390,7 @@ ifsbreakup(char *string, struct arglist *arglist)
5440 continue; 5390 continue;
5441 } 5391 }
5442 *q = '\0'; 5392 *q = '\0';
5443 sp = (struct strlist *)stalloc(sizeof(*sp)); 5393 sp = stalloc(sizeof(*sp));
5444 sp->text = start; 5394 sp->text = start;
5445 *arglist->lastp = sp; 5395 *arglist->lastp = sp;
5446 arglist->lastp = &sp->next; 5396 arglist->lastp = &sp->next;
@@ -5481,7 +5431,7 @@ ifsbreakup(char *string, struct arglist *arglist)
5481 return; 5431 return;
5482 5432
5483 add: 5433 add:
5484 sp = (struct strlist *)stalloc(sizeof(*sp)); 5434 sp = stalloc(sizeof(*sp));
5485 sp->text = start; 5435 sp->text = start;
5486 *arglist->lastp = sp; 5436 *arglist->lastp = sp;
5487 arglist->lastp = &sp->next; 5437 arglist->lastp = &sp->next;
@@ -5571,7 +5521,7 @@ addfname(const char *name)
5571{ 5521{
5572 struct strlist *sp; 5522 struct strlist *sp;
5573 5523
5574 sp = (struct strlist *)stalloc(sizeof(*sp)); 5524 sp = stalloc(sizeof(*sp));
5575 sp->text = sstrdup(name); 5525 sp->text = sstrdup(name);
5576 *exparg.lastp = sp; 5526 *exparg.lastp = sp;
5577 exparg.lastp = &sp->next; 5527 exparg.lastp = &sp->next;
@@ -6288,7 +6238,7 @@ pushfile(void)
6288 parsefile->lleft = parselleft; 6238 parsefile->lleft = parselleft;
6289 parsefile->nextc = parsenextc; 6239 parsefile->nextc = parsenextc;
6290 parsefile->linno = plinno; 6240 parsefile->linno = plinno;
6291 pf = (struct parsefile *)ckmalloc(sizeof(struct parsefile)); 6241 pf = ckmalloc(sizeof(*pf));
6292 pf->prev = parsefile; 6242 pf->prev = parsefile;
6293 pf->fd = -1; 6243 pf->fd = -1;
6294 pf->strpush = NULL; 6244 pf->strpush = NULL;
@@ -7802,152 +7752,6 @@ changemail(const char *val)
7802 7752
7803#endif /* ASH_MAIL */ 7753#endif /* ASH_MAIL */
7804 7754
7805/* main.c */
7806
7807
7808#if PROFILE
7809static short profile_buf[16384];
7810extern int etext();
7811#endif
7812
7813static int isloginsh;
7814
7815static void read_profile(const char *);
7816
7817/*
7818 * Main routine. We initialize things, parse the arguments, execute
7819 * profiles if we're a login shell, and then call cmdloop to execute
7820 * commands. The setjmp call sets up the location to jump to when an
7821 * exception occurs. When an exception occurs the variable "state"
7822 * is used to figure out how far we had gotten.
7823 */
7824int ash_main(int argc, char **argv);
7825int ash_main(int argc, char **argv)
7826{
7827 char *shinit;
7828 volatile int state;
7829 struct jmploc jmploc;
7830 struct stackmark smark;
7831
7832#ifdef __GLIBC__
7833 dash_errno = __errno_location();
7834#endif
7835
7836#if PROFILE
7837 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
7838#endif
7839
7840#if ENABLE_FEATURE_EDITING
7841 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
7842#endif
7843 state = 0;
7844 if (setjmp(jmploc.loc)) {
7845 int e;
7846 int s;
7847
7848 reset();
7849
7850 e = exception;
7851 if (e == EXERROR)
7852 exitstatus = 2;
7853 s = state;
7854 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7855 exitshell();
7856
7857 if (e == EXINT) {
7858 outcslow('\n', stderr);
7859 }
7860 popstackmark(&smark);
7861 FORCE_INT_ON; /* enable interrupts */
7862 if (s == 1)
7863 goto state1;
7864 else if (s == 2)
7865 goto state2;
7866 else if (s == 3)
7867 goto state3;
7868 else
7869 goto state4;
7870 }
7871 exception_handler = &jmploc;
7872#if DEBUG
7873 opentrace();
7874 trputs("Shell args: "); trargs(argv);
7875#endif
7876 rootpid = getpid();
7877
7878#if ENABLE_ASH_RANDOM_SUPPORT
7879 rseed = rootpid + ((time_t)time((time_t *)0));
7880#endif
7881 init();
7882 setstackmark(&smark);
7883 procargs(argc, argv);
7884#if ENABLE_FEATURE_EDITING_SAVEHISTORY
7885 if (iflag) {
7886 const char *hp = lookupvar("HISTFILE");
7887
7888 if (hp == NULL) {
7889 hp = lookupvar("HOME");
7890 if (hp != NULL) {
7891 char *defhp = concat_path_file(hp, ".ash_history");
7892 setvar("HISTFILE", defhp, 0);
7893 free(defhp);
7894 }
7895 }
7896 }
7897#endif
7898 if (argv[0] && argv[0][0] == '-')
7899 isloginsh = 1;
7900 if (isloginsh) {
7901 state = 1;
7902 read_profile("/etc/profile");
7903 state1:
7904 state = 2;
7905 read_profile(".profile");
7906 }
7907 state2:
7908 state = 3;
7909 if (
7910#ifndef linux
7911 getuid() == geteuid() && getgid() == getegid() &&
7912#endif
7913 iflag
7914 ) {
7915 shinit = lookupvar("ENV");
7916 if (shinit != NULL && *shinit != '\0') {
7917 read_profile(shinit);
7918 }
7919 }
7920 state3:
7921 state = 4;
7922 if (minusc)
7923 evalstring(minusc, 0);
7924
7925 if (sflag || minusc == NULL) {
7926#if ENABLE_FEATURE_EDITING_SAVEHISTORY
7927 if ( iflag ) {
7928 const char *hp = lookupvar("HISTFILE");
7929
7930 if (hp != NULL)
7931 line_input_state->hist_file = hp;
7932 }
7933#endif
7934 state4: /* XXX ??? - why isn't this before the "if" statement */
7935 cmdloop(1);
7936 }
7937#if PROFILE
7938 monitor(0);
7939#endif
7940#ifdef GPROF
7941 {
7942 extern void _mcleanup(void);
7943 _mcleanup();
7944 }
7945#endif
7946 exitshell();
7947 /* NOTREACHED */
7948}
7949
7950
7951/* 7755/*
7952 * Read and execute commands. "Top" is nonzero for the top level command 7756 * Read and execute commands. "Top" is nonzero for the top level command
7953 * loop; it turns on prompting if the shell is interactive. 7757 * loop; it turns on prompting if the shell is interactive.
@@ -8006,25 +7810,6 @@ cmdloop(int top)
8006 7810
8007 7811
8008/* 7812/*
8009 * Read /etc/profile or .profile. Return on error.
8010 */
8011static void
8012read_profile(const char *name)
8013{
8014 int skip;
8015
8016 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8017 return;
8018
8019 skip = cmdloop(0);
8020 popfile();
8021
8022 if (skip)
8023 exitshell();
8024}
8025
8026
8027/*
8028 * Read a file containing shell functions. 7813 * Read a file containing shell functions.
8029 */ 7814 */
8030static void 7815static void
@@ -8134,8 +7919,8 @@ testcmd(int argc, char **argv)
8134/* 7919/*
8135 * Same for malloc, realloc, but returns an error when out of space. 7920 * Same for malloc, realloc, but returns an error when out of space.
8136 */ 7921 */
8137static pointer 7922static void *
8138ckrealloc(pointer p, size_t nbytes) 7923ckrealloc(void * p, size_t nbytes)
8139{ 7924{
8140 p = realloc(p, nbytes); 7925 p = realloc(p, nbytes);
8141 if (p == NULL) 7926 if (p == NULL)
@@ -8143,7 +7928,7 @@ ckrealloc(pointer p, size_t nbytes)
8143 return p; 7928 return p;
8144} 7929}
8145 7930
8146static pointer 7931static void *
8147ckmalloc(size_t nbytes) 7932ckmalloc(size_t nbytes)
8148{ 7933{
8149 return ckrealloc(NULL, nbytes); 7934 return ckrealloc(NULL, nbytes);
@@ -8170,7 +7955,7 @@ savestr(const char *s)
8170 * The size 504 was chosen because the Ultrix malloc handles that size 7955 * The size 504 was chosen because the Ultrix malloc handles that size
8171 * well. 7956 * well.
8172 */ 7957 */
8173static pointer 7958static void *
8174stalloc(size_t nbytes) 7959stalloc(size_t nbytes)
8175{ 7960{
8176 char *p; 7961 char *p;
@@ -8205,7 +7990,7 @@ stalloc(size_t nbytes)
8205 7990
8206 7991
8207static void 7992static void
8208stunalloc(pointer p) 7993stunalloc(void *p)
8209{ 7994{
8210#if DEBUG 7995#if DEBUG
8211 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) { 7996 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
@@ -8280,7 +8065,7 @@ growstackblock(void)
8280 sp = stackp; 8065 sp = stackp;
8281 prevstackp = sp->prev; 8066 prevstackp = sp->prev;
8282 grosslen = newlen + sizeof(struct stack_block) - MINSIZE; 8067 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8283 sp = ckrealloc((pointer)sp, grosslen); 8068 sp = ckrealloc(sp, grosslen);
8284 sp->prev = prevstackp; 8069 sp->prev = prevstackp;
8285 stackp = sp; 8070 stackp = sp;
8286 stacknxt = sp->space; 8071 stacknxt = sp->space;
@@ -8710,71 +8495,9 @@ freefunc(struct funcnode *f)
8710} 8495}
8711 8496
8712 8497
8713static void options(int);
8714static void setoption(int, int); 8498static void setoption(int, int);
8715 8499
8716 8500
8717/*
8718 * Process the shell command line arguments.
8719 */
8720static void
8721procargs(int argc, char **argv)
8722{
8723 int i;
8724 const char *xminusc;
8725 char **xargv;
8726
8727 xargv = argv;
8728 arg0 = xargv[0];
8729 if (argc > 0)
8730 xargv++;
8731 for (i = 0; i < NOPTS; i++)
8732 optlist[i] = 2;
8733 argptr = xargv;
8734 options(1);
8735 xargv = argptr;
8736 xminusc = minusc;
8737 if (*xargv == NULL) {
8738 if (xminusc)
8739 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
8740 sflag = 1;
8741 }
8742 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8743 iflag = 1;
8744 if (mflag == 2)
8745 mflag = iflag;
8746 for (i = 0; i < NOPTS; i++)
8747 if (optlist[i] == 2)
8748 optlist[i] = 0;
8749#if DEBUG == 2
8750 debug = 1;
8751#endif
8752 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8753 if (xminusc) {
8754 minusc = *xargv++;
8755 if (*xargv)
8756 goto setarg0;
8757 } else if (!sflag) {
8758 setinputfile(*xargv, 0);
8759 setarg0:
8760 arg0 = *xargv++;
8761 commandname = arg0;
8762 }
8763
8764 shellparam.p = xargv;
8765#if ENABLE_ASH_GETOPTS
8766 shellparam.optind = 1;
8767 shellparam.optoff = -1;
8768#endif
8769 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8770 while (*xargv) {
8771 shellparam.nparam++;
8772 xargv++;
8773 }
8774 optschanged();
8775}
8776
8777
8778static void 8501static void
8779optschanged(void) 8502optschanged(void)
8780{ 8503{
@@ -8790,19 +8513,19 @@ static void minus_o(char *name, int val)
8790{ 8513{
8791 int i; 8514 int i;
8792 8515
8793 if (name == NULL) { 8516 if (name) {
8794 out1str("Current option settings\n"); 8517 for (i = 0; i < NOPTS; i++) {
8795 for (i = 0; i < NOPTS; i++)
8796 out1fmt("%-16s%s\n", optnames(i),
8797 optlist[i] ? "on" : "off");
8798 } else {
8799 for (i = 0; i < NOPTS; i++)
8800 if (equal(name, optnames(i))) { 8518 if (equal(name, optnames(i))) {
8801 optlist[i] = val; 8519 optlist[i] = val;
8802 return; 8520 return;
8803 } 8521 }
8522 }
8804 ash_msg_and_raise_error("Illegal option -o %s", name); 8523 ash_msg_and_raise_error("Illegal option -o %s", name);
8805 } 8524 }
8525 out1str("Current option settings\n");
8526 for (i = 0; i < NOPTS; i++)
8527 out1fmt("%-16s%s\n", optnames(i),
8528 optlist[i] ? "on" : "off");
8806} 8529}
8807 8530
8808 8531
@@ -8865,11 +8588,12 @@ setoption(int flag, int val)
8865{ 8588{
8866 int i; 8589 int i;
8867 8590
8868 for (i = 0; i < NOPTS; i++) 8591 for (i = 0; i < NOPTS; i++) {
8869 if (optletters(i) == flag) { 8592 if (optletters(i) == flag) {
8870 optlist[i] = val; 8593 optlist[i] = val;
8871 return; 8594 return;
8872 } 8595 }
8596 }
8873 ash_msg_and_raise_error("Illegal option -%c", flag); 8597 ash_msg_and_raise_error("Illegal option -%c", flag);
8874 /* NOTREACHED */ 8598 /* NOTREACHED */
8875} 8599}
@@ -8980,13 +8704,13 @@ getoptsreset(const char *value)
8980#if ENABLE_LOCALE_SUPPORT 8704#if ENABLE_LOCALE_SUPPORT
8981static void change_lc_all(const char *value) 8705static void change_lc_all(const char *value)
8982{ 8706{
8983 if (value != 0 && *value != 0) 8707 if (value && *value != '\0')
8984 setlocale(LC_ALL, value); 8708 setlocale(LC_ALL, value);
8985} 8709}
8986 8710
8987static void change_lc_ctype(const char *value) 8711static void change_lc_ctype(const char *value)
8988{ 8712{
8989 if (value != 0 && *value != 0) 8713 if (value && *value != '\0')
8990 setlocale(LC_CTYPE, value); 8714 setlocale(LC_CTYPE, value);
8991} 8715}
8992 8716
@@ -9188,7 +8912,6 @@ nextopt(const char *optstring)
9188 8912
9189#define EOFMARKLEN 79 8913#define EOFMARKLEN 79
9190 8914
9191
9192struct heredoc { 8915struct heredoc {
9193 struct heredoc *next; /* next here document in list */ 8916 struct heredoc *next; /* next here document in list */
9194 union node *here; /* redirection node */ 8917 union node *here; /* redirection node */
@@ -9196,11 +8919,8 @@ struct heredoc {
9196 int striptabs; /* if set, strip leading tabs */ 8919 int striptabs; /* if set, strip leading tabs */
9197}; 8920};
9198 8921
9199
9200
9201static struct heredoc *heredoclist; /* list of here documents to read */ 8922static struct heredoc *heredoclist; /* list of here documents to read */
9202 8923
9203
9204static union node *list(int); 8924static union node *list(int);
9205static union node *andor(void); 8925static union node *andor(void);
9206static union node *pipeline(void); 8926static union node *pipeline(void);
@@ -9214,16 +8934,40 @@ static int readtoken(void);
9214static int xxreadtoken(void); 8934static int xxreadtoken(void);
9215static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs); 8935static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9216static int noexpand(char *); 8936static int noexpand(char *);
9217static void synexpect(int) ATTRIBUTE_NORETURN;
9218static void synerror(const char *) ATTRIBUTE_NORETURN;
9219static void setprompt(int); 8937static void setprompt(int);
9220 8938
8939static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
8940static void
8941raise_error_syntax(const char *msg)
8942{
8943 ash_msg_and_raise_error("Syntax error: %s", msg);
8944 /* NOTREACHED */
8945}
8946
8947/*
8948 * Called when an unexpected token is read during the parse. The argument
8949 * is the token that is expected, or -1 if more than one type of token can
8950 * occur at this point.
8951 */
8952static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
8953static void
8954raise_error_unexpected_syntax(int token)
8955{
8956 char msg[64];
8957 int l;
8958
8959 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
8960 if (token >= 0)
8961 sprintf(msg + l, " (expecting %s)", tokname(token));
8962 raise_error_syntax(msg);
8963 /* NOTREACHED */
8964}
9221 8965
9222/* 8966/*
9223 * Read and parse a command. Returns NEOF on end of file. (NULL is a 8967 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9224 * valid parse tree indicating a blank line.) 8968 * valid parse tree indicating a blank line.)
9225 */ 8969 */
9226union node * 8970static union node *
9227parsecmd(int interact) 8971parsecmd(int interact)
9228{ 8972{
9229 int t; 8973 int t;
@@ -9272,7 +9016,7 @@ list(int nlflag)
9272 if (n1 == NULL) { 9016 if (n1 == NULL) {
9273 n1 = n2; 9017 n1 = n2;
9274 } else { 9018 } else {
9275 n3 = (union node *)stalloc(sizeof(struct nbinary)); 9019 n3 = stalloc(sizeof(struct nbinary));
9276 n3->type = NSEMI; 9020 n3->type = NSEMI;
9277 n3->nbinary.ch1 = n1; 9021 n3->nbinary.ch1 = n1;
9278 n3->nbinary.ch2 = n2; 9022 n3->nbinary.ch2 = n2;
@@ -9303,7 +9047,7 @@ list(int nlflag)
9303 return n1; 9047 return n1;
9304 default: 9048 default:
9305 if (nlflag == 1) 9049 if (nlflag == 1)
9306 synexpect(-1); 9050 raise_error_unexpected_syntax(-1);
9307 tokpushback++; 9051 tokpushback++;
9308 return n1; 9052 return n1;
9309 } 9053 }
@@ -9330,7 +9074,7 @@ andor(void)
9330 } 9074 }
9331 checkkwd = CHKNL | CHKKWD | CHKALIAS; 9075 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9332 n2 = pipeline(); 9076 n2 = pipeline();
9333 n3 = (union node *)stalloc(sizeof(struct nbinary)); 9077 n3 = stalloc(sizeof(struct nbinary));
9334 n3->type = t; 9078 n3->type = t;
9335 n3->nbinary.ch1 = n1; 9079 n3->nbinary.ch1 = n1;
9336 n3->nbinary.ch2 = n2; 9080 n3->nbinary.ch2 = n2;
@@ -9355,15 +9099,15 @@ pipeline(void)
9355 tokpushback++; 9099 tokpushback++;
9356 n1 = command(); 9100 n1 = command();
9357 if (readtoken() == TPIPE) { 9101 if (readtoken() == TPIPE) {
9358 pipenode = (union node *)stalloc(sizeof(struct npipe)); 9102 pipenode = stalloc(sizeof(struct npipe));
9359 pipenode->type = NPIPE; 9103 pipenode->type = NPIPE;
9360 pipenode->npipe.backgnd = 0; 9104 pipenode->npipe.backgnd = 0;
9361 lp = (struct nodelist *)stalloc(sizeof(struct nodelist)); 9105 lp = stalloc(sizeof(struct nodelist));
9362 pipenode->npipe.cmdlist = lp; 9106 pipenode->npipe.cmdlist = lp;
9363 lp->n = n1; 9107 lp->n = n1;
9364 do { 9108 do {
9365 prev = lp; 9109 prev = lp;
9366 lp = (struct nodelist *)stalloc(sizeof(struct nodelist)); 9110 lp = stalloc(sizeof(struct nodelist));
9367 checkkwd = CHKNL | CHKKWD | CHKALIAS; 9111 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9368 lp->n = command(); 9112 lp->n = command();
9369 prev->next = lp; 9113 prev->next = lp;
@@ -9373,7 +9117,7 @@ pipeline(void)
9373 } 9117 }
9374 tokpushback++; 9118 tokpushback++;
9375 if (negate) { 9119 if (negate) {
9376 n2 = (union node *)stalloc(sizeof(struct nnot)); 9120 n2 = stalloc(sizeof(struct nnot));
9377 n2->type = NNOT; 9121 n2->type = NNOT;
9378 n2->nnot.com = n1; 9122 n2->nnot.com = n1;
9379 return n2; 9123 return n2;
@@ -9397,23 +9141,23 @@ command(void)
9397 9141
9398 switch (readtoken()) { 9142 switch (readtoken()) {
9399 default: 9143 default:
9400 synexpect(-1); 9144 raise_error_unexpected_syntax(-1);
9401 /* NOTREACHED */ 9145 /* NOTREACHED */
9402 case TIF: 9146 case TIF:
9403 n1 = (union node *)stalloc(sizeof(struct nif)); 9147 n1 = stalloc(sizeof(struct nif));
9404 n1->type = NIF; 9148 n1->type = NIF;
9405 n1->nif.test = list(0); 9149 n1->nif.test = list(0);
9406 if (readtoken() != TTHEN) 9150 if (readtoken() != TTHEN)
9407 synexpect(TTHEN); 9151 raise_error_unexpected_syntax(TTHEN);
9408 n1->nif.ifpart = list(0); 9152 n1->nif.ifpart = list(0);
9409 n2 = n1; 9153 n2 = n1;
9410 while (readtoken() == TELIF) { 9154 while (readtoken() == TELIF) {
9411 n2->nif.elsepart = (union node *)stalloc(sizeof(struct nif)); 9155 n2->nif.elsepart = stalloc(sizeof(struct nif));
9412 n2 = n2->nif.elsepart; 9156 n2 = n2->nif.elsepart;
9413 n2->type = NIF; 9157 n2->type = NIF;
9414 n2->nif.test = list(0); 9158 n2->nif.test = list(0);
9415 if (readtoken() != TTHEN) 9159 if (readtoken() != TTHEN)
9416 synexpect(TTHEN); 9160 raise_error_unexpected_syntax(TTHEN);
9417 n2->nif.ifpart = list(0); 9161 n2->nif.ifpart = list(0);
9418 } 9162 }
9419 if (lasttoken == TELSE) 9163 if (lasttoken == TELSE)
@@ -9427,13 +9171,13 @@ command(void)
9427 case TWHILE: 9171 case TWHILE:
9428 case TUNTIL: { 9172 case TUNTIL: {
9429 int got; 9173 int got;
9430 n1 = (union node *)stalloc(sizeof(struct nbinary)); 9174 n1 = stalloc(sizeof(struct nbinary));
9431 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL; 9175 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9432 n1->nbinary.ch1 = list(0); 9176 n1->nbinary.ch1 = list(0);
9433 if ((got=readtoken()) != TDO) { 9177 if ((got=readtoken()) != TDO) {
9434 TRACE(("expecting DO got %s %s\n", tokname(got), 9178 TRACE(("expecting DO got %s %s\n", tokname(got),
9435 got == TWORD ? wordtext : "")); 9179 got == TWORD ? wordtext : ""));
9436 synexpect(TDO); 9180 raise_error_unexpected_syntax(TDO);
9437 } 9181 }
9438 n1->nbinary.ch2 = list(0); 9182 n1->nbinary.ch2 = list(0);
9439 t = TDONE; 9183 t = TDONE;
@@ -9441,15 +9185,15 @@ command(void)
9441 } 9185 }
9442 case TFOR: 9186 case TFOR:
9443 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext)) 9187 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9444 synerror("Bad for loop variable"); 9188 raise_error_syntax("Bad for loop variable");
9445 n1 = (union node *)stalloc(sizeof(struct nfor)); 9189 n1 = stalloc(sizeof(struct nfor));
9446 n1->type = NFOR; 9190 n1->type = NFOR;
9447 n1->nfor.var = wordtext; 9191 n1->nfor.var = wordtext;
9448 checkkwd = CHKKWD | CHKALIAS; 9192 checkkwd = CHKKWD | CHKALIAS;
9449 if (readtoken() == TIN) { 9193 if (readtoken() == TIN) {
9450 app = &ap; 9194 app = &ap;
9451 while (readtoken() == TWORD) { 9195 while (readtoken() == TWORD) {
9452 n2 = (union node *)stalloc(sizeof(struct narg)); 9196 n2 = stalloc(sizeof(struct narg));
9453 n2->type = NARG; 9197 n2->type = NARG;
9454 n2->narg.text = wordtext; 9198 n2->narg.text = wordtext;
9455 n2->narg.backquote = backquotelist; 9199 n2->narg.backquote = backquotelist;
@@ -9459,9 +9203,9 @@ command(void)
9459 *app = NULL; 9203 *app = NULL;
9460 n1->nfor.args = ap; 9204 n1->nfor.args = ap;
9461 if (lasttoken != TNL && lasttoken != TSEMI) 9205 if (lasttoken != TNL && lasttoken != TSEMI)
9462 synexpect(-1); 9206 raise_error_unexpected_syntax(-1);
9463 } else { 9207 } else {
9464 n2 = (union node *)stalloc(sizeof(struct narg)); 9208 n2 = stalloc(sizeof(struct narg));
9465 n2->type = NARG; 9209 n2->type = NARG;
9466 n2->narg.text = (char *)dolatstr; 9210 n2->narg.text = (char *)dolatstr;
9467 n2->narg.backquote = NULL; 9211 n2->narg.backquote = NULL;
@@ -9476,16 +9220,16 @@ command(void)
9476 } 9220 }
9477 checkkwd = CHKNL | CHKKWD | CHKALIAS; 9221 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9478 if (readtoken() != TDO) 9222 if (readtoken() != TDO)
9479 synexpect(TDO); 9223 raise_error_unexpected_syntax(TDO);
9480 n1->nfor.body = list(0); 9224 n1->nfor.body = list(0);
9481 t = TDONE; 9225 t = TDONE;
9482 break; 9226 break;
9483 case TCASE: 9227 case TCASE:
9484 n1 = (union node *)stalloc(sizeof(struct ncase)); 9228 n1 = stalloc(sizeof(struct ncase));
9485 n1->type = NCASE; 9229 n1->type = NCASE;
9486 if (readtoken() != TWORD) 9230 if (readtoken() != TWORD)
9487 synexpect(TWORD); 9231 raise_error_unexpected_syntax(TWORD);
9488 n1->ncase.expr = n2 = (union node *)stalloc(sizeof(struct narg)); 9232 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
9489 n2->type = NARG; 9233 n2->type = NARG;
9490 n2->narg.text = wordtext; 9234 n2->narg.text = wordtext;
9491 n2->narg.backquote = backquotelist; 9235 n2->narg.backquote = backquotelist;
@@ -9494,7 +9238,7 @@ command(void)
9494 checkkwd = CHKKWD | CHKALIAS; 9238 checkkwd = CHKKWD | CHKALIAS;
9495 } while (readtoken() == TNL); 9239 } while (readtoken() == TNL);
9496 if (lasttoken != TIN) 9240 if (lasttoken != TIN)
9497 synexpect(TIN); 9241 raise_error_unexpected_syntax(TIN);
9498 cpp = &n1->ncase.cases; 9242 cpp = &n1->ncase.cases;
9499 next_case: 9243 next_case:
9500 checkkwd = CHKNL | CHKKWD; 9244 checkkwd = CHKNL | CHKKWD;
@@ -9502,11 +9246,11 @@ command(void)
9502 while (t != TESAC) { 9246 while (t != TESAC) {
9503 if (lasttoken == TLP) 9247 if (lasttoken == TLP)
9504 readtoken(); 9248 readtoken();
9505 *cpp = cp = (union node *)stalloc(sizeof(struct nclist)); 9249 *cpp = cp = stalloc(sizeof(struct nclist));
9506 cp->type = NCLIST; 9250 cp->type = NCLIST;
9507 app = &cp->nclist.pattern; 9251 app = &cp->nclist.pattern;
9508 for (;;) { 9252 for (;;) {
9509 *app = ap = (union node *)stalloc(sizeof(struct narg)); 9253 *app = ap = stalloc(sizeof(struct narg));
9510 ap->type = NARG; 9254 ap->type = NARG;
9511 ap->narg.text = wordtext; 9255 ap->narg.text = wordtext;
9512 ap->narg.backquote = backquotelist; 9256 ap->narg.backquote = backquotelist;
@@ -9517,7 +9261,7 @@ command(void)
9517 } 9261 }
9518 ap->narg.next = NULL; 9262 ap->narg.next = NULL;
9519 if (lasttoken != TRP) 9263 if (lasttoken != TRP)
9520 synexpect(TRP); 9264 raise_error_unexpected_syntax(TRP);
9521 cp->nclist.body = list(2); 9265 cp->nclist.body = list(2);
9522 9266
9523 cpp = &cp->nclist.next; 9267 cpp = &cp->nclist.next;
@@ -9526,15 +9270,14 @@ command(void)
9526 t = readtoken(); 9270 t = readtoken();
9527 if (t != TESAC) { 9271 if (t != TESAC) {
9528 if (t != TENDCASE) 9272 if (t != TENDCASE)
9529 synexpect(TENDCASE); 9273 raise_error_unexpected_syntax(TENDCASE);
9530 else 9274 goto next_case;
9531 goto next_case;
9532 } 9275 }
9533 } 9276 }
9534 *cpp = NULL; 9277 *cpp = NULL;
9535 goto redir; 9278 goto redir;
9536 case TLP: 9279 case TLP:
9537 n1 = (union node *)stalloc(sizeof(struct nredir)); 9280 n1 = stalloc(sizeof(struct nredir));
9538 n1->type = NSUBSHELL; 9281 n1->type = NSUBSHELL;
9539 n1->nredir.n = list(0); 9282 n1->nredir.n = list(0);
9540 n1->nredir.redirect = NULL; 9283 n1->nredir.redirect = NULL;
@@ -9551,7 +9294,7 @@ command(void)
9551 } 9294 }
9552 9295
9553 if (readtoken() != t) 9296 if (readtoken() != t)
9554 synexpect(t); 9297 raise_error_unexpected_syntax(t);
9555 9298
9556 redir: 9299 redir:
9557 /* Now check for redirection which may follow command */ 9300 /* Now check for redirection which may follow command */
@@ -9566,7 +9309,7 @@ command(void)
9566 *rpp = NULL; 9309 *rpp = NULL;
9567 if (redir) { 9310 if (redir) {
9568 if (n1->type != NSUBSHELL) { 9311 if (n1->type != NSUBSHELL) {
9569 n2 = (union node *)stalloc(sizeof(struct nredir)); 9312 n2 = stalloc(sizeof(struct nredir));
9570 n2->type = NREDIR; 9313 n2->type = NREDIR;
9571 n2->nredir.n = n1; 9314 n2->nredir.n = n1;
9572 n1 = n2; 9315 n1 = n2;
@@ -9598,7 +9341,7 @@ simplecmd(void)
9598 checkkwd = savecheckkwd; 9341 checkkwd = savecheckkwd;
9599 switch (readtoken()) { 9342 switch (readtoken()) {
9600 case TWORD: 9343 case TWORD:
9601 n = (union node *)stalloc(sizeof(struct narg)); 9344 n = stalloc(sizeof(struct narg));
9602 n->type = NARG; 9345 n->type = NARG;
9603 n->narg.text = wordtext; 9346 n->narg.text = wordtext;
9604 n->narg.backquote = backquotelist; 9347 n->narg.backquote = backquotelist;
@@ -9617,24 +9360,21 @@ simplecmd(void)
9617 parsefname(); /* read name of redirection file */ 9360 parsefname(); /* read name of redirection file */
9618 break; 9361 break;
9619 case TLP: 9362 case TLP:
9620 if ( 9363 if (args && app == &args->narg.next
9621 args && app == &args->narg.next && 9364 && !vars && !redir
9622 !vars && !redir
9623 ) { 9365 ) {
9624 struct builtincmd *bcmd; 9366 struct builtincmd *bcmd;
9625 const char *name; 9367 const char *name;
9626 9368
9627 /* We have a function */ 9369 /* We have a function */
9628 if (readtoken() != TRP) 9370 if (readtoken() != TRP)
9629 synexpect(TRP); 9371 raise_error_unexpected_syntax(TRP);
9630 name = n->narg.text; 9372 name = n->narg.text;
9631 if ( 9373 if (!goodname(name)
9632 !goodname(name) || ( 9374 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
9633 (bcmd = find_builtin(name)) && 9375 ) {
9634 IS_BUILTIN_SPECIAL(bcmd) 9376 raise_error_syntax("Bad function name");
9635 ) 9377 }
9636 )
9637 synerror("Bad function name");
9638 n->type = NDEFUN; 9378 n->type = NDEFUN;
9639 checkkwd = CHKNL | CHKKWD | CHKALIAS; 9379 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9640 n->narg.next = command(); 9380 n->narg.next = command();
@@ -9650,7 +9390,7 @@ simplecmd(void)
9650 *app = NULL; 9390 *app = NULL;
9651 *vpp = NULL; 9391 *vpp = NULL;
9652 *rpp = NULL; 9392 *rpp = NULL;
9653 n = (union node *)stalloc(sizeof(struct ncmd)); 9393 n = stalloc(sizeof(struct ncmd));
9654 n->type = NCMD; 9394 n->type = NCMD;
9655 n->ncmd.args = args; 9395 n->ncmd.args = args;
9656 n->ncmd.assign = vars; 9396 n->ncmd.assign = vars;
@@ -9663,7 +9403,7 @@ makename(void)
9663{ 9403{
9664 union node *n; 9404 union node *n;
9665 9405
9666 n = (union node *)stalloc(sizeof(struct narg)); 9406 n = stalloc(sizeof(struct narg));
9667 n->type = NARG; 9407 n->type = NARG;
9668 n->narg.next = NULL; 9408 n->narg.next = NULL;
9669 n->narg.text = wordtext; 9409 n->narg.text = wordtext;
@@ -9682,11 +9422,9 @@ static void fixredir(union node *n, const char *text, int err)
9682 else if (LONE_DASH(text)) 9422 else if (LONE_DASH(text))
9683 n->ndup.dupfd = -1; 9423 n->ndup.dupfd = -1;
9684 else { 9424 else {
9685
9686 if (err) 9425 if (err)
9687 synerror("Bad fd number"); 9426 raise_error_syntax("Bad fd number");
9688 else 9427 n->ndup.vname = makename();
9689 n->ndup.vname = makename();
9690 } 9428 }
9691} 9429}
9692 9430
@@ -9697,7 +9435,7 @@ parsefname(void)
9697 union node *n = redirnode; 9435 union node *n = redirnode;
9698 9436
9699 if (readtoken() != TWORD) 9437 if (readtoken() != TWORD)
9700 synexpect(-1); 9438 raise_error_unexpected_syntax(-1);
9701 if (n->type == NHERE) { 9439 if (n->type == NHERE) {
9702 struct heredoc *here = heredoc; 9440 struct heredoc *here = heredoc;
9703 struct heredoc *p; 9441 struct heredoc *p;
@@ -9707,7 +9445,7 @@ parsefname(void)
9707 n->type = NXHERE; 9445 n->type = NXHERE;
9708 TRACE(("Here document %d\n", n->type)); 9446 TRACE(("Here document %d\n", n->type));
9709 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN) 9447 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9710 synerror("Illegal eof marker for << redirection"); 9448 raise_error_syntax("Illegal eof marker for << redirection");
9711 rmescapes(wordtext); 9449 rmescapes(wordtext);
9712 here->eofmark = wordtext; 9450 here->eofmark = wordtext;
9713 here->next = NULL; 9451 here->next = NULL;
@@ -9743,7 +9481,7 @@ parseheredoc(void)
9743 } 9481 }
9744 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX, 9482 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9745 here->eofmark, here->striptabs); 9483 here->eofmark, here->striptabs);
9746 n = (union node *)stalloc(sizeof(struct narg)); 9484 n = stalloc(sizeof(struct narg));
9747 n->narg.type = NARG; 9485 n->narg.type = NARG;
9748 n->narg.next = NULL; 9486 n->narg.next = NULL;
9749 n->narg.text = wordtext; 9487 n->narg.text = wordtext;
@@ -9845,10 +9583,8 @@ readtoken(void)
9845 * We could also make parseoperator in essence the main routine, and 9583 * We could also make parseoperator in essence the main routine, and
9846 * have parseword (readtoken1?) handle both words and redirection.] 9584 * have parseword (readtoken1?) handle both words and redirection.]
9847 */ 9585 */
9848
9849#define NEW_xxreadtoken 9586#define NEW_xxreadtoken
9850#ifdef NEW_xxreadtoken 9587#ifdef NEW_xxreadtoken
9851
9852/* singles must be first! */ 9588/* singles must be first! */
9853static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 }; 9589static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9854 9590
@@ -9881,9 +9617,9 @@ static int xxreadtoken(void)
9881 9617
9882 if ((c != ' ') && (c != '\t') 9618 if ((c != ' ') && (c != '\t')
9883#if ENABLE_ASH_ALIAS 9619#if ENABLE_ASH_ALIAS
9884 && (c != PEOA) 9620 && (c != PEOA)
9885#endif 9621#endif
9886 ) { 9622 ) {
9887 if (c == '#') { 9623 if (c == '#') {
9888 while ((c = pgetc()) != '\n' && c != PEOF); 9624 while ((c = pgetc()) != '\n' && c != PEOF);
9889 pungetc(); 9625 pungetc();
@@ -9907,7 +9643,7 @@ static int xxreadtoken(void)
9907 9643
9908 p = strchr(xxreadtoken_chars, c); 9644 p = strchr(xxreadtoken_chars, c);
9909 if (p == NULL) { 9645 if (p == NULL) {
9910 READTOKEN1: 9646 READTOKEN1:
9911 return readtoken1(c, BASESYNTAX, (char *) NULL, 0); 9647 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
9912 } 9648 }
9913 9649
@@ -9924,11 +9660,8 @@ static int xxreadtoken(void)
9924 } 9660 }
9925 } /* for */ 9661 } /* for */
9926} 9662}
9927
9928
9929#else 9663#else
9930#define RETURN(token) return lasttoken = token 9664#define RETURN(token) return lasttoken = token
9931
9932static int 9665static int
9933xxreadtoken(void) 9666xxreadtoken(void)
9934{ 9667{
@@ -10199,14 +9932,14 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10199 endword: 9932 endword:
10200#if ENABLE_ASH_MATH_SUPPORT 9933#if ENABLE_ASH_MATH_SUPPORT
10201 if (syntax == ARISYNTAX) 9934 if (syntax == ARISYNTAX)
10202 synerror("Missing '))'"); 9935 raise_error_syntax("Missing '))'");
10203#endif 9936#endif
10204 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL) 9937 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10205 synerror("Unterminated quoted string"); 9938 raise_error_syntax("Unterminated quoted string");
10206 if (varnest != 0) { 9939 if (varnest != 0) {
10207 startlinno = plinno; 9940 startlinno = plinno;
10208 /* { */ 9941 /* { */
10209 synerror("Missing '}'"); 9942 raise_error_syntax("Missing '}'");
10210 } 9943 }
10211 USTPUTC('\0', out); 9944 USTPUTC('\0', out);
10212 len = out - (char *)stackblock(); 9945 len = out - (char *)stackblock();
@@ -10277,7 +10010,7 @@ parseredir: {
10277 char fd = *out; 10010 char fd = *out;
10278 union node *np; 10011 union node *np;
10279 10012
10280 np = (union node *)stalloc(sizeof(struct nfile)); 10013 np = stalloc(sizeof(struct nfile));
10281 if (c == '>') { 10014 if (c == '>') {
10282 np->nfile.fd = 1; 10015 np->nfile.fd = 1;
10283 c = pgetc(); 10016 c = pgetc();
@@ -10297,11 +10030,11 @@ parseredir: {
10297 switch (c) { 10030 switch (c) {
10298 case '<': 10031 case '<':
10299 if (sizeof(struct nfile) != sizeof(struct nhere)) { 10032 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10300 np = (union node *)stalloc(sizeof(struct nhere)); 10033 np = stalloc(sizeof(struct nhere));
10301 np->nfile.fd = 0; 10034 np->nfile.fd = 0;
10302 } 10035 }
10303 np->type = NHERE; 10036 np->type = NHERE;
10304 heredoc = (struct heredoc *)stalloc(sizeof(struct heredoc)); 10037 heredoc = stalloc(sizeof(struct heredoc));
10305 heredoc->here = np; 10038 heredoc->here = np;
10306 c = pgetc(); 10039 c = pgetc();
10307 if (c == '-') { 10040 if (c == '-') {
@@ -10356,7 +10089,7 @@ parsesub: {
10356#if ENABLE_ASH_MATH_SUPPORT 10089#if ENABLE_ASH_MATH_SUPPORT
10357 PARSEARITH(); 10090 PARSEARITH();
10358#else 10091#else
10359 synerror("We unsupport $((arith))"); 10092 raise_error_syntax("We unsupport $((arith))");
10360#endif 10093#endif
10361 } else { 10094 } else {
10362 pungetc(); 10095 pungetc();
@@ -10392,7 +10125,7 @@ parsesub: {
10392 USTPUTC(c, out); 10125 USTPUTC(c, out);
10393 c = pgetc(); 10126 c = pgetc();
10394 } else 10127 } else
10395 badsub: synerror("Bad substitution"); 10128 badsub: raise_error_syntax("Bad substitution");
10396 10129
10397 STPUTC('=', out); 10130 STPUTC('=', out);
10398 flags = 0; 10131 flags = 0;
@@ -10523,7 +10256,7 @@ parsebackq: {
10523 case PEOA: 10256 case PEOA:
10524#endif 10257#endif
10525 startlinno = plinno; 10258 startlinno = plinno;
10526 synerror("EOF in backquote substitution"); 10259 raise_error_syntax("EOF in backquote substitution");
10527 10260
10528 case '\n': 10261 case '\n':
10529 plinno++; 10262 plinno++;
@@ -10546,7 +10279,7 @@ parsebackq: {
10546 nlpp = &bqlist; 10279 nlpp = &bqlist;
10547 while (*nlpp) 10280 while (*nlpp)
10548 nlpp = &(*nlpp)->next; 10281 nlpp = &(*nlpp)->next;
10549 *nlpp = (struct nodelist *)stalloc(sizeof(struct nodelist)); 10282 *nlpp = stalloc(sizeof(**nlpp));
10550 (*nlpp)->next = NULL; 10283 (*nlpp)->next = NULL;
10551 parsebackquote = oldstyle; 10284 parsebackquote = oldstyle;
10552 10285
@@ -10561,7 +10294,7 @@ parsebackq: {
10561 doprompt = saveprompt; 10294 doprompt = saveprompt;
10562 else { 10295 else {
10563 if (readtoken() != TRP) 10296 if (readtoken() != TRP)
10564 synexpect(TRP); 10297 raise_error_unexpected_syntax(TRP);
10565 } 10298 }
10566 10299
10567 (*nlpp)->n = n; 10300 (*nlpp)->n = n;
@@ -10592,8 +10325,7 @@ parsebackq: {
10592 USTPUTC(CTLBACKQ, out); 10325 USTPUTC(CTLBACKQ, out);
10593 if (oldstyle) 10326 if (oldstyle)
10594 goto parsebackq_oldreturn; 10327 goto parsebackq_oldreturn;
10595 else 10328 goto parsebackq_newreturn;
10596 goto parsebackq_newreturn;
10597} 10329}
10598 10330
10599#if ENABLE_ASH_MATH_SUPPORT 10331#if ENABLE_ASH_MATH_SUPPORT
@@ -10606,9 +10338,9 @@ parsearith: {
10606 syntax = ARISYNTAX; 10338 syntax = ARISYNTAX;
10607 USTPUTC(CTLARI, out); 10339 USTPUTC(CTLARI, out);
10608 if (dblquote) 10340 if (dblquote)
10609 USTPUTC('"',out); 10341 USTPUTC('"', out);
10610 else 10342 else
10611 USTPUTC(' ',out); 10343 USTPUTC(' ', out);
10612 } else { 10344 } else {
10613 /* 10345 /*
10614 * we collapse embedded arithmetic expansion to 10346 * we collapse embedded arithmetic expansion to
@@ -10667,31 +10399,6 @@ endofname(const char *name)
10667 10399
10668 10400
10669/* 10401/*
10670 * Called when an unexpected token is read during the parse. The argument
10671 * is the token that is expected, or -1 if more than one type of token can
10672 * occur at this point.
10673 */
10674static void synexpect(int token)
10675{
10676 char msg[64];
10677 int l;
10678
10679 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10680 if (token >= 0)
10681 sprintf(msg + l, " (expecting %s)", tokname(token));
10682 synerror(msg);
10683 /* NOTREACHED */
10684}
10685
10686static void
10687synerror(const char *msg)
10688{
10689 ash_msg_and_raise_error("Syntax error: %s", msg);
10690 /* NOTREACHED */
10691}
10692
10693
10694/*
10695 * called by editline -- any expansions to the prompt 10402 * called by editline -- any expansions to the prompt
10696 * should be added here. 10403 * should be added here.
10697 */ 10404 */
@@ -12353,7 +12060,7 @@ dash_arith(const char *s)
12353 else if (errcode == -5) 12060 else if (errcode == -5)
12354 ash_msg_and_raise_error("expression recursion loop detected"); 12061 ash_msg_and_raise_error("expression recursion loop detected");
12355 else 12062 else
12356 synerror(s); 12063 raise_error_syntax(s);
12357 } 12064 }
12358 INT_ON; 12065 INT_ON;
12359 12066
@@ -13485,6 +13192,257 @@ static arith_t arith(const char *expr, int *perrcode)
13485#endif /* ASH_MATH_SUPPORT */ 13192#endif /* ASH_MATH_SUPPORT */
13486 13193
13487 13194
13195/* ============ main() and helpers
13196 *
13197 * Main routine. We initialize things, parse the arguments, execute
13198 * profiles if we're a login shell, and then call cmdloop to execute
13199 * commands. The setjmp call sets up the location to jump to when an
13200 * exception occurs. When an exception occurs the variable "state"
13201 * is used to figure out how far we had gotten.
13202 */
13203
13204static void init(void)
13205{
13206 /* from input.c: */
13207 basepf.nextc = basepf.buf = basebuf;
13208
13209 /* from trap.c: */
13210 signal(SIGCHLD, SIG_DFL);
13211
13212 /* from var.c: */
13213 {
13214 char **envp;
13215 char ppid[32];
13216 const char *p;
13217 struct stat st1, st2;
13218
13219 initvar();
13220 for (envp = environ; envp && *envp; envp++) {
13221 if (strchr(*envp, '=')) {
13222 setvareq(*envp, VEXPORT|VTEXTFIXED);
13223 }
13224 }
13225
13226 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
13227 setvar("PPID", ppid, 0);
13228
13229 p = lookupvar("PWD");
13230 if (p)
13231 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13232 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13233 p = '\0';
13234 setpwd(p, 0);
13235 }
13236}
13237
13238/*
13239 * Process the shell command line arguments.
13240 */
13241static void
13242procargs(int argc, char **argv)
13243{
13244 int i;
13245 const char *xminusc;
13246 char **xargv;
13247
13248 xargv = argv;
13249 arg0 = xargv[0];
13250 if (argc > 0)
13251 xargv++;
13252 for (i = 0; i < NOPTS; i++)
13253 optlist[i] = 2;
13254 argptr = xargv;
13255 options(1);
13256 xargv = argptr;
13257 xminusc = minusc;
13258 if (*xargv == NULL) {
13259 if (xminusc)
13260 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13261 sflag = 1;
13262 }
13263 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13264 iflag = 1;
13265 if (mflag == 2)
13266 mflag = iflag;
13267 for (i = 0; i < NOPTS; i++)
13268 if (optlist[i] == 2)
13269 optlist[i] = 0;
13270#if DEBUG == 2
13271 debug = 1;
13272#endif
13273 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13274 if (xminusc) {
13275 minusc = *xargv++;
13276 if (*xargv)
13277 goto setarg0;
13278 } else if (!sflag) {
13279 setinputfile(*xargv, 0);
13280 setarg0:
13281 arg0 = *xargv++;
13282 commandname = arg0;
13283 }
13284
13285 shellparam.p = xargv;
13286#if ENABLE_ASH_GETOPTS
13287 shellparam.optind = 1;
13288 shellparam.optoff = -1;
13289#endif
13290 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
13291 while (*xargv) {
13292 shellparam.nparam++;
13293 xargv++;
13294 }
13295 optschanged();
13296}
13297
13298/*
13299 * Read /etc/profile or .profile.
13300 */
13301static void
13302read_profile(const char *name)
13303{
13304 int skip;
13305
13306 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13307 return;
13308 skip = cmdloop(0);
13309 popfile();
13310 if (skip)
13311 exitshell();
13312}
13313
13314#if PROFILE
13315static short profile_buf[16384];
13316extern int etext();
13317#endif
13318
13319int ash_main(int argc, char **argv);
13320int ash_main(int argc, char **argv)
13321{
13322 char *shinit;
13323 volatile int state;
13324 struct jmploc jmploc;
13325 struct stackmark smark;
13326
13327#ifdef __GLIBC__
13328 dash_errno = __errno_location();
13329#endif
13330
13331#if PROFILE
13332 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13333#endif
13334
13335#if ENABLE_FEATURE_EDITING
13336 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13337#endif
13338 state = 0;
13339 if (setjmp(jmploc.loc)) {
13340 int e;
13341 int s;
13342
13343 reset();
13344
13345 e = exception;
13346 if (e == EXERROR)
13347 exitstatus = 2;
13348 s = state;
13349 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13350 exitshell();
13351
13352 if (e == EXINT) {
13353 outcslow('\n', stderr);
13354 }
13355 popstackmark(&smark);
13356 FORCE_INT_ON; /* enable interrupts */
13357 if (s == 1)
13358 goto state1;
13359 else if (s == 2)
13360 goto state2;
13361 else if (s == 3)
13362 goto state3;
13363 else
13364 goto state4;
13365 }
13366 exception_handler = &jmploc;
13367#if DEBUG
13368 opentrace();
13369 trputs("Shell args: ");
13370 trargs(argv);
13371#endif
13372 rootpid = getpid();
13373
13374#if ENABLE_ASH_RANDOM_SUPPORT
13375 rseed = rootpid + time(NULL);
13376#endif
13377 init();
13378 setstackmark(&smark);
13379 procargs(argc, argv);
13380#if ENABLE_FEATURE_EDITING_SAVEHISTORY
13381 if (iflag) {
13382 const char *hp = lookupvar("HISTFILE");
13383
13384 if (hp == NULL) {
13385 hp = lookupvar("HOME");
13386 if (hp != NULL) {
13387 char *defhp = concat_path_file(hp, ".ash_history");
13388 setvar("HISTFILE", defhp, 0);
13389 free(defhp);
13390 }
13391 }
13392 }
13393#endif
13394 if (argv[0] && argv[0][0] == '-')
13395 isloginsh = 1;
13396 if (isloginsh) {
13397 state = 1;
13398 read_profile("/etc/profile");
13399 state1:
13400 state = 2;
13401 read_profile(".profile");
13402 }
13403 state2:
13404 state = 3;
13405 if (
13406#ifndef linux
13407 getuid() == geteuid() && getgid() == getegid() &&
13408#endif
13409 iflag
13410 ) {
13411 shinit = lookupvar("ENV");
13412 if (shinit != NULL && *shinit != '\0') {
13413 read_profile(shinit);
13414 }
13415 }
13416 state3:
13417 state = 4;
13418 if (minusc)
13419 evalstring(minusc, 0);
13420
13421 if (sflag || minusc == NULL) {
13422#if ENABLE_FEATURE_EDITING_SAVEHISTORY
13423 if ( iflag ) {
13424 const char *hp = lookupvar("HISTFILE");
13425
13426 if (hp != NULL)
13427 line_input_state->hist_file = hp;
13428 }
13429#endif
13430 state4: /* XXX ??? - why isn't this before the "if" statement */
13431 cmdloop(1);
13432 }
13433#if PROFILE
13434 monitor(0);
13435#endif
13436#ifdef GPROF
13437 {
13438 extern void _mcleanup(void);
13439 _mcleanup();
13440 }
13441#endif
13442 exitshell();
13443 /* NOTREACHED */
13444}
13445
13488#if DEBUG 13446#if DEBUG
13489const char *applet_name = "debug stuff usage"; 13447const char *applet_name = "debug stuff usage";
13490int main(int argc, char **argv) 13448int main(int argc, char **argv)
@@ -13493,6 +13451,7 @@ int main(int argc, char **argv)
13493} 13451}
13494#endif 13452#endif
13495 13453
13454
13496/*- 13455/*-
13497 * Copyright (c) 1989, 1991, 1993, 1994 13456 * Copyright (c) 1989, 1991, 1993, 1994
13498 * The Regents of the University of California. All rights reserved. 13457 * The Regents of the University of California. All rights reserved.