Пример #1
0
int
copyprevshellword(UNUSED(char **args))
{
    LinkList l;
    LinkNode n;
    int i;
    char *p = NULL;

    if (zmult <= 0)
	return 1;

    if ((l = bufferwords(NULL, NULL, &i, LEXFLAGS_ZLE))) {
	i -= (zmult-1);
	if (i < 0)
	    return 1;
        for (n = firstnode(l); n; incnode(n))
            if (!i--) {
                p = getdata(n);
                break;
            }
    }

    if (p) {
	int len;
	ZLE_STRING_T lineadd = stringaszleline(p, 0, &len, NULL, NULL);

	spaceinline(len);
	ZS_memcpy(zleline + zlecs, lineadd, len);
	zlecs += len;

	free(lineadd);
    }
    return 0;
}
Пример #2
0
int
countlinknodes(LinkList list)
{
    LinkNode nd;
    int ct = 0;

    for (nd = firstnode(list); nd; incnode(nd), ct++);
    return ct;
}
Пример #3
0
static Tcp_session
zts_byfd(int fd)
{
    LinkNode node;
    
    for (node = firstnode(ztcp_sessions); node; incnode(node))
	if (((Tcp_session)getdata(node))->fd == fd)
	    return (Tcp_session)getdata(node);
    
    return NULL;
}
Пример #4
0
void
prefork(LinkList list, int flags)
{
    LinkNode node;

    MUSTUSEHEAP("prefork");
    for (node = firstnode(list); node; incnode(node)) {
	char *str, *str3;

	str = str3 = (char *)getdata(node);
	if ((*str == Inang || *str == Outang || *str == Equals) &&
	    str[1] == Inpar) {
	    if (*str == Inang || *str == Outang)
		setdata(node, (void *) getproc(str));	/* <(...) or >(...) */
	    else
		setdata(node, (void *) getoutputfile(str));	/* =(...) */
	    if (!getdata(node))
		return;
	} else {
	    if (isset(SHFILEEXPANSION))
		filesub((char **)getaddrdata(node), flags & 3);
	    if (!(node = stringsubst(list, node, flags & 4)))
		return;
	}
    }
    for (node = firstnode(list); node; incnode(node)) {
	if (*(char *)getdata(node)) {
	    remnulargs(getdata(node));
	    if (unset(IGNOREBRACES) && !(flags & 4))
		while (hasbraces(getdata(node)))
		    xpandbraces(list, &node);
	    if (unset(SHFILEEXPANSION))
		filesub((char **)getaddrdata(node), flags & 3);
	} else if (!(flags & 4))
	    uremnode(list, node);
	if (errflag)
	    return;
    }
}
Пример #5
0
void
getredirs(LinkList redirs)
{
    LinkNode n;
    static char *fstr[] =
    {
	">", ">|", ">>", ">>|", "&>", "&>|", "&>>", "&>>|", "<>", "<",
	"<<", "<<-", "<<<", "<&", ">&", NULL /* >&- */, "<", ">"
    };
    taddchr(' ');
    for (n = firstnode(redirs); n; incnode(n)) {
	Redir f = (Redir) getdata(n);

	switch (f->type) {
	case REDIR_WRITE:
	case REDIR_WRITENOW:
	case REDIR_APP:
	case REDIR_APPNOW:
	case REDIR_ERRWRITE:
	case REDIR_ERRWRITENOW:
	case REDIR_ERRAPP:
	case REDIR_ERRAPPNOW:
	case REDIR_READ:
	case REDIR_READWRITE:
	case REDIR_HERESTR:
	case REDIR_MERGEIN:
	case REDIR_MERGEOUT:
	case REDIR_INPIPE:
	case REDIR_OUTPIPE:
	    if (f->varid) {
		taddchr('{');
		taddstr(f->varid);
		taddchr('}');
	    } else if (f->fd1 != (IS_READFD(f->type) ? 0 : 1))
		taddchr('0' + f->fd1);
	    if (f->type == REDIR_HERESTR &&
		(f->flags & REDIRF_FROM_HEREDOC)) {
		if (tnewlins) {
		    /*
		     * Strings that came from here-documents are converted
		     * to here strings without quotation, so convert them
		     * back.
		     */
		    taddstr(fstr[REDIR_HEREDOC]);
		    taddstr(f->here_terminator);
		    taddpending(f->name, f->munged_here_terminator);
		} else {
		    int fnamelen, sav;
		    taddstr(fstr[REDIR_HERESTR]);
		    /*
		     * Just a quick and dirty representation.
		     * Remove a terminating newline, if any.
		     */
		    fnamelen = strlen(f->name);
		    if (fnamelen > 0 && f->name[fnamelen-1] == '\n') {
			sav = 1;
			f->name[fnamelen-1] = '\0';
		    } else
			sav = 0;
		    /*
		     * Strings that came from here-documents are converted
		     * to here strings without quotation, so add that
		     * now.  If tokens are present we need to do double quoting.
		     */
		    if (!has_token(f->name)) {
			taddchr('\'');
			taddstr(quotestring(f->name, NULL, QT_SINGLE));
			taddchr('\'');
		    } else {
			taddchr('"');
			taddstr(quotestring(f->name, NULL, QT_DOUBLE));
			taddchr('"');
		    }
		    if (sav)
			f->name[fnamelen-1] = '\n';
		}
	    } else {
		taddstr(fstr[f->type]);
		if (f->type != REDIR_MERGEIN && f->type != REDIR_MERGEOUT)
		    taddchr(' ');
		taddstr(f->name);
	    }
	    taddchr(' ');
	    break;
#ifdef DEBUG
	case REDIR_CLOSE:
	    DPUTS(1, "BUG: CLOSE in getredirs()");
	    taddchr(f->fd1 + '0');
	    taddstr(">&- ");
	    break;
	default:
	    DPUTS(1, "BUG: unknown redirection in getredirs()");
#endif
	}
    }
    tptr--;
}
Пример #6
0
Файл: loop.c Проект: phy1729/zsh
int
execfor(Estate state, int do_exec)
{
    Wordcode end, loop;
    wordcode code = state->pc[-1];
    int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND), ctok = 0, atok = 0;
    int last = 0;
    char *name, *str, *cond = NULL, *advance = NULL;
    zlong val = 0;
    LinkList vars = NULL, args = NULL;
    int old_simple_pline = simple_pline;

    /* See comments in execwhile() */
    simple_pline = 1;

    end = state->pc + WC_FOR_SKIP(code);

    if (iscond) {
	str = dupstring(ecgetstr(state, EC_NODUP, NULL));
	singsub(&str);
	if (isset(XTRACE)) {
	    char *str2 = dupstring(str);
	    untokenize(str2);
	    printprompt4();
	    fprintf(xtrerr, "%s\n", str2);
	    fflush(xtrerr);
	}
	if (!errflag) {
	    matheval(str);
	}
	if (errflag) {
	    state->pc = end;
	    simple_pline = old_simple_pline;
	    return 1;
	}
	cond = ecgetstr(state, EC_NODUP, &ctok);
	advance = ecgetstr(state, EC_NODUP, &atok);
    } else {
	vars = ecgetlist(state, *state->pc++, EC_NODUP, NULL);

	if (WC_FOR_TYPE(code) == WC_FOR_LIST) {
	    int htok = 0;

	    if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
		state->pc = end;
		simple_pline = old_simple_pline;
		return 0;
	    }
	    if (htok) {
		execsubst(args);
		if (errflag) {
		    state->pc = end;
		    simple_pline = old_simple_pline;
		    return 1;
		}
	    }
	} else {
	    char **x;

	    args = newlinklist();
	    for (x = pparams; *x; x++)
		addlinknode(args, dupstring(*x));
	}
    }

    if (!args || empty(args))
	lastval = 0;

    loops++;
    pushheap();
    cmdpush(CS_FOR);
    loop = state->pc;
    while (!last) {
	if (iscond) {
	    if (ctok) {
		str = dupstring(cond);
		singsub(&str);
	    } else
		str = cond;
	    if (!errflag) {
		while (iblank(*str))
		    str++;
		if (*str) {
		    if (isset(XTRACE)) {
			printprompt4();
			fprintf(xtrerr, "%s\n", str);
			fflush(xtrerr);
		    }
		    val = mathevali(str);
		} else
		    val = 1;
	    }
	    if (errflag) {
		if (breaks)
		    breaks--;
		lastval = 1;
		break;
	    }
	    if (!val)
		break;
	} else {
	    LinkNode node;
	    int count = 0;
	    for (node = firstnode(vars); node; incnode(node))
	    {
		name = (char *)getdata(node);
		if (!args || !(str = (char *) ugetnode(args)))
		{
		    if (count) { 
			str = "";
			last = 1;
		    } else
			break;
		}
		if (isset(XTRACE)) {
		    printprompt4();
		    fprintf(xtrerr, "%s=%s\n", name, str);
		    fflush(xtrerr);
		}
		setsparam(name, ztrdup(str));
		count++;
	    }
	    if (!count)
		break;
	}
	state->pc = loop;
	execlist(state, 1, do_exec && args && empty(args));
	if (breaks) {
	    breaks--;
	    if (breaks || !contflag)
		break;
	    contflag = 0;
	}
	if (retflag)
	    break;
	if (iscond && !errflag) {
	    if (atok) {
		str = dupstring(advance);
		singsub(&str);
	    } else
		str = advance;
	    if (isset(XTRACE)) {
		printprompt4();
		fprintf(xtrerr, "%s\n", str);
		fflush(xtrerr);
	    }
	    if (!errflag)
		matheval(str);
	}
	if (errflag) {
	    if (breaks)
		breaks--;
	    lastval = 1;
	    break;
	}
	freeheap();
    }
    popheap();
    cmdpop();
    loops--;
    simple_pline = old_simple_pline;
    state->pc = end;
    return lastval;
}
Пример #7
0
Файл: loop.c Проект: phy1729/zsh
int
execselect(Estate state, UNUSED(int do_exec))
{
    Wordcode end, loop;
    wordcode code = state->pc[-1];
    char *str, *s, *name;
    LinkNode n;
    int i, usezle;
    FILE *inp;
    size_t more;
    LinkList args;
    int old_simple_pline = simple_pline;

    /* See comments in execwhile() */
    simple_pline = 1;

    end = state->pc + WC_FOR_SKIP(code);
    name = ecgetstr(state, EC_NODUP, NULL);

    if (WC_SELECT_TYPE(code) == WC_SELECT_PPARAM) {
	char **x;

	args = newlinklist();
	for (x = pparams; *x; x++)
	    addlinknode(args, dupstring(*x));
    } else {
	int htok = 0;

	if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
	    state->pc = end;
	    simple_pline = old_simple_pline;
	    return 0;
	}
	if (htok) {
	    execsubst(args);
	    if (errflag) {
		state->pc = end;
		simple_pline = old_simple_pline;
		return 1;
	    }
	}
    }
    if (!args || empty(args)) {
	state->pc = end;
	simple_pline = old_simple_pline;
	return 0;
    }
    loops++;

    pushheap();
    cmdpush(CS_SELECT);
    usezle = interact && SHTTY != -1 && isset(USEZLE);
    inp = fdopen(dup(usezle ? SHTTY : 0), "r");
    more = selectlist(args, 0);
    loop = state->pc;
    for (;;) {
	for (;;) {
	    if (empty(bufstack)) {
	    	if (usezle) {
		    int oef = errflag;

		    isfirstln = 1;
		    str = zleentry(ZLE_CMD_READ, &prompt3, NULL,
				   0, ZLCON_SELECT);
		    if (errflag)
			str = NULL;
		    /* Keep any user interrupt error status */
		    errflag = oef | (errflag & ERRFLAG_INT);
	    	} else {
		    str = promptexpand(prompt3, 0, NULL, NULL, NULL);
		    zputs(str, stderr);
		    free(str);
		    fflush(stderr);
		    str = fgets(zhalloc(256), 256, inp);
	    	}
	    } else
		str = (char *)getlinknode(bufstack);
            if (!str && !errflag)
                setsparam("REPLY", ztrdup("")); /* EOF (user pressed Ctrl+D) */
	    if (!str || errflag) {
		if (breaks)
		    breaks--;
		fprintf(stderr, "\n");
		fflush(stderr);
		goto done;
	    }
	    if ((s = strchr(str, '\n')))
		*s = '\0';
	    if (*str)
	      break;
	    more = selectlist(args, more);
	}
	setsparam("REPLY", ztrdup(str));
	i = atoi(str);
	if (!i)
	    str = "";
	else {
	    for (i--, n = firstnode(args); n && i; incnode(n), i--);
	    if (n)
		str = (char *) getdata(n);
	    else
		str = "";
	}
	setsparam(name, ztrdup(str));
	state->pc = loop;
	execlist(state, 1, 0);
	freeheap();
	if (breaks) {
	    breaks--;
	    if (breaks || !contflag)
		break;
	    contflag = 0;
	}
	if (retflag || errflag)
	    break;
    }
  done:
    cmdpop();
    popheap();
    fclose(inp);
    loops--;
    simple_pline = old_simple_pline;
    state->pc = end;
    return lastval;
}
Пример #8
0
//return 0 on success
Render_Node *render_state_getjob( Render_State *state)
{
  int i;
  Rect area;
  Tilehash hash;
  Render_Node *node;
  Tile *tile;
  Render_Node *jobnode;
  int found;
  struct timespec t_start;
  struct timespec t_stop;
  
  if (ea_count(state->ready))
    return ea_pop(state->ready);
  
  if (!ea_count(state->currstate)) {
    
    if (state->pending) {
      
      if (!ea_count(state->ready)) {
        clock_gettime(CLOCK_MONOTONIC,&t_start);
        lime_unlock();
        while(state->pending && !ea_count(state->ready)) {
          usleep(1000);
          lime_lock();
          lime_unlock();
        }
        lime_lock();
        
        clock_gettime(CLOCK_MONOTONIC,&t_stop);
        printf("we were blocked!\n");
        global_stat_thread_blocked += t_stop.tv_sec - t_start.tv_sec
        +  (t_stop.tv_nsec - t_start.tv_nsec)*1.0/1000000000.0;
      }
      
      assert(ea_count(state->ready));
      
      return ea_pop(state->ready);
    }

    return NULL;
  }

  node = ea_data(state->currstate, ea_count(state->currstate)-1);
    
  while (node) {
    if (!end_of_iteration(node)) {
      area.corner.x = node->pos.x;
      area.corner.y = node->pos.y;
      area.corner.scale = node->pos.scale;
      area.width = node->tw;
      area.height = node->th;
      
      hash = tile_hash_calc(filter_get_input_filter(node->f, node->channel), &area);
         
      if ((tile = cache_tile_get(&hash))) {
	
	cache_stats_update(tile, 1, 0, 0, 0);
	  
	assert(node->mode);
	  
	//check if we're alredy waiting for this tile on another channel
	found = 0;
	if (tile->want)
	  for(i=0;i<ea_count(tile->want);i++)
	    if (node == ea_data(tile->want, i)) {
	      found = 1;
	      break;
	  }
	  
	  if (found) {
	    //do nothing, we just continue
	    
	  }
	  else if (!tile->channels) {
	    //tile is not yet rendered, push ref
	    
	    if (!tile->want)
	      tile->want = eina_array_new(4);

	    node->need++;
	    ea_push(tile->want, node);
	  }
	  else {
	    if (node->mode == MODE_CLOBBER) {
	      //TODO attention: we assume channels are always processed in the same order
	      clobbertile_add(ea_data(node->inputs, node->channel), ea_data(tile->channels, node->channel));
	      assert(ea_count(node->inputs) > node->channel);
	    }
	    else if (node->mode == MODE_ITER) {
	      node->f->mode_iter->worker(node->f, ea_data(tile->channels, node->channel), node->channel, NULL, NULL, 0);
	    }
	    else
	      abort();
	  }
	  
	incnode(node);
      }
      //this node does not need any input tiles
      else if (!ea_count(node->f_source_curr->node->con_ch_in)) {
	jobnode = render_node_new(node->f_source_curr, tile_new(&area, hash, node->f_source_curr, node->f, node->depth), state, node->depth+1);
	assert(jobnode->f->fixme_outcount);
	cache_tile_add(jobnode->tile);
	cache_stats_update(jobnode->tile, 0, 1, 0, 0);

	//don't incnode so parent node will recheck for this tile
	//the parent will propably be added to tile->need
	return jobnode;
      }
      //node needs input tiles
      else {
	tile = tile_new(&area, hash, node->f_source_curr, node->f, node->depth);
	cache_stats_update(tile, 0, 1, 0, 0);
	if (node->f->fixme_outcount);
	  cache_tile_add(tile);
        
	jobnode = render_node_new(node->f_source_curr, tile, state, node->depth+1);
        
        tile->want = eina_array_new(4);
        node->need++;
        ea_push(tile->want, node);
        //FIXME this incnode would cause problems with tiffsave!
        //incnode(node);
        
        node = jobnode;
        
	//don't incnode so parent node will recheck for this tile
	//the parent will propably be added to tile->need
	
	ea_push(state->currstate, node);
	//to lock it in the currstate array
	node->need += 1000;
      }
    }
    else {
      //all inputs have been processed
      //this doesn't mean that all inputs are available
      jobnode = node;
      
      node = ea_pop(state->currstate);
      node->need -= 1000;
      
      assert(node == jobnode);

      if (jobnode->need) {
	//what happens with jobnode?
	//why this code??
	if (ea_count(state->currstate))
	  node = ea_data(state->currstate, ea_count(state->currstate)-1);
	else
	  node = NULL;
	state->pending++;
      }
      else
	return jobnode;
    }
  }
  
  if (ea_count(state->ready))
    return ea_pop(state->ready);
    
  if (state->pending) {
    lime_unlock();
    while(state->pending && !ea_count(state->ready)) {
      usleep(1000);
      lime_lock();
      lime_unlock();
    }

    lime_lock();
    
    assert(ea_count(state->ready));

    return ea_pop(state->ready);
  } 
  
  return NULL;
}
Пример #9
0
Файл: math.c Проект: blueyed/zsh
static mnumber
callmathfunc(char *o)
{
    MathFunc f;
    char *a, *n;
    static mnumber dummy;

    n = a = dupstring(o);

    while (*a != '(')
	a++;
    *a++ = '\0';
    a[strlen(a) - 1] = '\0';

    if ((f = getmathfunc(n, 1))) {
	if (f->flags & MFF_STR) {
	    return f->sfunc(n, a, f->funcid);
	} else {
	    int argc = 0;
	    mnumber *argv = NULL, *q, marg;
	    LinkList l = newlinklist();
	    LinkNode node;

	    if (f->flags & MFF_USERFUNC) {
		/* first argument is function name: always use mathfunc */
		addlinknode(l, n);
	    }

	    while (iblank(*a))
		a++;
	    while (*a) {
		if (*a) {
		    argc++;
		    if (f->flags & MFF_USERFUNC) {
			/* need to pass strings */
			char *str;
			marg = mathevall(a, MPREC_ARG, &a);
			if (marg.type & MN_FLOAT) {
			    /* convfloat is off the heap */
			    str = convfloat(marg.u.d, 0, 0, NULL);
			} else {
			    char buf[BDIGBUFSIZE];
			    convbase(buf, marg.u.l, 10);
			    str = dupstring(buf);
			}
			addlinknode(l, str);
		    } else {
			q = (mnumber *) zhalloc(sizeof(mnumber));
			*q = mathevall(a, MPREC_ARG, &a);
			addlinknode(l, q);
		    }
		    if (errflag || mtok != COMMA)
			break;
		}
	    }
	    if (*a && !errflag)
		zerr("bad math expression: illegal character: %c", *a);
	    if (!errflag) {
		if (argc >= f->minargs && (f->maxargs < 0 ||
					   argc <= f->maxargs)) {
		    if (f->flags & MFF_USERFUNC) {
			char *shfnam = f->module ? f->module : n;
			Shfunc shfunc = getshfunc(shfnam);
			if (!shfunc)
			    zerr("no such function: %s", shfnam);
			else {
			    doshfunc(shfunc, l, 1);
			    return lastmathval;
			}
		    } else {
			if (argc) {
			    q = argv =
				(mnumber *)zhalloc(argc * sizeof(mnumber));
			    for (node = firstnode(l); node; incnode(node))
				*q++ = *(mnumber *)getdata(node);
			}
			return f->nfunc(n, argc, argv, f->funcid);
		    }
		} else
		    zerr("wrong number of arguments: %s", o);
	    }
	}
    } else {
	zerr("unknown function: %s", n);
    }

    dummy.type = MN_INTEGER;
    dummy.u.l = 0;

    return dummy;
}
Пример #10
0
static int
bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
{
    int herrno, err=1, destport, force=0, verbose=0, test=0, targetfd=0;
    ZSOCKLEN_T  len;
    char **addrp, *desthost;
    const char *localname, *remotename;
    struct hostent *zthost = NULL, *ztpeer = NULL;
    struct servent *srv;
    Tcp_session sess = NULL;

    if (OPT_ISSET(ops,'f'))
	force = 1;

    if (OPT_ISSET(ops,'v'))
	verbose = 1;

    if (OPT_ISSET(ops,'t'))
        test = 1;

    if (OPT_ISSET(ops,'d')) {
	targetfd = atoi(OPT_ARG(ops,'d'));
	if (!targetfd) {
	    zwarnnam(nam, "%s is an invalid argument to -d", OPT_ARG(ops,'d'));
	    return 1;
	}
    }


    if (OPT_ISSET(ops,'c')) {
	if (!args[0]) {
	    tcp_cleanup();
	}
	else {
	    targetfd = atoi(args[0]);
	    sess = zts_byfd(targetfd);
	    if(!targetfd) {
		zwarnnam(nam, "%s is an invalid argument to -c", args[0]);
		return 1;
	    }

	    if (sess)
	    {
		if ((sess->flags & ZTCP_ZFTP) && !force)
		{
		    zwarnnam(nam, "use -f to force closure of a zftp control connection");
		    return 1;
		}
		tcp_close(sess);
		return 0;
	    }
	    else
	    {
		zwarnnam(nam, "fd %s not found in tcp table", args[0]);
		return 1;
	    }
	}
    }
    else if (OPT_ISSET(ops,'l')) {
	int lport = 0;

	if (!args[0]) {
	    zwarnnam(nam, "-l requires an argument");
	    return 1;
	}

	srv = getservbyname(args[0], "tcp");
	if (srv)
	    lport = srv->s_port;
	else
	    lport = htons(atoi(args[0]));
	if (!lport) { zwarnnam(nam, "bad service name or port number");
	return 1;
	}
	sess = tcp_socket(PF_INET, SOCK_STREAM, 0, ZTCP_LISTEN);

	if (!sess) {
	    zwarnnam(nam, "unable to allocate a TCP session slot");
	    return 1;
	}
#ifdef SO_OOBINLINE
	len = 1;
	setsockopt(sess->fd, SOL_SOCKET, SO_OOBINLINE, (char *)&len, sizeof(len));
#endif
	if (!zsh_inet_aton("0.0.0.0", &(sess->sock.in.sin_addr)))
	{
	    zwarnnam(nam, "bad address: %s", "0.0.0.0");
	    return 1;
	}

	sess->sock.in.sin_family = AF_INET;
	sess->sock.in.sin_port = lport;


	if (bind(sess->fd, (struct sockaddr *)&sess->sock.in, sizeof(struct sockaddr_in)))
	{
	    char buf[DIGBUFSIZE];
	    convbase(buf, (zlong)ntohs(lport), 10);
	    zwarnnam(nam, "could not bind to port %s: %e", buf, errno);
	    tcp_close(sess);
	    return 1;
	}

	if (listen(sess->fd, 1))
	{
	    zwarnnam(nam, "could not listen on socket: %e", errno);
	    tcp_close(sess);
	    return 1;
	}

	if (targetfd) {
	    sess->fd = redup(sess->fd, targetfd);
	}
	else {
	    /* move the fd since no one will want to read from it */
	    sess->fd = movefd(sess->fd);
	}

	if (sess->fd == -1) {
	    zwarnnam(nam, "cannot duplicate fd %d: %e", sess->fd, errno);
	    tcp_close(sess);
	    return 1;
	}

	setiparam_no_convert("REPLY", (zlong)sess->fd);

	if (verbose)
	    printf("%d listener is on fd %d\n", ntohs(sess->sock.in.sin_port), sess->fd);

	return 0;

    }
    else if (OPT_ISSET(ops,'a'))
    {
	int lfd, rfd;

	if (!args[0]) {
	    zwarnnam(nam, "-a requires an argument");
	    return 1;
	}

	lfd = atoi(args[0]);

	if (!lfd) {
	    zwarnnam(nam, "invalid numerical argument");
	    return 1;
	}

	sess = zts_byfd(lfd);
	if (!sess) {
	    zwarnnam(nam, "fd %s is not registered as a tcp connection", args[0]);
	    return 1;
	}

	if (!(sess->flags & ZTCP_LISTEN))
	{
	    zwarnnam(nam, "tcp connection not a listener");
	    return 1;
	}

	if (test) {
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
# ifdef HAVE_POLL
	    struct pollfd pfd;
	    int ret;

	    pfd.fd = lfd;
	    pfd.events = POLLIN;
	    if ((ret = poll(&pfd, 1, 0)) == 0) return 1;
	    else if (ret == -1)
	    {
		zwarnnam(nam, "poll error: %e", errno);
		return 1;
	    }
# else
	    fd_set rfds;
	    struct timeval tv;
	    int ret;
	    
	    FD_ZERO(&rfds);
	    FD_SET(lfd, &rfds);
	    tv.tv_sec = 0;
	    tv.tv_usec = 0;
	    
	    if ((ret = select(lfd+1, &rfds, NULL, NULL, &tv)) == 0) return 1;
	    else if (ret == -1)
	    {
		zwarnnam(nam, "select error: %e", errno);
		return 1;
	    }
	    
# endif
	    
#else
	    zwarnnam(nam, "not currently supported");
	    return 1;
#endif
	}
	sess = zts_alloc(ZTCP_INBOUND);

	len = sizeof(sess->peer.in);
	do {
	    rfd = accept(lfd, (struct sockaddr *)&sess->peer.in, &len);
	} while (rfd < 0 && errno == EINTR && !errflag);

	if (rfd == -1) {
	    zwarnnam(nam, "could not accept connection: %e", errno);
	    tcp_close(sess);
	    return 1;
	}

	/* redup expects fd is already registered */
	addmodulefd(rfd, FDT_MODULE);

	if (targetfd) {
	    sess->fd = redup(rfd, targetfd);
	    if (sess->fd < 0) {
		zerrnam(nam, "could not duplicate socket fd to %d: %e", targetfd, errno);
		return 1;
	    }
	}
	else {
	    sess->fd = rfd;
	}

	setiparam_no_convert("REPLY", (zlong)sess->fd);

	if (verbose)
	    printf("%d is on fd %d\n", ntohs(sess->peer.in.sin_port), sess->fd);
    }
    else
    {
	if (!args[0]) {
	    LinkNode node;
	    for(node = firstnode(ztcp_sessions); node; incnode(node))
	    {
		sess = (Tcp_session)getdata(node);

		if (sess->fd != -1)
		{
		    zthost = gethostbyaddr((const void *)&(sess->sock.in.sin_addr), sizeof(sess->sock.in.sin_addr), AF_INET);
		    if (zthost)
			localname = zthost->h_name;
		    else
			localname = inet_ntoa(sess->sock.in.sin_addr);
		    ztpeer = gethostbyaddr((const void *)&(sess->peer.in.sin_addr), sizeof(sess->peer.in.sin_addr), AF_INET);
		    if (ztpeer)
			remotename = ztpeer->h_name;
		    else
			remotename = inet_ntoa(sess->peer.in.sin_addr);
		    if (OPT_ISSET(ops,'L')) {
			int schar;
			if (sess->flags & ZTCP_ZFTP)
			    schar = 'Z';
			else if (sess->flags & ZTCP_LISTEN)
			    schar = 'L';
			else if (sess->flags & ZTCP_INBOUND)
			    schar = 'I';
			else
			    schar = 'O';
			printf("%d %c %s %d %s %d\n",
			       sess->fd, schar,
			       localname, ntohs(sess->sock.in.sin_port),
			       remotename, ntohs(sess->peer.in.sin_port));
		    } else {
			printf("%s:%d %s %s:%d is on fd %d%s\n",
			       localname, ntohs(sess->sock.in.sin_port),
			       ((sess->flags & ZTCP_LISTEN) ? "-<" :
				((sess->flags & ZTCP_INBOUND) ? "<-" : "->")),
			       remotename, ntohs(sess->peer.in.sin_port),
			       sess->fd,
			       (sess->flags & ZTCP_ZFTP) ? " ZFTP" : "");
		    }
		}
	    }
	    return 0;
	}
	else if (!args[1]) {
	    destport = htons(23);
	}
	else {

	    srv = getservbyname(args[1],"tcp");
	    if (srv)
		destport = srv->s_port;
	    else
		destport = htons(atoi(args[1]));
	}
	
	desthost = ztrdup(args[0]);
	
	zthost = zsh_getipnodebyname(desthost, AF_INET, 0, &herrno);
	if (!zthost || errflag) {
	    zwarnnam(nam, "host resolution failure: %s", desthost);
	    zsfree(desthost);
	    return 1;
	}
	
	sess = tcp_socket(PF_INET, SOCK_STREAM, 0, 0);

	if (!sess) {
	    zwarnnam(nam, "unable to allocate a TCP session slot");
	    zsfree(desthost);
	    return 1;
	}

#ifdef SO_OOBINLINE
	len = 1;
	setsockopt(sess->fd, SOL_SOCKET, SO_OOBINLINE, (char *)&len, sizeof(len));
#endif

	if (sess->fd < 0) {
	    zwarnnam(nam, "socket creation failed: %e", errno);
	    zsfree(desthost);
	    zts_delete(sess);
	    return 1;
	}
	
	for (addrp = zthost->h_addr_list; err && *addrp; addrp++) {
	    if (zthost->h_length != 4)
		zwarnnam(nam, "address length mismatch");
	    do {
		err = tcp_connect(sess, *addrp, zthost, destport);
	    } while (err && errno == EINTR && !errflag);
	}
	
	if (err) {
	    zwarnnam(nam, "connection failed: %e", errno);
	    tcp_close(sess);
	    zsfree(desthost);
	    return 1;
	}
	else
	{
	    if (targetfd) {
		sess->fd = redup(sess->fd, targetfd);
		if (sess->fd < 0) {
		    zerrnam(nam, "could not duplicate socket fd to %d: %e", targetfd, errno);
		    zsfree(desthost);
		    tcp_close(sess);
		    return 1;
		}
	    }

	    setiparam_no_convert("REPLY", (zlong)sess->fd);

	    if (verbose)
		printf("%s:%d is now on fd %d\n",
			desthost, destport, sess->fd);
	}
	
	zsfree(desthost);
    }

    return 0;
}