⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hush.c

📁 uboot详细解读可用启动引导LINUX2.6内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (rmode == RES_UNTIL)			flag_rep = last_return_code;		if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) ||		     (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) )			skip_more_in_this_rmode=rmode;#ifndef __U_BOOT__		checkjobs(NULL);#endif	}	return rcode;}/* broken, of course, but OK for testing */static char *indenter(int i){	static char blanks[]="                                    ";	return &blanks[sizeof(blanks)-i-1];}/* return code is the exit status of the pipe */static int free_pipe(struct pipe *pi, int indent){	char **p;	struct child_prog *child;#ifndef __U_BOOT__	struct redir_struct *r, *rnext;#endif	int a, i, ret_code=0;	char *ind = indenter(indent);#ifndef __U_BOOT__	if (pi->stopped_progs > 0)		return ret_code;	final_printf("%s run pipe: (pid %d)\n",ind,getpid());#endif	for (i=0; i<pi->num_progs; i++) {		child = &pi->progs[i];		final_printf("%s  command %d:\n",ind,i);		if (child->argv) {			for (a=0,p=child->argv; *p; a++,p++) {				final_printf("%s   argv[%d] = %s\n",ind,a,*p);			}#ifndef __U_BOOT__			globfree(&child->glob_result);#else			for (a = child->argc;a >= 0;a--) {				free(child->argv[a]);			}					free(child->argv);			child->argc = 0;#endif			child->argv=NULL;		} else if (child->group) {#ifndef __U_BOOT__			final_printf("%s   begin group (subshell:%d)\n",ind, child->subshell);#endif			ret_code = free_pipe_list(child->group,indent+3);			final_printf("%s   end group\n",ind);		} else {			final_printf("%s   (nil)\n",ind);		}#ifndef __U_BOOT__		for (r=child->redirects; r; r=rnext) {			final_printf("%s   redirect %d%s", ind, r->fd, redir_table[r->type].descrip);			if (r->dup == -1) {				/* guard against the case >$FOO, where foo is unset or blank */				if (r->word.gl_pathv) {					final_printf(" %s\n", *r->word.gl_pathv);					globfree(&r->word);				}			} else {				final_printf("&%d\n", r->dup);			}			rnext=r->next;			free(r);		}		child->redirects=NULL;#endif	}	free(pi->progs);   /* children are an array, they get freed all at once */	pi->progs=NULL;	return ret_code;}static int free_pipe_list(struct pipe *head, int indent){	int rcode=0;   /* if list has no members */	struct pipe *pi, *next;	char *ind = indenter(indent);	for (pi=head; pi; pi=next) {		final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode);		rcode = free_pipe(pi, indent);		final_printf("%s pipe followup code %d\n", ind, pi->followup);		next=pi->next;		pi->next=NULL;		free(pi);	}	return rcode;}/* Select which version we will use */static int run_list(struct pipe *pi){	int rcode=0;#ifndef __U_BOOT__	if (fake_mode==0) {#endif		rcode = run_list_real(pi);#ifndef __U_BOOT__	}#endif	/* free_pipe_list has the side effect of clearing memory	 * In the long run that function can be merged with run_list_real,	 * but doing that now would hobble the debugging effort. */	free_pipe_list(pi,0);	return rcode;}/* The API for glob is arguably broken.  This routine pushes a non-matching * string into the output structure, removing non-backslashed backslashes. * If someone can prove me wrong, by performing this function within the * original glob(3) api, feel free to rewrite this routine into oblivion. * Return code (0 vs. GLOB_NOSPACE) matches glob(3). * XXX broken if the last character is '\\', check that before calling. */#ifndef __U_BOOT__static int globhack(const char *src, int flags, glob_t *pglob){	int cnt=0, pathc;	const char *s;	char *dest;	for (cnt=1, s=src; s && *s; s++) {		if (*s == '\\') s++;		cnt++;	}	dest = malloc(cnt);	if (!dest) return GLOB_NOSPACE;	if (!(flags & GLOB_APPEND)) {		pglob->gl_pathv=NULL;		pglob->gl_pathc=0;		pglob->gl_offs=0;		pglob->gl_offs=0;	}	pathc = ++pglob->gl_pathc;	pglob->gl_pathv = realloc(pglob->gl_pathv, (pathc+1)*sizeof(*pglob->gl_pathv));	if (pglob->gl_pathv == NULL) return GLOB_NOSPACE;	pglob->gl_pathv[pathc-1]=dest;	pglob->gl_pathv[pathc]=NULL;	for (s=src; s && *s; s++, dest++) {		if (*s == '\\') s++;		*dest = *s;	}	*dest='\0';	return 0;}/* XXX broken if the last character is '\\', check that before calling */static int glob_needed(const char *s){	for (; *s; s++) {		if (*s == '\\') s++;		if (strchr("*[?",*s)) return 1;	}	return 0;}#if 0static void globprint(glob_t *pglob){	int i;	debug_printf("glob_t at %p:\n", pglob);	debug_printf("  gl_pathc=%d  gl_pathv=%p  gl_offs=%d  gl_flags=%d\n",		pglob->gl_pathc, pglob->gl_pathv, pglob->gl_offs, pglob->gl_flags);	for (i=0; i<pglob->gl_pathc; i++)		debug_printf("pglob->gl_pathv[%d] = %p = %s\n", i,			pglob->gl_pathv[i], pglob->gl_pathv[i]);}#endifstatic int xglob(o_string *dest, int flags, glob_t *pglob){	int gr;	/* short-circuit for null word */	/* we can code this better when the debug_printf's are gone */	if (dest->length == 0) {		if (dest->nonnull) {			/* bash man page calls this an "explicit" null */			gr = globhack(dest->data, flags, pglob);			debug_printf("globhack returned %d\n",gr);		} else {			return 0;		}	} else if (glob_needed(dest->data)) {		gr = glob(dest->data, flags, NULL, pglob);		debug_printf("glob returned %d\n",gr);		if (gr == GLOB_NOMATCH) {			/* quote removal, or more accurately, backslash removal */			gr = globhack(dest->data, flags, pglob);			debug_printf("globhack returned %d\n",gr);		}	} else {		gr = globhack(dest->data, flags, pglob);		debug_printf("globhack returned %d\n",gr);	}	if (gr == GLOB_NOSPACE)		error_msg_and_die("out of memory during glob");	if (gr != 0) { /* GLOB_ABORTED ? */		error_msg("glob(3) error %d",gr);	}	/* globprint(glob_target); */	return gr;}#endif#ifdef __U_BOOT__static char *get_dollar_var(char ch);#endif/* This is used to get/check local shell variables */static char *get_local_var(const char *s){	struct variables *cur;	if (!s)		return NULL;#ifdef __U_BOOT__	if (*s == '$')		return get_dollar_var(s[1]);#endif	for (cur = top_vars; cur; cur=cur->next)		if(strcmp(cur->name, s)==0)			return cur->value;	return NULL;}/* This is used to set local shell variables   flg_export==0 if only local (not exporting) variable   flg_export==1 if "new" exporting environ   flg_export>1  if current startup environ (not call putenv()) */static int set_local_var(const char *s, int flg_export){	char *name, *value;	int result=0;	struct variables *cur;#ifdef __U_BOOT__	/* might be possible! */	if (!isalpha(*s))		return -1;#endif	name=strdup(s);#ifdef __U_BOOT__	if (getenv(name) != NULL) {		printf ("ERROR: "				"There is a global environment variable with the same name.\n");		free(name);		return -1;	}#endif	/* Assume when we enter this function that we are already in	 * NAME=VALUE format.  So the first order of business is to	 * split 's' on the '=' into 'name' and 'value' */	value = strchr(name, '=');	if (value==0 && ++value==0) {		free(name);		return -1;	}	*value++ = 0;	for(cur = top_vars; cur; cur = cur->next) {		if(strcmp(cur->name, name)==0)			break;	}	if(cur) {		if(strcmp(cur->value, value)==0) {			if(flg_export>0 && cur->flg_export==0)				cur->flg_export=flg_export;			else				result++;		} else {			if(cur->flg_read_only) {				error_msg("%s: readonly variable", name);				result = -1;			} else {				if(flg_export>0 || cur->flg_export>1)					cur->flg_export=1;				free(cur->value);				cur->value = strdup(value);			}		}	} else {		cur = malloc(sizeof(struct variables));		if(!cur) {			result = -1;		} else {			cur->name = strdup(name);			if(cur->name == 0) {				free(cur);				result = -1;			} else {				struct variables *bottom = top_vars;				cur->value = strdup(value);				cur->next = 0;				cur->flg_export = flg_export;				cur->flg_read_only = 0;				while(bottom->next) bottom=bottom->next;				bottom->next = cur;			}		}	}#ifndef __U_BOOT__	if(result==0 && cur->flg_export==1) {		*(value-1) = '=';		result = putenv(name);	} else {#endif		free(name);#ifndef __U_BOOT__		if(result>0)            /* equivalent to previous set */			result = 0;	}#endif	return result;}#ifndef __U_BOOT__static void unset_local_var(const char *name){	struct variables *cur;	if (name) {		for (cur = top_vars; cur; cur=cur->next) {			if(strcmp(cur->name, name)==0)				break;		}		if(cur!=0) {			struct variables *next = top_vars;			if(cur->flg_read_only) {				error_msg("%s: readonly variable", name);				return;			} else {				if(cur->flg_export)					unsetenv(cur->name);				free(cur->name);				free(cur->value);				while (next->next != cur)					next = next->next;				next->next = cur->next;			}			free(cur);		}	}}#endifstatic int is_assignment(const char *s){	if (s == NULL)		return 0;	if (!isalpha(*s)) return 0;	++s;	while(isalnum(*s) || *s=='_') ++s;	return *s=='=';}#ifndef __U_BOOT__/* the src parameter allows us to peek forward to a possible &n syntax * for file descriptor duplication, e.g., "2>&1". * Return code is 0 normally, 1 if a syntax error is detected in src. * Resource errors (in xmalloc) cause the process to exit */static int setup_redirect(struct p_context *ctx, int fd, redir_type style,	struct in_str *input){	struct child_prog *child=ctx->child;	struct redir_struct *redir = child->redirects;	struct redir_struct *last_redir=NULL;	/* Create a new redir_struct and drop it onto the end of the linked list */	while(redir) {		last_redir=redir;		redir=redir->next;	}	redir = xmalloc(sizeof(struct redir_struct));	redir->next=NULL;	redir->word.gl_pathv=NULL;	if (last_redir) {		last_redir->next=redir;	} else {		child->redirects=redir;	}	redir->type=style;	redir->fd= (fd==-1) ? redir_table[style].default_fd : fd ;	debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip);	/* Check for a '2>&1' type redirect */	redir->dup = redirect_dup_num(input);	if (redir->dup == -2) return 1;  /* syntax error */	if (redir->dup != -1) {		/* Erik had a check here that the file descriptor in question		 * is legit; I postpone that to "run time"		 * A "-" representation of "close me" shows up as a -3 here */		debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup);	} else {		/* We do _not_ try to open the file that src points to,		 * since we need to return and let src be expanded first.		 * Set ctx->pending_redirect, so we know what to do at the		 * end of the next parsed word.		 */		ctx->pending_redirect = redir;	}	return 0;}#endifstruct pipe *new_pipe(void) {	struct pipe *pi;	pi = xmalloc(sizeof(struct pipe));	pi->num_progs = 0;	pi->progs = NULL;	pi->next = NULL;	pi->followup = 0;  /* invalid */	pi->r_mode = RES_NONE;	return pi;}static void initialize_context(struct p_context *ctx){	ctx->pipe=NULL;#ifndef __U_BOOT__	ctx->pending_redirect=NULL;#endif	ctx->child=NULL;	ctx->list_head=new_pipe();	ctx->pipe=ctx->list_head;	ctx->w=RES_NONE;	ctx->stack=NULL;#ifdef __U_BOOT__	ctx->old_flag=0;#endif	done_command(ctx);   /* creates the memory for working child */}/* normal return is 0 * if a reserved word is found, and processed, return 1 * should handle if, then, elif, else, fi, for, while, until, do, done. * case, function, and select are obnoxious, save those for later. */struct reserved_combo {	char *literal;	int code;	long flag;};/* Mostly a list of accepted follow-up reserved words. * FLAG_END means we are done with the sequence, and are ready * to turn the compound list into a command. * FLAG_START means the word must start a new compound list. */static struct reserved_combo reserved_list[] = {	{ "if",    RES_IF,    FLAG_THEN | FLAG_START },	{ "then",  RES_THEN,  FLAG_ELIF | FLAG_ELSE | FLAG_FI },	{ "elif",  RES_ELIF,  FLAG_THEN },	{ "else",  RES_ELSE,  FLAG_FI   },	{ "fi",    RES_FI,    FLAG_END  },	{ "for",   RES_FOR,   FLAG_IN   | FLAG_START },	{ "while", RES_WHILE, FLAG_DO   | FLAG_START },	{ "until", RES_UNTIL, FLAG_DO   | FLAG_START },	{ "in",    RES_IN,    FLAG_DO   },	{ "do",    RES_DO,    FLAG_DONE },	{ "done",  RES_DONE,  FLAG_END  }};#define NRES (sizeof(reserved_list)/sizeof(struct reserved_combo))int reserved_word(o_string *dest, struct p_context *ctx){	struc

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -