예제 #1
0
static int
rm(State_t* state, register FTSENT* ent)
{
	register char*	path;
	register int	n;
	int		v;
	struct stat	st;

	if (ent->fts_info == FTS_NS || ent->fts_info == FTS_ERR || ent->fts_info == FTS_SLNONE)
	{
		if (!state->force)
			error(2, "%s: not found", ent->fts_path);
	}
	else if (state->fs3d && iview(ent->fts_statp))
		fts_set(NiL, ent, FTS_SKIP);
	else switch (ent->fts_info)
	{
	case FTS_DNR:
	case FTS_DNX:
		if (state->unconditional)
		{
			if (!beenhere(ent))
				break;
			if (!chmod(ent->fts_name, (ent->fts_statp->st_mode & S_IPERM)|S_IRWXU))
			{
				fts_set(NiL, ent, FTS_AGAIN);
				break;
			}
			error_info.errors++;
		}
		else if (!state->force)
			error(2, "%s: cannot %s directory", ent->fts_path, (ent->fts_info & FTS_NR) ? "read" : "search");
		else
			error_info.errors++;
		fts_set(NiL, ent, FTS_SKIP);
		nonempty(ent);
		break;
	case FTS_D:
	case FTS_DC:
		path = ent->fts_name;
		if (path[0] == '.' && (!path[1] || path[1] == '.' && !path[2]) && (ent->fts_level > 0 || path[1]))
		{
			fts_set(NiL, ent, FTS_SKIP);
			if (!state->force)
				error(2, "%s: cannot remove", ent->fts_path);
			else
				error_info.errors++;
			break;
		}
		if (!state->recursive)
		{
			fts_set(NiL, ent, FTS_SKIP);
			error(2, "%s: directory", ent->fts_path);
			break;
		}
		if (!beenhere(ent))
		{
			if (state->unconditional && (ent->fts_statp->st_mode & S_IRWXU) != S_IRWXU)
				chmod(path, (ent->fts_statp->st_mode & S_IPERM)|S_IRWXU);
			if (ent->fts_level > 0)
			{
				char*	s;

				if (ent->fts_accpath == ent->fts_name || !(s = strrchr(ent->fts_accpath, '/')))
					v = !stat(".", &st);
				else
				{
					path = ent->fts_accpath;
					*s = 0;
					v = !stat(path, &st);
					*s = '/';
				}
				if (v)
					v = st.st_nlink <= 2 || st.st_ino == ent->fts_parent->fts_statp->st_ino && st.st_dev == ent->fts_parent->fts_statp->st_dev || strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'l');
			}
			else
				v = 1;
			if (v)
			{
				if (state->interactive)
				{
					if ((v = astquery(-1, "remove directory %s? ", ent->fts_path)) < 0 || sh_checksig(state->context))
						return -1;
					if (v > 0)
					{
						fts_set(NiL, ent, FTS_SKIP);
						nonempty(ent);
					}
				}
				if (ent->fts_info == FTS_D)
					break;
			}
			else
			{
				ent->fts_info = FTS_DC;
				error(1, "%s: hard link to directory", ent->fts_path);
			}
		}
		else if (ent->fts_info == FTS_D)
			break;
		/*FALLTHROUGH*/
	case FTS_DP:
		if (isempty(ent) || state->directory)
		{
			path = ent->fts_name;
			if (path[0] != '.' || path[1])
			{
				path = ent->fts_accpath;
				if (state->verbose)
					sfputr(sfstdout, ent->fts_path, '\n');
				if ((ent->fts_info == FTS_DC || state->directory) ? remove(path) : rmdir(path))
					switch (errno)
					{
					case ENOENT:
						break;
					case EEXIST:
#if defined(ENOTEMPTY) && (ENOTEMPTY) != (EEXIST)
					case ENOTEMPTY:
#endif
						if (ent->fts_info == FTS_DP && !beenhere(ent))
						{
							retry(ent);
							fts_set(NiL, ent, FTS_AGAIN);
							break;
						}
						/*FALLTHROUGH*/
					default:
						nonempty(ent);
						if (!state->force)
							error(ERROR_SYSTEM|2, "%s: directory not removed", ent->fts_path);
						else
							error_info.errors++;
						break;
					}
			}
			else if (!state->force)
				error(2, "%s: cannot remove", ent->fts_path);
			else
				error_info.errors++;
		}
		else
		{
			nonempty(ent);
			if (!state->force)
				error(2, "%s: directory not removed", ent->fts_path);
			else
				error_info.errors++;
		}
		break;
	default:
		path = ent->fts_accpath;
		if (state->verbose)
			sfputr(sfstdout, ent->fts_path, '\n');
		if (state->interactive)
		{
			if ((v = astquery(-1, "remove %s? ", ent->fts_path)) < 0 || sh_checksig(state->context))
				return -1;
			if (v > 0)
			{
				nonempty(ent);
				break;
			}
		}
		else if (!state->force && state->terminal && eaccess(path, W_OK))
		{
			if ((v = astquery(-1, "override protection %s for %s? ",
#ifdef ETXTBSY
				errno == ETXTBSY ? "``running program''" : 
#endif
				ent->fts_statp->st_uid != state->uid ? "``not owner''" :
				fmtmode(ent->fts_statp->st_mode & S_IPERM, 0) + 1, ent->fts_path)) < 0 ||
			    sh_checksig(state->context))
				return -1;
			if (v > 0)
			{
				nonempty(ent);
				break;
			}
		}
#if _lib_fsync
		if (state->clobber && S_ISREG(ent->fts_statp->st_mode) && ent->fts_statp->st_size > 0)
		{
			if ((n = open(path, O_WRONLY)) < 0)
				error(ERROR_SYSTEM|2, "%s: cannot clear data", ent->fts_path);
			else
			{
				off_t		c = ent->fts_statp->st_size;

				for (;;)
				{
					if (write(n, state->buf, sizeof(state->buf)) != sizeof(state->buf))
					{
						error(ERROR_SYSTEM|2, "%s: data clear error", ent->fts_path);
						break;
					}
					if (c <= sizeof(state->buf))
						break;
					c -= sizeof(state->buf);
				}
				fsync(n);
				close(n);
			}
		}
#endif
		if (remove(path))
		{
			nonempty(ent);
			switch (errno)
			{
			case ENOENT:
				break;
			default:
				if (!state->force || state->interactive)
					error(ERROR_SYSTEM|2, "%s: not removed", ent->fts_path);
				else
					error_info.errors++;
				break;
			}
		}
		break;
	}
	return 0;
}
예제 #2
0
파일: exeval.c 프로젝트: ISLEcode/kornshell
static Extype_t
eval(Expr_t* ex, register Exnode_t* expr, void* env)
{
	register Exnode_t*	x;
	register Exnode_t*	a;
	register Extype_t**	t;
	register int		n;
	Extype_t		v;
	Extype_t		r;
	Extype_t		i;
	char*			e;
	Exnode_t		tmp;
	Exassoc_t*		assoc;
	Extype_t		args[FRAME+1];
	Extype_t		save[FRAME];

	if (!expr || ex->loopcount)
	{
		v.integer = 1;
		return v;
	}
	x = expr->data.operand.left;
	switch (expr->op)
	{
	case BREAK:
	case CONTINUE:
		v = eval(ex, x, env);
		ex->loopcount = v.integer;
		ex->loopop = expr->op;
		return v;
	case CONSTANT:
		return expr->data.constant.value;
	case DEC:
		n = -1;
	add:
		if (x->op == DYNAMIC)
			r = getdyn(ex, x, env, &assoc);
		else
		{
			if (x->data.variable.index)
				i = eval(ex, x->data.variable.index, env);
			else
				i.integer = EX_SCALAR;
			r = (*ex->disc->getf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)i.integer, ex->disc);
		}
		v = r;
		switch (x->type)
		{
		case FLOATING:
			v.floating += n;
			break;
		case INTEGER:
		case UNSIGNED:
			v.integer += n;
			break;
		default:
			goto huh;
		}
	set:
		if (x->op == DYNAMIC)
		{
			if (x->type == STRING)
			{
				v.string = vmstrdup(ex->vm, v.string);
				if (e = assoc ? assoc->value.string : x->data.variable.symbol->value->data.constant.value.string)
					vmfree(ex->vm, e);
			}
			if (assoc)
				assoc->value = v;
			else
				x->data.variable.symbol->value->data.constant.value = v;
		}
		else
		{
			if (x->data.variable.index)
				i = eval(ex, x->data.variable.index, env);
			else
				i.integer = EX_SCALAR;
			if ((*ex->disc->setf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)i.integer, v, ex->disc) < 0)
				exerror("%s: cannot set value", x->data.variable.symbol->name);
		}
		if (expr->subop == PRE)
			r = v;
		return r;
	case DYNAMIC:
		return getdyn(ex, expr, env, &assoc);
	case EXIT:
		v = eval(ex, x, env);
		exit((int)v.integer);
		/*NOTREACHED*/
		v.integer = -1;
		return v;
	case IF:
		v = eval(ex, x, env);
		if (v.integer)
			eval(ex, expr->data.operand.right->data.operand.left, env);
		else
			eval(ex, expr->data.operand.right->data.operand.right, env);
		v.integer = 1;
		return v;
	case FOR:
	case WHILE:
		expr = expr->data.operand.right;
		for (;;)
		{
			r = eval(ex, x, env);
			if (!r.integer)
			{
				v.integer = 1;
				return v;
			}
			if (expr->data.operand.right)
			{
				eval(ex, expr->data.operand.right, env);
				if (ex->loopcount > 0 && (--ex->loopcount > 0 || ex->loopop != CONTINUE))
				{
					v.integer = 0;
					return v;
				}
			}
			if (expr->data.operand.left)
				eval(ex, expr->data.operand.left, env);
		}
		/*NOTREACHED*/
	case SWITCH:
		v = eval(ex, x, env);
		i.integer = x->type;
		r.integer = 0;
		x = expr->data.operand.right;
		a = x->data.select.statement;
		n = 0;
		while (x = x->data.select.next)
		{
			if (!(t = x->data.select.constant))
				n = 1;
			else
				for (; *t; t++)
				{
					switch ((int)i.integer)
					{
					case INTEGER:
					case UNSIGNED:
						if ((*t)->integer == v.integer)
							break;
						continue;
					case STRING:
						if ((ex->disc->version >= 19981111L && ex->disc->matchf) ? (*ex->disc->matchf)(ex, x, (*t)->string, expr->data.operand.left, v.string, env, ex->disc) : strmatch((*t)->string, v.string))
							break;
						continue;
					case FLOATING:
						if ((*t)->floating == v.floating)
							break;
						continue;
					}
					n = 1;
					break;
				}
			if (n)
			{
				if (!x->data.select.statement)
				{
					r.integer = 1;
					break;
				}
				r = eval(ex, x->data.select.statement, env);
				if (ex->loopcount > 0)
				{
					ex->loopcount--;
					break;
				}
			}
		}
		if (!n && a)
		{
			r = eval(ex, a, env);
			if (ex->loopcount > 0)
				ex->loopcount--;
		}
		return r;
	case ITERATE:
		v.integer = 0;
		if (expr->data.generate.array->op == DYNAMIC)
		{
			n = expr->data.generate.index->type == STRING;
			for (assoc = (Exassoc_t*)dtfirst((Dt_t*)expr->data.generate.array->data.variable.symbol->local.pointer); assoc; assoc = (Exassoc_t*)dtnext((Dt_t*)expr->data.generate.array->data.variable.symbol->local.pointer, assoc))
			{
				v.integer++;
				if (n)
					expr->data.generate.index->value->data.constant.value.string = assoc->name;
				else
					expr->data.generate.index->value->data.constant.value.integer = strtol(assoc->name, NiL, 0);
				eval(ex, expr->data.generate.statement, env);
				if (ex->loopcount > 0 && (--ex->loopcount > 0 || ex->loopop != CONTINUE))
				{
					v.integer = 0;
					break;
				}
			}
		}
		else
		{
			r = (*ex->disc->getf)(ex, expr, expr->data.generate.array->data.variable.symbol, expr->data.generate.array->data.variable.reference, env, 0, ex->disc);
			for (v.integer = 0; v.integer < r.integer; v.integer++)
			{
				expr->data.generate.index->value->data.constant.value.integer = v.integer;
				eval(ex, expr->data.generate.statement, env);
				if (ex->loopcount > 0 && (--ex->loopcount > 0 || ex->loopop != CONTINUE))
				{
					v.integer = 0;
					break;
				}
			}
		}
		return v;
	case CALL:
		x = expr->data.call.args;
		for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && x; a = a->data.operand.right)
		{
			if (n < elementsof(args))
			{
				save[n] = a->data.operand.left->data.variable.symbol->value->data.constant.value;
				args[n++] = eval(ex, x->data.operand.left, env);
			}
			else
				a->data.operand.left->data.variable.symbol->value->data.constant.value = eval(ex, x->data.operand.left, env);
			x = x->data.operand.right;
		}
		for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && n < elementsof(save); a = a->data.operand.right)
			a->data.operand.left->data.variable.symbol->value->data.constant.value = args[n++];
		if (x)
			exerror("too many actual args");
		else if (a)
			exerror("not enough actual args");
		v = exeval(ex, expr->data.call.procedure->value->data.procedure.body, env);
		for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && n < elementsof(save); a = a->data.operand.right)
			a->data.operand.left->data.variable.symbol->value->data.constant.value = save[n++];
		return v;
	case FUNCTION:
		n = 0;
		args[n++].string = (char*)env;
		for (x = expr->data.operand.right; x && n < elementsof(args); x = x->data.operand.right)
			args[n++] = eval(ex, x->data.operand.left, env);
		return (*ex->disc->getf)(ex, expr->data.operand.left, expr->data.operand.left->data.variable.symbol, expr->data.operand.left->data.variable.reference, args+1, EX_CALL, ex->disc);
	case ID:
		if (expr->data.variable.index)
			i = eval(ex, expr->data.variable.index, env);
		else
			i.integer = EX_SCALAR;
		return (*ex->disc->getf)(ex, expr, expr->data.variable.symbol, expr->data.variable.reference, env, (int)i.integer, ex->disc);
	case INC:
		n = 1;
		goto add;
	case PRINTF:
		v.integer = print(ex, expr, env, NiL);
		return v;
	case QUERY:
		print(ex, expr, env, sfstderr);
		v.integer = !astquery(2, "");
		return v;
	case RETURN:
		ex->loopret = eval(ex, x, env);
		ex->loopcount = 32767;
		ex->loopop = expr->op;
		return ex->loopret;
	case SCANF:
	case SSCANF:
		v.integer = scan(ex, expr, env, NiL);
		return v;
	case SPRINTF:
		print(ex, expr, env, ex->tmp);
		v.string = exstash(ex->tmp, ex->ve);
		return v;
	case '=':
		v = eval(ex, expr->data.operand.right, env);
		if (expr->subop != '=')
		{
			r = v;
			if (x->op == DYNAMIC)
				v = getdyn(ex, x, env, &assoc);
			else
			{
				if (x->data.variable.index)
					v = eval(ex, x->data.variable.index, env);
				else
					v.integer = EX_SCALAR;
				v = (*ex->disc->getf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)v.integer, ex->disc);
			}
			switch (x->type)
			{
			case FLOATING:
				switch (expr->subop)
				{
				case '+':
					v.floating += r.floating;
					break;
				case '-':
					v.floating -= r.floating;
					break;
				case '*':
					v.floating *= r.floating;
					break;
				case '/':
					if (r.floating == 0.0)
						exerror("floating divide by 0");
					else
						v.floating /= r.floating;
					break;
				case '%':
					if ((r.integer = r.floating) == 0)
						exerror("floating 0 modulus");
					else
						v.floating = ((Sflong_t)v.floating) % r.integer;
					break;
				case '&':
					v.floating = ((Sflong_t)v.floating) & ((Sflong_t)r.floating);
					break;
				case '|':
					v.floating = ((Sflong_t)v.floating) | ((Sflong_t)r.floating);
					break;
				case '^':
					v.floating = ((Sflong_t)v.floating) ^ ((Sflong_t)r.floating);
					break;
				case LS:
					v.floating = ((Sflong_t)v.floating) << ((Sflong_t)r.floating);
					break;
				case RS:
#if _WIN32
					v.floating = (Sflong_t)(((Sfulong_t)v.floating) >> ((Sflong_t)r.floating));
#else
					v.floating = ((Sfulong_t)v.floating) >> ((Sflong_t)r.floating);
#endif
					break;
				default:
					goto huh;
				}
				break;
			case INTEGER:
			case UNSIGNED:
				switch (expr->subop)
				{
				case '+':
					v.integer += r.integer;
					break;
				case '-':
					v.integer -= r.integer;
					break;
				case '*':
					v.integer *= r.integer;
					break;
				case '/':
					if (r.integer == 0)
						exerror("integer divide by 0");
					else
						v.integer /= r.integer;
					break;
				case '%':
					if (r.integer == 0)
						exerror("integer 0 modulus");
					else
						v.integer %= r.integer;
					break;
				case '&':
					v.integer &= r.integer;
					break;
				case '|':
					v.integer |= r.integer;
					break;
				case '^':
					v.integer ^= r.integer;
					break;
				case LS:
					v.integer <<= r.integer;
					break;
				case RS:
					v.integer = (Sfulong_t)v.integer >> r.integer;
					break;
				default:
					goto huh;
				}
				break;
			case STRING:
				switch (expr->subop)
				{
				case '+':
					v.string = str_add(ex, v.string, r.string);
					break;
				case '|':
					v.string = str_ior(ex, v.string, r.string);
					break;
				case '&':
					v.string = str_and(ex, v.string, r.string);
					break;
				case '^':
					v.string = str_xor(ex, v.string, r.string);
					break;
				case '%':
					v.string = str_mod(ex, v.string, r.string);
					break;
				case '*':
					v.string = str_mpy(ex, v.string, r.string);
					break;
				default:
					goto huh;
				}
				break;
			default:
				goto huh;
			}
		}
		else if (x->op == DYNAMIC)