Example #1
0
static int
bin_vared(char *name, char **args, Options ops, UNUSED(int func))
{
    char *s, *t, *ova = varedarg;
    struct value vbuf;
    Value v;
    Param pm = 0;
    int ifl;
    int type = PM_SCALAR, obreaks = breaks, haso = 0, oSHTTY = 0;
    char *p1, *p2, *main_keymapname, *vicmd_keymapname, *init, *finish;
    Keymap main_keymapsave = NULL, vicmd_keymapsave = NULL;
    FILE *oshout = NULL;

    if ((interact && unset(USEZLE)) || !strcmp(term, "emacs")) {
	zwarnnam(name, "ZLE not enabled");
	return 1;
    }
    if (zleactive) {
	zwarnnam(name, "ZLE cannot be used recursively (yet)");
	return 1;
    }

    if (OPT_ISSET(ops,'A'))
    {
	if (OPT_ISSET(ops, 'a'))
	{
	    zwarnnam(name, "specify only one of -a and -A");
	    return 1;
	}
	type = PM_HASHED;
    }
    else if (OPT_ISSET(ops,'a'))
	type = PM_ARRAY;
    p1 = OPT_ARG_SAFE(ops,'p');
    p2 = OPT_ARG_SAFE(ops,'r');
    main_keymapname = OPT_ARG_SAFE(ops,'M');
    vicmd_keymapname = OPT_ARG_SAFE(ops,'m');
    init = OPT_ARG_SAFE(ops,'i');
    finish = OPT_ARG_SAFE(ops,'f');

    if (type != PM_SCALAR && !OPT_ISSET(ops,'c')) {
	zwarnnam(name, "-%s ignored", type == PM_ARRAY ? "a" : "A");
    }

    /* handle non-existent parameter */
    s = args[0];
    queue_signals();
    v = fetchvalue(&vbuf, &s, (!OPT_ISSET(ops,'c') || type == PM_SCALAR),
		   SCANPM_WANTKEYS|SCANPM_WANTVALS|SCANPM_MATCHMANY);
    if (!v && !OPT_ISSET(ops,'c')) {
	unqueue_signals();
	zwarnnam(name, "no such variable: %s", args[0]);
	return 1;
    } else if (v) {
	if (*s) {
	    zwarnnam(name, "not an identifier: `%s'", args[0]);
	    return 1;
	}
	if (v->isarr) {
	    /* Array: check for separators and quote them. */
	    char **arr = getarrvalue(v), **aptr, **tmparr, **tptr;
	    tptr = tmparr = (char **)zhalloc(sizeof(char *)*(arrlen(arr)+1));
	    for (aptr = arr; *aptr; aptr++) {
		int sepcount = 0, clen;
		convchar_t c;
		/*
		 * See if this word contains a separator character
		 * or backslash
		 */
		MB_METACHARINIT();
		for (t = *aptr; *t; ) {
		    if (*t == '\\') {
			t++;
			sepcount++;
		    } else {
			t += MB_METACHARLENCONV(t, &c);
			if (WC_ZISTYPE(c, ISEP))
			    sepcount++;
		    }
		}
		if (sepcount) {
		    /* Yes, so allocate enough space to quote it. */
		    char *newstr, *nptr;
		    newstr = zhalloc(strlen(*aptr)+sepcount+1);
		    /* Go through string quoting separators */
		    MB_METACHARINIT();
		    for (t = *aptr, nptr = newstr; *t; ) {
			if (*t == '\\') {
			    *nptr++ = '\\';
			    *nptr++ = *t++;
			} else {
			    clen = MB_METACHARLENCONV(t, &c);
			    if (WC_ZISTYPE(c, ISEP))
				*nptr++ = '\\';
			    while (clen--)
				*nptr++ = *t++;
			}
		    }
		    *nptr = '\0';
		    /* Stick this into the array of words to join up */
		    *tptr++ = newstr;
		} else
		    *tptr++ = *aptr; /* No, keep original array element */
	    }
	    *tptr = NULL;
	    s = sepjoin(tmparr, NULL, 0);
	} else {
	    s = ztrdup(getstrvalue(v));
	}
	unqueue_signals();
    } else if (*s) {
	unqueue_signals();
	zwarnnam(name, "invalid parameter name: %s", args[0]);
	return 1;
    } else {
	unqueue_signals();
	s = ztrdup(s);
    }

    if (SHTTY == -1 || OPT_ISSET(ops,'t')) {
	/* need to open /dev/tty specially */
	oSHTTY = SHTTY;
	if ((SHTTY = open(OPT_ISSET(ops,'t') ? OPT_ARG(ops,'t') : "/dev/tty",
			  O_RDWR|O_NOCTTY)) == -1) {
	    zwarnnam(name, "can't access terminal");
	    zsfree(s);
	    return 1;
	}
	if (!isatty(SHTTY)) {
	    zwarnnam(name, "%s: not a terminal", OPT_ARG(ops,'t'));
	    close(SHTTY);
	    SHTTY = oSHTTY;
	    zsfree(s);
	    return 1;
	}
	oshout = shout;
	init_shout();

	haso = 1;
    }

    /* edit the parameter value */
    zpushnode(bufstack, s);

    if (main_keymapname &&
	savekeymap(name, "main", main_keymapname, &main_keymapsave))
	main_keymapname = NULL;
    if (vicmd_keymapname &&
	savekeymap(name, "vicmd", vicmd_keymapname, &vicmd_keymapsave))
	vicmd_keymapname = NULL;

    varedarg = *args;
    ifl = isfirstln;
    if (OPT_ISSET(ops,'h'))
	hbegin(2);
    isfirstln = OPT_ISSET(ops,'e');

    t = zleread(&p1, &p2, OPT_ISSET(ops,'h') ? ZLRF_HISTORY : 0, ZLCON_VARED,
		init ? init : "zle-line-init",
		finish ? finish : "zle-line-finish");
    if (OPT_ISSET(ops,'h'))
	hend(NULL);
    isfirstln = ifl;
    varedarg = ova;

    restorekeymap(name, "main", main_keymapname, main_keymapsave);
    restorekeymap(name, "vicmd", vicmd_keymapname, vicmd_keymapsave);

    if (haso) {
	fclose(shout);	/* close(SHTTY) */
	shout = oshout;
	SHTTY = oSHTTY;
    }
    if (!t || errflag) {
	/* error in editing */
	errflag &= ~ERRFLAG_ERROR;
	breaks = obreaks;
	if (t)
	    zsfree(t);
	return 1;
    }
    /* strip off trailing newline, if any */
    if (t[strlen(t) - 1] == '\n')
	t[strlen(t) - 1] = '\0';
    /* final assignment of parameter value */
    if (OPT_ISSET(ops,'c')) {
	unsetparam(args[0]);
	createparam(args[0], type);
    }
    queue_signals();
    pm = (Param) paramtab->getnode(paramtab, args[0]);
    if (pm && (PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED))) {
	char **a;

	/*
	 * Use spacesplit with fourth argument 1: identify quoted separators,
	 * and unquote.  This duplicates the string, so we still need to free.
	 */
	a = spacesplit(t, 1, 0, 1);
	zsfree(t);
	if (PM_TYPE(pm->node.flags) == PM_ARRAY)
	    setaparam(args[0], a);
	else
	    sethparam(args[0], a);
    } else
	setsparam(args[0], t);
    unqueue_signals();
    return 0;
}
Example #2
0
File: zselect.c Project: AMDmi3/zsh
static int
bin_zselect(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
{
#ifdef HAVE_SELECT
    int i, fd, fdsetind = 0, fdmax = 0, fdcount;
    fd_set fdset[3];
    const char fdchar[3] = "rwe";
    struct timeval tv, *tvptr = NULL;
    char *outarray = "reply", **outdata, **outptr;
    char *outhash = NULL;
    LinkList fdlist;

    for (i = 0; i < 3; i++)
	FD_ZERO(fdset+i);

    for (; *args; args++) {
	char *argptr = *args, *endptr;
	zlong tempnum;
	if (*argptr == '-') {
	    for (argptr++; *argptr; argptr++) {
		switch (*argptr) {
		    /*
		     * Array name for reply, if not $reply.
		     * This gets set to e.g. `-r 0 -w 1' if 0 is ready
		     * for reading and 1 is ready for writing.
		     */
		case 'a':
		case 'A':
		    i = *argptr;
		    if (argptr[1])
			argptr++;
		    else if (args[1]) {
			argptr = *++args;
		    } else {
			zwarnnam(nam, "argument expected after -%c", *argptr);
			return 1;
		    }
		    if (idigit(*argptr) || !isident(argptr)) {
			zwarnnam(nam, "invalid array name: %s", argptr);
			return 1;
		    }
		    if (i == 'a')
			outarray = argptr;
		    else
			outhash = argptr;
		    /* set argptr to next to last char because of increment */
		    while (argptr[1])
			argptr++;
		    break;

		    /* Following numbers indicate fd's for reading */
		case 'r':
		    fdsetind = 0;
		    break;

		    /* Following numbers indicate fd's for writing */
		case 'w':
		    fdsetind = 1;
		    break;

		    /* Following numbers indicate fd's for errors */
		case 'e':
		    fdsetind = 2;
		    break;

		    /*
		     * Get a timeout value in hundredths of a second
		     * (same units as KEYTIMEOUT).  0 means just poll.
		     * If not given, blocks indefinitely.
		     */
		case 't':
		    if (argptr[1])
			argptr++;
		    else if (args[1]) {
			argptr = *++args;
		    } else {
			zwarnnam(nam, "argument expected after -%c", *argptr);
			return 1;
		    }
		    if (!idigit(*argptr)) {
			zwarnnam(nam, "number expected after -t");
			return 1;
		    }
		    tempnum = zstrtol(argptr, &endptr, 10);
		    if (*endptr) {
			zwarnnam(nam, "garbage after -t argument: %s",
				 endptr);
			return 1;
		    }
		    /* timevalue now active */
		    tvptr = &tv;
		    tv.tv_sec = (long)(tempnum / 100);
		    tv.tv_usec = (long)(tempnum % 100) * 10000L;

		    /* remember argptr is incremented at end of loop */
		    argptr = endptr - 1;
		    break;

		    /* Digits following option without arguments are fd's. */
		default:
		    if (handle_digits(nam, argptr, fdset+fdsetind,
				      &fdmax))
			return 1;
		}
	    }
	} else if (handle_digits(nam, argptr, fdset+fdsetind, &fdmax))
	    return 1;
    }

    errno = 0;
    do {
	i = select(fdmax, (SELECT_ARG_2_T)fdset, (SELECT_ARG_2_T)(fdset+1),
		   (SELECT_ARG_2_T)(fdset+2), tvptr);
    } while (i < 0 && errno == EINTR && !errflag);

    if (i <= 0) {
	if (i < 0)
	    zwarnnam(nam, "error on select: %e", errno);
	/* else no fd's set.  Presumably a timeout. */
	return 1;
    }

    /*
     * Make a linked list of all file descriptors which are ready.
     * These go into an array preceded by -r, -w or -e for read, write,
     * error as appropriate.  Typically there will only be one set
     * so this looks rather like overkill.
     */
    fdlist = znewlinklist();
    for (i = 0; i < 3; i++) {
	int doneit = 0;
	for (fd = 0; fd < fdmax; fd++) {
	    if (FD_ISSET(fd, fdset+i)) {
		char buf[BDIGBUFSIZE];
		if (outhash) {
		    /*
		     * Key/value pairs; keys are fd's (as strings),
		     * value is a (possibly improper) subset of "rwe".
		     */
		    LinkNode nptr;
		    int found = 0;

		    convbase(buf, fd, 10);
		    for (nptr = firstnode(fdlist); nptr; 
			 nptr = nextnode(nextnode(nptr))) {
			if (!strcmp((char *)getdata(nptr), buf)) {
			    /* Already there, add new character. */
			    void **dataptr = getaddrdata(nextnode(nptr));
			    char *data = (char *)*dataptr, *ptr;
			    found = 1;
			    if (!strchr(data, fdchar[i])) {
				strcpy(buf, data);
				for (ptr = buf; *ptr; ptr++)
				    ;
				*ptr++ = fdchar[i];
				*ptr = '\0';
				zsfree(data);
				*dataptr = ztrdup(buf);
			    }
			    break;
			}
		    }
		    if (!found) {
			/* Add new key/value pair. */
			zaddlinknode(fdlist, ztrdup(buf));
			buf[0] = fdchar[i];
			buf[1] = '\0';
			zaddlinknode(fdlist, ztrdup(buf));
		    }
		} else {
		    /* List of fd's preceded by -r, -w, -e. */
		    if (!doneit) {
			buf[0] = '-';
			buf[1] = fdchar[i];
			buf[2] = 0;
			zaddlinknode(fdlist, ztrdup(buf));
			doneit = 1;
		    }
		    convbase(buf, fd, 10);
		    zaddlinknode(fdlist, ztrdup(buf));
		}
	    }
	}
    }

    /* convert list to array */
    fdcount = countlinknodes(fdlist);
    outptr = outdata = (char **)zalloc((fdcount+1)*sizeof(char *));
    while (nonempty(fdlist))
	*outptr++ = getlinknode(fdlist);
    *outptr = NULL;
    /* and store in array parameter */
    if (outhash)
	sethparam(outhash, outdata);
    else
	setaparam(outarray, outdata);
    freelinklist(fdlist, NULL);

    return 0;
#else
    /* TODO: use poll */
    zerrnam(nam, "your system does not implement the select system call.");
    return 2;
#endif
}
Example #3
0
File: stat.c Project: zsh-users/zsh
static int
bin_stat(char *name, char **args, Options ops, UNUSED(int func))
{
    char **aptr, *arrnam = NULL, **array = NULL, **arrptr = NULL;
    char *hashnam = NULL, **hash = NULL, **hashptr = NULL;
    int len, iwhich = -1, ret = 0, flags = 0, arrsize = 0, fd = 0;
    struct stat statbuf;
    int found = 0, nargs;

    timefmt = "%a %b %e %k:%M:%S %Z %Y";

    for (; *args && (**args == '+' || **args == '-'); args++) {
	char *arg = *args+1;
	if (!*arg || *arg == '-' || *arg == '+') {
	    args++;
	    break;
	}

	if (**args == '+') {
	    if (found)
		break;
	    len = strlen(arg);
	    for (aptr = statelts; *aptr; aptr++)
		if (!strncmp(*aptr, arg, len)) {
		    found++;
		    iwhich = aptr - statelts;
		}
	    if (found > 1) {
		zwarnnam(name, "%s: ambiguous stat element", arg);
		return 1;
	    } else if (found == 0) {
		zwarnnam(name, "%s: no such stat element", arg);
		return 1;
	    }
	    /* if name of link requested, turn on lstat */
	    if (iwhich == ST_READLINK)
		ops->ind['L'] = 1;
	    flags |= STF_PICK;
	} else {
	    for (; *arg; arg++) {
		if (strchr("glLnNorstT", *arg))
		    ops->ind[STOUC(*arg)] = 1;
		else if (*arg == 'A') {
		    if (arg[1]) {
			arrnam = arg+1;
		    } else if (!(arrnam = *++args)) {
			zwarnnam(name, "missing parameter name");
			return 1;
		    }
		    flags |= STF_ARRAY;
		    break;
		} else if (*arg == 'H') {
		    if (arg[1]) {
			hashnam = arg+1;
		    } else if (!(hashnam = *++args)) {
			zwarnnam(name, "missing parameter name");
			return 1;
		    }
		    flags |= STF_HASH;
		    break;
		} else if (*arg == 'f') {
		    char *sfd;
		    ops->ind['f'] = 1;
		    if (arg[1]) {
			sfd = arg+1;
		    } else if (!(sfd = *++args)) {
			zwarnnam(name, "missing file descriptor");
			return 1;
		    }
		    fd = zstrtol(sfd, &sfd, 10);
		    if (*sfd) {
			zwarnnam(name, "bad file descriptor");
			return 1;
		    }
		    break;
		} else if (*arg == 'F') {
		    if (arg[1]) {
			timefmt = arg+1;
		    } else if (!(timefmt = *++args)) {
			zwarnnam(name, "missing time format");
			return 1;
		    }
		    /* force string format in order to use time format */
		    ops->ind['s'] = 1;
		    break;
		} else {
		    zwarnnam(name, "bad option: -%c", *arg);
		    return 1;
		}
	    }
	}
    }

    if ((flags & STF_ARRAY) && (flags & STF_HASH)) {
    	/* We don't implement setting multiple variables at once */
	zwarnnam(name, "both array and hash requested");
	return 1;
	/* Alternate method would be to make -H blank arrnam etc etc *
	 * and so get 'silent loss' of earlier choice, which would   *
	 * be similar to stat -A foo -A bar filename                 */
    }

    if (OPT_ISSET(ops,'l')) {
	/* list types and return:  can also list to array */
	if (arrnam) {
	    arrptr = array = (char **)zalloc((ST_COUNT+1)*sizeof(char *));
	    array[ST_COUNT] = NULL;
	}
	for (aptr = statelts; *aptr; aptr++) {
	    if (arrnam) {
		*arrptr++ = ztrdup(*aptr);
	    } else {
		printf("%s", *aptr);
		if (aptr[1])
		    putchar(' ');
	    }
	}
	if (arrnam) {
	    setaparam(arrnam, array);
	    if (errflag)
		return 1;
	} else
	    putchar('\n');
	return 0;
    }

    if (!*args && !OPT_ISSET(ops,'f')) {
	zwarnnam(name, "no files given");
	return 1;
    } else if (*args && OPT_ISSET(ops,'f')) {
	zwarnnam(name, "no files allowed with -f");
	return 1;
    }

    nargs = 0;
    if (OPT_ISSET(ops,'f'))
	nargs = 1;
    else
	for (aptr = args; *aptr; aptr++)
	    nargs++;

    if (OPT_ISSET(ops,'g')) {
	flags |= STF_GMT;
	ops->ind['s'] = 1;
    }
    if (OPT_ISSET(ops,'s') || OPT_ISSET(ops,'r'))
	flags |= STF_STRING;
    if (OPT_ISSET(ops,'r') || !OPT_ISSET(ops,'s'))
	flags |= STF_RAW;
    if (OPT_ISSET(ops,'n'))
	flags |= STF_FILE;
    if (OPT_ISSET(ops,'o'))
	flags |= STF_OCTAL;
    if (OPT_ISSET(ops,'t'))
	flags |= STF_NAME;

    if (!(arrnam || hashnam)) {
	if (nargs > 1)
	    flags |= STF_FILE;
	if (!(flags & STF_PICK))
	    flags |= STF_NAME;
    }

    if (OPT_ISSET(ops,'N') || OPT_ISSET(ops,'f'))
	flags &= ~STF_FILE;
    if (OPT_ISSET(ops,'T') || OPT_ISSET(ops,'H'))
	flags &= ~STF_NAME;

    if (hashnam) {
    	if (nargs > 1) {
	    zwarnnam(name, "only one file allowed with -H");
	    return 1;
	}
	arrsize = (flags & STF_PICK) ? 1 : ST_COUNT;
	if (flags & STF_FILE)
	    arrsize++;
	hashptr = hash = (char **)zshcalloc((arrsize+1)*2*sizeof(char *));
    }

    if (arrnam) {
	arrsize = (flags & STF_PICK) ? 1 : ST_COUNT;
	if (flags & STF_FILE)
	    arrsize++;
	arrsize *= nargs;
	arrptr = array = (char **)zshcalloc((arrsize+1)*sizeof(char *));
    }

    for (; OPT_ISSET(ops,'f') || *args; args++) {
	char outbuf[PATH_MAX + 9]; /* "link   " + link name + NULL */
	int rval = OPT_ISSET(ops,'f') ? fstat(fd, &statbuf) :
	    OPT_ISSET(ops,'L') ? lstat(unmeta(*args), &statbuf) :
	    stat(unmeta(*args), &statbuf);
	if (rval) {
	    if (OPT_ISSET(ops,'f'))
		sprintf(outbuf, "%d", fd);
	    zwarnnam(name, "%s: %e", OPT_ISSET(ops,'f') ? outbuf : *args,
		     errno);
	    ret = 1;
	    if (OPT_ISSET(ops,'f') || arrnam)
		break;
	    else
		continue;
	}

	if (flags & STF_FILE) {
	    if (arrnam)
		*arrptr++ = ztrdup(*args);
	    else if (hashnam) {
	    	*hashptr++ = ztrdup(HNAMEKEY);
		*hashptr++ = ztrdup(*args);
	    } else
		printf("%s%s", *args, (flags & STF_PICK) ? " " : ":\n");
	}
	if (iwhich > -1) {
	    statprint(&statbuf, outbuf, *args, iwhich, flags);
	    if (arrnam)
		*arrptr++ = metafy(outbuf, -1, META_DUP);
	    else if (hashnam) {
		/* STF_NAME explicitly turned off for ops.ind['H'] above */
	    	*hashptr++ = ztrdup(statelts[iwhich]);
		*hashptr++ = metafy(outbuf, -1, META_DUP);
	    } else
		printf("%s\n", outbuf);
	} else {
	    int i;
	    for (i = 0; i < ST_COUNT; i++) {
		statprint(&statbuf, outbuf, *args, i, flags);
		if (arrnam)
		    *arrptr++= metafy(outbuf, -1, META_DUP);
		else if (hashnam) {
		    /* STF_NAME explicitly turned off for ops.ind['H'] above */
		    *hashptr++ = ztrdup(statelts[i]);
		    *hashptr++ = metafy(outbuf, -1, META_DUP);
		} else
		    printf("%s\n", outbuf);
	    }
	}
	if (OPT_ISSET(ops,'f'))
	    break;

	if (!arrnam && !hashnam && args[1] && !(flags & STF_PICK))
	    putchar('\n');
    }

    if (arrnam) {
	if (ret)
	    freearray(array);
	else {
	    setaparam(arrnam, array);
	    if (errflag)
		return 1;
	}
    }

    if (hashnam) {
    	if (ret)
	    freearray(hash);
	else {
	    sethparam(hashnam, hash);
	    if (errflag)
		return 1;
	}
    }

    return ret;
}