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; }
int countlinknodes(LinkList list) { LinkNode nd; int ct = 0; for (nd = firstnode(list); nd; incnode(nd), ct++); return ct; }
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; }
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; } }
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--; }
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; }
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; }
//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; }
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; }
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; }