1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1990-2012 AT&T Intellectual Property * 5* and is licensed under the * 6* Eclipse Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.eclipse.org/org/documents/epl-v10.html * 11* (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12* * 13* Information and Software Systems Research * 14* AT&T Research * 15* Florham Park NJ * 16* * 17* Glenn Fowler <gsf@research.att.com> * 18* * 19***********************************************************************/ 20#pragma prototyped 21/* 22 * Glenn Fowler 23 * AT&T Research 24 * 25 * return job initialization commands 26 */ 27 28#if _WIN32 29#undef _BLD_DLL 30#define _BLD_DLL 1 31#endif 32 33#include "colib.h" 34 35#include <ctype.h> 36#include <fs3d.h> 37#include <ls.h> 38 39static void 40exid(Sfio_t* sp, const char* pre, const char* name, const char* pos) 41{ 42 int c; 43 44 sfputr(sp, pre, -1); 45 if ((c = *name++) && c != '=') 46 { 47 if (isdigit(c)) 48 sfputc(sp, '_'); 49 do 50 { 51 if (!isalnum(c)) 52 c = '_'; 53 sfputc(sp, c); 54 } while ((c = *name++) && c != '='); 55 } 56 else 57 sfputc(sp, '_'); 58 sfputr(sp, pos, -1); 59} 60 61/* 62 * add n to the export list 63 * old!=0 formats in old style 64 * coex!=0 for CO_ENV_EXPORT 65 * if n prefixed by % then coquote conversion enabled 66 */ 67 68static void 69putexport(Coshell_t* co, Sfio_t* sp, char* n, int old, int coex, int flags) 70{ 71 int cvt; 72 char* v; 73 Coexport_t* ex; 74 75 if (cvt = *n == '%') 76 n++; 77 78 /* 79 * currently limited to valid identifer env var names 80 */ 81 82 if (!co->export || !dtmatch(co->export, n)) 83 { 84 if (old) 85 cvt = 0; 86 if ((v = getenv(n)) && *v || coex && ((flags & CO_EXPORT) || co->export && dtsize(co->export) > 0)) 87 { 88 if (!old) 89 sfprintf(sp, "\\\n"); 90 exid(sp, " ", n, "='"); 91 if (coex && (flags & CO_EXPORT)) 92 v = "(*)"; 93 if (v) 94 coquote(sp, v, cvt); 95 if (coex && !(flags & CO_EXPORT)) 96 { 97 v = v ? ":" : ""; 98 for (ex = (Coexport_t*)dtfirst(co->export); ex; ex = (Coexport_t*)dtnext(co->export, ex)) 99 { 100 sfprintf(sp, "%s%s", v, ex->name); 101 exid(sp, v, ex->name, ""); 102 v = ":"; 103 } 104 } 105 sfputc(sp, '\''); 106 if (old) 107 exid(sp, "\nexport ", n, "\n"); 108 } 109 } 110} 111 112/* 113 * return job initialization commands 114 */ 115 116char* 117coinitialize(Coshell_t* co, int flags) 118{ 119 register char* s; 120 int n; 121 int m; 122 int old; 123 int sync; 124 char* t; 125 long p; 126 Coexport_t* ex; 127 Sfio_t* sp; 128 Sfio_t* tp; 129 struct stat st; 130 131 sync = co->init.sync; 132 co->init.sync = 0; 133 134 /* 135 * pwd 136 */ 137 138 if (stat(".", &st)) 139 return 0; 140 if (!state.pwd || st.st_ino != co->init.pwd_ino || st.st_dev != co->init.pwd_dev) 141 { 142 co->init.pwd_dev = st.st_dev; 143 co->init.pwd_ino = st.st_ino; 144 if (state.pwd) 145 free(state.pwd); 146 if (!(state.pwd = getcwd(NiL, 0))) 147 { 148 if (errno != EINVAL || !(state.pwd = newof(0, char, PATH_MAX, 0))) 149 return 0; 150 if (!getcwd(state.pwd, PATH_MAX)) 151 { 152 free(state.pwd); 153 state.pwd = 0; 154 return 0; 155 } 156 } 157 if (!(flags & CO_INIT)) 158 sync = 1; 159 } 160 161 /* 162 * umask 163 */ 164 165 umask(n = umask(co->init.mask)); 166 if (co->init.mask != n) 167 { 168 co->init.mask = n; 169 if (!(flags & CO_INIT)) 170 sync = 1; 171 } 172 if (!co->init.script || sync) 173 { 174 /* 175 * co_export[] vars 176 */ 177 178 if (!(sp = sfstropen())) 179 return 0; 180 tp = 0; 181 old = !(flags & (CO_KSH|CO_SERVER)); 182 if (!old) 183 sfprintf(sp, "export"); 184 if (sync) 185 { 186 if (flags & CO_EXPORT) 187 s = "(*)"; 188 else 189 { 190 for (n = 0; s = co_export[n]; n++) 191 putexport(co, sp, s, old, !n, flags); 192 s = getenv(co_export[0]); 193 } 194 if (s) 195 { 196 if (*s == '(') 197 { 198 register char** ep = environ; 199 register char* e; 200 char* v; 201 char* es; 202 char* xs; 203 204 if (v = strchr(s, ':')) 205 *v = 0; 206 while (e = *ep++) 207 if ((t = strsubmatch(e, s, 1)) && (*t == '=' || !*t && (t = strchr(e, '=')))) 208 { 209 m = (int)(t - e); 210 if (!strneq(e, "PATH=", 5) && !strneq(e, "_=", 2)) 211 { 212 for (n = 0; xs = co_export[n]; n++) 213 { 214 es = e; 215 while (*xs && *es == *xs) 216 { 217 es++; 218 xs++; 219 } 220 if (*es == '=' && !*xs) 221 break; 222 } 223 if (!xs) 224 { 225 if (!old) 226 sfprintf(sp, "\\\n"); 227 exid(sp, " ", e, "='"); 228 coquote(sp, e + m + 1, 0); 229 sfputc(sp, '\''); 230 if (old) 231 exid(sp, "\nexport ", e, "\n"); 232 } 233 } 234 } 235 if (v) 236 { 237 *v++ = ':'; 238 s = v; 239 } 240 } 241 if (*s) 242 for (;;) 243 { 244 if (t = strchr(s, ':')) 245 *t = 0; 246 putexport(co, sp, s, old, 0, 0); 247 if (!(s = t)) 248 break; 249 *s++ = ':'; 250 } 251 } 252 if (co->export) 253 for (ex = (Coexport_t*)dtfirst(co->export); ex; ex = (Coexport_t*)dtnext(co->export, ex)) 254 { 255 if (!old) 256 sfprintf(sp, "\\\n"); 257 exid(sp, " ", ex->name, "='"); 258 coquote(sp, ex->value, 0); 259 sfputc(sp, '\''); 260 if (old) 261 exid(sp, "\nexport ", ex->name, "\n"); 262 } 263 } 264 265 /* 266 * PATH 267 */ 268 269 if (!old) 270 sfprintf(sp, "\\\n"); 271 sfprintf(sp, " PATH='"); 272 n = PATH_MAX; 273 if (!(t = sfstrrsrv(sp, n))) 274 { 275 bad: 276 sfstrclose(sp); 277 if (tp) 278 sfstrclose(tp); 279 return 0; 280 } 281 t += n / 2; 282 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)) 283 { 284 *strrchr(t, '/') = 0; 285 sfputc(sp, ':'); 286 coquote(sp, t, !old); 287 sfputc(sp, ':'); 288 s = pathbin(); 289 } 290 else 291 { 292 s = pathbin(); 293 if (!(flags & CO_CROSS)) 294 { 295 if (!sync && (*s == ':' || *s == '.' && *(s + 1) == ':')) 296 { 297 sfstrseek(sp, 0, SEEK_SET); 298 goto done; 299 } 300 sfputc(sp, ':'); 301 } 302 } 303 for (;;) 304 { 305 if (*s == ':') 306 s++; 307 else if (*s == '.' && *(s + 1) == ':') 308 s += 2; 309 else 310 break; 311 } 312 if (!(flags & CO_CROSS)) 313 tp = 0; 314 else if (!(tp = sfstropen())) 315 goto bad; 316 else 317 { 318 while (n = *s++) 319 { 320 if (n == ':') 321 { 322 while (*s == ':') 323 s++; 324 if (!*s) 325 break; 326 if (*s == '.') 327 { 328 if (!*(s + 1)) 329 break; 330 if (*(s + 1) == ':') 331 { 332 s++; 333 continue; 334 } 335 } 336 } 337 sfputc(tp, n); 338 } 339 if (!(s = costash(tp))) 340 goto bad; 341 } 342 coquote(sp, s, !old); 343 if (tp) 344 sfstrclose(tp); 345 sfputc(sp, '\''); 346 if (old) 347 sfprintf(sp, "\nexport PATH"); 348 sfputc(sp, '\n'); 349 if (sync) 350 { 351 /* 352 * VPATH 353 */ 354 355 p = (int)sfstrtell(sp); 356 sfprintf(sp, "vpath "); 357 n = PATH_MAX; 358 if (fs3d(FS3D_TEST)) 359 for (;;) 360 { 361 if (!(t = sfstrrsrv(sp, n))) 362 goto bad; 363 if ((m = mount(NiL, t, FS3D_GET|FS3D_ALL|FS3D_SIZE(n), NiL)) > 0) 364 m = n; 365 else 366 { 367 if (!m) 368 sfstrseek(sp, strlen(t), SEEK_CUR); 369 break; 370 } 371 } 372 else 373 { 374 m = 0; 375 sfprintf(sp, "- /#option/2d"); 376 } 377 if (m) 378 sfstrseek(sp, p, SEEK_SET); 379 else 380 sfprintf(sp, " 2>/dev/null || :\n"); 381 sfprintf(sp, "umask 0%o\ncd '%s'\n", co->init.mask, state.pwd); 382 } 383 done: 384 if (!(flags & CO_SERVER)) 385 { 386 sfprintf(sp, "%s%s=%05d${!%s-$$}\n", old ? "" : "export ", CO_ENV_TEMP, getpid(), (flags & CO_OSH) ? "" : ":"); 387 if (old) 388 sfprintf(sp, "export %s\n", CO_ENV_TEMP); 389 } 390 sfputc(sp, 0); 391 n = (int)sfstrtell(sp); 392 if (co->vm) 393 { 394 if (co->init.script) 395 vmfree(co->vm, co->init.script); 396 if (!(co->init.script = vmnewof(co->vm, 0, char, n, 1))) 397 goto bad; 398 } 399 else 400 { 401 if (co->init.script) 402 free(co->init.script); 403 if (!(co->init.script = newof(0, char, n, 1))) 404 goto bad; 405 } 406 memcpy(co->init.script, sfstrbase(sp), n); 407 sfstrclose(sp); 408 } 409 else if (!co->init.script) 410 { 411 if (co->init.script = co->vm ? vmnewof(co->vm, 0, char, 1, 0) : newof(0, char, 1, 0)) 412 *co->init.script = 0; 413 } 414 return co->init.script; 415} 416 417/* 418 * return generic job initialization commands 419 */ 420 421char* 422coinit(int flags) 423{ 424 if (!state.generic) 425 { 426 if (!(state.generic = newof(0, Coshell_t, 1, 0))) 427 return 0; 428 state.generic->init.sync = 1; 429 } 430 return coinitialize(state.generic, flags); 431} 432