Example #1
0
File: history.c Project: att/ast
//
// Flush the current history command.
//
void hist_flush(History_t *hp) {
    char *buff;
    if (hp) {
        buff = (char *)sfreserve(hp->histfp, 0, SF_LOCKR);
        if (buff) {
            hp->histflush = sfvalue(hp->histfp) + 1;
            sfwrite(hp->histfp, buff, 0);
        } else {
            hp->histflush = 0;
        }
        if (sfsync(hp->histfp) < 0) {
            Shell_t *shp = hp->histshell;
            hist_close(hp);
            if (!sh_histinit(shp)) sh_offoption(shp, SH_HISTORY);
        } else {
            hp->histflush = 0;
        }
    }
}
Example #2
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--;
	}
Example #3
0
File: history.c Project: att/ast
//
// Copy the last <n> commands to a new file and make this the history file.
//
static History_t *hist_trim(History_t *hp, int n) {
    char *cp;
    int incmd = 1, c = 0;
    History_t *hist_new, *hist_old = hp;
    char *buff, *endbuff, *tmpname = NULL;
    off_t oldp, newp;
    struct stat statb;

    unlink(hist_old->histname);
    if (access(hist_old->histname, F_OK) >= 0) {
        // The unlink can fail on windows 95.
        int fd;
        char *last, *name = hist_old->histname;
        sh_close(sffileno(hist_old->histfp));
        last = strrchr(name, '/');
        if (last) {
            *last = 0;
            tmpname = ast_temp_file(name, "hist", &fd, 0);
            *last = '/';
        } else {
            tmpname = ast_temp_file(".", "hist", &fd, 0);
        }
        if (!tmpname) {
            errormsg(SH_DICT, ERROR_exit(1), e_create, "hist");
            __builtin_unreachable();
        }
        close(fd);
        if (rename(name, tmpname) < 0) {
            free(tmpname);
            tmpname = name;
        }
        fd = open(tmpname, O_RDONLY | O_CLOEXEC);
        // What happens if this fails and returns -1? Coverity Scan #310940.
        (void)sfsetfd(hist_old->histfp, fd);
        if (tmpname == name) {
            free(tmpname);
            tmpname = NULL;
        }
    }
    hist_ptr = NULL;
    if (fstat(sffileno(hist_old->histfp), &statb) >= 0) {
        histinit = 1;
        histmode = statb.st_mode;
    }
    if (!sh_histinit(hp->histshell)) {
        // Use the old history file.
        hist_ptr = hist_old;
        return hist_ptr;
    }
    hist_new = hist_ptr;
    hist_ptr = hist_old;
    if (--n < 0) n = 0;
    newp = hist_seek(hist_old, ++n);
    while (1) {
        if (!incmd) {
            c = hist_ind(hist_new, ++hist_new->histind);
            hist_new->histcmds[c] = hist_new->histcnt;
            if (hist_new->histcnt > hist_new->histmarker + HIST_BSIZE / 2) {
                char locbuff[HIST_MARKSZ];
                hist_marker(locbuff, hist_new->histind);
                sfwrite(hist_new->histfp, locbuff, HIST_MARKSZ);
                hist_new->histcnt += HIST_MARKSZ;
                hist_new->histmarker = hist_new->histcmds[hist_ind(hist_new, c)] =
                    hist_new->histcnt;
            }
            oldp = newp;
            newp = hist_seek(hist_old, ++n);
            if (newp <= oldp) break;
        }
        if (!(buff = (char *)sfreserve(hist_old->histfp, SF_UNBOUND, 0))) break;
        *(endbuff = (cp = buff) + sfvalue(hist_old->histfp)) = 0;
        // Copy to null byte.
        incmd = 0;
        cp += strlen(cp) + 1;  // point past the terminating null
        if (cp > endbuff) {
            incmd = 1;
        } else if (*cp == 0) {
            cp++;
        }
        if (cp > endbuff) cp = endbuff;
        c = cp - buff;
        hist_new->histcnt += c;
        sfwrite(hist_new->histfp, buff, c);
    }
    hist_cancel(hist_new);
    sfclose(hist_old->histfp);
    if (tmpname) {
        unlink(tmpname);
        free(tmpname);
    }
    free(hist_old);
    hist_ptr = hist_new;
    return hist_ptr;
}
Example #4
0
int    b_print(int argc, char *argv[], Shbltin_t *context)
{
	register Sfio_t *outfile;
	register int exitval=0,n, fd = 1;
	register Shell_t *shp = context->shp;
	const char *options, *msg = e_file+4;
	char *format = 0, *fmttype=0;
	int sflag = 0, nflag=0, rflag=0, vflag=0;
	Namval_t *vname=0;
	Optdisc_t disc;
	disc.version = OPT_VERSION;
	disc.infof = infof;
	opt_info.disc = &disc;
	if(argc>0)
	{
		options = sh_optprint;
		nflag = rflag = 0;
		format = 0;
	}
	else
	{
		struct print *pp = (struct print*)context;
		shp = pp->sh;
		options = pp->options;
		if(argc==0)
		{
			nflag = pp->echon;
			rflag = pp->raw;
			argv++;
			goto skip;
		}
	}
	while((n = optget(argv,options))) switch(n)
	{
		case 'n':
			nflag++;
			break;
		case 'p':
			fd = shp->coutpipe;
			msg = e_query;
			break;
		case 'f':
			format = opt_info.arg;
			break;
		case 's':
			/* print to history file */
			if(!sh_histinit((void*)shp))
				errormsg(SH_DICT,ERROR_system(1),e_history);
			fd = sffileno(shp->gd->hist_ptr->histfp);
			sh_onstate(shp,SH_HISTORY);
			sflag++;
			break;
		case 'e':
			rflag = 0;
			break;
		case 'r':
			rflag = 1;
			break;
		case 'u':
			if(opt_info.arg[0]=='p' && opt_info.arg[1]==0)
			{
				fd = shp->coutpipe;
				msg = e_query;
				break;
			}
			fd = (int)strtol(opt_info.arg,&opt_info.arg,10);
			if(*opt_info.arg)
				fd = -1;
			else if(!sh_iovalidfd(shp,fd))
				fd = -1;
			else if(!(shp->inuse_bits&(1<<fd)) && (sh_inuse(shp,fd) || (shp->gd->hist_ptr && fd==sffileno(shp->gd->hist_ptr->histfp))))

				fd = -1;
			break;
		case 'j':
			fmttype = "json";
		case 'v':
			if(argc < 0)
			{
				if(!(vname = nv_open(opt_info.arg, shp->var_tree,NV_VARNAME|NV_NOARRAY)))
					errormsg(SH_DICT,2, "Cannot create variable %s", opt_info.arg);
			}
			else
				vflag='v';
			break;
		case 'C':
			vflag='C';
			break;
		case ':':
			/* The following is for backward compatibility */
#if OPT_VERSION >= 19990123
			if(strcmp(opt_info.name,"-R")==0)
#else
			if(strcmp(opt_info.option,"-R")==0)
#endif
			{
				rflag = 1;
				if(error_info.errors==0)
				{
					argv += opt_info.index+1;
					/* special case test for -Rn */
					if(strchr(argv[-1],'n'))
						nflag++;
					if(*argv && strcmp(*argv,"-n")==0)
					{

						nflag++;
						argv++;
					}
					goto skip2;
				}
			}
			else
				errormsg(SH_DICT,2, "%s", opt_info.arg);
			break;
		case '?':
			errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
			break;
	}
	argv += opt_info.index;
	if(error_info.errors || (argc<0 && !(format = *argv++)))
		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
	if(vflag && format)
		errormsg(SH_DICT,ERROR_usage(2),"-%c and -f are mutually exclusive",vflag);
skip:
	if(format)
		format = genformat(shp,format);
	/* handle special case of '-' operand for print */
	if(argc>0 && *argv && strcmp(*argv,"-")==0 && strcmp(argv[-1],"--"))
		argv++;
	if(vname)
	{
		if(!shp->strbuf2)
			shp->strbuf2 = sfstropen();
		outfile = shp->strbuf2;
		goto printv;
	}
skip2:
	if(fd < 0)
	{
		errno = EBADF;
		n = 0;
	}
	else if(!(n=shp->fdstatus[fd]))
		n = sh_iocheckfd(shp,fd,fd);
	if(!(n&IOWRITE))
	{
		/* don't print error message for stdout for compatibility */
		if(fd==1)
			return(1);
		errormsg(SH_DICT,ERROR_system(1),msg);
	}
	if(!(outfile=shp->sftable[fd]))
	{
		sh_onstate(shp,SH_NOTRACK);
		n = SF_WRITE|((n&IOREAD)?SF_READ:0);
		shp->sftable[fd] = outfile = sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fd,n);
		sh_offstate(shp,SH_NOTRACK);
		sfpool(outfile,shp->outpool,SF_WRITE);
	}