📄 fetch.c
字号:
oldintr = NULL;
if (setjmp(httpabort)) {
if (oldintr)
(void)signal(SIGINT, oldintr);
goto cleanup_url_get;
}
oldintr = signal(SIGINT, aborthttp);
bytes = 0;
hashbytes = mark;
progressmeter(-1);
/* Finally, suck down the file. */
i = 0;
while ((len = read(s, buf, sizeof(buf))) > 0) {
bytes += len;
for (cp = buf; len > 0; len -= i, cp += i) {
if ((i = (int)write(out, cp, len)) == -1) {
warn("Writing %s", savefile);
goto cleanup_url_get;
}
else if (i == 0)
break;
}
if (hash && !progress) {
while (bytes >= hashbytes) {
(void)putchar('#');
hashbytes += mark;
}
(void)fflush(stdout);
}
}
if (hash && !progress && bytes > 0) {
if (bytes < mark)
(void)putchar('#');
(void)putchar('\n');
(void)fflush(stdout);
}
if (len != 0) {
warn("Reading from socket");
goto cleanup_url_get;
}
progressmeter(1);
if (verbose)
puts("Successfully retrieved file.");
(void)signal(SIGINT, oldintr);
close(s);
close(out);
if (proxy)
free(proxy);
free(line);
return (0);
noftpautologin:
warnx(
"Auto-login using ftp URLs isn't supported when using $ftp_proxy");
goto cleanup_url_get;
improper:
warnx("Improper response from %s", host);
cleanup_url_get:
if (s != -1)
close(s);
if (proxy)
free(proxy);
free(line);
return (-1);
}
/*
* Abort a http retrieval
*/
void
aborthttp(notused)
int notused;
{
alarmtimer(0);
puts("\nhttp fetch aborted.");
(void)fflush(stdout);
longjmp(httpabort, 1);
}
/*
* Retrieve multiple files from the command line, transferring
* files of the form "host:path", "ftp://host/path" using the
* ftp protocol, and files of the form "http://host/path" using
* the http protocol.
* If path has a trailing "/", then return (-1);
* the path will be cd-ed into and the connection remains open,
* and the function will return -1 (to indicate the connection
* is alive).
* If an error occurs the return value will be the offset+1 in
* argv[] of the file that caused a problem (i.e, argv[x]
* returns x+1)
* Otherwise, 0 is returned if all files retrieved successfully.
*/
int
auto_fetch(argc, argv)
int argc;
char *argv[];
{
static char lasthost[MAXHOSTNAMELEN];
char *xargv[5];
char *cp, *line, *host, *dir, *file, *portnum;
char *user, *pass;
char *ftpproxy, *httpproxy;
int rval, xargc;
volatile int argpos;
int dirhasglob, filehasglob;
char rempath[MAXPATHLEN];
argpos = 0;
if (setjmp(toplevel)) {
if (connected)
disconnect(0, NULL);
return (argpos + 1);
}
(void)signal(SIGINT, (sig_t)intr);
(void)signal(SIGPIPE, (sig_t)lostpeer);
ftpproxy = getenv(FTP_PROXY);
httpproxy = getenv(HTTP_PROXY);
/*
* Loop through as long as there's files to fetch.
*/
for (rval = 0; (rval == 0) && (argpos < argc); free(line), argpos++) {
if (strchr(argv[argpos], ':') == NULL)
break;
host = dir = file = portnum = user = pass = NULL;
/*
* We muck with the string, so we make a copy.
*/
line = strdup(argv[argpos]);
if (line == NULL)
errx(1, "Can't allocate memory for auto-fetch.");
/*
* Try HTTP URL-style arguments first.
*/
if (strncasecmp(line, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) {
if (url_get(line, httpproxy) == -1)
rval = argpos + 1;
continue;
}
/*
* Try FTP URL-style arguments next. If ftpproxy is
* set, use url_get() instead of standard ftp.
* Finally, try host:file.
*/
host = line;
if (strncasecmp(line, FTP_URL, sizeof(FTP_URL) - 1) == 0) {
if (ftpproxy) {
if (url_get(line, ftpproxy) == -1)
rval = argpos + 1;
continue;
}
host += sizeof(FTP_URL) - 1;
dir = strchr(host, '/');
/* look for [user:pass@]host[:port] */
pass = strpbrk(host, ":@/");
if (pass == NULL || *pass == '/') {
pass = NULL;
goto parsed_url;
}
if (pass == host || *pass == '@') {
bad_ftp_url:
warnx("Invalid URL: %s", argv[argpos]);
rval = argpos + 1;
continue;
}
*pass++ = '\0';
cp = strpbrk(pass, ":@/");
if (cp == NULL || *cp == '/') {
portnum = pass;
pass = NULL;
goto parsed_url;
}
if (EMPTYSTRING(cp) || *cp == ':')
goto bad_ftp_url;
*cp++ = '\0';
user = host;
if (EMPTYSTRING(user))
goto bad_ftp_url;
host = cp;
portnum = strchr(host, ':');
if (portnum != NULL)
*portnum++ = '\0';
} else { /* classic style `host:file' */
dir = strchr(host, ':');
}
parsed_url:
if (EMPTYSTRING(host)) {
rval = argpos + 1;
continue;
}
/*
* If dir is NULL, the file wasn't specified
* (URL looked something like ftp://host)
*/
if (dir != NULL)
*dir++ = '\0';
/*
* Extract the file and (if present) directory name.
*/
if (! EMPTYSTRING(dir)) {
cp = strrchr(dir, '/');
if (cp != NULL) {
*cp++ = '\0';
file = cp;
} else {
file = dir;
dir = NULL;
}
}
if (debug)
printf("user %s:%s host %s port %s dir %s file %s\n",
user, pass, host, portnum, dir, file);
/*
* Set up the connection if we don't have one.
*/
if (strcmp(host, lasthost) != 0) {
int oautologin;
(void)strcpy(lasthost, host);
if (connected)
disconnect(0, NULL);
xargv[0] = __progname;
xargv[1] = host;
xargv[2] = NULL;
xargc = 2;
if (! EMPTYSTRING(portnum)) {
xargv[2] = portnum;
xargv[3] = NULL;
xargc = 3;
}
oautologin = autologin;
if (user != NULL)
autologin = 0;
setpeer(xargc, xargv);
autologin = oautologin;
if ((connected == 0)
|| ((connected == 1) && !login(host, user, pass)) ) {
warnx("Can't connect or login to host `%s'",
host);
rval = argpos + 1;
continue;
}
/* Always use binary transfers. */
setbinary(0, NULL);
}
/* cd back to '/' */
xargv[0] = "cd";
xargv[1] = "/";
xargv[2] = NULL;
cd(2, xargv);
if (! dirchange) {
rval = argpos + 1;
continue;
}
dirhasglob = filehasglob = 0;
if (doglob) {
if (! EMPTYSTRING(dir) &&
strpbrk(dir, "*?[]{}") != NULL)
dirhasglob = 1;
if (! EMPTYSTRING(file) &&
strpbrk(file, "*?[]{}") != NULL)
filehasglob = 1;
}
/* Change directories, if necessary. */
if (! EMPTYSTRING(dir) && !dirhasglob) {
xargv[0] = "cd";
xargv[1] = dir;
xargv[2] = NULL;
cd(2, xargv);
if (! dirchange) {
rval = argpos + 1;
continue;
}
}
if (EMPTYSTRING(file)) {
rval = -1;
continue;
}
if (!verbose)
printf("Retrieving %s/%s\n", dir ? dir : "", file);
if (dirhasglob) {
snprintf(rempath, sizeof(rempath), "%s/%s", dir, file);
file = rempath;
}
/* Fetch the file(s). */
xargv[0] = "get";
xargv[1] = file;
xargv[2] = NULL;
if (dirhasglob || filehasglob) {
int ointeractive;
ointeractive = interactive;
interactive = 0;
xargv[0] = "mget";
mget(2, xargv);
interactive = ointeractive;
} else
get(2, xargv);
if ((code / 100) != COMPLETE)
rval = argpos + 1;
}
if (connected && rval != -1)
disconnect(0, NULL);
return (rval);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -