Пример #1
0
Файл: attr.c Проект: AMDmi3/zsh
static int
bin_getattr(char *nam, char **argv, Options ops, UNUSED(int func))
{
    int ret = 0;
    int val_len = 0, attr_len = 0, slen;
    char *value, *file = argv[0], *attr = argv[1], *param = argv[2];
    int symlink = OPT_ISSET(ops, 'h');

    unmetafy(file, &slen);
    unmetafy(attr, NULL);
    val_len = xgetxattr(file, attr, NULL, 0, symlink);
    if (val_len == 0) {
        if (param)
            unsetparam(param);
        return 0;
    }
    if (val_len > 0) {
        value = (char *)zalloc(val_len+1);
        attr_len = xgetxattr(file, attr, value, val_len, symlink);
        if (attr_len > 0 && attr_len <= val_len) {
            value[attr_len] = '\0';
            if (param)
                setsparam(param, metafy(value, attr_len, META_DUP));
            else
                printf("%s\n", value);
        }
        zfree(value, val_len+1);
    }
    if (val_len < 0 || attr_len < 0 || attr_len > val_len)  {
        zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno);
        ret = 1 + ((val_len > 0 && attr_len > val_len) || attr_len < 0);
    }
    return ret;
}
Пример #2
0
static void
setpmmapfile(Param pm, char *value)
{
    int fd = -1, len;
    char *name = ztrdup(pm->nam);
#ifdef USE_MMAP
    caddr_t mmptr;
#else
    FILE *fout;
#endif

    /*
     * First unmetafy the value, and the name since we don't
     * where it's been.
     */
    unmetafy(name, &len);
    unmetafy(value, &len);

    /* Open the file for writing */
#ifdef USE_MMAP
    if (!(pm->flags & PM_READONLY) &&
	(fd = open(name, O_RDWR|O_CREAT|O_NOCTTY, 0666)) >= 0 &&
	(mmptr = (caddr_t)mmap((caddr_t)0, len, PROT_READ | PROT_WRITE,
			       MMAP_ARGS, fd, (off_t)0)) != (caddr_t)-1) {
	/*
	 * First we need to make sure the file is long enough for
	 * when we msync.  On AIX, at least, we just get zeroes otherwise.
	 */
	ftruncate(fd, len);
	memcpy(mmptr, value, len);
#ifndef MS_SYNC
#define MS_SYNC 0
#endif
	msync(mmptr, len, MS_SYNC);
	/*
	 * Then we need to truncate again, since mmap() always maps complete
	 * pages.  Honestly, I tried it without, and you need both.
	 */
	ftruncate(fd, len);
	munmap(mmptr, len);
    }
#else /* don't USE_MMAP */
    /* can't be bothered to do anything too clever here */
    if ((fout = fopen(name, "w"))) {
	while (len--)
	    putc(*value++, fout);
	fclose(fout);
    }
#endif /* USE_MMAP */
    if (fd >= 0)
	close(fd);
    free(name);
    free(value);
}
Пример #3
0
static int
ptywrite(Ptycmd cmd, char **args, int nonl)
{
    if (*args) {
	char sp = ' ', *tmp;
	int len;

	while (*args) {
	    unmetafy((tmp = dupstring(*args)), &len);
	    if (ptywritestr(cmd, tmp, len) ||
		(*++args && ptywritestr(cmd, &sp, 1)))
		return 1;
	}
	if (!nonl) {
	    sp = '\n';
	    if (ptywritestr(cmd, &sp, 1))
		return 1;
	}
    } else {
	int n;
	char buf[BUFSIZ];

	while ((n = read(0, buf, BUFSIZ)) > 0)
	    if (ptywritestr(cmd, buf, n))
		return 1;
    }
    return 0;
}
Пример #4
0
Файл: attr.c Проект: Jaharmi/zsh
static int
bin_setattr(char *nam, char **argv, Options ops, UNUSED(int func))
{
    int ret = 0, slen, vlen;
    int symlink = OPT_ISSET(ops, 'h');
    char *file = argv[0], *attr = argv[1], *value = argv[2];

    unmetafy(file, &slen);
    unmetafy(attr, NULL);
    unmetafy(value, &vlen);
    if (xsetxattr(file, attr, value, vlen, 0, symlink)) {
        zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno);
        ret = 1;
    }
    return ret;
}
Пример #5
0
static HashNode
getlanginfo(UNUSED(HashTable ht), const char *name)
{
    int len, *elem;
    char *listr, *nameu;
    Param pm = NULL;

    nameu = dupstring(name);
    unmetafy(nameu, &len);

    pm = (Param) hcalloc(sizeof(struct param));
    pm->node.nam = nameu;
    pm->node.flags = PM_READONLY | PM_SCALAR;
    pm->gsu.s = &nullsetscalar_gsu;

    if(name)
	elem = liitem(name);
    else
	elem = NULL;

    if (elem && (listr = nl_langinfo(*elem))) {
	pm->u.str = dupstring(listr);
    }
    else
    {
	/* zwarn("no such lang info: %s", name); */
	pm->u.str = dupstring("");
	pm->node.flags |= PM_UNSET;
    }
    return &pm->node;
}
Пример #6
0
Файл: cap.c Проект: AMDmi3/zsh
static int
bin_cap(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
{
    int ret = 0;
    cap_t caps;
    if(*argv) {
	unmetafy(*argv, NULL);
	caps = cap_from_text(*argv);
	if(!caps) {
	    zwarnnam(nam, "invalid capability string");
	    return 1;
	}
	if(cap_set_proc(caps)) {
	    zwarnnam(nam, "can't change capabilities: %e", errno);
	    ret = 1;
	}
    } else {
	char *result = NULL;
	ssize_t length;
	caps = cap_get_proc();
	if(caps)
	    result = cap_to_text(caps, &length);
	if(!caps || !result) {
	    zwarnnam(nam, "can't get capabilities: %e", errno);
	    ret = 1;
	} else
	    puts(result);
    }
    cap_free(caps);
    return ret;
}
Пример #7
0
Файл: attr.c Проект: Jaharmi/zsh
static int
bin_delattr(char *nam, char **argv, Options ops, UNUSED(int func))
{
    int ret = 0, slen;
    int symlink = OPT_ISSET(ops, 'h');
    char *file = argv[0], **attr = argv;

    unmetafy(file, &slen);
    while (*++attr) {
        unmetafy(*attr, NULL);
        if (xremovexattr(file, *attr, symlink)) {
            zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno);
            ret = 1;
            break;
        }
    }
    return ret;
}
Пример #8
0
void
setline(char const *s)
{
    sizeline(strlen(s));
    strcpy((char *) line, s);
    unmetafy((char *) line, &ll);
    if ((cs = ll) && bindtab == altbindtab)
	cs--;
    clearlist = 1;
}
Пример #9
0
static HashNode
gettermcap(UNUSED(HashTable ht), char *name)
{
    int len, num;
    char *tcstr, buf[2048], *u;
    Param pm = NULL;

    /* This depends on the termcap stuff in init.c */
    if (termflags & TERM_BAD)
	return NULL;
    if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term()))
	return NULL;

    unmetafy(name, &len);

    pm = (Param) hcalloc(sizeof(struct param));
    pm->nam = dupstring(name);
    pm->flags = PM_READONLY;
    u = buf;

    /* logic in the following cascade copied from echotc, above */

    if ((num = tgetnum(name)) != -1) {
	pm->gsu.i = &nullsetinteger_gsu;
	pm->u.val = num;
	pm->flags |= PM_INTEGER;
	return (HashNode) pm;
    }

    pm->gsu.s = &nullsetscalar_gsu;
    switch (ztgetflag(name)) {
    case -1:
	break;
    case 0:
	pm->u.str = dupstring("no");
	pm->flags |= PM_SCALAR;
	return (HashNode) pm;
    default:
	pm->u.str = dupstring("yes");
	pm->flags |= PM_SCALAR;
	return (HashNode) pm;
    }
    if ((tcstr = (char*)tgetstr(name, &u)) != NULL && tcstr != (char *)-1)
    {
	pm->u.str = dupstring(tcstr);
	pm->flags |= PM_SCALAR;
    }
    else
    {
	/* zwarn("no such capability: %s", name, 0); */
	pm->u.str = dupstring("");
	pm->flags |= PM_UNSET;
    }
    return (HashNode) pm;
}
Пример #10
0
Файл: attr.c Проект: Jaharmi/zsh
static int
bin_listattr(char *nam, char **argv, Options ops, UNUSED(int func))
{
    int ret = 0;
    int val_len, list_len = 0, slen;
    char *value, *file = argv[0], *param = argv[1];
    int symlink = OPT_ISSET(ops, 'h');

    unmetafy(file, &slen);
    val_len = xlistxattr(file, NULL, 0, symlink);
    if (val_len == 0) {
        if (param)
            unsetparam(param);
        return 0;
    }
    if (val_len > 0) {
        value = (char *)zalloc(val_len+1);
        list_len = xlistxattr(file, value, val_len, symlink);
        if (list_len > 0 && list_len <= val_len) {
            char *p = value;
            if (param) {
                if (strlen(value) + 1 == list_len)
                    setsparam(param, metafy(value, list_len-1, META_DUP));
                else {
                    int arrlen = 0;
                    char **array = NULL, **arrptr = NULL;

                    while (p < &value[list_len]) {
                        arrlen++;
                        p += strlen(p) + 1;
                    }
                    arrptr = array = (char **)zshcalloc((arrlen+1) * sizeof(char *));
                    p = value;
                    while (p < &value[list_len]) {
                        *arrptr++ = metafy(p, -1, META_DUP);
                        p += strlen(p) + 1;
                    }
                    setaparam(param, array);
                }
            } else while (p < &value[list_len]) {
                printf("%s\n", p);
                p += strlen(p) + 1;
            }
        }
        zfree(value, val_len+1);
    }
    if (val_len < 0 || list_len < 0 || list_len > val_len) {
        zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno);
        ret = 1 + (list_len > val_len || list_len < 0);
    }
    return ret;
}
Пример #11
0
static void
unsetpmmapfile(Param pm, UNUSED(int exp))
{
    /* Unlink the file given by pm->nam */
    char *fname = ztrdup(pm->nam);
    int dummy;
    unmetafy(fname, &dummy);

    if (!(pm->flags & PM_READONLY))
	unlink(fname);

    free(fname);
}
Пример #12
0
Файл: cap.c Проект: AMDmi3/zsh
static int
bin_setcap(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
{
    cap_t caps;
    int ret = 0;

    unmetafy(*argv, NULL);
    caps = cap_from_text(*argv++);
    if(!caps) {
	zwarnnam(nam, "invalid capability string");
	return 1;
    }

    do {
	if(cap_set_file(unmetafy(dupstring(*argv), NULL), caps)) {
	    zwarnnam(nam, "%s: %e", *argv, errno);
	    ret = 1;
	}
    } while(*++argv);
    cap_free(caps);
    return ret;
}
Пример #13
0
static HashNode
getgdbmnode(HashTable ht, const char *name)
{
    int len;
    char *nameu;
    Param pm = NULL;

    nameu = dupstring(name);
    unmetafy(nameu, &len);

    pm = (Param) hcalloc(sizeof(struct param));
    pm->node.nam = nameu;
    pm->node.flags = PM_SCALAR;
    pm->gsu.s = &gdbm_gsu;
    pm->u.hash = ht;

    return &pm->node;
}
Пример #14
0
void
getline(void)
{
    char *s = (char *)getlinknode(bufstack);

    if (!s)
	feep();
    else {
	int cc;

	unmetafy(s, &cc);
	spaceinline(cc);
	memcpy((char *)line + cs, s, cc);
	cs += cc;
	free(s);
	clearlist = 1;
    }
}
Пример #15
0
static char *
get_contents(char *fname)
{
    int fd;
#ifdef USE_MMAP
    caddr_t mmptr;
    struct stat sbuf;
#endif
    char *val;
    unmetafy(fname = ztrdup(fname), &fd);

#ifdef USE_MMAP
    if ((fd = open(fname, O_RDONLY | O_NOCTTY)) < 0 ||
	fstat(fd, &sbuf) ||
	(mmptr = (caddr_t)mmap((caddr_t)0, sbuf.st_size, PROT_READ,
			       MMAP_ARGS, fd, (off_t)0)) == (caddr_t)-1) {
	if (fd >= 0)
	    close(fd);
	free(fname);
	return NULL;
    }

    /*
     * Sadly, we need to copy the thing even if metafying doesn't
     * change it.  We just don't know when we might get a chance to
     * munmap it, otherwise.
     */
    val = metafy((char *)mmptr, sbuf.st_size, META_HEAPDUP);

    munmap(mmptr, sbuf.st_size);
    close(fd);
#else /* don't USE_MMAP */
    val = NULL;
    if ((fd = open(fname, O_RDONLY | O_NOCTTY)) >= 0) {
	LinkList ll;

	if ((ll = readoutput(fd, 1)))
	    val = peekfirst(ll);
    }
#endif /* USE_MMAP */
    free(fname);
    return val;
}
Пример #16
0
static int
bin_syswrite(char *nam, char **args, Options ops, UNUSED(int func))
{
    int outfd = 1, len, count, totcount;
    char *countvar = NULL;

    /* -o: output file descriptor if not stdout */
    if (OPT_ISSET(ops, 'o')) {
	outfd = getposint(OPT_ARG(ops, 'o'), nam);
	if (outfd < 0)
	    return 1;
    }

    /* -c: variable in which to store count of bytes written */
    if (OPT_ISSET(ops, 'c')) {
	countvar = OPT_ARG(ops, 'c');
	if (!isident(countvar)) {
	    zwarnnam(nam, "not an identifier: %s", countvar);
	    return 1;
	}
    }

    totcount = 0;
    unmetafy(*args, &len);
    while (len) {
	while ((count = write(outfd, *args, len)) < 0) {
	    if (errno != EINTR || errflag || retflag || breaks || contflag)
	    {
		if (countvar)
		    setiparam(countvar, totcount);
		return 2;
	    }
	}
	*args += count;
	totcount += count;
	len -= count;
    }
    if (countvar)
	setiparam(countvar, totcount);

    return 0;
}
Пример #17
0
static HashNode
getterminfo(UNUSED(HashTable ht), const char *name)
{
    int len, num;
    char *tistr, *nameu;
    Param pm = NULL;

    /* This depends on the termcap stuff in init.c */
    if (termflags & TERM_BAD)
	return NULL;
    if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term()))
	return NULL;

    nameu = dupstring(name);
    unmetafy(nameu, &len);

    pm = (Param) hcalloc(sizeof(struct param));
    pm->node.nam = nameu;
    pm->node.flags = PM_READONLY;

    if (((num = tigetnum(nameu)) != -1) && (num != -2)) {
	pm->u.val = num;
	pm->node.flags |= PM_INTEGER;
	pm->gsu.i = &nullsetinteger_gsu;
    } else if ((num = tigetflag(nameu)) != -1) {
	pm->u.str = num ? dupstring("yes") : dupstring("no");
	pm->node.flags |= PM_SCALAR;
	pm->gsu.s = &nullsetscalar_gsu;
    } else if ((tistr = (char *)tigetstr(nameu)) != NULL && tistr != (char *)-1) {
	pm->u.str = dupstring(tistr);
	pm->node.flags |= PM_SCALAR;
	pm->gsu.s = &nullsetscalar_gsu;
    } else {
	/* zwarn("no such capability: %s", name); */
	pm->u.str = dupstring("");
	pm->node.flags |= PM_UNSET;
	pm->gsu.s = &nullsetscalar_gsu;
    }
    return &pm->node;
}
Пример #18
0
Файл: cap.c Проект: AMDmi3/zsh
static int
bin_getcap(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
{
    int ret = 0;

    do {
	char *result = NULL;
	ssize_t length;
	cap_t caps;

	caps = cap_get_file(unmetafy(dupstring(*argv), NULL));
	if(caps)
	    result = cap_to_text(caps, &length);
	if (!caps || !result) {
	    zwarnnam(nam, "%s: %e", *argv, errno);
	    ret = 1;
	} else
	    printf("%s %s\n", *argv, result);
	cap_free(caps);
    } while(*++argv);
    return ret;
}
Пример #19
0
Файл: pcre.c Проект: Lujaw/zsh
static int
bin_pcre_compile(char *nam, char **args, Options ops, UNUSED(int func))
{
    int pcre_opts = 0, pcre_errptr;
    const char *pcre_error;
    char *target;
    
    if(OPT_ISSET(ops,'a')) pcre_opts |= PCRE_ANCHORED;
    if(OPT_ISSET(ops,'i')) pcre_opts |= PCRE_CASELESS;
    if(OPT_ISSET(ops,'m')) pcre_opts |= PCRE_MULTILINE;
    if(OPT_ISSET(ops,'x')) pcre_opts |= PCRE_EXTENDED;
    if(OPT_ISSET(ops,'s')) pcre_opts |= PCRE_DOTALL;
    
    if (zpcre_utf8_enabled())
	pcre_opts |= PCRE_UTF8;

    pcre_hints = NULL;  /* Is this necessary? */
    
    if (pcre_pattern)
	pcre_free(pcre_pattern);

    target = ztrdup(*args);
    unmetafy(target, NULL);

    pcre_pattern = pcre_compile(target, pcre_opts, &pcre_error, &pcre_errptr, NULL);
    
    free(target);

    if (pcre_pattern == NULL)
    {
	zwarnnam(nam, "error in regex: %s", pcre_error);
	return 1;
    }
    
    return 0;
}
Пример #20
0
Файл: pcre.c Проект: Lujaw/zsh
static int
cond_pcre_match(char **a, int id)
{
    pcre *pcre_pat;
    const char *pcre_err;
    char *lhstr, *rhre, *lhstr_plain, *rhre_plain, *avar=NULL;
    int r = 0, pcre_opts = 0, pcre_errptr, capcnt, *ov, ovsize;
    int return_value = 0;

    if (zpcre_utf8_enabled())
	pcre_opts |= PCRE_UTF8;

    lhstr = cond_str(a,0,0);
    rhre = cond_str(a,1,0);
    lhstr_plain = ztrdup(lhstr);
    rhre_plain = ztrdup(rhre);
    unmetafy(lhstr_plain, NULL);
    unmetafy(rhre_plain, NULL);
    pcre_pat = NULL;
    ov = NULL;
    ovsize = 0;

    if (isset(BASHREMATCH))
	avar="BASH_REMATCH";

    switch(id) {
	 case CPCRE_PLAIN:
		pcre_pat = pcre_compile(rhre_plain, pcre_opts, &pcre_err, &pcre_errptr, NULL);
		if (pcre_pat == NULL) {
		    zwarn("failed to compile regexp /%s/: %s", rhre, pcre_err);
		    break;
		}
                pcre_fullinfo(pcre_pat, NULL, PCRE_INFO_CAPTURECOUNT, &capcnt);
    		ovsize = (capcnt+1)*3;
		ov = zalloc(ovsize*sizeof(int));
    		r = pcre_exec(pcre_pat, NULL, lhstr_plain, strlen(lhstr_plain), 0, 0, ov, ovsize);
		/* r < 0 => error; r==0 match but not enough size in ov
		 * r > 0 => (r-1) substrings found; r==1 => no substrings
		 */
    		if (r==0) {
		    zwarn("reportable zsh problem: pcre_exec() returned 0");
		    return_value = 1;
		    break;
		}
	        else if (r==PCRE_ERROR_NOMATCH) {
		    return_value = 0; /* no match */
		    break;
		}
		else if (r<0) {
		    zwarn("pcre_exec() error [%d]", r);
		    break;
		}
                else if (r>0) {
		    zpcre_get_substrings(lhstr_plain, ov, r, NULL, avar, 0,
					 isset(BASHREMATCH),
					 !isset(BASHREMATCH));
		    return_value = 1;
		    break;
		}
		break;
    }

    if (lhstr_plain)
	free(lhstr_plain);
    if(rhre_plain)
	free(rhre_plain);
    if (pcre_pat)
	pcre_free(pcre_pat);
    if (ov)
	zfree(ov, ovsize*sizeof(int));

    return return_value;
}
Пример #21
0
Файл: pcre.c Проект: Lujaw/zsh
static int
bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func))
{
    int ret, capcount, *ovec, ovecsize, c;
    char *matched_portion = NULL;
    char *plaintext = NULL;
    char *receptacle = NULL;
    int return_value = 1;
    /* The subject length and offset start are both int values in pcre_exec */
    int subject_len;
    int offset_start = 0;
    int want_offset_pair = 0;

    if (pcre_pattern == NULL) {
	zwarnnam(nam, "no pattern has been compiled");
	return 1;
    }
    
    if(OPT_HASARG(ops,c='a')) {
	receptacle = OPT_ARG(ops,c);
    }
    if(OPT_HASARG(ops,c='v')) {
	matched_portion = OPT_ARG(ops,c);
    }
    if(OPT_HASARG(ops,c='n')) { /* The offset position to start the search, in bytes. */
	offset_start = getposint(OPT_ARG(ops,c), nam);
    }
    /* For the entire match, 'Return' the offset byte positions instead of the matched string */
    if(OPT_ISSET(ops,'b')) want_offset_pair = 1; 

    if(!*args) {
	zwarnnam(nam, "not enough arguments");
    }
    
    if ((ret = pcre_fullinfo(pcre_pattern, pcre_hints, PCRE_INFO_CAPTURECOUNT, &capcount)))
    {
	zwarnnam(nam, "error %d in fullinfo", ret);
	return 1;
    }

    ovecsize = (capcount+1)*3;
    ovec = zalloc(ovecsize*sizeof(int));

    plaintext = ztrdup(*args);
    unmetafy(plaintext, NULL);
    subject_len = (int)strlen(plaintext);

    if (offset_start < 0 || offset_start >= subject_len)
	ret = PCRE_ERROR_NOMATCH;
    else
	ret = pcre_exec(pcre_pattern, pcre_hints, plaintext, subject_len, offset_start, 0, ovec, ovecsize);

    if (ret==0) return_value = 0;
    else if (ret==PCRE_ERROR_NOMATCH) /* no match */;
    else if (ret>0) {
	zpcre_get_substrings(plaintext, ovec, ret, matched_portion, receptacle,
			     want_offset_pair, 0, 0);
	return_value = 0;
    }
    else {
	zwarnnam(nam, "error in pcre_exec [%d]", ret);
    }
    
    if (ovec)
	zfree(ovec, ovecsize*sizeof(int));

    return return_value;
}
Пример #22
0
Файл: input.c Проект: Osse/zsh
static int
inputline(void)
{
    char *ingetcline, **ingetcpmptl = NULL, **ingetcpmptr = NULL;
    int context = ZLCON_LINE_START;

    /* If reading code interactively, work out the prompts. */
    if (interact && isset(SHINSTDIN)) {
	if (!isfirstln) {
	    ingetcpmptl = &prompt2;
	    if (rprompt2)
		ingetcpmptr = &rprompt2;
	    context = ZLCON_LINE_CONT;
	}
	else {
	    ingetcpmptl = &prompt;
	    if (rprompt)
		ingetcpmptr = &rprompt;
	}
    }
    if (!(interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))) {
	/*
	 * If not using zle, read the line straight from the input file.
	 * Possibly we don't get the whole line at once:  in that case,
	 * we get another chunk with the next call to inputline().
	 */

	if (interact && isset(SHINSTDIN)) {
	    /*
	     * We may still be interactive (e.g. running under emacs),
	     * so output a prompt if necessary.  We don't know enough
	     * about the input device to be able to handle an rprompt,
	     * though.
	     */
	    char *pptbuf;
	    int pptlen;
	    pptbuf = unmetafy(promptexpand(ingetcpmptl ? *ingetcpmptl : NULL,
					   0, NULL, NULL, NULL), &pptlen);
	    write_loop(2, pptbuf, pptlen);
	    free(pptbuf);
	}
	ingetcline = shingetline();
    } else {
	/*
	 * Since we may have to read multiple lines before getting
	 * a complete piece of input, we tell zle not to restore the
	 * original tty settings after reading each chunk.  Instead,
	 * this is done when the history mechanism for the current input
	 * terminates, which is not until we have the whole input.
	 * This is supposed to minimise problems on systems that clobber
	 * typeahead when the terminal settings are altered.
	 *                     pws 1998/03/12
	 */
	int flags = ZLRF_HISTORY|ZLRF_NOSETTY;
	if (isset(IGNOREEOF))
	    flags |= ZLRF_IGNOREEOF;
	ingetcline = zleentry(ZLE_CMD_READ, ingetcpmptl, ingetcpmptr,
			      flags, context);
	histdone |= HISTFLAG_SETTY;
    }
    if (!ingetcline) {
	return lexstop = 1;
    }
    if (errflag) {
	free(ingetcline);
	return lexstop = errflag = 1;
    }
    if (isset(VERBOSE)) {
	/* Output the whole line read so far. */
	zputs(ingetcline, stderr);
	fflush(stderr);
    }
    if (keyboardhackchar && *ingetcline &&
	ingetcline[strlen(ingetcline) - 1] == '\n' &&
	interact && isset(SHINSTDIN) &&
	SHTTY != -1 && ingetcline[1])
    {
	char *stripptr = ingetcline + strlen(ingetcline) - 2;
	if (*stripptr == keyboardhackchar) {
	    /* Junk an unwanted character at the end of the line.
	       (key too close to return key) */
	    int ct = 1;  /* force odd */
	    char *ptr;

	    if (keyboardhackchar == '\'' || keyboardhackchar == '"' ||
		keyboardhackchar == '`') {
		/*
		 * for the chars above, also require an odd count before
		 * junking
		 */
		for (ct = 0, ptr = ingetcline; *ptr; ptr++)
		    if (*ptr == keyboardhackchar)
			ct++;
	    }
	    if (ct & 1) {
		stripptr[0] = '\n';
		stripptr[1] = '\0';
	    }
	}
    }
    isfirstch = 1;
    /* Put this into the input channel. */
    inputsetline(ingetcline, INP_FREE);

    return 0;
}
Пример #23
0
char *
zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
{
    char *s, **bracket;
    int old_errno = errno;
    int tmout = getiparam("TMOUT");

#if defined(HAVE_POLL) || defined(HAVE_SELECT)
    /* may not be set, but that's OK since getiparam() returns 0 == off */
    baud = getiparam("BAUD");
    costmult = (baud) ? 3840000L / baud : 0;
#endif

    /* ZLE doesn't currently work recursively.  This is needed in case a *
     * select loop is used in a function called from ZLE.  vared handles *
     * this differently itself.                                          */
    if(zleactive) {
	char *pptbuf;
	int pptlen;

	pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL,
				       &pmpt_attr),
			  &pptlen);
	write_loop(2, pptbuf, pptlen);
	free(pptbuf);
	return shingetline();
    }
    /*
     * The current status is what we need if we are going
     * to display a prompt.  We'll remember it here for
     * use further in.
     */
    pre_zle_status = lastval;

    keytimeout = (time_t)getiparam("KEYTIMEOUT");
    if (!shout) {
	if (SHTTY != -1)
	    init_shout();

	if (!shout)
	    return NULL;
	/* We could be smarter and default to a system read. */

	/* If we just got a new shout, make sure the terminal is set up. */
	if (termflags & TERM_UNKNOWN)
	    init_term();
    }

    fflush(shout);
    fflush(stderr);
    intr();
    insmode = unset(OVERSTRIKE);
    eofsent = 0;
    resetneeded = 0;
    fetchttyinfo = 0;
    trashedzle = 0;
    raw_lp = lp;
    lpromptbuf = promptexpand(lp ? *lp : NULL, 1, NULL, NULL, &pmpt_attr);
    raw_rp = rp;
    rpmpt_attr = pmpt_attr;
    rpromptbuf = promptexpand(rp ? *rp : NULL, 1, NULL, NULL, &rpmpt_attr);
    free_prepostdisplay();

    zlereadflags = flags;
    zlecontext = context;
    histline = curhist;
    vistartchange = -1;
    zleline = (ZLE_STRING_T)zalloc(((linesz = 256) + 2) * ZLE_CHAR_SIZE);
    *zleline = ZWC('\0');
    virangeflag = lastcmd = done = zlecs = zlell = mark = 0;
    vichgflag = 0;
    viinsbegin = 0;
    statusline = NULL;
    selectkeymap("main", 1);
    initundo();
    fixsuffix();
    if ((s = getlinknode(bufstack))) {
	setline(s, ZSL_TOEND);
	zsfree(s);
	if (stackcs != -1) {
	    zlecs = stackcs;
	    stackcs = -1;
	    if (zlecs > zlell)
		zlecs = zlell;
	    CCLEFT();
	}
	if (stackhist != -1) {
	    histline = stackhist;
	    stackhist = -1;
	}
	handleundo();
    }
    /*
     * If main is linked to the viins keymap, we need to register
     * explicitly that we're now in vi insert mode as there's
     * no user operation to indicate this.
     */
    if (openkeymap("main") == openkeymap("viins"))
	viinsert_init();
    selectlocalmap(NULL);
    if (isset(PROMPTCR))
	putc('\r', shout);
    if (tmout)
	alarm(tmout);

    /*
     * On some windowing systems we may enter this function before the
     * terminal is fully opened and sized, resulting in an infinite
     * series of SIGWINCH when the handler prints the prompt before we
     * have done so here.  Therefore, hold any such signal until the
     * first full refresh has completed.  The important bit is that the
     * handler must not see zleactive = 1 until ZLE really is active.
     * See the end of adjustwinsize() in Src/utils.c
     */
    queue_signals();

    zleactive = 1;
    resetneeded = 1;
    /*
     * Start of the main zle read.
     * Fully reset error conditions, including user interrupt.
     */
    errflag = retflag = 0;
    lastcol = -1;
    initmodifier(&zmod);
    prefixflag = 0;

    zrefresh();

    unqueue_signals();	/* Should now be safe to acknowledge SIGWINCH */

    zlecallhook(init, NULL);

    if ((bracket = getaparam("zle_bracketed_paste")) && arrlen(bracket) == 2)
	fputs(*bracket, shout);

    zrefresh();

    zlecore();

    if (errflag)
	setsparam((zlecontext == ZLCON_VARED) ?
		  "ZLE_VARED_ABORTED" :
		  "ZLE_LINE_ABORTED", zlegetline(NULL, NULL));

    if ((bracket = getaparam("zle_bracketed_paste")) && arrlen(bracket) == 2)
	fputs(bracket[1], shout);

    if (done && !exit_pending && !errflag)
	zlecallhook(finish, NULL);

    statusline = NULL;
    invalidatelist();
    trashzle();
    free(lpromptbuf);
    free(rpromptbuf);
    zleactive = zlereadflags = lastlistlen = zlecontext = 0;
    alarm(0);

    freeundo();
    if (eofsent || errflag || exit_pending) {
	s = NULL;
    } else {
	zleline[zlell++] = ZWC('\n');
	s = zlegetline(NULL, NULL);
    }
    free(zleline);
    zleline = NULL;
    forget_edits();
    errno = old_errno;
    /* highlight no longer valid */
    set_region_highlight(NULL, NULL);
    return s;
}
Пример #24
0
mod_export ZLE_STRING_T
stringaszleline(char *instr, int incs, int *outll, int *outsz, int *outcs)
{
    ZLE_STRING_T outstr;
    int ll, sz, sub;
    struct region_highlight *rhp;
#ifdef MULTIBYTE_SUPPORT
    mbstate_t mbs;
#endif

    if (outcs) {
	/*
	 * Take account of Meta characters in the input string
	 * before we unmetafy it.  This does not yet take account
	 * of multibyte characters.  If there are none, this
	 * is all the processing required to calculate outcs.
	 */
	char *inptr = instr, *cspos = instr + incs;
	if (region_highlights && outcs == &zlecs) {
	    for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
		 rhp < region_highlights + n_region_highlights;
		 rhp++) {
		rhp->start = rhp->start_meta;
		rhp->end = rhp->end_meta;
	    }
	}
	while (*inptr) {
	    if (*inptr == Meta) {
		if (inptr < cspos) {
		    incs--;
		}
		if (region_highlights && outcs == &zlecs) {
		    for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
			 rhp < region_highlights + n_region_highlights;
			 rhp++) {
			if (rhp->flags & ZRH_PREDISPLAY)
			    sub = predisplaylen;
			else
			    sub = 0;
			if (inptr - instr < rhp->start - sub) {
			    rhp->start_meta--;
			}
			if (inptr - instr < rhp->end - sub) {
			    rhp->end_meta--;
			}
		    }
		}
		inptr++;
	    }
	    inptr++;
	}
    }
    unmetafy(instr, &ll);

    /*
     * ll is the maximum number of characters there can be in
     * the output string; the closer to ASCII the string, the
     * better the guess.  For the 2 see above.
     */
    sz = (ll + 2) * ZLE_CHAR_SIZE;
    if (outsz)
	*outsz = ll;
    outstr = (ZLE_STRING_T)zalloc(sz);

