Beispiel #1
0
int	b_hist(int argc,char *argv[], void *extra)
{
	register History_t *hp;
	register char *arg;
	register int flag,fdo;
	register Shell_t *shp = ((Shbltin_t*)extra)->shp;
	Sfio_t *outfile;
	char *fname;
	int range[2], incr, index2, indx= -1;
	char *edit = 0;		/* name of editor */
	char *replace = 0;		/* replace old=new */
	int lflag = 0, nflag = 0, rflag = 0;
#if SHOPT_HISTEXPAND
	int pflag = 0;
#endif
	Histloc_t location;
	NOT_USED(argc);
	if(!sh_histinit((void*)shp))
		errormsg(SH_DICT,ERROR_system(1),e_histopen);
	hp = shp->gd->hist_ptr;
	while((flag = optget(argv,sh_opthist))) switch(flag)
	{
	    case 'e':
		edit = opt_info.arg;
		break;
	    case 'n':
		nflag++;
		break;
	    case 'l':
		lflag++;
		break;
	    case 'r':
		rflag++;
		break;
	    case 's':
		edit = "-";
		break;
#if SHOPT_HISTEXPAND
	    case 'p':
		pflag++;
		break;
#endif
	    case 'N':
		if(indx<=0)
		{
			if((flag = hist_max(hp) - opt_info.num-1) < 0)
				flag = 1;
			range[++indx] = flag;
			break;
		}
	    case ':':
		errormsg(SH_DICT,2, "%s", opt_info.arg);
		break;
	    case '?':
		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
		break;
	}
	if(error_info.errors)
		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
	argv += (opt_info.index-1);
#if SHOPT_HISTEXPAND
	if(pflag)
	{
		hist_cancel(hp);
		pflag = 0;
		while(arg=argv[1])
		{
			flag = hist_expand(arg,&replace);
			if(!(flag & HIST_ERROR))
				sfputr(sfstdout, replace, '\n');
			else
				pflag = 1;
			if(replace)
				free(replace);
			argv++;
		}
		return pflag;
	}
#endif
	flag = indx;
	while(flag<1 && (arg=argv[1]))
	{
		/* look for old=new argument */
		if(!replace && strchr(arg+1,'='))
		{
			replace = arg;
			argv++;
			continue;
		}
		else if(isdigit(*arg) || *arg == '-')
		{
			/* see if completely numeric */
			do	arg++;
			while(isdigit(*arg));
			if(*arg==0)
			{
				arg = argv[1];
				range[++flag] = (int)strtol(arg, (char**)0, 10);
				if(*arg == '-')
					range[flag] += (hist_max(hp)-1);
				argv++;
				continue;
			}
		}
		/* search for last line starting with string */
		location = hist_find(hp,argv[1],hist_max(hp)-1,0,-1);
		if((range[++flag] = location.hist_command) < 0)
			errormsg(SH_DICT,ERROR_exit(1),e_found,argv[1]);
		argv++;
	}
	if(flag <0)
	{
		/* set default starting range */
		if(lflag)
		{
			flag = hist_max(hp)-16;
			if(flag<1)
				flag = 1;
		}
		else
			flag = hist_max(hp)-2;
		range[0] = flag;
		flag = 0;
	}
	index2 = hist_min(hp);
	if(range[0]<index2)
		range[0] = index2;
	if(flag==0)
		/* set default termination range */
		range[1] = ((lflag && !edit)?hist_max(hp)-1:range[0]);
	if(range[1]>=(flag=(hist_max(hp) - !lflag)))
		range[1] = flag;
	/* check for valid ranges */
	if(range[1]<index2 || range[0]>=flag)
		errormsg(SH_DICT,ERROR_exit(1),e_badrange,range[0],range[1]);
	if(edit && *edit=='-' && range[0]!=range[1])
		errormsg(SH_DICT,ERROR_exit(1),e_eneedsarg);
	/* now list commands from range[rflag] to range[1-rflag] */
	incr = 1;
	flag = rflag>0;
	if(range[1-flag] < range[flag])
		incr = -1;
	if(lflag)
	{
		outfile = sfstdout;
		arg = "\n\t";
	}
	else
	{
		if(!(fname=pathtmp(NIL(char*),0,0,NIL(int*))))
			errormsg(SH_DICT,ERROR_exit(1),e_create,"");
		if((fdo=open(fname,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) < 0)
			errormsg(SH_DICT,ERROR_system(1),e_create,fname);
		outfile= sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fdo,SF_WRITE);
		arg = "\n";
		nflag++;
	}
	while(1)
	{
		if(nflag==0)
			sfprintf(outfile,"%d\t",range[flag]);
		else if(lflag)
			sfputc(outfile,'\t');
		hist_list(shp->gd->hist_ptr,outfile,hist_tell(shp->gd->hist_ptr,range[flag]),0,arg);
		if(lflag)
			sh_sigcheck(shp);
		if(range[flag] == range[1-flag])
			break;
		range[flag] += incr;
	}
	if(lflag)
		return(0);
	sfclose(outfile);
	hist_eof(hp);
	arg = edit;
	if(!arg && !(arg=nv_getval(sh_scoped(shp,HISTEDIT))) && !(arg=nv_getval(sh_scoped(shp,FCEDNOD))))
		arg = (char*)e_defedit;
#ifdef apollo
	/*
	 * Code to support the FC using the pad editor.
	 * Exampled of how to use: HISTEDIT=pad
	 */
	if (strcmp (arg, "pad") == 0)
	{
		extern int pad_create(char*);
		sh_close(fdo);
		fdo = pad_create(fname);
		pad_wait(fdo);
		unlink(fname);
		strcat(fname, ".bak");
		unlink(fname);
		lseek(fdo,(off_t)0,SEEK_SET);
	}
	else
	{
#endif /* apollo */
	if(*arg != '-')
	{
		char *com[3];
		com[0] =  arg;
		com[1] =  fname;
		com[2] = 0;
		error_info.errors = sh_eval(sh_sfeval(com),0);
	}
	fdo = sh_chkopen(fname);
	unlink(fname);
	free((void*)fname);
#ifdef apollo
	}
#endif /* apollo */
	/* don't history fc itself unless forked */
	error_info.flags |= ERROR_SILENT;
	if(!sh_isstate(SH_FORKED))
		hist_cancel(hp);
	sh_onstate(SH_HISTORY);
	sh_onstate(SH_VERBOSE);	/* echo lines as read */
	if(replace)
		hist_subst(error_info.id,fdo,replace);
	else if(error_info.errors == 0)
	{
		char buff[IOBSIZE+1];
		Sfio_t *iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fdo,SF_READ);
		/* read in and run the command */
		if(shp->hist_depth++ > HIST_RECURSE)
			errormsg(SH_DICT,ERROR_exit(1),e_toodeep,"history");
		sh_eval(iop,1);
		shp->hist_depth--;
	}
