invent builtin flags instead of special-casing cat and printf for prefer-external-over-builtin stuff
This commit is contained in:
		
							
								
								
									
										73
									
								
								exec.c
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								exec.c
									
									
									
									
									
								
							| @@ -23,7 +23,7 @@ | |||||||
|  |  | ||||||
| #include "sh.h" | #include "sh.h" | ||||||
|  |  | ||||||
| __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.176 2016/07/24 23:07:19 tg Exp $"); | __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.177 2016/07/24 23:10:02 tg Exp $"); | ||||||
|  |  | ||||||
| #ifndef MKSH_DEFAULT_EXECSHELL | #ifndef MKSH_DEFAULT_EXECSHELL | ||||||
| #define MKSH_DEFAULT_EXECSHELL	MKSH_UNIXROOT "/bin/sh" | #define MKSH_DEFAULT_EXECSHELL	MKSH_UNIXROOT "/bin/sh" | ||||||
| @@ -533,11 +533,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, | |||||||
| 			} | 			} | ||||||
| 			if ((tp = findcom(cp, FC_BI)) == NULL) | 			if ((tp = findcom(cp, FC_BI)) == NULL) | ||||||
| 				errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin"); | 				errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin"); | ||||||
| 			if (tp->type == CSHELL && (tp->val.f == c_cat | 			if (tp->type == CSHELL && (tp->flag & LOW_BI)) | ||||||
| #ifdef MKSH_PRINTF_BUILTIN |  | ||||||
| 			    || tp->val.f == c_printf |  | ||||||
| #endif |  | ||||||
| 			    )) |  | ||||||
| 				break; | 				break; | ||||||
| 			continue; | 			continue; | ||||||
| 		} else if (tp->val.f == c_exec) { | 		} else if (tp->val.f == c_exec) { | ||||||
| @@ -595,29 +591,21 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, | |||||||
| 				subst_exstat = 0; | 				subst_exstat = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 		} else if (tp->val.f == c_cat) { | 		} else if (tp->flag & LOW_BI) { | ||||||
| 			/* if we have any flags, do not use the builtin */ | 			/* if we have any flags, do not use the builtin */ | ||||||
| 			if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' && | 			if ((ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' && | ||||||
| 			    /* argument, begins with -, is not - or -- */ | 			    /* argument, begins with -, is not - or -- */ | ||||||
| 			    (ap[1][1] != '-' || ap[1][2] != '\0')) { | 			    (ap[1][1] != '-' || ap[1][2] != '\0')) || | ||||||
| 				struct tbl *ext_cat; | 			    /* always prefer the external utility */ | ||||||
|  | 			    (tp->flag & LOWER_BI)) { | ||||||
|  | 				struct tbl *ext_cmd; | ||||||
|  |  | ||||||
| 				ext_cat = findcom(Tcat, FC_PATH | FC_FUNC); | 				ext_cmd = findcom(tp->name, FC_PATH | FC_FUNC); | ||||||
| 				if (ext_cat && (ext_cat->type != CTALIAS || | 				if (ext_cmd && (ext_cmd->type != CTALIAS || | ||||||
| 				    (ext_cat->flag & ISSET))) | 				    (ext_cmd->flag & ISSET))) | ||||||
| 					tp = ext_cat; | 					tp = ext_cmd; | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| #ifdef MKSH_PRINTF_BUILTIN |  | ||||||
| 		} else if (tp->val.f == c_printf) { |  | ||||||
| 			struct tbl *ext_printf; |  | ||||||
|  |  | ||||||
| 			ext_printf = findcom(Tprintf, FC_PATH | FC_FUNC); |  | ||||||
| 			if (ext_printf && (ext_printf->type != CTALIAS || |  | ||||||
| 			    (ext_printf->flag & ISSET))) |  | ||||||
| 				tp = ext_printf; |  | ||||||
| 			break; |  | ||||||
| #endif |  | ||||||
| 		} else if (tp->val.f == c_trap) { | 		} else if (tp->val.f == c_trap) { | ||||||
| 			t->u.evalflags &= ~DOTCOMEXEC; | 			t->u.evalflags &= ~DOTCOMEXEC; | ||||||
| 			break; | 			break; | ||||||
| @@ -727,16 +715,12 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, | |||||||
| 			    !(ftp = findfunc(cp, hash(cp), false)) || | 			    !(ftp = findfunc(cp, hash(cp), false)) || | ||||||
| 			    !(ftp->flag & ISSET)) { | 			    !(ftp->flag & ISSET)) { | ||||||
| 				rv = errno; | 				rv = errno; | ||||||
| 				if (!strcmp(cp, Tcat)) { | 				if ((ftp = findcom(cp, FC_BI)) && | ||||||
| 					tp = findcom(Tcat, FC_BI); | 				    (ftp->type == CSHELL) && | ||||||
|  | 				    (ftp->flag & LOW_BI)) { | ||||||
|  | 					tp = ftp; | ||||||
| 					goto do_call_builtin; | 					goto do_call_builtin; | ||||||
| 				} | 				} | ||||||
| #ifdef MKSH_PRINTF_BUILTIN |  | ||||||
| 				if (!strcmp(cp, Tprintf)) { |  | ||||||
| 					tp = findcom(Tprintf, FC_BI); |  | ||||||
| 					goto do_call_builtin; |  | ||||||
| 				} |  | ||||||
| #endif |  | ||||||
| 				if (rv) { | 				if (rv) { | ||||||
| 					tp->u2.errnov = rv; | 					tp->u2.errnov = rv; | ||||||
| 					cp = tp->u.fpath; | 					cp = tp->u.fpath; | ||||||
| @@ -1089,23 +1073,38 @@ builtin(const char *name, int (*func) (const char **)) | |||||||
| 	uint32_t flag = DEFINED; | 	uint32_t flag = DEFINED; | ||||||
|  |  | ||||||
| 	/* see if any flags should be set for this builtin */ | 	/* see if any flags should be set for this builtin */ | ||||||
| 	while (1) { |  flags_loop: | ||||||
| 		if (*name == '=') | 	switch (*name) { | ||||||
|  | 	case '=': | ||||||
| 		/* command does variable assignment */ | 		/* command does variable assignment */ | ||||||
| 		flag |= KEEPASN; | 		flag |= KEEPASN; | ||||||
| 		else if (*name == '*') | 		break; | ||||||
|  | 	case '*': | ||||||
| 		/* POSIX special builtin */ | 		/* POSIX special builtin */ | ||||||
| 		flag |= SPEC_BI; | 		flag |= SPEC_BI; | ||||||
| 		else |  | ||||||
| 		break; | 		break; | ||||||
| 		name++; | 	case '~': | ||||||
|  | 		/* external utility overrides built-in utility, always */ | ||||||
|  | 		flag |= LOWER_BI; | ||||||
|  | 		/* FALLTHROUGH */ | ||||||
|  | 	case '!': | ||||||
|  | 		/* external utility overrides built-in utility, with flags */ | ||||||
|  | 		flag |= LOW_BI; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		goto flags_seen; | ||||||
| 	} | 	} | ||||||
|  | 	++name; | ||||||
|  | 	goto flags_loop; | ||||||
|  |  flags_seen: | ||||||
|  |  | ||||||
|  | 	/* enter into the builtins hash table */ | ||||||
| 	tp = ktenter(&builtins, name, hash(name)); | 	tp = ktenter(&builtins, name, hash(name)); | ||||||
| 	tp->flag = flag; | 	tp->flag = flag; | ||||||
| 	tp->type = CSHELL; | 	tp->type = CSHELL; | ||||||
| 	tp->val.f = func; | 	tp->val.f = func; | ||||||
|  |  | ||||||
|  | 	/* return name, for direct builtin call check in main.c */ | ||||||
| 	return (name); | 	return (name); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								funcs.c
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								funcs.c
									
									
									
									
									
								
							| @@ -38,7 +38,7 @@ | |||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.297 2016/06/26 00:44:25 tg Exp $"); | __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.298 2016/07/24 23:10:02 tg Exp $"); | ||||||
|  |  | ||||||
| #if HAVE_KILLPG | #if HAVE_KILLPG | ||||||
| /* | /* | ||||||
| @@ -101,7 +101,7 @@ const struct builtin mkshbuiltins[] = { | |||||||
| 	{Talias, c_alias}, | 	{Talias, c_alias}, | ||||||
| 	{"*=break", c_brkcont}, | 	{"*=break", c_brkcont}, | ||||||
| 	{Tgbuiltin, c_builtin}, | 	{Tgbuiltin, c_builtin}, | ||||||
| 	{Tcat, c_cat}, | 	{"!cat", c_cat}, | ||||||
| 	{"cd", c_cd}, | 	{"cd", c_cd}, | ||||||
| 	/* dash compatibility hack */ | 	/* dash compatibility hack */ | ||||||
| 	{"chdir", c_cd}, | 	{"chdir", c_cd}, | ||||||
| @@ -155,7 +155,7 @@ const struct builtin mkshbuiltins[] = { | |||||||
| 	{"mknod", c_mknod}, | 	{"mknod", c_mknod}, | ||||||
| #endif | #endif | ||||||
| #ifdef MKSH_PRINTF_BUILTIN | #ifdef MKSH_PRINTF_BUILTIN | ||||||
| 	{Tprintf, c_printf}, | 	{"~printf", c_printf}, | ||||||
| #endif | #endif | ||||||
| #if HAVE_SELECT | #if HAVE_SELECT | ||||||
| 	{"sleep", c_sleep}, | 	{"sleep", c_sleep}, | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.c
									
									
									
									
									
								
							| @@ -34,7 +34,7 @@ | |||||||
| #include <locale.h> | #include <locale.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| __RCSID("$MirOS: src/bin/mksh/main.c,v 1.310 2016/02/26 21:53:36 tg Exp $"); | __RCSID("$MirOS: src/bin/mksh/main.c,v 1.311 2016/07/24 23:10:03 tg Exp $"); | ||||||
|  |  | ||||||
| extern char **environ; | extern char **environ; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								sh.h
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								sh.h
									
									
									
									
									
								
							| @@ -175,7 +175,7 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef EXTERN | #ifdef EXTERN | ||||||
| __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.775 2016/07/12 23:07:10 tg Exp $"); | __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.776 2016/07/24 23:10:04 tg Exp $"); | ||||||
| #endif | #endif | ||||||
| #define MKSH_VERSION "R52 2016/07/12" | #define MKSH_VERSION "R52 2016/07/12" | ||||||
|  |  | ||||||
| @@ -864,13 +864,9 @@ EXTERN const char T_typeset[] E_INIT("=typeset"); | |||||||
| #define Ttypeset	(T_typeset + 1)		/* "typeset" */ | #define Ttypeset	(T_typeset + 1)		/* "typeset" */ | ||||||
| EXTERN const char Talias[] E_INIT("alias"); | EXTERN const char Talias[] E_INIT("alias"); | ||||||
| EXTERN const char Tunalias[] E_INIT("unalias"); | EXTERN const char Tunalias[] E_INIT("unalias"); | ||||||
| EXTERN const char Tcat[] E_INIT("cat"); |  | ||||||
| #ifdef __OS2__ | #ifdef __OS2__ | ||||||
| EXTERN const char Textproc[] E_INIT("extproc"); | EXTERN const char Textproc[] E_INIT("extproc"); | ||||||
| #endif | #endif | ||||||
| #ifdef MKSH_PRINTF_BUILTIN |  | ||||||
| EXTERN const char Tprintf[] E_INIT("printf"); |  | ||||||
| #endif |  | ||||||
| EXTERN const char Tsgset[] E_INIT("*=set"); | EXTERN const char Tsgset[] E_INIT("*=set"); | ||||||
| #define Tset		(Tsgset + 2)		/* "set" */ | #define Tset		(Tsgset + 2)		/* "set" */ | ||||||
| EXTERN const char Tsgexport[] E_INIT("*=export"); | EXTERN const char Tsgexport[] E_INIT("*=export"); | ||||||
| @@ -1243,6 +1239,9 @@ EXTERN bool last_lookup_was_array; | |||||||
| #define FDELETE		BIT(10)	/* function deleted while it was executing */ | #define FDELETE		BIT(10)	/* function deleted while it was executing */ | ||||||
| #define FKSH		BIT(11)	/* function defined with function x (vs x()) */ | #define FKSH		BIT(11)	/* function defined with function x (vs x()) */ | ||||||
| #define SPEC_BI		BIT(12)	/* a POSIX special builtin */ | #define SPEC_BI		BIT(12)	/* a POSIX special builtin */ | ||||||
|  | #define LOWER_BI	BIT(13)	/* (with LOW_BI) override even w/o flags */ | ||||||
|  | #define LOW_BI		BIT(14)	/* external utility overrides built-in one */ | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Attributes that can be set by the user (used to decide if an unset |  * Attributes that can be set by the user (used to decide if an unset | ||||||
|  * param should be repoted by set/typeset). Does not include ARRAY or |  * param should be repoted by set/typeset). Does not include ARRAY or | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user