#ifdef MULTIBYTE_SUPPORT
    if (ll) {
	char *inptr = instr;
	wchar_t *outptr = outstr;

	/* Reset shift state to input complete string */
	memset(&mbs, '\0', sizeof mbs);

	while (ll > 0) {
	    size_t cnt = mbrtowc(outptr, inptr, ll, &mbs);

#ifdef __STDC_ISO_10646__
	    if (cnt == MB_INCOMPLETE || cnt == MB_INVALID) {
		/* Use private encoding for invalid single byte */
		*outptr = ZSH_CHAR_TO_INVALID_WCHAR(*inptr);
		cnt = 1;
	    }
#else
	    /*
	     * At this point we don't handle either incomplete (-2) or
	     * invalid (-1) multibyte sequences.  Use the current length
	     * and return.
	     */
	    if (cnt == MB_INCOMPLETE || cnt == MB_INVALID)
		break;
#endif

	    if (cnt == 0) {
		/* Converting '\0' returns 0, but a '\0' is a real
		 * character for us, so we should consume 1 byte
		 * (certainly true for Unicode and unlikely to be false
		 * in any non-pathological multibyte representation). */
		cnt = 1;
	    } else if (cnt > (size_t)ll) {
		/*
		 * Some multibyte implementations return the
		 * full length of a previous incomplete character
		 * instead of the remaining length.
		 * This is paranoia: it only applies if we start
		 * midway through a multibyte character, which
		 * presumably can't happen.
		 */
		cnt = ll;
	    }

	    if (outcs) {
		int offs = inptr - instr;
		if (offs <= incs && incs < offs + (int)cnt)
		    *outcs = outptr - outstr;
		if (region_highlights && outcs == &zlecs) {
		    for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
			 rhp < region_highlights + n_region_highlights;
			 rhp++) {
			if (rhp->flags & ZRH_PREDISPLAY)
			    sub = predisplaylen;
			else
			    sub = 0;
			if (offs <= rhp->start_meta - sub &&
			    rhp->start_meta - sub < offs + (int)cnt) {
			    rhp->start = outptr - outstr + sub;
			}
			if (offs <= rhp->end_meta - sub &&
			    rhp->end_meta - sub < offs + (int)cnt) {
			    rhp->end = outptr - outstr + sub;
			}
		    }
		}
	    }

	    inptr += cnt;
	    outptr++;
	    ll -= cnt;
	}
	if (outcs && inptr <= instr + incs)
	    *outcs = outptr - outstr;
	*outll = outptr - outstr;
    } else {
	*outll = 0;
	if (outcs)
	    *outcs = 0;
    }
