- /* $NetBSD: cmds.c,v 1.125 2008/05/10 00:05:31 skd Exp $ */
+ /* $NetBSD: cmds.c,v 1.131 2010/01/12 06:50:04 lukem Exp $ */
/*-
- * Copyright (c) 1996-2007 The NetBSD Foundation, Inc.
+ * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
#if 0
static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94";
#else
- __RCSID("$NetBSD: cmds.c,v 1.125 2008/05/10 00:05:31 skd Exp $");
+ __RCSID("$NetBSD: cmds.c,v 1.131 2010/01/12 06:50:04 lukem Exp $");
#endif
#endif /* not lint */
#include <limits.h>
#include <netdb.h>
#include <paths.h>
+ #include <stddef.h>
#include <stdio.h>
+#include <libutil.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "version.h"
static struct types {
- char *t_name;
- char *t_mode;
- int t_type;
- char *t_arg;
+ const char *t_name;
+ const char *t_mode;
+ int t_type;
+ const char *t_arg;
} types[] = {
{ "ascii", "A", TYPE_A, 0 },
{ "binary", "I", TYPE_I, 0 },
{ "image", "I", TYPE_I, 0 },
{ "ebcdic", "E", TYPE_E, 0 },
{ "tenex", "L", TYPE_L, bytename },
- { NULL }
+ { NULL, NULL, 0, NULL }
};
static sigjmp_buf jabort;
static int confirm(const char *, const char *);
static void mintr(int);
static void mabort(const char *);
+ static void set_type(const char *);
static const char *doprocess(char *, size_t, const char *, int, int, int);
static const char *domap(char *, size_t, const char *);
confirm(const char *cmd, const char *file)
{
const char *errormsg;
- char line[BUFSIZ];
+ char cline[BUFSIZ];
const char *promptleft, *promptright;
if (!interactive || confirmrest)
while (1) {
fprintf(ttyout, "%s %s [anpqy?]? ", promptleft, promptright);
(void)fflush(ttyout);
- if (getline(stdin, line, sizeof(line), &errormsg) < 0) {
+ if (get_line(stdin, cline, sizeof(cline), &errormsg) < 0) {
mflag = 0;
fprintf(ttyout, "%s; %s aborted\n", errormsg, cmd);
return (0);
}
- switch (tolower((unsigned char)*line)) {
+ switch (tolower((unsigned char)*cline)) {
case 'a':
confirmrest = 1;
fprintf(ttyout,
settype(int argc, char *argv[])
{
struct types *p;
- int comret;
if (argc == 0 || argc > 2) {
- char *sep;
+ const char *sep;
UPRINTF("usage: %s [", argv[0]);
sep = " ";
code = 0;
return;
}
+ set_type(argv[1]);
+ }
+
+ void
+ set_type(const char *ttype)
+ {
+ struct types *p;
+ int comret;
+
for (p = types; p->t_name; p++)
- if (strcmp(argv[1], p->t_name) == 0)
+ if (strcmp(ttype, p->t_name) == 0)
break;
if (p->t_name == 0) {
- fprintf(ttyout, "%s: unknown mode.\n", argv[1]);
+ fprintf(ttyout, "%s: unknown mode.\n", ttype);
code = -1;
return;
}
verbose = oldverbose;
}
- char *stype[] = {
- "type",
- "",
- 0
- };
-
/*
* Set binary transfer type.
*/
code = -1;
return;
}
- stype[1] = "binary";
- settype(2, stype);
+ set_type("binary");
}
/*
code = -1;
return;
}
- stype[1] = "ascii";
- settype(2, stype);
+ set_type("ascii");
}
/*
code = -1;
return;
}
- stype[1] = "tenex";
- settype(2, stype);
+ set_type("tenex");
}
/*
put(int argc, char *argv[])
{
char buf[MAXPATHLEN];
- char *cmd;
+ const char *cmd;
int loc = 0;
char *locfile;
const char *remfile;
* If restartit is -1, restart the xfer only if the remote file is newer.
*/
int
- getit(int argc, char *argv[], int restartit, const char *mode)
+ getit(int argc, char *argv[], int restartit, const char *gmode)
{
int loc, rval;
char *remfile, *olocfile;
}
}
- recvrequest("RETR", locfile, remfile, mode,
+ recvrequest("RETR", locfile, remfile, gmode,
remfile != argv[1] || locfile != argv[2], loc);
restart_point = 0;
freegetit:
int ointer;
char *cp;
const char *tp;
- int restartit;
+ int volatile restartit;
if (argc == 0 ||
(argc == 1 && !another(&argc, &argv, "remote-files"))) {
void
fget(int argc, char *argv[])
{
- char *mode;
+ const char *gmode;
FILE *fp;
- char buf[MAXPATHLEN];
+ char buf[MAXPATHLEN], cmdbuf[MAX_C_NAME];
if (argc != 2) {
UPRINTF("usage: %s localfile\n", argv[0]);
return;
}
- argv[0] = "get";
- mode = restart_point ? "r+" : "w";
+ (void)strlcpy(cmdbuf, "get", sizeof(cmdbuf));
+ argv[0] = cmdbuf;
+ gmode = restart_point ? "r+" : "w";
- while (getline(fp, buf, sizeof(buf), NULL) >= 0) {
+ while (get_line(fp, buf, sizeof(buf), NULL) >= 0) {
if (buf[0] == '\0')
continue;
argv[1] = buf;
- (void)getit(argc, argv, 0, mode);
+ (void)getit(argc, argv, 0, gmode);
}
fclose(fp);
}
const char *
- onoff(int bool)
+ onoff(int val)
{
- return (bool ? "on" : "off");
+ return (val ? "on" : "off");
}
/*
* mlsd MLSD
* nlist NLST
* pdir, pls LIST |$PAGER
- * mmlsd MLSD |$PAGER
+ * pmlsd MLSD |$PAGER
*/
void
ls(int argc, char *argv[])
{
const char *cmd;
- char *remdir, *locfile;
- int freelocfile, pagecmd, mlsdcmd;
+ char *remdir, *locbuf;
+ const char *locfile;
+ int pagecmd, mlsdcmd;
remdir = NULL;
+ locbuf = NULL;
locfile = "-";
- freelocfile = pagecmd = mlsdcmd = 0;
+ pagecmd = mlsdcmd = 0;
/*
* the only commands that start with `p' are
* the `pager' versions.
}
if (pagecmd) {
- char *p;
+ const char *p;
size_t len;
p = getoptionvalue("pager");
if (EMPTYSTRING(p))
p = DEFAULTPAGER;
len = strlen(p) + 2;
- locfile = ftp_malloc(len);
- locfile[0] = '|';
- (void)strlcpy(locfile + 1, p, len - 1);
- freelocfile = 1;
+ locbuf = ftp_malloc(len);
+ locbuf[0] = '|';
+ (void)strlcpy(locbuf + 1, p, len - 1);
+ locfile = locbuf;
} else if ((strcmp(locfile, "-") != 0) && *locfile != '|') {
- if ((locfile = globulize(locfile)) == NULL ||
- !confirm("output to local-file:", locfile)) {
+ if ((locbuf = globulize(locfile)) == NULL ||
+ !confirm("output to local-file:", locbuf)) {
code = -1;
goto freels;
}
- freelocfile = 1;
+ locfile = locbuf;
}
recvrequest(cmd, locfile, remdir, "w", 0, 0);
freels:
- if (freelocfile && locfile)
- (void)free(locfile);
+ if (locbuf)
+ (void)free(locbuf);
}
/*
{
sigfunc oldintr;
int ointer, i;
- int dolist;
- char *mode, *dest, *odest;
+ int volatile dolist;
+ char * volatile dest, *odest;
+ const char *lmode;
if (argc == 0)
goto usage;
if (sigsetjmp(jabort, 1))
mabort(argv[0]);
for (i = 1; mflag && i < argc-1 && connected; i++) {
- mode = (i == 1) ? "w" : "a";
- recvrequest(dolist ? "LIST" : "NLST", dest, argv[i], mode,
+ lmode = (i == 1) ? "w" : "a";
+ recvrequest(dolist ? "LIST" : "NLST", dest, argv[i], lmode,
0, 0);
if (!mflag && fromatty) {
ointer = interactive;
{
pid_t pid;
sigfunc oldintr;
- char shellnam[MAXPATHLEN], *shell, *namep;
+ char shellnam[MAXPATHLEN];
+ const char *shellp, *namep;
int wait_status;
if (argc == 0) {
for (pid = 3; pid < 20; pid++)
(void)close(pid);
(void)xsignal(SIGINT, SIG_DFL);
- shell = getenv("SHELL");
- if (shell == NULL)
- shell = _PATH_BSHELL;
- namep = strrchr(shell, '/');
+ shellp = getenv("SHELL");
+ if (shellp == NULL)
+ shellp = _PATH_BSHELL;
+ namep = strrchr(shellp, '/');
if (namep == NULL)
- namep = shell;
+ namep = shellp;
else
namep++;
(void)strlcpy(shellnam, namep, sizeof(shellnam));
if (ftp_debug) {
- fputs(shell, ttyout);
+ fputs(shellp, ttyout);
putc('\n', ttyout);
}
if (argc > 1) {
- execl(shell, shellnam, "-c", altarg, (char *)0);
+ execl(shellp, shellnam, "-c", altarg, (char *)0);
}
else {
- execl(shell, shellnam, (char *)0);
+ execl(shellp, shellnam, (char *)0);
}
- warn("Can't execute `%s'", shell);
+ warn("Can't execute `%s'", shellp);
code = -1;
exit(1);
}
struct cmd *c;
int cmdpos;
sigfunc oldintr;
+ char cmdbuf[MAX_C_NAME];
if (argc == 0 || (argc == 1 && !another(&argc, &argv, "command"))) {
UPRINTF("usage: %s command\n", argv[0]);
cmdpos = strcspn(line, " \t");
if (cmdpos > 0) /* remove leading "proxy " from input buffer */
memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1);
- argv[1] = c->c_name;
+ (void)strlcpy(cmdbuf, c->c_name, sizeof(cmdbuf));
+ argv[1] = cmdbuf;
(*c->c_handler)(argc-1, argv+1);
if (connected) {
proxflag = 1;
found++;
if (i < ostop) {
*cp2++ = *(ntout + i);
- if (cp2 - dst >= dlen - 1)
+ if (cp2 - dst >= (ptrdiff_t)(dlen - 1))
goto out;
}
break;
lpage(int argc, char *argv[])
{
size_t len;
- char *p, *pager, *locfile;
+ const char *p;
+ char *pager, *locfile;
if (argc == 0 || argc > 2 ||
(argc == 1 && !another(&argc, &argv, "local-file"))) {
{
int ohash, orestart_point, overbose;
size_t len;
- char *p, *pager;
+ const char *p;
+ char *pager;
if (argc == 0 || argc > 2 ||
(argc == 1 && !another(&argc, &argv, "remote-file"))) {
o->name, o->value ? o->value : "");
}
} else {
- o = getoption(argv[1]);
- if (o == NULL) {
- fprintf(ttyout, "No such option `%s'.\n", argv[1]);
- return;
- }
- FREEPTR(o->value);
- o->value = ftp_strdup(argv[2]);
- if (verbose)
- fprintf(ttyout, "Setting `%s' to `%s'.\n",
- o->name, o->value);
+ set_option(argv[1], argv[2], 1);
}
code = 0;
}
+ void
+ set_option(const char * option, const char * value, int doverbose)
+ {
+ struct option *o;
+
+ o = getoption(option);
+ if (o == NULL) {
+ fprintf(ttyout, "No such option `%s'.\n", option);
+ return;
+ }
+ FREEPTR(o->value);
+ o->value = ftp_strdup(value);
+ if (verbose && doverbose)
+ fprintf(ttyout, "Setting `%s' to `%s'.\n",
+ o->name, o->value);
+ }
+
/*
* Unset an option
*/
- /* $NetBSD: fetch.c,v 1.185 2008/04/28 20:24:13 martin Exp $ */
+ /* $NetBSD: fetch.c,v 1.193 2010/03/05 07:41:10 lukem Exp $ */
/*-
- * Copyright (c) 1997-2008 The NetBSD Foundation, Inc.
+ * Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
#include <sys/cdefs.h>
#ifndef lint
- __RCSID("$NetBSD: fetch.c,v 1.185 2008/04/28 20:24:13 martin Exp $");
+ __RCSID("$NetBSD: fetch.c,v 1.193 2010/03/05 07:41:10 lukem Exp $");
#endif /* not lint */
/*
#include <netdb.h>
#include <fcntl.h>
#include <stdio.h>
+#include <libutil.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
{
const char *cp, *scheme, *errormsg;
char *ep, *clear, *realm;
- char user[BUFSIZ], *pass;
+ char uuser[BUFSIZ], *gotpass;
+ const char *upass;
int rval;
size_t len, clen, rlen;
rval = -1;
cp = challenge;
scheme = "Basic"; /* only support Basic authentication */
+ gotpass = NULL;
DPRINTF("auth_url: challenge `%s'\n", challenge);
}
/* XXX: need to improve quoted-string parsing to support \ quoting, etc. */
if ((ep = strchr(cp, '\"')) != NULL) {
- size_t len = ep - cp;
-
+ len = ep - cp;
realm = (char *)ftp_malloc(len + 1);
(void)strlcpy(realm, cp, len + 1);
} else {
fprintf(ttyout, "Username for `%s': ", realm);
if (guser != NULL) {
- (void)strlcpy(user, guser, sizeof(user));
- fprintf(ttyout, "%s\n", user);
+ (void)strlcpy(uuser, guser, sizeof(uuser));
+ fprintf(ttyout, "%s\n", uuser);
} else {
(void)fflush(ttyout);
- if (getline(stdin, user, sizeof(user), &errormsg) < 0) {
+ if (get_line(stdin, uuser, sizeof(uuser), &errormsg) < 0) {
warnx("%s; can't authenticate", errormsg);
goto cleanup_auth_url;
}
}
if (gpass != NULL)
- pass = (char *)gpass;
+ upass = gpass;
else {
- pass = getpass("Password: ");
- if (pass == NULL) {
+ gotpass = getpass("Password: ");
+ if (gotpass == NULL) {
warnx("Can't read password");
goto cleanup_auth_url;
}
+ upass = gotpass;
}
- clen = strlen(user) + strlen(pass) + 2; /* user + ":" + pass + "\0" */
+ clen = strlen(uuser) + strlen(upass) + 2; /* user + ":" + pass + "\0" */
clear = (char *)ftp_malloc(clen);
- (void)strlcpy(clear, user, clen);
+ (void)strlcpy(clear, uuser, clen);
(void)strlcat(clear, ":", clen);
- (void)strlcat(clear, pass, clen);
- if (gpass == NULL)
- memset(pass, 0, strlen(pass));
+ (void)strlcat(clear, upass, clen);
+ if (gotpass)
+ memset(gotpass, 0, strlen(gotpass));
/* scheme + " " + enc + "\0" */
rlen = strlen(scheme) + 1 + (clen + 2) * 4 / 3 + 1;
static const unsigned char enc[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char *cp;
- int i;
+ size_t i;
cp = encoded;
for (i = 0; i < len; i += 3) {
/*
- * Parse URL of form (per RFC3986):
+ * Parse URL of form (per RFC 3986):
* <type>://[<user>[:<password>]@]<host>[:<port>][/<path>]
* Returns -1 if a parse error occurred, otherwise 0.
* It's the caller's responsibility to url_decode() the returned
* malloc(3)ed strings of the relevant section, and port to
* the number given, or ftpport if ftp://, or httpport if http://.
*
- * XXX: this is not totally RFC3986 compliant; <path> will have the
+ * XXX: this is not totally RFC 3986 compliant; <path> will have the
* leading `/' unless it's an ftp:// URL, as this makes things easier
* for file:// and http:// URLs. ftp:// URLs have the `/' between the
* host and the URL-path removed, but any additional leading slashes
* "ftp://host//dir/file" "/dir/file"
*/
static int
- parse_url(const char *url, const char *desc, url_t *type,
- char **user, char **pass, char **host, char **port,
+ parse_url(const char *url, const char *desc, url_t *utype,
+ char **uuser, char **pass, char **host, char **port,
in_port_t *portnum, char **path)
{
- const char *origurl;
- char *cp, *ep, *thost, *tport;
+ const char *origurl, *tport;
+ char *cp, *ep, *thost;
size_t len;
- if (url == NULL || desc == NULL || type == NULL || user == NULL
+ if (url == NULL || desc == NULL || utype == NULL || uuser == NULL
|| pass == NULL || host == NULL || port == NULL || portnum == NULL
|| path == NULL)
errx(1, "parse_url: invoked with NULL argument!");
DPRINTF("parse_url: %s `%s'\n", desc, url);
origurl = url;
- *type = UNKNOWN_URL_T;
- *user = *pass = *host = *port = *path = NULL;
+ *utype = UNKNOWN_URL_T;
+ *uuser = *pass = *host = *port = *path = NULL;
*portnum = 0;
tport = NULL;
if (STRNEQUAL(url, HTTP_URL)) {
url += sizeof(HTTP_URL) - 1;
- *type = HTTP_URL_T;
+ *utype = HTTP_URL_T;
*portnum = HTTP_PORT;
tport = httpport;
} else if (STRNEQUAL(url, FTP_URL)) {
url += sizeof(FTP_URL) - 1;
- *type = FTP_URL_T;
+ *utype = FTP_URL_T;
*portnum = FTP_PORT;
tport = ftpport;
} else if (STRNEQUAL(url, FILE_URL)) {
url += sizeof(FILE_URL) - 1;
- *type = FILE_URL_T;
+ *utype = FILE_URL_T;
} else {
warnx("Invalid %s `%s'", desc, url);
cleanup_parse_url:
- FREEPTR(*user);
+ FREEPTR(*uuser);
if (*pass != NULL)
memset(*pass, 0, strlen(*pass));
FREEPTR(*pass);
len = ep - url;
thost = (char *)ftp_malloc(len + 1);
(void)strlcpy(thost, url, len + 1);
- if (*type == FTP_URL_T) /* skip first / for ftp URLs */
+ if (*utype == FTP_URL_T) /* skip first / for ftp URLs */
ep++;
*path = ftp_strdup(ep);
}
cp = strchr(thost, '@'); /* look for user[:pass]@ in URLs */
if (cp != NULL) {
- if (*type == FTP_URL_T)
+ if (*utype == FTP_URL_T)
anonftp = 0; /* disable anonftp */
- *user = thost;
+ *uuser = thost;
*cp = '\0';
thost = ftp_strdup(cp + 1);
- cp = strchr(*user, ':');
+ cp = strchr(*uuser, ':');
if (cp != NULL) {
*cp = '\0';
*pass = ftp_strdup(cp + 1);
}
- url_decode(*user);
+ url_decode(*uuser);
if (*pass)
url_decode(*pass);
}
#ifdef INET6
/*
* Check if thost is an encoded IPv6 address, as per
- * RFC3986:
+ * RFC 3986:
* `[' ipv6-address ']'
*/
if (*thost == '[') {
*port = ftp_strdup(tport);
if (*path == NULL) {
const char *emptypath = "/";
- if (*type == FTP_URL_T) /* skip first / for ftp URLs */
+ if (*utype == FTP_URL_T) /* skip first / for ftp URLs */
emptypath++;
*path = ftp_strdup(emptypath);
}
DPRINTF("parse_url: user `%s' pass `%s' host %s port %s(%d) "
"path `%s'\n",
- STRorNULL(*user), STRorNULL(*pass),
+ STRorNULL(*uuser), STRorNULL(*pass),
STRorNULL(*host), STRorNULL(*port),
*portnum ? *portnum : -1, STRorNULL(*path));
int volatile isproxy;
int volatile rval;
int volatile hcode;
- size_t len;
+ int len;
+ size_t flen;
static size_t bufsize;
static char *xferbuf;
const char *cp, *token;
char *volatile auth;
char *volatile location;
char *volatile message;
- char *user, *pass, *host, *port, *path;
+ char *uuser, *pass, *host, *port, *path;
char *volatile decodedpath;
char *puser, *ppass, *useragent;
off_t hashbytes, rangestart, rangeend, entitylen;
auth = location = message = NULL;
ischunked = isproxy = hcode = 0;
rval = 1;
- user = pass = host = path = decodedpath = puser = ppass = NULL;
+ uuser = pass = host = path = decodedpath = puser = ppass = NULL;
- if (parse_url(url, "URL", &urltype, &user, &pass, &host, &port,
+ if (parse_url(url, "URL", &urltype, &uuser, &pass, &host, &port,
&portnum, &path) == -1)
goto cleanup_fetch_url;
fputs("\n", ttyout);
}
} else { /* ftp:// or http:// URLs */
- char *leading;
+ const char *leading;
int hasleading;
if (proxyenv == NULL) {
}
/* Read the response */
- len = getline(fin, buf, sizeof(buf), &errormsg);
+ len = get_line(fin, buf, sizeof(buf), &errormsg);
if (len < 0) {
if (*errormsg == '\n')
errormsg++;
/* Read the rest of the header. */
while (1) {
- len = getline(fin, buf, sizeof(buf), &errormsg);
+ len = get_line(fin, buf, sizeof(buf), &errormsg);
if (len < 0) {
if (*errormsg == '\n')
errormsg++;
} else if (match_token(&cp, "Last-Modified:")) {
struct tm parsed;
- char *t;
+ const char *t;
memset(&parsed, 0, sizeof(parsed));
- /* RFC1123 */
- if ((t = strptime(cp,
- "%a, %d %b %Y %H:%M:%S GMT",
- &parsed))
- /* RFC0850 */
- || (t = strptime(cp,
- "%a, %d-%b-%y %H:%M:%S GMT",
- &parsed))
- /* asctime */
- || (t = strptime(cp,
- "%a, %b %d %H:%M:%S %Y",
- &parsed))) {
+ t = parse_rfc2616time(&parsed, cp);
+ if (t != NULL) {
parsed.tm_isdst = -1;
if (*t == '\0')
mtime = timegm(&parsed);
#ifndef NO_DEBUG
if (ftp_debug && mtime != -1) {
fprintf(ttyout,
- "parsed date as: %s",
+ "parsed time as: %s",
rfc2822time(localtime(&mtime)));
}
#endif
if (hcode == 401) {
authp = &wwwauth;
- auser = user;
+ auser = uuser;
apass = pass;
} else {
authp = &proxyauth;
fprintf(ttyout,
"Authorization failed. Retry (y/n)? ");
- if (getline(stdin, reply, sizeof(reply), NULL)
+ if (get_line(stdin, reply, sizeof(reply), NULL)
< 0) {
goto cleanup_fetch_url;
}
(void)xsignal(SIGQUIT, psummary);
oldintr = xsignal(SIGINT, aborthttp);
- if (rcvbuf_size > bufsize) {
+ if ((size_t)rcvbuf_size > bufsize) {
if (xferbuf)
(void)free(xferbuf);
bufsize = rcvbuf_size;
if (rate_get)
(void)gettimeofday(&then, NULL);
- bufrem = rate_get ? rate_get : bufsize;
+ bufrem = rate_get ? rate_get : (off_t)bufsize;
if (ischunked)
bufrem = MIN(chunksize, bufrem);
while (bufrem > 0) {
- len = fread(xferbuf, sizeof(char),
- MIN(bufsize, bufrem), fin);
- if (len <= 0)
+ flen = fread(xferbuf, sizeof(char),
+ MIN((off_t)bufsize, bufrem), fin);
+ if (flen <= 0)
goto chunkdone;
- bytes += len;
- bufrem -= len;
- if (fwrite(xferbuf, sizeof(char), len, fout)
- != len) {
+ bytes += flen;
+ bufrem -= flen;
+ if (fwrite(xferbuf, sizeof(char), flen, fout)
+ != flen) {
warn("Writing `%s'", savefile);
goto cleanup_fetch_url;
}
(void)fflush(ttyout);
}
if (ischunked) {
- chunksize -= len;
+ chunksize -= flen;
if (chunksize <= 0)
break;
}
if (res0)
freeaddrinfo(res0);
FREEPTR(savefile);
- FREEPTR(user);
+ FREEPTR(uuser);
if (pass != NULL)
memset(pass, 0, strlen(pass));
FREEPTR(pass);
fetch_ftp(const char *url)
{
char *cp, *xargv[5], rempath[MAXPATHLEN];
- char *host, *path, *dir, *file, *user, *pass;
+ char *host, *path, *dir, *file, *uuser, *pass;
char *port;
- int dirhasglob, filehasglob, rval, type, xargc;
+ char cmdbuf[MAXPATHLEN];
+ char dirbuf[4];
+ int dirhasglob, filehasglob, rval, transtype, xargc;
int oanonftp, oautologin;
in_port_t portnum;
url_t urltype;
DPRINTF("fetch_ftp: `%s'\n", url);
- host = path = dir = file = user = pass = NULL;
+ host = path = dir = file = uuser = pass = NULL;
port = NULL;
rval = 1;
- type = TYPE_I;
+ transtype = TYPE_I;
if (STRNEQUAL(url, FTP_URL)) {
- if ((parse_url(url, "URL", &urltype, &user, &pass,
+ if ((parse_url(url, "URL", &urltype, &uuser, &pass,
&host, &port, &portnum, &path) == -1) ||
- (user != NULL && *user == '\0') ||
+ (uuser != NULL && *uuser == '\0') ||
EMPTYSTRING(host)) {
warnx("Invalid URL `%s'", url);
goto cleanup_fetch_ftp;
/* check for trailing ';type=[aid]' */
if (! EMPTYSTRING(path) && (cp = strrchr(path, ';')) != NULL) {
if (strcasecmp(cp, ";type=a") == 0)
- type = TYPE_A;
+ transtype = TYPE_A;
else if (strcasecmp(cp, ";type=i") == 0)
- type = TYPE_I;
+ transtype = TYPE_I;
else if (strcasecmp(cp, ";type=d") == 0) {
warnx(
"Directory listing via a URL is not supported");
cp = strchr(host, '@');
if (cp != NULL) {
*cp = '\0';
- user = host;
+ uuser = host;
anonftp = 0; /* disable anonftp */
host = ftp_strdup(cp + 1);
}
cp = strrchr(dir, '/');
if (cp == dir && urltype == CLASSIC_URL_T) {
file = cp + 1;
- dir = "/";
+ (void)strlcpy(dirbuf, "/", sizeof(dirbuf));
+ dir = dirbuf;
} else if (cp != NULL) {
*cp++ = '\0';
file = cp;
}
DPRINTF("fetch_ftp: user `%s' pass `%s' host %s port %s "
"path `%s' dir `%s' file `%s'\n",
- STRorNULL(user), STRorNULL(pass),
+ STRorNULL(uuser), STRorNULL(pass),
STRorNULL(host), STRorNULL(port),
STRorNULL(path), STRorNULL(dir), STRorNULL(file));
if (connected)
disconnect(0, NULL);
anonftp = oanonftp;
- xargv[0] = (char *)getprogname(); /* XXX discards const */
+ (void)strlcpy(cmdbuf, getprogname(), sizeof(cmdbuf));
+ xargv[0] = cmdbuf;
xargv[1] = host;
xargv[2] = NULL;
xargc = 2;
setpeer(xargc, xargv);
autologin = oautologin;
if ((connected == 0) ||
- (connected == 1 && !ftp_login(host, user, pass))) {
- warnx("Can't connect or login to host `%s:%s'", host, port);
+ (connected == 1 && !ftp_login(host, uuser, pass))) {
+ warnx("Can't connect or login to host `%s:%s'",
+ host, port ? port : "?");
goto cleanup_fetch_ftp;
}
- switch (type) {
+ switch (transtype) {
case TYPE_A:
setascii(1, xargv);
break;
setbinary(1, xargv);
break;
default:
- errx(1, "fetch_ftp: unknown transfer type %d", type);
+ errx(1, "fetch_ftp: unknown transfer type %d", transtype);
}
/*
* directories in one step.
*
* If we are dealing with an `ftp://host/path' URL
- * (urltype is FTP_URL_T), then RFC3986 says we need to
+ * (urltype is FTP_URL_T), then RFC 3986 says we need to
* send a separate CWD command for each unescaped "/"
* in the path, and we have to interpret %hex escaping
* *after* we find the slashes. It's possible to get
* empty components here, (from multiple adjacent
- * slashes in the path) and RFC3986 says that we should
+ * slashes in the path) and RFC 3986 says that we should
* still do `CWD ' (with a null argument) in such cases.
*
* Many ftp servers don't support `CWD ', so if there's an
DPRINTF("fetch_ftp: dir `%s', nextpart `%s'\n",
STRorNULL(dir), STRorNULL(nextpart));
if (urltype == FTP_URL_T || *dir != '\0') {
- xargv[0] = "cd";
+ (void)strlcpy(cmdbuf, "cd", sizeof(cmdbuf));
+ xargv[0] = cmdbuf;
xargv[1] = dir;
xargv[2] = NULL;
dirchange = 0;
fprintf(stderr,
"\n"
"ftp: The `CWD ' command (without a directory), which is required by\n"
- " RFC3986 to support the empty directory in the URL pathname (`//'),\n"
- " conflicts with the server's conformance to RFC0959.\n"
+ " RFC 3986 to support the empty directory in the URL pathname (`//'),\n"
+ " conflicts with the server's conformance to RFC 959.\n"
" Try the same URL without the `//' in the URL pathname.\n"
"\n");
goto cleanup_fetch_ftp;
/* Fetch the file(s). */
xargc = 2;
- xargv[0] = "get";
+ (void)strlcpy(cmdbuf, "get", sizeof(cmdbuf));
+ xargv[0] = cmdbuf;
xargv[1] = file;
xargv[2] = NULL;
if (dirhasglob || filehasglob) {
ointeractive = interactive;
interactive = 0;
if (restartautofetch)
- xargv[0] = "mreget";
+ (void)strlcpy(cmdbuf, "mreget", sizeof(cmdbuf));
else
- xargv[0] = "mget";
+ (void)strlcpy(cmdbuf, "mget", sizeof(cmdbuf));
+ xargv[0] = cmdbuf;
mget(xargc, xargv);
interactive = ointeractive;
} else {
FREEPTR(port);
FREEPTR(host);
FREEPTR(path);
- FREEPTR(user);
+ FREEPTR(uuser);
if (pass)
memset(pass, 0, strlen(pass));
FREEPTR(pass);
static int
go_fetch(const char *url)
{
- char *proxy;
+ char *proxyenv;
#ifndef NO_ABOUT
/*
* If ftpproxy is set with an FTP URL, use fetch_url()
* Othewise, use fetch_ftp().
*/
- proxy = getoptionvalue("ftp_proxy");
- if (!EMPTYSTRING(proxy) && STRNEQUAL(url, FTP_URL))
+ proxyenv = getoptionvalue("ftp_proxy");
+ if (!EMPTYSTRING(proxyenv) && STRNEQUAL(url, FTP_URL))
return (fetch_url(url, NULL, NULL, NULL));
return (fetch_ftp(url));
char *uargv[4], *path, *pathsep;
int uargc, rval, argpos;
size_t len;
+ char cmdbuf[MAX_C_NAME];
- uargc = 0;
- uargv[uargc++] = "mput";
- uargv[uargc++] = argv[0];
+ (void)strlcpy(cmdbuf, "mput", sizeof(cmdbuf));
+ uargv[0] = cmdbuf;
+ uargv[1] = argv[0];
+ uargc = 2;
uargv[2] = uargv[3] = NULL;
pathsep = NULL;
rval = 1;
(void)strlcpy(path, uploadserver, len);
(void)strlcat(path, "/", len);
} else { /* single file to upload */
- uargv[0] = "put";
+ (void)strlcpy(cmdbuf, "put", sizeof(cmdbuf));
+ uargv[0] = cmdbuf;
pathsep = strrchr(path, '/');
if (pathsep == NULL) {
pathsep = strrchr(path, ':');
- /* $NetBSD: ftp_var.h,v 1.79 2008/05/10 00:05:31 skd Exp $ */
+ /* $NetBSD: ftp_var.h,v 1.81 2009/04/12 10:18:52 lukem Exp $ */
/*-
- * Copyright (c) 1996-2007 The NetBSD Foundation, Inc.
+ * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
#endif
#include <sys/param.h>
+#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
* Format of command table.
*/
struct cmd {
- char *c_name; /* name of command */
+ const char *c_name; /* name of command */
const char *c_help; /* help string */
char c_bell; /* give bell when command completes */
char c_conn; /* must be connected to use command */
void (*c_handler)(int, char **); /* function to call */
};
+ #define MAX_C_NAME 12 /* maximum length of cmd.c_name */
+
/*
* Format of macro table
*/
* Format of option table
*/
struct option {
- char *name;
- char *value;
+ const char *name;
+ char *value;
};
/*
GLOBAL int proxy; /* proxy server connection active */
GLOBAL int proxflag; /* proxy connection exists */
GLOBAL int gatemode; /* use gate-ftp */
- GLOBAL char *gateserver; /* server to use for gate-ftp */
+ GLOBAL const char *gateserver; /* server to use for gate-ftp */
GLOBAL int sunique; /* store files on server with unique name */
GLOBAL int runique; /* store local files with unique name */
GLOBAL int mcase; /* map upper to lower case for mget names */
GLOBAL int rate_put; /* maximum put xfer rate */
GLOBAL int rate_put_incr; /* increment for put xfer rate */
GLOBAL int retry_connect; /* seconds between retrying connection */
- GLOBAL char *tmpdir; /* temporary directory */
+ GLOBAL const char *tmpdir; /* temporary directory */
GLOBAL int epsv4; /* use EPSV/EPRT on IPv4 connections */
GLOBAL int epsv4bad; /* EPSV doesn't work on the current server */
GLOBAL int epsv6; /* use EPSV/EPRT on IPv6 connections */
GLOBAL size_t cursor_argo; /* offset of cursor in margv[cursor_argc] */
#endif /* !NO_EDITCOMPLETE */
- GLOBAL char *direction; /* direction transfer is occurring */
-
GLOBAL char *hostname; /* name of host connected to */
GLOBAL int unix_server; /* server is unix, can use binary for ascii */
GLOBAL int unix_proxy; /* proxy is unix, can use binary for ascii */
GLOBAL char *username; /* name of user logged in as. (dynamic) */
GLOBAL sa_family_t family; /* address family to use for connections */
- GLOBAL char *ftpport; /* port number to use for FTP connections */
- GLOBAL char *httpport; /* port number to use for HTTP connections */
- GLOBAL char *gateport; /* port number to use for gateftp connections */
+ GLOBAL const char *ftpport; /* port number to use for FTP connections */
+ GLOBAL const char *httpport; /* port number to use for HTTP connections */
+ GLOBAL const char *gateport; /* port number to use for gateftp connections */
GLOBAL struct addrinfo *bindai; /* local address to bind as */
GLOBAL char *outfile; /* filename to output URLs to */
- /* $NetBSD: util.c,v 1.147 2008/05/10 00:05:31 skd Exp $ */
+ /* $NetBSD: util.c,v 1.155 2010/06/05 13:59:39 lukem Exp $ */
/*-
- * Copyright (c) 1997-2008 The NetBSD Foundation, Inc.
+ * Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
#include <sys/cdefs.h>
#ifndef lint
- __RCSID("$NetBSD: util.c,v 1.147 2008/05/10 00:05:31 skd Exp $");
+ __RCSID("$NetBSD: util.c,v 1.155 2010/06/05 13:59:39 lukem Exp $");
#endif /* not lint */
/*
#include <signal.h>
#include <libgen.h>
#include <limits.h>
+ #include <locale.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
setpeer(int argc, char *argv[])
{
char *host;
- char *port;
+ const char *port;
if (argc == 0)
goto usage;
}
static void
- parse_feat(const char *line)
+ parse_feat(const char *fline)
{
/*
* work-around broken ProFTPd servers that can't
- * even obey RFC2389.
+ * even obey RFC 2389.
*/
- while (*line && isspace((int)*line))
- line++;
+ while (*fline && isspace((int)*fline))
+ fline++;
- if (strcasecmp(line, "MDTM") == 0)
+ if (strcasecmp(fline, "MDTM") == 0)
features[FEAT_MDTM] = 1;
- else if (strncasecmp(line, "MLST", sizeof("MLST") - 1) == 0) {
+ else if (strncasecmp(fline, "MLST", sizeof("MLST") - 1) == 0) {
features[FEAT_MLST] = 1;
- } else if (strcasecmp(line, "REST STREAM") == 0)
+ } else if (strcasecmp(fline, "REST STREAM") == 0)
features[FEAT_REST_STREAM] = 1;
- else if (strcasecmp(line, "SIZE") == 0)
+ else if (strcasecmp(fline, "SIZE") == 0)
features[FEAT_SIZE] = 1;
- else if (strcasecmp(line, "TVFS") == 0)
+ else if (strcasecmp(fline, "TVFS") == 0)
features[FEAT_TVFS] = 1;
}
ftp_login(const char *host, const char *luser, const char *lpass)
{
char tmp[80];
- char *user, *pass, *acct, *p;
+ char *fuser, *pass, *facct, *p;
char emptypass[] = "";
const char *errormsg;
int n, aflag, rval, nlen;
aflag = rval = 0;
- user = pass = acct = NULL;
+ fuser = pass = facct = NULL;
if (luser)
- user = ftp_strdup(luser);
+ fuser = ftp_strdup(luser);
if (lpass)
pass = ftp_strdup(lpass);
DPRINTF("ftp_login: user `%s' pass `%s' host `%s'\n",
- STRorNULL(user), STRorNULL(pass), STRorNULL(host));
+ STRorNULL(fuser), STRorNULL(pass), STRorNULL(host));
/*
* Set up arguments for an anonymous FTP session, if necessary.
*/
if (anonftp) {
- FREEPTR(user);
- user = ftp_strdup("anonymous"); /* as per RFC1635 */
+ FREEPTR(fuser);
+ fuser = ftp_strdup("anonymous"); /* as per RFC 1635 */
FREEPTR(pass);
pass = ftp_strdup(getoptionvalue("anonpass"));
}
- if (ruserpass(host, &user, &pass, &acct) < 0) {
+ if (ruserpass(host, &fuser, &pass, &facct) < 0) {
code = -1;
goto cleanup_ftp_login;
}
- while (user == NULL) {
+ while (fuser == NULL) {
if (localname)
fprintf(ttyout, "Name (%s:%s): ", host, localname);
else
fprintf(ttyout, "Name (%s): ", host);
errormsg = NULL;
- nlen = getline(stdin, tmp, sizeof(tmp), &errormsg);
+ nlen = get_line(stdin, tmp, sizeof(tmp), &errormsg);
if (nlen < 0) {
fprintf(ttyout, "%s; %s aborted.\n", errormsg, "login");
code = -1;
goto cleanup_ftp_login;
} else if (nlen == 0) {
- user = ftp_strdup(localname);
+ fuser = ftp_strdup(localname);
} else {
- user = ftp_strdup(tmp);
+ fuser = ftp_strdup(tmp);
}
}
char *nuser;
size_t len;
- len = strlen(user) + 1 + strlen(host) + 1;
+ len = strlen(fuser) + 1 + strlen(host) + 1;
nuser = ftp_malloc(len);
- (void)strlcpy(nuser, user, len);
+ (void)strlcpy(nuser, fuser, len);
(void)strlcat(nuser, "@", len);
(void)strlcat(nuser, host, len);
- FREEPTR(user);
- user = nuser;
+ FREEPTR(fuser);
+ fuser = nuser;
}
- n = command("USER %s", user);
+ n = command("USER %s", fuser);
if (n == CONTINUE) {
if (pass == NULL) {
p = getpass("Password: ");
}
if (n == CONTINUE) {
aflag++;
- if (acct == NULL) {
+ if (facct == NULL) {
p = getpass("Account: ");
if (p == NULL)
p = emptypass;
- acct = ftp_strdup(p);
+ facct = ftp_strdup(p);
memset(p, 0, strlen(p));
}
- if (acct[0] == '\0') {
+ if (facct[0] == '\0') {
warnx("Login failed");
goto cleanup_ftp_login;
}
- n = command("ACCT %s", acct);
- memset(acct, 0, strlen(acct));
+ n = command("ACCT %s", facct);
+ memset(facct, 0, strlen(facct));
}
if ((n != COMPLETE) ||
- (!aflag && acct != NULL && command("ACCT %s", acct) != COMPLETE)) {
+ (!aflag && facct != NULL && command("ACCT %s", facct) != COMPLETE)) {
warnx("Login failed");
goto cleanup_ftp_login;
}
rval = 1;
- username = ftp_strdup(user);
+ username = ftp_strdup(fuser);
if (proxy)
goto cleanup_ftp_login;
updateremotecwd();
cleanup_ftp_login:
- FREEPTR(user);
+ FREEPTR(fuser);
if (pass != NULL)
memset(pass, 0, strlen(pass));
FREEPTR(pass);
- if (acct != NULL)
- memset(acct, 0, strlen(acct));
- FREEPTR(acct);
+ if (facct != NULL)
+ memset(facct, 0, strlen(facct));
+ FREEPTR(facct);
return (rval);
}
* Returns false if no new arguments have been added.
*/
int
- another(int *pargc, char ***pargv, const char *prompt)
+ another(int *pargc, char ***pargv, const char *aprompt)
{
const char *errormsg;
int ret, nlen;
fputs("Sorry, arguments too long.\n", ttyout);
intr(0);
}
- fprintf(ttyout, "(%s) ", prompt);
+ fprintf(ttyout, "(%s) ", aprompt);
line[len++] = ' ';
errormsg = NULL;
- nlen = getline(stdin, line + len, sizeof(line)-len, &errormsg);
+ nlen = get_line(stdin, line + len, sizeof(line)-len, &errormsg);
if (nlen < 0) {
fprintf(ttyout, "%s; %s aborted.\n", errormsg, "operation");
intr(0);
char temp[MAXPATHLEN];
int oldverbose, oldhash, oldprogress, fd;
char *cp;
- const char *mode;
+ const char *rmode;
size_t len;
if (!mflag || !connected) {
progress = 0;
if (doswitch)
pswitch(!proxy);
- for (mode = "w"; *++argv != NULL; mode = "a")
- recvrequest("NLST", temp, *argv, mode, 0, 0);
+ for (rmode = "w"; *++argv != NULL; rmode = "a")
+ recvrequest("NLST", temp, *argv, rmode, 0, 0);
if ((code / 100) != COMPLETE) {
if (errbuf != NULL)
*errbuf = reply_string;
goto bad_parse_time;
else
goto cleanup_parse_time;
- } else
- DPRINTF("remotemodtime: parsed date `%s' as " LLF
+ } else {
+ DPRINTF("remotemodtime: parsed time `%s' as " LLF
", %s",
timestr, (LLT)rtime,
rfc2822time(localtime(&rtime)));
+ }
} else {
if (r == ERROR && code == 500 && features[FEAT_MDTM] == -1)
features[FEAT_MDTM] = 0;
}
/*
- * Format tm in an RFC2822 compatible manner, with a trailing \n.
+ * Format tm in an RFC 2822 compatible manner, with a trailing \n.
* Returns a pointer to a static string containing the result.
*/
const char *
if (strftime(result, sizeof(result),
"%a, %d %b %Y %H:%M:%S %z\n", tm) == 0)
- errx(1, "Can't convert RFC2822 time: buffer too small");
+ errx(1, "Can't convert RFC 2822 time: buffer too small");
return result;
}
/*
+ * Parse HTTP-date as per RFC 2616.
+ * Return a pointer to the next character of the consumed date string,
+ * or NULL if failed.
+ */
+ const char *
+ parse_rfc2616time(struct tm *parsed, const char *httpdate)
+ {
+ const char *t;
+ const char *curlocale;
+
+ /* The representation of %a depends on the current locale. */
+ curlocale = setlocale(LC_TIME, NULL);
+ (void)setlocale(LC_TIME, "C");
+ /* RFC 1123 */
+ if ((t = strptime(httpdate, "%a, %d %b %Y %H:%M:%S GMT", parsed)) ||
+ /* RFC 850 */
+ (t = strptime(httpdate, "%a, %d-%b-%y %H:%M:%S GMT", parsed)) ||
+ /* asctime */
+ (t = strptime(httpdate, "%a, %b %d %H:%M:%S %Y", parsed))) {
+ ; /* do nothing */
+ }
+ (void)setlocale(LC_TIME, curlocale);
+ return t;
+ }
+
+ /*
* Update global `localcwd', which contains the state of the local cwd
*/
void
void
updateremotecwd(void)
{
- int overbose, ocode, i;
+ int overbose, ocode;
+ size_t i;
char *cp;
overbose = verbose;
void
list_vertical(StringList *sl)
{
- int i, j;
- int columns, lines;
+ size_t i, j;
+ size_t columns, lines;
char *p;
size_t w, width;
void
ftpvis(char *dst, size_t dstlen, const char *src, size_t srclen)
{
- int di, si;
+ size_t di, si;
- for (di = si = 0;
- src[si] != '\0' && di < dstlen && si < srclen;
- di++, si++) {
+ di = si = 0;
+ while (src[si] != '\0' && di < dstlen && si < srclen) {
switch (src[si]) {
case '\\':
case ' ':
case '\r':
case '\n':
case '"':
- dst[di++] = '\\';
- if (di >= dstlen)
+ /*
+ * Need room for two characters and NUL, avoiding
+ * incomplete escape sequences at end of dst.
+ */
+ if (di >= dstlen - 3)
break;
+ dst[di++] = '\\';
/* FALLTHROUGH */
default:
- dst[di] = src[si];
+ dst[di] = src[si++];
+ if (di < dstlen)
+ di++;
}
}
dst[di] = '\0';
formatbuf(char *buf, size_t len, const char *src)
{
const char *p, *p2, *q;
- int i, op, updirs, pdirs;
+ size_t i;
+ int op, updirs, pdirs;
#define ADDBUF(x) do { \
if (i >= len - 1) \
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_INET6;
+ hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(addr, "0", &hints, &res) != 0)
* -3 line was too long
*/
int
- getline(FILE *stream, char *buf, size_t buflen, const char **errormsg)
+ get_line(FILE *stream, char *buf, size_t buflen, const char **errormsg)
{
int rv, ch;
size_t len;
ftp_sl_add(StringList *sl, char *i)
{
- if (sl_add(sl, i) == -1)
- err(1, "Unable to add `%s' to stringlist", i);
+ sl_add(sl, i);
}
/*