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--; }
int path_expand(Shell_t *shp, const char *pattern, struct argnod **arghead) { glob_t gdata; struct argnod *ap; glob_t *gp = &gdata; int flags, extra = 0; #if SHOPT_BASH int off; char *sp, *cp, *cp2; #endif sh_stats(STAT_GLOBS); memset(gp, 0, sizeof(gdata)); flags = GLOB_GROUP | GLOB_AUGMENTED | GLOB_NOCHECK | GLOB_NOSORT | GLOB_STACK | GLOB_LIST | GLOB_DISC; if (sh_isoption(shp, SH_MARKDIRS)) flags |= GLOB_MARK; if (sh_isoption(shp, SH_GLOBSTARS)) flags |= GLOB_STARSTAR; #if SHOPT_BASH #if 0 if(sh_isoption(shp,SH_BASH) && !sh_isoption(shp,SH_EXTGLOB)) flags &= ~GLOB_AUGMENTED; #endif if (sh_isoption(shp, SH_NULLGLOB)) flags &= ~GLOB_NOCHECK; if (sh_isoption(shp, SH_NOCASEGLOB)) flags |= GLOB_ICASE; #endif if (sh_isstate(shp, SH_COMPLETE)) { extra += scantree(shp, shp->alias_tree, pattern, arghead); extra += scantree(shp, shp->fun_tree, pattern, arghead); gp->gl_nextdir = nextdir; flags |= GLOB_COMPLETE; flags &= ~GLOB_NOCHECK; } #if SHOPT_BASH off = stktell(shp->stk); if (off) sp = stkfreeze(shp->stk, 0); if (sh_isoption(shp, SH_BASH)) { // For bash, FIGNORE is a colon separated list of suffixes to ignore // when doing filename/command completion. GLOBIGNORE is similar to ksh // FIGNORE, but colon separated instead of being an augmented shell // pattern. Generate shell patterns out of those here. if (sh_isstate(shp, SH_FCOMPLETE)) { cp = nv_getval(sh_scoped(shp, FIGNORENOD)); } else { static Namval_t *GLOBIGNORENOD; if (!GLOBIGNORENOD) GLOBIGNORENOD = nv_open("GLOBIGNORE", shp->var_tree, 0); cp = nv_getval(sh_scoped(shp, GLOBIGNORENOD)); } if (cp) { flags |= GLOB_AUGMENTED; sfputr(shp->stk, "@(", -1); if (!sh_isstate(shp, SH_FCOMPLETE)) { sfputr(shp->stk, cp, -1); for (cp = stkptr(shp->stk, off); *cp; cp++) { if (*cp == ':') *cp = '|'; } } else { cp2 = strtok(cp, ":"); if (!cp2) cp2 = cp; do { sfputc(shp->stk, '*'); sfputr(shp->stk, cp2, -1); cp2 = strtok(NULL, ":"); if (cp2) { *(cp2 - 1) = ':'; sfputc(shp->stk, '|'); } } while (cp2); } sfputc(shp->stk, ')'); gp->gl_fignore = stkfreeze(shp->stk, 1); } else if (!sh_isstate(shp, SH_FCOMPLETE) && sh_isoption(shp, SH_DOTGLOB)) { gp->gl_fignore = ""; } } else #endif gp->gl_fignore = nv_getval(sh_scoped(shp, FIGNORENOD)); if (suflen) gp->gl_suffix = sufstr; gp->gl_intr = &shp->trapnote; suflen = 0; if (strncmp(pattern, "~(N", 3) == 0) flags &= ~GLOB_NOCHECK; ast_glob(pattern, flags, 0, gp); #if SHOPT_BASH if (off) { stkset(shp->stk, sp, off); } else { stkseek(shp->stk, 0); } #endif sh_sigcheck(shp); for (ap = (struct argnod *)gp->gl_list; ap; ap = ap->argnxt.ap) { ap->argchn.ap = ap->argnxt.ap; if (!ap->argnxt.ap) ap->argchn.ap = *arghead; } if (gp->gl_list) *arghead = (struct argnod *)gp->gl_list; return gp->gl_pathc + extra; }