xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/bltins/hist.c (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
18*b30d1939SAndy Fiddaman *                                                                      *
19*b30d1939SAndy Fiddaman ***********************************************************************/
20*b30d1939SAndy Fiddaman #pragma prototyped
21*b30d1939SAndy Fiddaman #include	"defs.h"
22*b30d1939SAndy Fiddaman #include	<stak.h>
23*b30d1939SAndy Fiddaman #include	<ls.h>
24*b30d1939SAndy Fiddaman #include	<error.h>
25*b30d1939SAndy Fiddaman #include	"variables.h"
26*b30d1939SAndy Fiddaman #include	"io.h"
27*b30d1939SAndy Fiddaman #include	"name.h"
28*b30d1939SAndy Fiddaman #include	"history.h"
29*b30d1939SAndy Fiddaman #include	"builtins.h"
30*b30d1939SAndy Fiddaman #if SHOPT_HISTEXPAND
31*b30d1939SAndy Fiddaman #   include	"edit.h"
32*b30d1939SAndy Fiddaman #endif
33*b30d1939SAndy Fiddaman 
34*b30d1939SAndy Fiddaman #define HIST_RECURSE	5
35*b30d1939SAndy Fiddaman 
36*b30d1939SAndy Fiddaman static void hist_subst(const char*, int fd, char*);
37*b30d1939SAndy Fiddaman 
38*b30d1939SAndy Fiddaman #if 0
39*b30d1939SAndy Fiddaman     /* for the benefit of the dictionary generator */
40*b30d1939SAndy Fiddaman     int	b_fc(int argc,char *argv[], Shbltin_t *context){}
41*b30d1939SAndy Fiddaman #endif
b_hist(int argc,char * argv[],Shbltin_t * context)42*b30d1939SAndy Fiddaman int	b_hist(int argc,char *argv[], Shbltin_t *context)
43*b30d1939SAndy Fiddaman {
44*b30d1939SAndy Fiddaman 	register History_t *hp;
45*b30d1939SAndy Fiddaman 	register char *arg;
46*b30d1939SAndy Fiddaman 	register int flag,fdo;
47*b30d1939SAndy Fiddaman 	register Shell_t *shp = context->shp;
48*b30d1939SAndy Fiddaman 	Sfio_t *outfile;
49*b30d1939SAndy Fiddaman 	char *fname;
50*b30d1939SAndy Fiddaman 	int range[2], incr, index2, indx= -1;
51*b30d1939SAndy Fiddaman 	char *edit = 0;		/* name of editor */
52*b30d1939SAndy Fiddaman 	char *replace = 0;		/* replace old=new */
53*b30d1939SAndy Fiddaman 	int lflag = 0, nflag = 0, rflag = 0;
54*b30d1939SAndy Fiddaman #if SHOPT_HISTEXPAND
55*b30d1939SAndy Fiddaman 	int pflag = 0;
56*b30d1939SAndy Fiddaman #endif
57*b30d1939SAndy Fiddaman 	Histloc_t location;
58*b30d1939SAndy Fiddaman 	NOT_USED(argc);
59*b30d1939SAndy Fiddaman 	if(!sh_histinit((void*)shp))
60*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_system(1),e_histopen);
61*b30d1939SAndy Fiddaman 	hp = shp->gd->hist_ptr;
62*b30d1939SAndy Fiddaman 	while((flag = optget(argv,sh_opthist))) switch(flag)
63*b30d1939SAndy Fiddaman 	{
64*b30d1939SAndy Fiddaman 	    case 'e':
65*b30d1939SAndy Fiddaman 		edit = opt_info.arg;
66*b30d1939SAndy Fiddaman 		break;
67*b30d1939SAndy Fiddaman 	    case 'n':
68*b30d1939SAndy Fiddaman 		nflag++;
69*b30d1939SAndy Fiddaman 		break;
70*b30d1939SAndy Fiddaman 	    case 'l':
71*b30d1939SAndy Fiddaman 		lflag++;
72*b30d1939SAndy Fiddaman 		break;
73*b30d1939SAndy Fiddaman 	    case 'r':
74*b30d1939SAndy Fiddaman 		rflag++;
75*b30d1939SAndy Fiddaman 		break;
76*b30d1939SAndy Fiddaman 	    case 's':
77*b30d1939SAndy Fiddaman 		edit = "-";
78*b30d1939SAndy Fiddaman 		break;
79*b30d1939SAndy Fiddaman #if SHOPT_HISTEXPAND
80*b30d1939SAndy Fiddaman 	    case 'p':
81*b30d1939SAndy Fiddaman 		pflag++;
82*b30d1939SAndy Fiddaman 		break;
83*b30d1939SAndy Fiddaman #endif
84*b30d1939SAndy Fiddaman 	    case 'N':
85*b30d1939SAndy Fiddaman 		if(indx<=0)
86*b30d1939SAndy Fiddaman 		{
87*b30d1939SAndy Fiddaman 			if((flag = hist_max(hp) - opt_info.num-1) < 0)
88*b30d1939SAndy Fiddaman 				flag = 1;
89*b30d1939SAndy Fiddaman 			range[++indx] = flag;
90*b30d1939SAndy Fiddaman 			break;
91*b30d1939SAndy Fiddaman 		}
92*b30d1939SAndy Fiddaman 		/* FALLTHROUGH */
93*b30d1939SAndy Fiddaman 	    case ':':
94*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,2, "%s", opt_info.arg);
95*b30d1939SAndy Fiddaman 		break;
96*b30d1939SAndy Fiddaman 	    case '?':
97*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
98*b30d1939SAndy Fiddaman 		break;
99*b30d1939SAndy Fiddaman 	}
100*b30d1939SAndy Fiddaman 	if(error_info.errors)
101*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
102*b30d1939SAndy Fiddaman 	argv += (opt_info.index-1);
103*b30d1939SAndy Fiddaman #if SHOPT_HISTEXPAND
104*b30d1939SAndy Fiddaman 	if(pflag)
105*b30d1939SAndy Fiddaman 	{
106*b30d1939SAndy Fiddaman 		hist_cancel(hp);
107*b30d1939SAndy Fiddaman 		pflag = 0;
108*b30d1939SAndy Fiddaman 		while(arg=argv[1])
109*b30d1939SAndy Fiddaman 		{
110*b30d1939SAndy Fiddaman 			flag = hist_expand(arg,&replace);
111*b30d1939SAndy Fiddaman 			if(!(flag & HIST_ERROR))
112*b30d1939SAndy Fiddaman 				sfputr(sfstdout, replace, '\n');
113*b30d1939SAndy Fiddaman 			else
114*b30d1939SAndy Fiddaman 				pflag = 1;
115*b30d1939SAndy Fiddaman 			if(replace)
116*b30d1939SAndy Fiddaman 				free(replace);
117*b30d1939SAndy Fiddaman 			argv++;
118*b30d1939SAndy Fiddaman 		}
119*b30d1939SAndy Fiddaman 		return pflag;
120*b30d1939SAndy Fiddaman 	}
121*b30d1939SAndy Fiddaman #endif
122*b30d1939SAndy Fiddaman 	flag = indx;
123*b30d1939SAndy Fiddaman 	while(flag<1 && (arg=argv[1]))
124*b30d1939SAndy Fiddaman 	{
125*b30d1939SAndy Fiddaman 		/* look for old=new argument */
126*b30d1939SAndy Fiddaman 		if(!replace && strchr(arg+1,'='))
127*b30d1939SAndy Fiddaman 		{
128*b30d1939SAndy Fiddaman 			replace = arg;
129*b30d1939SAndy Fiddaman 			argv++;
130*b30d1939SAndy Fiddaman 			continue;
131*b30d1939SAndy Fiddaman 		}
132*b30d1939SAndy Fiddaman 		else if(isdigit(*arg) || *arg == '-')
133*b30d1939SAndy Fiddaman 		{
134*b30d1939SAndy Fiddaman 			/* see if completely numeric */
135*b30d1939SAndy Fiddaman 			do	arg++;
136*b30d1939SAndy Fiddaman 			while(isdigit(*arg));
137*b30d1939SAndy Fiddaman 			if(*arg==0)
138*b30d1939SAndy Fiddaman 			{
139*b30d1939SAndy Fiddaman 				arg = argv[1];
140*b30d1939SAndy Fiddaman 				range[++flag] = (int)strtol(arg, (char**)0, 10);
141*b30d1939SAndy Fiddaman 				if(*arg == '-')
142*b30d1939SAndy Fiddaman 					range[flag] += (hist_max(hp)-1);
143*b30d1939SAndy Fiddaman 				argv++;
144*b30d1939SAndy Fiddaman 				continue;
145*b30d1939SAndy Fiddaman 			}
146*b30d1939SAndy Fiddaman 		}
147*b30d1939SAndy Fiddaman 		/* search for last line starting with string */
148*b30d1939SAndy Fiddaman 		location = hist_find(hp,argv[1],hist_max(hp)-1,0,-1);
149*b30d1939SAndy Fiddaman 		if((range[++flag] = location.hist_command) < 0)
150*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_found,argv[1]);
151*b30d1939SAndy Fiddaman 		argv++;
152*b30d1939SAndy Fiddaman 	}
153*b30d1939SAndy Fiddaman 	if(flag <0)
154*b30d1939SAndy Fiddaman 	{
155*b30d1939SAndy Fiddaman 		/* set default starting range */
156*b30d1939SAndy Fiddaman 		if(lflag)
157*b30d1939SAndy Fiddaman 		{
158*b30d1939SAndy Fiddaman 			flag = hist_max(hp)-16;
159*b30d1939SAndy Fiddaman 			if(flag<1)
160*b30d1939SAndy Fiddaman 				flag = 1;
161*b30d1939SAndy Fiddaman 		}
162*b30d1939SAndy Fiddaman 		else
163*b30d1939SAndy Fiddaman 			flag = hist_max(hp)-2;
164*b30d1939SAndy Fiddaman 		range[0] = flag;
165*b30d1939SAndy Fiddaman 		flag = 0;
166*b30d1939SAndy Fiddaman 	}
167*b30d1939SAndy Fiddaman 	index2 = hist_min(hp);
168*b30d1939SAndy Fiddaman 	if(range[0]<index2)
169*b30d1939SAndy Fiddaman 		range[0] = index2;
170*b30d1939SAndy Fiddaman 	if(flag==0)
171*b30d1939SAndy Fiddaman 		/* set default termination range */
172*b30d1939SAndy Fiddaman 		range[1] = ((lflag && !edit)?hist_max(hp)-1:range[0]);
173*b30d1939SAndy Fiddaman 	if(range[1]>=(flag=(hist_max(hp) - !lflag)))
174*b30d1939SAndy Fiddaman 		range[1] = flag;
175*b30d1939SAndy Fiddaman 	/* check for valid ranges */
176*b30d1939SAndy Fiddaman 	if(range[1]<index2 || range[0]>=flag)
177*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_badrange,range[0],range[1]);
178*b30d1939SAndy Fiddaman 	if(edit && *edit=='-' && range[0]!=range[1])
179*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_eneedsarg);
180*b30d1939SAndy Fiddaman 	/* now list commands from range[rflag] to range[1-rflag] */
181*b30d1939SAndy Fiddaman 	incr = 1;
182*b30d1939SAndy Fiddaman 	flag = rflag>0;
183*b30d1939SAndy Fiddaman 	if(range[1-flag] < range[flag])
184*b30d1939SAndy Fiddaman 		incr = -1;
185*b30d1939SAndy Fiddaman 	if(lflag)
186*b30d1939SAndy Fiddaman 	{
187*b30d1939SAndy Fiddaman 		outfile = sfstdout;
188*b30d1939SAndy Fiddaman 		arg = "\n\t";
189*b30d1939SAndy Fiddaman 	}
190*b30d1939SAndy Fiddaman 	else
191*b30d1939SAndy Fiddaman 	{
192*b30d1939SAndy Fiddaman 		if(!(fname=pathtmp(NIL(char*),0,0,NIL(int*))))
193*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_create,"");
194*b30d1939SAndy Fiddaman 		if((fdo=open(fname,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) < 0)
195*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_system(1),e_create,fname);
196*b30d1939SAndy Fiddaman 		outfile= sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fdo,SF_WRITE);
197*b30d1939SAndy Fiddaman 		arg = "\n";
198*b30d1939SAndy Fiddaman 		nflag++;
199*b30d1939SAndy Fiddaman 	}
200*b30d1939SAndy Fiddaman 	while(1)
201*b30d1939SAndy Fiddaman 	{
202*b30d1939SAndy Fiddaman 		if(nflag==0)
203*b30d1939SAndy Fiddaman 			sfprintf(outfile,"%d\t",range[flag]);
204*b30d1939SAndy Fiddaman 		else if(lflag)
205*b30d1939SAndy Fiddaman 			sfputc(outfile,'\t');
206*b30d1939SAndy Fiddaman 		hist_list(shp->gd->hist_ptr,outfile,hist_tell(shp->gd->hist_ptr,range[flag]),0,arg);
207*b30d1939SAndy Fiddaman 		if(lflag)
208*b30d1939SAndy Fiddaman 			sh_sigcheck(shp);
209*b30d1939SAndy Fiddaman 		if(range[flag] == range[1-flag])
210*b30d1939SAndy Fiddaman 			break;
211*b30d1939SAndy Fiddaman 		range[flag] += incr;
212*b30d1939SAndy Fiddaman 	}
213*b30d1939SAndy Fiddaman 	if(lflag)
214*b30d1939SAndy Fiddaman 		return(0);
215*b30d1939SAndy Fiddaman 	sfclose(outfile);
216*b30d1939SAndy Fiddaman 	hist_eof(hp);
217*b30d1939SAndy Fiddaman 	arg = edit;
218*b30d1939SAndy Fiddaman 	if(!arg && !(arg=nv_getval(sh_scoped(shp,HISTEDIT))) && !(arg=nv_getval(sh_scoped(shp,FCEDNOD))))
219*b30d1939SAndy Fiddaman 	{
220*b30d1939SAndy Fiddaman 		arg = (char*)e_defedit;
221*b30d1939SAndy Fiddaman 		if(*arg!='/')
222*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),"ed not found set FCEDIT");
223*b30d1939SAndy Fiddaman 	}
224*b30d1939SAndy Fiddaman #ifdef apollo
225*b30d1939SAndy Fiddaman 	/*
226*b30d1939SAndy Fiddaman 	 * Code to support the FC using the pad editor.
227*b30d1939SAndy Fiddaman 	 * Exampled of how to use: HISTEDIT=pad
228*b30d1939SAndy Fiddaman 	 */
229*b30d1939SAndy Fiddaman 	if (strcmp (arg, "pad") == 0)
230*b30d1939SAndy Fiddaman 	{
231*b30d1939SAndy Fiddaman 		extern int pad_create(char*);
232*b30d1939SAndy Fiddaman 		sh_close(fdo);
233*b30d1939SAndy Fiddaman 		fdo = pad_create(fname);
234*b30d1939SAndy Fiddaman 		pad_wait(fdo);
235*b30d1939SAndy Fiddaman 		unlink(fname);
236*b30d1939SAndy Fiddaman 		strcat(fname, ".bak");
237*b30d1939SAndy Fiddaman 		unlink(fname);
238*b30d1939SAndy Fiddaman 		lseek(fdo,(off_t)0,SEEK_SET);
239*b30d1939SAndy Fiddaman 	}
240*b30d1939SAndy Fiddaman 	else
241*b30d1939SAndy Fiddaman 	{
242*b30d1939SAndy Fiddaman #endif /* apollo */
243*b30d1939SAndy Fiddaman 	if(*arg != '-')
244*b30d1939SAndy Fiddaman 	{
245*b30d1939SAndy Fiddaman 		char *com[3];
246*b30d1939SAndy Fiddaman 		com[0] =  arg;
247*b30d1939SAndy Fiddaman 		com[1] =  fname;
248*b30d1939SAndy Fiddaman 		com[2] = 0;
249*b30d1939SAndy Fiddaman 		error_info.errors = sh_eval(sh_sfeval(com),0);
250*b30d1939SAndy Fiddaman 	}
251*b30d1939SAndy Fiddaman 	fdo = sh_chkopen(fname);
252*b30d1939SAndy Fiddaman 	unlink(fname);
253*b30d1939SAndy Fiddaman 	free((void*)fname);
254*b30d1939SAndy Fiddaman #ifdef apollo
255*b30d1939SAndy Fiddaman 	}
256*b30d1939SAndy Fiddaman #endif /* apollo */
257*b30d1939SAndy Fiddaman 	/* don't history fc itself unless forked */
258*b30d1939SAndy Fiddaman 	error_info.flags |= ERROR_SILENT;
259*b30d1939SAndy Fiddaman 	if(!sh_isstate(SH_FORKED))
260*b30d1939SAndy Fiddaman 		hist_cancel(hp);
261*b30d1939SAndy Fiddaman 	sh_onstate(SH_HISTORY);
262*b30d1939SAndy Fiddaman 	sh_onstate(SH_VERBOSE);	/* echo lines as read */
263*b30d1939SAndy Fiddaman 	if(replace)
264*b30d1939SAndy Fiddaman 		hist_subst(error_info.id,fdo,replace);
265*b30d1939SAndy Fiddaman 	else if(error_info.errors == 0)
266*b30d1939SAndy Fiddaman 	{
267*b30d1939SAndy Fiddaman 		char buff[IOBSIZE+1];
268*b30d1939SAndy Fiddaman 		Sfio_t *iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fdo,SF_READ);
269*b30d1939SAndy Fiddaman 		/* read in and run the command */
270*b30d1939SAndy Fiddaman 		if(shp->hist_depth++ > HIST_RECURSE)
271*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_toodeep,"history");
272*b30d1939SAndy Fiddaman 		sh_eval(iop,1);
273*b30d1939SAndy Fiddaman 		shp->hist_depth--;
274*b30d1939SAndy Fiddaman 	}
275*b30d1939SAndy Fiddaman 	else
276*b30d1939SAndy Fiddaman 	{
277*b30d1939SAndy Fiddaman 		sh_close(fdo);
278*b30d1939SAndy Fiddaman 		if(!sh_isoption(SH_VERBOSE))
279*b30d1939SAndy Fiddaman 			sh_offstate(SH_VERBOSE);
280*b30d1939SAndy Fiddaman 		sh_offstate(SH_HISTORY);
281*b30d1939SAndy Fiddaman 	}
282*b30d1939SAndy Fiddaman 	return(shp->exitval);
283*b30d1939SAndy Fiddaman }
284*b30d1939SAndy Fiddaman 
285*b30d1939SAndy Fiddaman 
286*b30d1939SAndy Fiddaman /*
287*b30d1939SAndy Fiddaman  * given a file containing a command and a string of the form old=new,
288*b30d1939SAndy Fiddaman  * execute the command with the string old replaced by new
289*b30d1939SAndy Fiddaman  */
290*b30d1939SAndy Fiddaman 
hist_subst(const char * command,int fd,char * replace)291*b30d1939SAndy Fiddaman static void hist_subst(const char *command,int fd,char *replace)
292*b30d1939SAndy Fiddaman {
293*b30d1939SAndy Fiddaman 	register char *newp=replace;
294*b30d1939SAndy Fiddaman 	register char *sp;
295*b30d1939SAndy Fiddaman 	register int c;
296*b30d1939SAndy Fiddaman 	off_t size;
297*b30d1939SAndy Fiddaman 	char *string;
298*b30d1939SAndy Fiddaman 	while(*++newp != '='); /* skip to '=' */
299*b30d1939SAndy Fiddaman 	if((size = lseek(fd,(off_t)0,SEEK_END)) < 0)
300*b30d1939SAndy Fiddaman 		return;
301*b30d1939SAndy Fiddaman 	lseek(fd,(off_t)0,SEEK_SET);
302*b30d1939SAndy Fiddaman 	c =  (int)size;
303*b30d1939SAndy Fiddaman 	string = stakalloc(c+1);
304*b30d1939SAndy Fiddaman 	if(read(fd,string,c)!=c)
305*b30d1939SAndy Fiddaman 		return;
306*b30d1939SAndy Fiddaman 	string[c] = 0;
307*b30d1939SAndy Fiddaman 	*newp++ =  0;
308*b30d1939SAndy Fiddaman 	if((sp=sh_substitute(string,replace,newp))==0)
309*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_subst,command);
310*b30d1939SAndy Fiddaman 	*(newp-1) =  '=';
311*b30d1939SAndy Fiddaman 	sh_eval(sfopen(NIL(Sfio_t*),sp,"s"),1);
312*b30d1939SAndy Fiddaman }
313*b30d1939SAndy Fiddaman 
314