dirhandle = fxp_opendir_recv(pktin);
dirhandle = fxp_opendir_recv(pktin, rreq);
int scp_get_sink_action(struct scp_sink_action *act){    if (using_sftp) {	char *fname;	int must_free_fname;	struct fxp_attrs attrs;	struct sftp_packet *pktin;	struct sftp_request *req, *rreq;	int ret;	if (!scp_sftp_dirstack_head) {	    if (!scp_sftp_donethistarget) {		/*		 * Simple case: we are only dealing with one file.		 */		fname = scp_sftp_remotepath;		must_free_fname = 0;		scp_sftp_donethistarget = 1;	    } else {		/*		 * Even simpler case: one file _which we've done_.		 * Return 1 (finished).		 */		return 1;	    }	} else {	    /*	     * We're now in the middle of stepping through a list	     * of names returned from fxp_readdir(); so let's carry	     * on.	     */	    struct scp_sftp_dirstack *head = scp_sftp_dirstack_head;	    while (head->namepos < head->namelen &&		   (is_dots(head->names[head->namepos].filename) ||		    (head->wildcard &&		     !wc_match(head->wildcard,			       head->names[head->namepos].filename))))		head->namepos++;       /* skip . and .. */	    if (head->namepos < head->namelen) {		head->matched_something = 1;		fname = dupcat(head->dirpath, "/",			       head->names[head->namepos++].filename,			       NULL);		must_free_fname = 1;	    } else {		/*		 * We've come to the end of the list; pop it off		 * the stack and return an ENDDIR action (or RETRY		 * if this was a wildcard match).		 */		if (head->wildcard) {		    act->action = SCP_SINK_RETRY;		    if (!head->matched_something) {			tell_user(stderr, "pscp: wildcard '%s' matched "				  "no files", head->wildcard);			errs++;		    }		    sfree(head->wildcard);		} else {		    act->action = SCP_SINK_ENDDIR;		}		sfree(head->dirpath);		sfree(head->names);		scp_sftp_dirstack_head = head->next;		sfree(head);		return 0;	    }	}	/*	 * Now we have a filename. Stat it, and see if it's a file	 * or a directory.	 */	sftp_register(req = fxp_stat_send(fname));	rreq = sftp_find_request(pktin = sftp_recv());	assert(rreq == req);	ret = fxp_stat_recv(pktin, &attrs);	if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {	    tell_user(stderr, "unable to identify %s: %s", fname,		      ret ? "file type not supplied" : fxp_error());	    errs++;	    return 1;	}	if (attrs.permissions & 0040000) {	    struct scp_sftp_dirstack *newitem;	    struct fxp_handle *dirhandle;	    int nnames, namesize;	    struct fxp_name *ournames;	    struct fxp_names *names;	    /*	     * It's a directory. If we're not in recursive mode,	     * this merits a complaint (which is fatal if the name	     * was specified directly, but not if it was matched by	     * a wildcard).	     * 	     * We skip this complaint completely if	     * scp_sftp_wildcard is set, because that's an	     * indication that we're not actually supposed to	     * _recursively_ transfer the dir, just scan it for	     * things matching the wildcard.	     */	    if (!scp_sftp_recursive && !scp_sftp_wildcard) {		tell_user(stderr, "pscp: %s: is a directory", fname);		errs++;		if (must_free_fname) sfree(fname);		if (scp_sftp_dirstack_head) {		    act->action = SCP_SINK_RETRY;		    return 0;		} else {		    return 1;		}	    }	    /*	     * Otherwise, the fun begins. We must fxp_opendir() the	     * directory, slurp the filenames into memory, return	     * SCP_SINK_DIR (unless this is a wildcard match), and	     * set targetisdir. The next time we're called, we will	     * run through the list of filenames one by one,	     * matching them against a wildcard if present.	     * 	     * If targetisdir is _already_ set (meaning we're	     * already in the middle of going through another such	     * list), we must push the other (target,namelist) pair	     * on a stack.	     */	    sftp_register(req = fxp_opendir_send(fname));	    rreq = sftp_find_request(pktin = sftp_recv());	    assert(rreq == req);	    dirhandle = fxp_opendir_recv(pktin);	    if (!dirhandle) {		tell_user(stderr, "scp: unable to open directory %s: %s",			  fname, fxp_error());		if (must_free_fname) sfree(fname);		errs++;		return 1;	    }	    nnames = namesize = 0;	    ournames = NULL;	    while (1) {		int i;		sftp_register(req = fxp_readdir_send(dirhandle));		rreq = sftp_find_request(pktin = sftp_recv());		assert(rreq == req);		names = fxp_readdir_recv(pktin);		if (names == NULL) {		    if (fxp_error_type() == SSH_FX_EOF)			break;		    tell_user(stderr, "scp: reading directory %s: %s\n",			      fname, fxp_error());		    if (must_free_fname) sfree(fname);		    sfree(ournames);		    errs++;		    return 1;		}		if (names->nnames == 0) {		    fxp_free_names(names);		    break;		}		if (nnames + names->nnames >= namesize) {		    namesize += names->nnames + 128;		    ournames = sresize(ournames, namesize, struct fxp_name);		}		for (i = 0; i < names->nnames; i++)		    ournames[nnames++] = names->names[i];		names->nnames = 0;	       /* prevent free_names */		fxp_free_names(names);	    }	    sftp_register(req = fxp_close_send(dirhandle));	    rreq = sftp_find_request(pktin = sftp_recv());	    assert(rreq == req);	    fxp_close_recv(pktin);	    newitem = snew(struct scp_sftp_dirstack);	    newitem->next = scp_sftp_dirstack_head;	    newitem->names = ournames;	    newitem->namepos = 0;	    newitem->namelen = nnames;	    if (must_free_fname)		newitem->dirpath = fname;	    else		newitem->dirpath = dupstr(fname);	    if (scp_sftp_wildcard) {		newitem->wildcard = scp_sftp_wildcard;		newitem->matched_something = 0;		scp_sftp_wildcard = NULL;	    } else {		newitem->wildcard = NULL;	    }	    scp_sftp_dirstack_head = newitem;	    if (newitem->wildcard) {		act->action = SCP_SINK_RETRY;	    } else {		act->action = SCP_SINK_DIR;		act->buf = dupstr(stripslashes(fname, 0));		act->name = act->buf;		act->size = 0;	       /* duhh, it's a directory */		act->mode = 07777 & attrs.permissions;		if (scp_sftp_preserve &&		    (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {		    act->atime = attrs.atime;		    act->mtime = attrs.mtime;		    act->settime = 1;		} else		    act->settime = 0;	    }	    return 0;	} else {	    /*	     * It's a file. Return SCP_SINK_FILE.	     */	    act->action = SCP_SINK_FILE;	    act->buf = dupstr(stripslashes(fname, 0));	    act->name = act->buf;	    if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) {		if (uint64_compare(attrs.size,				   uint64_make(0, ULONG_MAX)) > 0) {		    act->size = ULONG_MAX;   /* *boggle* */		} else		    act->size = attrs.size.lo;	    } else		act->size = ULONG_MAX;   /* no idea */	    act->mode = 07777 & attrs.permissions;	    if (scp_sftp_preserve &&		(attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {		act->atime = attrs.atime;		act->mtime = attrs.mtime;		act->settime = 1;	    } else		act->settime = 0;	    if (must_free_fname)		scp_sftp_currentname = fname;	    else		scp_sftp_currentname = dupstr(fname);	    return 0;	}    } else {	int done = 0;	int i, bufsize;	int action;	char ch;	act->settime = 0;	act->buf = NULL;	bufsize = 0;	while (!done) {	    if (ssh_scp_recv(&ch, 1) <= 0)		return 1;	    if (ch == '\n')		bump("Protocol error: Unexpected newline");	    i = 0;	    action = ch;	    do {		if (ssh_scp_recv(&ch, 1) <= 0)		    bump("Lost connection");		if (i >= bufsize) {		    bufsize = i + 128;		    act->buf = sresize(act->buf, bufsize, char);		}		act->buf[i++] = ch;	    } while (ch != '\n');	    act->buf[i - 1] = '\0';	    switch (action) {	      case '\01':		       /* error */		tell_user(stderr, "%s\n", act->buf);		errs++;		continue;		       /* go round again */	      case '\02':		       /* fatal error */		bump("%s", act->buf);	      case 'E':		back->send(backhandle, "", 1);		act->action = SCP_SINK_ENDDIR;		return 0;	      case 'T':		if (sscanf(act->buf, "%ld %*d %ld %*d",			   &act->mtime, &act->atime) == 2) {		    act->settime = 1;		    back->send(backhandle, "", 1);		    continue;	       /* go round again */		}		bump("Protocol error: Illegal time format");	      case 'C':	      case 'D':		act->action = (action == 'C' ? SCP_SINK_FILE : SCP_SINK_DIR);		break;	      default:		bump("Protocol error: Expected control record");	    }	    /*	     * We will go round this loop only once, unless we hit	     * `continue' above.	     */	    done = 1;	}	/*	 * If we get here, we must have seen SCP_SINK_FILE or	 * SCP_SINK_DIR.	 */	if (sscanf(act->buf, "%o %lu %n", &act->mode, &act->size, &i) != 2)	    bump("Protocol error: Illegal file descriptor format");	act->name = act->buf + i;	return 0;    }}