#else
    memcpy(outstr, instr, ll);
    *outll = ll;
    if (outcs)
	*outcs = incs;
    if (region_highlights && outcs == &zlecs) {
	for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
	     rhp < region_highlights + n_region_highlights;
	     rhp++) {
	    rhp->start = rhp->start_meta;
	    rhp->end = rhp->end_meta;
	}
    }
#endif

    return outstr;
}
Пример #25
0
mod_export void
showmsg(char const *msg)
{
    char const *p;
    int up = 0, cc = 0;
    ZLE_CHAR_T c;
#ifdef MULTIBYTE_SUPPORT
    char *umsg;
    int ulen, eol = 0;
    size_t width;
    mbstate_t mbs;
#endif

    trashzle();
    clearflag = isset(USEZLE) && !termflags && isset(ALWAYSLASTPROMPT);

#ifdef MULTIBYTE_SUPPORT
    umsg = ztrdup(msg);
    p = unmetafy(umsg, &ulen);
    memset(&mbs, 0, sizeof mbs);

    mb_metacharinit();
    while (ulen > 0) {
	char const *n;
	if (*p == '\n') {
	    ulen--;
	    p++;

	    putc('\n', shout);
	    up += 1 + cc / zterm_columns;
	    cc = 0;
	} else {
	    /*
	     * Extract the next wide character from the multibyte string.
	     */
	    size_t cnt = eol ? MB_INVALID : mbrtowc(&c, p, ulen, &mbs);

	    switch (cnt) {
	    case MB_INCOMPLETE:
		eol = 1;
		/* FALL THROUGH */
	    case MB_INVALID:
		/*
		 * This really shouldn't be happening here, but...
		 * Treat it as a single byte character; it may get
		 * prettified.
		 */
		memset(&mbs, 0, sizeof mbs);
		n = nicechar(*p);
		cnt = 1;
		width = strlen(n);
		break;
	    case 0:
		cnt = 1;
		/* FALL THROUGH */
	    default:
		/*
		 * Paranoia: only needed if we start in the middle
		 * of a multibyte string and only in some implementations.
		 */
		if (cnt > (size_t)ulen)
		    cnt = ulen;
		n = wcs_nicechar(c, &width, NULL);
		break;
	    }
	    ulen -= cnt;
	    p += cnt;

	    zputs(n, shout);
	    cc += width;
	}
    }

    free(umsg);
#else
    for(p = msg; (c = *p); p++) {
	if(c == Meta)
	    c = *++p ^ 32;
	if(c == '\n') {
	    putc('\n', shout);
	    up += 1 + cc / zterm_columns;
	    cc = 0;
	} else {
	    char const *n = nicechar(c);
	    zputs(n, shout);
	    cc += strlen(n);
	}
    }
#endif
    up += cc / zterm_columns;

    if (clearflag) {
	putc('\r', shout);
	tcmultout(TCUP, TCMULTUP, up + nlnct);
    } else
	putc('\n', shout);
    showinglist = 0;
}
Пример #26
0
void
hashdir(char **dirp)
{
    Cmdnam cn;
    DIR *dir;
    char *fn, *unmetadir, *pathbuf, *pathptr;
    int dirlen;
#if defined(_WIN32) || defined(__CYGWIN__)
    char *exe;
#endif /* _WIN32 || _CYGWIN__ */

    if (isrelative(*dirp))
	return;
    unmetadir = unmeta(*dirp);
    if (!(dir = opendir(unmetadir)))
	return;

    dirlen = strlen(unmetadir);
    pathbuf = (char *)zalloc(dirlen + PATH_MAX + 2);
    sprintf(pathbuf, "%s/", unmetadir);
    pathptr = pathbuf + dirlen + 1;

    while ((fn = zreaddir(dir, 1))) {
	if (!cmdnamtab->getnode(cmdnamtab, fn)) {
	    char *fname = ztrdup(fn);
	    struct stat statbuf;
	    int add = 0, dummylen;

	    unmetafy(fn, &dummylen);
	    if (strlen(fn) > PATH_MAX) {
		/* Too heavy to do all the allocation */
		add = 1;
	    } else {
		strcpy(pathptr, fn);
		/*
		 * This is the same test as for the glob qualifier for
		 * executable plain files.
		 */
		if (unset(HASHEXECUTABLESONLY) ||
		    (access(pathbuf, X_OK) == 0 &&
		     stat(pathbuf, &statbuf) == 0 &&
		     S_ISREG(statbuf.st_mode) && (statbuf.st_mode & S_IXUGO)))
		    add = 1;
	    }
	    if (add) {
		cn = (Cmdnam) zshcalloc(sizeof *cn);
		cn->node.flags = 0;
		cn->u.name = dirp;
		cmdnamtab->addnode(cmdnamtab, fname, cn);
	    } else
		zsfree(fname);
	}
#if defined(_WIN32) || defined(__CYGWIN__)
	/* Hash foo.exe as foo, since when no real foo exists, foo.exe
	   will get executed by DOS automatically.  This quiets
	   spurious corrections when CORRECT or CORRECT_ALL is set. */
	if ((exe = strrchr(fn, '.')) &&
	    (exe[1] == 'E' || exe[1] == 'e') &&
	    (exe[2] == 'X' || exe[2] == 'x') &&
	    (exe[3] == 'E' || exe[3] == 'e') && exe[4] == 0) {
	    *exe = 0;
	    if (!cmdnamtab->getnode(cmdnamtab, fn)) {
		cn = (Cmdnam) zshcalloc(sizeof *cn);
		cn->node.flags = 0;
		cn->u.name = dirp;
		cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn);
	    }
	}
#endif /* _WIN32 || __CYGWIN__ */
    }
    closedir(dir);
    zfree(pathbuf, dirlen + PATH_MAX + 2);
}
Пример #27
0
Файл: files.c Проект: AMDmi3/zsh
static int
recursivecmd(char *nam, int opt_noerr, int opt_recurse, int opt_safe,
    char **args, RecurseFunc dirpre_func, RecurseFunc dirpost_func,
    RecurseFunc leaf_func, void *magic)
{
    int err = 0, len;
    char *rp, *s;
    struct dirsav ds;
    struct recursivecmd reccmd;

    reccmd.nam = nam;
    reccmd.opt_noerr = opt_noerr;
    reccmd.opt_recurse = opt_recurse;
    reccmd.opt_safe = opt_safe;
    reccmd.dirpre_func = dirpre_func;
    reccmd.dirpost_func = dirpost_func;
    reccmd.leaf_func = leaf_func;
    reccmd.magic = magic;
    init_dirsav(&ds);
    if (opt_recurse || opt_safe) {
	if ((ds.dirfd = open(".", O_RDONLY|O_NOCTTY)) < 0 &&
	    zgetdir(&ds) && *ds.dirname != '/')
	    ds.dirfd = open("..", O_RDONLY|O_NOCTTY);
    }
    for(; !errflag && !(err & 2) && *args; args++) {
	rp = ztrdup(*args);
	unmetafy(rp, &len);
	if (opt_safe) {
	    s = strrchr(rp, '/');
	    if (s && !s[1]) {
		while (*s == '/' && s > rp)
		    *s-- = '\0';
		while (*s != '/' && s > rp)
		    s--;
	    }
	    if (s && s[1]) {
		int e;

		*s = '\0';
		e = lchdir(s > rp ? rp : "/", &ds, 1);
		err |= -e;
		if (!e) {
		    struct dirsav d;

		    d.ino = d.dev = 0;
		    d.dirname = NULL;
		    d.dirfd = d.level = -1;
		    err |= recursivecmd_doone(&reccmd, *args, s + 1, &d, 0);
		    zsfree(d.dirname);
		    if (restoredir(&ds))
			err |= 2;
		} else if(!opt_noerr)
		    zwarnnam(nam, "%s: %e", *args, errno);
	    } else
		err |= recursivecmd_doone(&reccmd, *args, rp, &ds, 0);
	} else
	    err |= recursivecmd_doone(&reccmd, *args, rp, &ds, 1);
	zfree(rp, len + 1);
    }
    if ((err & 2) && ds.dirfd >= 0 && restoredir(&ds) && zchdir(pwd)) {
	zsfree(pwd);
	pwd = ztrdup("/");
	if (chdir(pwd) < 0)
	    zwarn("failed to chdir(%s): %e", pwd, errno);
    }
    if (ds.dirfd >= 0)
	close(ds.dirfd);
    zsfree(ds.dirname);
    return !!err;
}
Пример #28
0
Файл: files.c Проект: AMDmi3/zsh
static int
recursivecmd_dorec(struct recursivecmd const *reccmd,
    char *arg, char *rp, struct stat const *sp, struct dirsav *ds, int first)
{
    char *fn;
    DIR *d;
    int err, err1;
    struct dirsav dsav;
    char *files = NULL;
    int fileslen = 0;

    err1 = reccmd->dirpre_func(arg, rp, sp, reccmd->magic);
    if(err1 & 2)
	return 2;

    err = -lchdir(rp, ds, !first);
    if (err) {
	if(!reccmd->opt_noerr)
	    zwarnnam(reccmd->nam, "%s: %e", arg, errno);
	return err;
    }
    err = err1;

    init_dirsav(&dsav);
    d = opendir(".");
    if(!d) {
	if(!reccmd->opt_noerr)
	    zwarnnam(reccmd->nam, "%s: %e", arg, errno);
	err = 1;
    } else {
	int arglen = strlen(arg) + 1;

	while (!errflag && (fn = zreaddir(d, 1))) {
	    int l = strlen(fn) + 1;
	    files = hrealloc(files, fileslen, fileslen + l);
	    strcpy(files + fileslen, fn);
	    fileslen += l;
	}
	closedir(d);
	for (fn = files; !errflag && !(err & 2) && fn < files + fileslen;) {
	    int l = strlen(fn) + 1;
	    VARARR(char, narg, arglen + l);

	    strcpy(narg,arg);
	    narg[arglen-1] = '/';
	    strcpy(narg + arglen, fn);
	    unmetafy(fn, NULL);
	    err |= recursivecmd_doone(reccmd, narg, fn, &dsav, 0);
	    fn += l;
	}
	hrealloc(files, fileslen, 0);
    }
    zsfree(dsav.dirname);
    if (err & 2)
	return 2;
    if (restoredir(ds)) {
	if(!reccmd->opt_noerr)
	    zwarnnam(reccmd->nam, "failed to return to previous directory: %e",
		     errno);
	return 2;
    }
    return err | reccmd->dirpost_func(arg, rp, sp, reccmd->magic);
}
Пример #29
0
static int
inputline(void)
{
    char *ingetcline, **ingetcpmptl = NULL, **ingetcpmptr = NULL;
    int context = ZLCON_LINE_START;

    /* If reading code interactively, work out the prompts. */
    if (interact && isset(SHINSTDIN)) {
	if (!isfirstln) {
	    ingetcpmptl = &prompt2;
	    if (rprompt2)
		ingetcpmptr = &rprompt2;
	    context = ZLCON_LINE_CONT;
	}
	else {
	    ingetcpmptl = &prompt;
	    if (rprompt)
		ingetcpmptr = &rprompt;
	}
    }
    if (!(interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))) {
	/*
	 * If not using zle, read the line straight from the input file.
	 * Possibly we don't get the whole line at once:  in that case,
	 * we get another chunk with the next call to inputline().
	 */

	if (interact && isset(SHINSTDIN)) {
	    /*
	     * We may still be interactive (e.g. running under emacs),
	     * so output a prompt if necessary.  We don't know enough
	     * about the input device to be able to handle an rprompt,
	     * though.
	     */
	    char *pptbuf;
	    int pptlen;
	    pptbuf = unmetafy(promptexpand(ingetcpmptl ? *ingetcpmptl : NULL,
					   0, NULL, NULL, NULL), &pptlen);
	    write_loop(2, pptbuf, pptlen);
	    free(pptbuf);
	}
	ingetcline = shingetline();
    } else {
	/*
	 * Since we may have to read multiple lines before getting
	 * a complete piece of input, we tell zle not to restore the
	 * original tty settings after reading each chunk.  Instead,
	 * this is done when the history mechanism for the current input
	 * terminates, which is not until we have the whole input.
	 * This is supposed to minimise problems on systems that clobber
	 * typeahead when the terminal settings are altered.
	 *                     pws 1998/03/12
	 */
	int flags = ZLRF_HISTORY|ZLRF_NOSETTY;
	if (isset(IGNOREEOF))
	    flags |= ZLRF_IGNOREEOF;
	ingetcline = zleentry(ZLE_CMD_READ, ingetcpmptl, ingetcpmptr,
			      flags, context);
	histdone |= HISTFLAG_SETTY;
    }
    if (!ingetcline) {
	return lexstop = 1;
    }
    if (errflag) {
	free(ingetcline);
	errflag |= ERRFLAG_ERROR;
	return lexstop = 1;
    }
    if (isset(VERBOSE)) {
	/* Output the whole line read so far. */
	zputs(ingetcline, stderr);
	fflush(stderr);
    }
    if (keyboardhackchar && *ingetcline &&
	ingetcline[strlen(ingetcline) - 1] == '\n' &&
	interact && isset(SHINSTDIN) &&
	SHTTY != -1 && ingetcline[1])
    {
	char *stripptr = ingetcline + strlen(ingetcline) - 2;
	if (*stripptr == keyboardhackchar) {
	    /* Junk an unwanted character at the end of the line.
	       (key too close to return key) */
	    int ct = 1;  /* force odd */
	    char *ptr;

	    if (keyboardhackchar == '\'' || keyboardhackchar == '"' ||
		keyboardhackchar == '`') {
		/*
		 * for the chars above, also require an odd count before
		 * junking
		 */
		for (ct = 0, ptr = ingetcline; *ptr; ptr++)
		    if (*ptr == keyboardhackchar)
			ct++;
	    }
	    if (ct & 1) {
		stripptr[0] = '\n';
		stripptr[1] = '\0';
	    }
	}
    }
    isfirstch = 1;
    if ((inbufflags & INP_APPEND) && inbuf) {
	/*
	 * We need new input but need to be able to back up
	 * over the old input, so append this line.
	 * Pushing the line onto the stack doesn't have the right
	 * effect.
	 *
	 * This is quite a simple and inefficient fix, but currently
	 * we only need it when backing up over a multi-line $((...
	 * that turned out to be a command substitution rather than
	 * a math substitution, which is a very special case.
	 * So it's not worth rewriting.
	 */
	char *oinbuf = inbuf;
	int newlen = strlen(ingetcline);
	int oldlen = (int)(inbufptr - inbuf) + inbufleft;
	if (inbufflags & INP_FREE) {
	    inbuf = realloc(inbuf, oldlen + newlen + 1);
	} else {
	    inbuf = zalloc(oldlen + newlen + 1);
	    memcpy(inbuf, oinbuf, oldlen);
	}
	inbufptr += inbuf - oinbuf;
	strcpy(inbuf + oldlen, ingetcline);
	free(ingetcline);
	inbufleft += newlen;
	inbufct += newlen;
	inbufflags |= INP_FREE;
    } else {
	/* Put this into the input channel. */
	inputsetline(ingetcline, INP_FREE);
    }

    return 0;
}
Пример #30
0
void
stradd(char *d)
{
#ifdef MULTIBYTE_SUPPORT
    char *ums, *ups;
    int upslen, eol = 0;
    mbstate_t mbs;

    memset(&mbs, 0, sizeof mbs);
    ums = ztrdup(d);
    ups = unmetafy(ums, &upslen);

    /*
     * We now have a raw string of possibly multibyte characters.
     * Read each character one by one.
     */
    while (upslen > 0) {
	wchar_t cc;
	char *pc;
	size_t cnt = eol ? MB_INVALID : mbrtowc(&cc, ups, upslen, &mbs);

	switch (cnt) {
	case MB_INCOMPLETE:
	    eol = 1;
	    /* FALL THROUGH */
	case MB_INVALID:
	    /* Bad character.  Take the next byte on its own. */
	    pc = nicechar(*ups);
	    cnt = 1;
	    memset(&mbs, 0, sizeof mbs);
	    break;
	case 0:
	    cnt = 1;
	    /* FALL THROUGH */
	default:
	    /* Take full wide character in one go */
	    mb_metacharinit();
	    pc = wcs_nicechar(cc, NULL, NULL);
	    break;
	}
	/* Keep output as metafied string. */
	addbufspc(strlen(pc));

	upslen -= cnt;
	ups += cnt;

	/* Put printed representation into the buffer */
	while (*pc)
	    *bv->bp++ = *pc++;
    }

    free(ums);
#else
    char *ps, *pc;
    addbufspc(niceztrlen(d));
    /* This loop puts the nice representation of the string into the
     * prompt buffer. */
    for (ps = d; *ps; ps++) {
	for (pc = nicechar(*ps == Meta ? *++ps^32 : *ps); *pc; pc++)
	    *bv->bp++ = *pc;
    }
#endif
}