From c571730238486ed5a55a162a9eb0de7c38929757 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:35:23 +0200 Subject: win32: ash: setsignal(): return early, signalling is not supported --- shell/ash.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index ab935e72a..d6e44633a 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -3301,6 +3301,8 @@ setsignal(int signo) char cur_act, new_act; struct sigaction act; + if (ENABLE_PLATFORM_MINGW32) + return; t = trap[signo]; new_act = S_DFL; if (t != NULL) { /* trap for this sig is set */ -- cgit v1.2.3-55-g6feb From 1e105b8ae592274427039f07b6cbb864770cd660 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:37:05 +0200 Subject: win32: ash: waitcmd(): return early, not supported --- shell/ash.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index d6e44633a..f2f50c0e6 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -4054,6 +4054,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv) int retval; struct job *jp; + if (ENABLE_PLATFORM_MINGW32) + return 0; + if (pending_sig) raise_exception(EXSIG); -- cgit v1.2.3-55-g6feb From ceba268022afc208df12bb30798ad1bace95d8e8 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:37:48 +0200 Subject: win32: ash: forkshell(): return early, MinGW port will have another way to "fork" --- shell/ash.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index f2f50c0e6..34a5b65aa 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -4700,6 +4700,9 @@ forkshell(struct job *jp, union node *n, int mode) int pid; TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode)); + if (ENABLE_PLATFORM_MINGW32) + return -1; + pid = fork(); if (pid < 0) { TRACE(("Fork failed, errno=%d", errno)); -- cgit v1.2.3-55-g6feb From 75522a5e14bf1f145ec7add43c1ca4bad370d293 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:39:55 +0200 Subject: win32: ash: exptilde(): do not call (unsupported) getpwnam() --- shell/ash.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 34a5b65aa..f71f6a5e3 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5626,6 +5626,8 @@ exptilde(char *startp, char *p, int flags) if (*name == '\0') { home = lookupvar(homestr); } else { + if (ENABLE_PLATFORM_MINGW32) + goto lose; pw = getpwnam(name); if (pw == NULL) goto lose; -- cgit v1.2.3-55-g6feb From 7ed8528562d4b034f582afe0c0e2490303d0e6a2 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:32:54 +0200 Subject: win32: ash: skip O_APPEND support --- shell/ash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index f71f6a5e3..bfbd6a027 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -774,7 +774,7 @@ static void opentrace(void) { char s[100]; -#ifdef O_APPEND +#if defined(O_APPEND) && !ENABLE_PLATFORM_MINGW32 int flags; #endif @@ -799,7 +799,7 @@ opentrace(void) return; } } -#ifdef O_APPEND +#if defined(O_APPEND) && !ENABLE_PLATFORM_MINGW32 flags = fcntl(fileno(tracefile), F_GETFL); if (flags >= 0) fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); -- cgit v1.2.3-55-g6feb From ac30d16aa3780ced891b7cec3d1fabf9fc78cc7d Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:34:54 +0200 Subject: win32: ash: is_absolute_path() --- shell/ash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index bfbd6a027..05ca74579 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2527,7 +2527,7 @@ cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) } if (!dest) dest = nullstr; - if (*dest == '/') + if (is_absolute_path(dest)) goto step7; if (*dest == '.') { c = dest[1]; @@ -12213,7 +12213,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) } } /* if rehash, don't redo absolute path names */ - if (fullname[0] == '/' && idx <= prev) { + if (is_absolute_path(fullname) && idx <= prev) { if (idx < prev) continue; TRACE(("searchexec \"%s\": no change\n", name)); -- cgit v1.2.3-55-g6feb From 51ce60d01be26725012f0d15f89da002de2f727a Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:40:36 +0200 Subject: win32: ash: shellexec(): support both / and \ as dir separator --- shell/ash.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 05ca74579..85d8f18a5 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7300,7 +7300,7 @@ shellexec(char **argv, const char *path, int idx) clearredir(/*drop:*/ 1); envp = listvars(VEXPORT, VUNSET, 0); - if (strchr(argv[0], '/') != NULL + if ((strchr(argv[0], '/') || (ENABLE_PLATFORM_MINGW32 && strchr(argv[0], '\\'))) #if ENABLE_FEATURE_SH_STANDALONE || (applet_no = find_applet_by_name(argv[0])) >= 0 #endif @@ -12000,7 +12000,7 @@ find_dot_file(char *name) struct stat statb; /* don't try this for absolute or relative paths */ - if (strchr(name, '/')) + if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) return name; /* IIRC standards do not say whether . is to be searched. @@ -12103,10 +12103,11 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) struct stat statb; int e; int updatetbl; + IF_PLATFORM_MINGW32(int len); struct builtincmd *bcmd; /* If name contains a slash, don't use PATH or hash table */ - if (strchr(name, '/') != NULL) { + if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) { entry->u.index = -1; if (act & DO_ABS) { while (stat(name, &statb) < 0) { -- cgit v1.2.3-55-g6feb From ff46d9306a744665693f1f5420913ff97459c89c Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:41:42 +0200 Subject: win32: ash: preadbuffer(): accept \r\n as line ending --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 85d8f18a5..da3b6d031 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9573,7 +9573,7 @@ preadbuffer(void) more--; c = *q; - if (c == '\0') { + if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r')) { memmove(q, q + 1, more); } else { q++; -- cgit v1.2.3-55-g6feb From df0d6904f35049e31d5b484b127fcb97c7f3ef5f Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:34:05 +0200 Subject: win32: ash: path_advance(): support both colon and semicolon as path separator --- shell/ash.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index da3b6d031..db27cefe5 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2261,8 +2261,18 @@ path_advance(const char **path, const char *name) if (*path == NULL) return NULL; start = *path; +#if ENABLE_PLATFORM_MINGW32 + p = next_path_sep(start); + q = strchr(start, '%'); + if ((p && q && q < p) || (!p && q)) + p = q; + if (!p) + for (p = start; *p; p++) + continue; +#else for (p = start; *p && *p != ':' && *p != '%'; p++) continue; +#endif len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ while (stackblocksize() < len) growstackblock(); -- cgit v1.2.3-55-g6feb From 78519fdc536cbd5ce6e0d2c41d5de28e814267c8 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:33:30 +0200 Subject: win32: ash: path_advance(): save space for .exe later --- shell/ash.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index db27cefe5..8df1a4062 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2274,7 +2274,9 @@ path_advance(const char **path, const char *name) continue; #endif len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ - while (stackblocksize() < len) + + /* preserve space for .exe too */ + while (stackblocksize() < (ENABLE_PLATFORM_MINGW32 ? len+4 : len)) growstackblock(); q = stackblock(); if (p != start) { -- cgit v1.2.3-55-g6feb From 7014646c269d229d4d62bd95ab91490c45709f17 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:34:32 +0200 Subject: win32: ash: new implementation for updatepwd() --- shell/ash.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 8df1a4062..a0c22689f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2392,6 +2392,98 @@ cdopt(void) static const char * updatepwd(const char *dir) { +#if ENABLE_PLATFORM_MINGW32 + /* + * Due to Windows drive notion, getting pwd is a completely + * different thing. Handle it in a separate routine + */ + + char *new; + char *p; + char *cdcomppath; + const char *lim; + /* + * There are four cases + * absdrive + abspath: c:/path + * absdrive + !abspath: c:path + * !absdrive + abspath: /path + * !absdrive + !abspath: path + * + * Damn DOS! + * c:path behaviour is "undefined" + * To properly handle this case, I have to keep track of cwd + * of every drive, which is too painful to do. + * So when c:path is given, I assume it's c:${curdir}path + * with ${curdir} comes from the current drive + */ + int absdrive = *dir && dir[1] == ':'; + int abspath = absdrive ? dir[2] == '/' : *dir == '/'; + char *drive; + + cdcomppath = ststrdup(dir); + STARTSTACKSTR(new); + if (!absdrive && curdir == nullstr) + return 0; + if (!abspath) { + if (curdir == nullstr) + return 0; + new = stack_putstr(curdir, new); + } + new = makestrspace(strlen(dir) + 2, new); + + drive = stackblock(); + if (absdrive) { + *drive = *dir; + cdcomppath += 2; + dir += 2; + } else { + *drive = *curdir; + } + drive[1] = ':'; /* in case of absolute drive+path */ + + if (abspath) + new = drive + 2; + lim = drive + 3; + if (!abspath) { + if (new[-1] != '/') + USTPUTC('/', new); + if (new > lim && *lim == '/') + lim++; + } else { + USTPUTC('/', new); + cdcomppath ++; + if (dir[1] == '/' && dir[2] != '/') { + USTPUTC('/', new); + cdcomppath++; + lim++; + } + } + p = strtok(cdcomppath, "/"); + while (p) { + switch (*p) { + case '.': + if (p[1] == '.' && p[2] == '\0') { + while (new > lim) { + STUNPUTC(new); + if (new[-1] == '/') + break; + } + break; + } + if (p[1] == '\0') + break; + /* fall through */ + default: + new = stack_putstr(p, new); + USTPUTC('/', new); + } + p = strtok(0, "/"); + } + if (new > lim) + STUNPUTC(new); + *new = 0; + return stackblock(); +#else char *new; char *p; char *cdcomppath; @@ -2445,6 +2537,7 @@ updatepwd(const char *dir) STUNPUTC(new); *new = 0; return stackblock(); +#endif } /* -- cgit v1.2.3-55-g6feb From 18f4920aa10859a30104efb68978f5d72c8f7c47 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:36:22 +0200 Subject: win32: ash: stay away from fcntl(F_DUPFD) --- shell/ash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index a0c22689f..007d501f9 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -3715,7 +3715,7 @@ setjobctl(int on) if (--fd < 0) goto out; } - fd = fcntl(fd, F_DUPFD, 10); + fd = copyfd(fd, 10); if (ofd >= 0) close(ofd); if (fd < 0) @@ -5270,7 +5270,7 @@ redirect(union node *redir, int flags) #endif if (need_to_remember(sv, fd)) { /* Copy old descriptor */ - i = fcntl(fd, F_DUPFD, 10); + i = copyfd(fd, 10); /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds * are closed in popredir() in the child, preventing them from leaking * into child. (popredir() also cleans up the mess in case of failures) -- cgit v1.2.3-55-g6feb From 6ce8ae13d4556a2f966ad58b58309fba4ff97fe4 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:38:41 +0200 Subject: win32: ash: copyfd(): work around fcntl(F_DUPFD) --- shell/ash.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 007d501f9..3380e573e 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5126,6 +5126,18 @@ copyfd(int from, int to) /*if (from != to)*/ newfd = dup2(from, to); } else { + if (ENABLE_PLATFORM_MINGW32) { + char* fds = ckmalloc(to); + int i,fd; + memset(fds,0,to); + while ((fd = dup(from)) < to && fd >= 0) + fds[fd] = 1; + for (i = 0;i < to;i ++) + if (fds[i]) + close(i); + free(fds); + return fd; + } newfd = fcntl(from, F_DUPFD, to); } if (newfd < 0) { -- cgit v1.2.3-55-g6feb From 3c40a1819c3d9e02ba7a387a75f9b4144e8f5264 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:39:09 +0200 Subject: win32: ash: openredirect(): support /dev/null --- shell/ash.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 3380e573e..dcf6fcbcb 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5044,6 +5044,31 @@ openredirect(union node *redir) char *fname; int f; +#if ENABLE_PLATFORM_MINGW32 + /* Support for /dev/null */ + switch (redir->nfile.type) { + case NFROM: + if (!strcmp(redir->nfile.expfname, "/dev/null")) + return open("nul",O_RDWR); + if (!strncmp(redir->nfile.expfname, "/dev/", 5)) { + ash_msg("Unhandled device %s\n", redir->nfile.expfname); + return -1; + } + break; + + case NFROMTO: + case NTO: + case NCLOBBER: + case NAPPEND: + if (!strcmp(redir->nfile.expfname, "/dev/null")) + return open("nul",O_RDWR); + if (!strncmp(redir->nfile.expfname, "/dev/", 5)) { + ash_msg("Unhandled device %s\n", redir->nfile.expfname); + return -1; + } + break; + } +#endif switch (redir->nfile.type) { case NFROM: fname = redir->nfile.expfname; -- cgit v1.2.3-55-g6feb From d104eddf3071815bc9586763efb63ed14ca72790 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:43:59 +0200 Subject: win32: ash: find_command(): also find .exe --- shell/ash.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index dcf6fcbcb..1b448371d 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12362,6 +12362,26 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) TRACE(("searchexec \"%s\": no change\n", name)); goto success; } +#if ENABLE_PLATFORM_MINGW32 + len = strlen(fullname); + if (len > 4 && !strcasecmp(fullname+len-4, ".exe")) { + if (stat(fullname, &statb) < 0) { + if (errno != ENOENT && errno != ENOTDIR) + e = errno; + goto loop; + } + } + else { + /* path_advance() has reserved space for .exe */ + memcpy(fullname+len, ".exe", 5); + if (stat(fullname, &statb) < 0) { + if (errno != ENOENT && errno != ENOTDIR) + e = errno; + goto loop; + } + fullname[len] = '\0'; + } +#else while (stat(fullname, &statb) < 0) { #ifdef SYSV if (errno == EINTR) @@ -12371,6 +12391,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) e = errno; goto loop; } +#endif e = EACCES; /* if we fail, this will be the error */ if (!S_ISREG(statb.st_mode)) continue; -- cgit v1.2.3-55-g6feb From fa6f44ea7205416837bc72bb9948ba376c2af7c5 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:44:48 +0200 Subject: win32: ash: reimplement waitpid(-1) --- shell/ash.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 1b448371d..31ad46aa7 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -3889,6 +3889,53 @@ sprint_status(char *s, int status, int sigonly) return col; } +#if ENABLE_PLATFORM_MINGW32 +/* + * Windows does not know about parent-child relationship + * They don't support waitpid(-1) + */ +static pid_t +waitpid_child(int *status) +{ + HANDLE *pidlist, *pidp; + int pid_nr = 0; + pid_t pid; + DWORD win_status, idx; + struct job *jb; + + #define LOOP(stmt) \ + for (jb = curjob; jb; jb = jb->prev_job) { \ + struct procstat *ps, *psend; \ + if (jb->state == JOBDONE) \ + continue; \ + ps = jb->ps; \ + psend = ps + jb->nprocs; \ + while (ps < psend) { \ + if (ps->ps_pid != -1) { \ + stmt; \ + } \ + ps++; \ + } \ + } + + LOOP(pid_nr++); + pidp = pidlist = ckmalloc(sizeof(*pidlist)*pid_nr); + LOOP(*pidp++ = (HANDLE)ps->ps_pid); + #undef LOOP + + idx = WaitForMultipleObjects(pid_nr, pidlist, FALSE, INFINITE); + if (idx >= pid_nr) { + free(pidlist); + return -1; + } + GetExitCodeProcess(pidlist[idx], &win_status); + pid = (int)pidlist[idx]; + free(pidlist); + *status = (int)win_status; + return pid; +} +#endif + static int dowait(int wait_flags, struct job *job) { @@ -3905,7 +3952,11 @@ dowait(int wait_flags, struct job *job) * NB: _not_ safe_waitpid, we need to detect EINTR */ if (doing_jobctl) wait_flags |= WUNTRACED; +#if ENABLE_PLATFORM_MINGW32 + pid = waitpid_child(&status); +#else pid = waitpid(-1, &status, wait_flags); +#endif TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", pid, status, errno, strerror(errno))); if (pid <= 0) @@ -3928,6 +3979,8 @@ dowait(int wait_flags, struct job *job) jobno(jp), pid, ps->ps_status, status)); ps->ps_status = status; thisjob = jp; + if (ENABLE_PLATFORM_MINGW32) + ps->ps_pid = -1; } if (ps->ps_status == -1) state = JOBRUNNING; -- cgit v1.2.3-55-g6feb From a7b648d26f7ace9c025e5f4ae5060d83d69080ce Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:45:01 +0200 Subject: win32: ash: FIXME --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 31ad46aa7..181357c1c 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -4818,7 +4818,7 @@ static void forkparent(struct job *jp, union node *n, int mode, pid_t pid) { TRACE(("In parent shell: child = %d\n", pid)); - if (!jp) { + if (!jp && !ENABLE_PLATFORM_MINGW32) { /* FIXME not quite understand this */ while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0) continue; jobless++; -- cgit v1.2.3-55-g6feb From 40f78f44fe2fa52698be992ed3a8c0cf5429f8d6 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:40:59 +0200 Subject: win32: ash: nodeckstrdup(): tolerate NULL string --- shell/ash.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 181357c1c..d4b60f081 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8144,10 +8144,12 @@ calcsize(union node *n) } static char * -nodeckstrdup(char *s) +nodeckstrdup(const char *s) { char *rtn = funcstring; + if (!s) + return NULL; strcpy(funcstring, s); funcstring += strlen(s) + 1; return rtn; -- cgit v1.2.3-55-g6feb From 268083aec522fb734e2f8f5be796587d5dfd1bbc Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:31:43 +0200 Subject: win32: Support saving pointer location in calcsize()/copynode() --- shell/ash.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index d4b60f081..c99a1351f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8012,6 +8012,10 @@ static int funcblocksize; /* size of structures in function */ static int funcstringsize; /* size of strings in node */ static void *funcblock; /* block to allocate function from */ static char *funcstring; /* block to allocate strings from */ +#if ENABLE_PLATFORM_MINGW32 +static int nodeptrsize; +static int *nodeptr; +#endif /* flags in argument to evaltree */ #define EV_EXIT 01 /* exit after evaluating tree */ @@ -8057,6 +8061,7 @@ sizenodelist(struct nodelist *lp) { while (lp) { funcblocksize += SHELL_ALIGN(sizeof(struct nodelist)); + IF_PLATFORM_MINGW32(nodeptrsize += 2); calcsize(lp->n); lp = lp->next; } @@ -8073,15 +8078,18 @@ calcsize(union node *n) calcsize(n->ncmd.redirect); calcsize(n->ncmd.args); calcsize(n->ncmd.assign); + IF_PLATFORM_MINGW32(nodeptrsize += 3); break; case NPIPE: sizenodelist(n->npipe.cmdlist); + IF_PLATFORM_MINGW32(nodeptrsize++); break; case NREDIR: case NBACKGND: case NSUBSHELL: calcsize(n->nredir.redirect); calcsize(n->nredir.n); + IF_PLATFORM_MINGW32(nodeptrsize += 2); break; case NAND: case NOR: @@ -8090,31 +8098,37 @@ calcsize(union node *n) case NUNTIL: calcsize(n->nbinary.ch2); calcsize(n->nbinary.ch1); + IF_PLATFORM_MINGW32(nodeptrsize += 2); break; case NIF: calcsize(n->nif.elsepart); calcsize(n->nif.ifpart); calcsize(n->nif.test); + IF_PLATFORM_MINGW32(nodeptrsize += 3); break; case NFOR: funcstringsize += strlen(n->nfor.var) + 1; calcsize(n->nfor.body); calcsize(n->nfor.args); + IF_PLATFORM_MINGW32(nodeptrsize += 3); break; case NCASE: calcsize(n->ncase.cases); calcsize(n->ncase.expr); + IF_PLATFORM_MINGW32(nodeptrsize += 2); break; case NCLIST: calcsize(n->nclist.body); calcsize(n->nclist.pattern); calcsize(n->nclist.next); + IF_PLATFORM_MINGW32(nodeptrsize += 3); break; case NDEFUN: case NARG: sizenodelist(n->narg.backquote); funcstringsize += strlen(n->narg.text) + 1; calcsize(n->narg.next); + IF_PLATFORM_MINGW32(nodeptrsize += 3); break; case NTO: #if ENABLE_ASH_BASH_COMPAT @@ -8126,19 +8140,23 @@ calcsize(union node *n) case NAPPEND: calcsize(n->nfile.fname); calcsize(n->nfile.next); + IF_PLATFORM_MINGW32(nodeptrsize += 2); break; case NTOFD: case NFROMFD: calcsize(n->ndup.vname); calcsize(n->ndup.next); + IF_PLATFORM_MINGW32(nodeptrsize += 2); break; case NHERE: case NXHERE: calcsize(n->nhere.doc); calcsize(n->nhere.next); + IF_PLATFORM_MINGW32(nodeptrsize += 2); break; case NNOT: calcsize(n->nnot.com); + IF_PLATFORM_MINGW32(nodeptrsize++); break; }; } @@ -8157,6 +8175,18 @@ nodeckstrdup(const char *s) static union node *copynode(union node *); +#if ENABLE_PLATFORM_MINGW32 +# define SAVE_PTR(dst) {if (nodeptr) *nodeptr++ = (int)&(dst);} +# define SAVE_PTR2(dst1,dst2) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);}} +# define SAVE_PTR3(dst1,dst2,dst3) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);*nodeptr++ = (int)&(dst3);}} +# define SAVE_PTR4(dst1,dst2,dst3,dst4) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);*nodeptr++ = (int)&(dst3);*nodeptr++ = (int)&(dst4);}} +#else +# define SAVE_PTR(dst) +# define SAVE_PTR2(dst,dst2) +# define SAVE_PTR3(dst,dst2,dst3) +# define SAVE_PTR4(dst,dst2,dst3,dst4) +#endif + static struct nodelist * copynodelist(struct nodelist *lp) { @@ -8168,6 +8198,7 @@ copynodelist(struct nodelist *lp) *lpp = funcblock; funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist)); (*lpp)->n = copynode(lp->n); + SAVE_PTR2((*lpp)->n, (*lpp)->next); lp = lp->next; lpp = &(*lpp)->next; } @@ -8190,16 +8221,19 @@ copynode(union node *n) new->ncmd.redirect = copynode(n->ncmd.redirect); new->ncmd.args = copynode(n->ncmd.args); new->ncmd.assign = copynode(n->ncmd.assign); + SAVE_PTR3(new->ncmd.redirect,new->ncmd.args, new->ncmd.assign); break; case NPIPE: new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); new->npipe.pipe_backgnd = n->npipe.pipe_backgnd; + SAVE_PTR(new->npipe.cmdlist); break; case NREDIR: case NBACKGND: case NSUBSHELL: new->nredir.redirect = copynode(n->nredir.redirect); new->nredir.n = copynode(n->nredir.n); + SAVE_PTR2(new->nredir.redirect,new->nredir.n); break; case NAND: case NOR: @@ -8208,31 +8242,37 @@ copynode(union node *n) case NUNTIL: new->nbinary.ch2 = copynode(n->nbinary.ch2); new->nbinary.ch1 = copynode(n->nbinary.ch1); + SAVE_PTR2(new->nbinary.ch1,new->nbinary.ch2); break; case NIF: new->nif.elsepart = copynode(n->nif.elsepart); new->nif.ifpart = copynode(n->nif.ifpart); new->nif.test = copynode(n->nif.test); + SAVE_PTR3(new->nif.elsepart,new->nif.ifpart,new->nif.test); break; case NFOR: new->nfor.var = nodeckstrdup(n->nfor.var); new->nfor.body = copynode(n->nfor.body); new->nfor.args = copynode(n->nfor.args); + SAVE_PTR3(new->nfor.var,new->nfor.body,new->nfor.args); break; case NCASE: new->ncase.cases = copynode(n->ncase.cases); new->ncase.expr = copynode(n->ncase.expr); + SAVE_PTR2(new->ncase.cases,new->ncase.expr); break; case NCLIST: new->nclist.body = copynode(n->nclist.body); new->nclist.pattern = copynode(n->nclist.pattern); new->nclist.next = copynode(n->nclist.next); + SAVE_PTR3(new->nclist.body,new->nclist.pattern,new->nclist.next); break; case NDEFUN: case NARG: new->narg.backquote = copynodelist(n->narg.backquote); new->narg.text = nodeckstrdup(n->narg.text); new->narg.next = copynode(n->narg.next); + SAVE_PTR3(new->narg.backquote,new->narg.text,new->narg.next); break; case NTO: #if ENABLE_ASH_BASH_COMPAT @@ -8245,6 +8285,7 @@ copynode(union node *n) new->nfile.fname = copynode(n->nfile.fname); new->nfile.fd = n->nfile.fd; new->nfile.next = copynode(n->nfile.next); + SAVE_PTR2(new->nfile.fname,new->nfile.next); break; case NTOFD: case NFROMFD: @@ -8252,15 +8293,18 @@ copynode(union node *n) new->ndup.dupfd = n->ndup.dupfd; new->ndup.fd = n->ndup.fd; new->ndup.next = copynode(n->ndup.next); + SAVE_PTR2(new->ndup.vname,new->ndup.next); break; case NHERE: case NXHERE: new->nhere.doc = copynode(n->nhere.doc); new->nhere.fd = n->nhere.fd; new->nhere.next = copynode(n->nhere.next); + SAVE_PTR2(new->nhere.doc,new->nhere.next); break; case NNOT: new->nnot.com = copynode(n->nnot.com); + SAVE_PTR(new->nnot.com); break; }; new->type = n->type; @@ -8283,6 +8327,7 @@ copyfunc(union node *n) f = ckmalloc(blocksize + funcstringsize); funcblock = (char *) f + offsetof(struct funcnode, n); funcstring = (char *) f + blocksize; + IF_PLATFORM_MINGW32(nodeptr = NULL); copynode(n); f->count = 0; return f; -- cgit v1.2.3-55-g6feb From 7461a43ca9cc97f062b2e18fb07c58d0951250d7 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:52:06 +0200 Subject: win32: ash: macros for implementing simple foo_size, foo_copy --- shell/ash.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index c99a1351f..518615316 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13281,6 +13281,41 @@ int ash_main(int argc UNUSED_PARAM, char **argv) /* NOTREACHED */ } +/* + * forkshell_prepare() and friends + */ +#define SLIST_SIZE_BEGIN(name,type) \ +static void \ +name(type *p) \ +{ \ + while (p) { \ + funcblocksize += sizeof(type); + /* do something here with p */ +#define SLIST_SIZE_END() \ + nodeptrsize++; \ + p = p->next; \ + } \ +} + +#define SLIST_COPY_BEGIN(name,type) \ +static type * \ +name(type *vp) \ +{ \ + type *start; \ + type **vpp; \ + vpp = &start; \ + while (vp) { \ + *vpp = funcblock; \ + funcblock = (char *) funcblock + sizeof(type); + /* do something here with vpp and vp */ +#define SLIST_COPY_END() \ + SAVE_PTR((*vpp)->next); \ + vp = vp->next; \ + vpp = &(*vpp)->next; \ + } \ + *vpp = NULL; \ + return start; \ +} /*- * Copyright (c) 1989, 1991, 1993, 1994 -- cgit v1.2.3-55-g6feb From 10a40a90e360807cee1c1a4452013091f22f68e9 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:52:34 +0200 Subject: win32: ash: struct var --- shell/ash.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 518615316..fa4410749 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13317,6 +13317,24 @@ name(type *vp) \ return start; \ } +/* + * struct var + */ +SLIST_SIZE_BEGIN(var_size,struct var) +funcstringsize += strlen(p->text) + 1; +nodeptrsize++; /* p->text */ +SLIST_SIZE_END() + +SLIST_COPY_BEGIN(var_copy,struct var) +(*vpp)->text = nodeckstrdup(vp->text); +(*vpp)->flags = vp->flags; +/* + * The only place that can set struct var#func is varinit[], + * which will be fixed by forkshell_init() + */ +(*vpp)->func = NULL; +SAVE_PTR((*vpp)->text); +SLIST_COPY_END() /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From 28db08865aa86f66ac51ad58ca5c2cfdfebe9c0d Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:53:03 +0200 Subject: win32: ash: struct localvar --- shell/ash.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index fa4410749..e028d0fcd 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13335,6 +13335,22 @@ SLIST_COPY_BEGIN(var_copy,struct var) (*vpp)->func = NULL; SAVE_PTR((*vpp)->text); SLIST_COPY_END() + +/* + * struct localvar + */ +SLIST_SIZE_BEGIN(localvar_size,struct localvar) +var_size(p->vp); +funcstringsize += strlen(p->text) + 1; +nodeptrsize += 2; /* p->vp, p->text */ +SLIST_SIZE_END() + +SLIST_COPY_BEGIN(localvar_copy,struct localvar) +(*vpp)->text = nodeckstrdup(vp->text); +(*vpp)->flags = vp->flags; +(*vpp)->vp = var_copy(vp->vp); +SAVE_PTR2((*vpp)->vp, (*vpp)->text); +SLIST_COPY_END() /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From c485f06ab621b87c0501c4c628a697d48addafa8 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:53:26 +0200 Subject: win32: ash: struct strlist --- shell/ash.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index e028d0fcd..28d2f5b9a 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13351,6 +13351,19 @@ SLIST_COPY_BEGIN(localvar_copy,struct localvar) (*vpp)->vp = var_copy(vp->vp); SAVE_PTR2((*vpp)->vp, (*vpp)->text); SLIST_COPY_END() + +/* + * struct strlist + */ +SLIST_SIZE_BEGIN(strlist_size,struct strlist) +funcstringsize += strlen(p->text) + 1; +nodeptrsize++; /* p->text */ +SLIST_SIZE_END() + +SLIST_COPY_BEGIN(strlist_copy,struct strlist) +(*vpp)->text = nodeckstrdup(vp->text); +SAVE_PTR((*vpp)->text); +SLIST_COPY_END() /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From eab88849259848439c173f563c7a37079a8c36c8 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:53:53 +0200 Subject: win32: ash: struct tblentry --- shell/ash.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 28d2f5b9a..1fb2745b3 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13364,6 +13364,61 @@ SLIST_COPY_BEGIN(strlist_copy,struct strlist) (*vpp)->text = nodeckstrdup(vp->text); SAVE_PTR((*vpp)->text); SLIST_COPY_END() + +/* + * struct tblentry + */ +static void +tblentry_size(struct tblentry *tep) +{ + while (tep) { + funcblocksize += sizeof(struct tblentry) + strlen(tep->cmdname) + 1; + /* CMDBUILTIN, e->param.cmd needs no pointer relocation */ + if (tep->cmdtype == CMDFUNCTION) { + funcblocksize += offsetof(struct funcnode, n); + calcsize(&tep->param.func->n); + nodeptrsize++; /* tep->param.func */ + } + nodeptrsize++; /* tep->next */ + tep = tep->next; + } +} + +static struct tblentry * +tblentry_copy(struct tblentry *tep) +{ + struct tblentry *start; + struct tblentry **newp; + int size; + + newp = &start; + while (tep) { + *newp = funcblock; + size = sizeof(struct tblentry) + strlen(tep->cmdname) + 1; + + funcblock = (char *) funcblock + size; + memcpy(*newp, tep, size); + switch (tep->cmdtype) { + case CMDBUILTIN: + /* No pointer saving, this field must be fixed by forkshell_init() */ + (*newp)->param.cmd = (const struct builtincmd *)(tep->param.cmd - builtintab); + break; + case CMDFUNCTION: + (*newp)->param.func = funcblock; + funcblock = (char *) funcblock + offsetof(struct funcnode, n); + copynode(&tep->param.func->n); + SAVE_PTR((*newp)->param.func); + break; + default: + break; + } + SAVE_PTR((*newp)->next); + tep = tep->next; + newp = &(*newp)->next; + } + *newp = NULL; + return start; +} /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From 612facb32acb4907156c11a47b31e5edecf2957a Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:54:43 +0200 Subject: win32: ash: struct tblentry **cmdtable --- shell/ash.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 1fb2745b3..b4ecf9d3a 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13419,6 +13419,30 @@ tblentry_copy(struct tblentry *tep) *newp = NULL; return start; } + +static void +cmdtable_size(struct tblentry **cmdtablep) +{ + int i; + nodeptrsize += CMDTABLESIZE; + funcblocksize += sizeof(struct tblentry *)*CMDTABLESIZE; + for (i = 0; i < CMDTABLESIZE; i++) + tblentry_size(cmdtablep[i]); +} + +static struct tblentry ** +cmdtable_copy(struct tblentry **cmdtablep) +{ + struct tblentry **new = funcblock; + int i; + + funcblock = (char *) funcblock + sizeof(struct tblentry *)*CMDTABLESIZE; + for (i = 0; i < CMDTABLESIZE; i++) { + new[i] = tblentry_copy(cmdtablep[i]); + SAVE_PTR(new[i]); + } + return new; +} /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From 3a3de418649e2b2d5121cf1cfa0f4b9b2d0ed6ba Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:55:14 +0200 Subject: win32: ash: char ** --- shell/ash.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index b4ecf9d3a..2b7bc66c7 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13443,6 +13443,40 @@ cmdtable_copy(struct tblentry **cmdtablep) } return new; } + +/* + * char ** + */ +static void +argv_size(char **p) +{ + while (p && *p) { + funcblocksize += sizeof(char *); + funcstringsize += strlen(*p)+1; + nodeptrsize++; + p++; + } + funcblocksize += sizeof(char *); +} + +static char ** +argv_copy(char **p) +{ + char **new, **start = funcblock; + + while (p && *p) { + new = funcblock; + funcblock = (char *) funcblock + sizeof(char *); + *new = nodeckstrdup(*p); + SAVE_PTR(*new); + p++; + new++; + } + new = funcblock; + funcblock = (char *) funcblock + sizeof(char *); + *new = NULL; + return start; +} /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From c31f604099fe9b4c4da665eebab9536b86f99abd Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:55:42 +0200 Subject: win32: ash: struct redirtab --- shell/ash.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 2b7bc66c7..a04aecfd1 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13477,6 +13477,39 @@ argv_copy(char **p) *new = NULL; return start; } + +/* + * struct redirtab + */ +static void +redirtab_size(struct redirtab *rdtp) +{ + while (rdtp) { + funcblocksize += sizeof(*rdtp)+sizeof(rdtp->two_fd[0])*rdtp->pair_count; + rdtp = rdtp->next; + nodeptrsize++; /* rdtp->next */ + } +} + +static struct redirtab * +redirtab_copy(struct redirtab *rdtp) +{ + struct redirtab *start; + struct redirtab **vpp; + + vpp = &start; + while (rdtp) { + int size = sizeof(*rdtp)+sizeof(rdtp->two_fd[0])*rdtp->pair_count; + *vpp = funcblock; + funcblock = (char *) funcblock + size; + memcpy(*vpp, rdtp, size); + SAVE_PTR((*vpp)->next); + rdtp = rdtp->next; + vpp = &(*vpp)->next; + } + *vpp = NULL; + return start; +} /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From 5af6e2834e42261fa75af5942b6b3eef78b6028d Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:56:15 +0200 Subject: win32: ash: struct globals_var --- shell/ash.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index a04aecfd1..72f9630d8 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13510,6 +13510,63 @@ redirtab_copy(struct redirtab *rdtp) *vpp = NULL; return start; } + +#undef shellparam +#undef redirlist +#undef varinit +#undef vartab +static void +globals_var_size(struct globals_var *gvp) +{ + int i; + + funcblocksize += sizeof(struct globals_var); + argv_size(gvp->shellparam.p); + redirtab_size(gvp->redirlist); + for (i = 0; i < VTABSIZE; i++) + var_size(gvp->vartab[i]); + for (i = 0; i < ARRAY_SIZE(varinit_data); i++) + var_size(gvp->varinit+i); + nodeptrsize += 2 + VTABSIZE; /* gvp->redirlist, gvp->shellparam.p, vartab */ +} + +#undef g_nullredirs +#undef preverrout_fd +static struct globals_var * +globals_var_copy(struct globals_var *gvp) +{ + int i; + struct globals_var *new; + + new = funcblock; + funcblock = (char *) funcblock + sizeof(struct globals_var); + + /* shparam */ + memcpy(&new->shellparam, &gvp->shellparam, sizeof(struct shparam)); + new->shellparam.malloced = 0; + new->shellparam.p = argv_copy(gvp->shellparam.p); + SAVE_PTR(new->shellparam.p); + + new->redirlist = redirtab_copy(gvp->redirlist); + SAVE_PTR(new->redirlist); + + new->g_nullredirs = gvp->g_nullredirs; + new->preverrout_fd = gvp->preverrout_fd; + for (i = 0; i < VTABSIZE; i++) { + new->vartab[i] = var_copy(gvp->vartab[i]); + SAVE_PTR(new->vartab[i]); + } + + /* Can't use var_copy because varinit is already allocated */ + for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { + new->varinit[i].next = NULL; + new->varinit[i].text = nodeckstrdup(gvp->varinit[i].text); + SAVE_PTR(new->varinit[i].text); + new->varinit[i].flags = gvp->varinit[i].flags; + new->varinit[i].func = gvp->varinit[i].func; + } + return new; +} /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From 4084f1ce1e02548db7e0bc3ec6efb37078d445e8 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:56:40 +0200 Subject: win32: ash: struct globals_misc --- shell/ash.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 72f9630d8..f41bba36d 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13567,6 +13567,40 @@ globals_var_copy(struct globals_var *gvp) } return new; } + +#undef minusc +#undef curdir +#undef physdir +#undef arg0 +#undef nullstr +static void +globals_misc_size(struct globals_misc *p) +{ + funcblocksize += sizeof(struct globals_misc); + funcstringsize += p->minusc ? strlen(p->minusc) + 1 : 1; + if (p->curdir != p->nullstr) + funcstringsize += strlen(p->curdir) + 1; + if (p->physdir != p->nullstr) + funcstringsize += strlen(p->physdir) + 1; + funcstringsize += strlen(p->arg0) + 1; + nodeptrsize += 4; /* minusc, curdir, physdir, arg0 */ +} + +static struct globals_misc * +globals_misc_copy(struct globals_misc *p) +{ + struct globals_misc *new = funcblock; + + funcblock = (char *) funcblock + sizeof(struct globals_misc); + memcpy(new, p, sizeof(struct globals_misc)); + + new->minusc = nodeckstrdup(p->minusc); + new->curdir = p->curdir != p->nullstr ? nodeckstrdup(p->curdir) : new->nullstr; + new->physdir = p->physdir != p->nullstr ? nodeckstrdup(p->physdir) : new->nullstr; + new->arg0 = nodeckstrdup(p->arg0); + SAVE_PTR4(new->minusc, new->curdir, new->physdir, new->arg0); + return new; +} /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From e8fb0c108f83dbdd3dcd6110fa58fea7581d75f4 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:57:43 +0200 Subject: win32: ash: struct forkshell --- shell/ash.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index f41bba36d..4710f7153 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -81,6 +81,38 @@ # error "Do not even bother, ash will not run on NOMMU machine" #endif +#if ENABLE_PLATFORM_MINGW32 +struct forkshell; +union node; +struct strlist; +struct job; + +typedef void (*forkpoint_fn)(struct forkshell *fs); +struct forkshell { + /* filled by forkshell_copy() */ + struct globals_var *gvp; + struct globals_misc *gmp; + struct tblentry **cmdtable; + struct localvar *localvars; + /* struct alias **atab; */ + /* struct parsefile *g_parsefile; */ + int fpid; + HANDLE hMapFile; + void *old_base; + int nodeptr_offset; + int size; + + forkpoint_fn fp; + /* optional data, used by forkpoint_fn */ + int flags; + int fd[10]; + union node *n; + char **argv; + char *string; + struct strlist *strlist; + pid_t pid; +}; +#endif /* ============ Hash table sizes. Configurable. */ @@ -13601,6 +13633,49 @@ globals_misc_copy(struct globals_misc *p) SAVE_PTR4(new->minusc, new->curdir, new->physdir, new->arg0); return new; } + +static void +forkshell_size(struct forkshell *fs) +{ + funcblocksize += sizeof(struct forkshell); + globals_var_size(fs->gvp); + globals_misc_size(fs->gmp); + cmdtable_size(fs->cmdtable); + localvar_size(fs->localvars); + /* optlist_transfer(sending, fd); */ + /* misc_transfer(sending, fd); */ + + calcsize(fs->n); + argv_size(fs->argv); + funcstringsize += (fs->string ? strlen(fs->string) : 0) + 1; + strlist_size(fs->strlist); + + nodeptrsize += 8; /* gvp, gmp, cmdtable, localvars, n, argv, string, strlist */ +} + +static struct forkshell * +forkshell_copy(struct forkshell *fs) +{ + struct forkshell *new; + + new = funcblock; + funcblock = (char *) funcblock + sizeof(struct forkshell); + + memcpy(new, fs, sizeof(struct forkshell)); /* non-pointer stuff */ + new->gvp = globals_var_copy(fs->gvp); + new->gmp = globals_misc_copy(fs->gmp); + new->cmdtable = cmdtable_copy(fs->cmdtable); + new->localvars = localvar_copy(fs->localvars); + SAVE_PTR4(new->gvp, new->gmp, new->cmdtable, new->localvars); + + /* new->fs will be reconstructed from new->fpid */ + new->n = copynode(fs->n); + new->argv = argv_copy(fs->argv); + new->string = nodeckstrdup(fs->string); + new->strlist = strlist_copy(fs->strlist); + SAVE_PTR4(new->n, new->argv, new->string, new->strlist); + return new; +} /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From 2e8e8d67ae75454b835990107bdd81ea3e04a268 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:59:32 +0200 Subject: win32: ash: forkshell_prepare() --- shell/ash.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 4710f7153..6a1e78e19 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13172,6 +13172,14 @@ static short profile_buf[16384]; extern int etext(); #endif +#if ENABLE_PLATFORM_MINGW32 +static const forkpoint_fn forkpoints[] = { + NULL +}; + +static struct forkshell* forkshell_prepare(struct forkshell *fs); +#endif + /* * Main routine. We initialize things, parse the arguments, execute * profiles if we're a login shell, and then call cmdloop to execute @@ -13315,6 +13323,16 @@ int ash_main(int argc UNUSED_PARAM, char **argv) /* * forkshell_prepare() and friends + * + * The sequence is as follows: + * - funcblocksize, funcstringsize, nodeptrsize are initialized + * - forkshell_size(fs) is called to calculate the exact memory needed + * - a new struct is allocated + * - funcblock, funcstring, nodeptr are initialized from the new block + * - forkshell_copy(fs) is called to copy recursively everything over + * it will record all pointers along the way, to nodeptr + * + * When this memory is mapped elsewhere, pointer fixup will be needed */ #define SLIST_SIZE_BEGIN(name,type) \ static void \ @@ -13676,6 +13694,58 @@ forkshell_copy(struct forkshell *fs) SAVE_PTR4(new->n, new->argv, new->string, new->strlist); return new; } + +static struct forkshell * +forkshell_prepare(struct forkshell *fs) +{ + struct forkshell *new; + int size, fp, nodeptr_offset; + HANDLE h; + SECURITY_ATTRIBUTES sa; + + for (fp = 0; forkpoints[fp] && forkpoints[fp] != fs->fp; fp++) + ; + + if (!forkpoints[fp]) + bb_error_msg_and_die("invalid forkpoint %08x", (int)fs->fp); + fs->fpid = fp; + + /* Calculate size of "new" */ + fs->gvp = ash_ptr_to_globals_var; + fs->gmp = ash_ptr_to_globals_misc; + fs->cmdtable = cmdtable; + fs->localvars = localvars; + + nodeptrsize = 1; /* NULL terminated */ + funcblocksize = 0; + funcstringsize = 0; + forkshell_size(fs); + size = funcblocksize + funcstringsize + nodeptrsize*sizeof(int); + + /* Allocate, initialize pointers */ + memset(&sa, 0, sizeof(sa)); + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + h = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, size, NULL); + new = (struct forkshell *)MapViewOfFile(h, FILE_MAP_WRITE, 0,0, 0); + /* new = ckmalloc(size); */ + funcblock = new; + funcstring = (char *) funcblock + funcblocksize; + nodeptr = (int*)((char *) funcstring + funcstringsize); + nodeptr_offset = (int) nodeptr - (int) new; + + /* Now pack them all */ + forkshell_copy(fs); + + /* Finish it up */ + *nodeptr = 0; + new->size = size; + new->nodeptr_offset = nodeptr_offset; + new->old_base = new; + new->hMapFile = h; + return new; +} /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From eea918c5e4480d25e377cbb7a6275f55945f0919 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 01:00:32 +0200 Subject: win32: ash: spawn_forkshell() --- shell/ash.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 6a1e78e19..3dfe30006 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -112,6 +112,7 @@ struct forkshell { struct strlist *strlist; pid_t pid; }; +static int spawn_forkshell(struct job *jp, struct forkshell *fs, int mode); #endif /* ============ Hash table sizes. Configurable. */ @@ -13321,6 +13322,29 @@ int ash_main(int argc UNUSED_PARAM, char **argv) /* NOTREACHED */ } +/* FIXME: should consider running forkparent() and forkchild() */ +static int +spawn_forkshell(struct job *jp, struct forkshell *fs, int mode) +{ + const char *argv[] = { "sh", "--forkshell", NULL, NULL }; + char buf[16]; + + struct forkshell *new; + new = forkshell_prepare(fs); + sprintf(buf, "%x", (unsigned int)new->hMapFile); + argv[2] = buf; + fs->pid = mingw_spawn_applet(P_NOWAIT, "sh", argv, + (const char *const *)environ); + CloseHandle(new->hMapFile); + UnmapViewOfFile(new); + if (fs->pid == -1) { + free(jp); + return -1; + } + forkparent(jp, fs->node, mode, fs->pid); + return fs->pid; +} + /* * forkshell_prepare() and friends * -- cgit v1.2.3-55-g6feb From db169a1431dd5cf6c9e7cf9c699c7629946b3944 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 01:01:36 +0200 Subject: win32: ash: forkshell_init() --- shell/ash.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 3dfe30006..2e47fd272 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13179,6 +13179,7 @@ static const forkpoint_fn forkpoints[] = { }; static struct forkshell* forkshell_prepare(struct forkshell *fs); +static void forkshell_init(const char *idstr); #endif /* @@ -13248,6 +13249,15 @@ int ash_main(int argc UNUSED_PARAM, char **argv) init(); setstackmark(&smark); + +#if ENABLE_PLATFORM_MINGW32 + if (argc == 3 && !strcmp(argv[1], "--forkshell")) { + forkshell_init(argv[2]); + + /* NOTREACHED */ + bb_error_msg_and_die("subshell ended unexpectedly"); + } +#endif procargs(argv); #if ENABLE_FEATURE_EDITING_SAVEHISTORY @@ -13770,6 +13780,64 @@ forkshell_prepare(struct forkshell *fs) new->hMapFile = h; return new; } + +#undef exception_handler +#undef trap +#undef trap_ptr +static void +forkshell_init(const char *idstr) +{ + struct forkshell *fs; + int map_handle; + HANDLE h; + struct globals_var **gvpp; + struct globals_misc **gmpp; + int i; + + if (sscanf(idstr, "%x", &map_handle) != 1) + bb_error_msg_and_die("invalid forkshell ID"); + + h = (HANDLE)map_handle; + fs = (struct forkshell *)MapViewOfFile(h, FILE_MAP_WRITE, 0,0, 0); + if (!fs) + bb_error_msg_and_die("Invalid forkshell memory"); + + /* pointer fixup */ + nodeptr = (int*)((char*)fs + fs->nodeptr_offset); + while (*nodeptr) { + int *ptr = (int*)((char*)fs + (*nodeptr - (int)fs->old_base)); + if (*ptr) + *ptr -= ((int)fs->old_base - (int)fs); + nodeptr++; + } + /* Now fix up stuff that can't be transferred */ + fs->fp = forkpoints[fs->fpid]; + for (i = 0; i < ARRAY_SIZE(varinit_data); i++) + fs->gvp->varinit[i].func = varinit_data[i].func; + for (i = 0; i < CMDTABLESIZE; i++) { + struct tblentry *e = fs->cmdtable[i]; + while (e) { + if (e->cmdtype == CMDBUILTIN) + e->param.cmd = builtintab + (int)e->param.cmd; + e = e->next; + } + } + fs->gmp->exception_handler = ash_ptr_to_globals_misc->exception_handler; + for (i = 0; i < NSIG; i++) + fs->gmp->trap[i] = ash_ptr_to_globals_misc->trap[i]; + fs->gmp->trap_ptr = ash_ptr_to_globals_misc->trap_ptr; + + /* Switch global variables */ + gvpp = (struct globals_var **)&ash_ptr_to_globals_var; + *gvpp = fs->gvp; + gmpp = (struct globals_misc **)&ash_ptr_to_globals_misc; + *gmpp = fs->gmp; + localvars = fs->localvars; + cmdtable = fs->cmdtable; + + fs->fp(fs); +} + /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From 7191acfd88b9eb63789aae665d05434cde39e4a1 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 01:02:05 +0200 Subject: win32: ash: sticky_free() --- shell/ash.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 2e47fd272..ba5811213 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -112,6 +112,8 @@ struct forkshell { struct strlist *strlist; pid_t pid; }; +static void sticky_free(void *p); +#define free(p) sticky_free(p) static int spawn_forkshell(struct job *jp, struct forkshell *fs, int mode); #endif @@ -13784,6 +13786,7 @@ forkshell_prepare(struct forkshell *fs) #undef exception_handler #undef trap #undef trap_ptr +static void *sticky_mem_start, *sticky_mem_end; static void forkshell_init(const char *idstr) { @@ -13802,6 +13805,9 @@ forkshell_init(const char *idstr) if (!fs) bb_error_msg_and_die("Invalid forkshell memory"); + /* this memory can't be freed */ + sticky_mem_start = fs; + sticky_mem_end = (char *) fs + fs->size; /* pointer fixup */ nodeptr = (int*)((char*)fs + fs->nodeptr_offset); while (*nodeptr) { @@ -13838,6 +13844,15 @@ forkshell_init(const char *idstr) fs->fp(fs); } +#undef free +static void +sticky_free(void *base) +{ + if (base >= sticky_mem_start && base < sticky_mem_end) + return; + free(base); +} + /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. -- cgit v1.2.3-55-g6feb From aefcdde7da9eff70aa94ae30633f861068b943e3 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:45:28 +0200 Subject: win32: ash: openhere --- shell/ash.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index ba5811213..b2b246dfe 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5092,11 +5092,39 @@ noclobberopen(const char *fname) */ /* openhere needs this forward reference */ static void expandhere(union node *arg, int fd); +#if ENABLE_PLATFORM_MINGW32 +static void +forkshell_openhere(struct forkshell *fs) +{ + union node *redir = fs->n; + int pip[2]; + + pip[0] = fs->fd[0]; + pip[1] = fs->fd[1]; + + TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__)); + + close(pip[0]); + ignoresig(SIGINT); //signal(SIGINT, SIG_IGN); + ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN); + ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN); + ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN); + signal(SIGPIPE, SIG_DFL); + if (redir->type == NHERE) { + size_t len = strlen(redir->nhere.doc->narg.text); + full_write(pip[1], redir->nhere.doc->narg.text, len); + } else /* NXHERE */ + expandhere(redir->nhere.doc, pip[1]); + _exit(EXIT_SUCCESS); +} +#endif + static int openhere(union node *redir) { int pip[2]; size_t len = 0; + IF_PLATFORM_MINGW32(struct forkshell fs); if (pipe(pip) < 0) ash_msg_and_raise_error("pipe call failed"); @@ -5107,6 +5135,16 @@ openhere(union node *redir) goto out; } } +#if ENABLE_PLATFORM_MINGW32 + memset(&fs, 0, sizeof(fs)); + fs.fp = forkshell_openhere; + fs.flags = 0; + fs.n = redir; + fs.fd[0] = pip[0]; + fs.fd[1] = pip[1]; + if (spawn_forkshell(NULL, &fs, FORK_NOJOB) < 0) + ash_msg_and_raise_error("unable to spawn shell"); +#endif if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { /* child */ close(pip[0]); @@ -13177,6 +13215,7 @@ extern int etext(); #if ENABLE_PLATFORM_MINGW32 static const forkpoint_fn forkpoints[] = { + forkshell_openhere, NULL }; -- cgit v1.2.3-55-g6feb From b6146507960ce0f32609c2e3bc5b38ee308492ea Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:45:51 +0200 Subject: win32: ash: evalbackcmd --- shell/ash.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index b2b246dfe..5341ef75f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5923,6 +5923,7 @@ struct backcmd { /* result of evalbackcmd */ int fd; /* file descriptor to read from */ int nleft; /* number of chars in buffer */ char *buf; /* buffer */ + IF_PLATFORM_MINGW32(struct forkshell fs); struct job *jp; /* job structure for command */ }; @@ -5931,6 +5932,25 @@ static uint8_t back_exitstatus; /* exit status of backquoted command */ #define EV_EXIT 01 /* exit after evaluating tree */ static void evaltree(union node *, int); +#if ENABLE_PLATFORM_MINGW32 +static void +forkshell_evalbackcmd(struct forkshell *fs) +{ + union node *n = fs->n; + int pip[2] = {fs->fd[0], fs->fd[1]}; + + FORCE_INT_ON; + close(pip[0]); + if (pip[1] != 1) { + /*close(1);*/ + copyfd(pip[1], 1 | COPYFD_EXACT); + close(pip[1]); + } + eflag = 0; + evaltree(n, EV_EXIT); /* actually evaltreenr... */ + /* NOTREACHED */ +} +#endif static void FAST_FUNC evalbackcmd(union node *n, struct backcmd *result) { @@ -5939,6 +5959,7 @@ evalbackcmd(union node *n, struct backcmd *result) result->fd = -1; result->buf = NULL; result->nleft = 0; + IF_PLATFORM_MINGW32(memset(&result->fs, 0, sizeof(result->fs))); result->jp = NULL; if (n == NULL) goto out; @@ -5953,6 +5974,14 @@ evalbackcmd(union node *n, struct backcmd *result) if (pipe(pip) < 0) ash_msg_and_raise_error("pipe call failed"); jp = makejob(/*n,*/ 1); +#if ENABLE_PLATFORM_MINGW32 + result->fs.fp = forkshell_evalbackcmd; + result->fs.n = n; + result->fs.fd[0] = pip[0]; + result->fs.fd[1] = pip[1]; + if (spawn_forkshell(jp, &result->fs, FORK_NOJOB) < 0) + ash_msg_and_raise_error("unable to spawn shell"); +#endif if (forkshell(jp, n, FORK_NOJOB) == 0) { FORCE_INT_ON; close(pip[0]); @@ -13216,6 +13245,7 @@ extern int etext(); #if ENABLE_PLATFORM_MINGW32 static const forkpoint_fn forkpoints[] = { forkshell_openhere, + forkshell_evalbackcmd, NULL }; -- cgit v1.2.3-55-g6feb From e039e17c92f99a28b1be92b595c50aecd63eb6d7 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:46:12 +0200 Subject: win32: ash: evalsubshell --- shell/ash.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 5341ef75f..863158a6a 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8782,9 +8782,26 @@ evalcase(union node *n, int flags) /* * Kick off a subshell to evaluate a tree. */ +#if ENABLE_PLATFORM_MINGW32 +static void +forkshell_evalsubshell(struct forkshell *fs) +{ + union node *n = fs->n; + int flags = fs->flags; + + TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__)); + INT_ON; + flags |= EV_EXIT; + expredir(n->nredir.redirect); + redirect(n->nredir.redirect, 0); + evaltreenr(n->nredir.n, flags); + /* never returns */ +} +#endif static void evalsubshell(union node *n, int flags) { + IF_PLATFORM_MINGW32(struct forkshell fs); struct job *jp; int backgnd = (n->type == NBACKGND); int status; @@ -8794,6 +8811,14 @@ evalsubshell(union node *n, int flags) goto nofork; INT_OFF; jp = makejob(/*n,*/ 1); +#if ENABLE_PLATFORM_MINGW32 + memset(&fs, 0, sizeof(fs)); + fs.fp = forkshell_evalsubshell; + fs.n = n; + fs.flags = flags; + if (spawn_forkshell(jp, &fs, backgnd) < 0) + ash_msg_and_raise_error("unable to spawn shell"); +#endif if (forkshell(jp, n, backgnd) == 0) { INT_ON; flags |= EV_EXIT; @@ -13246,6 +13271,7 @@ extern int etext(); static const forkpoint_fn forkpoints[] = { forkshell_openhere, forkshell_evalbackcmd, + forkshell_evalsubshell, NULL }; -- cgit v1.2.3-55-g6feb From 22990b207b1ff9c636259dc494cf160fea2f476f Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:46:32 +0200 Subject: win32: ash: evalpipe --- shell/ash.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 863158a6a..d4bb3a55c 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8894,9 +8894,35 @@ expredir(union node *n) * of the shell, which make the last process in a pipeline the parent * of all the rest.) */ +#if ENABLE_PLATFORM_MINGW32 +static void +forkshell_evalpipe(struct forkshell *fs) +{ + union node *n = fs->n; + int flags = fs->flags; + int prevfd = fs->fd[2]; + int pip[2] = {fs->fd[0], fs->fd[1]}; + + TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__)); + INT_ON; + if (pip[1] >= 0) { + close(pip[0]); + } + if (prevfd > 0) { + dup2(prevfd, 0); + close(prevfd); + } + if (pip[1] > 1) { + dup2(pip[1], 1); + close(pip[1]); + } + evaltreenr(n, flags); +} +#endif static void evalpipe(union node *n, int flags) { + IF_PLATFORM_MINGW32(struct forkshell fs); struct job *jp; struct nodelist *lp; int pipelen; @@ -8920,6 +8946,17 @@ evalpipe(union node *n, int flags) ash_msg_and_raise_error("pipe call failed"); } } +#if ENABLE_PLATFORM_MINGW32 + memset(&fs, 0, sizeof(fs)); + fs.fp = forkshell_evalpipe; + fs.flags = flags; + fs.n = lp->n; + fs.fd[0] = pip[0]; + fs.fd[1] = pip[1]; + fs.fd[2] = prevfd; + if (spawn_forkshell(jp, &fs, n->npipe.pipe_backgnd) < 0) + ash_msg_and_raise_error("unable to spawn shell"); +#endif if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) { INT_ON; if (pip[1] >= 0) { @@ -13272,6 +13309,7 @@ static const forkpoint_fn forkpoints[] = { forkshell_openhere, forkshell_evalbackcmd, forkshell_evalsubshell, + forkshell_evalpipe, NULL }; -- cgit v1.2.3-55-g6feb From cf1763dbb3c88a50171effb9be11954ee300de4d Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:46:50 +0200 Subject: win32: ash: shellexec --- shell/ash.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index d4bb3a55c..ed892db98 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9423,6 +9423,20 @@ bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) * as POSIX mandates */ return back_exitstatus; } + +#if ENABLE_PLATFORM_MINGW32 +static void +forkshell_shellexec(struct forkshell *fs) +{ + int idx = fs->fd[0]; + struct strlist *varlist = fs->strlist; + char **argv = fs->argv; + char *path = fs->string; + + listsetvar(varlist, VEXPORT|VSTACK); + shellexec(argv, path, idx); +} +#endif static void evalcommand(union node *cmd, int flags) { @@ -9598,6 +9612,26 @@ evalcommand(union node *cmd, int flags) break; } } +#endif +#if ENABLE_PLATFORM_MINGW32 + if (!(flags & EV_EXIT) || trap[0]) { + struct forkshell fs; + + memset(&fs, 0, sizeof(fs)); + fs.fp = forkshell_shellexec; + fs.argv = argv; + fs.string = (char*)path; + fs.fd[0] = cmdentry.u.index; + fs.strlist = varlist.list; + jp = makejob(/*cmd,*/ 1); + if (spawn_forkshell(jp, &fs, FORK_FG) < 0) + ash_msg_and_raise_error("unable to spawn shell"); + exitstatus = waitforjob(jp); + INT_ON; + TRACE(("forked child exited with %d\n", exitstatus)); + break; + } + /* goes through to shellexec() */ #endif /* Fork off a child process if necessary. */ if (!(flags & EV_EXIT) || trap[0]) { @@ -13310,6 +13344,7 @@ static const forkpoint_fn forkpoints[] = { forkshell_evalbackcmd, forkshell_evalsubshell, forkshell_evalpipe, + forkshell_shellexec, NULL }; -- cgit v1.2.3-55-g6feb From 8c3c113f03d539cf15dd855273ec12f98091feff Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:47:18 +0200 Subject: win32: ash: work around case-insensitive env vars --- shell/ash.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index ed892db98..64e64d95e 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13216,6 +13216,33 @@ init(void) struct stat st1, st2; initvar(); + +#if ENABLE_PLATFORM_MINGW32 + /* + * case insensitive env names from Windows world + * + * Some standard env names such as PATH is named Path and so on + * ash itself is case sensitive, so "Path" will confuse it, as + * MSVC getenv() is case insensitive. + * + * We may end up having both Path and PATH. Then Path will be chosen + * because it appears first. + */ + for (envp = environ; envp && *envp; envp++) + if (!strncasecmp(*envp, "PATH=", 5) && + strncmp(*envp, "PATH=", 5)) + break; + if (envp && *envp) { + char *start, *end; + for (envp = environ; envp && *envp; envp++) { + end = strchr(*envp, '='); + if (!end) + continue; + for (start = *envp;start < end;start++) + *start = toupper(*start); + } + } +#endif for (envp = environ; envp && *envp; envp++) { if (strchr(*envp, '=')) { setvareq(*envp, VEXPORT|VTEXTFIXED); -- cgit v1.2.3-55-g6feb From b1c198c148f0b92b7099e39fd6b44afb16e0f212 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:47:34 +0200 Subject: win32: ash: do not set PPID --- shell/ash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 64e64d95e..758fdfde4 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13249,7 +13249,8 @@ init(void) } } - setvar("PPID", utoa(getppid()), 0); + if (!ENABLE_PLATFORM_MINGW32) + setvar("PPID", utoa(getppid()), 0); p = lookupvar("PWD"); if (p) -- cgit v1.2.3-55-g6feb From fcac95160b275602e87af86d36738fb089cdd350 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 00:32:32 +0200 Subject: win32: ash: general comments about MinGW port --- shell/ash.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 758fdfde4..f43d1653f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -16,6 +16,18 @@ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */ +/* + * MinGW notes + * + * - Environment variables from Windows will all be turned to uppercase. + * - PATH accepts both ; and : as separator, but can't be mixed + * - command without ".exe" is still understood as executable (option to turn off?) + * - both / and \ are supported in PATH. Usually you must use / + * - trap/job does not work + * - /dev/null is supported for redirection + * - no $PPID + */ + /* * The following should be set to reflect the type of system you have: * JOBS -> 1 if you have Berkeley job control, 0 otherwise. -- cgit v1.2.3-55-g6feb From 9375ca983262075d8420fd0d88d00a088916fc10 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Tue, 14 Sep 2010 11:00:47 +1000 Subject: win32: ash: support .com executables --- shell/ash.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index f43d1653f..5d8415a79 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12674,7 +12674,9 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) } #if ENABLE_PLATFORM_MINGW32 len = strlen(fullname); - if (len > 4 && !strcasecmp(fullname+len-4, ".exe")) { + if (len > 4 && + (!strcasecmp(fullname+len-4, ".exe") || + !strcasecmp(fullname+len-4, ".com"))) { if (stat(fullname, &statb) < 0) { if (errno != ENOENT && errno != ENOTDIR) e = errno; @@ -12687,7 +12689,12 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) if (stat(fullname, &statb) < 0) { if (errno != ENOENT && errno != ENOTDIR) e = errno; - goto loop; + memcpy(fullname+len, ".com", 5); + if (stat(fullname, &statb) < 0) { + if (errno != ENOENT && errno != ENOTDIR) + e = errno; + goto loop; + } } fullname[len] = '\0'; } -- cgit v1.2.3-55-g6feb