diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
commit | 3950ffe2a485479f6561c27364d3d7df5a21d124 (patch) | |
tree | 468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libcoshell/coinit.c | |
download | ksh-upstream.tar.gz |
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libcoshell/coinit.c')
-rw-r--r-- | src/lib/libcoshell/coinit.c | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/src/lib/libcoshell/coinit.c b/src/lib/libcoshell/coinit.c new file mode 100644 index 0000000..d36fbde --- /dev/null +++ b/src/lib/libcoshell/coinit.c @@ -0,0 +1,431 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1990-2012 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * Glenn Fowler + * AT&T Research + * + * return job initialization commands + */ + +#if _WIN32 +#undef _BLD_DLL +#define _BLD_DLL 1 +#endif + +#include "colib.h" + +#include <ctype.h> +#include <fs3d.h> +#include <ls.h> + +static void +exid(Sfio_t* sp, const char* pre, const char* name, const char* pos) +{ + int c; + + sfputr(sp, pre, -1); + if ((c = *name++) && c != '=') + { + if (isdigit(c)) + sfputc(sp, '_'); + do + { + if (!isalnum(c)) + c = '_'; + sfputc(sp, c); + } while ((c = *name++) && c != '='); + } + else + sfputc(sp, '_'); + sfputr(sp, pos, -1); +} + +/* + * add n to the export list + * old!=0 formats in old style + * coex!=0 for CO_ENV_EXPORT + * if n prefixed by % then coquote conversion enabled + */ + +static void +putexport(Coshell_t* co, Sfio_t* sp, char* n, int old, int coex, int flags) +{ + int cvt; + char* v; + Coexport_t* ex; + + if (cvt = *n == '%') + n++; + + /* + * currently limited to valid identifer env var names + */ + + if (!co->export || !dtmatch(co->export, n)) + { + if (old) + cvt = 0; + if ((v = getenv(n)) && *v || coex && ((flags & CO_EXPORT) || co->export && dtsize(co->export) > 0)) + { + if (!old) + sfprintf(sp, "\\\n"); + exid(sp, " ", n, "='"); + if (coex && (flags & CO_EXPORT)) + v = "(*)"; + if (v) + coquote(sp, v, cvt); + if (coex && !(flags & CO_EXPORT)) + { + v = v ? ":" : ""; + for (ex = (Coexport_t*)dtfirst(co->export); ex; ex = (Coexport_t*)dtnext(co->export, ex)) + { + sfprintf(sp, "%s%s", v, ex->name); + exid(sp, v, ex->name, ""); + v = ":"; + } + } + sfputc(sp, '\''); + if (old) + exid(sp, "\nexport ", n, "\n"); + } + } +} + +/* + * return job initialization commands + */ + +char* +coinitialize(Coshell_t* co, int flags) +{ + register char* s; + int n; + int m; + int old; + int sync; + char* t; + long p; + Coexport_t* ex; + Sfio_t* sp; + Sfio_t* tp; + struct stat st; + + sync = co->init.sync; + co->init.sync = 0; + + /* + * pwd + */ + + if (stat(".", &st)) + return 0; + if (!state.pwd || st.st_ino != co->init.pwd_ino || st.st_dev != co->init.pwd_dev) + { + co->init.pwd_dev = st.st_dev; + co->init.pwd_ino = st.st_ino; + if (state.pwd) + free(state.pwd); + if (!(state.pwd = getcwd(NiL, 0))) + { + if (errno != EINVAL || !(state.pwd = newof(0, char, PATH_MAX, 0))) + return 0; + if (!getcwd(state.pwd, PATH_MAX)) + { + free(state.pwd); + state.pwd = 0; + return 0; + } + } + if (!(flags & CO_INIT)) + sync = 1; + } + + /* + * umask + */ + + umask(n = umask(co->init.mask)); + if (co->init.mask != n) + { + co->init.mask = n; + if (!(flags & CO_INIT)) + sync = 1; + } + if (!co->init.script || sync) + { + /* + * co_export[] vars + */ + + if (!(sp = sfstropen())) + return 0; + tp = 0; + old = !(flags & (CO_KSH|CO_SERVER)); + if (!old) + sfprintf(sp, "export"); + if (sync) + { + if (flags & CO_EXPORT) + s = "(*)"; + else + { + for (n = 0; s = co_export[n]; n++) + putexport(co, sp, s, old, !n, flags); + s = getenv(co_export[0]); + } + if (s) + { + if (*s == '(') + { + register char** ep = environ; + register char* e; + char* v; + char* es; + char* xs; + + if (v = strchr(s, ':')) + *v = 0; + while (e = *ep++) + if ((t = strsubmatch(e, s, 1)) && (*t == '=' || !*t && (t = strchr(e, '=')))) + { + m = (int)(t - e); + if (!strneq(e, "PATH=", 5) && !strneq(e, "_=", 2)) + { + for (n = 0; xs = co_export[n]; n++) + { + es = e; + while (*xs && *es == *xs) + { + es++; + xs++; + } + if (*es == '=' && !*xs) + break; + } + if (!xs) + { + if (!old) + sfprintf(sp, "\\\n"); + exid(sp, " ", e, "='"); + coquote(sp, e + m + 1, 0); + sfputc(sp, '\''); + if (old) + exid(sp, "\nexport ", e, "\n"); + } + } + } + if (v) + { + *v++ = ':'; + s = v; + } + } + if (*s) + for (;;) + { + if (t = strchr(s, ':')) + *t = 0; + putexport(co, sp, s, old, 0, 0); + if (!(s = t)) + break; + *s++ = ':'; + } + } + if (co->export) + for (ex = (Coexport_t*)dtfirst(co->export); ex; ex = (Coexport_t*)dtnext(co->export, ex)) + { + if (!old) + sfprintf(sp, "\\\n"); + exid(sp, " ", ex->name, "='"); + coquote(sp, ex->value, 0); + sfputc(sp, '\''); + if (old) + exid(sp, "\nexport ", ex->name, "\n"); + } + } + + /* + * PATH + */ + + if (!old) + sfprintf(sp, "\\\n"); + sfprintf(sp, " PATH='"); + n = PATH_MAX; + if (!(t = sfstrrsrv(sp, n))) + { + bad: + sfstrclose(sp); + if (tp) + sfstrclose(tp); + return 0; + } + t += n / 2; + if (!(flags & CO_CROSS) && !pathpath("ignore", NiL, PATH_ABSOLUTE|PATH_REGULAR|PATH_EXECUTE, t, n / 2) && pathpath("bin/ignore", "", PATH_ABSOLUTE|PATH_REGULAR|PATH_EXECUTE, t, n / 2)) + { + *strrchr(t, '/') = 0; + sfputc(sp, ':'); + coquote(sp, t, !old); + sfputc(sp, ':'); + s = pathbin(); + } + else + { + s = pathbin(); + if (!(flags & CO_CROSS)) + { + if (!sync && (*s == ':' || *s == '.' && *(s + 1) == ':')) + { + sfstrseek(sp, 0, SEEK_SET); + goto done; + } + sfputc(sp, ':'); + } + } + for (;;) + { + if (*s == ':') + s++; + else if (*s == '.' && *(s + 1) == ':') + s += 2; + else + break; + } + if (!(flags & CO_CROSS)) + tp = 0; + else if (!(tp = sfstropen())) + goto bad; + else + { + while (n = *s++) + { + if (n == ':') + { + while (*s == ':') + s++; + if (!*s) + break; + if (*s == '.') + { + if (!*(s + 1)) + break; + if (*(s + 1) == ':') + { + s++; + continue; + } + } + } + sfputc(tp, n); + } + if (!(s = costash(tp))) + goto bad; + } + coquote(sp, s, !old); + if (tp) + sfstrclose(tp); + sfputc(sp, '\''); + if (old) + sfprintf(sp, "\nexport PATH"); + sfputc(sp, '\n'); + if (sync) + { + /* + * VPATH + */ + + p = (int)sfstrtell(sp); + sfprintf(sp, "vpath "); + n = PATH_MAX; + if (fs3d(FS3D_TEST)) + for (;;) + { + if (!(t = sfstrrsrv(sp, n))) + goto bad; + if ((m = mount(NiL, t, FS3D_GET|FS3D_ALL|FS3D_SIZE(n), NiL)) > 0) + m = n; + else + { + if (!m) + sfstrseek(sp, strlen(t), SEEK_CUR); + break; + } + } + else + { + m = 0; + sfprintf(sp, "- /#option/2d"); + } + if (m) + sfstrseek(sp, p, SEEK_SET); + else + sfprintf(sp, " 2>/dev/null || :\n"); + sfprintf(sp, "umask 0%o\ncd '%s'\n", co->init.mask, state.pwd); + } + done: + if (!(flags & CO_SERVER)) + { + sfprintf(sp, "%s%s=%05d${!%s-$$}\n", old ? "" : "export ", CO_ENV_TEMP, getpid(), (flags & CO_OSH) ? "" : ":"); + if (old) + sfprintf(sp, "export %s\n", CO_ENV_TEMP); + } + sfputc(sp, 0); + n = (int)sfstrtell(sp); + if (co->vm) + { + if (co->init.script) + vmfree(co->vm, co->init.script); + if (!(co->init.script = vmnewof(co->vm, 0, char, n, 1))) + goto bad; + } + else + { + if (co->init.script) + free(co->init.script); + if (!(co->init.script = newof(0, char, n, 1))) + goto bad; + } + memcpy(co->init.script, sfstrbase(sp), n); + sfstrclose(sp); + } + else if (!co->init.script) + { + if (co->init.script = co->vm ? vmnewof(co->vm, 0, char, 1, 0) : newof(0, char, 1, 0)) + *co->init.script = 0; + } + return co->init.script; +} + +/* + * return generic job initialization commands + */ + +char* +coinit(int flags) +{ + if (!state.generic) + { + if (!(state.generic = newof(0, Coshell_t, 1, 0))) + return 0; + state.generic->init.sync = 1; + } + return coinitialize(state.generic, flags); +} |