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