Esempio n. 1
0
void write_name_quoted_relative(const char *name, size_t len,
				const char *prefix, size_t prefix_len,
				FILE *fp, int terminator)
{
	struct strbuf sb = STRBUF_INIT;

	name = path_relative(name, len, &sb, prefix, prefix_len);
	write_name_quoted(name, fp, terminator);

	strbuf_release(&sb);
}
Esempio n. 2
0
/* quote path as relative to the given prefix */
char *quote_path_relative(const char *in, int len,
			  struct strbuf *out, const char *prefix)
{
	struct strbuf sb = STRBUF_INIT;
	const char *rel = path_relative(in, len, &sb, prefix, -1);
	strbuf_reset(out);
	quote_c_style_counted(rel, strlen(rel), out, NULL, 0);
	strbuf_release(&sb);

	if (!out->len)
		strbuf_addstr(out, "./");

	return out->buf;
}
Esempio n. 3
0
File: history.c Progetto: att/ast
//
// Open the history file. If HISTNAME is not given and userid==0 then no history file. If login_sh
// and HISTFILE is longer than HIST_MAX bytes then it is cleaned up.
//
// hist_open() returns 1, if history file is opened.
//
int sh_histinit(void *sh_context) {
    Shell_t *shp = sh_context;
    int fd;
    History_t *hp;
    char *histname;
    char *fname = NULL;
    int histmask, maxlines, hist_start = 0;
    char *cp;
    off_t hsize = 0;

    shgd->hist_ptr = hist_ptr;
    if (shgd->hist_ptr) return 1;
    if (!(histname = nv_getval(HISTFILE))) {
        int offset = stktell(shp->stk);
        cp = nv_getval(HOME);
        if (cp) sfputr(shp->stk, cp, -1);
        sfputr(shp->stk, hist_fname, 0);
        stkseek(shp->stk, offset);
        histname = stkptr(shp->stk, offset);
    }

#if 0
// TODO: Figure out if this should be enabled. Originally excluded via `#ifdef future`.
    if (hp = wasopen) {
        // Reuse history file if same name.
        wasopen = 0;
        shgd->hist_ptr = hist_ptr = hp;
        if (strcmp(histname, hp->histname) == 0) {
            return 1;
        } else {
            hist_free();
        }
    }
#endif  // future

retry:
    cp = path_relative(shp, histname);
    if (!histinit) histmode = S_IRUSR | S_IWUSR;
    if ((fd = open(cp, O_BINARY | O_APPEND | O_RDWR | O_CREAT | O_CLOEXEC, histmode)) >= 0) {
        hsize = lseek(fd, (off_t)0, SEEK_END);
    }
    if ((unsigned)fd < 10) {
        int n;
        if ((n = sh_fcntl(fd, F_DUPFD_CLOEXEC, 10)) >= 0) {
            sh_close(fd);
            fd = n;
        }
    }
    // Make sure that file has history file format.
    if (hsize && hist_check(fd)) {
        sh_close(fd);
        hsize = 0;
        if (unlink(cp) >= 0) goto retry;
        fd = -1;
    }

    // Don't allow root a history_file in /tmp.
    if (fd < 0 && shgd->userid) {
        fname = ast_temp_file(NULL, NULL, &fd, O_APPEND | O_CLOEXEC);
        if (!fname) return 0;
    }

    if (fd < 0) return 0;
    // Set the file to close-on-exec.
    (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
    cp = nv_getval(HISTSIZE);
    if (cp) {
        maxlines = (unsigned)strtol(cp, NULL, 10);
    } else {
        maxlines = HIST_DFLT;
    }
    for (histmask = 16; histmask <= maxlines; histmask <<= 1) {
        ;  // empty loop
    }
    histmask -= 1;
    hp = calloc(1, sizeof(History_t) + histmask * sizeof(off_t));
    if (!hp) {
        sh_close(fd);
        return 0;
    }

    shgd->hist_ptr = hist_ptr = hp;
    hp->histshell = shp;
    hp->histsize = maxlines;
    hp->histmask = histmask;
    hp->histfp = sfnew(NULL, NULL, HIST_BSIZE, fd, SF_READ | SF_WRITE | SF_APPENDWR | SF_SHARE);
    hp->histind = 1;
    hp->histcmds[1] = 2;
    hp->histcnt = 2;
    hp->histname = strdup(histname);
    hp->histdisc = hist_disc;
    if (hsize == 0) {
        // Put special characters at front of file.
        sfwrite(hp->histfp, (char *)hist_stamp, 2);
        sfsync(hp->histfp);
    } else {
        // Initialize history list.
        int first, last;
        off_t mark, size = (HIST_MAX / 4) + maxlines * HIST_LINE;
        hp->histind = first = hist_nearend(hp, hp->histfp, hsize - size);
        histinit = 1;
        hist_eof(hp);  // this sets histind to last command
        if ((hist_start = (last = (int)hp->histind) - maxlines) <= 0) hist_start = 1;
        mark = hp->histmarker;
        while (first > hist_start) {
            size += size;
            first = hist_nearend(hp, hp->histfp, hsize - size);
            hp->histind = first;
        }
        histinit = hist_start;
        hist_eof(hp);
        if (!histinit) {
            sfseek(hp->histfp, hp->histcnt = hsize, SEEK_SET);
            hp->histind = last;
            hp->histmarker = mark;
        }
        histinit = 0;
    }
    if (fname) {
        unlink(fname);
        free(fname);
    }
    if (hist_clean(fd) && hist_start > 1 && hsize > HIST_MAX) {
#ifdef DEBUG
        sfprintf(sfstderr, "%d: hist_trim hsize=%d\n", getpid(), hsize);
        sfsync(sfstderr);
#endif  // DEBUG
        hp = hist_trim(hp, (int)hp->histind - maxlines);
    }
    sfdisc(hp->histfp, &hp->histdisc);
    STORE_VT((HISTCUR)->nvalue, i32p, &hp->histind);
    sh_timeradd(1000L * (HIST_RECENT - 30), 1, hist_touch, hp->histname);
    hp->auditfp = NULL;

    char buff[SF_BUFSIZE];
    if (!sh_isstate(shp, SH_INTERACTIVE)) return 1;
    hp->auditmask = sh_checkaudit(hp, AUDIT_FILE, buff, sizeof(buff));
    if (!hp->auditmask) return 1;

    if ((fd = sh_open(buff, O_BINARY | O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC,
                      S_IRUSR | S_IWUSR)) >= 0 &&
        fd < 10) {
        int n;
        if ((n = sh_fcntl(fd, F_DUPFD_CLOEXEC, 10)) >= 0) {
            sh_close(fd);
            fd = n;
        }
    }
    if (fd >= 0) {
        (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
        hp->tty = strdup(isatty(2) ? ttyname(2) : "notty");
        hp->auditfp = sfnew(NULL, NULL, -1, fd, SF_WRITE);
    }

    return 1;
}
Esempio n. 4
0
/*
 * open the history file
 * if HISTNAME is not given and userid==0 then no history file.
 * if login_sh and HISTFILE is longer than HIST_MAX bytes then it is
 * cleaned up.
 * hist_open() returns 1, if history file is open
 */
int  sh_histinit(void *sh_context)
{
	Shell_t *shp = (Shell_t*)sh_context;
	register int fd;
	register History_t *hp;
	register char *histname;
	char *fname=0;
	int histmask, maxlines, hist_start=0;
	register char *cp;
	register off_t hsize = 0;

	if(shgd->hist_ptr=hist_ptr)
		return(1);
	if(!(histname = nv_getval(HISTFILE)))
	{
		int offset = staktell();
		if(cp=nv_getval(HOME))
			stakputs(cp);
		stakputs(hist_fname);
		stakputc(0);
		stakseek(offset);
		histname = stakptr(offset);
	}
#ifdef future
	if(hp=wasopen)
	{
		/* reuse history file if same name */
		wasopen = 0;
		shgd->hist_ptr = hist_ptr = hp;
		if(strcmp(histname,hp->histname)==0)
			return(1);
		else
			hist_free();
	}
#endif
retry:
	cp = path_relative(shp,histname);
	if(!histinit)
		histmode = S_IRUSR|S_IWUSR;
	if((fd=open(cp,O_BINARY|O_APPEND|O_RDWR|O_CREAT,histmode))>=0)
	{
		hsize=lseek(fd,(off_t)0,SEEK_END);
	}
	if((unsigned)fd <=2)
	{
		int n;
		if((n=fcntl(fd,F_DUPFD,10))>=0)
		{
			close(fd);
			fd=n;
		}
	}
	/* make sure that file has history file format */
	if(hsize && hist_check(fd))
	{
		close(fd);
		hsize = 0;
		if(unlink(cp)>=0)
			goto retry;
		fd = -1;
	}
	if(fd < 0)
	{
#if KSHELL
		/* don't allow root a history_file in /tmp */
		if(shgd->userid)
#endif	/* KSHELL */
		{
			if(!(fname = pathtmp(NIL(char*),0,0,NIL(int*))))
				return(0);
			fd = open(fname,O_BINARY|O_APPEND|O_CREAT|O_RDWR,S_IRUSR|S_IWUSR);
		}
	}
	if(fd<0)
		return(0);
	/* set the file to close-on-exec */
	fcntl(fd,F_SETFD,FD_CLOEXEC);
	if(cp=nv_getval(HISTSIZE))
		maxlines = (unsigned)strtol(cp, (char**)0, 10);
	else
		maxlines = HIST_DFLT;
	for(histmask=16;histmask <= maxlines; histmask <<=1 );
	if(!(hp=new_of(History_t,(--histmask)*sizeof(off_t))))
	{
		close(fd);
		return(0);
	}
	shgd->hist_ptr = hist_ptr = hp;
	hp->histshell = (void*)shp;
	hp->histsize = maxlines;
	hp->histmask = histmask;
	hp->histfp= sfnew(NIL(Sfio_t*),hp->histbuff,HIST_BSIZE,fd,SF_READ|SF_WRITE|SF_APPENDWR|SF_SHARE);
	memset((char*)hp->histcmds,0,sizeof(off_t)*(hp->histmask+1));
	hp->histind = 1;
	hp->histcmds[1] = 2;
	hp->histcnt = 2;
	hp->histname = strdup(histname);
	hp->histdisc = hist_disc;
	if(hsize==0)
	{
		/* put special characters at front of file */
		sfwrite(hp->histfp,(char*)hist_stamp,2);
		sfsync(hp->histfp);
	}
	/* initialize history list */
	else
	{
		int first,last;
		off_t mark,size = (HIST_MAX/4)+maxlines*HIST_LINE;
		hp->histind = first = hist_nearend(hp,hp->histfp,hsize-size);
		histinit = 1;
		hist_eof(hp);	 /* this sets histind to last command */
		if((hist_start = (last=(int)hp->histind)-maxlines) <=0)
			hist_start = 1;
		mark = hp->histmarker;
		while(first > hist_start)
		{
			size += size;
			first = hist_nearend(hp,hp->histfp,hsize-size);
			hp->histind = first;
		}
		histinit = hist_start;
		hist_eof(hp);
		if(!histinit)
		{
			sfseek(hp->histfp,hp->histcnt=hsize,SEEK_SET);
			hp->histind = last;
			hp->histmarker = mark;
		}
		histinit = 0;
	}
	if(fname)
	{
		unlink(fname);
		free((void*)fname);
	}
	if(hist_clean(fd) && hist_start>1 && hsize > HIST_MAX)
	{
#ifdef DEBUG
		sfprintf(sfstderr,"%d: hist_trim hsize=%d\n",getpid(),hsize);
		sfsync(sfstderr);
#endif /* DEBUG */
		hp = hist_trim(hp,(int)hp->histind-maxlines);
	}
	sfdisc(hp->histfp,&hp->histdisc);
#if KSHELL
	(HISTCUR)->nvalue.lp = (&hp->histind);
#endif /* KSHELL */
	sh_timeradd(1000L*(HIST_RECENT-30), 1, hist_touch, (void*)hp->histname);
#if SHOPT_ACCTFILE
	if(sh_isstate(SH_INTERACTIVE))
		acctinit(hp);
#endif /* SHOPT_ACCTFILE */
#if SHOPT_AUDIT
	{
		char buff[SF_BUFSIZE];
		hp->auditfp = 0;
		if(sh_isstate(SH_INTERACTIVE) && (hp->auditmask=sh_checkaudit(hp,SHOPT_AUDITFILE, buff, sizeof(buff))))
		{
			if((fd=sh_open(buff,O_BINARY|O_WRONLY|O_APPEND|O_CREAT,S_IRUSR|S_IWUSR))>=0 && fd < 10)
			{
				int n;
				if((n = sh_fcntl(fd,F_DUPFD, 10)) >= 0)
				{
					sh_close(fd);
					fd = n;
				}
			}
			if(fd>=0)
			{
				fcntl(fd,F_SETFD,FD_CLOEXEC);
				hp->tty = strdup(ttyname(2));
				hp->auditfp = sfnew((Sfio_t*)0,NULL,-1,fd,SF_WRITE);
			}
		}
	}
#endif
	return(1);
}