Beispiel #2
0
void	ed_setup(register Edit_t *ep, int fd, int reedit)
{
	Shell_t *shp = ep->sh;
	register char *pp;
	register char *last, *prev;
	char *ppmax;
	int myquote = 0, n;
	register int qlen = 1, qwid;
	char inquote = 0;
	ep->e_fd = fd;
	ep->e_multiline = sh_isoption(SH_MULTILINE)!=0;
#ifdef SIGWINCH
	if(!(shp->sigflag[SIGWINCH]&SH_SIGFAULT))
	{
		signal(SIGWINCH,sh_fault);
		shp->sigflag[SIGWINCH] |= SH_SIGFAULT;
	}
	pp = shp->st.trapcom[SIGWINCH];
	shp->st.trapcom[SIGWINCH] = 0;
	sh_fault(SIGWINCH);
	shp->st.trapcom[SIGWINCH] = pp;
	ep->sh->winch = 0;
#endif
#if SHOPT_EDPREDICT
	ep->hlist = 0;
	ep->nhlist = 0;
	ep->hoff = 0;
#endif /* SHOPT_EDPREDICT */
#if KSHELL
	ep->e_stkptr = stakptr(0);
	ep->e_stkoff = staktell();
	if(!(last = shp->prompt))
		last = "";
	shp->prompt = 0;
#else
	last = ep->e_prbuff;
#endif /* KSHELL */
	if(shp->gd->hist_ptr)
	{
		register History_t *hp = shp->gd->hist_ptr;
		ep->e_hismax = hist_max(hp);
		ep->e_hismin = hist_min(hp);
	}
	else
	{
		ep->e_hismax = ep->e_hismin = ep->e_hloff = 0;
	}
	ep->e_hline = ep->e_hismax;
	if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
		ep->e_wsize = MAXLINE;
	else
		ep->e_wsize = ed_window()-2;
	ep->e_winsz = ep->e_wsize+2;
	ep->e_crlf = 1;
	ep->e_plen = 0;
	pp = ep->e_prompt;
	ppmax = pp+PRSIZE-1;
	*pp++ = '\r';
	{
		register int c;
		while(prev = last, c = mbchar(last)) switch(c)
		{
			case ESC:
			{
				int skip=0;
				ep->e_crlf = 0;
				*pp++ = c;
				for(n=1; c = *last++; n++)
				{
					if(pp < ppmax)
						*pp++ = c;
					if(c=='\a' || c==ESC || c=='\r')
						break;
					if(skip || (c>='0' && c<='9'))
					{
						skip = 0;
						continue;
					}
					if(n>1 && c==';')
						skip = 1;
					else if(n>2 || (c!= '[' &&  c!= ']'))
						break;
				}
				if(c==0 || c==ESC || c=='\r')
					last--;
				qlen += (n+1);
				break;
			}
			case '\b':
				if(pp>ep->e_prompt+1)
					pp--;
				break;
			case '\r':
				if(pp == (ep->e_prompt+2)) /* quote char */
					myquote = *(pp-1);
				/*FALLTHROUGH*/

			case '\n':
				/* start again */
				ep->e_crlf = 1;
				qlen = 1;
				inquote = 0;
				pp = ep->e_prompt+1;
				break;

			case '\t':
				/* expand tabs */
				while((pp-ep->e_prompt)%TABSIZE)
				{
					if(pp >= ppmax)
						break;
					*pp++ = ' ';
				}
				break;

			case '\a':
				/* cut out bells */
				break;

			default:
				if(c==myquote)
				{
					qlen += inquote;
					inquote ^= 1;
				}
				if(pp < ppmax)
				{
					if(inquote)
						qlen++;
					else if(!is_print(c))
						ep->e_crlf = 0;
					if((qwid = last - prev) > 1)
						qlen += qwid - mbwidth(c);
					while(prev < last && pp < ppmax)
						*pp++ = *prev++;
				}
				break;
		}
	}
	if(pp-ep->e_prompt > qlen)
		ep->e_plen = pp - ep->e_prompt - qlen;
	*pp = 0;
	if(!ep->e_multiline && (ep->e_wsize -= ep->e_plen) < 7)
	{
		register int shift = 7-ep->e_wsize;
		ep->e_wsize = 7;
		pp = ep->e_prompt+1;
		strcpy(pp,pp+shift);
		ep->e_plen -= shift;
		last[-ep->e_plen-2] = '\r';
	}
	sfsync(sfstderr);
	if(fd == sffileno(sfstderr))
	{
		/* can't use output buffer when reading from stderr */
		static char *buff;
		if(!buff)
			buff = (char*)malloc(MAXLINE);
		ep->e_outbase = ep->e_outptr = buff;
		ep->e_outlast = ep->e_outptr + MAXLINE;
		return;
	}
	qlen = sfset(sfstderr,SF_READ,0);
	/* make sure SF_READ not on */
	ep->e_outbase = ep->e_outptr = (char*)sfreserve(sfstderr,SF_UNBOUND,SF_LOCKR);
	ep->e_outlast = ep->e_outptr + sfvalue(sfstderr);
	if(qlen)
		sfset(sfstderr,SF_READ,1);
	sfwrite(sfstderr,ep->e_outptr,0);
	ep->e_eol = reedit;
	if(ep->e_multiline)
	{
#ifdef _cmd_tput
		char *term;
		if(!ep->e_term)
			ep->e_term = nv_search("TERM",shp->var_tree,0);
		if(ep->e_term && (term=nv_getval(ep->e_term)) && strlen(term)<sizeof(ep->e_termname) && strcmp(term,ep->e_termname))
		{
			sh_trap(".sh.subscript=$(tput cuu1 2>/dev/null)",0);
			if(pp=nv_getval(SH_SUBSCRNOD))
				strncpy(CURSOR_UP,pp,sizeof(CURSOR_UP)-1);
			nv_unset(SH_SUBSCRNOD);
			strcpy(ep->e_termname,term);
		}
#endif
		ep->e_wsize = MAXLINE - (ep->e_plen+1);
	}
	if(ep->e_default && (pp = nv_getval(ep->e_default)))
	{
		n = strlen(pp);
		if(n > LOOKAHEAD)
			n = LOOKAHEAD;
		ep->e_lookahead = n;
		while(n-- > 0)
			ep->e_lbuf[n] = *pp++;
		ep->e_default = 0;
	}
}