コード例 #1
0
ファイル: trap.c プロジェクト: ISLEcode/kornshell
void
wakeup(Seconds_t t, register List_t* p)
{
	register Alarms_t*	a;
	register Alarms_t*	z;
	register Alarms_t*	x;
	Alarms_t*		alarms;
	Seconds_t		now;

	alarms = trap.alarms;
	now = CURSECS;
	if (t)
	{
		t += now;
		if (!p)
			p = cons(catrule(external.interrupt, ".", fmtsignal(-SIGALRM), 1), NiL);
	}
	if (p)
	{
		do
		{
			x = 0;
			for (z = 0, a = trap.alarms; a; z = a, a = a->next)
				if (a->rule == p->rule)
				{
					x = a;
					if (z)
						z->next = a->next;
					else
						trap.alarms = a->next;
					break;
				}
			if (t)
			{
				if (!x)
				{
					if (x = trap.freealarms)
						trap.freealarms = trap.freealarms->next;
					else
						x = newof(0, Alarms_t, 1, 0);
					x->rule = p->rule;
				}
				x->time = t;
				x->next = 0;
				for (z = 0, a = trap.alarms; a; z = a, a = a->next)
					if (t <= a->time)
					{
						x->next = a;
						break;
					}
				if (z)
					z->next = x;
				else
					trap.alarms = x;
			}
		} while (p = p->next);
	}
	else if (a = trap.alarms)
	{
		trap.alarms = 0;
		while (x = a->next)
			a = x;
		a->next = trap.freealarms;
		trap.freealarms = a;
	}
	if (trap.alarms != alarms)
		setwakeup();
}
コード例 #2
0
ファイル: trap.c プロジェクト: ISLEcode/kornshell
int
handle(void)
{
	register int		sig;
	register Rule_t*	r;
	register Alarms_t*	a;
	char*			s;
	char*			w;
	Var_t*			v;
	Seconds_t		t;

	if (!state.caught)
		return 0;
	while (state.caught)
	{
		state.caught = 0;
		for (sig = 1; sig <= sig_info.sigmax; sig++)
			if (trap.caught[sig])
			{
				trap.caught[sig] = 0;

				/*
				 * flush the output streams
				 */

				sfsync(sfstderr);
				sfsync(sfstdout);

				/*
				 * continue if already in finish
				 */

				if (state.finish)
				{
					if (!state.interrupt)
						state.interrupt = sig;
					for (sig = 1; sig <= sig_info.sigmax; sig++)
						trap.caught[sig] = 0;
					return 0;
				}

				/*
				 * check user trap (some cannot be trapped)
				 */

				w = 0;
				if (!state.compileonly)
					switch (sig)
					{
					case SIGALRM:
						s = fmtsignal(-sig);
						t = CURSECS;
						while ((a = trap.alarms) && a->time <= t)
						{
							trap.alarms = a->next;
							r = a->rule;
							a->next = trap.freealarms;
							trap.freealarms = a;
							maketop(r, (P_dontcare|P_force|P_ignore|P_repeat)|((r->property & P_make)?0:P_foreground), s);
						}
						setwakeup();
						continue;
					default:
						s = fmtsignal(-sig);
						if ((r = catrule(external.interrupt, ".", s, 0)) || (r = getrule(external.interrupt)))
						{
							if (!(r->property & P_functional))
								v = setvar(external.interrupt, s, 0);
							maketop(r, (P_dontcare|P_force|P_ignore|P_repeat)|((r->property & P_make)?0:P_foreground), s);
							if (r->property & P_functional)
								v = getvar(r->name);
							w = v->value;
							if (r->status == EXISTS && (streq(w, s) || streq(w, "continue")))
							{
								message((-1, "trap %s handler %s status CONTINUE return %s", s, r->name, w));
								continue;
							}
							message((-1, "trap %s handler %s status TERMINATE return %s", s, r->name, w));
						}
						/*FALLTHROUGH*/
#ifdef SIGILL
					case SIGILL:
#endif
#ifdef SIGIOT
					case SIGIOT:
#endif
#ifdef SIGEMT
					case SIGEMT:
#endif
#ifdef SIGBUS
					case SIGBUS:
#endif
#ifdef SIGSEGV
					case SIGSEGV:
#endif
						break;
					}

				/*
				 * terminate outstanding jobs
				 */

				terminate();

				/*
				 * the interpreter resumes without exit
				 */

				if (state.interpreter)
				{
					if (state.waiting)
						return 1;
					longjmp(state.resume.label, 1);
				}

				/*
				 * if external.interrupt=""|"exit" then exit
				 * otherwise terminate via original signal
				 */

				if (w && (!*w || streq(w, "exit")))
					state.interrupt = 0;
				else if (!state.interrupt)
					state.interrupt = sig;
				finish(3);

				/*
				 * shouldn't get here
				 */

				exit(3);
			}
	}
	return 1;
}
コード例 #3
0
ファイル: command.c プロジェクト: nathanmkaya/ksh-arch
void
trigger(register Rule_t* r, Rule_t* a, char* action, Flags_t flags)
{
	register Joblist_t*	job;
	register List_t*	p;
	List_t*			prereqs;
	int			n;

	/*
	 * update flags
	 */

	if (!a)
		a = r;
	if (state.exec && !state.touch || (a->property & P_always) && (!state.never || (flags & CO_URGENT)))
		flags |= CO_ALWAYS;
	if ((a->property | r->property) & P_local)
		flags |= CO_LOCAL;
	if (!state.jobs || (r->property & P_foreground) || (r->property & (P_make|P_functional)) == P_functional || (r->dynamic & D_hasmake))
		flags |= CO_FOREGROUND|CO_LOCAL;
	if (state.keepgoing || state.unwind)
		flags |= CO_KEEPGOING;
	if (state.silent)
		flags |= CO_SILENT;
	if (state.ignore)
		flags |= CO_IGNORE;
	if (r->property & (P_functional|P_read))
		flags |= CO_DATAFILE;
	if (action)
	{
		message((-1, "triggering %s action%s%s", r->name, r == a ? null : " using ", r == a ? null : a->name));
		if (state.exec)
			jobs.triggered = r;
		r->dynamic |= D_triggered;
		if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
			for (p = r->prereqs->rule->prereqs; p; p = p->next)
				p->rule->dynamic |= D_triggered;
		if (!*action)
			action = 0;
	}
	if (state.coshell && (action && !(r->property & P_make) || (flags & CO_FOREGROUND)))
	{
		/*
		 * the make thread blocks when too many jobs are outstanding
		 */

		n = (flags & CO_FOREGROUND) ? 0 : (state.jobs - 1);
		while ((cozombie(state.coshell) || cojobs(state.coshell) > n) && block(0));
		if ((flags & CO_FOREGROUND) && r->active && r->active->parent && r->active->parent->prereqs && copending(state.coshell) > cojobs(state.coshell))
			serial(r, r->active->parent->prereqs);
	}
	prereqs = r->prereqs;
	if (r->active && r->active->primary)
	{
		prereqs = cons(getrule(r->active->primary), prereqs);
		flags |= CO_PRIMARY;
	}
	if (r->property & P_make)
	{
		if (r->property & P_local)
		{
			r->status = EXISTS;
			return;
		}

		/*
		 * make actions are done immediately, bypassing the job queue
		 */

		if (prereqs && complete(NiL, prereqs, NiL, 0))
			r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
		else
		{
			if (action && cancel(r, prereqs))
				r->status = EXISTS;
			else if ((r->dynamic & (D_hasbefore|D_triggered)) == (D_hasbefore|D_triggered) && (makebefore(r) || complete(NiL, prereqs, NiL, 0)))
				r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
			else
			{
				if (r->property & P_functional)
					setvar(r->name, null, 0);
				if (action)
					switch (parse(NiL, action, r->name, NiL))
					{
					case EXISTS:
						if (!(r->property & (P_state|P_virtual)))
							statetime(r, 0);
						break;
					case FAILED:
						r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
						break;
					case TOUCH:
						r->time = internal.internal->time;
						break;
					case UPDATE:
						if ((r->property & (P_state|P_virtual)) != (P_state|P_virtual))
							r->time = CURTIME;
						break;
					}
				if (r->status == UPDATE)
					r->status = EXISTS;
			}
		}
		if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
			for (p = r->prereqs->rule->prereqs; p; p = p->next)
				if (p->rule != r)
				{
					p->rule->status = r->status;
					p->rule->time = r->time;
				}
		if ((r->dynamic & (D_hasafter|D_triggered)) == (D_hasafter|D_triggered))
		{
			if (r->status == FAILED)
			{
				if (hasafter(r, P_failure) && !makeafter(r, P_failure) && !complete(NiL, prereqs, NiL, 0))
					r->status = EXISTS;
			}
			else if (hasafter(r, P_after) && (makeafter(r, P_after) || complete(NiL, prereqs, NiL, 0)))
				r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
		}
	}
	else
	{
		/*
		 * only one repeat action at a time
		 */

		if ((r->property & P_repeat) && (r->property & (P_before|P_after)) && !(r->dynamic & D_hassemaphore))
		{
			a = catrule(internal.semaphore->name, ".", r->name, 1);
			a->semaphore = 2;
			r->prereqs = append(r->prereqs, cons(a, NiL));
			r->dynamic |= D_hassemaphore;
		}

		/*
		 * check if any prerequisites are blocking execution
		 * FAILED prerequisites cause the target to fail too
		 */

		n = READY;
		for (;;)
		{
			for (p = prereqs; p; p = p->next)
			{
				if ((a = p->rule)->dynamic & D_alias)
					a = makerule(a->name);
				if (a->property & P_after)
					continue;
				switch (a->status)
				{
				case FAILED:
					if (a->property & P_repeat)
						continue;
					r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
					if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
						for (p = r->prereqs->rule->prereqs; p; p = p->next)
							if (p->rule != r)
								p->rule->status = (p->rule->property & P_dontcare) ? IGNORE : FAILED;
					return;
				case MAKING:
					if (a->active)
						error(1, "%s: prerequisite %s is active", r->name, a->name);
					else
						n = BLOCKED;
					break;
				}
			}
			if (n != READY)
				break;
			if (action)
			{
				if (cancel(r, prereqs))
					return;
				if ((r->dynamic & D_intermediate) && r->must == 1)
				{
					n = INTERMEDIATE;
					jobs.intermediate++;
					break;
				}
			}
			if ((r->dynamic & (D_hasbefore|D_triggered)) != (D_hasbefore|D_triggered))
				break;
			if (makebefore(r))
			{
				r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
				if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
					for (p = r->prereqs->rule->prereqs; p; p = p->next)
						if (p->rule != r)
							p->rule->status = (p->rule->property & P_dontcare) ? IGNORE : FAILED;
				return;
			}
		}
		if (action || n != READY)
		{
			/*
			 * allocate a job cell and add to job list
			 * the first READY job from the top is executed next
			 */

			if (job = jobs.freejob)
				jobs.freejob = jobs.freejob->next;
			else
				job = newof(0, Joblist_t, 1, 0);
			if (flags & CO_URGENT)
			{
				job->prev = 0;
				if (job->next = jobs.firstjob)
					jobs.firstjob->prev = job;
				else
					jobs.lastjob = job;
				jobs.firstjob = job;
			}
			else
			{
				job->next = 0;
				if (job->prev = jobs.lastjob)
					jobs.lastjob->next = job;
				else
					jobs.firstjob = job;
				jobs.lastjob = job;
			}

			/*
			 * fill in the info
			 */

			job->target = r;
			job->prereqs = prereqs;
			job->status = n;
			job->flags = flags;
			job->action = action;
			r->status = MAKING;
			if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
				for (p = r->prereqs->rule->prereqs; p; p = p->next)
					if (p->rule != r)
						p->rule->status = r->status;
			if (n == READY)
			{
				execute(job);
				if (r->dynamic & D_hasafter)
					save(job);
			}
			else
				save(job);
			jobstatus();
		}
		else
		{
			if (r->status == UPDATE)
				r->status = EXISTS;
			if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
				for (p = r->prereqs->rule->prereqs; p; p = p->next)
					if (p->rule->status == UPDATE)
						p->rule->status = EXISTS;
			if ((r->dynamic & (D_hasafter|D_triggered)) == (D_hasafter|D_triggered))
			{
				if (r->status == FAILED)
				{
					if (hasafter(r, P_failure) && !makeafter(r, P_failure) && !complete(NiL, prereqs, NiL, 0))
						r->status = EXISTS;
				}
				else if (hasafter(r, P_after) && (makeafter(r, P_after) || complete(NiL, prereqs, NiL, 0)))
					r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
				if (r->status == EXISTS)
				{
					char*	t;
					Sfio_t*	tmp;

					tmp = sfstropen();
					edit(tmp, r->name, KEEP, DELETE, DELETE);
					if (*(t = sfstruse(tmp)))
						newfile(r, t, r->time);
					sfstrclose(tmp);
				}
			}
		}
		if (r->dynamic & D_triggered)
		{
			r->time = CURTIME;
			if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
				for (p = r->prereqs->rule->prereqs; p; p = p->next)
					p->rule->time = r->time;
		}
	}
}