diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-02-19 22:45:43 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-02-19 22:45:43 +0000 |
commit | 75810c0feeb259a08290f2207314a358066997e0 (patch) | |
tree | cae26fc88e8f21cc6cc34b3f53b9de6cff27b9ac /shell/ash.c | |
parent | 26cff6c3a9282d8a928dee12f1952b669168fa97 (diff) | |
download | busybox-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.c | 805 |
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 | ||
144 | static int isloginsh; | ||
144 | /* pid of main shell */ | 145 | /* pid of main shell */ |
145 | static int rootpid; | 146 | static 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 | ||
782 | typedef void *pointer; | ||
783 | |||
784 | static char nullstr[1]; /* zero length string */ | 783 | static char nullstr[1]; /* zero length string */ |
785 | static const char spcstr[] = " "; | 784 | static const char spcstr[] = " "; |
786 | static const char snlfmt[] = "%s\n"; | 785 | static const char snlfmt[] = "%s\n"; |
@@ -1356,7 +1355,7 @@ static const char syntax_index_table[258] = { | |||
1356 | 1355 | ||
1357 | static int funcblocksize; /* size of structures in function */ | 1356 | static int funcblocksize; /* size of structures in function */ |
1358 | static int funcstringsize; /* size of strings in node */ | 1357 | static int funcstringsize; /* size of strings in node */ |
1359 | static pointer funcblock; /* block to allocate function from */ | 1358 | static void *funcblock; /* block to allocate function from */ |
1360 | static char *funcstring; /* block to allocate strings from */ | 1359 | static char *funcstring; /* block to allocate strings from */ |
1361 | 1360 | ||
1362 | static const short nodesize[26] = { | 1361 | static const short nodesize[26] = { |
@@ -1853,45 +1852,6 @@ static void initvar(void) | |||
1853 | } while (++vp < end); | 1852 | } while (++vp < end); |
1854 | } | 1853 | } |
1855 | 1854 | ||
1856 | static 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 | ||
1897 | enum { | 1857 | enum { |
@@ -1989,8 +1949,7 @@ static void showjobs(FILE *, int); | |||
1989 | 1949 | ||
1990 | 1950 | ||
1991 | static void readcmdfile(char *); | 1951 | static void readcmdfile(char *); |
1992 | static 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; | |||
2018 | static int herefd = -1; | 1977 | static int herefd = -1; |
2019 | 1978 | ||
2020 | 1979 | ||
2021 | static pointer ckmalloc(size_t); | 1980 | static void *ckmalloc(size_t); |
2022 | static pointer ckrealloc(pointer, size_t); | 1981 | static void *ckrealloc(void *, size_t); |
2023 | static char *savestr(const char *); | 1982 | static char *savestr(const char *); |
2024 | static pointer stalloc(size_t); | 1983 | static void *stalloc(size_t); |
2025 | static void stunalloc(pointer); | 1984 | static void stunalloc(void *); |
2026 | static void setstackmark(struct stackmark *); | 1985 | static void setstackmark(struct stackmark *); |
2027 | static void popstackmark(struct stackmark *); | 1986 | static void popstackmark(struct stackmark *); |
2028 | static void growstackblock(void); | 1987 | static void growstackblock(void); |
@@ -2098,7 +2057,6 @@ static char *optptr; /* used by nextopt */ | |||
2098 | static char *minusc; /* argument to -c option */ | 2057 | static char *minusc; /* argument to -c option */ |
2099 | 2058 | ||
2100 | 2059 | ||
2101 | static void procargs(int, char **); | ||
2102 | static void optschanged(void); | 2060 | static void optschanged(void); |
2103 | static void setparam(char **); | 2061 | static void setparam(char **); |
2104 | static void freeparam(volatile struct shparam *); | 2062 | static void freeparam(volatile struct shparam *); |
@@ -2187,27 +2145,19 @@ static void | |||
2187 | reset(void) | 2145 | reset(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 | ||
7809 | static short profile_buf[16384]; | ||
7810 | extern int etext(); | ||
7811 | #endif | ||
7812 | |||
7813 | static int isloginsh; | ||
7814 | |||
7815 | static 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 | */ | ||
7824 | int ash_main(int argc, char **argv); | ||
7825 | int 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 | */ | ||
8011 | static void | ||
8012 | read_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 | */ |
8030 | static void | 7815 | static 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 | */ |
8137 | static pointer | 7922 | static void * |
8138 | ckrealloc(pointer p, size_t nbytes) | 7923 | ckrealloc(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 | ||
8146 | static pointer | 7931 | static void * |
8147 | ckmalloc(size_t nbytes) | 7932 | ckmalloc(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 | */ |
8173 | static pointer | 7958 | static void * |
8174 | stalloc(size_t nbytes) | 7959 | stalloc(size_t nbytes) |
8175 | { | 7960 | { |
8176 | char *p; | 7961 | char *p; |
@@ -8205,7 +7990,7 @@ stalloc(size_t nbytes) | |||
8205 | 7990 | ||
8206 | 7991 | ||
8207 | static void | 7992 | static void |
8208 | stunalloc(pointer p) | 7993 | stunalloc(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 | ||
8713 | static void options(int); | ||
8714 | static void setoption(int, int); | 8498 | static void setoption(int, int); |
8715 | 8499 | ||
8716 | 8500 | ||
8717 | /* | ||
8718 | * Process the shell command line arguments. | ||
8719 | */ | ||
8720 | static void | ||
8721 | procargs(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 | |||
8778 | static void | 8501 | static void |
8779 | optschanged(void) | 8502 | optschanged(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 |
8981 | static void change_lc_all(const char *value) | 8705 | static 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 | ||
8987 | static void change_lc_ctype(const char *value) | 8711 | static 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 | |||
9192 | struct heredoc { | 8915 | struct 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 | |||
9201 | static struct heredoc *heredoclist; /* list of here documents to read */ | 8922 | static struct heredoc *heredoclist; /* list of here documents to read */ |
9202 | 8923 | ||
9203 | |||
9204 | static union node *list(int); | 8924 | static union node *list(int); |
9205 | static union node *andor(void); | 8925 | static union node *andor(void); |
9206 | static union node *pipeline(void); | 8926 | static union node *pipeline(void); |
@@ -9214,16 +8934,40 @@ static int readtoken(void); | |||
9214 | static int xxreadtoken(void); | 8934 | static int xxreadtoken(void); |
9215 | static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs); | 8935 | static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs); |
9216 | static int noexpand(char *); | 8936 | static int noexpand(char *); |
9217 | static void synexpect(int) ATTRIBUTE_NORETURN; | ||
9218 | static void synerror(const char *) ATTRIBUTE_NORETURN; | ||
9219 | static void setprompt(int); | 8937 | static void setprompt(int); |
9220 | 8938 | ||
8939 | static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN; | ||
8940 | static void | ||
8941 | raise_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 | */ | ||
8952 | static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN; | ||
8953 | static void | ||
8954 | raise_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 | */ |
9226 | union node * | 8970 | static union node * |
9227 | parsecmd(int interact) | 8971 | parsecmd(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 = ≈ | 9194 | app = ≈ |
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! */ |
9853 | static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 }; | 9589 | static 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 | |||
9932 | static int | 9665 | static int |
9933 | xxreadtoken(void) | 9666 | xxreadtoken(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 | */ | ||
10674 | static 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 | |||
10686 | static void | ||
10687 | synerror(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 | |||
13204 | static 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 | */ | ||
13241 | static void | ||
13242 | procargs(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 | */ | ||
13301 | static void | ||
13302 | read_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 | ||
13315 | static short profile_buf[16384]; | ||
13316 | extern int etext(); | ||
13317 | #endif | ||
13318 | |||
13319 | int ash_main(int argc, char **argv); | ||
13320 | int 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 |
13489 | const char *applet_name = "debug stuff usage"; | 13447 | const char *applet_name = "debug stuff usage"; |
13490 | int main(int argc, char **argv) | 13448 | int 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. |