X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=src%2Fftp.c;h=46a520ed25897f3c94721c4f224f095437ae633f;hb=319f52d756238aca0ba7c671f529d336757806c5;hp=d2e031e731f8b3e863cbc25be01e978a0ba5663c;hpb=c36e9a5272e8ec394625dfa0f63bf9c1722eeaef;p=wget diff --git a/src/ftp.c b/src/ftp.c index d2e031e7..46a520ed 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -32,15 +32,10 @@ so, delete this exception statement from your version. */ #include #include -#ifdef HAVE_STRING_H -# include -#else -# include -#endif +#include #ifdef HAVE_UNISTD_H # include #endif -#include #include #include @@ -55,19 +50,13 @@ so, delete this exception statement from your version. */ #include "convert.h" /* for downloaded_file */ #include "recur.h" /* for INFINITE_RECURSION */ -#ifndef errno -extern int errno; -#endif - -extern LARGE_INT total_downloaded_bytes; - /* File where the "ls -al" listing will be saved. */ #define LIST_FILENAME ".listing" extern char ftp_last_respline[]; extern FILE *output_stream; -extern int output_stream_regular; +extern bool output_stream_regular; typedef struct { @@ -220,6 +209,25 @@ ftp_do_port (int csock, int *local_sock) } #endif +static void +print_length (wgint size, wgint start, bool authoritative) +{ + logprintf (LOG_VERBOSE, _("Length: %s"), number_to_static_string (size)); + if (size >= 1024) + logprintf (LOG_VERBOSE, " (%s)", human_readable (size)); + if (start > 0) + { + if (start >= 1024) + logprintf (LOG_VERBOSE, _(", %s (%s) remaining"), + number_to_static_string (size - start), + human_readable (size - start)); + else + logprintf (LOG_VERBOSE, _(", %s remaining"), + number_to_static_string (size - start)); + } + logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n"); +} + /* Retrieves a file with denoted parameters through opening an FTP connection to the server. It always closes the data connection, and closes the control connection in case of error. */ @@ -230,11 +238,12 @@ getftp (struct url *u, wgint *len, wgint restval, ccon *con) uerr_t err = RETROK; /* appease the compiler */ FILE *fp; char *user, *passwd, *respline; - char *tms, *tmrate; + char *tms; + const char *tmrate; int cmd = con->cmd; - int pasv_mode_open = 0; - wgint expected_bytes = 0L; - int rest_failed = 0; + bool pasv_mode_open = false; + wgint expected_bytes = 0; + bool rest_failed = false; int flags; wgint rd_size; @@ -251,9 +260,10 @@ getftp (struct url *u, wgint *len, wgint restval, ccon *con) user = u->user; passwd = u->passwd; search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1); - user = user ? user : opt.ftp_acc; - passwd = passwd ? passwd : opt.ftp_pass; - assert (user && passwd); + user = user ? user : (opt.ftp_user ? opt.ftp_user : opt.user); + if (!user) user = "anonymous"; + passwd = passwd ? passwd : (opt.ftp_passwd ? opt.ftp_passwd : opt.passwd); + if (!passwd) passwd = "-wget@"; dtsock = -1; local_sock = -1; @@ -309,14 +319,12 @@ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case FTPSRVERR: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Error in server greeting.\n")); fd_close (csock); con->csock = -1; return err; - break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, @@ -324,29 +332,24 @@ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case FTPLOGREFUSED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("The server refuses login.\n")); fd_close (csock); con->csock = -1; return FTPLOGREFUSED; - break; case FTPLOGINC: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Login incorrect.\n")); fd_close (csock); con->csock = -1; return FTPLOGINC; - break; case FTPOK: if (!opt.server_response) logputs (LOG_VERBOSE, _("Logged in!\n")); break; default: abort (); - exit (1); - break; } /* Third: Get the system type */ if (!opt.server_response) @@ -362,7 +365,6 @@ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case FTPSRVERR: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, @@ -373,7 +375,6 @@ Error in server response, closing control connection.\n")); break; default: abort (); - break; } if (!opt.server_response && err != FTPSRVERR) logputs (LOG_VERBOSE, _("done. ")); @@ -393,7 +394,6 @@ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case FTPSRVERR : /* PWD unsupported -- assume "/". */ xfree_null (con->id); @@ -404,7 +404,6 @@ Error in server response, closing control connection.\n")); break; default: abort (); - break; } /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]". Convert it to "/INITIAL/FOLDER" */ @@ -447,7 +446,6 @@ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, @@ -455,7 +453,6 @@ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case FTPUNKNOWNTYPE: logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, @@ -469,7 +466,6 @@ Error in server response, closing control connection.\n")); break; default: abort (); - break; } if (!opt.server_response) logputs (LOG_VERBOSE, _("done. ")); @@ -562,7 +558,6 @@ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, @@ -570,7 +565,6 @@ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case FTPNSFOD: logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"), @@ -578,13 +572,10 @@ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case FTPOK: - /* fine and dandy */ break; default: abort (); - break; } if (!opt.server_response) logputs (LOG_VERBOSE, _("done.\n")); @@ -593,7 +584,7 @@ Error in server response, closing control connection.\n")); else /* do not CWD */ logputs (LOG_VERBOSE, _("==> CWD not required.\n")); - if ((cmd & DO_RETR) && restval && *len == 0) + if ((cmd & DO_RETR) && *len == 0) { if (opt.verbose) { @@ -606,29 +597,28 @@ Error in server response, closing control connection.\n")); switch (err) { case FTPRERR: - case FTPSRVERR : + case FTPSRVERR: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("\ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case FTPOK: /* Everything is OK. */ break; default: abort (); - break; } if (!opt.server_response) - logputs (LOG_VERBOSE, _("done.\n")); + logprintf (LOG_VERBOSE, *len ? "%s\n" : _("done.\n"), + number_to_static_string (*len)); } /* If anything is to be retrieved, PORT (or PASV) must be sent. */ if (cmd & (DO_LIST | DO_RETR)) { - if (opt.ftp_pasv > 0) + if (opt.ftp_pasv) { ip_address passive_addr; int passive_port; @@ -643,7 +633,6 @@ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, @@ -651,7 +640,6 @@ Error in server response, closing control connection.\n")); fd_close (csock); con->csock = -1; return err; - break; case FTPNOPASV: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n")); @@ -661,11 +649,9 @@ Error in server response, closing control connection.\n")); logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n")); break; case FTPOK: - /* fine and dandy */ break; default: abort (); - break; } /* switch (err) */ if (err==FTPOK) { @@ -685,7 +671,7 @@ Error in server response, closing control connection.\n")); ? CONERROR : CONIMPOSSIBLE); } - pasv_mode_open = 1; /* Flag to avoid accept port */ + pasv_mode_open = true; /* Flag to avoid accept port */ if (!opt.server_response) logputs (LOG_VERBOSE, _("done. ")); } /* err==FTP_OK */ @@ -707,7 +693,6 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, @@ -717,7 +702,6 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case CONSOCKERR: logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno)); @@ -726,14 +710,12 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case FTPSYSERR: logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"), strerror (errno)); fd_close (dtsock); return err; - break; case FTPPORTERR: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Invalid PORT.\n")); @@ -742,13 +724,10 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case FTPOK: - /* fine and dandy */ break; default: abort (); - break; } /* port switch */ if (!opt.server_response) logputs (LOG_VERBOSE, _("done. ")); @@ -775,7 +754,6 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, @@ -785,17 +763,14 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case FTPRESTFAIL: logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n")); - rest_failed = 1; + rest_failed = true; break; case FTPOK: - /* fine and dandy */ break; default: abort (); - break; } if (err != FTPRESTFAIL && !opt.server_response) logputs (LOG_VERBOSE, _("done. ")); @@ -839,7 +814,6 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, @@ -849,7 +823,6 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case FTPNSFOD: logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), @@ -857,13 +830,10 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case FTPOK: - /* fine and dandy */ break; default: abort (); - break; } if (!opt.server_response) @@ -891,7 +861,6 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, @@ -901,7 +870,6 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case FTPNSFOD: logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"), @@ -909,13 +877,10 @@ Error in server response, closing control connection.\n")); fd_close (dtsock); fd_close (local_sock); return err; - break; case FTPOK: - /* fine and dandy */ break; default: abort (); - break; } if (!opt.server_response) logputs (LOG_VERBOSE, _("done.\n")); @@ -962,7 +927,7 @@ Error in server response, closing control connection.\n")); fp = fopen (con->target, "wb"); else { - fp = fopen_excl (con->target, 0); + fp = fopen_excl (con->target, true); if (!fp && errno == EEXIST) { /* We cannot just invent a new name and use it (which is @@ -993,20 +958,11 @@ Error in server response, closing control connection.\n")); if (*len) { - logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len)); - if (restval) - logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval)); - logputs (LOG_VERBOSE, "\n"); + print_length (*len, restval, true); expected_bytes = *len; /* for get_contents/show_progress */ } else if (expected_bytes) - { - logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes)); - if (restval) - logprintf (LOG_VERBOSE, _(" [%s to go]"), - legible (expected_bytes - restval)); - logputs (LOG_VERBOSE, _(" (unauthoritative)\n")); - } + print_length (expected_bytes, restval, false); /* Get the contents of the document. */ flags = 0; @@ -1019,7 +975,9 @@ Error in server response, closing control connection.\n")); restval, &rd_size, len, &con->dltime, flags); tms = time_str (NULL); - tmrate = retr_rate (rd_size, con->dltime, 0); + tmrate = retr_rate (rd_size, con->dltime); + total_download_time += con->dltime; + /* Close data connection socket. */ fd_close (dtsock); fd_close (local_sock); @@ -1136,7 +1094,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con) int count, orig_lp; wgint restval, len = 0; char *tms, *locf; - char *tmrate = NULL; + const char *tmrate = NULL; uerr_t err; struct_stat st; @@ -1146,7 +1104,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con) if (opt.noclobber && file_exists_p (con->target)) { logprintf (LOG_VERBOSE, - _("File `%s' already there, not retrieving.\n"), con->target); + _("File `%s' already there; not retrieving.\n"), con->target); /* If the file is there, we suppose it's retrieved OK. */ return RETROK; } @@ -1193,20 +1151,24 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con) } /* Decide whether or not to restart. */ - restval = 0; - if (count > 1) - restval = len; /* start where the previous run left off */ - else if (opt.always_rest - && stat (locf, &st) == 0 - && S_ISREG (st.st_mode)) + if (opt.always_rest + && stat (locf, &st) == 0 + && S_ISREG (st.st_mode)) + /* When -c is used, continue from on-disk size. (Can't use + hstat.len even if count>1 because we don't want a failed + first attempt to clobber existing data.) */ restval = st.st_size; + else if (count > 1) + restval = len; /* start where the previous run left off */ + else + restval = 0; /* Get the current time string. */ tms = time_str (NULL); /* Print fetch message, if opt.verbose. */ if (opt.verbose) { - char *hurl = url_string (u, 1); + char *hurl = url_string (u, true); char tmp[256]; strcpy (tmp, " "); if (count > 1) @@ -1236,7 +1198,6 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con) case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED: /* Fatal errors, give up. */ return err; - break; case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR: case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR: case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV: @@ -1251,7 +1212,6 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con) locf = con->target; } continue; - break; case FTPRETRINT: /* If the control connection was closed, the retrieval will be considered OK if f->size == len. */ @@ -1270,7 +1230,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con) } tms = time_str (NULL); if (!opt.spider) - tmrate = retr_rate (len - restval, con->dltime, 0); + tmrate = retr_rate (len - restval, con->dltime); /* If we get out of the switch above without continue'ing, we've successfully downloaded a file. Remember this fact. */ @@ -1289,7 +1249,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con) /* Need to hide the password from the URL. The `if' is here so that we don't do the needless allocation every time. */ - char *hurl = url_string (u, 1); + char *hurl = url_string (u, true); logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n", tms, hurl, number_to_static_string (len), locf, count); xfree (hurl); @@ -1322,8 +1282,8 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con) if (opt.delete_after) { - DEBUGP (("Removing file due to --delete-after in" - " ftp_loop_internal():\n")); + DEBUGP (("\ +Removing file due to --delete-after in ftp_loop_internal():\n")); logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf); if (unlink (locf)) logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno)); @@ -1388,12 +1348,10 @@ ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f) return err; } -static uerr_t ftp_retrieve_dirs PARAMS ((struct url *, struct fileinfo *, - ccon *)); -static uerr_t ftp_retrieve_glob PARAMS ((struct url *, ccon *, int)); -static struct fileinfo *delelement PARAMS ((struct fileinfo *, - struct fileinfo **)); -static void freefileinfo PARAMS ((struct fileinfo *f)); +static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *); +static uerr_t ftp_retrieve_glob (struct url *, ccon *, int); +static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **); +static void freefileinfo (struct fileinfo *f); /* Retrieve a list of files given in struct fileinfo linked list. If a file is a symbolic link, do not retrieve it, but rather try to @@ -1410,7 +1368,7 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con) struct fileinfo *orig; wgint local_size; time_t tml; - int dlthis; + bool dlthis; /* Increase the depth. */ ++depth; @@ -1456,7 +1414,7 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con) con->target = url_file_name (u); err = RETROK; - dlthis = 1; + dlthis = true; if (opt.timestamping && f->type == FT_PLAINFILE) { struct_stat st; @@ -1467,8 +1425,8 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con) .orig suffix. */ if (!stat (con->target, &st)) { - int eq_size; - int cor_val; + bool eq_size; + bool cor_val; /* Else, get it from the file. */ local_size = st.st_size; tml = st.st_mtime; @@ -1481,14 +1439,14 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con) values. Assumme sizes being equal for servers that lie about file size. */ cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT); - eq_size = cor_val ? (local_size == f->size) : 1 ; + eq_size = cor_val ? (local_size == f->size) : true; if (f->tstamp <= tml && eq_size) { /* Remote file is older, file sizes can be compared and are both equal. */ logprintf (LOG_VERBOSE, _("\ Remote file no newer than local file `%s' -- not retrieving.\n"), con->target); - dlthis = 0; + dlthis = false; } else if (eq_size) { @@ -1538,7 +1496,7 @@ The sizes do not match (local %s) -- retrieving.\n\n"), logprintf (LOG_VERBOSE, _("\ Already have correct symlink %s -> %s\n\n"), con->target, escnonprint (f->linkto)); - dlthis = 0; + dlthis = false; break; } } @@ -1690,7 +1648,7 @@ Not descending to `%s' as it is excluded/not-included.\n"), odir = xstrdup (u->dir); /* because url_set_dir will free u->dir. */ url_set_dir (u, newdir); - ftp_retrieve_glob (u, con, GETALL); + ftp_retrieve_glob (u, con, GLOB_GETALL); url_set_dir (u, odir); xfree (odir); @@ -1703,17 +1661,17 @@ Not descending to `%s' as it is excluded/not-included.\n"), return RETROK; } -/* Return non-zero if S has a leading '/' or contains '../' */ -static int +/* Return true if S has a leading '/' or contains '../' */ +static bool has_insecure_name_p (const char *s) { if (*s == '/') - return 1; + return true; if (strstr (s, "../") != 0) - return 1; + return true; - return 0; + return false; } /* A near-top-level function to retrieve the files in a directory. @@ -1721,9 +1679,10 @@ has_insecure_name_p (const char *s) Then it weeds out the file names that do not match the pattern. ftp_retrieve_list is called with this updated list as an argument. - If the argument ACTION is GETONE, just download the file (but first - get the listing, so that the time-stamp is heeded); if it's GLOBALL, - use globbing; if it's GETALL, download the whole directory. */ + If the argument ACTION is GLOB_GETONE, just download the file (but + first get the listing, so that the time-stamp is heeded); if it's + GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole + directory. */ static uerr_t ftp_retrieve_glob (struct url *u, ccon *con, int action) { @@ -1767,7 +1726,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) } /* Now weed out the files that do not match our globbing pattern. If we are dealing with a globbing pattern, that is. */ - if (*u->file && (action == GLOBALL || action == GETONE)) + if (*u->file && (action == GLOB_GLOBALL || action == GLOB_GETONE)) { int matchres = 0; @@ -1799,7 +1758,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) } else if (!start) { - if (action == GLOBALL) + if (action == GLOB_GLOBALL) { /* No luck. */ /* #### This message SUCKS. We should see what was the @@ -1807,7 +1766,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), escnonprint (u->file)); } - else /* GETONE or GETALL */ + else /* GLOB_GETONE or GLOB_GETALL */ { /* Let's try retrieving it anyway. */ con->st |= ON_YOUR_OWN; @@ -1834,7 +1793,7 @@ ftp_loop (struct url *u, int *dt, struct url *proxy) *dt = 0; - memset (&con, 0, sizeof (con)); + xzero (con); con.csock = -1; con.st = ON_YOUR_OWN; @@ -1885,14 +1844,25 @@ ftp_loop (struct url *u, int *dt, struct url *proxy) } else { - int wild = has_wildcards_p (u->file); - if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping) + bool ispattern = false; + if (opt.ftp_glob) + { + /* Treat the URL as a pattern if the file name part of the + URL path contains wildcards. (Don't check for u->file + because it is unescaped and therefore doesn't leave users + the option to escape literal '*' as %2A.) */ + char *file_part = strrchr (u->path, '/'); + if (!file_part) + file_part = u->path; + ispattern = has_wildcards_p (file_part); + } + if (ispattern || opt.recursive || opt.timestamping) { /* ftp_retrieve_glob is a catch-all function that gets called if we need globbing, time-stamping or recursion. Its third argument is just what we really need. */ res = ftp_retrieve_glob (u, &con, - (opt.ftp_glob && wild) ? GLOBALL : GETONE); + ispattern ? GLOB_GLOBALL : GLOB_GETONE); } else res = ftp_loop_internal (u, NULL, &con);